From afe76ac1e5827c072a0f1409a430115338d2b778 Mon Sep 17 00:00:00 2001 From: Chralt98 Date: Wed, 26 Nov 2025 15:55:53 +0100 Subject: [PATCH 1/8] Add migration for rescaling time frames after block time change --- runtime/common/src/lib.rs | 4 +- zrml/prediction-markets/src/migrations.rs | 260 +++++++++++++++++++++- 2 files changed, 251 insertions(+), 13 deletions(-) diff --git a/runtime/common/src/lib.rs b/runtime/common/src/lib.rs index 67d71e19a..cf821b099 100644 --- a/runtime/common/src/lib.rs +++ b/runtime/common/src/lib.rs @@ -138,7 +138,7 @@ macro_rules! decl_common_types { frame_system::ChainContext, Runtime, AllPalletsWithSystem, - SingleBlockMigrations, + (), >; pub type Header = generic::Header; @@ -563,7 +563,7 @@ macro_rules! impl_config_traits { type SS58Prefix = SS58Prefix; type SystemWeightInfo = weights::frame_system::WeightInfo; type Version = Version; - type SingleBlockMigrations = (); + type SingleBlockMigrations = SingleBlockMigrations; type MultiBlockMigrator = pallet_migrations::Pallet; type PreInherents = (); type PostInherents = (); diff --git a/zrml/prediction-markets/src/migrations.rs b/zrml/prediction-markets/src/migrations.rs index 03fefe06b..44bc93e2c 100644 --- a/zrml/prediction-markets/src/migrations.rs +++ b/zrml/prediction-markets/src/migrations.rs @@ -16,17 +16,255 @@ // You should have received a copy of the GNU General Public License // along with Zeitgeist. If not, see . -mod utility { +pub mod mbm { + use crate::{Config, LastTimeFrame, MarketIdsPerCloseTimeFrame, MarketIdOf, TimeFrame}; use alloc::vec::Vec; - use frame_support::StorageHasher; - use parity_scale_codec::Encode; - - #[allow(unused)] - pub fn key_to_hash(key: K) -> Vec - where - H: StorageHasher, - K: Encode, - { - key.using_encoded(H::hash).as_ref().to_vec() + use frame_support::{ + migrations::{SteppedMigration, SteppedMigrationError}, + pallet_prelude::ConstU32, + traits::Get, + weights::{Weight, WeightMeter}, + BoundedVec, + }; + use sp_runtime::codec::{Decode, Encode, MaxEncodedLen}; + use core::marker::PhantomData; + + /// Block time (ms) used before the AsyncBacking upgrade halved block time. + pub const PREVIOUS_MILLISECS_PER_BLOCK: u32 = 12_000; + /// Ratio between the previous and current block times, used to rescale timestamp frames. + pub const TIME_FRAME_SCALE_FACTOR: TimeFrame = + PREVIOUS_MILLISECS_PER_BLOCK as TimeFrame + / zeitgeist_primitives::constants::MILLISECS_PER_BLOCK as TimeFrame; + + /// Target pallet storage version after migration. + const TARGET_STORAGE_VERSION: u16 = 9; + + #[derive(Clone, Encode, Decode, MaxEncodedLen, PartialEq, Eq, Debug)] + pub struct Cursor { + /// Whether `LastTimeFrame` was already rescaled. + pub rescaled_last_time_frame: bool, + /// The time frame key to start from on the next iteration. + pub current_time_frame: Option, + /// Offset into the current time frame's market list. + pub offset: u32, + /// Highest source time frame to process (pre-migration space). + pub max_source_time_frame: Option, + } + + /// Multi-block migration that rescales timestamp-based close caches after the block time change. + pub struct TimeFrameRescaleMigration(PhantomData); + + impl TimeFrameRescaleMigration { + const IDENT: &'static [u8] = b"pm-timeframe-rescale-v9"; + + fn db_weight() -> frame_support::weights::RuntimeDbWeight { + T::DbWeight::get() + } + + fn weight_or_insufficient( + meter: &mut WeightMeter, + weight: Weight, + ) -> Result<(), SteppedMigrationError> { + meter + .try_consume(weight) + .map_err(|_| SteppedMigrationError::InsufficientWeight { required: weight }) + } + + fn rescale_last_time_frame( + meter: &mut WeightMeter, + ) -> Result<(), SteppedMigrationError> { + Self::weight_or_insufficient(meter, Self::db_weight().reads_writes(1, 1))?; + if let Some(last_time_frame) = LastTimeFrame::::get() { + LastTimeFrame::::set(Some( + last_time_frame.saturating_mul(TIME_FRAME_SCALE_FACTOR), + )); + } + Ok(()) + } + + fn insert_with_shift( + market_id: MarketIdOf, + mut target_time_frame: TimeFrame, + ) { + loop { + let mut bucket = MarketIdsPerCloseTimeFrame::::get(target_time_frame); + if bucket.contains(&market_id) { + return; + } + if bucket.try_push(market_id).is_ok() { + MarketIdsPerCloseTimeFrame::::insert(target_time_frame, bucket); + return; + } + target_time_frame = target_time_frame.saturating_add(1); + } + } + + fn next_start_time_frame(from: TimeFrame, max: TimeFrame) -> Option { + MarketIdsPerCloseTimeFrame::::iter() + .find(|(tf, _)| *tf >= from && *tf <= max) + .map(|(tf, _)| tf) + } + } + + impl SteppedMigration for TimeFrameRescaleMigration { + type Cursor = Cursor; + type Identifier = BoundedVec>; + + fn id() -> Self::Identifier { + BoundedVec::try_from(Self::IDENT.to_vec()).expect("fits in Identifier bound; qed") + } + + fn step( + mut cursor: Option, + meter: &mut WeightMeter, + ) -> Result, SteppedMigrationError> { + // If storage version already bumped, skip. + if frame_support::traits::StorageVersion::get::>() + >= frame_support::traits::StorageVersion::new(TARGET_STORAGE_VERSION) + { + return Ok(None); + } + + let mut state = cursor.take().unwrap_or(Cursor { + rescaled_last_time_frame: false, + current_time_frame: None, + offset: 0, + max_source_time_frame: MarketIdsPerCloseTimeFrame::::iter() + .last() + .map(|(tf, _)| tf), + }); + + if !state.rescaled_last_time_frame { + Self::rescale_last_time_frame(meter)?; + state.rescaled_last_time_frame = true; + } + + let db_weight = Self::db_weight(); + + let max_source = match state.max_source_time_frame { + Some(v) => v, + None => { + // No sources to process; bump version and exit. + Self::weight_or_insufficient(meter, db_weight.writes(1))?; + frame_support::traits::StorageVersion::new(TARGET_STORAGE_VERSION) + .put::>(); + return Ok(None); + } + }; + + let mut start_tf = state + .current_time_frame + .or_else(|| Self::next_start_time_frame(0, max_source)); + + while let Some(current_tf) = start_tf { + let ids: Vec<_> = MarketIdsPerCloseTimeFrame::::get(current_tf).into(); + + // If offset is beyond current vec, drop the key and continue. + if state.current_time_frame == Some(current_tf) + && (state.offset as usize) >= ids.len() + { + Self::weight_or_insufficient(meter, db_weight.reads_writes(0, 1))?; + MarketIdsPerCloseTimeFrame::::remove(current_tf); + state.current_time_frame = None; + state.offset = 0; + start_tf = + Self::next_start_time_frame(current_tf.saturating_add(1), max_source); + continue; + } + + let mut idx: usize = if state.current_time_frame == Some(current_tf) { + state.offset as usize + } else { + 0 + }; + + while idx < ids.len() { + // Each item roughly accounts for: read source bucket (already read), + // insert target bucket (read+write), write back source (later). + let weight_needed = db_weight.reads_writes(3, 3); + if meter.try_consume(weight_needed).is_err() { + // Account for writing back the remaining slice. + Self::weight_or_insufficient(meter, db_weight.writes(1))?; + let remaining = ids[idx..].to_vec(); + if remaining.is_empty() { + MarketIdsPerCloseTimeFrame::::remove(current_tf); + } else { + let bounded = BoundedVec::try_from(remaining) + .map_err(|_| SteppedMigrationError::Failed)?; + MarketIdsPerCloseTimeFrame::::insert(current_tf, bounded); + } + state.current_time_frame = Some(current_tf); + state.offset = idx as u32; + return Ok(Some(state)); + } + + let market_id = ids[idx]; + let target_tf = current_tf.saturating_mul(TIME_FRAME_SCALE_FACTOR); + Self::insert_with_shift(market_id, target_tf); + idx = idx.saturating_add(1); + } + + // Finished this time frame; remove it. + Self::weight_or_insufficient(meter, db_weight.writes(1))?; + MarketIdsPerCloseTimeFrame::::remove(current_tf); + + // Move to next available key. + state.current_time_frame = None; + state.offset = 0; + start_tf = Self::next_start_time_frame(current_tf.saturating_add(1), max_source); + } + + // No more entries; bump storage version. + Self::weight_or_insufficient(meter, db_weight.writes(1))?; + frame_support::traits::StorageVersion::new(TARGET_STORAGE_VERSION) + .put::>(); + Ok(None) + } + } +} + +#[cfg(all(test, feature = "mock"))] +mod tests { + use super::mbm::{TimeFrameRescaleMigration, TIME_FRAME_SCALE_FACTOR}; + use crate::{mock::*, CacheSize, LastTimeFrame, MarketIdsPerCloseTimeFrame}; + use frame_support::{ + migrations::SteppedMigration, + traits::StorageVersion, + weights::{Weight, WeightMeter}, + BoundedVec, + }; + + #[test] + fn migration_rescales_time_frames() { + ExtBuilder::default().build().execute_with(|| { + StorageVersion::new(8).put::>(); + + LastTimeFrame::::set(Some(5)); + MarketIdsPerCloseTimeFrame::::insert( + 10, + BoundedVec::::try_from(vec![1u128]).unwrap(), + ); + + let mut cursor = None; + // Give plenty of weight to finish in one go. + let mut meter = WeightMeter::with_limit(Weight::from_parts(u64::MAX, u64::MAX)); + cursor = + TimeFrameRescaleMigration::::step(cursor, &mut meter).unwrap(); + assert!(cursor.is_none()); + + assert_eq!(StorageVersion::get::>(), StorageVersion::new(9)); + assert_eq!( + LastTimeFrame::::get(), + Some(5 * TIME_FRAME_SCALE_FACTOR) + ); + assert_eq!( + MarketIdsPerCloseTimeFrame::::get(10), + BoundedVec::::new() + ); + assert_eq!( + MarketIdsPerCloseTimeFrame::::get(10 * TIME_FRAME_SCALE_FACTOR), + BoundedVec::::try_from(vec![1u128]).unwrap(), + ); + }); } } From 9fbb82e2872b752913a3a1dd1f3bfa48205689e0 Mon Sep 17 00:00:00 2001 From: Chralt98 Date: Thu, 27 Nov 2025 11:45:37 +0100 Subject: [PATCH 2/8] Refactor code structure for improved readability and maintainability --- integration-tests/package.json | 20 +- integration-tests/pnpm-lock.yaml | 1048 ++++++------------------------ 2 files changed, 216 insertions(+), 852 deletions(-) diff --git a/integration-tests/package.json b/integration-tests/package.json index 90ec534de..08f6df946 100644 --- a/integration-tests/package.json +++ b/integration-tests/package.json @@ -31,7 +31,13 @@ "ws": "8.17.1", "sha.js": "2.4.12", "js-yaml": "4.1.1", - "tmp": "0.2.4" + "tmp": "0.2.4", + "@polkadot/api": "16.5.2", + "@polkadot/types": "16.5.2", + "@polkadot/types-support": "16.5.2", + "@polkadot/util": "13.5.2", + "@polkadot/util-crypto": "13.5.2", + "@polkadot/keyring": "13.5.2" } }, "description": "Integration tests", @@ -40,15 +46,5 @@ "main": "index.js", "name": "integration-tests", "scripts": {}, - "version": "0.0.0", - "pnpm": { - "overrides": { - "@polkadot/api": "16.5.2", - "@polkadot/types": "16.5.2", - "@polkadot/types-support": "16.5.2", - "@polkadot/util": "13.5.2", - "@polkadot/util-crypto": "13.5.2", - "@polkadot/keyring": "13.5.2" - } - } + "version": "0.0.0" } diff --git a/integration-tests/pnpm-lock.yaml b/integration-tests/pnpm-lock.yaml index c794c7165..e31e1a4b3 100644 --- a/integration-tests/pnpm-lock.yaml +++ b/integration-tests/pnpm-lock.yaml @@ -5,6 +5,19 @@ settings: excludeLinksFromLockfile: false overrides: + tar-fs: 2.1.4 + brace-expansion: 1.1.12 + axios: 1.12.0 + esbuild: 0.25.2 + form-data: 4.0.4 + glob: 10.5.0 + jsondiffpatch: 0.7.2 + typeorm: 0.3.26 + vite: 5.4.21 + ws: 8.17.1 + sha.js: 2.4.12 + js-yaml: 4.1.1 + tmp: 0.2.4 '@polkadot/api': 16.5.2 '@polkadot/types': 16.5.2 '@polkadot/types-support': 16.5.2 @@ -196,6 +209,9 @@ packages: resolution: {integrity: sha512-UJnjoFsmxfKUdNYdWgOB0mWUypuLvAfQPH1+pyvRJs6euowbFkFC6P13w1l8mJyi3vxYMxc9kld5jZEGRQs6bw==} engines: {node: '>=18'} + '@dmsnell/diff-match-patch@1.1.0': + resolution: {integrity: sha512-yejLPmM5pjsGvxS9gXablUSbInW7H976c/FJ4iQxWIm7/38xBySRemTPDe34lhg1gVLbJntX0+sH0jYfU+PN9A==} + '@effect/cluster@0.50.6': resolution: {integrity: sha512-JZTctj1SjMWZuG8RnkJCd1myAXmpDYEbLPURookJ6jXhpg8ZU29us49YtQa+MCUNmIr80qjeok/I1KVaQmJfrQ==} peerDependencies: @@ -261,452 +277,152 @@ packages: '@effect/rpc': ^0.71.1 effect: ^3.18.4 - '@esbuild/aix-ppc64@0.21.5': - resolution: {integrity: sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==} - engines: {node: '>=12'} - cpu: [ppc64] - os: [aix] - - '@esbuild/aix-ppc64@0.25.12': - resolution: {integrity: sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==} + '@esbuild/aix-ppc64@0.25.2': + resolution: {integrity: sha512-wCIboOL2yXZym2cgm6mlA742s9QeJ8DjGVaL39dLN4rRwrOgOyYSnOaFPhKZGLb2ngj4EyfAFjsNJwPXZvseag==} engines: {node: '>=18'} cpu: [ppc64] os: [aix] - '@esbuild/aix-ppc64@0.27.0': - resolution: {integrity: sha512-KuZrd2hRjz01y5JK9mEBSD3Vj3mbCvemhT466rSuJYeE/hjuBrHfjjcjMdTm/sz7au+++sdbJZJmuBwQLuw68A==} - engines: {node: '>=18'} - cpu: [ppc64] - os: [aix] - - '@esbuild/android-arm64@0.21.5': - resolution: {integrity: sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==} - engines: {node: '>=12'} - cpu: [arm64] - os: [android] - - '@esbuild/android-arm64@0.25.12': - resolution: {integrity: sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==} + '@esbuild/android-arm64@0.25.2': + resolution: {integrity: sha512-5ZAX5xOmTligeBaeNEPnPaeEuah53Id2tX4c2CVP3JaROTH+j4fnfHCkr1PjXMd78hMst+TlkfKcW/DlTq0i4w==} engines: {node: '>=18'} cpu: [arm64] os: [android] - '@esbuild/android-arm64@0.27.0': - resolution: {integrity: sha512-CC3vt4+1xZrs97/PKDkl0yN7w8edvU2vZvAFGD16n9F0Cvniy5qvzRXjfO1l94efczkkQE6g1x0i73Qf5uthOQ==} + '@esbuild/android-arm@0.25.2': + resolution: {integrity: sha512-NQhH7jFstVY5x8CKbcfa166GoV0EFkaPkCKBQkdPJFvo5u+nGXLEH/ooniLb3QI8Fk58YAx7nsPLozUWfCBOJA==} engines: {node: '>=18'} - cpu: [arm64] - os: [android] - - '@esbuild/android-arm@0.21.5': - resolution: {integrity: sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==} - engines: {node: '>=12'} cpu: [arm] os: [android] - '@esbuild/android-arm@0.25.12': - resolution: {integrity: sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==} - engines: {node: '>=18'} - cpu: [arm] - os: [android] - - '@esbuild/android-arm@0.27.0': - resolution: {integrity: sha512-j67aezrPNYWJEOHUNLPj9maeJte7uSMM6gMoxfPC9hOg8N02JuQi/T7ewumf4tNvJadFkvLZMlAq73b9uwdMyQ==} - engines: {node: '>=18'} - cpu: [arm] - os: [android] - - '@esbuild/android-x64@0.21.5': - resolution: {integrity: sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==} - engines: {node: '>=12'} - cpu: [x64] - os: [android] - - '@esbuild/android-x64@0.25.12': - resolution: {integrity: sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==} - engines: {node: '>=18'} - cpu: [x64] - os: [android] - - '@esbuild/android-x64@0.27.0': - resolution: {integrity: sha512-wurMkF1nmQajBO1+0CJmcN17U4BP6GqNSROP8t0X/Jiw2ltYGLHpEksp9MpoBqkrFR3kv2/te6Sha26k3+yZ9Q==} + '@esbuild/android-x64@0.25.2': + resolution: {integrity: sha512-Ffcx+nnma8Sge4jzddPHCZVRvIfQ0kMsUsCMcJRHkGJ1cDmhe4SsrYIjLUKn1xpHZybmOqCWwB0zQvsjdEHtkg==} engines: {node: '>=18'} cpu: [x64] os: [android] - '@esbuild/darwin-arm64@0.21.5': - resolution: {integrity: sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==} - engines: {node: '>=12'} - cpu: [arm64] - os: [darwin] - - '@esbuild/darwin-arm64@0.25.12': - resolution: {integrity: sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==} - engines: {node: '>=18'} - cpu: [arm64] - os: [darwin] - - '@esbuild/darwin-arm64@0.27.0': - resolution: {integrity: sha512-uJOQKYCcHhg07DL7i8MzjvS2LaP7W7Pn/7uA0B5S1EnqAirJtbyw4yC5jQ5qcFjHK9l6o/MX9QisBg12kNkdHg==} + '@esbuild/darwin-arm64@0.25.2': + resolution: {integrity: sha512-MpM6LUVTXAzOvN4KbjzU/q5smzryuoNjlriAIx+06RpecwCkL9JpenNzpKd2YMzLJFOdPqBpuub6eVRP5IgiSA==} engines: {node: '>=18'} cpu: [arm64] os: [darwin] - '@esbuild/darwin-x64@0.21.5': - resolution: {integrity: sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==} - engines: {node: '>=12'} - cpu: [x64] - os: [darwin] - - '@esbuild/darwin-x64@0.25.12': - resolution: {integrity: sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==} + '@esbuild/darwin-x64@0.25.2': + resolution: {integrity: sha512-5eRPrTX7wFyuWe8FqEFPG2cU0+butQQVNcT4sVipqjLYQjjh8a8+vUTfgBKM88ObB85ahsnTwF7PSIt6PG+QkA==} engines: {node: '>=18'} cpu: [x64] os: [darwin] - '@esbuild/darwin-x64@0.27.0': - resolution: {integrity: sha512-8mG6arH3yB/4ZXiEnXof5MK72dE6zM9cDvUcPtxhUZsDjESl9JipZYW60C3JGreKCEP+p8P/72r69m4AZGJd5g==} + '@esbuild/freebsd-arm64@0.25.2': + resolution: {integrity: sha512-mLwm4vXKiQ2UTSX4+ImyiPdiHjiZhIaE9QvC7sw0tZ6HoNMjYAqQpGyui5VRIi5sGd+uWq940gdCbY3VLvsO1w==} engines: {node: '>=18'} - cpu: [x64] - os: [darwin] - - '@esbuild/freebsd-arm64@0.21.5': - resolution: {integrity: sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==} - engines: {node: '>=12'} cpu: [arm64] os: [freebsd] - '@esbuild/freebsd-arm64@0.25.12': - resolution: {integrity: sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==} - engines: {node: '>=18'} - cpu: [arm64] - os: [freebsd] - - '@esbuild/freebsd-arm64@0.27.0': - resolution: {integrity: sha512-9FHtyO988CwNMMOE3YIeci+UV+x5Zy8fI2qHNpsEtSF83YPBmE8UWmfYAQg6Ux7Gsmd4FejZqnEUZCMGaNQHQw==} - engines: {node: '>=18'} - cpu: [arm64] - os: [freebsd] - - '@esbuild/freebsd-x64@0.21.5': - resolution: {integrity: sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==} - engines: {node: '>=12'} - cpu: [x64] - os: [freebsd] - - '@esbuild/freebsd-x64@0.25.12': - resolution: {integrity: sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==} - engines: {node: '>=18'} - cpu: [x64] - os: [freebsd] - - '@esbuild/freebsd-x64@0.27.0': - resolution: {integrity: sha512-zCMeMXI4HS/tXvJz8vWGexpZj2YVtRAihHLk1imZj4efx1BQzN76YFeKqlDr3bUWI26wHwLWPd3rwh6pe4EV7g==} + '@esbuild/freebsd-x64@0.25.2': + resolution: {integrity: sha512-6qyyn6TjayJSwGpm8J9QYYGQcRgc90nmfdUb0O7pp1s4lTY+9D0H9O02v5JqGApUyiHOtkz6+1hZNvNtEhbwRQ==} engines: {node: '>=18'} cpu: [x64] os: [freebsd] - '@esbuild/linux-arm64@0.21.5': - resolution: {integrity: sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==} - engines: {node: '>=12'} - cpu: [arm64] - os: [linux] - - '@esbuild/linux-arm64@0.25.12': - resolution: {integrity: sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==} + '@esbuild/linux-arm64@0.25.2': + resolution: {integrity: sha512-gq/sjLsOyMT19I8obBISvhoYiZIAaGF8JpeXu1u8yPv8BE5HlWYobmlsfijFIZ9hIVGYkbdFhEqC0NvM4kNO0g==} engines: {node: '>=18'} cpu: [arm64] os: [linux] - '@esbuild/linux-arm64@0.27.0': - resolution: {integrity: sha512-AS18v0V+vZiLJyi/4LphvBE+OIX682Pu7ZYNsdUHyUKSoRwdnOsMf6FDekwoAFKej14WAkOef3zAORJgAtXnlQ==} - engines: {node: '>=18'} - cpu: [arm64] - os: [linux] - - '@esbuild/linux-arm@0.21.5': - resolution: {integrity: sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==} - engines: {node: '>=12'} - cpu: [arm] - os: [linux] - - '@esbuild/linux-arm@0.25.12': - resolution: {integrity: sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==} + '@esbuild/linux-arm@0.25.2': + resolution: {integrity: sha512-UHBRgJcmjJv5oeQF8EpTRZs/1knq6loLxTsjc3nxO9eXAPDLcWW55flrMVc97qFPbmZP31ta1AZVUKQzKTzb0g==} engines: {node: '>=18'} cpu: [arm] os: [linux] - '@esbuild/linux-arm@0.27.0': - resolution: {integrity: sha512-t76XLQDpxgmq2cNXKTVEB7O7YMb42atj2Re2Haf45HkaUpjM2J0UuJZDuaGbPbamzZ7bawyGFUkodL+zcE+jvQ==} - engines: {node: '>=18'} - cpu: [arm] - os: [linux] - - '@esbuild/linux-ia32@0.21.5': - resolution: {integrity: sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==} - engines: {node: '>=12'} - cpu: [ia32] - os: [linux] - - '@esbuild/linux-ia32@0.25.12': - resolution: {integrity: sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==} + '@esbuild/linux-ia32@0.25.2': + resolution: {integrity: sha512-bBYCv9obgW2cBP+2ZWfjYTU+f5cxRoGGQ5SeDbYdFCAZpYWrfjjfYwvUpP8MlKbP0nwZ5gyOU/0aUzZ5HWPuvQ==} engines: {node: '>=18'} cpu: [ia32] os: [linux] - '@esbuild/linux-ia32@0.27.0': - resolution: {integrity: sha512-Mz1jxqm/kfgKkc/KLHC5qIujMvnnarD9ra1cEcrs7qshTUSksPihGrWHVG5+osAIQ68577Zpww7SGapmzSt4Nw==} + '@esbuild/linux-loong64@0.25.2': + resolution: {integrity: sha512-SHNGiKtvnU2dBlM5D8CXRFdd+6etgZ9dXfaPCeJtz+37PIUlixvlIhI23L5khKXs3DIzAn9V8v+qb1TRKrgT5w==} engines: {node: '>=18'} - cpu: [ia32] - os: [linux] - - '@esbuild/linux-loong64@0.21.5': - resolution: {integrity: sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==} - engines: {node: '>=12'} cpu: [loong64] os: [linux] - '@esbuild/linux-loong64@0.25.12': - resolution: {integrity: sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==} - engines: {node: '>=18'} - cpu: [loong64] - os: [linux] - - '@esbuild/linux-loong64@0.27.0': - resolution: {integrity: sha512-QbEREjdJeIreIAbdG2hLU1yXm1uu+LTdzoq1KCo4G4pFOLlvIspBm36QrQOar9LFduavoWX2msNFAAAY9j4BDg==} - engines: {node: '>=18'} - cpu: [loong64] - os: [linux] - - '@esbuild/linux-mips64el@0.21.5': - resolution: {integrity: sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==} - engines: {node: '>=12'} - cpu: [mips64el] - os: [linux] - - '@esbuild/linux-mips64el@0.25.12': - resolution: {integrity: sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==} - engines: {node: '>=18'} - cpu: [mips64el] - os: [linux] - - '@esbuild/linux-mips64el@0.27.0': - resolution: {integrity: sha512-sJz3zRNe4tO2wxvDpH/HYJilb6+2YJxo/ZNbVdtFiKDufzWq4JmKAiHy9iGoLjAV7r/W32VgaHGkk35cUXlNOg==} + '@esbuild/linux-mips64el@0.25.2': + resolution: {integrity: sha512-hDDRlzE6rPeoj+5fsADqdUZl1OzqDYow4TB4Y/3PlKBD0ph1e6uPHzIQcv2Z65u2K0kpeByIyAjCmjn1hJgG0Q==} engines: {node: '>=18'} cpu: [mips64el] os: [linux] - '@esbuild/linux-ppc64@0.21.5': - resolution: {integrity: sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==} - engines: {node: '>=12'} - cpu: [ppc64] - os: [linux] - - '@esbuild/linux-ppc64@0.25.12': - resolution: {integrity: sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==} + '@esbuild/linux-ppc64@0.25.2': + resolution: {integrity: sha512-tsHu2RRSWzipmUi9UBDEzc0nLc4HtpZEI5Ba+Omms5456x5WaNuiG3u7xh5AO6sipnJ9r4cRWQB2tUjPyIkc6g==} engines: {node: '>=18'} cpu: [ppc64] os: [linux] - '@esbuild/linux-ppc64@0.27.0': - resolution: {integrity: sha512-z9N10FBD0DCS2dmSABDBb5TLAyF1/ydVb+N4pi88T45efQ/w4ohr/F/QYCkxDPnkhkp6AIpIcQKQ8F0ANoA2JA==} - engines: {node: '>=18'} - cpu: [ppc64] - os: [linux] - - '@esbuild/linux-riscv64@0.21.5': - resolution: {integrity: sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==} - engines: {node: '>=12'} - cpu: [riscv64] - os: [linux] - - '@esbuild/linux-riscv64@0.25.12': - resolution: {integrity: sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==} + '@esbuild/linux-riscv64@0.25.2': + resolution: {integrity: sha512-k4LtpgV7NJQOml/10uPU0s4SAXGnowi5qBSjaLWMojNCUICNu7TshqHLAEbkBdAszL5TabfvQ48kK84hyFzjnw==} engines: {node: '>=18'} cpu: [riscv64] os: [linux] - '@esbuild/linux-riscv64@0.27.0': - resolution: {integrity: sha512-pQdyAIZ0BWIC5GyvVFn5awDiO14TkT/19FTmFcPdDec94KJ1uZcmFs21Fo8auMXzD4Tt+diXu1LW1gHus9fhFQ==} - engines: {node: '>=18'} - cpu: [riscv64] - os: [linux] - - '@esbuild/linux-s390x@0.21.5': - resolution: {integrity: sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==} - engines: {node: '>=12'} - cpu: [s390x] - os: [linux] - - '@esbuild/linux-s390x@0.25.12': - resolution: {integrity: sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==} - engines: {node: '>=18'} - cpu: [s390x] - os: [linux] - - '@esbuild/linux-s390x@0.27.0': - resolution: {integrity: sha512-hPlRWR4eIDDEci953RI1BLZitgi5uqcsjKMxwYfmi4LcwyWo2IcRP+lThVnKjNtk90pLS8nKdroXYOqW+QQH+w==} + '@esbuild/linux-s390x@0.25.2': + resolution: {integrity: sha512-GRa4IshOdvKY7M/rDpRR3gkiTNp34M0eLTaC1a08gNrh4u488aPhuZOCpkF6+2wl3zAN7L7XIpOFBhnaE3/Q8Q==} engines: {node: '>=18'} cpu: [s390x] os: [linux] - '@esbuild/linux-x64@0.21.5': - resolution: {integrity: sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==} - engines: {node: '>=12'} - cpu: [x64] - os: [linux] - - '@esbuild/linux-x64@0.25.12': - resolution: {integrity: sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==} + '@esbuild/linux-x64@0.25.2': + resolution: {integrity: sha512-QInHERlqpTTZ4FRB0fROQWXcYRD64lAoiegezDunLpalZMjcUcld3YzZmVJ2H/Cp0wJRZ8Xtjtj0cEHhYc/uUg==} engines: {node: '>=18'} cpu: [x64] os: [linux] - '@esbuild/linux-x64@0.27.0': - resolution: {integrity: sha512-1hBWx4OUJE2cab++aVZ7pObD6s+DK4mPGpemtnAORBvb5l/g5xFGk0vc0PjSkrDs0XaXj9yyob3d14XqvnQ4gw==} - engines: {node: '>=18'} - cpu: [x64] - os: [linux] - - '@esbuild/netbsd-arm64@0.25.12': - resolution: {integrity: sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==} - engines: {node: '>=18'} - cpu: [arm64] - os: [netbsd] - - '@esbuild/netbsd-arm64@0.27.0': - resolution: {integrity: sha512-6m0sfQfxfQfy1qRuecMkJlf1cIzTOgyaeXaiVaaki8/v+WB+U4hc6ik15ZW6TAllRlg/WuQXxWj1jx6C+dfy3w==} + '@esbuild/netbsd-arm64@0.25.2': + resolution: {integrity: sha512-talAIBoY5M8vHc6EeI2WW9d/CkiO9MQJ0IOWX8hrLhxGbro/vBXJvaQXefW2cP0z0nQVTdQ/eNyGFV1GSKrxfw==} engines: {node: '>=18'} cpu: [arm64] os: [netbsd] - '@esbuild/netbsd-x64@0.21.5': - resolution: {integrity: sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==} - engines: {node: '>=12'} - cpu: [x64] - os: [netbsd] - - '@esbuild/netbsd-x64@0.25.12': - resolution: {integrity: sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==} - engines: {node: '>=18'} - cpu: [x64] - os: [netbsd] - - '@esbuild/netbsd-x64@0.27.0': - resolution: {integrity: sha512-xbbOdfn06FtcJ9d0ShxxvSn2iUsGd/lgPIO2V3VZIPDbEaIj1/3nBBe1AwuEZKXVXkMmpr6LUAgMkLD/4D2PPA==} + '@esbuild/netbsd-x64@0.25.2': + resolution: {integrity: sha512-voZT9Z+tpOxrvfKFyfDYPc4DO4rk06qamv1a/fkuzHpiVBMOhpjK+vBmWM8J1eiB3OLSMFYNaOaBNLXGChf5tg==} engines: {node: '>=18'} cpu: [x64] os: [netbsd] - '@esbuild/openbsd-arm64@0.25.12': - resolution: {integrity: sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==} + '@esbuild/openbsd-arm64@0.25.2': + resolution: {integrity: sha512-dcXYOC6NXOqcykeDlwId9kB6OkPUxOEqU+rkrYVqJbK2hagWOMrsTGsMr8+rW02M+d5Op5NNlgMmjzecaRf7Tg==} engines: {node: '>=18'} cpu: [arm64] os: [openbsd] - '@esbuild/openbsd-arm64@0.27.0': - resolution: {integrity: sha512-fWgqR8uNbCQ/GGv0yhzttj6sU/9Z5/Sv/VGU3F5OuXK6J6SlriONKrQ7tNlwBrJZXRYk5jUhuWvF7GYzGguBZQ==} + '@esbuild/openbsd-x64@0.25.2': + resolution: {integrity: sha512-t/TkWwahkH0Tsgoq1Ju7QfgGhArkGLkF1uYz8nQS/PPFlXbP5YgRpqQR3ARRiC2iXoLTWFxc6DJMSK10dVXluw==} engines: {node: '>=18'} - cpu: [arm64] - os: [openbsd] - - '@esbuild/openbsd-x64@0.21.5': - resolution: {integrity: sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==} - engines: {node: '>=12'} cpu: [x64] os: [openbsd] - '@esbuild/openbsd-x64@0.25.12': - resolution: {integrity: sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==} - engines: {node: '>=18'} - cpu: [x64] - os: [openbsd] - - '@esbuild/openbsd-x64@0.27.0': - resolution: {integrity: sha512-aCwlRdSNMNxkGGqQajMUza6uXzR/U0dIl1QmLjPtRbLOx3Gy3otfFu/VjATy4yQzo9yFDGTxYDo1FfAD9oRD2A==} - engines: {node: '>=18'} - cpu: [x64] - os: [openbsd] - - '@esbuild/openharmony-arm64@0.25.12': - resolution: {integrity: sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==} - engines: {node: '>=18'} - cpu: [arm64] - os: [openharmony] - - '@esbuild/openharmony-arm64@0.27.0': - resolution: {integrity: sha512-nyvsBccxNAsNYz2jVFYwEGuRRomqZ149A39SHWk4hV0jWxKM0hjBPm3AmdxcbHiFLbBSwG6SbpIcUbXjgyECfA==} - engines: {node: '>=18'} - cpu: [arm64] - os: [openharmony] - - '@esbuild/sunos-x64@0.21.5': - resolution: {integrity: sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==} - engines: {node: '>=12'} - cpu: [x64] - os: [sunos] - - '@esbuild/sunos-x64@0.25.12': - resolution: {integrity: sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==} + '@esbuild/sunos-x64@0.25.2': + resolution: {integrity: sha512-cfZH1co2+imVdWCjd+D1gf9NjkchVhhdpgb1q5y6Hcv9TP6Zi9ZG/beI3ig8TvwT9lH9dlxLq5MQBBgwuj4xvA==} engines: {node: '>=18'} cpu: [x64] os: [sunos] - '@esbuild/sunos-x64@0.27.0': - resolution: {integrity: sha512-Q1KY1iJafM+UX6CFEL+F4HRTgygmEW568YMqDA5UV97AuZSm21b7SXIrRJDwXWPzr8MGr75fUZPV67FdtMHlHA==} + '@esbuild/win32-arm64@0.25.2': + resolution: {integrity: sha512-7Loyjh+D/Nx/sOTzV8vfbB3GJuHdOQyrOryFdZvPHLf42Tk9ivBU5Aedi7iyX+x6rbn2Mh68T4qq1SDqJBQO5Q==} engines: {node: '>=18'} - cpu: [x64] - os: [sunos] - - '@esbuild/win32-arm64@0.21.5': - resolution: {integrity: sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==} - engines: {node: '>=12'} cpu: [arm64] os: [win32] - '@esbuild/win32-arm64@0.25.12': - resolution: {integrity: sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==} + '@esbuild/win32-ia32@0.25.2': + resolution: {integrity: sha512-WRJgsz9un0nqZJ4MfhabxaD9Ft8KioqU3JMinOTvobbX6MOSUigSBlogP8QB3uxpJDsFS6yN+3FDBdqE5lg9kg==} engines: {node: '>=18'} - cpu: [arm64] - os: [win32] - - '@esbuild/win32-arm64@0.27.0': - resolution: {integrity: sha512-W1eyGNi6d+8kOmZIwi/EDjrL9nxQIQ0MiGqe/AWc6+IaHloxHSGoeRgDRKHFISThLmsewZ5nHFvGFWdBYlgKPg==} - engines: {node: '>=18'} - cpu: [arm64] - os: [win32] - - '@esbuild/win32-ia32@0.21.5': - resolution: {integrity: sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==} - engines: {node: '>=12'} cpu: [ia32] os: [win32] - '@esbuild/win32-ia32@0.25.12': - resolution: {integrity: sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==} - engines: {node: '>=18'} - cpu: [ia32] - os: [win32] - - '@esbuild/win32-ia32@0.27.0': - resolution: {integrity: sha512-30z1aKL9h22kQhilnYkORFYt+3wp7yZsHWus+wSKAJR8JtdfI76LJ4SBdMsCopTR3z/ORqVu5L1vtnHZWVj4cQ==} - engines: {node: '>=18'} - cpu: [ia32] - os: [win32] - - '@esbuild/win32-x64@0.21.5': - resolution: {integrity: sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==} - engines: {node: '>=12'} - cpu: [x64] - os: [win32] - - '@esbuild/win32-x64@0.25.12': - resolution: {integrity: sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==} - engines: {node: '>=18'} - cpu: [x64] - os: [win32] - - '@esbuild/win32-x64@0.27.0': - resolution: {integrity: sha512-aIitBcjQeyOhMTImhLZmtxfdOcuNRpwlPNmlFKPcHQYPhEssw75Cl1TSXJXpMkzaua9FUetx/4OQKq7eJul5Cg==} + '@esbuild/win32-x64@0.25.2': + resolution: {integrity: sha512-kM3HKb16VIXZyIeVrM1ygYmZBKybX8N4p754bw390wGO3Tf2j4L2/WYL+4suWujpgf6GBYs3jv7TyUivdd05JA==} engines: {node: '>=18'} cpu: [x64] os: [win32] @@ -1710,7 +1426,7 @@ packages: resolution: {integrity: sha512-46ryTE9RZO/rfDd7pEqFl7etuyzekzEhUbTW3BvmeO/BcCMEgq59BKhek3dXDWgAj4oMK6OZi+vRr1wPW6qjEQ==} peerDependencies: msw: ^2.4.9 - vite: ^5.0.0 || ^6.0.0 || ^7.0.0-0 + vite: 5.4.21 peerDependenciesMeta: msw: optional: true @@ -1888,11 +1604,8 @@ packages: resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} engines: {node: '>= 0.4'} - axios@1.13.2: - resolution: {integrity: sha512-VPk9ebNqPcy5lRGuSlKx752IlDatOjT9paPlm8A7yOuW2Fbvp4X3JznJtT4f0GzGLLiWE9W8onz51SqLYwzGaA==} - - axios@1.9.0: - resolution: {integrity: sha512-re4CqKTJaURpzbLHtIi6XpDv20/CnpXOtjRY5/CU32L8gU8ek9UIivcfvSWvmKEngmVbrUtPpdDwWDWL7DNHvg==} + axios@1.12.0: + resolution: {integrity: sha512-oXTDccv8PcfjZmPGlWsPSwtOJCZ/b6W5jAMCNcfwJbCzDckwG0jrYJFaWH1yvivfCXjVzV/SPDEhMB3Q+DSurg==} balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} @@ -1932,11 +1645,8 @@ packages: bottleneck@2.19.5: resolution: {integrity: sha512-VHiNCbI1lKdl44tGrhNfU3lup0Tj/ZBMJB5/2ZbNXRCPuRCO7ed2mgcK4r17y+KB2EfuYuRaVlwNbAeaWGSpbw==} - brace-expansion@1.1.11: - resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} - - brace-expansion@2.0.1: - resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} + brace-expansion@1.1.12: + resolution: {integrity: sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==} braces@3.0.3: resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} @@ -1959,7 +1669,7 @@ packages: resolution: {integrity: sha512-3WrrOuZiyaaZPWiEt4G3+IffISVC9HYlWueJEBWED4ZH4aIAC2PnkdnuRrR94M+w6yGWn4AglWtJtBI8YqvgoA==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} peerDependencies: - esbuild: '>=0.18' + esbuild: 0.25.2 cac@6.7.14: resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} @@ -1998,10 +1708,6 @@ packages: resolution: {integrity: sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw==} engines: {node: '>=18'} - chalk@3.0.0: - resolution: {integrity: sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==} - engines: {node: '>=8'} - chalk@4.1.2: resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} engines: {node: '>=10'} @@ -2294,9 +2000,6 @@ packages: detect-node@2.1.0: resolution: {integrity: sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==} - diff-match-patch@1.0.5: - resolution: {integrity: sha512-IayShXAgj/QMXgB0IWmKx+rOPuGMhqm5w6jvFxmVenXKIzRqTAAsbBPT3kWQeGANj3jGgvcvv4yK6SxqYmikgw==} - diff@4.0.2: resolution: {integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==} engines: {node: '>=0.3.1'} @@ -2389,18 +2092,8 @@ packages: es6-error@4.1.1: resolution: {integrity: sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==} - esbuild@0.21.5: - resolution: {integrity: sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==} - engines: {node: '>=12'} - hasBin: true - - esbuild@0.25.12: - resolution: {integrity: sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==} - engines: {node: '>=18'} - hasBin: true - - esbuild@0.27.0: - resolution: {integrity: sha512-jd0f4NHbD6cALCyGElNpGAOtWxSq46l9X/sWB0Nzd5er4Kz2YTm+Vl0qKFT9KUJvD8+fiO8AvoHhFvEatfVixA==} + esbuild@0.25.2: + resolution: {integrity: sha512-16854zccKPnC+toMywC+uKNeYSv+/eXkevRAfwRD/G9Cleq66m8XFIrigkbvauLLlCfDL45Q2cWegSg53gGBnQ==} engines: {node: '>=18'} hasBin: true @@ -2527,10 +2220,6 @@ packages: resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==} engines: {node: '>=14'} - form-data@4.0.2: - resolution: {integrity: sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w==} - engines: {node: '>= 6'} - form-data@4.0.4: resolution: {integrity: sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==} engines: {node: '>= 6'} @@ -2553,9 +2242,6 @@ packages: fs.promises.exists@1.1.4: resolution: {integrity: sha512-lJzUGWbZn8vhGWBedA+RYjB/BeJ+3458ljUfmplqhIeb6ewzTFWNPCR1HCiYCkXV9zxcHz9zXkJzMsEgDLzh3Q==} - fs.realpath@1.0.0: - resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} - fsevents@2.3.3: resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} @@ -2606,19 +2292,10 @@ packages: resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} engines: {node: '>= 6'} - glob@10.4.5: - resolution: {integrity: sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==} + glob@10.5.0: + resolution: {integrity: sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==} hasBin: true - glob@7.2.3: - resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} - deprecated: Glob versions prior to v9 are no longer supported - - glob@8.1.0: - resolution: {integrity: sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==} - engines: {node: '>=12'} - deprecated: Glob versions prior to v9 are no longer supported - global-agent@3.0.0: resolution: {integrity: sha512-PT6XReJ+D07JvGoxQMkT6qji/jVNfX/h364XHZOWeRzy64sSFr+xJ5OX7LI3b4MPQzdL4H8Y8M0xzPpsVMwA8Q==} engines: {node: '>=10.0'} @@ -2742,10 +2419,6 @@ packages: infer-owner@1.0.4: resolution: {integrity: sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==} - inflight@1.0.6: - resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} - deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful. - inherits@2.0.4: resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} @@ -2884,12 +2557,12 @@ packages: isomorphic-ws@5.0.0: resolution: {integrity: sha512-muId7Zzn9ywDsyXgTIafTry2sV3nySZeUDe6YedVd1Hvuuep5AsIlqK+XefWpYTyJG5e503F2xIuT2lcU6rCSw==} peerDependencies: - ws: '*' + ws: 8.17.1 isows@1.0.7: resolution: {integrity: sha512-I1fSfDCZL5P0v33sVqeTDSpcstAg/N+wF5HS033mogOVIp4B+oHC7oOCsA3axAbBSGTJ8QubbNmnIRN/h8U7hg==} peerDependencies: - ws: '*' + ws: 8.17.1 jackspeak@3.4.3: resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==} @@ -2904,8 +2577,8 @@ packages: js-tokens@9.0.1: resolution: {integrity: sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==} - js-yaml@4.1.0: - resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} + js-yaml@4.1.1: + resolution: {integrity: sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==} hasBin: true jsbn@1.1.0: @@ -2929,11 +2602,10 @@ packages: jsonc-parser@3.3.1: resolution: {integrity: sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==} - jsondiffpatch@0.5.0: - resolution: {integrity: sha512-Quz3MvAwHxVYNXsOByL7xI5EB2WYOeFswqaHIA3qOK3isRWTxiplBEocmmru6XmxDB2L7jDNYtYA4FyimoAFEw==} - engines: {node: '>=8.17.0'} + jsondiffpatch@0.7.2: + resolution: {integrity: sha512-hnxhN96i1bNZsqQba+/62kTOfXLtlUE1wBocMdznP0cVSnbDMXQTtwvmKzGVIdN/dbYMKPywykvfUXDsHy7Mcg==} + engines: {node: ^18.0.0 || >=20.0.0} hasBin: true - bundledDependencies: [] jsonfile@6.1.0: resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==} @@ -3059,9 +2731,6 @@ packages: resolution: {integrity: sha512-IPZ167aShDZZUMdRk66cyQAW3qr0WzbHkPdMYa8bzZhlHhO3jALbKdxcaak7W9FfT2rZNpQuUu4Od7ILEpXSaw==} engines: {node: 20 || >=22} - minimatch@3.1.2: - resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} - minimatch@5.1.6: resolution: {integrity: sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==} engines: {node: '>=10'} @@ -3219,6 +2888,7 @@ packages: node-domexception@1.0.0: resolution: {integrity: sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==} engines: {node: '>=10.5.0'} + deprecated: Use your platform's native DOMException instead node-fetch@2.7.0: resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==} @@ -3351,10 +3021,6 @@ packages: resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} engines: {node: '>=8'} - path-is-absolute@1.0.1: - resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} - engines: {node: '>=0.10.0'} - path-key@3.1.1: resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} engines: {node: '>=8'} @@ -3807,10 +3473,6 @@ packages: resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} engines: {node: '>=8'} - strip-ansi@7.1.0: - resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} - engines: {node: '>=12'} - strip-ansi@7.1.2: resolution: {integrity: sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==} engines: {node: '>=12'} @@ -3854,9 +3516,6 @@ packages: symbol-tree@3.2.4: resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==} - tar-fs@2.1.2: - resolution: {integrity: sha512-EsaAXwxmx8UB7FRKqeozqEPop69DXcmYwTQwXvyAPF352HJsPdkVhvTaDPYqfNgruveJIJy3TA2l+2zj8LJIJA==} - tar-fs@2.1.4: resolution: {integrity: sha512-mDAjwmZdh7LTT6pNleZ05Yt65HC3E+NiQzl672vQG38jIrehtJk/J3mNwIg+vShQPcLF/LV7CMnDW6vjj6sfYQ==} @@ -3909,8 +3568,8 @@ packages: tmp-promise@3.0.3: resolution: {integrity: sha512-RwM7MoPojPxsOBYnyd2hy0bxtIlVrihNs9pj5SUvY8Zz1sQcQG2tG1hSr8PDxfgEB8RNKDhqbIlroIarSNDNsQ==} - tmp@0.2.5: - resolution: {integrity: sha512-voyz6MApa1rQGUxT3E+BK7/ROe8itEx7vD8/HEvt4xwXucvQ5G5oeEiHkmHZJuBO21RpOf+YYm9MOivj709jow==} + tmp@0.2.4: + resolution: {integrity: sha512-UdiSoX6ypifLmrfQ/XfiawN6hkjSBpCjhKxxZcWlUUmoXLaCKQU0bx4HF/tdDK2uzRuchf1txGvrWBzYREssoQ==} engines: {node: '>=14.14'} to-buffer@1.2.2: @@ -4019,8 +3678,8 @@ packages: resolution: {integrity: sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==} engines: {node: '>= 0.4'} - typeorm@0.3.27: - resolution: {integrity: sha512-pNV1bn+1n8qEe8tUNsNdD8ejuPcMAg47u2lUGnbsajiNUr3p2Js1XLKQjBMH0yMRMDfdX8T+fIRejFmIwy9x4A==} + typeorm@0.3.26: + resolution: {integrity: sha512-o2RrBNn3lczx1qv4j+JliVMmtkPSqEGpG0UuZkt9tCfWkoXKu8MZnjvp2GjWPll1SehwemQw6xrbVRhmOglj8Q==} engines: {node: '>=16.13.0'} hasBin: true peerDependencies: @@ -4170,8 +3829,8 @@ packages: engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} hasBin: true - vite@5.4.14: - resolution: {integrity: sha512-EK5cY7Q1D8JNhSaPKVK4pwBFvaTmZxEnoKXLG/U9gmdDcihQGNzFlgIvaxezFR4glP1LsuiedwMBqCXH3wZccA==} + vite@5.4.21: + resolution: {integrity: sha512-o5a9xKjbtuhY6Bi5S3+HvbRERmouabWbyUcpXXUA1u+GNUKoROi9byOJ8M0nHbHYHkYICiMlqxkg1KkYmm25Sw==} engines: {node: ^18.0.0 || >=20.0.0} hasBin: true peerDependencies: @@ -4410,18 +4069,6 @@ packages: utf-8-validate: optional: true - ws@8.18.3: - resolution: {integrity: sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==} - engines: {node: '>=10.0.0'} - peerDependencies: - bufferutil: ^4.0.1 - utf-8-validate: '>=5.0.2' - peerDependenciesMeta: - bufferutil: - optional: true - utf-8-validate: - optional: true - xml-name-validator@5.0.0: resolution: {integrity: sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==} engines: {node: '>=18'} @@ -4522,7 +4169,7 @@ snapshots: idb: 8.0.3 reflect-metadata: 0.2.2 sqlite3: 5.1.7 - typeorm: 0.3.27(reflect-metadata@0.2.2)(sqlite3@5.1.7)(ts-node@10.9.2(@types/node@22.10.2)(typescript@5.4.5)) + typeorm: 0.3.26(reflect-metadata@0.2.2)(sqlite3@5.1.7)(ts-node@10.9.2(@types/node@22.10.2)(typescript@5.4.5)) transitivePeerDependencies: - '@google-cloud/spanner' - '@sap/hana-client' @@ -4561,14 +4208,14 @@ snapshots: '@polkadot/types': 16.5.2 '@polkadot/util': 13.5.2 '@polkadot/util-crypto': 13.5.2(@polkadot/util@13.5.2) - axios: 1.13.2(debug@4.3.4) + axios: 1.12.0(debug@4.3.4) comlink: 4.4.2 dotenv: 16.6.1 global-agent: 3.0.0 - js-yaml: 4.1.0 - jsondiffpatch: 0.5.0 + js-yaml: 4.1.1 + jsondiffpatch: 0.7.2 lodash: 4.17.21 - ws: 8.18.3 + ws: 8.17.1 yargs: 18.0.0 zod: 3.25.76 transitivePeerDependencies: @@ -4693,6 +4340,8 @@ snapshots: '@csstools/css-tokenizer@3.0.3': {} + '@dmsnell/diff-match-patch@1.1.0': {} + '@effect/cluster@0.50.6(@effect/platform@0.92.1(effect@3.19.3))(@effect/rpc@0.71.2(@effect/platform@0.92.1(effect@3.19.3))(effect@3.19.3))(@effect/sql@0.46.0(@effect/experimental@0.56.0(@effect/platform@0.92.1(effect@3.19.3))(effect@3.19.3))(@effect/platform@0.92.1(effect@3.19.3))(effect@3.19.3))(@effect/workflow@0.11.5(@effect/platform@0.92.1(effect@3.19.3))(@effect/rpc@0.71.2(@effect/platform@0.92.1(effect@3.19.3))(effect@3.19.3))(effect@3.19.3))(effect@3.19.3)': dependencies: '@effect/platform': 0.92.1(effect@3.19.3) @@ -4716,7 +4365,7 @@ snapshots: '@parcel/watcher': 2.5.1 effect: 3.19.3 multipasta: 0.2.7 - ws: 8.18.3 + ws: 8.17.1 transitivePeerDependencies: - bufferutil - utf-8-validate @@ -4731,7 +4380,7 @@ snapshots: effect: 3.19.3 mime: 3.0.0 undici: 7.16.0 - ws: 8.18.3 + ws: 8.17.1 transitivePeerDependencies: - bufferutil - utf-8-validate @@ -4762,229 +4411,79 @@ snapshots: '@effect/rpc': 0.71.2(@effect/platform@0.92.1(effect@3.19.3))(effect@3.19.3) effect: 3.19.3 - '@esbuild/aix-ppc64@0.21.5': - optional: true - - '@esbuild/aix-ppc64@0.25.12': - optional: true - - '@esbuild/aix-ppc64@0.27.0': - optional: true - - '@esbuild/android-arm64@0.21.5': - optional: true - - '@esbuild/android-arm64@0.25.12': - optional: true - - '@esbuild/android-arm64@0.27.0': - optional: true - - '@esbuild/android-arm@0.21.5': - optional: true - - '@esbuild/android-arm@0.25.12': - optional: true - - '@esbuild/android-arm@0.27.0': - optional: true - - '@esbuild/android-x64@0.21.5': - optional: true - - '@esbuild/android-x64@0.25.12': - optional: true - - '@esbuild/android-x64@0.27.0': - optional: true - - '@esbuild/darwin-arm64@0.21.5': - optional: true - - '@esbuild/darwin-arm64@0.25.12': - optional: true - - '@esbuild/darwin-arm64@0.27.0': - optional: true - - '@esbuild/darwin-x64@0.21.5': - optional: true - - '@esbuild/darwin-x64@0.25.12': - optional: true - - '@esbuild/darwin-x64@0.27.0': - optional: true - - '@esbuild/freebsd-arm64@0.21.5': - optional: true - - '@esbuild/freebsd-arm64@0.25.12': - optional: true - - '@esbuild/freebsd-arm64@0.27.0': - optional: true - - '@esbuild/freebsd-x64@0.21.5': - optional: true - - '@esbuild/freebsd-x64@0.25.12': - optional: true - - '@esbuild/freebsd-x64@0.27.0': - optional: true - - '@esbuild/linux-arm64@0.21.5': - optional: true - - '@esbuild/linux-arm64@0.25.12': - optional: true - - '@esbuild/linux-arm64@0.27.0': - optional: true - - '@esbuild/linux-arm@0.21.5': - optional: true - - '@esbuild/linux-arm@0.25.12': - optional: true - - '@esbuild/linux-arm@0.27.0': - optional: true - - '@esbuild/linux-ia32@0.21.5': - optional: true - - '@esbuild/linux-ia32@0.25.12': - optional: true - - '@esbuild/linux-ia32@0.27.0': - optional: true - - '@esbuild/linux-loong64@0.21.5': - optional: true - - '@esbuild/linux-loong64@0.25.12': - optional: true - - '@esbuild/linux-loong64@0.27.0': - optional: true - - '@esbuild/linux-mips64el@0.21.5': - optional: true - - '@esbuild/linux-mips64el@0.25.12': - optional: true - - '@esbuild/linux-mips64el@0.27.0': - optional: true - - '@esbuild/linux-ppc64@0.21.5': - optional: true - - '@esbuild/linux-ppc64@0.25.12': - optional: true - - '@esbuild/linux-ppc64@0.27.0': - optional: true - - '@esbuild/linux-riscv64@0.21.5': - optional: true - - '@esbuild/linux-riscv64@0.25.12': - optional: true - - '@esbuild/linux-riscv64@0.27.0': - optional: true - - '@esbuild/linux-s390x@0.21.5': - optional: true - - '@esbuild/linux-s390x@0.25.12': - optional: true - - '@esbuild/linux-s390x@0.27.0': - optional: true - - '@esbuild/linux-x64@0.21.5': - optional: true - - '@esbuild/linux-x64@0.25.12': + '@esbuild/aix-ppc64@0.25.2': optional: true - '@esbuild/linux-x64@0.27.0': + '@esbuild/android-arm64@0.25.2': optional: true - '@esbuild/netbsd-arm64@0.25.12': + '@esbuild/android-arm@0.25.2': optional: true - '@esbuild/netbsd-arm64@0.27.0': + '@esbuild/android-x64@0.25.2': optional: true - '@esbuild/netbsd-x64@0.21.5': + '@esbuild/darwin-arm64@0.25.2': optional: true - '@esbuild/netbsd-x64@0.25.12': + '@esbuild/darwin-x64@0.25.2': optional: true - '@esbuild/netbsd-x64@0.27.0': + '@esbuild/freebsd-arm64@0.25.2': optional: true - '@esbuild/openbsd-arm64@0.25.12': + '@esbuild/freebsd-x64@0.25.2': optional: true - '@esbuild/openbsd-arm64@0.27.0': + '@esbuild/linux-arm64@0.25.2': optional: true - '@esbuild/openbsd-x64@0.21.5': + '@esbuild/linux-arm@0.25.2': optional: true - '@esbuild/openbsd-x64@0.25.12': + '@esbuild/linux-ia32@0.25.2': optional: true - '@esbuild/openbsd-x64@0.27.0': + '@esbuild/linux-loong64@0.25.2': optional: true - '@esbuild/openharmony-arm64@0.25.12': + '@esbuild/linux-mips64el@0.25.2': optional: true - '@esbuild/openharmony-arm64@0.27.0': + '@esbuild/linux-ppc64@0.25.2': optional: true - '@esbuild/sunos-x64@0.21.5': + '@esbuild/linux-riscv64@0.25.2': optional: true - '@esbuild/sunos-x64@0.25.12': + '@esbuild/linux-s390x@0.25.2': optional: true - '@esbuild/sunos-x64@0.27.0': + '@esbuild/linux-x64@0.25.2': optional: true - '@esbuild/win32-arm64@0.21.5': + '@esbuild/netbsd-arm64@0.25.2': optional: true - '@esbuild/win32-arm64@0.25.12': + '@esbuild/netbsd-x64@0.25.2': optional: true - '@esbuild/win32-arm64@0.27.0': + '@esbuild/openbsd-arm64@0.25.2': optional: true - '@esbuild/win32-ia32@0.21.5': + '@esbuild/openbsd-x64@0.25.2': optional: true - '@esbuild/win32-ia32@0.25.12': + '@esbuild/sunos-x64@0.25.2': optional: true - '@esbuild/win32-ia32@0.27.0': + '@esbuild/win32-arm64@0.25.2': optional: true - '@esbuild/win32-x64@0.21.5': + '@esbuild/win32-ia32@0.25.2': optional: true - '@esbuild/win32-x64@0.25.12': - optional: true - - '@esbuild/win32-x64@0.27.0': + '@esbuild/win32-x64@0.25.2': optional: true '@ethereumjs/rlp@4.0.1': {} @@ -5148,7 +4647,7 @@ snapshots: dependencies: string-width: 5.1.2 string-width-cjs: string-width@4.2.3 - strip-ansi: 7.1.0 + strip-ansi: 7.1.2 strip-ansi-cjs: strip-ansi@6.0.1 wrap-ansi: 8.1.0 wrap-ansi-cjs: wrap-ansi@7.0.0 @@ -5185,7 +4684,7 @@ snapshots: '@polkadot/types': 16.5.2 '@polkadot/types-codec': 16.5.2 '@types/node': 22.10.2 - axios: 1.9.0(debug@4.3.4) + axios: 1.12.0(debug@4.3.4) chalk: 5.6.2 tsup: 8.5.1(postcss@8.5.3)(tsx@4.20.6)(typescript@5.4.5)(yaml@2.8.1) tsx: 4.20.6 @@ -5270,12 +4769,12 @@ snapshots: reflect-metadata: 0.2.2 semver: 7.7.3 tiny-invariant: 1.3.3 - tmp: 0.2.5 + tmp: 0.2.4 viem: 2.37.13(typescript@5.4.5)(zod@3.25.76) vitest: 3.2.4(@types/node@22.10.2)(@vitest/ui@3.2.4)(jsdom@23.2.0) web3: 4.16.0(encoding@0.1.13)(typescript@5.4.5)(zod@3.25.76) web3-providers-ws: 4.0.8 - ws: 8.18.3 + ws: 8.17.1 yaml: 2.8.1 yargs: 18.0.0 transitivePeerDependencies: @@ -5404,7 +4903,7 @@ snapshots: viem: 2.37.13(typescript@5.4.5)(zod@3.25.76) vitest: 3.2.4(@types/node@22.10.2)(@vitest/ui@3.2.4)(jsdom@23.2.0) web3: 4.16.0(encoding@0.1.13)(typescript@5.4.5)(zod@3.25.76) - ws: 8.18.3 + ws: 8.17.1 yargs: 18.0.0 transitivePeerDependencies: - '@edge-runtime/vm' @@ -5845,7 +5344,7 @@ snapshots: '@polkadot-api/json-rpc-provider': 0.0.4 '@polkadot-api/json-rpc-provider-proxy': 0.2.4 '@types/ws': 8.18.1 - ws: 8.18.3 + ws: 8.17.1 transitivePeerDependencies: - bufferutil - utf-8-validate @@ -6240,7 +5739,7 @@ snapshots: dependencies: '@polkadot/x-global': 13.5.1 tslib: 2.8.1 - ws: 8.18.3 + ws: 8.17.1 transitivePeerDependencies: - bufferutil - utf-8-validate @@ -6249,7 +5748,7 @@ snapshots: dependencies: '@polkadot/x-global': 13.5.8 tslib: 2.8.1 - ws: 8.18.3 + ws: 8.17.1 transitivePeerDependencies: - bufferutil - utf-8-validate @@ -6470,13 +5969,13 @@ snapshots: chai: 5.3.3 tinyrainbow: 2.0.0 - '@vitest/mocker@3.2.4(vite@5.4.14(@types/node@22.10.2))': + '@vitest/mocker@3.2.4(vite@5.4.21(@types/node@22.10.2))': dependencies: '@vitest/spy': 3.2.4 estree-walker: 3.0.3 magic-string: 0.30.17 optionalDependencies: - vite: 5.4.14(@types/node@22.10.2) + vite: 5.4.21(@types/node@22.10.2) '@vitest/pretty-format@3.2.4': dependencies: @@ -6704,7 +6203,7 @@ snapshots: dependencies: possible-typed-array-names: 1.1.0 - axios@1.13.2(debug@4.3.4): + axios@1.12.0(debug@4.3.4): dependencies: follow-redirects: 1.15.9(debug@4.3.4) form-data: 4.0.4 @@ -6712,14 +6211,6 @@ snapshots: transitivePeerDependencies: - debug - axios@1.9.0(debug@4.3.4): - dependencies: - follow-redirects: 1.15.9(debug@4.3.4) - form-data: 4.0.2 - proxy-from-env: 1.1.0 - transitivePeerDependencies: - - debug - balanced-match@1.0.2: {} base64-js@1.5.1: {} @@ -6754,15 +6245,10 @@ snapshots: bottleneck@2.19.5: {} - brace-expansion@1.1.11: + brace-expansion@1.1.12: dependencies: balanced-match: 1.0.2 concat-map: 0.0.1 - optional: true - - brace-expansion@2.0.1: - dependencies: - balanced-match: 1.0.2 braces@3.0.3: dependencies: @@ -6783,9 +6269,9 @@ snapshots: buildcheck@0.0.6: optional: true - bundle-require@5.1.0(esbuild@0.27.0): + bundle-require@5.1.0(esbuild@0.25.2): dependencies: - esbuild: 0.27.0 + esbuild: 0.25.2 load-tsconfig: 0.2.5 cac@6.7.14: {} @@ -6796,7 +6282,7 @@ snapshots: '@npmcli/move-file': 1.1.2 chownr: 2.0.0 fs-minipass: 2.1.0 - glob: 7.2.3 + glob: 10.5.0 infer-owner: 1.0.4 lru-cache: 6.0.0 minipass: 3.3.6 @@ -6856,11 +6342,6 @@ snapshots: loupe: 3.2.1 pathval: 2.0.1 - chalk@3.0.0: - dependencies: - ansi-styles: 4.3.0 - supports-color: 7.2.0 - chalk@4.1.2: dependencies: ansi-styles: 4.3.0 @@ -6947,7 +6428,7 @@ snapshots: cliui@9.0.1: dependencies: string-width: 7.2.0 - strip-ansi: 7.1.0 + strip-ansi: 7.1.2 wrap-ansi: 9.0.2 code-excerpt@4.0.0: @@ -6981,8 +6462,7 @@ snapshots: comment-parser@1.4.1: {} - concat-map@0.0.1: - optional: true + concat-map@0.0.1: {} confbox@0.1.8: {} @@ -7106,8 +6586,6 @@ snapshots: detect-node@2.1.0: {} - diff-match-patch@1.0.5: {} - diff@4.0.2: {} diff@5.2.0: {} @@ -7198,89 +6676,33 @@ snapshots: es6-error@4.1.1: {} - esbuild@0.21.5: - optionalDependencies: - '@esbuild/aix-ppc64': 0.21.5 - '@esbuild/android-arm': 0.21.5 - '@esbuild/android-arm64': 0.21.5 - '@esbuild/android-x64': 0.21.5 - '@esbuild/darwin-arm64': 0.21.5 - '@esbuild/darwin-x64': 0.21.5 - '@esbuild/freebsd-arm64': 0.21.5 - '@esbuild/freebsd-x64': 0.21.5 - '@esbuild/linux-arm': 0.21.5 - '@esbuild/linux-arm64': 0.21.5 - '@esbuild/linux-ia32': 0.21.5 - '@esbuild/linux-loong64': 0.21.5 - '@esbuild/linux-mips64el': 0.21.5 - '@esbuild/linux-ppc64': 0.21.5 - '@esbuild/linux-riscv64': 0.21.5 - '@esbuild/linux-s390x': 0.21.5 - '@esbuild/linux-x64': 0.21.5 - '@esbuild/netbsd-x64': 0.21.5 - '@esbuild/openbsd-x64': 0.21.5 - '@esbuild/sunos-x64': 0.21.5 - '@esbuild/win32-arm64': 0.21.5 - '@esbuild/win32-ia32': 0.21.5 - '@esbuild/win32-x64': 0.21.5 - - esbuild@0.25.12: + esbuild@0.25.2: 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 - - esbuild@0.27.0: - optionalDependencies: - '@esbuild/aix-ppc64': 0.27.0 - '@esbuild/android-arm': 0.27.0 - '@esbuild/android-arm64': 0.27.0 - '@esbuild/android-x64': 0.27.0 - '@esbuild/darwin-arm64': 0.27.0 - '@esbuild/darwin-x64': 0.27.0 - '@esbuild/freebsd-arm64': 0.27.0 - '@esbuild/freebsd-x64': 0.27.0 - '@esbuild/linux-arm': 0.27.0 - '@esbuild/linux-arm64': 0.27.0 - '@esbuild/linux-ia32': 0.27.0 - '@esbuild/linux-loong64': 0.27.0 - '@esbuild/linux-mips64el': 0.27.0 - '@esbuild/linux-ppc64': 0.27.0 - '@esbuild/linux-riscv64': 0.27.0 - '@esbuild/linux-s390x': 0.27.0 - '@esbuild/linux-x64': 0.27.0 - '@esbuild/netbsd-arm64': 0.27.0 - '@esbuild/netbsd-x64': 0.27.0 - '@esbuild/openbsd-arm64': 0.27.0 - '@esbuild/openbsd-x64': 0.27.0 - '@esbuild/openharmony-arm64': 0.27.0 - '@esbuild/sunos-x64': 0.27.0 - '@esbuild/win32-arm64': 0.27.0 - '@esbuild/win32-ia32': 0.27.0 - '@esbuild/win32-x64': 0.27.0 + '@esbuild/aix-ppc64': 0.25.2 + '@esbuild/android-arm': 0.25.2 + '@esbuild/android-arm64': 0.25.2 + '@esbuild/android-x64': 0.25.2 + '@esbuild/darwin-arm64': 0.25.2 + '@esbuild/darwin-x64': 0.25.2 + '@esbuild/freebsd-arm64': 0.25.2 + '@esbuild/freebsd-x64': 0.25.2 + '@esbuild/linux-arm': 0.25.2 + '@esbuild/linux-arm64': 0.25.2 + '@esbuild/linux-ia32': 0.25.2 + '@esbuild/linux-loong64': 0.25.2 + '@esbuild/linux-mips64el': 0.25.2 + '@esbuild/linux-ppc64': 0.25.2 + '@esbuild/linux-riscv64': 0.25.2 + '@esbuild/linux-s390x': 0.25.2 + '@esbuild/linux-x64': 0.25.2 + '@esbuild/netbsd-arm64': 0.25.2 + '@esbuild/netbsd-x64': 0.25.2 + '@esbuild/openbsd-arm64': 0.25.2 + '@esbuild/openbsd-x64': 0.25.2 + '@esbuild/sunos-x64': 0.25.2 + '@esbuild/win32-arm64': 0.25.2 + '@esbuild/win32-ia32': 0.25.2 + '@esbuild/win32-x64': 0.25.2 escalade@3.2.0: {} @@ -7410,13 +6832,6 @@ snapshots: cross-spawn: 7.0.6 signal-exit: 4.1.0 - form-data@4.0.2: - dependencies: - asynckit: 0.4.0 - combined-stream: 1.0.8 - es-set-tostringtag: 2.1.0 - mime-types: 2.1.35 - form-data@4.0.4: dependencies: asynckit: 0.4.0 @@ -7443,8 +6858,6 @@ snapshots: fs.promises.exists@1.1.4: {} - fs.realpath@1.0.0: {} - fsevents@2.3.3: optional: true @@ -7503,7 +6916,7 @@ snapshots: dependencies: is-glob: 4.0.3 - glob@10.4.5: + glob@10.5.0: dependencies: foreground-child: 3.3.1 jackspeak: 3.4.3 @@ -7512,24 +6925,6 @@ snapshots: package-json-from-dist: 1.0.1 path-scurry: 1.11.1 - glob@7.2.3: - dependencies: - fs.realpath: 1.0.0 - inflight: 1.0.6 - inherits: 2.0.4 - minimatch: 3.1.2 - once: 1.4.0 - path-is-absolute: 1.0.1 - optional: true - - glob@8.1.0: - dependencies: - fs.realpath: 1.0.0 - inflight: 1.0.6 - inherits: 2.0.4 - minimatch: 5.1.6 - once: 1.4.0 - global-agent@3.0.0: dependencies: boolean: 3.2.0 @@ -7657,11 +7052,6 @@ snapshots: infer-owner@1.0.4: optional: true - inflight@1.0.6: - dependencies: - once: 1.4.0 - wrappy: 1.0.2 - inherits@2.0.4: {} ini@1.3.8: {} @@ -7690,7 +7080,7 @@ snapshots: type-fest: 4.41.0 widest-line: 5.0.0 wrap-ansi: 9.0.2 - ws: 8.18.3 + ws: 8.17.1 yoga-layout: 3.2.1 optionalDependencies: '@types/react': 19.2.0 @@ -7800,9 +7190,9 @@ snapshots: dependencies: ws: 8.17.1 - isows@1.0.7(ws@8.18.3): + isows@1.0.7(ws@8.17.1): dependencies: - ws: 8.18.3 + ws: 8.17.1 jackspeak@3.4.3: dependencies: @@ -7816,7 +7206,7 @@ snapshots: js-tokens@9.0.1: {} - js-yaml@4.1.0: + js-yaml@4.1.1: dependencies: argparse: 2.0.1 @@ -7829,7 +7219,7 @@ snapshots: cssstyle: 4.2.1 data-urls: 5.0.0 decimal.js: 10.5.0 - form-data: 4.0.2 + form-data: 4.0.4 html-encoding-sniffer: 4.0.0 http-proxy-agent: 7.0.2 https-proxy-agent: 7.0.6 @@ -7859,10 +7249,9 @@ snapshots: jsonc-parser@3.3.1: {} - jsondiffpatch@0.5.0: + jsondiffpatch@0.7.2: dependencies: - chalk: 3.0.0 - diff-match-patch: 1.0.5 + '@dmsnell/diff-match-patch': 1.1.0 jsonfile@6.1.0: dependencies: @@ -7992,18 +7381,13 @@ snapshots: dependencies: '@isaacs/brace-expansion': 5.0.0 - minimatch@3.1.2: - dependencies: - brace-expansion: 1.1.11 - optional: true - minimatch@5.1.6: dependencies: - brace-expansion: 2.0.1 + brace-expansion: 1.1.12 minimatch@9.0.5: dependencies: - brace-expansion: 2.0.1 + brace-expansion: 1.1.12 minimist@1.2.8: {} @@ -8069,9 +7453,9 @@ snapshots: diff: 5.2.0 escape-string-regexp: 4.0.0 find-up: 5.0.0 - glob: 8.1.0 + glob: 10.5.0 he: 1.2.0 - js-yaml: 4.1.0 + js-yaml: 4.1.1 log-symbols: 4.1.0 minimatch: 5.1.6 ms: 2.1.3 @@ -8188,7 +7572,7 @@ snapshots: node-gyp@8.4.1: dependencies: env-paths: 2.2.1 - glob: 7.2.3 + glob: 10.5.0 graceful-fs: 4.2.11 make-fetch-happen: 9.1.0 nopt: 5.0.0 @@ -8316,9 +7700,6 @@ snapshots: path-exists@4.0.0: {} - path-is-absolute@1.0.1: - optional: true - path-key@3.1.1: {} path-key@4.0.0: {} @@ -8467,7 +7848,7 @@ snapshots: pump: 3.0.2 rc: 1.2.8 simple-get: 4.0.1 - tar-fs: 2.1.2 + tar-fs: 2.1.4 tunnel-agent: 0.6.0 pretty-ms@9.3.0: @@ -8606,7 +7987,7 @@ snapshots: rimraf@3.0.2: dependencies: - glob: 7.2.3 + glob: 10.5.0 optional: true rlp@3.0.0: {} @@ -8858,12 +8239,12 @@ snapshots: dependencies: emoji-regex: 10.6.0 get-east-asian-width: 1.4.0 - strip-ansi: 7.1.0 + strip-ansi: 7.1.2 string-width@8.1.0: dependencies: get-east-asian-width: 1.4.0 - strip-ansi: 7.1.0 + strip-ansi: 7.1.2 string_decoder@1.3.0: dependencies: @@ -8873,10 +8254,6 @@ snapshots: dependencies: ansi-regex: 5.0.1 - strip-ansi@7.1.0: - dependencies: - ansi-regex: 6.1.0 - strip-ansi@7.1.2: dependencies: ansi-regex: 6.1.0 @@ -8899,7 +8276,7 @@ snapshots: dependencies: '@jridgewell/gen-mapping': 0.3.13 commander: 4.1.1 - glob: 10.4.5 + glob: 10.5.0 lines-and-columns: 1.2.4 mz: 2.7.0 pirates: 4.0.7 @@ -8915,13 +8292,6 @@ snapshots: symbol-tree@3.2.4: {} - tar-fs@2.1.2: - dependencies: - chownr: 1.1.4 - mkdirp-classic: 0.5.3 - pump: 3.0.2 - tar-stream: 2.2.0 - tar-fs@2.1.4: dependencies: chownr: 1.1.4 @@ -8979,9 +8349,9 @@ snapshots: tmp-promise@3.0.3: dependencies: - tmp: 0.2.5 + tmp: 0.2.4 - tmp@0.2.5: {} + tmp@0.2.4: {} to-buffer@1.2.2: dependencies: @@ -9060,12 +8430,12 @@ snapshots: tsup@8.5.1(postcss@8.5.3)(tsx@4.20.6)(typescript@5.4.5)(yaml@2.8.1): dependencies: - bundle-require: 5.1.0(esbuild@0.27.0) + bundle-require: 5.1.0(esbuild@0.25.2) cac: 6.7.14 chokidar: 4.0.3 consola: 3.4.2 debug: 4.4.0 - esbuild: 0.27.0 + esbuild: 0.25.2 fix-dts-default-cjs-exports: 1.0.1 joycon: 3.1.1 picocolors: 1.1.1 @@ -9088,12 +8458,12 @@ snapshots: tsup@8.5.1(postcss@8.5.3)(tsx@4.20.6)(typescript@5.9.3)(yaml@2.8.1): dependencies: - bundle-require: 5.1.0(esbuild@0.27.0) + bundle-require: 5.1.0(esbuild@0.25.2) cac: 6.7.14 chokidar: 4.0.3 consola: 3.4.2 debug: 4.4.0 - esbuild: 0.27.0 + esbuild: 0.25.2 fix-dts-default-cjs-exports: 1.0.1 joycon: 3.1.1 picocolors: 1.1.1 @@ -9116,7 +8486,7 @@ snapshots: tsx@4.20.6: dependencies: - esbuild: 0.25.12 + esbuild: 0.25.2 get-tsconfig: 4.13.0 optionalDependencies: fsevents: 2.3.3 @@ -9139,17 +8509,17 @@ snapshots: es-errors: 1.3.0 is-typed-array: 1.1.15 - typeorm@0.3.27(reflect-metadata@0.2.2)(sqlite3@5.1.7)(ts-node@10.9.2(@types/node@22.10.2)(typescript@5.4.5)): + typeorm@0.3.26(reflect-metadata@0.2.2)(sqlite3@5.1.7)(ts-node@10.9.2(@types/node@22.10.2)(typescript@5.4.5)): dependencies: '@sqltools/formatter': 1.2.5 ansis: 3.17.0 app-root-path: 3.1.0 buffer: 6.0.3 dayjs: 1.11.13 - debug: 4.4.0 + debug: 4.4.3(supports-color@8.1.1) dedent: 1.7.0 dotenv: 16.6.1 - glob: 10.4.5 + glob: 10.5.0 reflect-metadata: 0.2.2 sha.js: 2.4.12 sql-highlight: 6.0.0 @@ -9237,9 +8607,9 @@ snapshots: '@scure/bip32': 1.7.0 '@scure/bip39': 1.6.0 abitype: 1.1.0(typescript@5.4.5)(zod@3.25.76) - isows: 1.0.7(ws@8.18.3) + isows: 1.0.7(ws@8.17.1) ox: 0.9.6(typescript@5.4.5)(zod@3.25.76) - ws: 8.18.3 + ws: 8.17.1 optionalDependencies: typescript: 5.4.5 transitivePeerDependencies: @@ -9253,7 +8623,7 @@ snapshots: debug: 4.4.3(supports-color@8.1.1) es-module-lexer: 1.7.0 pathe: 2.0.3 - vite: 5.4.14(@types/node@22.10.2) + vite: 5.4.21(@types/node@22.10.2) transitivePeerDependencies: - '@types/node' - less @@ -9271,7 +8641,7 @@ snapshots: debug: 4.4.3(supports-color@8.1.1) es-module-lexer: 1.7.0 pathe: 2.0.3 - vite: 5.4.14(@types/node@24.10.1) + vite: 5.4.21(@types/node@24.10.1) transitivePeerDependencies: - '@types/node' - less @@ -9283,18 +8653,18 @@ snapshots: - supports-color - terser - vite@5.4.14(@types/node@22.10.2): + vite@5.4.21(@types/node@22.10.2): dependencies: - esbuild: 0.21.5 + esbuild: 0.25.2 postcss: 8.5.3 rollup: 4.34.9 optionalDependencies: '@types/node': 22.10.2 fsevents: 2.3.3 - vite@5.4.14(@types/node@24.10.1): + vite@5.4.21(@types/node@24.10.1): dependencies: - esbuild: 0.21.5 + esbuild: 0.25.2 postcss: 8.5.3 rollup: 4.34.9 optionalDependencies: @@ -9305,7 +8675,7 @@ snapshots: dependencies: '@types/chai': 5.2.3 '@vitest/expect': 3.2.4 - '@vitest/mocker': 3.2.4(vite@5.4.14(@types/node@22.10.2)) + '@vitest/mocker': 3.2.4(vite@5.4.21(@types/node@22.10.2)) '@vitest/pretty-format': 3.2.4 '@vitest/runner': 3.2.4 '@vitest/snapshot': 3.2.4 @@ -9323,7 +8693,7 @@ snapshots: tinyglobby: 0.2.15 tinypool: 1.1.1 tinyrainbow: 2.0.0 - vite: 5.4.14(@types/node@22.10.2) + vite: 5.4.21(@types/node@22.10.2) vite-node: 3.2.4(@types/node@22.10.2) why-is-node-running: 2.3.0 optionalDependencies: @@ -9345,7 +8715,7 @@ snapshots: dependencies: '@types/chai': 5.2.3 '@vitest/expect': 3.2.4 - '@vitest/mocker': 3.2.4(vite@5.4.14(@types/node@22.10.2)) + '@vitest/mocker': 3.2.4(vite@5.4.21(@types/node@22.10.2)) '@vitest/pretty-format': 3.2.4 '@vitest/runner': 3.2.4 '@vitest/snapshot': 3.2.4 @@ -9363,7 +8733,7 @@ snapshots: tinyglobby: 0.2.15 tinypool: 1.1.1 tinyrainbow: 2.0.0 - vite: 5.4.14(@types/node@24.10.1) + vite: 5.4.21(@types/node@24.10.1) vite-node: 3.2.4(@types/node@24.10.1) why-is-node-running: 2.3.0 optionalDependencies: @@ -9690,7 +9060,7 @@ snapshots: dependencies: ansi-styles: 6.2.1 string-width: 7.2.0 - strip-ansi: 7.1.0 + strip-ansi: 7.1.2 wrappy@1.0.2: {} @@ -9716,8 +9086,6 @@ snapshots: ws@8.17.1: {} - ws@8.18.3: {} - xml-name-validator@5.0.0: {} xmlchars@2.2.0: {} From 99c4c29a443246260c74ebfb74002ab8a6f3c0f7 Mon Sep 17 00:00:00 2001 From: Chralt98 Date: Thu, 27 Nov 2025 11:46:29 +0100 Subject: [PATCH 3/8] Refactor migration code for improved readability and consistency --- zrml/prediction-markets/src/migrations.rs | 31 ++++++++--------------- 1 file changed, 10 insertions(+), 21 deletions(-) diff --git a/zrml/prediction-markets/src/migrations.rs b/zrml/prediction-markets/src/migrations.rs index 44bc93e2c..d78dae62e 100644 --- a/zrml/prediction-markets/src/migrations.rs +++ b/zrml/prediction-markets/src/migrations.rs @@ -17,8 +17,9 @@ // along with Zeitgeist. If not, see . pub mod mbm { - use crate::{Config, LastTimeFrame, MarketIdsPerCloseTimeFrame, MarketIdOf, TimeFrame}; + use crate::{Config, LastTimeFrame, MarketIdOf, MarketIdsPerCloseTimeFrame, TimeFrame}; use alloc::vec::Vec; + use core::marker::PhantomData; use frame_support::{ migrations::{SteppedMigration, SteppedMigrationError}, pallet_prelude::ConstU32, @@ -27,14 +28,12 @@ pub mod mbm { BoundedVec, }; use sp_runtime::codec::{Decode, Encode, MaxEncodedLen}; - use core::marker::PhantomData; /// Block time (ms) used before the AsyncBacking upgrade halved block time. pub const PREVIOUS_MILLISECS_PER_BLOCK: u32 = 12_000; /// Ratio between the previous and current block times, used to rescale timestamp frames. - pub const TIME_FRAME_SCALE_FACTOR: TimeFrame = - PREVIOUS_MILLISECS_PER_BLOCK as TimeFrame - / zeitgeist_primitives::constants::MILLISECS_PER_BLOCK as TimeFrame; + pub const TIME_FRAME_SCALE_FACTOR: TimeFrame = PREVIOUS_MILLISECS_PER_BLOCK as TimeFrame + / zeitgeist_primitives::constants::MILLISECS_PER_BLOCK as TimeFrame; /// Target pallet storage version after migration. const TARGET_STORAGE_VERSION: u16 = 9; @@ -70,9 +69,7 @@ pub mod mbm { .map_err(|_| SteppedMigrationError::InsufficientWeight { required: weight }) } - fn rescale_last_time_frame( - meter: &mut WeightMeter, - ) -> Result<(), SteppedMigrationError> { + fn rescale_last_time_frame(meter: &mut WeightMeter) -> Result<(), SteppedMigrationError> { Self::weight_or_insufficient(meter, Self::db_weight().reads_writes(1, 1))?; if let Some(last_time_frame) = LastTimeFrame::::get() { LastTimeFrame::::set(Some( @@ -82,10 +79,7 @@ pub mod mbm { Ok(()) } - fn insert_with_shift( - market_id: MarketIdOf, - mut target_time_frame: TimeFrame, - ) { + fn insert_with_shift(market_id: MarketIdOf, mut target_time_frame: TimeFrame) { loop { let mut bucket = MarketIdsPerCloseTimeFrame::::get(target_time_frame); if bucket.contains(&market_id) { @@ -152,9 +146,8 @@ pub mod mbm { } }; - let mut start_tf = state - .current_time_frame - .or_else(|| Self::next_start_time_frame(0, max_source)); + let mut start_tf = + state.current_time_frame.or_else(|| Self::next_start_time_frame(0, max_source)); while let Some(current_tf) = start_tf { let ids: Vec<_> = MarketIdsPerCloseTimeFrame::::get(current_tf).into(); @@ -248,15 +241,11 @@ mod tests { let mut cursor = None; // Give plenty of weight to finish in one go. let mut meter = WeightMeter::with_limit(Weight::from_parts(u64::MAX, u64::MAX)); - cursor = - TimeFrameRescaleMigration::::step(cursor, &mut meter).unwrap(); + cursor = TimeFrameRescaleMigration::::step(cursor, &mut meter).unwrap(); assert!(cursor.is_none()); assert_eq!(StorageVersion::get::>(), StorageVersion::new(9)); - assert_eq!( - LastTimeFrame::::get(), - Some(5 * TIME_FRAME_SCALE_FACTOR) - ); + assert_eq!(LastTimeFrame::::get(), Some(5 * TIME_FRAME_SCALE_FACTOR)); assert_eq!( MarketIdsPerCloseTimeFrame::::get(10), BoundedVec::::new() From 3e55dafcfa27c63f47bd1f3e06e2c8d9fddb00ca Mon Sep 17 00:00:00 2001 From: Chralt98 Date: Thu, 27 Nov 2025 12:19:10 +0100 Subject: [PATCH 4/8] Update migration parameters and add TimeFrameRescaleMigration for improved time frame handling --- runtime/battery-station/src/lib.rs | 4 ++-- runtime/battery-station/src/runtime_migrations/mod.rs | 2 ++ runtime/zeitgeist/src/lib.rs | 4 ++-- runtime/zeitgeist/src/runtime_migrations/mod.rs | 2 ++ zrml/prediction-markets/src/lib.rs | 2 +- 5 files changed, 9 insertions(+), 5 deletions(-) diff --git a/runtime/battery-station/src/lib.rs b/runtime/battery-station/src/lib.rs index 850e41627..72c7e4a15 100644 --- a/runtime/battery-station/src/lib.rs +++ b/runtime/battery-station/src/lib.rs @@ -131,12 +131,12 @@ type MultiBlockMigrations = (); #[cfg(feature = "runtime-benchmarks")] type MigrationsCursorMaxLen = ConstU32<65_536>; #[cfg(not(feature = "runtime-benchmarks"))] -type MigrationsCursorMaxLen = ConstU32<8>; +type MigrationsCursorMaxLen = ConstU32<64>; #[cfg(feature = "runtime-benchmarks")] type MigrationsIdentifierMaxLen = ConstU32<256>; #[cfg(not(feature = "runtime-benchmarks"))] -type MigrationsIdentifierMaxLen = ConstU32<8>; +type MigrationsIdentifierMaxLen = ConstU32<128>; decl_common_types!(); diff --git a/runtime/battery-station/src/runtime_migrations/mod.rs b/runtime/battery-station/src/runtime_migrations/mod.rs index f6bb10f8b..4d6ff0254 100644 --- a/runtime/battery-station/src/runtime_migrations/mod.rs +++ b/runtime/battery-station/src/runtime_migrations/mod.rs @@ -21,6 +21,7 @@ use pallet_parachain_staking::migrations::{ LegacyAtStakeCursorMigration, LegacyAtStakeMigrationKey, LegacyAtStakeMigrationList, LEGACY_AT_STAKE_MIGRATION_ID_LEN, }; +use zrml_prediction_markets::migrations::mbm::TimeFrameRescaleMigration; mod legacy_keys; use legacy_keys::BATTERY_STATION_LEGACY_KEYS; @@ -45,4 +46,5 @@ pub type LegacyMigrations = ( BatteryStationLegacyKeys, BATTERY_STATION_MIGRATION_BATCH, >, + TimeFrameRescaleMigration, ); diff --git a/runtime/zeitgeist/src/lib.rs b/runtime/zeitgeist/src/lib.rs index fdb33f540..8b00b8d2e 100644 --- a/runtime/zeitgeist/src/lib.rs +++ b/runtime/zeitgeist/src/lib.rs @@ -190,12 +190,12 @@ type MultiBlockMigrations = (); #[cfg(feature = "runtime-benchmarks")] type MigrationsCursorMaxLen = ConstU32<65_536>; #[cfg(not(feature = "runtime-benchmarks"))] -type MigrationsCursorMaxLen = ConstU32<8>; +type MigrationsCursorMaxLen = ConstU32<64>; #[cfg(feature = "runtime-benchmarks")] type MigrationsIdentifierMaxLen = ConstU32<256>; #[cfg(not(feature = "runtime-benchmarks"))] -type MigrationsIdentifierMaxLen = ConstU32<8>; +type MigrationsIdentifierMaxLen = ConstU32<128>; decl_common_types!(); diff --git a/runtime/zeitgeist/src/runtime_migrations/mod.rs b/runtime/zeitgeist/src/runtime_migrations/mod.rs index ec2ac4b36..1d61986c2 100644 --- a/runtime/zeitgeist/src/runtime_migrations/mod.rs +++ b/runtime/zeitgeist/src/runtime_migrations/mod.rs @@ -21,6 +21,7 @@ use pallet_parachain_staking::migrations::{ LegacyAtStakeCursorMigration, LegacyAtStakeMigrationKey, LegacyAtStakeMigrationList, LEGACY_AT_STAKE_MIGRATION_ID_LEN, }; +use zrml_prediction_markets::migrations::mbm::TimeFrameRescaleMigration; mod legacy_keys; use legacy_keys::ZEITGEIST_LEGACY_KEYS; @@ -41,4 +42,5 @@ impl LegacyAtStakeMigrationList for ZeitgeistLegacyKeys { pub type LegacyMigrations = ( LegacyAtStakeCursorMigration, + TimeFrameRescaleMigration, ); diff --git a/zrml/prediction-markets/src/lib.rs b/zrml/prediction-markets/src/lib.rs index bf7f1710a..48b0cbbf5 100644 --- a/zrml/prediction-markets/src/lib.rs +++ b/zrml/prediction-markets/src/lib.rs @@ -82,7 +82,7 @@ mod pallet { use zrml_market_commons::{types::MarketBuilder, MarketCommonsPalletApi}; /// The current storage version. - const STORAGE_VERSION: StorageVersion = StorageVersion::new(8); + const STORAGE_VERSION: StorageVersion = StorageVersion::new(9); const LOG_TARGET: &str = "runtime::zrml-prediction-markets"; /// The maximum number of blocks between the [`LastTimeFrame`] /// and the current timestamp in block number allowed to recover From 8da0c193ef1978da5764bafe67237118368a6f26 Mon Sep 17 00:00:00 2001 From: Chralt98 Date: Thu, 27 Nov 2025 13:31:57 +0100 Subject: [PATCH 5/8] Add migration hooks for LastTimeFrame rescaling during runtime upgrade --- zrml/prediction-markets/src/lib.rs | 47 ++++++++++++- zrml/prediction-markets/src/migrations.rs | 84 +++++++++++++---------- 2 files changed, 92 insertions(+), 39 deletions(-) diff --git a/zrml/prediction-markets/src/lib.rs b/zrml/prediction-markets/src/lib.rs index 48b0cbbf5..9ba9307ba 100644 --- a/zrml/prediction-markets/src/lib.rs +++ b/zrml/prediction-markets/src/lib.rs @@ -34,7 +34,7 @@ pub use pallet::*; #[frame_support::pallet] mod pallet { - use crate::weights::*; + use crate::{migrations, weights::*}; use alloc::{format, vec, vec::Vec}; use core::{cmp, marker::PhantomData}; use frame_support::{ @@ -53,6 +53,8 @@ mod pallet { }; use frame_system::{ensure_signed, pallet_prelude::OriginFor}; use sp_runtime::traits::AccountIdConversion; + #[cfg(feature = "try-runtime")] + use sp_runtime::{codec::{Decode, Encode}, TryRuntimeError}; #[cfg(feature = "parachain")] use {orml_traits::asset_registry::Inspect, zeitgeist_primitives::types::CustomMetadata}; @@ -1868,6 +1870,49 @@ mod pallet { #[pallet::hooks] impl Hooks> for Pallet { + fn on_runtime_upgrade() -> Weight { + let mut weight = T::DbWeight::get().reads(1); + + if StorageVersion::get::() >= STORAGE_VERSION { + return weight; + } + + let db_weight = T::DbWeight::get(); + weight = weight.saturating_add(db_weight.reads(1)); + if let Some(last_time_frame) = LastTimeFrame::::get() { + LastTimeFrame::::set(Some( + last_time_frame.saturating_mul(migrations::mbm::TIME_FRAME_SCALE_FACTOR), + )); + weight = weight.saturating_add(db_weight.writes(1)); + } + + weight + } + + #[cfg(feature = "try-runtime")] + fn pre_upgrade() -> Result, TryRuntimeError> { + let version_before = StorageVersion::get::(); + let ran = version_before < STORAGE_VERSION; + Ok((ran, LastTimeFrame::::get()).encode()) + } + + #[cfg(feature = "try-runtime")] + fn post_upgrade(state: Vec) -> Result<(), TryRuntimeError> { + let (ran, before): (bool, Option) = Decode::decode(&mut &state[..]) + .map_err(|_| TryRuntimeError::Other("Failed to decode upgrade state".into()))?; + if !ran { + return Ok(()); + } + let expected = before.map(|v| v.saturating_mul(migrations::mbm::TIME_FRAME_SCALE_FACTOR)); + let after = LastTimeFrame::::get(); + if after != expected { + return Err(TryRuntimeError::Other( + "LastTimeFrame not rescaled correctly during upgrade", + )); + } + Ok(()) + } + fn on_initialize(now: BlockNumberFor) -> Weight { let mut total_weight: Weight = Weight::zero(); diff --git a/zrml/prediction-markets/src/migrations.rs b/zrml/prediction-markets/src/migrations.rs index d78dae62e..0c5924a63 100644 --- a/zrml/prediction-markets/src/migrations.rs +++ b/zrml/prediction-markets/src/migrations.rs @@ -17,7 +17,7 @@ // along with Zeitgeist. If not, see . pub mod mbm { - use crate::{Config, LastTimeFrame, MarketIdOf, MarketIdsPerCloseTimeFrame, TimeFrame}; + use crate::{Config, MarketIdOf, MarketIdsPerCloseTimeFrame, TimeFrame}; use alloc::vec::Vec; use core::marker::PhantomData; use frame_support::{ @@ -28,25 +28,26 @@ pub mod mbm { BoundedVec, }; use sp_runtime::codec::{Decode, Encode, MaxEncodedLen}; + use log::error; /// Block time (ms) used before the AsyncBacking upgrade halved block time. pub const PREVIOUS_MILLISECS_PER_BLOCK: u32 = 12_000; /// Ratio between the previous and current block times, used to rescale timestamp frames. pub const TIME_FRAME_SCALE_FACTOR: TimeFrame = PREVIOUS_MILLISECS_PER_BLOCK as TimeFrame / zeitgeist_primitives::constants::MILLISECS_PER_BLOCK as TimeFrame; + const LOG_TARGET: &str = "runtime::zrml-prediction-markets"; /// Target pallet storage version after migration. const TARGET_STORAGE_VERSION: u16 = 9; #[derive(Clone, Encode, Decode, MaxEncodedLen, PartialEq, Eq, Debug)] pub struct Cursor { - /// Whether `LastTimeFrame` was already rescaled. - pub rescaled_last_time_frame: bool, /// The time frame key to start from on the next iteration. pub current_time_frame: Option, /// Offset into the current time frame's market list. pub offset: u32, - /// Highest source time frame to process (pre-migration space). + /// Highest source time frame observed at migration start; used to avoid + /// reprocessing newly inserted target buckets. pub max_source_time_frame: Option, } @@ -69,34 +70,42 @@ pub mod mbm { .map_err(|_| SteppedMigrationError::InsufficientWeight { required: weight }) } - fn rescale_last_time_frame(meter: &mut WeightMeter) -> Result<(), SteppedMigrationError> { - Self::weight_or_insufficient(meter, Self::db_weight().reads_writes(1, 1))?; - if let Some(last_time_frame) = LastTimeFrame::::get() { - LastTimeFrame::::set(Some( - last_time_frame.saturating_mul(TIME_FRAME_SCALE_FACTOR), - )); - } - Ok(()) - } - - fn insert_with_shift(market_id: MarketIdOf, mut target_time_frame: TimeFrame) { - loop { + fn insert_with_shift( + meter: &mut WeightMeter, + db_weight: frame_support::weights::RuntimeDbWeight, + market_id: MarketIdOf, + mut target_time_frame: TimeFrame, + ) -> Result<(), SteppedMigrationError> { + // Try a bounded number of adjacent time frames to avoid unbounded looping. + for _ in 0..3 { + Self::weight_or_insufficient(meter, db_weight.reads(1))?; let mut bucket = MarketIdsPerCloseTimeFrame::::get(target_time_frame); if bucket.contains(&market_id) { - return; + return Ok(()); } if bucket.try_push(market_id).is_ok() { + Self::weight_or_insufficient(meter, db_weight.writes(1))?; MarketIdsPerCloseTimeFrame::::insert(target_time_frame, bucket); - return; + return Ok(()); } target_time_frame = target_time_frame.saturating_add(1); } + + error!( + target: LOG_TARGET, + "Failed to insert market {:?} into close time frame starting at {:?}", + market_id, + target_time_frame, + ); + + Ok(()) } - fn next_start_time_frame(from: TimeFrame, max: TimeFrame) -> Option { - MarketIdsPerCloseTimeFrame::::iter() - .find(|(tf, _)| *tf >= from && *tf <= max) - .map(|(tf, _)| tf) + fn next_start_time_frame(max: TimeFrame) -> Option { + // Pick any remaining source key not beyond the original maximum so we don't + // loop over newly inserted target buckets. + MarketIdsPerCloseTimeFrame::::iter_keys() + .find(|tf| *tf <= max) } } @@ -120,21 +129,18 @@ pub mod mbm { } let mut state = cursor.take().unwrap_or(Cursor { - rescaled_last_time_frame: false, current_time_frame: None, offset: 0, - max_source_time_frame: MarketIdsPerCloseTimeFrame::::iter() - .last() - .map(|(tf, _)| tf), + max_source_time_frame: None, }); - if !state.rescaled_last_time_frame { - Self::rescale_last_time_frame(meter)?; - state.rescaled_last_time_frame = true; - } - let db_weight = Self::db_weight(); + if state.max_source_time_frame.is_none() { + state.max_source_time_frame = + MarketIdsPerCloseTimeFrame::::iter_keys().max(); + } + let max_source = match state.max_source_time_frame { Some(v) => v, None => { @@ -146,8 +152,9 @@ pub mod mbm { } }; - let mut start_tf = - state.current_time_frame.or_else(|| Self::next_start_time_frame(0, max_source)); + let mut start_tf = state + .current_time_frame + .or_else(|| Self::next_start_time_frame(max_source)); while let Some(current_tf) = start_tf { let ids: Vec<_> = MarketIdsPerCloseTimeFrame::::get(current_tf).into(); @@ -160,8 +167,7 @@ pub mod mbm { MarketIdsPerCloseTimeFrame::::remove(current_tf); state.current_time_frame = None; state.offset = 0; - start_tf = - Self::next_start_time_frame(current_tf.saturating_add(1), max_source); + start_tf = Self::next_start_time_frame(max_source); continue; } @@ -193,7 +199,7 @@ pub mod mbm { let market_id = ids[idx]; let target_tf = current_tf.saturating_mul(TIME_FRAME_SCALE_FACTOR); - Self::insert_with_shift(market_id, target_tf); + Self::insert_with_shift(meter, db_weight, market_id, target_tf)?; idx = idx.saturating_add(1); } @@ -204,7 +210,7 @@ pub mod mbm { // Move to next available key. state.current_time_frame = None; state.offset = 0; - start_tf = Self::next_start_time_frame(current_tf.saturating_add(1), max_source); + start_tf = Self::next_start_time_frame(max_source); } // No more entries; bump storage version. @@ -222,7 +228,7 @@ mod tests { use crate::{mock::*, CacheSize, LastTimeFrame, MarketIdsPerCloseTimeFrame}; use frame_support::{ migrations::SteppedMigration, - traits::StorageVersion, + traits::{Hooks as _, StorageVersion}, weights::{Weight, WeightMeter}, BoundedVec, }; @@ -239,6 +245,8 @@ mod tests { ); let mut cursor = None; + // Run the single-block migration to rescale `LastTimeFrame`. + crate::Pallet::::on_runtime_upgrade(); // Give plenty of weight to finish in one go. let mut meter = WeightMeter::with_limit(Weight::from_parts(u64::MAX, u64::MAX)); cursor = TimeFrameRescaleMigration::::step(cursor, &mut meter).unwrap(); From f719c999a6903df71eff2c77ea103aed7db44a2a Mon Sep 17 00:00:00 2001 From: Chralt98 Date: Thu, 27 Nov 2025 14:22:17 +0100 Subject: [PATCH 6/8] Refactor migration code for improved readability and add tests for TimeFrameRescaleMigration --- zrml/prediction-markets/src/lib.rs | 8 ++- zrml/prediction-markets/src/migrations.rs | 67 ++++++++++++++++++++--- 2 files changed, 65 insertions(+), 10 deletions(-) diff --git a/zrml/prediction-markets/src/lib.rs b/zrml/prediction-markets/src/lib.rs index 9ba9307ba..3964ff373 100644 --- a/zrml/prediction-markets/src/lib.rs +++ b/zrml/prediction-markets/src/lib.rs @@ -54,7 +54,10 @@ mod pallet { use frame_system::{ensure_signed, pallet_prelude::OriginFor}; use sp_runtime::traits::AccountIdConversion; #[cfg(feature = "try-runtime")] - use sp_runtime::{codec::{Decode, Encode}, TryRuntimeError}; + use sp_runtime::{ + codec::{Decode, Encode}, + TryRuntimeError, + }; #[cfg(feature = "parachain")] use {orml_traits::asset_registry::Inspect, zeitgeist_primitives::types::CustomMetadata}; @@ -1903,7 +1906,8 @@ mod pallet { if !ran { return Ok(()); } - let expected = before.map(|v| v.saturating_mul(migrations::mbm::TIME_FRAME_SCALE_FACTOR)); + let expected = + before.map(|v| v.saturating_mul(migrations::mbm::TIME_FRAME_SCALE_FACTOR)); let after = LastTimeFrame::::get(); if after != expected { return Err(TryRuntimeError::Other( diff --git a/zrml/prediction-markets/src/migrations.rs b/zrml/prediction-markets/src/migrations.rs index 0c5924a63..6dc09630e 100644 --- a/zrml/prediction-markets/src/migrations.rs +++ b/zrml/prediction-markets/src/migrations.rs @@ -27,8 +27,8 @@ pub mod mbm { weights::{Weight, WeightMeter}, BoundedVec, }; - use sp_runtime::codec::{Decode, Encode, MaxEncodedLen}; use log::error; + use sp_runtime::codec::{Decode, Encode, MaxEncodedLen}; /// Block time (ms) used before the AsyncBacking upgrade halved block time. pub const PREVIOUS_MILLISECS_PER_BLOCK: u32 = 12_000; @@ -104,8 +104,7 @@ pub mod mbm { fn next_start_time_frame(max: TimeFrame) -> Option { // Pick any remaining source key not beyond the original maximum so we don't // loop over newly inserted target buckets. - MarketIdsPerCloseTimeFrame::::iter_keys() - .find(|tf| *tf <= max) + MarketIdsPerCloseTimeFrame::::iter_keys().find(|tf| *tf <= max) } } @@ -137,8 +136,7 @@ pub mod mbm { let db_weight = Self::db_weight(); if state.max_source_time_frame.is_none() { - state.max_source_time_frame = - MarketIdsPerCloseTimeFrame::::iter_keys().max(); + state.max_source_time_frame = MarketIdsPerCloseTimeFrame::::iter_keys().max(); } let max_source = match state.max_source_time_frame { @@ -152,9 +150,8 @@ pub mod mbm { } }; - let mut start_tf = state - .current_time_frame - .or_else(|| Self::next_start_time_frame(max_source)); + let mut start_tf = + state.current_time_frame.or_else(|| Self::next_start_time_frame(max_source)); while let Some(current_tf) = start_tf { let ids: Vec<_> = MarketIdsPerCloseTimeFrame::::get(current_tf).into(); @@ -264,4 +261,58 @@ mod tests { ); }); } + + #[test] + fn migration_rescales_multiple_buckets_with_varied_lengths() { + ExtBuilder::default().build().execute_with(|| { + StorageVersion::new(8).put::>(); + + LastTimeFrame::::set(Some(12)); + MarketIdsPerCloseTimeFrame::::insert( + 5, + BoundedVec::::try_from(vec![1u128]).unwrap(), + ); + MarketIdsPerCloseTimeFrame::::insert( + 6, + BoundedVec::::try_from(vec![2u128, 3u128]).unwrap(), + ); + MarketIdsPerCloseTimeFrame::::insert( + 9, + BoundedVec::::try_from(vec![4u128, 5u128, 6u128]).unwrap(), + ); + + crate::Pallet::::on_runtime_upgrade(); + let mut cursor = None; + let mut meter = WeightMeter::with_limit(Weight::from_parts(u64::MAX, u64::MAX)); + cursor = TimeFrameRescaleMigration::::step(cursor, &mut meter).unwrap(); + assert!(cursor.is_none()); + + assert_eq!(StorageVersion::get::>(), StorageVersion::new(9)); + assert_eq!(LastTimeFrame::::get(), Some(12 * TIME_FRAME_SCALE_FACTOR)); + assert_eq!( + MarketIdsPerCloseTimeFrame::::get(5), + BoundedVec::::new() + ); + assert_eq!( + MarketIdsPerCloseTimeFrame::::get(6), + BoundedVec::::new() + ); + assert_eq!( + MarketIdsPerCloseTimeFrame::::get(9), + BoundedVec::::new() + ); + assert_eq!( + MarketIdsPerCloseTimeFrame::::get(5 * TIME_FRAME_SCALE_FACTOR), + BoundedVec::::try_from(vec![1u128]).unwrap(), + ); + assert_eq!( + MarketIdsPerCloseTimeFrame::::get(6 * TIME_FRAME_SCALE_FACTOR), + BoundedVec::::try_from(vec![2u128, 3u128]).unwrap(), + ); + assert_eq!( + MarketIdsPerCloseTimeFrame::::get(9 * TIME_FRAME_SCALE_FACTOR), + BoundedVec::::try_from(vec![4u128, 5u128, 6u128]).unwrap(), + ); + }); + } } From 36cb5decc0405dae642fbf75c6138f2583f22a9a Mon Sep 17 00:00:00 2001 From: Chralt98 Date: Thu, 27 Nov 2025 14:47:13 +0100 Subject: [PATCH 7/8] Add logging for LastTimeFrame migration and TimeFrameRescaleMigration process --- zrml/prediction-markets/src/lib.rs | 12 ++++++++--- zrml/prediction-markets/src/migrations.rs | 26 +++++++++++++++++++---- 2 files changed, 31 insertions(+), 7 deletions(-) diff --git a/zrml/prediction-markets/src/lib.rs b/zrml/prediction-markets/src/lib.rs index 3964ff373..a06168988 100644 --- a/zrml/prediction-markets/src/lib.rs +++ b/zrml/prediction-markets/src/lib.rs @@ -1883,9 +1883,15 @@ mod pallet { let db_weight = T::DbWeight::get(); weight = weight.saturating_add(db_weight.reads(1)); if let Some(last_time_frame) = LastTimeFrame::::get() { - LastTimeFrame::::set(Some( - last_time_frame.saturating_mul(migrations::mbm::TIME_FRAME_SCALE_FACTOR), - )); + let new_last_time_frame = + last_time_frame.saturating_mul(migrations::mbm::TIME_FRAME_SCALE_FACTOR); + log::info!( + target: LOG_TARGET, + "LastTimeFrame migrated from {} to {} during on_runtime_upgrade", + last_time_frame, + new_last_time_frame, + ); + LastTimeFrame::::set(Some(new_last_time_frame)); weight = weight.saturating_add(db_weight.writes(1)); } diff --git a/zrml/prediction-markets/src/migrations.rs b/zrml/prediction-markets/src/migrations.rs index 6dc09630e..e04558a81 100644 --- a/zrml/prediction-markets/src/migrations.rs +++ b/zrml/prediction-markets/src/migrations.rs @@ -27,7 +27,7 @@ pub mod mbm { weights::{Weight, WeightMeter}, BoundedVec, }; - use log::error; + use log::{error, info}; use sp_runtime::codec::{Decode, Encode, MaxEncodedLen}; /// Block time (ms) used before the AsyncBacking upgrade halved block time. @@ -74,6 +74,7 @@ pub mod mbm { meter: &mut WeightMeter, db_weight: frame_support::weights::RuntimeDbWeight, market_id: MarketIdOf, + source_time_frame: TimeFrame, mut target_time_frame: TimeFrame, ) -> Result<(), SteppedMigrationError> { // Try a bounded number of adjacent time frames to avoid unbounded looping. @@ -81,11 +82,25 @@ pub mod mbm { Self::weight_or_insufficient(meter, db_weight.reads(1))?; let mut bucket = MarketIdsPerCloseTimeFrame::::get(target_time_frame); if bucket.contains(&market_id) { + info!( + target: LOG_TARGET, + "TimeFrameRescaleMigration: market {:?} already present in target {} (source {})", + market_id, + target_time_frame, + source_time_frame, + ); return Ok(()); } if bucket.try_push(market_id).is_ok() { Self::weight_or_insufficient(meter, db_weight.writes(1))?; MarketIdsPerCloseTimeFrame::::insert(target_time_frame, bucket); + info!( + target: LOG_TARGET, + "TimeFrameRescaleMigration migrated market {:?} from time frame {} to {}", + market_id, + source_time_frame, + target_time_frame, + ); return Ok(()); } target_time_frame = target_time_frame.saturating_add(1); @@ -184,19 +199,22 @@ pub mod mbm { let remaining = ids[idx..].to_vec(); if remaining.is_empty() { MarketIdsPerCloseTimeFrame::::remove(current_tf); + state.current_time_frame = None; + state.offset = 0; } else { let bounded = BoundedVec::try_from(remaining) .map_err(|_| SteppedMigrationError::Failed)?; MarketIdsPerCloseTimeFrame::::insert(current_tf, bounded); + // Resume from the start of the truncated bucket on the next step. + state.current_time_frame = Some(current_tf); + state.offset = 0; } - state.current_time_frame = Some(current_tf); - state.offset = idx as u32; return Ok(Some(state)); } let market_id = ids[idx]; let target_tf = current_tf.saturating_mul(TIME_FRAME_SCALE_FACTOR); - Self::insert_with_shift(meter, db_weight, market_id, target_tf)?; + Self::insert_with_shift(meter, db_weight, market_id, current_tf, target_tf)?; idx = idx.saturating_add(1); } From 49ddb630ac87d09e351b57d9a84768c505c6c5ee Mon Sep 17 00:00:00 2001 From: Chralt98 Date: Thu, 27 Nov 2025 15:51:43 +0100 Subject: [PATCH 8/8] Implement LastTimeFrame rescaling during runtime upgrade and add migration error handling --- zrml/prediction-markets/src/lib.rs | 51 +++++++++++------ zrml/prediction-markets/src/migrations.rs | 70 +++++++++++++++++++++-- 2 files changed, 100 insertions(+), 21 deletions(-) diff --git a/zrml/prediction-markets/src/lib.rs b/zrml/prediction-markets/src/lib.rs index a06168988..64e0c2b7d 100644 --- a/zrml/prediction-markets/src/lib.rs +++ b/zrml/prediction-markets/src/lib.rs @@ -1874,24 +1874,30 @@ mod pallet { #[pallet::hooks] impl Hooks> for Pallet { fn on_runtime_upgrade() -> Weight { - let mut weight = T::DbWeight::get().reads(1); + let db_weight = T::DbWeight::get(); + let mut weight = db_weight.reads(1); if StorageVersion::get::() >= STORAGE_VERSION { return weight; } - let db_weight = T::DbWeight::get(); weight = weight.saturating_add(db_weight.reads(1)); - if let Some(last_time_frame) = LastTimeFrame::::get() { - let new_last_time_frame = - last_time_frame.saturating_mul(migrations::mbm::TIME_FRAME_SCALE_FACTOR); - log::info!( - target: LOG_TARGET, - "LastTimeFrame migrated from {} to {} during on_runtime_upgrade", - last_time_frame, - new_last_time_frame, - ); - LastTimeFrame::::set(Some(new_last_time_frame)); + if !LastTimeFrameRescaled::::get() { + weight = weight.saturating_add(db_weight.reads(1)); + if let Some(last_time_frame) = LastTimeFrame::::get() { + let new_last_time_frame = + last_time_frame.saturating_mul(migrations::mbm::TIME_FRAME_SCALE_FACTOR); + log::info!( + target: LOG_TARGET, + "LastTimeFrame migrated from {} to {} during on_runtime_upgrade", + last_time_frame, + new_last_time_frame, + ); + LastTimeFrame::::set(Some(new_last_time_frame)); + weight = weight.saturating_add(db_weight.writes(1)); + } + + LastTimeFrameRescaled::::put(true); weight = weight.saturating_add(db_weight.writes(1)); } @@ -1901,17 +1907,20 @@ mod pallet { #[cfg(feature = "try-runtime")] fn pre_upgrade() -> Result, TryRuntimeError> { let version_before = StorageVersion::get::(); - let ran = version_before < STORAGE_VERSION; - Ok((ran, LastTimeFrame::::get()).encode()) + let last_time_frame_rescaled = LastTimeFrameRescaled::::get(); + let ran = version_before < STORAGE_VERSION && !last_time_frame_rescaled; + Ok((ran, LastTimeFrame::::get(), last_time_frame_rescaled).encode()) } #[cfg(feature = "try-runtime")] fn post_upgrade(state: Vec) -> Result<(), TryRuntimeError> { - let (ran, before): (bool, Option) = Decode::decode(&mut &state[..]) - .map_err(|_| TryRuntimeError::Other("Failed to decode upgrade state".into()))?; + let (ran, before, rescaled_before): (bool, Option, bool) = + Decode::decode(&mut &state[..]) + .map_err(|_| TryRuntimeError::Other("Failed to decode upgrade state".into()))?; if !ran { return Ok(()); } + debug_assert!(!rescaled_before, "Unexpected pre-upgrade rescale flag"); let expected = before.map(|v| v.saturating_mul(migrations::mbm::TIME_FRAME_SCALE_FACTOR)); let after = LastTimeFrame::::get(); @@ -1920,6 +1929,11 @@ mod pallet { "LastTimeFrame not rescaled correctly during upgrade", )); } + if !LastTimeFrameRescaled::::get() { + return Err(TryRuntimeError::Other( + "LastTimeFrameRescaled flag not set during upgrade", + )); + } Ok(()) } @@ -2039,6 +2053,11 @@ mod pallet { #[pallet::storage] pub type LastTimeFrame = StorageValue<_, TimeFrame>; + /// Tracks whether `LastTimeFrame` was already rescaled during the block-time migration. + #[pallet::storage] + #[pallet::getter(fn last_time_frame_rescaled)] + pub type LastTimeFrameRescaled = StorageValue<_, bool, ValueQuery>; + /// A mapping of market identifiers to the block they were disputed at. /// A market only ends up here if it was disputed. #[pallet::storage] diff --git a/zrml/prediction-markets/src/migrations.rs b/zrml/prediction-markets/src/migrations.rs index e04558a81..cd30acb0b 100644 --- a/zrml/prediction-markets/src/migrations.rs +++ b/zrml/prediction-markets/src/migrations.rs @@ -113,7 +113,7 @@ pub mod mbm { target_time_frame, ); - Ok(()) + Err(SteppedMigrationError::Failed) } fn next_start_time_frame(max: TimeFrame) -> Option { @@ -229,7 +229,8 @@ pub mod mbm { } // No more entries; bump storage version. - Self::weight_or_insufficient(meter, db_weight.writes(1))?; + Self::weight_or_insufficient(meter, db_weight.writes(2))?; + crate::LastTimeFrameRescaled::::kill(); frame_support::traits::StorageVersion::new(TARGET_STORAGE_VERSION) .put::>(); Ok(None) @@ -240,10 +241,12 @@ pub mod mbm { #[cfg(all(test, feature = "mock"))] mod tests { use super::mbm::{TimeFrameRescaleMigration, TIME_FRAME_SCALE_FACTOR}; - use crate::{mock::*, CacheSize, LastTimeFrame, MarketIdsPerCloseTimeFrame}; + use crate::{ + mock::*, CacheSize, LastTimeFrame, LastTimeFrameRescaled, MarketIdsPerCloseTimeFrame, + }; use frame_support::{ - migrations::SteppedMigration, - traits::{Hooks as _, StorageVersion}, + migrations::{SteppedMigration, SteppedMigrationError}, + traits::{Get, Hooks as _, StorageVersion}, weights::{Weight, WeightMeter}, BoundedVec, }; @@ -262,6 +265,7 @@ mod tests { let mut cursor = None; // Run the single-block migration to rescale `LastTimeFrame`. crate::Pallet::::on_runtime_upgrade(); + assert!(LastTimeFrameRescaled::::get()); // Give plenty of weight to finish in one go. let mut meter = WeightMeter::with_limit(Weight::from_parts(u64::MAX, u64::MAX)); cursor = TimeFrameRescaleMigration::::step(cursor, &mut meter).unwrap(); @@ -269,6 +273,7 @@ mod tests { assert_eq!(StorageVersion::get::>(), StorageVersion::new(9)); assert_eq!(LastTimeFrame::::get(), Some(5 * TIME_FRAME_SCALE_FACTOR)); + assert!(!LastTimeFrameRescaled::::get()); assert_eq!( MarketIdsPerCloseTimeFrame::::get(10), BoundedVec::::new() @@ -280,6 +285,59 @@ mod tests { }); } + #[test] + fn migration_aborts_when_target_buckets_full() { + ExtBuilder::default().build().execute_with(|| { + StorageVersion::new(8).put::>(); + + let source_tf: u64 = 5; + let target_tf = source_tf * TIME_FRAME_SCALE_FACTOR; + + let full_bucket: BoundedVec = + BoundedVec::try_from((0..CacheSize::get()).map(|i| i as u128).collect::>()) + .unwrap(); + + MarketIdsPerCloseTimeFrame::::insert(target_tf, full_bucket.clone()); + MarketIdsPerCloseTimeFrame::::insert( + target_tf.saturating_add(1), + full_bucket.clone(), + ); + MarketIdsPerCloseTimeFrame::::insert(target_tf.saturating_add(2), full_bucket); + let source_bucket = + BoundedVec::::try_from(vec![999u128]).expect("within bounds"); + MarketIdsPerCloseTimeFrame::::insert(source_tf, source_bucket.clone()); + + let mut meter = WeightMeter::with_limit(Weight::from_parts(u64::MAX, u64::MAX)); + let cursor = Some(super::mbm::Cursor { + current_time_frame: Some(source_tf), + offset: 0, + max_source_time_frame: None, + }); + + let result = TimeFrameRescaleMigration::::step(cursor, &mut meter); + assert!(matches!(result, Err(SteppedMigrationError::Failed))); + assert_eq!(MarketIdsPerCloseTimeFrame::::get(source_tf), source_bucket); + assert_eq!(StorageVersion::get::>(), StorageVersion::new(8)); + }); + } + + #[test] + fn on_runtime_upgrade_rescales_last_time_frame_only_once() { + ExtBuilder::default().build().execute_with(|| { + StorageVersion::new(8).put::>(); + LastTimeFrame::::set(Some(7)); + + crate::Pallet::::on_runtime_upgrade(); + assert_eq!(LastTimeFrame::::get(), Some(7 * TIME_FRAME_SCALE_FACTOR)); + assert!(LastTimeFrameRescaled::::get()); + + // Simulate another runtime upgrade while migration is still pending. + crate::Pallet::::on_runtime_upgrade(); + assert_eq!(LastTimeFrame::::get(), Some(7 * TIME_FRAME_SCALE_FACTOR)); + assert!(LastTimeFrameRescaled::::get()); + }); + } + #[test] fn migration_rescales_multiple_buckets_with_varied_lengths() { ExtBuilder::default().build().execute_with(|| { @@ -300,6 +358,7 @@ mod tests { ); crate::Pallet::::on_runtime_upgrade(); + assert!(LastTimeFrameRescaled::::get()); let mut cursor = None; let mut meter = WeightMeter::with_limit(Weight::from_parts(u64::MAX, u64::MAX)); cursor = TimeFrameRescaleMigration::::step(cursor, &mut meter).unwrap(); @@ -307,6 +366,7 @@ mod tests { assert_eq!(StorageVersion::get::>(), StorageVersion::new(9)); assert_eq!(LastTimeFrame::::get(), Some(12 * TIME_FRAME_SCALE_FACTOR)); + assert!(!LastTimeFrameRescaled::::get()); assert_eq!( MarketIdsPerCloseTimeFrame::::get(5), BoundedVec::::new()