diff --git a/.github/workflows/check-bittensor-e2e-tests.yml.yml b/.github/workflows/check-bittensor-e2e-tests.yml.yml index 721eb96994..c133efab22 100644 --- a/.github/workflows/check-bittensor-e2e-tests.yml.yml +++ b/.github/workflows/check-bittensor-e2e-tests.yml.yml @@ -26,7 +26,7 @@ env: jobs: check-label: - runs-on: [self-hosted, type-ccx13] + runs-on: ubuntu-latest outputs: skip-bittensor-e2e-tests: ${{ steps.get-labels.outputs.skip-bittensor-e2e-tests }} steps: @@ -57,7 +57,7 @@ jobs: find-btcli-e2e-tests: needs: check-label if: needs.check-label.outputs.skip-bittensor-e2e-tests == 'false' - runs-on: [self-hosted, type-ccx13] + runs-on: ubuntu-latest outputs: test-files: ${{ steps.get-btcli-tests.outputs.test-files }} steps: @@ -84,7 +84,7 @@ jobs: find-sdk-e2e-tests: needs: check-label if: needs.check-label.outputs.skip-bittensor-e2e-tests == 'false' - runs-on: [self-hosted, type-ccx13] + runs-on: ubuntu-latest outputs: test-files: ${{ steps.get-sdk-tests.outputs.test-files }} steps: @@ -111,7 +111,7 @@ jobs: build-image-with-current-branch: needs: check-label if: needs.check-label.outputs.skip-bittensor-e2e-tests == 'false' - runs-on: [self-hosted, type-ccx33] + runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v4 @@ -130,17 +130,27 @@ jobs: - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 + - name: Move Docker data-root to /mnt/data + run: | + sudo systemctl stop docker + sudo mkdir -p /mnt/data/docker + sudo chown -R runner:runner /mnt/data + sudo chmod -R 777 /mnt/data + echo '{"data-root": "/mnt/data/docker"}' | sudo tee /etc/docker/daemon.json + sudo systemctl start docker + docker info | grep "Docker Root Dir" + - name: Build Docker Image run: docker build -f Dockerfile-localnet -t localnet . - name: Save Docker Image as Tar - run: docker save -o subtensor-localnet.tar localnet + run: docker save -o /mnt/data/subtensor-localnet.tar localnet - name: Upload Docker Image as Artifact uses: actions/upload-artifact@v4 with: name: subtensor-localnet - path: subtensor-localnet.tar + path: /mnt/data/subtensor-localnet.tar # main btcli job run-btcli-e2e-tests: @@ -149,7 +159,7 @@ jobs: - find-btcli-e2e-tests - build-image-with-current-branch if: needs.check-label.outputs.skip-bittensor-e2e-tests == 'false' - runs-on: [self-hosted, type-ccx13] + runs-on: ubuntu-latest strategy: fail-fast: false max-parallel: 16 @@ -181,7 +191,7 @@ jobs: - name: Install uv uses: astral-sh/setup-uv@v5 with: - enable-cache: 'false' + enable-cache: "false" - name: Create Python virtual environment working-directory: ${{ github.workspace }} @@ -243,7 +253,7 @@ jobs: - find-sdk-e2e-tests - build-image-with-current-branch if: needs.check-label.outputs.skip-bittensor-e2e-tests == 'false' - runs-on: [self-hosted, type-ccx13] + runs-on: ubuntu-latest strategy: fail-fast: false max-parallel: 16 @@ -275,7 +285,7 @@ jobs: - name: Install uv uses: astral-sh/setup-uv@v5 with: - enable-cache: 'false' + enable-cache: "false" - name: Create Python virtual environment working-directory: ${{ github.workspace }} diff --git a/.github/workflows/evm-tests.yml b/.github/workflows/contract-tests.yml similarity index 92% rename from .github/workflows/evm-tests.yml rename to .github/workflows/contract-tests.yml index b818695237..2e74e408b3 100644 --- a/.github/workflows/evm-tests.yml +++ b/.github/workflows/contract-tests.yml @@ -1,4 +1,4 @@ -name: EVM E2E Tests +name: Contract E2E Tests on: pull_request: @@ -24,7 +24,7 @@ permissions: jobs: run: - runs-on: [self-hosted, type-ccx33] + runs-on: ubuntu-latest env: RUST_BACKTRACE: full steps: @@ -52,10 +52,10 @@ jobs: - name: Run tests uses: nick-fields/retry@v3 with: - timeout_minutes: 60 + timeout_minutes: 90 max_attempts: 3 retry_wait_seconds: 60 command: | cd ${{ github.workspace }} npm install --global yarn - ./evm-tests/run-ci.sh + ./contract-tests/run-ci.sh diff --git a/Cargo.lock b/Cargo.lock index 99538d9ef5..4b32cbe31a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6020,6 +6020,15 @@ dependencies = [ "serde", ] +[[package]] +name = "hybrid-array" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2d35805454dc9f8662a98d6d61886ffe26bd465f5960e0e55345c70d5c0d2a9" +dependencies = [ + "typenum", +] + [[package]] name = "hyper" version = "0.14.32" @@ -6766,6 +6775,16 @@ dependencies = [ "tiny-keccak", ] +[[package]] +name = "kem" +version = "0.3.0-pre.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b8645470337db67b01a7f966decf7d0bafedbae74147d33e641c67a91df239f" +dependencies = [ + "rand_core 0.6.4", + "zeroize", +] + [[package]] name = "keystream" version = "1.0.0" @@ -7787,6 +7806,18 @@ dependencies = [ "zeroize", ] +[[package]] +name = "ml-kem" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97befee0c869cb56f3118f49d0f9bb68c9e3f380dec23c1100aedc4ec3ba239a" +dependencies = [ + "hybrid-array", + "kem", + "rand_core 0.6.4", + "sha3", +] + [[package]] name = "mmr-gadget" version = "46.0.0" @@ -8159,7 +8190,10 @@ checksum = "43794a0ace135be66a25d3ae77d41b91615fb68ae937f904090203e81f755b65" name = "node-subtensor" version = "4.0.0-dev" dependencies = [ + "anyhow", "async-trait", + "blake2 0.10.6", + "chacha20poly1305", "clap", "fc-api", "fc-aura", @@ -8179,19 +8213,26 @@ dependencies = [ "frame-system-rpc-runtime-api", "futures", "hex", + "hkdf", "jsonrpsee", "log", "memmap2 0.9.8", + "ml-kem", "node-subtensor-runtime", "num-traits", "pallet-commitments", "pallet-drand", + "pallet-shield", + "pallet-subtensor", "pallet-subtensor-swap-rpc", "pallet-subtensor-swap-runtime-api", "pallet-transaction-payment", "pallet-transaction-payment-rpc", "pallet-transaction-payment-rpc-runtime-api", + "parity-scale-codec", "polkadot-sdk", + "rand 0.8.5", + "rand_core 0.9.3", "sc-basic-authorship", "sc-chain-spec", "sc-chain-spec-derive", @@ -8219,6 +8260,7 @@ dependencies = [ "sc-transaction-pool-api", "serde", "serde_json", + "sha2 0.10.9", "sp-api", "sp-block-builder", "sp-blockchain", @@ -8243,7 +8285,10 @@ dependencies = [ "substrate-prometheus-endpoint", "subtensor-custom-rpc", "subtensor-custom-rpc-runtime-api", + "subtensor-macros", "subtensor-runtime-common", + "tokio", + "x25519-dalek", ] [[package]] @@ -8301,6 +8346,7 @@ dependencies = [ "pallet-safe-mode", "pallet-scheduler", "pallet-session", + "pallet-shield", "pallet-staking", "pallet-staking-reward-curve", "pallet-staking-reward-fn", @@ -9544,8 +9590,8 @@ dependencies = [ "serde", "serde_json", "sha2 0.10.9", - "sp-ark-bls12-381", "sp-core", + "sp-crypto-ec-utils", "sp-io", "sp-keyring", "sp-keystore", @@ -10521,6 +10567,26 @@ dependencies = [ "sp-session", ] +[[package]] +name = "pallet-shield" +version = "0.0.1" +dependencies = [ + "frame-benchmarking", + "frame-support", + "frame-system", + "pallet-aura", + "pallet-timestamp", + "parity-scale-codec", + "scale-info", + "sp-consensus-aura", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", + "sp-weights", + "subtensor-macros", +] + [[package]] name = "pallet-skip-feeless-payment" version = "16.0.0" @@ -16735,15 +16801,6 @@ dependencies = [ "static_assertions", ] -[[package]] -name = "sp-ark-bls12-381" -version = "0.4.2" -source = "git+https://github.com/paritytech/arkworks-substrate#f08093a5f7c32778eae1295430ec064dccd062a6" -dependencies = [ - "ark-bls12-381-ext", - "sp-crypto-ec-utils", -] - [[package]] name = "sp-authority-discovery" version = "37.0.0" diff --git a/Cargo.toml b/Cargo.toml index c9259c9e83..1d65a3cd5e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -274,7 +274,6 @@ sp-keystore = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "p w3f-bls = { git = "https://github.com/opentensor/bls", branch = "fix-no-std", default-features = false } ark-crypto-primitives = { version = "0.4.0", default-features = false } ark-scale = { version = "0.0.11", default-features = false } -sp-ark-bls12-381 = { git = "https://github.com/paritytech/arkworks-substrate", package = "sp-ark-bls12-381", default-features = false } ark-bls12-381 = { version = "0.4.0", default-features = false } ark-serialize = { version = "0.4.0", default-features = false } ark-ff = { version = "0.4.0", default-features = false } @@ -285,6 +284,9 @@ sha2 = { version = "0.10.8", default-features = false } rand_chacha = { version = "0.3.1", default-features = false } tle = { git = "https://github.com/ideal-lab5/timelock", rev = "5416406cfd32799e31e1795393d4916894de4468", default-features = false } +pallet-shield = { path = "pallets/shield", default-features = false } +ml-kem = { version = "0.2.0", default-features = true } + # Primitives [profile.release] diff --git a/common/src/lib.rs b/common/src/lib.rs index a98a957ad8..28a33c2ae6 100644 --- a/common/src/lib.rs +++ b/common/src/lib.rs @@ -162,6 +162,33 @@ pub enum ProxyType { RootClaim, } +impl TryFrom for ProxyType { + type Error = (); + + fn try_from(value: u8) -> Result { + match value { + 0 => Ok(Self::Any), + 1 => Ok(Self::Owner), + 2 => Ok(Self::NonCritical), + 3 => Ok(Self::NonTransfer), + 4 => Ok(Self::Senate), + 5 => Ok(Self::NonFungible), + 6 => Ok(Self::Triumvirate), + 7 => Ok(Self::Governance), + 8 => Ok(Self::Staking), + 9 => Ok(Self::Registration), + 10 => Ok(Self::Transfer), + 11 => Ok(Self::SmallTransfer), + 12 => Ok(Self::RootWeights), + 13 => Ok(Self::ChildKeys), + 14 => Ok(Self::SudoUncheckedSetCode), + 15 => Ok(Self::SwapHotkey), + 16 => Ok(Self::SubnetLeaseBeneficiary), + _ => Err(()), + } + } +} + impl Default for ProxyType { // allow all Calls; required to be most permissive fn default() -> Self { diff --git a/evm-tests/.gitignore b/contract-tests/.gitignore similarity index 100% rename from evm-tests/.gitignore rename to contract-tests/.gitignore diff --git a/evm-tests/README.md b/contract-tests/README.md similarity index 75% rename from evm-tests/README.md rename to contract-tests/README.md index ed3782e0f7..78294603d3 100644 --- a/evm-tests/README.md +++ b/contract-tests/README.md @@ -1,12 +1,16 @@ # type-test -The evm-tests folder includes all typescript code to test the basic EVM function +The contract-tests folder includes all typescript code to test the basic EVM function like token transfer, and all precompile contracts in Subtensor. It is implemented in typescript, use both ethers and viem lib to interact with contracts. The polkadot API is used to call extrinsic, get storage in Subtensor . The developers can use it to verify the code change in precompile contracts. -It is also included in the CI process, all test cases are executed for new +The Ink contract tests also are included in the contract-tests folder. +There is an Ink project in the bittensor folder, which include all functions defined +in the runtime extension. The test file for it is wasm.contract.test.ts. + +The whole test process is also included in the CI, all test cases are executed for new commit. CI flow can get catch any failed test cases. The polkadot API get the latest metadata from the runtime, the case also can find out any incompatibility between runtime and precompile contracts. diff --git a/contract-tests/bittensor/.gitignore b/contract-tests/bittensor/.gitignore new file mode 100755 index 0000000000..8de8f877e4 --- /dev/null +++ b/contract-tests/bittensor/.gitignore @@ -0,0 +1,9 @@ +# Ignore build artifacts from the local tests sub-crate. +/target/ + +# Ignore backup files creates by cargo fmt. +**/*.rs.bk + +# Remove Cargo.lock when creating an executable, leave it for libraries +# More information here http://doc.crates.io/guide.html#cargotoml-vs-cargolock +Cargo.lock diff --git a/contract-tests/bittensor/Cargo.toml b/contract-tests/bittensor/Cargo.toml new file mode 100755 index 0000000000..ff46eb3696 --- /dev/null +++ b/contract-tests/bittensor/Cargo.toml @@ -0,0 +1,30 @@ +[workspace] + +[package] +name = "bittensor" +version = "0.1.0" +authors = ["[your_name] <[your_email]>"] +edition = "2021" + +[dependencies] +ink = { version = "5.1.1", default-features = false } +parity-scale-codec = { version = "3.0.0", default-features = false } +serde = { version = "1.0.228", default-features = false } +subtensor-runtime-common = { path = "../../common", default-features = false } +[dev-dependencies] +ink_e2e = { version = "5.1.1" } + +[lib] +path = "lib.rs" + +[features] +default = ["std"] +std = [ + "ink/std", + "parity-scale-codec/std", + "serde/std", + "subtensor-runtime-common/std", +] + +ink-as-dependency = [] +e2e-tests = [] diff --git a/contract-tests/bittensor/lib.rs b/contract-tests/bittensor/lib.rs new file mode 100755 index 0000000000..03367339ca --- /dev/null +++ b/contract-tests/bittensor/lib.rs @@ -0,0 +1,416 @@ +#![cfg_attr(not(feature = "std"), no_std, no_main)] + +use parity_scale_codec::Compact; + +#[derive(Debug, Clone)] +pub struct CustomEnvironment; + +use subtensor_runtime_common::{AlphaCurrency, NetUid, TaoCurrency}; +pub enum FunctionId { + GetStakeInfoForHotkeyColdkeyNetuidV1 = 0, + AddStakeV1 = 1, + RemoveStakeV1 = 2, + UnstakeAllV1 = 3, + UnstakeAllAlphaV1 = 4, + MoveStakeV1 = 5, + TransferStakeV1 = 6, + SwapStakeV1 = 7, + AddStakeLimitV1 = 8, + RemoveStakeLimitV1 = 9, + SwapStakeLimitV1 = 10, + RemoveStakeFullLimitV1 = 11, + SetColdkeyAutoStakeHotkeyV1 = 12, + AddProxyV1 = 13, + RemoveProxyV1 = 14, +} + +#[ink::chain_extension(extension = 0x1000)] +pub trait RuntimeReadWrite { + type ErrorCode = ReadWriteErrorCode; + + #[ink(function = 0)] + fn get_stake_info_for_hotkey_coldkey_netuid( + hotkey: ink::primitives::AccountId, + coldkey: ink::primitives::AccountId, + netuid: u16, + ) -> Option>; + + #[ink(function = 1)] + fn add_stake( + hotkey: ::AccountId, + netuid: NetUid, + amount: AlphaCurrency, + ); + + #[ink(function = 2)] + fn remove_stake( + hotkey: ::AccountId, + netuid: NetUid, + amount: AlphaCurrency, + ); + + #[ink(function = 3)] + fn unstake_all(hotkey: ::AccountId); + + #[ink(function = 4)] + fn unstake_all_alpha(hotkey: ::AccountId); + + #[ink(function = 5)] + fn move_stake( + origin_hotkey: ::AccountId, + destination_hotkey: ::AccountId, + origin_netuid: NetUid, + destination_netuid: NetUid, + amount: AlphaCurrency, + ); + + #[ink(function = 6)] + fn transfer_stake( + destination_coldkey: ::AccountId, + hotkey: ::AccountId, + origin_netuid: NetUid, + destination_netuid: NetUid, + amount: AlphaCurrency, + ); + + #[ink(function = 7)] + fn swap_stake( + hotkey: ::AccountId, + origin_netuid: NetUid, + destination_netuid: NetUid, + amount: AlphaCurrency, + ); + + #[ink(function = 8)] + fn add_stake_limit( + hotkey: ::AccountId, + netuid: NetUid, + amount: TaoCurrency, + limit_price: TaoCurrency, + allow_partial: bool, + ); + + #[ink(function = 9)] + fn remove_stake_limit( + hotkey: ::AccountId, + netuid: NetUid, + amount: TaoCurrency, + limit_price: TaoCurrency, + allow_partial: bool, + ); + + #[ink(function = 10)] + fn swap_stake_limit( + hotkey: ::AccountId, + origin_netuid: NetUid, + destination_netuid: NetUid, + amount: AlphaCurrency, + limit_price: TaoCurrency, + allow_partial: bool, + ); + + #[ink(function = 11)] + fn remove_stake_full_limit( + hotkey: ::AccountId, + netuid: NetUid, + limit_price: TaoCurrency, + ); + + #[ink(function = 12)] + fn set_coldkey_auto_stake_hotkey( + netuid: NetUid, + hotkey: ::AccountId, + ); + + #[ink(function = 13)] + fn add_proxy(delegate: ::AccountId); + + #[ink(function = 14)] + fn remove_proxy(delegate: ::AccountId); +} + +#[ink::scale_derive(Encode, Decode, TypeInfo)] +pub enum ReadWriteErrorCode { + ReadFailed, + WriteFailed, +} + +impl ink::env::chain_extension::FromStatusCode for ReadWriteErrorCode { + fn from_status_code(status_code: u32) -> Result<(), Self> { + match status_code { + 0 => Ok(()), + 1 => Err(ReadWriteErrorCode::ReadFailed), + 2 => Err(ReadWriteErrorCode::WriteFailed), + _ => Err(ReadWriteErrorCode::ReadFailed), + } + } +} + +impl ink::env::Environment for CustomEnvironment { + const MAX_EVENT_TOPICS: usize = 4; + + type AccountId = ink::primitives::AccountId; + type Balance = u64; + type Hash = ink::primitives::Hash; + type BlockNumber = u32; + type Timestamp = u64; + + type ChainExtension = RuntimeReadWrite; +} + +#[ink::scale_derive(Encode, Decode, TypeInfo)] +pub struct StakeInfo { + hotkey: AccountId, + coldkey: AccountId, + netuid: Compact, + stake: Compact, + locked: Compact, + emission: Compact, + tao_emission: Compact, + drain: Compact, + is_registered: bool, +} + +#[ink::contract(env = crate::CustomEnvironment)] +mod bittensor { + use super::*; + + /// Defines the storage of your contract. + /// Add new fields to the below struct in order + /// to add new static storage fields to your contract. + #[ink(storage)] + pub struct Bittensor {} + + impl Bittensor { + /// Constructor + #[ink(constructor)] + pub fn new() -> Self { + Self {} + } + + /// Constructor + #[ink(constructor)] + pub fn default() -> Self { + Self::new() + } + + #[ink(message)] + pub fn get_stake_info_for_hotkey_coldkey_netuid( + &self, + hotkey: [u8; 32], + coldkey: [u8; 32], + netuid: u16, + ) -> Result>, ReadWriteErrorCode> { + self.env() + .extension() + .get_stake_info_for_hotkey_coldkey_netuid(hotkey.into(), coldkey.into(), netuid) + .map_err(|_e| ReadWriteErrorCode::ReadFailed) + } + + #[ink(message)] + pub fn add_stake( + &self, + hotkey: [u8; 32], + netuid: u16, + amount: u64, + ) -> Result<(), ReadWriteErrorCode> { + self.env() + .extension() + .add_stake(hotkey.into(), netuid.into(), amount.into()) + .map_err(|_e| ReadWriteErrorCode::WriteFailed) + } + + #[ink(message)] + pub fn remove_stake( + &self, + hotkey: [u8; 32], + netuid: u16, + amount: u64, + ) -> Result<(), ReadWriteErrorCode> { + self.env() + .extension() + .remove_stake(hotkey.into(), netuid.into(), amount.into()) + .map_err(|_e| ReadWriteErrorCode::WriteFailed) + } + + #[ink(message)] + pub fn unstake_all(&self, hotkey: [u8; 32]) -> Result<(), ReadWriteErrorCode> { + self.env() + .extension() + .unstake_all(hotkey.into()) + .map_err(|_e| ReadWriteErrorCode::WriteFailed) + } + + #[ink(message)] + pub fn unstake_all_alpha(&self, hotkey: [u8; 32]) -> Result<(), ReadWriteErrorCode> { + self.env() + .extension() + .unstake_all_alpha(hotkey.into()) + .map_err(|_e| ReadWriteErrorCode::WriteFailed) + } + + #[ink(message)] + pub fn move_stake( + &self, + origin_hotkey: [u8; 32], + destination_hotkey: [u8; 32], + origin_netuid: u16, + destination_netuid: u16, + amount: u64, + ) -> Result<(), ReadWriteErrorCode> { + self.env() + .extension() + .move_stake( + origin_hotkey.into(), + destination_hotkey.into(), + origin_netuid.into(), + destination_netuid.into(), + amount.into(), + ) + .map_err(|_e| ReadWriteErrorCode::WriteFailed) + } + + #[ink(message)] + pub fn transfer_stake( + &self, + destination_coldkey: [u8; 32], + hotkey: [u8; 32], + origin_netuid: u16, + destination_netuid: u16, + amount: u64, + ) -> Result<(), ReadWriteErrorCode> { + self.env() + .extension() + .transfer_stake( + destination_coldkey.into(), + hotkey.into(), + origin_netuid.into(), + destination_netuid.into(), + amount.into(), + ) + .map_err(|_e| ReadWriteErrorCode::WriteFailed) + } + + #[ink(message)] + pub fn swap_stake( + &self, + hotkey: [u8; 32], + origin_netuid: u16, + destination_netuid: u16, + amount: u64, + ) -> Result<(), ReadWriteErrorCode> { + self.env() + .extension() + .swap_stake( + hotkey.into(), + origin_netuid.into(), + destination_netuid.into(), + amount.into(), + ) + .map_err(|_e| ReadWriteErrorCode::WriteFailed) + } + + #[ink(message)] + pub fn add_stake_limit( + &self, + hotkey: [u8; 32], + netuid: u16, + amount: u64, + limit_price: u64, + allow_partial: bool, + ) -> Result<(), ReadWriteErrorCode> { + self.env() + .extension() + .add_stake_limit( + hotkey.into(), + netuid.into(), + amount.into(), + limit_price.into(), + allow_partial, + ) + .map_err(|_e| ReadWriteErrorCode::WriteFailed) + } + + #[ink(message)] + pub fn remove_stake_limit( + &self, + hotkey: [u8; 32], + netuid: u16, + amount: u64, + limit_price: u64, + allow_partial: bool, + ) -> Result<(), ReadWriteErrorCode> { + self.env().extension().remove_stake_limit( + hotkey.into(), + netuid.into(), + amount.into(), + limit_price.into(), + allow_partial, + ) + } + + #[ink(message)] + pub fn swap_stake_limit( + &self, + hotkey: [u8; 32], + origin_netuid: u16, + destination_netuid: u16, + amount: u64, + limit_price: u64, + allow_partial: bool, + ) -> Result<(), ReadWriteErrorCode> { + self.env() + .extension() + .swap_stake_limit( + hotkey.into(), + origin_netuid.into(), + destination_netuid.into(), + amount.into(), + limit_price.into(), + allow_partial, + ) + .map_err(|_e| ReadWriteErrorCode::WriteFailed) + } + + #[ink(message)] + pub fn remove_stake_full_limit( + &self, + hotkey: [u8; 32], + netuid: u16, + limit_price: u64, + ) -> Result<(), ReadWriteErrorCode> { + self.env() + .extension() + .remove_stake_full_limit(hotkey.into(), netuid.into(), limit_price.into()) + .map_err(|_e| ReadWriteErrorCode::WriteFailed) + } + + #[ink(message)] + pub fn set_coldkey_auto_stake_hotkey( + &self, + netuid: u16, + hotkey: [u8; 32], + ) -> Result<(), ReadWriteErrorCode> { + self.env() + .extension() + .set_coldkey_auto_stake_hotkey(netuid.into(), hotkey.into()) + .map_err(|_e| ReadWriteErrorCode::WriteFailed) + } + + #[ink(message)] + pub fn add_proxy(&self, delegate: [u8; 32]) -> Result<(), ReadWriteErrorCode> { + self.env() + .extension() + .add_proxy(delegate.into()) + .map_err(|_e| ReadWriteErrorCode::WriteFailed) + } + + #[ink(message)] + pub fn remove_proxy(&self, delegate: [u8; 32]) -> Result<(), ReadWriteErrorCode> { + self.env() + .extension() + .remove_proxy(delegate.into()) + .map_err(|_e| ReadWriteErrorCode::WriteFailed) + } + } +} diff --git a/evm-tests/get-metadata.sh b/contract-tests/get-metadata.sh similarity index 50% rename from evm-tests/get-metadata.sh rename to contract-tests/get-metadata.sh index 6d7727009d..64d76bff29 100755 --- a/evm-tests/get-metadata.sh +++ b/contract-tests/get-metadata.sh @@ -1,3 +1,3 @@ rm -rf .papi npx papi add devnet -w ws://localhost:9944 - +npx papi ink add ./bittensor/target/ink/bittensor.json \ No newline at end of file diff --git a/evm-tests/package.json b/contract-tests/package.json similarity index 75% rename from evm-tests/package.json rename to contract-tests/package.json index ae756ae55f..26136346bb 100644 --- a/evm-tests/package.json +++ b/contract-tests/package.json @@ -7,28 +7,28 @@ "license": "ISC", "dependencies": { "@polkadot-api/descriptors": "file:.papi/descriptors", - "@polkadot-labs/hdkd": "^0.0.23", - "@polkadot-labs/hdkd-helpers": "^0.0.23", - "@polkadot/api": "^16.4.6", + "@polkadot-api/ink-contracts": "^0.4.1", + "@polkadot-api/sdk-ink": "^0.5.1", + "@polkadot-labs/hdkd": "^0.0.25", + "@polkadot-labs/hdkd-helpers": "^0.0.25", "@types/mocha": "^10.0.10", "dotenv": "17.2.1", "ethers": "^6.13.5", "mocha": "^11.1.0", - "polkadot-api": "^1.9.5", + "polkadot-api": "^1.22.0", + "@polkadot/api": "^16.4.6", "rxjs": "^7.8.2", "scale-ts": "^1.6.1", "viem": "2.23.4", "ws": "^8.18.2" }, "devDependencies": { - "@types/bun": "^1.1.13", "@types/chai": "^5.0.1", "@types/node": "^22.18.0", "assert": "^2.1.0", "chai": "^6.0.1", "prettier": "^3.3.3", "ts-node": "^10.9.2", - "typescript": "^5.7.2", - "vite": "^7.1.4" + "typescript": "^5.7.2" } } diff --git a/evm-tests/run-ci.sh b/contract-tests/run-ci.sh similarity index 79% rename from evm-tests/run-ci.sh rename to contract-tests/run-ci.sh index 7ad4bb2186..a5a8c2f52e 100755 --- a/evm-tests/run-ci.sh +++ b/contract-tests/run-ci.sh @@ -5,7 +5,7 @@ echo "start run-ci.sh" scripts/localnet.sh &>/dev/null & i=1 -while [ $i -le 1000 ]; do +while [ $i -le 2000 ]; do if nc -z localhost 9944; then echo "node subtensor is running after $i seconds" break @@ -19,14 +19,22 @@ if [ "$i" -eq 1000 ]; then exit 1 fi -sleep 5 +sleep 10 if ! nc -z localhost 9944; then echo "node subtensor exit, port not available" exit 1 fi -cd evm-tests +cd contract-tests + +cd bittensor + +rustup component add rust-src +cargo install cargo-contract +cargo contract build --release + +cd .. # required for papi in get-metadata.sh, but we cannot run yarn before papi as it adds the descriptors to the package.json which won't resolve npm i -g polkadot-api @@ -35,7 +43,7 @@ bash get-metadata.sh sleep 5 -yarn +yarn install --frozen-lockfile yarn run test TEST_EXIT_CODE=$? diff --git a/evm-tests/src/address-utils.ts b/contract-tests/src/address-utils.ts similarity index 97% rename from evm-tests/src/address-utils.ts rename to contract-tests/src/address-utils.ts index ed3abc5008..753eed2530 100644 --- a/evm-tests/src/address-utils.ts +++ b/contract-tests/src/address-utils.ts @@ -1,6 +1,6 @@ import { Address } from "viem" import { encodeAddress } from "@polkadot/util-crypto"; -import { ss58Address } from "@polkadot-labs/hdkd-helpers"; +import { ss58Address, ss58Decode } from "@polkadot-labs/hdkd-helpers"; import { hexToU8a } from "@polkadot/util"; import { blake2AsU8a, decodeAddress } from "@polkadot/util-crypto"; import { Binary } from "polkadot-api"; diff --git a/evm-tests/src/balance-math.ts b/contract-tests/src/balance-math.ts similarity index 100% rename from evm-tests/src/balance-math.ts rename to contract-tests/src/balance-math.ts diff --git a/evm-tests/src/config.ts b/contract-tests/src/config.ts similarity index 100% rename from evm-tests/src/config.ts rename to contract-tests/src/config.ts diff --git a/evm-tests/src/contracts/alpha.ts b/contract-tests/src/contracts/alpha.ts similarity index 100% rename from evm-tests/src/contracts/alpha.ts rename to contract-tests/src/contracts/alpha.ts diff --git a/evm-tests/src/contracts/alphaPool.sol b/contract-tests/src/contracts/alphaPool.sol similarity index 100% rename from evm-tests/src/contracts/alphaPool.sol rename to contract-tests/src/contracts/alphaPool.sol diff --git a/evm-tests/src/contracts/alphaPool.ts b/contract-tests/src/contracts/alphaPool.ts similarity index 100% rename from evm-tests/src/contracts/alphaPool.ts rename to contract-tests/src/contracts/alphaPool.ts diff --git a/evm-tests/src/contracts/bridgeToken.ts b/contract-tests/src/contracts/bridgeToken.ts similarity index 100% rename from evm-tests/src/contracts/bridgeToken.ts rename to contract-tests/src/contracts/bridgeToken.ts diff --git a/evm-tests/src/contracts/crowdloan.ts b/contract-tests/src/contracts/crowdloan.ts similarity index 100% rename from evm-tests/src/contracts/crowdloan.ts rename to contract-tests/src/contracts/crowdloan.ts diff --git a/evm-tests/src/contracts/incremental.sol b/contract-tests/src/contracts/incremental.sol similarity index 100% rename from evm-tests/src/contracts/incremental.sol rename to contract-tests/src/contracts/incremental.sol diff --git a/evm-tests/src/contracts/incremental.ts b/contract-tests/src/contracts/incremental.ts similarity index 100% rename from evm-tests/src/contracts/incremental.ts rename to contract-tests/src/contracts/incremental.ts diff --git a/evm-tests/src/contracts/leasing.ts b/contract-tests/src/contracts/leasing.ts similarity index 100% rename from evm-tests/src/contracts/leasing.ts rename to contract-tests/src/contracts/leasing.ts diff --git a/evm-tests/src/contracts/metagraph.ts b/contract-tests/src/contracts/metagraph.ts similarity index 100% rename from evm-tests/src/contracts/metagraph.ts rename to contract-tests/src/contracts/metagraph.ts diff --git a/evm-tests/src/contracts/neuron.ts b/contract-tests/src/contracts/neuron.ts similarity index 100% rename from evm-tests/src/contracts/neuron.ts rename to contract-tests/src/contracts/neuron.ts diff --git a/contract-tests/src/contracts/precompileGas.sol b/contract-tests/src/contracts/precompileGas.sol new file mode 100644 index 0000000000..ee31bce61d --- /dev/null +++ b/contract-tests/src/contracts/precompileGas.sol @@ -0,0 +1,62 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.23; + +interface ISR25519Verify { + function verify( + bytes32 message, + bytes32 publicKey, + bytes32 r, + bytes32 s + ) external pure returns (bool); +} + +interface IED25519Verify { + function verify( + bytes32 message, + bytes32 publicKey, + bytes32 r, + bytes32 s + ) external pure returns (bool); +} + +contract PrecompileGas { + address constant IED25519VERIFY_ADDRESS = + 0x0000000000000000000000000000000000000402; + address constant ISR25519VERIFY_ADDRESS = + 0x0000000000000000000000000000000000000403; + IED25519Verify constant ed25519 = IED25519Verify(IED25519VERIFY_ADDRESS); + ISR25519Verify constant sr25519 = ISR25519Verify(ISR25519VERIFY_ADDRESS); + + event Log(string message); + + bytes32 message = + 0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef; + bytes32 publicKey = + 0x0000000000000000000000000000000000000000000000000000000000000000; + bytes32 r = + 0x0000000000000000000000000000000000000000000000000000000000000000; + bytes32 s = + 0x0000000000000000000000000000000000000000000000000000000000000000; + + /** + * @notice Call the precompile using hardcoded signature data + * @param iterations Number of times to call the precompile + */ + function callED25519(uint64 iterations) external { + for (uint64 i = 0; i < iterations; i++) { + ed25519.verify(message, publicKey, r, s); + } + emit Log("callED25519"); + } + + /** + * @notice Call the precompile using hardcoded signature data + * @param iterations Number of times to call the precompile + */ + function callSR25519(uint64 iterations) external { + for (uint64 i = 0; i < iterations; i++) { + sr25519.verify(message, publicKey, r, s); + } + emit Log("callSR25519"); + } +} diff --git a/contract-tests/src/contracts/precompileGas.ts b/contract-tests/src/contracts/precompileGas.ts new file mode 100644 index 0000000000..d94cfd5d26 --- /dev/null +++ b/contract-tests/src/contracts/precompileGas.ts @@ -0,0 +1,44 @@ + +export const PrecompileGas_CONTRACT_ABI = [ + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "string", + "name": "message", + "type": "string" + } + ], + "name": "Log", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "iterations", + "type": "uint64" + } + ], + "name": "callED25519", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "iterations", + "type": "uint64" + } + ], + "name": "callSR25519", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] + +export const PrecompileGas_CONTRACT_BYTECODE = "60806040527f1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef5f1b5f555f5f1b6001555f5f1b6002555f5f1b6003553480156045575f5ffd5b5061048b806100535f395ff3fe608060405234801561000f575f5ffd5b5060043610610034575f3560e01c806356554a5714610038578063bd9cac2b14610054575b5f5ffd5b610052600480360381019061004d919061028f565b610070565b005b61006e6004803603810190610069919061028f565b61015f565b005b5f5f90505b8167ffffffffffffffff168167ffffffffffffffff1610156101265761040373ffffffffffffffffffffffffffffffffffffffff1663869adcb95f546001546002546003546040518563ffffffff1660e01b81526004016100d994939291906102d2565b602060405180830381865afa1580156100f4573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610118919061034a565b508080600101915050610075565b507fcf34ef537ac33ee1ac626ca1587a0a7e8e51561e5514f8cb36afa1c5102b3bab604051610154906103cf565b60405180910390a150565b5f5f90505b8167ffffffffffffffff168167ffffffffffffffff1610156102155761040273ffffffffffffffffffffffffffffffffffffffff1663869adcb95f546001546002546003546040518563ffffffff1660e01b81526004016101c894939291906102d2565b602060405180830381865afa1580156101e3573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610207919061034a565b508080600101915050610164565b507fcf34ef537ac33ee1ac626ca1587a0a7e8e51561e5514f8cb36afa1c5102b3bab60405161024390610437565b60405180910390a150565b5f5ffd5b5f67ffffffffffffffff82169050919050565b61026e81610252565b8114610278575f5ffd5b50565b5f8135905061028981610265565b92915050565b5f602082840312156102a4576102a361024e565b5b5f6102b18482850161027b565b91505092915050565b5f819050919050565b6102cc816102ba565b82525050565b5f6080820190506102e55f8301876102c3565b6102f260208301866102c3565b6102ff60408301856102c3565b61030c60608301846102c3565b95945050505050565b5f8115159050919050565b61032981610315565b8114610333575f5ffd5b50565b5f8151905061034481610320565b92915050565b5f6020828403121561035f5761035e61024e565b5b5f61036c84828501610336565b91505092915050565b5f82825260208201905092915050565b7f63616c6c535232353531390000000000000000000000000000000000000000005f82015250565b5f6103b9600b83610375565b91506103c482610385565b602082019050919050565b5f6020820190508181035f8301526103e6816103ad565b9050919050565b7f63616c6c454432353531390000000000000000000000000000000000000000005f82015250565b5f610421600b83610375565b915061042c826103ed565b602082019050919050565b5f6020820190508181035f83015261044e81610415565b905091905056fea26469706673582212202addcdae9c59ee78157cddedc3148678edf455132bdfc62347f85e7c660b4d2164736f6c634300081e0033" \ No newline at end of file diff --git a/contract-tests/src/contracts/proxy.ts b/contract-tests/src/contracts/proxy.ts new file mode 100644 index 0000000000..48ffd0a50f --- /dev/null +++ b/contract-tests/src/contracts/proxy.ts @@ -0,0 +1,148 @@ +export const IPROXY_ADDRESS = "0x000000000000000000000000000000000000080b"; + +export const IProxyABI = [ + { + "inputs": [ + { + "internalType": "uint8", + "name": "proxy_type", + "type": "uint8" + }, + { + "internalType": "uint32", + "name": "delay", + "type": "uint32" + }, + { + "internalType": "uint16", + "name": "index", + "type": "uint16" + } + ], + "name": "createPureProxy", + "outputs": [ + { + "internalType": "bytes32", + "name": "proxy", + "type": "bytes32" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "spawner", + "type": "bytes32" + }, + { + "internalType": "uint8", + "name": "proxy_type", + "type": "uint8" + }, + { + "internalType": "uint16", + "name": "index", + "type": "uint16" + }, + { + "internalType": "uint32", + "name": "height", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "ext_index", + "type": "uint32" + } + ], + "name": "killPureProxy", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "real", + "type": "bytes32" + }, + { + "internalType": "uint8[]", + "name": "force_proxy_type", // optional + "type": "uint8[]" + }, + { + "internalType": "uint8[]", + "name": "call", + "type": "uint8[]" + } + ], + "name": "proxyCall", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "removeProxies", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, { + "inputs": [], + "name": "pokeDeposit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "delegate", + "type": "bytes32" + }, + { + "internalType": "uint8", + "name": "proxy_type", + "type": "uint8" + }, + { + "internalType": "uint32", + "name": "delay", + "type": "uint32" + } + ], + "name": "removeProxy", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "delegate", + "type": "bytes32" + }, + { + "internalType": "uint8", + "name": "proxy_type", + "type": "uint8" + }, + { + "internalType": "uint32", + "name": "delay", + "type": "uint32" + } + ], + "name": "addProxy", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +]; diff --git a/evm-tests/src/contracts/stakeWrap.sol b/contract-tests/src/contracts/stakeWrap.sol similarity index 100% rename from evm-tests/src/contracts/stakeWrap.sol rename to contract-tests/src/contracts/stakeWrap.sol diff --git a/evm-tests/src/contracts/stakeWrap.ts b/contract-tests/src/contracts/stakeWrap.ts similarity index 100% rename from evm-tests/src/contracts/stakeWrap.ts rename to contract-tests/src/contracts/stakeWrap.ts diff --git a/evm-tests/src/contracts/staking.ts b/contract-tests/src/contracts/staking.ts similarity index 100% rename from evm-tests/src/contracts/staking.ts rename to contract-tests/src/contracts/staking.ts diff --git a/evm-tests/src/contracts/subnet.ts b/contract-tests/src/contracts/subnet.ts similarity index 100% rename from evm-tests/src/contracts/subnet.ts rename to contract-tests/src/contracts/subnet.ts diff --git a/evm-tests/src/contracts/uidLookup.ts b/contract-tests/src/contracts/uidLookup.ts similarity index 100% rename from evm-tests/src/contracts/uidLookup.ts rename to contract-tests/src/contracts/uidLookup.ts diff --git a/evm-tests/src/contracts/withdraw.sol b/contract-tests/src/contracts/withdraw.sol similarity index 100% rename from evm-tests/src/contracts/withdraw.sol rename to contract-tests/src/contracts/withdraw.sol diff --git a/evm-tests/src/contracts/withdraw.ts b/contract-tests/src/contracts/withdraw.ts similarity index 100% rename from evm-tests/src/contracts/withdraw.ts rename to contract-tests/src/contracts/withdraw.ts diff --git a/evm-tests/src/eth.ts b/contract-tests/src/eth.ts similarity index 100% rename from evm-tests/src/eth.ts rename to contract-tests/src/eth.ts diff --git a/evm-tests/src/setup.ts b/contract-tests/src/setup.ts similarity index 100% rename from evm-tests/src/setup.ts rename to contract-tests/src/setup.ts diff --git a/evm-tests/src/substrate.ts b/contract-tests/src/substrate.ts similarity index 98% rename from evm-tests/src/substrate.ts rename to contract-tests/src/substrate.ts index 6f3acc866c..c7c9efe3d9 100644 --- a/evm-tests/src/substrate.ts +++ b/contract-tests/src/substrate.ts @@ -17,6 +17,7 @@ export type ClientUrlType = 'ws://localhost:9944' export async function getDevnetApi() { if (api === undefined) { let client = await getClient() + api = client.getTypedApi(devnet) } return api @@ -75,9 +76,9 @@ export function getRandomSubstrateKeypair() { return hdkdKeyPair } -export async function getBalance(api: TypedApi) { - const value = await api.query.Balances.Account.getValue("") - return value +export async function getBalance(api: TypedApi, ss58Address: string) { + const value = await api.query.System.Account.getValue(ss58Address) + return value.data.free } export async function getNonce(api: TypedApi, ss58Address: string): Promise { diff --git a/evm-tests/src/subtensor.ts b/contract-tests/src/subtensor.ts similarity index 96% rename from evm-tests/src/subtensor.ts rename to contract-tests/src/subtensor.ts index 63a5ef6e8e..12d652a9a3 100644 --- a/evm-tests/src/subtensor.ts +++ b/contract-tests/src/subtensor.ts @@ -1,6 +1,6 @@ import * as assert from "assert"; import { devnet, MultiAddress } from '@polkadot-api/descriptors'; -import { TypedApi, TxCallData } from 'polkadot-api'; +import { TypedApi, TxCallData, Binary, Enum } from 'polkadot-api'; import { KeyPair } from "@polkadot-labs/hdkd-helpers" import { getAliceSigner, waitForTransactionCompletion, getSignerFromKeypair, waitForTransactionWithRetry } from './substrate' import { convertH160ToSS58, convertPublicKeyToSs58, ethAddressToH160 } from './address-utils' @@ -384,3 +384,18 @@ export async function disableAdminFreezeWindowAndOwnerHyperparamRateLimit(api: T assert.equal(0, await api.query.SubtensorModule.AdminFreezeWindow.getValue()) assert.equal(BigInt(0), await api.query.SubtensorModule.OwnerHyperparamRateLimit.getValue()) } + +export async function sendWasmContractExtrinsic(api: TypedApi, coldkey: KeyPair, contractAddress: string, data: Binary) { + const signer = getSignerFromKeypair(coldkey) + const tx = await api.tx.Contracts.call({ + value: BigInt(0), + dest: MultiAddress.Id(contractAddress), + data: Binary.fromBytes(data.asBytes()), + gas_limit: { + ref_time: BigInt(10000000000), + proof_size: BigInt(10000000), + }, + storage_deposit_limit: BigInt(1000000000) + }) + await waitForTransactionWithRetry(api, tx, signer) +} \ No newline at end of file diff --git a/evm-tests/src/utils.ts b/contract-tests/src/utils.ts similarity index 100% rename from evm-tests/src/utils.ts rename to contract-tests/src/utils.ts diff --git a/evm-tests/test/alpha.precompile.test.ts b/contract-tests/test/alpha.precompile.test.ts similarity index 100% rename from evm-tests/test/alpha.precompile.test.ts rename to contract-tests/test/alpha.precompile.test.ts diff --git a/evm-tests/test/alphaPool.test.ts b/contract-tests/test/alphaPool.test.ts similarity index 100% rename from evm-tests/test/alphaPool.test.ts rename to contract-tests/test/alphaPool.test.ts diff --git a/evm-tests/test/crowdloan.precompile.test.ts b/contract-tests/test/crowdloan.precompile.test.ts similarity index 100% rename from evm-tests/test/crowdloan.precompile.test.ts rename to contract-tests/test/crowdloan.precompile.test.ts diff --git a/evm-tests/test/ed25519.precompile.verify.test.ts b/contract-tests/test/ed25519.precompile.verify.test.ts similarity index 100% rename from evm-tests/test/ed25519.precompile.verify.test.ts rename to contract-tests/test/ed25519.precompile.verify.test.ts diff --git a/evm-tests/test/eth.bridgeToken.deploy.test.ts b/contract-tests/test/eth.bridgeToken.deploy.test.ts similarity index 100% rename from evm-tests/test/eth.bridgeToken.deploy.test.ts rename to contract-tests/test/eth.bridgeToken.deploy.test.ts diff --git a/evm-tests/test/eth.chain-id.test.ts b/contract-tests/test/eth.chain-id.test.ts similarity index 100% rename from evm-tests/test/eth.chain-id.test.ts rename to contract-tests/test/eth.chain-id.test.ts diff --git a/evm-tests/test/eth.incremental.deploy.test.ts b/contract-tests/test/eth.incremental.deploy.test.ts similarity index 100% rename from evm-tests/test/eth.incremental.deploy.test.ts rename to contract-tests/test/eth.incremental.deploy.test.ts diff --git a/evm-tests/test/eth.substrate-transfer.test.ts b/contract-tests/test/eth.substrate-transfer.test.ts similarity index 100% rename from evm-tests/test/eth.substrate-transfer.test.ts rename to contract-tests/test/eth.substrate-transfer.test.ts diff --git a/evm-tests/test/evm-uid.precompile.lookup.test.ts b/contract-tests/test/evm-uid.precompile.lookup.test.ts similarity index 100% rename from evm-tests/test/evm-uid.precompile.lookup.test.ts rename to contract-tests/test/evm-uid.precompile.lookup.test.ts diff --git a/evm-tests/test/leasing.precompile.test.ts b/contract-tests/test/leasing.precompile.test.ts similarity index 100% rename from evm-tests/test/leasing.precompile.test.ts rename to contract-tests/test/leasing.precompile.test.ts diff --git a/evm-tests/test/metagraph.precompile.test.ts b/contract-tests/test/metagraph.precompile.test.ts similarity index 100% rename from evm-tests/test/metagraph.precompile.test.ts rename to contract-tests/test/metagraph.precompile.test.ts diff --git a/evm-tests/test/neuron.precompile.emission-check.test.ts b/contract-tests/test/neuron.precompile.emission-check.test.ts similarity index 96% rename from evm-tests/test/neuron.precompile.emission-check.test.ts rename to contract-tests/test/neuron.precompile.emission-check.test.ts index 8abafec907..1a2b053ed0 100644 --- a/evm-tests/test/neuron.precompile.emission-check.test.ts +++ b/contract-tests/test/neuron.precompile.emission-check.test.ts @@ -45,7 +45,7 @@ describe("Test the Neuron precompile with emission", () => { it("Burned register and check emission", async () => { let netuid = (await api.query.SubtensorModule.TotalNetworks.getValue()) - 1 - + const uid = await api.query.SubtensorModule.SubnetworkN.getValue(netuid) const contract = new ethers.Contract(INEURON_ADDRESS, INeuronABI, wallet); @@ -63,7 +63,7 @@ describe("Test the Neuron precompile with emission", () => { let i = 0; while (i < 10) { - const emission = await api.query.SubtensorModule.ServerEmission.getValue(netuid) + const emission = await api.query.SubtensorModule.Emission.getValue(netuid) console.log("emission is ", emission); await new Promise((resolve) => setTimeout(resolve, 2000)); diff --git a/evm-tests/test/neuron.precompile.reveal-weights.test.ts b/contract-tests/test/neuron.precompile.reveal-weights.test.ts similarity index 100% rename from evm-tests/test/neuron.precompile.reveal-weights.test.ts rename to contract-tests/test/neuron.precompile.reveal-weights.test.ts diff --git a/evm-tests/test/neuron.precompile.serve.axon-prometheus.test.ts b/contract-tests/test/neuron.precompile.serve.axon-prometheus.test.ts similarity index 100% rename from evm-tests/test/neuron.precompile.serve.axon-prometheus.test.ts rename to contract-tests/test/neuron.precompile.serve.axon-prometheus.test.ts diff --git a/evm-tests/test/neuron.precompile.set-weights.test.ts b/contract-tests/test/neuron.precompile.set-weights.test.ts similarity index 100% rename from evm-tests/test/neuron.precompile.set-weights.test.ts rename to contract-tests/test/neuron.precompile.set-weights.test.ts diff --git a/contract-tests/test/precompileGas.test.ts b/contract-tests/test/precompileGas.test.ts new file mode 100644 index 0000000000..120d7fdd79 --- /dev/null +++ b/contract-tests/test/precompileGas.test.ts @@ -0,0 +1,88 @@ +import * as assert from "assert"; +import { generateRandomEthersWallet, getPublicClient } from "../src/utils"; +import { ETH_LOCAL_URL } from "../src/config"; +import { getBalance, getDevnetApi } from "../src/substrate"; +import { forceSetBalanceToEthAddress } from "../src/subtensor"; +import { PrecompileGas_CONTRACT_ABI, PrecompileGas_CONTRACT_BYTECODE } from "../src/contracts/precompileGas"; +import { ethers } from "ethers"; +import { TypedApi } from "polkadot-api"; +import { devnet } from "@polkadot-api/descriptors"; +import { disableWhiteListCheck } from "../src/subtensor"; +import { convertH160ToSS58, convertPublicKeyToSs58 } from "../src/address-utils"; + +describe("SR25519 ED25519 Precompile Gas Test", () => { + const wallet = generateRandomEthersWallet(); + let api: TypedApi; + + // scope of precompile gas usage for sr25519 and ed25519 + const minPrecompileGas = BigInt(6000); + const maxPrecompileGas = BigInt(10000); + + before(async () => { + api = await getDevnetApi(); + await forceSetBalanceToEthAddress(api, wallet.address); + await disableWhiteListCheck(api, true); + }); + + it("Can deploy and call attackHardcoded", async () => { + const fee = await api.query.BaseFee.BaseFeePerGas.getValue() + assert.ok(fee[0] > 1000000000); + const baseFee = BigInt(fee[0]) / BigInt(1000000000); + console.log("Base fee per gas:", baseFee); + + const contractFactory = new ethers.ContractFactory(PrecompileGas_CONTRACT_ABI, PrecompileGas_CONTRACT_BYTECODE, wallet); + const contractDeploy = await contractFactory.deploy(); + + const result = await contractDeploy.waitForDeployment(); + console.log("Contract deployed to:", result.target); + + + let oneIterationGas = BigInt(0); + + for (const iter of [1, 11, 101]) { + const balanceBefore = await getBalance(api, convertH160ToSS58(wallet.address)); + const contract = new ethers.Contract(result.target, PrecompileGas_CONTRACT_ABI, wallet); + const iterations = iter; + const tx = await contract.callED25519(iterations) + await tx.wait() + + const balanceAfter = await getBalance(api, convertH160ToSS58(wallet.address)); + assert.ok(balanceAfter < balanceBefore); + + const usedGas = balanceBefore - balanceAfter; + if (iterations === 1) { + oneIterationGas = usedGas; + continue; + } + + assert.ok(usedGas >= oneIterationGas); + + const precompileUsedGas = BigInt(usedGas - oneIterationGas); + assert.ok(precompileUsedGas >= minPrecompileGas * BigInt(iterations - 1) * baseFee); + assert.ok(precompileUsedGas <= maxPrecompileGas * BigInt(iterations - 1) * baseFee); + } + + for (const iter of [1, 11, 101]) { + const balanceBefore = await getBalance(api, convertH160ToSS58(wallet.address)); + const contract = new ethers.Contract(result.target, PrecompileGas_CONTRACT_ABI, wallet); + const iterations = iter; + const tx = await contract.callSR25519(iterations) + await tx.wait() + + const balanceAfter = await getBalance(api, convertH160ToSS58(wallet.address)); + assert.ok(balanceAfter < balanceBefore); + + const usedGas = balanceBefore - balanceAfter; + if (iterations === 1) { + oneIterationGas = usedGas; + continue; + } + + assert.ok(usedGas >= oneIterationGas); + + const precompileUsedGas = BigInt(usedGas - oneIterationGas); + assert.ok(precompileUsedGas >= minPrecompileGas * BigInt(iterations - 1) * baseFee); + assert.ok(precompileUsedGas <= maxPrecompileGas * BigInt(iterations - 1) * baseFee); + } + }); +}); diff --git a/contract-tests/test/pure-proxy.precompile.test.ts b/contract-tests/test/pure-proxy.precompile.test.ts new file mode 100644 index 0000000000..1a34b02cf7 --- /dev/null +++ b/contract-tests/test/pure-proxy.precompile.test.ts @@ -0,0 +1,163 @@ +import * as assert from "assert"; + +import { getAliceSigner, getDevnetApi, getRandomSubstrateKeypair } from "../src/substrate" +import { generateRandomEthersWallet } from "../src/utils"; +import { devnet, MultiAddress } from "@polkadot-api/descriptors" +import { PolkadotSigner, TypedApi } from "polkadot-api"; +import { convertH160ToPublicKey, convertH160ToSS58, convertPublicKeyToSs58 } from "../src/address-utils" +import { IProxyABI, IPROXY_ADDRESS } from "../src/contracts/proxy" +import { ethers } from 'ethers'; +import { forceSetBalanceToEthAddress, forceSetBalanceToSs58Address } from "../src/subtensor"; +import { KeyPair } from "@polkadot-labs/hdkd-helpers"; + +import { decodeAddress } from "@polkadot/util-crypto"; + +async function getTransferCallCode(api: TypedApi, receiver: KeyPair, transferAmount: number) { + + const unsignedTx = api.tx.Balances.transfer_keep_alive({ + dest: MultiAddress.Id(convertPublicKeyToSs58(receiver.publicKey)), + value: BigInt(1000000000), + }); + const encodedCallDataBytes = await unsignedTx.getEncodedData(); + + // encoded call should be 0x050300d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d02286bee + // const transferCall = encodedCallDataBytes + + const data = encodedCallDataBytes.asBytes() + + return [...data] +} + +async function getProxies(api: TypedApi, address: string) { + const entries = await api.query.Proxy.Proxies.getEntries() + const result = [] + for (const entry of entries) { + const proxyAddress = entry.keyArgs[0] + const values = entry.value + const proxies = values[0] + for (const proxy of proxies) { + if (proxy.delegate === address) { + result.push(proxyAddress) + } + } + } + return result +} + +describe("Test pure proxy precompile", () => { + const evmWallet = generateRandomEthersWallet(); + const evmWallet2 = generateRandomEthersWallet(); + const evmWallet3 = generateRandomEthersWallet(); + const receiver = getRandomSubstrateKeypair(); + + let api: TypedApi + + let alice: PolkadotSigner; + + before(async () => { + api = await getDevnetApi() + alice = await getAliceSigner(); + + await forceSetBalanceToEthAddress(api, evmWallet.address) + await forceSetBalanceToEthAddress(api, evmWallet2.address) + await forceSetBalanceToEthAddress(api, evmWallet3.address) + }) + + it("Call createPureProxy, then use proxy to call transfer", async () => { + const proxies = await getProxies(api, convertH160ToSS58(evmWallet.address)) + const contract = new ethers.Contract(IPROXY_ADDRESS, IProxyABI, evmWallet) + console.log("evmWallet", evmWallet.address) + + const type = 0; + const delay = 0; + const index = 0; + const tx = await contract.createPureProxy(type, delay, index) + const response = await tx.wait() + console.log("response", response.blockNumber) + + const proxiesAfterAdd = await getProxies(api, convertH160ToSS58(evmWallet.address)) + + const length = proxiesAfterAdd.length + assert.equal(length, proxies.length + 1, "proxy should be set") + const proxy = proxiesAfterAdd[proxiesAfterAdd.length - 1] + + await forceSetBalanceToSs58Address(api, proxy) + const balance = (await api.query.System.Account.getValue(convertPublicKeyToSs58(receiver.publicKey))).data.free + + const amount = 1000000000; + + const callCode = await getTransferCallCode(api, receiver, amount) + const tx2 = await contract.proxyCall(decodeAddress(proxy), [type], callCode) + await tx2.wait() + + const balanceAfter = (await api.query.System.Account.getValue(convertPublicKeyToSs58(receiver.publicKey))).data.free + assert.equal(balanceAfter, balance + BigInt(amount), "balance should be increased") + }) + + it("Call createPureProxy, add multiple proxies", async () => { + const contract = new ethers.Contract(IPROXY_ADDRESS, IProxyABI, evmWallet) + const type = 0; + const delay = 0; + const index = 0; + const proxies = await getProxies(api, convertH160ToSS58(evmWallet.address)) + const length = proxies.length + for (let i = 0; i < 5; i++) { + const tx = await contract.createPureProxy(type, delay, index) + await tx.wait() + + await new Promise(resolve => setTimeout(resolve, 500)); + const currentProxies = await getProxies(api, convertH160ToSS58(evmWallet.address)) + assert.equal(currentProxies.length, length + i + 1, "proxy should be set") + } + }) + + it("Call createPureProxy, edge cases, call via wrong proxy", async () => { + const contract = new ethers.Contract(IPROXY_ADDRESS, IProxyABI, evmWallet2) + const amount = 1000000000; + const callCode = await getTransferCallCode(api, receiver, amount) + const type = 0; + + // call with wrong proxy + try { + const tx = await contract.proxyCall(receiver, [type], callCode) + await tx.wait() + } catch (error) { + assert.notEqual(error, undefined, "should fail if proxy not set") + } + }) + + it("Call createProxy, then use proxy to call transfer", async () => { + const proxies = await api.query.Proxy.Proxies.getValue(convertH160ToSS58(evmWallet2.address)) + const contract = new ethers.Contract(IPROXY_ADDRESS, IProxyABI, evmWallet2) + + const type = 0; + const delay = 0; + + const tx = await contract.addProxy(convertH160ToPublicKey(evmWallet3.address), type, delay) + await tx.wait() + + + const proxiesAfterAdd = await await api.query.Proxy.Proxies.getValue(convertH160ToSS58(evmWallet2.address)) + + const length = proxiesAfterAdd[0].length + assert.equal(length, proxies[0].length + 1, "proxy should be set") + const proxy = proxiesAfterAdd[0][proxiesAfterAdd[0].length - 1] + + assert.equal(proxy.delegate, convertH160ToSS58(evmWallet3.address), "proxy should be set") + + + const balance = (await api.query.System.Account.getValue(convertPublicKeyToSs58(receiver.publicKey))).data.free + + const amount = 1000000000; + + const contract2 = new ethers.Contract(IPROXY_ADDRESS, IProxyABI, evmWallet3) + + + const callCode = await getTransferCallCode(api, receiver, amount) + const tx2 = await contract2.proxyCall(convertH160ToPublicKey(evmWallet2.address), [type], callCode) + await tx2.wait() + + const balanceAfter = (await api.query.System.Account.getValue(convertPublicKeyToSs58(receiver.publicKey))).data.free + assert.equal(balanceAfter, balance + BigInt(amount), "balance should be increased") + }) +}); diff --git a/evm-tests/test/runtime.call.precompile.test.ts b/contract-tests/test/runtime.call.precompile.test.ts similarity index 100% rename from evm-tests/test/runtime.call.precompile.test.ts rename to contract-tests/test/runtime.call.precompile.test.ts diff --git a/evm-tests/test/sr25519.precompile.verify.test.ts b/contract-tests/test/sr25519.precompile.verify.test.ts similarity index 100% rename from evm-tests/test/sr25519.precompile.verify.test.ts rename to contract-tests/test/sr25519.precompile.verify.test.ts diff --git a/evm-tests/test/staking.precompile.add-remove.test.ts b/contract-tests/test/staking.precompile.add-remove.test.ts similarity index 100% rename from evm-tests/test/staking.precompile.add-remove.test.ts rename to contract-tests/test/staking.precompile.add-remove.test.ts diff --git a/evm-tests/test/staking.precompile.burn-alpha.test.ts b/contract-tests/test/staking.precompile.burn-alpha.test.ts similarity index 100% rename from evm-tests/test/staking.precompile.burn-alpha.test.ts rename to contract-tests/test/staking.precompile.burn-alpha.test.ts diff --git a/evm-tests/test/staking.precompile.full-limit.test.ts b/contract-tests/test/staking.precompile.full-limit.test.ts similarity index 100% rename from evm-tests/test/staking.precompile.full-limit.test.ts rename to contract-tests/test/staking.precompile.full-limit.test.ts diff --git a/evm-tests/test/staking.precompile.limit.test.ts b/contract-tests/test/staking.precompile.limit.test.ts similarity index 100% rename from evm-tests/test/staking.precompile.limit.test.ts rename to contract-tests/test/staking.precompile.limit.test.ts diff --git a/evm-tests/test/staking.precompile.reward.test.ts b/contract-tests/test/staking.precompile.reward.test.ts similarity index 97% rename from evm-tests/test/staking.precompile.reward.test.ts rename to contract-tests/test/staking.precompile.reward.test.ts index 1b47239e1d..d04620c91b 100644 --- a/evm-tests/test/staking.precompile.reward.test.ts +++ b/contract-tests/test/staking.precompile.reward.test.ts @@ -74,7 +74,7 @@ describe("Test neuron precompile reward", () => { let index = 0; while (index < 60) { - const pending = await api.query.SubtensorModule.ValidatorEmission.getValue(netuid); + const pending = await api.query.SubtensorModule.PendingValidatorEmission.getValue(netuid); if (pending > 0) { console.log("pending amount is ", pending); break; diff --git a/evm-tests/test/staking.precompile.stake-get.test.ts b/contract-tests/test/staking.precompile.stake-get.test.ts similarity index 100% rename from evm-tests/test/staking.precompile.stake-get.test.ts rename to contract-tests/test/staking.precompile.stake-get.test.ts diff --git a/evm-tests/test/staking.precompile.wrap.test.ts b/contract-tests/test/staking.precompile.wrap.test.ts similarity index 100% rename from evm-tests/test/staking.precompile.wrap.test.ts rename to contract-tests/test/staking.precompile.wrap.test.ts diff --git a/evm-tests/test/subnet.precompile.hyperparameter.test.ts b/contract-tests/test/subnet.precompile.hyperparameter.test.ts similarity index 100% rename from evm-tests/test/subnet.precompile.hyperparameter.test.ts rename to contract-tests/test/subnet.precompile.hyperparameter.test.ts diff --git a/contract-tests/test/wasm.contract.test.ts b/contract-tests/test/wasm.contract.test.ts new file mode 100644 index 0000000000..680a4a56f2 --- /dev/null +++ b/contract-tests/test/wasm.contract.test.ts @@ -0,0 +1,566 @@ +import { getDevnetApi, getRandomSubstrateKeypair, getSignerFromKeypair, waitForTransactionWithRetry } from "../src/substrate" +import { devnet, MultiAddress } from "@polkadot-api/descriptors"; +import { Binary, TypedApi } from "polkadot-api"; +import * as assert from "assert"; +import { contracts } from "../.papi/descriptors"; +import { getInkClient, InkClient, } from "@polkadot-api/ink-contracts" +import { forceSetBalanceToSs58Address, startCall, burnedRegister } from "../src/subtensor"; +import fs from "fs" +import { convertPublicKeyToSs58 } from "../src/address-utils"; +import { addNewSubnetwork, sendWasmContractExtrinsic } from "../src/subtensor"; +import { tao } from "../src/balance-math"; + +const bittensorWasmPath = "./bittensor/target/ink/bittensor.wasm" +const bittensorBytecode = fs.readFileSync(bittensorWasmPath) + +describe("Test wasm contract", () => { + + let api: TypedApi + const hotkey = getRandomSubstrateKeypair(); + const coldkey = getRandomSubstrateKeypair(); + + const hotkey2 = getRandomSubstrateKeypair(); + const coldkey2 = getRandomSubstrateKeypair(); + + // set initial netuid to 0 to avoid warning + let netuid: number = 0; + let contractAddress: string; + let inkClient: InkClient; + + async function addStakeWhenWithoutStake() { + const stakeBefore = (await api.apis.StakeInfoRuntimeApi.get_stake_info_for_hotkey_coldkey_netuid( + convertPublicKeyToSs58(hotkey.publicKey), + contractAddress, + netuid, + ))?.stake + + assert.ok(stakeBefore !== undefined) + if (stakeBefore > BigInt(0)) { + return; + } + + const amount = tao(100) + const message = inkClient.message("add_stake") + const data = message.encode({ + hotkey: Binary.fromBytes(hotkey.publicKey), + netuid: netuid, + amount: amount, + }) + await sendWasmContractExtrinsic(api, coldkey, contractAddress, data) + + const stake = (await api.apis.StakeInfoRuntimeApi.get_stake_info_for_hotkey_coldkey_netuid( + convertPublicKeyToSs58(hotkey.publicKey), + contractAddress, + netuid, + ))?.stake + + assert.ok(stake !== undefined) + assert.ok(stake > BigInt(0)) + } + + + before(async () => { + // init variables got from await and async + api = await getDevnetApi() + + inkClient = getInkClient(contracts.bittensor) + await forceSetBalanceToSs58Address(api, convertPublicKeyToSs58(coldkey.publicKey)) + await forceSetBalanceToSs58Address(api, convertPublicKeyToSs58(coldkey2.publicKey)) + await forceSetBalanceToSs58Address(api, convertPublicKeyToSs58(hotkey.publicKey)) + await forceSetBalanceToSs58Address(api, convertPublicKeyToSs58(hotkey2.publicKey)) + netuid = await addNewSubnetwork(api, hotkey, coldkey) + await startCall(api, netuid, coldkey) + console.log("test the case on subnet ", netuid) + await burnedRegister(api, netuid, convertPublicKeyToSs58(hotkey2.publicKey), coldkey2) + + await addNewSubnetwork(api, hotkey, coldkey) + await startCall(api, netuid + 1, coldkey) + }) + + it("Can instantiate contract", async () => { + const signer = getSignerFromKeypair(coldkey); + const constructor = inkClient.constructor('new') + const data = constructor.encode() + const instantiate_with_code = await api.tx.Contracts.instantiate_with_code({ + code: Binary.fromBytes(bittensorBytecode), + storage_deposit_limit: BigInt(10000000), + value: BigInt(0), + gas_limit: { + ref_time: BigInt(1000000000), + proof_size: BigInt(1000000), + }, + data: Binary.fromBytes(data.asBytes()), + salt: Binary.fromHex("0x"), + }).signAndSubmit(signer) + + let codeStoredEvents = await api.event.Contracts.Instantiated.filter(instantiate_with_code.events) + if (codeStoredEvents.length === 0) { + throw new Error("No events found after instantiating contract call") + } + contractAddress = codeStoredEvents[0].contract + + // transfer 10 Tao to contract then we can stake + const transfer = await api.tx.Balances.transfer_keep_alive({ + dest: MultiAddress.Id(contractAddress), + value: tao(2000), + }) + await waitForTransactionWithRetry(api, transfer, signer) + + console.log("===== contractAddress", contractAddress) + }) + + + it("Can query stake info from contract", async () => { + const queryMessage = inkClient.message("get_stake_info_for_hotkey_coldkey_netuid") + + const data = queryMessage.encode({ + hotkey: Binary.fromBytes(hotkey.publicKey), + coldkey: Binary.fromBytes(coldkey.publicKey), + netuid: netuid, + }) + + const response = await api.apis.ContractsApi.call( + convertPublicKeyToSs58(hotkey.publicKey), + contractAddress, + BigInt(0), + undefined, + undefined, + Binary.fromBytes(data.asBytes()), + ) + + assert.ok(response.result.success) + const result = queryMessage.decode(response.result.value).value.value + + if (typeof result === "object" && "hotkey" in result && "coldkey" in result && "netuid" in result && "stake" in result && "locked" in result && "emission" in result && "tao_emission" in result && "drain" in result && "is_registered" in result) { + assert.equal(result.hotkey, convertPublicKeyToSs58(hotkey.publicKey)) + assert.equal(result.coldkey, convertPublicKeyToSs58(coldkey.publicKey)) + assert.equal(result.netuid, netuid) + assert.equal(result.is_registered, true) + } else { + throw new Error("result is not an object") + } + + }) + + it("Can add stake to contract", async () => { + await addStakeWhenWithoutStake() + }) + + it("Can remove stake to contract", async () => { + await addStakeWhenWithoutStake() + const stake = (await api.apis.StakeInfoRuntimeApi.get_stake_info_for_hotkey_coldkey_netuid( + convertPublicKeyToSs58(hotkey.publicKey), + contractAddress, + netuid, + ))?.stake + + assert.ok(stake !== undefined) + + let amount = stake / BigInt(2) + const message = inkClient.message("remove_stake") + const data = message.encode({ + hotkey: Binary.fromBytes(hotkey.publicKey), + netuid: netuid, + amount: amount, + }) + + await sendWasmContractExtrinsic(api, coldkey, contractAddress, data) + + const stakeAfterAddStake = (await api.apis.StakeInfoRuntimeApi.get_stake_info_for_hotkey_coldkey_netuid( + convertPublicKeyToSs58(hotkey.publicKey), + contractAddress, + netuid, + ))?.stake + + assert.ok(stakeAfterAddStake !== undefined) + assert.ok(stake !== undefined) + assert.ok(stakeAfterAddStake < stake) + }) + + it("Can unstake all from contract", async () => { + await addStakeWhenWithoutStake() + + // Get stake before unstake_all + const stakeBefore = (await api.apis.StakeInfoRuntimeApi.get_stake_info_for_hotkey_coldkey_netuid( + convertPublicKeyToSs58(hotkey.publicKey), + contractAddress, + netuid, + ))?.stake + + assert.ok(stakeBefore !== undefined && stakeBefore > BigInt(0)) + + // Call unstake_all + const unstakeMessage = inkClient.message("unstake_all") + const unstakeData = unstakeMessage.encode({ + hotkey: Binary.fromBytes(hotkey.publicKey), + }) + await sendWasmContractExtrinsic(api, coldkey, contractAddress, unstakeData) + + // Verify stake is now zero + const stakeAfter = (await api.apis.StakeInfoRuntimeApi.get_stake_info_for_hotkey_coldkey_netuid( + convertPublicKeyToSs58(hotkey.publicKey), + contractAddress, + netuid, + ))?.stake + + assert.ok(stakeAfter !== undefined) + assert.equal(stakeAfter, BigInt(0)) + }) + + it("Can unstake all alpha from contract", async () => { + await addStakeWhenWithoutStake() + // Get stake before unstake_all_alpha + const stakeBefore = (await api.apis.StakeInfoRuntimeApi.get_stake_info_for_hotkey_coldkey_netuid( + convertPublicKeyToSs58(hotkey.publicKey), + contractAddress, + netuid, + ))?.stake + + assert.ok(stakeBefore !== undefined && stakeBefore > BigInt(0)) + + // Call unstake_all_alpha + const message = inkClient.message("unstake_all_alpha") + const data = message.encode({ + hotkey: Binary.fromBytes(hotkey.publicKey), + }) + await sendWasmContractExtrinsic(api, coldkey, contractAddress, data) + + // Verify stake is now zero + const stakeAfter = (await api.apis.StakeInfoRuntimeApi.get_stake_info_for_hotkey_coldkey_netuid( + convertPublicKeyToSs58(hotkey.publicKey), + contractAddress, + netuid, + ))?.stake + + assert.ok(stakeAfter !== undefined) + assert.equal(stakeAfter, BigInt(0)) + }) + + it("Can move stake between hotkeys", async () => { + await addStakeWhenWithoutStake() + + // Get initial stakes + const originStakeBefore = (await api.apis.StakeInfoRuntimeApi.get_stake_info_for_hotkey_coldkey_netuid( + convertPublicKeyToSs58(hotkey.publicKey), + contractAddress, + netuid, + ))?.stake + + const destStakeBefore = (await api.apis.StakeInfoRuntimeApi.get_stake_info_for_hotkey_coldkey_netuid( + convertPublicKeyToSs58(hotkey2.publicKey), + contractAddress, + netuid, + ))?.stake || BigInt(0) + + assert.ok(originStakeBefore !== undefined && originStakeBefore > BigInt(0)) + + // Move stake + const moveAmount = originStakeBefore / BigInt(2) + const message = inkClient.message("move_stake") + const data = message.encode({ + origin_hotkey: Binary.fromBytes(hotkey.publicKey), + destination_hotkey: Binary.fromBytes(hotkey2.publicKey), + origin_netuid: netuid, + destination_netuid: netuid, + amount: moveAmount, + }) + await sendWasmContractExtrinsic(api, coldkey, contractAddress, data) + + // Verify stakes changed + const originStakeAfter = (await api.apis.StakeInfoRuntimeApi.get_stake_info_for_hotkey_coldkey_netuid( + convertPublicKeyToSs58(hotkey.publicKey), + contractAddress, + netuid, + ))?.stake + + const destStakeAfter = (await api.apis.StakeInfoRuntimeApi.get_stake_info_for_hotkey_coldkey_netuid( + convertPublicKeyToSs58(hotkey2.publicKey), + contractAddress, + netuid, + ))?.stake + + assert.ok(originStakeAfter !== undefined) + assert.ok(destStakeAfter !== undefined) + assert.ok(originStakeAfter < originStakeBefore!) + assert.ok(destStakeAfter > destStakeBefore) + }) + + it("Can transfer stake between coldkeys", async () => { + await addStakeWhenWithoutStake() + + // Get initial stake + const stakeBeforeOrigin = (await api.apis.StakeInfoRuntimeApi.get_stake_info_for_hotkey_coldkey_netuid( + convertPublicKeyToSs58(hotkey.publicKey), + contractAddress, + netuid, + ))?.stake + + const stakeBeforeDest = (await api.apis.StakeInfoRuntimeApi.get_stake_info_for_hotkey_coldkey_netuid( + convertPublicKeyToSs58(hotkey.publicKey), + convertPublicKeyToSs58(coldkey2.publicKey), + netuid, + ))?.stake + + assert.ok(stakeBeforeOrigin !== undefined && stakeBeforeOrigin > BigInt(0)) + assert.ok(stakeBeforeDest !== undefined) + + // Transfer stake + const transferAmount = stakeBeforeOrigin / BigInt(2) + const message = inkClient.message("transfer_stake") + const data = message.encode({ + destination_coldkey: Binary.fromBytes(coldkey2.publicKey), + hotkey: Binary.fromBytes(hotkey.publicKey), + origin_netuid: netuid, + destination_netuid: netuid, + amount: transferAmount, + }) + await sendWasmContractExtrinsic(api, coldkey, contractAddress, data) + + // Verify stake transferred + const stakeAfterOrigin = (await api.apis.StakeInfoRuntimeApi.get_stake_info_for_hotkey_coldkey_netuid( + convertPublicKeyToSs58(hotkey.publicKey), + contractAddress, + netuid, + ))?.stake + + const stakeAfterDest = (await api.apis.StakeInfoRuntimeApi.get_stake_info_for_hotkey_coldkey_netuid( + convertPublicKeyToSs58(hotkey.publicKey), + convertPublicKeyToSs58(coldkey2.publicKey), + netuid, + ))?.stake + + assert.ok(stakeAfterOrigin !== undefined) + assert.ok(stakeAfterDest !== undefined) + assert.ok(stakeAfterOrigin < stakeBeforeOrigin!) + assert.ok(stakeAfterDest > stakeBeforeDest!) + }) + + it("Can swap stake between networks", async () => { + await addStakeWhenWithoutStake() + + // Get initial stakes + const stakeBefore = (await api.apis.StakeInfoRuntimeApi.get_stake_info_for_hotkey_coldkey_netuid( + convertPublicKeyToSs58(hotkey.publicKey), + contractAddress, + netuid, + ))?.stake + + const stakeBefore2 = (await api.apis.StakeInfoRuntimeApi.get_stake_info_for_hotkey_coldkey_netuid( + convertPublicKeyToSs58(hotkey.publicKey), + contractAddress, + netuid + 1, + ))?.stake || BigInt(0) + + assert.ok(stakeBefore !== undefined && stakeBefore > BigInt(0)) + + // Swap stake + const swapAmount = stakeBefore / BigInt(2) + const message = inkClient.message("swap_stake") + const data = message.encode({ + hotkey: Binary.fromBytes(hotkey.publicKey), + origin_netuid: netuid, + destination_netuid: netuid + 1, + amount: swapAmount, + }) + await sendWasmContractExtrinsic(api, coldkey, contractAddress, data) + + // Verify stakes swapped + const stakeAfter = (await api.apis.StakeInfoRuntimeApi.get_stake_info_for_hotkey_coldkey_netuid( + convertPublicKeyToSs58(hotkey.publicKey), + contractAddress, + netuid, + ))?.stake + + const stakeAfter2 = (await api.apis.StakeInfoRuntimeApi.get_stake_info_for_hotkey_coldkey_netuid( + convertPublicKeyToSs58(hotkey.publicKey), + contractAddress, + netuid + 1, + ))?.stake + + assert.ok(stakeAfter !== undefined) + assert.ok(stakeAfter2 !== undefined) + assert.ok(stakeAfter < stakeBefore) + assert.ok(stakeAfter2 > stakeBefore2) + }) + + it("Can add stake with limit", async () => { + await addStakeWhenWithoutStake() + const stakeBefore = (await api.apis.StakeInfoRuntimeApi.get_stake_info_for_hotkey_coldkey_netuid( + convertPublicKeyToSs58(hotkey.publicKey), + contractAddress, + netuid, + ))?.stake + + assert.ok(stakeBefore !== undefined) + + const message = inkClient.message("add_stake_limit") + const data = message.encode({ + hotkey: Binary.fromBytes(hotkey.publicKey), + netuid: netuid, + amount: tao(200), + limit_price: tao(100), + allow_partial: false, + }) + await sendWasmContractExtrinsic(api, coldkey, contractAddress, data) + + // Verify stake was added + const stakeAfter = (await api.apis.StakeInfoRuntimeApi.get_stake_info_for_hotkey_coldkey_netuid( + convertPublicKeyToSs58(hotkey.publicKey), + contractAddress, + netuid, + ))?.stake + + assert.ok(stakeAfter !== undefined) + assert.ok(stakeAfter > stakeBefore!) + }) + + it("Can remove stake with limit", async () => { + await addStakeWhenWithoutStake() + const stakeBefore = (await api.apis.StakeInfoRuntimeApi.get_stake_info_for_hotkey_coldkey_netuid( + convertPublicKeyToSs58(hotkey.publicKey), + contractAddress, + netuid, + ))?.stake + + assert.ok(stakeBefore !== undefined && stakeBefore > BigInt(0)) + + const message = inkClient.message("remove_stake_limit") + const data = message.encode({ + hotkey: Binary.fromBytes(hotkey.publicKey), + netuid: netuid, + amount: stakeBefore / BigInt(2), + limit_price: tao(1), + allow_partial: false, + }) + await sendWasmContractExtrinsic(api, coldkey, contractAddress, data) + + const stakeAfter = (await api.apis.StakeInfoRuntimeApi.get_stake_info_for_hotkey_coldkey_netuid( + convertPublicKeyToSs58(hotkey.publicKey), + contractAddress, + netuid, + ))?.stake + + assert.ok(stakeAfter !== undefined) + assert.ok(stakeAfter < stakeBefore!) + }) + + it("Can swap stake with limit", async () => { + await addStakeWhenWithoutStake() + + const stakeBefore = (await api.apis.StakeInfoRuntimeApi.get_stake_info_for_hotkey_coldkey_netuid( + convertPublicKeyToSs58(hotkey.publicKey), + contractAddress, + netuid, + ))?.stake + + const stakeBefore2 = (await api.apis.StakeInfoRuntimeApi.get_stake_info_for_hotkey_coldkey_netuid( + convertPublicKeyToSs58(hotkey.publicKey), + contractAddress, + netuid + 1, + ))?.stake + + assert.ok(stakeBefore !== undefined && stakeBefore > BigInt(0)) + assert.ok(stakeBefore2 !== undefined) + + const message = inkClient.message("swap_stake_limit") + const data = message.encode({ + hotkey: Binary.fromBytes(hotkey.publicKey), + origin_netuid: netuid, + destination_netuid: netuid + 1, + amount: stakeBefore / BigInt(2), + limit_price: tao(1), + allow_partial: false, + }) + await sendWasmContractExtrinsic(api, coldkey, contractAddress, data) + + const stakeAfter = (await api.apis.StakeInfoRuntimeApi.get_stake_info_for_hotkey_coldkey_netuid( + convertPublicKeyToSs58(hotkey.publicKey), + contractAddress, + netuid, + ))?.stake + + const stakeAfter2 = (await api.apis.StakeInfoRuntimeApi.get_stake_info_for_hotkey_coldkey_netuid( + convertPublicKeyToSs58(hotkey.publicKey), + contractAddress, + netuid + 1, + ))?.stake + + assert.ok(stakeAfter !== undefined) + assert.ok(stakeAfter2 !== undefined) + assert.ok(stakeAfter < stakeBefore) + assert.ok(stakeAfter2 > stakeBefore2) + }) + + it("Can remove stake full limit", async () => { + await addStakeWhenWithoutStake() + + const stakeBefore = (await api.apis.StakeInfoRuntimeApi.get_stake_info_for_hotkey_coldkey_netuid( + convertPublicKeyToSs58(hotkey.publicKey), + contractAddress, + netuid, + ))?.stake + + assert.ok(stakeBefore !== undefined && stakeBefore > BigInt(0)) + + const message = inkClient.message("remove_stake_full_limit") + const data = message.encode({ + hotkey: Binary.fromBytes(hotkey.publicKey), + netuid: netuid, + limit_price: tao(60), + }) + await sendWasmContractExtrinsic(api, coldkey, contractAddress, data) + + const stakeAfter = (await api.apis.StakeInfoRuntimeApi.get_stake_info_for_hotkey_coldkey_netuid( + convertPublicKeyToSs58(hotkey.publicKey), + contractAddress, + netuid, + ))?.stake + + assert.ok(stakeAfter !== undefined) + assert.ok(stakeAfter < stakeBefore!) + }) + + it("Can set coldkey auto stake hotkey", async () => { + const message = inkClient.message("set_coldkey_auto_stake_hotkey") + const data = message.encode({ + netuid: netuid, + hotkey: Binary.fromBytes(hotkey2.publicKey), + }) + await sendWasmContractExtrinsic(api, coldkey, contractAddress, data) + + let autoStakeHotkey = await api.query.SubtensorModule.AutoStakeDestination.getValue( + contractAddress, + netuid, + ) + + assert.ok(autoStakeHotkey !== undefined) + assert.ok(autoStakeHotkey === convertPublicKeyToSs58(hotkey2.publicKey)) + }) + + it("Can add and remove proxy", async () => { + const message = inkClient.message("add_proxy") + const data = message.encode({ + delegate: Binary.fromBytes(hotkey2.publicKey), + }) + await sendWasmContractExtrinsic(api, coldkey, contractAddress, data) + let proxies = await api.query.Proxy.Proxies.getValue( + contractAddress, + ) + assert.ok(proxies !== undefined) + assert.ok(proxies.length > 0 && proxies[0].length > 0) + assert.ok(proxies[0][0].delegate === convertPublicKeyToSs58(hotkey2.publicKey)) + + + const removeMessage = inkClient.message("remove_proxy") + const removeData = removeMessage.encode({ + delegate: Binary.fromBytes(hotkey2.publicKey), + }) + await sendWasmContractExtrinsic(api, coldkey, contractAddress, removeData) + + let proxiesAfterRemove = await api.query.Proxy.Proxies.getValue( + contractAddress, + ) + assert.ok(proxiesAfterRemove !== undefined) + assert.ok(proxiesAfterRemove[0].length === 0) + }) +}); \ No newline at end of file diff --git a/evm-tests/tsconfig.json b/contract-tests/tsconfig.json similarity index 100% rename from evm-tests/tsconfig.json rename to contract-tests/tsconfig.json diff --git a/contract-tests/yarn.lock b/contract-tests/yarn.lock new file mode 100644 index 0000000000..625b65c07d --- /dev/null +++ b/contract-tests/yarn.lock @@ -0,0 +1,3106 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@adraffy/ens-normalize@1.10.1": + version "1.10.1" + resolved "https://registry.yarnpkg.com/@adraffy/ens-normalize/-/ens-normalize-1.10.1.tgz#63430d04bd8c5e74f8d7d049338f1cd9d4f02069" + integrity sha512-96Z2IP3mYmF1Xg2cDm8f1gWGf/HUVedQ3FMifV4kG/PQ4yEP51xDtRAEfhVNt5f/uzpNkZHwWQuUcu6D6K+Ekw== + +"@adraffy/ens-normalize@^1.10.1", "@adraffy/ens-normalize@^1.11.0": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@adraffy/ens-normalize/-/ens-normalize-1.11.1.tgz#6c2d657d4b2dfb37f8ea811dcb3e60843d4ac24a" + integrity sha512-nhCBV3quEgesuf7c7KYfperqSS14T8bYuvJ8PcLJp6znkZpFc0AuW4qBtr8eKVyPPe/8RSr7sglCWPU5eaxwKQ== + +"@babel/code-frame@^7.26.2": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.27.1.tgz#200f715e66d52a23b221a9435534a91cc13ad5be" + integrity sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg== + dependencies: + "@babel/helper-validator-identifier" "^7.27.1" + js-tokens "^4.0.0" + picocolors "^1.1.1" + +"@babel/helper-validator-identifier@^7.27.1": + version "7.28.5" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz#010b6938fab7cb7df74aa2bbc06aa503b8fe5fb4" + integrity sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q== + +"@commander-js/extra-typings@^14.0.0": + version "14.0.0" + resolved "https://registry.yarnpkg.com/@commander-js/extra-typings/-/extra-typings-14.0.0.tgz#a48b73e8e9c80d5c7538d361f9c1fb9b231643d7" + integrity sha512-hIn0ncNaJRLkZrxBIp5AsW/eXEHNKYQBh0aPdoUqNgD+Io3NIykQqpKFyKcuasZhicGaEZJX/JBSIkZ4e5x8Dg== + +"@cspotcode/source-map-support@^0.8.0": + version "0.8.1" + resolved "https://registry.yarnpkg.com/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz#00629c35a688e05a88b1cda684fb9d5e73f000a1" + integrity sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw== + dependencies: + "@jridgewell/trace-mapping" "0.3.9" + +"@esbuild/aix-ppc64@0.25.12": + version "0.25.12" + resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz#80fcbe36130e58b7670511e888b8e88a259ed76c" + integrity sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA== + +"@esbuild/android-arm64@0.25.12": + version "0.25.12" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.25.12.tgz#8aa4965f8d0a7982dc21734bf6601323a66da752" + integrity sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg== + +"@esbuild/android-arm@0.25.12": + version "0.25.12" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.25.12.tgz#300712101f7f50f1d2627a162e6e09b109b6767a" + integrity sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg== + +"@esbuild/android-x64@0.25.12": + version "0.25.12" + resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.25.12.tgz#87dfb27161202bdc958ef48bb61b09c758faee16" + integrity sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg== + +"@esbuild/darwin-arm64@0.25.12": + version "0.25.12" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.25.12.tgz#79197898ec1ff745d21c071e1c7cc3c802f0c1fd" + integrity sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg== + +"@esbuild/darwin-x64@0.25.12": + version "0.25.12" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.25.12.tgz#146400a8562133f45c4d2eadcf37ddd09718079e" + integrity sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA== + +"@esbuild/freebsd-arm64@0.25.12": + version "0.25.12" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.12.tgz#1c5f9ba7206e158fd2b24c59fa2d2c8bb47ca0fe" + integrity sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg== + +"@esbuild/freebsd-x64@0.25.12": + version "0.25.12" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.25.12.tgz#ea631f4a36beaac4b9279fa0fcc6ca29eaeeb2b3" + integrity sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ== + +"@esbuild/linux-arm64@0.25.12": + version "0.25.12" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.25.12.tgz#e1066bce58394f1b1141deec8557a5f0a22f5977" + integrity sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ== + +"@esbuild/linux-arm@0.25.12": + version "0.25.12" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.25.12.tgz#452cd66b20932d08bdc53a8b61c0e30baf4348b9" + integrity sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw== + +"@esbuild/linux-ia32@0.25.12": + version "0.25.12" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.25.12.tgz#b24f8acc45bcf54192c7f2f3be1b53e6551eafe0" + integrity sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA== + +"@esbuild/linux-loong64@0.25.12": + version "0.25.12" + resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.25.12.tgz#f9cfffa7fc8322571fbc4c8b3268caf15bd81ad0" + integrity sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng== + +"@esbuild/linux-mips64el@0.25.12": + version "0.25.12" + resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.25.12.tgz#575a14bd74644ffab891adc7d7e60d275296f2cd" + integrity sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw== + +"@esbuild/linux-ppc64@0.25.12": + version "0.25.12" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.25.12.tgz#75b99c70a95fbd5f7739d7692befe60601591869" + integrity sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA== + +"@esbuild/linux-riscv64@0.25.12": + version "0.25.12" + resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.25.12.tgz#2e3259440321a44e79ddf7535c325057da875cd6" + integrity sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w== + +"@esbuild/linux-s390x@0.25.12": + version "0.25.12" + resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.25.12.tgz#17676cabbfe5928da5b2a0d6df5d58cd08db2663" + integrity sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg== + +"@esbuild/linux-x64@0.25.12": + version "0.25.12" + resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.25.12.tgz#0583775685ca82066d04c3507f09524d3cd7a306" + integrity sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw== + +"@esbuild/netbsd-arm64@0.25.12": + version "0.25.12" + resolved "https://registry.yarnpkg.com/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.12.tgz#f04c4049cb2e252fe96b16fed90f70746b13f4a4" + integrity sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg== + +"@esbuild/netbsd-x64@0.25.12": + version "0.25.12" + resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.25.12.tgz#77da0d0a0d826d7c921eea3d40292548b258a076" + integrity sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ== + +"@esbuild/openbsd-arm64@0.25.12": + version "0.25.12" + resolved "https://registry.yarnpkg.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.12.tgz#6296f5867aedef28a81b22ab2009c786a952dccd" + integrity sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A== + +"@esbuild/openbsd-x64@0.25.12": + version "0.25.12" + resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.25.12.tgz#f8d23303360e27b16cf065b23bbff43c14142679" + integrity sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw== + +"@esbuild/openharmony-arm64@0.25.12": + version "0.25.12" + resolved "https://registry.yarnpkg.com/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.12.tgz#49e0b768744a3924be0d7fd97dd6ce9b2923d88d" + integrity sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg== + +"@esbuild/sunos-x64@0.25.12": + version "0.25.12" + resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.25.12.tgz#a6ed7d6778d67e528c81fb165b23f4911b9b13d6" + integrity sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w== + +"@esbuild/win32-arm64@0.25.12": + version "0.25.12" + resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.25.12.tgz#9ac14c378e1b653af17d08e7d3ce34caef587323" + integrity sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg== + +"@esbuild/win32-ia32@0.25.12": + version "0.25.12" + resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.25.12.tgz#918942dcbbb35cc14fca39afb91b5e6a3d127267" + integrity sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ== + +"@esbuild/win32-x64@0.25.12": + version "0.25.12" + resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.25.12.tgz#9bdad8176be7811ad148d1f8772359041f46c6c5" + integrity sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA== + +"@ethereumjs/rlp@^10.0.0": + version "10.1.0" + resolved "https://registry.yarnpkg.com/@ethereumjs/rlp/-/rlp-10.1.0.tgz#fe681ed0fd2f55ed8623c0d445353d1411703b5d" + integrity sha512-r67BJbwilammAqYI4B5okA66cNdTlFzeWxPNJOolKV52ZS/flo0tUBf4x4gxWXBgh48OgsdFV1Qp5pRoSe8IhQ== + +"@isaacs/cliui@^8.0.2": + version "8.0.2" + resolved "https://registry.yarnpkg.com/@isaacs/cliui/-/cliui-8.0.2.tgz#b37667b7bc181c168782259bab42474fbf52b550" + integrity sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA== + dependencies: + string-width "^5.1.2" + string-width-cjs "npm:string-width@^4.2.0" + strip-ansi "^7.0.1" + strip-ansi-cjs "npm:strip-ansi@^6.0.1" + wrap-ansi "^8.1.0" + wrap-ansi-cjs "npm:wrap-ansi@^7.0.0" + +"@jridgewell/gen-mapping@^0.3.2": + version "0.3.13" + resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz#6342a19f44347518c93e43b1ac69deb3c4656a1f" + integrity sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA== + dependencies: + "@jridgewell/sourcemap-codec" "^1.5.0" + "@jridgewell/trace-mapping" "^0.3.24" + +"@jridgewell/resolve-uri@^3.0.3", "@jridgewell/resolve-uri@^3.1.0": + version "3.1.2" + resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz#7a0ee601f60f99a20c7c7c5ff0c80388c1189bd6" + integrity sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw== + +"@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.14", "@jridgewell/sourcemap-codec@^1.5.0", "@jridgewell/sourcemap-codec@^1.5.5": + version "1.5.5" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz#6912b00d2c631c0d15ce1a7ab57cd657f2a8f8ba" + integrity sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og== + +"@jridgewell/trace-mapping@0.3.9": + version "0.3.9" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz#6534fd5933a53ba7cbf3a17615e273a0d1273ff9" + integrity sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ== + dependencies: + "@jridgewell/resolve-uri" "^3.0.3" + "@jridgewell/sourcemap-codec" "^1.4.10" + +"@jridgewell/trace-mapping@^0.3.24": + version "0.3.31" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz#db15d6781c931f3a251a3dac39501c98a6082fd0" + integrity sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw== + dependencies: + "@jridgewell/resolve-uri" "^3.1.0" + "@jridgewell/sourcemap-codec" "^1.4.14" + +"@noble/ciphers@^1.3.0": + version "1.3.0" + resolved "https://registry.yarnpkg.com/@noble/ciphers/-/ciphers-1.3.0.tgz#f64b8ff886c240e644e5573c097f86e5b43676dc" + integrity sha512-2I0gnIVPtfnMw9ee9h1dJG7tp81+8Ob3OJb3Mv37rx5L40/b0i7djjCVvGOVqc9AEIQyvyu1i6ypKdFw8R8gQw== + +"@noble/curves@1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.2.0.tgz#92d7e12e4e49b23105a2555c6984d41733d65c35" + integrity sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw== + dependencies: + "@noble/hashes" "1.3.2" + +"@noble/curves@1.8.1": + version "1.8.1" + resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.8.1.tgz#19bc3970e205c99e4bdb1c64a4785706bce497ff" + integrity sha512-warwspo+UYUPep0Q+vtdVB4Ugn8GGQj8iyB3gnRWsztmUHTI3S1nhdiWNsPUGL0vud7JlRRk1XEu7Lq1KGTnMQ== + dependencies: + "@noble/hashes" "1.7.1" + +"@noble/curves@1.9.1": + version "1.9.1" + resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.9.1.tgz#9654a0bc6c13420ae252ddcf975eaf0f58f0a35c" + integrity sha512-k11yZxZg+t+gWvBbIswW0yoJlu8cHOC7dhunwOzoWH/mXGBiYyR4YY6hAEK/3EUs4UpB8la1RfdRpeGsFHkWsA== + dependencies: + "@noble/hashes" "1.8.0" + +"@noble/curves@^1.3.0", "@noble/curves@^1.6.0", "@noble/curves@~1.9.0": + version "1.9.7" + resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.9.7.tgz#79d04b4758a43e4bca2cbdc62e7771352fa6b951" + integrity sha512-gbKGcRUYIjA3/zCCNaWDciTMFI0dCkvou3TL8Zmy5Nc7sJ47a0jtOeZoTaMxkuqRo9cRhjOdZJXegxYE5FN/xw== + dependencies: + "@noble/hashes" "1.8.0" + +"@noble/curves@^2.0.0", "@noble/curves@^2.0.1", "@noble/curves@~2.0.0": + version "2.0.1" + resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-2.0.1.tgz#64ba8bd5e8564a02942655602515646df1cdb3ad" + integrity sha512-vs1Az2OOTBiP4q0pwjW5aF0xp9n4MxVrmkFBxc6EKZc6ddYx5gaZiAsZoq0uRRXWbi3AT/sBqn05eRPtn1JCPw== + dependencies: + "@noble/hashes" "2.0.1" + +"@noble/curves@~1.8.1": + version "1.8.2" + resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.8.2.tgz#8f24c037795e22b90ae29e222a856294c1d9ffc7" + integrity sha512-vnI7V6lFNe0tLAuJMu+2sX+FcL14TaCWy1qiczg1VwRmPrpQCdq5ESXQMqUc2tluRNf6irBXrWbl1mGN8uaU/g== + dependencies: + "@noble/hashes" "1.7.2" + +"@noble/hashes@1.3.2": + version "1.3.2" + resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.3.2.tgz#6f26dbc8fbc7205873ce3cee2f690eba0d421b39" + integrity sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ== + +"@noble/hashes@1.7.1": + version "1.7.1" + resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.7.1.tgz#5738f6d765710921e7a751e00c20ae091ed8db0f" + integrity sha512-B8XBPsn4vT/KJAGqDzbwztd+6Yte3P4V7iafm24bxgDe/mlRuK6xmWPuCNrKt2vDafZ8MfJLlchDG/vYafQEjQ== + +"@noble/hashes@1.7.2", "@noble/hashes@~1.7.1": + version "1.7.2" + resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.7.2.tgz#d53c65a21658fb02f3303e7ee3ba89d6754c64b4" + integrity sha512-biZ0NUSxyjLLqo6KxEJ1b+C2NAx0wtDoFvCaXHGgUkeHzf3Xc1xKumFKREuT7f7DARNZ/slvYUwFG6B0f2b6hQ== + +"@noble/hashes@1.8.0", "@noble/hashes@^1.3.1", "@noble/hashes@^1.3.3", "@noble/hashes@^1.5.0", "@noble/hashes@^1.8.0", "@noble/hashes@~1.8.0": + version "1.8.0" + resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.8.0.tgz#cee43d801fcef9644b11b8194857695acd5f815a" + integrity sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A== + +"@noble/hashes@2.0.1", "@noble/hashes@^2.0.0", "@noble/hashes@^2.0.1", "@noble/hashes@~2.0.0": + version "2.0.1" + resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-2.0.1.tgz#fc1a928061d1232b0a52bb754393c37a5216c89e" + integrity sha512-XlOlEbQcE9fmuXxrVTXCTlG2nlRXa9Rj3rr5Ue/+tX+nmkgbX720YHh0VR3hBF9xDvwnb8D2shVGOwNx+ulArw== + +"@pkgjs/parseargs@^0.11.0": + version "0.11.0" + resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33" + integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg== + +"@polkadot-api/cli@0.16.3": + version "0.16.3" + resolved "https://registry.yarnpkg.com/@polkadot-api/cli/-/cli-0.16.3.tgz#d4cf7cca802d473c68612899586f721cdfac7e88" + integrity sha512-s+p3dFw1vOeyMMqhUbt1RFyqPZdR7vg6joS0v9wBvK3qX5xU+QfOOaMxXJ8fl0mJEbwoJnJsvVl4MzjsABaKCg== + dependencies: + "@commander-js/extra-typings" "^14.0.0" + "@polkadot-api/codegen" "0.20.0" + "@polkadot-api/ink-contracts" "0.4.3" + "@polkadot-api/json-rpc-provider" "0.0.4" + "@polkadot-api/known-chains" "0.9.15" + "@polkadot-api/legacy-provider" "0.3.6" + "@polkadot-api/metadata-compatibility" "0.4.1" + "@polkadot-api/observable-client" "0.17.0" + "@polkadot-api/polkadot-sdk-compat" "2.3.3" + "@polkadot-api/sm-provider" "0.1.14" + "@polkadot-api/smoldot" "0.3.14" + "@polkadot-api/substrate-bindings" "0.16.5" + "@polkadot-api/substrate-client" "0.4.7" + "@polkadot-api/utils" "0.2.0" + "@polkadot-api/wasm-executor" "^0.2.2" + "@polkadot-api/ws-provider" "0.7.4" + "@types/node" "^24.10.1" + commander "^14.0.2" + execa "^9.6.0" + fs.promises.exists "^1.1.4" + ora "^9.0.0" + read-pkg "^10.0.0" + rxjs "^7.8.2" + tsc-prog "^2.3.0" + tsup "8.5.0" + typescript "^5.9.3" + write-package "^7.2.0" + +"@polkadot-api/codegen@0.20.0": + version "0.20.0" + resolved "https://registry.yarnpkg.com/@polkadot-api/codegen/-/codegen-0.20.0.tgz#b411c9243813a6adaa53df957ee775b339ab6738" + integrity sha512-akwPArm35UZcebUFtTKcEkdBLCjYyKweGw3/tT04p/EtM4OsQ1FxhRdXZ51ScBC3JVGCFQTUO2hNsd1E6YXvlw== + dependencies: + "@polkadot-api/ink-contracts" "0.4.3" + "@polkadot-api/metadata-builders" "0.13.7" + "@polkadot-api/metadata-compatibility" "0.4.1" + "@polkadot-api/substrate-bindings" "0.16.5" + "@polkadot-api/utils" "0.2.0" + +"@polkadot-api/common-sdk-utils@0.1.0": + version "0.1.0" + resolved "https://registry.yarnpkg.com/@polkadot-api/common-sdk-utils/-/common-sdk-utils-0.1.0.tgz#01e62f512c9e9bff2c938ecc69f508040521e64c" + integrity sha512-cgA9fh8dfBai9b46XaaQmj9vwzyHStQjc/xrAvQksgF6SqvZ0yAfxVqLvGrsz/Xi3dsAdKLg09PybC7MUAMv9w== + +"@polkadot-api/descriptors@file:.papi/descriptors": + version "0.1.0-autogenerated.17248082825697549564" + +"@polkadot-api/ink-contracts@0.4.3", "@polkadot-api/ink-contracts@^0.4.1": + version "0.4.3" + resolved "https://registry.yarnpkg.com/@polkadot-api/ink-contracts/-/ink-contracts-0.4.3.tgz#1df23db2aba67d293578cf2f5eb3b0b336994024" + integrity sha512-Wl+4Dxjt0GAl+rADZEgrrqEesqX/xygTpX18TmzmspcKhb9QIZf9FJI8A5Sgtq0TKAOwsd1d/hbHVX3LgbXFXg== + dependencies: + "@polkadot-api/metadata-builders" "0.13.7" + "@polkadot-api/substrate-bindings" "0.16.5" + "@polkadot-api/utils" "0.2.0" + +"@polkadot-api/json-rpc-provider-proxy@0.2.7": + version "0.2.7" + resolved "https://registry.yarnpkg.com/@polkadot-api/json-rpc-provider-proxy/-/json-rpc-provider-proxy-0.2.7.tgz#b6d639c98ea667e36e99d8d743465b5b3247d2ba" + integrity sha512-+HM4JQXzO2GPUD2++4GOLsmFL6LO8RoLvig0HgCLuypDgfdZMlwd8KnyGHjRnVEHA5X+kvXbk84TDcAXVxTazQ== + +"@polkadot-api/json-rpc-provider-proxy@^0.1.0": + version "0.1.0" + resolved "https://registry.yarnpkg.com/@polkadot-api/json-rpc-provider-proxy/-/json-rpc-provider-proxy-0.1.0.tgz#6e191f28e7d0fbbe8b540fc51d12a0adaeba297e" + integrity sha512-8GSFE5+EF73MCuLQm8tjrbCqlgclcHBSRaswvXziJ0ZW7iw3UEMsKkkKvELayWyBuOPa2T5i1nj6gFOeIsqvrg== + +"@polkadot-api/json-rpc-provider@0.0.1", "@polkadot-api/json-rpc-provider@^0.0.1": + version "0.0.1" + resolved "https://registry.yarnpkg.com/@polkadot-api/json-rpc-provider/-/json-rpc-provider-0.0.1.tgz#333645d40ccd9bccfd1f32503f17e4e63e76e297" + integrity sha512-/SMC/l7foRjpykLTUTacIH05H3mr9ip8b5xxfwXlVezXrNVLp3Cv0GX6uItkKd+ZjzVPf3PFrDF2B2/HLSNESA== + +"@polkadot-api/json-rpc-provider@0.0.4": + version "0.0.4" + resolved "https://registry.yarnpkg.com/@polkadot-api/json-rpc-provider/-/json-rpc-provider-0.0.4.tgz#15d0c6a7ec14aa6d0dd64039f931bebea83ffdb3" + integrity sha512-9cDijLIxzHOBuq6yHqpqjJ9jBmXrctjc1OFqU+tQrS96adQze3mTIH6DTgfb/0LMrqxzxffz1HQGrIlEH00WrA== + +"@polkadot-api/known-chains@0.9.15": + version "0.9.15" + resolved "https://registry.yarnpkg.com/@polkadot-api/known-chains/-/known-chains-0.9.15.tgz#04ea0cc19483392b8a9e0ed34187580e82700a5b" + integrity sha512-VQGu2Anvnx0y0Ltd6sQB3aYzQFGsaQwf2znh+w4Oflaxln5lsjO/+trpXz/rdrdgyi0iafkhpeho/p/EGBwJ+A== + +"@polkadot-api/legacy-provider@0.3.6": + version "0.3.6" + resolved "https://registry.yarnpkg.com/@polkadot-api/legacy-provider/-/legacy-provider-0.3.6.tgz#f4a644dd40b6c30136d73cc1f53dba5a88ada018" + integrity sha512-JZQg0HVtBowFKxNrZdnMBKXmeSBD4yFlz6egEpvE97RXRvjaBzTaVuFFhBchngq9YmgFQewuWSoX5XSUW6hcEg== + dependencies: + "@polkadot-api/json-rpc-provider" "0.0.4" + "@polkadot-api/raw-client" "0.1.1" + "@polkadot-api/substrate-bindings" "0.16.5" + "@polkadot-api/utils" "0.2.0" + +"@polkadot-api/logs-provider@0.0.6": + version "0.0.6" + resolved "https://registry.yarnpkg.com/@polkadot-api/logs-provider/-/logs-provider-0.0.6.tgz#a22f6abf937208cea44c6722a80ce0e6eadfd116" + integrity sha512-4WgHlvy+xee1ADaaVf6+MlK/+jGMtsMgAzvbQOJZnP4PfQuagoTqaeayk8HYKxXGphogLlPbD06tANxcb+nvAg== + dependencies: + "@polkadot-api/json-rpc-provider" "0.0.4" + +"@polkadot-api/merkleize-metadata@1.1.27": + version "1.1.27" + resolved "https://registry.yarnpkg.com/@polkadot-api/merkleize-metadata/-/merkleize-metadata-1.1.27.tgz#5b1cfabeb1e0b318eeb4e2c3a7c0e9037b9cb588" + integrity sha512-OdKwOzzrLL0Ju3pQA9LjeQEquMcD+KtLybUAO3fVxwjxD5cyI0RwillGoAIBJvfMaZpNxnxJnD+WzNjRcr7FiQ== + dependencies: + "@polkadot-api/metadata-builders" "0.13.7" + "@polkadot-api/substrate-bindings" "0.16.5" + "@polkadot-api/utils" "0.2.0" + +"@polkadot-api/metadata-builders@0.13.7": + version "0.13.7" + resolved "https://registry.yarnpkg.com/@polkadot-api/metadata-builders/-/metadata-builders-0.13.7.tgz#10f5c2b15a02f0a5a790174e6ff2129c8c00aab0" + integrity sha512-xwggY8F/gtX7qGzz+jzP3DZvWgBWIIFQhk+r2MJ431CR+tNKeTtzGdwNocVrb9NYTK2naC9ckJS14nrNM6LWLw== + dependencies: + "@polkadot-api/substrate-bindings" "0.16.5" + "@polkadot-api/utils" "0.2.0" + +"@polkadot-api/metadata-builders@0.3.2": + version "0.3.2" + resolved "https://registry.yarnpkg.com/@polkadot-api/metadata-builders/-/metadata-builders-0.3.2.tgz#007f158c9e0546cf79ba440befc0c753ab1a6629" + integrity sha512-TKpfoT6vTb+513KDzMBTfCb/ORdgRnsS3TDFpOhAhZ08ikvK+hjHMt5plPiAX/OWkm1Wc9I3+K6W0hX5Ab7MVg== + dependencies: + "@polkadot-api/substrate-bindings" "0.6.0" + "@polkadot-api/utils" "0.1.0" + +"@polkadot-api/metadata-compatibility@0.4.1": + version "0.4.1" + resolved "https://registry.yarnpkg.com/@polkadot-api/metadata-compatibility/-/metadata-compatibility-0.4.1.tgz#5f1acc47df2e8e1336d7baee8b902efb5b8919ca" + integrity sha512-mZt4Af6oPXEHAprrckJiSZkWRVf0mqwF+Bm+703rPsezLptQid9AjSzh1hkgIkOrPbg6IhWbmMhbuJVjx9VeQA== + dependencies: + "@polkadot-api/metadata-builders" "0.13.7" + "@polkadot-api/substrate-bindings" "0.16.5" + +"@polkadot-api/observable-client@0.17.0": + version "0.17.0" + resolved "https://registry.yarnpkg.com/@polkadot-api/observable-client/-/observable-client-0.17.0.tgz#317bb8e30410c753b2eba62a56cb0d6d6d5989d8" + integrity sha512-hilb12Fg1JrlM/0nucMT85//EQltB53fmoh7YNBsZMiNpavn/3qGTO4s0JMlC/LBbddYg0nxA+DMkSVlapo7cQ== + dependencies: + "@polkadot-api/metadata-builders" "0.13.7" + "@polkadot-api/substrate-bindings" "0.16.5" + "@polkadot-api/substrate-client" "0.4.7" + "@polkadot-api/utils" "0.2.0" + +"@polkadot-api/observable-client@^0.3.0": + version "0.3.2" + resolved "https://registry.yarnpkg.com/@polkadot-api/observable-client/-/observable-client-0.3.2.tgz#fd91efee350595a6e0ecfd3f294cc80de86c0cf7" + integrity sha512-HGgqWgEutVyOBXoGOPp4+IAq6CNdK/3MfQJmhCJb8YaJiaK4W6aRGrdQuQSTPHfERHCARt9BrOmEvTXAT257Ug== + dependencies: + "@polkadot-api/metadata-builders" "0.3.2" + "@polkadot-api/substrate-bindings" "0.6.0" + "@polkadot-api/utils" "0.1.0" + +"@polkadot-api/pjs-signer@0.6.17": + version "0.6.17" + resolved "https://registry.yarnpkg.com/@polkadot-api/pjs-signer/-/pjs-signer-0.6.17.tgz#5a886c9b8fea936a02ab71d88580aa85b31c471a" + integrity sha512-bxFtyiNOchV0osh6m+1CaN4tkWF7Mo4IT9XPLZBwSybpHZgwmu2wbhgqBkVL98QMyGzud7NHfrJsTCgFU6jHGg== + dependencies: + "@polkadot-api/metadata-builders" "0.13.7" + "@polkadot-api/polkadot-signer" "0.1.6" + "@polkadot-api/signers-common" "0.1.18" + "@polkadot-api/substrate-bindings" "0.16.5" + "@polkadot-api/utils" "0.2.0" + +"@polkadot-api/polkadot-sdk-compat@2.3.3": + version "2.3.3" + resolved "https://registry.yarnpkg.com/@polkadot-api/polkadot-sdk-compat/-/polkadot-sdk-compat-2.3.3.tgz#3ce0bb5ab6857f82d78c9d2d207fc82ce7ac084d" + integrity sha512-p30po+iv4trniSJ7UZiIt/rFInvtA9Tzg65EzuRkCaQAnh54a3MPp9w/q+x+SNLEcfzVLvf8LyPnMPOIpKuj5w== + dependencies: + "@polkadot-api/json-rpc-provider" "0.0.4" + +"@polkadot-api/polkadot-signer@0.1.6": + version "0.1.6" + resolved "https://registry.yarnpkg.com/@polkadot-api/polkadot-signer/-/polkadot-signer-0.1.6.tgz#6870fd9827b282838a074380ba1a02fb3bdd5e83" + integrity sha512-X7ghAa4r7doETtjAPTb50IpfGtrBmy3BJM5WCfNKa1saK04VFY9w+vDn+hwEcM4p0PcDHt66Ts74hzvHq54d9A== + +"@polkadot-api/raw-client@0.1.1": + version "0.1.1" + resolved "https://registry.yarnpkg.com/@polkadot-api/raw-client/-/raw-client-0.1.1.tgz#4b4aac274b3de60f5d838ec5d1b2d8b041cd682d" + integrity sha512-HxalpNEo8JCYXfxKM5p3TrK8sEasTGMkGjBNLzD4TLye9IK2smdb5oTvp2yfkU1iuVBdmjr69uif4NaukOYo2g== + dependencies: + "@polkadot-api/json-rpc-provider" "0.0.4" + +"@polkadot-api/sdk-ink@^0.5.1": + version "0.5.1" + resolved "https://registry.yarnpkg.com/@polkadot-api/sdk-ink/-/sdk-ink-0.5.1.tgz#a19c5d18e1adcfa2ceb8da07265c1d82d3c828f6" + integrity sha512-9pRnghjigivvgq7375hzkoazstvPDbc0YB01Jzw1/MYKcX+YJn1p/H8SAQTWbKlz2ohFgi1nwU52a0bsmKqb/Q== + dependencies: + "@ethereumjs/rlp" "^10.0.0" + "@polkadot-api/common-sdk-utils" "0.1.0" + "@polkadot-api/substrate-bindings" "^0.16.3" + abitype "^1.1.1" + viem "^2.37.9" + +"@polkadot-api/signer@0.2.11": + version "0.2.11" + resolved "https://registry.yarnpkg.com/@polkadot-api/signer/-/signer-0.2.11.tgz#1ba8f97a6e0b503d5827c0904141fe73e05a4f06" + integrity sha512-32tqbJo6JDfc/lHg+nTveeunFRULonWoTQX9xbs70arr/tAyyZfljupdECRK8CVRx1777es/CQO3QVj8EpWtYg== + dependencies: + "@noble/hashes" "^2.0.1" + "@polkadot-api/merkleize-metadata" "1.1.27" + "@polkadot-api/polkadot-signer" "0.1.6" + "@polkadot-api/signers-common" "0.1.18" + "@polkadot-api/substrate-bindings" "0.16.5" + "@polkadot-api/utils" "0.2.0" + +"@polkadot-api/signers-common@0.1.18": + version "0.1.18" + resolved "https://registry.yarnpkg.com/@polkadot-api/signers-common/-/signers-common-0.1.18.tgz#1e717937547b65c52da24447f0b37d8def59f4fc" + integrity sha512-UQXuRZoQ+jMolEpIPF0mVXcoqQ/382fHrSOgfK5sIvjeH0HPf4P+s3IwcnwyAdpHY2gdHXYlHd/SAw7Q1gJ4EA== + dependencies: + "@polkadot-api/metadata-builders" "0.13.7" + "@polkadot-api/polkadot-signer" "0.1.6" + "@polkadot-api/substrate-bindings" "0.16.5" + "@polkadot-api/utils" "0.2.0" + +"@polkadot-api/sm-provider@0.1.14": + version "0.1.14" + resolved "https://registry.yarnpkg.com/@polkadot-api/sm-provider/-/sm-provider-0.1.14.tgz#c45a6e82729bc518c4061d7cc2a519be01451a22" + integrity sha512-QQvoeBSIwnEm8IUhGA6sBU6LNh2v7SOuVOnF77ZD7P5ELTrdmQH2Tcn0W15qGTmTG45b3Z52XsKpuQbIJ7c7XA== + dependencies: + "@polkadot-api/json-rpc-provider" "0.0.4" + "@polkadot-api/json-rpc-provider-proxy" "0.2.7" + +"@polkadot-api/smoldot@0.3.14": + version "0.3.14" + resolved "https://registry.yarnpkg.com/@polkadot-api/smoldot/-/smoldot-0.3.14.tgz#a43b2a5e057607d4746d7e679106851ffae06581" + integrity sha512-eWqO0xFQaKzqY5mRYxYuZcj1IiaLcQP+J38UQyuJgEorm+9yHVEQ/XBWoM83P+Y8TwE5IWTICp1LCVeiFQTGPQ== + dependencies: + "@types/node" "^24.5.2" + smoldot "2.0.39" + +"@polkadot-api/substrate-bindings@0.16.5", "@polkadot-api/substrate-bindings@^0.16.3": + version "0.16.5" + resolved "https://registry.yarnpkg.com/@polkadot-api/substrate-bindings/-/substrate-bindings-0.16.5.tgz#96540f01c5bb834cc2529cf19fc11b093ca15926" + integrity sha512-QFgNlBmtLtiUGTCTurxcE6UZrbI2DaQ5/gyIiC2FYfEhStL8tl20b09FRYHcSjY+lxN42Rcf9HVX+MCFWLYlpQ== + dependencies: + "@noble/hashes" "^2.0.1" + "@polkadot-api/utils" "0.2.0" + "@scure/base" "^2.0.0" + scale-ts "^1.6.1" + +"@polkadot-api/substrate-bindings@0.6.0": + version "0.6.0" + resolved "https://registry.yarnpkg.com/@polkadot-api/substrate-bindings/-/substrate-bindings-0.6.0.tgz#889b0c3ba19dc95282286506bf6e370a43ce119a" + integrity sha512-lGuhE74NA1/PqdN7fKFdE5C1gNYX357j1tWzdlPXI0kQ7h3kN0zfxNOpPUN7dIrPcOFZ6C0tRRVrBylXkI6xPw== + dependencies: + "@noble/hashes" "^1.3.1" + "@polkadot-api/utils" "0.1.0" + "@scure/base" "^1.1.1" + scale-ts "^1.6.0" + +"@polkadot-api/substrate-client@0.4.7": + version "0.4.7" + resolved "https://registry.yarnpkg.com/@polkadot-api/substrate-client/-/substrate-client-0.4.7.tgz#257a9acd3dc4ad64a097c99cce9523ba04093b03" + integrity sha512-Mmx9VKincVqfVQmq89gzDk4DN3uKwf8CxoqYvq+EiPUZ1QmMUc7X4QMwG1MXIlYdnm5LSXzn+2Jn8ik8xMgL+w== + dependencies: + "@polkadot-api/json-rpc-provider" "0.0.4" + "@polkadot-api/raw-client" "0.1.1" + "@polkadot-api/utils" "0.2.0" + +"@polkadot-api/substrate-client@^0.1.2": + version "0.1.4" + resolved "https://registry.yarnpkg.com/@polkadot-api/substrate-client/-/substrate-client-0.1.4.tgz#7a808e5cb85ecb9fa2b3a43945090a6c807430ce" + integrity sha512-MljrPobN0ZWTpn++da9vOvt+Ex+NlqTlr/XT7zi9sqPtDJiQcYl+d29hFAgpaeTqbeQKZwz3WDE9xcEfLE8c5A== + dependencies: + "@polkadot-api/json-rpc-provider" "0.0.1" + "@polkadot-api/utils" "0.1.0" + +"@polkadot-api/utils@0.1.0": + version "0.1.0" + resolved "https://registry.yarnpkg.com/@polkadot-api/utils/-/utils-0.1.0.tgz#d36937cdc465c2ea302f3278cf53157340ab33a0" + integrity sha512-MXzWZeuGxKizPx2Xf/47wx9sr/uxKw39bVJUptTJdsaQn/TGq+z310mHzf1RCGvC1diHM8f593KrnDgc9oNbJA== + +"@polkadot-api/utils@0.2.0": + version "0.2.0" + resolved "https://registry.yarnpkg.com/@polkadot-api/utils/-/utils-0.2.0.tgz#812d4c4ee282691440aed4b6ddf863651e804444" + integrity sha512-nY3i5fQJoAxU4n3bD7Fs208/KR2J95SGfVc58kDjbRYN5a84kWaGEqzjBNtP9oqht49POM8Bm9mbIrkvC1Bzuw== + +"@polkadot-api/wasm-executor@^0.2.2": + version "0.2.3" + resolved "https://registry.yarnpkg.com/@polkadot-api/wasm-executor/-/wasm-executor-0.2.3.tgz#a77d74bf95dbdec2dfa815b278a78af1cf628635" + integrity sha512-B2h1o+Qlo9idpASaHvMSoViB2I5ko5OAfwfhYF8LQDkTADK0B+SeStzNj1Qn+FG34wqTuv7HzBCdjaUgzYINJQ== + +"@polkadot-api/ws-provider@0.7.4": + version "0.7.4" + resolved "https://registry.yarnpkg.com/@polkadot-api/ws-provider/-/ws-provider-0.7.4.tgz#cffdf03beaced6e201b8904c20c8e588e4417e8b" + integrity sha512-mkk2p8wPht+ljU1xULCPMsLpNF7NHuGaufuDCIZZgopALaZpfVFJxc3qa9s6Xv8X3hM+TRoC5WknuD1ykRY99A== + dependencies: + "@polkadot-api/json-rpc-provider" "0.0.4" + "@polkadot-api/json-rpc-provider-proxy" "0.2.7" + "@types/ws" "^8.18.1" + ws "^8.18.3" + +"@polkadot-labs/hdkd-helpers@^0.0.25": + version "0.0.25" + resolved "https://registry.yarnpkg.com/@polkadot-labs/hdkd-helpers/-/hdkd-helpers-0.0.25.tgz#6f70f4836acc3f821521babd17d52ab1a92ef13a" + integrity sha512-GwHayBuyHKfzvGD0vG47NbjFeiK6rRQHQAn1syut9nt0mhXMg4yb3tJ//IyM317qWuDU3HbD2OIp5jKDEQz2/A== + dependencies: + "@noble/curves" "^2.0.0" + "@noble/hashes" "^2.0.0" + "@scure/base" "^2.0.0" + "@scure/sr25519" "^0.3.0" + scale-ts "^1.6.1" + +"@polkadot-labs/hdkd-helpers@~0.0.26": + version "0.0.26" + resolved "https://registry.yarnpkg.com/@polkadot-labs/hdkd-helpers/-/hdkd-helpers-0.0.26.tgz#06d74f16f0e4c131fd1b1cc004e4411030f33610" + integrity sha512-mp3GCSiOQeh4aPt+DYBQq6UnX/tKgYUH5F75knjW3ATSA90ifEEWWjRan0Bddt4QKYKamaDGadK9GbVREgzQFw== + dependencies: + "@noble/curves" "^2.0.1" + "@noble/hashes" "^2.0.1" + "@scure/base" "^2.0.0" + "@scure/sr25519" "^0.3.0" + scale-ts "^1.6.1" + +"@polkadot-labs/hdkd@^0.0.25": + version "0.0.25" + resolved "https://registry.yarnpkg.com/@polkadot-labs/hdkd/-/hdkd-0.0.25.tgz#cb7725792485ee5dcf0a7a8491dff1989adf5cd3" + integrity sha512-+yZJC1TE4ZKdfoILw8nGxu3H/klrYXm9GdVB0kcyQDecq320ThUmM1M4l8d1F/3QD0Nez9NwHi9t5B++OgJU5A== + dependencies: + "@polkadot-labs/hdkd-helpers" "~0.0.26" + +"@polkadot/api-augment@16.5.3": + version "16.5.3" + resolved "https://registry.yarnpkg.com/@polkadot/api-augment/-/api-augment-16.5.3.tgz#af4bf6aa7a72a82093e9a46b095bf8288d89de1e" + integrity sha512-9+8YKSS66x9qpWS+ZQ/FSm9P4mgE+icD53oAmeIykriPW2gcSTAiNufLwAjmAJAkOLcqbTD7LPjFW6xFlmtYsA== + dependencies: + "@polkadot/api-base" "16.5.3" + "@polkadot/rpc-augment" "16.5.3" + "@polkadot/types" "16.5.3" + "@polkadot/types-augment" "16.5.3" + "@polkadot/types-codec" "16.5.3" + "@polkadot/util" "^13.5.9" + tslib "^2.8.1" + +"@polkadot/api-base@16.5.3": + version "16.5.3" + resolved "https://registry.yarnpkg.com/@polkadot/api-base/-/api-base-16.5.3.tgz#16e4d89df2ccd3c0872a1115bf9ba6a7ed87cf82" + integrity sha512-M1+pY6OFQ1uOB73VQMt2JAGq/UVISVQJISqyfjiUllUc0qIzaDMkcZxRqE34Lwaib3fD3RuIpG6dXqCL9rdzJQ== + dependencies: + "@polkadot/rpc-core" "16.5.3" + "@polkadot/types" "16.5.3" + "@polkadot/util" "^13.5.9" + rxjs "^7.8.1" + tslib "^2.8.1" + +"@polkadot/api-derive@16.5.3": + version "16.5.3" + resolved "https://registry.yarnpkg.com/@polkadot/api-derive/-/api-derive-16.5.3.tgz#e27f768d8603b251acb6bcf4f486147aab09d0ba" + integrity sha512-nMsnSC/N1SK1kNhgh2FhrrR1S8bTVH+3WsuBHFRzl+txKHq232IeIn9LpebSvgZdd77PaKaYBxbhYcNaA8Ypew== + dependencies: + "@polkadot/api" "16.5.3" + "@polkadot/api-augment" "16.5.3" + "@polkadot/api-base" "16.5.3" + "@polkadot/rpc-core" "16.5.3" + "@polkadot/types" "16.5.3" + "@polkadot/types-codec" "16.5.3" + "@polkadot/util" "^13.5.9" + "@polkadot/util-crypto" "^13.5.9" + rxjs "^7.8.1" + tslib "^2.8.1" + +"@polkadot/api@16.5.3", "@polkadot/api@^16.4.6": + version "16.5.3" + resolved "https://registry.yarnpkg.com/@polkadot/api/-/api-16.5.3.tgz#d45b45a7ae33889cc774661275a7db7d30f06cf9" + integrity sha512-Ptwo0f5Qonmus7KIklsbFcGTdHtNjbTAwl5GGI8Mp0dmBc7Y/ISJpIJX49UrG6FhW6COMa0ItsU87XIWMRwI/Q== + dependencies: + "@polkadot/api-augment" "16.5.3" + "@polkadot/api-base" "16.5.3" + "@polkadot/api-derive" "16.5.3" + "@polkadot/keyring" "^13.5.9" + "@polkadot/rpc-augment" "16.5.3" + "@polkadot/rpc-core" "16.5.3" + "@polkadot/rpc-provider" "16.5.3" + "@polkadot/types" "16.5.3" + "@polkadot/types-augment" "16.5.3" + "@polkadot/types-codec" "16.5.3" + "@polkadot/types-create" "16.5.3" + "@polkadot/types-known" "16.5.3" + "@polkadot/util" "^13.5.9" + "@polkadot/util-crypto" "^13.5.9" + eventemitter3 "^5.0.1" + rxjs "^7.8.1" + tslib "^2.8.1" + +"@polkadot/keyring@^13.5.9": + version "13.5.9" + resolved "https://registry.yarnpkg.com/@polkadot/keyring/-/keyring-13.5.9.tgz#257a7614879c2674836def56776348d690902df6" + integrity sha512-bMCpHDN7U8ytxawjBZ89/he5s3AmEZuOdkM/ABcorh/flXNPfyghjFK27Gy4OKoFxX52yJ2sTHR4NxM87GuFXQ== + dependencies: + "@polkadot/util" "13.5.9" + "@polkadot/util-crypto" "13.5.9" + tslib "^2.8.0" + +"@polkadot/networks@13.5.9", "@polkadot/networks@^13.5.9": + version "13.5.9" + resolved "https://registry.yarnpkg.com/@polkadot/networks/-/networks-13.5.9.tgz#d5ed8fa0478956835ba489bd3ed10da40881b9c2" + integrity sha512-nmKUKJjiLgcih0MkdlJNMnhEYdwEml2rv/h59ll2+rAvpsVWMTLCb6Cq6q7UC44+8kiWK2UUJMkFU+3PFFxndA== + dependencies: + "@polkadot/util" "13.5.9" + "@substrate/ss58-registry" "^1.51.0" + tslib "^2.8.0" + +"@polkadot/rpc-augment@16.5.3": + version "16.5.3" + resolved "https://registry.yarnpkg.com/@polkadot/rpc-augment/-/rpc-augment-16.5.3.tgz#edd776278e848fca297fb9271da9480301d8ff91" + integrity sha512-q3Y+b0FSwbYe8Qopd4In+9KCL3eH5QmGVvimX7Z8+cvQ9+h+JUA6TP1bfpWBmYJRKlolaljsBQPBWoubchmxSw== + dependencies: + "@polkadot/rpc-core" "16.5.3" + "@polkadot/types" "16.5.3" + "@polkadot/types-codec" "16.5.3" + "@polkadot/util" "^13.5.9" + tslib "^2.8.1" + +"@polkadot/rpc-core@16.5.3": + version "16.5.3" + resolved "https://registry.yarnpkg.com/@polkadot/rpc-core/-/rpc-core-16.5.3.tgz#113e7b43caea3b8adc002ec8dc95782ee9cdd79f" + integrity sha512-UYEIRhO/1uTz/rpWLwUN9Re3c4fuTs0I9RR8dHKpKsH3jZTs1M3CtqME3NNzpGqApY1xb9tZemU/0GfHjCpeBQ== + dependencies: + "@polkadot/rpc-augment" "16.5.3" + "@polkadot/rpc-provider" "16.5.3" + "@polkadot/types" "16.5.3" + "@polkadot/util" "^13.5.9" + rxjs "^7.8.1" + tslib "^2.8.1" + +"@polkadot/rpc-provider@16.5.3": + version "16.5.3" + resolved "https://registry.yarnpkg.com/@polkadot/rpc-provider/-/rpc-provider-16.5.3.tgz#6bbf6b86bb2b0cef3f8a467ebce69e2739df3f8f" + integrity sha512-O7hD82HwjT4XJ4i/G58B52RSDM7arHXSpzahZKz4/wtb4x6d6b4JVdfZoskInadARFi5RwIWCrftwPtpRH81Fw== + dependencies: + "@polkadot/keyring" "^13.5.9" + "@polkadot/types" "16.5.3" + "@polkadot/types-support" "16.5.3" + "@polkadot/util" "^13.5.9" + "@polkadot/util-crypto" "^13.5.9" + "@polkadot/x-fetch" "^13.5.9" + "@polkadot/x-global" "^13.5.9" + "@polkadot/x-ws" "^13.5.9" + eventemitter3 "^5.0.1" + mock-socket "^9.3.1" + nock "^13.5.5" + tslib "^2.8.1" + optionalDependencies: + "@substrate/connect" "0.8.11" + +"@polkadot/types-augment@16.5.3": + version "16.5.3" + resolved "https://registry.yarnpkg.com/@polkadot/types-augment/-/types-augment-16.5.3.tgz#2a02b179d06c0e941358603045c503dc81ef6557" + integrity sha512-SfS4arJUxW6BeCEhLMVPrZwWOLte69k5+/lvEKOKHQA8Mz0MEkD4uqGZGibDjgBgdnu8N+3b+rs+Fn3YfZu4yA== + dependencies: + "@polkadot/types" "16.5.3" + "@polkadot/types-codec" "16.5.3" + "@polkadot/util" "^13.5.9" + tslib "^2.8.1" + +"@polkadot/types-codec@16.5.3": + version "16.5.3" + resolved "https://registry.yarnpkg.com/@polkadot/types-codec/-/types-codec-16.5.3.tgz#b44e54dcc7929e8b3990364868c541e4eed61abf" + integrity sha512-b+oKMrIZrsFH4pPwvGQ6lMS8oFrYAGMy9QSbytA+KDmXAgTCtShz5XGvdQabvsGCjJ45EKgkKpKynVcYh3gk8g== + dependencies: + "@polkadot/util" "^13.5.9" + "@polkadot/x-bigint" "^13.5.9" + tslib "^2.8.1" + +"@polkadot/types-create@16.5.3": + version "16.5.3" + resolved "https://registry.yarnpkg.com/@polkadot/types-create/-/types-create-16.5.3.tgz#f2b6b23be130674a2b3fe6b1d2df1a8a0a49e554" + integrity sha512-XGnBLNamPh7eQGcHNGFghA/prH7z2BsQ+9EVSbHCvw9ENr/Ow24mmmkZyMG5WM/5I6/4HRdfwFJucYt1GL/p9g== + dependencies: + "@polkadot/types-codec" "16.5.3" + "@polkadot/util" "^13.5.9" + tslib "^2.8.1" + +"@polkadot/types-known@16.5.3": + version "16.5.3" + resolved "https://registry.yarnpkg.com/@polkadot/types-known/-/types-known-16.5.3.tgz#0a323f8bddcb1a21dcfc70cde689f23831efa506" + integrity sha512-ZLAZI24bQD0C9CJWYHxrLG8QSmzRzfWa51rlSNwZ9Atsc3R+GeX1YZGc9IljpQxYJCHrCqd6X8TXpAmEJdnbKw== + dependencies: + "@polkadot/networks" "^13.5.9" + "@polkadot/types" "16.5.3" + "@polkadot/types-codec" "16.5.3" + "@polkadot/types-create" "16.5.3" + "@polkadot/util" "^13.5.9" + tslib "^2.8.1" + +"@polkadot/types-support@16.5.3": + version "16.5.3" + resolved "https://registry.yarnpkg.com/@polkadot/types-support/-/types-support-16.5.3.tgz#577effc098a2739622ff052cff2eba4f4b77a21b" + integrity sha512-ggyIRV+4Kn+aG1PiVT0PE00pAqMveyS3CuFsW9gJnKxeev4VrGfr08R4vw/61D7uIfpilkQdkXNgXAbeN09Mxg== + dependencies: + "@polkadot/util" "^13.5.9" + tslib "^2.8.1" + +"@polkadot/types@16.5.3": + version "16.5.3" + resolved "https://registry.yarnpkg.com/@polkadot/types/-/types-16.5.3.tgz#00d3ad05584ced089c8ec6e374a86d0fccc2b66d" + integrity sha512-xy9uv/X4iT7uJ7TNCoqbcMkR8ePHwNW6DgpOU+1y1zc/KSu9ZC5i+haFOL68BpmR/QXk99YfuHoKwXvteDmykw== + dependencies: + "@polkadot/keyring" "^13.5.9" + "@polkadot/types-augment" "16.5.3" + "@polkadot/types-codec" "16.5.3" + "@polkadot/types-create" "16.5.3" + "@polkadot/util" "^13.5.9" + "@polkadot/util-crypto" "^13.5.9" + rxjs "^7.8.1" + tslib "^2.8.1" + +"@polkadot/util-crypto@13.5.9", "@polkadot/util-crypto@^13.5.9": + version "13.5.9" + resolved "https://registry.yarnpkg.com/@polkadot/util-crypto/-/util-crypto-13.5.9.tgz#13dfa31f83527b0d486298bd85bbf604304caa20" + integrity sha512-foUesMhxkTk8CZ0/XEcfvHk6I0O+aICqqVJllhOpyp/ZVnrTBKBf59T6RpsXx2pCtBlMsLRvg/6Mw7RND1HqDg== + dependencies: + "@noble/curves" "^1.3.0" + "@noble/hashes" "^1.3.3" + "@polkadot/networks" "13.5.9" + "@polkadot/util" "13.5.9" + "@polkadot/wasm-crypto" "^7.5.3" + "@polkadot/wasm-util" "^7.5.3" + "@polkadot/x-bigint" "13.5.9" + "@polkadot/x-randomvalues" "13.5.9" + "@scure/base" "^1.1.7" + tslib "^2.8.0" + +"@polkadot/util@13.5.9", "@polkadot/util@^13.5.9": + version "13.5.9" + resolved "https://registry.yarnpkg.com/@polkadot/util/-/util-13.5.9.tgz#26fb10b6479a6a884101d3ad8a3198c35903481c" + integrity sha512-pIK3XYXo7DKeFRkEBNYhf3GbCHg6dKQisSvdzZwuyzA6m7YxQq4DFw4IE464ve4Z7WsJFt3a6C9uII36hl9EWw== + dependencies: + "@polkadot/x-bigint" "13.5.9" + "@polkadot/x-global" "13.5.9" + "@polkadot/x-textdecoder" "13.5.9" + "@polkadot/x-textencoder" "13.5.9" + "@types/bn.js" "^5.1.6" + bn.js "^5.2.1" + tslib "^2.8.0" + +"@polkadot/wasm-bridge@7.5.3": + version "7.5.3" + resolved "https://registry.yarnpkg.com/@polkadot/wasm-bridge/-/wasm-bridge-7.5.3.tgz#f4701e10848c80fe4bb3fcd1720ffda51ce322af" + integrity sha512-mUvwwNH+uP1wqpMuHjmEwHxRIaVc5csmb+ukycWQGhzwhpXe/0fvBEU2TQ8kwgqO2MU0FS3hN/QcIWKfPRJgxQ== + dependencies: + "@polkadot/wasm-util" "7.5.3" + tslib "^2.7.0" + +"@polkadot/wasm-crypto-asmjs@7.5.3": + version "7.5.3" + resolved "https://registry.yarnpkg.com/@polkadot/wasm-crypto-asmjs/-/wasm-crypto-asmjs-7.5.3.tgz#7b5f7f6d58b3cdf81d56b627864c8207f1eb7a48" + integrity sha512-fSbbjI+4p0U3PQ8nOz/3p7euHriSdh+2CSywNuXHa8fMaYlMqCKt9K7+HI8CQ4RZNvZWDq+Py1nEDEkM4rZrvw== + dependencies: + tslib "^2.7.0" + +"@polkadot/wasm-crypto-init@7.5.3": + version "7.5.3" + resolved "https://registry.yarnpkg.com/@polkadot/wasm-crypto-init/-/wasm-crypto-init-7.5.3.tgz#9ad66e44e3a95bfd66df4f33ea59176230e6649f" + integrity sha512-KvUpxqvW70XhuDiw/N6rM8fQ7zRjIFblw+vdJ0/wwyagwg9jrYNA9TMei5ksQd9sxGCGXN/xJmwHJXuUjkocmg== + dependencies: + "@polkadot/wasm-bridge" "7.5.3" + "@polkadot/wasm-crypto-asmjs" "7.5.3" + "@polkadot/wasm-crypto-wasm" "7.5.3" + "@polkadot/wasm-util" "7.5.3" + tslib "^2.7.0" + +"@polkadot/wasm-crypto-wasm@7.5.3": + version "7.5.3" + resolved "https://registry.yarnpkg.com/@polkadot/wasm-crypto-wasm/-/wasm-crypto-wasm-7.5.3.tgz#f10e77063bacb70f4e20b8c2427816e14bb81a6b" + integrity sha512-fc88+HyVxebB/40GVgGUOLBqyO3C571DXWPTFmtt5EX9H8gw7Jg0Bkitz7hgSVP2x4FjXpqS9UNTJ8trVH0x1A== + dependencies: + "@polkadot/wasm-util" "7.5.3" + tslib "^2.7.0" + +"@polkadot/wasm-crypto@^7.5.3": + version "7.5.3" + resolved "https://registry.yarnpkg.com/@polkadot/wasm-crypto/-/wasm-crypto-7.5.3.tgz#2b21670ff90594d1dc520d5ced149afab0e28dd2" + integrity sha512-dmKUM9vw1wrnCHGuIeOtQo1pwuSF7fkyF4TYimTn3tAa0+3cDctYBErtGxgUeqP0Bo4Q0Of4/vnHlSk5Rbt9Uw== + dependencies: + "@polkadot/wasm-bridge" "7.5.3" + "@polkadot/wasm-crypto-asmjs" "7.5.3" + "@polkadot/wasm-crypto-init" "7.5.3" + "@polkadot/wasm-crypto-wasm" "7.5.3" + "@polkadot/wasm-util" "7.5.3" + tslib "^2.7.0" + +"@polkadot/wasm-util@7.5.3", "@polkadot/wasm-util@^7.5.3": + version "7.5.3" + resolved "https://registry.yarnpkg.com/@polkadot/wasm-util/-/wasm-util-7.5.3.tgz#0619487cad6ffbe67243fff5da53669b42b397ca" + integrity sha512-hBr9bbjS+Yr7DrDUSkIIuvlTSoAlI8WXuo9YEB4C76j130u/cl+zyq6Iy/WnaTE6QH+8i9DhM8QTety6TqYnUQ== + dependencies: + tslib "^2.7.0" + +"@polkadot/x-bigint@13.5.9", "@polkadot/x-bigint@^13.5.9": + version "13.5.9" + resolved "https://registry.yarnpkg.com/@polkadot/x-bigint/-/x-bigint-13.5.9.tgz#a0b665a7c120dba02fbe4f2272762895b39e9d0f" + integrity sha512-JVW6vw3e8fkcRyN9eoc6JIl63MRxNQCP/tuLdHWZts1tcAYao0hpWUzteqJY93AgvmQ91KPsC1Kf3iuuZCi74g== + dependencies: + "@polkadot/x-global" "13.5.9" + tslib "^2.8.0" + +"@polkadot/x-fetch@^13.5.9": + version "13.5.9" + resolved "https://registry.yarnpkg.com/@polkadot/x-fetch/-/x-fetch-13.5.9.tgz#396a5a884d13d26a04c61b6e43240ca69fd72190" + integrity sha512-urwXQZtT4yYROiRdJS6zHu18J/jCoAGpbgPIAjwdqjT11t9XIq4SjuPMxD19xBRhbYe9ocWV8i1KHuoMbZgKbA== + dependencies: + "@polkadot/x-global" "13.5.9" + node-fetch "^3.3.2" + tslib "^2.8.0" + +"@polkadot/x-global@13.5.9", "@polkadot/x-global@^13.5.9": + version "13.5.9" + resolved "https://registry.yarnpkg.com/@polkadot/x-global/-/x-global-13.5.9.tgz#22d680f036a879a5aef15963f96d71dd115927a3" + integrity sha512-zSRWvELHd3Q+bFkkI1h2cWIqLo1ETm+MxkNXLec3lB56iyq/MjWBxfXnAFFYFayvlEVneo7CLHcp+YTFd9aVSA== + dependencies: + tslib "^2.8.0" + +"@polkadot/x-randomvalues@13.5.9": + version "13.5.9" + resolved "https://registry.yarnpkg.com/@polkadot/x-randomvalues/-/x-randomvalues-13.5.9.tgz#5d5e2bdef2bbd6ded99a1ff081d7d67af500c8e7" + integrity sha512-Uuuz3oubf1JCCK97fsnVUnHvk4BGp/W91mQWJlgl5TIOUSSTIRr+lb5GurCfl4kgnQq53Zi5fJV+qR9YumbnZw== + dependencies: + "@polkadot/x-global" "13.5.9" + tslib "^2.8.0" + +"@polkadot/x-textdecoder@13.5.9": + version "13.5.9" + resolved "https://registry.yarnpkg.com/@polkadot/x-textdecoder/-/x-textdecoder-13.5.9.tgz#ce6dc1177c2d89549ad5bdfe5409cb6b42182c14" + integrity sha512-W2HhVNUbC/tuFdzNMbnXAWsIHSg9SC9QWDNmFD3nXdSzlXNgL8NmuiwN2fkYvCQBtp/XSoy0gDLx0C+Fo19cfw== + dependencies: + "@polkadot/x-global" "13.5.9" + tslib "^2.8.0" + +"@polkadot/x-textencoder@13.5.9": + version "13.5.9" + resolved "https://registry.yarnpkg.com/@polkadot/x-textencoder/-/x-textencoder-13.5.9.tgz#c70f7add6e2c40c04d190160bc5c574674def78f" + integrity sha512-SG0MHnLUgn1ZxFdm0KzMdTHJ47SfqFhdIPMcGA0Mg/jt2rwrfrP3jtEIJMsHfQpHvfsNPfv55XOMmoPWuQnP/Q== + dependencies: + "@polkadot/x-global" "13.5.9" + tslib "^2.8.0" + +"@polkadot/x-ws@^13.5.9": + version "13.5.9" + resolved "https://registry.yarnpkg.com/@polkadot/x-ws/-/x-ws-13.5.9.tgz#796564254e64809619993e8ff77ad098b3b95023" + integrity sha512-NKVgvACTIvKT8CjaQu9d0dERkZsWIZngX/4NVSjc01WHmln4F4y/zyBdYn/Z2V0Zw28cISx+lB4qxRmqTe7gbg== + dependencies: + "@polkadot/x-global" "13.5.9" + tslib "^2.8.0" + ws "^8.18.0" + +"@rollup/rollup-android-arm-eabi@4.53.3": + version "4.53.3" + resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.53.3.tgz#7e478b66180c5330429dd161bf84dad66b59c8eb" + integrity sha512-mRSi+4cBjrRLoaal2PnqH82Wqyb+d3HsPUN/W+WslCXsZsyHa9ZeQQX/pQsZaVIWDkPcpV6jJ+3KLbTbgnwv8w== + +"@rollup/rollup-android-arm64@4.53.3": + version "4.53.3" + resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.53.3.tgz#2b025510c53a5e3962d3edade91fba9368c9d71c" + integrity sha512-CbDGaMpdE9sh7sCmTrTUyllhrg65t6SwhjlMJsLr+J8YjFuPmCEjbBSx4Z/e4SmDyH3aB5hGaJUP2ltV/vcs4w== + +"@rollup/rollup-darwin-arm64@4.53.3": + version "4.53.3" + resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.53.3.tgz#3577c38af68ccf34c03e84f476bfd526abca10a0" + integrity sha512-Nr7SlQeqIBpOV6BHHGZgYBuSdanCXuw09hon14MGOLGmXAFYjx1wNvquVPmpZnl0tLjg25dEdr4IQ6GgyToCUA== + +"@rollup/rollup-darwin-x64@4.53.3": + version "4.53.3" + resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.53.3.tgz#2bf5f2520a1f3b551723d274b9669ba5b75ed69c" + integrity sha512-DZ8N4CSNfl965CmPktJ8oBnfYr3F8dTTNBQkRlffnUarJ2ohudQD17sZBa097J8xhQ26AwhHJ5mvUyQW8ddTsQ== + +"@rollup/rollup-freebsd-arm64@4.53.3": + version "4.53.3" + resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.53.3.tgz#4bb9cc80252564c158efc0710153c71633f1927c" + integrity sha512-yMTrCrK92aGyi7GuDNtGn2sNW+Gdb4vErx4t3Gv/Tr+1zRb8ax4z8GWVRfr3Jw8zJWvpGHNpss3vVlbF58DZ4w== + +"@rollup/rollup-freebsd-x64@4.53.3": + version "4.53.3" + resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.53.3.tgz#2301289094d49415a380cf942219ae9d8b127440" + integrity sha512-lMfF8X7QhdQzseM6XaX0vbno2m3hlyZFhwcndRMw8fbAGUGL3WFMBdK0hbUBIUYcEcMhVLr1SIamDeuLBnXS+Q== + +"@rollup/rollup-linux-arm-gnueabihf@4.53.3": + version "4.53.3" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.53.3.tgz#1d03d776f2065e09fc141df7d143476e94acca88" + integrity sha512-k9oD15soC/Ln6d2Wv/JOFPzZXIAIFLp6B+i14KhxAfnq76ajt0EhYc5YPeX6W1xJkAdItcVT+JhKl1QZh44/qw== + +"@rollup/rollup-linux-arm-musleabihf@4.53.3": + version "4.53.3" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.53.3.tgz#8623de0e040b2fd52a541c602688228f51f96701" + integrity sha512-vTNlKq+N6CK/8UktsrFuc+/7NlEYVxgaEgRXVUVK258Z5ymho29skzW1sutgYjqNnquGwVUObAaxae8rZ6YMhg== + +"@rollup/rollup-linux-arm64-gnu@4.53.3": + version "4.53.3" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.53.3.tgz#ce2d1999bc166277935dde0301cde3dd0417fb6e" + integrity sha512-RGrFLWgMhSxRs/EWJMIFM1O5Mzuz3Xy3/mnxJp/5cVhZ2XoCAxJnmNsEyeMJtpK+wu0FJFWz+QF4mjCA7AUQ3w== + +"@rollup/rollup-linux-arm64-musl@4.53.3": + version "4.53.3" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.53.3.tgz#88c2523778444da952651a2219026416564a4899" + integrity sha512-kASyvfBEWYPEwe0Qv4nfu6pNkITLTb32p4yTgzFCocHnJLAHs+9LjUu9ONIhvfT/5lv4YS5muBHyuV84epBo/A== + +"@rollup/rollup-linux-loong64-gnu@4.53.3": + version "4.53.3" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.53.3.tgz#578ca2220a200ac4226c536c10c8cc6e4f276714" + integrity sha512-JiuKcp2teLJwQ7vkJ95EwESWkNRFJD7TQgYmCnrPtlu50b4XvT5MOmurWNrCj3IFdyjBQ5p9vnrX4JM6I8OE7g== + +"@rollup/rollup-linux-ppc64-gnu@4.53.3": + version "4.53.3" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.53.3.tgz#aa338d3effd4168a20a5023834a74ba2c3081293" + integrity sha512-EoGSa8nd6d3T7zLuqdojxC20oBfNT8nexBbB/rkxgKj5T5vhpAQKKnD+h3UkoMuTyXkP5jTjK/ccNRmQrPNDuw== + +"@rollup/rollup-linux-riscv64-gnu@4.53.3": + version "4.53.3" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.53.3.tgz#16ba582f9f6cff58119aa242782209b1557a1508" + integrity sha512-4s+Wped2IHXHPnAEbIB0YWBv7SDohqxobiiPA1FIWZpX+w9o2i4LezzH/NkFUl8LRci/8udci6cLq+jJQlh+0g== + +"@rollup/rollup-linux-riscv64-musl@4.53.3": + version "4.53.3" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.53.3.tgz#e404a77ebd6378483888b8064c703adb011340ab" + integrity sha512-68k2g7+0vs2u9CxDt5ktXTngsxOQkSEV/xBbwlqYcUrAVh6P9EgMZvFsnHy4SEiUl46Xf0IObWVbMvPrr2gw8A== + +"@rollup/rollup-linux-s390x-gnu@4.53.3": + version "4.53.3" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.53.3.tgz#92ad52d306227c56bec43d96ad2164495437ffe6" + integrity sha512-VYsFMpULAz87ZW6BVYw3I6sWesGpsP9OPcyKe8ofdg9LHxSbRMd7zrVrr5xi/3kMZtpWL/wC+UIJWJYVX5uTKg== + +"@rollup/rollup-linux-x64-gnu@4.53.3": + version "4.53.3" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.53.3.tgz#fd0dea3bb9aa07e7083579f25e1c2285a46cb9fa" + integrity sha512-3EhFi1FU6YL8HTUJZ51imGJWEX//ajQPfqWLI3BQq4TlvHy4X0MOr5q3D2Zof/ka0d5FNdPwZXm3Yyib/UEd+w== + +"@rollup/rollup-linux-x64-musl@4.53.3": + version "4.53.3" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.53.3.tgz#37a3efb09f18d555f8afc490e1f0444885de8951" + integrity sha512-eoROhjcc6HbZCJr+tvVT8X4fW3/5g/WkGvvmwz/88sDtSJzO7r/blvoBDgISDiCjDRZmHpwud7h+6Q9JxFwq1Q== + +"@rollup/rollup-openharmony-arm64@4.53.3": + version "4.53.3" + resolved "https://registry.yarnpkg.com/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.53.3.tgz#c489bec9f4f8320d42c9b324cca220c90091c1f7" + integrity sha512-OueLAWgrNSPGAdUdIjSWXw+u/02BRTcnfw9PN41D2vq/JSEPnJnVuBgw18VkN8wcd4fjUs+jFHVM4t9+kBSNLw== + +"@rollup/rollup-win32-arm64-msvc@4.53.3": + version "4.53.3" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.53.3.tgz#152832b5f79dc22d1606fac3db946283601b7080" + integrity sha512-GOFuKpsxR/whszbF/bzydebLiXIHSgsEUp6M0JI8dWvi+fFa1TD6YQa4aSZHtpmh2/uAlj/Dy+nmby3TJ3pkTw== + +"@rollup/rollup-win32-ia32-msvc@4.53.3": + version "4.53.3" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.53.3.tgz#54d91b2bb3bf3e9f30d32b72065a4e52b3a172a5" + integrity sha512-iah+THLcBJdpfZ1TstDFbKNznlzoxa8fmnFYK4V67HvmuNYkVdAywJSoteUszvBQ9/HqN2+9AZghbajMsFT+oA== + +"@rollup/rollup-win32-x64-gnu@4.53.3": + version "4.53.3" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.53.3.tgz#df9df03e61a003873efec8decd2034e7f135c71e" + integrity sha512-J9QDiOIZlZLdcot5NXEepDkstocktoVjkaKUtqzgzpt2yWjGlbYiKyp05rWwk4nypbYUNoFAztEgixoLaSETkg== + +"@rollup/rollup-win32-x64-msvc@4.53.3": + version "4.53.3" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.53.3.tgz#38ae84f4c04226c1d56a3b17296ef1e0460ecdfe" + integrity sha512-UhTd8u31dXadv0MopwGgNOBpUVROFKWVQgAg5N1ESyCz8AuBcMqm4AuTjrwgQKGDfoFuz02EuMRHQIw/frmYKQ== + +"@rx-state/core@^0.1.4": + version "0.1.4" + resolved "https://registry.yarnpkg.com/@rx-state/core/-/core-0.1.4.tgz#586dde80be9dbdac31844006a0dcaa2bc7f35a5c" + integrity sha512-Z+3hjU2xh1HisLxt+W5hlYX/eGSDaXXP+ns82gq/PLZpkXLu0uwcNUh9RLY3Clq4zT+hSsA3vcpIGt6+UAb8rQ== + +"@scure/base@^1.1.1", "@scure/base@^1.1.7", "@scure/base@~1.2.2", "@scure/base@~1.2.4", "@scure/base@~1.2.5": + version "1.2.6" + resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.2.6.tgz#ca917184b8231394dd8847509c67a0be522e59f6" + integrity sha512-g/nm5FgUa//MCj1gV09zTJTaM6KBAHqLN907YVQqf7zC49+DcO4B1so4ZX07Ef10Twr6nuqYEH9GEggFXA4Fmg== + +"@scure/base@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@scure/base/-/base-2.0.0.tgz#ba6371fddf92c2727e88ad6ab485db6e624f9a98" + integrity sha512-3E1kpuZginKkek01ovG8krQ0Z44E3DHPjc5S2rjJw9lZn3KSQOs8S7wqikF/AH7iRanHypj85uGyxk0XAyC37w== + +"@scure/bip32@1.6.2": + version "1.6.2" + resolved "https://registry.yarnpkg.com/@scure/bip32/-/bip32-1.6.2.tgz#093caa94961619927659ed0e711a6e4bf35bffd0" + integrity sha512-t96EPDMbtGgtb7onKKqxRLfE5g05k7uHnHRM2xdE6BP/ZmxaLtPek4J4KfVn/90IQNrU1IOAqMgiDtUdtbe3nw== + dependencies: + "@noble/curves" "~1.8.1" + "@noble/hashes" "~1.7.1" + "@scure/base" "~1.2.2" + +"@scure/bip32@1.7.0", "@scure/bip32@^1.5.0", "@scure/bip32@^1.7.0": + version "1.7.0" + resolved "https://registry.yarnpkg.com/@scure/bip32/-/bip32-1.7.0.tgz#b8683bab172369f988f1589640e53c4606984219" + integrity sha512-E4FFX/N3f4B80AKWp5dP6ow+flD1LQZo/w8UnLGYZO674jS6YnYeepycOOksv+vLPSpgN35wgKgy+ybfTb2SMw== + dependencies: + "@noble/curves" "~1.9.0" + "@noble/hashes" "~1.8.0" + "@scure/base" "~1.2.5" + +"@scure/bip39@1.5.4": + version "1.5.4" + resolved "https://registry.yarnpkg.com/@scure/bip39/-/bip39-1.5.4.tgz#07fd920423aa671be4540d59bdd344cc1461db51" + integrity sha512-TFM4ni0vKvCfBpohoh+/lY05i9gRbSwXWngAsF4CABQxoaOHijxuaZ2R6cStDQ5CHtHO9aGJTr4ksVJASRRyMA== + dependencies: + "@noble/hashes" "~1.7.1" + "@scure/base" "~1.2.4" + +"@scure/bip39@1.6.0", "@scure/bip39@^1.4.0", "@scure/bip39@^1.6.0": + version "1.6.0" + resolved "https://registry.yarnpkg.com/@scure/bip39/-/bip39-1.6.0.tgz#475970ace440d7be87a6086cbee77cb8f1a684f9" + integrity sha512-+lF0BbLiJNwVlev4eKelw1WWLaiKXw7sSl8T6FvBlWkdX+94aGJ4o8XjUdlyhTCjd8c+B3KT3JfS8P0bLRNU6A== + dependencies: + "@noble/hashes" "~1.8.0" + "@scure/base" "~1.2.5" + +"@scure/sr25519@^0.3.0": + version "0.3.0" + resolved "https://registry.yarnpkg.com/@scure/sr25519/-/sr25519-0.3.0.tgz#1fb075ef05086c1dc59f16bdda1327627a552352" + integrity sha512-SKsinX2sImunfcsH3seGrwH/OayBwwaJqVN8J1cJBNRCfbBq5q0jyTKGa9PcW1HWv9vXT6Yuq41JsxFLvF59ew== + dependencies: + "@noble/curves" "~2.0.0" + "@noble/hashes" "~2.0.0" + +"@sec-ant/readable-stream@^0.4.1": + version "0.4.1" + resolved "https://registry.yarnpkg.com/@sec-ant/readable-stream/-/readable-stream-0.4.1.tgz#60de891bb126abfdc5410fdc6166aca065f10a0c" + integrity sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg== + +"@sindresorhus/merge-streams@^4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/@sindresorhus/merge-streams/-/merge-streams-4.0.0.tgz#abb11d99aeb6d27f1b563c38147a72d50058e339" + integrity sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ== + +"@substrate/connect-extension-protocol@^2.0.0": + version "2.2.2" + resolved "https://registry.yarnpkg.com/@substrate/connect-extension-protocol/-/connect-extension-protocol-2.2.2.tgz#2cf8f2eaf1879308d307a1a08df83cd5db918fe0" + integrity sha512-t66jwrXA0s5Goq82ZtjagLNd7DPGCNjHeehRlE/gcJmJ+G56C0W+2plqOMRicJ8XGR1/YFnUSEqUFiSNbjGrAA== + +"@substrate/connect-known-chains@^1.1.5": + version "1.10.3" + resolved "https://registry.yarnpkg.com/@substrate/connect-known-chains/-/connect-known-chains-1.10.3.tgz#71a89864f13626c412fa0a9d0ffc4f6ca39fdcec" + integrity sha512-OJEZO1Pagtb6bNE3wCikc2wrmvEU5x7GxFFLqqbz1AJYYxSlrPCGu4N2og5YTExo4IcloNMQYFRkBGue0BKZ4w== + +"@substrate/connect@0.8.11": + version "0.8.11" + resolved "https://registry.yarnpkg.com/@substrate/connect/-/connect-0.8.11.tgz#983ec69a05231636e217b573b8130a6b942af69f" + integrity sha512-ofLs1PAO9AtDdPbdyTYj217Pe+lBfTLltdHDs3ds8no0BseoLeAGxpz1mHfi7zB4IxI3YyAiLjH6U8cw4pj4Nw== + dependencies: + "@substrate/connect-extension-protocol" "^2.0.0" + "@substrate/connect-known-chains" "^1.1.5" + "@substrate/light-client-extension-helpers" "^1.0.0" + smoldot "2.0.26" + +"@substrate/light-client-extension-helpers@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@substrate/light-client-extension-helpers/-/light-client-extension-helpers-1.0.0.tgz#7b60368c57e06e5cf798c6557422d12e6d81f1ff" + integrity sha512-TdKlni1mBBZptOaeVrKnusMg/UBpWUORNDv5fdCaJklP4RJiFOzBCrzC+CyVI5kQzsXBisZ+2pXm+rIjS38kHg== + dependencies: + "@polkadot-api/json-rpc-provider" "^0.0.1" + "@polkadot-api/json-rpc-provider-proxy" "^0.1.0" + "@polkadot-api/observable-client" "^0.3.0" + "@polkadot-api/substrate-client" "^0.1.2" + "@substrate/connect-extension-protocol" "^2.0.0" + "@substrate/connect-known-chains" "^1.1.5" + rxjs "^7.8.1" + +"@substrate/ss58-registry@^1.51.0": + version "1.51.0" + resolved "https://registry.yarnpkg.com/@substrate/ss58-registry/-/ss58-registry-1.51.0.tgz#39e0341eb4069c2d3e684b93f0d8cb0bec572383" + integrity sha512-TWDurLiPxndFgKjVavCniytBIw+t4ViOi7TYp9h/D0NMmkEc9klFTo+827eyEJ0lELpqO207Ey7uGxUa+BS1jQ== + +"@tsconfig/node10@^1.0.7": + version "1.0.12" + resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.12.tgz#be57ceac1e4692b41be9de6be8c32a106636dba4" + integrity sha512-UCYBaeFvM11aU2y3YPZ//O5Rhj+xKyzy7mvcIoAjASbigy8mHMryP5cK7dgjlz2hWxh1g5pLw084E0a/wlUSFQ== + +"@tsconfig/node12@^1.0.7": + version "1.0.11" + resolved "https://registry.yarnpkg.com/@tsconfig/node12/-/node12-1.0.11.tgz#ee3def1f27d9ed66dac6e46a295cffb0152e058d" + integrity sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag== + +"@tsconfig/node14@^1.0.0": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@tsconfig/node14/-/node14-1.0.3.tgz#e4386316284f00b98435bf40f72f75a09dabf6c1" + integrity sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow== + +"@tsconfig/node16@^1.0.2": + version "1.0.4" + resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.4.tgz#0b92dcc0cc1c81f6f306a381f28e31b1a56536e9" + integrity sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA== + +"@types/bn.js@^5.1.6": + version "5.2.0" + resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-5.2.0.tgz#4349b9710e98f9ab3cdc50f1c5e4dcbd8ef29c80" + integrity sha512-DLbJ1BPqxvQhIGbeu8VbUC1DiAiahHtAYvA0ZEAa4P31F7IaArc8z3C3BRQdWX4mtLQuABG4yzp76ZrS02Ui1Q== + dependencies: + "@types/node" "*" + +"@types/chai@^5.0.1": + version "5.2.3" + resolved "https://registry.yarnpkg.com/@types/chai/-/chai-5.2.3.tgz#8e9cd9e1c3581fa6b341a5aed5588eb285be0b4a" + integrity sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA== + dependencies: + "@types/deep-eql" "*" + assertion-error "^2.0.1" + +"@types/deep-eql@*": + version "4.0.2" + resolved "https://registry.yarnpkg.com/@types/deep-eql/-/deep-eql-4.0.2.tgz#334311971d3a07121e7eb91b684a605e7eea9cbd" + integrity sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw== + +"@types/estree@1.0.8": + version "1.0.8" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.8.tgz#958b91c991b1867ced318bedea0e215ee050726e" + integrity sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w== + +"@types/mocha@^10.0.10": + version "10.0.10" + resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-10.0.10.tgz#91f62905e8d23cbd66225312f239454a23bebfa0" + integrity sha512-xPyYSz1cMPnJQhl0CLMH68j3gprKZaTjG3s5Vi+fDgx+uhG9NOXwbVt52eFS8ECyXhyKcjDLCBEqBExKuiZb7Q== + +"@types/node@*", "@types/node@^24.10.1", "@types/node@^24.5.2": + version "24.10.1" + resolved "https://registry.yarnpkg.com/@types/node/-/node-24.10.1.tgz#91e92182c93db8bd6224fca031e2370cef9a8f01" + integrity sha512-GNWcUTRBgIRJD5zj+Tq0fKOJ5XZajIiBroOF0yvj2bSU1WvNdYS/dn9UxwsujGW4JX06dnHyjV2y9rRaybH0iQ== + dependencies: + undici-types "~7.16.0" + +"@types/node@22.7.5": + version "22.7.5" + resolved "https://registry.yarnpkg.com/@types/node/-/node-22.7.5.tgz#cfde981727a7ab3611a481510b473ae54442b92b" + integrity sha512-jML7s2NAzMWc//QSJ1a3prpk78cOPchGvXJsC3C6R6PSMoooztvRVQEz89gmBTBY1SPMaqo5teB4uNHPdetShQ== + dependencies: + undici-types "~6.19.2" + +"@types/node@^22.18.0": + version "22.19.1" + resolved "https://registry.yarnpkg.com/@types/node/-/node-22.19.1.tgz#1188f1ddc9f46b4cc3aec76749050b4e1f459b7b" + integrity sha512-LCCV0HdSZZZb34qifBsyWlUmok6W7ouER+oQIGBScS8EsZsQbrtFTUrDX4hOl+CS6p7cnNC4td+qrSVGSCTUfQ== + dependencies: + undici-types "~6.21.0" + +"@types/normalize-package-data@^2.4.3", "@types/normalize-package-data@^2.4.4": + version "2.4.4" + resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz#56e2cc26c397c038fab0e3a917a12d5c5909e901" + integrity sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA== + +"@types/ws@^8.18.1": + version "8.18.1" + resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.18.1.tgz#48464e4bf2ddfd17db13d845467f6070ffea4aa9" + integrity sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg== + dependencies: + "@types/node" "*" + +abitype@1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/abitype/-/abitype-1.0.8.tgz#3554f28b2e9d6e9f35eb59878193eabd1b9f46ba" + integrity sha512-ZeiI6h3GnW06uYDLx0etQtX/p8E24UaHHBj57RSjK7YBFe7iuVn07EDpOeP451D06sF27VOz9JJPlIKJmXgkEg== + +abitype@1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/abitype/-/abitype-1.1.0.tgz#510c5b3f92901877977af5e864841f443bf55406" + integrity sha512-6Vh4HcRxNMLA0puzPjM5GBgT4aAcFGKZzSgAXvuZ27shJP6NEpielTuqbBmZILR5/xd0PizkBGy5hReKz9jl5A== + +abitype@^1.0.6, abitype@^1.0.9, abitype@^1.1.1: + version "1.2.0" + resolved "https://registry.yarnpkg.com/abitype/-/abitype-1.2.0.tgz#aeb24a323c3d28d4e78f2ada9bf2c7610907737a" + integrity sha512-fD3ROjckUrWsybaSor2AdWxzA0e/DSyV2dA4aYd7bd8orHsoJjl09fOgKfUkTDfk0BsDGBf4NBgu/c7JoS2Npw== + +acorn-walk@^8.1.1: + version "8.3.4" + resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.3.4.tgz#794dd169c3977edf4ba4ea47583587c5866236b7" + integrity sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g== + dependencies: + acorn "^8.11.0" + +acorn@^8.11.0, acorn@^8.15.0, acorn@^8.4.1: + version "8.15.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.15.0.tgz#a360898bc415edaac46c8241f6383975b930b816" + integrity sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg== + +aes-js@4.0.0-beta.5: + version "4.0.0-beta.5" + resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-4.0.0-beta.5.tgz#8d2452c52adedebc3a3e28465d858c11ca315873" + integrity sha512-G965FqalsNyrPqgEGON7nIx1e/OVENSgiEIzyC63haUMuvNnwIgIjMs52hlTCKhkBny7A2ORNlfY9Zu+jmGk1Q== + +ansi-regex@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" + integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== + +ansi-regex@^6.0.1: + version "6.2.2" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-6.2.2.tgz#60216eea464d864597ce2832000738a0589650c1" + integrity sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg== + +ansi-styles@^4.0.0, ansi-styles@^4.1.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" + integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== + dependencies: + color-convert "^2.0.1" + +ansi-styles@^6.1.0: + version "6.2.3" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.2.3.tgz#c044d5dcc521a076413472597a1acb1f103c4041" + integrity sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg== + +any-promise@^1.0.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/any-promise/-/any-promise-1.3.0.tgz#abc6afeedcea52e809cdc0376aed3ce39635d17f" + integrity sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A== + +arg@^4.1.0: + version "4.1.3" + resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089" + integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA== + +argparse@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" + integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== + +assert@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/assert/-/assert-2.1.0.tgz#6d92a238d05dc02e7427c881fb8be81c8448b2dd" + integrity sha512-eLHpSK/Y4nhMJ07gDaAzoX/XAKS8PSaojml3M0DM4JpV1LAi5JOJ/p6H/XWrl8L+DzVEvVCW1z3vWAaB9oTsQw== + dependencies: + call-bind "^1.0.2" + is-nan "^1.3.2" + object-is "^1.1.5" + object.assign "^4.1.4" + util "^0.12.5" + +assertion-error@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-2.0.1.tgz#f641a196b335690b1070bf00b6e7593fec190bf7" + integrity sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA== + +available-typed-arrays@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz#a5cc375d6a03c2efc87a553f3e0b1522def14846" + integrity sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ== + dependencies: + possible-typed-array-names "^1.0.0" + +balanced-match@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" + integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== + +bn.js@^5.2.1: + version "5.2.2" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.2.tgz#82c09f9ebbb17107cd72cb7fd39bd1f9d0aaa566" + integrity sha512-v2YAxEmKaBLahNwE1mjp4WON6huMNeuDvagFZW+ASCuA/ku0bXR9hSMw0XpiqMoA3+rmnyck/tPRSFQkoC9Cuw== + +brace-expansion@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.2.tgz#54fc53237a613d854c7bd37463aad17df87214e7" + integrity sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ== + dependencies: + balanced-match "^1.0.0" + +browser-stdout@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" + integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw== + +bundle-require@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/bundle-require/-/bundle-require-5.1.0.tgz#8db66f41950da3d77af1ef3322f4c3e04009faee" + integrity sha512-3WrrOuZiyaaZPWiEt4G3+IffISVC9HYlWueJEBWED4ZH4aIAC2PnkdnuRrR94M+w6yGWn4AglWtJtBI8YqvgoA== + dependencies: + load-tsconfig "^0.2.3" + +cac@^6.7.14: + version "6.7.14" + resolved "https://registry.yarnpkg.com/cac/-/cac-6.7.14.tgz#804e1e6f506ee363cb0e3ccbb09cad5dd9870959" + integrity sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ== + +call-bind-apply-helpers@^1.0.0, call-bind-apply-helpers@^1.0.1, call-bind-apply-helpers@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz#4b5428c222be985d79c3d82657479dbe0b59b2d6" + integrity sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ== + dependencies: + es-errors "^1.3.0" + function-bind "^1.1.2" + +call-bind@^1.0.0, call-bind@^1.0.2, call-bind@^1.0.7, call-bind@^1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.8.tgz#0736a9660f537e3388826f440d5ec45f744eaa4c" + integrity sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww== + dependencies: + call-bind-apply-helpers "^1.0.0" + es-define-property "^1.0.0" + get-intrinsic "^1.2.4" + set-function-length "^1.2.2" + +call-bound@^1.0.2, call-bound@^1.0.3, call-bound@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/call-bound/-/call-bound-1.0.4.tgz#238de935d2a2a692928c538c7ccfa91067fd062a" + integrity sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg== + dependencies: + call-bind-apply-helpers "^1.0.2" + get-intrinsic "^1.3.0" + +camelcase@^6.0.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" + integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== + +chai@^6.0.1: + version "6.2.1" + resolved "https://registry.yarnpkg.com/chai/-/chai-6.2.1.tgz#d1e64bc42433fbee6175ad5346799682060b5b6a" + integrity sha512-p4Z49OGG5W/WBCPSS/dH3jQ73kD6tiMmUM+bckNK6Jr5JHMG3k9bg/BvKR8lKmtVBKmOiuVaV2ws8s9oSbwysg== + +chalk@^4.1.0: + version "4.1.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" + integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + +chalk@^5.6.2: + version "5.6.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-5.6.2.tgz#b1238b6e23ea337af71c7f8a295db5af0c158aea" + integrity sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA== + +chokidar@^4.0.1, chokidar@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-4.0.3.tgz#7be37a4c03c9aee1ecfe862a4a23b2c70c205d30" + integrity sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA== + dependencies: + readdirp "^4.0.1" + +cli-cursor@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-5.0.0.tgz#24a4831ecf5a6b01ddeb32fb71a4b2088b0dce38" + integrity sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw== + dependencies: + restore-cursor "^5.0.0" + +cli-spinners@^3.2.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-3.3.0.tgz#2ba7c98b4f4662e67315b5634365661be8574440" + integrity sha512-/+40ljC3ONVnYIttjMWrlL51nItDAbBrq2upN8BPyvGU/2n5Oxw3tbNwORCaNuNqLJnxGqOfjUuhsv7l5Q4IsQ== + +cliui@^8.0.1: + version "8.0.1" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-8.0.1.tgz#0c04b075db02cbfe60dc8e6cf2f5486b1a3608aa" + integrity sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.1" + wrap-ansi "^7.0.0" + +color-convert@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" + integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== + dependencies: + color-name "~1.1.4" + +color-name@~1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" + integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== + +commander@^14.0.2: + version "14.0.2" + resolved "https://registry.yarnpkg.com/commander/-/commander-14.0.2.tgz#b71fd37fe4069e4c3c7c13925252ada4eba14e8e" + integrity sha512-TywoWNNRbhoD0BXs1P3ZEScW8W5iKrnbithIl0YH+uCmBd0QpPOA8yc82DS3BIE5Ma6FnBVUsJ7wVUDz4dvOWQ== + +commander@^4.0.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/commander/-/commander-4.1.1.tgz#9fd602bd936294e9e9ef46a3f4d6964044b18068" + integrity sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA== + +confbox@^0.1.8: + version "0.1.8" + resolved "https://registry.yarnpkg.com/confbox/-/confbox-0.1.8.tgz#820d73d3b3c82d9bd910652c5d4d599ef8ff8b06" + integrity sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w== + +consola@^3.4.0: + version "3.4.2" + resolved "https://registry.yarnpkg.com/consola/-/consola-3.4.2.tgz#5af110145397bb67afdab77013fdc34cae590ea7" + integrity sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA== + +create-require@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" + integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== + +cross-spawn@^7.0.6: + version "7.0.6" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.6.tgz#8a58fe78f00dcd70c370451759dfbfaf03e8ee9f" + integrity sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA== + dependencies: + path-key "^3.1.0" + shebang-command "^2.0.0" + which "^2.0.1" + +data-uri-to-buffer@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz#d8feb2b2881e6a4f58c2e08acfd0e2834e26222e" + integrity sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A== + +debug@^4.1.0, debug@^4.3.5, debug@^4.4.0: + version "4.4.3" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.3.tgz#c6ae432d9bd9662582fce08709b038c58e9e3d6a" + integrity sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA== + dependencies: + ms "^2.1.3" + +decamelize@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-4.0.0.tgz#aa472d7bf660eb15f3494efd531cab7f2a709837" + integrity sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ== + +deepmerge-ts@^7.1.0: + version "7.1.5" + resolved "https://registry.yarnpkg.com/deepmerge-ts/-/deepmerge-ts-7.1.5.tgz#ff818564007f5c150808d2b7b732cac83aa415ab" + integrity sha512-HOJkrhaYsweh+W+e74Yn7YStZOilkoPb6fycpwNLKzSPtruFs48nYis0zy5yJz1+ktUhHxoRDJ27RQAWLIJVJw== + +define-data-property@^1.0.1, define-data-property@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/define-data-property/-/define-data-property-1.1.4.tgz#894dc141bb7d3060ae4366f6a0107e68fbe48c5e" + integrity sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A== + dependencies: + es-define-property "^1.0.0" + es-errors "^1.3.0" + gopd "^1.0.1" + +define-properties@^1.1.3, define-properties@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.2.1.tgz#10781cc616eb951a80a034bafcaa7377f6af2b6c" + integrity sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg== + dependencies: + define-data-property "^1.0.1" + has-property-descriptors "^1.0.0" + object-keys "^1.1.1" + +detect-indent@^7.0.1: + version "7.0.2" + resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-7.0.2.tgz#16c516bf75d4b2f759f68214554996d467c8d648" + integrity sha512-y+8xyqdGLL+6sh0tVeHcfP/QDd8gUgbasolJJpY7NgeQGSZ739bDtSiaiDgtoicy+mtYB81dKLxO9xRhCyIB3A== + +diff@^4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" + integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== + +diff@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/diff/-/diff-7.0.0.tgz#3fb34d387cd76d803f6eebea67b921dab0182a9a" + integrity sha512-PJWHUb1RFevKCwaFA9RlG5tCd+FO5iRh9A8HEtkmBH2Li03iJriB6m6JIN4rGz3K3JLawI7/veA1xzRKP6ISBw== + +dotenv@17.2.1: + version "17.2.1" + resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-17.2.1.tgz#6f32e10faf014883515538dc922a0fb8765d9b32" + integrity sha512-kQhDYKZecqnM0fCnzI5eIv5L4cAe/iRI+HqMbO/hbRdTAeXDG+M9FjipUxNfbARuEg4iHIbhnhs78BCHNbSxEQ== + +dunder-proto@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/dunder-proto/-/dunder-proto-1.0.1.tgz#d7ae667e1dc83482f8b70fd0f6eefc50da30f58a" + integrity sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A== + dependencies: + call-bind-apply-helpers "^1.0.1" + es-errors "^1.3.0" + gopd "^1.2.0" + +eastasianwidth@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb" + integrity sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA== + +emoji-regex@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" + integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== + +emoji-regex@^9.2.2: + version "9.2.2" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72" + integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg== + +es-define-property@^1.0.0, es-define-property@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/es-define-property/-/es-define-property-1.0.1.tgz#983eb2f9a6724e9303f61addf011c72e09e0b0fa" + integrity sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g== + +es-errors@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/es-errors/-/es-errors-1.3.0.tgz#05f75a25dab98e4fb1dcd5e1472c0546d5057c8f" + integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw== + +es-object-atoms@^1.0.0, es-object-atoms@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/es-object-atoms/-/es-object-atoms-1.1.1.tgz#1c4f2c4837327597ce69d2ca190a7fdd172338c1" + integrity sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA== + dependencies: + es-errors "^1.3.0" + +esbuild@^0.25.0: + version "0.25.12" + resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.25.12.tgz#97a1d041f4ab00c2fce2f838d2b9969a2d2a97a5" + integrity sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg== + optionalDependencies: + "@esbuild/aix-ppc64" "0.25.12" + "@esbuild/android-arm" "0.25.12" + "@esbuild/android-arm64" "0.25.12" + "@esbuild/android-x64" "0.25.12" + "@esbuild/darwin-arm64" "0.25.12" + "@esbuild/darwin-x64" "0.25.12" + "@esbuild/freebsd-arm64" "0.25.12" + "@esbuild/freebsd-x64" "0.25.12" + "@esbuild/linux-arm" "0.25.12" + "@esbuild/linux-arm64" "0.25.12" + "@esbuild/linux-ia32" "0.25.12" + "@esbuild/linux-loong64" "0.25.12" + "@esbuild/linux-mips64el" "0.25.12" + "@esbuild/linux-ppc64" "0.25.12" + "@esbuild/linux-riscv64" "0.25.12" + "@esbuild/linux-s390x" "0.25.12" + "@esbuild/linux-x64" "0.25.12" + "@esbuild/netbsd-arm64" "0.25.12" + "@esbuild/netbsd-x64" "0.25.12" + "@esbuild/openbsd-arm64" "0.25.12" + "@esbuild/openbsd-x64" "0.25.12" + "@esbuild/openharmony-arm64" "0.25.12" + "@esbuild/sunos-x64" "0.25.12" + "@esbuild/win32-arm64" "0.25.12" + "@esbuild/win32-ia32" "0.25.12" + "@esbuild/win32-x64" "0.25.12" + +escalade@^3.1.1: + version "3.2.0" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.2.0.tgz#011a3f69856ba189dffa7dc8fcce99d2a87903e5" + integrity sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA== + +escape-string-regexp@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" + integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== + +ethers@^6.13.5: + version "6.16.0" + resolved "https://registry.yarnpkg.com/ethers/-/ethers-6.16.0.tgz#fff9b4f05d7a359c774ad6e91085a800f7fccf65" + integrity sha512-U1wulmetNymijEhpSEQ7Ct/P/Jw9/e7R1j5XIbPRydgV2DjLVMsULDlNksq3RQnFgKoLlZf88ijYtWEXcPa07A== + dependencies: + "@adraffy/ens-normalize" "1.10.1" + "@noble/curves" "1.2.0" + "@noble/hashes" "1.3.2" + "@types/node" "22.7.5" + aes-js "4.0.0-beta.5" + tslib "2.7.0" + ws "8.17.1" + +eventemitter3@5.0.1, eventemitter3@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-5.0.1.tgz#53f5ffd0a492ac800721bb42c66b841de96423c4" + integrity sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA== + +execa@^9.6.0: + version "9.6.1" + resolved "https://registry.yarnpkg.com/execa/-/execa-9.6.1.tgz#5b90acedc6bdc0fa9b9a6ddf8f9cbb0c75a7c471" + integrity sha512-9Be3ZoN4LmYR90tUoVu2te2BsbzHfhJyfEiAVfz7N5/zv+jduIfLrV2xdQXOHbaD6KgpGdO9PRPM1Y4Q9QkPkA== + dependencies: + "@sindresorhus/merge-streams" "^4.0.0" + cross-spawn "^7.0.6" + figures "^6.1.0" + get-stream "^9.0.0" + human-signals "^8.0.1" + is-plain-obj "^4.1.0" + is-stream "^4.0.1" + npm-run-path "^6.0.0" + pretty-ms "^9.2.0" + signal-exit "^4.1.0" + strip-final-newline "^4.0.0" + yoctocolors "^2.1.1" + +fdir@^6.5.0: + version "6.5.0" + resolved "https://registry.yarnpkg.com/fdir/-/fdir-6.5.0.tgz#ed2ab967a331ade62f18d077dae192684d50d350" + integrity sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg== + +fetch-blob@^3.1.2, fetch-blob@^3.1.4: + version "3.2.0" + resolved "https://registry.yarnpkg.com/fetch-blob/-/fetch-blob-3.2.0.tgz#f09b8d4bbd45adc6f0c20b7e787e793e309dcce9" + integrity sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ== + dependencies: + node-domexception "^1.0.0" + web-streams-polyfill "^3.0.3" + +figures@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/figures/-/figures-6.1.0.tgz#935479f51865fa7479f6fa94fc6fc7ac14e62c4a" + integrity sha512-d+l3qxjSesT4V7v2fh+QnmFnUWv9lSpjarhShNTgBOfA0ttejbQUAlHLitbjkoRiDulW0OPoQPYIGhIC8ohejg== + dependencies: + is-unicode-supported "^2.0.0" + +find-up@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" + integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== + dependencies: + locate-path "^6.0.0" + path-exists "^4.0.0" + +fix-dts-default-cjs-exports@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/fix-dts-default-cjs-exports/-/fix-dts-default-cjs-exports-1.0.1.tgz#955cb6b3d519691c57828b078adadf2cb92e9549" + integrity sha512-pVIECanWFC61Hzl2+oOCtoJ3F17kglZC/6N94eRWycFgBH35hHx0Li604ZIzhseh97mf2p0cv7vVrOZGoqhlEg== + dependencies: + magic-string "^0.30.17" + mlly "^1.7.4" + rollup "^4.34.8" + +flat@^5.0.2: + version "5.0.2" + resolved "https://registry.yarnpkg.com/flat/-/flat-5.0.2.tgz#8ca6fe332069ffa9d324c327198c598259ceb241" + integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ== + +for-each@^0.3.5: + version "0.3.5" + resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.5.tgz#d650688027826920feeb0af747ee7b9421a41d47" + integrity sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg== + dependencies: + is-callable "^1.2.7" + +foreground-child@^3.1.0: + version "3.3.1" + resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-3.3.1.tgz#32e8e9ed1b68a3497befb9ac2b6adf92a638576f" + integrity sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw== + dependencies: + cross-spawn "^7.0.6" + signal-exit "^4.0.1" + +formdata-polyfill@^4.0.10: + version "4.0.10" + resolved "https://registry.yarnpkg.com/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz#24807c31c9d402e002ab3d8c720144ceb8848423" + integrity sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g== + dependencies: + fetch-blob "^3.1.2" + +fs.promises.exists@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/fs.promises.exists/-/fs.promises.exists-1.1.4.tgz#6a1d8fd24df79248eda19a8ba9dd7fd68b941921" + integrity sha512-lJzUGWbZn8vhGWBedA+RYjB/BeJ+3458ljUfmplqhIeb6ewzTFWNPCR1HCiYCkXV9zxcHz9zXkJzMsEgDLzh3Q== + +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.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" + integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== + +generator-function@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/generator-function/-/generator-function-2.0.1.tgz#0e75dd410d1243687a0ba2e951b94eedb8f737a2" + integrity sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g== + +get-caller-file@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" + integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== + +get-east-asian-width@^1.3.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/get-east-asian-width/-/get-east-asian-width-1.4.0.tgz#9bc4caa131702b4b61729cb7e42735bc550c9ee6" + integrity sha512-QZjmEOC+IT1uk6Rx0sX22V6uHWVwbdbxf1faPqJ1QhLdGgsRGCZoyaQBm/piRdJy/D2um6hM1UP7ZEeQ4EkP+Q== + +get-intrinsic@^1.2.4, get-intrinsic@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.3.0.tgz#743f0e3b6964a93a5491ed1bffaae054d7f98d01" + integrity sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ== + dependencies: + call-bind-apply-helpers "^1.0.2" + es-define-property "^1.0.1" + es-errors "^1.3.0" + es-object-atoms "^1.1.1" + function-bind "^1.1.2" + get-proto "^1.0.1" + gopd "^1.2.0" + has-symbols "^1.1.0" + hasown "^2.0.2" + math-intrinsics "^1.1.0" + +get-proto@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/get-proto/-/get-proto-1.0.1.tgz#150b3f2743869ef3e851ec0c49d15b1d14d00ee1" + integrity sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g== + dependencies: + dunder-proto "^1.0.1" + es-object-atoms "^1.0.0" + +get-stream@^9.0.0: + version "9.0.1" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-9.0.1.tgz#95157d21df8eb90d1647102b63039b1df60ebd27" + integrity sha512-kVCxPF3vQM/N0B1PmoqVUqgHP+EeVjmZSQn+1oCRPxd2P21P2F19lIgbR3HBosbB1PUhOAoctJnfEn2GbN2eZA== + dependencies: + "@sec-ant/readable-stream" "^0.4.1" + is-stream "^4.0.1" + +glob@^10.4.5: + version "10.5.0" + resolved "https://registry.yarnpkg.com/glob/-/glob-10.5.0.tgz#8ec0355919cd3338c28428a23d4f24ecc5fe738c" + integrity sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg== + dependencies: + foreground-child "^3.1.0" + jackspeak "^3.1.2" + minimatch "^9.0.4" + minipass "^7.1.2" + package-json-from-dist "^1.0.0" + path-scurry "^1.11.1" + +gopd@^1.0.1, gopd@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.2.0.tgz#89f56b8217bdbc8802bd299df6d7f1081d7e51a1" + integrity sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg== + +has-flag@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" + integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== + +has-property-descriptors@^1.0.0, has-property-descriptors@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz#963ed7d071dc7bf5f084c5bfbe0d1b6222586854" + integrity sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg== + dependencies: + es-define-property "^1.0.0" + +has-symbols@^1.0.3, has-symbols@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.1.0.tgz#fc9c6a783a084951d0b971fe1018de813707a338" + integrity sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ== + +has-tostringtag@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.2.tgz#2cdc42d40bef2e5b4eeab7c01a73c54ce7ab5abc" + integrity sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw== + dependencies: + has-symbols "^1.0.3" + +hasown@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003" + integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ== + dependencies: + function-bind "^1.1.2" + +he@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" + integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== + +hosted-git-info@^7.0.0: + version "7.0.2" + resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-7.0.2.tgz#9b751acac097757667f30114607ef7b661ff4f17" + integrity sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w== + dependencies: + lru-cache "^10.0.1" + +hosted-git-info@^9.0.0: + version "9.0.2" + resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-9.0.2.tgz#b38c8a802b274e275eeeccf9f4a1b1a0a8557ada" + integrity sha512-M422h7o/BR3rmCQ8UHi7cyyMqKltdP9Uo+J2fXK+RSAY+wTcKOIRyhTuKv4qn+DJf3g+PL890AzId5KZpX+CBg== + dependencies: + lru-cache "^11.1.0" + +human-signals@^8.0.1: + version "8.0.1" + resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-8.0.1.tgz#f08bb593b6d1db353933d06156cedec90abe51fb" + integrity sha512-eKCa6bwnJhvxj14kZk5NCPc6Hb6BdsU9DZcOnmQKSnO1VKrfV0zCvtttPZUsBvjmNDn8rpcJfpwSYnHBjc95MQ== + +imurmurhash@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" + integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA== + +index-to-position@^1.1.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/index-to-position/-/index-to-position-1.2.0.tgz#c800eb34dacf4dbf96b9b06c7eb78d5f704138b4" + integrity sha512-Yg7+ztRkqslMAS2iFaU+Oa4KTSidr63OsFGlOrJoW981kIYO3CGCS3wA95P1mUi/IVSJkn0D479KTJpVpvFNuw== + +inherits@^2.0.3: + version "2.0.4" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + +is-arguments@^1.0.4: + version "1.2.0" + resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.2.0.tgz#ad58c6aecf563b78ef2bf04df540da8f5d7d8e1b" + integrity sha512-7bVbi0huj/wrIAOzb8U1aszg9kdi3KN/CyU19CTI7tAoZYEZoL9yCDXpbXN+uPsuWnP02cyug1gleqq+TU+YCA== + dependencies: + call-bound "^1.0.2" + has-tostringtag "^1.0.2" + +is-callable@^1.2.7: + version "1.2.7" + resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055" + integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA== + +is-fullwidth-code-point@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" + integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== + +is-generator-function@^1.0.7: + version "1.1.2" + resolved "https://registry.yarnpkg.com/is-generator-function/-/is-generator-function-1.1.2.tgz#ae3b61e3d5ea4e4839b90bad22b02335051a17d5" + integrity sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA== + dependencies: + call-bound "^1.0.4" + generator-function "^2.0.0" + get-proto "^1.0.1" + has-tostringtag "^1.0.2" + safe-regex-test "^1.1.0" + +is-interactive@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-interactive/-/is-interactive-2.0.0.tgz#40c57614593826da1100ade6059778d597f16e90" + integrity sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ== + +is-nan@^1.3.2: + version "1.3.2" + resolved "https://registry.yarnpkg.com/is-nan/-/is-nan-1.3.2.tgz#043a54adea31748b55b6cd4e09aadafa69bd9e1d" + integrity sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w== + dependencies: + call-bind "^1.0.0" + define-properties "^1.1.3" + +is-path-inside@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283" + integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ== + +is-plain-obj@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287" + integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA== + +is-plain-obj@^4.0.0, is-plain-obj@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-4.1.0.tgz#d65025edec3657ce032fd7db63c97883eaed71f0" + integrity sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg== + +is-regex@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.2.1.tgz#76d70a3ed10ef9be48eb577887d74205bf0cad22" + integrity sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g== + dependencies: + call-bound "^1.0.2" + gopd "^1.2.0" + has-tostringtag "^1.0.2" + hasown "^2.0.2" + +is-stream@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-4.0.1.tgz#375cf891e16d2e4baec250b85926cffc14720d9b" + integrity sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A== + +is-typed-array@^1.1.3: + version "1.1.15" + resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.15.tgz#4bfb4a45b61cee83a5a46fba778e4e8d59c0ce0b" + integrity sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ== + dependencies: + which-typed-array "^1.1.16" + +is-unicode-supported@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7" + integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw== + +is-unicode-supported@^2.0.0, is-unicode-supported@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-2.1.0.tgz#09f0ab0de6d3744d48d265ebb98f65d11f2a9b3a" + integrity sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ== + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== + +isows@1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/isows/-/isows-1.0.6.tgz#0da29d706fa51551c663c627ace42769850f86e7" + integrity sha512-lPHCayd40oW98/I0uvgaHKWCSvkzY27LjWLbtzOm64yQ+G3Q5npjjbdppU65iZXkK1Zt+kH9pfegli0AYfwYYw== + +isows@1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/isows/-/isows-1.0.7.tgz#1c06400b7eed216fbba3bcbd68f12490fc342915" + integrity sha512-I1fSfDCZL5P0v33sVqeTDSpcstAg/N+wF5HS033mogOVIp4B+oHC7oOCsA3axAbBSGTJ8QubbNmnIRN/h8U7hg== + +jackspeak@^3.1.2: + version "3.4.3" + resolved "https://registry.yarnpkg.com/jackspeak/-/jackspeak-3.4.3.tgz#8833a9d89ab4acde6188942bd1c53b6390ed5a8a" + integrity sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw== + dependencies: + "@isaacs/cliui" "^8.0.2" + optionalDependencies: + "@pkgjs/parseargs" "^0.11.0" + +joycon@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/joycon/-/joycon-3.1.1.tgz#bce8596d6ae808f8b68168f5fc69280996894f03" + integrity sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw== + +js-tokens@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" + integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== + +js-yaml@^4.1.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.1.tgz#854c292467705b699476e1a2decc0c8a3458806b" + integrity sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA== + dependencies: + argparse "^2.0.1" + +json-stringify-safe@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" + integrity sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA== + +lilconfig@^3.1.1: + version "3.1.3" + resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-3.1.3.tgz#a1bcfd6257f9585bf5ae14ceeebb7b559025e4c4" + integrity sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw== + +lines-and-columns@^1.1.6: + version "1.2.4" + resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" + integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== + +load-tsconfig@^0.2.3: + version "0.2.5" + resolved "https://registry.yarnpkg.com/load-tsconfig/-/load-tsconfig-0.2.5.tgz#453b8cd8961bfb912dea77eb6c168fe8cca3d3a1" + integrity sha512-IXO6OCs9yg8tMKzfPZ1YmheJbZCiEsnBdcB03l0OcfK9prKnJb96siuHCr5Fl37/yo9DnKU+TLpxzTUspw9shg== + +locate-path@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" + integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== + dependencies: + p-locate "^5.0.0" + +lodash.sortby@^4.7.0: + version "4.7.0" + resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438" + integrity sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA== + +log-symbols@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.1.0.tgz#3fbdbb95b4683ac9fc785111e792e558d4abd503" + integrity sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg== + dependencies: + chalk "^4.1.0" + is-unicode-supported "^0.1.0" + +log-symbols@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-7.0.1.tgz#f52e68037d96f589fc572ff2193dc424d48c195b" + integrity sha512-ja1E3yCr9i/0hmBVaM0bfwDjnGy8I/s6PP4DFp+yP+a+mrHO4Rm7DtmnqROTUkHIkqffC84YY7AeqX6oFk0WFg== + dependencies: + is-unicode-supported "^2.0.0" + yoctocolors "^2.1.1" + +lru-cache@^10.0.1, lru-cache@^10.2.0: + version "10.4.3" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.4.3.tgz#410fc8a17b70e598013df257c2446b7f3383f119" + integrity sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ== + +lru-cache@^11.1.0: + version "11.2.4" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-11.2.4.tgz#ecb523ebb0e6f4d837c807ad1abaea8e0619770d" + integrity sha512-B5Y16Jr9LB9dHVkh6ZevG+vAbOsNOYCX+sXvFWFu7B3Iz5mijW3zdbMyhsh8ANd2mSWBYdJgnqi+mL7/LrOPYg== + +magic-string@^0.30.17: + version "0.30.21" + resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.30.21.tgz#56763ec09a0fa8091df27879fd94d19078c00d91" + integrity sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ== + dependencies: + "@jridgewell/sourcemap-codec" "^1.5.5" + +make-error@^1.1.1: + version "1.3.6" + resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" + integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== + +math-intrinsics@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/math-intrinsics/-/math-intrinsics-1.1.0.tgz#a0dd74be81e2aa5c2f27e65ce283605ee4e2b7f9" + integrity sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g== + +mimic-function@^5.0.0: + version "5.0.1" + resolved "https://registry.yarnpkg.com/mimic-function/-/mimic-function-5.0.1.tgz#acbe2b3349f99b9deaca7fb70e48b83e94e67076" + integrity sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA== + +minimatch@^9.0.4, minimatch@^9.0.5: + version "9.0.5" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.5.tgz#d74f9dd6b57d83d8e98cfb82133b03978bc929e5" + integrity sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow== + dependencies: + brace-expansion "^2.0.1" + +"minipass@^5.0.0 || ^6.0.2 || ^7.0.0", minipass@^7.1.2: + version "7.1.2" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-7.1.2.tgz#93a9626ce5e5e66bd4db86849e7515e92340a707" + integrity sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw== + +mlly@^1.7.4: + version "1.8.0" + resolved "https://registry.yarnpkg.com/mlly/-/mlly-1.8.0.tgz#e074612b938af8eba1eaf43299cbc89cb72d824e" + integrity sha512-l8D9ODSRWLe2KHJSifWGwBqpTZXIXTeo8mlKjY+E2HAakaTeNpqAyBZ8GSqLzHgw4XmHmC8whvpjJNMbFZN7/g== + dependencies: + acorn "^8.15.0" + pathe "^2.0.3" + pkg-types "^1.3.1" + ufo "^1.6.1" + +mocha@^11.1.0: + version "11.7.5" + resolved "https://registry.yarnpkg.com/mocha/-/mocha-11.7.5.tgz#58f5bbfa5e0211ce7e5ee6128107cefc2515a627" + integrity sha512-mTT6RgopEYABzXWFx+GcJ+ZQ32kp4fMf0xvpZIIfSq9Z8lC/++MtcCnQ9t5FP2veYEP95FIYSvW+U9fV4xrlig== + dependencies: + browser-stdout "^1.3.1" + chokidar "^4.0.1" + debug "^4.3.5" + diff "^7.0.0" + escape-string-regexp "^4.0.0" + find-up "^5.0.0" + glob "^10.4.5" + he "^1.2.0" + is-path-inside "^3.0.3" + js-yaml "^4.1.0" + log-symbols "^4.1.0" + minimatch "^9.0.5" + ms "^2.1.3" + picocolors "^1.1.1" + serialize-javascript "^6.0.2" + strip-json-comments "^3.1.1" + supports-color "^8.1.1" + workerpool "^9.2.0" + yargs "^17.7.2" + yargs-parser "^21.1.1" + yargs-unparser "^2.0.0" + +mock-socket@^9.3.1: + version "9.3.1" + resolved "https://registry.yarnpkg.com/mock-socket/-/mock-socket-9.3.1.tgz#24fb00c2f573c84812aa4a24181bb025de80cc8e" + integrity sha512-qxBgB7Qa2sEQgHFjj0dSigq7fX4k6Saisd5Nelwp2q8mlbAFh5dHV9JTTlF8viYJLSSWgMCZFUom8PJcMNBoJw== + +ms@^2.1.3: + version "2.1.3" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" + integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== + +mz@^2.7.0: + version "2.7.0" + resolved "https://registry.yarnpkg.com/mz/-/mz-2.7.0.tgz#95008057a56cafadc2bc63dde7f9ff6955948e32" + integrity sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q== + dependencies: + any-promise "^1.0.0" + object-assign "^4.0.1" + thenify-all "^1.0.0" + +nock@^13.5.5: + version "13.5.6" + resolved "https://registry.yarnpkg.com/nock/-/nock-13.5.6.tgz#5e693ec2300bbf603b61dae6df0225673e6c4997" + integrity sha512-o2zOYiCpzRqSzPj0Zt/dQ/DqZeYoaQ7TUonc/xUPjCGl9WeHpNbxgVvOquXYAaJzI0M9BXV3HTzG0p8IUAbBTQ== + dependencies: + debug "^4.1.0" + json-stringify-safe "^5.0.1" + propagate "^2.0.0" + +node-domexception@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/node-domexception/-/node-domexception-1.0.0.tgz#6888db46a1f71c0b76b3f7555016b63fe64766e5" + integrity sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ== + +node-fetch@^3.3.2: + version "3.3.2" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-3.3.2.tgz#d1e889bacdf733b4ff3b2b243eb7a12866a0b78b" + integrity sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA== + dependencies: + data-uri-to-buffer "^4.0.0" + fetch-blob "^3.1.4" + formdata-polyfill "^4.0.10" + +normalize-package-data@^6.0.0: + version "6.0.2" + resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-6.0.2.tgz#a7bc22167fe24025412bcff0a9651eb768b03506" + integrity sha512-V6gygoYb/5EmNI+MEGrWkC+e6+Rr7mTmfHrxDbLzxQogBkgzo76rkok0Am6thgSF7Mv2nLOajAJj5vDJZEFn7g== + dependencies: + hosted-git-info "^7.0.0" + semver "^7.3.5" + validate-npm-package-license "^3.0.4" + +normalize-package-data@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-8.0.0.tgz#bdce7ff2d6ba891b853e179e45a5337766e304a7" + integrity sha512-RWk+PI433eESQ7ounYxIp67CYuVsS1uYSonX3kA6ps/3LWfjVQa/ptEg6Y3T6uAMq1mWpX9PQ+qx+QaHpsc7gQ== + dependencies: + hosted-git-info "^9.0.0" + semver "^7.3.5" + validate-npm-package-license "^3.0.4" + +npm-run-path@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-6.0.0.tgz#25cfdc4eae04976f3349c0b1afc089052c362537" + integrity sha512-9qny7Z9DsQU8Ou39ERsPU4OZQlSTP47ShQzuKZ6PRXpYLtIFgl/DEBYEXKlvcEa+9tHVcK8CF81Y2V72qaZhWA== + dependencies: + path-key "^4.0.0" + unicorn-magic "^0.3.0" + +object-assign@^4.0.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" + integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== + +object-is@^1.1.5: + version "1.1.6" + resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.1.6.tgz#1a6a53aed2dd8f7e6775ff870bea58545956ab07" + integrity sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q== + dependencies: + call-bind "^1.0.7" + define-properties "^1.2.1" + +object-keys@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" + integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== + +object.assign@^4.1.4: + version "4.1.7" + resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.7.tgz#8c14ca1a424c6a561b0bb2a22f66f5049a945d3d" + integrity sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw== + dependencies: + call-bind "^1.0.8" + call-bound "^1.0.3" + define-properties "^1.2.1" + es-object-atoms "^1.0.0" + has-symbols "^1.1.0" + object-keys "^1.1.1" + +onetime@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-7.0.0.tgz#9f16c92d8c9ef5120e3acd9dd9957cceecc1ab60" + integrity sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ== + dependencies: + mimic-function "^5.0.0" + +ora@^9.0.0: + version "9.0.0" + resolved "https://registry.yarnpkg.com/ora/-/ora-9.0.0.tgz#945236f5ce78a024cf4c25df6c46ecd09ab6e685" + integrity sha512-m0pg2zscbYgWbqRR6ABga5c3sZdEon7bSgjnlXC64kxtxLOyjRcbbUkLj7HFyy/FTD+P2xdBWu8snGhYI0jc4A== + dependencies: + chalk "^5.6.2" + cli-cursor "^5.0.0" + cli-spinners "^3.2.0" + is-interactive "^2.0.0" + is-unicode-supported "^2.1.0" + log-symbols "^7.0.1" + stdin-discarder "^0.2.2" + string-width "^8.1.0" + strip-ansi "^7.1.2" + +ox@0.6.7: + version "0.6.7" + resolved "https://registry.yarnpkg.com/ox/-/ox-0.6.7.tgz#afd53f2ecef68b8526660e9d29dee6e6b599a832" + integrity sha512-17Gk/eFsFRAZ80p5eKqv89a57uXjd3NgIf1CaXojATPBuujVc/fQSVhBeAU9JCRB+k7J50WQAyWTxK19T9GgbA== + dependencies: + "@adraffy/ens-normalize" "^1.10.1" + "@noble/curves" "^1.6.0" + "@noble/hashes" "^1.5.0" + "@scure/bip32" "^1.5.0" + "@scure/bip39" "^1.4.0" + abitype "^1.0.6" + eventemitter3 "5.0.1" + +ox@0.9.6: + version "0.9.6" + resolved "https://registry.yarnpkg.com/ox/-/ox-0.9.6.tgz#5cf02523b6db364c10ee7f293ff1e664e0e1eab7" + integrity sha512-8SuCbHPvv2eZLYXrNmC0EC12rdzXQLdhnOMlHDW2wiCPLxBrOOJwX5L5E61by+UjTPOryqQiRSnjIKCI+GykKg== + dependencies: + "@adraffy/ens-normalize" "^1.11.0" + "@noble/ciphers" "^1.3.0" + "@noble/curves" "1.9.1" + "@noble/hashes" "^1.8.0" + "@scure/bip32" "^1.7.0" + "@scure/bip39" "^1.6.0" + abitype "^1.0.9" + eventemitter3 "5.0.1" + +p-limit@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" + integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== + dependencies: + yocto-queue "^0.1.0" + +p-locate@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" + integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== + dependencies: + p-limit "^3.0.2" + +package-json-from-dist@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz#4f1471a010827a86f94cfd9b0727e36d267de505" + integrity sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw== + +parse-json@^8.0.0, parse-json@^8.3.0: + version "8.3.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-8.3.0.tgz#88a195a2157025139a2317a4f2f9252b61304ed5" + integrity sha512-ybiGyvspI+fAoRQbIPRddCcSTV9/LsJbf0e/S85VLowVGzRmokfneg2kwVW/KU5rOXrPSbF1qAKPMgNTqqROQQ== + dependencies: + "@babel/code-frame" "^7.26.2" + index-to-position "^1.1.0" + type-fest "^4.39.1" + +parse-ms@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/parse-ms/-/parse-ms-4.0.0.tgz#c0c058edd47c2a590151a718990533fd62803df4" + integrity sha512-TXfryirbmq34y8QBwgqCVLi+8oA3oWx2eAnSn62ITyEhEYaWRlVZ2DvMM9eZbMs/RfxPu/PK/aBLyGj4IrqMHw== + +path-exists@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" + integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== + +path-key@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" + integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== + +path-key@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-4.0.0.tgz#295588dc3aee64154f877adb9d780b81c554bf18" + integrity sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ== + +path-scurry@^1.11.1: + version "1.11.1" + resolved "https://registry.yarnpkg.com/path-scurry/-/path-scurry-1.11.1.tgz#7960a668888594a0720b12a911d1a742ab9f11d2" + integrity sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA== + dependencies: + lru-cache "^10.2.0" + minipass "^5.0.0 || ^6.0.2 || ^7.0.0" + +pathe@^2.0.1, pathe@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/pathe/-/pathe-2.0.3.tgz#3ecbec55421685b70a9da872b2cff3e1cbed1716" + integrity sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w== + +picocolors@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.1.1.tgz#3d321af3eab939b083c8f929a1d12cda81c26b6b" + integrity sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA== + +picomatch@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-4.0.3.tgz#796c76136d1eead715db1e7bad785dedd695a042" + integrity sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q== + +pirates@^4.0.1: + version "4.0.7" + resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.7.tgz#643b4a18c4257c8a65104b73f3049ce9a0a15e22" + integrity sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA== + +pkg-types@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/pkg-types/-/pkg-types-1.3.1.tgz#bd7cc70881192777eef5326c19deb46e890917df" + integrity sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ== + dependencies: + confbox "^0.1.8" + mlly "^1.7.4" + pathe "^2.0.1" + +polkadot-api@^1.22.0: + version "1.22.0" + resolved "https://registry.yarnpkg.com/polkadot-api/-/polkadot-api-1.22.0.tgz#fc042d9e86154ab5d3a27f335aab222eda2abb00" + integrity sha512-uREBLroPbnJxBBQ+qSkKLF493qukX4PAg32iThlELrZdxfNNgro6nvWRdVmBv73tFHvf+nyWWHKTx1c57nbixg== + dependencies: + "@polkadot-api/cli" "0.16.3" + "@polkadot-api/ink-contracts" "0.4.3" + "@polkadot-api/json-rpc-provider" "0.0.4" + "@polkadot-api/known-chains" "0.9.15" + "@polkadot-api/logs-provider" "0.0.6" + "@polkadot-api/metadata-builders" "0.13.7" + "@polkadot-api/metadata-compatibility" "0.4.1" + "@polkadot-api/observable-client" "0.17.0" + "@polkadot-api/pjs-signer" "0.6.17" + "@polkadot-api/polkadot-sdk-compat" "2.3.3" + "@polkadot-api/polkadot-signer" "0.1.6" + "@polkadot-api/signer" "0.2.11" + "@polkadot-api/sm-provider" "0.1.14" + "@polkadot-api/smoldot" "0.3.14" + "@polkadot-api/substrate-bindings" "0.16.5" + "@polkadot-api/substrate-client" "0.4.7" + "@polkadot-api/utils" "0.2.0" + "@polkadot-api/ws-provider" "0.7.4" + "@rx-state/core" "^0.1.4" + +possible-typed-array-names@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz#93e3582bc0e5426586d9d07b79ee40fc841de4ae" + integrity sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg== + +postcss-load-config@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/postcss-load-config/-/postcss-load-config-6.0.1.tgz#6fd7dcd8ae89badcf1b2d644489cbabf83aa8096" + integrity sha512-oPtTM4oerL+UXmx+93ytZVN82RrlY/wPUV8IeDxFrzIjXOLF1pN+EmKPLbubvKHT2HC20xXsCAH2Z+CKV6Oz/g== + dependencies: + lilconfig "^3.1.1" + +prettier@^3.3.3: + version "3.7.4" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.7.4.tgz#d2f8335d4b1cec47e1c8098645411b0c9dff9c0f" + integrity sha512-v6UNi1+3hSlVvv8fSaoUbggEM5VErKmmpGA7Pl3HF8V6uKY7rvClBOJlH6yNwQtfTueNkGVpOv/mtWL9L4bgRA== + +pretty-ms@^9.2.0: + version "9.3.0" + resolved "https://registry.yarnpkg.com/pretty-ms/-/pretty-ms-9.3.0.tgz#dd2524fcb3c326b4931b2272dfd1e1a8ed9a9f5a" + integrity sha512-gjVS5hOP+M3wMm5nmNOucbIrqudzs9v/57bWRHQWLYklXqoXKrVfYW2W9+glfGsqtPgpiz5WwyEEB+ksXIx3gQ== + dependencies: + parse-ms "^4.0.0" + +propagate@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/propagate/-/propagate-2.0.1.tgz#40cdedab18085c792334e64f0ac17256d38f9a45" + integrity sha512-vGrhOavPSTz4QVNuBNdcNXePNdNMaO1xj9yBeH1ScQPjk/rhg9sSlCXPhMkFuaNNW/syTvYqsnbIJxMBfRbbag== + +punycode@^2.1.0: + version "2.3.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5" + integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg== + +randombytes@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" + integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== + dependencies: + safe-buffer "^5.1.0" + +read-pkg@^10.0.0: + version "10.0.0" + resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-10.0.0.tgz#06401f0331115e9fba9880cb3f2ae1efa3db00e4" + integrity sha512-A70UlgfNdKI5NSvTTfHzLQj7NJRpJ4mT5tGafkllJ4wh71oYuGm/pzphHcmW4s35iox56KSK721AihodoXSc/A== + dependencies: + "@types/normalize-package-data" "^2.4.4" + normalize-package-data "^8.0.0" + parse-json "^8.3.0" + type-fest "^5.2.0" + unicorn-magic "^0.3.0" + +read-pkg@^9.0.1: + version "9.0.1" + resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-9.0.1.tgz#b1b81fb15104f5dbb121b6bbdee9bbc9739f569b" + integrity sha512-9viLL4/n1BJUCT1NXVTdS1jtm80yDEgR5T4yCelII49Mbj0v1rZdKqj7zCiYdbB0CuCgdrvHcNogAKTFPBocFA== + dependencies: + "@types/normalize-package-data" "^2.4.3" + normalize-package-data "^6.0.0" + parse-json "^8.0.0" + type-fest "^4.6.0" + unicorn-magic "^0.1.0" + +readdirp@^4.0.1: + version "4.1.2" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-4.1.2.tgz#eb85801435fbf2a7ee58f19e0921b068fc69948d" + integrity sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg== + +require-directory@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== + +resolve-from@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" + integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== + +restore-cursor@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-5.1.0.tgz#0766d95699efacb14150993f55baf0953ea1ebe7" + integrity sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA== + dependencies: + onetime "^7.0.0" + signal-exit "^4.1.0" + +rollup@^4.34.8: + version "4.53.3" + resolved "https://registry.yarnpkg.com/rollup/-/rollup-4.53.3.tgz#dbc8cd8743b38710019fb8297e8d7a76e3faa406" + integrity sha512-w8GmOxZfBmKknvdXU1sdM9NHcoQejwF/4mNgj2JuEEdRaHwwF12K7e9eXn1nLZ07ad+du76mkVsyeb2rKGllsA== + dependencies: + "@types/estree" "1.0.8" + optionalDependencies: + "@rollup/rollup-android-arm-eabi" "4.53.3" + "@rollup/rollup-android-arm64" "4.53.3" + "@rollup/rollup-darwin-arm64" "4.53.3" + "@rollup/rollup-darwin-x64" "4.53.3" + "@rollup/rollup-freebsd-arm64" "4.53.3" + "@rollup/rollup-freebsd-x64" "4.53.3" + "@rollup/rollup-linux-arm-gnueabihf" "4.53.3" + "@rollup/rollup-linux-arm-musleabihf" "4.53.3" + "@rollup/rollup-linux-arm64-gnu" "4.53.3" + "@rollup/rollup-linux-arm64-musl" "4.53.3" + "@rollup/rollup-linux-loong64-gnu" "4.53.3" + "@rollup/rollup-linux-ppc64-gnu" "4.53.3" + "@rollup/rollup-linux-riscv64-gnu" "4.53.3" + "@rollup/rollup-linux-riscv64-musl" "4.53.3" + "@rollup/rollup-linux-s390x-gnu" "4.53.3" + "@rollup/rollup-linux-x64-gnu" "4.53.3" + "@rollup/rollup-linux-x64-musl" "4.53.3" + "@rollup/rollup-openharmony-arm64" "4.53.3" + "@rollup/rollup-win32-arm64-msvc" "4.53.3" + "@rollup/rollup-win32-ia32-msvc" "4.53.3" + "@rollup/rollup-win32-x64-gnu" "4.53.3" + "@rollup/rollup-win32-x64-msvc" "4.53.3" + fsevents "~2.3.2" + +rxjs@^7.8.1, rxjs@^7.8.2: + version "7.8.2" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.8.2.tgz#955bc473ed8af11a002a2be52071bf475638607b" + integrity sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA== + dependencies: + tslib "^2.1.0" + +safe-buffer@^5.1.0: + version "5.2.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" + integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== + +safe-regex-test@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/safe-regex-test/-/safe-regex-test-1.1.0.tgz#7f87dfb67a3150782eaaf18583ff5d1711ac10c1" + integrity sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw== + dependencies: + call-bound "^1.0.2" + es-errors "^1.3.0" + is-regex "^1.2.1" + +scale-ts@^1.6.0, scale-ts@^1.6.1: + version "1.6.1" + resolved "https://registry.yarnpkg.com/scale-ts/-/scale-ts-1.6.1.tgz#45151e156d6c04792223c39d8e7484ce926445f2" + integrity sha512-PBMc2AWc6wSEqJYBDPcyCLUj9/tMKnLX70jLOSndMtcUoLQucP/DM0vnQo1wJAYjTrQiq8iG9rD0q6wFzgjH7g== + +semver@^7.3.5: + version "7.7.3" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.7.3.tgz#4b5f4143d007633a8dc671cd0a6ef9147b8bb946" + integrity sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q== + +serialize-javascript@^6.0.2: + version "6.0.2" + resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.2.tgz#defa1e055c83bf6d59ea805d8da862254eb6a6c2" + integrity sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g== + dependencies: + randombytes "^2.1.0" + +set-function-length@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/set-function-length/-/set-function-length-1.2.2.tgz#aac72314198eaed975cf77b2c3b6b880695e5449" + integrity sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg== + dependencies: + define-data-property "^1.1.4" + es-errors "^1.3.0" + function-bind "^1.1.2" + get-intrinsic "^1.2.4" + gopd "^1.0.1" + has-property-descriptors "^1.0.2" + +shebang-command@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" + integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== + dependencies: + shebang-regex "^3.0.0" + +shebang-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" + integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== + +signal-exit@^4.0.1, signal-exit@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-4.1.0.tgz#952188c1cbd546070e2dd20d0f41c0ae0530cb04" + integrity sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw== + +smoldot@2.0.26: + version "2.0.26" + resolved "https://registry.yarnpkg.com/smoldot/-/smoldot-2.0.26.tgz#0e64c7fcd26240fbe4c8d6b6e4b9a9aca77e00f6" + integrity sha512-F+qYmH4z2s2FK+CxGj8moYcd1ekSIKH8ywkdqlOz88Dat35iB1DIYL11aILN46YSGMzQW/lbJNS307zBSDN5Ig== + dependencies: + ws "^8.8.1" + +smoldot@2.0.39: + version "2.0.39" + resolved "https://registry.yarnpkg.com/smoldot/-/smoldot-2.0.39.tgz#e99981d13476702bbd906b8d14d18a77ddef0c0d" + integrity sha512-yFMSzI6nkqWFTNao99lBA/TguUFU+bR3A5UGTDd/QqqB12jqzvZnmW/No6l2rKmagt8Qx/KybMNowV/E28znhA== + dependencies: + ws "^8.8.1" + +sort-keys@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/sort-keys/-/sort-keys-5.1.0.tgz#50a3f3d1ad3c5a76d043e0aeeba7299241e9aa5c" + integrity sha512-aSbHV0DaBcr7u0PVHXzM6NbZNAtrr9sF6+Qfs9UUVG7Ll3jQ6hHi8F/xqIIcn2rvIVbr0v/2zyjSdwSV47AgLQ== + dependencies: + is-plain-obj "^4.0.0" + +source-map@0.8.0-beta.0: + version "0.8.0-beta.0" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.8.0-beta.0.tgz#d4c1bb42c3f7ee925f005927ba10709e0d1d1f11" + integrity sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA== + dependencies: + whatwg-url "^7.0.0" + +spdx-correct@^3.0.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.2.0.tgz#4f5ab0668f0059e34f9c00dce331784a12de4e9c" + integrity sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA== + dependencies: + spdx-expression-parse "^3.0.0" + spdx-license-ids "^3.0.0" + +spdx-exceptions@^2.1.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz#5d607d27fc806f66d7b64a766650fa890f04ed66" + integrity sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w== + +spdx-expression-parse@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz#cf70f50482eefdc98e3ce0a6833e4a53ceeba679" + integrity sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q== + dependencies: + spdx-exceptions "^2.1.0" + spdx-license-ids "^3.0.0" + +spdx-license-ids@^3.0.0: + version "3.0.22" + resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.22.tgz#abf5a08a6f5d7279559b669f47f0a43e8f3464ef" + integrity sha512-4PRT4nh1EImPbt2jASOKHX7PB7I+e4IWNLvkKFDxNhJlfjbYlleYQh285Z/3mPTHSAK/AvdMmw5BNNuYH8ShgQ== + +stdin-discarder@^0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/stdin-discarder/-/stdin-discarder-0.2.2.tgz#390037f44c4ae1a1ae535c5fe38dc3aba8d997be" + integrity sha512-UhDfHmA92YAlNnCfhmq0VeNL5bDbiZGg7sZ2IvPsXubGkiNa9EC+tUTsjBRsYUAz87btI6/1wf4XoVvQ3uRnmQ== + +"string-width-cjs@npm:string-width@^4.2.0": + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +string-width@^5.0.1, string-width@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794" + integrity sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA== + dependencies: + eastasianwidth "^0.2.0" + emoji-regex "^9.2.2" + strip-ansi "^7.0.1" + +string-width@^8.1.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-8.1.0.tgz#9e9fb305174947cf45c30529414b5da916e9e8d1" + integrity sha512-Kxl3KJGb/gxkaUMOjRsQ8IrXiGW75O4E3RPjFIINOVH8AMl2SQ/yWdTzWwF3FevIX9LcMAjJW+GRwAlAbTSXdg== + dependencies: + get-east-asian-width "^1.3.0" + strip-ansi "^7.1.0" + +"strip-ansi-cjs@npm:strip-ansi@^6.0.1": + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + +strip-ansi@^6.0.0, strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + +strip-ansi@^7.0.1, strip-ansi@^7.1.0, strip-ansi@^7.1.2: + version "7.1.2" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.2.tgz#132875abde678c7ea8d691533f2e7e22bb744dba" + integrity sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA== + dependencies: + ansi-regex "^6.0.1" + +strip-final-newline@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-4.0.0.tgz#35a369ec2ac43df356e3edd5dcebb6429aa1fa5c" + integrity sha512-aulFJcD6YK8V1G7iRB5tigAP4TsHBZZrOV8pjV++zdUwmeV8uzbY7yn6h9MswN62adStNZFuCIx4haBnRuMDaw== + +strip-json-comments@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" + integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== + +sucrase@^3.35.0: + version "3.35.1" + resolved "https://registry.yarnpkg.com/sucrase/-/sucrase-3.35.1.tgz#4619ea50393fe8bd0ae5071c26abd9b2e346bfe1" + integrity sha512-DhuTmvZWux4H1UOnWMB3sk0sbaCVOoQZjv8u1rDoTV0HTdGem9hkAZtl4JZy8P2z4Bg0nT+YMeOFyVr4zcG5Tw== + dependencies: + "@jridgewell/gen-mapping" "^0.3.2" + commander "^4.0.0" + lines-and-columns "^1.1.6" + mz "^2.7.0" + pirates "^4.0.1" + tinyglobby "^0.2.11" + ts-interface-checker "^0.1.9" + +supports-color@^7.1.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" + integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== + dependencies: + has-flag "^4.0.0" + +supports-color@^8.1.1: + version "8.1.1" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" + integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== + dependencies: + has-flag "^4.0.0" + +tagged-tag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/tagged-tag/-/tagged-tag-1.0.0.tgz#a0b5917c2864cba54841495abfa3f6b13edcf4d6" + integrity sha512-yEFYrVhod+hdNyx7g5Bnkkb0G6si8HJurOoOEgC8B/O0uXLHlaey/65KRv6cuWBNhBgHKAROVpc7QyYqE5gFng== + +thenify-all@^1.0.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/thenify-all/-/thenify-all-1.6.0.tgz#1a1918d402d8fc3f98fbf234db0bcc8cc10e9726" + integrity sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA== + dependencies: + thenify ">= 3.1.0 < 4" + +"thenify@>= 3.1.0 < 4": + version "3.3.1" + resolved "https://registry.yarnpkg.com/thenify/-/thenify-3.3.1.tgz#8932e686a4066038a016dd9e2ca46add9838a95f" + integrity sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw== + dependencies: + any-promise "^1.0.0" + +tinyexec@^0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/tinyexec/-/tinyexec-0.3.2.tgz#941794e657a85e496577995c6eef66f53f42b3d2" + integrity sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA== + +tinyglobby@^0.2.11: + version "0.2.15" + resolved "https://registry.yarnpkg.com/tinyglobby/-/tinyglobby-0.2.15.tgz#e228dd1e638cea993d2fdb4fcd2d4602a79951c2" + integrity sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ== + dependencies: + fdir "^6.5.0" + picomatch "^4.0.3" + +tr46@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-1.0.1.tgz#a8b13fd6bfd2489519674ccde55ba3693b706d09" + integrity sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA== + dependencies: + punycode "^2.1.0" + +tree-kill@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/tree-kill/-/tree-kill-1.2.2.tgz#4ca09a9092c88b73a7cdc5e8a01b507b0790a0cc" + integrity sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A== + +ts-interface-checker@^0.1.9: + version "0.1.13" + resolved "https://registry.yarnpkg.com/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz#784fd3d679722bc103b1b4b8030bcddb5db2a699" + integrity sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA== + +ts-node@^10.9.2: + version "10.9.2" + resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.9.2.tgz#70f021c9e185bccdca820e26dc413805c101c71f" + integrity sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ== + dependencies: + "@cspotcode/source-map-support" "^0.8.0" + "@tsconfig/node10" "^1.0.7" + "@tsconfig/node12" "^1.0.7" + "@tsconfig/node14" "^1.0.0" + "@tsconfig/node16" "^1.0.2" + acorn "^8.4.1" + acorn-walk "^8.1.1" + arg "^4.1.0" + create-require "^1.1.0" + diff "^4.0.1" + make-error "^1.1.1" + v8-compile-cache-lib "^3.0.1" + yn "3.1.1" + +tsc-prog@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/tsc-prog/-/tsc-prog-2.3.0.tgz#b14ffb4e9487cca5cf42185f2a94963978faf8ee" + integrity sha512-ycET2d75EgcX7y8EmG4KiZkLAwUzbY4xRhA6NU0uVbHkY4ZjrAAuzTMxXI85kOwATqPnBI5C/7y7rlpY0xdqHA== + +tslib@2.7.0: + version "2.7.0" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.7.0.tgz#d9b40c5c40ab59e8738f297df3087bf1a2690c01" + integrity sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA== + +tslib@^2.1.0, tslib@^2.7.0, tslib@^2.8.0, tslib@^2.8.1: + version "2.8.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f" + integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w== + +tsup@8.5.0: + version "8.5.0" + resolved "https://registry.yarnpkg.com/tsup/-/tsup-8.5.0.tgz#4b1e25b1a8f4e4f89b764207bf37cfe2d7411d31" + integrity sha512-VmBp77lWNQq6PfuMqCHD3xWl22vEoWsKajkF8t+yMBawlUS8JzEI+vOVMeuNZIuMML8qXRizFKi9oD5glKQVcQ== + dependencies: + bundle-require "^5.1.0" + cac "^6.7.14" + chokidar "^4.0.3" + consola "^3.4.0" + debug "^4.4.0" + esbuild "^0.25.0" + fix-dts-default-cjs-exports "^1.0.0" + joycon "^3.1.1" + picocolors "^1.1.1" + postcss-load-config "^6.0.1" + resolve-from "^5.0.0" + rollup "^4.34.8" + source-map "0.8.0-beta.0" + sucrase "^3.35.0" + tinyexec "^0.3.2" + tinyglobby "^0.2.11" + tree-kill "^1.2.2" + +type-fest@^4.23.0, type-fest@^4.39.1, type-fest@^4.6.0: + version "4.41.0" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-4.41.0.tgz#6ae1c8e5731273c2bf1f58ad39cbae2c91a46c58" + integrity sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA== + +type-fest@^5.2.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-5.3.0.tgz#9422125b3094b1087d8446ba151b72fb9f39411a" + integrity sha512-d9CwU93nN0IA1QL+GSNDdwLAu1Ew5ZjTwupvedwg3WdfoH6pIDvYQ2hV0Uc2nKBLPq7NB5apCx57MLS5qlmO5g== + dependencies: + tagged-tag "^1.0.0" + +typescript@^5.7.2, typescript@^5.9.3: + version "5.9.3" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.9.3.tgz#5b4f59e15310ab17a216f5d6cf53ee476ede670f" + integrity sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw== + +ufo@^1.6.1: + version "1.6.1" + resolved "https://registry.yarnpkg.com/ufo/-/ufo-1.6.1.tgz#ac2db1d54614d1b22c1d603e3aef44a85d8f146b" + integrity sha512-9a4/uxlTWJ4+a5i0ooc1rU7C7YOw3wT+UGqdeNNHWnOF9qcMBgLRS+4IYUqbczewFx4mLEig6gawh7X6mFlEkA== + +undici-types@~6.19.2: + version "6.19.8" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.19.8.tgz#35111c9d1437ab83a7cdc0abae2f26d88eda0a02" + integrity sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw== + +undici-types@~6.21.0: + version "6.21.0" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.21.0.tgz#691d00af3909be93a7faa13be61b3a5b50ef12cb" + integrity sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ== + +undici-types@~7.16.0: + version "7.16.0" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-7.16.0.tgz#ffccdff36aea4884cbfce9a750a0580224f58a46" + integrity sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw== + +unicorn-magic@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/unicorn-magic/-/unicorn-magic-0.1.0.tgz#1bb9a51c823aaf9d73a8bfcd3d1a23dde94b0ce4" + integrity sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ== + +unicorn-magic@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/unicorn-magic/-/unicorn-magic-0.3.0.tgz#4efd45c85a69e0dd576d25532fbfa22aa5c8a104" + integrity sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA== + +util@^0.12.5: + version "0.12.5" + resolved "https://registry.yarnpkg.com/util/-/util-0.12.5.tgz#5f17a6059b73db61a875668781a1c2b136bd6fbc" + integrity sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA== + dependencies: + inherits "^2.0.3" + is-arguments "^1.0.4" + is-generator-function "^1.0.7" + is-typed-array "^1.1.3" + which-typed-array "^1.1.2" + +v8-compile-cache-lib@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz#6336e8d71965cb3d35a1bbb7868445a7c05264bf" + integrity sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg== + +validate-npm-package-license@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a" + integrity sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew== + dependencies: + spdx-correct "^3.0.0" + spdx-expression-parse "^3.0.0" + +viem@2.23.4: + version "2.23.4" + resolved "https://registry.yarnpkg.com/viem/-/viem-2.23.4.tgz#164279352d7b5df2603e3d338386b026dc355b80" + integrity sha512-UQquuolKlS1w5H5e0Fd1KKoUlIPJryIEBzY5AUhGyV1ka+9O6+3uYVhUzj6RbvGK0PtsMKn2ddwPZFwjNDVU/A== + dependencies: + "@noble/curves" "1.8.1" + "@noble/hashes" "1.7.1" + "@scure/bip32" "1.6.2" + "@scure/bip39" "1.5.4" + abitype "1.0.8" + isows "1.0.6" + ox "0.6.7" + ws "8.18.0" + +viem@^2.37.9: + version "2.41.2" + resolved "https://registry.yarnpkg.com/viem/-/viem-2.41.2.tgz#117eab182b6b5501e47462269bb63f8b365a802e" + integrity sha512-LYliajglBe1FU6+EH9mSWozp+gRA/QcHfxeD9Odf83AdH5fwUS7DroH4gHvlv6Sshqi1uXrYFA2B/EOczxd15g== + dependencies: + "@noble/curves" "1.9.1" + "@noble/hashes" "1.8.0" + "@scure/bip32" "1.7.0" + "@scure/bip39" "1.6.0" + abitype "1.1.0" + isows "1.0.7" + ox "0.9.6" + ws "8.18.3" + +web-streams-polyfill@^3.0.3: + version "3.3.3" + resolved "https://registry.yarnpkg.com/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz#2073b91a2fdb1fbfbd401e7de0ac9f8214cecb4b" + integrity sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw== + +webidl-conversions@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad" + integrity sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg== + +whatwg-url@^7.0.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-7.1.0.tgz#c2c492f1eca612988efd3d2266be1b9fc6170d06" + integrity sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg== + dependencies: + lodash.sortby "^4.7.0" + tr46 "^1.0.1" + webidl-conversions "^4.0.2" + +which-typed-array@^1.1.16, which-typed-array@^1.1.2: + version "1.1.19" + resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.19.tgz#df03842e870b6b88e117524a4b364b6fc689f956" + integrity sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw== + dependencies: + available-typed-arrays "^1.0.7" + call-bind "^1.0.8" + call-bound "^1.0.4" + for-each "^0.3.5" + get-proto "^1.0.1" + gopd "^1.2.0" + has-tostringtag "^1.0.2" + +which@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" + integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== + dependencies: + isexe "^2.0.0" + +workerpool@^9.2.0: + version "9.3.4" + resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-9.3.4.tgz#f6c92395b2141afd78e2a889e80cb338fe9fca41" + integrity sha512-TmPRQYYSAnnDiEB0P/Ytip7bFGvqnSU6I2BcuSw7Hx+JSg/DsUi5ebYfc8GYaSdpuvOcEs6dXxPurOYpe9QFwg== + +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + +wrap-ansi@^8.1.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" + integrity sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ== + dependencies: + ansi-styles "^6.1.0" + string-width "^5.0.1" + strip-ansi "^7.0.1" + +write-file-atomic@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-5.0.1.tgz#68df4717c55c6fa4281a7860b4c2ba0a6d2b11e7" + integrity sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw== + dependencies: + imurmurhash "^0.1.4" + signal-exit "^4.0.1" + +write-json-file@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/write-json-file/-/write-json-file-6.0.0.tgz#52f5d8178c5beb543ed14a2a24195b696b27e7cb" + integrity sha512-MNHcU3f9WxnNyR6MxsYSj64Jz0+dwIpisWKWq9gqLj/GwmA9INg3BZ3vt70/HB3GEwrnDQWr4RPrywnhNzmUFA== + dependencies: + detect-indent "^7.0.1" + is-plain-obj "^4.1.0" + sort-keys "^5.0.0" + write-file-atomic "^5.0.1" + +write-package@^7.2.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/write-package/-/write-package-7.2.0.tgz#d84e5a0dfe92cb7d17399adc8c083d38671cd871" + integrity sha512-uMQTubF/vcu+Wd0b5BGtDmiXePd/+44hUWQz2nZPbs92/BnxRo74tqs+hqDo12RLiEd+CXFKUwxvvIZvtt34Jw== + dependencies: + deepmerge-ts "^7.1.0" + read-pkg "^9.0.1" + sort-keys "^5.0.0" + type-fest "^4.23.0" + write-json-file "^6.0.0" + +ws@8.17.1: + version "8.17.1" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.17.1.tgz#9293da530bb548febc95371d90f9c878727d919b" + integrity sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ== + +ws@8.18.0: + version "8.18.0" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.18.0.tgz#0d7505a6eafe2b0e712d232b42279f53bc289bbc" + integrity sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw== + +ws@8.18.3, ws@^8.18.0, ws@^8.18.2, ws@^8.18.3, ws@^8.8.1: + version "8.18.3" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.18.3.tgz#b56b88abffde62791c639170400c93dcb0c95472" + integrity sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg== + +y18n@^5.0.5: + version "5.0.8" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" + integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== + +yargs-parser@^21.1.1: + version "21.1.1" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35" + integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== + +yargs-unparser@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/yargs-unparser/-/yargs-unparser-2.0.0.tgz#f131f9226911ae5d9ad38c432fe809366c2325eb" + integrity sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA== + dependencies: + camelcase "^6.0.0" + decamelize "^4.0.0" + flat "^5.0.2" + is-plain-obj "^2.1.0" + +yargs@^17.7.2: + version "17.7.2" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269" + integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w== + dependencies: + cliui "^8.0.1" + escalade "^3.1.1" + get-caller-file "^2.0.5" + require-directory "^2.1.1" + string-width "^4.2.3" + y18n "^5.0.5" + yargs-parser "^21.1.1" + +yn@3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50" + integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q== + +yocto-queue@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" + integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== + +yoctocolors@^2.1.1: + version "2.1.2" + resolved "https://registry.yarnpkg.com/yoctocolors/-/yoctocolors-2.1.2.tgz#d795f54d173494e7d8db93150cec0ed7f678c83a" + integrity sha512-CzhO+pFNo8ajLM2d2IW/R93ipy99LWjtwblvC1RsoSUMZgyLbYFr221TnSNT7GjGdYui6P459mw9JH/g/zW2ug== diff --git a/evm-tests/yarn.lock b/evm-tests/yarn.lock deleted file mode 100644 index 678576deb6..0000000000 --- a/evm-tests/yarn.lock +++ /dev/null @@ -1,3245 +0,0 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. -# yarn lockfile v1 - - -"@adraffy/ens-normalize@1.10.1": - version "1.10.1" - resolved "https://registry.npmjs.org/@adraffy/ens-normalize/-/ens-normalize-1.10.1.tgz" - integrity sha512-96Z2IP3mYmF1Xg2cDm8f1gWGf/HUVedQ3FMifV4kG/PQ4yEP51xDtRAEfhVNt5f/uzpNkZHwWQuUcu6D6K+Ekw== - -"@adraffy/ens-normalize@^1.10.1": - version "1.11.0" - resolved "https://registry.npmjs.org/@adraffy/ens-normalize/-/ens-normalize-1.11.0.tgz" - integrity sha512-/3DDPKHqqIqxUULp8yP4zODUY1i+2xvVWsv8A79xGWdCAG+8sb0hRh0Rk2QyOJUnnbyPUAZYcpBuRe3nS2OIUg== - -"@babel/code-frame@^7.26.2": - version "7.27.1" - resolved "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz" - integrity sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg== - dependencies: - "@babel/helper-validator-identifier" "^7.27.1" - js-tokens "^4.0.0" - picocolors "^1.1.1" - -"@babel/helper-validator-identifier@^7.27.1": - version "7.27.1" - resolved "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz" - integrity sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow== - -"@commander-js/extra-typings@^14.0.0": - version "14.0.0" - resolved "https://registry.yarnpkg.com/@commander-js/extra-typings/-/extra-typings-14.0.0.tgz#a48b73e8e9c80d5c7538d361f9c1fb9b231643d7" - integrity sha512-hIn0ncNaJRLkZrxBIp5AsW/eXEHNKYQBh0aPdoUqNgD+Io3NIykQqpKFyKcuasZhicGaEZJX/JBSIkZ4e5x8Dg== - -"@cspotcode/source-map-support@^0.8.0": - version "0.8.1" - resolved "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz" - integrity sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw== - dependencies: - "@jridgewell/trace-mapping" "0.3.9" - -"@esbuild/aix-ppc64@0.25.5": - version "0.25.5" - resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.25.5.tgz#4e0f91776c2b340e75558f60552195f6fad09f18" - integrity sha512-9o3TMmpmftaCMepOdA5k/yDw8SfInyzWWTjYTFCX3kPSDJMROQTb8jg+h9Cnwnmm1vOzvxN7gIfB5V2ewpjtGA== - -"@esbuild/android-arm64@0.25.5": - version "0.25.5" - resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.25.5.tgz#bc766407f1718923f6b8079c8c61bf86ac3a6a4f" - integrity sha512-VGzGhj4lJO+TVGV1v8ntCZWJktV7SGCs3Pn1GRWI1SBFtRALoomm8k5E9Pmwg3HOAal2VDc2F9+PM/rEY6oIDg== - -"@esbuild/android-arm@0.25.5": - version "0.25.5" - resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.25.5.tgz#4290d6d3407bae3883ad2cded1081a234473ce26" - integrity sha512-AdJKSPeEHgi7/ZhuIPtcQKr5RQdo6OO2IL87JkianiMYMPbCtot9fxPbrMiBADOWWm3T2si9stAiVsGbTQFkbA== - -"@esbuild/android-x64@0.25.5": - version "0.25.5" - resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.25.5.tgz#40c11d9cbca4f2406548c8a9895d321bc3b35eff" - integrity sha512-D2GyJT1kjvO//drbRT3Hib9XPwQeWd9vZoBJn+bu/lVsOZ13cqNdDeqIF/xQ5/VmWvMduP6AmXvylO/PIc2isw== - -"@esbuild/darwin-arm64@0.25.5": - version "0.25.5" - resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.25.5.tgz#49d8bf8b1df95f759ac81eb1d0736018006d7e34" - integrity sha512-GtaBgammVvdF7aPIgH2jxMDdivezgFu6iKpmT+48+F8Hhg5J/sfnDieg0aeG/jfSvkYQU2/pceFPDKlqZzwnfQ== - -"@esbuild/darwin-x64@0.25.5": - version "0.25.5" - resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.25.5.tgz#e27a5d92a14886ef1d492fd50fc61a2d4d87e418" - integrity sha512-1iT4FVL0dJ76/q1wd7XDsXrSW+oLoquptvh4CLR4kITDtqi2e/xwXwdCVH8hVHU43wgJdsq7Gxuzcs6Iq/7bxQ== - -"@esbuild/freebsd-arm64@0.25.5": - version "0.25.5" - resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.5.tgz#97cede59d638840ca104e605cdb9f1b118ba0b1c" - integrity sha512-nk4tGP3JThz4La38Uy/gzyXtpkPW8zSAmoUhK9xKKXdBCzKODMc2adkB2+8om9BDYugz+uGV7sLmpTYzvmz6Sw== - -"@esbuild/freebsd-x64@0.25.5": - version "0.25.5" - resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.25.5.tgz#71c77812042a1a8190c3d581e140d15b876b9c6f" - integrity sha512-PrikaNjiXdR2laW6OIjlbeuCPrPaAl0IwPIaRv+SMV8CiM8i2LqVUHFC1+8eORgWyY7yhQY+2U2fA55mBzReaw== - -"@esbuild/linux-arm64@0.25.5": - version "0.25.5" - resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.25.5.tgz#f7b7c8f97eff8ffd2e47f6c67eb5c9765f2181b8" - integrity sha512-Z9kfb1v6ZlGbWj8EJk9T6czVEjjq2ntSYLY2cw6pAZl4oKtfgQuS4HOq41M/BcoLPzrUbNd+R4BXFyH//nHxVg== - -"@esbuild/linux-arm@0.25.5": - version "0.25.5" - resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.25.5.tgz#2a0be71b6cd8201fa559aea45598dffabc05d911" - integrity sha512-cPzojwW2okgh7ZlRpcBEtsX7WBuqbLrNXqLU89GxWbNt6uIg78ET82qifUy3W6OVww6ZWobWub5oqZOVtwolfw== - -"@esbuild/linux-ia32@0.25.5": - version "0.25.5" - resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.25.5.tgz#763414463cd9ea6fa1f96555d2762f9f84c61783" - integrity sha512-sQ7l00M8bSv36GLV95BVAdhJ2QsIbCuCjh/uYrWiMQSUuV+LpXwIqhgJDcvMTj+VsQmqAHL2yYaasENvJ7CDKA== - -"@esbuild/linux-loong64@0.25.5": - version "0.25.5" - resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.25.5.tgz#428cf2213ff786a502a52c96cf29d1fcf1eb8506" - integrity sha512-0ur7ae16hDUC4OL5iEnDb0tZHDxYmuQyhKhsPBV8f99f6Z9KQM02g33f93rNH5A30agMS46u2HP6qTdEt6Q1kg== - -"@esbuild/linux-mips64el@0.25.5": - version "0.25.5" - resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.25.5.tgz#5cbcc7fd841b4cd53358afd33527cd394e325d96" - integrity sha512-kB/66P1OsHO5zLz0i6X0RxlQ+3cu0mkxS3TKFvkb5lin6uwZ/ttOkP3Z8lfR9mJOBk14ZwZ9182SIIWFGNmqmg== - -"@esbuild/linux-ppc64@0.25.5": - version "0.25.5" - resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.25.5.tgz#0d954ab39ce4f5e50f00c4f8c4fd38f976c13ad9" - integrity sha512-UZCmJ7r9X2fe2D6jBmkLBMQetXPXIsZjQJCjgwpVDz+YMcS6oFR27alkgGv3Oqkv07bxdvw7fyB71/olceJhkQ== - -"@esbuild/linux-riscv64@0.25.5": - version "0.25.5" - resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.25.5.tgz#0e7dd30730505abd8088321e8497e94b547bfb1e" - integrity sha512-kTxwu4mLyeOlsVIFPfQo+fQJAV9mh24xL+y+Bm6ej067sYANjyEw1dNHmvoqxJUCMnkBdKpvOn0Ahql6+4VyeA== - -"@esbuild/linux-s390x@0.25.5": - version "0.25.5" - resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.25.5.tgz#5669af81327a398a336d7e40e320b5bbd6e6e72d" - integrity sha512-K2dSKTKfmdh78uJ3NcWFiqyRrimfdinS5ErLSn3vluHNeHVnBAFWC8a4X5N+7FgVE1EjXS1QDZbpqZBjfrqMTQ== - -"@esbuild/linux-x64@0.25.5": - version "0.25.5" - resolved "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.5.tgz" - integrity sha512-uhj8N2obKTE6pSZ+aMUbqq+1nXxNjZIIjCjGLfsWvVpy7gKCOL6rsY1MhRh9zLtUtAI7vpgLMK6DxjO8Qm9lJw== - -"@esbuild/netbsd-arm64@0.25.5": - version "0.25.5" - resolved "https://registry.yarnpkg.com/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.5.tgz#53b4dfb8fe1cee93777c9e366893bd3daa6ba63d" - integrity sha512-pwHtMP9viAy1oHPvgxtOv+OkduK5ugofNTVDilIzBLpoWAM16r7b/mxBvfpuQDpRQFMfuVr5aLcn4yveGvBZvw== - -"@esbuild/netbsd-x64@0.25.5": - version "0.25.5" - resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.25.5.tgz#a0206f6314ce7dc8713b7732703d0f58de1d1e79" - integrity sha512-WOb5fKrvVTRMfWFNCroYWWklbnXH0Q5rZppjq0vQIdlsQKuw6mdSihwSo4RV/YdQ5UCKKvBy7/0ZZYLBZKIbwQ== - -"@esbuild/openbsd-arm64@0.25.5": - version "0.25.5" - resolved "https://registry.yarnpkg.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.5.tgz#2a796c87c44e8de78001d808c77d948a21ec22fd" - integrity sha512-7A208+uQKgTxHd0G0uqZO8UjK2R0DDb4fDmERtARjSHWxqMTye4Erz4zZafx7Di9Cv+lNHYuncAkiGFySoD+Mw== - -"@esbuild/openbsd-x64@0.25.5": - version "0.25.5" - resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.25.5.tgz#28d0cd8909b7fa3953af998f2b2ed34f576728f0" - integrity sha512-G4hE405ErTWraiZ8UiSoesH8DaCsMm0Cay4fsFWOOUcz8b8rC6uCvnagr+gnioEjWn0wC+o1/TAHt+It+MpIMg== - -"@esbuild/sunos-x64@0.25.5": - version "0.25.5" - resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.25.5.tgz#a28164f5b997e8247d407e36c90d3fd5ddbe0dc5" - integrity sha512-l+azKShMy7FxzY0Rj4RCt5VD/q8mG/e+mDivgspo+yL8zW7qEwctQ6YqKX34DTEleFAvCIUviCFX1SDZRSyMQA== - -"@esbuild/win32-arm64@0.25.5": - version "0.25.5" - resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.25.5.tgz#6eadbead38e8bd12f633a5190e45eff80e24007e" - integrity sha512-O2S7SNZzdcFG7eFKgvwUEZ2VG9D/sn/eIiz8XRZ1Q/DO5a3s76Xv0mdBzVM5j5R639lXQmPmSo0iRpHqUUrsxw== - -"@esbuild/win32-ia32@0.25.5": - version "0.25.5" - resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.25.5.tgz#bab6288005482f9ed2adb9ded7e88eba9a62cc0d" - integrity sha512-onOJ02pqs9h1iMJ1PQphR+VZv8qBMQ77Klcsqv9CNW2w6yLqoURLcgERAIurY6QE63bbLuqgP9ATqajFLK5AMQ== - -"@esbuild/win32-x64@0.25.5": - version "0.25.5" - resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.25.5.tgz#7fc114af5f6563f19f73324b5d5ff36ece0803d1" - integrity sha512-TXv6YnJ8ZMVdX+SXWVBo/0p8LTcrUYngpWjvm91TMjjBQii7Oz11Lw5lbDV5Y0TzuhSJHwiH4hEtC1I42mMS0g== - -"@isaacs/cliui@^8.0.2": - version "8.0.2" - resolved "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz" - integrity sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA== - dependencies: - string-width "^5.1.2" - string-width-cjs "npm:string-width@^4.2.0" - strip-ansi "^7.0.1" - strip-ansi-cjs "npm:strip-ansi@^6.0.1" - wrap-ansi "^8.1.0" - wrap-ansi-cjs "npm:wrap-ansi@^7.0.0" - -"@jridgewell/gen-mapping@^0.3.2": - version "0.3.8" - resolved "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz" - integrity sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA== - dependencies: - "@jridgewell/set-array" "^1.2.1" - "@jridgewell/sourcemap-codec" "^1.4.10" - "@jridgewell/trace-mapping" "^0.3.24" - -"@jridgewell/resolve-uri@^3.0.3", "@jridgewell/resolve-uri@^3.1.0": - version "3.1.2" - resolved "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz" - integrity sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw== - -"@jridgewell/set-array@^1.2.1": - version "1.2.1" - resolved "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz" - integrity sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A== - -"@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.14", "@jridgewell/sourcemap-codec@^1.5.0": - version "1.5.0" - resolved "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz" - integrity sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ== - -"@jridgewell/trace-mapping@0.3.9": - version "0.3.9" - resolved "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz" - integrity sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ== - dependencies: - "@jridgewell/resolve-uri" "^3.0.3" - "@jridgewell/sourcemap-codec" "^1.4.10" - -"@jridgewell/trace-mapping@^0.3.24": - version "0.3.25" - resolved "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz" - integrity sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ== - dependencies: - "@jridgewell/resolve-uri" "^3.1.0" - "@jridgewell/sourcemap-codec" "^1.4.14" - -"@noble/curves@1.2.0": - version "1.2.0" - resolved "https://registry.npmjs.org/@noble/curves/-/curves-1.2.0.tgz" - integrity sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw== - dependencies: - "@noble/hashes" "1.3.2" - -"@noble/curves@1.8.1", "@noble/curves@^1.6.0", "@noble/curves@~1.8.1": - version "1.8.1" - resolved "https://registry.npmjs.org/@noble/curves/-/curves-1.8.1.tgz" - integrity sha512-warwspo+UYUPep0Q+vtdVB4Ugn8GGQj8iyB3gnRWsztmUHTI3S1nhdiWNsPUGL0vud7JlRRk1XEu7Lq1KGTnMQ== - dependencies: - "@noble/hashes" "1.7.1" - -"@noble/curves@^1.3.0": - version "1.9.7" - resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.9.7.tgz#79d04b4758a43e4bca2cbdc62e7771352fa6b951" - integrity sha512-gbKGcRUYIjA3/zCCNaWDciTMFI0dCkvou3TL8Zmy5Nc7sJ47a0jtOeZoTaMxkuqRo9cRhjOdZJXegxYE5FN/xw== - dependencies: - "@noble/hashes" "1.8.0" - -"@noble/curves@^2.0.0", "@noble/curves@~2.0.0": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-2.0.0.tgz#1b1d75b447e5ccfaa6a4a3c34280f0c02a763f57" - integrity sha512-RiwZZeJnsTnhT+/gg2KvITJZhK5oagQrpZo+yQyd3mv3D5NAG2qEeEHpw7IkXRlpkoD45wl2o4ydHAvY9wyEfw== - dependencies: - "@noble/hashes" "2.0.0" - -"@noble/hashes@1.3.2": - version "1.3.2" - resolved "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.2.tgz" - integrity sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ== - -"@noble/hashes@1.7.1", "@noble/hashes@^1.5.0", "@noble/hashes@~1.7.1": - version "1.7.1" - resolved "https://registry.npmjs.org/@noble/hashes/-/hashes-1.7.1.tgz" - integrity sha512-B8XBPsn4vT/KJAGqDzbwztd+6Yte3P4V7iafm24bxgDe/mlRuK6xmWPuCNrKt2vDafZ8MfJLlchDG/vYafQEjQ== - -"@noble/hashes@1.8.0", "@noble/hashes@^1.3.1", "@noble/hashes@^1.3.3", "@noble/hashes@^1.8.0": - version "1.8.0" - resolved "https://registry.npmjs.org/@noble/hashes/-/hashes-1.8.0.tgz" - integrity sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A== - -"@noble/hashes@2.0.0", "@noble/hashes@^2.0.0", "@noble/hashes@~2.0.0": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-2.0.0.tgz#5c39388259a0868cadb17d688cd8cf07eae344a4" - integrity sha512-h8VUBlE8R42+XIDO229cgisD287im3kdY6nbNZJFjc6ZvKIXPYXe6Vc/t+kyjFdMFyt5JpapzTsEg8n63w5/lw== - -"@pkgjs/parseargs@^0.11.0": - version "0.11.0" - resolved "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz" - integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg== - -"@polkadot-api/cli@0.14.5": - version "0.14.5" - resolved "https://registry.yarnpkg.com/@polkadot-api/cli/-/cli-0.14.5.tgz#e87cef726d6844d720170e917d00d86b7b4955d8" - integrity sha512-510nvNWsOOYQJZq1ZJKPlvQ81sNXmwlmb8Ww9UI5THgarFJcuUvPe7W/kCRAUBdrK5yp5hziVrxuy84p55pWDQ== - dependencies: - "@commander-js/extra-typings" "^14.0.0" - "@polkadot-api/codegen" "0.17.1" - "@polkadot-api/ink-contracts" "0.3.7" - "@polkadot-api/json-rpc-provider" "0.0.4" - "@polkadot-api/known-chains" "0.9.3" - "@polkadot-api/metadata-compatibility" "0.3.2" - "@polkadot-api/observable-client" "0.13.4" - "@polkadot-api/polkadot-sdk-compat" "2.3.2" - "@polkadot-api/sm-provider" "0.1.7" - "@polkadot-api/smoldot" "0.3.10" - "@polkadot-api/substrate-bindings" "0.15.1" - "@polkadot-api/substrate-client" "0.4.2" - "@polkadot-api/utils" "0.2.0" - "@polkadot-api/wasm-executor" "^0.2.1" - "@polkadot-api/ws-provider" "0.4.1" - "@types/node" "^24.0.14" - commander "^14.0.0" - execa "^9.6.0" - fs.promises.exists "^1.1.4" - ora "^8.2.0" - read-pkg "^9.0.1" - rxjs "^7.8.2" - tsc-prog "^2.3.0" - tsup "^8.5.0" - typescript "^5.8.3" - write-package "^7.1.0" - -"@polkadot-api/codegen@0.17.1": - version "0.17.1" - resolved "https://registry.yarnpkg.com/@polkadot-api/codegen/-/codegen-0.17.1.tgz#53af24167656cbf327ec7a0e418225957f438108" - integrity sha512-JAbKbnqNH5W/siIA2tYJqCsDehzXOVStTrSgiWuIjfly+6fvXig/tKqoreNpY6NAmAe9BBkVw8kSfZs4mm/UfA== - dependencies: - "@polkadot-api/ink-contracts" "0.3.7" - "@polkadot-api/metadata-builders" "0.13.1" - "@polkadot-api/metadata-compatibility" "0.3.2" - "@polkadot-api/substrate-bindings" "0.15.1" - "@polkadot-api/utils" "0.2.0" - -"@polkadot-api/descriptors@file:.papi/descriptors": - version "0.1.0-autogenerated.1855018811236749851" - -"@polkadot-api/ink-contracts@0.3.7": - version "0.3.7" - resolved "https://registry.yarnpkg.com/@polkadot-api/ink-contracts/-/ink-contracts-0.3.7.tgz#d3f3800c542a8bfd149373686a5190397d450e30" - integrity sha512-n72H9xu7E7gvVB3+YhRRcYuD5ozc5u2Camv/NyYRrKg+omoL3qtn6k9ucPb1j77GbrZA1dLXpBYmjd9fVuQ4Xg== - dependencies: - "@polkadot-api/metadata-builders" "0.13.1" - "@polkadot-api/substrate-bindings" "0.15.1" - "@polkadot-api/utils" "0.2.0" - -"@polkadot-api/json-rpc-provider-proxy@0.2.4": - version "0.2.4" - resolved "https://registry.npmjs.org/@polkadot-api/json-rpc-provider-proxy/-/json-rpc-provider-proxy-0.2.4.tgz" - integrity sha512-nuGoY9QpBAiRU7xmXN3nugFvPcnSu3IxTLm1OWcNTGlZ1LW5bvdQHz3JLk56+Jlyb3GJ971hqdg2DJsMXkKCOg== - -"@polkadot-api/json-rpc-provider-proxy@^0.1.0": - version "0.1.0" - resolved "https://registry.yarnpkg.com/@polkadot-api/json-rpc-provider-proxy/-/json-rpc-provider-proxy-0.1.0.tgz#6e191f28e7d0fbbe8b540fc51d12a0adaeba297e" - integrity sha512-8GSFE5+EF73MCuLQm8tjrbCqlgclcHBSRaswvXziJ0ZW7iw3UEMsKkkKvELayWyBuOPa2T5i1nj6gFOeIsqvrg== - -"@polkadot-api/json-rpc-provider@0.0.1", "@polkadot-api/json-rpc-provider@^0.0.1": - version "0.0.1" - resolved "https://registry.yarnpkg.com/@polkadot-api/json-rpc-provider/-/json-rpc-provider-0.0.1.tgz#333645d40ccd9bccfd1f32503f17e4e63e76e297" - integrity sha512-/SMC/l7foRjpykLTUTacIH05H3mr9ip8b5xxfwXlVezXrNVLp3Cv0GX6uItkKd+ZjzVPf3PFrDF2B2/HLSNESA== - -"@polkadot-api/json-rpc-provider@0.0.4": - version "0.0.4" - resolved "https://registry.npmjs.org/@polkadot-api/json-rpc-provider/-/json-rpc-provider-0.0.4.tgz" - integrity sha512-9cDijLIxzHOBuq6yHqpqjJ9jBmXrctjc1OFqU+tQrS96adQze3mTIH6DTgfb/0LMrqxzxffz1HQGrIlEH00WrA== - -"@polkadot-api/json-rpc-provider@workspace:*": - version "0.0.4" - resolved "https://registry.yarnpkg.com/@polkadot-api/json-rpc-provider/-/json-rpc-provider-0.0.4.tgz#15d0c6a7ec14aa6d0dd64039f931bebea83ffdb3" - integrity sha512-9cDijLIxzHOBuq6yHqpqjJ9jBmXrctjc1OFqU+tQrS96adQze3mTIH6DTgfb/0LMrqxzxffz1HQGrIlEH00WrA== - -"@polkadot-api/known-chains@0.9.3": - version "0.9.3" - resolved "https://registry.yarnpkg.com/@polkadot-api/known-chains/-/known-chains-0.9.3.tgz#e0a65be93fef367cc27cd4dfc3cef3b877846547" - integrity sha512-zP+6R8JrrkDfFa5p6pBtRGCxuc0vJlzbgJ/EXokpe+FHl4HyVobj0fgo9UXklOXXbV2iTQnNXOsXiE8QfLBwIQ== - -"@polkadot-api/logs-provider@0.0.6": - version "0.0.6" - resolved "https://registry.npmjs.org/@polkadot-api/logs-provider/-/logs-provider-0.0.6.tgz" - integrity sha512-4WgHlvy+xee1ADaaVf6+MlK/+jGMtsMgAzvbQOJZnP4PfQuagoTqaeayk8HYKxXGphogLlPbD06tANxcb+nvAg== - dependencies: - "@polkadot-api/json-rpc-provider" "0.0.4" - -"@polkadot-api/merkleize-metadata@1.1.20": - version "1.1.20" - resolved "https://registry.yarnpkg.com/@polkadot-api/merkleize-metadata/-/merkleize-metadata-1.1.20.tgz#bcda511fa3fdc7f9c465396f4843987e4e1dd575" - integrity sha512-biHRZbMJkKhmzBegiOk4W+iwiVNgNQ1YV5QzMrgmFwFeGBhm8iaNILnz0iB7t48+IaiWczQYnT3ZqYMTJslXwg== - dependencies: - "@polkadot-api/metadata-builders" "0.13.1" - "@polkadot-api/substrate-bindings" "0.15.1" - "@polkadot-api/utils" "0.2.0" - -"@polkadot-api/metadata-builders@0.13.1": - version "0.13.1" - resolved "https://registry.yarnpkg.com/@polkadot-api/metadata-builders/-/metadata-builders-0.13.1.tgz#9c78bffa3f28bbb0da0c059b95c012de2efb9638" - integrity sha512-a0vnN/BmSBnpsC/rD52Uej8dIiwWwdVy0K67NKw8jmRgl2LXYbsy4YSLB49WDwCD6p9AGm5chydNDCGYq4wOMw== - dependencies: - "@polkadot-api/substrate-bindings" "0.15.1" - "@polkadot-api/utils" "0.2.0" - -"@polkadot-api/metadata-builders@0.3.2": - version "0.3.2" - resolved "https://registry.yarnpkg.com/@polkadot-api/metadata-builders/-/metadata-builders-0.3.2.tgz#007f158c9e0546cf79ba440befc0c753ab1a6629" - integrity sha512-TKpfoT6vTb+513KDzMBTfCb/ORdgRnsS3TDFpOhAhZ08ikvK+hjHMt5plPiAX/OWkm1Wc9I3+K6W0hX5Ab7MVg== - dependencies: - "@polkadot-api/substrate-bindings" "0.6.0" - "@polkadot-api/utils" "0.1.0" - -"@polkadot-api/metadata-compatibility@0.3.2": - version "0.3.2" - resolved "https://registry.yarnpkg.com/@polkadot-api/metadata-compatibility/-/metadata-compatibility-0.3.2.tgz#940c5ae355edc2fa17d8eef36668d467bbf9ccf0" - integrity sha512-3RE2e4hyeucx1uSvYt5sVQozjLLAEX3RDBM0XWqjHHjTqomihF8c+ozuoXtprR2h92x9UdiHg/jYuDT6/cL24w== - dependencies: - "@polkadot-api/metadata-builders" "0.13.1" - "@polkadot-api/substrate-bindings" "0.15.1" - -"@polkadot-api/observable-client@0.13.4": - version "0.13.4" - resolved "https://registry.yarnpkg.com/@polkadot-api/observable-client/-/observable-client-0.13.4.tgz#d9a913469e042211c1d3461e76ee2dade24b07a6" - integrity sha512-UYdssmUSMS0YKBtoQx9hFeSYDKg27iYx0FQZKmPHRfZ9Mk8EYZq4Mls71sTjuqXTl34GwYMgjrPUaSpK7jBL0w== - dependencies: - "@polkadot-api/metadata-builders" "0.13.1" - "@polkadot-api/substrate-bindings" "0.15.1" - "@polkadot-api/utils" "0.2.0" - -"@polkadot-api/observable-client@^0.3.0": - version "0.3.2" - resolved "https://registry.yarnpkg.com/@polkadot-api/observable-client/-/observable-client-0.3.2.tgz#fd91efee350595a6e0ecfd3f294cc80de86c0cf7" - integrity sha512-HGgqWgEutVyOBXoGOPp4+IAq6CNdK/3MfQJmhCJb8YaJiaK4W6aRGrdQuQSTPHfERHCARt9BrOmEvTXAT257Ug== - dependencies: - "@polkadot-api/metadata-builders" "0.3.2" - "@polkadot-api/substrate-bindings" "0.6.0" - "@polkadot-api/utils" "0.1.0" - -"@polkadot-api/pjs-signer@0.6.11": - version "0.6.11" - resolved "https://registry.yarnpkg.com/@polkadot-api/pjs-signer/-/pjs-signer-0.6.11.tgz#0dd235c8d37c9ee411df92ba1d4e250418f66b66" - integrity sha512-tgv4l/PsCzOxJ8TXXd4x1QEZPow7Mt8WaUSIt+dUFLMKO+ZPWS0WEsBc0oMvHbriJuDSILmEi7YVXPFukF5OIA== - dependencies: - "@polkadot-api/metadata-builders" "0.13.1" - "@polkadot-api/polkadot-signer" "0.1.6" - "@polkadot-api/signers-common" "0.1.12" - "@polkadot-api/substrate-bindings" "0.15.1" - "@polkadot-api/utils" "0.2.0" - -"@polkadot-api/polkadot-sdk-compat@2.3.2": - version "2.3.2" - resolved "https://registry.npmjs.org/@polkadot-api/polkadot-sdk-compat/-/polkadot-sdk-compat-2.3.2.tgz" - integrity sha512-rLCveP3a6Xd0r218yRqVY34lJ8bXVmE12cArbU4JFp9p8e8Jbb6xdqOdu7bQtjlZUsahhcmfIHYQSXKziST7PA== - dependencies: - "@polkadot-api/json-rpc-provider" "0.0.4" - -"@polkadot-api/polkadot-signer@0.1.6": - version "0.1.6" - resolved "https://registry.npmjs.org/@polkadot-api/polkadot-signer/-/polkadot-signer-0.1.6.tgz" - integrity sha512-X7ghAa4r7doETtjAPTb50IpfGtrBmy3BJM5WCfNKa1saK04VFY9w+vDn+hwEcM4p0PcDHt66Ts74hzvHq54d9A== - -"@polkadot-api/raw-client@0.1.0": - version "0.1.0" - resolved "https://registry.yarnpkg.com/@polkadot-api/raw-client/-/raw-client-0.1.0.tgz#495c9cd65c2e34927bf4a737051c21e09db296ed" - integrity sha512-gHhPxTy9jbpoX3MBKT5QwPKX4gNmapJ+dC+ACZ5AXuqMraAUnFR1lu0QeUWH04Tc2gykVH1Eigz1kTDCSpN+zA== - dependencies: - "@polkadot-api/json-rpc-provider" "workspace:*" - -"@polkadot-api/signer@0.2.4": - version "0.2.4" - resolved "https://registry.yarnpkg.com/@polkadot-api/signer/-/signer-0.2.4.tgz#36a36bb4f7f0f2c1d1477798fff1ba4eb0da4d01" - integrity sha512-DOTUCnVwvWWEnJ1u/oyPbVk/RplDKJpRKJUOUGraoYh+J0PBicLvdVQF8680Guo/GJf7GBQpSFnev3mIcma6Pg== - dependencies: - "@noble/hashes" "^1.8.0" - "@polkadot-api/merkleize-metadata" "1.1.20" - "@polkadot-api/polkadot-signer" "0.1.6" - "@polkadot-api/signers-common" "0.1.12" - "@polkadot-api/substrate-bindings" "0.15.1" - "@polkadot-api/utils" "0.2.0" - -"@polkadot-api/signers-common@0.1.12": - version "0.1.12" - resolved "https://registry.yarnpkg.com/@polkadot-api/signers-common/-/signers-common-0.1.12.tgz#e3e08dcad3f7ec356e0dd726c7ac2cf1621e82ed" - integrity sha512-wnNe08BbH1nG6XUy3hNbpRKsbAXFU0m4YovXp74hEDw0ycyjni0RnO2sUEV/vaghej8xFtD+7abjzE/lzmnHRA== - dependencies: - "@polkadot-api/metadata-builders" "0.13.1" - "@polkadot-api/polkadot-signer" "0.1.6" - "@polkadot-api/substrate-bindings" "0.15.1" - "@polkadot-api/utils" "0.2.0" - -"@polkadot-api/sm-provider@0.1.7": - version "0.1.7" - resolved "https://registry.npmjs.org/@polkadot-api/sm-provider/-/sm-provider-0.1.7.tgz" - integrity sha512-BhNKVeIFZdawpPVadXszLl8IP4EDjcLHe/GchfRRFkvoNFuwS2nNv/npYIqCviXV+dd2R8VnEELxwScsf380Og== - dependencies: - "@polkadot-api/json-rpc-provider" "0.0.4" - "@polkadot-api/json-rpc-provider-proxy" "0.2.4" - -"@polkadot-api/smoldot@0.3.10": - version "0.3.10" - resolved "https://registry.yarnpkg.com/@polkadot-api/smoldot/-/smoldot-0.3.10.tgz#e7d9316546f5c214d4ce083b5458f3fc5cc69531" - integrity sha512-oL0Qsq2p3h2mU1/+gNq4h2rC/S99WoDiqkpmxg/phzknjXcbYXouYLSvhGbECygE1vWPVPl3IWAOjW/gcKdYKw== - dependencies: - "@types/node" "^22.15.30" - smoldot "2.0.36" - -"@polkadot-api/substrate-bindings@0.15.1": - version "0.15.1" - resolved "https://registry.yarnpkg.com/@polkadot-api/substrate-bindings/-/substrate-bindings-0.15.1.tgz#d6fbd758eb87fb4b3617ea170ef4ca326f4b9ac9" - integrity sha512-zQqgjjEqx7aQtssu5OMm+nLOGDQXvPZUrWGwtbT6rWJNDB5s3FcMhG5RBiBB2HUwjWPrC28XO/A2c8dNUtRKOw== - dependencies: - "@noble/hashes" "^1.8.0" - "@polkadot-api/utils" "0.2.0" - "@scure/base" "^1.2.6" - scale-ts "^1.6.1" - -"@polkadot-api/substrate-bindings@0.6.0": - version "0.6.0" - resolved "https://registry.yarnpkg.com/@polkadot-api/substrate-bindings/-/substrate-bindings-0.6.0.tgz#889b0c3ba19dc95282286506bf6e370a43ce119a" - integrity sha512-lGuhE74NA1/PqdN7fKFdE5C1gNYX357j1tWzdlPXI0kQ7h3kN0zfxNOpPUN7dIrPcOFZ6C0tRRVrBylXkI6xPw== - dependencies: - "@noble/hashes" "^1.3.1" - "@polkadot-api/utils" "0.1.0" - "@scure/base" "^1.1.1" - scale-ts "^1.6.0" - -"@polkadot-api/substrate-client@0.4.2": - version "0.4.2" - resolved "https://registry.yarnpkg.com/@polkadot-api/substrate-client/-/substrate-client-0.4.2.tgz#74fda584e9646066233a80eec5eccc3248ab1257" - integrity sha512-RXOqIy0h1EsiHiubPxZedVNbwBJR3Z/+bBlDFIxS81CSjP8eohs8xHQ/SDUm+4279XATwHdb8qeWnotFNcpl8A== - dependencies: - "@polkadot-api/json-rpc-provider" "0.0.4" - "@polkadot-api/raw-client" "0.1.0" - "@polkadot-api/utils" "0.2.0" - -"@polkadot-api/substrate-client@^0.1.2": - version "0.1.4" - resolved "https://registry.yarnpkg.com/@polkadot-api/substrate-client/-/substrate-client-0.1.4.tgz#7a808e5cb85ecb9fa2b3a43945090a6c807430ce" - integrity sha512-MljrPobN0ZWTpn++da9vOvt+Ex+NlqTlr/XT7zi9sqPtDJiQcYl+d29hFAgpaeTqbeQKZwz3WDE9xcEfLE8c5A== - dependencies: - "@polkadot-api/json-rpc-provider" "0.0.1" - "@polkadot-api/utils" "0.1.0" - -"@polkadot-api/utils@0.1.0": - version "0.1.0" - resolved "https://registry.yarnpkg.com/@polkadot-api/utils/-/utils-0.1.0.tgz#d36937cdc465c2ea302f3278cf53157340ab33a0" - integrity sha512-MXzWZeuGxKizPx2Xf/47wx9sr/uxKw39bVJUptTJdsaQn/TGq+z310mHzf1RCGvC1diHM8f593KrnDgc9oNbJA== - -"@polkadot-api/utils@0.2.0": - version "0.2.0" - resolved "https://registry.yarnpkg.com/@polkadot-api/utils/-/utils-0.2.0.tgz#812d4c4ee282691440aed4b6ddf863651e804444" - integrity sha512-nY3i5fQJoAxU4n3bD7Fs208/KR2J95SGfVc58kDjbRYN5a84kWaGEqzjBNtP9oqht49POM8Bm9mbIrkvC1Bzuw== - -"@polkadot-api/wasm-executor@^0.2.1": - version "0.2.1" - resolved "https://registry.yarnpkg.com/@polkadot-api/wasm-executor/-/wasm-executor-0.2.1.tgz#632b2ebc243b55eda4b1dd71cc457b51406a229e" - integrity sha512-EN3qtu9Aurz1PoEjvrvL/Z9lSMrLkRU2K1fOjzWFpI5siBgQ2eN/tMLbX1VjaSk1VhvXmbXPaqBrkfdMCxLdsg== - -"@polkadot-api/ws-provider@0.4.1": - version "0.4.1" - resolved "https://registry.yarnpkg.com/@polkadot-api/ws-provider/-/ws-provider-0.4.1.tgz#8e0eb0e189cfa6c1fa2d0282ad5ab9fc8a11fc60" - integrity sha512-C4SM3IExBghHAaNIGL7Xi1Pg8+1dJCOgYQ4HmdYUqqP2rcNtUUN68jx5vTfPFtCPw4z7kldP4DvL0BU0YtmauQ== - dependencies: - "@polkadot-api/json-rpc-provider" "0.0.4" - "@polkadot-api/json-rpc-provider-proxy" "0.2.4" - ws "^8.18.3" - -"@polkadot-labs/hdkd-helpers@^0.0.23", "@polkadot-labs/hdkd-helpers@~0.0.23": - version "0.0.23" - resolved "https://registry.yarnpkg.com/@polkadot-labs/hdkd-helpers/-/hdkd-helpers-0.0.23.tgz#68b8ec8fb3e26e1eaeed289db2fa54eb13adefe9" - integrity sha512-wfayRSCqOhcg4eaTltdynQHrn53FftGZ3Ws1HmxlE4N6VJYTfsTrfHAWI7l3BZz14nUUDDZe7IlvyX14Qqaakw== - dependencies: - "@noble/curves" "^2.0.0" - "@noble/hashes" "^2.0.0" - "@scure/base" "^2.0.0" - "@scure/sr25519" "^0.3.0" - scale-ts "^1.6.1" - -"@polkadot-labs/hdkd@^0.0.23": - version "0.0.23" - resolved "https://registry.yarnpkg.com/@polkadot-labs/hdkd/-/hdkd-0.0.23.tgz#fecacb353c7f9d15aa9f826ba4208e8828935399" - integrity sha512-EyBNsdoX2SQrjp3PpBv2kvtkvL3714ydqKwXH1t3kWOuBq6VwnOm0zRMkmGawhFA+25aUEnBC/dmwI4Xb4hCYg== - dependencies: - "@polkadot-labs/hdkd-helpers" "~0.0.23" - -"@polkadot/api-augment@16.4.6": - version "16.4.6" - resolved "https://registry.yarnpkg.com/@polkadot/api-augment/-/api-augment-16.4.6.tgz#9c23c100736ccf469091153b992547037a2b1e06" - integrity sha512-YoNOKNk5dca/32Lu5aaLdafGkkUbMHjKRSzrOUAx48jVUWaQYz0WXps2zfx1zDM2hqIgcmkgCQfMdzwHRnj63w== - dependencies: - "@polkadot/api-base" "16.4.6" - "@polkadot/rpc-augment" "16.4.6" - "@polkadot/types" "16.4.6" - "@polkadot/types-augment" "16.4.6" - "@polkadot/types-codec" "16.4.6" - "@polkadot/util" "^13.5.6" - tslib "^2.8.1" - -"@polkadot/api-base@16.4.6": - version "16.4.6" - resolved "https://registry.yarnpkg.com/@polkadot/api-base/-/api-base-16.4.6.tgz#223b28f93b58734b3d3cb37874de0cbaf535ba01" - integrity sha512-tR7rtNmK+NSqqYLzj0C0OPBqqTMOFiyIxKRj2D3/d1IiS6/pUUo455xdwDPTyuUj7adAinSSUOcTtFOcI5BLOA== - dependencies: - "@polkadot/rpc-core" "16.4.6" - "@polkadot/types" "16.4.6" - "@polkadot/util" "^13.5.6" - rxjs "^7.8.1" - tslib "^2.8.1" - -"@polkadot/api-derive@16.4.6": - version "16.4.6" - resolved "https://registry.yarnpkg.com/@polkadot/api-derive/-/api-derive-16.4.6.tgz#bc7e9ba2695d6d5ed5347e911870aed89ca0912b" - integrity sha512-kh57AhyLtKU3dM2SLCitMEqUJ3cIjwtLtMpiMB7yNH/OvaE7BZ3VO1TuWoU2+kKgyL8DdX6vhdmM5G9/ni+B3w== - dependencies: - "@polkadot/api" "16.4.6" - "@polkadot/api-augment" "16.4.6" - "@polkadot/api-base" "16.4.6" - "@polkadot/rpc-core" "16.4.6" - "@polkadot/types" "16.4.6" - "@polkadot/types-codec" "16.4.6" - "@polkadot/util" "^13.5.6" - "@polkadot/util-crypto" "^13.5.6" - rxjs "^7.8.1" - tslib "^2.8.1" - -"@polkadot/api@16.4.6", "@polkadot/api@^16.4.6": - version "16.4.6" - resolved "https://registry.yarnpkg.com/@polkadot/api/-/api-16.4.6.tgz#86fbecb60867ae6eae1ed11a7962819e4abdfd80" - integrity sha512-/RYqejRoAgTR0PJpxRYWgYO7iKMXS/mIhFr7vLKzYNOzEA0nePUHE3iYkrhAj2Rluwy1gPcVoUU8/EYGVsWLGQ== - dependencies: - "@polkadot/api-augment" "16.4.6" - "@polkadot/api-base" "16.4.6" - "@polkadot/api-derive" "16.4.6" - "@polkadot/keyring" "^13.5.6" - "@polkadot/rpc-augment" "16.4.6" - "@polkadot/rpc-core" "16.4.6" - "@polkadot/rpc-provider" "16.4.6" - "@polkadot/types" "16.4.6" - "@polkadot/types-augment" "16.4.6" - "@polkadot/types-codec" "16.4.6" - "@polkadot/types-create" "16.4.6" - "@polkadot/types-known" "16.4.6" - "@polkadot/util" "^13.5.6" - "@polkadot/util-crypto" "^13.5.6" - eventemitter3 "^5.0.1" - rxjs "^7.8.1" - tslib "^2.8.1" - -"@polkadot/keyring@^13.5.6": - version "13.5.6" - resolved "https://registry.yarnpkg.com/@polkadot/keyring/-/keyring-13.5.6.tgz#b26d0cba323bb0520826211317701aa540428406" - integrity sha512-Ybe6Mflrh96FKR5tfEaf/93RxJD7x9UigseNOJW6Yd8LF+GesdxrqmZD7zh+53Hb7smGQWf/0FCfwhoWZVgPUQ== - dependencies: - "@polkadot/util" "13.5.6" - "@polkadot/util-crypto" "13.5.6" - tslib "^2.8.0" - -"@polkadot/networks@13.5.6", "@polkadot/networks@^13.5.6": - version "13.5.6" - resolved "https://registry.yarnpkg.com/@polkadot/networks/-/networks-13.5.6.tgz#fc74b556dc2aa03a49ee6543df0ae74a280da7a5" - integrity sha512-9HqUIBOHnz9x/ssPb0aOD/7XcU8vGokEYpLoNgexFNIJzqDgrDHXR197iFpkbMqA/+98zagrvYUyPYj1yYs9Jw== - dependencies: - "@polkadot/util" "13.5.6" - "@substrate/ss58-registry" "^1.51.0" - tslib "^2.8.0" - -"@polkadot/rpc-augment@16.4.6": - version "16.4.6" - resolved "https://registry.yarnpkg.com/@polkadot/rpc-augment/-/rpc-augment-16.4.6.tgz#ee4c56c9c0feb281adbbdd23ec6768d487ff53e3" - integrity sha512-Fqx41st3KTCfk831OrAh69ftBzqxklEi5e5S/rB2l5F+OQYAsbGMfTSFWTRRVGgBliWZO+T/Tpw2zJqUwrgn3Q== - dependencies: - "@polkadot/rpc-core" "16.4.6" - "@polkadot/types" "16.4.6" - "@polkadot/types-codec" "16.4.6" - "@polkadot/util" "^13.5.6" - tslib "^2.8.1" - -"@polkadot/rpc-core@16.4.6": - version "16.4.6" - resolved "https://registry.yarnpkg.com/@polkadot/rpc-core/-/rpc-core-16.4.6.tgz#f46bd58e31f04846abc9e2bf02620f1cba1dc943" - integrity sha512-xi3VIGRXjebdz0jctZpa7y2A+JaI9LSBdUgkHoUOmGrpNzDpMXoE2xWdxg3M/0hql69mSLhatWS9JvSb5MrBTQ== - dependencies: - "@polkadot/rpc-augment" "16.4.6" - "@polkadot/rpc-provider" "16.4.6" - "@polkadot/types" "16.4.6" - "@polkadot/util" "^13.5.6" - rxjs "^7.8.1" - tslib "^2.8.1" - -"@polkadot/rpc-provider@16.4.6": - version "16.4.6" - resolved "https://registry.yarnpkg.com/@polkadot/rpc-provider/-/rpc-provider-16.4.6.tgz#d0b47f4c67076a89a60857e8cc47881bf7a15eba" - integrity sha512-/ZD1rOWBRoMxnp039pOa8Czpjr/l4+3YYY5OcW9WZj16dRcJK84qVi1m91Hro+Gfe9Dus8VeOD/ncJB+a+haRA== - dependencies: - "@polkadot/keyring" "^13.5.6" - "@polkadot/types" "16.4.6" - "@polkadot/types-support" "16.4.6" - "@polkadot/util" "^13.5.6" - "@polkadot/util-crypto" "^13.5.6" - "@polkadot/x-fetch" "^13.5.6" - "@polkadot/x-global" "^13.5.6" - "@polkadot/x-ws" "^13.5.6" - eventemitter3 "^5.0.1" - mock-socket "^9.3.1" - nock "^13.5.5" - tslib "^2.8.1" - optionalDependencies: - "@substrate/connect" "0.8.11" - -"@polkadot/types-augment@16.4.6": - version "16.4.6" - resolved "https://registry.yarnpkg.com/@polkadot/types-augment/-/types-augment-16.4.6.tgz#6b9f712dd755b6bc1d771b6238521698e4ff0261" - integrity sha512-ZFe6j+HHK+ST4D2MwV7oC4y6pyBMZV1b8ZZT2htTtWf03PE0W2ziQVM+Fg42iSHpgmCyJLSABU11QkGSGtRfyQ== - dependencies: - "@polkadot/types" "16.4.6" - "@polkadot/types-codec" "16.4.6" - "@polkadot/util" "^13.5.6" - tslib "^2.8.1" - -"@polkadot/types-codec@16.4.6": - version "16.4.6" - resolved "https://registry.yarnpkg.com/@polkadot/types-codec/-/types-codec-16.4.6.tgz#54ef45a84b807c73054d739cf77cb21f62acb462" - integrity sha512-KCDDJNPTrScQV1HEMNjBIvtx12/J+DPV/niC+klb39wqeBAt7+wYNd8zSnFQzrLvx+n2eWlJjq0dxQiK+Ljc5A== - dependencies: - "@polkadot/util" "^13.5.6" - "@polkadot/x-bigint" "^13.5.6" - tslib "^2.8.1" - -"@polkadot/types-create@16.4.6": - version "16.4.6" - resolved "https://registry.yarnpkg.com/@polkadot/types-create/-/types-create-16.4.6.tgz#55bf3178daeb82345f9e858c007aac0b4aa4974d" - integrity sha512-+ABF/SKX+xuCPyKvcHIFNybQYQID7bTfvQPkRhK1QxssMwdVtpYCb6RxYU7gYQhlMBAyEZUwele6/JwT/J5VqA== - dependencies: - "@polkadot/types-codec" "16.4.6" - "@polkadot/util" "^13.5.6" - tslib "^2.8.1" - -"@polkadot/types-known@16.4.6": - version "16.4.6" - resolved "https://registry.yarnpkg.com/@polkadot/types-known/-/types-known-16.4.6.tgz#6b2c028f19dcf55dc5272b9038f99edd9177db9d" - integrity sha512-aYCWhn0l+19Vasn32SbXbxf19RX1IHaCizYtSW02FlNKpVlZGfOdqebtpQZUz5TmPIkvk1LGPo+qF0xiJSVlOA== - dependencies: - "@polkadot/networks" "^13.5.6" - "@polkadot/types" "16.4.6" - "@polkadot/types-codec" "16.4.6" - "@polkadot/types-create" "16.4.6" - "@polkadot/util" "^13.5.6" - tslib "^2.8.1" - -"@polkadot/types-support@16.4.6": - version "16.4.6" - resolved "https://registry.yarnpkg.com/@polkadot/types-support/-/types-support-16.4.6.tgz#35fc46454193b73df150040b8f268c9e3c9f87c7" - integrity sha512-e83H4MzamzNzxZdxf104xqzsl1YUCF24i2pw19I/6zPVxpt6a9zn4+7VzSVMclaztxxSTITCLbks7/9dLiNhEw== - dependencies: - "@polkadot/util" "^13.5.6" - tslib "^2.8.1" - -"@polkadot/types@16.4.6": - version "16.4.6" - resolved "https://registry.yarnpkg.com/@polkadot/types/-/types-16.4.6.tgz#9594f6f80e249f270f9092016957860a4554de5e" - integrity sha512-vfZSOxs64oy1XOcMY3fAbSCBwqLeWvsUYSOhDkZaaC5zIbKdtimPQgbV1QA2fMli568rehmmpLXpZZtj2CNnmA== - dependencies: - "@polkadot/keyring" "^13.5.6" - "@polkadot/types-augment" "16.4.6" - "@polkadot/types-codec" "16.4.6" - "@polkadot/types-create" "16.4.6" - "@polkadot/util" "^13.5.6" - "@polkadot/util-crypto" "^13.5.6" - rxjs "^7.8.1" - tslib "^2.8.1" - -"@polkadot/util-crypto@13.5.6", "@polkadot/util-crypto@^13.5.6": - version "13.5.6" - resolved "https://registry.yarnpkg.com/@polkadot/util-crypto/-/util-crypto-13.5.6.tgz#aef44d6c201d7c47897288aa268532f396e4cd5f" - integrity sha512-1l+t5lVc9UWxvbJe7/3V+QK8CwrDPuQjDK6FKtDZgZCU0JRrjySOxV0J4PeDIv8TgXZtbIcQFVUhIsJTyKZZJQ== - dependencies: - "@noble/curves" "^1.3.0" - "@noble/hashes" "^1.3.3" - "@polkadot/networks" "13.5.6" - "@polkadot/util" "13.5.6" - "@polkadot/wasm-crypto" "^7.5.1" - "@polkadot/wasm-util" "^7.5.1" - "@polkadot/x-bigint" "13.5.6" - "@polkadot/x-randomvalues" "13.5.6" - "@scure/base" "^1.1.7" - tslib "^2.8.0" - -"@polkadot/util@13.5.6", "@polkadot/util@^13.5.6": - version "13.5.6" - resolved "https://registry.yarnpkg.com/@polkadot/util/-/util-13.5.6.tgz#fceb7fe823724535516b304a5675566974cb60e6" - integrity sha512-V+CkW2VdhcMWvl7eXdmlCLGqLxrKvXZtXE76KBbPP5n0Z+8DqQ58IHNOE9xe2LOgqDwIzdLlOUwkyF9Zj19y+Q== - dependencies: - "@polkadot/x-bigint" "13.5.6" - "@polkadot/x-global" "13.5.6" - "@polkadot/x-textdecoder" "13.5.6" - "@polkadot/x-textencoder" "13.5.6" - "@types/bn.js" "^5.1.6" - bn.js "^5.2.1" - tslib "^2.8.0" - -"@polkadot/wasm-bridge@7.5.1": - version "7.5.1" - resolved "https://registry.yarnpkg.com/@polkadot/wasm-bridge/-/wasm-bridge-7.5.1.tgz#f738858213a8a599ae8bf6a6c179b325dcf091f4" - integrity sha512-E+N3CSnX3YaXpAmfIQ+4bTyiAqJQKvVcMaXjkuL8Tp2zYffClWLG5e+RY15Uh+EWfUl9If4y6cLZi3D5NcpAGQ== - dependencies: - "@polkadot/wasm-util" "7.5.1" - tslib "^2.7.0" - -"@polkadot/wasm-crypto-asmjs@7.5.1": - version "7.5.1" - resolved "https://registry.yarnpkg.com/@polkadot/wasm-crypto-asmjs/-/wasm-crypto-asmjs-7.5.1.tgz#87e07aa340249d5c978cd03eb58b395563066a4c" - integrity sha512-jAg7Uusk+xeHQ+QHEH4c/N3b1kEGBqZb51cWe+yM61kKpQwVGZhNdlWetW6U23t/BMyZArIWMsZqmK/Ij0PHog== - dependencies: - tslib "^2.7.0" - -"@polkadot/wasm-crypto-init@7.5.1": - version "7.5.1" - resolved "https://registry.yarnpkg.com/@polkadot/wasm-crypto-init/-/wasm-crypto-init-7.5.1.tgz#0434850b7f05619ff312d5cbfd33629a54f9b31a" - integrity sha512-Obu4ZEo5jYO6sN31eqCNOXo88rPVkP9TrUOyynuFCnXnXr8V/HlmY/YkAd9F87chZnkTJRlzak17kIWr+i7w3A== - dependencies: - "@polkadot/wasm-bridge" "7.5.1" - "@polkadot/wasm-crypto-asmjs" "7.5.1" - "@polkadot/wasm-crypto-wasm" "7.5.1" - "@polkadot/wasm-util" "7.5.1" - tslib "^2.7.0" - -"@polkadot/wasm-crypto-wasm@7.5.1": - version "7.5.1" - resolved "https://registry.yarnpkg.com/@polkadot/wasm-crypto-wasm/-/wasm-crypto-wasm-7.5.1.tgz#b3996007875db6945d29f94f4d4719fce2b3bb8f" - integrity sha512-S2yQSGbOGTcaV6UdipFVyEGanJvG6uD6Tg7XubxpiGbNAblsyYKeFcxyH1qCosk/4qf+GIUwlOL4ydhosZflqg== - dependencies: - "@polkadot/wasm-util" "7.5.1" - tslib "^2.7.0" - -"@polkadot/wasm-crypto@^7.5.1": - version "7.5.1" - resolved "https://registry.yarnpkg.com/@polkadot/wasm-crypto/-/wasm-crypto-7.5.1.tgz#324ebf9a86a30fd19bf4b02a6582367bdddb62c9" - integrity sha512-acjt4VJ3w19v7b/SIPsV/5k9s6JsragHKPnwoZ0KTfBvAFXwzz80jUzVGxA06SKHacfCUe7vBRlz7M5oRby1Pw== - dependencies: - "@polkadot/wasm-bridge" "7.5.1" - "@polkadot/wasm-crypto-asmjs" "7.5.1" - "@polkadot/wasm-crypto-init" "7.5.1" - "@polkadot/wasm-crypto-wasm" "7.5.1" - "@polkadot/wasm-util" "7.5.1" - tslib "^2.7.0" - -"@polkadot/wasm-util@7.5.1", "@polkadot/wasm-util@^7.5.1": - version "7.5.1" - resolved "https://registry.yarnpkg.com/@polkadot/wasm-util/-/wasm-util-7.5.1.tgz#4568a9bf8d02d2d68fc139f331719865300e5233" - integrity sha512-sbvu71isFhPXpvMVX+EkRnUg/+54Tx7Sf9BEMqxxoPj7cG1I/MKeDEwbQz6MaU4gm7xJqvEWCAemLFcXfHQ/2A== - dependencies: - tslib "^2.7.0" - -"@polkadot/x-bigint@13.5.6", "@polkadot/x-bigint@^13.5.6": - version "13.5.6" - resolved "https://registry.yarnpkg.com/@polkadot/x-bigint/-/x-bigint-13.5.6.tgz#1468aab88e9bc41ea7ca118ab72d111681d7a4be" - integrity sha512-HpqZJ9ud94iK/+0Ofacw7QdtvzFp6SucBBml4XwWZTWoLaLOGDsO7FoWE7yCuwPbX8nLgIM6YmQBeUoZmBtVqQ== - dependencies: - "@polkadot/x-global" "13.5.6" - tslib "^2.8.0" - -"@polkadot/x-fetch@^13.5.6": - version "13.5.6" - resolved "https://registry.yarnpkg.com/@polkadot/x-fetch/-/x-fetch-13.5.6.tgz#39393a4873199320c2474d48af883be853c6deca" - integrity sha512-gqx8c6lhnD7Qht+56J+4oeTA8YZ9bAPqzOt2cRJf9MTplMy44W6671T2p6hA3QMvzy4aBTxMie3uKc4tGpLu4A== - dependencies: - "@polkadot/x-global" "13.5.6" - node-fetch "^3.3.2" - tslib "^2.8.0" - -"@polkadot/x-global@13.5.6", "@polkadot/x-global@^13.5.6": - version "13.5.6" - resolved "https://registry.yarnpkg.com/@polkadot/x-global/-/x-global-13.5.6.tgz#37a52d1cd32fde6d385cb745c0cec534753be1e5" - integrity sha512-iw97n0Bnl2284WgAK732LYR4DW6w5+COfBfHzkhiHqs5xwPEwWMgWGrf2hM8WAQqNIz6Ni8w/jagucPyQBur3Q== - dependencies: - tslib "^2.8.0" - -"@polkadot/x-randomvalues@13.5.6": - version "13.5.6" - resolved "https://registry.yarnpkg.com/@polkadot/x-randomvalues/-/x-randomvalues-13.5.6.tgz#a05e0e4fb188c99c5a84043668a27ae6f05259bc" - integrity sha512-w1F9G7FxrJ7+hGC8bh9/VpPH4KN8xmyzgiQdR7+rVB2V8KsKQBQidG69pj5Kwsh3oODOz0yQYsTG6Rm6TAJbGA== - dependencies: - "@polkadot/x-global" "13.5.6" - tslib "^2.8.0" - -"@polkadot/x-textdecoder@13.5.6": - version "13.5.6" - resolved "https://registry.yarnpkg.com/@polkadot/x-textdecoder/-/x-textdecoder-13.5.6.tgz#a9c37f1033e41747856674d47ce149f71a0cbb1b" - integrity sha512-jTGeYCxFh89KRrP7bNj1CPqKO36Onsi0iA6A+5YtRS5wjdQU+/OFM/EHLTP2nvkvZo/tOkOewMR9sausisUvVQ== - dependencies: - "@polkadot/x-global" "13.5.6" - tslib "^2.8.0" - -"@polkadot/x-textencoder@13.5.6": - version "13.5.6" - resolved "https://registry.yarnpkg.com/@polkadot/x-textencoder/-/x-textencoder-13.5.6.tgz#e6468a0a97a0cb9e64363aae35e932baad1abe37" - integrity sha512-iVwz9+OrYCEF9QbNfr9M206mmWvY/AhDmGPfAIeTR4fRgKGVYqcP8RIF8iu/x0MVQWqiVO3vlhlUk7MfrmAnoQ== - dependencies: - "@polkadot/x-global" "13.5.6" - tslib "^2.8.0" - -"@polkadot/x-ws@^13.5.6": - version "13.5.6" - resolved "https://registry.yarnpkg.com/@polkadot/x-ws/-/x-ws-13.5.6.tgz#394bc6c5408e2cecbd8742c883c1b73ce1b23258" - integrity sha512-247ktVp/iE57NTXjFpHaoPoDcvoEPb8+16r2Eq0IBQ2umOV7P6KmxvdNx5eFUvRsgXvBpNwUXE1WVnXjK/eDtA== - dependencies: - "@polkadot/x-global" "13.5.6" - tslib "^2.8.0" - ws "^8.18.0" - -"@rollup/rollup-android-arm-eabi@4.34.8": - version "4.34.8" - resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.34.8.tgz#731df27dfdb77189547bcef96ada7bf166bbb2fb" - integrity sha512-q217OSE8DTp8AFHuNHXo0Y86e1wtlfVrXiAlwkIvGRQv9zbc6mE3sjIVfwI8sYUyNxwOg0j/Vm1RKM04JcWLJw== - -"@rollup/rollup-android-arm-eabi@4.50.0": - version "4.50.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.50.0.tgz#939c1be9625d428d8513e4ab60d406fe8db23718" - integrity sha512-lVgpeQyy4fWN5QYebtW4buT/4kn4p4IJ+kDNB4uYNT5b8c8DLJDg6titg20NIg7E8RWwdWZORW6vUFfrLyG3KQ== - -"@rollup/rollup-android-arm64@4.34.8": - version "4.34.8" - resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.34.8.tgz#4bea6db78e1f6927405df7fe0faf2f5095e01343" - integrity sha512-Gigjz7mNWaOL9wCggvoK3jEIUUbGul656opstjaUSGC3eT0BM7PofdAJaBfPFWWkXNVAXbaQtC99OCg4sJv70Q== - -"@rollup/rollup-android-arm64@4.50.0": - version "4.50.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.50.0.tgz#b74005775903f7a8f4e363d2840c1dcef3776ff3" - integrity sha512-2O73dR4Dc9bp+wSYhviP6sDziurB5/HCym7xILKifWdE9UsOe2FtNcM+I4xZjKrfLJnq5UR8k9riB87gauiQtw== - -"@rollup/rollup-darwin-arm64@4.34.8": - version "4.34.8" - resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.34.8.tgz#a7aab77d44be3c44a20f946e10160f84e5450e7f" - integrity sha512-02rVdZ5tgdUNRxIUrFdcMBZQoaPMrxtwSb+/hOfBdqkatYHR3lZ2A2EGyHq2sGOd0Owk80oV3snlDASC24He3Q== - -"@rollup/rollup-darwin-arm64@4.50.0": - version "4.50.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.50.0.tgz#8c04603cdcf1ec0cd6b27152b3827e49295f2962" - integrity sha512-vwSXQN8T4sKf1RHr1F0s98Pf8UPz7pS6P3LG9NSmuw0TVh7EmaE+5Ny7hJOZ0M2yuTctEsHHRTMi2wuHkdS6Hg== - -"@rollup/rollup-darwin-x64@4.34.8": - version "4.34.8" - resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.34.8.tgz#c572c024b57ee8ddd1b0851703ace9eb6cc0dd82" - integrity sha512-qIP/elwR/tq/dYRx3lgwK31jkZvMiD6qUtOycLhTzCvrjbZ3LjQnEM9rNhSGpbLXVJYQ3rq39A6Re0h9tU2ynw== - -"@rollup/rollup-darwin-x64@4.50.0": - version "4.50.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.50.0.tgz#19ec976f1cc663def2692cd7ffb32981f2b0b733" - integrity sha512-cQp/WG8HE7BCGyFVuzUg0FNmupxC+EPZEwWu2FCGGw5WDT1o2/YlENbm5e9SMvfDFR6FRhVCBePLqj0o8MN7Vw== - -"@rollup/rollup-freebsd-arm64@4.34.8": - version "4.34.8" - resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.34.8.tgz#cf74f8113b5a83098a5c026c165742277cbfb88b" - integrity sha512-IQNVXL9iY6NniYbTaOKdrlVP3XIqazBgJOVkddzJlqnCpRi/yAeSOa8PLcECFSQochzqApIOE1GHNu3pCz+BDA== - -"@rollup/rollup-freebsd-arm64@4.50.0": - version "4.50.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.50.0.tgz#a96b4ad8346229f6fcbd9d57f1c53040b037c2da" - integrity sha512-UR1uTJFU/p801DvvBbtDD7z9mQL8J80xB0bR7DqW7UGQHRm/OaKzp4is7sQSdbt2pjjSS72eAtRh43hNduTnnQ== - -"@rollup/rollup-freebsd-x64@4.34.8": - version "4.34.8" - resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.34.8.tgz#39561f3a2f201a4ad6a01425b1ff5928154ecd7c" - integrity sha512-TYXcHghgnCqYFiE3FT5QwXtOZqDj5GmaFNTNt3jNC+vh22dc/ukG2cG+pi75QO4kACohZzidsq7yKTKwq/Jq7Q== - -"@rollup/rollup-freebsd-x64@4.50.0": - version "4.50.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.50.0.tgz#fa565a282bc57967ee6668607b181678bdd74e4a" - integrity sha512-G/DKyS6PK0dD0+VEzH/6n/hWDNPDZSMBmqsElWnCRGrYOb2jC0VSupp7UAHHQ4+QILwkxSMaYIbQ72dktp8pKA== - -"@rollup/rollup-linux-arm-gnueabihf@4.34.8": - version "4.34.8" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.34.8.tgz#980d6061e373bfdaeb67925c46d2f8f9b3de537f" - integrity sha512-A4iphFGNkWRd+5m3VIGuqHnG3MVnqKe7Al57u9mwgbyZ2/xF9Jio72MaY7xxh+Y87VAHmGQr73qoKL9HPbXj1g== - -"@rollup/rollup-linux-arm-gnueabihf@4.50.0": - version "4.50.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.50.0.tgz#dfc88f7295e1f98d77f25296be787e8a5d6ced75" - integrity sha512-u72Mzc6jyJwKjJbZZcIYmd9bumJu7KNmHYdue43vT1rXPm2rITwmPWF0mmPzLm9/vJWxIRbao/jrQmxTO0Sm9w== - -"@rollup/rollup-linux-arm-musleabihf@4.34.8": - version "4.34.8" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.34.8.tgz#f91a90f30dc00d5a64ac2d9bbedc829cd3cfaa78" - integrity sha512-S0lqKLfTm5u+QTxlFiAnb2J/2dgQqRy/XvziPtDd1rKZFXHTyYLoVL58M/XFwDI01AQCDIevGLbQrMAtdyanpA== - -"@rollup/rollup-linux-arm-musleabihf@4.50.0": - version "4.50.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.50.0.tgz#32cd70c87455ca031f0361090cf17da5a2ef66d5" - integrity sha512-S4UefYdV0tnynDJV1mdkNawp0E5Qm2MtSs330IyHgaccOFrwqsvgigUD29uT+B/70PDY1eQ3t40+xf6wIvXJyg== - -"@rollup/rollup-linux-arm64-gnu@4.34.8": - version "4.34.8" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.34.8.tgz#fac700fa5c38bc13a0d5d34463133093da4c92a0" - integrity sha512-jpz9YOuPiSkL4G4pqKrus0pn9aYwpImGkosRKwNi+sJSkz+WU3anZe6hi73StLOQdfXYXC7hUfsQlTnjMd3s1A== - -"@rollup/rollup-linux-arm64-gnu@4.50.0": - version "4.50.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.50.0.tgz#0e7e1fe7241e3384f6c6b4ccdbcfa8ad8c78b869" - integrity sha512-1EhkSvUQXJsIhk4msxP5nNAUWoB4MFDHhtc4gAYvnqoHlaL9V3F37pNHabndawsfy/Tp7BPiy/aSa6XBYbaD1g== - -"@rollup/rollup-linux-arm64-musl@4.34.8": - version "4.34.8" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.34.8.tgz#f50ecccf8c78841ff6df1706bc4782d7f62bf9c3" - integrity sha512-KdSfaROOUJXgTVxJNAZ3KwkRc5nggDk+06P6lgi1HLv1hskgvxHUKZ4xtwHkVYJ1Rep4GNo+uEfycCRRxht7+Q== - -"@rollup/rollup-linux-arm64-musl@4.50.0": - version "4.50.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.50.0.tgz#5d421f2f3e4a84786c4dfd9ce97e595c9b59e7f4" - integrity sha512-EtBDIZuDtVg75xIPIK1l5vCXNNCIRM0OBPUG+tbApDuJAy9mKago6QxX+tfMzbCI6tXEhMuZuN1+CU8iDW+0UQ== - -"@rollup/rollup-linux-loongarch64-gnu@4.34.8": - version "4.34.8" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.34.8.tgz#5869dc0b28242da6553e2b52af41374f4038cd6e" - integrity sha512-NyF4gcxwkMFRjgXBM6g2lkT58OWztZvw5KkV2K0qqSnUEqCVcqdh2jN4gQrTn/YUpAcNKyFHfoOZEer9nwo6uQ== - -"@rollup/rollup-linux-loongarch64-gnu@4.50.0": - version "4.50.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.50.0.tgz#a0fb5c7d0e88319e18acfd9436f19ee39354b027" - integrity sha512-BGYSwJdMP0hT5CCmljuSNx7+k+0upweM2M4YGfFBjnFSZMHOLYR0gEEj/dxyYJ6Zc6AiSeaBY8dWOa11GF/ppQ== - -"@rollup/rollup-linux-powerpc64le-gnu@4.34.8": - version "4.34.8" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.34.8.tgz#5cdd9f851ce1bea33d6844a69f9574de335f20b1" - integrity sha512-LMJc999GkhGvktHU85zNTDImZVUCJ1z/MbAJTnviiWmmjyckP5aQsHtcujMjpNdMZPT2rQEDBlJfubhs3jsMfw== - -"@rollup/rollup-linux-ppc64-gnu@4.50.0": - version "4.50.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.50.0.tgz#a65b598af12f25210c3295da551a6e3616ea488d" - integrity sha512-I1gSMzkVe1KzAxKAroCJL30hA4DqSi+wGc5gviD0y3IL/VkvcnAqwBf4RHXHyvH66YVHxpKO8ojrgc4SrWAnLg== - -"@rollup/rollup-linux-riscv64-gnu@4.34.8": - version "4.34.8" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.34.8.tgz#ef5dc37f4388f5253f0def43e1440ec012af204d" - integrity sha512-xAQCAHPj8nJq1PI3z8CIZzXuXCstquz7cIOL73HHdXiRcKk8Ywwqtx2wrIy23EcTn4aZ2fLJNBB8d0tQENPCmw== - -"@rollup/rollup-linux-riscv64-gnu@4.50.0": - version "4.50.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.50.0.tgz#10ba776214ae2857c5bf4389690dabb2fbaf7d98" - integrity sha512-bSbWlY3jZo7molh4tc5dKfeSxkqnf48UsLqYbUhnkdnfgZjgufLS/NTA8PcP/dnvct5CCdNkABJ56CbclMRYCA== - -"@rollup/rollup-linux-riscv64-musl@4.50.0": - version "4.50.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.50.0.tgz#c2a46cbaa329d5f21e5808f5a66bb9c78cf68aac" - integrity sha512-LSXSGumSURzEQLT2e4sFqFOv3LWZsEF8FK7AAv9zHZNDdMnUPYH3t8ZlaeYYZyTXnsob3htwTKeWtBIkPV27iQ== - -"@rollup/rollup-linux-s390x-gnu@4.34.8": - version "4.34.8" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.34.8.tgz#7dbc3ccbcbcfb3e65be74538dfb6e8dd16178fde" - integrity sha512-DdePVk1NDEuc3fOe3dPPTb+rjMtuFw89gw6gVWxQFAuEqqSdDKnrwzZHrUYdac7A7dXl9Q2Vflxpme15gUWQFA== - -"@rollup/rollup-linux-s390x-gnu@4.50.0": - version "4.50.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.50.0.tgz#a07447be069d64462e30c66611be20c4513963ed" - integrity sha512-CxRKyakfDrsLXiCyucVfVWVoaPA4oFSpPpDwlMcDFQvrv3XY6KEzMtMZrA+e/goC8xxp2WSOxHQubP8fPmmjOQ== - -"@rollup/rollup-linux-x64-gnu@4.34.8": - version "4.34.8" - resolved "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.34.8.tgz" - integrity sha512-8y7ED8gjxITUltTUEJLQdgpbPh1sUQ0kMTmufRF/Ns5tI9TNMNlhWtmPKKHCU0SilX+3MJkZ0zERYYGIVBYHIA== - -"@rollup/rollup-linux-x64-gnu@4.50.0": - version "4.50.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.50.0.tgz#8887c58bd51242754ae9c56947d6e883332dcc74" - integrity sha512-8PrJJA7/VU8ToHVEPu14FzuSAqVKyo5gg/J8xUerMbyNkWkO9j2ExBho/68RnJsMGNJq4zH114iAttgm7BZVkA== - -"@rollup/rollup-linux-x64-musl@4.34.8": - version "4.34.8" - resolved "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.34.8.tgz" - integrity sha512-SCXcP0ZpGFIe7Ge+McxY5zKxiEI5ra+GT3QRxL0pMMtxPfpyLAKleZODi1zdRHkz5/BhueUrYtYVgubqe9JBNQ== - -"@rollup/rollup-linux-x64-musl@4.50.0": - version "4.50.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.50.0.tgz#6403fda72a2b3b9fbbeeff93d14f1c45ef9775f3" - integrity sha512-SkE6YQp+CzpyOrbw7Oc4MgXFvTw2UIBElvAvLCo230pyxOLmYwRPwZ/L5lBe/VW/qT1ZgND9wJfOsdy0XptRvw== - -"@rollup/rollup-openharmony-arm64@4.50.0": - version "4.50.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.50.0.tgz#52809afccaff47e731b965a0c16e5686be819d5f" - integrity sha512-PZkNLPfvXeIOgJWA804zjSFH7fARBBCpCXxgkGDRjjAhRLOR8o0IGS01ykh5GYfod4c2yiiREuDM8iZ+pVsT+Q== - -"@rollup/rollup-win32-arm64-msvc@4.34.8": - version "4.34.8" - resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.34.8.tgz#cbfee01f1fe73791c35191a05397838520ca3cdd" - integrity sha512-YHYsgzZgFJzTRbth4h7Or0m5O74Yda+hLin0irAIobkLQFRQd1qWmnoVfwmKm9TXIZVAD0nZ+GEb2ICicLyCnQ== - -"@rollup/rollup-win32-arm64-msvc@4.50.0": - version "4.50.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.50.0.tgz#23fe00ddbb40b27a3889bc1e99e6310d97353ad5" - integrity sha512-q7cIIdFvWQoaCbLDUyUc8YfR3Jh2xx3unO8Dn6/TTogKjfwrax9SyfmGGK6cQhKtjePI7jRfd7iRYcxYs93esg== - -"@rollup/rollup-win32-ia32-msvc@4.34.8": - version "4.34.8" - resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.34.8.tgz#95cdbdff48fe6c948abcf6a1d500b2bd5ce33f62" - integrity sha512-r3NRQrXkHr4uWy5TOjTpTYojR9XmF0j/RYgKCef+Ag46FWUTltm5ziticv8LdNsDMehjJ543x/+TJAek/xBA2w== - -"@rollup/rollup-win32-ia32-msvc@4.50.0": - version "4.50.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.50.0.tgz#520b588076b593413d919912d69dfd5728a1f305" - integrity sha512-XzNOVg/YnDOmFdDKcxxK410PrcbcqZkBmz+0FicpW5jtjKQxcW1BZJEQOF0NJa6JO7CZhett8GEtRN/wYLYJuw== - -"@rollup/rollup-win32-x64-msvc@4.34.8": - version "4.34.8" - resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.34.8.tgz#4cdb2cfae69cdb7b1a3cc58778e820408075e928" - integrity sha512-U0FaE5O1BCpZSeE6gBl3c5ObhePQSfk9vDRToMmTkbhCOgW4jqvtS5LGyQ76L1fH8sM0keRp4uDTsbjiUyjk0g== - -"@rollup/rollup-win32-x64-msvc@4.50.0": - version "4.50.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.50.0.tgz#d81efe6a12060c7feddf9805e2a94c3ab0679f48" - integrity sha512-xMmiWRR8sp72Zqwjgtf3QbZfF1wdh8X2ABu3EaozvZcyHJeU0r+XAnXdKgs4cCAp6ORoYoCygipYP1mjmbjrsg== - -"@rx-state/core@^0.1.4": - version "0.1.4" - resolved "https://registry.npmjs.org/@rx-state/core/-/core-0.1.4.tgz" - integrity sha512-Z+3hjU2xh1HisLxt+W5hlYX/eGSDaXXP+ns82gq/PLZpkXLu0uwcNUh9RLY3Clq4zT+hSsA3vcpIGt6+UAb8rQ== - -"@scure/base@^1.1.1", "@scure/base@^1.1.7", "@scure/base@^1.2.6": - version "1.2.6" - resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.2.6.tgz#ca917184b8231394dd8847509c67a0be522e59f6" - integrity sha512-g/nm5FgUa//MCj1gV09zTJTaM6KBAHqLN907YVQqf7zC49+DcO4B1so4ZX07Ef10Twr6nuqYEH9GEggFXA4Fmg== - -"@scure/base@^2.0.0": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@scure/base/-/base-2.0.0.tgz#ba6371fddf92c2727e88ad6ab485db6e624f9a98" - integrity sha512-3E1kpuZginKkek01ovG8krQ0Z44E3DHPjc5S2rjJw9lZn3KSQOs8S7wqikF/AH7iRanHypj85uGyxk0XAyC37w== - -"@scure/base@~1.2.2", "@scure/base@~1.2.4": - version "1.2.5" - resolved "https://registry.npmjs.org/@scure/base/-/base-1.2.5.tgz" - integrity sha512-9rE6EOVeIQzt5TSu4v+K523F8u6DhBsoZWPGKlnCshhlDhy0kJzUX4V+tr2dWmzF1GdekvThABoEQBGBQI7xZw== - -"@scure/bip32@1.6.2", "@scure/bip32@^1.5.0": - version "1.6.2" - resolved "https://registry.npmjs.org/@scure/bip32/-/bip32-1.6.2.tgz" - integrity sha512-t96EPDMbtGgtb7onKKqxRLfE5g05k7uHnHRM2xdE6BP/ZmxaLtPek4J4KfVn/90IQNrU1IOAqMgiDtUdtbe3nw== - dependencies: - "@noble/curves" "~1.8.1" - "@noble/hashes" "~1.7.1" - "@scure/base" "~1.2.2" - -"@scure/bip39@1.5.4", "@scure/bip39@^1.4.0": - version "1.5.4" - resolved "https://registry.npmjs.org/@scure/bip39/-/bip39-1.5.4.tgz" - integrity sha512-TFM4ni0vKvCfBpohoh+/lY05i9gRbSwXWngAsF4CABQxoaOHijxuaZ2R6cStDQ5CHtHO9aGJTr4ksVJASRRyMA== - dependencies: - "@noble/hashes" "~1.7.1" - "@scure/base" "~1.2.4" - -"@scure/sr25519@^0.3.0": - version "0.3.0" - resolved "https://registry.yarnpkg.com/@scure/sr25519/-/sr25519-0.3.0.tgz#1fb075ef05086c1dc59f16bdda1327627a552352" - integrity sha512-SKsinX2sImunfcsH3seGrwH/OayBwwaJqVN8J1cJBNRCfbBq5q0jyTKGa9PcW1HWv9vXT6Yuq41JsxFLvF59ew== - dependencies: - "@noble/curves" "~2.0.0" - "@noble/hashes" "~2.0.0" - -"@sec-ant/readable-stream@^0.4.1": - version "0.4.1" - resolved "https://registry.npmjs.org/@sec-ant/readable-stream/-/readable-stream-0.4.1.tgz" - integrity sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg== - -"@sindresorhus/merge-streams@^4.0.0": - version "4.0.0" - resolved "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-4.0.0.tgz" - integrity sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ== - -"@substrate/connect-extension-protocol@^2.0.0": - version "2.2.2" - resolved "https://registry.yarnpkg.com/@substrate/connect-extension-protocol/-/connect-extension-protocol-2.2.2.tgz#2cf8f2eaf1879308d307a1a08df83cd5db918fe0" - integrity sha512-t66jwrXA0s5Goq82ZtjagLNd7DPGCNjHeehRlE/gcJmJ+G56C0W+2plqOMRicJ8XGR1/YFnUSEqUFiSNbjGrAA== - -"@substrate/connect-known-chains@^1.1.5": - version "1.10.3" - resolved "https://registry.yarnpkg.com/@substrate/connect-known-chains/-/connect-known-chains-1.10.3.tgz#71a89864f13626c412fa0a9d0ffc4f6ca39fdcec" - integrity sha512-OJEZO1Pagtb6bNE3wCikc2wrmvEU5x7GxFFLqqbz1AJYYxSlrPCGu4N2og5YTExo4IcloNMQYFRkBGue0BKZ4w== - -"@substrate/connect@0.8.11": - version "0.8.11" - resolved "https://registry.yarnpkg.com/@substrate/connect/-/connect-0.8.11.tgz#983ec69a05231636e217b573b8130a6b942af69f" - integrity sha512-ofLs1PAO9AtDdPbdyTYj217Pe+lBfTLltdHDs3ds8no0BseoLeAGxpz1mHfi7zB4IxI3YyAiLjH6U8cw4pj4Nw== - dependencies: - "@substrate/connect-extension-protocol" "^2.0.0" - "@substrate/connect-known-chains" "^1.1.5" - "@substrate/light-client-extension-helpers" "^1.0.0" - smoldot "2.0.26" - -"@substrate/light-client-extension-helpers@^1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@substrate/light-client-extension-helpers/-/light-client-extension-helpers-1.0.0.tgz#7b60368c57e06e5cf798c6557422d12e6d81f1ff" - integrity sha512-TdKlni1mBBZptOaeVrKnusMg/UBpWUORNDv5fdCaJklP4RJiFOzBCrzC+CyVI5kQzsXBisZ+2pXm+rIjS38kHg== - dependencies: - "@polkadot-api/json-rpc-provider" "^0.0.1" - "@polkadot-api/json-rpc-provider-proxy" "^0.1.0" - "@polkadot-api/observable-client" "^0.3.0" - "@polkadot-api/substrate-client" "^0.1.2" - "@substrate/connect-extension-protocol" "^2.0.0" - "@substrate/connect-known-chains" "^1.1.5" - rxjs "^7.8.1" - -"@substrate/ss58-registry@^1.51.0": - version "1.51.0" - resolved "https://registry.yarnpkg.com/@substrate/ss58-registry/-/ss58-registry-1.51.0.tgz#39e0341eb4069c2d3e684b93f0d8cb0bec572383" - integrity sha512-TWDurLiPxndFgKjVavCniytBIw+t4ViOi7TYp9h/D0NMmkEc9klFTo+827eyEJ0lELpqO207Ey7uGxUa+BS1jQ== - -"@tsconfig/node10@^1.0.7": - version "1.0.11" - resolved "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz" - integrity sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw== - -"@tsconfig/node12@^1.0.7": - version "1.0.11" - resolved "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz" - integrity sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag== - -"@tsconfig/node14@^1.0.0": - version "1.0.3" - resolved "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz" - integrity sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow== - -"@tsconfig/node16@^1.0.2": - version "1.0.4" - resolved "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz" - integrity sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA== - -"@types/bn.js@^5.1.6": - version "5.2.0" - resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-5.2.0.tgz#4349b9710e98f9ab3cdc50f1c5e4dcbd8ef29c80" - integrity sha512-DLbJ1BPqxvQhIGbeu8VbUC1DiAiahHtAYvA0ZEAa4P31F7IaArc8z3C3BRQdWX4mtLQuABG4yzp76ZrS02Ui1Q== - dependencies: - "@types/node" "*" - -"@types/bun@^1.1.13": - version "1.2.3" - resolved "https://registry.npmjs.org/@types/bun/-/bun-1.2.3.tgz" - integrity sha512-054h79ipETRfjtsCW9qJK8Ipof67Pw9bodFWmkfkaUaRiIQ1dIV2VTlheshlBx3mpKr0KeK8VqnMMCtgN9rQtw== - dependencies: - bun-types "1.2.3" - -"@types/chai@^5.0.1": - version "5.0.1" - resolved "https://registry.npmjs.org/@types/chai/-/chai-5.0.1.tgz" - integrity sha512-5T8ajsg3M/FOncpLYW7sdOcD6yf4+722sze/tc4KQV0P8Z2rAr3SAuHCIkYmYpt8VbcQlnz8SxlOlPQYefe4cA== - dependencies: - "@types/deep-eql" "*" - -"@types/deep-eql@*": - version "4.0.2" - resolved "https://registry.npmjs.org/@types/deep-eql/-/deep-eql-4.0.2.tgz" - integrity sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw== - -"@types/estree@1.0.6": - version "1.0.6" - resolved "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz" - integrity sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw== - -"@types/estree@1.0.8": - version "1.0.8" - resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.8.tgz#958b91c991b1867ced318bedea0e215ee050726e" - integrity sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w== - -"@types/mocha@^10.0.10": - version "10.0.10" - resolved "https://registry.npmjs.org/@types/mocha/-/mocha-10.0.10.tgz" - integrity sha512-xPyYSz1cMPnJQhl0CLMH68j3gprKZaTjG3s5Vi+fDgx+uhG9NOXwbVt52eFS8ECyXhyKcjDLCBEqBExKuiZb7Q== - -"@types/node@*": - version "22.15.21" - resolved "https://registry.npmjs.org/@types/node/-/node-22.15.21.tgz" - integrity sha512-EV/37Td6c+MgKAbkcLG6vqZ2zEYHD7bvSrzqqs2RIhbA6w3x+Dqz8MZM3sP6kGTeLrdoOgKZe+Xja7tUB2DNkQ== - dependencies: - undici-types "~6.21.0" - -"@types/node@22.7.5": - version "22.7.5" - resolved "https://registry.npmjs.org/@types/node/-/node-22.7.5.tgz" - integrity sha512-jML7s2NAzMWc//QSJ1a3prpk78cOPchGvXJsC3C6R6PSMoooztvRVQEz89gmBTBY1SPMaqo5teB4uNHPdetShQ== - dependencies: - undici-types "~6.19.2" - -"@types/node@^22.15.30": - version "22.17.0" - resolved "https://registry.yarnpkg.com/@types/node/-/node-22.17.0.tgz#e8c9090e957bd4d9860efb323eb92d297347eac7" - integrity sha512-bbAKTCqX5aNVryi7qXVMi+OkB3w/OyblodicMbvE38blyAz7GxXf6XYhklokijuPwwVg9sDLKRxt0ZHXQwZVfQ== - dependencies: - undici-types "~6.21.0" - -"@types/node@^22.18.0": - version "22.18.0" - resolved "https://registry.yarnpkg.com/@types/node/-/node-22.18.0.tgz#9e4709be4f104e3568f7dd1c71e2949bf147a47b" - integrity sha512-m5ObIqwsUp6BZzyiy4RdZpzWGub9bqLJMvZDD0QMXhxjqMHMENlj+SqF5QxoUwaQNFe+8kz8XM8ZQhqkQPTgMQ== - dependencies: - undici-types "~6.21.0" - -"@types/node@^24.0.14": - version "24.2.0" - resolved "https://registry.yarnpkg.com/@types/node/-/node-24.2.0.tgz#cde712f88c5190006d6b069232582ecd1f94a760" - integrity sha512-3xyG3pMCq3oYCNg7/ZP+E1ooTaGB4cG8JWRsqqOYQdbWNY4zbaV0Ennrd7stjiJEFZCaybcIgpTjJWHRfBSIDw== - dependencies: - undici-types "~7.10.0" - -"@types/normalize-package-data@^2.4.3": - version "2.4.4" - resolved "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz" - integrity sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA== - -"@types/ws@~8.5.10": - version "8.5.14" - resolved "https://registry.npmjs.org/@types/ws/-/ws-8.5.14.tgz" - integrity sha512-bd/YFLW+URhBzMXurx7lWByOu+xzU9+kb3RboOteXYDfW+tr+JZa99OyNmPINEGB/ahzKrEuc8rcv4gnpJmxTw== - dependencies: - "@types/node" "*" - -abitype@1.0.8, abitype@^1.0.6: - version "1.0.8" - resolved "https://registry.npmjs.org/abitype/-/abitype-1.0.8.tgz" - integrity sha512-ZeiI6h3GnW06uYDLx0etQtX/p8E24UaHHBj57RSjK7YBFe7iuVn07EDpOeP451D06sF27VOz9JJPlIKJmXgkEg== - -acorn-walk@^8.1.1: - version "8.3.4" - resolved "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz" - integrity sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g== - dependencies: - acorn "^8.11.0" - -acorn@^8.11.0, acorn@^8.14.0, acorn@^8.4.1: - version "8.14.0" - resolved "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz" - integrity sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA== - -aes-js@4.0.0-beta.5: - version "4.0.0-beta.5" - resolved "https://registry.npmjs.org/aes-js/-/aes-js-4.0.0-beta.5.tgz" - integrity sha512-G965FqalsNyrPqgEGON7nIx1e/OVENSgiEIzyC63haUMuvNnwIgIjMs52hlTCKhkBny7A2ORNlfY9Zu+jmGk1Q== - -ansi-colors@^4.1.3: - version "4.1.3" - resolved "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz" - integrity sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw== - -ansi-regex@^5.0.1: - version "5.0.1" - resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz" - integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== - -ansi-regex@^6.0.1: - version "6.1.0" - resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz" - integrity sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA== - -ansi-styles@^4.0.0, ansi-styles@^4.1.0: - version "4.3.0" - resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz" - integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== - dependencies: - color-convert "^2.0.1" - -ansi-styles@^6.1.0: - version "6.2.1" - resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz" - integrity sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug== - -any-promise@^1.0.0: - version "1.3.0" - resolved "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz" - integrity sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A== - -anymatch@~3.1.2: - version "3.1.3" - resolved "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz" - integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== - dependencies: - normalize-path "^3.0.0" - picomatch "^2.0.4" - -arg@^4.1.0: - version "4.1.3" - resolved "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz" - integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA== - -argparse@^2.0.1: - version "2.0.1" - resolved "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz" - integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== - -assert@^2.1.0: - version "2.1.0" - resolved "https://registry.npmjs.org/assert/-/assert-2.1.0.tgz" - integrity sha512-eLHpSK/Y4nhMJ07gDaAzoX/XAKS8PSaojml3M0DM4JpV1LAi5JOJ/p6H/XWrl8L+DzVEvVCW1z3vWAaB9oTsQw== - dependencies: - call-bind "^1.0.2" - is-nan "^1.3.2" - object-is "^1.1.5" - object.assign "^4.1.4" - util "^0.12.5" - -available-typed-arrays@^1.0.7: - version "1.0.7" - resolved "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz" - integrity sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ== - dependencies: - possible-typed-array-names "^1.0.0" - -balanced-match@^1.0.0: - version "1.0.2" - resolved "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz" - integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== - -binary-extensions@^2.0.0: - version "2.3.0" - resolved "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz" - integrity sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw== - -bn.js@^5.2.1: - version "5.2.2" - resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.2.tgz#82c09f9ebbb17107cd72cb7fd39bd1f9d0aaa566" - integrity sha512-v2YAxEmKaBLahNwE1mjp4WON6huMNeuDvagFZW+ASCuA/ku0bXR9hSMw0XpiqMoA3+rmnyck/tPRSFQkoC9Cuw== - -brace-expansion@^2.0.1: - version "2.0.1" - resolved "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz" - integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA== - dependencies: - balanced-match "^1.0.0" - -braces@~3.0.2: - version "3.0.3" - resolved "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz" - integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA== - dependencies: - fill-range "^7.1.1" - -browser-stdout@^1.3.1: - version "1.3.1" - resolved "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz" - integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw== - -bun-types@1.2.3: - version "1.2.3" - resolved "https://registry.npmjs.org/bun-types/-/bun-types-1.2.3.tgz" - integrity sha512-P7AeyTseLKAvgaZqQrvp3RqFM3yN9PlcLuSTe7SoJOfZkER73mLdT2vEQi8U64S1YvM/ldcNiQjn0Sn7H9lGgg== - dependencies: - "@types/node" "*" - "@types/ws" "~8.5.10" - -bundle-require@^5.1.0: - version "5.1.0" - resolved "https://registry.npmjs.org/bundle-require/-/bundle-require-5.1.0.tgz" - integrity sha512-3WrrOuZiyaaZPWiEt4G3+IffISVC9HYlWueJEBWED4ZH4aIAC2PnkdnuRrR94M+w6yGWn4AglWtJtBI8YqvgoA== - dependencies: - load-tsconfig "^0.2.3" - -cac@^6.7.14: - version "6.7.14" - resolved "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz" - integrity sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ== - -call-bind-apply-helpers@^1.0.0, call-bind-apply-helpers@^1.0.1, call-bind-apply-helpers@^1.0.2: - version "1.0.2" - resolved "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz" - integrity sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ== - dependencies: - es-errors "^1.3.0" - function-bind "^1.1.2" - -call-bind@^1.0.0, call-bind@^1.0.2, call-bind@^1.0.7, call-bind@^1.0.8: - version "1.0.8" - resolved "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz" - integrity sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww== - dependencies: - call-bind-apply-helpers "^1.0.0" - es-define-property "^1.0.0" - get-intrinsic "^1.2.4" - set-function-length "^1.2.2" - -call-bound@^1.0.2, call-bound@^1.0.3: - version "1.0.3" - resolved "https://registry.npmjs.org/call-bound/-/call-bound-1.0.3.tgz" - integrity sha512-YTd+6wGlNlPxSuri7Y6X8tY2dmm12UMH66RpKMhiX6rsk5wXXnYgbUcOt8kiS31/AjfoTOvCsE+w8nZQLQnzHA== - dependencies: - call-bind-apply-helpers "^1.0.1" - get-intrinsic "^1.2.6" - -camelcase@^6.0.0: - version "6.3.0" - resolved "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz" - integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== - -chai@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/chai/-/chai-6.0.1.tgz#88c2b4682fb56050647e222d2cf9d6772f2607b3" - integrity sha512-/JOoU2//6p5vCXh00FpNgtlw0LjvhGttaWc+y7wpW9yjBm3ys0dI8tSKZxIOgNruz5J0RleccatSIC3uxEZP0g== - -chalk@^4.1.0: - version "4.1.2" - resolved "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz" - integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== - dependencies: - ansi-styles "^4.1.0" - supports-color "^7.1.0" - -chalk@^5.3.0: - version "5.4.1" - resolved "https://registry.npmjs.org/chalk/-/chalk-5.4.1.tgz" - integrity sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w== - -chokidar@^3.5.3: - version "3.6.0" - resolved "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz" - integrity sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw== - dependencies: - anymatch "~3.1.2" - braces "~3.0.2" - glob-parent "~5.1.2" - is-binary-path "~2.1.0" - is-glob "~4.0.1" - normalize-path "~3.0.0" - readdirp "~3.6.0" - optionalDependencies: - fsevents "~2.3.2" - -chokidar@^4.0.3: - version "4.0.3" - resolved "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz" - integrity sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA== - dependencies: - readdirp "^4.0.1" - -cli-cursor@^5.0.0: - version "5.0.0" - resolved "https://registry.npmjs.org/cli-cursor/-/cli-cursor-5.0.0.tgz" - integrity sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw== - dependencies: - restore-cursor "^5.0.0" - -cli-spinners@^2.9.2: - version "2.9.2" - resolved "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz" - integrity sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg== - -cliui@^8.0.1: - version "8.0.1" - resolved "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz" - integrity sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ== - dependencies: - string-width "^4.2.0" - strip-ansi "^6.0.1" - wrap-ansi "^7.0.0" - -color-convert@^2.0.1: - version "2.0.1" - resolved "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz" - integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== - 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== - -commander@^14.0.0: - version "14.0.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-14.0.0.tgz#f244fc74a92343514e56229f16ef5c5e22ced5e9" - integrity sha512-2uM9rYjPvyq39NwLRqaiLtWHyDC1FvryJDa2ATTVims5YAS4PupsEQsDvP14FqhFr0P49CYDugi59xaxJlTXRA== - -commander@^4.0.0: - version "4.1.1" - resolved "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz" - integrity sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA== - -confbox@^0.1.8: - version "0.1.8" - resolved "https://registry.npmjs.org/confbox/-/confbox-0.1.8.tgz" - integrity sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w== - -consola@^3.4.0: - version "3.4.2" - resolved "https://registry.npmjs.org/consola/-/consola-3.4.2.tgz" - integrity sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA== - -create-require@^1.1.0: - version "1.1.1" - resolved "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz" - integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== - -cross-spawn@^7.0.6: - version "7.0.6" - resolved "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz" - integrity sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA== - dependencies: - path-key "^3.1.0" - shebang-command "^2.0.0" - which "^2.0.1" - -data-uri-to-buffer@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz#d8feb2b2881e6a4f58c2e08acfd0e2834e26222e" - integrity sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A== - -debug@^4.1.0: - version "4.4.1" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.1.tgz#e5a8bc6cbc4c6cd3e64308b0693a3d4fa550189b" - integrity sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ== - dependencies: - ms "^2.1.3" - -debug@^4.3.5, debug@^4.4.0: - version "4.4.0" - resolved "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz" - integrity sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA== - dependencies: - ms "^2.1.3" - -decamelize@^4.0.0: - version "4.0.0" - resolved "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz" - integrity sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ== - -deepmerge-ts@^7.1.0: - version "7.1.5" - resolved "https://registry.npmjs.org/deepmerge-ts/-/deepmerge-ts-7.1.5.tgz" - integrity sha512-HOJkrhaYsweh+W+e74Yn7YStZOilkoPb6fycpwNLKzSPtruFs48nYis0zy5yJz1+ktUhHxoRDJ27RQAWLIJVJw== - -define-data-property@^1.0.1, define-data-property@^1.1.4: - version "1.1.4" - resolved "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz" - integrity sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A== - dependencies: - es-define-property "^1.0.0" - es-errors "^1.3.0" - gopd "^1.0.1" - -define-properties@^1.1.3, define-properties@^1.2.1: - version "1.2.1" - resolved "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz" - integrity sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg== - dependencies: - define-data-property "^1.0.1" - has-property-descriptors "^1.0.0" - object-keys "^1.1.1" - -detect-indent@^7.0.1: - version "7.0.1" - resolved "https://registry.npmjs.org/detect-indent/-/detect-indent-7.0.1.tgz" - integrity sha512-Mc7QhQ8s+cLrnUfU/Ji94vG/r8M26m8f++vyres4ZoojaRDpZ1eSIh/EpzLNwlWuvzSZ3UbDFspjFvTDXe6e/g== - -diff@^4.0.1: - version "4.0.2" - resolved "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz" - integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== - -diff@^5.2.0: - version "5.2.0" - resolved "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz" - integrity sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A== - -dotenv@17.2.1: - version "17.2.1" - resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-17.2.1.tgz#6f32e10faf014883515538dc922a0fb8765d9b32" - integrity sha512-kQhDYKZecqnM0fCnzI5eIv5L4cAe/iRI+HqMbO/hbRdTAeXDG+M9FjipUxNfbARuEg4iHIbhnhs78BCHNbSxEQ== - -dunder-proto@^1.0.1: - version "1.0.1" - resolved "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz" - integrity sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A== - dependencies: - call-bind-apply-helpers "^1.0.1" - es-errors "^1.3.0" - gopd "^1.2.0" - -eastasianwidth@^0.2.0: - version "0.2.0" - resolved "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz" - integrity sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA== - -emoji-regex@^10.3.0: - version "10.4.0" - resolved "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.4.0.tgz" - integrity sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw== - -emoji-regex@^8.0.0: - version "8.0.0" - resolved "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz" - integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== - -emoji-regex@^9.2.2: - version "9.2.2" - resolved "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz" - integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg== - -es-define-property@^1.0.0, es-define-property@^1.0.1: - version "1.0.1" - resolved "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz" - integrity sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g== - -es-errors@^1.3.0: - version "1.3.0" - resolved "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz" - integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw== - -es-object-atoms@^1.0.0, es-object-atoms@^1.1.1: - version "1.1.1" - resolved "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz" - integrity sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA== - dependencies: - es-errors "^1.3.0" - -esbuild@^0.25.0: - version "0.25.5" - resolved "https://registry.npmjs.org/esbuild/-/esbuild-0.25.5.tgz" - integrity sha512-P8OtKZRv/5J5hhz0cUAdu/cLuPIKXpQl1R9pZtvmHWQvrAUVd0UNIPT4IB4W3rNOqVO0rlqHmCIbSwxh/c9yUQ== - optionalDependencies: - "@esbuild/aix-ppc64" "0.25.5" - "@esbuild/android-arm" "0.25.5" - "@esbuild/android-arm64" "0.25.5" - "@esbuild/android-x64" "0.25.5" - "@esbuild/darwin-arm64" "0.25.5" - "@esbuild/darwin-x64" "0.25.5" - "@esbuild/freebsd-arm64" "0.25.5" - "@esbuild/freebsd-x64" "0.25.5" - "@esbuild/linux-arm" "0.25.5" - "@esbuild/linux-arm64" "0.25.5" - "@esbuild/linux-ia32" "0.25.5" - "@esbuild/linux-loong64" "0.25.5" - "@esbuild/linux-mips64el" "0.25.5" - "@esbuild/linux-ppc64" "0.25.5" - "@esbuild/linux-riscv64" "0.25.5" - "@esbuild/linux-s390x" "0.25.5" - "@esbuild/linux-x64" "0.25.5" - "@esbuild/netbsd-arm64" "0.25.5" - "@esbuild/netbsd-x64" "0.25.5" - "@esbuild/openbsd-arm64" "0.25.5" - "@esbuild/openbsd-x64" "0.25.5" - "@esbuild/sunos-x64" "0.25.5" - "@esbuild/win32-arm64" "0.25.5" - "@esbuild/win32-ia32" "0.25.5" - "@esbuild/win32-x64" "0.25.5" - -escalade@^3.1.1: - version "3.2.0" - resolved "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz" - integrity sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA== - -escape-string-regexp@^4.0.0: - version "4.0.0" - resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz" - integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== - -ethers@^6.13.5: - version "6.13.5" - resolved "https://registry.npmjs.org/ethers/-/ethers-6.13.5.tgz" - integrity sha512-+knKNieu5EKRThQJWwqaJ10a6HE9sSehGeqWN65//wE7j47ZpFhKAnHB/JJFibwwg61I/koxaPsXbXpD/skNOQ== - dependencies: - "@adraffy/ens-normalize" "1.10.1" - "@noble/curves" "1.2.0" - "@noble/hashes" "1.3.2" - "@types/node" "22.7.5" - aes-js "4.0.0-beta.5" - tslib "2.7.0" - ws "8.17.1" - -eventemitter3@5.0.1, eventemitter3@^5.0.1: - version "5.0.1" - resolved "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz" - integrity sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA== - -execa@^9.6.0: - version "9.6.0" - resolved "https://registry.yarnpkg.com/execa/-/execa-9.6.0.tgz#38665530e54e2e018384108322f37f35ae74f3bc" - integrity sha512-jpWzZ1ZhwUmeWRhS7Qv3mhpOhLfwI+uAX4e5fOcXqwMR7EcJ0pj2kV1CVzHVMX/LphnKWD3LObjZCoJ71lKpHw== - dependencies: - "@sindresorhus/merge-streams" "^4.0.0" - cross-spawn "^7.0.6" - figures "^6.1.0" - get-stream "^9.0.0" - human-signals "^8.0.1" - is-plain-obj "^4.1.0" - is-stream "^4.0.1" - npm-run-path "^6.0.0" - pretty-ms "^9.2.0" - signal-exit "^4.1.0" - strip-final-newline "^4.0.0" - yoctocolors "^2.1.1" - -fdir@^6.4.4: - version "6.4.4" - resolved "https://registry.npmjs.org/fdir/-/fdir-6.4.4.tgz" - integrity sha512-1NZP+GK4GfuAv3PqKvxQRDMjdSRZjnkq7KfhlNrCNNlZ0ygQFpebfrnfnq/W7fpUnAv9aGWmY1zKx7FYL3gwhg== - -fdir@^6.5.0: - version "6.5.0" - resolved "https://registry.yarnpkg.com/fdir/-/fdir-6.5.0.tgz#ed2ab967a331ade62f18d077dae192684d50d350" - integrity sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg== - -fetch-blob@^3.1.2, fetch-blob@^3.1.4: - version "3.2.0" - resolved "https://registry.yarnpkg.com/fetch-blob/-/fetch-blob-3.2.0.tgz#f09b8d4bbd45adc6f0c20b7e787e793e309dcce9" - integrity sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ== - dependencies: - node-domexception "^1.0.0" - web-streams-polyfill "^3.0.3" - -figures@^6.1.0: - version "6.1.0" - resolved "https://registry.npmjs.org/figures/-/figures-6.1.0.tgz" - integrity sha512-d+l3qxjSesT4V7v2fh+QnmFnUWv9lSpjarhShNTgBOfA0ttejbQUAlHLitbjkoRiDulW0OPoQPYIGhIC8ohejg== - dependencies: - is-unicode-supported "^2.0.0" - -fill-range@^7.1.1: - version "7.1.1" - resolved "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz" - integrity sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg== - dependencies: - to-regex-range "^5.0.1" - -find-up@^5.0.0: - version "5.0.0" - resolved "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz" - integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== - dependencies: - locate-path "^6.0.0" - path-exists "^4.0.0" - -fix-dts-default-cjs-exports@^1.0.0: - version "1.0.1" - resolved "https://registry.npmjs.org/fix-dts-default-cjs-exports/-/fix-dts-default-cjs-exports-1.0.1.tgz" - integrity sha512-pVIECanWFC61Hzl2+oOCtoJ3F17kglZC/6N94eRWycFgBH35hHx0Li604ZIzhseh97mf2p0cv7vVrOZGoqhlEg== - dependencies: - magic-string "^0.30.17" - mlly "^1.7.4" - rollup "^4.34.8" - -flat@^5.0.2: - version "5.0.2" - resolved "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz" - integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ== - -for-each@^0.3.3: - version "0.3.5" - resolved "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz" - integrity sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg== - dependencies: - is-callable "^1.2.7" - -foreground-child@^3.1.0: - version "3.3.1" - resolved "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz" - integrity sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw== - dependencies: - cross-spawn "^7.0.6" - signal-exit "^4.0.1" - -formdata-polyfill@^4.0.10: - version "4.0.10" - resolved "https://registry.yarnpkg.com/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz#24807c31c9d402e002ab3d8c720144ceb8848423" - integrity sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g== - dependencies: - fetch-blob "^3.1.2" - -fs.promises.exists@^1.1.4: - version "1.1.4" - resolved "https://registry.npmjs.org/fs.promises.exists/-/fs.promises.exists-1.1.4.tgz" - integrity sha512-lJzUGWbZn8vhGWBedA+RYjB/BeJ+3458ljUfmplqhIeb6ewzTFWNPCR1HCiYCkXV9zxcHz9zXkJzMsEgDLzh3Q== - -fsevents@~2.3.2, fsevents@~2.3.3: - 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.2: - version "1.1.2" - resolved "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz" - integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== - -get-caller-file@^2.0.5: - version "2.0.5" - resolved "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz" - integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== - -get-east-asian-width@^1.0.0: - version "1.3.0" - resolved "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.3.0.tgz" - integrity sha512-vpeMIQKxczTD/0s2CdEWHcb0eeJe6TFjxb+J5xgX7hScxqrGuyjmv4c1D4A/gelKfyox0gJJwIHF+fLjeaM8kQ== - -get-intrinsic@^1.2.4, get-intrinsic@^1.2.6: - version "1.3.0" - resolved "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz" - integrity sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ== - dependencies: - call-bind-apply-helpers "^1.0.2" - es-define-property "^1.0.1" - es-errors "^1.3.0" - es-object-atoms "^1.1.1" - function-bind "^1.1.2" - get-proto "^1.0.1" - gopd "^1.2.0" - has-symbols "^1.1.0" - hasown "^2.0.2" - math-intrinsics "^1.1.0" - -get-proto@^1.0.0, get-proto@^1.0.1: - version "1.0.1" - resolved "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz" - integrity sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g== - dependencies: - dunder-proto "^1.0.1" - es-object-atoms "^1.0.0" - -get-stream@^9.0.0: - version "9.0.1" - resolved "https://registry.npmjs.org/get-stream/-/get-stream-9.0.1.tgz" - integrity sha512-kVCxPF3vQM/N0B1PmoqVUqgHP+EeVjmZSQn+1oCRPxd2P21P2F19lIgbR3HBosbB1PUhOAoctJnfEn2GbN2eZA== - dependencies: - "@sec-ant/readable-stream" "^0.4.1" - is-stream "^4.0.1" - -glob-parent@~5.1.2: - version "5.1.2" - resolved "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz" - integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== - dependencies: - is-glob "^4.0.1" - -glob@^10.3.10, glob@^10.4.5: - version "10.4.5" - resolved "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz" - integrity sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg== - dependencies: - foreground-child "^3.1.0" - jackspeak "^3.1.2" - minimatch "^9.0.4" - minipass "^7.1.2" - package-json-from-dist "^1.0.0" - path-scurry "^1.11.1" - -gopd@^1.0.1, gopd@^1.2.0: - version "1.2.0" - resolved "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz" - integrity sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg== - -has-flag@^4.0.0: - version "4.0.0" - resolved "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz" - integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== - -has-property-descriptors@^1.0.0, has-property-descriptors@^1.0.2: - version "1.0.2" - resolved "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz" - integrity sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg== - dependencies: - es-define-property "^1.0.0" - -has-symbols@^1.0.3, has-symbols@^1.1.0: - version "1.1.0" - resolved "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz" - integrity sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ== - -has-tostringtag@^1.0.2: - version "1.0.2" - resolved "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz" - integrity sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw== - dependencies: - has-symbols "^1.0.3" - -hasown@^2.0.2: - version "2.0.2" - resolved "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz" - integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ== - dependencies: - function-bind "^1.1.2" - -he@^1.2.0: - version "1.2.0" - resolved "https://registry.npmjs.org/he/-/he-1.2.0.tgz" - integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== - -hosted-git-info@^7.0.0: - version "7.0.2" - resolved "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-7.0.2.tgz" - integrity sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w== - dependencies: - lru-cache "^10.0.1" - -human-signals@^8.0.1: - version "8.0.1" - resolved "https://registry.npmjs.org/human-signals/-/human-signals-8.0.1.tgz" - integrity sha512-eKCa6bwnJhvxj14kZk5NCPc6Hb6BdsU9DZcOnmQKSnO1VKrfV0zCvtttPZUsBvjmNDn8rpcJfpwSYnHBjc95MQ== - -imurmurhash@^0.1.4: - version "0.1.4" - resolved "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz" - integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA== - -index-to-position@^1.1.0: - version "1.1.0" - resolved "https://registry.npmjs.org/index-to-position/-/index-to-position-1.1.0.tgz" - integrity sha512-XPdx9Dq4t9Qk1mTMbWONJqU7boCoumEH7fRET37HX5+khDUl3J2W6PdALxhILYlIYx2amlwYcRPp28p0tSiojg== - -inherits@^2.0.3: - version "2.0.4" - resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz" - integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== - -is-arguments@^1.0.4: - version "1.2.0" - resolved "https://registry.npmjs.org/is-arguments/-/is-arguments-1.2.0.tgz" - integrity sha512-7bVbi0huj/wrIAOzb8U1aszg9kdi3KN/CyU19CTI7tAoZYEZoL9yCDXpbXN+uPsuWnP02cyug1gleqq+TU+YCA== - dependencies: - call-bound "^1.0.2" - has-tostringtag "^1.0.2" - -is-binary-path@~2.1.0: - version "2.1.0" - resolved "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz" - integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== - dependencies: - binary-extensions "^2.0.0" - -is-callable@^1.2.7: - version "1.2.7" - resolved "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz" - integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA== - -is-extglob@^2.1.1: - version "2.1.1" - resolved "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz" - integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== - -is-fullwidth-code-point@^3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz" - integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== - -is-generator-function@^1.0.7: - version "1.1.0" - resolved "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.0.tgz" - integrity sha512-nPUB5km40q9e8UfN/Zc24eLlzdSf9OfKByBw9CIdw4H1giPMeA0OIJvbchsCu4npfI2QcMVBsGEBHKZ7wLTWmQ== - dependencies: - call-bound "^1.0.3" - get-proto "^1.0.0" - has-tostringtag "^1.0.2" - safe-regex-test "^1.1.0" - -is-glob@^4.0.1, is-glob@~4.0.1: - version "4.0.3" - resolved "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz" - integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== - dependencies: - is-extglob "^2.1.1" - -is-interactive@^2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/is-interactive/-/is-interactive-2.0.0.tgz" - integrity sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ== - -is-nan@^1.3.2: - version "1.3.2" - resolved "https://registry.npmjs.org/is-nan/-/is-nan-1.3.2.tgz" - integrity sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w== - dependencies: - call-bind "^1.0.0" - define-properties "^1.1.3" - -is-number@^7.0.0: - version "7.0.0" - resolved "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz" - integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== - -is-plain-obj@^2.1.0: - version "2.1.0" - resolved "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz" - integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA== - -is-plain-obj@^4.0.0, is-plain-obj@^4.1.0: - version "4.1.0" - resolved "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz" - integrity sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg== - -is-regex@^1.2.1: - version "1.2.1" - resolved "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz" - integrity sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g== - dependencies: - call-bound "^1.0.2" - gopd "^1.2.0" - has-tostringtag "^1.0.2" - hasown "^2.0.2" - -is-stream@^4.0.1: - version "4.0.1" - resolved "https://registry.npmjs.org/is-stream/-/is-stream-4.0.1.tgz" - integrity sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A== - -is-typed-array@^1.1.3: - version "1.1.15" - resolved "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz" - integrity sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ== - dependencies: - which-typed-array "^1.1.16" - -is-unicode-supported@^0.1.0: - version "0.1.0" - resolved "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz" - integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw== - -is-unicode-supported@^1.3.0: - version "1.3.0" - resolved "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-1.3.0.tgz" - integrity sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ== - -is-unicode-supported@^2.0.0: - version "2.1.0" - resolved "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-2.1.0.tgz" - integrity sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ== - -isexe@^2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz" - integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== - -isows@1.0.6: - version "1.0.6" - resolved "https://registry.npmjs.org/isows/-/isows-1.0.6.tgz" - integrity sha512-lPHCayd40oW98/I0uvgaHKWCSvkzY27LjWLbtzOm64yQ+G3Q5npjjbdppU65iZXkK1Zt+kH9pfegli0AYfwYYw== - -jackspeak@^3.1.2: - version "3.4.3" - resolved "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz" - integrity sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw== - dependencies: - "@isaacs/cliui" "^8.0.2" - optionalDependencies: - "@pkgjs/parseargs" "^0.11.0" - -joycon@^3.1.1: - version "3.1.1" - resolved "https://registry.npmjs.org/joycon/-/joycon-3.1.1.tgz" - integrity sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw== - -js-tokens@^4.0.0: - version "4.0.0" - resolved "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz" - integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== - -js-yaml@^4.1.0: - version "4.1.0" - resolved "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz" - integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== - dependencies: - argparse "^2.0.1" - -json-stringify-safe@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" - integrity sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA== - -lilconfig@^3.1.1: - version "3.1.3" - resolved "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz" - integrity sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw== - -lines-and-columns@^1.1.6: - version "1.2.4" - resolved "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz" - integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== - -load-tsconfig@^0.2.3: - version "0.2.5" - resolved "https://registry.npmjs.org/load-tsconfig/-/load-tsconfig-0.2.5.tgz" - integrity sha512-IXO6OCs9yg8tMKzfPZ1YmheJbZCiEsnBdcB03l0OcfK9prKnJb96siuHCr5Fl37/yo9DnKU+TLpxzTUspw9shg== - -locate-path@^6.0.0: - version "6.0.0" - resolved "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz" - integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== - dependencies: - p-locate "^5.0.0" - -lodash.sortby@^4.7.0: - version "4.7.0" - resolved "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz" - integrity sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA== - -log-symbols@^4.1.0: - version "4.1.0" - resolved "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz" - integrity sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg== - dependencies: - chalk "^4.1.0" - is-unicode-supported "^0.1.0" - -log-symbols@^6.0.0: - version "6.0.0" - resolved "https://registry.npmjs.org/log-symbols/-/log-symbols-6.0.0.tgz" - integrity sha512-i24m8rpwhmPIS4zscNzK6MSEhk0DUWa/8iYQWxhffV8jkI4Phvs3F+quL5xvS0gdQR0FyTCMMH33Y78dDTzzIw== - dependencies: - chalk "^5.3.0" - is-unicode-supported "^1.3.0" - -lru-cache@^10.0.1, lru-cache@^10.2.0: - version "10.4.3" - resolved "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz" - integrity sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ== - -magic-string@^0.30.17: - version "0.30.17" - resolved "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz" - integrity sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA== - dependencies: - "@jridgewell/sourcemap-codec" "^1.5.0" - -make-error@^1.1.1: - version "1.3.6" - resolved "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz" - integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== - -math-intrinsics@^1.1.0: - version "1.1.0" - resolved "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz" - integrity sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g== - -mimic-function@^5.0.0: - version "5.0.1" - resolved "https://registry.npmjs.org/mimic-function/-/mimic-function-5.0.1.tgz" - integrity sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA== - -minimatch@^5.1.6: - version "5.1.6" - resolved "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz" - integrity sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g== - dependencies: - brace-expansion "^2.0.1" - -minimatch@^9.0.4: - version "9.0.5" - resolved "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz" - integrity sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow== - dependencies: - brace-expansion "^2.0.1" - -"minipass@^5.0.0 || ^6.0.2 || ^7.0.0", minipass@^7.1.2: - version "7.1.2" - resolved "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz" - integrity sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw== - -mlly@^1.7.4: - version "1.7.4" - resolved "https://registry.npmjs.org/mlly/-/mlly-1.7.4.tgz" - integrity sha512-qmdSIPC4bDJXgZTCR7XosJiNKySV7O215tsPtDN9iEO/7q/76b/ijtgRu/+epFXSJhijtTCCGp3DWS549P3xKw== - dependencies: - acorn "^8.14.0" - pathe "^2.0.1" - pkg-types "^1.3.0" - ufo "^1.5.4" - -mocha@^11.1.0: - version "11.1.0" - resolved "https://registry.npmjs.org/mocha/-/mocha-11.1.0.tgz" - integrity sha512-8uJR5RTC2NgpY3GrYcgpZrsEd9zKbPDpob1RezyR2upGHRQtHWofmzTMzTMSV6dru3tj5Ukt0+Vnq1qhFEEwAg== - dependencies: - ansi-colors "^4.1.3" - browser-stdout "^1.3.1" - chokidar "^3.5.3" - debug "^4.3.5" - diff "^5.2.0" - escape-string-regexp "^4.0.0" - find-up "^5.0.0" - glob "^10.4.5" - he "^1.2.0" - js-yaml "^4.1.0" - log-symbols "^4.1.0" - minimatch "^5.1.6" - ms "^2.1.3" - serialize-javascript "^6.0.2" - strip-json-comments "^3.1.1" - supports-color "^8.1.1" - workerpool "^6.5.1" - yargs "^17.7.2" - yargs-parser "^21.1.1" - yargs-unparser "^2.0.0" - -mock-socket@^9.3.1: - version "9.3.1" - resolved "https://registry.yarnpkg.com/mock-socket/-/mock-socket-9.3.1.tgz#24fb00c2f573c84812aa4a24181bb025de80cc8e" - integrity sha512-qxBgB7Qa2sEQgHFjj0dSigq7fX4k6Saisd5Nelwp2q8mlbAFh5dHV9JTTlF8viYJLSSWgMCZFUom8PJcMNBoJw== - -ms@^2.1.3: - version "2.1.3" - resolved "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz" - integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== - -mz@^2.7.0: - version "2.7.0" - resolved "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz" - integrity sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q== - dependencies: - any-promise "^1.0.0" - object-assign "^4.0.1" - thenify-all "^1.0.0" - -nanoid@^3.3.11: - version "3.3.11" - resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.11.tgz#4f4f112cefbe303202f2199838128936266d185b" - integrity sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w== - -nock@^13.5.5: - version "13.5.6" - resolved "https://registry.yarnpkg.com/nock/-/nock-13.5.6.tgz#5e693ec2300bbf603b61dae6df0225673e6c4997" - integrity sha512-o2zOYiCpzRqSzPj0Zt/dQ/DqZeYoaQ7TUonc/xUPjCGl9WeHpNbxgVvOquXYAaJzI0M9BXV3HTzG0p8IUAbBTQ== - dependencies: - debug "^4.1.0" - json-stringify-safe "^5.0.1" - propagate "^2.0.0" - -node-domexception@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/node-domexception/-/node-domexception-1.0.0.tgz#6888db46a1f71c0b76b3f7555016b63fe64766e5" - integrity sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ== - -node-fetch@^3.3.2: - version "3.3.2" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-3.3.2.tgz#d1e889bacdf733b4ff3b2b243eb7a12866a0b78b" - integrity sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA== - dependencies: - data-uri-to-buffer "^4.0.0" - fetch-blob "^3.1.4" - formdata-polyfill "^4.0.10" - -normalize-package-data@^6.0.0: - version "6.0.2" - resolved "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-6.0.2.tgz" - integrity sha512-V6gygoYb/5EmNI+MEGrWkC+e6+Rr7mTmfHrxDbLzxQogBkgzo76rkok0Am6thgSF7Mv2nLOajAJj5vDJZEFn7g== - dependencies: - hosted-git-info "^7.0.0" - semver "^7.3.5" - validate-npm-package-license "^3.0.4" - -normalize-path@^3.0.0, normalize-path@~3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz" - integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== - -npm-run-path@^6.0.0: - version "6.0.0" - resolved "https://registry.npmjs.org/npm-run-path/-/npm-run-path-6.0.0.tgz" - integrity sha512-9qny7Z9DsQU8Ou39ERsPU4OZQlSTP47ShQzuKZ6PRXpYLtIFgl/DEBYEXKlvcEa+9tHVcK8CF81Y2V72qaZhWA== - dependencies: - path-key "^4.0.0" - unicorn-magic "^0.3.0" - -object-assign@^4.0.1: - version "4.1.1" - resolved "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz" - integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== - -object-is@^1.1.5: - version "1.1.6" - resolved "https://registry.npmjs.org/object-is/-/object-is-1.1.6.tgz" - integrity sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q== - dependencies: - call-bind "^1.0.7" - define-properties "^1.2.1" - -object-keys@^1.1.1: - version "1.1.1" - resolved "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz" - integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== - -object.assign@^4.1.4: - version "4.1.7" - resolved "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz" - integrity sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw== - dependencies: - call-bind "^1.0.8" - call-bound "^1.0.3" - define-properties "^1.2.1" - es-object-atoms "^1.0.0" - has-symbols "^1.1.0" - object-keys "^1.1.1" - -onetime@^7.0.0: - version "7.0.0" - resolved "https://registry.npmjs.org/onetime/-/onetime-7.0.0.tgz" - integrity sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ== - dependencies: - mimic-function "^5.0.0" - -ora@^8.2.0: - version "8.2.0" - resolved "https://registry.npmjs.org/ora/-/ora-8.2.0.tgz" - integrity sha512-weP+BZ8MVNnlCm8c0Qdc1WSWq4Qn7I+9CJGm7Qali6g44e/PUzbjNqJX5NJ9ljlNMosfJvg1fKEGILklK9cwnw== - dependencies: - chalk "^5.3.0" - cli-cursor "^5.0.0" - cli-spinners "^2.9.2" - is-interactive "^2.0.0" - is-unicode-supported "^2.0.0" - log-symbols "^6.0.0" - stdin-discarder "^0.2.2" - string-width "^7.2.0" - strip-ansi "^7.1.0" - -ox@0.6.7: - version "0.6.7" - resolved "https://registry.npmjs.org/ox/-/ox-0.6.7.tgz" - integrity sha512-17Gk/eFsFRAZ80p5eKqv89a57uXjd3NgIf1CaXojATPBuujVc/fQSVhBeAU9JCRB+k7J50WQAyWTxK19T9GgbA== - dependencies: - "@adraffy/ens-normalize" "^1.10.1" - "@noble/curves" "^1.6.0" - "@noble/hashes" "^1.5.0" - "@scure/bip32" "^1.5.0" - "@scure/bip39" "^1.4.0" - abitype "^1.0.6" - eventemitter3 "5.0.1" - -p-limit@^3.0.2: - version "3.1.0" - resolved "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz" - integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== - dependencies: - yocto-queue "^0.1.0" - -p-locate@^5.0.0: - version "5.0.0" - resolved "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz" - integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== - dependencies: - p-limit "^3.0.2" - -package-json-from-dist@^1.0.0: - version "1.0.1" - resolved "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz" - integrity sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw== - -parse-json@^8.0.0: - version "8.3.0" - resolved "https://registry.npmjs.org/parse-json/-/parse-json-8.3.0.tgz" - integrity sha512-ybiGyvspI+fAoRQbIPRddCcSTV9/LsJbf0e/S85VLowVGzRmokfneg2kwVW/KU5rOXrPSbF1qAKPMgNTqqROQQ== - dependencies: - "@babel/code-frame" "^7.26.2" - index-to-position "^1.1.0" - type-fest "^4.39.1" - -parse-ms@^4.0.0: - version "4.0.0" - resolved "https://registry.npmjs.org/parse-ms/-/parse-ms-4.0.0.tgz" - integrity sha512-TXfryirbmq34y8QBwgqCVLi+8oA3oWx2eAnSn62ITyEhEYaWRlVZ2DvMM9eZbMs/RfxPu/PK/aBLyGj4IrqMHw== - -path-exists@^4.0.0: - version "4.0.0" - resolved "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz" - integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== - -path-key@^3.1.0: - version "3.1.1" - resolved "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz" - integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== - -path-key@^4.0.0: - version "4.0.0" - resolved "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz" - integrity sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ== - -path-scurry@^1.11.1: - version "1.11.1" - resolved "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz" - integrity sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA== - dependencies: - lru-cache "^10.2.0" - minipass "^5.0.0 || ^6.0.2 || ^7.0.0" - -pathe@^2.0.1: - version "2.0.3" - resolved "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz" - integrity sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w== - -picocolors@^1.1.1: - version "1.1.1" - resolved "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz" - integrity sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA== - -picomatch@^2.0.4, picomatch@^2.2.1: - version "2.3.1" - resolved "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz" - integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== - -picomatch@^4.0.2: - version "4.0.2" - resolved "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz" - integrity sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg== - -picomatch@^4.0.3: - version "4.0.3" - resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-4.0.3.tgz#796c76136d1eead715db1e7bad785dedd695a042" - integrity sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q== - -pirates@^4.0.1: - version "4.0.7" - resolved "https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz" - integrity sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA== - -pkg-types@^1.3.0: - version "1.3.1" - resolved "https://registry.npmjs.org/pkg-types/-/pkg-types-1.3.1.tgz" - integrity sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ== - dependencies: - confbox "^0.1.8" - mlly "^1.7.4" - pathe "^2.0.1" - -polkadot-api@^1.9.5: - version "1.15.3" - resolved "https://registry.yarnpkg.com/polkadot-api/-/polkadot-api-1.15.3.tgz#c8d02c9d79536669c50d17b2426f9fb905825804" - integrity sha512-ikv7+3SvIXE03NBEi3Otn10c5L80TXimAvRnbZKugO0lilE9+uW1JXkMemaP13qlkoH5jrZbvz6xOEcz0ali9Q== - dependencies: - "@polkadot-api/cli" "0.14.5" - "@polkadot-api/ink-contracts" "0.3.7" - "@polkadot-api/json-rpc-provider" "0.0.4" - "@polkadot-api/known-chains" "0.9.3" - "@polkadot-api/logs-provider" "0.0.6" - "@polkadot-api/metadata-builders" "0.13.1" - "@polkadot-api/metadata-compatibility" "0.3.2" - "@polkadot-api/observable-client" "0.13.4" - "@polkadot-api/pjs-signer" "0.6.11" - "@polkadot-api/polkadot-sdk-compat" "2.3.2" - "@polkadot-api/polkadot-signer" "0.1.6" - "@polkadot-api/signer" "0.2.4" - "@polkadot-api/sm-provider" "0.1.7" - "@polkadot-api/smoldot" "0.3.10" - "@polkadot-api/substrate-bindings" "0.15.1" - "@polkadot-api/substrate-client" "0.4.2" - "@polkadot-api/utils" "0.2.0" - "@polkadot-api/ws-provider" "0.4.1" - "@rx-state/core" "^0.1.4" - -possible-typed-array-names@^1.0.0: - version "1.1.0" - resolved "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz" - integrity sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg== - -postcss-load-config@^6.0.1: - version "6.0.1" - resolved "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-6.0.1.tgz" - integrity sha512-oPtTM4oerL+UXmx+93ytZVN82RrlY/wPUV8IeDxFrzIjXOLF1pN+EmKPLbubvKHT2HC20xXsCAH2Z+CKV6Oz/g== - dependencies: - lilconfig "^3.1.1" - -postcss@^8.5.6: - version "8.5.6" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.5.6.tgz#2825006615a619b4f62a9e7426cc120b349a8f3c" - integrity sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg== - dependencies: - nanoid "^3.3.11" - picocolors "^1.1.1" - source-map-js "^1.2.1" - -prettier@^3.3.3: - version "3.5.2" - resolved "https://registry.npmjs.org/prettier/-/prettier-3.5.2.tgz" - integrity sha512-lc6npv5PH7hVqozBR7lkBNOGXV9vMwROAPlumdBkX0wTbbzPu/U1hk5yL8p2pt4Xoc+2mkT8t/sow2YrV/M5qg== - -pretty-ms@^9.2.0: - version "9.2.0" - resolved "https://registry.npmjs.org/pretty-ms/-/pretty-ms-9.2.0.tgz" - integrity sha512-4yf0QO/sllf/1zbZWYnvWw3NxCQwLXKzIj0G849LSufP15BXKM0rbD2Z3wVnkMfjdn/CB0Dpp444gYAACdsplg== - dependencies: - parse-ms "^4.0.0" - -propagate@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/propagate/-/propagate-2.0.1.tgz#40cdedab18085c792334e64f0ac17256d38f9a45" - integrity sha512-vGrhOavPSTz4QVNuBNdcNXePNdNMaO1xj9yBeH1ScQPjk/rhg9sSlCXPhMkFuaNNW/syTvYqsnbIJxMBfRbbag== - -punycode@^2.1.0: - version "2.3.1" - resolved "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz" - integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg== - -randombytes@^2.1.0: - version "2.1.0" - resolved "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz" - integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== - dependencies: - safe-buffer "^5.1.0" - -read-pkg@^9.0.1: - version "9.0.1" - resolved "https://registry.npmjs.org/read-pkg/-/read-pkg-9.0.1.tgz" - integrity sha512-9viLL4/n1BJUCT1NXVTdS1jtm80yDEgR5T4yCelII49Mbj0v1rZdKqj7zCiYdbB0CuCgdrvHcNogAKTFPBocFA== - dependencies: - "@types/normalize-package-data" "^2.4.3" - normalize-package-data "^6.0.0" - parse-json "^8.0.0" - type-fest "^4.6.0" - unicorn-magic "^0.1.0" - -readdirp@^4.0.1: - version "4.1.2" - resolved "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz" - integrity sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg== - -readdirp@~3.6.0: - version "3.6.0" - resolved "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz" - integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== - dependencies: - picomatch "^2.2.1" - -require-directory@^2.1.1: - version "2.1.1" - resolved "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz" - integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== - -resolve-from@^5.0.0: - version "5.0.0" - resolved "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz" - integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== - -restore-cursor@^5.0.0: - version "5.1.0" - resolved "https://registry.npmjs.org/restore-cursor/-/restore-cursor-5.1.0.tgz" - integrity sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA== - dependencies: - onetime "^7.0.0" - signal-exit "^4.1.0" - -rollup@^4.34.8: - version "4.34.8" - resolved "https://registry.npmjs.org/rollup/-/rollup-4.34.8.tgz" - integrity sha512-489gTVMzAYdiZHFVA/ig/iYFllCcWFHMvUHI1rpFmkoUtRlQxqh6/yiNqnYibjMZ2b/+FUQwldG+aLsEt6bglQ== - dependencies: - "@types/estree" "1.0.6" - optionalDependencies: - "@rollup/rollup-android-arm-eabi" "4.34.8" - "@rollup/rollup-android-arm64" "4.34.8" - "@rollup/rollup-darwin-arm64" "4.34.8" - "@rollup/rollup-darwin-x64" "4.34.8" - "@rollup/rollup-freebsd-arm64" "4.34.8" - "@rollup/rollup-freebsd-x64" "4.34.8" - "@rollup/rollup-linux-arm-gnueabihf" "4.34.8" - "@rollup/rollup-linux-arm-musleabihf" "4.34.8" - "@rollup/rollup-linux-arm64-gnu" "4.34.8" - "@rollup/rollup-linux-arm64-musl" "4.34.8" - "@rollup/rollup-linux-loongarch64-gnu" "4.34.8" - "@rollup/rollup-linux-powerpc64le-gnu" "4.34.8" - "@rollup/rollup-linux-riscv64-gnu" "4.34.8" - "@rollup/rollup-linux-s390x-gnu" "4.34.8" - "@rollup/rollup-linux-x64-gnu" "4.34.8" - "@rollup/rollup-linux-x64-musl" "4.34.8" - "@rollup/rollup-win32-arm64-msvc" "4.34.8" - "@rollup/rollup-win32-ia32-msvc" "4.34.8" - "@rollup/rollup-win32-x64-msvc" "4.34.8" - fsevents "~2.3.2" - -rollup@^4.43.0: - version "4.50.0" - resolved "https://registry.yarnpkg.com/rollup/-/rollup-4.50.0.tgz#6f237f598b7163ede33ce827af8534c929aaa186" - integrity sha512-/Zl4D8zPifNmyGzJS+3kVoyXeDeT/GrsJM94sACNg9RtUE0hrHa1bNPtRSrfHTMH5HjRzce6K7rlTh3Khiw+pw== - dependencies: - "@types/estree" "1.0.8" - optionalDependencies: - "@rollup/rollup-android-arm-eabi" "4.50.0" - "@rollup/rollup-android-arm64" "4.50.0" - "@rollup/rollup-darwin-arm64" "4.50.0" - "@rollup/rollup-darwin-x64" "4.50.0" - "@rollup/rollup-freebsd-arm64" "4.50.0" - "@rollup/rollup-freebsd-x64" "4.50.0" - "@rollup/rollup-linux-arm-gnueabihf" "4.50.0" - "@rollup/rollup-linux-arm-musleabihf" "4.50.0" - "@rollup/rollup-linux-arm64-gnu" "4.50.0" - "@rollup/rollup-linux-arm64-musl" "4.50.0" - "@rollup/rollup-linux-loongarch64-gnu" "4.50.0" - "@rollup/rollup-linux-ppc64-gnu" "4.50.0" - "@rollup/rollup-linux-riscv64-gnu" "4.50.0" - "@rollup/rollup-linux-riscv64-musl" "4.50.0" - "@rollup/rollup-linux-s390x-gnu" "4.50.0" - "@rollup/rollup-linux-x64-gnu" "4.50.0" - "@rollup/rollup-linux-x64-musl" "4.50.0" - "@rollup/rollup-openharmony-arm64" "4.50.0" - "@rollup/rollup-win32-arm64-msvc" "4.50.0" - "@rollup/rollup-win32-ia32-msvc" "4.50.0" - "@rollup/rollup-win32-x64-msvc" "4.50.0" - fsevents "~2.3.2" - -rxjs@^7.8.1, rxjs@^7.8.2: - version "7.8.2" - resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.8.2.tgz#955bc473ed8af11a002a2be52071bf475638607b" - integrity sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA== - dependencies: - tslib "^2.1.0" - -safe-buffer@^5.1.0: - version "5.2.1" - resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz" - integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== - -safe-regex-test@^1.1.0: - version "1.1.0" - resolved "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz" - integrity sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw== - dependencies: - call-bound "^1.0.2" - es-errors "^1.3.0" - is-regex "^1.2.1" - -scale-ts@^1.6.0, scale-ts@^1.6.1: - version "1.6.1" - resolved "https://registry.npmjs.org/scale-ts/-/scale-ts-1.6.1.tgz" - integrity sha512-PBMc2AWc6wSEqJYBDPcyCLUj9/tMKnLX70jLOSndMtcUoLQucP/DM0vnQo1wJAYjTrQiq8iG9rD0q6wFzgjH7g== - -semver@^7.3.5: - version "7.7.2" - resolved "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz" - integrity sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA== - -serialize-javascript@^6.0.2: - version "6.0.2" - resolved "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz" - integrity sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g== - dependencies: - randombytes "^2.1.0" - -set-function-length@^1.2.2: - version "1.2.2" - resolved "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz" - integrity sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg== - dependencies: - define-data-property "^1.1.4" - es-errors "^1.3.0" - function-bind "^1.1.2" - get-intrinsic "^1.2.4" - gopd "^1.0.1" - has-property-descriptors "^1.0.2" - -shebang-command@^2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz" - integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== - dependencies: - shebang-regex "^3.0.0" - -shebang-regex@^3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz" - integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== - -signal-exit@^4.0.1, signal-exit@^4.1.0: - version "4.1.0" - resolved "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz" - integrity sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw== - -smoldot@2.0.26: - version "2.0.26" - resolved "https://registry.yarnpkg.com/smoldot/-/smoldot-2.0.26.tgz#0e64c7fcd26240fbe4c8d6b6e4b9a9aca77e00f6" - integrity sha512-F+qYmH4z2s2FK+CxGj8moYcd1ekSIKH8ywkdqlOz88Dat35iB1DIYL11aILN46YSGMzQW/lbJNS307zBSDN5Ig== - dependencies: - ws "^8.8.1" - -smoldot@2.0.36: - version "2.0.36" - resolved "https://registry.yarnpkg.com/smoldot/-/smoldot-2.0.36.tgz#3d4216b7fe33130fcf276f691d37f7503485ab78" - integrity sha512-0GtHgxOs1VGs+WzpUgTQ52Zg92/q4mnIPEl+smArI4pis6aduQ6ZiXRllbDafsIb18wWYsxaBLNjBkNOB8xBrw== - dependencies: - ws "^8.8.1" - -sort-keys@^5.0.0: - version "5.1.0" - resolved "https://registry.npmjs.org/sort-keys/-/sort-keys-5.1.0.tgz" - integrity sha512-aSbHV0DaBcr7u0PVHXzM6NbZNAtrr9sF6+Qfs9UUVG7Ll3jQ6hHi8F/xqIIcn2rvIVbr0v/2zyjSdwSV47AgLQ== - dependencies: - is-plain-obj "^4.0.0" - -source-map-js@^1.2.1: - version "1.2.1" - resolved "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz" - integrity sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA== - -source-map@0.8.0-beta.0: - version "0.8.0-beta.0" - resolved "https://registry.npmjs.org/source-map/-/source-map-0.8.0-beta.0.tgz" - integrity sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA== - dependencies: - whatwg-url "^7.0.0" - -spdx-correct@^3.0.0: - version "3.2.0" - resolved "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz" - integrity sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA== - dependencies: - spdx-expression-parse "^3.0.0" - spdx-license-ids "^3.0.0" - -spdx-exceptions@^2.1.0: - version "2.5.0" - resolved "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz" - integrity sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w== - -spdx-expression-parse@^3.0.0: - version "3.0.1" - resolved "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz" - integrity sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q== - dependencies: - spdx-exceptions "^2.1.0" - spdx-license-ids "^3.0.0" - -spdx-license-ids@^3.0.0: - version "3.0.21" - resolved "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.21.tgz" - integrity sha512-Bvg/8F5XephndSK3JffaRqdT+gyhfqIPwDHpX80tJrF8QQRYMo8sNMeaZ2Dp5+jhwKnUmIOyFFQfHRkjJm5nXg== - -stdin-discarder@^0.2.2: - version "0.2.2" - resolved "https://registry.npmjs.org/stdin-discarder/-/stdin-discarder-0.2.2.tgz" - integrity sha512-UhDfHmA92YAlNnCfhmq0VeNL5bDbiZGg7sZ2IvPsXubGkiNa9EC+tUTsjBRsYUAz87btI6/1wf4XoVvQ3uRnmQ== - -"string-width-cjs@npm:string-width@^4.2.0": - version "4.2.3" - resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz" - integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== - dependencies: - emoji-regex "^8.0.0" - is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.1" - -string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: - version "4.2.3" - resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz" - integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== - dependencies: - emoji-regex "^8.0.0" - is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.1" - -string-width@^5.0.1, string-width@^5.1.2: - version "5.1.2" - resolved "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz" - integrity sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA== - dependencies: - eastasianwidth "^0.2.0" - emoji-regex "^9.2.2" - strip-ansi "^7.0.1" - -string-width@^7.2.0: - version "7.2.0" - resolved "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz" - integrity sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ== - dependencies: - emoji-regex "^10.3.0" - get-east-asian-width "^1.0.0" - strip-ansi "^7.1.0" - -"strip-ansi-cjs@npm:strip-ansi@^6.0.1": - version "6.0.1" - resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz" - integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== - dependencies: - ansi-regex "^5.0.1" - -strip-ansi@^6.0.0, strip-ansi@^6.0.1: - version "6.0.1" - resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz" - integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== - dependencies: - ansi-regex "^5.0.1" - -strip-ansi@^7.0.1, strip-ansi@^7.1.0: - version "7.1.0" - resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz" - integrity sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ== - dependencies: - ansi-regex "^6.0.1" - -strip-final-newline@^4.0.0: - version "4.0.0" - resolved "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-4.0.0.tgz" - integrity sha512-aulFJcD6YK8V1G7iRB5tigAP4TsHBZZrOV8pjV++zdUwmeV8uzbY7yn6h9MswN62adStNZFuCIx4haBnRuMDaw== - -strip-json-comments@^3.1.1: - version "3.1.1" - resolved "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz" - integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== - -sucrase@^3.35.0: - version "3.35.0" - resolved "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz" - integrity sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA== - dependencies: - "@jridgewell/gen-mapping" "^0.3.2" - commander "^4.0.0" - glob "^10.3.10" - lines-and-columns "^1.1.6" - mz "^2.7.0" - pirates "^4.0.1" - ts-interface-checker "^0.1.9" - -supports-color@^7.1.0: - version "7.2.0" - resolved "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz" - integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== - dependencies: - has-flag "^4.0.0" - -supports-color@^8.1.1: - version "8.1.1" - resolved "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz" - integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== - dependencies: - has-flag "^4.0.0" - -thenify-all@^1.0.0: - version "1.6.0" - resolved "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz" - integrity sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA== - dependencies: - thenify ">= 3.1.0 < 4" - -"thenify@>= 3.1.0 < 4": - version "3.3.1" - resolved "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz" - integrity sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw== - dependencies: - any-promise "^1.0.0" - -tinyexec@^0.3.2: - version "0.3.2" - resolved "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.2.tgz" - integrity sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA== - -tinyglobby@^0.2.11, tinyglobby@^0.2.14: - version "0.2.14" - resolved "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.14.tgz" - integrity sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ== - dependencies: - fdir "^6.4.4" - picomatch "^4.0.2" - -to-regex-range@^5.0.1: - version "5.0.1" - resolved "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz" - integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== - dependencies: - is-number "^7.0.0" - -tr46@^1.0.1: - version "1.0.1" - resolved "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz" - integrity sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA== - dependencies: - punycode "^2.1.0" - -tree-kill@^1.2.2: - version "1.2.2" - resolved "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz" - integrity sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A== - -ts-interface-checker@^0.1.9: - version "0.1.13" - resolved "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz" - integrity sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA== - -ts-node@^10.9.2: - version "10.9.2" - resolved "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz" - integrity sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ== - dependencies: - "@cspotcode/source-map-support" "^0.8.0" - "@tsconfig/node10" "^1.0.7" - "@tsconfig/node12" "^1.0.7" - "@tsconfig/node14" "^1.0.0" - "@tsconfig/node16" "^1.0.2" - acorn "^8.4.1" - acorn-walk "^8.1.1" - arg "^4.1.0" - create-require "^1.1.0" - diff "^4.0.1" - make-error "^1.1.1" - v8-compile-cache-lib "^3.0.1" - yn "3.1.1" - -tsc-prog@^2.3.0: - version "2.3.0" - resolved "https://registry.npmjs.org/tsc-prog/-/tsc-prog-2.3.0.tgz" - integrity sha512-ycET2d75EgcX7y8EmG4KiZkLAwUzbY4xRhA6NU0uVbHkY4ZjrAAuzTMxXI85kOwATqPnBI5C/7y7rlpY0xdqHA== - -tslib@2.7.0: - version "2.7.0" - resolved "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz" - integrity sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA== - -tslib@^2.1.0, tslib@^2.7.0, tslib@^2.8.0, tslib@^2.8.1: - version "2.8.1" - resolved "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz" - integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w== - -tsup@^8.5.0: - version "8.5.0" - resolved "https://registry.yarnpkg.com/tsup/-/tsup-8.5.0.tgz#4b1e25b1a8f4e4f89b764207bf37cfe2d7411d31" - integrity sha512-VmBp77lWNQq6PfuMqCHD3xWl22vEoWsKajkF8t+yMBawlUS8JzEI+vOVMeuNZIuMML8qXRizFKi9oD5glKQVcQ== - dependencies: - bundle-require "^5.1.0" - cac "^6.7.14" - chokidar "^4.0.3" - consola "^3.4.0" - debug "^4.4.0" - esbuild "^0.25.0" - fix-dts-default-cjs-exports "^1.0.0" - joycon "^3.1.1" - picocolors "^1.1.1" - postcss-load-config "^6.0.1" - resolve-from "^5.0.0" - rollup "^4.34.8" - source-map "0.8.0-beta.0" - sucrase "^3.35.0" - tinyexec "^0.3.2" - tinyglobby "^0.2.11" - tree-kill "^1.2.2" - -type-fest@^4.23.0, type-fest@^4.39.1, type-fest@^4.6.0: - version "4.41.0" - resolved "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz" - integrity sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA== - -typescript@^5.7.2, typescript@^5.8.3: - version "5.8.3" - resolved "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz" - integrity sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ== - -ufo@^1.5.4: - version "1.6.1" - resolved "https://registry.npmjs.org/ufo/-/ufo-1.6.1.tgz" - integrity sha512-9a4/uxlTWJ4+a5i0ooc1rU7C7YOw3wT+UGqdeNNHWnOF9qcMBgLRS+4IYUqbczewFx4mLEig6gawh7X6mFlEkA== - -undici-types@~6.19.2: - version "6.19.8" - resolved "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz" - integrity sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw== - -undici-types@~6.21.0: - version "6.21.0" - resolved "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz" - integrity sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ== - -undici-types@~7.10.0: - version "7.10.0" - resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-7.10.0.tgz#4ac2e058ce56b462b056e629cc6a02393d3ff350" - integrity sha512-t5Fy/nfn+14LuOc2KNYg75vZqClpAiqscVvMygNnlsHBFpSXdJaYtXMcdNLpl/Qvc3P2cB3s6lOV51nqsFq4ag== - -unicorn-magic@^0.1.0: - version "0.1.0" - resolved "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.1.0.tgz" - integrity sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ== - -unicorn-magic@^0.3.0: - version "0.3.0" - resolved "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.3.0.tgz" - integrity sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA== - -util@^0.12.5: - version "0.12.5" - resolved "https://registry.npmjs.org/util/-/util-0.12.5.tgz" - integrity sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA== - dependencies: - inherits "^2.0.3" - is-arguments "^1.0.4" - is-generator-function "^1.0.7" - is-typed-array "^1.1.3" - which-typed-array "^1.1.2" - -v8-compile-cache-lib@^3.0.1: - version "3.0.1" - resolved "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz" - integrity sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg== - -validate-npm-package-license@^3.0.4: - version "3.0.4" - resolved "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz" - integrity sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew== - dependencies: - spdx-correct "^3.0.0" - spdx-expression-parse "^3.0.0" - -viem@2.23.4: - version "2.23.4" - resolved "https://registry.npmjs.org/viem/-/viem-2.23.4.tgz" - integrity sha512-UQquuolKlS1w5H5e0Fd1KKoUlIPJryIEBzY5AUhGyV1ka+9O6+3uYVhUzj6RbvGK0PtsMKn2ddwPZFwjNDVU/A== - dependencies: - "@noble/curves" "1.8.1" - "@noble/hashes" "1.7.1" - "@scure/bip32" "1.6.2" - "@scure/bip39" "1.5.4" - abitype "1.0.8" - isows "1.0.6" - ox "0.6.7" - ws "8.18.0" - -vite@^7.1.4: - version "7.1.4" - resolved "https://registry.yarnpkg.com/vite/-/vite-7.1.4.tgz#354944affb55e1aff0157406b74e0d0a3232df9a" - integrity sha512-X5QFK4SGynAeeIt+A7ZWnApdUyHYm+pzv/8/A57LqSGcI88U6R6ipOs3uCesdc6yl7nl+zNO0t8LmqAdXcQihw== - dependencies: - esbuild "^0.25.0" - fdir "^6.5.0" - picomatch "^4.0.3" - postcss "^8.5.6" - rollup "^4.43.0" - tinyglobby "^0.2.14" - optionalDependencies: - fsevents "~2.3.3" - -web-streams-polyfill@^3.0.3: - version "3.3.3" - resolved "https://registry.yarnpkg.com/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz#2073b91a2fdb1fbfbd401e7de0ac9f8214cecb4b" - integrity sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw== - -webidl-conversions@^4.0.2: - version "4.0.2" - resolved "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz" - integrity sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg== - -whatwg-url@^7.0.0: - version "7.1.0" - resolved "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.1.0.tgz" - integrity sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg== - dependencies: - lodash.sortby "^4.7.0" - tr46 "^1.0.1" - webidl-conversions "^4.0.2" - -which-typed-array@^1.1.16, which-typed-array@^1.1.2: - version "1.1.18" - resolved "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.18.tgz" - integrity sha512-qEcY+KJYlWyLH9vNbsr6/5j59AXk5ni5aakf8ldzBvGde6Iz4sxZGkJyWSAueTG7QhOvNRYb1lDdFmL5Td0QKA== - dependencies: - available-typed-arrays "^1.0.7" - call-bind "^1.0.8" - call-bound "^1.0.3" - for-each "^0.3.3" - gopd "^1.2.0" - has-tostringtag "^1.0.2" - -which@^2.0.1: - version "2.0.2" - resolved "https://registry.npmjs.org/which/-/which-2.0.2.tgz" - integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== - dependencies: - isexe "^2.0.0" - -workerpool@^6.5.1: - version "6.5.1" - resolved "https://registry.npmjs.org/workerpool/-/workerpool-6.5.1.tgz" - integrity sha512-Fs4dNYcsdpYSAfVxhnl1L5zTksjvOJxtC5hzMNl+1t9B8hTJTdKDyZ5ju7ztgPy+ft9tBFXoOlDNiOT9WUXZlA== - -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": - version "7.0.0" - resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz" - integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== - dependencies: - ansi-styles "^4.0.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" - -wrap-ansi@^7.0.0: - version "7.0.0" - resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz" - integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== - dependencies: - ansi-styles "^4.0.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" - -wrap-ansi@^8.1.0: - version "8.1.0" - resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz" - integrity sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ== - dependencies: - ansi-styles "^6.1.0" - string-width "^5.0.1" - strip-ansi "^7.0.1" - -write-file-atomic@^5.0.1: - version "5.0.1" - resolved "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-5.0.1.tgz" - integrity sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw== - dependencies: - imurmurhash "^0.1.4" - signal-exit "^4.0.1" - -write-json-file@^6.0.0: - version "6.0.0" - resolved "https://registry.npmjs.org/write-json-file/-/write-json-file-6.0.0.tgz" - integrity sha512-MNHcU3f9WxnNyR6MxsYSj64Jz0+dwIpisWKWq9gqLj/GwmA9INg3BZ3vt70/HB3GEwrnDQWr4RPrywnhNzmUFA== - dependencies: - detect-indent "^7.0.1" - is-plain-obj "^4.1.0" - sort-keys "^5.0.0" - write-file-atomic "^5.0.1" - -write-package@^7.1.0: - version "7.1.0" - resolved "https://registry.npmjs.org/write-package/-/write-package-7.1.0.tgz" - integrity sha512-DqUx8GI3r9BFWwU2DPKddL1E7xWfbFED82mLVhGXKlFEPe8IkBftzO7WfNwHtk7oGDHDeuH/o8VMpzzfMwmLUA== - dependencies: - deepmerge-ts "^7.1.0" - read-pkg "^9.0.1" - sort-keys "^5.0.0" - type-fest "^4.23.0" - write-json-file "^6.0.0" - -ws@8.17.1: - version "8.17.1" - resolved "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz" - integrity sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ== - -ws@8.18.0: - version "8.18.0" - resolved "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz" - integrity sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw== - -ws@^8.18.0, ws@^8.18.2, ws@^8.18.3, ws@^8.8.1: - version "8.18.3" - resolved "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz" - integrity sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg== - -y18n@^5.0.5: - version "5.0.8" - resolved "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz" - integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== - -yargs-parser@^21.1.1: - version "21.1.1" - resolved "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz" - integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== - -yargs-unparser@^2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz" - integrity sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA== - dependencies: - camelcase "^6.0.0" - decamelize "^4.0.0" - flat "^5.0.2" - is-plain-obj "^2.1.0" - -yargs@^17.7.2: - version "17.7.2" - resolved "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz" - integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w== - dependencies: - cliui "^8.0.1" - escalade "^3.1.1" - get-caller-file "^2.0.5" - require-directory "^2.1.1" - string-width "^4.2.3" - y18n "^5.0.5" - yargs-parser "^21.1.1" - -yn@3.1.1: - version "3.1.1" - resolved "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz" - integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q== - -yocto-queue@^0.1.0: - version "0.1.0" - resolved "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz" - integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== - -yoctocolors@^2.1.1: - version "2.1.1" - resolved "https://registry.npmjs.org/yoctocolors/-/yoctocolors-2.1.1.tgz" - integrity sha512-GQHQqAopRhwU8Kt1DDM8NjibDXHC8eoh1erhGAJPEyveY9qqVeXvVikNKrDz69sHowPMorbPUrH/mx8c50eiBQ== diff --git a/node/Cargo.toml b/node/Cargo.toml index 12a4b71189..1d2351c265 100644 --- a/node/Cargo.toml +++ b/node/Cargo.toml @@ -114,6 +114,21 @@ fc-aura.workspace = true fp-consensus.workspace = true num-traits = { workspace = true, features = ["std"] } +# Mev Shield +pallet-shield.workspace = true +tokio = { version = "1.38", features = ["time"] } +x25519-dalek = "2" +hkdf = "0.12" +chacha20poly1305 = { version = "0.10", features = ["std"] } +codec.workspace = true +rand.workspace = true +sha2.workspace = true +anyhow.workspace = true +pallet-subtensor.workspace = true +ml-kem.workspace = true +rand_core = "0.9.3" +blake2 = "0.10.6" + # Local Dependencies node-subtensor-runtime = { workspace = true, features = ["std"] } subtensor-runtime-common = { workspace = true, features = ["std"] } @@ -121,6 +136,7 @@ subtensor-custom-rpc = { workspace = true, features = ["std"] } subtensor-custom-rpc-runtime-api = { workspace = true, features = ["std"] } pallet-subtensor-swap-rpc = { workspace = true, features = ["std"] } pallet-subtensor-swap-runtime-api = { workspace = true, features = ["std"] } +subtensor-macros.workspace = true [build-dependencies] substrate-build-script-utils.workspace = true @@ -138,6 +154,7 @@ default = ["rocksdb", "sql", "txpool"] fast-runtime = [ "node-subtensor-runtime/fast-runtime", "subtensor-runtime-common/fast-runtime", + "pallet-subtensor/fast-runtime", ] sql = ["fc-db/sql", "fc-mapping-sync/sql"] txpool = ["fc-rpc/txpool", "fc-rpc-core/txpool"] @@ -154,7 +171,10 @@ runtime-benchmarks = [ "pallet-drand/runtime-benchmarks", "pallet-transaction-payment/runtime-benchmarks", "polkadot-sdk/runtime-benchmarks", + "pallet-subtensor/runtime-benchmarks", + "pallet-shield/runtime-benchmarks", ] + pow-faucet = [] # Enable features that allow the runtime to be tried and debugged. Name might be subject to change @@ -167,6 +187,8 @@ try-runtime = [ "pallet-commitments/try-runtime", "pallet-drand/try-runtime", "polkadot-sdk/try-runtime", + "pallet-shield/try-runtime", + "pallet-subtensor/try-runtime", ] metadata-hash = ["node-subtensor-runtime/metadata-hash"] diff --git a/node/src/chain_spec/localnet.rs b/node/src/chain_spec/localnet.rs index d65849ae94..02ea8896b5 100644 --- a/node/src/chain_spec/localnet.rs +++ b/node/src/chain_spec/localnet.rs @@ -34,11 +34,11 @@ pub fn localnet_config(single_authority: bool) -> Result { // aura | grandpa if single_authority { // single authority allows you to run the network using a single node - vec![authority_keys_from_seed("Alice")] + vec![authority_keys_from_seed("One")] } else { vec![ - authority_keys_from_seed("Alice"), - authority_keys_from_seed("Bob"), + authority_keys_from_seed("One"), + authority_keys_from_seed("Two"), ] }, // Pre-funded accounts @@ -77,6 +77,14 @@ fn localnet_genesis( get_account_id_from_seed::("Ferdie"), 2000000000000u128, ), + ( + get_account_id_from_seed::("One"), + 2000000000000u128, + ), + ( + get_account_id_from_seed::("Two"), + 2000000000000u128, + ), // ETH ( // Alith - 0xf24FF3a9CF04c71Dbc94D0b566f7A27B94566cac diff --git a/node/src/lib.rs b/node/src/lib.rs index c447a07309..ab4a409e1b 100644 --- a/node/src/lib.rs +++ b/node/src/lib.rs @@ -4,5 +4,6 @@ pub mod client; pub mod conditional_evm_block_import; pub mod consensus; pub mod ethereum; +pub mod mev_shield; pub mod rpc; pub mod service; diff --git a/node/src/main.rs b/node/src/main.rs index 64f25acc67..7adffa0ae9 100644 --- a/node/src/main.rs +++ b/node/src/main.rs @@ -10,6 +10,7 @@ mod command; mod conditional_evm_block_import; mod consensus; mod ethereum; +mod mev_shield; mod rpc; mod service; diff --git a/node/src/mev_shield/author.rs b/node/src/mev_shield/author.rs new file mode 100644 index 0000000000..7d9238a809 --- /dev/null +++ b/node/src/mev_shield/author.rs @@ -0,0 +1,472 @@ +use chacha20poly1305::{ + KeyInit, XChaCha20Poly1305, XNonce, + aead::{Aead, Payload}, +}; +use frame_system_rpc_runtime_api::AccountNonceApi; +use ml_kem::{EncodedSizeUser, KemCore, MlKem768}; +use node_subtensor_runtime as runtime; +use rand::rngs::OsRng; +use sp_api::ProvideRuntimeApi; +use sp_core::blake2_256; +use sp_runtime::{AccountId32, KeyTypeId}; +use std::sync::{Arc, Mutex}; +use subtensor_macros::freeze_struct; +use tokio::time::sleep; + +/// Parameters controlling time windows inside the slot. +#[freeze_struct("5c7ce101b36950de")] +#[derive(Clone)] +pub struct TimeParams { + pub slot_ms: u64, + pub announce_at_ms: u64, + pub decrypt_window_ms: u64, +} + +/// Holds the current/next ML‑KEM keypairs and their 32‑byte fingerprints. +#[freeze_struct("5e3c8209248282c3")] +#[derive(Clone)] +pub struct ShieldKeys { + pub current_sk: Vec, // ML‑KEM secret key bytes (encoded form) + pub current_pk: Vec, // ML‑KEM public key bytes (encoded form) + pub current_fp: [u8; 32], // blake2_256(pk) + pub next_sk: Vec, + pub next_pk: Vec, + pub next_fp: [u8; 32], +} + +impl ShieldKeys { + pub fn new() -> Self { + let (sk, pk) = MlKem768::generate(&mut OsRng); + + let sk_bytes = sk.as_bytes(); + let pk_bytes = pk.as_bytes(); + let sk_slice: &[u8] = sk_bytes.as_ref(); + let pk_slice: &[u8] = pk_bytes.as_ref(); + + let current_sk = sk_slice.to_vec(); + let current_pk = pk_slice.to_vec(); + let current_fp = blake2_256(pk_slice); + + let (nsk, npk) = MlKem768::generate(&mut OsRng); + let nsk_bytes = nsk.as_bytes(); + let npk_bytes = npk.as_bytes(); + let nsk_slice: &[u8] = nsk_bytes.as_ref(); + let npk_slice: &[u8] = npk_bytes.as_ref(); + let next_sk = nsk_slice.to_vec(); + let next_pk = npk_slice.to_vec(); + let next_fp = blake2_256(npk_slice); + + Self { + current_sk, + current_pk, + current_fp, + next_sk, + next_pk, + next_fp, + } + } + + pub fn roll_for_next_slot(&mut self) { + // Move next -> current + self.current_sk = core::mem::take(&mut self.next_sk); + self.current_pk = core::mem::take(&mut self.next_pk); + self.current_fp = self.next_fp; + + // Generate fresh next + let (nsk, npk) = MlKem768::generate(&mut OsRng); + let nsk_bytes = nsk.as_bytes(); + let npk_bytes = npk.as_bytes(); + let nsk_slice: &[u8] = nsk_bytes.as_ref(); + let npk_slice: &[u8] = npk_bytes.as_ref(); + self.next_sk = nsk_slice.to_vec(); + self.next_pk = npk_slice.to_vec(); + self.next_fp = blake2_256(npk_slice); + } +} + +impl Default for ShieldKeys { + fn default() -> Self { + Self::new() + } +} + +/// Shared context state. +#[freeze_struct("62af7d26cf7c1271")] +#[derive(Clone)] +pub struct ShieldContext { + pub keys: Arc>, + pub timing: TimeParams, +} + +/// Derive AEAD key directly from the 32‑byte ML‑KEM shared secret. +pub fn derive_aead_key(ss: &[u8]) -> [u8; 32] { + let mut key = [0u8; 32]; + let n = ss.len().min(32); + + if let (Some(dst), Some(src)) = (key.get_mut(..n), ss.get(..n)) { + dst.copy_from_slice(src); + } + key +} + +/// Plain XChaCha20-Poly1305 decrypt helper +pub fn aead_decrypt( + key: [u8; 32], + nonce24: [u8; 24], + ciphertext: &[u8], + aad: &[u8], +) -> Option> { + let aead = XChaCha20Poly1305::new((&key).into()); + aead.decrypt( + XNonce::from_slice(&nonce24), + Payload { + msg: ciphertext, + aad, + }, + ) + .ok() +} + +const AURA_KEY_TYPE: KeyTypeId = KeyTypeId(*b"aura"); + +/// Start background tasks: +/// - per-slot ML‑KEM key rotation +/// - at ~announce_at_ms announce the next key bytes on chain, +pub fn spawn_author_tasks( + task_spawner: &sc_service::SpawnTaskHandle, + client: Arc, + pool: Arc, + keystore: sp_keystore::KeystorePtr, + timing: TimeParams, +) -> ShieldContext +where + B: sp_runtime::traits::Block, + C: sc_client_api::HeaderBackend + + sc_client_api::BlockchainEvents + + ProvideRuntimeApi + + Send + + Sync + + 'static, + C::Api: AccountNonceApi, + Pool: sc_transaction_pool_api::TransactionPool + Send + Sync + 'static, + B::Extrinsic: From, +{ + let ctx = ShieldContext { + keys: Arc::new(Mutex::new(ShieldKeys::new())), + timing: timing.clone(), + }; + + let aura_keys: Vec = keystore.sr25519_public_keys(AURA_KEY_TYPE); + + let local_aura_pub = match aura_keys.first().copied() { + Some(k) => k, + None => { + log::warn!( + target: "mev-shield", + "spawn_author_tasks: no local Aura sr25519 key in keystore; \ + this node will NOT announce MEV-Shield keys" + ); + return ctx; + } + }; + + let aura_account: AccountId32 = local_aura_pub.into(); + let ctx_clone = ctx.clone(); + let client_clone = client.clone(); + let pool_clone = pool.clone(); + let keystore_clone = keystore.clone(); + + // Slot tick / key-announce loop. + task_spawner.spawn( + "mev-shield-keys-and-announce", + None, + async move { + use futures::StreamExt; + use sp_consensus::BlockOrigin; + + let slot_ms = timing.slot_ms; + + // Clamp announce_at_ms so it never exceeds slot_ms. + let mut announce_at_ms = timing.announce_at_ms; + if announce_at_ms > slot_ms { + log::warn!( + target: "mev-shield", + "spawn_author_tasks: announce_at_ms ({announce_at_ms}) > slot_ms ({slot_ms}); clamping to slot_ms", + ); + announce_at_ms = slot_ms; + } + let tail_ms = slot_ms.saturating_sub(announce_at_ms); + + log::debug!( + target: "mev-shield", + "author timing: slot_ms={slot_ms} announce_at_ms={announce_at_ms} (effective) tail_ms={tail_ms}", + ); + + let mut import_stream = client_clone.import_notification_stream(); + + while let Some(notif) = import_stream.next().await { + // Only act on blocks that this node authored. + if notif.origin != BlockOrigin::Own { + continue; + } + + let (curr_pk_len, next_pk_len) = match ctx_clone.keys.lock() { + Ok(k) => (k.current_pk.len(), k.next_pk.len()), + Err(e) => { + log::debug!( + target: "mev-shield", + "spawn_author_tasks: failed to lock ShieldKeys (poisoned?): {e:?}", + ); + continue; + } + }; + + log::debug!( + target: "mev-shield", + "Slot start (local author): (pk sizes: curr={curr_pk_len}B, next={next_pk_len}B)", + ); + + // Wait until the announce window in this slot. + if announce_at_ms > 0 { + sleep(std::time::Duration::from_millis(announce_at_ms)).await; + } + + // Read the next key we intend to use for the following block. + let next_pk = match ctx_clone.keys.lock() { + Ok(k) => k.next_pk.clone(), + Err(e) => { + log::debug!( + target: "mev-shield", + "spawn_author_tasks: failed to lock ShieldKeys for next_pk: {e:?}", + ); + continue; + } + }; + + // 🔑 Fetch the current on-chain nonce for the Aura account using the best block hash. + let best_hash = client_clone.info().best_hash; + + let nonce: u32 = match client_clone + .runtime_api() + .account_nonce(best_hash, aura_account.clone()) + { + Ok(n) => n, + Err(e) => { + log::debug!( + target: "mev-shield", + "spawn_author_tasks: failed to fetch account nonce for MEV-Shield author: {e:?}", + ); + continue; + } + }; + + // Submit announce_next_key signed with the Aura key using the correct nonce. + if let Err(e) = submit_announce_extrinsic::( + client_clone.clone(), + pool_clone.clone(), + keystore_clone.clone(), + local_aura_pub, + next_pk.clone(), + nonce, + ) + .await + { + log::debug!( + target: "mev-shield", + "announce_next_key submit error (nonce={nonce:?}): {e:?}" + ); + } + + // Sleep the remainder of the slot (if any). + if tail_ms > 0 { + sleep(std::time::Duration::from_millis(tail_ms)).await; + } + + // Roll keys for the next block. + match ctx_clone.keys.lock() { + Ok(mut k) => { + k.roll_for_next_slot(); + log::debug!( + target: "mev-shield", + "Rolled ML-KEM key at slot boundary", + ); + } + Err(e) => { + log::debug!( + target: "mev-shield", + "spawn_author_tasks: failed to lock ShieldKeys for roll_for_next_slot: {e:?}", + ); + } + } + } + }, + ); + + ctx +} + +/// Build & submit the signed `announce_next_key` extrinsic OFF-CHAIN +pub async fn submit_announce_extrinsic( + client: Arc, + pool: Arc, + keystore: sp_keystore::KeystorePtr, + aura_pub: sp_core::sr25519::Public, + next_public_key: Vec, + nonce: u32, +) -> anyhow::Result<()> +where + B: sp_runtime::traits::Block, + C: sc_client_api::HeaderBackend + sp_api::ProvideRuntimeApi + Send + Sync + 'static, + C::Api: sp_api::Core, + Pool: sc_transaction_pool_api::TransactionPool + Send + Sync + 'static, + B::Extrinsic: From, + B::Hash: AsRef<[u8]>, +{ + use node_subtensor_runtime as runtime; + use runtime::{RuntimeCall, SignedPayload, UncheckedExtrinsic}; + + use sc_transaction_pool_api::TransactionSource; + use sp_api::Core as _; + use sp_core::H256; + use sp_runtime::codec::Encode; + use sp_runtime::{ + BoundedVec, MultiSignature, + generic::Era, + traits::{ConstU32, SaturatedConversion, TransactionExtension}, + }; + + fn to_h256>(h: H) -> H256 { + let bytes = h.as_ref(); + let mut out = [0u8; 32]; + + if bytes.is_empty() { + return H256(out); + } + + let n = bytes.len().min(32); + let src_start = bytes.len().saturating_sub(n); + let dst_start = 32usize.saturating_sub(n); + + let src_slice = bytes.get(src_start..).and_then(|s| s.get(..n)); + + if let (Some(dst), Some(src)) = (out.get_mut(dst_start..32), src_slice) { + dst.copy_from_slice(src); + H256(out) + } else { + // Extremely defensive fallback. + H256([0u8; 32]) + } + } + + type MaxPk = ConstU32<2048>; + let public_key: BoundedVec = BoundedVec::try_from(next_public_key) + .map_err(|_| anyhow::anyhow!("public key too long (>2048 bytes)"))?; + + // 1) Runtime call carrying the public key bytes. + let call = RuntimeCall::MevShield(pallet_shield::Call::announce_next_key { public_key }); + + // 2) Build the transaction extensions exactly like the runtime. + type Extra = runtime::TransactionExtensions; + + let info = client.info(); + let at_hash = info.best_hash; + let at_hash_h256: H256 = to_h256(at_hash); + let genesis_h256: H256 = to_h256(info.genesis_hash); + + const ERA_PERIOD: u64 = 12; + let current_block: u64 = info.best_number.saturated_into(); + let era = Era::mortal(ERA_PERIOD, current_block); + + let extra: Extra = + ( + frame_system::CheckNonZeroSender::::new(), + frame_system::CheckSpecVersion::::new(), + frame_system::CheckTxVersion::::new(), + frame_system::CheckGenesis::::new(), + frame_system::CheckEra::::from(era), + node_subtensor_runtime::check_nonce::CheckNonce::::from(nonce).into(), + frame_system::CheckWeight::::new(), + node_subtensor_runtime::transaction_payment_wrapper::ChargeTransactionPaymentWrapper::< + runtime::Runtime, + >::new(pallet_transaction_payment::ChargeTransactionPayment::< + runtime::Runtime, + >::from(0u64)), + pallet_subtensor::transaction_extension::SubtensorTransactionExtension::< + runtime::Runtime, + >::new(), + pallet_drand::drand_priority::DrandPriority::::new(), + frame_metadata_hash_extension::CheckMetadataHash::::new(false), + ); + + // 3) Manually construct the `Implicit` tuple that the runtime will also derive. + type Implicit = >::Implicit; + + // Try to get the *current* runtime version from on-chain WASM; if that fails, + // fall back to the compiled runtime::VERSION. + let (spec_version, tx_version) = match client.runtime_api().version(at_hash) { + Ok(v) => (v.spec_version, v.transaction_version), + Err(e) => { + log::debug!( + target: "mev-shield", + "runtime_api::version failed at_hash={at_hash:?}: {e:?}; \ + falling back to compiled runtime::VERSION", + ); + ( + runtime::VERSION.spec_version, + runtime::VERSION.transaction_version, + ) + } + }; + + let implicit: Implicit = ( + (), // CheckNonZeroSender + spec_version, // dynamic or fallback spec_version + tx_version, // dynamic or fallback transaction_version + genesis_h256, // CheckGenesis::Implicit = Hash + at_hash_h256, // CheckEra::Implicit = hash of the block the tx is created at + (), // CheckNonce::Implicit = () + (), // CheckWeight::Implicit = () + (), // ChargeTransactionPaymentWrapper::Implicit = () + (), // SubtensorTransactionExtension::Implicit = () + (), // DrandPriority::Implicit = () + None, // CheckMetadataHash::Implicit = Option<[u8; 32]> + ); + + // 4) Build the exact signable payload from call + extra + implicit. + let payload: SignedPayload = SignedPayload::from_raw(call.clone(), extra.clone(), implicit); + + // 5) Sign with the local Aura key using the same SCALE bytes the runtime expects. + let sig_opt = payload + .using_encoded(|bytes| keystore.sr25519_sign(AURA_KEY_TYPE, &aura_pub, bytes)) + .map_err(|e| anyhow::anyhow!("keystore sr25519_sign error: {e:?}"))?; + + let sig = sig_opt + .ok_or_else(|| anyhow::anyhow!("keystore sr25519_sign returned None for Aura key"))?; + + let signature: MultiSignature = sig.into(); + + // 6) Sender address = AccountId32 derived from the Aura sr25519 public key. + let who: AccountId32 = aura_pub.into(); + let address = sp_runtime::MultiAddress::Id(who); + + // 7) Assemble the signed extrinsic and submit it to the pool. + let uxt: UncheckedExtrinsic = UncheckedExtrinsic::new_signed(call, address, signature, extra); + + let xt_bytes = uxt.encode(); + let xt_hash = sp_core::hashing::blake2_256(&xt_bytes); + let xt_hash_hex = hex::encode(xt_hash); + + let opaque: sp_runtime::OpaqueExtrinsic = uxt.into(); + let xt: ::Extrinsic = opaque.into(); + + pool.submit_one(at_hash, TransactionSource::Local, xt) + .await?; + + log::debug!( + target: "mev-shield", + "announce_next_key submitted: xt=0x{xt_hash_hex}, nonce={nonce:?}, \ + spec_version={spec_version}, tx_version={tx_version}, era={era:?}", + ); + + Ok(()) +} diff --git a/node/src/mev_shield/mod.rs b/node/src/mev_shield/mod.rs new file mode 100644 index 0000000000..91817097bf --- /dev/null +++ b/node/src/mev_shield/mod.rs @@ -0,0 +1,2 @@ +pub mod author; +pub mod proposer; diff --git a/node/src/mev_shield/proposer.rs b/node/src/mev_shield/proposer.rs new file mode 100644 index 0000000000..614cb785fd --- /dev/null +++ b/node/src/mev_shield/proposer.rs @@ -0,0 +1,899 @@ +use super::author::ShieldContext; +use futures::StreamExt; +use ml_kem::kem::{Decapsulate, DecapsulationKey}; +use ml_kem::{Ciphertext, Encoded, EncodedSizeUser, MlKem768, MlKem768Params}; +use sc_service::SpawnTaskHandle; +use sc_transaction_pool_api::{TransactionPool, TransactionSource}; +use sp_core::H256; +use sp_runtime::traits::{Header, SaturatedConversion}; +use sp_runtime::{AccountId32, OpaqueExtrinsic}; +use std::{ + collections::HashMap, + sync::{Arc, Mutex}, + time::Duration, +}; +use tokio::time::sleep; + +/// Buffer of wrappers keyed by the block number in which they were included. +#[derive(Default, Clone)] +struct WrapperBuffer { + by_id: HashMap< + H256, + ( + Vec, // ciphertext blob + u64, // originating block number + AccountId32, // wrapper author + ), + >, +} + +impl WrapperBuffer { + fn upsert(&mut self, id: H256, block_number: u64, author: AccountId32, ciphertext: Vec) { + self.by_id.insert(id, (ciphertext, block_number, author)); + } + + /// Drain only wrappers whose `block_number` matches the given `block`. + /// - Wrappers with `block_number > block` are kept for future decrypt windows. + /// - Wrappers with `block_number < block` are considered stale and dropped. + fn drain_for_block( + &mut self, + block: u64, + ) -> Vec<(H256, u64, sp_runtime::AccountId32, Vec)> { + let mut ready = Vec::new(); + let mut kept_future: usize = 0; + let mut dropped_past: usize = 0; + + self.by_id.retain(|id, (ct, block_number, who)| { + if *block_number == block { + // Ready to process now; remove from buffer. + ready.push((*id, *block_number, who.clone(), ct.clone())); + false + } else if *block_number > block { + // Not yet reveal time; keep for future blocks. + kept_future = kept_future.saturating_add(1); + true + } else { + // block_number < block => stale / missed reveal window; drop. + dropped_past = dropped_past.saturating_add(1); + log::debug!( + target: "mev-shield", + "revealer: dropping stale wrapper id=0x{} block_number={} < block={}", + hex::encode(id.as_bytes()), + *block_number, + block + ); + false + } + }); + + log::debug!( + target: "mev-shield", + "revealer: drain_for_block(block={}): ready={}, kept_future={}, dropped_past={}", + block, + ready.len(), + kept_future, + dropped_past + ); + + ready + } +} + +/// Start a background worker that: +/// • watches imported blocks and captures `MevShield::submit_encrypted` +/// • buffers those wrappers per originating block, +/// • during the last `decrypt_window_ms` of the slot: decrypt & submit `submit_one` +pub fn spawn_revealer( + task_spawner: &SpawnTaskHandle, + client: Arc, + pool: Arc, + ctx: ShieldContext, +) where + B: sp_runtime::traits::Block, + C: sc_client_api::HeaderBackend + + sc_client_api::BlockchainEvents + + sc_client_api::BlockBackend + + Send + + Sync + + 'static, + Pool: TransactionPool + Send + Sync + 'static, +{ + use codec::{Decode, Encode}; + + type Address = sp_runtime::MultiAddress; + type RUnchecked = node_subtensor_runtime::UncheckedExtrinsic; + + let buffer: Arc> = Arc::new(Mutex::new(WrapperBuffer::default())); + + // ── 1) buffer wrappers ─────────────────────────────────────── + { + let client = Arc::clone(&client); + let buffer = Arc::clone(&buffer); + + task_spawner.spawn( + "mev-shield-buffer-wrappers", + None, + async move { + log::debug!(target: "mev-shield", "buffer-wrappers task started"); + let mut import_stream = client.import_notification_stream(); + + while let Some(notif) = import_stream.next().await { + let at_hash = notif.hash; + let block_number_u64: u64 = (*notif.header.number()).saturated_into(); + + log::debug!( + target: "mev-shield", + "imported block hash={:?} number={} origin={:?}", + at_hash, + block_number_u64, + notif.origin + ); + + match client.block_body(at_hash) { + Ok(Some(body)) => { + log::debug!( + target: "mev-shield", + " block has {} extrinsics", + body.len() + ); + + for (idx, opaque_xt) in body.into_iter().enumerate() { + let encoded = opaque_xt.encode(); + log::debug!( + target: "mev-shield", + " [xt #{idx}] opaque len={} bytes", + encoded.len() + ); + + let uxt: RUnchecked = match RUnchecked::decode(&mut &encoded[..]) { + Ok(u) => u, + Err(e) => { + log::debug!( + target: "mev-shield", + " [xt #{idx}] failed to decode UncheckedExtrinsic: {e:?}", + ); + continue; + } + }; + + log::debug!( + target: "mev-shield", + " [xt #{idx}] decoded call: {:?}", + &uxt.0.function + ); + + let author_opt: Option = + match &uxt.0.preamble { + sp_runtime::generic::Preamble::Signed( + addr, + _sig, + _ext, + ) => match addr.clone() { + Address::Id(acc) => Some(acc), + Address::Address32(bytes) => { + Some(sp_runtime::AccountId32::new(bytes)) + } + _ => None, + }, + _ => None, + }; + + let Some(author) = author_opt else { + log::debug!( + target: "mev-shield", + " [xt #{idx}] not a Signed(AccountId32) extrinsic; skipping" + ); + continue; + }; + + if let node_subtensor_runtime::RuntimeCall::MevShield( + pallet_shield::Call::submit_encrypted { + commitment, + ciphertext, + }, + ) = &uxt.0.function + { + let payload = + (author.clone(), *commitment, ciphertext).encode(); + let id = H256(sp_core::hashing::blake2_256(&payload)); + + log::debug!( + target: "mev-shield", + " [xt #{idx}] buffered submit_encrypted: id=0x{}, block_number={}, author={}, ct_len={}, commitment={:?}", + hex::encode(id.as_bytes()), + block_number_u64, + author, + ciphertext.len(), + commitment + ); + + if let Ok(mut buf) = buffer.lock() { + buf.upsert( + id, + block_number_u64, + author, + ciphertext.to_vec(), + ); + } else { + log::debug!( + target: "mev-shield", + " [xt #{idx}] failed to lock WrapperBuffer; dropping wrapper" + ); + } + } + } + } + Ok(None) => log::debug!( + target: "mev-shield", + " block_body returned None for hash={at_hash:?}", + ), + Err(e) => log::debug!( + target: "mev-shield", + " block_body error for hash={at_hash:?}: {e:?}", + ), + } + } + }, + ); + } + + // ── 2) decrypt window revealer ────────────────────────────── + { + let client = Arc::clone(&client); + let pool = Arc::clone(&pool); + let buffer = Arc::clone(&buffer); + let ctx = ctx.clone(); + + task_spawner.spawn( + "mev-shield-last-window-revealer", + None, + async move { + log::debug!(target: "mev-shield", "last-window-revealer task started"); + + // Respect the configured slot_ms, but clamp the decrypt window so it never + // exceeds the slot length (important for fast runtimes). + let slot_ms = ctx.timing.slot_ms; + let mut decrypt_window_ms = ctx.timing.decrypt_window_ms; + + if decrypt_window_ms > slot_ms { + log::warn!( + target: "mev-shield", + "spawn_revealer: decrypt_window_ms ({decrypt_window_ms}) > slot_ms ({slot_ms}); clamping to slot_ms", + ); + decrypt_window_ms = slot_ms; + } + + let tail_ms = slot_ms.saturating_sub(decrypt_window_ms); + + log::debug!( + target: "mev-shield", + "revealer timing: slot_ms={slot_ms} decrypt_window_ms={decrypt_window_ms} (effective) tail_ms={tail_ms}", + ); + + loop { + log::debug!( + target: "mev-shield", + "revealer: sleeping {tail_ms} ms before decrypt window (slot_ms={slot_ms}, decrypt_window_ms={decrypt_window_ms})", + ); + + if tail_ms > 0 { + sleep(Duration::from_millis(tail_ms)).await; + } + + // Snapshot the current ML‑KEM secret. + let snapshot_opt = match ctx.keys.lock() { + Ok(k) => { + let sk_hash = sp_core::hashing::blake2_256(&k.current_sk); + Some(( + k.current_sk.clone(), + k.current_pk.len(), + k.next_pk.len(), + sk_hash, + )) + } + Err(e) => { + log::debug!( + target: "mev-shield", + "revealer: failed to lock ShieldKeys (poisoned?): {e:?}", + ); + None + } + }; + + let (curr_sk_bytes, curr_pk_len, next_pk_len, sk_hash) = + match snapshot_opt { + Some(v) => v, + None => { + // Skip this decrypt window entirely, without holding any guard. + if decrypt_window_ms > 0 { + sleep(Duration::from_millis(decrypt_window_ms)).await; + } + continue; + } + }; + + // Use best block number as the block whose submissions we reveal now. + let curr_block: u64 = client.info().best_number.saturated_into(); + + log::debug!( + target: "mev-shield", + "revealer: decrypt window start. reveal_block={} sk_len={} sk_hash=0x{} curr_pk_len={} next_pk_len={}", + curr_block, + curr_sk_bytes.len(), + hex::encode(sk_hash), + curr_pk_len, + next_pk_len + ); + + // Only process wrappers whose originating block matches the reveal_block. + let drained: Vec<(H256, u64, sp_runtime::AccountId32, Vec)> = + match buffer.lock() { + Ok(mut buf) => buf.drain_for_block(curr_block), + Err(e) => { + log::debug!( + target: "mev-shield", + "revealer: failed to lock WrapperBuffer for drain_for_block: {e:?}", + ); + Vec::new() + } + }; + + log::debug!( + target: "mev-shield", + "revealer: drained {} buffered wrappers for reveal_block={}", + drained.len(), + curr_block + ); + + let mut to_submit: Vec<(H256, node_subtensor_runtime::UncheckedExtrinsic)> = + Vec::new(); + let mut failed_calls: Vec<(H256, node_subtensor_runtime::RuntimeCall)> = + Vec::new(); + + // Helper to create mark_decryption_failed call + let create_failed_call = |id: H256, reason: &str| -> node_subtensor_runtime::RuntimeCall { + use sp_runtime::BoundedVec; + let reason_bytes = reason.as_bytes(); + let reason_bounded = BoundedVec::try_from(reason_bytes.to_vec()) + .unwrap_or_else(|_| { // Fallback if the reason is too long + BoundedVec::try_from(b"Decryption failed".to_vec()).unwrap_or_default() + }); + + node_subtensor_runtime::RuntimeCall::MevShield( + pallet_shield::Call::mark_decryption_failed { + id, + reason: reason_bounded, + }, + ) + }; + + for (id, block_number, author, blob) in drained.into_iter() { + log::debug!( + target: "mev-shield", + "revealer: candidate id=0x{} submitted_in={} (reveal_block={}) author={} blob_len={}", + hex::encode(id.as_bytes()), + block_number, + curr_block, + author, + blob.len() + ); + + // Safely parse blob: [u16 kem_len][kem_ct][nonce24][aead_ct] + if blob.len() < 2 { + let error_message = "blob too short to contain kem_len"; + log::debug!( + target: "mev-shield", + " id=0x{}: {}", + hex::encode(id.as_bytes()), + error_message + ); + failed_calls.push(( + id, + create_failed_call(id, error_message), + )); + continue; + } + + let mut cursor: usize = 0; + + // 1) kem_len (u16 LE) + let kem_len_end = match cursor.checked_add(2usize) { + Some(e) => e, + None => { + let error_message = "kem_len range overflow"; + log::debug!( + target: "mev-shield", + " id=0x{}: {}", + hex::encode(id.as_bytes()), + error_message + ); + failed_calls.push(( + id, + create_failed_call(id, error_message), + )); + continue; + } + }; + + let kem_len_slice = match blob.get(cursor..kem_len_end) { + Some(s) => s, + None => { + let error_message = "blob too short for kem_len bytes"; + log::debug!( + target: "mev-shield", + " id=0x{}: {} (cursor={} end={})", + hex::encode(id.as_bytes()), + error_message, + cursor, + kem_len_end + ); + failed_calls.push(( + id, + create_failed_call(id, error_message), + )); + continue; + } + }; + + let kem_len_bytes: [u8; 2] = match kem_len_slice.try_into() { + Ok(arr) => arr, + Err(_) => { + let error_message = "kem_len slice not 2 bytes"; + log::debug!( + target: "mev-shield", + " id=0x{}: {}", + hex::encode(id.as_bytes()), + error_message + ); + failed_calls.push(( + id, + create_failed_call(id, error_message), + )); + continue; + } + }; + + let kem_len = u16::from_le_bytes(kem_len_bytes) as usize; + cursor = kem_len_end; + + // 2) KEM ciphertext + let kem_ct_end = match cursor.checked_add(kem_len) { + Some(e) => e, + None => { + let error_message = "kem_ct range overflow"; + log::debug!( + target: "mev-shield", + " id=0x{}: {} (cursor={} kem_len={})", + hex::encode(id.as_bytes()), + error_message, + cursor, + kem_len + ); + failed_calls.push(( + id, + create_failed_call(id, error_message), + )); + continue; + } + }; + + let kem_ct_bytes = match blob.get(cursor..kem_ct_end) { + Some(s) => s, + None => { + let error_message = "blob too short for kem_ct"; + log::debug!( + target: "mev-shield", + " id=0x{}: {} (cursor={} end={})", + hex::encode(id.as_bytes()), + error_message, + cursor, + kem_ct_end + ); + failed_calls.push(( + id, + create_failed_call(id, error_message), + )); + continue; + } + }; + cursor = kem_ct_end; + + // 3) Nonce (24 bytes) + const NONCE_LEN: usize = 24; + let nonce_end = match cursor.checked_add(NONCE_LEN) { + Some(e) => e, + None => { + let error_message = "nonce range overflow"; + log::debug!( + target: "mev-shield", + " id=0x{}: {} (cursor={})", + hex::encode(id.as_bytes()), + error_message, + cursor + ); + failed_calls.push(( + id, + create_failed_call(id, error_message), + )); + continue; + } + }; + + let nonce_bytes = match blob.get(cursor..nonce_end) { + Some(s) => s, + None => { + let error_message = "blob too short for nonce24"; + log::debug!( + target: "mev-shield", + " id=0x{}: {} (cursor={} end={})", + hex::encode(id.as_bytes()), + error_message, + cursor, + nonce_end + ); + failed_calls.push(( + id, + create_failed_call(id, error_message), + )); + continue; + } + }; + cursor = nonce_end; + + // 4) AEAD body (rest) + let aead_body = match blob.get(cursor..) { + Some(s) => s, + None => { + let error_message = "blob too short for aead_body"; + log::debug!( + target: "mev-shield", + " id=0x{}: {} (cursor={})", + hex::encode(id.as_bytes()), + error_message, + cursor + ); + failed_calls.push(( + id, + create_failed_call(id, error_message), + )); + continue; + } + }; + + let kem_ct_hash = sp_core::hashing::blake2_256(kem_ct_bytes); + let aead_body_hash = sp_core::hashing::blake2_256(aead_body); + + log::debug!( + target: "mev-shield", + " id=0x{}: kem_len={} kem_ct_hash=0x{} nonce=0x{} aead_body_len={} aead_body_hash=0x{}", + hex::encode(id.as_bytes()), + kem_len, + hex::encode(kem_ct_hash), + hex::encode(nonce_bytes), + aead_body.len(), + hex::encode(aead_body_hash), + ); + + // Rebuild DecapsulationKey and decapsulate. + let enc_sk = + match Encoded::>::try_from( + &curr_sk_bytes[..], + ) { + Ok(e) => e, + Err(e) => { + let error_message = "DecapsulationKey::try_from failed"; + log::debug!( + target: "mev-shield", + " id=0x{}: {} (len={}, err={:?})", + hex::encode(id.as_bytes()), + error_message, + curr_sk_bytes.len(), + e + ); + failed_calls.push(( + id, + create_failed_call(id, error_message), + )); + continue; + } + }; + let sk = DecapsulationKey::::from_bytes(&enc_sk); + + let ct = match Ciphertext::::try_from(kem_ct_bytes) { + Ok(c) => c, + Err(e) => { + let error_message = "Ciphertext::try_from failed"; + log::debug!( + target: "mev-shield", + " id=0x{}: {}: {:?}", + hex::encode(id.as_bytes()), + error_message, + e + ); + failed_calls.push(( + id, + create_failed_call(id, error_message), + )); + continue; + } + }; + + let ss = match sk.decapsulate(&ct) { + Ok(s) => s, + Err(_) => { + let error_message = "ML-KEM decapsulate failed"; + log::debug!( + target: "mev-shield", + " id=0x{}: {}", + hex::encode(id.as_bytes()), + error_message + ); + failed_calls.push(( + id, + create_failed_call(id, error_message), + )); + continue; + } + }; + + let ss_bytes: &[u8] = ss.as_ref(); + if ss_bytes.len() != 32 { + let error_message = "shared secret length != 32"; + log::debug!( + target: "mev-shield", + " id=0x{}: {} (len={})", + hex::encode(id.as_bytes()), + error_message, + ss_bytes.len() + ); + failed_calls.push(( + id, + create_failed_call(id, error_message), + )); + continue; + } + let mut ss32 = [0u8; 32]; + ss32.copy_from_slice(ss_bytes); + + let ss_hash = sp_core::hashing::blake2_256(&ss32); + let aead_key = + crate::mev_shield::author::derive_aead_key(&ss32); + let key_hash_dbg = sp_core::hashing::blake2_256(&aead_key); + + log::debug!( + target: "mev-shield", + " id=0x{}: decapsulated shared_secret_len=32 shared_secret_hash=0x{}", + hex::encode(id.as_bytes()), + hex::encode(ss_hash) + ); + log::debug!( + target: "mev-shield", + " id=0x{}: derived AEAD key hash=0x{} (direct-from-ss)", + hex::encode(id.as_bytes()), + hex::encode(key_hash_dbg) + ); + + let mut nonce24 = [0u8; 24]; + nonce24.copy_from_slice(nonce_bytes); + + log::debug!( + target: "mev-shield", + " id=0x{}: attempting AEAD decrypt nonce=0x{} ct_len={}", + hex::encode(id.as_bytes()), + hex::encode(nonce24), + aead_body.len() + ); + + let plaintext = match crate::mev_shield::author::aead_decrypt( + aead_key, + nonce24, + aead_body, + &[], + ) { + Some(pt) => pt, + None => { + let error_message = "AEAD decrypt failed"; + log::debug!( + target: "mev-shield", + " id=0x{}: {}; ct_hash=0x{}", + hex::encode(id.as_bytes()), + error_message, + hex::encode(aead_body_hash), + ); + continue; + } + }; + + log::debug!( + target: "mev-shield", + " id=0x{}: AEAD decrypt OK, plaintext_len={}", + hex::encode(id.as_bytes()), + plaintext.len() + ); + + // Safely parse plaintext layout without panics. + + if plaintext.is_empty() { + let error_message = "plaintext too short"; + log::debug!( + target: "mev-shield", + " id=0x{}: {} (len={}, min={})", + hex::encode(id.as_bytes()), + error_message, + plaintext.len(), + 1 + ); + failed_calls.push(( + id, + create_failed_call(id, error_message), + )); + continue; + } + + let signed_extrinsic_bytes = match plaintext.get(0..plaintext.len()) { + Some(s) if !s.is_empty() => s, + _ => { + let error_message = "missing signed extrinsic bytes"; + log::debug!( + target: "mev-shield", + " id=0x{}: {}", + hex::encode(id.as_bytes()), + error_message + ); + failed_calls.push(( + id, + create_failed_call(id, error_message), + )); + continue; + } + }; + + + let signed_extrinsic: node_subtensor_runtime::UncheckedExtrinsic = + match Decode::decode(&mut &signed_extrinsic_bytes[..]) { + Ok(c) => c, + Err(e) => { + let error_message = "failed to decode UncheckedExtrinsic"; + log::debug!( + target: "mev-shield", + " id=0x{}: {} (len={}): {:?}", + hex::encode(id.as_bytes()), + error_message, + signed_extrinsic_bytes.len(), + e + ); + failed_calls.push(( + id, + create_failed_call(id, error_message), + )); + continue; + } + }; + + to_submit.push((id, signed_extrinsic)); + } + + // Submit as external the signed extrinsics. + let at = client.info().best_hash; + log::debug!( + target: "mev-shield", + "revealer: submitting {} extrinsics to pool at best_hash={:?}", + to_submit.len(), + at + ); + + for (id, uxt) in to_submit.into_iter() { + let xt_bytes = uxt.encode(); + + log::debug!( + target: "mev-shield", + " id=0x{}: encoded UncheckedExtrinsic len={}", + hex::encode(id.as_bytes()), + xt_bytes.len() + ); + + match OpaqueExtrinsic::from_bytes(&xt_bytes) { + Ok(opaque) => { + match pool + .submit_one(at, TransactionSource::External, opaque) + .await + { + Ok(_) => { + let xt_hash = + sp_core::hashing::blake2_256(&xt_bytes); + log::debug!( + target: "mev-shield", + " id=0x{}: submit_one(...) OK, xt_hash=0x{}", + hex::encode(id.as_bytes()), + hex::encode(xt_hash) + ); + } + Err(e) => { + log::debug!( + target: "mev-shield", + " id=0x{}: submit_one(...) FAILED: {:?}", + hex::encode(id.as_bytes()), + e + ); + } + } + } + Err(e) => { + log::debug!( + target: "mev-shield", + " id=0x{}: OpaqueExtrinsic::from_bytes failed: {:?}", + hex::encode(id.as_bytes()), + e + ); + } + } + } + + // Submit failed decryption calls + if !failed_calls.is_empty() { + log::debug!( + target: "mev-shield", + "revealer: submitting {} mark_decryption_failed calls at best_hash={:?}", + failed_calls.len(), + at + ); + + for (id, call) in failed_calls.into_iter() { + let uxt: node_subtensor_runtime::UncheckedExtrinsic = + node_subtensor_runtime::UncheckedExtrinsic::new_bare(call); + let xt_bytes = uxt.encode(); + + log::debug!( + target: "mev-shield", + " id=0x{}: encoded mark_decryption_failed UncheckedExtrinsic len={}", + hex::encode(id.as_bytes()), + xt_bytes.len() + ); + + match OpaqueExtrinsic::from_bytes(&xt_bytes) { + Ok(opaque) => { + match pool + .submit_one(at, TransactionSource::Local, opaque) + .await + { + Ok(_) => { + let xt_hash = + sp_core::hashing::blake2_256(&xt_bytes); + log::debug!( + target: "mev-shield", + " id=0x{}: submit_one(mark_decryption_failed) OK, xt_hash=0x{}", + hex::encode(id.as_bytes()), + hex::encode(xt_hash) + ); + } + Err(e) => { + log::warn!( + target: "mev-shield", + " id=0x{}: submit_one(mark_decryption_failed) FAILED: {:?}", + hex::encode(id.as_bytes()), + e + ); + } + } + } + Err(e) => { + log::warn!( + target: "mev-shield", + " id=0x{}: OpaqueExtrinsic::from_bytes(mark_decryption_failed) failed: {:?}", + hex::encode(id.as_bytes()), + e + ); + } + } + } + } + + // Let the decrypt window elapse. + if decrypt_window_ms > 0 { + sleep(Duration::from_millis(decrypt_window_ms)).await; + } + } + }, + ); + } +} diff --git a/node/src/service.rs b/node/src/service.rs index 2ef1904f08..9e1c241f34 100644 --- a/node/src/service.rs +++ b/node/src/service.rs @@ -34,6 +34,7 @@ use crate::ethereum::{ BackendType, EthConfiguration, FrontierBackend, FrontierPartialComponents, StorageOverride, StorageOverrideHandler, db_config_dir, new_frontier_partial, spawn_frontier_tasks, }; +use crate::mev_shield::{author, proposer}; const LOG_TARGET: &str = "node-service"; @@ -534,6 +535,48 @@ where ) .await; + // ==== MEV-SHIELD HOOKS ==== + let mut mev_timing: Option = None; + + if role.is_authority() { + let slot_duration = consensus_mechanism.slot_duration(&client)?; + let slot_duration_ms: u64 = u64::try_from(slot_duration.as_millis()).unwrap_or(u64::MAX); + + // For 12s blocks: announce ≈ 7s, decrypt window ≈ 3s. + // For 250ms blocks: announce ≈ 145ms, decrypt window ≈ 62ms, etc. + let announce_at_ms_raw = slot_duration_ms.saturating_mul(7).saturating_div(12); + + let decrypt_window_ms = slot_duration_ms.saturating_mul(3).saturating_div(12); + + // Ensure announce_at_ms + decrypt_window_ms never exceeds slot_ms. + let max_announce = slot_duration_ms.saturating_sub(decrypt_window_ms); + let announce_at_ms = announce_at_ms_raw.min(max_announce); + + let timing = author::TimeParams { + slot_ms: slot_duration_ms, + announce_at_ms, + decrypt_window_ms, + }; + mev_timing = Some(timing.clone()); + + // Start author-side tasks with dynamic timing. + let mev_ctx = author::spawn_author_tasks::( + &task_manager.spawn_handle(), + client.clone(), + transaction_pool.clone(), + keystore_container.keystore(), + timing.clone(), + ); + + // Start last-portion-of-slot revealer (decrypt -> submit_one). + proposer::spawn_revealer::( + &task_manager.spawn_handle(), + client.clone(), + transaction_pool.clone(), + mev_ctx.clone(), + ); + } + if role.is_authority() { // manual-seal authorship if let Some(sealing) = sealing { @@ -548,7 +591,6 @@ where telemetry.as_ref(), commands_stream, )?; - log::info!("Manual Seal Ready"); return Ok(task_manager); } @@ -562,6 +604,26 @@ where ); let slot_duration = consensus_mechanism.slot_duration(&client)?; + + let start_fraction: f32 = { + let (slot_ms, decrypt_ms) = mev_timing + .as_ref() + .map(|t| (t.slot_ms, t.decrypt_window_ms)) + .unwrap_or((slot_duration.as_millis(), 3_000)); + + let guard_ms: u64 = 200; // small cushion so reveals hit the pool first + let after_decrypt_ms = slot_ms.saturating_sub(decrypt_ms).saturating_add(guard_ms); + + let f_raw = if slot_ms > 0 { + (after_decrypt_ms as f32) / (slot_ms as f32) + } else { + // Extremely defensive fallback; should never happen in practice. + 0.75 + }; + + f_raw.clamp(0.50, 0.98) + }; + let create_inherent_data_providers = move |_, ()| async move { CM::create_inherent_data_providers(slot_duration) }; @@ -579,7 +641,7 @@ where force_authoring, backoff_authoring_blocks, keystore: keystore_container.keystore(), - block_proposal_slot_portion: SlotProportion::new(2f32 / 3f32), + block_proposal_slot_portion: SlotProportion::new(start_fraction), max_block_proposal_slot_portion: None, telemetry: telemetry.as_ref().map(|x| x.handle()), }, diff --git a/pallets/admin-utils/src/lib.rs b/pallets/admin-utils/src/lib.rs index 01e9e7b33e..b95d3ac82c 100644 --- a/pallets/admin-utils/src/lib.rs +++ b/pallets/admin-utils/src/lib.rs @@ -139,8 +139,8 @@ pub mod pallet { Alpha, /// Enum for crowdloan precompile Crowdloan, - /// Pure proxy precompile - PureProxy, + /// Proxy precompile + Proxy, /// Leasing precompile Leasing, } @@ -236,6 +236,7 @@ pub mod pallet { netuid, &[Hyperparameter::ServingRateLimit.into()], )?; + pallet_subtensor::Pallet::::ensure_admin_window_open(netuid)?; pallet_subtensor::Pallet::::set_serving_rate_limit(netuid, serving_rate_limit); log::debug!("ServingRateLimitSet( serving_rate_limit: {serving_rate_limit:?} ) "); pallet_subtensor::Pallet::::record_owner_rl( @@ -258,7 +259,8 @@ pub mod pallet { netuid: NetUid, min_difficulty: u64, ) -> DispatchResult { - pallet_subtensor::Pallet::::ensure_root_with_rate_limit(origin, netuid)?; + ensure_root(origin)?; + pallet_subtensor::Pallet::::ensure_admin_window_open(netuid)?; ensure!( pallet_subtensor::Pallet::::if_subnet_exist(netuid), @@ -288,6 +290,7 @@ pub mod pallet { netuid, &[Hyperparameter::MaxDifficulty.into()], )?; + pallet_subtensor::Pallet::::ensure_admin_window_open(netuid)?; ensure!( pallet_subtensor::Pallet::::if_subnet_exist(netuid), @@ -322,6 +325,7 @@ pub mod pallet { netuid, &[TransactionType::SetWeightsVersionKey], )?; + pallet_subtensor::Pallet::::ensure_admin_window_open(netuid)?; ensure!( pallet_subtensor::Pallet::::if_subnet_exist(netuid), @@ -413,6 +417,7 @@ pub mod pallet { netuid, &[Hyperparameter::AdjustmentAlpha.into()], )?; + pallet_subtensor::Pallet::::ensure_admin_window_open(netuid)?; ensure!( pallet_subtensor::Pallet::::if_subnet_exist(netuid), @@ -445,6 +450,7 @@ pub mod pallet { netuid, &[Hyperparameter::ImmunityPeriod.into()], )?; + pallet_subtensor::Pallet::::ensure_admin_window_open(netuid)?; ensure!( pallet_subtensor::Pallet::::if_subnet_exist(netuid), Error::::SubnetDoesNotExist @@ -479,6 +485,7 @@ pub mod pallet { netuid, &[Hyperparameter::MinAllowedWeights.into()], )?; + pallet_subtensor::Pallet::::ensure_admin_window_open(netuid)?; ensure!( pallet_subtensor::Pallet::::if_subnet_exist(netuid), @@ -513,6 +520,7 @@ pub mod pallet { netuid, &[Hyperparameter::MaxAllowedUids.into()], )?; + pallet_subtensor::Pallet::::ensure_admin_window_open(netuid)?; ensure!( pallet_subtensor::Pallet::::if_subnet_exist(netuid), Error::::SubnetDoesNotExist @@ -572,6 +580,7 @@ pub mod pallet { netuid, &[Hyperparameter::Rho.into()], )?; + pallet_subtensor::Pallet::::ensure_admin_window_open(netuid)?; ensure!( pallet_subtensor::Pallet::::if_subnet_exist(netuid), @@ -604,6 +613,7 @@ pub mod pallet { netuid, &[Hyperparameter::ActivityCutoff.into()], )?; + pallet_subtensor::Pallet::::ensure_admin_window_open(netuid)?; ensure!( pallet_subtensor::Pallet::::if_subnet_exist(netuid), @@ -672,6 +682,7 @@ pub mod pallet { netuid, &[Hyperparameter::PowRegistrationAllowed.into()], )?; + pallet_subtensor::Pallet::::ensure_admin_window_open(netuid)?; pallet_subtensor::Pallet::::set_network_pow_registration_allowed( netuid, @@ -700,7 +711,8 @@ pub mod pallet { netuid: NetUid, target_registrations_per_interval: u16, ) -> DispatchResult { - pallet_subtensor::Pallet::::ensure_root_with_rate_limit(origin, netuid)?; + ensure_root(origin)?; + pallet_subtensor::Pallet::::ensure_admin_window_open(netuid)?; ensure!( pallet_subtensor::Pallet::::if_subnet_exist(netuid), @@ -733,6 +745,7 @@ pub mod pallet { netuid, &[Hyperparameter::MinBurn.into()], )?; + pallet_subtensor::Pallet::::ensure_admin_window_open(netuid)?; ensure!( pallet_subtensor::Pallet::::if_subnet_exist(netuid), Error::::SubnetDoesNotExist @@ -773,6 +786,7 @@ pub mod pallet { netuid, &[Hyperparameter::MaxBurn.into()], )?; + pallet_subtensor::Pallet::::ensure_admin_window_open(netuid)?; ensure!( pallet_subtensor::Pallet::::if_subnet_exist(netuid), Error::::SubnetDoesNotExist @@ -808,7 +822,8 @@ pub mod pallet { netuid: NetUid, difficulty: u64, ) -> DispatchResult { - pallet_subtensor::Pallet::::ensure_root_with_rate_limit(origin, netuid)?; + ensure_root(origin)?; + pallet_subtensor::Pallet::::ensure_admin_window_open(netuid)?; ensure!( pallet_subtensor::Pallet::::if_subnet_exist(netuid), Error::::SubnetDoesNotExist @@ -830,7 +845,8 @@ pub mod pallet { netuid: NetUid, max_allowed_validators: u16, ) -> DispatchResult { - pallet_subtensor::Pallet::::ensure_root_with_rate_limit(origin, netuid)?; + ensure_root(origin)?; + pallet_subtensor::Pallet::::ensure_admin_window_open(netuid)?; ensure!( pallet_subtensor::Pallet::::if_subnet_exist(netuid), Error::::SubnetDoesNotExist @@ -868,6 +884,7 @@ pub mod pallet { netuid, &[Hyperparameter::BondsMovingAverage.into()], )?; + pallet_subtensor::Pallet::::ensure_admin_window_open(netuid)?; if maybe_owner.is_some() { ensure!( bonds_moving_average <= 975000, @@ -908,6 +925,7 @@ pub mod pallet { netuid, &[Hyperparameter::BondsPenalty.into()], )?; + pallet_subtensor::Pallet::::ensure_admin_window_open(netuid)?; ensure!( pallet_subtensor::Pallet::::if_subnet_exist(netuid), @@ -935,7 +953,8 @@ pub mod pallet { netuid: NetUid, max_registrations_per_block: u16, ) -> DispatchResult { - pallet_subtensor::Pallet::::ensure_root_with_rate_limit(origin, netuid)?; + ensure_root(origin)?; + pallet_subtensor::Pallet::::ensure_admin_window_open(netuid)?; ensure!( pallet_subtensor::Pallet::::if_subnet_exist(netuid), @@ -999,7 +1018,8 @@ pub mod pallet { .saturating_add(::DbWeight::get().reads(3_u64)) .saturating_add(::DbWeight::get().writes(1_u64)))] pub fn sudo_set_tempo(origin: OriginFor, netuid: NetUid, tempo: u16) -> DispatchResult { - pallet_subtensor::Pallet::::ensure_root_with_rate_limit(origin, netuid)?; + ensure_root(origin)?; + pallet_subtensor::Pallet::::ensure_admin_window_open(netuid)?; ensure!( pallet_subtensor::Pallet::::if_subnet_exist(netuid), Error::::SubnetDoesNotExist @@ -1245,6 +1265,7 @@ pub mod pallet { netuid, &[Hyperparameter::CommitRevealEnabled.into()], )?; + pallet_subtensor::Pallet::::ensure_admin_window_open(netuid)?; ensure!( pallet_subtensor::Pallet::::if_subnet_exist(netuid), @@ -1288,6 +1309,7 @@ pub mod pallet { netuid, &[Hyperparameter::LiquidAlphaEnabled.into()], )?; + pallet_subtensor::Pallet::::ensure_admin_window_open(netuid)?; pallet_subtensor::Pallet::::set_liquid_alpha_enabled(netuid, enabled); log::debug!("LiquidAlphaEnableToggled( netuid: {netuid:?}, Enabled: {enabled:?} ) "); pallet_subtensor::Pallet::::record_owner_rl( @@ -1318,6 +1340,7 @@ pub mod pallet { netuid, &[Hyperparameter::AlphaValues.into()], )?; + pallet_subtensor::Pallet::::ensure_admin_window_open(netuid)?; let res = pallet_subtensor::Pallet::::do_set_alpha_values( origin, netuid, alpha_low, alpha_high, ); @@ -1437,6 +1460,7 @@ pub mod pallet { netuid, &[Hyperparameter::WeightCommitInterval.into()], )?; + pallet_subtensor::Pallet::::ensure_admin_window_open(netuid)?; ensure!( pallet_subtensor::Pallet::::if_subnet_exist(netuid), @@ -1535,6 +1559,7 @@ pub mod pallet { netuid, &[Hyperparameter::TransferEnabled.into()], )?; + pallet_subtensor::Pallet::::ensure_admin_window_open(netuid)?; let res = pallet_subtensor::Pallet::::toggle_transfer(netuid, toggle); if res.is_ok() { pallet_subtensor::Pallet::::record_owner_rl( @@ -1567,6 +1592,7 @@ pub mod pallet { netuid, &[Hyperparameter::RecycleOrBurn.into()], )?; + pallet_subtensor::Pallet::::ensure_admin_window_open(netuid)?; pallet_subtensor::Pallet::::set_recycle_or_burn(netuid, recycle_or_burn); pallet_subtensor::Pallet::::record_owner_rl( @@ -1734,6 +1760,7 @@ pub mod pallet { netuid, &[Hyperparameter::AlphaSigmoidSteepness.into()], )?; + pallet_subtensor::Pallet::::ensure_admin_window_open(netuid)?; ensure!( pallet_subtensor::Pallet::::if_subnet_exist(netuid), @@ -1784,6 +1811,7 @@ pub mod pallet { netuid, &[Hyperparameter::Yuma3Enabled.into()], )?; + pallet_subtensor::Pallet::::ensure_admin_window_open(netuid)?; pallet_subtensor::Pallet::::set_yuma3_enabled(netuid, enabled); Self::deposit_event(Event::Yuma3EnableToggled { netuid, enabled }); @@ -1823,6 +1851,7 @@ pub mod pallet { netuid, &[Hyperparameter::BondsResetEnabled.into()], )?; + pallet_subtensor::Pallet::::ensure_admin_window_open(netuid)?; pallet_subtensor::Pallet::::set_bonds_reset(netuid, enabled); Self::deposit_event(Event::BondsResetToggled { netuid, enabled }); @@ -1906,7 +1935,8 @@ pub mod pallet { netuid: NetUid, subtoken_enabled: bool, ) -> DispatchResult { - pallet_subtensor::Pallet::::ensure_root_with_rate_limit(origin, netuid)?; + ensure_root(origin)?; + pallet_subtensor::Pallet::::ensure_admin_window_open(netuid)?; pallet_subtensor::SubtokenEnabled::::set(netuid, subtoken_enabled); log::debug!( @@ -1948,6 +1978,7 @@ pub mod pallet { netuid, &[Hyperparameter::ImmuneNeuronLimit.into()], )?; + pallet_subtensor::Pallet::::ensure_admin_window_open(netuid)?; pallet_subtensor::Pallet::::set_owner_immune_neuron_limit(netuid, immune_neurons)?; pallet_subtensor::Pallet::::record_owner_rl( maybe_owner, @@ -2021,6 +2052,7 @@ pub mod pallet { netuid, &[TransactionType::MechanismCountUpdate], )?; + pallet_subtensor::Pallet::::ensure_admin_window_open(netuid)?; pallet_subtensor::Pallet::::do_set_mechanism_count(netuid, mechanism_count)?; @@ -2047,6 +2079,7 @@ pub mod pallet { netuid, &[TransactionType::MechanismEmission], )?; + pallet_subtensor::Pallet::::ensure_admin_window_open(netuid)?; pallet_subtensor::Pallet::::do_set_emission_split(netuid, maybe_split)?; @@ -2077,6 +2110,7 @@ pub mod pallet { netuid, &[TransactionType::MaxUidsTrimming], )?; + pallet_subtensor::Pallet::::ensure_admin_window_open(netuid)?; pallet_subtensor::Pallet::::trim_to_max_allowed_uids(netuid, max_n)?; @@ -2099,7 +2133,8 @@ pub mod pallet { netuid: NetUid, min_allowed_uids: u16, ) -> DispatchResult { - pallet_subtensor::Pallet::::ensure_root_with_rate_limit(origin, netuid)?; + ensure_root(origin)?; + pallet_subtensor::Pallet::::ensure_admin_window_open(netuid)?; ensure!( pallet_subtensor::Pallet::::if_subnet_exist(netuid), diff --git a/pallets/drand/Cargo.toml b/pallets/drand/Cargo.toml index 269e993d02..6e3ad982f7 100644 --- a/pallets/drand/Cargo.toml +++ b/pallets/drand/Cargo.toml @@ -17,7 +17,7 @@ scale-info = { workspace = true, features = ["derive"] } serde = { workspace = true, features = ["derive"] } serde_json.workspace = true log.workspace = true -hex = { workspace = true, features = ["serde"] } +hex = { workspace = true, features = ["serde", "alloc"] } sha2.workspace = true anyhow.workspace = true # frame deps @@ -29,7 +29,7 @@ sp-io.workspace = true sp-runtime.workspace = true sp-std.workspace = true # arkworks dependencies -sp-ark-bls12-381.workspace = true +sp-crypto-ec-utils = { workspace = true, features = ["bls12-381"] } ark-bls12-381 = { workspace = true, features = ["curve"] } ark-serialize = { workspace = true, features = ["derive"] } ark-ff.workspace = true @@ -64,7 +64,7 @@ std = [ "serde/std", "serde_json/std", "hex/std", - "sp-ark-bls12-381/std", + "sp-crypto-ec-utils/std", "ark-bls12-381/std", "ark-serialize/std", "ark-ff/std", diff --git a/pallets/drand/src/bls12_381.rs b/pallets/drand/src/bls12_381.rs index 1415613ef6..e31118a3e4 100644 --- a/pallets/drand/src/bls12_381.rs +++ b/pallets/drand/src/bls12_381.rs @@ -16,7 +16,7 @@ use ark_ec::pairing::Pairing; use ark_std::{Zero, ops::Neg}; -use sp_ark_bls12_381::{ +use sp_crypto_ec_utils::bls12_381::{ Bls12_381 as Bls12_381Opt, G1Affine as G1AffineOpt, G2Affine as G2AffineOpt, }; diff --git a/pallets/drand/src/verifier.rs b/pallets/drand/src/verifier.rs index e24b82003a..36c212181a 100644 --- a/pallets/drand/src/verifier.rs +++ b/pallets/drand/src/verifier.rs @@ -27,7 +27,7 @@ use ark_ec::{AffineRepr, hashing::HashToCurve}; use ark_serialize::CanonicalSerialize; use codec::Decode; use sha2::{Digest, Sha256}; -use sp_ark_bls12_381::{G1Affine as G1AffineOpt, G2Affine as G2AffineOpt}; +use sp_crypto_ec_utils::bls12_381::{G1Affine as G1AffineOpt, G2Affine as G2AffineOpt}; use tle::curves::drand::TinyBLS381; use w3f_bls::engine::EngineBLS; diff --git a/pallets/proxy/src/lib.rs b/pallets/proxy/src/lib.rs index 93ac568668..70337fc7a8 100644 --- a/pallets/proxy/src/lib.rs +++ b/pallets/proxy/src/lib.rs @@ -39,6 +39,7 @@ use frame::{ prelude::*, traits::{Currency, InstanceFilter, ReservableCurrency}, }; +use frame_system::pallet_prelude::BlockNumberFor as SystemBlockNumberFor; pub use pallet::*; use subtensor_macros::freeze_struct; pub use weights::WeightInfo; @@ -752,6 +753,14 @@ pub mod pallet { InvalidDerivedAccountId, } + #[pallet::hooks] + impl Hooks> for Pallet { + fn on_finalize(_n: SystemBlockNumberFor) { + // clear this map on end of each block + let _ = LastCallResult::::clear(u32::MAX, None); + } + } + /// The set of account proxies. Maps the account which has delegated to the accounts /// which are being delegated to, together with the amount held on deposit. #[pallet::storage] @@ -782,6 +791,11 @@ pub mod pallet { ValueQuery, >; + /// The result of the last call made by the proxy (key). + #[pallet::storage] + pub type LastCallResult = + StorageMap<_, Twox64Concat, T::AccountId, DispatchResult, OptionQuery>; + #[pallet::view_functions] impl Pallet { /// Check if a `RuntimeCall` is allowed for a given `ProxyType`. @@ -1028,7 +1042,7 @@ impl Pallet { ) { use frame::traits::{InstanceFilter as _, OriginTrait as _}; // This is a freshly authenticated new account, the origin restrictions doesn't apply. - let mut origin: T::RuntimeOrigin = frame_system::RawOrigin::Signed(real).into(); + let mut origin: T::RuntimeOrigin = frame_system::RawOrigin::Signed(real.clone()).into(); origin.add_filter(move |c: &::RuntimeCall| { let c = ::RuntimeCall::from_ref(c); // We make sure the proxy call does access this pallet to change modify proxies. @@ -1052,6 +1066,9 @@ impl Pallet { } }); let e = call.dispatch(origin); + + LastCallResult::::insert(real, e.map(|_| ()).map_err(|e| e.error)); + Self::deposit_event(Event::ProxyExecuted { result: e.map(|_| ()).map_err(|e| e.error), }); diff --git a/pallets/shield/Cargo.toml b/pallets/shield/Cargo.toml new file mode 100644 index 0000000000..1a0d9ef1f5 --- /dev/null +++ b/pallets/shield/Cargo.toml @@ -0,0 +1,73 @@ +[package] +name = "pallet-shield" +description = "FRAME pallet for opt-in, per-block ephemeral-key encrypted transactions, MEV-shielded." +authors = ["Subtensor Contributors "] +version = "0.0.1" +license = "Unlicense" +edition.workspace = true +homepage = "https://github.com/opentensor/subtensor" +repository = "https://github.com/opentensor/subtensor" +publish = false + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[dependencies] +codec = { workspace = true, features = ["derive", "max-encoded-len"] } +scale-info = { workspace = true, features = ["derive"] } + +subtensor-macros.workspace = true + +# FRAME core +frame-support.workspace = true +frame-system.workspace = true +frame-benchmarking = { workspace = true, optional = true } + +# Substrate primitives +sp-core.workspace = true +sp-runtime.workspace = true +sp-io.workspace = true +sp-std.workspace = true +sp-weights.workspace = true + +# Pallets used in Config +pallet-timestamp.workspace = true +pallet-aura.workspace = true +sp-consensus-aura.workspace = true + +[dev-dependencies] + +[features] +default = ["std"] + +std = [ + "codec/std", + "scale-info/std", + "frame-support/std", + "frame-system/std", + "frame-benchmarking?/std", + "sp-core/std", + "sp-runtime/std", + "sp-io/std", + "sp-std/std", + "sp-weights/std", + "pallet-timestamp/std", + "pallet-aura/std", + "sp-consensus-aura/std", +] + +runtime-benchmarks = [ + "frame-benchmarking/runtime-benchmarks", + "frame-support/runtime-benchmarks", + "frame-system/runtime-benchmarks", + "sp-runtime/runtime-benchmarks", + "pallet-timestamp/runtime-benchmarks", +] + +try-runtime = [ + "frame-support/try-runtime", + "frame-system/try-runtime", + "sp-runtime/try-runtime", + "pallet-aura/try-runtime", + "pallet-timestamp/try-runtime", +] diff --git a/pallets/shield/src/benchmarking.rs b/pallets/shield/src/benchmarking.rs new file mode 100644 index 0000000000..a88061287e --- /dev/null +++ b/pallets/shield/src/benchmarking.rs @@ -0,0 +1,144 @@ +use super::*; + +use frame_benchmarking::v2::*; +use frame_support::{BoundedVec, pallet_prelude::ConstU32}; +use frame_system::{RawOrigin, pallet_prelude::BlockNumberFor}; +use sp_core::{crypto::KeyTypeId, sr25519}; +use sp_io::crypto::sr25519_generate; +use sp_runtime::{AccountId32, traits::Hash as HashT}; +use sp_std::vec; + +/// Helper to build bounded bytes (public key) of a given length. +fn bounded_pk(len: usize) -> BoundedVec> { + let v = vec![7u8; len]; + BoundedVec::>::try_from(v).expect("within bound; qed") +} + +/// Helper to build bounded bytes (ciphertext) of a given length. +fn bounded_ct(len: usize) -> BoundedVec> { + let v = vec![0u8; len]; + BoundedVec::>::try_from(v).expect("within bound; qed") +} + +/// Seed Aura authorities so `EnsureAuraAuthority` passes for a given sr25519 pubkey. +/// +/// We avoid requiring `ByteArray` on `AuthorityId` by relying on: +/// `::AuthorityId: From`. +fn seed_aura_authority_from_sr25519(pubkey: &sr25519::Public) +where + T: pallet::Config + pallet_aura::Config, + ::AuthorityId: From, +{ + let auth_id: ::AuthorityId = (*pubkey).into(); + pallet_aura::Authorities::::mutate(|auths| { + let _ = auths.try_push(auth_id); + }); +} + +#[benchmarks( + where + // Needed to build a concrete inner call and convert into T::RuntimeCall. + ::RuntimeCall: From>, + // Needed so we can seed Authorities from a dev sr25519 pubkey. + ::AuthorityId: From, +)] +mod benches { + use super::*; + + /// Benchmark `announce_next_key`. + #[benchmark] + fn announce_next_key() { + // Generate a deterministic dev key in the host keystore (for benchmarks). + // Any 4-byte KeyTypeId works for generation; it does not affect AccountId derivation. + const KT: KeyTypeId = KeyTypeId(*b"benc"); + let alice_pub: sr25519::Public = sr25519_generate(KT, Some("//Alice".as_bytes().to_vec())); + let alice_acc: AccountId32 = alice_pub.into(); + + // Make this account an Aura authority for the generic runtime. + seed_aura_authority_from_sr25519::(&alice_pub); + + // Valid Kyber768 public key length per pallet check. + const KYBER768_PK_LEN: usize = 1184; + let public_key: BoundedVec> = bounded_pk::<2048>(KYBER768_PK_LEN); + + // Measure: dispatch the extrinsic. + #[extrinsic_call] + announce_next_key(RawOrigin::Signed(alice_acc.clone()), public_key.clone()); + + // Assert: NextKey should be set exactly. + let stored = NextKey::::get().expect("must be set by announce_next_key"); + assert_eq!(stored, public_key); + } + + /// Benchmark `submit_encrypted`. + #[benchmark] + fn submit_encrypted() { + // Any whitelisted caller is fine (no authority requirement). + let who: T::AccountId = whitelisted_caller(); + + // Dummy commitment and ciphertext (bounded to 8192). + let commitment: T::Hash = ::Hashing::hash(b"bench-commitment"); + const CT_DEFAULT_LEN: usize = 256; + let ciphertext: BoundedVec> = super::bounded_ct::<8192>(CT_DEFAULT_LEN); + + // Pre-compute expected id to assert postconditions. + let id: T::Hash = + ::Hashing::hash_of(&(who.clone(), commitment, &ciphertext)); + + // Measure: dispatch the extrinsic. + #[extrinsic_call] + submit_encrypted( + RawOrigin::Signed(who.clone()), + commitment, + ciphertext.clone(), + ); + + // Assert: stored under expected id. + let got = Submissions::::get(id).expect("submission must exist"); + assert_eq!(got.author, who); + assert_eq!( + got.commitment, + ::Hashing::hash(b"bench-commitment") + ); + assert_eq!(got.ciphertext.as_slice(), ciphertext.as_slice()); + } + + /// Benchmark `mark_decryption_failed`. + #[benchmark] + fn mark_decryption_failed() { + // Any account can be the author of the submission. + let who: T::AccountId = whitelisted_caller(); + let submitted_in: BlockNumberFor = frame_system::Pallet::::block_number(); + + // Build a dummy commitment and ciphertext. + let commitment: T::Hash = + ::Hashing::hash(b"bench-mark-decryption-failed"); + const CT_DEFAULT_LEN: usize = 32; + let ciphertext: BoundedVec> = + BoundedVec::truncate_from(vec![0u8; CT_DEFAULT_LEN]); + + // Compute the submission id exactly like `submit_encrypted` does. + let id: T::Hash = + ::Hashing::hash_of(&(who.clone(), commitment, &ciphertext)); + + // Seed Submissions with an entry for this id. + let sub = Submission::, ::Hash> { + author: who, + commitment, + ciphertext: ciphertext.clone(), + submitted_in, + }; + Submissions::::insert(id, sub); + + // Reason for failure. + let reason: BoundedVec> = + BoundedVec::truncate_from(b"benchmark-decryption-failed".to_vec()); + + // Measure: dispatch the unsigned extrinsic. + #[extrinsic_call] + mark_decryption_failed(RawOrigin::None, id, reason); + + // Assert: submission is removed. + assert!(Submissions::::get(id).is_none()); + } +} diff --git a/pallets/shield/src/lib.rs b/pallets/shield/src/lib.rs new file mode 100644 index 0000000000..22cf3240a1 --- /dev/null +++ b/pallets/shield/src/lib.rs @@ -0,0 +1,476 @@ +// pallets/mev-shield/src/lib.rs +#![cfg_attr(not(feature = "std"), no_std)] + +pub use pallet::*; +#[cfg(feature = "runtime-benchmarks")] +mod benchmarking; + +#[cfg(test)] +pub mod mock; + +#[cfg(test)] +mod tests; + +#[frame_support::pallet] +pub mod pallet { + use super::*; + use codec::Encode; + use frame_support::{ + dispatch::{DispatchInfo, GetDispatchInfo, PostDispatchInfo}, + pallet_prelude::*, + traits::ConstU32, + traits::IsSubType, + weights::Weight, + }; + use frame_system::pallet_prelude::*; + use sp_consensus_aura::sr25519::AuthorityId as AuraAuthorityId; + use sp_core::ByteArray; + use sp_runtime::{ + AccountId32, DispatchErrorWithPostInfo, RuntimeDebug, Saturating, + traits::{ + BadOrigin, DispatchInfoOf, DispatchOriginOf, Dispatchable, Hash, Implication, + TransactionExtension, + }, + transaction_validity::{InvalidTransaction, TransactionSource, ValidTransaction}, + }; + use sp_std::{marker::PhantomData, prelude::*}; + use subtensor_macros::freeze_struct; + + /// Origin helper: ensure the signer is an Aura authority (no session/authorship). + pub struct EnsureAuraAuthority(PhantomData); + + pub trait AuthorityOriginExt { + type AccountId; + + fn ensure_validator(origin: Origin) -> Result; + } + + impl AuthorityOriginExt> for EnsureAuraAuthority + where + T: frame_system::Config + + pallet_aura::Config, + { + type AccountId = AccountId32; + + fn ensure_validator(origin: OriginFor) -> Result { + let who: AccountId32 = frame_system::ensure_signed(origin)?; + + let aura_id = + ::from_slice(who.as_ref()).map_err(|_| BadOrigin)?; + + let is_validator = pallet_aura::Authorities::::get() + .into_iter() + .any(|id| id == aura_id); + + if is_validator { + Ok(who) + } else { + Err(BadOrigin) + } + } + } + + // ----------------- Types ----------------- + + /// AEAD‑independent commitment over the revealed payload. + #[freeze_struct("66e393c88124f360")] + #[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo, MaxEncodedLen)] + pub struct Submission { + pub author: AccountId, + pub commitment: Hash, + pub ciphertext: BoundedVec>, + pub submitted_in: BlockNumber, + } + + // ----------------- Config ----------------- + + #[pallet::config] + pub trait Config: + frame_system::Config>> + + pallet_timestamp::Config + + pallet_aura::Config + { + type RuntimeCall: Parameter + + sp_runtime::traits::Dispatchable< + RuntimeOrigin = Self::RuntimeOrigin, + PostInfo = PostDispatchInfo, + > + GetDispatchInfo; + + type AuthorityOrigin: AuthorityOriginExt; + } + + #[pallet::pallet] + pub struct Pallet(_); + + // ----------------- Storage ----------------- + + /// Current ML‑KEM‑768 public key bytes (encoded form). + #[pallet::storage] + pub type CurrentKey = StorageValue<_, BoundedVec>, OptionQuery>; + + /// Next ML‑KEM‑768 public key bytes, announced by the block author. + #[pallet::storage] + pub type NextKey = StorageValue<_, BoundedVec>, OptionQuery>; + + /// Buffered encrypted submissions, indexed by wrapper id. + #[pallet::storage] + pub type Submissions = StorageMap< + _, + Blake2_128Concat, + T::Hash, + Submission, T::Hash>, + OptionQuery, + >; + + /// Hash(CurrentKey) per block, used to bind `key_hash` to the epoch at submit time. + #[pallet::storage] + pub type KeyHashByBlock = + StorageMap<_, Blake2_128Concat, BlockNumberFor, T::Hash, OptionQuery>; + + /// How many recent blocks of key-epoch hashes we retain. + const KEY_EPOCH_HISTORY: u32 = 100; + + // ----------------- Events & Errors ----------------- + + #[pallet::event] + #[pallet::generate_deposit(pub(super) fn deposit_event)] + pub enum Event { + /// Encrypted wrapper accepted. + EncryptedSubmitted { id: T::Hash, who: T::AccountId }, + /// Decrypted call executed. + DecryptedExecuted { id: T::Hash, signer: T::AccountId }, + /// Decrypted execution rejected. + DecryptedRejected { + id: T::Hash, + reason: DispatchErrorWithPostInfo, + }, + /// Decryption failed - validator could not decrypt the submission. + DecryptionFailed { + id: T::Hash, + reason: BoundedVec>, + }, + } + + #[pallet::error] + pub enum Error { + /// A submission with the same id already exists in `Submissions`. + SubmissionAlreadyExists, + /// The referenced submission id does not exist in `Submissions`. + MissingSubmission, + /// The recomputed commitment does not match the stored commitment. + CommitmentMismatch, + /// The provided signature over the payload is invalid. + SignatureInvalid, + /// The announced ML‑KEM public key length is invalid. + BadPublicKeyLen, + /// The MEV‑Shield key epoch for this submission has expired and is no longer accepted. + KeyExpired, + /// The provided `key_hash` does not match the expected epoch key hash. + KeyHashMismatch, + } + + // ----------------- Hooks ----------------- + + #[pallet::hooks] + impl Hooks> for Pallet { + fn on_initialize(n: BlockNumberFor) -> Weight { + let db_weight = T::DbWeight::get(); + let mut reads: u64 = 0; + let mut writes: u64 = 0; + + // 1) Roll NextKey -> CurrentKey if a next key is present. + reads = reads.saturating_add(1); + writes = writes.saturating_add(1); + let mut current_opt: Option>> = + if let Some(next) = NextKey::::take() { + CurrentKey::::put(&next); + writes = writes.saturating_add(1); + Some(next) + } else { + None + }; + + // 2) If we didn't roll, read the existing CurrentKey exactly once. + if current_opt.is_none() { + reads = reads.saturating_add(1); + current_opt = CurrentKey::::get(); + } + + // 3) Maintain KeyHashByBlock entry for this block: + match current_opt { + Some(current) => { + let epoch_hash: T::Hash = T::Hashing::hash(current.as_ref()); + KeyHashByBlock::::insert(n, epoch_hash); + writes = writes.saturating_add(1); + } + None => { + KeyHashByBlock::::remove(n); + writes = writes.saturating_add(1); + } + } + + // 4) Prune old epoch hashes with a sliding window of size KEY_EPOCH_HISTORY. + let depth: BlockNumberFor = KEY_EPOCH_HISTORY.into(); + if n >= depth { + let prune_bn = n.saturating_sub(depth); + KeyHashByBlock::::remove(prune_bn); + writes = writes.saturating_add(1); + } + + // 5) TTL-based pruning of stale submissions. + let ttl: BlockNumberFor = KEY_EPOCH_HISTORY.into(); + let threshold: BlockNumberFor = n.saturating_sub(ttl); + + let mut to_remove: Vec = Vec::new(); + + for (id, sub) in Submissions::::iter() { + reads = reads.saturating_add(1); + if sub.submitted_in < threshold { + to_remove.push(id); + } + } + + for id in to_remove { + Submissions::::remove(id); + writes = writes.saturating_add(1); + } + + db_weight.reads_writes(reads, writes) + } + } + + // ----------------- Calls ----------------- + + #[pallet::call] + impl Pallet { + /// Announce the ML‑KEM public key that will become `CurrentKey` in + /// the following block. + #[pallet::call_index(0)] + #[pallet::weight(( + Weight::from_parts(9_979_000, 0) + .saturating_add(T::DbWeight::get().reads(1_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)), + DispatchClass::Operational, + Pays::Yes + ))] + #[allow(clippy::useless_conversion)] + pub fn announce_next_key( + origin: OriginFor, + public_key: BoundedVec>, + ) -> DispatchResultWithPostInfo { + // Only a current Aura validator may call this (signed account ∈ Aura authorities) + T::AuthorityOrigin::ensure_validator(origin)?; + + const MAX_KYBER768_PK_LENGTH: usize = 1184; + ensure!( + public_key.len() == MAX_KYBER768_PK_LENGTH, + Error::::BadPublicKeyLen + ); + + NextKey::::put(public_key); + + // Refund the fee on success by setting pays_fee = Pays::No + Ok(PostDispatchInfo { + actual_weight: None, + pays_fee: Pays::No, + }) + } + + /// Users submit an encrypted wrapper. + /// + /// Client‑side: + /// + /// 1. Read `NextKey` (ML‑KEM public key bytes) from storage. + /// 2. Sign your extrinsic so that it can be executed when added to the pool, + /// i.e. you may need to increment the nonce if you submit using the same account. + /// 3. `commitment = Hashing::hash(signed_extrinsic)`. + /// 4. Encrypt: + /// + /// plaintext = signed_extrinsic + /// + /// with ML‑KEM‑768 + XChaCha20‑Poly1305, producing + /// + /// ciphertext = [u16 kem_len] || kem_ct || nonce24 || aead_ct + /// + #[pallet::call_index(1)] + #[pallet::weight(( + Weight::from_parts(13_980_000, 0) + .saturating_add(T::DbWeight::get().reads(1_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)), + DispatchClass::Normal, + Pays::Yes, + ))] + pub fn submit_encrypted( + origin: OriginFor, + commitment: T::Hash, + ciphertext: BoundedVec>, + ) -> DispatchResult { + let who = ensure_signed(origin)?; + + let id: T::Hash = T::Hashing::hash_of(&(who.clone(), commitment, &ciphertext)); + let sub = Submission::, T::Hash> { + author: who.clone(), + commitment, + ciphertext, + submitted_in: >::block_number(), + }; + ensure!( + !Submissions::::contains_key(id), + Error::::SubmissionAlreadyExists + ); + Submissions::::insert(id, sub); + Self::deposit_event(Event::EncryptedSubmitted { id, who }); + Ok(()) + } + + /// Marks a submission as failed to decrypt and removes it from storage. + /// + /// Called by the block author when decryption fails at any stage (e.g., ML-KEM decapsulate + /// failed, AEAD decrypt failed, invalid ciphertext format, etc.). This allows clients to be + /// notified of decryption failures through on-chain events. + /// + /// # Arguments + /// + /// * `id` - The wrapper id (hash of (author, commitment, ciphertext)) + /// * `reason` - Human-readable reason for the decryption failure (e.g., "ML-KEM decapsulate failed") + #[pallet::call_index(3)] + #[pallet::weight(( + Weight::from_parts(13_260_000, 0) + .saturating_add(T::DbWeight::get().reads(1_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)), + DispatchClass::Normal, + Pays::No + ))] + pub fn mark_decryption_failed( + origin: OriginFor, + id: T::Hash, + reason: BoundedVec>, + ) -> DispatchResult { + // Unsigned: only the author node may inject this via ValidateUnsigned. + ensure_none(origin)?; + + // Load and consume the submission. + let Some(_sub) = Submissions::::take(id) else { + return Err(Error::::MissingSubmission.into()); + }; + + // Emit event to notify clients + Self::deposit_event(Event::DecryptionFailed { id, reason }); + + Ok(()) + } + } + + #[pallet::validate_unsigned] + impl ValidateUnsigned for Pallet { + type Call = Call; + + fn validate_unsigned(source: TransactionSource, call: &Self::Call) -> TransactionValidity { + match call { + Call::mark_decryption_failed { id, .. } => { + match source { + TransactionSource::Local | TransactionSource::InBlock => { + ValidTransaction::with_tag_prefix("mev-shield-failed") + .priority(1u64) + .longevity(64) // long because propagate(false) + .and_provides(id) // dedupe by wrapper id + .propagate(false) // CRITICAL: no gossip, stays on author node + .build() + } + _ => InvalidTransaction::Call.into(), + } + } + _ => InvalidTransaction::Call.into(), + } + } + } + + #[freeze_struct("51f74eb54f5ab1fe")] + #[derive(Default, Encode, Decode, DecodeWithMemTracking, Clone, Eq, PartialEq, TypeInfo)] + pub struct MevShieldDecryptionFilter(pub PhantomData); + + impl sp_std::fmt::Debug for MevShieldDecryptionFilter { + fn fmt(&self, f: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { + write!(f, "MevShieldDecryptionFilter") + } + } + + impl MevShieldDecryptionFilter { + pub fn new() -> Self { + Self(PhantomData) + } + + #[inline] + fn mev_failed_priority() -> TransactionPriority { + 1u64 + } + } + + impl TransactionExtension> + for MevShieldDecryptionFilter + where + ::RuntimeCall: + Dispatchable, + ::RuntimeCall: IsSubType>, + { + const IDENTIFIER: &'static str = "MevShieldDecryptionFilter"; + + type Implicit = (); + type Val = (); + type Pre = (); + + fn weight(&self, _call: &RuntimeCallFor) -> Weight { + // Only does light pattern matching; treat as free. + Weight::zero() + } + + fn validate( + &self, + origin: DispatchOriginOf>, + call: &RuntimeCallFor, + _info: &DispatchInfoOf>, + _len: usize, + _self_implicit: Self::Implicit, + _inherited_implication: &impl Implication, + source: TransactionSource, + ) -> ValidateResult> { + match call.is_sub_type() { + Some(Call::mark_decryption_failed { id, .. }) => { + match source { + TransactionSource::Local | TransactionSource::InBlock => { + let validity_res = + ValidTransaction::with_tag_prefix("mev-shield-failed") + .priority(Self::mev_failed_priority()) + .longevity(64) + .and_provides(id) + .propagate(false) + .build(); + + match validity_res { + Ok(validity) => Ok((validity, (), origin)), + Err(e) => Err(e), + } + } + + // Anything coming from the outside world (including *signed* + // transactions) is rejected at the pool boundary. + _ => Err(InvalidTransaction::Call.into()), + } + } + + _ => Ok((Default::default(), (), origin)), + } + } + + fn prepare( + self, + _val: Self::Val, + _origin: &DispatchOriginOf>, + _call: &RuntimeCallFor, + _info: &DispatchInfoOf>, + _len: usize, + ) -> Result { + Ok(()) + } + } +} diff --git a/pallets/shield/src/mock.rs b/pallets/shield/src/mock.rs new file mode 100644 index 0000000000..0732670406 --- /dev/null +++ b/pallets/shield/src/mock.rs @@ -0,0 +1,145 @@ +use crate as pallet_mev_shield; + +use frame_support::{construct_runtime, derive_impl, parameter_types, traits::Everything}; +use frame_system as system; + +use sp_consensus_aura::sr25519::AuthorityId as AuraId; +use sp_core::{ConstU32, H256}; +use sp_runtime::traits::BadOrigin; +use sp_runtime::{ + AccountId32, BuildStorage, + traits::{BlakeTwo256, IdentityLookup}, +}; + +// ----------------------------------------------------------------------------- +// Mock runtime +// ----------------------------------------------------------------------------- + +pub type UncheckedExtrinsic = system::mocking::MockUncheckedExtrinsic; +pub type Block = system::mocking::MockBlock; + +construct_runtime!( + pub enum Test { + System: frame_system = 0, + Timestamp: pallet_timestamp = 1, + Aura: pallet_aura = 2, + MevShield: pallet_mev_shield = 3, + } +); + +// A concrete nonce type used in tests. +pub type TestNonce = u64; + +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] +impl system::Config for Test { + // Basic system config + type BaseCallFilter = Everything; + type BlockWeights = (); + type BlockLength = (); + type DbWeight = (); + + type RuntimeOrigin = RuntimeOrigin; + type RuntimeCall = RuntimeCall; + type RuntimeEvent = RuntimeEvent; + + type Nonce = TestNonce; + type Hash = H256; + type Hashing = BlakeTwo256; + + type AccountId = AccountId32; + type Lookup = IdentityLookup; + type Block = Block; + + type BlockHashCount = (); + type Version = (); + type PalletInfo = PalletInfo; + + type AccountData = (); + type OnNewAccount = (); + type OnKilledAccount = (); + type SystemWeightInfo = (); + type SS58Prefix = (); + type OnSetCode = (); + + // Max number of consumer refs per account. + type MaxConsumers = ConstU32<16>; +} + +parameter_types! { + pub const MinimumPeriod: u64 = 1; +} + +impl pallet_timestamp::Config for Test { + type Moment = u64; + type OnTimestampSet = (); + type MinimumPeriod = MinimumPeriod; + type WeightInfo = (); +} + +// Aura mock configuration +parameter_types! { + pub const MaxAuthorities: u32 = 32; + pub const AllowMultipleBlocksPerSlot: bool = false; + pub const SlotDuration: u64 = 6000; +} + +impl pallet_aura::Config for Test { + type AuthorityId = AuraId; + // For tests we don't need dynamic disabling; just use unit type. + type DisabledValidators = (); + type MaxAuthorities = MaxAuthorities; + type AllowMultipleBlocksPerSlot = AllowMultipleBlocksPerSlot; + type SlotDuration = SlotDuration; +} + +// ----------------------------------------------------------------------------- +// Authority origin for tests – root-only +// ----------------------------------------------------------------------------- + +/// For tests, treat Root as the “validator set” and return a dummy AccountId. +pub struct TestAuthorityOrigin; + +impl pallet_mev_shield::AuthorityOriginExt for TestAuthorityOrigin { + type AccountId = AccountId32; + + fn ensure_validator(origin: RuntimeOrigin) -> Result { + // Must be a signed origin. + let who: AccountId32 = frame_system::ensure_signed(origin).map_err(|_| BadOrigin)?; + + // Interpret the AccountId bytes as an AuraId, just like the real pallet. + let aura_id = + ::from_slice(who.as_ref()).map_err(|_| BadOrigin)?; + + // Check membership in the Aura validator set. + let is_validator = pallet_aura::Authorities::::get() + .into_iter() + .any(|id| id == aura_id); + + if is_validator { + Ok(who) + } else { + Err(BadOrigin) + } + } +} + +// ----------------------------------------------------------------------------- +// MevShield Config +// ----------------------------------------------------------------------------- + +impl pallet_mev_shield::Config for Test { + type RuntimeCall = RuntimeCall; + type AuthorityOrigin = TestAuthorityOrigin; +} + +// ----------------------------------------------------------------------------- +// new_test_ext +// ----------------------------------------------------------------------------- + +pub fn new_test_ext() -> sp_io::TestExternalities { + // Use the construct_runtime!-generated genesis config. + RuntimeGenesisConfig::default() + .build_storage() + .expect("RuntimeGenesisConfig builds valid default genesis storage") + .into() +} diff --git a/pallets/shield/src/tests.rs b/pallets/shield/src/tests.rs new file mode 100644 index 0000000000..18eda7eacc --- /dev/null +++ b/pallets/shield/src/tests.rs @@ -0,0 +1,443 @@ +use crate as pallet_mev_shield; +use crate::mock::*; + +use frame_support::{ + BoundedVec, assert_noop, assert_ok, + traits::{ConstU32 as FrameConstU32, Hooks}, +}; +use frame_system::pallet_prelude::BlockNumberFor; +use pallet_mev_shield::{ + Call as MevShieldCall, CurrentKey, Event as MevShieldEvent, KeyHashByBlock, NextKey, + Submissions, +}; +use sp_core::{Pair, sr25519}; +use sp_runtime::{ + AccountId32, + traits::{Hash, SaturatedConversion}, +}; + +// Type aliases for convenience in tests. +type TestHash = ::Hash; +type TestBlockNumber = BlockNumberFor; + +// ----------------------------------------------------------------------------- +// Helpers +// ----------------------------------------------------------------------------- + +/// Deterministic sr25519 pair for tests (acts as "Alice"). +fn test_sr25519_pair() -> sr25519::Pair { + sr25519::Pair::from_seed(&[1u8; 32]) +} + +// ----------------------------------------------------------------------------- +// Tests +// ----------------------------------------------------------------------------- + +#[test] +fn authority_can_announce_next_key_and_on_initialize_rolls_it_and_records_epoch_hash() { + new_test_ext().execute_with(|| { + const KYBER_PK_LEN: usize = 1184; + let pk_bytes = vec![7u8; KYBER_PK_LEN]; + let bounded_pk: BoundedVec> = + BoundedVec::truncate_from(pk_bytes.clone()); + + // Seed Aura authorities with a single validator and derive the matching account. + let validator_pair = test_sr25519_pair(); + let validator_account: AccountId32 = validator_pair.public().into(); + let validator_aura_id: ::AuthorityId = + validator_pair.public().into(); + + // Authorities storage expects a BoundedVec. + let authorities: BoundedVec< + ::AuthorityId, + ::MaxAuthorities, + > = BoundedVec::truncate_from(vec![validator_aura_id.clone()]); + pallet_aura::Authorities::::put(authorities); + + assert!(CurrentKey::::get().is_none()); + assert!(NextKey::::get().is_none()); + + // Signed by an Aura validator -> passes TestAuthorityOrigin::ensure_validator. + assert_ok!(MevShield::announce_next_key( + RuntimeOrigin::signed(validator_account.clone()), + bounded_pk.clone(), + )); + + // NextKey storage updated + let next = NextKey::::get().expect("NextKey should be set"); + assert_eq!(next, pk_bytes); + + // Simulate beginning of block #2. + let block_two: TestBlockNumber = 2u64.saturated_into(); + MevShield::on_initialize(block_two); + + // CurrentKey should now equal the previously announced NextKey. + let curr = CurrentKey::::get().expect("CurrentKey should be set"); + assert_eq!(curr, pk_bytes); + + // And NextKey cleared. + assert!(NextKey::::get().is_none()); + + // Key hash for this block should be recorded and equal hash(CurrentKey_bytes). + let expected_hash: TestHash = ::Hashing::hash(curr.as_ref()); + let recorded = + KeyHashByBlock::::get(block_two).expect("epoch key hash must be recorded"); + assert_eq!(recorded, expected_hash); + }); +} + +#[test] +fn announce_next_key_rejects_non_validator_origins() { + new_test_ext().execute_with(|| { + const KYBER_PK_LEN: usize = 1184; + + // Validator account: bytes match the Aura authority we put into storage. + let validator_pair = test_sr25519_pair(); + let validator_account: AccountId32 = validator_pair.public().into(); + let validator_aura_id: ::AuthorityId = + validator_pair.public().into(); + + // Non‑validator is some other key (not in Aura::Authorities). + let non_validator_pair = sr25519::Pair::from_seed(&[2u8; 32]); + let non_validator: AccountId32 = non_validator_pair.public().into(); + + // Only the validator is in the Aura validator set. + let authorities: BoundedVec< + ::AuthorityId, + ::MaxAuthorities, + > = BoundedVec::truncate_from(vec![validator_aura_id.clone()]); + pallet_aura::Authorities::::put(authorities); + + let pk_bytes = vec![9u8; KYBER_PK_LEN]; + let bounded_pk: BoundedVec> = + BoundedVec::truncate_from(pk_bytes.clone()); + + // 1) Signed non‑validator origin must fail with BadOrigin. + assert_noop!( + MevShield::announce_next_key( + RuntimeOrigin::signed(non_validator.clone()), + bounded_pk.clone(), + ), + sp_runtime::DispatchError::BadOrigin + ); + + // 2) Unsigned origin must also fail with BadOrigin. + assert_noop!( + MevShield::announce_next_key(RuntimeOrigin::none(), bounded_pk.clone(),), + sp_runtime::DispatchError::BadOrigin + ); + + // 3) Signed validator origin succeeds (sanity check). + assert_ok!(MevShield::announce_next_key( + RuntimeOrigin::signed(validator_account.clone()), + bounded_pk.clone(), + )); + + let next = NextKey::::get().expect("NextKey must be set by validator"); + assert_eq!(next, pk_bytes); + }); +} + +#[test] +fn submit_encrypted_stores_submission_and_emits_event() { + new_test_ext().execute_with(|| { + let pair = test_sr25519_pair(); + let who: AccountId32 = pair.public().into(); + + System::set_block_number(10); + + let commitment = + ::Hashing::hash(b"test-mevshield-commitment"); + let ciphertext_bytes = vec![1u8, 2, 3, 4]; + let ciphertext: BoundedVec> = + BoundedVec::truncate_from(ciphertext_bytes.clone()); + + assert_ok!(MevShield::submit_encrypted( + RuntimeOrigin::signed(who.clone()), + commitment, + ciphertext.clone(), + )); + + let id = ::Hashing::hash_of(&( + who.clone(), + commitment, + &ciphertext, + )); + + let stored = Submissions::::get(id).expect("submission stored"); + assert_eq!(stored.author, who); + assert_eq!(stored.commitment, commitment); + assert_eq!(stored.ciphertext.to_vec(), ciphertext_bytes); + assert_eq!(stored.submitted_in, 10); + + let events = System::events(); + let last = events.last().expect("at least one event").event.clone(); + + assert!( + matches!( + last, + RuntimeEvent::MevShield( + MevShieldEvent::::EncryptedSubmitted { id: ev_id, who: ev_who } + ) + if ev_id == id && ev_who == who + ), + "expected EncryptedSubmitted event with correct id & who", + ); + }); +} + +#[test] +fn key_hash_by_block_prunes_old_entries() { + new_test_ext().execute_with(|| { + // This must match the constant configured in the pallet. + const KEEP: u64 = 100; + const TOTAL: u64 = KEEP + 5; + + // For each block n, set a CurrentKey and call on_initialize(n), + // which will record KeyHashByBlock[n] and prune old entries. + for n in 1..=TOTAL { + let key_bytes = vec![n as u8; 32]; + let bounded: BoundedVec> = + BoundedVec::truncate_from(key_bytes.clone()); + + CurrentKey::::put(bounded.clone()); + + let bn: TestBlockNumber = n.saturated_into(); + MevShield::on_initialize(bn); + } + + // The oldest block that should still be kept after TOTAL blocks. + let oldest_kept: u64 = if TOTAL > KEEP { TOTAL - KEEP + 1 } else { 1 }; + + // Blocks strictly before oldest_kept must be pruned. + for old in 0..oldest_kept { + let bn: TestBlockNumber = old.saturated_into(); + assert!( + KeyHashByBlock::::get(bn).is_none(), + "block {bn:?} should have been pruned" + ); + } + + // Blocks from oldest_kept..=TOTAL must still have entries. + for recent in oldest_kept..=TOTAL { + let bn: TestBlockNumber = recent.saturated_into(); + assert!( + KeyHashByBlock::::get(bn).is_some(), + "block {bn:?} should be retained" + ); + } + + // Additionally, assert we never exceed the configured cap. + let mut count: u64 = 0; + for bn in 0..=TOTAL { + let bn_t: TestBlockNumber = bn.saturated_into(); + if KeyHashByBlock::::get(bn_t).is_some() { + count += 1; + } + } + let expected = KEEP.min(TOTAL); + assert_eq!( + count, expected, + "expected at most {expected} entries in KeyHashByBlock after pruning, got {count}" + ); + }); +} + +#[test] +fn submissions_pruned_after_ttl_window() { + new_test_ext().execute_with(|| { + // This must match KEY_EPOCH_HISTORY in the pallet. + const KEEP: u64 = 100; + const TOTAL: u64 = KEEP + 5; + + let pair = test_sr25519_pair(); + let who: AccountId32 = pair.public().into(); + + // Helper: create a submission at a specific block with a tagged commitment. + let make_submission = |block: u64, tag: &[u8]| -> TestHash { + System::set_block_number(block); + let commitment: TestHash = ::Hashing::hash(tag); + let ciphertext_bytes = vec![block as u8; 4]; + let ciphertext: BoundedVec> = + BoundedVec::truncate_from(ciphertext_bytes); + + assert_ok!(MevShield::submit_encrypted( + RuntimeOrigin::signed(who.clone()), + commitment, + ciphertext.clone(), + )); + + ::Hashing::hash_of(&( + who.clone(), + commitment, + &ciphertext, + )) + }; + + // With n = TOTAL and depth = KEEP, prune_before = n - KEEP = 5. + let stale_block1: u64 = 1; // < 5, should be pruned + let stale_block2: u64 = 4; // < 5, should be pruned + let keep_block1: u64 = 5; // == prune_before, should be kept + let keep_block2: u64 = TOTAL; // latest, should be kept + + let id_stale1 = make_submission(stale_block1, b"stale-1"); + let id_stale2 = make_submission(stale_block2, b"stale-2"); + let id_keep1 = make_submission(keep_block1, b"keep-1"); + let id_keep2 = make_submission(keep_block2, b"keep-2"); + + // Sanity: all are present before pruning. + assert!(Submissions::::get(id_stale1).is_some()); + assert!(Submissions::::get(id_stale2).is_some()); + assert!(Submissions::::get(id_keep1).is_some()); + assert!(Submissions::::get(id_keep2).is_some()); + + // Run on_initialize at block TOTAL, triggering TTL pruning over Submissions. + let n_final: TestBlockNumber = TOTAL.saturated_into(); + MevShield::on_initialize(n_final); + + // Submissions with submitted_in < prune_before (5) should be gone. + assert!(Submissions::::get(id_stale1).is_none()); + assert!(Submissions::::get(id_stale2).is_none()); + + // Submissions at or after prune_before should remain. + assert!(Submissions::::get(id_keep1).is_some()); + assert!(Submissions::::get(id_keep2).is_some()); + }); +} + +#[test] +fn mark_decryption_failed_removes_submission_and_emits_event() { + new_test_ext().execute_with(|| { + System::set_block_number(42); + let pair = test_sr25519_pair(); + let who: AccountId32 = pair.public().into(); + + let commitment: TestHash = + ::Hashing::hash(b"failed-decryption-commitment"); + let ciphertext_bytes = vec![5u8; 8]; + let ciphertext: BoundedVec> = + BoundedVec::truncate_from(ciphertext_bytes.clone()); + + assert_ok!(MevShield::submit_encrypted( + RuntimeOrigin::signed(who.clone()), + commitment, + ciphertext.clone(), + )); + + let id: TestHash = ::Hashing::hash_of(&( + who.clone(), + commitment, + &ciphertext, + )); + + // Sanity: submission exists. + assert!(Submissions::::get(id).is_some()); + + // Reason we will pass into mark_decryption_failed. + let reason_bytes = b"AEAD decrypt failed".to_vec(); + let reason: BoundedVec> = + BoundedVec::truncate_from(reason_bytes.clone()); + + // Call mark_decryption_failed as unsigned (RuntimeOrigin::none()). + assert_ok!(MevShield::mark_decryption_failed( + RuntimeOrigin::none(), + id, + reason.clone(), + )); + + // Submission should be removed. + assert!(Submissions::::get(id).is_none()); + + // Last event should be DecryptionFailed with the correct id and reason. + let events = System::events(); + let last = events + .last() + .expect("an event should be emitted") + .event + .clone(); + + assert!( + matches!( + last, + RuntimeEvent::MevShield( + MevShieldEvent::::DecryptionFailed { id: ev_id, reason: ev_reason } + ) + if ev_id == id && ev_reason.to_vec() == reason_bytes + ), + "expected DecryptionFailed event with correct id & reason" + ); + + // A second call with the same id should now fail with MissingSubmission. + let res = MevShield::mark_decryption_failed(RuntimeOrigin::none(), id, reason); + assert_noop!(res, pallet_mev_shield::Error::::MissingSubmission); + }); +} + +#[test] +fn announce_next_key_charges_then_refunds_fee() { + new_test_ext().execute_with(|| { + const KYBER_PK_LEN: usize = 1184; + + // --------------------------------------------------------------------- + // 1. Seed Aura authorities with a single validator and derive account. + // --------------------------------------------------------------------- + let validator_pair = test_sr25519_pair(); + let validator_account: AccountId32 = validator_pair.public().into(); + let validator_aura_id: ::AuthorityId = + validator_pair.public().into(); + + let authorities: BoundedVec< + ::AuthorityId, + ::MaxAuthorities, + > = BoundedVec::truncate_from(vec![validator_aura_id]); + pallet_aura::Authorities::::put(authorities); + + // --------------------------------------------------------------------- + // 2. Build a valid Kyber public key and the corresponding RuntimeCall. + // --------------------------------------------------------------------- + let pk_bytes = vec![42u8; KYBER_PK_LEN]; + let bounded_pk: BoundedVec> = + BoundedVec::truncate_from(pk_bytes.clone()); + + let runtime_call = RuntimeCall::MevShield(MevShieldCall::::announce_next_key { + public_key: bounded_pk.clone(), + }); + + // --------------------------------------------------------------------- + // 3. Pre-dispatch: DispatchInfo must say Pays::Yes. + // --------------------------------------------------------------------- + let pre_info = ::get_dispatch_info( + &runtime_call, + ); + + assert_eq!( + pre_info.pays_fee, + frame_support::dispatch::Pays::Yes, + "announce_next_key must be declared as fee-paying at pre-dispatch" + ); + + // --------------------------------------------------------------------- + // 4. Dispatch via the pallet function. + // --------------------------------------------------------------------- + let post = MevShield::announce_next_key( + RuntimeOrigin::signed(validator_account.clone()), + bounded_pk.clone(), + ) + .expect("announce_next_key should succeed for an Aura validator"); + + // Post-dispatch info should switch pays_fee from Yes -> No (refund). + assert_eq!( + post.pays_fee, + frame_support::dispatch::Pays::No, + "announce_next_key must refund the previously chargeable fee" + ); + + // And we don't override the actual weight (None => use pre-dispatch weight). + assert!( + post.actual_weight.is_none(), + "announce_next_key should not override actual_weight in PostDispatchInfo" + ); + let next = NextKey::::get().expect("NextKey should be set by announce_next_key"); + assert_eq!(next, pk_bytes); + }); +} diff --git a/pallets/subtensor/Cargo.toml b/pallets/subtensor/Cargo.toml index fdd5e5f9ab..2e35a89d19 100644 --- a/pallets/subtensor/Cargo.toml +++ b/pallets/subtensor/Cargo.toml @@ -59,6 +59,8 @@ pallet-subtensor-proxy.workspace = true [dev-dependencies] pallet-balances = { workspace = true, features = ["std"] } pallet-scheduler.workspace = true +pallet-subtensor-proxy.workspace = true +subtensor-runtime-common.workspace = true pallet-subtensor-swap.workspace = true sp-version.workspace = true # Substrate diff --git a/pallets/subtensor/src/benchmarks.rs b/pallets/subtensor/src/benchmarks.rs index 223c086419..476be905e9 100644 --- a/pallets/subtensor/src/benchmarks.rs +++ b/pallets/subtensor/src/benchmarks.rs @@ -446,15 +446,16 @@ mod pallet_benchmarks { Subtensor::::add_balance_to_coldkey_account(&old_coldkey, free_balance_old.into()); let name: Vec = b"The fourth Coolest Identity".to_vec(); - let identity = ChainIdentity { + let identity = ChainIdentityV2 { name, url: vec![], + github_repo: vec![], image: vec![], discord: vec![], description: vec![], additional: vec![], }; - Identities::::insert(&old_coldkey, identity); + IdentitiesV2::::insert(&old_coldkey, identity); #[extrinsic_call] _( diff --git a/pallets/subtensor/src/coinbase/block_step.rs b/pallets/subtensor/src/coinbase/block_step.rs index 818235a955..21f7866459 100644 --- a/pallets/subtensor/src/coinbase/block_step.rs +++ b/pallets/subtensor/src/coinbase/block_step.rs @@ -18,13 +18,18 @@ impl Pallet { .to_u64(), ); log::debug!("Block emission: {block_emission:?}"); - // --- 3. Run emission through network. + + // --- 3. Reveal matured weights. + Self::reveal_crv3_commits(); + // --- 4. Run emission through network. Self::run_coinbase(block_emission); - // --- 4. Set pending children on the epoch; but only after the coinbase has been run. + // --- 5. Update moving prices AFTER using them for emissions. + Self::update_moving_prices(); + // --- 6. Set pending children on the epoch; but only after the coinbase has been run. Self::try_set_pending_children(block_number); - // --- 5. Run auto-claim root divs. + // --- 7. Run auto-claim root divs. Self::run_auto_claim_root_divs(last_block_hash); - // --- 6. Populate root coldkey maps. + // --- 8. Populate root coldkey maps. Self::populate_root_coldkey_staking_maps(); // Return ok. @@ -261,4 +266,24 @@ impl Pallet { return next_value.saturating_to_num::().into(); } } + + pub fn update_moving_prices() { + let subnets_to_emit_to: Vec = + Self::get_subnets_to_emit_to(&Self::get_all_subnet_netuids()); + // Only update price EMA for subnets that we emit to. + for netuid_i in subnets_to_emit_to.iter() { + // Update moving prices after using them above. + Self::update_moving_price(*netuid_i); + } + } + + pub fn reveal_crv3_commits() { + let netuids: Vec = Self::get_all_subnet_netuids(); + for netuid in netuids.into_iter().filter(|netuid| *netuid != NetUid::ROOT) { + // Reveal matured weights. + if let Err(e) = Self::reveal_crv3_commits_for_subnet(netuid) { + log::warn!("Failed to reveal commits for subnet {netuid} due to error: {e:?}"); + }; + } + } } diff --git a/pallets/subtensor/src/coinbase/reveal_commits.rs b/pallets/subtensor/src/coinbase/reveal_commits.rs index 889c41d96a..6fdafa76da 100644 --- a/pallets/subtensor/src/coinbase/reveal_commits.rs +++ b/pallets/subtensor/src/coinbase/reveal_commits.rs @@ -36,7 +36,7 @@ pub struct LegacyWeightsTlockPayload { impl Pallet { /// The `reveal_crv3_commits` function is run at the very beginning of epoch `n`, - pub fn reveal_crv3_commits(netuid: NetUid) -> dispatch::DispatchResult { + pub fn reveal_crv3_commits_for_subnet(netuid: NetUid) -> dispatch::DispatchResult { let reveal_period = Self::get_reveal_period(netuid); let cur_block = Self::get_current_block_as_u64(); let cur_epoch = Self::get_epoch_index(netuid, cur_block); diff --git a/pallets/subtensor/src/coinbase/root.rs b/pallets/subtensor/src/coinbase/root.rs index 893f855f3e..d508a0162b 100644 --- a/pallets/subtensor/src/coinbase/root.rs +++ b/pallets/subtensor/src/coinbase/root.rs @@ -391,8 +391,6 @@ impl Pallet { let _ = LastHotkeySwapOnNetuid::::clear_prefix(netuid, u32::MAX, None); // --- 20. Identity maps across versions (netuid-scoped). - SubnetIdentities::::remove(netuid); - SubnetIdentitiesV2::::remove(netuid); if SubnetIdentitiesV3::::contains_key(netuid) { SubnetIdentitiesV3::::remove(netuid); Self::deposit_event(Event::SubnetIdentityRemoved(netuid)); diff --git a/pallets/subtensor/src/coinbase/run_coinbase.rs b/pallets/subtensor/src/coinbase/run_coinbase.rs index 45eec7ddec..3b82ec86d5 100644 --- a/pallets/subtensor/src/coinbase/run_coinbase.rs +++ b/pallets/subtensor/src/coinbase/run_coinbase.rs @@ -22,114 +22,66 @@ impl Pallet { pub fn run_coinbase(block_emission: U96F32) { // --- 0. Get current block. let current_block: u64 = Self::get_current_block_as_u64(); - log::debug!("Current block: {current_block:?}"); - - // --- 1. Get all netuids (filter out root) + log::debug!( + "Running coinbase for block {current_block:?} with block emission: {block_emission:?}" + ); + // --- 1. Get all subnets (excluding root). let subnets: Vec = Self::get_all_subnet_netuids() .into_iter() .filter(|netuid| *netuid != NetUid::ROOT) .collect(); - log::debug!("All subnet netuids: {subnets:?}"); + log::debug!("All subnets: {subnets:?}"); + // --- 2. Get subnets to emit to let subnets_to_emit_to: Vec = Self::get_subnets_to_emit_to(&subnets); log::debug!("Subnets to emit to: {subnets_to_emit_to:?}"); - // 2. Get subnets to emit to and emissions + // --- 3. Get emissions for subnets to emit to let subnet_emissions = Self::get_subnet_block_emissions(&subnets_to_emit_to, block_emission); + log::debug!("Subnet emissions: {subnet_emissions:?}"); let root_sell_flag = Self::get_network_root_sell_flag(&subnets_to_emit_to); + log::debug!("Root sell flag: {root_sell_flag:?}"); - // --- 3. Get subnet terms (tao_in, alpha_in, and alpha_out) - // Computation is described in detail in the dtao whitepaper. - let mut tao_in: BTreeMap = BTreeMap::new(); - let mut alpha_in: BTreeMap = BTreeMap::new(); - let mut alpha_out: BTreeMap = BTreeMap::new(); - let mut excess_tao: BTreeMap = BTreeMap::new(); - - // Only calculate for subnets that we are emitting to. - for netuid_i in subnets_to_emit_to.iter() { - // Get subnet price. - let price_i = T::SwapInterface::current_alpha_price((*netuid_i).into()); - log::debug!("price_i: {price_i:?}"); - // Emission is price over total. - let default_tao_in_i: U96F32 = subnet_emissions - .get(netuid_i) - .copied() - .unwrap_or(asfloat!(0)); - log::debug!("default_tao_in_i: {default_tao_in_i:?}"); - let default_alpha_in_i: U96F32 = - default_tao_in_i.safe_div_or(price_i, U96F32::saturating_from_num(0.0)); - log::debug!("default_alpha_in_i: {default_alpha_in_i:?}"); - // Get alpha_emission total - let alpha_emission_i: U96F32 = asfloat!( - Self::get_block_emission_for_issuance(Self::get_alpha_issuance(*netuid_i).into()) - .unwrap_or(0) - ); - log::debug!("alpha_emission_i: {alpha_emission_i:?}"); - - // Get initial alpha_in - let mut alpha_in_i: U96F32; - let mut tao_in_i: U96F32; + // --- 4. Emit to subnets for this block. + Self::emit_to_subnets(&subnets_to_emit_to, &subnet_emissions, root_sell_flag); - if default_alpha_in_i > alpha_emission_i { - alpha_in_i = alpha_emission_i; - tao_in_i = alpha_in_i.saturating_mul(price_i); - let difference_tao: U96F32 = default_tao_in_i.saturating_sub(tao_in_i); - excess_tao.insert(*netuid_i, difference_tao); - } else { - tao_in_i = default_tao_in_i; - alpha_in_i = default_alpha_in_i; - excess_tao.insert(*netuid_i, U96F32::from_num(0.0)); - } - log::debug!("alpha_in_i: {alpha_in_i:?}"); + // --- 5. Drain pending emissions. + let emissions_to_distribute = Self::drain_pending(&subnets, current_block); - // Get alpha_out. - let mut alpha_out_i = alpha_emission_i; - // Only emit TAO if the subnetwork allows registration. - if !Self::get_network_registration_allowed(*netuid_i) - && !Self::get_network_pow_registration_allowed(*netuid_i) - { - tao_in_i = asfloat!(0.0); - alpha_in_i = asfloat!(0.0); - alpha_out_i = asfloat!(0.0); - } - // Insert values into maps - tao_in.insert(*netuid_i, tao_in_i); - alpha_in.insert(*netuid_i, alpha_in_i); - alpha_out.insert(*netuid_i, alpha_out_i); - } - log::debug!("tao_in: {tao_in:?}"); - log::debug!("alpha_in: {alpha_in:?}"); - log::debug!("alpha_out: {alpha_out:?}"); - log::debug!("excess_tao: {excess_tao:?}"); - log::debug!("root_sell_flag: {root_sell_flag:?}"); + // --- 6. Distribute the emissions to the subnets. + Self::distribute_emissions_to_subnets(&emissions_to_distribute); + } - // --- 4. Inject and buy Alpha with any excess TAO. + pub fn inject_and_maybe_swap( + subnets_to_emit_to: &[NetUid], + tao_in: &BTreeMap, + alpha_in: &BTreeMap, + excess_tao: &BTreeMap, + ) { for netuid_i in subnets_to_emit_to.iter() { let tao_in_i: TaoCurrency = tou64!(*tao_in.get(netuid_i).unwrap_or(&asfloat!(0))).into(); let alpha_in_i: AlphaCurrency = - AlphaCurrency::from(tou64!(*alpha_in.get(netuid_i).unwrap_or(&asfloat!(0)))); - let difference_tao: U96F32 = *excess_tao.get(netuid_i).unwrap_or(&asfloat!(0)); + tou64!(*alpha_in.get(netuid_i).unwrap_or(&asfloat!(0))).into(); + let tao_to_swap_with: TaoCurrency = + tou64!(excess_tao.get(netuid_i).unwrap_or(&asfloat!(0))).into(); T::SwapInterface::adjust_protocol_liquidity(*netuid_i, tao_in_i, alpha_in_i); - if difference_tao > asfloat!(0) { + if tao_to_swap_with > TaoCurrency::ZERO { let buy_swap_result = Self::swap_tao_for_alpha( *netuid_i, - tou64!(difference_tao).into(), + tao_to_swap_with, T::SwapInterface::max_price(), true, ); if let Ok(buy_swap_result_ok) = buy_swap_result { - let bought_alpha = AlphaCurrency::from(buy_swap_result_ok.amount_paid_out); + let bought_alpha: AlphaCurrency = buy_swap_result_ok.amount_paid_out.into(); Self::recycle_subnet_alpha(*netuid_i, bought_alpha); } } - } - // --- 5. Update counters - for netuid_i in subnets_to_emit_to.iter() { // Inject Alpha in. let alpha_in_i = AlphaCurrency::from(tou64!(*alpha_in.get(netuid_i).unwrap_or(&asfloat!(0)))); @@ -137,52 +89,94 @@ impl Pallet { SubnetAlphaIn::::mutate(*netuid_i, |total| { *total = total.saturating_add(alpha_in_i); }); - // Injection Alpha out. - let alpha_out_i = - AlphaCurrency::from(tou64!(*alpha_out.get(netuid_i).unwrap_or(&asfloat!(0)))); - SubnetAlphaOutEmission::::insert(*netuid_i, alpha_out_i); - SubnetAlphaOut::::mutate(*netuid_i, |total| { - *total = total.saturating_add(alpha_out_i); - }); + // Inject TAO in. - let tao_in_i: TaoCurrency = + let injected_tao: TaoCurrency = tou64!(*tao_in.get(netuid_i).unwrap_or(&asfloat!(0))).into(); - SubnetTaoInEmission::::insert(*netuid_i, TaoCurrency::from(tao_in_i)); + SubnetTaoInEmission::::insert(*netuid_i, injected_tao); SubnetTAO::::mutate(*netuid_i, |total| { - *total = total.saturating_add(tao_in_i.into()); + *total = total.saturating_add(injected_tao); }); TotalStake::::mutate(|total| { - *total = total.saturating_add(tao_in_i.into()); + *total = total.saturating_add(injected_tao); }); - let difference_tao: U96F32 = *excess_tao.get(netuid_i).unwrap_or(&asfloat!(0)); + // Update total TAO issuance. + let difference_tao = tou64!(*excess_tao.get(netuid_i).unwrap_or(&asfloat!(0))); TotalIssuance::::mutate(|total| { - *total = total.saturating_add(tao_in_i.into()); - *total = total.saturating_add(tou64!(difference_tao).into()); + *total = total + .saturating_add(injected_tao.into()) + .saturating_add(difference_tao.into()); }); } + } - // --- 6. Compute owner cuts and remove them from alpha_out remaining. - // Remove owner cuts here so that we can properly seperate root dividends in the next step. - // Owner cuts are accumulated and then fed to the drain at the end of this func. - let cut_percent: U96F32 = Self::get_float_subnet_owner_cut(); - let mut owner_cuts: BTreeMap = BTreeMap::new(); - for netuid_i in subnets_to_emit_to.iter() { - // Get alpha out. - let alpha_out_i: U96F32 = *alpha_out.get(netuid_i).unwrap_or(&asfloat!(0)); - log::debug!("alpha_out_i: {alpha_out_i:?}"); - // Calculate the owner cut. - let owner_cut_i: U96F32 = alpha_out_i.saturating_mul(cut_percent); - log::debug!("owner_cut_i: {owner_cut_i:?}"); - // Save owner cut. - *owner_cuts.entry(*netuid_i).or_insert(asfloat!(0)) = owner_cut_i; - // Save new alpha_out. - alpha_out.insert(*netuid_i, alpha_out_i.saturating_sub(owner_cut_i)); - // Accumulate the owner cut in pending. - PendingOwnerCut::::mutate(*netuid_i, |total| { - *total = total.saturating_add(tou64!(owner_cut_i).into()); - }); + pub fn get_subnet_terms( + subnet_emissions: &BTreeMap, + ) -> ( + BTreeMap, + BTreeMap, + BTreeMap, + BTreeMap, + ) { + // Computation is described in detail in the dtao whitepaper. + let mut tao_in: BTreeMap = BTreeMap::new(); + let mut alpha_in: BTreeMap = BTreeMap::new(); + let mut alpha_out: BTreeMap = BTreeMap::new(); + let mut excess_tao: BTreeMap = BTreeMap::new(); + + // Only calculate for subnets that we are emitting to. + for (&netuid_i, &tao_emission_i) in subnet_emissions.iter() { + // Get alpha_emission this block. + let alpha_emission_i: U96F32 = asfloat!( + Self::get_block_emission_for_issuance(Self::get_alpha_issuance(netuid_i).into()) + .unwrap_or(0) + ); + log::debug!("alpha_emission_i: {alpha_emission_i:?}"); + + // Get subnet price. + let price_i: U96F32 = T::SwapInterface::current_alpha_price(netuid_i.into()); + log::debug!("price_i: {price_i:?}"); + + let mut tao_in_i: U96F32 = tao_emission_i; + let alpha_out_i: U96F32 = alpha_emission_i; + let mut alpha_in_i: U96F32 = tao_emission_i.safe_div_or(price_i, U96F32::from_num(0.0)); + + if alpha_in_i > alpha_emission_i { + alpha_in_i = alpha_emission_i; + tao_in_i = alpha_in_i.saturating_mul(price_i); + } + + let excess_amount: U96F32 = tao_emission_i.saturating_sub(tao_in_i); + excess_tao.insert(netuid_i, excess_amount); + + // Insert values into maps + tao_in.insert(netuid_i, tao_in_i); + alpha_in.insert(netuid_i, alpha_in_i); + alpha_out.insert(netuid_i, alpha_out_i); } + (tao_in, alpha_in, alpha_out, excess_tao) + } + + pub fn emit_to_subnets( + subnets_to_emit_to: &[NetUid], + subnet_emissions: &BTreeMap, + root_sell_flag: bool, + ) { + // --- 1. Get subnet terms (tao_in, alpha_in, and alpha_out) + // and excess_tao amounts. + let (tao_in, alpha_in, alpha_out, excess_amount) = Self::get_subnet_terms(subnet_emissions); + + log::debug!("tao_in: {tao_in:?}"); + log::debug!("alpha_in: {alpha_in:?}"); + log::debug!("alpha_out: {alpha_out:?}"); + log::debug!("excess_amount: {excess_amount:?}"); + + // --- 2. Inject TAO and ALPHA to pool and swap with excess TAO. + Self::inject_and_maybe_swap(subnets_to_emit_to, &tao_in, &alpha_in, &excess_amount); + + // --- 3. Inject ALPHA for participants. + let cut_percent: U96F32 = Self::get_float_subnet_owner_cut(); // Get total TAO on root. let root_tao: U96F32 = asfloat!(SubnetTAO::::get(NetUid::ROOT)); @@ -191,12 +185,25 @@ impl Pallet { let tao_weight: U96F32 = root_tao.saturating_mul(Self::get_tao_weight()); log::debug!("tao_weight: {tao_weight:?}"); - // --- 7. Seperate out root dividends in alpha and keep them. - // Then accumulate those dividends for later. for netuid_i in subnets_to_emit_to.iter() { - // Get remaining alpha out. - let alpha_out_i: U96F32 = *alpha_out.get(netuid_i).unwrap_or(&asfloat!(0.0)); - log::debug!("alpha_out_i: {alpha_out_i:?}"); + // Get alpha_out for this block. + let mut alpha_out_i: U96F32 = *alpha_out.get(netuid_i).unwrap_or(&asfloat!(0)); + + let alpha_created: AlphaCurrency = AlphaCurrency::from(tou64!(alpha_out_i)); + SubnetAlphaOutEmission::::insert(*netuid_i, alpha_created); + SubnetAlphaOut::::mutate(*netuid_i, |total| { + *total = total.saturating_add(alpha_created); + }); + + // Calculate the owner cut. + let owner_cut_i: U96F32 = alpha_out_i.saturating_mul(cut_percent); + log::debug!("owner_cut_i: {owner_cut_i:?}"); + // Deduct owner cut from alpha_out. + alpha_out_i = alpha_out_i.saturating_sub(owner_cut_i); + // Accumulate the owner cut in pending. + PendingOwnerCut::::mutate(*netuid_i, |total| { + *total = total.saturating_add(tou64!(owner_cut_i).into()); + }); // Get ALPHA issuance. let alpha_issuance: U96F32 = asfloat!(Self::get_alpha_issuance(*netuid_i)); @@ -214,24 +221,16 @@ impl Pallet { .saturating_mul(asfloat!(0.5)); // 50% to validators. log::debug!("root_alpha: {root_alpha:?}"); - if root_sell_flag { - // Only accumulate root alpha divs if root sell is allowed. - PendingRootAlphaDivs::::mutate(*netuid_i, |total| { - *total = total.saturating_add(tou64!(root_alpha).into()); - }); - } else { - // If we are not selling the root alpha, we should recycle it. - Self::recycle_subnet_alpha(*netuid_i, AlphaCurrency::from(tou64!(root_alpha))); - } - // Get pending server alpha, which is the miner cut of the alpha out. // Currently miner cut is 50% of the alpha out. let pending_server_alpha = alpha_out_i.saturating_mul(asfloat!(0.5)); + log::debug!("pending_server_alpha: {pending_server_alpha:?}"); // The total validator alpha is the remaining alpha out minus the server alpha. let total_validator_alpha = alpha_out_i.saturating_sub(pending_server_alpha); - + log::debug!("total_validator_alpha: {total_validator_alpha:?}"); // The alpha validators don't get the root alpha. let pending_validator_alpha = total_validator_alpha.saturating_sub(root_alpha); + log::debug!("pending_validator_alpha: {pending_validator_alpha:?}"); // Accumulate the server alpha emission. PendingServerEmission::::mutate(*netuid_i, |total| { @@ -241,23 +240,35 @@ impl Pallet { PendingValidatorEmission::::mutate(*netuid_i, |total| { *total = total.saturating_add(tou64!(pending_validator_alpha).into()); }); - } - // --- 8. Update moving prices after using them in the emission calculation. - // Only update price EMA for subnets that we emit to. - for netuid_i in subnets_to_emit_to.iter() { - // Update moving prices after using them above. - Self::update_moving_price(*netuid_i); + if root_sell_flag { + // Only accumulate root alpha divs if root sell is allowed. + PendingRootAlphaDivs::::mutate(*netuid_i, |total| { + *total = total.saturating_add(tou64!(root_alpha).into()); + }); + } else { + // If we are not selling the root alpha, we should recycle it. + Self::recycle_subnet_alpha(*netuid_i, AlphaCurrency::from(tou64!(root_alpha))); + } } + } - // --- 9. Drain pending emission through the subnet based on tempo. + pub fn drain_pending( + subnets: &[NetUid], + current_block: u64, + ) -> BTreeMap { + // Map of netuid to (pending_server_alpha, pending_validator_alpha, pending_root_alpha, pending_owner_cut). + let mut emissions_to_distribute: BTreeMap< + NetUid, + (AlphaCurrency, AlphaCurrency, AlphaCurrency, AlphaCurrency), + > = BTreeMap::new(); + // --- Drain pending emissions for all subnets hat are at their tempo. // Run the epoch for *all* subnets, even if we don't emit anything. for &netuid in subnets.iter() { - // Reveal matured weights. - if let Err(e) = Self::reveal_crv3_commits(netuid) { - log::warn!("Failed to reveal commits for subnet {netuid} due to error: {e:?}"); - }; - // Pass on subnets that have not reached their tempo. + // Increment blocks since last step. + BlocksSinceLastStep::::mutate(netuid, |total| *total = total.saturating_add(1)); + + // Run the epoch if applicable. if Self::should_run_epoch(netuid, current_block) && Self::is_epoch_input_state_consistent(netuid) { @@ -272,27 +283,49 @@ impl Pallet { let pending_validator_alpha = PendingValidatorEmission::::get(netuid); PendingValidatorEmission::::insert(netuid, AlphaCurrency::ZERO); - // Get and drain the subnet pending root alpha divs. + // Get and drain the pending Alpha for root divs. let pending_root_alpha = PendingRootAlphaDivs::::get(netuid); PendingRootAlphaDivs::::insert(netuid, AlphaCurrency::ZERO); - // Get owner cut and drain. + // Get and drain the pending owner cut. let owner_cut = PendingOwnerCut::::get(netuid); PendingOwnerCut::::insert(netuid, AlphaCurrency::ZERO); - // Distribute the emission. - Self::distribute_emission( + // Save the emissions to distribute. + emissions_to_distribute.insert( netuid, - pending_server_alpha, - pending_validator_alpha, - pending_root_alpha, - owner_cut, + ( + pending_server_alpha, + pending_validator_alpha, + pending_root_alpha, + owner_cut, + ), ); - } else { - // Increment - BlocksSinceLastStep::::mutate(netuid, |total| *total = total.saturating_add(1)); } } + emissions_to_distribute + } + + pub fn distribute_emissions_to_subnets( + emissions_to_distribute: &BTreeMap< + NetUid, + (AlphaCurrency, AlphaCurrency, AlphaCurrency, AlphaCurrency), + >, + ) { + for ( + &netuid, + &(pending_server_alpha, pending_validator_alpha, pending_root_alpha, pending_owner_cut), + ) in emissions_to_distribute.iter() + { + // Distribute the emission to the subnet. + Self::distribute_emission( + netuid, + pending_server_alpha, + pending_validator_alpha, + pending_root_alpha, + pending_owner_cut, + ); + } } pub fn get_network_root_sell_flag(subnets_to_emit_to: &[NetUid]) -> bool { @@ -582,6 +615,7 @@ impl Pallet { } // Distribute root alpha divs. + let _ = RootAlphaDividendsPerSubnet::::clear_prefix(netuid, u32::MAX, None); for (hotkey, mut root_alpha) in root_alpha_dividends { // Get take prop let alpha_take: U96F32 = @@ -604,7 +638,7 @@ impl Pallet { ); // Record root alpha dividends for this validator on this subnet. - AlphaDividendsPerSubnet::::mutate(netuid, hotkey.clone(), |divs| { + RootAlphaDividendsPerSubnet::::mutate(netuid, &hotkey, |divs| { *divs = divs.saturating_add(tou64!(root_alpha).into()); }); } diff --git a/pallets/subtensor/src/coinbase/subnet_emissions.rs b/pallets/subtensor/src/coinbase/subnet_emissions.rs index 379a5c4bb1..477a678864 100644 --- a/pallets/subtensor/src/coinbase/subnet_emissions.rs +++ b/pallets/subtensor/src/coinbase/subnet_emissions.rs @@ -6,10 +6,18 @@ use substrate_fixed::types::{I32F32, I64F64, U64F64, U96F32}; impl Pallet { pub fn get_subnets_to_emit_to(subnets: &[NetUid]) -> Vec { + // Filter out root subnet. // Filter out subnets with no first emission block number. subnets .iter() + .filter(|netuid| !netuid.is_root()) .filter(|netuid| FirstEmissionBlockNumber::::get(*netuid).is_some()) + .filter(|netuid| SubtokenEnabled::::get(*netuid)) + .filter(|&netuid| { + // Only emit TAO if the subnetwork allows registration. + Self::get_network_registration_allowed(*netuid) + || Self::get_network_pow_registration_allowed(*netuid) + }) .copied() .collect() } diff --git a/pallets/subtensor/src/lib.rs b/pallets/subtensor/src/lib.rs index 6c3ee1d84e..6d61baadf3 100644 --- a/pallets/subtensor/src/lib.rs +++ b/pallets/subtensor/src/lib.rs @@ -334,50 +334,46 @@ pub mod pallet { Swap, /// Keep all alpha emission. Keep, + /// Keep all alpha emission for specified subnets. + KeepSubnets { + /// Subnets to keep alpha emissions (swap everything else). + subnets: BTreeSet, + }, } - /// Enum for the per-coldkey root claim frequency setting. - #[derive(Encode, Decode, Default, TypeInfo, Clone, PartialEq, Eq, Debug)] - pub enum RootClaimFrequencyEnum { - /// Claim automatically. - #[default] - Auto, - /// Only claim manually; Never automatically. - Manual, - } - - #[pallet::type_value] /// Default minimum root claim amount. /// This is the minimum amount of root claim that can be made. /// Any amount less than this will not be claimed. + #[pallet::type_value] pub fn DefaultMinRootClaimAmount() -> I96F32 { 500_000u64.into() } - #[pallet::type_value] /// Default root claim type. /// This is the type of root claim that will be made. /// This is set by the user. Either swap to TAO or keep as alpha. + #[pallet::type_value] pub fn DefaultRootClaimType() -> RootClaimTypeEnum { RootClaimTypeEnum::default() } - #[pallet::type_value] /// Default number of root claims per claim call. /// Ideally this is calculated using the number of staking coldkey /// and the block time. + #[pallet::type_value] pub fn DefaultNumRootClaim() -> u64 { // once per week (+ spare keys for skipped tries) 5 } - #[pallet::type_value] /// Default value for zero. + #[pallet::type_value] pub fn DefaultZeroU64() -> u64 { 0 } - #[pallet::type_value] + /// Default value for zero. + #[pallet::type_value] pub fn DefaultZeroI64() -> i64 { 0 } @@ -386,92 +382,105 @@ pub mod pallet { pub fn DefaultZeroAlpha() -> AlphaCurrency { AlphaCurrency::ZERO } + /// Default value for Tao currency. #[pallet::type_value] pub fn DefaultZeroTao() -> TaoCurrency { TaoCurrency::ZERO } - #[pallet::type_value] + /// Default value for zero. + #[pallet::type_value] pub fn DefaultZeroU128() -> u128 { 0 } - #[pallet::type_value] + /// Default value for zero. + #[pallet::type_value] pub fn DefaultZeroU16() -> u16 { 0 } - #[pallet::type_value] + /// Default value for false. + #[pallet::type_value] pub fn DefaultFalse() -> bool { false } - #[pallet::type_value] + /// Default value for false. + #[pallet::type_value] pub fn DefaultTrue() -> bool { true } - #[pallet::type_value] + /// Total Rao in circulation. + #[pallet::type_value] pub fn TotalSupply() -> u64 { 21_000_000_000_000_000 } - #[pallet::type_value] + /// Default Delegate Take. + #[pallet::type_value] pub fn DefaultDelegateTake() -> u16 { T::InitialDefaultDelegateTake::get() } - #[pallet::type_value] /// Default childkey take. + #[pallet::type_value] pub fn DefaultChildKeyTake() -> u16 { T::InitialDefaultChildKeyTake::get() } - #[pallet::type_value] + /// Default minimum delegate take. + #[pallet::type_value] pub fn DefaultMinDelegateTake() -> u16 { T::InitialMinDelegateTake::get() } - #[pallet::type_value] /// Default minimum childkey take. + #[pallet::type_value] pub fn DefaultMinChildKeyTake() -> u16 { T::InitialMinChildKeyTake::get() } - #[pallet::type_value] /// Default maximum childkey take. + #[pallet::type_value] pub fn DefaultMaxChildKeyTake() -> u16 { T::InitialMaxChildKeyTake::get() } - #[pallet::type_value] /// Default account take. + #[pallet::type_value] pub fn DefaultAccountTake() -> u64 { 0 } - #[pallet::type_value] + /// Default value for global weight. + #[pallet::type_value] pub fn DefaultTaoWeight() -> u64 { T::InitialTaoWeight::get() } - #[pallet::type_value] + /// Default emission per block. + #[pallet::type_value] pub fn DefaultBlockEmission() -> u64 { 1_000_000_000 } - #[pallet::type_value] + /// Default allowed delegation. + #[pallet::type_value] pub fn DefaultAllowsDelegation() -> bool { false } - #[pallet::type_value] + /// Default total issuance. + #[pallet::type_value] pub fn DefaultTotalIssuance() -> TaoCurrency { T::InitialIssuance::get().into() } - #[pallet::type_value] + /// Default account, derived from zero trailing bytes. + #[pallet::type_value] pub fn DefaultAccount() -> T::AccountId { #[allow(clippy::expect_used)] T::AccountId::decode(&mut TrailingZeroInput::zeroes()) @@ -480,329 +489,392 @@ pub mod pallet { // pub fn DefaultStakeInterval() -> u64 { // 360 // } (DEPRECATED) - #[pallet::type_value] + /// Default account linkage + #[pallet::type_value] pub fn DefaultAccountLinkage() -> Vec<(u64, T::AccountId)> { vec![] } - #[pallet::type_value] + /// Default pending childkeys + #[pallet::type_value] pub fn DefaultPendingChildkeys() -> (Vec<(u64, T::AccountId)>, u64) { (vec![], 0) } - #[pallet::type_value] + /// Default account linkage + #[pallet::type_value] pub fn DefaultProportion() -> u64 { 0 } - #[pallet::type_value] + /// Default accumulated emission for a hotkey + #[pallet::type_value] pub fn DefaultAccumulatedEmission() -> u64 { 0 } - #[pallet::type_value] + /// Default last adjustment block. + #[pallet::type_value] pub fn DefaultLastAdjustmentBlock() -> u64 { 0 } - #[pallet::type_value] + /// Default last adjustment block. + #[pallet::type_value] pub fn DefaultRegistrationsThisBlock() -> u16 { 0 } - #[pallet::type_value] + /// Default EMA price halving blocks + #[pallet::type_value] pub fn DefaultEMAPriceMovingBlocks() -> u64 { T::InitialEmaPriceHalvingPeriod::get() } - #[pallet::type_value] + /// Default registrations this block. + #[pallet::type_value] pub fn DefaultBurn() -> TaoCurrency { T::InitialBurn::get().into() } - #[pallet::type_value] + /// Default burn token. + #[pallet::type_value] pub fn DefaultMinBurn() -> TaoCurrency { T::InitialMinBurn::get().into() } - #[pallet::type_value] + /// Default min burn token. + #[pallet::type_value] pub fn DefaultMaxBurn() -> TaoCurrency { T::InitialMaxBurn::get().into() } - #[pallet::type_value] + /// Default max burn token. + #[pallet::type_value] pub fn DefaultDifficulty() -> u64 { T::InitialDifficulty::get() } - #[pallet::type_value] + /// Default difficulty value. + #[pallet::type_value] pub fn DefaultMinDifficulty() -> u64 { T::InitialMinDifficulty::get() } - #[pallet::type_value] + /// Default min difficulty value. + #[pallet::type_value] pub fn DefaultMaxDifficulty() -> u64 { T::InitialMaxDifficulty::get() } - #[pallet::type_value] + /// Default max difficulty value. + #[pallet::type_value] pub fn DefaultMaxRegistrationsPerBlock() -> u16 { T::InitialMaxRegistrationsPerBlock::get() } - #[pallet::type_value] + /// Default max registrations per block. + #[pallet::type_value] pub fn DefaultRAORecycledForRegistration() -> TaoCurrency { T::InitialRAORecycledForRegistration::get().into() } - #[pallet::type_value] + /// Default number of networks. + #[pallet::type_value] pub fn DefaultN() -> u16 { 0 } - #[pallet::type_value] + /// Default value for hotkeys. + #[pallet::type_value] pub fn DefaultHotkeys() -> Vec { vec![] } - #[pallet::type_value] + /// Default value if network is added. + #[pallet::type_value] pub fn DefaultNeworksAdded() -> bool { false } - #[pallet::type_value] + /// Default value for network member. + #[pallet::type_value] pub fn DefaultIsNetworkMember() -> bool { false } - #[pallet::type_value] + /// Default value for registration allowed. + #[pallet::type_value] pub fn DefaultRegistrationAllowed() -> bool { true } - #[pallet::type_value] + /// Default value for network registered at. + #[pallet::type_value] pub fn DefaultNetworkRegisteredAt() -> u64 { 0 } - #[pallet::type_value] + /// Default value for network immunity period. + #[pallet::type_value] pub fn DefaultNetworkImmunityPeriod() -> u64 { T::InitialNetworkImmunityPeriod::get() } - #[pallet::type_value] + /// Default value for network min lock cost. + #[pallet::type_value] pub fn DefaultNetworkMinLockCost() -> TaoCurrency { T::InitialNetworkMinLockCost::get().into() } - #[pallet::type_value] + /// Default value for network lock reduction interval. + #[pallet::type_value] pub fn DefaultNetworkLockReductionInterval() -> u64 { T::InitialNetworkLockReductionInterval::get() } - #[pallet::type_value] + /// Default value for subnet owner cut. + #[pallet::type_value] pub fn DefaultSubnetOwnerCut() -> u16 { T::InitialSubnetOwnerCut::get() } - #[pallet::type_value] + /// Default value for recycle or burn. + #[pallet::type_value] pub fn DefaultRecycleOrBurn() -> RecycleOrBurnEnum { RecycleOrBurnEnum::Burn // default to burn } - #[pallet::type_value] + /// Default value for network rate limit. + #[pallet::type_value] pub fn DefaultNetworkRateLimit() -> u64 { if cfg!(feature = "pow-faucet") { return 0; } T::InitialNetworkRateLimit::get() } - #[pallet::type_value] + /// Default value for network rate limit. + #[pallet::type_value] pub fn DefaultNetworkRegistrationStartBlock() -> u64 { 0 } - #[pallet::type_value] + /// Default value for weights version key rate limit. /// In units of tempos. + #[pallet::type_value] pub fn DefaultWeightsVersionKeyRateLimit() -> u64 { 5 // 5 tempos } - #[pallet::type_value] + /// Default value for pending emission. + #[pallet::type_value] pub fn DefaultPendingEmission() -> AlphaCurrency { 0.into() } - #[pallet::type_value] + /// Default value for blocks since last step. + #[pallet::type_value] pub fn DefaultBlocksSinceLastStep() -> u64 { 0 } - #[pallet::type_value] + /// Default value for last mechanism step block. + #[pallet::type_value] pub fn DefaultLastMechanismStepBlock() -> u64 { 0 } - #[pallet::type_value] + /// Default value for subnet owner. + #[pallet::type_value] pub fn DefaultSubnetOwner() -> T::AccountId { #[allow(clippy::expect_used)] T::AccountId::decode(&mut sp_runtime::traits::TrailingZeroInput::zeroes()) .expect("trailing zeroes always produce a valid account ID; qed") } - #[pallet::type_value] + /// Default value for subnet locked. + #[pallet::type_value] pub fn DefaultSubnetLocked() -> u64 { 0 } - #[pallet::type_value] + /// Default value for network tempo + #[pallet::type_value] pub fn DefaultTempo() -> u16 { T::InitialTempo::get() } - #[pallet::type_value] + /// Default value for weights set rate limit. + #[pallet::type_value] pub fn DefaultWeightsSetRateLimit() -> u64 { 100 } - #[pallet::type_value] + /// Default block number at registration. + #[pallet::type_value] pub fn DefaultBlockAtRegistration() -> u64 { 0 } - #[pallet::type_value] + /// Default value for rho parameter. + #[pallet::type_value] pub fn DefaultRho() -> u16 { T::InitialRho::get() } - #[pallet::type_value] + /// Default value for alpha sigmoid steepness. + #[pallet::type_value] pub fn DefaultAlphaSigmoidSteepness() -> i16 { T::InitialAlphaSigmoidSteepness::get() } - #[pallet::type_value] + /// Default value for kappa parameter. + #[pallet::type_value] pub fn DefaultKappa() -> u16 { T::InitialKappa::get() } - #[pallet::type_value] + /// Default value for network min allowed UIDs. + #[pallet::type_value] pub fn DefaultMinAllowedUids() -> u16 { T::InitialMinAllowedUids::get() } - #[pallet::type_value] + /// Default maximum allowed UIDs. + #[pallet::type_value] pub fn DefaultMaxAllowedUids() -> u16 { T::InitialMaxAllowedUids::get() } - #[pallet::type_value] + /// -- Rate limit for set max allowed UIDs + #[pallet::type_value] pub fn MaxUidsTrimmingRateLimit() -> u64 { prod_or_fast!(30 * 7200, 1) } - #[pallet::type_value] + /// Default immunity period. + #[pallet::type_value] pub fn DefaultImmunityPeriod() -> u16 { T::InitialImmunityPeriod::get() } - #[pallet::type_value] + /// Default activity cutoff. + #[pallet::type_value] pub fn DefaultActivityCutoff() -> u16 { T::InitialActivityCutoff::get() } - #[pallet::type_value] + /// Default weights version key. + #[pallet::type_value] pub fn DefaultWeightsVersionKey() -> u64 { T::InitialWeightsVersionKey::get() } - #[pallet::type_value] + /// Default minimum allowed weights. + #[pallet::type_value] pub fn DefaultMinAllowedWeights() -> u16 { T::InitialMinAllowedWeights::get() } - #[pallet::type_value] /// Default maximum allowed validators. + #[pallet::type_value] pub fn DefaultMaxAllowedValidators() -> u16 { T::InitialMaxAllowedValidators::get() } - #[pallet::type_value] + /// Default adjustment interval. + #[pallet::type_value] pub fn DefaultAdjustmentInterval() -> u16 { T::InitialAdjustmentInterval::get() } - #[pallet::type_value] + /// Default bonds moving average. + #[pallet::type_value] pub fn DefaultBondsMovingAverage() -> u64 { T::InitialBondsMovingAverage::get() } + /// Default bonds penalty. #[pallet::type_value] pub fn DefaultBondsPenalty() -> u16 { T::InitialBondsPenalty::get() } + /// Default value for bonds reset - will not reset bonds #[pallet::type_value] pub fn DefaultBondsResetOn() -> bool { T::InitialBondsResetOn::get() } + /// Default validator prune length. #[pallet::type_value] pub fn DefaultValidatorPruneLen() -> u64 { T::InitialValidatorPruneLen::get() } - #[pallet::type_value] + /// Default scaling law power. + #[pallet::type_value] pub fn DefaultScalingLawPower() -> u16 { T::InitialScalingLawPower::get() } - #[pallet::type_value] + /// Default target registrations per interval. + #[pallet::type_value] pub fn DefaultTargetRegistrationsPerInterval() -> u16 { T::InitialTargetRegistrationsPerInterval::get() } - #[pallet::type_value] + /// Default adjustment alpha. + #[pallet::type_value] pub fn DefaultAdjustmentAlpha() -> u64 { T::InitialAdjustmentAlpha::get() } - #[pallet::type_value] + /// Default minimum stake for weights. + #[pallet::type_value] pub fn DefaultStakeThreshold() -> u64 { 0 } - #[pallet::type_value] + /// Default Reveal Period Epochs + #[pallet::type_value] pub fn DefaultRevealPeriodEpochs() -> u64 { 1 } - #[pallet::type_value] + /// Value definition for vector of u16. + #[pallet::type_value] pub fn EmptyU16Vec() -> Vec { vec![] } - #[pallet::type_value] + /// Value definition for vector of u64. + #[pallet::type_value] pub fn EmptyU64Vec() -> Vec { vec![] } - #[pallet::type_value] + /// Value definition for vector of bool. + #[pallet::type_value] pub fn EmptyBoolVec() -> Vec { vec![] } - #[pallet::type_value] + /// Value definition for bonds with type vector of (u16, u16). + #[pallet::type_value] pub fn DefaultBonds() -> Vec<(u16, u16)> { vec![] } - #[pallet::type_value] + /// Value definition for weights with vector of (u16, u16). + #[pallet::type_value] pub fn DefaultWeights() -> Vec<(u16, u16)> { vec![] } - #[pallet::type_value] + /// Default value for key with type T::AccountId derived from trailing zeroes. + #[pallet::type_value] pub fn DefaultKey() -> T::AccountId { #[allow(clippy::expect_used)] T::AccountId::decode(&mut sp_runtime::traits::TrailingZeroInput::zeroes()) @@ -811,124 +883,137 @@ pub mod pallet { // pub fn DefaultHotkeyEmissionTempo() -> u64 { // T::InitialHotkeyEmissionTempo::get() // } (DEPRECATED) - #[pallet::type_value] + /// Default value for rate limiting + #[pallet::type_value] pub fn DefaultTxRateLimit() -> u64 { T::InitialTxRateLimit::get() } - #[pallet::type_value] + /// Default value for delegate take rate limiting + #[pallet::type_value] pub fn DefaultTxDelegateTakeRateLimit() -> u64 { T::InitialTxDelegateTakeRateLimit::get() } - #[pallet::type_value] + /// Default value for chidlkey take rate limiting + #[pallet::type_value] pub fn DefaultTxChildKeyTakeRateLimit() -> u64 { T::InitialTxChildKeyTakeRateLimit::get() } - #[pallet::type_value] + /// Default value for last extrinsic block. + #[pallet::type_value] pub fn DefaultLastTxBlock() -> u64 { 0 } - #[pallet::type_value] + /// Default value for serving rate limit. + #[pallet::type_value] pub fn DefaultServingRateLimit() -> u64 { T::InitialServingRateLimit::get() } - #[pallet::type_value] + /// Default value for weight commit/reveal enabled. + #[pallet::type_value] pub fn DefaultCommitRevealWeightsEnabled() -> bool { true } - #[pallet::type_value] + /// Default value for weight commit/reveal version. + #[pallet::type_value] pub fn DefaultCommitRevealWeightsVersion() -> u16 { 4 } - #[pallet::type_value] + /// -- ITEM (switches liquid alpha on) + #[pallet::type_value] pub fn DefaultLiquidAlpha() -> bool { false } - #[pallet::type_value] + /// -- ITEM (switches liquid alpha on) + #[pallet::type_value] pub fn DefaultYuma3() -> bool { false } - #[pallet::type_value] + /// (alpha_low: 0.7, alpha_high: 0.9) + #[pallet::type_value] pub fn DefaultAlphaValues() -> (u16, u16) { (45875, 58982) } - #[pallet::type_value] + /// Default value for coldkey swap schedule duration + #[pallet::type_value] pub fn DefaultColdkeySwapScheduleDuration() -> BlockNumberFor { T::InitialColdkeySwapScheduleDuration::get() } - #[pallet::type_value] /// Default value for coldkey swap reschedule duration + #[pallet::type_value] pub fn DefaultColdkeySwapRescheduleDuration() -> BlockNumberFor { T::InitialColdkeySwapRescheduleDuration::get() } - #[pallet::type_value] /// Default value for applying pending items (e.g. childkeys). + #[pallet::type_value] pub fn DefaultPendingCooldown() -> u64 { prod_or_fast!(7_200, 15) } - #[pallet::type_value] /// Default minimum stake. + #[pallet::type_value] pub fn DefaultMinStake() -> TaoCurrency { 2_000_000.into() } - #[pallet::type_value] /// Default unicode vector for tau symbol. + #[pallet::type_value] pub fn DefaultUnicodeVecU8() -> Vec { b"\xF0\x9D\x9C\x8F".to_vec() // Unicode for tau (𝜏) } - #[pallet::type_value] /// Default value for dissolve network schedule duration + #[pallet::type_value] pub fn DefaultDissolveNetworkScheduleDuration() -> BlockNumberFor { T::InitialDissolveNetworkScheduleDuration::get() } - #[pallet::type_value] /// Default moving alpha for the moving price. + #[pallet::type_value] pub fn DefaultMovingAlpha() -> I96F32 { // Moving average take 30 days to reach 50% of the price // and 3.5 months to reach 90%. I96F32::saturating_from_num(0.000003) } - #[pallet::type_value] + /// Default subnet moving price. + #[pallet::type_value] pub fn DefaultMovingPrice() -> I96F32 { I96F32::saturating_from_num(0.0) } - #[pallet::type_value] /// Default subnet root claimable + #[pallet::type_value] pub fn DefaultRootClaimable() -> BTreeMap { Default::default() } - #[pallet::type_value] + /// Default value for Share Pool variables + #[pallet::type_value] pub fn DefaultSharePoolZero() -> U64F64 { U64F64::saturating_from_num(0) } - #[pallet::type_value] /// Default value for minimum activity cutoff + #[pallet::type_value] pub fn DefaultMinActivityCutoff() -> u16 { 360 } - #[pallet::type_value] /// Default value for coldkey swap scheduled + #[pallet::type_value] pub fn DefaultColdkeySwapScheduled() -> (BlockNumberFor, T::AccountId) { #[allow(clippy::expect_used)] let default_account = T::AccountId::decode(&mut TrailingZeroInput::zeroes()) @@ -936,8 +1021,8 @@ pub mod pallet { (BlockNumberFor::::from(0_u32), default_account) } - #[pallet::type_value] /// Default value for setting subnet owner hotkey rate limit + #[pallet::type_value] pub fn DefaultSetSNOwnerHotkeyRateLimit() -> u64 { 50400 } @@ -948,58 +1033,62 @@ pub mod pallet { None } - #[pallet::type_value] /// Default number of terminal blocks in a tempo during which admin operations are prohibited + #[pallet::type_value] pub fn DefaultAdminFreezeWindow() -> u16 { 10 } - #[pallet::type_value] /// Default number of tempos for owner hyperparameter update rate limit + #[pallet::type_value] pub fn DefaultOwnerHyperparamRateLimit() -> u16 { 2 } - #[pallet::type_value] /// Default value for ck burn, 18%. + #[pallet::type_value] pub fn DefaultCKBurn() -> u64 { 0 } - #[pallet::type_value] /// Default value for subnet limit. + #[pallet::type_value] pub fn DefaultSubnetLimit() -> u16 { 128 } + /// Global minimum activity cutoff value #[pallet::storage] pub type MinActivityCutoff = StorageValue<_, u16, ValueQuery, DefaultMinActivityCutoff>; - #[pallet::storage] /// Global window (in blocks) at the end of each tempo where admin ops are disallowed + #[pallet::storage] pub type AdminFreezeWindow = StorageValue<_, u16, ValueQuery, DefaultAdminFreezeWindow>; - #[pallet::storage] /// Global number of epochs used to rate limit subnet owner hyperparameter updates + #[pallet::storage] pub type OwnerHyperparamRateLimit = StorageValue<_, u16, ValueQuery, DefaultOwnerHyperparamRateLimit>; + /// Duration of coldkey swap schedule before execution #[pallet::storage] pub type ColdkeySwapScheduleDuration = StorageValue<_, BlockNumberFor, ValueQuery, DefaultColdkeySwapScheduleDuration>; + /// Duration of coldkey swap reschedule before execution #[pallet::storage] pub type ColdkeySwapRescheduleDuration = StorageValue<_, BlockNumberFor, ValueQuery, DefaultColdkeySwapRescheduleDuration>; + /// Duration of dissolve network schedule before execution #[pallet::storage] pub type DissolveNetworkScheduleDuration = StorageValue<_, BlockNumberFor, ValueQuery, DefaultDissolveNetworkScheduleDuration>; - #[pallet::storage] /// --- DMap ( netuid, coldkey ) --> blocknumber | last hotkey swap on network. + #[pallet::storage] pub type LastHotkeySwapOnNetuid = StorageDoubleMap< _, Identity, @@ -1011,8 +1100,8 @@ pub mod pallet { DefaultZeroU64, >; - #[pallet::storage] /// Ensures unique IDs for StakeJobs storage map + #[pallet::storage] pub type NextStakeJobId = StorageValue<_, u64, ValueQuery, DefaultZeroU64>; /// ============================ @@ -1027,34 +1116,42 @@ pub mod pallet { /// /// Eventually, Bittensor should migrate to using Holds afterwhich time we will not require this /// separate accounting. - #[pallet::storage] /// --- ITEM --> Global weight - pub type TaoWeight = StorageValue<_, u64, ValueQuery, DefaultTaoWeight>; #[pallet::storage] + pub type TaoWeight = StorageValue<_, u64, ValueQuery, DefaultTaoWeight>; + /// --- ITEM --> CK burn - pub type CKBurn = StorageValue<_, u64, ValueQuery, DefaultCKBurn>; #[pallet::storage] + pub type CKBurn = StorageValue<_, u64, ValueQuery, DefaultCKBurn>; + /// --- ITEM ( default_delegate_take ) - pub type MaxDelegateTake = StorageValue<_, u16, ValueQuery, DefaultDelegateTake>; #[pallet::storage] + pub type MaxDelegateTake = StorageValue<_, u16, ValueQuery, DefaultDelegateTake>; + /// --- ITEM ( min_delegate_take ) - pub type MinDelegateTake = StorageValue<_, u16, ValueQuery, DefaultMinDelegateTake>; #[pallet::storage] + pub type MinDelegateTake = StorageValue<_, u16, ValueQuery, DefaultMinDelegateTake>; + /// --- ITEM ( default_childkey_take ) - pub type MaxChildkeyTake = StorageValue<_, u16, ValueQuery, DefaultMaxChildKeyTake>; #[pallet::storage] + pub type MaxChildkeyTake = StorageValue<_, u16, ValueQuery, DefaultMaxChildKeyTake>; + /// --- ITEM ( min_childkey_take ) + #[pallet::storage] pub type MinChildkeyTake = StorageValue<_, u16, ValueQuery, DefaultMinChildKeyTake>; + + /// MAP ( hot ) --> cold | Returns the controlling coldkey for a hotkey #[pallet::storage] - /// MAP ( hot ) --> cold | Returns the controlling coldkey for a hotkey. pub type Owner = StorageMap<_, Blake2_128Concat, T::AccountId, T::AccountId, ValueQuery, DefaultAccount>; + + /// MAP ( hot ) --> take | Returns the hotkey delegation take. And signals that this key is open for delegation #[pallet::storage] - /// MAP ( hot ) --> take | Returns the hotkey delegation take. And signals that this key is open for delegation. pub type Delegates = StorageMap<_, Blake2_128Concat, T::AccountId, u16, ValueQuery, DefaultDelegateTake>; - #[pallet::storage] + /// DMAP ( hot, netuid ) --> take | Returns the hotkey childkey take for a specific subnet + #[pallet::storage] pub type ChildkeyTake = StorageDoubleMap< _, Blake2_128Concat, @@ -1064,8 +1161,9 @@ pub mod pallet { u16, // Value: take ValueQuery, >; - #[pallet::storage] + /// DMAP ( netuid, parent ) --> (Vec<(proportion,child)>, cool_down_block) + #[pallet::storage] pub type PendingChildKeys = StorageDoubleMap< _, Identity, @@ -1076,8 +1174,9 @@ pub mod pallet { ValueQuery, DefaultPendingChildkeys, >; - #[pallet::storage] + /// DMAP ( parent, netuid ) --> Vec<(proportion,child)> + #[pallet::storage] pub type ChildKeys = StorageDoubleMap< _, Blake2_128Concat, @@ -1088,8 +1187,9 @@ pub mod pallet { ValueQuery, DefaultAccountLinkage, >; - #[pallet::storage] + /// DMAP ( child, netuid ) --> Vec<(proportion,parent)> + #[pallet::storage] pub type ParentKeys = StorageDoubleMap< _, Blake2_128Concat, @@ -1100,7 +1200,9 @@ pub mod pallet { ValueQuery, DefaultAccountLinkage, >; - #[pallet::storage] // --- DMAP ( netuid, hotkey ) --> u64 | Last total dividend this hotkey got on tempo. + + /// --- DMAP ( netuid, hotkey ) --> u64 | Last alpha dividend this hotkey got on tempo. + #[pallet::storage] pub type AlphaDividendsPerSubnet = StorageDoubleMap< _, Identity, @@ -1112,14 +1214,28 @@ pub mod pallet { DefaultZeroAlpha, >; + /// --- DMAP ( netuid, hotkey ) --> u64 | Last root alpha dividend this hotkey got on tempo. + #[pallet::storage] + pub type RootAlphaDividendsPerSubnet = StorageDoubleMap< + _, + Identity, + NetUid, + Blake2_128Concat, + T::AccountId, + AlphaCurrency, + ValueQuery, + DefaultZeroAlpha, + >; + /// ================== /// ==== Coinbase ==== /// ================== + /// --- ITEM ( global_block_emission ) #[pallet::storage] - /// --- ITEM ( global_block_emission ) pub type BlockEmission = StorageValue<_, u64, ValueQuery, DefaultBlockEmission>; - #[pallet::storage] + /// --- DMap ( hot, netuid ) --> emission | last hotkey emission on network. + #[pallet::storage] pub type LastHotkeyEmissionOnNetuid = StorageDoubleMap< _, Blake2_128Concat, @@ -1130,7 +1246,6 @@ pub mod pallet { ValueQuery, DefaultZeroAlpha, >; - /// ========================== /// ==== Staking Counters ==== /// ========================== @@ -1143,53 +1258,84 @@ pub mod pallet { /// /// Eventually, Bittensor should migrate to using Holds afterwhich time we will not require this /// separate accounting. - - #[pallet::storage] // --- ITEM ( maximum_number_of_networks ) + /// --- ITEM ( maximum_number_of_networks ) + #[pallet::storage] pub type SubnetLimit = StorageValue<_, u16, ValueQuery, DefaultSubnetLimit>; - #[pallet::storage] // --- ITEM ( total_issuance ) + + /// --- ITEM ( total_issuance ) + #[pallet::storage] pub type TotalIssuance = StorageValue<_, TaoCurrency, ValueQuery, DefaultTotalIssuance>; - #[pallet::storage] // --- ITEM ( total_stake ) - pub type TotalStake = StorageValue<_, TaoCurrency, ValueQuery>; - #[pallet::storage] // --- ITEM ( moving_alpha ) -- subnet moving alpha. + + /// --- ITEM ( total_stake ) + #[pallet::storage] + pub type TotalStake = StorageValue<_, TaoCurrency, ValueQuery, DefaultZeroTao>; + + /// --- ITEM ( moving_alpha ) -- subnet moving alpha. + #[pallet::storage] pub type SubnetMovingAlpha = StorageValue<_, I96F32, ValueQuery, DefaultMovingAlpha>; - #[pallet::storage] // --- MAP ( netuid ) --> moving_price | The subnet moving price. + + /// --- MAP ( netuid ) --> moving_price | The subnet moving price. + #[pallet::storage] pub type SubnetMovingPrice = StorageMap<_, Identity, NetUid, I96F32, ValueQuery, DefaultMovingPrice>; - #[pallet::storage] // --- MAP ( netuid ) --> total_volume | The total amount of TAO bought and sold since the start of the network. + + /// --- MAP ( netuid ) --> total_volume | The total amount of TAO bought and sold since the start of the network. + #[pallet::storage] pub type SubnetVolume = StorageMap<_, Identity, NetUid, u128, ValueQuery, DefaultZeroU128>; - #[pallet::storage] // --- MAP ( netuid ) --> tao_in_subnet | Returns the amount of TAO in the subnet. + + /// --- MAP ( netuid ) --> tao_in_subnet | Returns the amount of TAO in the subnet. + #[pallet::storage] pub type SubnetTAO = StorageMap<_, Identity, NetUid, TaoCurrency, ValueQuery, DefaultZeroTao>; - #[pallet::storage] // --- MAP ( netuid ) --> tao_in_user_subnet | Returns the amount of TAO in the subnet reserve provided by users as liquidity. + + /// --- MAP ( netuid ) --> tao_in_user_subnet | Returns the amount of TAO in the subnet reserve provided by users as liquidity. + #[pallet::storage] pub type SubnetTaoProvided = StorageMap<_, Identity, NetUid, TaoCurrency, ValueQuery, DefaultZeroTao>; - #[pallet::storage] // --- MAP ( netuid ) --> alpha_in_emission | Returns the amount of alph in emission into the pool per block. + + /// --- MAP ( netuid ) --> alpha_in_emission | Returns the amount of alph in emission into the pool per block. + #[pallet::storage] pub type SubnetAlphaInEmission = StorageMap<_, Identity, NetUid, AlphaCurrency, ValueQuery, DefaultZeroAlpha>; - #[pallet::storage] // --- MAP ( netuid ) --> alpha_out_emission | Returns the amount of alpha out emission into the network per block. + + /// --- MAP ( netuid ) --> alpha_out_emission | Returns the amount of alpha out emission into the network per block. + #[pallet::storage] pub type SubnetAlphaOutEmission = StorageMap<_, Identity, NetUid, AlphaCurrency, ValueQuery, DefaultZeroAlpha>; - #[pallet::storage] // --- MAP ( netuid ) --> tao_in_emission | Returns the amount of tao emitted into this subent on the last block. + + /// --- MAP ( netuid ) --> tao_in_emission | Returns the amount of tao emitted into this subent on the last block. + #[pallet::storage] pub type SubnetTaoInEmission = StorageMap<_, Identity, NetUid, TaoCurrency, ValueQuery, DefaultZeroTao>; - #[pallet::storage] // --- MAP ( netuid ) --> alpha_supply_in_pool | Returns the amount of alpha in the pool. + + /// --- MAP ( netuid ) --> alpha_supply_in_pool | Returns the amount of alpha in the pool. + #[pallet::storage] pub type SubnetAlphaIn = StorageMap<_, Identity, NetUid, AlphaCurrency, ValueQuery, DefaultZeroAlpha>; - #[pallet::storage] // --- MAP ( netuid ) --> alpha_supply_user_in_pool | Returns the amount of alpha in the pool provided by users as liquidity. + + /// --- MAP ( netuid ) --> alpha_supply_user_in_pool | Returns the amount of alpha in the pool provided by users as liquidity. + #[pallet::storage] pub type SubnetAlphaInProvided = StorageMap<_, Identity, NetUid, AlphaCurrency, ValueQuery, DefaultZeroAlpha>; - #[pallet::storage] + /// --- MAP ( netuid ) --> alpha_supply_in_subnet | Returns the amount of alpha in the subnet. + #[pallet::storage] pub type SubnetAlphaOut = StorageMap<_, Identity, NetUid, AlphaCurrency, ValueQuery, DefaultZeroAlpha>; - #[pallet::storage] // --- MAP ( cold ) --> Vec | Maps coldkey to hotkeys that stake to it + + /// --- MAP ( cold ) --> Vec | Maps coldkey to hotkeys that stake to it + #[pallet::storage] pub type StakingHotkeys = StorageMap<_, Blake2_128Concat, T::AccountId, Vec, ValueQuery>; - #[pallet::storage] // --- MAP ( cold ) --> Vec | Returns the vector of hotkeys controlled by this coldkey. + + /// --- MAP ( cold ) --> Vec | Returns the vector of hotkeys controlled by this coldkey. + #[pallet::storage] pub type OwnedHotkeys = StorageMap<_, Blake2_128Concat, T::AccountId, Vec, ValueQuery>; - #[pallet::storage] // --- DMAP ( cold, netuid )--> hot | Returns the hotkey a coldkey will autostake to with mining rewards. + + /// --- DMAP ( cold, netuid )--> hot | Returns the hotkey a coldkey will autostake to with mining rewards. + #[pallet::storage] pub type AutoStakeDestination = StorageDoubleMap< _, Blake2_128Concat, @@ -1199,7 +1345,9 @@ pub mod pallet { T::AccountId, OptionQuery, >; - #[pallet::storage] // --- DMAP ( hot, netuid )--> Vec | Returns a list of coldkeys that are autostaking to a hotkey. + + /// --- DMAP ( hot, netuid )--> Vec | Returns a list of coldkeys that are autostaking to a hotkey + #[pallet::storage] pub type AutoStakeDestinationColdkeys = StorageDoubleMap< _, Blake2_128Concat, @@ -1210,7 +1358,8 @@ pub mod pallet { ValueQuery, >; - #[pallet::storage] // --- DMAP ( cold ) --> (block_expected, new_coldkey) | Maps coldkey to the block to swap at and new coldkey. + /// --- DMAP ( cold ) --> (block_expected, new_coldkey), Maps coldkey to the block to swap at and new coldkey. + #[pallet::storage] pub type ColdkeySwapScheduled = StorageMap< _, Blake2_128Concat, @@ -1220,7 +1369,8 @@ pub mod pallet { DefaultColdkeySwapScheduled, >; - #[pallet::storage] // --- DMAP ( hot, netuid ) --> alpha | Returns the total amount of alpha a hotkey owns. + /// --- DMAP ( hot, netuid ) --> alpha | Returns the total amount of alpha a hotkey owns. + #[pallet::storage] pub type TotalHotkeyAlpha = StorageDoubleMap< _, Blake2_128Concat, @@ -1231,7 +1381,9 @@ pub mod pallet { ValueQuery, DefaultZeroAlpha, >; - #[pallet::storage] // --- DMAP ( hot, netuid ) --> alpha | Returns the total amount of alpha a hotkey owned in the last epoch. + + /// --- DMAP ( hot, netuid ) --> alpha | Returns the total amount of alpha a hotkey owned in the last epoch. + #[pallet::storage] pub type TotalHotkeyAlphaLastEpoch = StorageDoubleMap< _, Blake2_128Concat, @@ -1242,8 +1394,9 @@ pub mod pallet { ValueQuery, DefaultZeroAlpha, >; - #[pallet::storage] + /// DMAP ( hot, netuid ) --> total_alpha_shares | Returns the number of alpha shares for a hotkey on a subnet. + #[pallet::storage] pub type TotalHotkeyShares = StorageDoubleMap< _, Blake2_128Concat, @@ -1254,7 +1407,9 @@ pub mod pallet { ValueQuery, DefaultSharePoolZero, >; - #[pallet::storage] // --- NMAP ( hot, cold, netuid ) --> alpha | Returns the alpha shares for a hotkey, coldkey, netuid triplet. + + /// --- NMAP ( hot, cold, netuid ) --> alpha | Returns the alpha shares for a hotkey, coldkey, netuid triplet. + #[pallet::storage] pub type Alpha = StorageNMap< _, ( @@ -1266,22 +1421,28 @@ pub mod pallet { ValueQuery, >; - #[pallet::storage] // Contains last Alpha storage map key to iterate (check first) + /// Contains last Alpha storage map key to iterate (check first) + #[pallet::storage] pub type AlphaMapLastKey = StorageValue<_, Option>, ValueQuery, DefaultAlphaIterationLastKey>; - #[pallet::storage] // --- MAP ( netuid ) --> token_symbol | Returns the token symbol for a subnet. + /// --- MAP ( netuid ) --> token_symbol | Returns the token symbol for a subnet. + #[pallet::storage] pub type TokenSymbol = StorageMap<_, Identity, NetUid, Vec, ValueQuery, DefaultUnicodeVecU8>; - #[pallet::storage] // --- MAP ( netuid ) --> subnet_tao_flow | Returns the TAO inflow-outflow balance. + /// --- MAP ( netuid ) --> subnet_tao_flow | Returns the TAO inflow-outflow balance. + #[pallet::storage] pub type SubnetTaoFlow = StorageMap<_, Identity, NetUid, i64, ValueQuery, DefaultZeroI64>; - #[pallet::storage] // --- MAP ( netuid ) --> subnet_ema_tao_flow | Returns the EMA of TAO inflow-outflow balance. + + /// --- MAP ( netuid ) --> subnet_ema_tao_flow | Returns the EMA of TAO inflow-outflow balance. + #[pallet::storage] pub type SubnetEmaTaoFlow = StorageMap<_, Identity, NetUid, (u64, I64F64), OptionQuery>; - #[pallet::type_value] + /// Default value for flow cutoff. + #[pallet::type_value] pub fn DefaultFlowCutoff() -> I64F64 { I64F64::saturating_from_num(0) } @@ -1319,72 +1480,87 @@ pub mod pallet { /// ============================ /// ==== Global Parameters ===== /// ============================ - #[pallet::storage] /// --- StorageItem Global Used Work. - pub type UsedWork = StorageMap<_, Identity, Vec, u64, ValueQuery>; #[pallet::storage] + pub type UsedWork = StorageMap<_, Identity, Vec, u64, ValueQuery>; + /// --- ITEM( global_max_registrations_per_block ) + #[pallet::storage] pub type MaxRegistrationsPerBlock = StorageMap<_, Identity, NetUid, u16, ValueQuery, DefaultMaxRegistrationsPerBlock>; - #[pallet::storage] + /// --- ITEM( total_number_of_existing_networks ) - pub type TotalNetworks = StorageValue<_, u16, ValueQuery>; #[pallet::storage] + pub type TotalNetworks = StorageValue<_, u16, ValueQuery>; + /// ITEM( network_immunity_period ) + #[pallet::storage] pub type NetworkImmunityPeriod = StorageValue<_, u64, ValueQuery, DefaultNetworkImmunityPeriod>; - #[pallet::storage] + /// ITEM( min_network_lock_cost ) + #[pallet::storage] pub type NetworkMinLockCost = StorageValue<_, TaoCurrency, ValueQuery, DefaultNetworkMinLockCost>; - #[pallet::storage] + /// ITEM( last_network_lock_cost ) + #[pallet::storage] pub type NetworkLastLockCost = StorageValue<_, TaoCurrency, ValueQuery, DefaultNetworkMinLockCost>; - #[pallet::storage] + /// ITEM( network_lock_reduction_interval ) + #[pallet::storage] pub type NetworkLockReductionInterval = StorageValue<_, u64, ValueQuery, DefaultNetworkLockReductionInterval>; - #[pallet::storage] + /// ITEM( subnet_owner_cut ) - pub type SubnetOwnerCut = StorageValue<_, u16, ValueQuery, DefaultSubnetOwnerCut>; #[pallet::storage] + pub type SubnetOwnerCut = StorageValue<_, u16, ValueQuery, DefaultSubnetOwnerCut>; + /// ITEM( network_rate_limit ) - pub type NetworkRateLimit = StorageValue<_, u64, ValueQuery, DefaultNetworkRateLimit>; #[pallet::storage] + pub type NetworkRateLimit = StorageValue<_, u64, ValueQuery, DefaultNetworkRateLimit>; + /// --- ITEM( nominator_min_required_stake ) --- Factor of DefaultMinStake in per-mill format. - pub type NominatorMinRequiredStake = StorageValue<_, u64, ValueQuery, DefaultZeroU64>; #[pallet::storage] + pub type NominatorMinRequiredStake = StorageValue<_, u64, ValueQuery, DefaultZeroU64>; + /// ITEM( weights_version_key_rate_limit ) --- Rate limit in tempos. + #[pallet::storage] pub type WeightsVersionKeyRateLimit = StorageValue<_, u64, ValueQuery, DefaultWeightsVersionKeyRateLimit>; /// ============================ /// ==== Rate Limiting ===== /// ============================ - - #[pallet::storage] /// --- MAP ( RateLimitKey ) --> Block number in which the last rate limited operation occured + #[pallet::storage] pub type LastRateLimitedBlock = StorageMap<_, Identity, RateLimitKey, u64, ValueQuery, DefaultZeroU64>; /// ============================ /// ==== Subnet Locks ===== /// ============================ - #[pallet::storage] // --- MAP ( netuid ) --> transfer_toggle + /// --- MAP ( netuid ) --> transfer_toggle + #[pallet::storage] pub type TransferToggle = StorageMap<_, Identity, NetUid, bool, ValueQuery, DefaultTrue>; - #[pallet::storage] // --- MAP ( netuid ) --> total_subnet_locked + + /// --- MAP ( netuid ) --> total_subnet_locked + #[pallet::storage] pub type SubnetLocked = StorageMap<_, Identity, NetUid, TaoCurrency, ValueQuery, DefaultZeroTao>; - #[pallet::storage] // --- MAP ( netuid ) --> largest_locked + + /// --- MAP ( netuid ) --> largest_locked + #[pallet::storage] pub type LargestLocked = StorageMap<_, Identity, NetUid, u64, ValueQuery, DefaultZeroU64>; /// ================= /// ==== Tempos ===== /// ================= - #[pallet::storage] // --- MAP ( netuid ) --> tempo + /// --- MAP ( netuid ) --> tempo + #[pallet::storage] pub type Tempo = StorageMap<_, Identity, NetUid, u16, ValueQuery, DefaultTempo>; /// ============================ @@ -1394,19 +1570,23 @@ pub mod pallet { #[pallet::storage] pub type FirstEmissionBlockNumber = StorageMap<_, Identity, NetUid, u64, OptionQuery>; + /// --- MAP ( netuid ) --> subnet mechanism #[pallet::storage] pub type SubnetMechanism = StorageMap<_, Identity, NetUid, u16, ValueQuery, DefaultZeroU16>; - #[pallet::storage] + /// --- MAP ( netuid ) --> subnetwork_n (Number of UIDs in the network). - pub type SubnetworkN = StorageMap<_, Identity, NetUid, u16, ValueQuery, DefaultN>; #[pallet::storage] + pub type SubnetworkN = StorageMap<_, Identity, NetUid, u16, ValueQuery, DefaultN>; + /// --- MAP ( netuid ) --> network_is_added + #[pallet::storage] pub type NetworksAdded = StorageMap<_, Identity, NetUid, bool, ValueQuery, DefaultNeworksAdded>; - #[pallet::storage] + /// --- DMAP ( hotkey, netuid ) --> bool + #[pallet::storage] pub type IsNetworkMember = StorageDoubleMap< _, Blake2_128Concat, @@ -1417,94 +1597,117 @@ pub mod pallet { ValueQuery, DefaultIsNetworkMember, >; - #[pallet::storage] + /// --- MAP ( netuid ) --> network_registration_allowed + #[pallet::storage] pub type NetworkRegistrationAllowed = StorageMap<_, Identity, NetUid, bool, ValueQuery, DefaultRegistrationAllowed>; - #[pallet::storage] + /// --- MAP ( netuid ) --> network_pow_allowed + #[pallet::storage] pub type NetworkPowRegistrationAllowed = StorageMap<_, Identity, NetUid, bool, ValueQuery, DefaultRegistrationAllowed>; - #[pallet::storage] + /// --- MAP ( netuid ) --> block_created + #[pallet::storage] pub type NetworkRegisteredAt = StorageMap<_, Identity, NetUid, u64, ValueQuery, DefaultNetworkRegisteredAt>; - #[pallet::storage] + /// --- MAP ( netuid ) --> pending_server_emission + #[pallet::storage] pub type PendingServerEmission = StorageMap<_, Identity, NetUid, AlphaCurrency, ValueQuery, DefaultZeroAlpha>; + /// --- MAP ( netuid ) --> pending_validator_emission #[pallet::storage] pub type PendingValidatorEmission = StorageMap<_, Identity, NetUid, AlphaCurrency, ValueQuery, DefaultZeroAlpha>; + /// --- MAP ( netuid ) --> pending_root_alpha_emission #[pallet::storage] pub type PendingRootAlphaDivs = StorageMap<_, Identity, NetUid, AlphaCurrency, ValueQuery, DefaultZeroAlpha>; - #[pallet::storage] + /// --- MAP ( netuid ) --> pending_owner_cut + #[pallet::storage] pub type PendingOwnerCut = StorageMap<_, Identity, NetUid, AlphaCurrency, ValueQuery, DefaultZeroAlpha>; - #[pallet::storage] + /// --- MAP ( netuid ) --> blocks_since_last_step + #[pallet::storage] pub type BlocksSinceLastStep = StorageMap<_, Identity, NetUid, u64, ValueQuery, DefaultBlocksSinceLastStep>; - #[pallet::storage] + /// --- MAP ( netuid ) --> last_mechanism_step_block + #[pallet::storage] pub type LastMechansimStepBlock = StorageMap<_, Identity, NetUid, u64, ValueQuery, DefaultLastMechanismStepBlock>; - #[pallet::storage] + /// --- MAP ( netuid ) --> subnet_owner + #[pallet::storage] pub type SubnetOwner = StorageMap<_, Identity, NetUid, T::AccountId, ValueQuery, DefaultSubnetOwner>; - #[pallet::storage] + /// --- MAP ( netuid ) --> subnet_owner_hotkey + #[pallet::storage] pub type SubnetOwnerHotkey = StorageMap<_, Identity, NetUid, T::AccountId, ValueQuery, DefaultSubnetOwner>; - #[pallet::storage] + /// --- MAP ( netuid ) --> recycle_or_burn + #[pallet::storage] pub type RecycleOrBurn = StorageMap<_, Identity, NetUid, RecycleOrBurnEnum, ValueQuery, DefaultRecycleOrBurn>; - #[pallet::storage] + /// --- MAP ( netuid ) --> serving_rate_limit + #[pallet::storage] pub type ServingRateLimit = StorageMap<_, Identity, NetUid, u64, ValueQuery, DefaultServingRateLimit>; - #[pallet::storage] + /// --- MAP ( netuid ) --> Rho - pub type Rho = StorageMap<_, Identity, NetUid, u16, ValueQuery, DefaultRho>; #[pallet::storage] + pub type Rho = StorageMap<_, Identity, NetUid, u16, ValueQuery, DefaultRho>; + /// --- MAP ( netuid ) --> AlphaSigmoidSteepness + #[pallet::storage] pub type AlphaSigmoidSteepness = StorageMap<_, Identity, NetUid, i16, ValueQuery, DefaultAlphaSigmoidSteepness>; - #[pallet::storage] + /// --- MAP ( netuid ) --> Kappa - pub type Kappa = StorageMap<_, Identity, NetUid, u16, ValueQuery, DefaultKappa>; #[pallet::storage] + pub type Kappa = StorageMap<_, Identity, NetUid, u16, ValueQuery, DefaultKappa>; + /// --- MAP ( netuid ) --> registrations_this_interval + #[pallet::storage] pub type RegistrationsThisInterval = StorageMap<_, Identity, NetUid, u16, ValueQuery>; - #[pallet::storage] + /// --- MAP ( netuid ) --> pow_registrations_this_interval + #[pallet::storage] pub type POWRegistrationsThisInterval = StorageMap<_, Identity, NetUid, u16, ValueQuery>; - #[pallet::storage] + /// --- MAP ( netuid ) --> burn_registrations_this_interval + #[pallet::storage] pub type BurnRegistrationsThisInterval = StorageMap<_, Identity, NetUid, u16, ValueQuery>; - #[pallet::storage] + /// --- MAP ( netuid ) --> min_allowed_uids + #[pallet::storage] pub type MinAllowedUids = StorageMap<_, Identity, NetUid, u16, ValueQuery, DefaultMinAllowedUids>; - #[pallet::storage] + /// --- MAP ( netuid ) --> max_allowed_uids + #[pallet::storage] pub type MaxAllowedUids = StorageMap<_, Identity, NetUid, u16, ValueQuery, DefaultMaxAllowedUids>; - #[pallet::storage] + /// --- MAP ( netuid ) --> immunity_period + #[pallet::storage] pub type ImmunityPeriod = StorageMap<_, Identity, NetUid, u16, ValueQuery, DefaultImmunityPeriod>; - #[pallet::storage] + /// --- MAP ( netuid ) --> activity_cutoff + #[pallet::storage] pub type ActivityCutoff = StorageMap<_, Identity, NetUid, u16, ValueQuery, DefaultActivityCutoff>; #[pallet::type_value] @@ -1512,98 +1715,122 @@ pub mod pallet { pub fn DefaultMaxWeightsLimit() -> u16 { u16::MAX } - #[pallet::storage] + /// --- MAP ( netuid ) --> max_weight_limit + #[pallet::storage] pub type MaxWeightsLimit = StorageMap<_, Identity, NetUid, u16, ValueQuery, DefaultMaxWeightsLimit>; - #[pallet::storage] + /// --- MAP ( netuid ) --> weights_version_key + #[pallet::storage] pub type WeightsVersionKey = StorageMap<_, Identity, NetUid, u64, ValueQuery, DefaultWeightsVersionKey>; - #[pallet::storage] + /// --- MAP ( netuid ) --> min_allowed_weights + #[pallet::storage] pub type MinAllowedWeights = StorageMap<_, Identity, NetUid, u16, ValueQuery, DefaultMinAllowedWeights>; - #[pallet::storage] + /// --- MAP ( netuid ) --> max_allowed_validators + #[pallet::storage] pub type MaxAllowedValidators = StorageMap<_, Identity, NetUid, u16, ValueQuery, DefaultMaxAllowedValidators>; - #[pallet::storage] + /// --- MAP ( netuid ) --> adjustment_interval + #[pallet::storage] pub type AdjustmentInterval = StorageMap<_, Identity, NetUid, u16, ValueQuery, DefaultAdjustmentInterval>; - #[pallet::storage] + /// --- MAP ( netuid ) --> bonds_moving_average + #[pallet::storage] pub type BondsMovingAverage = StorageMap<_, Identity, NetUid, u64, ValueQuery, DefaultBondsMovingAverage>; - #[pallet::storage] + /// --- MAP ( netuid ) --> bonds_penalty + #[pallet::storage] pub type BondsPenalty = StorageMap<_, Identity, NetUid, u16, ValueQuery, DefaultBondsPenalty>; - #[pallet::storage] + /// --- MAP ( netuid ) --> bonds_reset + #[pallet::storage] pub type BondsResetOn = StorageMap<_, Identity, NetUid, bool, ValueQuery, DefaultBondsResetOn>; + /// --- MAP ( netuid ) --> weights_set_rate_limit #[pallet::storage] pub type WeightsSetRateLimit = StorageMap<_, Identity, NetUid, u64, ValueQuery, DefaultWeightsSetRateLimit>; - #[pallet::storage] + /// --- MAP ( netuid ) --> validator_prune_len + #[pallet::storage] pub type ValidatorPruneLen = StorageMap<_, Identity, NetUid, u64, ValueQuery, DefaultValidatorPruneLen>; - #[pallet::storage] + /// --- MAP ( netuid ) --> scaling_law_power + #[pallet::storage] pub type ScalingLawPower = StorageMap<_, Identity, NetUid, u16, ValueQuery, DefaultScalingLawPower>; - #[pallet::storage] + /// --- MAP ( netuid ) --> target_registrations_this_interval + #[pallet::storage] pub type TargetRegistrationsPerInterval = StorageMap<_, Identity, NetUid, u16, ValueQuery, DefaultTargetRegistrationsPerInterval>; - #[pallet::storage] + /// --- MAP ( netuid ) --> adjustment_alpha + #[pallet::storage] pub type AdjustmentAlpha = StorageMap<_, Identity, NetUid, u64, ValueQuery, DefaultAdjustmentAlpha>; - #[pallet::storage] + /// --- MAP ( netuid ) --> commit reveal v2 weights are enabled + #[pallet::storage] pub type CommitRevealWeightsEnabled = StorageMap<_, Identity, NetUid, bool, ValueQuery, DefaultCommitRevealWeightsEnabled>; - #[pallet::storage] + /// --- MAP ( netuid ) --> Burn - pub type Burn = StorageMap<_, Identity, NetUid, TaoCurrency, ValueQuery, DefaultBurn>; #[pallet::storage] + pub type Burn = StorageMap<_, Identity, NetUid, TaoCurrency, ValueQuery, DefaultBurn>; + /// --- MAP ( netuid ) --> Difficulty - pub type Difficulty = StorageMap<_, Identity, NetUid, u64, ValueQuery, DefaultDifficulty>; #[pallet::storage] + pub type Difficulty = StorageMap<_, Identity, NetUid, u64, ValueQuery, DefaultDifficulty>; + /// --- MAP ( netuid ) --> MinBurn + #[pallet::storage] pub type MinBurn = StorageMap<_, Identity, NetUid, TaoCurrency, ValueQuery, DefaultMinBurn>; - #[pallet::storage] + /// --- MAP ( netuid ) --> MaxBurn + #[pallet::storage] pub type MaxBurn = StorageMap<_, Identity, NetUid, TaoCurrency, ValueQuery, DefaultMaxBurn>; - #[pallet::storage] + /// --- MAP ( netuid ) --> MinDifficulty + #[pallet::storage] pub type MinDifficulty = StorageMap<_, Identity, NetUid, u64, ValueQuery, DefaultMinDifficulty>; - #[pallet::storage] + /// --- MAP ( netuid ) --> MaxDifficulty + #[pallet::storage] pub type MaxDifficulty = StorageMap<_, Identity, NetUid, u64, ValueQuery, DefaultMaxDifficulty>; - #[pallet::storage] + /// --- MAP ( netuid ) --> Block at last adjustment. + #[pallet::storage] pub type LastAdjustmentBlock = StorageMap<_, Identity, NetUid, u64, ValueQuery, DefaultLastAdjustmentBlock>; - #[pallet::storage] + /// --- MAP ( netuid ) --> Registrations of this Block. + #[pallet::storage] pub type RegistrationsThisBlock = StorageMap<_, Identity, NetUid, u16, ValueQuery, DefaultRegistrationsThisBlock>; - #[pallet::storage] + /// --- MAP ( netuid ) --> Halving time of average moving price. + #[pallet::storage] pub type EMAPriceHalvingBlocks = StorageMap<_, Identity, NetUid, u64, ValueQuery, DefaultEMAPriceMovingBlocks>; - #[pallet::storage] + /// --- MAP ( netuid ) --> global_RAO_recycled_for_registration + #[pallet::storage] pub type RAORecycledForRegistration = StorageMap< _, Identity, @@ -1612,66 +1839,79 @@ pub mod pallet { ValueQuery, DefaultRAORecycledForRegistration, >; - #[pallet::storage] + /// --- ITEM ( tx_rate_limit ) - pub type TxRateLimit = StorageValue<_, u64, ValueQuery, DefaultTxRateLimit>; #[pallet::storage] + pub type TxRateLimit = StorageValue<_, u64, ValueQuery, DefaultTxRateLimit>; + /// --- ITEM ( tx_delegate_take_rate_limit ) + #[pallet::storage] pub type TxDelegateTakeRateLimit = StorageValue<_, u64, ValueQuery, DefaultTxDelegateTakeRateLimit>; - #[pallet::storage] + /// --- ITEM ( tx_childkey_take_rate_limit ) + #[pallet::storage] pub type TxChildkeyTakeRateLimit = StorageValue<_, u64, ValueQuery, DefaultTxChildKeyTakeRateLimit>; - #[pallet::storage] + /// --- MAP ( netuid ) --> Whether or not Liquid Alpha is enabled + #[pallet::storage] pub type LiquidAlphaOn = StorageMap<_, Blake2_128Concat, NetUid, bool, ValueQuery, DefaultLiquidAlpha>; - #[pallet::storage] + /// --- MAP ( netuid ) --> Whether or not Yuma3 is enabled + #[pallet::storage] pub type Yuma3On = StorageMap<_, Blake2_128Concat, NetUid, bool, ValueQuery, DefaultYuma3>; - #[pallet::storage] + /// MAP ( netuid ) --> (alpha_low, alpha_high) + #[pallet::storage] pub type AlphaValues = StorageMap<_, Identity, NetUid, (u16, u16), ValueQuery, DefaultAlphaValues>; - #[pallet::storage] + /// --- MAP ( netuid ) --> If subtoken trading enabled + #[pallet::storage] pub type SubtokenEnabled = StorageMap<_, Identity, NetUid, bool, ValueQuery, DefaultFalse>; - #[pallet::type_value] /// Default value for burn keys limit + #[pallet::type_value] pub fn DefaultImmuneOwnerUidsLimit() -> u16 { 1 } - #[pallet::type_value] + /// Maximum value for burn keys limit + #[pallet::type_value] pub fn MaxImmuneOwnerUidsLimit() -> u16 { 10 } - #[pallet::type_value] + /// Minimum value for burn keys limit + #[pallet::type_value] pub fn MinImmuneOwnerUidsLimit() -> u16 { 1 } - #[pallet::storage] + /// --- MAP ( netuid ) --> Burn key limit + #[pallet::storage] pub type ImmuneOwnerUidsLimit = StorageMap<_, Identity, NetUid, u16, ValueQuery, DefaultImmuneOwnerUidsLimit>; /// ======================================= /// ==== Subnetwork Consensus Storage ==== /// ======================================= - #[pallet::storage] // --- DMAP ( netuid ) --> stake_weight | weight for stake used in YC. + /// --- DMAP ( netuid ) --> stake_weight | weight for stake used in YC. + #[pallet::storage] pub type StakeWeight = StorageMap<_, Identity, NetUid, Vec, ValueQuery, EmptyU16Vec>; - #[pallet::storage] + /// --- DMAP ( netuid, hotkey ) --> uid + #[pallet::storage] pub type Uids = StorageDoubleMap<_, Identity, NetUid, Blake2_128Concat, T::AccountId, u16, OptionQuery>; - #[pallet::storage] + /// --- DMAP ( netuid, uid ) --> hotkey + #[pallet::storage] pub type Keys = StorageDoubleMap< _, Identity, @@ -1682,55 +1922,68 @@ pub mod pallet { ValueQuery, DefaultKey, >; - #[pallet::storage] + /// --- MAP ( netuid ) --> (hotkey, se, ve) + #[pallet::storage] pub type LoadedEmission = StorageMap<_, Identity, NetUid, Vec<(T::AccountId, u64, u64)>, OptionQuery>; - #[pallet::storage] + /// --- MAP ( netuid ) --> active + #[pallet::storage] pub type Active = StorageMap<_, Identity, NetUid, Vec, ValueQuery, EmptyBoolVec>; - #[pallet::storage] + /// --- MAP ( netuid ) --> rank + #[pallet::storage] pub type Rank = StorageMap<_, Identity, NetUid, Vec, ValueQuery, EmptyU16Vec>; - #[pallet::storage] + /// --- MAP ( netuid ) --> trust + #[pallet::storage] pub type Trust = StorageMap<_, Identity, NetUid, Vec, ValueQuery, EmptyU16Vec>; - #[pallet::storage] + /// --- MAP ( netuid ) --> consensus + #[pallet::storage] pub type Consensus = StorageMap<_, Identity, NetUid, Vec, ValueQuery, EmptyU16Vec>; - #[pallet::storage] + /// --- MAP ( netuid ) --> incentive + #[pallet::storage] pub type Incentive = StorageMap<_, Identity, NetUidStorageIndex, Vec, ValueQuery, EmptyU16Vec>; - #[pallet::storage] + /// --- MAP ( netuid ) --> dividends + #[pallet::storage] pub type Dividends = StorageMap<_, Identity, NetUid, Vec, ValueQuery, EmptyU16Vec>; - #[pallet::storage] + /// --- MAP ( netuid ) --> emission - pub type Emission = StorageMap<_, Identity, NetUid, Vec, ValueQuery>; #[pallet::storage] + pub type Emission = StorageMap<_, Identity, NetUid, Vec, ValueQuery>; + /// --- MAP ( netuid ) --> last_update + #[pallet::storage] pub type LastUpdate = StorageMap<_, Identity, NetUidStorageIndex, Vec, ValueQuery, EmptyU64Vec>; - #[pallet::storage] + /// --- MAP ( netuid ) --> validator_trust + #[pallet::storage] pub type ValidatorTrust = StorageMap<_, Identity, NetUid, Vec, ValueQuery, EmptyU16Vec>; - #[pallet::storage] + /// --- MAP ( netuid ) --> pruning_scores + #[pallet::storage] pub type PruningScores = StorageMap<_, Identity, NetUid, Vec, ValueQuery, EmptyU16Vec>; - #[pallet::storage] + /// --- MAP ( netuid ) --> validator_permit + #[pallet::storage] pub type ValidatorPermit = StorageMap<_, Identity, NetUid, Vec, ValueQuery, EmptyBoolVec>; - #[pallet::storage] + /// --- DMAP ( netuid, uid ) --> weights + #[pallet::storage] pub type Weights = StorageDoubleMap< _, Identity, @@ -1741,8 +1994,9 @@ pub mod pallet { ValueQuery, DefaultWeights, >; - #[pallet::storage] + /// --- DMAP ( netuid, uid ) --> bonds + #[pallet::storage] pub type Bonds = StorageDoubleMap< _, Identity, @@ -1753,8 +2007,9 @@ pub mod pallet { ValueQuery, DefaultBonds, >; - #[pallet::storage] + /// --- DMAP ( netuid, uid ) --> block_at_registration + #[pallet::storage] pub type BlockAtRegistration = StorageDoubleMap< _, Identity, @@ -1765,8 +2020,9 @@ pub mod pallet { ValueQuery, DefaultBlockAtRegistration, >; - #[pallet::storage] + /// --- MAP ( netuid, hotkey ) --> axon_info + #[pallet::storage] pub type Axons = StorageDoubleMap< _, Identity, @@ -1776,6 +2032,7 @@ pub mod pallet { AxonInfoOf, OptionQuery, >; + /// --- MAP ( netuid, hotkey ) --> certificate #[pallet::storage] pub type NeuronCertificates = StorageDoubleMap< @@ -1787,8 +2044,9 @@ pub mod pallet { NeuronCertificateOf, OptionQuery, >; - #[pallet::storage] + /// --- MAP ( netuid, hotkey ) --> prometheus_info + #[pallet::storage] pub type Prometheus = StorageDoubleMap< _, Identity, @@ -1798,30 +2056,22 @@ pub mod pallet { PrometheusInfoOf, OptionQuery, >; - #[pallet::storage] // --- MAP ( coldkey ) --> identity. (DEPRECATED for V2) - pub type Identities = - StorageMap<_, Blake2_128Concat, T::AccountId, ChainIdentityOf, OptionQuery>; - #[pallet::storage] // --- MAP ( coldkey ) --> identity + /// --- MAP ( coldkey ) --> identity + #[pallet::storage] pub type IdentitiesV2 = StorageMap<_, Blake2_128Concat, T::AccountId, ChainIdentityOfV2, OptionQuery>; - #[pallet::storage] // --- MAP ( netuid ) --> identity. (DEPRECATED for V2) - pub type SubnetIdentities = - StorageMap<_, Blake2_128Concat, NetUid, SubnetIdentityOf, OptionQuery>; - - #[pallet::storage] // --- MAP ( netuid ) --> identityV2 (DEPRECATED for V3) - pub type SubnetIdentitiesV2 = - StorageMap<_, Blake2_128Concat, NetUid, SubnetIdentityOfV2, OptionQuery>; - - #[pallet::storage] // --- MAP ( netuid ) --> SubnetIdentityOfV3 + /// --- MAP ( netuid ) --> SubnetIdentityOfV3 + #[pallet::storage] pub type SubnetIdentitiesV3 = StorageMap<_, Blake2_128Concat, NetUid, SubnetIdentityOfV3, OptionQuery>; /// ================================= /// ==== Axon / Promo Endpoints ===== /// ================================= - #[pallet::storage] // --- NMAP ( hot, netuid, name ) --> last_block | Returns the last block of a transaction for a given key, netuid, and name. + /// --- NMAP ( hot, netuid, name ) --> last_block | Returns the last block of a transaction for a given key, netuid, and name. + #[pallet::storage] pub type TransactionKeyLastBlock = StorageNMap< _, ( @@ -1832,27 +2082,32 @@ pub mod pallet { u64, ValueQuery, >; + + /// --- MAP ( key ) --> last_block #[deprecated] #[pallet::storage] - /// --- MAP ( key ) --> last_block pub type LastTxBlock = StorageMap<_, Identity, T::AccountId, u64, ValueQuery, DefaultLastTxBlock>; + + /// --- MAP ( key ) --> last_tx_block_childkey_take #[deprecated] #[pallet::storage] - /// --- MAP ( key ) --> last_tx_block_childkey_take pub type LastTxBlockChildKeyTake = StorageMap<_, Identity, T::AccountId, u64, ValueQuery, DefaultLastTxBlock>; + + /// --- MAP ( key ) --> last_tx_block_delegate_take #[deprecated] #[pallet::storage] - /// --- MAP ( key ) --> last_tx_block_delegate_take pub type LastTxBlockDelegateTake = StorageMap<_, Identity, T::AccountId, u64, ValueQuery, DefaultLastTxBlock>; + + /// ITEM( weights_min_stake ) // FIXME: this storage is used interchangably for alpha/tao #[pallet::storage] - /// ITEM( weights_min_stake ) pub type StakeThreshold = StorageValue<_, u64, ValueQuery, DefaultStakeThreshold>; - #[pallet::storage] + /// --- MAP (netuid, who) --> VecDeque<(hash, commit_block, first_reveal_block, last_reveal_block)> | Stores a queue of commits for an account on a given netuid. + #[pallet::storage] pub type WeightCommits = StorageDoubleMap< _, Twox64Concat, @@ -1862,9 +2117,10 @@ pub mod pallet { VecDeque<(H256, u64, u64, u64)>, OptionQuery, >; - #[pallet::storage] + /// MAP (netuid, epoch) → VecDeque<(who, commit_block, ciphertext, reveal_round)> /// Stores a queue of weight commits for an account on a given subnet. + #[pallet::storage] pub type TimelockedWeightCommits = StorageDoubleMap< _, Twox64Concat, @@ -1879,9 +2135,10 @@ pub mod pallet { )>, ValueQuery, >; - #[pallet::storage] + /// MAP (netuid, epoch) → VecDeque<(who, ciphertext, reveal_round)> /// DEPRECATED for CRV3WeightCommitsV2 + #[pallet::storage] pub type CRV3WeightCommits = StorageDoubleMap< _, Twox64Concat, @@ -1895,9 +2152,10 @@ pub mod pallet { )>, ValueQuery, >; - #[pallet::storage] + /// MAP (netuid, epoch) → VecDeque<(who, commit_block, ciphertext, reveal_round)> /// DEPRECATED for TimelockedWeightCommits + #[pallet::storage] pub type CRV3WeightCommitsV2 = StorageDoubleMap< _, Twox64Concat, @@ -1912,13 +2170,14 @@ pub mod pallet { )>, ValueQuery, >; - #[pallet::storage] + /// --- Map (netuid) --> Number of epochs allowed for commit reveal periods + #[pallet::storage] pub type RevealPeriodEpochs = StorageMap<_, Twox64Concat, NetUid, u64, ValueQuery, DefaultRevealPeriodEpochs>; - #[pallet::storage] /// --- Map (coldkey, hotkey) --> u64 the last block at which stake was added/removed. + #[pallet::storage] pub type LastColdkeyHotkeyStakeBlock = StorageDoubleMap< _, Twox64Concat, @@ -1929,9 +2188,9 @@ pub mod pallet { OptionQuery, >; - #[pallet::storage] /// DMAP ( hot, cold, netuid ) --> rate limits for staking operations /// Value contains just a marker: we use this map as a set. + #[pallet::storage] pub type StakingOperationRateLimiter = StorageNMap< _, ( @@ -1993,94 +2252,100 @@ pub mod pallet { /// ============================= /// ==== EVM related storage ==== /// ============================= - #[pallet::storage] /// --- DMAP (netuid, uid) --> (H160, last_block_where_ownership_was_proven) + #[pallet::storage] pub type AssociatedEvmAddress = StorageDoubleMap<_, Twox64Concat, NetUid, Twox64Concat, u16, (H160, u64), OptionQuery>; /// ======================== /// ==== Subnet Leasing ==== /// ======================== - #[pallet::storage] /// --- MAP ( lease_id ) --> subnet lease | The subnet lease for a given lease id. + #[pallet::storage] pub type SubnetLeases = StorageMap<_, Twox64Concat, LeaseId, SubnetLeaseOf, OptionQuery>; - #[pallet::storage] /// --- DMAP ( lease_id, contributor ) --> shares | The shares of a contributor for a given lease. + #[pallet::storage] pub type SubnetLeaseShares = StorageDoubleMap<_, Twox64Concat, LeaseId, Identity, T::AccountId, U64F64, ValueQuery>; + /// --- MAP ( netuid ) --> lease_id | The lease id for a given netuid. #[pallet::storage] - // --- MAP ( netuid ) --> lease_id | The lease id for a given netuid. pub type SubnetUidToLeaseId = StorageMap<_, Twox64Concat, NetUid, LeaseId, OptionQuery>; - #[pallet::storage] /// --- ITEM ( next_lease_id ) | The next lease id. + #[pallet::storage] pub type NextSubnetLeaseId = StorageValue<_, LeaseId, ValueQuery, ConstU32<0>>; - #[pallet::storage] /// --- MAP ( lease_id ) --> accumulated_dividends | The accumulated dividends for a given lease that needs to be distributed. + #[pallet::storage] pub type AccumulatedLeaseDividends = StorageMap<_, Twox64Concat, LeaseId, AlphaCurrency, ValueQuery, DefaultZeroAlpha>; - #[pallet::storage] /// --- ITEM ( CommitRevealWeightsVersion ) + #[pallet::storage] pub type CommitRevealWeightsVersion = StorageValue<_, u16, ValueQuery, DefaultCommitRevealWeightsVersion>; - #[pallet::storage] /// ITEM( NetworkRegistrationStartBlock ) + #[pallet::storage] pub type NetworkRegistrationStartBlock = StorageValue<_, u64, ValueQuery, DefaultNetworkRegistrationStartBlock>; /// ============================ /// ==== Subnet Mechanisms ===== /// ============================ - #[pallet::type_value] /// -- ITEM (Default number of sub-subnets) + #[pallet::type_value] pub fn DefaultMechanismCount() -> MechId { MechId::from(1) } - #[pallet::type_value] + /// -- ITEM (Maximum number of sub-subnets) + #[pallet::type_value] pub fn MaxMechanismCount() -> MechId { MechId::from(2) } - #[pallet::type_value] + /// -- ITEM (Rate limit for mechanism count updates) + #[pallet::type_value] pub fn MechanismCountSetRateLimit() -> u64 { prod_or_fast!(7_200, 1) } - #[pallet::type_value] + /// -- ITEM (Rate limit for mechanism emission distribution updates) + #[pallet::type_value] pub fn MechanismEmissionRateLimit() -> u64 { prod_or_fast!(7_200, 1) } - #[pallet::storage] + /// --- MAP ( netuid ) --> Current number of subnet mechanisms + #[pallet::storage] pub type MechanismCountCurrent = StorageMap<_, Twox64Concat, NetUid, MechId, ValueQuery, DefaultMechanismCount>; - #[pallet::storage] + /// --- MAP ( netuid ) --> Normalized vector of emission split proportion between subnet mechanisms + #[pallet::storage] pub type MechanismEmissionSplit = StorageMap<_, Twox64Concat, NetUid, Vec, OptionQuery>; /// ================== /// ==== Genesis ===== /// ================== - #[pallet::storage] // --- Storage for migration run status + /// --- Storage for migration run status + #[pallet::storage] pub type HasMigrationRun = StorageMap<_, Identity, Vec, bool, ValueQuery>; - #[pallet::type_value] /// Default value for pending childkey cooldown (settable by root, default 0) + #[pallet::type_value] pub fn DefaultPendingChildKeyCooldown() -> u64 { 0 } - #[pallet::storage] /// Storage value for pending childkey cooldown, settable by root. + #[pallet::storage] pub type PendingChildKeyCooldown = StorageValue<_, u64, ValueQuery, DefaultPendingChildKeyCooldown>; diff --git a/pallets/subtensor/src/macros/dispatches.rs b/pallets/subtensor/src/macros/dispatches.rs index d534dbb0c6..ef36b17921 100644 --- a/pallets/subtensor/src/macros/dispatches.rs +++ b/pallets/subtensor/src/macros/dispatches.rs @@ -712,7 +712,7 @@ mod dispatches { /// #[pallet::call_index(2)] #[pallet::weight((Weight::from_parts(340_800_000, 0) - .saturating_add(T::DbWeight::get().reads(25_u64)) + .saturating_add(T::DbWeight::get().reads(27_u64)) .saturating_add(T::DbWeight::get().writes(16_u64)), DispatchClass::Normal, Pays::Yes))] pub fn add_stake( origin: OriginFor, @@ -1084,7 +1084,7 @@ mod dispatches { #[pallet::call_index(71)] #[pallet::weight((Weight::from_parts(161_700_000, 0) .saturating_add(T::DbWeight::get().reads(16_u64)) - .saturating_add(T::DbWeight::get().writes(9)), DispatchClass::Operational, Pays::Yes))] + .saturating_add(T::DbWeight::get().writes(11_u64)), DispatchClass::Operational, Pays::Yes))] pub fn swap_coldkey( origin: OriginFor, old_coldkey: T::AccountId, @@ -1587,7 +1587,7 @@ mod dispatches { /// - Thrown if key has hit transaction rate limit #[pallet::call_index(84)] #[pallet::weight((Weight::from_parts(358_500_000, 0) - .saturating_add(T::DbWeight::get().reads(41_u64)) + .saturating_add(T::DbWeight::get().reads(44_u64)) .saturating_add(T::DbWeight::get().writes(26_u64)), DispatchClass::Normal, Pays::Yes))] pub fn unstake_all_alpha(origin: OriginFor, hotkey: T::AccountId) -> DispatchResult { Self::do_unstake_all_alpha(origin, hotkey) @@ -1701,7 +1701,7 @@ mod dispatches { #[pallet::call_index(87)] #[pallet::weight(( Weight::from_parts(351_300_000, 0) - .saturating_add(T::DbWeight::get().reads(37_u64)) + .saturating_add(T::DbWeight::get().reads(40_u64)) .saturating_add(T::DbWeight::get().writes(24_u64)), DispatchClass::Normal, Pays::Yes @@ -1766,7 +1766,7 @@ mod dispatches { /// #[pallet::call_index(88)] #[pallet::weight((Weight::from_parts(402_900_000, 0) - .saturating_add(T::DbWeight::get().reads(25_u64)) + .saturating_add(T::DbWeight::get().reads(27_u64)) .saturating_add(T::DbWeight::get().writes(16_u64)), DispatchClass::Normal, Pays::Yes))] pub fn add_stake_limit( origin: OriginFor, @@ -1830,7 +1830,7 @@ mod dispatches { /// #[pallet::call_index(89)] #[pallet::weight((Weight::from_parts(377_400_000, 0) - .saturating_add(T::DbWeight::get().reads(29_u64)) + .saturating_add(T::DbWeight::get().reads(31_u64)) .saturating_add(T::DbWeight::get().writes(15_u64)), DispatchClass::Normal, Pays::Yes))] pub fn remove_stake_limit( origin: OriginFor, @@ -1874,7 +1874,7 @@ mod dispatches { #[pallet::call_index(90)] #[pallet::weight(( Weight::from_parts(411_500_000, 0) - .saturating_add(T::DbWeight::get().reads(37_u64)) + .saturating_add(T::DbWeight::get().reads(40_u64)) .saturating_add(T::DbWeight::get().writes(24_u64)), DispatchClass::Normal, Pays::Yes @@ -2052,7 +2052,7 @@ mod dispatches { /// Without limit_price it remove all the stake similar to `remove_stake` extrinsic #[pallet::call_index(103)] #[pallet::weight((Weight::from_parts(395_300_000, 10142) - .saturating_add(T::DbWeight::get().reads(29_u64)) + .saturating_add(T::DbWeight::get().reads(31_u64)) .saturating_add(T::DbWeight::get().writes(15_u64)), DispatchClass::Normal, Pays::Yes))] pub fn remove_stake_full_limit( origin: T::RuntimeOrigin, @@ -2362,7 +2362,9 @@ mod dispatches { /// #[pallet::call_index(122)] #[pallet::weight(( - Weight::from_parts(19_420_000, 0).saturating_add(T::DbWeight::get().writes(4_u64)), + Weight::from_parts(19_420_000, 0) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(4_u64)), DispatchClass::Normal, Pays::Yes ))] @@ -2372,6 +2374,10 @@ mod dispatches { ) -> DispatchResult { let coldkey: T::AccountId = ensure_signed(origin)?; + if let RootClaimTypeEnum::KeepSubnets { subnets } = &new_root_claim_type { + ensure!(!subnets.is_empty(), Error::::InvalidSubnetNumber); + } + Self::maybe_add_coldkey_index(&coldkey); Self::change_root_claim_type(&coldkey, new_root_claim_type); @@ -2381,7 +2387,9 @@ mod dispatches { /// --- Sets root claim number (sudo extrinsic). Zero disables auto-claim. #[pallet::call_index(123)] #[pallet::weight(( - Weight::from_parts(4_000_000, 0).saturating_add(T::DbWeight::get().writes(1_u64)), + Weight::from_parts(4_000_000, 0) + .saturating_add(T::DbWeight::get().reads(0_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)), DispatchClass::Operational, Pays::Yes ))] @@ -2401,7 +2409,9 @@ mod dispatches { /// --- Sets root claim threshold for subnet (sudo or owner origin). #[pallet::call_index(124)] #[pallet::weight(( - Weight::from_parts(5_711_000, 0).saturating_add(T::DbWeight::get().writes(1_u64)), + Weight::from_parts(5_711_000, 0) + .saturating_add(T::DbWeight::get().reads(0_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)), DispatchClass::Operational, Pays::Yes ))] diff --git a/pallets/subtensor/src/macros/events.rs b/pallets/subtensor/src/macros/events.rs index c2931024ee..d015205d4d 100644 --- a/pallets/subtensor/src/macros/events.rs +++ b/pallets/subtensor/src/macros/events.rs @@ -467,5 +467,15 @@ mod events { /// Claim type root_claim_type: RootClaimTypeEnum, }, + + /// Subnet lease dividends have been distributed. + SubnetLeaseDividendsDistributed { + /// The lease ID + lease_id: LeaseId, + /// The contributor + contributor: T::AccountId, + /// The amount of alpha distributed + alpha: AlphaCurrency, + }, } } diff --git a/pallets/subtensor/src/macros/hooks.rs b/pallets/subtensor/src/macros/hooks.rs index 1b7d5fd77e..b62263e370 100644 --- a/pallets/subtensor/src/macros/hooks.rs +++ b/pallets/subtensor/src/macros/hooks.rs @@ -75,8 +75,6 @@ mod hooks { // Populate OwnedHotkeys map for coldkey swap. Doesn't update storage vesion. // Storage version v6 -> v7 .saturating_add(migrations::migrate_populate_owned_hotkeys::migrate_populate_owned::()) - // Migrate Delegate Ids on chain - .saturating_add(migrations::migrate_chain_identity::migrate_set_hotkey_identities::()) // Migrate Commit-Reval 2.0 .saturating_add(migrations::migrate_commit_reveal_v2::migrate_commit_reveal_2::()) // Migrate to RAO @@ -84,8 +82,6 @@ mod hooks { // Fix the IsNetworkMember map to be consistent with other storage maps .saturating_add(migrations::migrate_fix_is_network_member::migrate_fix_is_network_member::()) .saturating_add(migrations::migrate_subnet_volume::migrate_subnet_volume::()) - // Upgrade identities to V2 - .saturating_add(migrations::migrate_identities_v2::migrate_identities_to_v2::()) // Set the min burn across all subnets to a new minimum .saturating_add(migrations::migrate_set_min_burn::migrate_set_min_burn::()) // Set the min difficulty across all subnets to a new minimum @@ -121,8 +117,6 @@ mod hooks { .saturating_add(migrations::migrate_fix_root_subnet_tao::migrate_fix_root_subnet_tao::()) // Fix the owner disable the registration .saturating_add(migrations::migrate_set_registration_enable::migrate_set_registration_enable::()) - // Migrate Subnet Identities to V3 - .saturating_add(migrations::migrate_subnet_identities_to_v3::migrate_subnet_identities_to_v3::()) // Migrate subnet symbols to fix the shift after subnet 81 .saturating_add(migrations::migrate_subnet_symbols::migrate_subnet_symbols::()) // Migrate CRV3 add commit_block @@ -162,7 +156,11 @@ mod hooks { // Migrate pending emissions .saturating_add(migrations::migrate_pending_emissions::migrate_pending_emissions::()) // Reset unactive subnets - .saturating_add(migrations::migrate_reset_unactive_sn::migrate_reset_unactive_sn::()); + .saturating_add(migrations::migrate_reset_unactive_sn::migrate_reset_unactive_sn::()) + // Remove old identity map entries(Identities, SubnetIdentities, SubnetIdentitiesV2) + .saturating_add(migrations::migrate_remove_old_identity_maps::migrate_remove_old_identity_maps::()) + // Remove unknown neuron axon, certificate prom + .saturating_add(migrations::migrate_remove_unknown_neuron_axon_cert_prom::migrate_remove_unknown_neuron_axon_cert_prom::()); weight } diff --git a/pallets/subtensor/src/migrations/migrate_chain_identity.rs b/pallets/subtensor/src/migrations/migrate_chain_identity.rs deleted file mode 100644 index 735e63168c..0000000000 --- a/pallets/subtensor/src/migrations/migrate_chain_identity.rs +++ /dev/null @@ -1,171 +0,0 @@ -use crate::alloc::borrow::ToOwned; -use codec::Decode; -use scale_info::prelude::{string::String, vec::Vec}; -use serde::Deserialize; -use sp_core::{ConstU32, crypto::Ss58Codec}; -use sp_runtime::{AccountId32, BoundedVec}; - -use super::*; -use frame_support::{traits::Get, weights::Weight}; -use log; - -#[derive(Deserialize, Debug)] -struct RegistrationRecordJSON { - address: String, - name: String, - url: String, - description: String, -} - -fn string_to_bounded_vec(input: &str) -> Result>, &'static str> { - let vec_u8: Vec = input.to_owned().into_bytes(); - - // Check if the length is within bounds - if vec_u8.len() > 64 { - return Err("Input string is too long"); - } - - // Convert to BoundedVec - BoundedVec::>::try_from(vec_u8) - .map_err(|_| "Failed to convert to BoundedVec") -} - -pub fn migrate_set_hotkey_identities() -> Weight { - let migration_name = b"migrate_identities".to_vec(); - - // Initialize the weight with one read operation. - let mut weight = T::DbWeight::get().reads(1); - - // Check if the migration has already run - if HasMigrationRun::::get(&migration_name) { - log::info!( - "Migration '{:?}' has already run. Skipping.", - String::from_utf8_lossy(&migration_name) - ); - return weight; - } - log::info!( - "Running migration '{}'", - String::from_utf8_lossy(&migration_name) - ); - - // Include the JSON file with delegate info - let data = include_str!("../../../../docs/delegate-info.json"); - - // Iterate over all the delegate records - if let Ok(delegates) = serde_json::from_str::>(data) { - // Iterate through the delegates - for delegate in delegates.iter() { - // Convert fields to bounded vecs - let name_result = string_to_bounded_vec(&delegate.name); - let desc_result = string_to_bounded_vec(&delegate.description); - let url_result = string_to_bounded_vec(&delegate.url); - let hotkey: AccountId32 = match AccountId32::from_ss58check(&delegate.address) { - Ok(account) => account, - Err(_) => { - log::warn!( - "Invalid SS58 address: {:?}. Skipping this delegate.", - delegate.address - ); - continue; - } - }; - let decoded_hotkey: T::AccountId = match T::AccountId::decode(&mut hotkey.as_ref()) { - Ok(decoded) => decoded, - Err(e) => { - log::warn!("Failed to decode hotkey: {e:?}. Skipping this delegate."); - continue; - } - }; - log::info!("Hotkey unwrapped: {decoded_hotkey:?}"); - - // If we should continue with real values. - let mut name: BoundedVec> = BoundedVec::default(); - let mut description: BoundedVec> = BoundedVec::default(); - let mut url: BoundedVec> = BoundedVec::default(); - if let Ok(n) = name_result { - name = n; - } - if let Ok(d) = desc_result { - description = d; - } - if let Ok(u) = url_result { - url = u; - } - - // Unwrap the real values. - let image: BoundedVec> = BoundedVec::default(); - let discord: BoundedVec> = BoundedVec::default(); - let additional: BoundedVec> = BoundedVec::default(); - - // Create the chain identity. - let identity = ChainIdentityOf { - name: name.into(), - url: url.into(), - image: image.into(), - discord: discord.into(), - description: description.into(), - additional: additional.into(), - }; - - // Log the identity details - log::info!("Setting identity for hotkey: {hotkey:?}"); - log::info!("Name: {:?}", String::from_utf8_lossy(&identity.name)); - log::info!("URL: {:?}", String::from_utf8_lossy(&identity.url)); - log::info!("Image: {:?}", String::from_utf8_lossy(&identity.image)); - log::info!("Discord: {:?}", String::from_utf8_lossy(&identity.discord)); - log::info!( - "Description: {:?}", - String::from_utf8_lossy(&identity.description) - ); - log::info!( - "Additional: {:?}", - String::from_utf8_lossy(&identity.additional) - ); - - // Check validation. - let total_length = identity - .name - .len() - .saturating_add(identity.url.len()) - .saturating_add(identity.image.len()) - .saturating_add(identity.discord.len()) - .saturating_add(identity.description.len()) - .saturating_add(identity.additional.len()); - let is_valid: bool = total_length <= 256 + 256 + 1024 + 256 + 1024 + 1024 - && identity.name.len() <= 256 - && identity.url.len() <= 256 - && identity.image.len() <= 1024 - && identity.discord.len() <= 256 - && identity.description.len() <= 1024 - && identity.additional.len() <= 1024; - if !is_valid { - log::info!("Bytes not correct"); - continue; - } - - // Get the owning coldkey. - let coldkey = Owner::::get(decoded_hotkey.clone()); - log::info!("ColdKey: {decoded_hotkey:?}"); - - weight = weight.saturating_add(T::DbWeight::get().reads(1)); - - // Sink into the map. - Identities::::insert(coldkey.clone(), identity.clone()); - weight = weight.saturating_add(T::DbWeight::get().writes(1)); - } - } else { - log::info!("Failed to decode JSON"); - } - // Mark the migration as completed - HasMigrationRun::::insert(&migration_name, true); - weight = weight.saturating_add(T::DbWeight::get().writes(1)); - - log::info!( - "Migration '{:?}' completed. Storage version set to 7.", - String::from_utf8_lossy(&migration_name) - ); - - // Return the migration weight. - weight -} diff --git a/pallets/subtensor/src/migrations/migrate_identities_v2.rs b/pallets/subtensor/src/migrations/migrate_identities_v2.rs deleted file mode 100644 index 505b617b2f..0000000000 --- a/pallets/subtensor/src/migrations/migrate_identities_v2.rs +++ /dev/null @@ -1,91 +0,0 @@ -use super::*; -use frame_support::weights::Weight; -use log; -use scale_info::prelude::{string::String, vec::Vec}; - -pub fn migrate_identities_to_v2() -> Weight { - use frame_support::traits::Get; - let migration_name = b"migrate_identities_to_v2".to_vec(); - - // Start counting weight - let mut weight = T::DbWeight::get().reads(1); - - // Check if we already ran this migration - if HasMigrationRun::::get(&migration_name) { - log::info!( - target: "runtime", - "Migration '{:?}' has already run. Skipping.", - String::from_utf8_lossy(&migration_name) - ); - return weight; - } - - log::info!( - target: "runtime", - "Running migration '{}'", - String::from_utf8_lossy(&migration_name) - ); - - // ----------------------------- - // 1) Migrate Chain Identities - // ----------------------------- - let old_identities = Identities::::iter().collect::>(); - for (account_id, old_identity) in old_identities.clone() { - let new_identity = ChainIdentityV2 { - name: old_identity.name, - url: old_identity.url, - github_repo: Vec::new(), - image: old_identity.image, - discord: old_identity.discord, - description: old_identity.description, - additional: old_identity.additional, - }; - - // Insert into the new storage map - IdentitiesV2::::insert(&account_id, &new_identity); - weight = weight.saturating_add(T::DbWeight::get().writes(1)); - - Identities::::remove(&account_id); - weight = weight.saturating_add(T::DbWeight::get().writes(1)); - } - - weight = weight.saturating_add(T::DbWeight::get().reads(old_identities.len() as u64)); - - // ----------------------------- - // 2) Migrate Subnet Identities - // ----------------------------- - let old_subnet_identities = SubnetIdentities::::iter().collect::>(); - for (netuid, old_subnet_identity) in old_subnet_identities.clone() { - let new_subnet_identity = SubnetIdentityV2 { - subnet_name: old_subnet_identity.subnet_name, - github_repo: old_subnet_identity.github_repo, - subnet_contact: old_subnet_identity.subnet_contact, - subnet_url: Vec::new(), - discord: Vec::new(), - description: Vec::new(), - additional: Vec::new(), - }; - - // Insert into the new storage map - SubnetIdentitiesV2::::insert(netuid, &new_subnet_identity); - weight = weight.saturating_add(T::DbWeight::get().writes(1)); - - SubnetIdentities::::remove(netuid); - weight = weight.saturating_add(T::DbWeight::get().writes(1)); - } - weight = weight.saturating_add(T::DbWeight::get().reads(old_subnet_identities.len() as u64)); - - // ----------------------------- - // Mark the migration as done - // ----------------------------- - HasMigrationRun::::insert(&migration_name, true); - weight = weight.saturating_add(T::DbWeight::get().writes(1)); - - log::info!( - target: "runtime", - "Migration '{}' completed successfully.", - String::from_utf8_lossy(&migration_name) - ); - - weight -} diff --git a/pallets/subtensor/src/migrations/migrate_remove_old_identity_maps.rs b/pallets/subtensor/src/migrations/migrate_remove_old_identity_maps.rs new file mode 100644 index 0000000000..96dc4de2b4 --- /dev/null +++ b/pallets/subtensor/src/migrations/migrate_remove_old_identity_maps.rs @@ -0,0 +1,43 @@ +use super::*; +use crate::HasMigrationRun; +use frame_support::{traits::Get, weights::Weight}; +use scale_info::prelude::string::String; + +pub fn migrate_remove_old_identity_maps() -> Weight { + let migration_name = b"migrate_remove_old_identity_maps".to_vec(); + let mut weight = T::DbWeight::get().reads(1); + + if HasMigrationRun::::get(&migration_name) { + log::info!( + "Migration '{:?}' has already run. Skipping.", + String::from_utf8_lossy(&migration_name) + ); + return weight; + } + + log::info!( + "Running migration '{}'", + String::from_utf8_lossy(&migration_name), + ); + + // ------------------------------ + // Step 1: Remove Map entries + // ------------------------------ + remove_prefix::("SubtensorModule", "Identities", &mut weight); + remove_prefix::("SubtensorModule", "SubnetIdentities", &mut weight); + remove_prefix::("SubtensorModule", "SubnetIdentitiesV2", &mut weight); + + // ------------------------------ + // Step 2: Mark Migration as Completed + // ------------------------------ + + HasMigrationRun::::insert(&migration_name, true); + weight = weight.saturating_add(T::DbWeight::get().writes(1)); + + log::info!( + "Migration '{:?}' completed successfully.", + String::from_utf8_lossy(&migration_name) + ); + + weight +} diff --git a/pallets/subtensor/src/migrations/migrate_remove_unknown_neuron_axon_cert_prom.rs b/pallets/subtensor/src/migrations/migrate_remove_unknown_neuron_axon_cert_prom.rs new file mode 100644 index 0000000000..4553333e65 --- /dev/null +++ b/pallets/subtensor/src/migrations/migrate_remove_unknown_neuron_axon_cert_prom.rs @@ -0,0 +1,83 @@ +use super::*; +use crate::HasMigrationRun; +use frame_support::{traits::Get, weights::Weight}; +use scale_info::prelude::string::String; +use sp_std::collections::btree_set::BTreeSet; + +pub fn migrate_remove_unknown_neuron_axon_cert_prom() -> Weight { + let migration_name = b"migrate_remove_neuron_axon_cert_prom".to_vec(); + let mut weight: Weight = T::DbWeight::get().reads(1); + + // Skip if already executed + if HasMigrationRun::::get(&migration_name) { + log::info!( + target: "runtime", + "Migration '{}' already run - skipping.", + String::from_utf8_lossy(&migration_name) + ); + return weight; + } + log::info!( + "Running migration '{}'", + String::from_utf8_lossy(&migration_name) + ); + + for network in NetworksAdded::::iter_keys() { + weight.saturating_accrue(T::DbWeight::get().reads(1)); + + let hotkeys = BTreeSet::from_iter(Uids::::iter_key_prefix(network)); + weight.saturating_accrue(T::DbWeight::get().reads(hotkeys.len() as u64)); + + // Axons + let axons = Axons::::iter_key_prefix(network).collect::>(); + weight.saturating_accrue(T::DbWeight::get().reads(axons.len() as u64)); + let mut cleaned_axons: u32 = 0; + for axon_hotkey in axons { + if !hotkeys.contains(&axon_hotkey) { + Axons::::remove(network, &axon_hotkey); + cleaned_axons = cleaned_axons.saturating_add(1); + } + } + weight.saturating_accrue(T::DbWeight::get().writes(cleaned_axons as u64)); + + // Neuron Certificates + let certificates = NeuronCertificates::::iter_key_prefix(network).collect::>(); + weight.saturating_accrue(T::DbWeight::get().reads(certificates.len() as u64)); + let mut cleaned_certificates: u32 = 0; + for certificate_hotkey in certificates { + if !hotkeys.contains(&certificate_hotkey) { + NeuronCertificates::::remove(network, &certificate_hotkey); + cleaned_certificates = cleaned_certificates.saturating_add(1); + } + } + weight.saturating_accrue(T::DbWeight::get().writes(cleaned_certificates as u64)); + + // Prometheus + let prometheus = Prometheus::::iter_key_prefix(network).collect::>(); + weight.saturating_accrue(T::DbWeight::get().reads(prometheus.len() as u64)); + let mut cleaned_prometheus: u32 = 0; + for prometheus_hotkey in prometheus { + if !hotkeys.contains(&prometheus_hotkey) { + Prometheus::::remove(network, &prometheus_hotkey); + cleaned_prometheus = cleaned_prometheus.saturating_add(1); + } + } + weight.saturating_accrue(T::DbWeight::get().writes(cleaned_prometheus as u64)); + + log::info!( + "Cleaned {cleaned_axons} axons, {cleaned_certificates} neuron certificates, {cleaned_prometheus} prometheus for network {network}" + ); + } + + HasMigrationRun::::insert(&migration_name, true); + weight = weight.saturating_add(T::DbWeight::get().writes(1)); + + log::info!( + "Migration '{:?}' completed successfully.", + String::from_utf8_lossy(&migration_name) + ); + + log::info!("{weight:#?} weight"); + + weight +} diff --git a/pallets/subtensor/src/migrations/migrate_subnet_identities_to_v3.rs b/pallets/subtensor/src/migrations/migrate_subnet_identities_to_v3.rs deleted file mode 100644 index fb892645d5..0000000000 --- a/pallets/subtensor/src/migrations/migrate_subnet_identities_to_v3.rs +++ /dev/null @@ -1,70 +0,0 @@ -use super::*; -use frame_support::weights::Weight; -use log; -use scale_info::prelude::{string::String, vec::Vec}; - -pub fn migrate_subnet_identities_to_v3() -> Weight { - use frame_support::traits::Get; - let migration_name = b"migrate_subnet_identities_to_v3".to_vec(); - - // Start counting weight - let mut weight = T::DbWeight::get().reads(1); - - // Check if we already ran this migration - if HasMigrationRun::::get(&migration_name) { - log::info!( - target: "runtime", - "Migration '{:?}' has already run. Skipping.", - String::from_utf8_lossy(&migration_name) - ); - return weight; - } - - log::info!( - target: "runtime", - "Running migration '{}'", - String::from_utf8_lossy(&migration_name) - ); - // ----------------------------- - // 1) Migrate Subnet Identities - // ----------------------------- - let old_subnet_identities = SubnetIdentitiesV2::::iter().collect::>(); - for (netuid, old_subnet_identity) in old_subnet_identities.clone() { - // check for existing SubnetIdentitiesV3 entry, skip if found - if SubnetIdentitiesV3::::contains_key(netuid) { - continue; - } - let new_subnet_identity = SubnetIdentityV3 { - subnet_name: old_subnet_identity.subnet_name, - github_repo: old_subnet_identity.github_repo, - subnet_contact: old_subnet_identity.subnet_contact, - subnet_url: Vec::new(), - discord: Vec::new(), - description: Vec::new(), - logo_url: Vec::new(), - additional: Vec::new(), - }; - - // Insert into the new storage map - SubnetIdentitiesV3::::insert(netuid, &new_subnet_identity); - weight = weight.saturating_add(T::DbWeight::get().writes(1)); - - SubnetIdentitiesV2::::remove(netuid); - weight = weight.saturating_add(T::DbWeight::get().writes(1)); - } - weight = weight.saturating_add(T::DbWeight::get().reads(old_subnet_identities.len() as u64)); - - // ----------------------------- - // Mark the migration as done - // ----------------------------- - HasMigrationRun::::insert(&migration_name, true); - weight = weight.saturating_add(T::DbWeight::get().writes(1)); - - log::info!( - target: "runtime", - "Migration '{}' completed successfully.", - String::from_utf8_lossy(&migration_name) - ); - - weight -} diff --git a/pallets/subtensor/src/migrations/mod.rs b/pallets/subtensor/src/migrations/mod.rs index 41c1333a89..6e654cd2ee 100644 --- a/pallets/subtensor/src/migrations/mod.rs +++ b/pallets/subtensor/src/migrations/mod.rs @@ -5,7 +5,6 @@ use sp_io::KillStorageResult; use sp_io::hashing::twox_128; use sp_io::storage::clear_prefix; pub mod migrate_auto_stake_destination; -pub mod migrate_chain_identity; pub mod migrate_coldkey_swap_scheduled; pub mod migrate_commit_reveal_settings; pub mod migrate_commit_reveal_v2; @@ -19,7 +18,6 @@ pub mod migrate_fix_childkeys; pub mod migrate_fix_is_network_member; pub mod migrate_fix_root_subnet_tao; pub mod migrate_fix_root_tao_and_alpha_in; -pub mod migrate_identities_v2; pub mod migrate_init_tao_flow; pub mod migrate_init_total_issuance; pub mod migrate_kappa_map_to_default; @@ -34,9 +32,11 @@ pub mod migrate_rate_limit_keys; pub mod migrate_rate_limiting_last_blocks; pub mod migrate_remove_commitments_rate_limit; pub mod migrate_remove_network_modality; +pub mod migrate_remove_old_identity_maps; pub mod migrate_remove_stake_map; pub mod migrate_remove_tao_dividends; pub mod migrate_remove_total_hotkey_coldkey_stakes_this_interval; +pub mod migrate_remove_unknown_neuron_axon_cert_prom; pub mod migrate_remove_unused_maps_and_values; pub mod migrate_remove_zero_total_hotkey_alpha; pub mod migrate_reset_bonds_moving_average; @@ -49,7 +49,6 @@ pub mod migrate_set_nominator_min_stake; pub mod migrate_set_registration_enable; pub mod migrate_set_subtoken_enabled; pub mod migrate_stake_threshold; -pub mod migrate_subnet_identities_to_v3; pub mod migrate_subnet_limit_to_default; pub mod migrate_subnet_locked; pub mod migrate_subnet_symbols; diff --git a/pallets/subtensor/src/staking/claim_root.rs b/pallets/subtensor/src/staking/claim_root.rs index 7071a1ad55..24a26d154c 100644 --- a/pallets/subtensor/src/staking/claim_root.rs +++ b/pallets/subtensor/src/staking/claim_root.rs @@ -157,48 +157,52 @@ impl Pallet { return; // no-op } - match root_claim_type { - // Increase stake on root - RootClaimTypeEnum::Swap => { - // Swap the alpha owed to TAO - let owed_tao = match Self::swap_alpha_for_tao( - netuid, - owed_u64.into(), - T::SwapInterface::min_price::(), - true, - ) { - Ok(owed_tao) => owed_tao, - Err(err) => { - log::error!("Error swapping alpha for TAO: {err:?}"); - - return; - } - }; - - Self::increase_stake_for_hotkey_and_coldkey_on_subnet( - hotkey, - coldkey, - NetUid::ROOT, - owed_tao.amount_paid_out.to_u64().into(), - ); - - Self::add_stake_adjust_root_claimed_for_hotkey_and_coldkey( - hotkey, - coldkey, - owed_tao.amount_paid_out.into(), - ); - } - RootClaimTypeEnum::Keep => { - // Increase the stake with the alpha owned - Self::increase_stake_for_hotkey_and_coldkey_on_subnet( - hotkey, - coldkey, - netuid, - owed_u64.into(), - ); - } + let swap = match root_claim_type { + RootClaimTypeEnum::Swap => true, + RootClaimTypeEnum::Keep => false, + RootClaimTypeEnum::KeepSubnets { subnets } => !subnets.contains(&netuid), }; + if swap { + // Increase stake on root. Swap the alpha owed to TAO + let owed_tao = match Self::swap_alpha_for_tao( + netuid, + owed_u64.into(), + T::SwapInterface::min_price::(), + true, + ) { + Ok(owed_tao) => owed_tao, + Err(err) => { + log::error!("Error swapping alpha for TAO: {err:?}"); + + return; + } + }; + + Self::increase_stake_for_hotkey_and_coldkey_on_subnet( + hotkey, + coldkey, + NetUid::ROOT, + owed_tao.amount_paid_out.to_u64().into(), + ); + + Self::add_stake_adjust_root_claimed_for_hotkey_and_coldkey( + hotkey, + coldkey, + owed_tao.amount_paid_out.into(), + ); + } else + /* Keep */ + { + // Increase the stake with the alpha owned + Self::increase_stake_for_hotkey_and_coldkey_on_subnet( + hotkey, + coldkey, + netuid, + owed_u64.into(), + ); + } + // Increase root claimed by owed amount. RootClaimed::::mutate((netuid, hotkey, coldkey), |root_claimed| { *root_claimed = root_claimed.saturating_add(owed_u64.into()); diff --git a/pallets/subtensor/src/staking/stake_utils.rs b/pallets/subtensor/src/staking/stake_utils.rs index ab052aa527..d0f78551c1 100644 --- a/pallets/subtensor/src/staking/stake_utils.rs +++ b/pallets/subtensor/src/staking/stake_utils.rs @@ -18,7 +18,9 @@ impl Pallet { /// # Returns /// * `u64` - The total alpha issuance for the specified subnet. pub fn get_alpha_issuance(netuid: NetUid) -> AlphaCurrency { - SubnetAlphaIn::::get(netuid).saturating_add(SubnetAlphaOut::::get(netuid)) + SubnetAlphaIn::::get(netuid) + .saturating_add(SubnetAlphaInProvided::::get(netuid)) + .saturating_add(SubnetAlphaOut::::get(netuid)) } pub fn get_protocol_tao(netuid: NetUid) -> TaoCurrency { diff --git a/pallets/subtensor/src/subnets/leasing.rs b/pallets/subtensor/src/subnets/leasing.rs index cf263a1335..a202a22a45 100644 --- a/pallets/subtensor/src/subnets/leasing.rs +++ b/pallets/subtensor/src/subnets/leasing.rs @@ -24,8 +24,7 @@ use frame_system::pallet_prelude::*; use sp_core::blake2_256; use sp_runtime::{Percent, traits::TrailingZeroInput}; use substrate_fixed::types::U64F64; -use subtensor_runtime_common::{AlphaCurrency, NetUid, TaoCurrency}; -use subtensor_swap_interface::SwapHandler; +use subtensor_runtime_common::{AlphaCurrency, NetUid}; pub type LeaseId = u32; @@ -130,6 +129,9 @@ impl Pallet { ); SubnetUidToLeaseId::::insert(netuid, lease_id); + // The lease take should be 0% to allow all contributors to receive dividends entirely. + Self::delegate_hotkey(&lease_hotkey, 0); + // Get all the contributions to the crowdloan except for the beneficiary // because its share will be computed as the dividends are distributed let contributions = pallet_crowdloan::Contributions::::iter_prefix(crowdloan_id) @@ -249,9 +251,8 @@ impl Pallet { /// Hook used when the subnet owner's cut is distributed to split the amount into dividends /// for the contributors and the beneficiary in shares relative to their initial contributions. - /// - /// It will ensure the subnet has enough alpha in its liquidity pool before swapping it to tao to be distributed, - /// and if not enough liquidity is available, it will accumulate the dividends for later distribution. + /// It accumulates dividends to be distributed later when the interval for distribution is reached. + /// Distribution is made in alpha and stake to the contributor coldkey and lease hotkey. pub fn distribute_leased_network_dividends(lease_id: LeaseId, owner_cut_alpha: AlphaCurrency) { // Ensure the lease exists let Some(lease) = SubnetLeases::::get(lease_id) else { @@ -290,55 +291,60 @@ impl Pallet { return; } - // Ensure there is enough liquidity to unstake the contributors cut - if let Err(err) = Self::validate_remove_stake( - &lease.coldkey, - &lease.hotkey, - lease.netuid, - total_contributors_cut_alpha, - total_contributors_cut_alpha, - false, - ) { - log::debug!("Couldn't distributing dividends for lease {lease_id}: {err:?}"); - AccumulatedLeaseDividends::::set(lease_id, total_contributors_cut_alpha); - return; - } - - // Unstake the contributors cut from the subnet as tao to the lease coldkey - let tao_unstaked = match Self::unstake_from_subnet( - &lease.hotkey, - &lease.coldkey, - lease.netuid, - total_contributors_cut_alpha, - T::SwapInterface::min_price(), - false, - ) { - Ok(tao_unstaked) => tao_unstaked, - Err(err) => { - log::debug!("Couldn't distributing dividends for lease {lease_id}: {err:?}"); - AccumulatedLeaseDividends::::set(lease_id, total_contributors_cut_alpha); - return; + // We use a storage layer to ensure the distribution is atomic. + if let Err(err) = frame_support::storage::with_storage_layer(|| { + let mut alpha_distributed = AlphaCurrency::ZERO; + + // Distribute the contributors cut to the contributors and accumulate the alpha + // distributed so far to obtain how much alpha is left to distribute to the beneficiary + for (contributor, share) in SubnetLeaseShares::::iter_prefix(lease_id) { + let alpha_for_contributor = share + .saturating_mul(U64F64::from(total_contributors_cut_alpha.to_u64())) + .ceil() + .saturating_to_num::(); + + Self::transfer_stake_within_subnet( + &lease.coldkey, + &lease.hotkey, + &contributor, + &lease.hotkey, + lease.netuid, + alpha_for_contributor.into(), + )?; + alpha_distributed = alpha_distributed.saturating_add(alpha_for_contributor.into()); + + Self::deposit_event(Event::SubnetLeaseDividendsDistributed { + lease_id, + contributor, + alpha: alpha_for_contributor.into(), + }); } - }; - // Distribute the contributors cut to the contributors and accumulate the tao - // distributed so far to obtain how much tao is left to distribute to the beneficiary - let mut tao_distributed = TaoCurrency::ZERO; - for (contributor, share) in SubnetLeaseShares::::iter_prefix(lease_id) { - let tao_for_contributor = share - .saturating_mul(U64F64::from(tao_unstaked.to_u64())) - .floor() - .saturating_to_num::(); - Self::add_balance_to_coldkey_account(&contributor, tao_for_contributor); - tao_distributed = tao_distributed.saturating_add(tao_for_contributor.into()); - } + // Distribute the leftover alpha to the beneficiary + let beneficiary_cut_alpha = + total_contributors_cut_alpha.saturating_sub(alpha_distributed); + Self::transfer_stake_within_subnet( + &lease.coldkey, + &lease.hotkey, + &lease.beneficiary, + &lease.hotkey, + lease.netuid, + beneficiary_cut_alpha.into(), + )?; + Self::deposit_event(Event::SubnetLeaseDividendsDistributed { + lease_id, + contributor: lease.beneficiary.clone(), + alpha: beneficiary_cut_alpha.into(), + }); - // Distribute the leftover tao to the beneficiary - let beneficiary_cut_tao = tao_unstaked.saturating_sub(tao_distributed); - Self::add_balance_to_coldkey_account(&lease.beneficiary, beneficiary_cut_tao.into()); + // Reset the accumulated dividends + AccumulatedLeaseDividends::::insert(lease_id, AlphaCurrency::ZERO); - // Reset the accumulated dividends - AccumulatedLeaseDividends::::insert(lease_id, AlphaCurrency::ZERO); + Ok::<(), DispatchError>(()) + }) { + log::debug!("Couldn't distributing dividends for lease {lease_id}: {err:?}"); + AccumulatedLeaseDividends::::set(lease_id, total_contributors_cut_alpha); + }; } fn lease_coldkey(lease_id: LeaseId) -> Result { diff --git a/pallets/subtensor/src/subnets/uids.rs b/pallets/subtensor/src/subnets/uids.rs index 669f74bccc..fda21bc33f 100644 --- a/pallets/subtensor/src/subnets/uids.rs +++ b/pallets/subtensor/src/subnets/uids.rs @@ -88,14 +88,13 @@ impl Pallet { BlockAtRegistration::::insert(netuid, uid_to_replace, block_number); // Fill block at registration. IsNetworkMember::::insert(new_hotkey.clone(), netuid, true); // Fill network is member. - // 4. Clear neuron certificates - NeuronCertificates::::remove(netuid, old_hotkey.clone()); + // 4. Clear neuron axons, certificates and prometheus info + Axons::::remove(netuid, &old_hotkey); + NeuronCertificates::::remove(netuid, &old_hotkey); + Prometheus::::remove(netuid, &old_hotkey); // 5. Reset new neuron's values. Self::clear_neuron(netuid, uid_to_replace); - - // 5a. reset axon info for the new uid. - Axons::::remove(netuid, old_hotkey); } /// Appends the uid to the network. diff --git a/pallets/subtensor/src/tests/claim_root.rs b/pallets/subtensor/src/tests/claim_root.rs index 3128674d31..b910fa1e83 100644 --- a/pallets/subtensor/src/tests/claim_root.rs +++ b/pallets/subtensor/src/tests/claim_root.rs @@ -1,5 +1,6 @@ #![allow(clippy::expect_used)] +use crate::RootAlphaDividendsPerSubnet; use crate::tests::mock::{ RuntimeOrigin, SubtensorModule, Test, add_dynamic_network, new_test_ext, run_to_block, }; @@ -599,9 +600,6 @@ fn test_claim_root_with_drain_emissions_and_swap_claim_type() { SubtensorModule::set_tao_weight(u64::MAX); // Set TAO weight to 1.0 SubnetMechanism::::insert(netuid, 1); - // let initial_balance = 10_000_000u64; - // SubtensorModule::add_balance_to_coldkey_account(&coldkey, initial_balance.into()); - let tao_reserve = TaoCurrency::from(50_000_000_000); let alpha_in = AlphaCurrency::from(100_000_000_000); SubnetTAO::::insert(netuid, tao_reserve); @@ -1557,3 +1555,264 @@ fn test_claim_root_with_unrelated_subnets() { assert_eq!(u128::from(new_stake), claimed); }); } + +#[test] +fn test_claim_root_fill_root_alpha_dividends_per_subnet() { + new_test_ext(1).execute_with(|| { + let owner_coldkey = U256::from(1001); + let other_coldkey = U256::from(10010); + let hotkey = U256::from(1002); + let coldkey = U256::from(1003); + let netuid = add_dynamic_network(&hotkey, &owner_coldkey); + + SubtensorModule::set_tao_weight(u64::MAX); // Set TAO weight to 1.0 + SubnetMechanism::::insert(netuid, 1); + + let tao_reserve = TaoCurrency::from(50_000_000_000); + let alpha_in = AlphaCurrency::from(100_000_000_000); + SubnetTAO::::insert(netuid, tao_reserve); + SubnetAlphaIn::::insert(netuid, alpha_in); + + let root_stake = 2_000_000u64; + SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( + &hotkey, + &coldkey, + NetUid::ROOT, + root_stake.into(), + ); + SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( + &hotkey, + &other_coldkey, + NetUid::ROOT, + (9 * root_stake).into(), + ); + + let initial_total_hotkey_alpha = 10_000_000u64; + SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( + &hotkey, + &owner_coldkey, + netuid, + initial_total_hotkey_alpha.into(), + ); + + // Check RootAlphaDividendsPerSubnet is empty on start + assert!(!RootAlphaDividendsPerSubnet::::contains_key( + netuid, hotkey + )); + + let pending_root_alpha = 10_000_000u64; + SubtensorModule::distribute_emission( + netuid, + AlphaCurrency::ZERO, + AlphaCurrency::ZERO, + pending_root_alpha.into(), + AlphaCurrency::ZERO, + ); + + // Check RootAlphaDividendsPerSubnet value + let root_claim_dividends1 = RootAlphaDividendsPerSubnet::::get(netuid, hotkey); + + let validator_take_percent = 0.18f64; + let estimated_root_claim_dividends = + (pending_root_alpha as f64) * (1f64 - validator_take_percent); + + assert_abs_diff_eq!( + estimated_root_claim_dividends as u64, + u64::from(root_claim_dividends1), + epsilon = 100u64, + ); + + SubtensorModule::distribute_emission( + netuid, + AlphaCurrency::ZERO, + AlphaCurrency::ZERO, + pending_root_alpha.into(), + AlphaCurrency::ZERO, + ); + + let root_claim_dividends2 = RootAlphaDividendsPerSubnet::::get(netuid, hotkey); + + // Check RootAlphaDividendsPerSubnet is cleaned each epoch + assert_eq!(root_claim_dividends1, root_claim_dividends2); + }); +} + +#[test] +fn test_claim_root_with_keep_subnets() { + new_test_ext(1).execute_with(|| { + let owner_coldkey = U256::from(1001); + let hotkey = U256::from(1002); + let coldkey = U256::from(1003); + let netuid = add_dynamic_network(&hotkey, &owner_coldkey); + + SubtensorModule::set_tao_weight(u64::MAX); // Set TAO weight to 1.0 + + let root_stake = 2_000_000u64; + SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( + &hotkey, + &coldkey, + NetUid::ROOT, + root_stake.into(), + ); + + let initial_total_hotkey_alpha = 10_000_000u64; + SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( + &hotkey, + &owner_coldkey, + netuid, + initial_total_hotkey_alpha.into(), + ); + + let old_validator_stake = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( + &hotkey, + &owner_coldkey, + netuid, + ); + assert_eq!(old_validator_stake, initial_total_hotkey_alpha.into()); + + // Distribute pending root alpha + + let pending_root_alpha = 1_000_000u64; + SubtensorModule::distribute_emission( + netuid, + AlphaCurrency::ZERO, + AlphaCurrency::ZERO, + pending_root_alpha.into(), + AlphaCurrency::ZERO, + ); + + let claimable = *RootClaimable::::get(hotkey) + .get(&netuid) + .expect("claimable must exist at this point"); + + // Claim root alpha + assert_err!( + SubtensorModule::set_root_claim_type( + RuntimeOrigin::signed(coldkey), + RootClaimTypeEnum::KeepSubnets { + subnets: BTreeSet::new() + }, + ), + Error::::InvalidSubnetNumber + ); + + let keep_subnets = RootClaimTypeEnum::KeepSubnets { + subnets: BTreeSet::from([netuid]), + }; + assert_ok!(SubtensorModule::set_root_claim_type( + RuntimeOrigin::signed(coldkey), + keep_subnets.clone(), + ),); + assert_eq!(RootClaimType::::get(coldkey), keep_subnets); + + assert_ok!(SubtensorModule::claim_root( + RuntimeOrigin::signed(coldkey), + BTreeSet::from([netuid]) + )); + + let new_stake: u64 = + SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet(&hotkey, &coldkey, netuid) + .into(); + + assert_abs_diff_eq!( + new_stake, + (I96F32::from(root_stake) * claimable).saturating_to_num::(), + epsilon = 10u64, + ); + }); +} + +#[test] +fn test_claim_root_keep_subnets_swap_claim_type() { + new_test_ext(1).execute_with(|| { + let owner_coldkey = U256::from(1001); + let other_coldkey = U256::from(10010); + let hotkey = U256::from(1002); + let coldkey = U256::from(1003); + let netuid = add_dynamic_network(&hotkey, &owner_coldkey); + + SubtensorModule::set_tao_weight(u64::MAX); // Set TAO weight to 1.0 + SubnetMechanism::::insert(netuid, 1); + + let tao_reserve = TaoCurrency::from(50_000_000_000); + let alpha_in = AlphaCurrency::from(100_000_000_000); + SubnetTAO::::insert(netuid, tao_reserve); + SubnetAlphaIn::::insert(netuid, alpha_in); + let current_price = + ::SwapInterface::current_alpha_price(netuid.into()) + .saturating_to_num::(); + assert_eq!(current_price, 0.5f64); + + let root_stake = 2_000_000u64; + SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( + &hotkey, + &coldkey, + NetUid::ROOT, + root_stake.into(), + ); + let root_stake_rate = 0.1f64; + SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( + &hotkey, + &other_coldkey, + NetUid::ROOT, + (9 * root_stake).into(), + ); + + let initial_total_hotkey_alpha = 10_000_000u64; + SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( + &hotkey, + &owner_coldkey, + netuid, + initial_total_hotkey_alpha.into(), + ); + + // Distribute pending root alpha + + let pending_root_alpha = 10_000_000u64; + SubtensorModule::distribute_emission( + netuid, + AlphaCurrency::ZERO, + AlphaCurrency::ZERO, + pending_root_alpha.into(), + AlphaCurrency::ZERO, + ); + + // Claim root alpha + + let validator_take_percent = 0.18f64; + // Set to keep 'another' subnet + let keep_subnets = RootClaimTypeEnum::KeepSubnets { + subnets: BTreeSet::from([NetUid::from(100u16)]), + }; + assert_ok!(SubtensorModule::set_root_claim_type( + RuntimeOrigin::signed(coldkey), + keep_subnets.clone() + ),); + assert_eq!(RootClaimType::::get(coldkey), keep_subnets); + + assert_ok!(SubtensorModule::claim_root( + RuntimeOrigin::signed(coldkey), + BTreeSet::from([netuid]) + )); + + // Check new stake + + let new_stake: u64 = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( + &hotkey, + &coldkey, + NetUid::ROOT, + ) + .into(); + + let estimated_stake_increment = (pending_root_alpha as f64) + * (1f64 - validator_take_percent) + * current_price + * root_stake_rate; + + assert_abs_diff_eq!( + new_stake, + root_stake + estimated_stake_increment as u64, + epsilon = 10000u64, + ); + }); +} diff --git a/pallets/subtensor/src/tests/coinbase.rs b/pallets/subtensor/src/tests/coinbase.rs index 12b3392397..c7ad008c04 100644 --- a/pallets/subtensor/src/tests/coinbase.rs +++ b/pallets/subtensor/src/tests/coinbase.rs @@ -1,4 +1,10 @@ -#![allow(unused, clippy::indexing_slicing, clippy::panic, clippy::unwrap_used)] +#![allow( + unused, + clippy::indexing_slicing, + clippy::panic, + clippy::unwrap_used, + clippy::expect_used +)] use super::mock::*; use crate::tests::mock; @@ -8,7 +14,10 @@ use approx::assert_abs_diff_eq; use frame_support::assert_ok; use pallet_subtensor_swap::position::PositionId; use sp_core::U256; -use substrate_fixed::types::{I64F64, I96F32, U64F64, U96F32}; +use substrate_fixed::{ + transcendental::sqrt, + types::{I64F64, I96F32, U64F64, U96F32}, +}; use subtensor_runtime_common::{AlphaCurrency, NetUidStorageIndex}; use subtensor_swap_interface::{SwapEngine, SwapHandler}; @@ -3333,6 +3342,501 @@ fn test_mining_emission_distribution_with_root_sell() { }); } +#[test] +fn test_coinbase_subnets_with_no_reg_get_no_emission() { + new_test_ext(1).execute_with(|| { + let zero = U96F32::saturating_from_num(0); + let netuid0 = add_dynamic_network(&U256::from(1), &U256::from(2)); + let netuid1 = add_dynamic_network(&U256::from(3), &U256::from(4)); + + // Setup initial state + SubtokenEnabled::::insert(netuid0, true); + SubtokenEnabled::::insert(netuid1, true); + FirstEmissionBlockNumber::::insert(netuid0, 0); + FirstEmissionBlockNumber::::insert(netuid1, 0); + // Explicitly allow registration for both subnets + NetworkRegistrationAllowed::::insert(netuid0, true); + NetworkRegistrationAllowed::::insert(netuid1, true); + NetworkPowRegistrationAllowed::::insert(netuid0, false); + NetworkPowRegistrationAllowed::::insert(netuid1, true); + + // Note that netuid0 has only one method allowed + // And, netuid1 has *both* methods allowed + // Both should be in the list. + let subnets_to_emit_to_0 = SubtensorModule::get_subnets_to_emit_to(&[netuid0, netuid1]); + // Check that both subnets are in the list + assert_eq!(subnets_to_emit_to_0.len(), 2); + assert!(subnets_to_emit_to_0.contains(&netuid0)); + assert!(subnets_to_emit_to_0.contains(&netuid1)); + + // Disabled registration of both methods on ONLY netuid0 + NetworkRegistrationAllowed::::insert(netuid0, false); + NetworkPowRegistrationAllowed::::insert(netuid0, false); + + // Check that netuid0 is not in the list + let subnets_to_emit_to_1 = SubtensorModule::get_subnets_to_emit_to(&[netuid0, netuid1]); + assert_eq!(subnets_to_emit_to_1.len(), 1); + assert!(!subnets_to_emit_to_1.contains(&netuid0)); + // Netuid1 still in the list + assert!(subnets_to_emit_to_1.contains(&netuid1)); + }); +} + +// Tests for the excess TAO condition +#[test] +fn test_coinbase_subnet_terms_with_alpha_in_gt_alpha_emission() { + new_test_ext(1).execute_with(|| { + let zero = U96F32::saturating_from_num(0); + let netuid0 = add_dynamic_network(&U256::from(1), &U256::from(2)); + mock::setup_reserves( + netuid0, + TaoCurrency::from(1_000_000_000_000_000), + AlphaCurrency::from(1_000_000_000_000_000), + ); + // Initialize swap v3 + Swap::maybe_initialize_v3(netuid0); + + // Set netuid0 to have price tao_emission / price > alpha_emission + let alpha_emission = U96F32::saturating_from_num( + SubtensorModule::get_block_emission_for_issuance( + SubtensorModule::get_alpha_issuance(netuid0).into(), + ) + .unwrap_or(0), + ); + let price_to_set: U64F64 = U64F64::saturating_from_num(0.01); + let price_to_set_fixed: U96F32 = U96F32::saturating_from_num(price_to_set); + let sqrt_price_to_set: U64F64 = sqrt(price_to_set).unwrap(); + + let tao_emission: U96F32 = U96F32::saturating_from_num(alpha_emission) + .saturating_mul(price_to_set_fixed) + .saturating_add(U96F32::saturating_from_num(0.01)); + + // Set the price + pallet_subtensor_swap::AlphaSqrtPrice::::insert(netuid0, sqrt_price_to_set); + // Check the price is set + assert_abs_diff_eq!( + pallet_subtensor_swap::Pallet::::current_alpha_price(netuid0).to_num::(), + price_to_set.to_num::(), + epsilon = 0.001 + ); + + let subnet_emissions = BTreeMap::from([(netuid0, tao_emission)]); + + let (tao_in, alpha_in, alpha_out, excess_tao) = + SubtensorModule::get_subnet_terms(&subnet_emissions); + + // Check our condition is met + assert!(tao_emission / price_to_set_fixed > alpha_emission); + + // alpha_out should be the alpha_emission, always + assert_abs_diff_eq!( + alpha_out[&netuid0].to_num::(), + alpha_emission.to_num::(), + epsilon = 0.01 + ); + + // alpha_in should equal the alpha_emission + assert_abs_diff_eq!( + alpha_in[&netuid0].to_num::(), + alpha_emission.to_num::(), + epsilon = 0.01 + ); + // tao_in should be the alpha_in at the ratio of the price + assert_abs_diff_eq!( + tao_in[&netuid0].to_num::(), + alpha_in[&netuid0] + .saturating_mul(price_to_set_fixed) + .to_num::(), + epsilon = 0.01 + ); + + // excess_tao should be the difference between the tao_emission and the tao_in + assert_abs_diff_eq!( + excess_tao[&netuid0].to_num::(), + tao_emission.to_num::() - tao_in[&netuid0].to_num::(), + epsilon = 0.01 + ); + }); +} + +#[test] +fn test_coinbase_subnet_terms_with_alpha_in_lte_alpha_emission() { + new_test_ext(1).execute_with(|| { + let zero = U96F32::saturating_from_num(0); + let netuid0 = add_dynamic_network(&U256::from(1), &U256::from(2)); + mock::setup_reserves( + netuid0, + TaoCurrency::from(1_000_000_000_000_000), + AlphaCurrency::from(1_000_000_000_000_000), + ); + // Initialize swap v3 + Swap::maybe_initialize_v3(netuid0); + + let alpha_emission = U96F32::saturating_from_num( + SubtensorModule::get_block_emission_for_issuance( + SubtensorModule::get_alpha_issuance(netuid0).into(), + ) + .unwrap_or(0), + ); + let tao_emission = U96F32::saturating_from_num(34566756_u64); + + let price: U96F32 = Swap::current_alpha_price(netuid0); + + let subnet_emissions = BTreeMap::from([(netuid0, tao_emission)]); + + let (tao_in, alpha_in, alpha_out, excess_tao) = + SubtensorModule::get_subnet_terms(&subnet_emissions); + + // Check our condition is met + assert!(tao_emission / price <= alpha_emission); + + // alpha_out should be the alpha_emission, always + assert_abs_diff_eq!( + alpha_out[&netuid0].to_num::(), + alpha_emission.to_num::(), + epsilon = 0.1 + ); + + // assuming alpha_in < alpha_emission + // Then alpha_in should be tao_emission / price + assert_abs_diff_eq!( + alpha_in[&netuid0].to_num::(), + tao_emission.to_num::() / price.to_num::(), + epsilon = 0.01 + ); + + // tao_in should be the tao_emission + assert_abs_diff_eq!( + tao_in[&netuid0].to_num::(), + tao_emission.to_num::(), + epsilon = 0.01 + ); + + // excess_tao should be 0 + assert_abs_diff_eq!( + excess_tao[&netuid0].to_num::(), + tao_emission.to_num::() - tao_in[&netuid0].to_num::(), + epsilon = 0.01 + ); + }); +} + +// Tests for the inject and swap are in the right order. +#[test] +fn test_coinbase_inject_and_maybe_swap_does_not_skew_reserves() { + new_test_ext(1).execute_with(|| { + let zero = U96F32::saturating_from_num(0); + let netuid0 = add_dynamic_network(&U256::from(1), &U256::from(2)); + mock::setup_reserves( + netuid0, + TaoCurrency::from(1_000_000_000_000_000), + AlphaCurrency::from(1_000_000_000_000_000), + ); + // Initialize swap v3 + Swap::maybe_initialize_v3(netuid0); + + let tao_in = BTreeMap::from([(netuid0, U96F32::saturating_from_num(123))]); + let alpha_in = BTreeMap::from([(netuid0, U96F32::saturating_from_num(456))]); + // We have excess TAO, so we will be swapping with it. + let excess_tao = BTreeMap::from([(netuid0, U96F32::saturating_from_num(789100))]); + + // Run the inject and maybe swap + SubtensorModule::inject_and_maybe_swap(&[netuid0], &tao_in, &alpha_in, &excess_tao); + + let tao_in_after = SubnetTAO::::get(netuid0); + let alpha_in_after = SubnetAlphaIn::::get(netuid0); + + // Make sure that when we inject and swap, we do it in the right order. + // Thereby not skewing the ratio away from the price. + let ratio_after: U96F32 = U96F32::saturating_from_num(alpha_in_after.to_u64()) + .saturating_div(U96F32::saturating_from_num(tao_in_after.to_u64())); + let price_after: U96F32 = U96F32::saturating_from_num( + pallet_subtensor_swap::Pallet::::current_alpha_price(netuid0).to_num::(), + ); + assert_abs_diff_eq!( + ratio_after.to_num::(), + price_after.to_num::(), + epsilon = 1.0 + ); + }); +} + +#[test] +fn test_coinbase_drain_pending_increments_blockssincelaststep() { + new_test_ext(1).execute_with(|| { + let zero = U96F32::saturating_from_num(0); + let netuid0 = add_dynamic_network(&U256::from(1), &U256::from(2)); + + let blocks_since_last_step_before = BlocksSinceLastStep::::get(netuid0); + + // Check that blockssincelaststep is incremented + SubtensorModule::drain_pending(&[netuid0], 1); + + let blocks_since_last_step_after = BlocksSinceLastStep::::get(netuid0); + assert!(blocks_since_last_step_after > blocks_since_last_step_before); + assert_eq!( + blocks_since_last_step_after, + blocks_since_last_step_before + 1 + ); + }); +} + +#[test] +fn test_coinbase_drain_pending_resets_blockssincelaststep() { + new_test_ext(1).execute_with(|| { + let zero = U96F32::saturating_from_num(0); + let netuid0 = add_dynamic_network(&U256::from(1), &U256::from(2)); + Tempo::::insert(netuid0, 100); + // Ensure the block number we use is the tempo block + let block_number = 98; + assert!(SubtensorModule::should_run_epoch(netuid0, block_number)); + + let blocks_since_last_step_before = 12345678; + BlocksSinceLastStep::::insert(netuid0, blocks_since_last_step_before); + LastMechansimStepBlock::::insert(netuid0, 12345); // garbage value + + // Check that blockssincelaststep is reset to 0 on tempo + SubtensorModule::drain_pending(&[netuid0], block_number); + + let blocks_since_last_step_after = BlocksSinceLastStep::::get(netuid0); + assert_eq!(blocks_since_last_step_after, 0); + // Also check LastMechansimStepBlock is set to the block number we ran on + assert_eq!(LastMechansimStepBlock::::get(netuid0), block_number); + }); +} + +#[test] +fn test_coinbase_drain_pending_gets_counters_and_resets_them() { + new_test_ext(1).execute_with(|| { + let zero = U96F32::saturating_from_num(0); + let netuid0 = add_dynamic_network(&U256::from(1), &U256::from(2)); + Tempo::::insert(netuid0, 100); + // Ensure the block number we use is the tempo block + let block_number = 98; + assert!(SubtensorModule::should_run_epoch(netuid0, block_number)); + + let pending_server_em = AlphaCurrency::from(123434534); + let pending_validator_em = AlphaCurrency::from(111111); + let pending_root = AlphaCurrency::from(12222222); + let pending_owner_cut = AlphaCurrency::from(12345678); + + PendingServerEmission::::insert(netuid0, pending_server_em); + PendingValidatorEmission::::insert(netuid0, pending_validator_em); + PendingRootAlphaDivs::::insert(netuid0, pending_root); + PendingOwnerCut::::insert(netuid0, pending_owner_cut); + + let emissions_to_distribute = SubtensorModule::drain_pending(&[netuid0], block_number); + assert_eq!(emissions_to_distribute.len(), 1); + assert_eq!( + emissions_to_distribute[&netuid0], + ( + pending_server_em, + pending_validator_em, + pending_root, + pending_owner_cut + ) + ); + + // Check that the pending emissions are reset + assert_eq!( + PendingServerEmission::::get(netuid0), + AlphaCurrency::ZERO + ); + assert_eq!( + PendingValidatorEmission::::get(netuid0), + AlphaCurrency::ZERO + ); + assert_eq!( + PendingRootAlphaDivs::::get(netuid0), + AlphaCurrency::ZERO + ); + assert_eq!(PendingOwnerCut::::get(netuid0), AlphaCurrency::ZERO); + }); +} + +#[test] +fn test_coinbase_emit_to_subnets_with_no_root_sell() { + new_test_ext(1).execute_with(|| { + let zero = U96F32::saturating_from_num(0); + let netuid0 = add_dynamic_network(&U256::from(1), &U256::from(2)); + // Set owner cut to ~10% + SubnetOwnerCut::::set(u16::MAX / 10); + mock::setup_reserves( + netuid0, + TaoCurrency::from(1_000_000_000_000_000), + AlphaCurrency::from(1_000_000_000_000_000), + ); + // Initialize swap v3 + Swap::maybe_initialize_v3(netuid0); + + let tao_emission = U96F32::saturating_from_num(12345678); + let subnet_emissions = BTreeMap::from([(netuid0, tao_emission)]); + + // NO root sell + let root_sell_flag = false; + + let alpha_emission = U96F32::saturating_from_num( + SubtensorModule::get_block_emission_for_issuance( + SubtensorModule::get_alpha_issuance(netuid0).into(), + ) + .unwrap_or(0), + ); + let price: U96F32 = Swap::current_alpha_price(netuid0); + let (tao_in, alpha_in, alpha_out, excess_tao) = + SubtensorModule::get_subnet_terms(&subnet_emissions); + // Based on the price, we should have NO excess TAO + assert!(tao_emission / price <= alpha_emission); + + // ==== Run the emit to subnets ===== + SubtensorModule::emit_to_subnets(&[netuid0], &subnet_emissions, root_sell_flag); + + // Find the owner cut expected + let owner_cut: U96F32 = SubtensorModule::get_float_subnet_owner_cut(); + let owner_cut_expected: U96F32 = owner_cut.saturating_mul(alpha_emission); + log::info!("owner_cut_expected: {owner_cut_expected:?}"); + log::info!("alpha_emission: {alpha_emission:?}"); + log::info!("owner_cut: {owner_cut:?}"); + + let alpha_issuance: U96F32 = + U96F32::saturating_from_num(SubtensorModule::get_alpha_issuance(netuid0)); + let root_tao: U96F32 = U96F32::saturating_from_num(SubnetTAO::::get(NetUid::ROOT)); + let tao_weight: U96F32 = root_tao.saturating_mul(SubtensorModule::get_tao_weight()); + let root_prop: U96F32 = tao_weight + .checked_div(tao_weight.saturating_add(alpha_issuance)) + .unwrap_or(U96F32::min_value()); + // Expect root alpha divs to be root prop * alpha emission + let expected_root_alpha_divs: AlphaCurrency = AlphaCurrency::from( + root_prop + .saturating_mul(alpha_emission) + .saturating_to_num::(), + ); + + // ===== Check that the pending emissions are set correctly ===== + // Owner cut is as expected + assert_abs_diff_eq!( + PendingOwnerCut::::get(netuid0).to_u64(), + owner_cut_expected.saturating_to_num::(), + epsilon = 200_u64 + ); + // NO root sell, so no root alpha divs + assert_eq!( + PendingRootAlphaDivs::::get(netuid0), + AlphaCurrency::ZERO + ); + // Should be alpha_emission minus the owner cut, + assert_abs_diff_eq!( + PendingServerEmission::::get(netuid0).to_u64(), + alpha_emission + .saturating_sub(owner_cut_expected) + .saturating_div(U96F32::saturating_from_num(2)) + .saturating_to_num::(), + epsilon = 200_u64 + ); + // We ALWAYS deduct the root alpha divs + assert_abs_diff_eq!( + PendingValidatorEmission::::get(netuid0).to_u64(), + alpha_emission + .saturating_sub(owner_cut_expected) + .saturating_div(U96F32::saturating_from_num(2)) + .saturating_sub(expected_root_alpha_divs.to_u64().into()) + .saturating_to_num::(), + epsilon = 200_u64 + ); + }); +} + +#[test] +fn test_coinbase_emit_to_subnets_with_root_sell() { + new_test_ext(1).execute_with(|| { + let zero = U96F32::saturating_from_num(0); + let netuid0 = add_dynamic_network(&U256::from(1), &U256::from(2)); + // Set owner cut to ~10% + SubnetOwnerCut::::set(u16::MAX / 10); + mock::setup_reserves( + netuid0, + TaoCurrency::from(1_000_000_000_000_000), + AlphaCurrency::from(1_000_000_000_000_000), + ); + // Initialize swap v3 + Swap::maybe_initialize_v3(netuid0); + + let tao_emission = U96F32::saturating_from_num(12345678); + let subnet_emissions = BTreeMap::from([(netuid0, tao_emission)]); + + // NO root sell + let root_sell_flag = true; + + let alpha_emission: U96F32 = U96F32::saturating_from_num( + SubtensorModule::get_block_emission_for_issuance( + SubtensorModule::get_alpha_issuance(netuid0).into(), + ) + .unwrap_or(0), + ); + let price: U96F32 = Swap::current_alpha_price(netuid0); + let (tao_in, alpha_in, alpha_out, excess_tao) = + SubtensorModule::get_subnet_terms(&subnet_emissions); + // Based on the price, we should have NO excess TAO + assert!(tao_emission / price <= alpha_emission); + + // ==== Run the emit to subnets ===== + SubtensorModule::emit_to_subnets(&[netuid0], &subnet_emissions, root_sell_flag); + + // Find the owner cut expected + let owner_cut: U96F32 = SubtensorModule::get_float_subnet_owner_cut(); + let owner_cut_expected: U96F32 = owner_cut.saturating_mul(alpha_emission); + log::info!("owner_cut_expected: {owner_cut_expected:?}"); + log::info!("alpha_emission: {alpha_emission:?}"); + log::info!("owner_cut: {owner_cut:?}"); + + let alpha_issuance: U96F32 = + U96F32::saturating_from_num(SubtensorModule::get_alpha_issuance(netuid0)); + let root_tao: U96F32 = U96F32::saturating_from_num(SubnetTAO::::get(NetUid::ROOT)); + let tao_weight: U96F32 = root_tao.saturating_mul(SubtensorModule::get_tao_weight()); + let root_prop: U96F32 = tao_weight + .checked_div(tao_weight.saturating_add(alpha_issuance)) + .unwrap_or(U96F32::min_value()); + // Expect root alpha divs to be root prop * alpha emission + let expected_root_alpha_divs: AlphaCurrency = AlphaCurrency::from( + root_prop + .saturating_mul(alpha_emission) + .saturating_to_num::(), + ); + + // ===== Check that the pending emissions are set correctly ===== + // Owner cut is as expected + assert_abs_diff_eq!( + PendingOwnerCut::::get(netuid0).to_u64(), + owner_cut_expected.saturating_to_num::(), + epsilon = 200_u64 + ); + // YES root sell, so we have root alpha divs + assert_abs_diff_eq!( + PendingRootAlphaDivs::::get(netuid0).to_u64(), + expected_root_alpha_divs.to_u64(), + epsilon = 200_u64 + ); + // Should be alpha_emission minus the owner cut + assert_abs_diff_eq!( + PendingServerEmission::::get(netuid0).to_u64(), + alpha_emission + .saturating_sub(owner_cut_expected) + .saturating_div(U96F32::saturating_from_num(2)) + .saturating_to_num::(), + epsilon = 200_u64 + ); + // Validator emission is also minus root alpha divs + assert_abs_diff_eq!( + PendingValidatorEmission::::get(netuid0).to_u64(), + alpha_emission + .saturating_sub(owner_cut_expected) + .saturating_div(U96F32::saturating_from_num(2)) + .saturating_sub(expected_root_alpha_divs.to_u64().into()) + .saturating_to_num::(), + epsilon = 200_u64 + ); + }); +} + // SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --package pallet-subtensor --lib -- tests::coinbase::test_pending_emission_start_call_not_done --exact --show-output --nocapture #[test] fn test_pending_emission_start_call_not_done() { diff --git a/pallets/subtensor/src/tests/ensure.rs b/pallets/subtensor/src/tests/ensure.rs index a59bfd7484..1253285306 100644 --- a/pallets/subtensor/src/tests/ensure.rs +++ b/pallets/subtensor/src/tests/ensure.rs @@ -63,26 +63,20 @@ fn ensure_subnet_owner_or_root_distinguishes_root_and_owner() { } #[test] -fn ensure_root_with_rate_limit_blocks_in_freeze_window() { +fn ensure_admin_window_open_blocks_in_freeze_window() { new_test_ext(1).execute_with(|| { - let netuid = NetUid::from(1); + let netuid = NetUid::from(0); let tempo = 10; add_network(netuid, 10, 0); - // Set freeze window to 3 let freeze_window = 3; crate::Pallet::::set_admin_freeze_window(freeze_window); - run_to_block((tempo - freeze_window + 1).into()); + System::set_block_number((tempo - freeze_window).into()); + assert!(crate::Pallet::::ensure_admin_window_open(netuid).is_err()); - // Root is blocked in freeze window - assert!( - crate::Pallet::::ensure_root_with_rate_limit( - <::RuntimeOrigin>::root(), - netuid - ) - .is_err() - ); + System::set_block_number((tempo - freeze_window - 1).into()); + assert!(crate::Pallet::::ensure_admin_window_open(netuid).is_ok()); }); } @@ -111,6 +105,7 @@ fn ensure_owner_or_root_with_limits_checks_rl_and_freeze() { ) .expect("should pass"); assert_eq!(res, Some(owner)); + assert_ok!(crate::Pallet::::ensure_admin_window_open(netuid)); // Simulate previous update at current block -> next call should fail due to rate limit let now = crate::Pallet::::get_current_block_as_u64(); @@ -127,11 +122,14 @@ fn ensure_owner_or_root_with_limits_checks_rl_and_freeze() { // Advance beyond RL and ensure passes again run_to_block(now + 3); + TransactionType::from(Hyperparameter::Kappa) + .set_last_block_on_subnet::(&owner, netuid, 0); assert_ok!(crate::Pallet::::ensure_sn_owner_or_root_with_limits( <::RuntimeOrigin>::signed(owner), netuid, &[Hyperparameter::Kappa.into()] )); + assert_ok!(crate::Pallet::::ensure_admin_window_open(netuid)); // Now advance into the freeze window; ensure blocks // (using loop for clarity, because epoch calculation function uses netuid) @@ -148,12 +146,13 @@ fn ensure_owner_or_root_with_limits_checks_rl_and_freeze() { } run_to_block(cur + 1); } + assert_ok!(crate::Pallet::::ensure_sn_owner_or_root_with_limits( + <::RuntimeOrigin>::signed(owner), + netuid, + &[Hyperparameter::Kappa.into()] + )); assert_noop!( - crate::Pallet::::ensure_sn_owner_or_root_with_limits( - <::RuntimeOrigin>::signed(owner), - netuid, - &[Hyperparameter::Kappa.into()], - ), + crate::Pallet::::ensure_admin_window_open(netuid), crate::Error::::AdminActionProhibitedDuringWeightsWindow ); }); diff --git a/pallets/subtensor/src/tests/leasing.rs b/pallets/subtensor/src/tests/leasing.rs index 4ffc18230a..9f8bf4d6bf 100644 --- a/pallets/subtensor/src/tests/leasing.rs +++ b/pallets/subtensor/src/tests/leasing.rs @@ -65,6 +65,9 @@ fn test_register_leased_network_works() { contributor2_share ); + // Ensure the lease hotkey has 0 take from staking + assert_eq!(SubtensorModule::get_hotkey_take(&lease.hotkey), 0); + // Ensure each contributor and beneficiary has been refunded their share of the leftover cap let leftover_cap = cap.saturating_sub(lease.cost); @@ -502,54 +505,111 @@ fn test_distribute_lease_network_dividends_multiple_contributors_works() { // Setup the correct block to distribute dividends run_to_block(::LeaseDividendsDistributionInterval::get() as u64); - // Get the initial subnet tao after stake and ensure all contributor - // balances are in initial state - let subnet_tao_before = SubnetTAO::::get(lease.netuid); - let contributor1_balance_before = SubtensorModule::get_coldkey_balance(&contributions[0].0); - let contributor2_balance_before = SubtensorModule::get_coldkey_balance(&contributions[1].0); - let beneficiary_balance_before = SubtensorModule::get_coldkey_balance(&beneficiary); + // Get the initial alpha for the contributors and beneficiary and ensure they are zero + let contributor1_alpha_before = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( + &lease.hotkey, + &contributions[0].0, + lease.netuid, + ); + assert_eq!(contributor1_alpha_before, AlphaCurrency::ZERO); + let contributor2_alpha_before = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( + &lease.hotkey, + &contributions[1].0, + lease.netuid, + ); + assert_eq!(contributor2_alpha_before, AlphaCurrency::ZERO); + let beneficiary_alpha_before = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( + &lease.hotkey, + &beneficiary, + lease.netuid, + ); + assert_eq!(beneficiary_alpha_before, AlphaCurrency::ZERO); // Setup some previously accumulated dividends - let accumulated_dividends = AlphaCurrency::from(5_000_000); + let accumulated_dividends = AlphaCurrency::from(10_000_000_000); AccumulatedLeaseDividends::::insert(lease_id, accumulated_dividends); // Distribute the dividends - let owner_cut_alpha = AlphaCurrency::from(5_000_000); + let owner_cut_alpha = AlphaCurrency::from(5_000_000_000); SubtensorModule::distribute_leased_network_dividends(lease_id, owner_cut_alpha); // Ensure the dividends were distributed correctly relative to their shares - let distributed_tao = subnet_tao_before - SubnetTAO::::get(lease.netuid); - let contributor1_balance_delta = SubtensorModule::get_coldkey_balance(&contributions[0].0) - .saturating_sub(contributor1_balance_before); - let contributor2_balance_delta = SubtensorModule::get_coldkey_balance(&contributions[1].0) - .saturating_sub(contributor2_balance_before); - let beneficiary_balance_delta = SubtensorModule::get_coldkey_balance(&beneficiary) - .saturating_sub(beneficiary_balance_before); - + let distributed_alpha = + accumulated_dividends + emissions_share.mul_ceil(owner_cut_alpha.to_u64()).into(); + assert_ne!(distributed_alpha, AlphaCurrency::ZERO); + + let contributor1_alpha_delta = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( + &lease.hotkey, + &contributions[0].0, + lease.netuid, + ) + .saturating_sub(contributor1_alpha_before); + assert_ne!(contributor1_alpha_delta, AlphaCurrency::ZERO); + + let contributor2_alpha_delta = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( + &lease.hotkey, + &contributions[1].0, + lease.netuid, + ) + .saturating_sub(contributor2_alpha_before); + assert_ne!(contributor2_alpha_delta, AlphaCurrency::ZERO); + + let beneficiary_alpha_delta = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( + &lease.hotkey, + &beneficiary, + lease.netuid, + ) + .saturating_sub(beneficiary_alpha_before); + assert_ne!(beneficiary_alpha_delta, AlphaCurrency::ZERO); + + // What has been distributed should be equal to the sum of all contributors received alpha assert_eq!( - distributed_tao, - (beneficiary_balance_delta + contributor1_balance_delta + contributor2_balance_delta) - .into() + distributed_alpha, + (beneficiary_alpha_delta + contributor1_alpha_delta + contributor2_alpha_delta).into() ); - let expected_contributor1_balance = + let expected_contributor1_alpha = SubnetLeaseShares::::get(lease_id, contributions[0].0) - .saturating_mul(U64F64::from(distributed_tao.to_u64())) - .floor() + .saturating_mul(U64F64::from(distributed_alpha.to_u64())) + .ceil() .to_num::(); - assert_eq!(contributor1_balance_delta, expected_contributor1_balance); + assert_eq!(contributor1_alpha_delta, expected_contributor1_alpha.into()); + assert_eq!( + System::events()[2].event, + RuntimeEvent::SubtensorModule(Event::SubnetLeaseDividendsDistributed { + lease_id, + contributor: contributions[0].0.into(), + alpha: expected_contributor1_alpha.into(), + },) + ); - let expected_contributor2_balance = + let expected_contributor2_alpha = SubnetLeaseShares::::get(lease_id, contributions[1].0) - .saturating_mul(U64F64::from(distributed_tao.to_u64())) - .floor() + .saturating_mul(U64F64::from(distributed_alpha.to_u64())) + .ceil() .to_num::(); - assert_eq!(contributor2_balance_delta, expected_contributor2_balance); + assert_eq!(contributor2_alpha_delta, expected_contributor2_alpha.into()); + assert_eq!( + System::events()[5].event, + RuntimeEvent::SubtensorModule(Event::SubnetLeaseDividendsDistributed { + lease_id, + contributor: contributions[1].0.into(), + alpha: expected_contributor2_alpha.into(), + },) + ); // The beneficiary should have received the remaining dividends - let expected_beneficiary_balance = distributed_tao.to_u64() - - (expected_contributor1_balance + expected_contributor2_balance); - assert_eq!(beneficiary_balance_delta, expected_beneficiary_balance); + let expected_beneficiary_alpha = distributed_alpha.to_u64() + - (expected_contributor1_alpha + expected_contributor2_alpha); + assert_eq!(beneficiary_alpha_delta, expected_beneficiary_alpha.into()); + assert_eq!( + System::events()[8].event, + RuntimeEvent::SubtensorModule(Event::SubnetLeaseDividendsDistributed { + lease_id, + contributor: beneficiary.into(), + alpha: expected_beneficiary_alpha.into(), + },) + ); // Ensure nothing was accumulated for later distribution assert_eq!( @@ -584,23 +644,40 @@ fn test_distribute_lease_network_dividends_only_beneficiary_works() { // Setup the correct block to distribute dividends run_to_block(::LeaseDividendsDistributionInterval::get() as u64); - // Get the initial subnet tao after stake and beneficiary balance - let subnet_tao_before = SubnetTAO::::get(lease.netuid); - let beneficiary_balance_before = SubtensorModule::get_coldkey_balance(&beneficiary); + // Get the initial alpha for the beneficiary and ensure it is zero + let beneficiary_alpha_before = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( + &lease.hotkey, + &beneficiary, + lease.netuid, + ); + assert_eq!(beneficiary_alpha_before, AlphaCurrency::ZERO); // Setup some previously accumulated dividends - let accumulated_dividends = AlphaCurrency::from(5_000_000); + let accumulated_dividends = AlphaCurrency::from(10_000_000_000); AccumulatedLeaseDividends::::insert(lease_id, accumulated_dividends); // Distribute the dividends - let owner_cut_alpha = AlphaCurrency::from(5_000_000); + let owner_cut_alpha = AlphaCurrency::from(5_000_000_000); SubtensorModule::distribute_leased_network_dividends(lease_id, owner_cut_alpha); // Ensure the dividends were distributed correctly relative to their shares - let distributed_tao = subnet_tao_before - SubnetTAO::::get(lease.netuid); - let beneficiary_balance_delta = SubtensorModule::get_coldkey_balance(&beneficiary) - .saturating_sub(beneficiary_balance_before); - assert_eq!(distributed_tao, beneficiary_balance_delta.into()); + let distributed_alpha = + accumulated_dividends + emissions_share.mul_ceil(owner_cut_alpha.to_u64()).into(); + assert_ne!(distributed_alpha, AlphaCurrency::ZERO); + let beneficiary_alpha_delta = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( + &lease.hotkey, + &beneficiary, + lease.netuid, + ) + .saturating_sub(beneficiary_alpha_before); + assert_eq!(beneficiary_alpha_delta, distributed_alpha.into()); + assert_last_event::(RuntimeEvent::SubtensorModule( + Event::SubnetLeaseDividendsDistributed { + lease_id, + contributor: beneficiary.into(), + alpha: distributed_alpha, + }, + )); // Ensure nothing was accumulated for later distribution assert_eq!( @@ -628,7 +705,7 @@ fn test_distribute_lease_network_dividends_accumulates_if_not_the_correct_block( let end_block = 500; let emissions_share = Percent::from_percent(30); let tao_to_stake = 100_000_000_000; // 100 TAO - let (lease_id, _) = setup_leased_network( + let (lease_id, lease) = setup_leased_network( beneficiary, emissions_share, Some(end_block), @@ -638,31 +715,58 @@ fn test_distribute_lease_network_dividends_accumulates_if_not_the_correct_block( // Setup incorrect block to distribute dividends run_to_block(::LeaseDividendsDistributionInterval::get() as u64 + 1); - // Get the initial subnet tao after stake and ensure all contributor - let contributor1_balance_before = SubtensorModule::get_coldkey_balance(&contributions[0].0); - let contributor2_balance_before = SubtensorModule::get_coldkey_balance(&contributions[1].0); - let beneficiary_balance_before = SubtensorModule::get_coldkey_balance(&beneficiary); + // Get the initial alpha for the contributors and beneficiary and ensure they are zero + let contributor1_alpha_before = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( + &lease.hotkey, + &contributions[0].0, + lease.netuid, + ); + assert_eq!(contributor1_alpha_before, AlphaCurrency::ZERO); + let contributor2_alpha_before = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( + &lease.hotkey, + &contributions[1].0, + lease.netuid, + ); + assert_eq!(contributor2_alpha_before, AlphaCurrency::ZERO); + let beneficiary_alpha_before = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( + &lease.hotkey, + &beneficiary, + lease.netuid, + ); + assert_eq!(beneficiary_alpha_before, AlphaCurrency::ZERO); // Setup some previously accumulated dividends - let accumulated_dividends = AlphaCurrency::from(5_000_000); + let accumulated_dividends = AlphaCurrency::from(10_000_000_000); AccumulatedLeaseDividends::::insert(lease_id, accumulated_dividends); // Distribute the dividends - let owner_cut_alpha = AlphaCurrency::from(5_000_000); + let owner_cut_alpha = AlphaCurrency::from(5_000_000_000); SubtensorModule::distribute_leased_network_dividends(lease_id, owner_cut_alpha); // Ensure the dividends were not distributed assert_eq!( - SubtensorModule::get_coldkey_balance(&contributions[0].0), - contributor1_balance_before + SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( + &lease.hotkey, + &contributions[0].0, + lease.netuid + ), + contributor1_alpha_before ); assert_eq!( - SubtensorModule::get_coldkey_balance(&contributions[1].0), - contributor2_balance_before + SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( + &lease.hotkey, + &contributions[1].0, + lease.netuid + ), + contributor2_alpha_before ); assert_eq!( - SubtensorModule::get_coldkey_balance(&beneficiary), - beneficiary_balance_before + SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( + &lease.hotkey, + &beneficiary, + lease.netuid + ), + beneficiary_alpha_before ); // Ensure we correctly accumulated the dividends @@ -711,29 +815,58 @@ fn test_distribute_lease_network_dividends_does_nothing_if_lease_has_ended() { // Run to the end of the lease run_to_block(end_block); - let subnet_tao_before = SubnetTAO::::get(lease.netuid); - let contributor1_balance_before = SubtensorModule::get_coldkey_balance(&contributions[0].0); - let contributor2_balance_before = SubtensorModule::get_coldkey_balance(&contributions[1].0); - let beneficiary_balance_before = SubtensorModule::get_coldkey_balance(&beneficiary); + // Get the initial alpha for the contributors and beneficiary and ensure they are zero + let contributor1_alpha_before = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( + &lease.hotkey, + &contributions[0].0, + lease.netuid, + ); + assert_eq!(contributor1_alpha_before, AlphaCurrency::ZERO); + let contributor2_alpha_before = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( + &lease.hotkey, + &contributions[1].0, + lease.netuid, + ); + assert_eq!(contributor2_alpha_before, AlphaCurrency::ZERO); + let beneficiary_alpha_before = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( + &lease.hotkey, + &beneficiary, + lease.netuid, + ); + assert_eq!(beneficiary_alpha_before, AlphaCurrency::ZERO); + + // No dividends are present, lease is new let accumulated_dividends_before = AccumulatedLeaseDividends::::get(lease_id); + assert_eq!(accumulated_dividends_before, AlphaCurrency::ZERO); // Try to distribute the dividends - let owner_cut_alpha = AlphaCurrency::from(5_000_000); + let owner_cut_alpha = AlphaCurrency::from(5_000_000_000); SubtensorModule::distribute_leased_network_dividends(lease_id, owner_cut_alpha); // Ensure the dividends were not distributed - assert_eq!(SubnetTAO::::get(lease.netuid), subnet_tao_before); assert_eq!( - SubtensorModule::get_coldkey_balance(&contributions[0].0), - contributor1_balance_before + SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( + &lease.hotkey, + &contributions[0].0, + lease.netuid + ), + contributor1_alpha_before ); assert_eq!( - SubtensorModule::get_coldkey_balance(&contributions[1].0), - contributor2_balance_before + SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( + &lease.hotkey, + &contributions[1].0, + lease.netuid + ), + contributor2_alpha_before ); assert_eq!( - SubtensorModule::get_coldkey_balance(&beneficiary), - beneficiary_balance_before + SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( + &lease.hotkey, + &beneficiary, + lease.netuid + ), + beneficiary_alpha_before ); // Ensure nothing was accumulated for later distribution assert_eq!( @@ -768,28 +901,54 @@ fn test_distribute_lease_network_dividends_accumulates_if_amount_is_too_low() { None, // We don't add any liquidity ); - let subnet_tao_before = SubnetTAO::::get(lease.netuid); - let contributor1_balance_before = SubtensorModule::get_coldkey_balance(&contributions[0].0); - let contributor2_balance_before = SubtensorModule::get_coldkey_balance(&contributions[1].0); - let beneficiary_balance_before = SubtensorModule::get_coldkey_balance(&beneficiary); + // Get the initial alpha for the contributors and beneficiary and ensure they are zero + let contributor1_alpha_before = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( + &lease.hotkey, + &contributions[0].0, + lease.netuid, + ); + assert_eq!(contributor1_alpha_before, AlphaCurrency::ZERO); + let contributor2_alpha_before = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( + &lease.hotkey, + &contributions[1].0, + lease.netuid, + ); + assert_eq!(contributor2_alpha_before, AlphaCurrency::ZERO); + let beneficiary_alpha_before = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( + &lease.hotkey, + &beneficiary, + lease.netuid, + ); + assert_eq!(beneficiary_alpha_before, AlphaCurrency::ZERO); // Try to distribute the dividends let owner_cut_alpha = AlphaCurrency::from(5_000); SubtensorModule::distribute_leased_network_dividends(lease_id, owner_cut_alpha); // Ensure the dividends were not distributed - assert_eq!(SubnetTAO::::get(lease.netuid), subnet_tao_before); assert_eq!( - SubtensorModule::get_coldkey_balance(&contributions[0].0), - contributor1_balance_before + SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( + &lease.hotkey, + &contributions[0].0, + lease.netuid + ), + contributor1_alpha_before ); assert_eq!( - SubtensorModule::get_coldkey_balance(&contributions[1].0), - contributor2_balance_before + SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( + &lease.hotkey, + &contributions[1].0, + lease.netuid + ), + contributor2_alpha_before ); assert_eq!( - SubtensorModule::get_coldkey_balance(&beneficiary), - beneficiary_balance_before + SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( + &lease.hotkey, + &beneficiary, + lease.netuid + ), + beneficiary_alpha_before ); // Ensure the correct amount of alpha was accumulated for later dividends distribution assert_eq!( @@ -824,28 +983,53 @@ fn test_distribute_lease_network_dividends_accumulates_if_insufficient_liquidity None, // We don't add any liquidity ); - let subnet_tao_before = SubnetTAO::::get(lease.netuid); - let contributor1_balance_before = SubtensorModule::get_coldkey_balance(&contributions[0].0); - let contributor2_balance_before = SubtensorModule::get_coldkey_balance(&contributions[1].0); - let beneficiary_balance_before = SubtensorModule::get_coldkey_balance(&beneficiary); + let contributor1_alpha_before = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( + &lease.hotkey, + &contributions[0].0, + lease.netuid, + ); + assert_eq!(contributor1_alpha_before, AlphaCurrency::ZERO); + let contributor2_alpha_before = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( + &lease.hotkey, + &contributions[1].0, + lease.netuid, + ); + assert_eq!(contributor2_alpha_before, AlphaCurrency::ZERO); + let beneficiary_alpha_before = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( + &lease.hotkey, + &beneficiary, + lease.netuid, + ); + assert_eq!(beneficiary_alpha_before, AlphaCurrency::ZERO); // Try to distribute the dividends let owner_cut_alpha = AlphaCurrency::from(5_000_000); SubtensorModule::distribute_leased_network_dividends(lease_id, owner_cut_alpha); // Ensure the dividends were not distributed - assert_eq!(SubnetTAO::::get(lease.netuid), subnet_tao_before); assert_eq!( - SubtensorModule::get_coldkey_balance(&contributions[0].0), - contributor1_balance_before + SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( + &lease.hotkey, + &contributions[0].0, + lease.netuid + ), + contributor1_alpha_before ); assert_eq!( - SubtensorModule::get_coldkey_balance(&contributions[1].0), - contributor2_balance_before + SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( + &lease.hotkey, + &contributions[1].0, + lease.netuid + ), + contributor2_alpha_before ); assert_eq!( - SubtensorModule::get_coldkey_balance(&beneficiary), - beneficiary_balance_before + SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( + &lease.hotkey, + &beneficiary, + lease.netuid + ), + beneficiary_alpha_before ); // Ensure the correct amount of alpha was accumulated for later dividends distribution assert_eq!( diff --git a/pallets/subtensor/src/tests/migration.rs b/pallets/subtensor/src/tests/migration.rs index b694459eaa..8d439e4e8f 100644 --- a/pallets/subtensor/src/tests/migration.rs +++ b/pallets/subtensor/src/tests/migration.rs @@ -2724,3 +2724,97 @@ fn test_migrate_reset_unactive_sn_idempotence() { assert_eq!(TotalIssuance::::get(), total_issuance_before); }); } + +#[test] +fn test_migrate_remove_old_identity_maps() { + let migration = + crate::migrations::migrate_remove_old_identity_maps::migrate_remove_old_identity_maps::; + + const MIGRATION_NAME: &str = "migrate_remove_old_identity_maps"; + + let pallet_name = "SubtensorModule"; + + test_remove_storage_item(MIGRATION_NAME, pallet_name, "Identities", migration, 100); + + test_remove_storage_item( + MIGRATION_NAME, + pallet_name, + "SubnetIdentities", + migration, + 100, + ); + + test_remove_storage_item( + MIGRATION_NAME, + pallet_name, + "SubnetIdentitiesV2", + migration, + 100, + ); +} + +#[test] +fn test_migrate_remove_unknown_neuron_axon_cert_prom() { + use crate::migrations::migrate_remove_unknown_neuron_axon_cert_prom::*; + const MIGRATION_NAME: &[u8] = b"migrate_remove_neuron_axon_cert_prom"; + + new_test_ext(1).execute_with(|| { + setup_for(NetUid::from(2), 64, 1231); + setup_for(NetUid::from(42), 256, 15151); + setup_for(NetUid::from(99), 1024, 32323); + assert!(!HasMigrationRun::::get(MIGRATION_NAME)); + + let w = migrate_remove_unknown_neuron_axon_cert_prom::(); + assert!(!w.is_zero(), "Weight must be non-zero"); + + assert!(HasMigrationRun::::get(MIGRATION_NAME)); + assert_for(NetUid::from(2), 64, 1231); + assert_for(NetUid::from(42), 256, 15151); + assert_for(NetUid::from(99), 1024, 32323); + }); + + fn setup_for(netuid: NetUid, uids: u32, items: u32) { + NetworksAdded::::insert(netuid, true); + + for i in 1u32..=uids { + let hk = U256::from(netuid.inner() as u32 * 1000 + i); + Uids::::insert(netuid, hk, i as u16); + } + + for i in 1u32..=items { + let hk = U256::from(netuid.inner() as u32 * 1000 + i); + Axons::::insert(netuid, hk, AxonInfo::default()); + NeuronCertificates::::insert(netuid, hk, NeuronCertificate::default()); + Prometheus::::insert(netuid, hk, PrometheusInfo::default()); + } + } + + fn assert_for(netuid: NetUid, uids: u32, items: u32) { + assert_eq!( + Axons::::iter_key_prefix(netuid).count(), + uids as usize + ); + assert_eq!( + NeuronCertificates::::iter_key_prefix(netuid).count(), + uids as usize + ); + assert_eq!( + Prometheus::::iter_key_prefix(netuid).count(), + uids as usize + ); + + for i in 1u32..=uids { + let hk = U256::from(netuid.inner() as u32 * 1000 + i); + assert!(Axons::::contains_key(netuid, hk)); + assert!(NeuronCertificates::::contains_key(netuid, hk)); + assert!(Prometheus::::contains_key(netuid, hk)); + } + + for i in uids + 1u32..=items { + let hk = U256::from(netuid.inner() as u32 * 1000 + i); + assert!(!Axons::::contains_key(netuid, hk)); + assert!(!NeuronCertificates::::contains_key(netuid, hk)); + assert!(!Prometheus::::contains_key(netuid, hk)); + } + } +} diff --git a/pallets/subtensor/src/tests/mock.rs b/pallets/subtensor/src/tests/mock.rs index ddd259441e..090fcf8f75 100644 --- a/pallets/subtensor/src/tests/mock.rs +++ b/pallets/subtensor/src/tests/mock.rs @@ -8,7 +8,7 @@ use core::num::NonZeroU64; use crate::utils::rate_limiting::TransactionType; use crate::*; -use frame_support::traits::{Contains, Everything, InherentBuilder, InsideBoth}; +use frame_support::traits::{Contains, Everything, InherentBuilder, InsideBoth, InstanceFilter}; use frame_support::weights::Weight; use frame_support::weights::constants::RocksDbWeight; use frame_support::{PalletId, derive_impl}; @@ -18,6 +18,7 @@ use frame_support::{ }; use frame_system as system; use frame_system::{EnsureRoot, RawOrigin, limits, offchain::CreateTransactionBase}; +use pallet_subtensor_proxy as pallet_proxy; use pallet_subtensor_utility as pallet_utility; use sp_core::{ConstU64, Get, H256, U256, offchain::KeyTypeId}; use sp_runtime::Perbill; @@ -30,7 +31,6 @@ use sp_tracing::tracing_subscriber; use subtensor_runtime_common::{NetUid, TaoCurrency}; use subtensor_swap_interface::{Order, SwapHandler}; use tracing_subscriber::{EnvFilter, layer::SubscriberExt, util::SubscriberInitExt}; - type Block = frame_system::mocking::MockBlock; // Configure a mock runtime to test the pallet. @@ -46,6 +46,7 @@ frame_support::construct_runtime!( Drand: pallet_drand::{Pallet, Call, Storage, Event} = 11, Swap: pallet_subtensor_swap::{Pallet, Call, Storage, Event} = 12, Crowdloan: pallet_crowdloan::{Pallet, Call, Storage, Event} = 13, + Proxy: pallet_subtensor_proxy = 14, } ); @@ -425,6 +426,51 @@ impl pallet_crowdloan::Config for Test { type MaxContributors = MaxContributors; } +// Proxy Pallet config +parameter_types! { + // Set as 1 for testing purposes + pub const ProxyDepositBase: Balance = 1; + // Set as 1 for testing purposes + pub const ProxyDepositFactor: Balance = 1; + // Set as 20 for testing purposes + pub const MaxProxies: u32 = 20; // max num proxies per acct + // Set as 15 for testing purposes + pub const MaxPending: u32 = 15; // max blocks pending ~15min + // Set as 1 for testing purposes + pub const AnnouncementDepositBase: Balance = 1; + // Set as 1 for testing purposes + pub const AnnouncementDepositFactor: Balance = 1; +} + +impl pallet_proxy::Config for Test { + type RuntimeCall = RuntimeCall; + type Currency = Balances; + type ProxyType = subtensor_runtime_common::ProxyType; + type ProxyDepositBase = ProxyDepositBase; + type ProxyDepositFactor = ProxyDepositFactor; + type MaxProxies = MaxProxies; + type WeightInfo = pallet_proxy::weights::SubstrateWeight; + type MaxPending = MaxPending; + type CallHasher = BlakeTwo256; + type AnnouncementDepositBase = AnnouncementDepositBase; + type AnnouncementDepositFactor = AnnouncementDepositFactor; + type BlockNumberProvider = System; +} + +impl InstanceFilter for subtensor_runtime_common::ProxyType { + fn filter(&self, _c: &RuntimeCall) -> bool { + // In tests, allow all proxy types to pass through + true + } + fn is_superset(&self, o: &Self) -> bool { + match (self, o) { + (x, y) if x == y => true, + (subtensor_runtime_common::ProxyType::Any, _) => true, + _ => false, + } + } +} + mod test_crypto { use super::KEY_TYPE; use sp_core::{ @@ -570,6 +616,7 @@ pub fn test_ext_with_balances(balances: Vec<(U256, u128)>) -> sp_io::TestExterna pub(crate) fn step_block(n: u16) { for _ in 0..n { Scheduler::on_finalize(System::block_number()); + Proxy::on_finalize(System::block_number()); SubtensorModule::on_finalize(System::block_number()); System::on_finalize(System::block_number()); System::set_block_number(System::block_number() + 1); diff --git a/pallets/subtensor/src/tests/serving.rs b/pallets/subtensor/src/tests/serving.rs index d8a9b866d9..b52666bf26 100644 --- a/pallets/subtensor/src/tests/serving.rs +++ b/pallets/subtensor/src/tests/serving.rs @@ -5,7 +5,6 @@ use crate::Error; use crate::transaction_extension::SubtensorTransactionExtension; use crate::*; use frame_support::assert_noop; -use frame_support::pallet_prelude::Weight; use frame_support::{ assert_ok, dispatch::{DispatchClass, DispatchInfo, GetDispatchInfo, Pays}, @@ -908,208 +907,6 @@ fn test_set_and_get_identity() { }); } -// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test serving -- test_migrate_set_hotkey_identities --exact --nocapture -#[test] -fn test_migrate_set_hotkey_identities() { - new_test_ext(1).execute_with(|| { - // Run the migration - let weight = - crate::migrations::migrate_chain_identity::migrate_set_hotkey_identities::(); - - // Assert that the migration has run - assert!(HasMigrationRun::::get(b"migrate_identities".to_vec())); - - // Verify that some identities were set - // Note: This assumes that at least one valid identity was in the JSON file - let mut identity_count = 0; - for (_, _) in Identities::::iter() { - identity_count += 1; - } - assert!( - identity_count > 0, - "No identities were set during migration" - ); - - // Verify that the weight is non-zero - assert!( - weight != Weight::zero(), - "Migration weight should be non-zero" - ); - }); -} - -#[test] -fn test_migrate_identities_to_v2() { - new_test_ext(1).execute_with(|| { - let account_id_1 = U256::from(1); - let account_id_2 = U256::from(2); - - let chainone_name = b"ChainOne".to_vec(); - let chainone_url = b"https://chainone.example".to_vec(); - let chainone_image = b"some_image_data".to_vec(); - let chainone_discord = b"discord#1".to_vec(); - let chainone_description = b"Old chain identity".to_vec(); - let chainone_additional = b"extra-info".to_vec(); - - let chaintwo_name = b"ChainTwo".to_vec(); - let chaintwo_url = b"https://chaintwo.example".to_vec(); - let chaintwo_description = b"Another chain identity".to_vec(); - - Identities::::insert( - account_id_1, - ChainIdentity { - name: chainone_name.clone(), - url: chainone_url.clone(), - image: chainone_image.clone(), - discord: chainone_discord.clone(), - description: chainone_description.clone(), - additional: chainone_additional.clone(), - }, - ); - - Identities::::insert( - account_id_2, - ChainIdentity { - name: chaintwo_name.clone(), - url: chaintwo_url.clone(), - image: b"".to_vec(), - discord: b"".to_vec(), - description: chaintwo_description.clone(), - additional: b"".to_vec(), - }, - ); - - let old_subnet_name = b"SubnetExample".to_vec(); - let old_github_repo = b"https://github.com/org/repo".to_vec(); - let old_subnet_contact = b"subnet@example".to_vec(); - - SubnetIdentities::::insert( - NetUid::from(42), - SubnetIdentity { - subnet_name: old_subnet_name.clone(), - github_repo: old_github_repo.clone(), - subnet_contact: old_subnet_contact.clone(), - }, - ); - - assert!(Identities::::get(account_id_1).is_some()); - assert!(Identities::::get(account_id_2).is_some()); - assert!(SubnetIdentities::::get(NetUid::from(42)).is_some()); - assert!(!HasMigrationRun::::get( - b"migrate_identities_to_v2".to_vec() - )); - - let weight = crate::migrations::migrate_identities_v2::migrate_identities_to_v2::(); - - assert!( - HasMigrationRun::::get(b"migrate_identities_to_v2".to_vec()), - "Expected HasMigrationRun to be true after migration" - ); - assert!(Identities::::get(account_id_1).is_none()); - assert!(Identities::::get(account_id_2).is_none()); - assert!(SubnetIdentities::::get(NetUid::from(42)).is_none()); - - let new_identity_1 = IdentitiesV2::::get(account_id_1) - .expect("ChainOne should be migrated to IdentitiesV2"); - let expected_github_repo = b"".to_vec(); - - assert_eq!(new_identity_1.name, chainone_name); - assert_eq!(new_identity_1.url, chainone_url); - assert_eq!(new_identity_1.github_repo, expected_github_repo); - assert_eq!(new_identity_1.image, chainone_image); - assert_eq!(new_identity_1.discord, chainone_discord); - assert_eq!(new_identity_1.description, chainone_description); - assert_eq!(new_identity_1.additional, chainone_additional); - - let new_identity_2 = IdentitiesV2::::get(account_id_2) - .expect("ChainTwo should be migrated to IdentitiesV2"); - assert_eq!(new_identity_2.name, chaintwo_name); - assert_eq!(new_identity_2.url, chaintwo_url); - assert_eq!(new_identity_2.github_repo, b"".to_vec()); - - let new_subnet_identity = SubnetIdentitiesV2::::get(NetUid::from(42)) - .expect("SubnetExample should be migrated to SubnetIdentitiesV2"); - - let expected_subnet_url = b"".to_vec(); - let expected_discord = b"".to_vec(); - let expected_description = b"".to_vec(); - let expected_additional = b"".to_vec(); - - assert_eq!(new_subnet_identity.subnet_name, old_subnet_name); - assert_eq!(new_subnet_identity.github_repo, old_github_repo); - assert_eq!(new_subnet_identity.subnet_contact, old_subnet_contact); - assert_eq!(new_subnet_identity.subnet_url, expected_subnet_url); - assert_eq!(new_subnet_identity.discord, expected_discord); - assert_eq!(new_subnet_identity.description, expected_description); - assert_eq!(new_subnet_identity.additional, expected_additional); - - assert!( - weight != Weight::zero(), - "Migration weight should be non-zero" - ); - }); -} - -// SKIP_WASM_BUILD=1 RUST_LOG=DEBUG cargo test --release -p pallet-subtensor test_migrate_subnet_identities_to_v3 -- --nocapture -#[test] -fn test_migrate_subnet_identities_to_v3() { - new_test_ext(1).execute_with(|| { - let old_subnet_name = b"SubnetExample".to_vec(); - let old_github_repo = b"https://github.com/org/repo".to_vec(); - let old_subnet_contact = b"subnet@example".to_vec(); - - SubnetIdentitiesV2::::insert( - NetUid::from(16), - SubnetIdentityV2 { - subnet_name: old_subnet_name.clone(), - github_repo: old_github_repo.clone(), - subnet_contact: old_subnet_contact.clone(), - subnet_url: b"".to_vec(), - discord: b"".to_vec(), - description: b"".to_vec(), - additional: b"".to_vec(), - }, - ); - - assert!(SubnetIdentitiesV2::::get(NetUid::from(16)).is_some()); - assert!(!HasMigrationRun::::get( - b"migrate_subnet_identities_to_v3".to_vec() - )); - - let weight = - crate::migrations::migrate_subnet_identities_to_v3::migrate_subnet_identities_to_v3::< - Test, - >(); - - assert!( - HasMigrationRun::::get(b"migrate_subnet_identities_to_v3".to_vec()), - "Expected HasMigrationRun to be true after migration" - ); - assert!(SubnetIdentitiesV2::::get(NetUid::from(16)).is_none()); - - let new_subnet_identity = SubnetIdentitiesV3::::get(NetUid::from(16)) - .expect("SubnetExample should be migrated to SubnetIdentitiesV3"); - - let expected_subnet_url = b"".to_vec(); - let expected_discord = b"".to_vec(); - let expected_description = b"".to_vec(); - let expected_additional = b"".to_vec(); - - assert_eq!(new_subnet_identity.subnet_name, old_subnet_name); - assert_eq!(new_subnet_identity.github_repo, old_github_repo); - assert_eq!(new_subnet_identity.subnet_contact, old_subnet_contact); - assert_eq!(new_subnet_identity.subnet_url, expected_subnet_url); - assert_eq!(new_subnet_identity.discord, expected_discord); - assert_eq!(new_subnet_identity.description, expected_description); - assert_eq!(new_subnet_identity.additional, expected_additional); - - assert!( - weight != Weight::zero(), - "Migration weight should be non-zero" - ); - }); -} - // SKIP_WASM_BUILD=1 RUST_LOG=DEBUG cargo test --release -p pallet-subtensor test_do_set_subnet_identity -- --nocapture #[test] fn test_do_set_subnet_identity() { diff --git a/pallets/subtensor/src/tests/uids.rs b/pallets/subtensor/src/tests/uids.rs index 8fee5f7507..df4f8f29ec 100644 --- a/pallets/subtensor/src/tests/uids.rs +++ b/pallets/subtensor/src/tests/uids.rs @@ -32,7 +32,6 @@ fn test_replace_neuron() { let new_hotkey_account_id = U256::from(2); let _new_colkey_account_id = U256::from(12345); - let certificate = NeuronCertificate::try_from(vec![1, 2, 3]).unwrap(); let evm_address = H160::from_slice(&[1_u8; 20]); //add network add_network(netuid, tempo, 0); @@ -71,28 +70,15 @@ fn test_replace_neuron() { }); Bonds::::insert(NetUidStorageIndex::from(netuid), neuron_uid, vec![(0, 1)]); - // serve axon mock address - let ip: u128 = 1676056785; - let port: u16 = 9999; - let ip_type: u8 = 4; - assert!( - SubtensorModule::serve_axon( - <::RuntimeOrigin>::signed(hotkey_account_id), - netuid, - 0, - ip, - port, - ip_type, - 0, - 0, - 0 - ) - .is_ok() + Axons::::insert(netuid, hotkey_account_id, AxonInfoOf::default()); + NeuronCertificates::::insert( + netuid, + hotkey_account_id, + NeuronCertificateOf::default(), ); - - // Set a neuron certificate for it - NeuronCertificates::::insert(netuid, hotkey_account_id, certificate); + Prometheus::::insert(netuid, hotkey_account_id, PrometheusInfoOf::default()); AssociatedEvmAddress::::insert(netuid, neuron_uid, (evm_address, 1)); + // Replace the neuron. SubtensorModule::replace_neuron(netuid, neuron_uid, &new_hotkey_account_id, block_number); @@ -139,10 +125,15 @@ fn test_replace_neuron() { ); // Check axon info is reset. - let axon_info = SubtensorModule::get_axon_info(netuid, &curr_hotkey.unwrap()); - assert_eq!(axon_info.ip, 0); - assert_eq!(axon_info.port, 0); - assert_eq!(axon_info.ip_type, 0); + assert!(!Axons::::contains_key(netuid, curr_hotkey.unwrap())); + assert!(!NeuronCertificates::::contains_key( + netuid, + curr_hotkey.unwrap() + )); + assert!(!Prometheus::::contains_key( + netuid, + curr_hotkey.unwrap() + )); // Check bonds are cleared. assert_eq!( diff --git a/pallets/subtensor/src/tests/weights.rs b/pallets/subtensor/src/tests/weights.rs index a71a225dc7..21d37984e4 100644 --- a/pallets/subtensor/src/tests/weights.rs +++ b/pallets/subtensor/src/tests/weights.rs @@ -5016,7 +5016,7 @@ fn test_reveal_crv3_commits_cannot_reveal_after_reveal_epoch() { step_epochs(1, netuid); // Attempt to reveal commits after the reveal epoch has passed - assert_ok!(SubtensorModule::reveal_crv3_commits(netuid)); + assert_ok!(SubtensorModule::reveal_crv3_commits_for_subnet(netuid)); // Verify that the weights for the neuron have not been set let weights_sparse = SubtensorModule::get_weights_sparse(netuid.into()); @@ -5353,7 +5353,7 @@ fn test_reveal_crv3_commits_decryption_failure() { }, ); - assert_ok!(SubtensorModule::reveal_crv3_commits(netuid)); + assert_ok!(SubtensorModule::reveal_crv3_commits_for_subnet(netuid)); let neuron_uid = SubtensorModule::get_uid_for_net_and_hotkey(netuid, &hotkey) .expect("Failed to get neuron UID for hotkey") as usize; @@ -5973,7 +5973,7 @@ fn test_reveal_crv3_commits_removes_past_epoch_commits() { // --------------------------------------------------------------------- // Run the reveal pass WITHOUT a pulse – only expiry housekeeping runs. // --------------------------------------------------------------------- - assert_ok!(SubtensorModule::reveal_crv3_commits(netuid)); + assert_ok!(SubtensorModule::reveal_crv3_commits_for_subnet(netuid)); // past_epoch (< reveal_epoch) must be gone assert!( diff --git a/pallets/subtensor/src/utils/misc.rs b/pallets/subtensor/src/utils/misc.rs index 46dc8e42c2..70012fd44a 100644 --- a/pallets/subtensor/src/utils/misc.rs +++ b/pallets/subtensor/src/utils/misc.rs @@ -1,8 +1,6 @@ use super::*; use crate::Error; -use crate::system::{ - ensure_root, ensure_signed, ensure_signed_or_root, pallet_prelude::BlockNumberFor, -}; +use crate::system::{ensure_signed, ensure_signed_or_root, pallet_prelude::BlockNumberFor}; use safe_math::*; use sp_core::Get; use sp_core::U256; @@ -36,29 +34,13 @@ impl Pallet { } } - /// Like `ensure_root` but also prohibits calls during the last N blocks of the tempo. - pub fn ensure_root_with_rate_limit( - o: T::RuntimeOrigin, - netuid: NetUid, - ) -> Result<(), DispatchError> { - ensure_root(o)?; - let now = Self::get_current_block_as_u64(); - Self::ensure_not_in_admin_freeze_window(netuid, now)?; - Ok(()) - } - /// Ensure owner-or-root with a set of TransactionType rate checks (owner only). - /// - Root: only freeze window is enforced; no TransactionType checks. - /// - Owner (Signed): freeze window plus all rate checks in `limits` using signer extracted from - /// origin. pub fn ensure_sn_owner_or_root_with_limits( o: T::RuntimeOrigin, netuid: NetUid, limits: &[crate::utils::rate_limiting::TransactionType], ) -> Result, DispatchError> { let maybe_who = Self::ensure_subnet_owner_or_root(o, netuid)?; - let now = Self::get_current_block_as_u64(); - Self::ensure_not_in_admin_freeze_window(netuid, now)?; if let Some(who) = maybe_who.as_ref() { for tx in limits.iter() { ensure!( @@ -70,26 +52,6 @@ impl Pallet { Ok(maybe_who) } - /// Ensure the caller is the subnet owner and passes all provided rate limits. - /// This does NOT allow root; it is strictly owner-only. - /// Returns the signer (owner) on success so callers may record last-blocks. - pub fn ensure_sn_owner_with_limits( - o: T::RuntimeOrigin, - netuid: NetUid, - limits: &[crate::utils::rate_limiting::TransactionType], - ) -> Result { - let who = Self::ensure_subnet_owner(o, netuid)?; - let now = Self::get_current_block_as_u64(); - Self::ensure_not_in_admin_freeze_window(netuid, now)?; - for tx in limits.iter() { - ensure!( - tx.passes_rate_limit_on_subnet::(&who, netuid), - Error::::TxRateLimitExceeded - ); - } - Ok(who) - } - /// Returns true if the current block is within the terminal freeze window of the tempo for the /// given subnet. During this window, admin ops are prohibited to avoid interference with /// validator weight submissions. @@ -103,7 +65,9 @@ impl Pallet { remaining < window } - fn ensure_not_in_admin_freeze_window(netuid: NetUid, now: u64) -> Result<(), DispatchError> { + /// Ensures the admin freeze window is not currently active for the given subnet. + pub fn ensure_admin_window_open(netuid: NetUid) -> Result<(), DispatchError> { + let now = Self::get_current_block_as_u64(); ensure!( !Self::is_in_admin_freeze_window(netuid, now), Error::::AdminActionProhibitedDuringWeightsWindow diff --git a/pallets/swap/src/pallet/impls.rs b/pallets/swap/src/pallet/impls.rs index d92afda1c3..9c27b82a02 100644 --- a/pallets/swap/src/pallet/impls.rs +++ b/pallets/swap/src/pallet/impls.rs @@ -68,7 +68,7 @@ impl Pallet { } // initializes V3 swap for a subnet if needed - pub(super) fn maybe_initialize_v3(netuid: NetUid) -> Result<(), Error> { + pub fn maybe_initialize_v3(netuid: NetUid) -> Result<(), Error> { if SwapV3Initialized::::get(netuid) { return Ok(()); } diff --git a/precompiles/src/alpha.rs b/precompiles/src/alpha.rs index 9dd0379f10..8dcea0e829 100644 --- a/precompiles/src/alpha.rs +++ b/precompiles/src/alpha.rs @@ -35,8 +35,9 @@ where #[precompile::public("getAlphaPrice(uint16)")] #[precompile::view] fn get_alpha_price(_handle: &mut impl PrecompileHandle, netuid: u16) -> EvmResult { - let price = + let current_alpha_price = as SwapHandler>::current_alpha_price(netuid.into()); + let price = current_alpha_price.saturating_mul(U96F32::from_num(1_000_000_000)); let price: SubstrateBalance = price.saturating_to_num::().into(); let price_eth = ::BalanceConverter::into_evm_balance(price) .map(|amount| amount.into_u256()) @@ -48,7 +49,9 @@ where #[precompile::public("getMovingAlphaPrice(uint16)")] #[precompile::view] fn get_moving_alpha_price(_handle: &mut impl PrecompileHandle, netuid: u16) -> EvmResult { - let price: U96F32 = pallet_subtensor::Pallet::::get_moving_alpha_price(netuid.into()); + let moving_alpha_price: U96F32 = + pallet_subtensor::Pallet::::get_moving_alpha_price(netuid.into()); + let price = moving_alpha_price.saturating_mul(U96F32::from_num(1_000_000_000)); let price: SubstrateBalance = price.saturating_to_num::().into(); let price_eth = ::BalanceConverter::into_evm_balance(price) .map(|amount| amount.into_u256()) @@ -202,7 +205,8 @@ where } } - let price: SubstrateBalance = sum_alpha_price.saturating_to_num::().into(); + let price = sum_alpha_price.saturating_mul(U96F32::from_num(1_000_000_000)); + let price: SubstrateBalance = price.saturating_to_num::().into(); let price_eth = ::BalanceConverter::into_evm_balance(price) .map(|amount| amount.into_u256()) .ok_or(ExitError::InvalidRange)?; diff --git a/precompiles/src/ed25519.rs b/precompiles/src/ed25519.rs index 5e186f344f..1ea581bd35 100644 --- a/precompiles/src/ed25519.rs +++ b/precompiles/src/ed25519.rs @@ -21,8 +21,12 @@ impl LinearCostPrecompile for Ed25519Verify where A: From<[u8; 32]>, { - const BASE: u64 = 15; - const WORD: u64 = 3; + // https://eips.ethereum.org/EIPS/eip-665#gas-costs + // According to the EIP, the base cost should be 2000 gas, less than ECDSA/secp256k1 which is 3000. + // Reality: Ed25519 verification is ~2.3x more computationally expensive than ECDSA/secp256k1 + // So we set the base cost to 6000 gas, which is 3x of the EIP's base cost. + const BASE: u64 = 6000; + const WORD: u64 = 0; fn execute(input: &[u8], _: u64) -> Result<(ExitSucceed, Vec), PrecompileFailure> { if input.len() < 132 { diff --git a/precompiles/src/extensions.rs b/precompiles/src/extensions.rs index 62c2cef6e6..fab35a8b79 100644 --- a/precompiles/src/extensions.rs +++ b/precompiles/src/extensions.rs @@ -2,7 +2,7 @@ extern crate alloc; use alloc::format; -use frame_support::dispatch::{GetDispatchInfo, Pays, PostDispatchInfo}; +use frame_support::dispatch::{DispatchInfo, GetDispatchInfo, Pays, PostDispatchInfo}; use frame_system::RawOrigin; use pallet_admin_utils::{PrecompileEnable, PrecompileEnum}; use pallet_evm::{ @@ -71,33 +71,16 @@ pub(crate) trait PrecompileHandleExt: PrecompileHandle { match call.dispatch(R::RuntimeOrigin::from(origin)) { Ok(post_info) => { - if post_info.pays_fee(&info) == Pays::Yes { - let actual_weight = post_info.actual_weight.unwrap_or(info.call_weight); - let cost = - ::GasWeightMapping::weight_to_gas(actual_weight); - self.record_cost(cost)?; - - self.refund_external_cost( - Some( - info.call_weight - .ref_time() - .saturating_sub(actual_weight.ref_time()), - ), - Some( - info.call_weight - .proof_size() - .saturating_sub(actual_weight.proof_size()), - ), - ); - } - log::debug!("Dispatch succeeded. Post info: {post_info:?}"); + self.charge_and_refund_after_dispatch::(&info, &post_info)?; Ok(()) } Err(e) => { log::error!("Dispatch failed. Error: {e:?}"); log::warn!("Returning error PrecompileFailure::Error"); + self.charge_and_refund_after_dispatch::(&info, &e.post_info)?; + Err(PrecompileFailure::Error { exit_status: ExitError::Other( format!("dispatch execution failed: {}", <&'static str>::from(e)).into(), @@ -106,6 +89,36 @@ pub(crate) trait PrecompileHandleExt: PrecompileHandle { } } } + + fn charge_and_refund_after_dispatch( + &mut self, + info: &DispatchInfo, + post_info: &PostDispatchInfo, + ) -> EvmResult<()> + where + R: frame_system::Config + pallet_evm::Config, + { + if post_info.pays_fee(info) == Pays::Yes { + let actual_weight = post_info.actual_weight.unwrap_or(info.call_weight); + let cost = ::GasWeightMapping::weight_to_gas(actual_weight); + self.record_cost(cost)?; + + self.refund_external_cost( + Some( + info.call_weight + .ref_time() + .saturating_sub(actual_weight.ref_time()), + ), + Some( + info.call_weight + .proof_size() + .saturating_sub(actual_weight.proof_size()), + ), + ); + } + + Ok(()) + } } impl PrecompileHandleExt for T where T: PrecompileHandle {} diff --git a/precompiles/src/lib.rs b/precompiles/src/lib.rs index 6b1a004ef2..8069a1eb92 100644 --- a/precompiles/src/lib.rs +++ b/precompiles/src/lib.rs @@ -34,6 +34,7 @@ use crate::extensions::*; use crate::leasing::*; use crate::metagraph::*; use crate::neuron::*; +use crate::proxy::*; use crate::sr25519::*; use crate::staking::*; use crate::storage_query::*; @@ -48,6 +49,7 @@ mod extensions; mod leasing; mod metagraph; mod neuron; +mod proxy; mod sr25519; mod staking; mod storage_query; @@ -108,7 +110,7 @@ where Self(Default::default()) } - pub fn used_addresses() -> [H160; 24] { + pub fn used_addresses() -> [H160; 25] { [ hash(1), hash(2), @@ -134,6 +136,7 @@ where hash(AlphaPrecompile::::INDEX), hash(CrowdloanPrecompile::::INDEX), hash(LeasingPrecompile::::INDEX), + hash(ProxyPrecompile::::INDEX), ] } } @@ -220,6 +223,9 @@ where a if a == hash(LeasingPrecompile::::INDEX) => { LeasingPrecompile::::try_execute::(handle, PrecompileEnum::Leasing) } + a if a == hash(ProxyPrecompile::::INDEX) => { + ProxyPrecompile::::try_execute::(handle, PrecompileEnum::Proxy) + } _ => None, } } diff --git a/precompiles/src/proxy.rs b/precompiles/src/proxy.rs new file mode 100644 index 0000000000..1399177766 --- /dev/null +++ b/precompiles/src/proxy.rs @@ -0,0 +1,242 @@ +use core::marker::PhantomData; + +use crate::{PrecompileExt, PrecompileHandleExt}; + +use alloc::format; +use fp_evm::{ExitError, PrecompileFailure}; +use frame_support::dispatch::{GetDispatchInfo, PostDispatchInfo}; +use frame_system::RawOrigin; +use pallet_evm::{AddressMapping, PrecompileHandle}; +use pallet_subtensor_proxy as pallet_proxy; +use precompile_utils::EvmResult; +use sp_core::H256; +use sp_runtime::{ + codec::DecodeLimit, + traits::{Dispatchable, StaticLookup}, +}; +use sp_std::boxed::Box; +use sp_std::vec::Vec; +use subtensor_runtime_common::ProxyType; +pub struct ProxyPrecompile(PhantomData); +const MAX_DECODE_DEPTH: u32 = 8; + +impl PrecompileExt for ProxyPrecompile +where + R: frame_system::Config + + pallet_evm::Config + + pallet_subtensor::Config + + pallet_proxy::Config, + R::AccountId: From<[u8; 32]> + Into<[u8; 32]>, + ::AddressMapping: AddressMapping, + ::RuntimeCall: From> + + From> + + GetDispatchInfo + + Dispatchable, + ::AddressMapping: AddressMapping, + <::Lookup as StaticLookup>::Source: From, +{ + const INDEX: u64 = 2059; +} + +#[precompile_utils::precompile] +impl ProxyPrecompile +where + R: frame_system::Config + + pallet_evm::Config + + pallet_subtensor::Config + + pallet_proxy::Config, + R::AccountId: From<[u8; 32]> + Into<[u8; 32]>, + ::AddressMapping: AddressMapping, + ::RuntimeCall: From> + + From> + + GetDispatchInfo + + Dispatchable, + <::Lookup as StaticLookup>::Source: From, +{ + #[precompile::public("createPureProxy(uint8,uint32,uint16)")] + pub fn create_pure_proxy( + handle: &mut impl PrecompileHandle, + proxy_type_: u8, + delay: u32, + index: u16, + ) -> EvmResult { + let account_id = handle.caller_account_id::(); + let proxy_type = + ProxyType::try_from(proxy_type_).map_err(|_| PrecompileFailure::Error { + exit_status: ExitError::Other("Invalid proxy type".into()), + })?; + + let call = pallet_proxy::Call::::create_pure { + proxy_type, + delay: delay.into(), + index, + }; + + handle.try_dispatch_runtime_call::(call, RawOrigin::Signed(account_id.clone()))?; + + // Success! + // Try to get proxy address + let proxy_address: [u8; 32] = + pallet_proxy::pallet::Pallet::::pure_account(&account_id, &proxy_type, index, None) + .map_err(|_| PrecompileFailure::Error { + exit_status: ExitError::Other("Proxy not found".into()), + })? + .into(); + + // Check if in the proxies map + let proxy_entry = pallet_proxy::pallet::Pallet::::proxies(proxy_address.into()); + if proxy_entry + .0 + .iter() + .any(|p| account_id == p.delegate && proxy_type == p.proxy_type) + { + return Ok(proxy_address.into()); + } + + Err(PrecompileFailure::Error { + exit_status: ExitError::Other("Proxy not found".into()), + }) + } + + #[precompile::public("killPureProxy(bytes32,uint8,uint16,uint32,uint32)")] + pub fn kill_pure_proxy( + handle: &mut impl PrecompileHandle, + spawner: H256, + proxy_type: u8, + index: u16, + height: u32, + ext_index: u32, + ) -> EvmResult<()> { + let account_id = handle.caller_account_id::(); + let proxy_type = ProxyType::try_from(proxy_type).map_err(|_| PrecompileFailure::Error { + exit_status: ExitError::Other("Invalid proxy type".into()), + })?; + + let call = pallet_proxy::Call::::kill_pure { + spawner: <::Lookup as StaticLookup>::Source::from( + spawner.0.into(), + ), + proxy_type, + index, + height: height.into(), + ext_index: ext_index.into(), + }; + + handle.try_dispatch_runtime_call::(call, RawOrigin::Signed(account_id)) + } + + #[precompile::public("proxyCall(bytes32,uint8[],uint8[])")] + pub fn proxy_call( + handle: &mut impl PrecompileHandle, + real: H256, + force_proxy_type: Vec, + call: Vec, + ) -> EvmResult<()> { + let account_id = handle.caller_account_id::(); + + let call = ::RuntimeCall::decode_with_depth_limit( + MAX_DECODE_DEPTH, + &mut &call[..], + ) + .map_err(|_| PrecompileFailure::Error { + exit_status: ExitError::Other("The raw call data not correctly encoded".into()), + })?; + + let mut proxy_type: Option = None; + if let Some(p) = force_proxy_type.first() { + let proxy_type_ = ProxyType::try_from(*p).map_err(|_| PrecompileFailure::Error { + exit_status: ExitError::Other("Invalid proxy type".into()), + })?; + proxy_type = Some(proxy_type_); + }; + + let call = pallet_proxy::Call::::proxy { + real: <::Lookup as StaticLookup>::Source::from( + real.0.into(), + ), + force_proxy_type: proxy_type, + call: Box::new(call), + }; + + handle.try_dispatch_runtime_call::(call, RawOrigin::Signed(account_id))?; + + let real_account_id = R::AccountId::from(real.0.into()); + + let last_call_result = pallet_proxy::LastCallResult::::get(real_account_id); + match last_call_result { + Some(last_call_result) => match last_call_result { + Ok(()) => Ok(()), + Err(e) => Err(PrecompileFailure::Error { + exit_status: ExitError::Other(format!("{e:?}").into()), + }), + }, + None => Err(PrecompileFailure::Error { + exit_status: ExitError::Other("Proxy execution failed".into()), + }), + } + } + + #[precompile::public("addProxy(bytes32,uint8,uint32)")] + pub fn add_proxy( + handle: &mut impl PrecompileHandle, + delegate: H256, + proxy_type: u8, + delay: u32, + ) -> EvmResult<()> { + let account_id = handle.caller_account_id::(); + let proxy_type = ProxyType::try_from(proxy_type).map_err(|_| PrecompileFailure::Error { + exit_status: ExitError::Other("Invalid proxy type".into()), + })?; + + let call = pallet_proxy::Call::::add_proxy { + delegate: <::Lookup as StaticLookup>::Source::from( + delegate.0.into(), + ), + proxy_type, + delay: delay.into(), + }; + + handle.try_dispatch_runtime_call::(call, RawOrigin::Signed(account_id)) + } + + #[precompile::public("removeProxy(bytes32,uint8,uint32)")] + pub fn remove_proxy( + handle: &mut impl PrecompileHandle, + delegate: H256, + proxy_type: u8, + delay: u32, + ) -> EvmResult<()> { + let account_id = handle.caller_account_id::(); + let proxy_type = ProxyType::try_from(proxy_type).map_err(|_| PrecompileFailure::Error { + exit_status: ExitError::Other("Invalid proxy type".into()), + })?; + + let call = pallet_proxy::Call::::remove_proxy { + delegate: <::Lookup as StaticLookup>::Source::from( + delegate.0.into(), + ), + proxy_type, + delay: delay.into(), + }; + + handle.try_dispatch_runtime_call::(call, RawOrigin::Signed(account_id)) + } + + #[precompile::public("removeProxies()")] + pub fn remove_proxies(handle: &mut impl PrecompileHandle) -> EvmResult<()> { + let account_id = handle.caller_account_id::(); + + let call = pallet_proxy::Call::::remove_proxies {}; + + handle.try_dispatch_runtime_call::(call, RawOrigin::Signed(account_id)) + } + + #[precompile::public("pokeDeposit()")] + pub fn poke_deposit(handle: &mut impl PrecompileHandle) -> EvmResult<()> { + let account_id = handle.caller_account_id::(); + + let call = pallet_proxy::Call::::poke_deposit {}; + + handle.try_dispatch_runtime_call::(call, RawOrigin::Signed(account_id)) + } +} diff --git a/precompiles/src/solidity/proxy.sol b/precompiles/src/solidity/proxy.sol new file mode 100644 index 0000000000..b0e03031bf --- /dev/null +++ b/precompiles/src/solidity/proxy.sol @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +address constant IPROXY_ADDRESS = 0x000000000000000000000000000000000000080b; + +interface IProxy { + function createPureProxy( + uint8 proxy_type, + uint32 delay, + uint16 index + ) external; + + function proxyCall(bytes32 real, uint8[] memory force_proxy_type, bytes memory call) external; + + function killPureProxy( + bytes32 spawner, + uint8 proxy_type, + uint16 index, + uint16 height, + uint32 ext_index + ) external; + + function addProxy(bytes32 delegate, uint8 proxy_type, uint32 delay) external; + + function removeProxy(bytes32 delegate, uint8 proxy_type, uint32 delay) external; + + function removeProxies() external; + + function pokeDeposit() external; +} diff --git a/precompiles/src/sr25519.rs b/precompiles/src/sr25519.rs index c81443dc19..6c6245d8f0 100644 --- a/precompiles/src/sr25519.rs +++ b/precompiles/src/sr25519.rs @@ -22,8 +22,9 @@ impl LinearCostPrecompile for Sr25519Verify where A: From<[u8; 32]>, { - const BASE: u64 = 15; - const WORD: u64 = 3; + // There is no EIP for SR25519, so we use the same base cost as Ed25519. + const BASE: u64 = 6000; + const WORD: u64 = 0; fn execute(input: &[u8], _: u64) -> Result<(ExitSucceed, Vec), PrecompileFailure> { if input.len() < 132 { diff --git a/runtime/Cargo.toml b/runtime/Cargo.toml index 9760ac1b53..b3aced2160 100644 --- a/runtime/Cargo.toml +++ b/runtime/Cargo.toml @@ -149,6 +149,9 @@ ark-serialize = { workspace = true, features = ["derive"] } # Crowdloan pallet-crowdloan.workspace = true +# Mev Shield +pallet-shield.workspace = true + ethereum.workspace = true [dev-dependencies] @@ -271,6 +274,7 @@ std = [ "pallet-contracts/std", "subtensor-chain-extensions/std", "ethereum/std", + "pallet-shield/std", ] runtime-benchmarks = [ "frame-benchmarking/runtime-benchmarks", @@ -315,6 +319,7 @@ runtime-benchmarks = [ # Smart Tx fees pallet "subtensor-transaction-fee/runtime-benchmarks", + "pallet-shield/runtime-benchmarks", ] try-runtime = [ "frame-try-runtime/try-runtime", @@ -362,5 +367,6 @@ try-runtime = [ "pallet-drand/try-runtime", "runtime-common/try-runtime", "pallet-aura/try-runtime", + "pallet-shield/try-runtime", ] metadata-hash = ["substrate-wasm-builder/metadata-hash"] diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index c90942afb9..35272d9817 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -29,6 +29,7 @@ use frame_system::{EnsureRoot, EnsureRootWithSuccess, EnsureSigned}; use pallet_commitments::{CanCommit, OnMetadataCommitment}; use pallet_grandpa::{AuthorityId as GrandpaId, fg_primitives}; use pallet_registry::CanRegisterIdentity; +pub use pallet_shield; use pallet_subtensor::rpc_info::{ delegate_info::DelegateInfo, dynamic_info::DynamicInfo, @@ -119,6 +120,22 @@ impl frame_system::offchain::SigningTypes for Runtime { type Signature = Signature; } +impl pallet_shield::Config for Runtime { + type RuntimeCall = RuntimeCall; + type AuthorityOrigin = pallet_shield::EnsureAuraAuthority; +} + +parameter_types! { + /// Milliseconds per slot; use the chain’s configured slot duration. + pub const ShieldSlotMs: u64 = SLOT_DURATION; + /// Emit the *next* ephemeral public key event at 7s. + pub const ShieldAnnounceAtMs: u64 = 7_000; + /// Old key remains accepted until 9s (2s grace). + pub const ShieldGraceMs: u64 = 2_000; + /// Last 3s of the slot reserved for decrypt+execute. + pub const ShieldDecryptWindowMs: u64 = 3_000; +} + impl frame_system::offchain::CreateTransactionBase for Runtime where RuntimeCall: From, @@ -220,7 +237,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { // `spec_version`, and `authoring_version` are the same between Wasm and native. // This value is set to 100 to notify Polkadot-JS App (https://polkadot.js.org/apps) to use // the compatible custom types. - spec_version: 352, + spec_version: 361, impl_version: 1, apis: RUNTIME_API_VERSIONS, transaction_version: 1, @@ -636,6 +653,9 @@ impl InstanceFilter for ProxyType { | RuntimeCall::SubtensorModule( pallet_subtensor::Call::remove_stake_full_limit { .. } ) + | RuntimeCall::SubtensorModule( + pallet_subtensor::Call::set_root_claim_type { .. } + ) ), ProxyType::Registration => matches!( c, @@ -1569,6 +1589,7 @@ construct_runtime!( Crowdloan: pallet_crowdloan = 27, Swap: pallet_subtensor_swap = 28, Contracts: pallet_contracts = 29, + MevShield: pallet_shield = 30, } ); @@ -1593,22 +1614,12 @@ pub type TransactionExtensions = ( frame_metadata_hash_extension::CheckMetadataHash, ); -parameter_types! { - pub const TriumviratePalletStr: &'static str = "Triumvirate"; - pub const TriumvirateMembersPalletStr: &'static str = "TriumvirateMembers"; - pub const SenateMembersPalletStr: &'static str = "SenateMembers"; -} - type Migrations = ( // Leave this migration in the runtime, so every runtime upgrade tiny rounding errors (fractions of fractions // of a cent) are cleaned up. These tiny rounding errors occur due to floating point coversion. pallet_subtensor::migrations::migrate_init_total_issuance::initialise_total_issuance::Migration< Runtime, >, - // Remove storage from removed governance pallets - frame_support::migrations::RemovePallet, - frame_support::migrations::RemovePallet, - frame_support::migrations::RemovePallet, ); // Unchecked extrinsic type as expected by this runtime. @@ -1650,6 +1661,7 @@ mod benches { [pallet_drand, Drand] [pallet_crowdloan, Crowdloan] [pallet_subtensor_swap, Swap] + [pallet_shield, MevShield] ); } diff --git a/scripts/benchmark_action.sh b/scripts/benchmark_action.sh index a475211163..29bd7744d3 100755 --- a/scripts/benchmark_action.sh +++ b/scripts/benchmark_action.sh @@ -1,13 +1,14 @@ #!/usr/bin/env bash set -euo pipefail -PALLET_LIST=(subtensor admin_utils commitments drand) +PALLET_LIST=(subtensor admin_utils commitments drand shield) declare -A DISPATCH_PATHS=( [subtensor]="../pallets/subtensor/src/macros/dispatches.rs" [admin_utils]="../pallets/admin-utils/src/lib.rs" [commitments]="../pallets/commitments/src/lib.rs" [drand]="../pallets/drand/src/lib.rs" + [shield]="../pallets/shield/src/lib.rs" [swap]="../pallets/swap/src/pallet/mod.rs" ) diff --git a/scripts/benchmark_all.sh b/scripts/benchmark_all.sh index 22d23483f3..99bdb60338 100755 --- a/scripts/benchmark_all.sh +++ b/scripts/benchmark_all.sh @@ -6,6 +6,7 @@ pallets=( "pallet_commitments" "pallet_drand" "pallet_admin_utils" + "pallet_shield" ) RUNTIME_WASM=./target/production/wbuild/node-subtensor-runtime/node_subtensor_runtime.compact.compressed.wasm diff --git a/scripts/localnet.sh b/scripts/localnet.sh index 1b96baa19b..868079aee1 100755 --- a/scripts/localnet.sh +++ b/scripts/localnet.sh @@ -87,26 +87,26 @@ echo "*** Building chainspec..." echo "*** Chainspec built and output to file" # Generate node keys -"$BUILD_DIR/release/node-subtensor" key generate-node-key --chain="$FULL_PATH" --base-path /tmp/alice -"$BUILD_DIR/release/node-subtensor" key generate-node-key --chain="$FULL_PATH" --base-path /tmp/bob +"$BUILD_DIR/release/node-subtensor" key generate-node-key --chain="$FULL_PATH" --base-path /tmp/one +"$BUILD_DIR/release/node-subtensor" key generate-node-key --chain="$FULL_PATH" --base-path /tmp/two if [ $NO_PURGE -eq 1 ]; then echo "*** Purging previous state skipped..." else echo "*** Purging previous state..." - "$BUILD_DIR/release/node-subtensor" purge-chain -y --base-path /tmp/bob --chain="$FULL_PATH" >/dev/null 2>&1 - "$BUILD_DIR/release/node-subtensor" purge-chain -y --base-path /tmp/alice --chain="$FULL_PATH" >/dev/null 2>&1 + "$BUILD_DIR/release/node-subtensor" purge-chain -y --base-path /tmp/two --chain="$FULL_PATH" >/dev/null 2>&1 + "$BUILD_DIR/release/node-subtensor" purge-chain -y --base-path /tmp/one --chain="$FULL_PATH" >/dev/null 2>&1 echo "*** Previous chainstate purged" fi if [ $BUILD_ONLY -eq 0 ]; then echo "*** Starting localnet nodes..." - alice_start=( + one_start=( "$BUILD_DIR/release/node-subtensor" - --base-path /tmp/alice + --base-path /tmp/one --chain="$FULL_PATH" - --alice + --one --port 30334 --rpc-port 9944 --validator @@ -116,11 +116,11 @@ if [ $BUILD_ONLY -eq 0 ]; then --unsafe-force-node-key-generation ) - bob_start=( + two_start=( "$BUILD_DIR/release/node-subtensor" - --base-path /tmp/bob + --base-path /tmp/two --chain="$FULL_PATH" - --bob + --two --port 30335 --rpc-port 9945 --validator @@ -132,15 +132,15 @@ if [ $BUILD_ONLY -eq 0 ]; then # Provide RUN_IN_DOCKER local environment variable if run script in the docker image if [ "${RUN_IN_DOCKER}" == "1" ]; then - alice_start+=(--unsafe-rpc-external) - bob_start+=(--unsafe-rpc-external) + one_start+=(--unsafe-rpc-external) + two_start+=(--unsafe-rpc-external) fi trap 'pkill -P $$' EXIT SIGINT SIGTERM ( - ("${alice_start[@]}" 2>&1) & - ("${bob_start[@]}" 2>&1) + ("${one_start[@]}" 2>&1) & + ("${two_start[@]}" 2>&1) wait ) fi