From 57c009b5e447db7d02185da343761e679c77150d Mon Sep 17 00:00:00 2001 From: Osman Abdelnasir Date: Sun, 18 Jan 2026 09:08:04 +0400 Subject: [PATCH 1/3] feat: btc vault --- Cargo.lock | 482 ++- Cargo.toml | 2 + pallets/btc-vault/Cargo.toml | 68 + pallets/btc-vault/src/lib.rs | 459 ++ pallets/btc-vault/src/tests.rs | 429 ++ pallets/signet/Cargo.toml | 4 +- pallets/signet/src/lib.rs | 158 +- pallets/signet/src/tests/tests.rs | 116 +- pallets/signet/src/tests/utils.rs | 20 +- runtime/hydradx/Cargo.toml | 3 + runtime/hydradx/src/assets.rs | 13 + runtime/hydradx/src/lib.rs | 1 + signet-ts-client-scripts/README.md | 248 ++ signet-ts-client-scripts/btc-vault.test.ts | 991 +++++ signet-ts-client-scripts/coinselect.d.ts | 28 + signet-ts-client-scripts/key-derivation.ts | 30 + signet-ts-client-scripts/package.json | 39 + signet-ts-client-scripts/signet-client.ts | 247 ++ .../transaction-builder.ts | 28 + signet-ts-client-scripts/tsconfig.json | 15 + signet-ts-client-scripts/yarn.lock | 3776 +++++++++++++++++ 21 files changed, 7049 insertions(+), 108 deletions(-) create mode 100644 pallets/btc-vault/Cargo.toml create mode 100644 pallets/btc-vault/src/lib.rs create mode 100644 pallets/btc-vault/src/tests.rs create mode 100644 signet-ts-client-scripts/README.md create mode 100644 signet-ts-client-scripts/btc-vault.test.ts create mode 100644 signet-ts-client-scripts/coinselect.d.ts create mode 100644 signet-ts-client-scripts/key-derivation.ts create mode 100644 signet-ts-client-scripts/package.json create mode 100644 signet-ts-client-scripts/signet-client.ts create mode 100644 signet-ts-client-scripts/transaction-builder.ts create mode 100644 signet-ts-client-scripts/tsconfig.json create mode 100644 signet-ts-client-scripts/yarn.lock diff --git a/Cargo.lock b/Cargo.lock index 5748f3110b..19a470848f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -126,10 +126,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bc05b04ac331a9f07e3a4036ef7926e49a8bf84a99a1ccfc7e2ab55a5fcbb372" dependencies = [ "alloy-primitives 0.7.7", - "alloy-sol-type-parser", + "alloy-sol-type-parser 0.7.7", "serde", ] +[[package]] +name = "alloy-json-abi" +version = "0.8.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c357da577dfb56998d01f574d81ad7a1958d248740a7981b205d69d65a7da404" +dependencies = [ + "alloy-primitives 0.8.15", + "alloy-sol-type-parser 0.8.26", + "serde", + "serde_json", +] + [[package]] name = "alloy-primitives" version = "0.4.2" @@ -172,6 +184,34 @@ dependencies = [ "tiny-keccak", ] +[[package]] +name = "alloy-primitives" +version = "0.8.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6259a506ab13e1d658796c31e6e39d2e2ee89243bcc505ddc613b35732e0a430" +dependencies = [ + "alloy-rlp", + "bytes", + "cfg-if", + "const-hex", + "derive_more 1.0.0", + "foldhash", + "hashbrown 0.15.2", + "hex-literal", + "indexmap 2.7.0", + "itoa", + "k256", + "keccak-asm", + "paste", + "proptest", + "rand 0.8.5", + "ruint", + "rustc-hash 2.1.0", + "serde", + "sha3", + "tiny-keccak", +] + [[package]] name = "alloy-rlp" version = "0.3.12" @@ -194,7 +234,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.114", "syn-solidity 0.4.2", "tiny-keccak", ] @@ -205,12 +245,26 @@ version = "0.7.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b40397ddcdcc266f59f959770f601ce1280e699a91fc1862f29cef91707cd09" dependencies = [ - "alloy-sol-macro-expander", - "alloy-sol-macro-input", + "alloy-sol-macro-expander 0.7.7", + "alloy-sol-macro-input 0.7.7", "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.114", +] + +[[package]] +name = "alloy-sol-macro" +version = "0.8.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e68b32b6fa0d09bb74b4cefe35ccc8269d711c26629bc7cd98a47eeb12fe353f" +dependencies = [ + "alloy-sol-macro-expander 0.8.26", + "alloy-sol-macro-input 0.8.26", + "proc-macro-error2", + "proc-macro2", + "quote", + "syn 2.0.114", ] [[package]] @@ -219,36 +273,70 @@ version = "0.7.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "867a5469d61480fea08c7333ffeca52d5b621f5ca2e44f271b117ec1fc9a0525" dependencies = [ - "alloy-json-abi", - "alloy-sol-macro-input", + "alloy-json-abi 0.7.7", + "alloy-sol-macro-input 0.7.7", "const-hex", "heck 0.5.0", "indexmap 2.7.0", "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.114", "syn-solidity 0.7.7", "tiny-keccak", ] +[[package]] +name = "alloy-sol-macro-expander" +version = "0.8.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2afe6879ac373e58fd53581636f2cce843998ae0b058ebe1e4f649195e2bd23c" +dependencies = [ + "alloy-sol-macro-input 0.8.26", + "const-hex", + "heck 0.5.0", + "indexmap 2.7.0", + "proc-macro-error2", + "proc-macro2", + "quote", + "syn 2.0.114", + "syn-solidity 0.8.26", + "tiny-keccak", +] + [[package]] name = "alloy-sol-macro-input" version = "0.7.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2e482dc33a32b6fadbc0f599adea520bd3aaa585c141a80b404d0a3e3fa72528" dependencies = [ - "alloy-json-abi", + "alloy-json-abi 0.7.7", "const-hex", "dunce", "heck 0.5.0", "proc-macro2", "quote", "serde_json", - "syn 2.0.90", + "syn 2.0.114", "syn-solidity 0.7.7", ] +[[package]] +name = "alloy-sol-macro-input" +version = "0.8.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3ba01aee235a8c699d07e5be97ba215607564e71be72f433665329bec307d28" +dependencies = [ + "const-hex", + "dunce", + "heck 0.5.0", + "macro-string", + "proc-macro2", + "quote", + "syn 2.0.114", + "syn-solidity 0.8.26", +] + [[package]] name = "alloy-sol-type-parser" version = "0.7.7" @@ -259,6 +347,16 @@ dependencies = [ "winnow 0.6.20", ] +[[package]] +name = "alloy-sol-type-parser" +version = "0.8.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c13fc168b97411e04465f03e632f31ef94cad1c7c8951bf799237fd7870d535" +dependencies = [ + "serde", + "winnow 0.7.13", +] + [[package]] name = "alloy-sol-types" version = "0.4.2" @@ -277,13 +375,26 @@ version = "0.7.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a91ca40fa20793ae9c3841b83e74569d1cc9af29a2f5237314fd3452d51e38c7" dependencies = [ - "alloy-json-abi", + "alloy-json-abi 0.7.7", "alloy-primitives 0.7.7", "alloy-sol-macro 0.7.7", "const-hex", "serde", ] +[[package]] +name = "alloy-sol-types" +version = "0.8.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1174cafd6c6d810711b4e00383037bdb458efc4fe3dbafafa16567e0320c54d8" +dependencies = [ + "alloy-json-abi 0.8.15", + "alloy-primitives 0.8.15", + "alloy-sol-macro 0.8.26", + "const-hex", + "serde", +] + [[package]] name = "always-assert" version = "0.1.3" @@ -386,7 +497,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.114", ] [[package]] @@ -787,7 +898,7 @@ checksum = "965c2d33e53cb6b267e148a4cb0760bc01f4904c1cd4bb4002a085bb016d1490" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.114", "synstructure 0.13.1", ] @@ -810,7 +921,7 @@ checksum = "7b18050c2cd6fe86c3a76584ef5e0baf286d038cda203eb6223df2cc413565f7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.114", ] [[package]] @@ -1042,7 +1153,7 @@ checksum = "6e0c28dcc82d7c8ead5cb13beb15405b57b8546e93215673ff8ca0349a028107" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.114", ] [[package]] @@ -1201,7 +1312,7 @@ dependencies = [ "regex", "rustc-hash 1.1.0", "shlex", - "syn 2.0.90", + "syn 2.0.114", ] [[package]] @@ -1396,7 +1507,7 @@ dependencies = [ "proc-macro-crate 3.1.0", "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.114", ] [[package]] @@ -2049,7 +2160,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.114", ] [[package]] @@ -2098,7 +2209,7 @@ dependencies = [ "nom", "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.114", ] [[package]] @@ -2878,7 +2989,7 @@ dependencies = [ "proc-macro-crate 3.1.0", "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.114", ] [[package]] @@ -3210,7 +3321,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.114", ] [[package]] @@ -3250,7 +3361,7 @@ dependencies = [ "proc-macro2", "quote", "scratch", - "syn 2.0.90", + "syn 2.0.114", ] [[package]] @@ -3267,7 +3378,7 @@ checksum = "5c6888cd161769d65134846d4d4981d5a6654307cc46ec83fb917e530aea5f84" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.114", ] [[package]] @@ -3375,7 +3486,7 @@ checksum = "d65d7ce8132b7c0e54497a4d9a55a1c2a0912a0d786cf894472ba818fba45762" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.114", ] [[package]] @@ -3388,7 +3499,7 @@ dependencies = [ "proc-macro2", "quote", "rustc_version 0.4.0", - "syn 2.0.90", + "syn 2.0.114", ] [[package]] @@ -3408,7 +3519,7 @@ checksum = "cb7330aeadfbe296029522e6c40f315320aba36fc43a5b3632f3795348f3bd22" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.114", "unicode-xid", ] @@ -3504,7 +3615,7 @@ checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.114", ] [[package]] @@ -3528,7 +3639,7 @@ dependencies = [ "proc-macro2", "quote", "regex", - "syn 2.0.90", + "syn 2.0.114", "termcolor", "toml 0.8.19", "walkdir", @@ -3693,7 +3804,7 @@ dependencies = [ "heck 0.4.1", "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.114", ] [[package]] @@ -3713,7 +3824,7 @@ checksum = "f95e2801cd355d4a1a3e3953ce6ee5ae9603a5c833455343a8bfe3f44d418246" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.114", ] [[package]] @@ -3724,7 +3835,7 @@ checksum = "2f9ed6b3789237c8a0c1c505af1c7eb2c560df6186f01b098c3a1064ea532f38" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.114", ] [[package]] @@ -3809,7 +3920,7 @@ dependencies = [ "hash-db", "hash256-std-hasher", "parity-scale-codec", - "rlp", + "rlp 0.5.2", "scale-info", "serde", "sha3", @@ -3895,7 +4006,7 @@ dependencies = [ "log", "parity-scale-codec", "primitive-types 0.12.2", - "rlp", + "rlp 0.5.2", "scale-info", "serde", "sha3", @@ -3956,7 +4067,7 @@ dependencies = [ "prettyplease 0.2.25", "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.114", ] [[package]] @@ -4035,7 +4146,7 @@ dependencies = [ "proc-macro-crate 3.1.0", "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.114", ] [[package]] @@ -4132,7 +4243,7 @@ dependencies = [ "parity-scale-codec", "prometheus", "rand 0.8.5", - "rlp", + "rlp 0.5.2", "sc-client-api", "sc-consensus-aura", "sc-network", @@ -4171,7 +4282,7 @@ dependencies = [ "ethereum", "ethereum-types 0.14.1", "jsonrpsee", - "rlp", + "rlp 0.5.2", "rustc-hex", "serde", "serde_json", @@ -4571,7 +4682,7 @@ dependencies = [ "proc-macro-crate 3.1.0", "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.114", ] [[package]] @@ -4715,7 +4826,7 @@ dependencies = [ "proc-macro2", "quote", "sp-crypto-hashing", - "syn 2.0.90", + "syn 2.0.114", ] [[package]] @@ -4727,7 +4838,7 @@ dependencies = [ "proc-macro-crate 3.1.0", "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.114", ] [[package]] @@ -4737,7 +4848,7 @@ source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409- dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.114", ] [[package]] @@ -4925,7 +5036,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.114", ] [[package]] @@ -5235,6 +5346,7 @@ dependencies = [ "allocator-api2", "equivalent", "foldhash", + "serde", ] [[package]] @@ -5652,6 +5764,7 @@ dependencies = [ "pallet-balances", "pallet-bonds", "pallet-broadcast", + "pallet-btc-vault", "pallet-circuit-breaker", "pallet-claims", "pallet-collator-rewards", @@ -5992,7 +6105,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f28220f89297a075ddc7245cd538076ee98b01f2a9c23a53a4f1105d5a322808" dependencies = [ - "rlp", + "rlp 0.5.2", ] [[package]] @@ -6053,6 +6166,7 @@ checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f" dependencies = [ "equivalent", "hashbrown 0.15.2", + "serde", ] [[package]] @@ -6389,7 +6503,7 @@ dependencies = [ "proc-macro-crate 3.1.0", "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.114", ] [[package]] @@ -6895,7 +7009,7 @@ dependencies = [ "proc-macro-warning 0.4.2", "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.114", ] [[package]] @@ -7301,6 +7415,17 @@ dependencies = [ "libc", ] +[[package]] +name = "macro-string" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b27834086c65ec3f9387b096d66e99f221cf081c2b738042aa252bcd41204e3" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.114", +] + [[package]] name = "macro_magic" version = "0.5.1" @@ -7310,7 +7435,7 @@ dependencies = [ "macro_magic_core", "macro_magic_macros", "quote", - "syn 2.0.90", + "syn 2.0.114", ] [[package]] @@ -7324,7 +7449,7 @@ dependencies = [ "macro_magic_core_macros", "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.114", ] [[package]] @@ -7335,7 +7460,7 @@ checksum = "b02abfe41815b5bd98dbd4260173db2c116dda171dc0fe7838cb206333b83308" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.114", ] [[package]] @@ -7346,7 +7471,7 @@ checksum = "73ea28ee64b88876bf45277ed9a5817c1817df061a74f2b988971a12570e5869" dependencies = [ "macro_magic_core", "quote", - "syn 2.0.90", + "syn 2.0.114", ] [[package]] @@ -7362,7 +7487,7 @@ dependencies = [ "serde", "serde_derive", "serde_json", - "syn 2.0.90", + "syn 2.0.114", ] [[package]] @@ -7635,7 +7760,7 @@ dependencies = [ "cfg-if", "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.114", ] [[package]] @@ -8045,7 +8170,7 @@ checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.114", ] [[package]] @@ -8127,7 +8252,7 @@ dependencies = [ "proc-macro-crate 3.1.0", "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.114", ] [[package]] @@ -8231,7 +8356,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.114", ] [[package]] @@ -8950,6 +9075,29 @@ dependencies = [ "sp-runtime", ] +[[package]] +name = "pallet-btc-vault" +version = "1.0.0" +dependencies = [ + "alloy-sol-types 0.8.15", + "borsh", + "frame-benchmarking", + "frame-support", + "frame-system", + "hex", + "pallet-balances", + "pallet-signet", + "parity-scale-codec", + "scale-info", + "secp256k1 0.29.1", + "serde", + "serde_json", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", +] + [[package]] name = "pallet-child-bounties" version = "37.0.0" @@ -9166,7 +9314,7 @@ source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409- dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.114", ] [[package]] @@ -10772,7 +10920,7 @@ source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409- dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.114", ] [[package]] @@ -10956,8 +11104,9 @@ dependencies = [ "frame-system", "pallet-balances", "parity-scale-codec", - "rlp", + "rlp 0.5.2", "scale-info", + "signet-rs", "sp-core", "sp-io", "sp-runtime", @@ -11839,7 +11988,7 @@ dependencies = [ "pest_meta", "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.114", ] [[package]] @@ -11880,7 +12029,7 @@ checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.114", ] [[package]] @@ -13461,7 +13610,7 @@ dependencies = [ "polkavm-common 0.9.0", "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.114", ] [[package]] @@ -13473,7 +13622,7 @@ dependencies = [ "polkavm-common 0.10.0", "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.114", ] [[package]] @@ -13483,7 +13632,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ba81f7b5faac81e528eb6158a6f3c9e0bb1008e0ffa19653bc8dea925ecb429" dependencies = [ "polkavm-derive-impl 0.9.0", - "syn 2.0.90", + "syn 2.0.114", ] [[package]] @@ -13493,7 +13642,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9324fe036de37c17829af233b46ef6b5562d4a0c09bb7fdb9f8378856dee30cf" dependencies = [ "polkavm-derive-impl 0.10.0", - "syn 2.0.90", + "syn 2.0.114", ] [[package]] @@ -13730,7 +13879,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "64d1ec885c64d0457d564db4ec299b2dae3f9c02808b8ad9c3a089c591b18033" dependencies = [ "proc-macro2", - "syn 2.0.90", + "syn 2.0.114", ] [[package]] @@ -13831,6 +13980,28 @@ dependencies = [ "version_check", ] +[[package]] +name = "proc-macro-error-attr2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96de42df36bb9bba5542fe9f1a054b8cc87e172759a1868aa05c1f3acc89dfc5" +dependencies = [ + "proc-macro2", + "quote", +] + +[[package]] +name = "proc-macro-error2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11ec05c52be0a07b08061f7dd003e7d7092e0472bc731b4af7bb1ef876109802" +dependencies = [ + "proc-macro-error-attr2", + "proc-macro2", + "quote", + "syn 2.0.114", +] + [[package]] name = "proc-macro-warning" version = "0.4.2" @@ -13839,7 +14010,7 @@ checksum = "3d1eaa7fa0aa1929ffdf7eeb6eac234dde6268914a14ad44d23521ab6a9b258e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.114", ] [[package]] @@ -13850,7 +14021,7 @@ checksum = "834da187cfe638ae8abb0203f0b33e5ccdb02a28e7199f2f47b3e2754f50edca" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.114", ] [[package]] @@ -13896,7 +14067,7 @@ checksum = "440f724eba9f6996b75d63681b0a92b06947f1457076d503a4d2e2c8f56442b8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.114", ] [[package]] @@ -13978,7 +14149,7 @@ dependencies = [ "prost 0.12.6", "prost-types 0.12.6", "regex", - "syn 2.0.90", + "syn 2.0.114", "tempfile", ] @@ -14005,7 +14176,7 @@ dependencies = [ "itertools 0.11.0", "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.114", ] [[package]] @@ -14205,6 +14376,7 @@ dependencies = [ "libc", "rand_chacha 0.3.1", "rand_core 0.6.4", + "serde", ] [[package]] @@ -14397,7 +14569,7 @@ checksum = "bcc303e793d3734489387d205e9b186fac9c6cfacedd98cbb2e8a5943595f3e6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.114", ] [[package]] @@ -14538,6 +14710,16 @@ dependencies = [ "rustc-hex", ] +[[package]] +name = "rlp" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa24e92bb2a83198bb76d661a71df9f7076b8c420b8696e4d3d97d50d94479e3" +dependencies = [ + "bytes", + "rustc-hex", +] + [[package]] name = "rlp-derive" version = "0.1.0" @@ -14750,7 +14932,7 @@ dependencies = [ "proptest", "rand 0.8.5", "rand 0.9.2", - "rlp", + "rlp 0.5.2", "ruint-macro", "serde", "valuable", @@ -15346,7 +15528,7 @@ dependencies = [ "proc-macro-crate 3.1.0", "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.114", ] [[package]] @@ -16353,7 +16535,7 @@ dependencies = [ "proc-macro-crate 3.1.0", "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.114", ] [[package]] @@ -16478,6 +16660,30 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "schemars" +version = "0.8.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fbf2ae1b8bc8e02df939598064d22402220cd5bbcca1c76f7d6a310974d5615" +dependencies = [ + "dyn-clone", + "schemars_derive", + "serde", + "serde_json", +] + +[[package]] +name = "schemars_derive" +version = "0.8.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32e265784ad618884abaea0600a9adf15393368d840e0222d101a072f3f7534d" +dependencies = [ + "proc-macro2", + "quote", + "serde_derive_internals", + "syn 2.0.114", +] + [[package]] name = "schnellru" version = "0.2.3" @@ -16633,6 +16839,16 @@ dependencies = [ "secp256k1-sys 0.9.2", ] +[[package]] +name = "secp256k1" +version = "0.29.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9465315bc9d4566e1724f0fffcbcc446268cb522e60f9a27bcded6b19c108113" +dependencies = [ + "rand 0.8.5", + "secp256k1-sys 0.10.1", +] + [[package]] name = "secp256k1-sys" version = "0.8.2" @@ -16651,6 +16867,15 @@ dependencies = [ "cc", ] +[[package]] +name = "secp256k1-sys" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4387882333d3aa8cb20530a17c69a3752e97837832f34f6dccc760e715001d9" +dependencies = [ + "cc", +] + [[package]] name = "secrecy" version = "0.8.0" @@ -16759,6 +16984,15 @@ dependencies = [ "serde", ] +[[package]] +name = "serde-big-array" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11fc7cc2c76d73e0f27ee52abbd64eec84d46f370c88371120433196934e4b7f" +dependencies = [ + "serde", +] + [[package]] name = "serde-hex-utils" version = "0.1.0" @@ -16786,7 +17020,18 @@ checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.114", +] + +[[package]] +name = "serde_derive_internals" +version = "0.29.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.114", ] [[package]] @@ -16944,6 +17189,22 @@ dependencies = [ "rand_core 0.6.4", ] +[[package]] +name = "signet-rs" +version = "0.2.5" +source = "git+https://github.com/esaminu/signet.rs?branch=borsh-1.5.7#d85f0e81507c315ae65e08b9c28f172baf9a59ce" +dependencies = [ + "borsh", + "bs58 0.5.1", + "hex", + "rlp 0.6.1", + "schemars", + "serde", + "serde-big-array 0.5.1", + "serde_json", + "sha2 0.10.8", +] + [[package]] name = "simba" version = "0.8.1" @@ -17200,7 +17461,7 @@ dependencies = [ "frame-support", "hex", "parity-scale-codec", - "rlp", + "rlp 0.5.2", "scale-info", "serde", "snowbridge-ethereum", @@ -17247,10 +17508,10 @@ dependencies = [ "hex-literal", "parity-bytes", "parity-scale-codec", - "rlp", + "rlp 0.5.2", "scale-info", "serde", - "serde-big-array", + "serde-big-array 0.3.3", "sp-io", "sp-runtime", "sp-std", @@ -17576,7 +17837,7 @@ dependencies = [ "proc-macro-crate 3.1.0", "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.114", ] [[package]] @@ -17851,7 +18112,7 @@ source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409- dependencies = [ "quote", "sp-crypto-hashing", - "syn 2.0.90", + "syn 2.0.114", ] [[package]] @@ -17870,7 +18131,7 @@ source = "git+https://github.com/galacticcouncil/polkadot-sdk?branch=stable2409- dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.114", ] [[package]] @@ -18100,7 +18361,7 @@ dependencies = [ "proc-macro-crate 3.1.0", "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.114", ] [[package]] @@ -18285,7 +18546,7 @@ dependencies = [ "parity-scale-codec", "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.114", ] [[package]] @@ -18610,7 +18871,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.90", + "syn 2.0.114", ] [[package]] @@ -18623,7 +18884,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.90", + "syn 2.0.114", ] [[package]] @@ -18795,9 +19056,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.90" +version = "2.0.114" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "919d3b74a5dd0ccd15aeb8f93e7006bd9e14c295087c9896a110f490752bcf31" +checksum = "d4d107df263a3013ef9b1879b0df87d706ff80f65a86ea879bd9c31f9b307c2a" dependencies = [ "proc-macro2", "quote", @@ -18813,7 +19074,7 @@ dependencies = [ "paste", "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.114", ] [[package]] @@ -18825,7 +19086,19 @@ dependencies = [ "paste", "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.114", +] + +[[package]] +name = "syn-solidity" +version = "0.8.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab4e6eed052a117409a1a744c8bda9c3ea6934597cf7419f791cb7d590871c4c" +dependencies = [ + "paste", + "proc-macro2", + "quote", + "syn 2.0.114", ] [[package]] @@ -18848,7 +19121,7 @@ checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.114", ] [[package]] @@ -19002,7 +19275,7 @@ checksum = "e4c60d69f36615a077cc7663b9cb8e42275722d23e58a7fa3d2c7f2915d09d04" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.114", ] [[package]] @@ -19013,7 +19286,7 @@ checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.114", ] [[package]] @@ -19024,7 +19297,7 @@ checksum = "cc5b44b4ab9c2fdd0e0512e6bece8388e214c0749f5862b114cc5b7a25daf227" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.114", ] [[package]] @@ -19195,7 +19468,7 @@ checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.114", ] [[package]] @@ -19398,7 +19671,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.114", ] [[package]] @@ -19441,7 +19714,7 @@ dependencies = [ "proc-macro-crate 3.1.0", "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.114", ] [[package]] @@ -19899,7 +20172,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.114", "wasm-bindgen-shared", ] @@ -19933,7 +20206,7 @@ checksum = "f0eb82fcb7930ae6219a7ecfd55b217f5f0893484b7a13022ebb2b2bf20b5283" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.114", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -20777,6 +21050,15 @@ dependencies = [ "memchr", ] +[[package]] +name = "winnow" +version = "0.7.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21a0236b59786fed61e2a80582dd500fe61f18b5dca67a4a067d0bc9039339cf" +dependencies = [ + "memchr", +] + [[package]] name = "winreg" version = "0.50.0" @@ -20894,7 +21176,7 @@ dependencies = [ "Inflector", "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.114", ] [[package]] @@ -20995,7 +21277,7 @@ checksum = "9ecf5b4cc5364572d7f4c329661bcc82724222973f2cab6f050a4e5c22f75181" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.114", ] [[package]] @@ -21015,7 +21297,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.114", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 123a66d17c..d77b15fafb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -50,6 +50,7 @@ members = [ 'liquidation-worker-support', 'pallets/hsm', "pallets/signet", + "pallets/btc-vault", "pallets/dispenser" ] @@ -162,6 +163,7 @@ liquidation-worker-support = { path = "liquidation-worker-support", default-feat pallet-hsm = { path = "pallets/hsm", default-features = false } pallet-parameters = { path = "pallets/parameters", default-features = false } pallet-signet = { path = "pallets/signet", default-features = false } +pallet-btc-vault = { path = "pallets/btc-vault", default-features = false } pallet-dispenser = { path = "pallets/dispenser", default-features = false } hydra-dx-build-script-utils = { path = "utils/build-script-utils", default-features = false } diff --git a/pallets/btc-vault/Cargo.toml b/pallets/btc-vault/Cargo.toml new file mode 100644 index 0000000000..229bce9ad8 --- /dev/null +++ b/pallets/btc-vault/Cargo.toml @@ -0,0 +1,68 @@ +[package] +name = "pallet-btc-vault" +version = "1.0.0" +authors = ["GalacticCouncil"] +edition = "2021" +license = "Apache-2.0" +repository = "https://github.com/galacticcouncil/hydration-node" +description = "BTC Vault pallet for Bitcoin deposits via MPC signing" + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[dependencies] +codec = { workspace = true } +scale-info = { workspace = true } +hex = { version = "0.4", default-features = false, features = ["alloc"] } +serde = { version = "1.0", default-features = false, features = ["derive", "alloc"] } +serde_json = { version = "1.0", default-features = false, features = ["alloc"] } + +frame-benchmarking = { workspace = true, optional = true } +frame-support = { workspace = true } +frame-system = { workspace = true } +sp-io = { workspace = true } +sp-core = { workspace = true } +sp-std = { workspace = true } +sp-runtime = { workspace = true } + +alloy-sol-types = { version = "0.8.14", default-features = false } + +pallet-signet = { path = "../signet", default-features = false } + +[dev-dependencies] +pallet-balances = { workspace = true, features = ["std"] } +secp256k1 = { version = "0.29.1", features = ["rand", "recovery"] } + +[features] +default = ["std"] +std = [ + "codec/std", + "scale-info/std", + "hex/std", + "serde/std", + "serde_json/std", + "frame-benchmarking?/std", + "frame-support/std", + "frame-system/std", + "sp-io/std", + "sp-core/std", + "sp-std/std", + "sp-runtime/std", + "alloy-sol-types/std", + "pallet-signet/std", +] +runtime-benchmarks = [ + "frame-benchmarking/runtime-benchmarks", + "frame-support/runtime-benchmarks", + "frame-system/runtime-benchmarks", +] +try-runtime = [ + "frame-support/try-runtime", + "frame-system/try-runtime", +] + +[target.'cfg(not(feature = "std"))'.dependencies] +borsh = { version = "1.5", default-features = false, features = ["derive", "hashbrown"] } + +[target.'cfg(feature = "std")'.dependencies] +borsh = { version = "1.5", default-features = false, features = ["derive", "std"] } diff --git a/pallets/btc-vault/src/lib.rs b/pallets/btc-vault/src/lib.rs new file mode 100644 index 0000000000..d69f0c79e8 --- /dev/null +++ b/pallets/btc-vault/src/lib.rs @@ -0,0 +1,459 @@ +#![cfg_attr(not(feature = "std"), no_std)] + +extern crate alloc; +use alloc::{format, vec}; + +use codec::{Decode, Encode, MaxEncodedLen}; +use frame_support::pallet_prelude::*; +use frame_support::traits::Currency; +use frame_support::PalletId; +use frame_support::{dispatch::DispatchResult, pallet_prelude::Weight, BoundedVec}; +use frame_system::pallet_prelude::*; +use sp_runtime::traits::{AccountIdConversion, Saturating}; +use sp_std::vec::Vec; + +const MAX_SERIALIZED_OUTPUT_LENGTH: u32 = 4 * 1024 * 1024; // 4 MB + +#[cfg(test)] +mod tests; + +pub use pallet::*; + +/// Bitcoin testnet vault address (P2WPKH pubkey hash - 20 bytes) +/// tb1q38c2sg5nc3v0tkcle2uncdyqspc4kuawjxpf0j +pub const TESTNET_VAULT_ADDRESS: [u8; 20] = [ + 0x89, 0xf0, 0xa8, 0x23, 0x93, 0x8c, 0x58, 0xcf, 0x5b, 0x17, 0xc8, 0xeb, 0x93, 0xc6, 0x82, 0x80, 0x63, 0x5b, 0x73, + 0x4e, +]; + +/// Bitcoin testnet CAIP-2 chain ID +const BITCOIN_TESTNET_CAIP2: &str = "bip122:000000000933ea01ad0ee984209779ba"; + +#[frame_support::pallet] +pub mod pallet { + use super::*; + use sp_io::hashing; + + // ========================= Configuration ========================= + + #[pallet::config] + pub trait Config: frame_system::Config + pallet_signet::Config { + type RuntimeEvent: From> + IsType<::RuntimeEvent>; + type VaultPalletId: Get; + + /// Maximum number of Bitcoin inputs per transaction + #[pallet::constant] + type MaxBtcInputs: Get; + + /// Maximum number of Bitcoin outputs per transaction + #[pallet::constant] + type MaxBtcOutputs: Get; + } + + #[pallet::pallet] + pub struct Pallet(_); + + // ========================= Storage ========================= + + /// Global vault configuration + #[pallet::storage] + #[pallet::getter(fn vault_config)] + pub type VaultConfig = StorageValue<_, VaultConfigData, OptionQuery>; + + /// Pending deposits awaiting signature + #[pallet::storage] + #[pallet::getter(fn pending_deposits)] + pub type PendingDeposits = StorageMap< + _, + Blake2_128Concat, + [u8; 32], // request_id + PendingDepositData, + OptionQuery, + >; + + /// User BTC balances (in satoshis) + #[pallet::storage] + #[pallet::getter(fn user_balances)] + pub type UserBalances = StorageMap< + _, + Blake2_128Concat, + T::AccountId, + u64, // satoshis + ValueQuery, + >; + + // ========================= Types ========================= + + #[derive(Encode, Decode, TypeInfo, Clone, Debug, PartialEq, MaxEncodedLen)] + pub struct VaultConfigData { + pub mpc_root_signer_address: [u8; 20], + } + + #[derive(Encode, Decode, TypeInfo, Clone, Debug, MaxEncodedLen)] + pub struct PendingDepositData { + pub requester: AccountId, + pub amount: u64, // satoshis + pub path: BoundedVec>, + } + + // ========================= Events ========================= + + #[pallet::event] + #[pallet::generate_deposit(pub(super) fn deposit_event)] + pub enum Event { + VaultInitialized { + mpc_address: [u8; 20], + initialized_by: T::AccountId, + }, + DepositRequested { + request_id: [u8; 32], + requester: T::AccountId, + amount: u64, + }, + DepositClaimed { + request_id: [u8; 32], + claimer: T::AccountId, + amount: u64, + }, + DebugTxid { + txid: [u8; 32], + }, + DebugTransaction { + tx_hex: BoundedVec>, + version: u32, + locktime: u32, + }, + } + + // ========================= Errors ========================= + + #[pallet::error] + pub enum Error { + NotInitialized, + AlreadyInitialized, + InvalidRequestId, + DuplicateRequest, + DepositNotFound, + UnauthorizedClaimer, + InvalidSignature, + InvalidSigner, + InvalidOutput, + TransferFailed, + Overflow, + SerializationError, + PathTooLong, + PalletAccountNotFunded, + NoVaultOutput, + InvalidVaultOutput, + TooManyInputs, + TooManyOutputs, + } + + // ========================= Hooks ========================= + + #[pallet::hooks] + impl Hooks> for Pallet {} + + // ========================= Extrinsics ========================= + + #[pallet::call] + impl Pallet { + /// Initialize the vault with MPC signer address + #[pallet::call_index(0)] + #[pallet::weight(Weight::from_parts(10_000, 0))] + pub fn initialize(origin: OriginFor, mpc_root_signer_address: [u8; 20]) -> DispatchResult { + let initializer = ensure_signed(origin)?; + ensure!(VaultConfig::::get().is_none(), Error::::AlreadyInitialized); + + VaultConfig::::put(VaultConfigData { + mpc_root_signer_address, + }); + + Self::deposit_event(Event::VaultInitialized { + mpc_address: mpc_root_signer_address, + initialized_by: initializer, + }); + + Ok(()) + } + + /// Request to deposit BTC tokens + /// Note: The pallet account must be funded before calling this + #[pallet::call_index(1)] + #[pallet::weight(Weight::from_parts(100_000, 0))] + pub fn deposit_btc( + origin: OriginFor, + request_id: [u8; 32], + inputs: Vec, + outputs: Vec, + lock_time: u32, + ) -> DispatchResult { + let requester = ensure_signed(origin)?; + + // Ensure vault is initialized + ensure!(VaultConfig::::get().is_some(), Error::::NotInitialized); + + // Ensure no duplicate request + ensure!( + PendingDeposits::::get(&request_id).is_none(), + Error::::DuplicateRequest + ); + + // Convert to bounded vecs + let bounded_inputs: BoundedVec = + inputs.clone().try_into().map_err(|_| Error::::TooManyInputs)?; + let bounded_outputs: BoundedVec = + outputs.clone().try_into().map_err(|_| Error::::TooManyOutputs)?; + + // Get signet deposit amount and pallet account + let signet_deposit = pallet_signet::Pallet::::signature_deposit(); + let pallet_account = Self::account_id(); + let existential_deposit = ::Currency::minimum_balance(); + + // Ensure pallet account has sufficient balance + let pallet_balance = ::Currency::free_balance(&pallet_account); + let required_balance = existential_deposit.saturating_add(signet_deposit); + ensure!(pallet_balance >= required_balance, Error::::PalletAccountNotFunded); + + // Transfer signet deposit from requester to pallet account + ::Currency::transfer( + &requester, + &pallet_account, + signet_deposit, + frame_support::traits::ExistenceRequirement::AllowDeath, + )?; + + // Find vault output and extract deposit amount + let vault_script_pubkey = Self::create_p2wpkh_script(&TESTNET_VAULT_ADDRESS); + let deposit_amount = outputs + .iter() + .find(|output| output.script_pubkey.to_vec() == vault_script_pubkey) + .map(|output| output.value) + .ok_or(Error::::NoVaultOutput)?; + + ensure!(deposit_amount > 0, Error::::InvalidVaultOutput); + + // Use requester account as path + let path = { + let encoded = requester.encode(); + format!("0x{}", hex::encode(encoded)).into_bytes() + }; + + // Build PSBT using signet's build_bitcoin_tx + let psbt_bytes = pallet_signet::Pallet::::build_bitcoin_tx( + frame_system::RawOrigin::Signed(requester.clone()).into(), + bounded_inputs.clone(), + bounded_outputs.clone(), + lock_time, + )?; + + let txid = pallet_signet::Pallet::::get_bitcoin_txid( + frame_system::RawOrigin::Signed(requester.clone()).into(), + bounded_inputs, + bounded_outputs, + lock_time, + )?; + + Self::deposit_event(Event::DebugTxid { txid }); + + Self::deposit_event(Event::DebugTransaction { + tx_hex: psbt_bytes.clone().try_into().unwrap_or_default(), + version: 2, + locktime: lock_time, + }); + + // Generate and verify request ID + let computed_request_id = Self::generate_request_id( + &Self::account_id(), + &txid, + BITCOIN_TESTNET_CAIP2, + 0, + &path, + b"ecdsa", + b"bitcoin", + b"", + ); + + ensure!(computed_request_id == request_id, Error::::InvalidRequestId); + + // Store pending deposit + PendingDeposits::::insert( + &request_id, + PendingDepositData { + requester: requester.clone(), + amount: deposit_amount, + path: path.clone().try_into().map_err(|_| Error::::PathTooLong)?, + }, + ); + + // Create schemas for the response (simple boolean for Bitcoin) + let explorer_schema = + serde_json::to_vec(&serde_json::json!("bool")).map_err(|_| Error::::SerializationError)?; + + let callback_schema = + serde_json::to_vec(&serde_json::json!("bool")).map_err(|_| Error::::SerializationError)?; + + // Call sign_bidirectional from the pallet account + pallet_signet::Pallet::::sign_bidirectional( + frame_system::RawOrigin::Signed(Self::account_id()).into(), + BoundedVec::try_from(psbt_bytes).map_err(|_| Error::::SerializationError)?, + BoundedVec::try_from(BITCOIN_TESTNET_CAIP2.as_bytes().to_vec()) + .map_err(|_| Error::::SerializationError)?, + 0, // key_version + BoundedVec::try_from(path).map_err(|_| Error::::PathTooLong)?, + BoundedVec::try_from(b"ecdsa".to_vec()).map_err(|_| Error::::SerializationError)?, + BoundedVec::try_from(b"bitcoin".to_vec()).map_err(|_| Error::::SerializationError)?, + BoundedVec::try_from(vec![]).map_err(|_| Error::::SerializationError)?, + BoundedVec::try_from(explorer_schema).map_err(|_| Error::::SerializationError)?, + BoundedVec::try_from(callback_schema).map_err(|_| Error::::SerializationError)?, + )?; + + Self::deposit_event(Event::DepositRequested { + request_id, + requester, + amount: deposit_amount, + }); + + Ok(()) + } + + /// Claim deposited BTC tokens after signature verification + #[pallet::call_index(2)] + #[pallet::weight(Weight::from_parts(50_000, 0))] + pub fn claim_btc( + origin: OriginFor, + request_id: [u8; 32], + serialized_output: BoundedVec>, + signature: pallet_signet::Signature, + ) -> DispatchResult { + let claimer = ensure_signed(origin)?; + + // Get pending deposit + let pending = PendingDeposits::::get(&request_id).ok_or(Error::::DepositNotFound)?; + + // Verify claimer is the original requester + ensure!(pending.requester == claimer, Error::::UnauthorizedClaimer); + + // Get vault config + let config = VaultConfig::::get().ok_or(Error::::NotInitialized)?; + + // Verify signature + let message_hash = Self::hash_message(&request_id, &serialized_output); + Self::verify_signature_from_address(&message_hash, &signature, &config.mpc_root_signer_address)?; + + // Check for error magic prefix + const ERROR_PREFIX: [u8; 4] = [0xDE, 0xAD, 0xBE, 0xEF]; + + let success = if serialized_output.len() >= 4 && &serialized_output[..4] == ERROR_PREFIX { + false + } else { + // Decode boolean (Borsh serialized) + use borsh::BorshDeserialize; + bool::try_from_slice(&serialized_output).map_err(|_| Error::::InvalidOutput)? + }; + + ensure!(success, Error::::TransferFailed); + + // Update user balance + UserBalances::::mutate(&claimer, |balance| -> DispatchResult { + *balance = balance.checked_add(pending.amount).ok_or(Error::::Overflow)?; + Ok(()) + })?; + + // Clean up storage + PendingDeposits::::remove(&request_id); + + Self::deposit_event(Event::DepositClaimed { + request_id, + claimer, + amount: pending.amount, + }); + + Ok(()) + } + } + + // ========================= Helper Functions ========================= + + impl Pallet { + fn generate_request_id( + sender: &T::AccountId, + txid: &[u8; 32], + caip2_id: &str, + key_version: u32, + path: &[u8], + algo: &[u8], + dest: &[u8], + params: &[u8], + ) -> [u8; 32] { + use alloy_sol_types::SolValue; + use sp_core::crypto::Ss58Codec; + + let encoded = sender.encode(); + let mut account_bytes = [0u8; 32]; + let len = encoded.len().min(32); + account_bytes[..len].copy_from_slice(&encoded[..len]); + + let account_id32 = sp_runtime::AccountId32::from(account_bytes); + let sender_ss58 = account_id32.to_ss58check_with_version(sp_core::crypto::Ss58AddressFormat::custom(0)); + + let encoded = ( + sender_ss58.as_str(), + txid.as_ref(), + caip2_id, + key_version, + core::str::from_utf8(path).unwrap_or(""), + core::str::from_utf8(algo).unwrap_or(""), + core::str::from_utf8(dest).unwrap_or(""), + core::str::from_utf8(params).unwrap_or(""), + ) + .abi_encode_packed(); + + sp_io::hashing::keccak_256(&encoded) + } + + fn hash_message(request_id: &[u8; 32], output: &[u8]) -> [u8; 32] { + let mut data = Vec::with_capacity(32 + output.len()); + data.extend_from_slice(request_id); + data.extend_from_slice(output); + hashing::keccak_256(&data) + } + + fn verify_signature_from_address( + message_hash: &[u8; 32], + signature: &pallet_signet::Signature, + expected_address: &[u8; 20], + ) -> DispatchResult { + ensure!(signature.recovery_id < 4, Error::::InvalidSignature); + + let mut sig_bytes = [0u8; 65]; + sig_bytes[..32].copy_from_slice(&signature.big_r.x); + sig_bytes[32..64].copy_from_slice(&signature.s); + sig_bytes[64] = signature.recovery_id; + + let pubkey = sp_io::crypto::secp256k1_ecdsa_recover(&sig_bytes, message_hash) + .map_err(|_| Error::::InvalidSignature)?; + + let pubkey_hash = hashing::keccak_256(&pubkey); + let recovered_address = &pubkey_hash[12..]; + + ensure!(recovered_address == expected_address, Error::::InvalidSigner); + + Ok(()) + } + + fn create_p2wpkh_script(pubkey_hash: &[u8; 20]) -> Vec { + let mut script = Vec::with_capacity(22); + script.push(0x00); // OP_0 + script.push(0x14); // Push 20 bytes + script.extend_from_slice(pubkey_hash); + script + } + } + + impl Pallet { + pub fn account_id() -> T::AccountId { + T::VaultPalletId::get().into_account_truncating() + } + } +} diff --git a/pallets/btc-vault/src/tests.rs b/pallets/btc-vault/src/tests.rs new file mode 100644 index 0000000000..f5bad2698b --- /dev/null +++ b/pallets/btc-vault/src/tests.rs @@ -0,0 +1,429 @@ +use crate::{self as pallet_btc_vault, *}; +use frame_support::{assert_noop, assert_ok, parameter_types, traits::Currency as CurrencyTrait, PalletId, BoundedVec}; +use frame_system as system; +use secp256k1::{Message, PublicKey, Secp256k1, SecretKey}; +use sp_core::H256; +use sp_io::hashing::keccak_256; +use sp_runtime::{ + traits::{BlakeTwo256, IdentityLookup}, + BuildStorage, +}; + +// Test secret key for signing +fn get_test_secret_key() -> SecretKey { + SecretKey::from_slice(&[42u8; 32]).expect("Valid secret key") +} + +fn bounded_u8(v: Vec) -> BoundedVec> { + BoundedVec::try_from(v).unwrap() +} + +fn bounded_chain_id(v: Vec) -> BoundedVec { + BoundedVec::try_from(v).unwrap() +} + +// Get public key from secret key +fn get_test_public_key() -> PublicKey { + let secp = Secp256k1::new(); + let secret_key = get_test_secret_key(); + PublicKey::from_secret_key(&secp, &secret_key) +} + +fn public_key_to_btc_address(public_key: &PublicKey) -> [u8; 20] { + let uncompressed = public_key.serialize_uncompressed(); + let hash = keccak_256(&uncompressed[1..]); + let mut address = [0u8; 20]; + address.copy_from_slice(&hash[12..]); + address +} + +// Create a valid signature for testing using secp256k1 directly +fn create_valid_signature(message_hash: &[u8; 32]) -> pallet_signet::Signature { + let secp = Secp256k1::new(); + let secret_key = get_test_secret_key(); + let message = Message::from_slice(message_hash).expect("Valid message hash"); + + let sig = secp.sign_ecdsa_recoverable(&message, &secret_key); + let (recovery_id, sig_bytes) = sig.serialize_compact(); + + let mut r = [0u8; 32]; + let mut s = [0u8; 32]; + r.copy_from_slice(&sig_bytes[0..32]); + s.copy_from_slice(&sig_bytes[32..64]); + + pallet_signet::Signature { + big_r: pallet_signet::AffinePoint { + x: r, + y: [0u8; 32], + }, + s, + recovery_id: recovery_id.to_i32() as u8, + } +} + +type Block = frame_system::mocking::MockBlock; + +// Mock runtime construction +frame_support::construct_runtime!( + pub enum Test { + System: frame_system, + Balances: pallet_balances, + Signet: pallet_signet, + BtcVault: pallet_btc_vault, + } +); + +// System config +parameter_types! { + pub const BlockHashCount: u64 = 250; +} + +impl system::Config for Test { + type BaseCallFilter = frame_support::traits::Everything; + type BlockWeights = (); + type BlockLength = (); + type DbWeight = (); + type RuntimeOrigin = RuntimeOrigin; + type RuntimeCall = RuntimeCall; + type Nonce = u64; + type Hash = H256; + type Hashing = BlakeTwo256; + type AccountId = u64; + type Lookup = IdentityLookup; + type Block = Block; + type RuntimeEvent = RuntimeEvent; + type BlockHashCount = BlockHashCount; + type Version = (); + type PalletInfo = PalletInfo; + type AccountData = pallet_balances::AccountData; + type OnNewAccount = (); + type OnKilledAccount = (); + type SystemWeightInfo = (); + type SS58Prefix = (); + type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; + type RuntimeTask = (); + type SingleBlockMigrations = (); + type MultiBlockMigrator = (); + type PreInherents = (); + type PostInherents = (); + type PostTransactions = (); +} + +// Balances config +parameter_types! { + pub const ExistentialDeposit: u128 = 1; +} + +impl pallet_balances::Config for Test { + type Balance = u128; + type DustRemoval = (); + type RuntimeEvent = RuntimeEvent; + type ExistentialDeposit = ExistentialDeposit; + type AccountStore = System; + type WeightInfo = (); + type MaxLocks = (); + type MaxReserves = (); + type ReserveIdentifier = [u8; 8]; + type FreezeIdentifier = (); + type MaxFreezes = (); + type RuntimeHoldReason = (); + type RuntimeFreezeReason = (); +} + +// Signet config +parameter_types! { + pub const SignetPalletId: PalletId = PalletId(*b"py/signt"); + pub const MaxChainIdLength: u32 = 128; + pub const MaxDataLength: u32 = 100_000; + pub const MaxSignatureDeposit: u128 = 10_000_000; +} + +impl pallet_signet::Config for Test { + type RuntimeEvent = RuntimeEvent; + type Currency = Balances; + type PalletId = SignetPalletId; + type MaxChainIdLength = MaxChainIdLength; + type WeightInfo = pallet_signet::weights::WeightInfo; + type MaxDataLength = MaxDataLength; + type UpdateOrigin = frame_system::EnsureRoot; + type MaxSignatureDeposit = MaxSignatureDeposit; +} + +// BTC Vault config +parameter_types! { + pub const BtcVaultPalletId: PalletId = PalletId(*b"py/btcvt"); + pub const MaxBtcInputs: u32 = 100; + pub const MaxBtcOutputs: u32 = 100; +} + +impl pallet_btc_vault::Config for Test { + type RuntimeEvent = RuntimeEvent; + type VaultPalletId = BtcVaultPalletId; + type MaxBtcInputs = MaxBtcInputs; + type MaxBtcOutputs = MaxBtcOutputs; +} + +// Helper to build test externalities +pub fn new_test_ext() -> sp_io::TestExternalities { + let t = system::GenesisConfig::::default().build_storage().unwrap(); + let mut ext = sp_io::TestExternalities::new(t); + ext.execute_with(|| { + System::set_block_number(1); + // Fund test accounts + let _ = >::deposit_creating(&1, 1_000_000); + let _ = >::deposit_creating(&2, 1_000_000); + let _ = >::deposit_creating(&3, 100); + // Initialize signet pallet + let _ = pallet_signet::Pallet::::initialize( + RuntimeOrigin::root(), + 1, + 100, + bounded_chain_id(b"test-chain".to_vec()), + ); + // Fund pallet account + let pallet_account = BtcVault::account_id(); + let _ = >::deposit_creating(&pallet_account, 10_000); + }); + ext +} + +fn create_test_mpc_address() -> [u8; 20] { + let public_key = get_test_public_key(); + public_key_to_btc_address(&public_key) +} + +// ======================================== +// INITIALIZATION TESTS +// ======================================== + +#[test] +fn test_initialize_works() { + new_test_ext().execute_with(|| { + let initializer = 2u64; + let mpc_address = create_test_mpc_address(); + + assert_eq!(BtcVault::vault_config(), None); + + assert_ok!(BtcVault::initialize(RuntimeOrigin::signed(initializer), mpc_address)); + + assert_eq!( + BtcVault::vault_config(), + Some(VaultConfigData { + mpc_root_signer_address: mpc_address + }) + ); + + System::assert_last_event( + Event::VaultInitialized { + mpc_address, + initialized_by: initializer, + } + .into(), + ); + }); +} + +#[test] +fn test_cannot_initialize_twice() { + new_test_ext().execute_with(|| { + let mpc_address = create_test_mpc_address(); + + assert_ok!(BtcVault::initialize(RuntimeOrigin::signed(1), mpc_address)); + + assert_noop!( + BtcVault::initialize(RuntimeOrigin::signed(2), [4u8; 20]), + Error::::AlreadyInitialized + ); + }); +} + +// ======================================== +// DEPOSIT TESTS +// ======================================== + +#[test] +fn test_deposit_btc_fails_without_initialization() { + new_test_ext().execute_with(|| { + let requester = 1u64; + let request_id = [1u8; 32]; + + let inputs = vec![pallet_signet::UtxoInput { + txid: [0x42; 32], + vout: 0, + value: 100_000_000, + script_pubkey: BoundedVec::try_from(vec![0x00, 0x14]).unwrap(), + sequence: 0xFFFFFFFF, + }]; + + let outputs = vec![pallet_signet::BitcoinOutput { + value: 99_900_000, + script_pubkey: BoundedVec::try_from(vec![0x00, 0x14]).unwrap(), + }]; + + assert_noop!( + BtcVault::deposit_btc(RuntimeOrigin::signed(requester), request_id, inputs, outputs, 0), + Error::::NotInitialized + ); + }); +} + +#[test] +fn test_deposit_btc_fails_without_vault_output() { + new_test_ext().execute_with(|| { + assert_ok!(BtcVault::initialize(RuntimeOrigin::signed(1), create_test_mpc_address())); + + let requester = 2u64; + let request_id = [1u8; 32]; + + let inputs = vec![pallet_signet::UtxoInput { + txid: [0x42; 32], + vout: 0, + value: 100_000_000, + script_pubkey: BoundedVec::try_from(vec![0x00, 0x14]).unwrap(), + sequence: 0xFFFFFFFF, + }]; + + // Output that doesn't go to vault + let outputs = vec![pallet_signet::BitcoinOutput { + value: 99_900_000, + script_pubkey: BoundedVec::try_from(vec![0x00, 0x14, 0x99, 0x99]).unwrap(), + }]; + + assert_noop!( + BtcVault::deposit_btc(RuntimeOrigin::signed(requester), request_id, inputs, outputs, 0), + Error::::NoVaultOutput + ); + }); +} + +// ======================================== +// CLAIM TESTS +// ======================================== + +#[test] +fn test_claim_nonexistent_deposit_fails() { + new_test_ext().execute_with(|| { + assert_ok!(BtcVault::initialize(RuntimeOrigin::signed(1), create_test_mpc_address())); + + let claimer = 2u64; + let request_id = [99u8; 32]; + + assert_noop!( + BtcVault::claim_btc( + RuntimeOrigin::signed(claimer), + request_id, + bounded_u8::<4194304>(vec![1u8]), + pallet_signet::Signature { + big_r: pallet_signet::AffinePoint { + x: [1u8; 32], + y: [2u8; 32], + }, + s: [3u8; 32], + recovery_id: 0, + }, + ), + Error::::DepositNotFound + ); + }); +} + +#[test] +fn test_claim_with_error_response_fails() { + new_test_ext().execute_with(|| { + let mpc_address = create_test_mpc_address(); + assert_ok!(BtcVault::initialize(RuntimeOrigin::signed(1), mpc_address)); + + // Manually insert a pending deposit for testing + let requester = 2u64; + let request_id = [1u8; 32]; + let amount = 50_000_000u64; + + PendingDeposits::::insert( + &request_id, + PendingDepositData { + requester, + amount, + path: bounded_u8::<256>(b"test".to_vec()), + }, + ); + + // Error response with magic prefix + let error_output = vec![0xDE, 0xAD, 0xBE, 0xEF, 1, 2, 3]; + + let message_hash = { + let mut data = Vec::with_capacity(32 + error_output.len()); + data.extend_from_slice(&request_id); + data.extend_from_slice(&error_output); + keccak_256(&data) + }; + + let valid_signature = create_valid_signature(&message_hash); + + assert_noop!( + BtcVault::claim_btc( + RuntimeOrigin::signed(requester), + request_id, + bounded_u8::<4194304>(error_output), + valid_signature, + ), + Error::::TransferFailed + ); + + assert_eq!(BtcVault::user_balances(requester), 0); + }); +} + +#[test] +fn test_claim_successful_with_valid_signature() { + new_test_ext().execute_with(|| { + let mpc_address = create_test_mpc_address(); + assert_ok!(BtcVault::initialize(RuntimeOrigin::signed(1), mpc_address)); + + let requester = 2u64; + let request_id = [1u8; 32]; + let amount = 50_000_000u64; + + PendingDeposits::::insert( + &request_id, + PendingDepositData { + requester, + amount, + path: bounded_u8::<256>(b"test".to_vec()), + }, + ); + + // Success response: Borsh-encoded true (1u8) + let success_output = vec![1u8]; + + let message_hash = { + let mut data = Vec::with_capacity(32 + success_output.len()); + data.extend_from_slice(&request_id); + data.extend_from_slice(&success_output); + keccak_256(&data) + }; + + let valid_signature = create_valid_signature(&message_hash); + + assert_eq!(BtcVault::user_balances(requester), 0); + + assert_ok!(BtcVault::claim_btc( + RuntimeOrigin::signed(requester), + request_id, + bounded_u8::<4194304>(success_output), + valid_signature, + )); + + assert_eq!(BtcVault::user_balances(requester), amount); + assert!(BtcVault::pending_deposits(&request_id).is_none()); + + System::assert_has_event( + Event::DepositClaimed { + request_id, + claimer: requester, + amount, + } + .into(), + ); + }); +} diff --git a/pallets/signet/Cargo.toml b/pallets/signet/Cargo.toml index a8e644333c..62ac117a46 100644 --- a/pallets/signet/Cargo.toml +++ b/pallets/signet/Cargo.toml @@ -18,6 +18,7 @@ frame-system = { workspace = true } sp-runtime = { workspace = true } sp-std = { workspace = true } ethereum = { workspace = true } +signet-rs = { git = "https://github.com/esaminu/signet.rs", branch = "borsh-1.5.7", default-features = false, features = ["bitcoin"] } # Optional imports for benchmarking frame-benchmarking = { workspace = true, optional = true } @@ -41,7 +42,8 @@ std = [ "sp-std/std", "sp-io/std", "frame-benchmarking?/std", - "pallet-balances/std" + "pallet-balances/std", + "signet-rs/std", ] runtime-benchmarks = [ "frame-benchmarking/runtime-benchmarks", diff --git a/pallets/signet/src/lib.rs b/pallets/signet/src/lib.rs index 5e3cd593d5..405ea28fb7 100644 --- a/pallets/signet/src/lib.rs +++ b/pallets/signet/src/lib.rs @@ -6,6 +6,7 @@ use frame_support::{ traits::{Currency, ExistenceRequirement}, PalletId, }; +use sp_runtime::RuntimeDebug; use frame_system::pallet_prelude::*; pub use pallet::*; use sp_core::{H160, U256}; @@ -22,8 +23,9 @@ const MAX_DEST_LENGTH: u32 = 64; const MAX_PARAMS_LENGTH: u32 = 1024; /// Maximum length for transaction data and serialized outputs -const MAX_TRANSACTION_LENGTH: u32 = 65536; // 64 KB -const MAX_SERIALIZED_OUTPUT_LENGTH: u32 = 65536; // 64 KB +/// Set to 4MB to accommodate the largest possible Bitcoin transaction +const MAX_TRANSACTION_LENGTH: u32 = 4 * 1024 * 1024; // 4 MB +const MAX_SERIALIZED_OUTPUT_LENGTH: u32 = 4 * 1024 * 1024; // 4 MB /// Maximum length for schemas and error messages const MAX_SCHEMA_LENGTH: u32 = 4096; // 4 KB @@ -111,6 +113,36 @@ pub mod pallet { pub error_message: BoundedVec>, } + // ======================================== + // Bitcoin Types + // ======================================== + + /// Bitcoin script max size (10KB - generous for any script type) + pub type MaxScriptLength = ConstU32<10_000>; + + /// Maximum number of Bitcoin inputs (supports large consolidation txs) + pub type MaxBitcoinInputs = ConstU32<5_000>; + + /// Maximum number of Bitcoin outputs (supports large batch payouts) + pub type MaxBitcoinOutputs = ConstU32<5_000>; + + /// Bitcoin UTXO input with metadata required for PSBT construction + #[derive(Encode, Decode, TypeInfo, Clone, PartialEq, Eq, RuntimeDebug)] + pub struct UtxoInput { + pub txid: [u8; 32], + pub vout: u32, + pub value: u64, + pub script_pubkey: BoundedVec, + pub sequence: u32, + } + + /// Bitcoin transaction output + #[derive(Encode, Decode, TypeInfo, Clone, PartialEq, Eq, RuntimeDebug)] + pub struct BitcoinOutput { + pub value: u64, + pub script_pubkey: BoundedVec, + } + // ======================================== // Storage // ======================================== @@ -235,6 +267,17 @@ pub mod pallet { InvalidGasPrice, /// Signature Deposit cannot exceed MaxSignatureDeposit MaxDepositExceeded, + // Bitcoin errors + /// Bitcoin transaction must have at least one input + NoInputs, + /// Bitcoin transaction must have at least one output + NoOutputs, + /// Invalid lock time value + InvalidLockTime, + /// Failed to create PSBT + PsbtCreationFailed, + /// Failed to serialize PSBT + PsbtSerializationFailed, } // ======================================== @@ -538,5 +581,116 @@ pub mod pallet { Ok(output) } + + /// Build a Bitcoin PSBT and return the serialized bytes + /// + /// # Parameters + /// - `origin`: The signed origin + /// - `inputs`: UTXOs to spend + /// - `outputs`: Transaction outputs + /// - `lock_time`: Transaction locktime + /// + /// # Returns + /// Serialized PSBT bytes + pub fn build_bitcoin_tx( + origin: OriginFor, + inputs: BoundedVec, + outputs: BoundedVec, + lock_time: u32, + ) -> Result, DispatchError> { + ensure_signed(origin)?; + + ensure!(!inputs.is_empty(), Error::::NoInputs); + ensure!(!outputs.is_empty(), Error::::NoOutputs); + + let (psbt_bytes, _) = Self::build_psbt(&inputs, &outputs, lock_time)?; + Ok(psbt_bytes) + } + + /// Get the transaction ID (txid) for a Bitcoin transaction + /// + /// # Parameters + /// - `origin`: The signed origin + /// - `inputs`: UTXOs to spend + /// - `outputs`: Transaction outputs + /// - `lock_time`: Transaction locktime + /// + /// # Returns + /// 32-byte transaction ID (canonical, excludes witness) + pub fn get_bitcoin_txid( + origin: OriginFor, + inputs: BoundedVec, + outputs: BoundedVec, + lock_time: u32, + ) -> Result<[u8; 32], DispatchError> { + ensure_signed(origin)?; + + ensure!(!inputs.is_empty(), Error::::NoInputs); + ensure!(!outputs.is_empty(), Error::::NoOutputs); + + let (_, txid) = Self::build_psbt(&inputs, &outputs, lock_time)?; + Ok(txid) + } + + fn build_psbt( + inputs: &[UtxoInput], + outputs: &[BitcoinOutput], + lock_time: u32, + ) -> Result<(Vec, [u8; 32]), DispatchError> { + use signet_rs::bitcoin::types::{ + Amount, Hash, LockTime, OutPoint, ScriptBuf, Sequence, TxIn, TxOut, Txid, Version, Witness, + }; + use signet_rs::{TransactionBuilder, TxBuilder, BITCOIN}; + + let tx_inputs: Vec = inputs + .iter() + .map(|input| TxIn { + previous_output: OutPoint::new(Txid(Hash(input.txid)), input.vout), + script_sig: ScriptBuf::default(), + sequence: Sequence(input.sequence), + witness: Witness::default(), + }) + .collect(); + + let tx_outputs: Vec = outputs + .iter() + .map(|output| TxOut { + value: Amount::from_sat(output.value), + script_pubkey: ScriptBuf(output.script_pubkey.to_vec()), + }) + .collect(); + + let lock_time_parsed = if lock_time < 500_000_000 { + LockTime::from_height(lock_time).map_err(|_| Error::::InvalidLockTime)? + } else { + LockTime::from_time(lock_time).map_err(|_| Error::::InvalidLockTime)? + }; + + let tx = TransactionBuilder::new::() + .version(Version::Two) + .inputs(tx_inputs) + .outputs(tx_outputs) + .lock_time(lock_time_parsed) + .build(); + + // Extract txid before creating PSBT + let txid = tx.compute_txid(); + let mut txid_bytes = txid.as_byte_array(); + txid_bytes.reverse(); + + let mut psbt = tx.to_psbt(); + + for (i, input) in inputs.iter().enumerate() { + psbt.update_input_with_witness_utxo(i, input.script_pubkey.to_vec(), input.value) + .map_err(|_| Error::::PsbtCreationFailed)?; + + psbt.update_input_with_sighash_type(i, 1) + .map_err(|_| Error::::PsbtCreationFailed)?; + } + + let psbt_bytes = psbt.serialize().map_err(|_| Error::::PsbtSerializationFailed)?; + + Ok((psbt_bytes, txid_bytes)) + } } } diff --git a/pallets/signet/src/tests/tests.rs b/pallets/signet/src/tests/tests.rs index c2332f2e27..ae05505b4a 100644 --- a/pallets/signet/src/tests/tests.rs +++ b/pallets/signet/src/tests/tests.rs @@ -7,7 +7,7 @@ use crate::{ Error, ErrorResponse, Event, }; use frame_support::traits::Currency; -use frame_support::{assert_noop, assert_ok}; +use frame_support::{assert_noop, assert_ok, BoundedVec}; use sp_runtime::traits::AccountIdConversion; // ----------------------------------------------------------------------------- @@ -491,7 +491,7 @@ fn test_sign_bidirectional_works() { assert_ok!(Signet::sign_bidirectional( RuntimeOrigin::signed(requester), - bounded_u8::<65536>(tx_data.clone()), + bounded_u8::<4194304>(tx_data.clone()), bounded_u8::<64>(caip2_id.to_vec()), 1, bounded_u8::<256>(b"path".to_vec()), @@ -523,7 +523,7 @@ fn test_sign_bidirectional_empty_transaction_fails() { assert_noop!( Signet::sign_bidirectional( RuntimeOrigin::signed(requester), - bounded_u8::<65536>(vec![]), + bounded_u8::<4194304>(vec![]), bounded_u8::<64>(CAIP2_SEPOLIA.to_vec()), 1, bounded_u8::<256>(b"path".to_vec()), @@ -673,7 +673,7 @@ fn test_respond_bidirectional() { assert_ok!(Signet::respond_bidirectional( RuntimeOrigin::signed(responder), request_id, - bounded_u8::<65536>(output.clone()), + bounded_u8::<4194304>(output.clone()), signature.clone() )); @@ -775,3 +775,111 @@ fn test_cross_pallet_execution() { println!(" NOT as: {} (the original user)", NON_ADMIN); }); } + +// ----------------------------------------------------------------------------- +// Bitcoin Transaction Tests +// ----------------------------------------------------------------------------- + +use crate::{ + tests::utils::{create_test_bitcoin_output, create_test_utxo_input}, + BitcoinOutput, MaxBitcoinInputs, MaxBitcoinOutputs, UtxoInput, +}; + +#[test] +fn test_build_bitcoin_tx_works() { + new_test_ext().execute_with(|| { + let inputs = BoundedVec::::try_from(vec![create_test_utxo_input( + [0x42; 32], + 0, + 100_000_000, + )]) + .unwrap(); + + let outputs = + BoundedVec::::try_from(vec![create_test_bitcoin_output(99_900_000)]) + .unwrap(); + + let result = Signet::build_bitcoin_tx(RuntimeOrigin::signed(ADMIN), inputs, outputs, 0); + + assert_ok!(&result); + let psbt = result.unwrap(); + assert!(!psbt.is_empty(), "PSBT should not be empty"); + }); +} + +#[test] +fn test_get_bitcoin_txid_works() { + new_test_ext().execute_with(|| { + let inputs = BoundedVec::::try_from(vec![create_test_utxo_input( + [0x42; 32], + 0, + 100_000_000, + )]) + .unwrap(); + + let outputs = + BoundedVec::::try_from(vec![create_test_bitcoin_output(99_900_000)]) + .unwrap(); + + let result = Signet::get_bitcoin_txid(RuntimeOrigin::signed(ADMIN), inputs.clone(), outputs.clone(), 0); + + assert_ok!(&result); + let txid = result.unwrap(); + assert_eq!(txid.len(), 32, "Txid should be 32 bytes"); + + // Verify txid is deterministic + let result2 = Signet::get_bitcoin_txid(RuntimeOrigin::signed(ADMIN), inputs, outputs, 0); + assert_eq!(txid, result2.unwrap(), "Same inputs should produce same txid"); + }); +} + +#[test] +fn test_build_bitcoin_tx_no_inputs_fails() { + new_test_ext().execute_with(|| { + let outputs = + BoundedVec::::try_from(vec![create_test_bitcoin_output(100_000_000)]) + .unwrap(); + + assert_noop!( + Signet::build_bitcoin_tx( + RuntimeOrigin::signed(ADMIN), + BoundedVec::default(), + outputs.clone(), + 0 + ), + Error::::NoInputs + ); + + assert_noop!( + Signet::get_bitcoin_txid(RuntimeOrigin::signed(ADMIN), BoundedVec::default(), outputs, 0), + Error::::NoInputs + ); + }); +} + +#[test] +fn test_build_bitcoin_tx_no_outputs_fails() { + new_test_ext().execute_with(|| { + let inputs = BoundedVec::::try_from(vec![create_test_utxo_input( + [0x42; 32], + 0, + 100_000_000, + )]) + .unwrap(); + + assert_noop!( + Signet::build_bitcoin_tx( + RuntimeOrigin::signed(ADMIN), + inputs.clone(), + BoundedVec::default(), + 0 + ), + Error::::NoOutputs + ); + + assert_noop!( + Signet::get_bitcoin_txid(RuntimeOrigin::signed(ADMIN), inputs, BoundedVec::default(), 0), + Error::::NoOutputs + ); + }); +} diff --git a/pallets/signet/src/tests/utils.rs b/pallets/signet/src/tests/utils.rs index 2183d0f28f..d406dcaee4 100644 --- a/pallets/signet/src/tests/utils.rs +++ b/pallets/signet/src/tests/utils.rs @@ -1,4 +1,4 @@ -use crate::{tests::MaxChainIdLength, AffinePoint, ErrorResponse, Signature}; +use crate::{tests::MaxChainIdLength, AffinePoint, BitcoinOutput, ErrorResponse, MaxScriptLength, Signature, UtxoInput}; use sp_core::ConstU32; use sp_runtime::BoundedVec; @@ -32,3 +32,21 @@ pub fn create_test_signature() -> Signature { recovery_id: 0, } } + +// Bitcoin helpers +pub fn create_test_utxo_input(txid: [u8; 32], vout: u32, value: u64) -> UtxoInput { + UtxoInput { + txid, + vout, + value, + script_pubkey: BoundedVec::::try_from(vec![0x00, 0x14]).unwrap(), + sequence: 0xFFFFFFFF, + } +} + +pub fn create_test_bitcoin_output(value: u64) -> BitcoinOutput { + BitcoinOutput { + value, + script_pubkey: BoundedVec::::try_from(vec![0x00, 0x14]).unwrap(), + } +} diff --git a/runtime/hydradx/Cargo.toml b/runtime/hydradx/Cargo.toml index cd103f865b..0ff38e5d07 100644 --- a/runtime/hydradx/Cargo.toml +++ b/runtime/hydradx/Cargo.toml @@ -92,6 +92,7 @@ pallet-whitelist = { workspace = true } pallet-message-queue = { workspace = true } pallet-state-trie-migration = { workspace = true } pallet-signet = { workspace = true } +pallet-btc-vault = { workspace = true } pallet-dispenser = { workspace = true } # ORML dependencies @@ -386,6 +387,7 @@ std = [ "pallet-broadcast/std", "pallet-dispatcher/std", "pallet-signet/std", + "pallet-btc-vault/std", "pallet-dispenser/std", # Hyperbridge "anyhow/std", @@ -475,6 +477,7 @@ try-runtime = [ "pallet-broadcast/try-runtime", "pallet-dispatcher/try-runtime", "pallet-signet/try-runtime", + "pallet-btc-vault/try-runtime", ] metadata-hash = [ diff --git a/runtime/hydradx/src/assets.rs b/runtime/hydradx/src/assets.rs index 4adeff08b1..d76dc1bd34 100644 --- a/runtime/hydradx/src/assets.rs +++ b/runtime/hydradx/src/assets.rs @@ -1867,6 +1867,19 @@ impl pallet_signet::Config for Runtime { type MaxSignatureDeposit = MaxSignatureDeposit; } +parameter_types! { + pub const BtcVaultPalletId: PalletId = PalletId(*b"py/btcvt"); + pub const MaxBtcInputs: u32 = 100; + pub const MaxBtcOutputs: u32 = 100; +} + +impl pallet_btc_vault::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type VaultPalletId = BtcVaultPalletId; + type MaxBtcInputs = MaxBtcInputs; + type MaxBtcOutputs = MaxBtcOutputs; +} + parameter_types! { pub const SigEthPalletId: PalletId = PalletId(*b"py/fucet"); pub const SigEthFaucetDispenserFee: u128 = 5_000; diff --git a/runtime/hydradx/src/lib.rs b/runtime/hydradx/src/lib.rs index 93dd09d935..15aae61e89 100644 --- a/runtime/hydradx/src/lib.rs +++ b/runtime/hydradx/src/lib.rs @@ -193,6 +193,7 @@ construct_runtime!( HSM: pallet_hsm = 82, Parameters: pallet_parameters = 83, Signet: pallet_signet = 84, + BtcVault: pallet_btc_vault = 86, EthDispenser: pallet_dispenser = 85, // ORML related modules diff --git a/signet-ts-client-scripts/README.md b/signet-ts-client-scripts/README.md new file mode 100644 index 0000000000..faee2707c9 --- /dev/null +++ b/signet-ts-client-scripts/README.md @@ -0,0 +1,248 @@ +# Signet Substrate Client + +Test client for the Signet pallet on Substrate/Polkadot. Validates signature generation and verification for both simple payloads, EIP-1559 transactions, and ERC20 vault deposits. + +## Prerequisites + +- Node.js v16+ and npm/yarn +- Running Substrate node with Signet pallet deployed (port 8000) +- Access to the Signet signature server +- For ERC20 vault tests: Funded Ethereum Sepolia account with ETH and USDC +- For Bitcoin vault tests: Docker for running Bitcoin regtest + +## Setup + +### 1. Start Bitcoin Regtest (for Bitcoin vault tests) +```bash +# Clone the Bitcoin regtest repository +git clone https://github.com/Pessina/bitcoin-regtest.git +cd bitcoin-regtest + +# Start Bitcoin Core in regtest mode +yarn docker:dev +``` + +The Bitcoin regtest node will be available at `http://localhost:18443`. + +### 2. Start the Signature Server + +Clone and run the signature server that responds to Substrate signature requests. Add .env to the root of the repository: + +```bash +# Clone the server repository (substrate-new branch) +git clone -b substrate-new https://github.com/sig-net/solana-signet-program.git +cd solana-signet-program/clients/response-server + +# Install dependencies +yarn install + +# Configure environment variables +cat > .env << EOF +# Substrate Configuration +SUBSTRATE_WS_URL=ws://localhost:8000 +SUBSTRATE_SIGNER_SEED=//Bob + +# Signing Keys (must match ROOT_PUBLIC_KEY in tests) +PRIVATE_KEY_TESTNET=0x... # Your private key for signing + +# Ethereum Configuration (for vault monitoring) +SEPOLIA_RPC_URL=https://sepolia.infura.io/v3/your_infura_key_here + +# Bitcoin Configuration (for Bitcoin vault monitoring) +BITCOIN_NETWORK=regtest + +# Dummy solana key +SOLANA_PRIVATE_KEY='[16,151,155,240,122,151,187,95,145,26,179,205,196,113,3,62,17,105,18,240,197,176,45,90,176,108,30,106,182,43,7,104,80,202,59,51,239,219,236,17,39,204,155,35,175,195,17,172,201,196,134,125,25,214,148,76,102,47,123,37,203,86,159,147]' +EOF + +# Start the server +yarn start +``` + +The server will: +- Connect to your Substrate node +- Automatically respond to signature requests +- Monitor Ethereum transactions and report results back to Substrate +- Monitor Bitcoin transactions on regtest and report results back to Substrate + +### 3. Install Test Client Dependencies + +```bash +yarn install +``` + +### 4. Ensure Substrate Node is Running + +The tests expect a Substrate node with the Signet pallet at `ws://localhost:8000`. If using Chopsticks: + +```bash +npx @acala-network/chopsticks@latest --config=hydradx \ + --wasm-override ./target/release/wbuild/hydradx-runtime/hydradx_runtime.compact.compressed.wasm \ + --db=:memory: +``` + +### 5. Fund Ethereum Account for Vault Tests + +The ERC20 vault test requires a funded account on Sepolia. The test derives an Ethereum address from your Substrate account and expects it to have: + +- At least 0.001 ETH for gas +- At least 0.01 USDC (testnet) at address `0xbe72E441BF55620febc26715db68d3494213D8Cb` + +The derived address is deterministic based on your Substrate account. Run the test once to see the address, then fund it on Sepolia + +## Running Tests + +```bash +# Run all tests +yarn test + +# Run specific test suite +yarn test signet.test.ts +yarn test erc20vault.test.ts +yarn test btc-vault.test.ts + +# Run with watch mode +yarn test:watch +``` + +## Test Coverage + +### Basic Signature Tests (`signet.test.ts`) +- **Simple Signatures**: Request and verify ECDSA signatures for 32-byte payloads +- **Transaction Signatures**: Sign and verify EIP-1559 Ethereum transactions +- **Key Derivation**: Verify derived keys match between client and server +- **Address Recovery**: Ensure signature recovery produces expected addresses + +### ERC20 Vault Integration (`erc20vault.test.ts`) +- **Vault Initialization**: Initialize vault with MPC signer address +- **Deposit Flow**: + - Request MPC signature for ERC20 transfer transaction + - Verify signature and broadcast to Sepolia + - Wait for transaction confirmation +- **Result Monitoring**: MPC server observes transaction result on Ethereum +- **Claim Flow**: + - Receive transaction output from MPC + - Verify MPC signature on result + - Claim deposited tokens in Substrate vault +- **Multi-token Support**: Vault supports any ERC20 token (decimal-agnostic) + +### Bitcoin Vault Integration (`btc-vault.test.ts`) +- **Vault Initialization**: Initialize vault with MPC signer address hash +- **UTXO Management**: Automatically discover and select UTXOs for spending +- **Deposit Flow**: + - Fund Bitcoin address derived from Substrate account + - Build PSBT (Partially Signed Bitcoin Transaction) with vault output + - Request per-input MPC signatures for each PSBT input + - Finalize and broadcast signed transaction to regtest + - Wait for confirmation +- **Result Monitoring**: MPC server observes transaction confirmation on Bitcoin +- **Claim Flow**: + - Receive transaction output from MPC + - Verify MPC signature on result + - Claim deposited sats in Substrate vault +- **Per-Input Signing**: Each UTXO input receives an individual signature with unique request ID + +## Expected Output + +### Basic Signature Test +``` +PASS ./signet.test.ts + Signet Pallet Integration + Sign + āœ“ should request and verify a signature + āœ… Signature received from: 14E5nqKAp3oAJcmzgZhUD2RcptBeUBScxKHgJKU4HPNcKVf3 + Recovered: 0xF4a62e4f48e8e71170BA758b5bAf90646db61301 + Expected: 0xf4a62e4f48e8e71170ba758b5baf90646db61301 + āœ… Signature verification PASSED + + SignRespond + āœ“ should request and verify a transaction signature + āœ… Transaction signature received from: 14E5nqKAp3oAJcmzgZhUD2RcptBeUBScxKHgJKU4HPNcKVf3 + āœ… Transaction signature verification PASSED +``` + +### ERC20 Vault Test +``` +PASS ./erc20vault.test.ts (47.902 s) + ERC20 Vault Integration + āœ“ should complete full deposit and claim flow (43924 ms) + + šŸ”‘ Derived Ethereum Address: 0xde36cd568b21c9e5b19ab6ecf01f9e5024398913 + šŸ’° Balances for 0xde36cd568b21c9e5b19ab6ecf01f9e5024398913: + ETH: 0.00999946 + USDC: 0.06 + + Initializing vault with MPC address: 0x00a40c2661293d5134e53da52951a3f7767836ef + āœ… Vault initialized + + šŸ“Š Current nonce for 0xde36cd568b21c9e5b19ab6ecf01f9e5024398913: 18 + šŸ“‹ Request ID: 0x15dc855a7fb93a3e694d5a93b9a40a2a141c7af0bbfc6afdc20d8c80ce4124f7 + šŸš€ Submitting deposit_erc20 transaction... + ā³ Waiting for MPC signature... + + āœ… Received signature from: 14E5nqKAp3oAJcmzgZhUD2RcptBeUBScxKHgJKU4HPNcKVf3 + šŸ” Signature verification: + Expected address: 0xde36cd568b21c9e5b19ab6ecf01f9e5024398913 + Recovered address: 0xDE36CD568B21C9E5B19AB6ECF01F9e5024398913 + Match: true + + šŸ“Š Fresh nonce check: 18 + šŸ“” Broadcasting transaction to Sepolia... + Tx Hash: 0xead2b6a3de9fdd90d04da5f329c5ada25060b4f0e48ebc65aa1c1c601696f974 + āœ… Transaction confirmed in block 9357487 + + ā³ Waiting for MPC to read transaction result... + āœ… Received read response + āœ… Claim transaction confirmed + āœ… Balance increased by: 0.01 USDC + Total balance: 0.04 USDC + +Test Suites: 1 passed, 1 total +Tests: 1 passed, 1 total +Time: 48.056 s +``` + +### Bitcoin Vault Test +``` +PASS ./btc-vault-perinput.test.ts (131.227 s) +BTC Vault Integration +āœ“ should complete full deposit and claim flow (125678 ms) +šŸ”‘ Derived Bitcoin Address: bcrt1qmr8q7udefh6e3mld7xpahh7g652pq3zurswrxz +šŸ’° Funding bcrt1qmr8q7udefh6e3mld7xpahh7g652pq3zurswrxz with 1 BTC... +šŸ“¦ Found 32 UTXO(s) +šŸ“Š Transaction breakdown: +Inputs: 1 +To vault: 36879590 sats +Fee: 138 sats +āœ… Deposit BTC included in block +ā³ Waiting for MPC signature(s)... +āœ… Received all 1 signature(s) from MPC +šŸ“” Broadcasting transaction to regtest... +āœ… Transaction confirmed (1 confirmations) +āœ… Balance increased by: 36879590 sats +Test Suites: 1 passed, 1 total +Tests: 1 passed, 1 total +``` + +## Configuration + +The root public key used for derivation is hardcoded in the tests. Ensure the server's `PRIVATE_KEY_TESTNET` corresponds to: + +```typescript +const ROOT_PUBLIC_KEY = "0x044eef776e4f257d68983e45b340c2e9546c5df95447900b6aadfec68fb46fdee257e26b8ba383ddba9914b33c60e869265f859566fff4baef283c54d821ca3b64"; +``` + +## Troubleshooting + +- **Timeout errors**: Ensure the signature server is running and connected to the same Substrate node +- **Address mismatch**: Verify the server's private key matches the client's expected public key +- **Transaction errors**: Check that the Signet pallet is initialized (tests handle this automatically) +- **ERC20 vault test failures**: + - Ensure your derived Ethereum address is funded with ETH and USDC on Sepolia + - Verify the MPC server has Ethereum monitoring enabled with `SEPOLIA_RPC_URL` configured + - Check that the vault's MPC address matches the server's signing key +- **Bitcoin vault test failures**: + - Ensure Bitcoin regtest is running at `http://localhost:18443` + - Verify the MPC server has `BITCOIN_NETWORK=regtest` configured + - The test automatically funds addresses and mines blocks, but ensure Docker has sufficient resources +- **InvalidSigner errors**: The output bytes from Substrate events include SCALE encoding that must be stripped before verification \ No newline at end of file diff --git a/signet-ts-client-scripts/btc-vault.test.ts b/signet-ts-client-scripts/btc-vault.test.ts new file mode 100644 index 0000000000..95f25136dd --- /dev/null +++ b/signet-ts-client-scripts/btc-vault.test.ts @@ -0,0 +1,991 @@ +import { ApiPromise, WsProvider, Keyring } from "@polkadot/api"; +import { ISubmittableResult } from "@polkadot/types/types"; +import { waitReady } from "@polkadot/wasm-crypto"; +import { u8aToHex } from "@polkadot/util"; +import { encodeAddress } from "@polkadot/keyring"; +import { ethers } from "ethers"; +import * as bitcoin from "bitcoinjs-lib"; +import Client from "bitcoin-core"; +import { SignetClient } from "./signet-client"; +import { KeyDerivation } from "./key-derivation"; +import * as ecc from "tiny-secp256k1"; +import coinSelect from "coinselect"; + +// Initialize tiny-secp256k1 with bitcoinjs-lib +bitcoin.initEccLib(ecc); + +const ROOT_PUBLIC_KEY = + "0x044eef776e4f257d68983e45b340c2e9546c5df95447900b6aadfec68fb46fdee257e26b8ba383ddba9914b33c60e869265f859566fff4baef283c54d821ca3b64"; +const CHAIN_ID = "bip122:000000000933ea01ad0ee984209779ba"; + +function normalizeSignature(r: Buffer, s: Buffer): { r: Buffer; s: Buffer } { + const N = BigInt( + "0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141" + ); + const halfN = N / 2n; + const sBigInt = BigInt("0x" + s.toString("hex")); + + if (sBigInt > halfN) { + const normalizedS = N - sBigInt; + const sBuffer = Buffer.from( + normalizedS.toString(16).padStart(64, "0"), + "hex" + ); + return { r, s: sBuffer }; + } + + return { r, s }; +} + +const TESTNET_VAULT_ADDRESS_HASH = new Uint8Array([ + 0x89, 0xf0, 0xa8, 0x23, 0x93, 0x8c, 0x58, 0xcf, 0x5b, 0x17, 0xc8, 0xeb, 0x93, + 0xc6, 0x82, 0x80, 0x63, 0x5b, 0x73, 0x4e, +]); + +function getPalletAccountId(): Uint8Array { + const palletId = new TextEncoder().encode("py/btcvt"); + const modl = new TextEncoder().encode("modl"); + const data = new Uint8Array(32); + data.set(modl, 0); + data.set(palletId, 4); + return data; +} + +async function submitWithRetry( + tx: any, + signer: any, + api: ApiPromise, + label: string, + maxRetries: number = 1, + timeoutMs: number = 60000 +): Promise<{ events: any[] }> { + let attempt = 0; + + while (attempt <= maxRetries) { + try { + console.log(`${label} - Attempt ${attempt + 1}/${maxRetries + 1}`); + + const result = await new Promise<{ events: any[] }>((resolve, reject) => { + let unsubscribe: any; + + const timer = setTimeout(() => { + if (unsubscribe) unsubscribe(); + console.log(`ā±ļø ${label} timed out after ${timeoutMs}ms`); + reject(new Error("TIMEOUT")); + }, timeoutMs); + + tx.signAndSend(signer, (result: ISubmittableResult) => { + const { status, events, dispatchError } = result; + + if (status.isInBlock) { + clearTimeout(timer); + if (unsubscribe) unsubscribe(); + + console.log( + `āœ… ${label} included in block ${status.asInBlock.toHex()}` + ); + + console.log(`šŸ“‹ All events (${events.length}):`); + for (const record of events) { + const { event } = record; + console.log(` ${event.section}.${event.method}`); + + if ( + event.section === "btcVault" && + event.method === "DebugTxid" + ) { + const palletTxid = event.data[0].toU8a(); + console.log( + `šŸ” PALLET TXID: ${Buffer.from(palletTxid).toString("hex")}` + ); + } + } + + if (dispatchError) { + if (dispatchError.isModule) { + const decoded = api.registry.findMetaError( + dispatchError.asModule + ); + reject( + new Error( + `${decoded.section}.${decoded.name}: ${decoded.docs.join( + " " + )}` + ) + ); + } else { + reject(new Error(dispatchError.toString())); + } + return; + } + + resolve({ events: Array.from(events) }); + } else if (status.isInvalid) { + clearTimeout(timer); + if (unsubscribe) unsubscribe(); + console.log(`āŒ Transaction INVALID - status:`, JSON.stringify(status.toJSON())); + reject(new Error("INVALID_TX")); + } else if (status.isDropped) { + clearTimeout(timer); + if (unsubscribe) unsubscribe(); + reject(new Error(`${label} dropped`)); + } + }) + .then((unsub: any) => { + unsubscribe = unsub; + }) + .catch((error: any) => { + clearTimeout(timer); + reject(error); + }); + }); + + return result; + } catch (error: any) { + if ( + (error.message === "INVALID_TX" || error.message === "TIMEOUT") && + attempt < maxRetries + ) { + console.log(`šŸ”„ Retrying ${label}...`); + attempt++; + await new Promise((resolve) => setTimeout(resolve, 2000)); + continue; + } + throw error; + } + } + + throw new Error(`${label} failed after ${maxRetries + 1} attempts`); +} + +describe("BTC Vault Integration", () => { + let api: ApiPromise; + let alice: any; + let signetClient: SignetClient; + let btcClient: any; + let derivedBtcAddress: string; + let derivedPubKey: string; + let network: bitcoin.Network; + + beforeAll(async () => { + await waitReady(); + + console.log("šŸ”— Connecting to Bitcoin regtest..."); + btcClient = new Client({ + host: "http://localhost:18443", + username: "test", + password: "test123", + }); + + try { + const blockCount = await btcClient.command("getblockcount"); + console.log( + `āœ… Connected to Bitcoin regtest (block height: ${blockCount})\n` + ); + } catch (error) { + throw new Error( + "āŒ Cannot connect to Bitcoin regtest. Make sure it's running:\n" + + " cd bitcoin-regtest && yarn docker:dev" + ); + } + + api = await ApiPromise.create({ + provider: new WsProvider("ws://127.0.0.1:8000"), + types: { + AffinePoint: { x: "[u8; 32]", y: "[u8; 32]" }, + Signature: { big_r: "AffinePoint", s: "[u8; 32]", recovery_id: "u8" }, + }, + }); + + const keyring = new Keyring({ type: "sr25519" }); + alice = keyring.addFromUri("//Alice"); + const bob = keyring.addFromUri("//Bob"); + + const { data: bobBalance } = (await api.query.system.account( + bob.address + )) as any; + + if (bobBalance.free.toBigInt() < 1000000000000n) { + console.log("Funding Bob's account for server responses..."); + const bobFundTx = api.tx.balances.transferKeepAlive( + bob.address, + 100000000000000n + ); + await submitWithRetry(bobFundTx, alice, api, "Fund Bob account"); + } + + const palletAccountId = getPalletAccountId(); + const palletSS58 = encodeAddress(palletAccountId, 0); + + const { data: palletBalance } = (await api.query.system.account( + palletSS58 + )) as any; + + const fundingAmount = 10000000000000n; + + if (palletBalance.free.toBigInt() < fundingAmount) { + console.log(`Funding BTC vault pallet account ${palletSS58}...`); + const fundTx = api.tx.balances.transferKeepAlive( + palletSS58, + fundingAmount + ); + await submitWithRetry(fundTx, alice, api, "Fund pallet account"); + } + + signetClient = new SignetClient(api, alice); + await signetClient.ensureInitialized(CHAIN_ID); + + const aliceAccountId = keyring.decodeAddress(alice.address); + const aliceHexPath = "0x" + u8aToHex(aliceAccountId).slice(2); + + derivedPubKey = KeyDerivation.derivePublicKey( + ROOT_PUBLIC_KEY, + palletSS58, + aliceHexPath, + "polkadot:2034" + ); + + const compressedForComparison = compressPubkey(derivedPubKey); + console.log( + `šŸ” Test expects compressed pubkey: ${compressedForComparison.toString( + "hex" + )}` + ); + + console.log(`šŸ” Test using path: ${aliceHexPath}`); + console.log(`šŸ” Test using sender: ${palletSS58}`); + console.log(`šŸ” Derived public key: ${derivedPubKey}`); + + network = bitcoin.networks.regtest; + derivedBtcAddress = btcAddressFromPubKey(derivedPubKey, network); + + console.log(`\nšŸ”‘ Derived Bitcoin Address: ${derivedBtcAddress}`); + + await fundBitcoinAddress(derivedBtcAddress); + }, 180000); + + afterAll(async () => { + if (api) { + await api.disconnect(); + } + }); + + async function fundBitcoinAddress(address: string) { + console.log(`šŸ’° Funding ${address} with 1 BTC...`); + + try { + let walletAddress; + try { + walletAddress = await btcClient.command("getnewaddress"); + } catch (e) { + try { + await btcClient.command("createwallet", "testwallet"); + walletAddress = await btcClient.command("getnewaddress"); + } catch (createErr: any) { + await btcClient.command("loadwallet", "testwallet"); + walletAddress = await btcClient.command("getnewaddress"); + } + } + + await btcClient.command("generatetoaddress", 101, walletAddress); + console.log(` Mined 101 blocks to wallet`); + + const txid = await btcClient.command("sendtoaddress", address, 1.0); + console.log(` Funding txid: ${txid}`); + + await btcClient.command("generatetoaddress", 1, walletAddress); + + const scanResult = await btcClient.command("scantxoutset", "start", [ + `addr(${derivedBtcAddress})`, + ]); + + console.log(`šŸ“¦ Found ${scanResult.unspents.length} UTXO(s)`); + + for (const utxo of scanResult.unspents) { + console.log(`\nšŸ” UTXO ${utxo.txid}:${utxo.vout}`); + console.log(` scriptPubKey: ${utxo.scriptPubKey}`); + console.log(` amount: ${utxo.amount} BTC`); + } + + if (scanResult.unspents.length === 0) { + throw new Error("No UTXOs found after funding"); + } + + console.log("āœ… Funding confirmed\n"); + } catch (error: any) { + console.error("Funding error:", error.message); + throw error; + } + } + + it("should complete full deposit and claim flow", async () => { + const mpcEthAddress = ethAddressFromPubKey(ROOT_PUBLIC_KEY); + console.log("Checking vault initialization..."); + + const existingConfig = await api.query.btcVault.vaultConfig(); + const configJson = existingConfig.toJSON(); + + if (configJson !== null) { + console.log("āš ļø Vault already initialized, skipping initialization"); + console.log(" Existing config:", existingConfig.toHuman()); + } else { + console.log("Initializing vault with MPC address hash"); + const initTx = api.tx.btcVault.initialize(Array.from(mpcEthAddress)); + await submitWithRetry(initTx, alice, api, "Initialize vault"); + } + + const scanResult = await btcClient.command("scantxoutset", "start", [ + `addr(${derivedBtcAddress})`, + ]); + + if (scanResult.unspents.length === 0) { + throw new Error("No UTXOs available for derived address"); + } + + console.log(`šŸ“¦ Found ${scanResult.unspents.length} UTXO(s)`); + + const depositAmount = 36879690; + const feeRate = 2; // satoshis per vbyte (min relay fee requires slightly more than 1) + + // Convert UTXOs to coinselect format + const utxos = scanResult.unspents.map((u: any) => ({ + txid: u.txid, + vout: u.vout, + value: Math.floor(u.amount * 100000000), + script: Buffer.from( + bitcoin.address.toOutputScript(derivedBtcAddress, network) + ), + })); + + // Vault output + const vaultScript = Buffer.concat([ + Buffer.from([0x00, 0x14]), + Buffer.from(TESTNET_VAULT_ADDRESS_HASH), + ]); + + const targets = [ + { + script: vaultScript, + value: depositAmount, + }, + ]; + + // Let coinselect pick optimal UTXOs and calculate fee + const { inputs, outputs, fee } = coinSelect(utxos, targets, feeRate); + + if (!inputs || !outputs) { + throw new Error("Insufficient funds for transaction"); + } + + console.log(`šŸ“Š Transaction breakdown:`); + console.log(` Inputs: ${inputs.length}`); + inputs.forEach((inp: any, i: number) => { + console.log( + ` Input ${i}: ${inp.value} sats (${inp.txid.slice(0, 8)}...)` + ); + }); + console.log(` To vault: ${outputs[0].value} sats`); + if (outputs.length > 1) { + console.log(` Change: ${outputs[1].value} sats`); + } + console.log(` Fee: ${fee} sats\n`); + + // Build PSBT with selected inputs/outputs + const psbt = new bitcoin.Psbt({ network }); + + for (const input of inputs) { + const txidBytes = Buffer.from(input.txid, "hex").reverse(); + psbt.addInput({ + hash: txidBytes, + index: input.vout, + sequence: 0xffffffff, + witnessUtxo: { + script: input.script!, + value: input.value, + }, + }); + } + + for (let i = 0; i < inputs.length; i++) { + psbt.updateInput(i, { + sighashType: bitcoin.Transaction.SIGHASH_ALL, + }); + } + + for (const output of outputs) { + if (output.script) { + psbt.addOutput({ + script: output.script, + value: output.value, + }); + } else { + // Change output + psbt.addOutput({ + address: derivedBtcAddress, + value: output.value, + }); + } + } + + const psbtBytes = psbt.toBuffer(); + console.log(`šŸ“ PSBT bytes length: ${psbtBytes.length}`); + + console.log(`šŸ” Test prevout txid (as sent to pallet): ${inputs[0].txid}`); + console.log( + `šŸ” Test prevout txid (reversed for PSBT): ${Buffer.from( + inputs[0].txid, + "hex" + ) + .reverse() + .toString("hex")}` + ); + + // Extract txid from PSBT + const unsignedTxBuffer = psbt.data.globalMap.unsignedTx.toBuffer(); + const unsignedTx = bitcoin.Transaction.fromBuffer(unsignedTxBuffer); + const txid = Buffer.from(unsignedTx.getId(), "hex"); + + const testUnsignedTx = bitcoin.Transaction.fromBuffer(unsignedTxBuffer); + + const getScriptCode = (witnessScript: Buffer): Buffer => { + // witnessScript is P2WPKH: 00 14 + const pubkeyHash = witnessScript.slice(2); // Skip version byte and push opcode + return bitcoin.payments.p2pkh({ hash: pubkeyHash, network }).output!; + }; + + for (let i = 0; i < inputs.length; i++) { + const scriptCode = getScriptCode(inputs[i].script!); + const testSighash = testUnsignedTx.hashForWitnessV0( + i, + scriptCode, + inputs[i].value, + bitcoin.Transaction.SIGHASH_ALL + ); + console.log(`šŸ” Test Input ${i} sighash: ${testSighash.toString("hex")}`); + } + + console.log(`šŸ”‘ Transaction ID: ${txid.toString("hex")}`); + + console.log(`šŸ” Test tx version: ${unsignedTx.version}`); + console.log(`šŸ” Test tx locktime: ${unsignedTx.locktime}`); + + const keyring = new Keyring({ type: "sr25519" }); + const palletAccountId = getPalletAccountId(); + const palletSS58 = encodeAddress(palletAccountId, 0); + const aliceAccountId = keyring.decodeAddress(alice.address); + const aliceHexPath = "0x" + u8aToHex(aliceAccountId).slice(2); + + console.log(`šŸ” Pallet SS58 (sender): ${palletSS58}`); + console.log(`šŸ” Alice hex path: ${aliceHexPath}`); + + // Calculate aggregate request ID (for monitoring) + const aggregateRequestId = signetClient.calculateSignRespondRequestId( + palletSS58, + Array.from(txid), + { + caip2Id: CHAIN_ID, + keyVersion: 0, + path: aliceHexPath, + algo: "ecdsa", + dest: "bitcoin", + params: "", + } + ); + + console.log( + `šŸ“‹ Aggregate Request ID: ${ethers.hexlify(aggregateRequestId)}` + ); + + // Generate per-input request IDs + const txidForPerInputRequestId = Buffer.from(unsignedTx.getId(), "hex"); + + // Generate per-input request IDs + const perInputRequestIds: string[] = []; + for (let i = 0; i < inputs.length; i++) { + const inputIndexBytes = Buffer.alloc(4); + inputIndexBytes.writeUInt32LE(i, 0); + // Use the display order txid reversed (internal order) to match server + const txDataForInput = Buffer.concat([ + txidForPerInputRequestId, + inputIndexBytes, + ]); + + const perInputRequestId = signetClient.calculateSignRespondRequestId( + palletSS58, + Array.from(txDataForInput), + { + caip2Id: CHAIN_ID, + keyVersion: 0, + path: aliceHexPath, + algo: "ecdsa", + dest: "bitcoin", + params: "", + } + ); + + perInputRequestIds.push(ethers.hexlify(perInputRequestId)); + console.log(`šŸ“‹ Input ${i} Request ID: ${perInputRequestIds[i]}`); + } + console.log(""); // Empty line + + // Convert to pallet format + const palletInputs = inputs.map((input: any) => ({ + txid: Array.from(Buffer.from(input.txid, "hex")), + vout: input.vout, + value: input.value, + scriptPubkey: Array.from(input.script), + sequence: 0xffffffff, + })); + + const palletOutputs = outputs.map((output: any) => { + if (output.script) { + return { + value: output.value, + scriptPubkey: Array.from(output.script), + }; + } else { + return { + value: output.value, + scriptPubkey: Array.from( + bitcoin.address.toOutputScript(derivedBtcAddress, network) + ), + }; + } + }); + + const depositTx = api.tx.btcVault.depositBtc( + Array.from(ethers.getBytes(aggregateRequestId)), + palletInputs, + palletOutputs, + 0 + ); + + console.log("šŸš€ Submitting deposit_btc transaction..."); + const depositResult = await submitWithRetry( + depositTx, + alice, + api, + "Deposit BTC" + ); + + const debugEvent = depositResult.events.find( + (record: any) => + record.event.section === "btcVault" && + record.event.method === "DebugTxid" + ); + + if (debugEvent) { + const palletTxid = debugEvent.event.data[0].toU8a(); + console.log( + `šŸ” Pallet computed txid: ${Buffer.from(palletTxid).toString("hex")}` + ); + console.log( + `šŸ” Test computed txid: ${Buffer.from(txid).toString("hex")}` + ); + console.log( + `šŸ” Match: ${ + Buffer.from(palletTxid).toString("hex") === + Buffer.from(txid).toString("hex") + }` + ); + } else { + console.log("āš ļø DebugTxid event not found"); + } + + const debugTxEvent = depositResult.events.find( + (record: any) => + record.event.section === "btcVault" && + record.event.method === "DebugTransaction" + ); + + if (debugTxEvent) { + const palletTxHex = debugTxEvent.event.data[0].toHex(); + const palletVersion = debugTxEvent.event.data[1].toNumber(); + const palletLocktime = debugTxEvent.event.data[2].toNumber(); + + console.log(`šŸ” Pallet PSBT hex: ${palletTxHex}`); + console.log( + `šŸ” Pallet version: ${palletVersion}, locktime: ${palletLocktime}` + ); + } + + const signetEvents = depositResult.events.filter( + (record: any) => + record.event.section === "signet" && + record.event.method === "SignBidirectionalRequested" + ); + + console.log( + `šŸ“Š Found ${signetEvents.length} SignBidirectionalRequested event(s)` + ); + + if (signetEvents.length > 0) { + console.log( + "āœ… SignBidirectionalRequested event emitted - MPC should pick it up!" + ); + } + + console.log("ā³ Waiting for MPC signature(s)..."); + + // Wait for each input's signature separately + const signatures: any[] = []; + for (let i = 0; i < perInputRequestIds.length; i++) { + console.log( + ` Waiting for signature ${i + 1}/${perInputRequestIds.length}...` + ); + const sig = await waitForSingleSignature( + api, + perInputRequestIds[i], + 120000 + ); + signatures.push(sig); + console.log(` āœ… Received signature ${i + 1}`); + } + + console.log( + `\nāœ… Received all ${signatures.length} signature(s) from MPC\n` + ); + + const compressedPubkey = compressPubkey(derivedPubKey); + + for (let i = 0; i < signatures.length; i++) { + const sig = signatures[i]; + + const rBuf = + typeof sig.bigR.x === "string" + ? Buffer.from(sig.bigR.x.slice(2), "hex") + : Buffer.from(sig.bigR.x); + + const sBuf = + typeof sig.s === "string" + ? Buffer.from(sig.s.slice(2), "hex") + : Buffer.from(sig.s); + + const { r: normalizedR, s: normalizedS } = normalizeSignature(rBuf, sBuf); + + console.log(`šŸ” Signature ${i} verification:`); + console.log(` R: ${normalizedR.toString("hex")}`); + console.log(` S: ${normalizedS.toString("hex")}`); + console.log(` Recovery ID: ${sig.recoveryId}`); + + // VERIFY THE SIGNATURE - use correct BIP-143 scriptCode + const scriptCode = getScriptCode(inputs[i].script!); + const testSighash = testUnsignedTx.hashForWitnessV0( + i, + scriptCode, + inputs[i].value, + bitcoin.Transaction.SIGHASH_ALL + ); + + // Verify signature is valid before broadcasting to Bitcoin + const rawSig = Buffer.concat([normalizedR, normalizedS]); + console.log(` Sighash for verify: ${testSighash.toString("hex")}`); + console.log(` Pubkey: ${compressedPubkey.toString("hex")}`); + console.log(` RawSig (64 bytes): ${rawSig.toString("hex")}`); + const isValid = ecc.verify(testSighash, compressedPubkey, rawSig); + console.log(` Signature valid (ecc.verify): ${isValid}`); + expect(isValid).toBe(true); + + const derSig = encodeDER(normalizedR, normalizedS); + const fullSig = Buffer.concat([derSig, Buffer.from([0x01])]); + + psbt.updateInput(i, { + partialSig: [ + { + pubkey: compressedPubkey, + signature: fullSig, + }, + ], + }); + } + + console.log(`šŸ” Input 0 witnessUtxo:`, psbt.data.inputs[0].witnessUtxo); + psbt.finalizeAllInputs(); + const signedTx = psbt.extractTransaction(); + console.log(`šŸ” Witness for input 0:`); + const witness = signedTx.ins[0].witness; + witness.forEach((w, idx) => { + console.log(` Witness ${idx}: ${w.toString("hex")}`); + }); + const signedTxHex = signedTx.toHex(); + + console.log(`\nšŸ” Full signed transaction hex (first 200 chars):`); + console.log(` ${signedTxHex.substring(0, 200)}...`); + console.log( + `šŸ” Transaction input 0 sequence: 0x${signedTx.ins[0].sequence.toString( + 16 + )}` + ); + + console.log(`āœ… Transaction finalized: ${signedTx.getId()}\n`); + + console.log("šŸ“” Broadcasting transaction to regtest..."); + const broadcastTxid = await btcClient.command( + "sendrawtransaction", + signedTxHex + ); + console.log(` Tx Hash: ${broadcastTxid}`); + + console.log("ā›ļø Mining block to confirm transaction..."); + await btcClient.command("generatetoaddress", 1, derivedBtcAddress); + + const txDetails = await btcClient.command( + "getrawtransaction", + broadcastTxid, + true + ); + + console.log( + `āœ… Transaction confirmed (${txDetails.confirmations} confirmations)\n` + ); + + console.log("ā³ Waiting for MPC to read transaction result..."); + const readResponse = await waitForReadResponse( + api, + ethers.hexlify(aggregateRequestId), + 120000 + ); + + if (!readResponse) { + throw new Error("āŒ Timeout waiting for read response"); + } + + console.log("āœ… Received read response\n"); + + console.log("\nšŸ” Claim Debug:"); + console.log(" Request ID:", ethers.hexlify(aggregateRequestId)); + console.log( + " Output (hex):", + Buffer.from(readResponse.output).toString("hex") + ); + + let outputBytes = new Uint8Array(readResponse.output); + if (outputBytes.length > 0) { + const mode = outputBytes[0] & 0b11; + if (mode === 0) { + outputBytes = outputBytes.slice(1); + } else if (mode === 1) { + outputBytes = outputBytes.slice(2); + } else if (mode === 2) { + outputBytes = outputBytes.slice(4); + } + } + + console.log( + " Stripped output (hex):", + Buffer.from(outputBytes).toString("hex") + ); + console.log(" Signature:", JSON.stringify(readResponse.signature)); + + // Verify the signature manually + const requestIdBytes = ethers.getBytes(aggregateRequestId); + const messageForHash = new Uint8Array(requestIdBytes.length + outputBytes.length); + messageForHash.set(requestIdBytes); + messageForHash.set(outputBytes, requestIdBytes.length); + const expectedMessageHash = ethers.keccak256(messageForHash); + console.log(" Expected message hash:", expectedMessageHash); + + // Try to recover address from signature + const sig = readResponse.signature; + // sig.bigR.x can be either a hex string or an array - handle both + const rHex = typeof sig.bigR.x === 'string' + ? sig.bigR.x + : "0x" + Buffer.from(sig.bigR.x).toString("hex"); + const sHex = typeof sig.s === 'string' + ? sig.s + : "0x" + Buffer.from(sig.s).toString("hex"); + const recoveryId = sig.recoveryId; + console.log(" Sig R:", rHex); + console.log(" Sig S:", sHex); + console.log(" Recovery ID:", recoveryId); + + try { + const ethSignature = ethers.Signature.from({ + r: rHex, + s: sHex, + v: 27 + recoveryId, + }); + const recoveredAddress = ethers.recoverAddress(expectedMessageHash, ethSignature); + console.log(" Recovered address:", recoveredAddress.toLowerCase()); + } catch (e: any) { + console.log(" Address recovery failed:", e.message); + } + + // Check vault config + const vaultConfig = await api.query.btcVault.vaultConfig(); + console.log(" Vault config:", vaultConfig.toJSON()); + + // Check if pending deposit exists + const pendingDeposit = await api.query.btcVault.pendingDeposits( + Array.from(ethers.getBytes(aggregateRequestId)) + ); + console.log(" Pending deposit exists:", !pendingDeposit.isEmpty); + if (!pendingDeposit.isEmpty) { + console.log(" Pending deposit:", pendingDeposit.toJSON()); + } + + const balanceBefore = await api.query.btcVault.userBalances(alice.address); + + const claimTx = api.tx.btcVault.claimBtc( + Array.from(ethers.getBytes(aggregateRequestId)), + Array.from(outputBytes), + readResponse.signature + ); + + // Try to do a dry run first + console.log("šŸ” Testing claim transaction (dry run)..."); + try { + const paymentInfo = await claimTx.paymentInfo(alice); + console.log(" Payment info:", paymentInfo.toJSON()); + } catch (e: any) { + console.log(" Dry run failed:", e.message); + } + + console.log("šŸš€ Submitting claim transaction..."); + await submitWithRetry(claimTx, alice, api, "Claim BTC"); + + const balanceAfter = await api.query.btcVault.userBalances(alice.address); + + const balanceIncrease = + BigInt(balanceAfter.toString()) - BigInt(balanceBefore.toString()); + + expect(balanceIncrease.toString()).toBe(depositAmount.toString()); + console.log(`āœ… Balance increased by: ${balanceIncrease} sats`); + console.log(` Total balance: ${balanceAfter} sats\n`); + }, 300000); + + function compressPubkey(pubKey: string): Buffer { + const uncompressed = Buffer.from(pubKey.slice(4), "hex"); + const fullUncompressed = Buffer.concat([Buffer.from([0x04]), uncompressed]); + const compressed = ecc.pointCompress(fullUncompressed, true); + return Buffer.from(compressed); + } + + function btcAddressFromPubKey( + pubKey: string, + network: bitcoin.Network + ): string { + const compressedPubkey = compressPubkey(pubKey); + const payment = bitcoin.payments.p2wpkh({ + pubkey: compressedPubkey, + network, + }); + return payment.address!; + } + + function ethAddressFromPubKey(pubKey: string): Uint8Array { + const uncompressedPubkey = Buffer.from(pubKey.slice(4), "hex"); + const hash = ethers.keccak256(uncompressedPubkey); + return new Uint8Array(Buffer.from(hash.slice(2), "hex").slice(-20)); + } + + function encodeDER(r: Buffer, s: Buffer): Buffer { + function toDER(x: Buffer): Buffer { + let i = 0; + while (i < x.length - 1 && x[i] === 0 && x[i + 1] < 0x80) i++; + + const xDER = x.slice(i); + + if (xDER[0] >= 0x80) { + return Buffer.concat([Buffer.from([0x00]), xDER]); + } + + return xDER; + } + + const rDER = toDER(r); + const sDER = toDER(s); + + const len = 2 + rDER.length + 2 + sDER.length; + const buf = Buffer.allocUnsafe(2 + len); + + buf[0] = 0x30; + buf[1] = len; + buf[2] = 0x02; + buf[3] = rDER.length; + rDER.copy(buf, 4); + buf[4 + rDER.length] = 0x02; + buf[5 + rDER.length] = sDER.length; + sDER.copy(buf, 6 + rDER.length); + + return buf; + } + + async function waitForSingleSignature( + api: ApiPromise, + requestId: string, + timeout: number + ): Promise { + return new Promise((resolve, reject) => { + let unsubscribe: any; + const timer = setTimeout(() => { + if (unsubscribe) unsubscribe(); + reject( + new Error( + `Timeout waiting for signature with request ID ${requestId}` + ) + ); + }, timeout); + + api.query.system + .events((events: any) => { + events.forEach((record: any) => { + const { event } = record; + if ( + event.section === "signet" && + event.method === "SignatureResponded" + ) { + const [reqId, responder, signature] = event.data; + if (ethers.hexlify(reqId.toU8a()) === requestId) { + clearTimeout(timer); + if (unsubscribe) unsubscribe(); + resolve(signature.toJSON()); + } + } + }); + }) + .then((unsub: any) => { + unsubscribe = unsub; + }); + }); + } + + async function waitForReadResponse( + api: ApiPromise, + requestId: string, + timeout: number + ): Promise { + return new Promise((resolve) => { + let unsubscribe: any; + const timer = setTimeout(() => { + if (unsubscribe) unsubscribe(); + resolve(null); + }, timeout); + + api.query.system + .events((events: any) => { + events.forEach((record: any) => { + const { event } = record; + if ( + event.section === "signet" && + event.method === "RespondBidirectionalEvent" + ) { + const [reqId, responder, output, signature] = event.data; + if (ethers.hexlify(reqId.toU8a()) === requestId) { + clearTimeout(timer); + if (unsubscribe) unsubscribe(); + resolve({ + responder: responder.toString(), + output: Array.from(output.toU8a()), + signature: signature.toJSON(), + }); + } + } + }); + }) + .then((unsub: any) => { + unsubscribe = unsub; + }); + }); + } +}); diff --git a/signet-ts-client-scripts/coinselect.d.ts b/signet-ts-client-scripts/coinselect.d.ts new file mode 100644 index 0000000000..8c421164b7 --- /dev/null +++ b/signet-ts-client-scripts/coinselect.d.ts @@ -0,0 +1,28 @@ +declare module 'coinselect' { + export interface UTXO { + txid: string; + vout: number; + value: number; + script?: Buffer; + } + + export interface Target { + address?: string; + script?: Buffer; + value: number; + } + + export interface CoinSelectResult { + inputs: UTXO[] | undefined; + outputs: Array<{ address?: string; script?: Buffer; value: number }> | undefined; + fee: number; + } + + function coinSelect( + utxos: UTXO[], + targets: Target[], + feeRate: number + ): CoinSelectResult; + + export default coinSelect; +} \ No newline at end of file diff --git a/signet-ts-client-scripts/key-derivation.ts b/signet-ts-client-scripts/key-derivation.ts new file mode 100644 index 0000000000..3ef2d1e371 --- /dev/null +++ b/signet-ts-client-scripts/key-derivation.ts @@ -0,0 +1,30 @@ +import { ethers } from "ethers"; +import { ec as EC } from "elliptic"; + +export class KeyDerivation { + private static readonly EPSILON_PREFIX = "sig.network v1.0.0 epsilon derivation"; + + static derivePublicKey( + rootPublicKey: string, + predecessorId: string, + path: string, + chainId: string + ): string { + const ec = new EC("secp256k1"); + + const uncompressedRoot = rootPublicKey.slice(4); + + const derivationPath = `${this.EPSILON_PREFIX},${chainId},${predecessorId},${path}`; + const hash = ethers.keccak256(ethers.toUtf8Bytes(derivationPath)); + const scalarHex = hash.slice(2); + + const x = uncompressedRoot.substring(0, 64); + const y = uncompressedRoot.substring(64); + + const oldPoint = ec.curve.point(x, y); + const scalarTimesG = ec.g.mul(scalarHex); + const newPoint = oldPoint.add(scalarTimesG); + + return `0x04${newPoint.getX().toString(16).padStart(64, "0")}${newPoint.getY().toString(16).padStart(64, "0")}`; + } +} \ No newline at end of file diff --git a/signet-ts-client-scripts/package.json b/signet-ts-client-scripts/package.json new file mode 100644 index 0000000000..d46b625b76 --- /dev/null +++ b/signet-ts-client-scripts/package.json @@ -0,0 +1,39 @@ +{ + "name": "hydration-signet-interaction", + "version": "1.0.0", + "description": "TypeScript client for Signet pallet interaction", + "main": "emit-event.ts", + "scripts": { + "test": "jest", + "test:watch": "jest --watch" + }, + "jest": { + "preset": "ts-jest", + "testEnvironment": "node", + "testMatch": [ + "**/*.test.ts" + ] + }, + "dependencies": { + "@polkadot/api": "^11.2.1", + "@polkadot/keyring": "^12.6.2", + "@polkadot/util": "^12.6.2", + "bitcoin-regtest": "^1.0.1", + "bitcoinjs-lib": "^6.1.6", + "coinselect": "^3.1.13", + "elliptic": "^6.6.1", + "ethers": "^6.15.0", + "tiny-secp256k1": "^2.2.4", + "ts-node": "^10.9.2", + "typescript": "^5.3.3", + "viem": "^2.37.6" + }, + "devDependencies": { + "@types/elliptic": "^6.4.18", + "@types/jest": "^30.0.0", + "@types/mocha": "^10.0.10", + "@types/node": "^20.11.5", + "jest": "^30.1.3", + "ts-jest": "^29.4.4" + } +} diff --git a/signet-ts-client-scripts/signet-client.ts b/signet-ts-client-scripts/signet-client.ts new file mode 100644 index 0000000000..0084248d3a --- /dev/null +++ b/signet-ts-client-scripts/signet-client.ts @@ -0,0 +1,247 @@ +import { ApiPromise } from "@polkadot/api"; +import { EventRecord } from "@polkadot/types/interfaces"; +import { Vec } from "@polkadot/types"; +import { u8aToHex } from "@polkadot/util"; +import { ISubmittableResult } from "@polkadot/types/types"; +import { ethers } from "ethers"; +import { keccak256, recoverAddress } from "viem"; + +export class SignetClient { + constructor(private api: ApiPromise, private signer: any) {} + + async ensureInitialized(chainId: string): Promise { + // Use direct RPC call to chopsticks + const rpcCall = async (method: string, params: any[]) => { + const response = await fetch("http://127.0.0.1:8000", { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ + jsonrpc: "2.0", + id: 1, + method, + params, + }), + }); + return response.json(); + }; + + // Always set storage to ensure ChainId is correct + console.log(" Setting Signet storage via dev_setStorage..."); + + // ChainId is a BoundedVec which needs SCALE encoding with length prefix + const chainIdBytes = Buffer.from(chainId); + const lengthPrefix = chainIdBytes.length << 2; // SCALE compact encoding for small lengths + const scaledEncodedChainId = "0x" + Buffer.from([lengthPrefix, ...chainIdBytes]).toString("hex"); + + console.log(" ChainId SCALE encoded:", scaledEncodedChainId); + + await rpcCall("dev_setStorage", [{ + Signet: { + Admin: this.signer.address, + SignatureDeposit: 1000000000000, + ChainId: scaledEncodedChainId, + } + }]); + + // Build a new block to apply storage changes + await rpcCall("dev_newBlock", []); + + console.log(" Signet storage set! ChainId:", chainId); + } + + async requestSignature(payload: Uint8Array, params: any): Promise { + const tx = this.api.tx.signet.sign( + Array.from(payload), + params.keyVersion, + params.path, + params.algo, + params.dest, + params.params + ); + + await new Promise((resolve, reject) => { + tx.signAndSend(this.signer, (result: ISubmittableResult) => { + const { status, dispatchError } = result; + if (dispatchError) { + reject(dispatchError); + } else if (status.isInBlock) { + resolve(); + } + }).catch(reject); + }); + } + + async requestTransactionSignature( + serializedTx: number[], + params: any + ): Promise { + const caip2Id = params.caip2Id; + const caip2Bytes = Array.from(new TextEncoder().encode(caip2Id)); + + const tx = this.api.tx.signet.signBidirectional( + serializedTx, + caip2Bytes, + params.keyVersion, + params.path, + params.algo || "", + params.dest || "", + params.params || "", + Array.from(new TextEncoder().encode(params.schemas.explorer.schema)), + Array.from(new TextEncoder().encode(params.schemas.callback.schema)) + ); + + await tx.signAndSend(this.signer); + } + + async waitForSignature(requestId: string, timeout: number): Promise { + return new Promise((resolve) => { + let unsubscribe: any; + const timer = setTimeout(() => { + if (unsubscribe) unsubscribe(); + resolve(null); + }, timeout); + + this.api.query.system + .events((events: Vec) => { + events.forEach((record: EventRecord) => { + const { event } = record; + if ( + event.section === "signet" && + event.method === "SignatureResponded" + ) { + const [reqId, responder, signature] = event.data as any; + if (u8aToHex(reqId.toU8a()) === requestId) { + clearTimeout(timer); + if (unsubscribe) unsubscribe(); + resolve({ + responder: responder.toString(), + signature: signature.toJSON(), + }); + } + } + }); + }) + .then((unsub: any) => { + unsubscribe = unsub; + }); + }); + } + + calculateRequestId( + sender: string, + payload: Uint8Array, + params: any, + chainId: string + ): string { + const payloadHex = "0x" + Buffer.from(payload).toString("hex"); + const encoded = ethers.AbiCoder.defaultAbiCoder().encode( + [ + "string", + "bytes", + "string", + "uint32", + "string", + "string", + "string", + "string", + ], + [ + sender, + payloadHex, + params.path, + params.keyVersion, + chainId, + params.algo, + params.dest, + params.params, + ] + ); + return ethers.keccak256(encoded); + } + + calculateSignRespondRequestId( + sender: string, + txData: number[], + params: any + ): string { + const txHex = "0x" + Buffer.from(txData).toString("hex"); + const caip2Id = params.caip2Id; + + const encoded = ethers.solidityPacked( + [ + "string", + "bytes", + "string", + "uint32", + "string", + "string", + "string", + "string", + ], + [ + sender, + txHex, + caip2Id, + params.keyVersion, + params.path, + params.algo || "", + params.dest || "", + params.params || "", + ] + ); + return ethers.keccak256(encoded); + } + + async verifySignature( + payload: Uint8Array, + signature: any, + derivedPublicKey: string + ): Promise { + const r = signature.bigR.x.startsWith("0x") + ? signature.bigR.x + : `0x${signature.bigR.x}`; + const s = signature.s.startsWith("0x") ? signature.s : `0x${signature.s}`; + const v = BigInt(signature.recoveryId + 27); + + const recoveredAddress = await recoverAddress({ + hash: payload as any, + signature: { r, s, v }, + }); + + const expectedAddress = + "0x" + + keccak256(Buffer.from(derivedPublicKey.slice(4), "hex")).slice(-40); + + console.log(" Recovered:", recoveredAddress); + console.log(" Expected: ", expectedAddress); + + return recoveredAddress.toLowerCase() === expectedAddress.toLowerCase(); + } + + async verifyTransactionSignature( + tx: ethers.Transaction, + signature: any, + derivedPublicKey: string + ): Promise { + const msgHash = ethers.keccak256(tx.unsignedSerialized); + const r = signature.bigR.x.startsWith("0x") + ? signature.bigR.x + : `0x${signature.bigR.x}`; + const s = signature.s.startsWith("0x") ? signature.s : `0x${signature.s}`; + const v = BigInt(signature.recoveryId + 27); + + const recoveredAddress = await recoverAddress({ + hash: msgHash as `0x${string}`, + signature: { r, s, v } as any, + }); + + const expectedAddress = + "0x" + + keccak256(Buffer.from(derivedPublicKey.slice(4), "hex")).slice(-40); + + console.log(" Recovered:", recoveredAddress); + console.log(" Expected: ", expectedAddress); + + return recoveredAddress.toLowerCase() === expectedAddress.toLowerCase(); + } +} diff --git a/signet-ts-client-scripts/transaction-builder.ts b/signet-ts-client-scripts/transaction-builder.ts new file mode 100644 index 0000000000..478c9d9f45 --- /dev/null +++ b/signet-ts-client-scripts/transaction-builder.ts @@ -0,0 +1,28 @@ +import { ethers } from "ethers"; + +export class TransactionBuilder { + static buildEIP1559(params: { + chainId: number; + nonce: number; + maxPriorityFeePerGas: bigint; + maxFeePerGas: bigint; + gasLimit: number; + to: string; + value: bigint; + data: string; + accessList: any[]; + }): { transaction: ethers.Transaction; serialized: number[]; unwrapped: number[] } { + const transaction = ethers.Transaction.from({ + type: 2, + ...params + }); + + const fullSerialized = Array.from(ethers.getBytes(transaction.unsignedSerialized)); + + return { + transaction, + serialized: fullSerialized, + unwrapped: fullSerialized.slice(1) + }; + } +} \ No newline at end of file diff --git a/signet-ts-client-scripts/tsconfig.json b/signet-ts-client-scripts/tsconfig.json new file mode 100644 index 0000000000..5e71b205bf --- /dev/null +++ b/signet-ts-client-scripts/tsconfig.json @@ -0,0 +1,15 @@ +{ + "compilerOptions": { + "target": "ES2020", + "module": "commonjs", + "lib": ["ES2020"], + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true, + "resolveJsonModule": true, + "types": ["jest", "node"] + }, + "include": ["**/*.ts"], + "exclude": ["node_modules"] +} \ No newline at end of file diff --git a/signet-ts-client-scripts/yarn.lock b/signet-ts-client-scripts/yarn.lock new file mode 100644 index 0000000000..aab6414af4 --- /dev/null +++ b/signet-ts-client-scripts/yarn.lock @@ -0,0 +1,3776 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@adraffy/ens-normalize@1.10.1": + version "1.10.1" + resolved "https://registry.yarnpkg.com/@adraffy/ens-normalize/-/ens-normalize-1.10.1.tgz#63430d04bd8c5e74f8d7d049338f1cd9d4f02069" + integrity sha512-96Z2IP3mYmF1Xg2cDm8f1gWGf/HUVedQ3FMifV4kG/PQ4yEP51xDtRAEfhVNt5f/uzpNkZHwWQuUcu6D6K+Ekw== + +"@adraffy/ens-normalize@^1.11.0": + version "1.11.0" + resolved "https://registry.yarnpkg.com/@adraffy/ens-normalize/-/ens-normalize-1.11.0.tgz#42cc67c5baa407ac25059fcd7d405cc5ecdb0c33" + integrity sha512-/3DDPKHqqIqxUULp8yP4zODUY1i+2xvVWsv8A79xGWdCAG+8sb0hRh0Rk2QyOJUnnbyPUAZYcpBuRe3nS2OIUg== + +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.27.1.tgz#200f715e66d52a23b221a9435534a91cc13ad5be" + integrity sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg== + dependencies: + "@babel/helper-validator-identifier" "^7.27.1" + js-tokens "^4.0.0" + picocolors "^1.1.1" + +"@babel/compat-data@^7.27.2": + version "7.28.4" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.28.4.tgz#96fdf1af1b8859c8474ab39c295312bfb7c24b04" + integrity sha512-YsmSKC29MJwf0gF8Rjjrg5LQCmyh+j/nD8/eP7f+BeoQTKYqs9RoWbjGOdy0+1Ekr68RJZMUOPVQaQisnIo4Rw== + +"@babel/core@^7.23.9", "@babel/core@^7.27.4": + version "7.28.4" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.28.4.tgz#12a550b8794452df4c8b084f95003bce1742d496" + integrity sha512-2BCOP7TN8M+gVDj7/ht3hsaO/B/n5oDbiAyyvnRlNOs+u1o+JWNYTQrmpuNp1/Wq2gcFrI01JAW+paEKDMx/CA== + dependencies: + "@babel/code-frame" "^7.27.1" + "@babel/generator" "^7.28.3" + "@babel/helper-compilation-targets" "^7.27.2" + "@babel/helper-module-transforms" "^7.28.3" + "@babel/helpers" "^7.28.4" + "@babel/parser" "^7.28.4" + "@babel/template" "^7.27.2" + "@babel/traverse" "^7.28.4" + "@babel/types" "^7.28.4" + "@jridgewell/remapping" "^2.3.5" + convert-source-map "^2.0.0" + debug "^4.1.0" + gensync "^1.0.0-beta.2" + json5 "^2.2.3" + semver "^6.3.1" + +"@babel/generator@^7.27.5", "@babel/generator@^7.28.3": + version "7.28.3" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.28.3.tgz#9626c1741c650cbac39121694a0f2d7451b8ef3e" + integrity sha512-3lSpxGgvnmZznmBkCRnVREPUFJv2wrv9iAoFDvADJc0ypmdOxdUtcLeBgBJ6zE0PMeTKnxeQzyk0xTBq4Ep7zw== + dependencies: + "@babel/parser" "^7.28.3" + "@babel/types" "^7.28.2" + "@jridgewell/gen-mapping" "^0.3.12" + "@jridgewell/trace-mapping" "^0.3.28" + jsesc "^3.0.2" + +"@babel/helper-compilation-targets@^7.27.2": + version "7.27.2" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz#46a0f6efab808d51d29ce96858dd10ce8732733d" + integrity sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ== + dependencies: + "@babel/compat-data" "^7.27.2" + "@babel/helper-validator-option" "^7.27.1" + browserslist "^4.24.0" + lru-cache "^5.1.1" + semver "^6.3.1" + +"@babel/helper-globals@^7.28.0": + version "7.28.0" + resolved "https://registry.yarnpkg.com/@babel/helper-globals/-/helper-globals-7.28.0.tgz#b9430df2aa4e17bc28665eadeae8aa1d985e6674" + integrity sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw== + +"@babel/helper-module-imports@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz#7ef769a323e2655e126673bb6d2d6913bbead204" + integrity sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w== + dependencies: + "@babel/traverse" "^7.27.1" + "@babel/types" "^7.27.1" + +"@babel/helper-module-transforms@^7.28.3": + version "7.28.3" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.28.3.tgz#a2b37d3da3b2344fe085dab234426f2b9a2fa5f6" + integrity sha512-gytXUbs8k2sXS9PnQptz5o0QnpLL51SwASIORY6XaBKF88nsOT0Zw9szLqlSGQDP/4TljBAD5y98p2U1fqkdsw== + dependencies: + "@babel/helper-module-imports" "^7.27.1" + "@babel/helper-validator-identifier" "^7.27.1" + "@babel/traverse" "^7.28.3" + +"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.27.1", "@babel/helper-plugin-utils@^7.8.0": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.27.1.tgz#ddb2f876534ff8013e6c2b299bf4d39b3c51d44c" + integrity sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw== + +"@babel/helper-string-parser@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz#54da796097ab19ce67ed9f88b47bb2ec49367687" + integrity sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA== + +"@babel/helper-validator-identifier@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz#a7054dcc145a967dd4dc8fee845a57c1316c9df8" + integrity sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow== + +"@babel/helper-validator-option@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz#fa52f5b1e7db1ab049445b421c4471303897702f" + integrity sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg== + +"@babel/helpers@^7.28.4": + version "7.28.4" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.28.4.tgz#fe07274742e95bdf7cf1443593eeb8926ab63827" + integrity sha512-HFN59MmQXGHVyYadKLVumYsA9dBFun/ldYxipEjzA4196jpLZd8UjEEBLkbEkvfYreDqJhZxYAWFPtrfhNpj4w== + dependencies: + "@babel/template" "^7.27.2" + "@babel/types" "^7.28.4" + +"@babel/parser@^7.1.0", "@babel/parser@^7.20.7", "@babel/parser@^7.23.9", "@babel/parser@^7.27.2", "@babel/parser@^7.28.3", "@babel/parser@^7.28.4": + version "7.28.4" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.28.4.tgz#da25d4643532890932cc03f7705fe19637e03fa8" + integrity sha512-yZbBqeM6TkpP9du/I2pUZnJsRMGGvOuIrhjzC1AwHwW+6he4mni6Bp/m8ijn0iOuZuPI2BfkCoSRunpyjnrQKg== + dependencies: + "@babel/types" "^7.28.4" + +"@babel/plugin-syntax-async-generators@^7.8.4": + version "7.8.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz#a983fb1aeb2ec3f6ed042a210f640e90e786fe0d" + integrity sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-bigint@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz#4c9a6f669f5d0cdf1b90a1671e9a146be5300cea" + integrity sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-class-properties@^7.12.13": + version "7.12.13" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz#b5c987274c4a3a82b89714796931a6b53544ae10" + integrity sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA== + dependencies: + "@babel/helper-plugin-utils" "^7.12.13" + +"@babel/plugin-syntax-class-static-block@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz#195df89b146b4b78b3bf897fd7a257c84659d406" + integrity sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw== + dependencies: + "@babel/helper-plugin-utils" "^7.14.5" + +"@babel/plugin-syntax-import-attributes@^7.24.7": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.27.1.tgz#34c017d54496f9b11b61474e7ea3dfd5563ffe07" + integrity sha512-oFT0FrKHgF53f4vOsZGi2Hh3I35PfSmVs4IBFLFj4dnafP+hIWDLg3VyKmUHfLoLHlyxY4C7DGtmHuJgn+IGww== + dependencies: + "@babel/helper-plugin-utils" "^7.27.1" + +"@babel/plugin-syntax-import-meta@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz#ee601348c370fa334d2207be158777496521fd51" + integrity sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-syntax-json-strings@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz#01ca21b668cd8218c9e640cb6dd88c5412b2c96a" + integrity sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-jsx@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.27.1.tgz#2f9beb5eff30fa507c5532d107daac7b888fa34c" + integrity sha512-y8YTNIeKoyhGd9O0Jiyzyyqk8gdjnumGTQPsz0xOZOQ2RmkVJeZ1vmmfIvFEKqucBG6axJGBZDE/7iI5suUI/w== + dependencies: + "@babel/helper-plugin-utils" "^7.27.1" + +"@babel/plugin-syntax-logical-assignment-operators@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz#ca91ef46303530448b906652bac2e9fe9941f699" + integrity sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-syntax-nullish-coalescing-operator@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz#167ed70368886081f74b5c36c65a88c03b66d1a9" + integrity sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-numeric-separator@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz#b9b070b3e33570cd9fd07ba7fa91c0dd37b9af97" + integrity sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-syntax-object-rest-spread@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz#60e225edcbd98a640332a2e72dd3e66f1af55871" + integrity sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-optional-catch-binding@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz#6111a265bcfb020eb9efd0fdfd7d26402b9ed6c1" + integrity sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-optional-chaining@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz#4f69c2ab95167e0180cd5336613f8c5788f7d48a" + integrity sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-private-property-in-object@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz#0dc6671ec0ea22b6e94a1114f857970cd39de1ad" + integrity sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg== + dependencies: + "@babel/helper-plugin-utils" "^7.14.5" + +"@babel/plugin-syntax-top-level-await@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz#c1cfdadc35a646240001f06138247b741c34d94c" + integrity sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw== + dependencies: + "@babel/helper-plugin-utils" "^7.14.5" + +"@babel/plugin-syntax-typescript@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.27.1.tgz#5147d29066a793450f220c63fa3a9431b7e6dd18" + integrity sha512-xfYCBMxveHrRMnAWl1ZlPXOZjzkN82THFvLhQhFXFt81Z5HnN+EtUkZhv/zcKpmT3fzmWZB0ywiBrbC3vogbwQ== + dependencies: + "@babel/helper-plugin-utils" "^7.27.1" + +"@babel/template@^7.27.2": + version "7.27.2" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.27.2.tgz#fa78ceed3c4e7b63ebf6cb39e5852fca45f6809d" + integrity sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw== + dependencies: + "@babel/code-frame" "^7.27.1" + "@babel/parser" "^7.27.2" + "@babel/types" "^7.27.1" + +"@babel/traverse@^7.27.1", "@babel/traverse@^7.28.3", "@babel/traverse@^7.28.4": + version "7.28.4" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.28.4.tgz#8d456101b96ab175d487249f60680221692b958b" + integrity sha512-YEzuboP2qvQavAcjgQNVgsvHIDv6ZpwXvcvjmyySP2DIMuByS/6ioU5G9pYrWHM6T2YDfc7xga9iNzYOs12CFQ== + dependencies: + "@babel/code-frame" "^7.27.1" + "@babel/generator" "^7.28.3" + "@babel/helper-globals" "^7.28.0" + "@babel/parser" "^7.28.4" + "@babel/template" "^7.27.2" + "@babel/types" "^7.28.4" + debug "^4.3.1" + +"@babel/types@^7.0.0", "@babel/types@^7.20.7", "@babel/types@^7.27.1", "@babel/types@^7.27.3", "@babel/types@^7.28.2", "@babel/types@^7.28.4": + version "7.28.4" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.28.4.tgz#0a4e618f4c60a7cd6c11cb2d48060e4dbe38ac3a" + integrity sha512-bkFqkLhh3pMBUQQkpVgWDWq/lqzc2678eUyDlTBhRqhCHFguYYGM0Efga7tYk4TogG/3x0EEl66/OQ+WGbWB/Q== + dependencies: + "@babel/helper-string-parser" "^7.27.1" + "@babel/helper-validator-identifier" "^7.27.1" + +"@bcoe/v8-coverage@^0.2.3": + version "0.2.3" + resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" + integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== + +"@cspotcode/source-map-support@^0.8.0": + version "0.8.1" + resolved "https://registry.yarnpkg.com/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz#00629c35a688e05a88b1cda684fb9d5e73f000a1" + integrity sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw== + dependencies: + "@jridgewell/trace-mapping" "0.3.9" + +"@emnapi/core@^1.4.3": + version "1.5.0" + resolved "https://registry.yarnpkg.com/@emnapi/core/-/core-1.5.0.tgz#85cd84537ec989cebb2343606a1ee663ce4edaf0" + integrity sha512-sbP8GzB1WDzacS8fgNPpHlp6C9VZe+SJP3F90W9rLemaQj2PzIuTEl1qDOYQf58YIpyjViI24y9aPWCjEzY2cg== + dependencies: + "@emnapi/wasi-threads" "1.1.0" + tslib "^2.4.0" + +"@emnapi/runtime@^1.4.3": + version "1.5.0" + resolved "https://registry.yarnpkg.com/@emnapi/runtime/-/runtime-1.5.0.tgz#9aebfcb9b17195dce3ab53c86787a6b7d058db73" + integrity sha512-97/BJ3iXHww3djw6hYIfErCZFee7qCtrneuLa20UXFCOTCfBM2cvQHjWJ2EG0s0MtdNwInarqCTz35i4wWXHsQ== + dependencies: + tslib "^2.4.0" + +"@emnapi/wasi-threads@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@emnapi/wasi-threads/-/wasi-threads-1.1.0.tgz#60b2102fddc9ccb78607e4a3cf8403ea69be41bf" + integrity sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ== + dependencies: + tslib "^2.4.0" + +"@isaacs/cliui@^8.0.2": + version "8.0.2" + resolved "https://registry.yarnpkg.com/@isaacs/cliui/-/cliui-8.0.2.tgz#b37667b7bc181c168782259bab42474fbf52b550" + integrity sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA== + dependencies: + string-width "^5.1.2" + string-width-cjs "npm:string-width@^4.2.0" + strip-ansi "^7.0.1" + strip-ansi-cjs "npm:strip-ansi@^6.0.1" + wrap-ansi "^8.1.0" + wrap-ansi-cjs "npm:wrap-ansi@^7.0.0" + +"@istanbuljs/load-nyc-config@^1.0.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz#fd3db1d59ecf7cf121e80650bb86712f9b55eced" + integrity sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ== + dependencies: + camelcase "^5.3.1" + find-up "^4.1.0" + get-package-type "^0.1.0" + js-yaml "^3.13.1" + resolve-from "^5.0.0" + +"@istanbuljs/schema@^0.1.2", "@istanbuljs/schema@^0.1.3": + version "0.1.3" + resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.3.tgz#e45e384e4b8ec16bce2fd903af78450f6bf7ec98" + integrity sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA== + +"@jest/console@30.1.2": + version "30.1.2" + resolved "https://registry.yarnpkg.com/@jest/console/-/console-30.1.2.tgz#3d32b966454d57874520b27647129228a654c995" + integrity sha512-BGMAxj8VRmoD0MoA/jo9alMXSRoqW8KPeqOfEo1ncxnRLatTBCpRoOwlwlEMdudp68Q6WSGwYrrLtTGOh8fLzw== + dependencies: + "@jest/types" "30.0.5" + "@types/node" "*" + chalk "^4.1.2" + jest-message-util "30.1.0" + jest-util "30.0.5" + slash "^3.0.0" + +"@jest/core@30.1.3": + version "30.1.3" + resolved "https://registry.yarnpkg.com/@jest/core/-/core-30.1.3.tgz#c097dcead36ac6ccee2825a35078163465f8b79d" + integrity sha512-LIQz7NEDDO1+eyOA2ZmkiAyYvZuo6s1UxD/e2IHldR6D7UYogVq3arTmli07MkENLq6/3JEQjp0mA8rrHHJ8KQ== + dependencies: + "@jest/console" "30.1.2" + "@jest/pattern" "30.0.1" + "@jest/reporters" "30.1.3" + "@jest/test-result" "30.1.3" + "@jest/transform" "30.1.2" + "@jest/types" "30.0.5" + "@types/node" "*" + ansi-escapes "^4.3.2" + chalk "^4.1.2" + ci-info "^4.2.0" + exit-x "^0.2.2" + graceful-fs "^4.2.11" + jest-changed-files "30.0.5" + jest-config "30.1.3" + jest-haste-map "30.1.0" + jest-message-util "30.1.0" + jest-regex-util "30.0.1" + jest-resolve "30.1.3" + jest-resolve-dependencies "30.1.3" + jest-runner "30.1.3" + jest-runtime "30.1.3" + jest-snapshot "30.1.2" + jest-util "30.0.5" + jest-validate "30.1.0" + jest-watcher "30.1.3" + micromatch "^4.0.8" + pretty-format "30.0.5" + slash "^3.0.0" + +"@jest/diff-sequences@30.0.1": + version "30.0.1" + resolved "https://registry.yarnpkg.com/@jest/diff-sequences/-/diff-sequences-30.0.1.tgz#0ededeae4d071f5c8ffe3678d15f3a1be09156be" + integrity sha512-n5H8QLDJ47QqbCNn5SuFjCRDrOLEZ0h8vAHCK5RL9Ls7Xa8AQLa/YxAc9UjFqoEDM48muwtBGjtMY5cr0PLDCw== + +"@jest/environment@30.1.2": + version "30.1.2" + resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-30.1.2.tgz#f1bd73a7571f96104a3ff2007747c2ce12b5c038" + integrity sha512-N8t1Ytw4/mr9uN28OnVf0SYE2dGhaIxOVYcwsf9IInBKjvofAjbFRvedvBBlyTYk2knbJTiEjEJ2PyyDIBnd9w== + dependencies: + "@jest/fake-timers" "30.1.2" + "@jest/types" "30.0.5" + "@types/node" "*" + jest-mock "30.0.5" + +"@jest/expect-utils@30.1.2": + version "30.1.2" + resolved "https://registry.yarnpkg.com/@jest/expect-utils/-/expect-utils-30.1.2.tgz#88ea18040f707c9fadb6fd9e77568cae5266cee8" + integrity sha512-HXy1qT/bfdjCv7iC336ExbqqYtZvljrV8odNdso7dWK9bSeHtLlvwWWC3YSybSPL03Gg5rug6WLCZAZFH72m0A== + dependencies: + "@jest/get-type" "30.1.0" + +"@jest/expect@30.1.2": + version "30.1.2" + resolved "https://registry.yarnpkg.com/@jest/expect/-/expect-30.1.2.tgz#35283e8bd083aab6cc26d4d30aeeacb5e7190a0f" + integrity sha512-tyaIExOwQRCxPCGNC05lIjWJztDwk2gPDNSDGg1zitXJJ8dC3++G/CRjE5mb2wQsf89+lsgAgqxxNpDLiCViTA== + dependencies: + expect "30.1.2" + jest-snapshot "30.1.2" + +"@jest/fake-timers@30.1.2": + version "30.1.2" + resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-30.1.2.tgz#cb0df6995034d50c6973ffd3ffdaa1353a816c41" + integrity sha512-Beljfv9AYkr9K+ETX9tvV61rJTY706BhBUtiaepQHeEGfe0DbpvUA5Z3fomwc5Xkhns6NWrcFDZn+72fLieUnA== + dependencies: + "@jest/types" "30.0.5" + "@sinonjs/fake-timers" "^13.0.0" + "@types/node" "*" + jest-message-util "30.1.0" + jest-mock "30.0.5" + jest-util "30.0.5" + +"@jest/get-type@30.1.0": + version "30.1.0" + resolved "https://registry.yarnpkg.com/@jest/get-type/-/get-type-30.1.0.tgz#4fcb4dc2ebcf0811be1c04fd1cb79c2dba431cbc" + integrity sha512-eMbZE2hUnx1WV0pmURZY9XoXPkUYjpc55mb0CrhtdWLtzMQPFvu/rZkTLZFTsdaVQa+Tr4eWAteqcUzoawq/uA== + +"@jest/globals@30.1.2": + version "30.1.2" + resolved "https://registry.yarnpkg.com/@jest/globals/-/globals-30.1.2.tgz#821cad7d8ef3dc145979088bb0bfbc1f81a5d8ce" + integrity sha512-teNTPZ8yZe3ahbYnvnVRDeOjr+3pu2uiAtNtrEsiMjVPPj+cXd5E/fr8BL7v/T7F31vYdEHrI5cC/2OoO/vM9A== + dependencies: + "@jest/environment" "30.1.2" + "@jest/expect" "30.1.2" + "@jest/types" "30.0.5" + jest-mock "30.0.5" + +"@jest/pattern@30.0.1": + version "30.0.1" + resolved "https://registry.yarnpkg.com/@jest/pattern/-/pattern-30.0.1.tgz#d5304147f49a052900b4b853dedb111d080e199f" + integrity sha512-gWp7NfQW27LaBQz3TITS8L7ZCQ0TLvtmI//4OwlQRx4rnWxcPNIYjxZpDcN4+UlGxgm3jS5QPz8IPTCkb59wZA== + dependencies: + "@types/node" "*" + jest-regex-util "30.0.1" + +"@jest/reporters@30.1.3": + version "30.1.3" + resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-30.1.3.tgz#015b5838b3edf60f6e995186cd805b7fcbac86b3" + integrity sha512-VWEQmJWfXMOrzdFEOyGjUEOuVXllgZsoPtEHZzfdNz18RmzJ5nlR6kp8hDdY8dDS1yGOXAY7DHT+AOHIPSBV0w== + dependencies: + "@bcoe/v8-coverage" "^0.2.3" + "@jest/console" "30.1.2" + "@jest/test-result" "30.1.3" + "@jest/transform" "30.1.2" + "@jest/types" "30.0.5" + "@jridgewell/trace-mapping" "^0.3.25" + "@types/node" "*" + chalk "^4.1.2" + collect-v8-coverage "^1.0.2" + exit-x "^0.2.2" + glob "^10.3.10" + graceful-fs "^4.2.11" + istanbul-lib-coverage "^3.0.0" + istanbul-lib-instrument "^6.0.0" + istanbul-lib-report "^3.0.0" + istanbul-lib-source-maps "^5.0.0" + istanbul-reports "^3.1.3" + jest-message-util "30.1.0" + jest-util "30.0.5" + jest-worker "30.1.0" + slash "^3.0.0" + string-length "^4.0.2" + v8-to-istanbul "^9.0.1" + +"@jest/schemas@30.0.5": + version "30.0.5" + resolved "https://registry.yarnpkg.com/@jest/schemas/-/schemas-30.0.5.tgz#7bdf69fc5a368a5abdb49fd91036c55225846473" + integrity sha512-DmdYgtezMkh3cpU8/1uyXakv3tJRcmcXxBOcO0tbaozPwpmh4YMsnWrQm9ZmZMfa5ocbxzbFk6O4bDPEc/iAnA== + dependencies: + "@sinclair/typebox" "^0.34.0" + +"@jest/snapshot-utils@30.1.2": + version "30.1.2" + resolved "https://registry.yarnpkg.com/@jest/snapshot-utils/-/snapshot-utils-30.1.2.tgz#320500eba29a25c33e9ec968154e521873624309" + integrity sha512-vHoMTpimcPSR7OxS2S0V1Cpg8eKDRxucHjoWl5u4RQcnxqQrV3avETiFpl8etn4dqxEGarBeHbIBety/f8mLXw== + dependencies: + "@jest/types" "30.0.5" + chalk "^4.1.2" + graceful-fs "^4.2.11" + natural-compare "^1.4.0" + +"@jest/source-map@30.0.1": + version "30.0.1" + resolved "https://registry.yarnpkg.com/@jest/source-map/-/source-map-30.0.1.tgz#305ebec50468f13e658b3d5c26f85107a5620aaa" + integrity sha512-MIRWMUUR3sdbP36oyNyhbThLHyJ2eEDClPCiHVbrYAe5g3CHRArIVpBw7cdSB5fr+ofSfIb2Tnsw8iEHL0PYQg== + dependencies: + "@jridgewell/trace-mapping" "^0.3.25" + callsites "^3.1.0" + graceful-fs "^4.2.11" + +"@jest/test-result@30.1.3": + version "30.1.3" + resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-30.1.3.tgz#69fe7ff93da8c0c47bae245727e0ce23571d058e" + integrity sha512-P9IV8T24D43cNRANPPokn7tZh0FAFnYS2HIfi5vK18CjRkTDR9Y3e1BoEcAJnl4ghZZF4Ecda4M/k41QkvurEQ== + dependencies: + "@jest/console" "30.1.2" + "@jest/types" "30.0.5" + "@types/istanbul-lib-coverage" "^2.0.6" + collect-v8-coverage "^1.0.2" + +"@jest/test-sequencer@30.1.3": + version "30.1.3" + resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-30.1.3.tgz#df64038d46150e704ed07c5fee4626609f518089" + integrity sha512-82J+hzC0qeQIiiZDThh+YUadvshdBswi5nuyXlEmXzrhw5ZQSRHeQ5LpVMD/xc8B3wPePvs6VMzHnntxL+4E3w== + dependencies: + "@jest/test-result" "30.1.3" + graceful-fs "^4.2.11" + jest-haste-map "30.1.0" + slash "^3.0.0" + +"@jest/transform@30.1.2": + version "30.1.2" + resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-30.1.2.tgz#42624a9c89f2427cd413b989aaf9f6aeb58cae56" + integrity sha512-UYYFGifSgfjujf1Cbd3iU/IQoSd6uwsj8XHj5DSDf5ERDcWMdJOPTkHWXj4U+Z/uMagyOQZ6Vne8C4nRIrCxqA== + dependencies: + "@babel/core" "^7.27.4" + "@jest/types" "30.0.5" + "@jridgewell/trace-mapping" "^0.3.25" + babel-plugin-istanbul "^7.0.0" + chalk "^4.1.2" + convert-source-map "^2.0.0" + fast-json-stable-stringify "^2.1.0" + graceful-fs "^4.2.11" + jest-haste-map "30.1.0" + jest-regex-util "30.0.1" + jest-util "30.0.5" + micromatch "^4.0.8" + pirates "^4.0.7" + slash "^3.0.0" + write-file-atomic "^5.0.1" + +"@jest/types@30.0.5": + version "30.0.5" + resolved "https://registry.yarnpkg.com/@jest/types/-/types-30.0.5.tgz#29a33a4c036e3904f1cfd94f6fe77f89d2e1cc05" + integrity sha512-aREYa3aku9SSnea4aX6bhKn4bgv3AXkgijoQgbYV3yvbiGt6z+MQ85+6mIhx9DsKW2BuB/cLR/A+tcMThx+KLQ== + dependencies: + "@jest/pattern" "30.0.1" + "@jest/schemas" "30.0.5" + "@types/istanbul-lib-coverage" "^2.0.6" + "@types/istanbul-reports" "^3.0.4" + "@types/node" "*" + "@types/yargs" "^17.0.33" + chalk "^4.1.2" + +"@jridgewell/gen-mapping@^0.3.12", "@jridgewell/gen-mapping@^0.3.5": + version "0.3.13" + resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz#6342a19f44347518c93e43b1ac69deb3c4656a1f" + integrity sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA== + dependencies: + "@jridgewell/sourcemap-codec" "^1.5.0" + "@jridgewell/trace-mapping" "^0.3.24" + +"@jridgewell/remapping@^2.3.5": + version "2.3.5" + resolved "https://registry.yarnpkg.com/@jridgewell/remapping/-/remapping-2.3.5.tgz#375c476d1972947851ba1e15ae8f123047445aa1" + integrity sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ== + dependencies: + "@jridgewell/gen-mapping" "^0.3.5" + "@jridgewell/trace-mapping" "^0.3.24" + +"@jridgewell/resolve-uri@^3.0.3", "@jridgewell/resolve-uri@^3.1.0": + version "3.1.2" + resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz#7a0ee601f60f99a20c7c7c5ff0c80388c1189bd6" + integrity sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw== + +"@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.14", "@jridgewell/sourcemap-codec@^1.5.0": + version "1.5.5" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz#6912b00d2c631c0d15ce1a7ab57cd657f2a8f8ba" + integrity sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og== + +"@jridgewell/trace-mapping@0.3.9": + version "0.3.9" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz#6534fd5933a53ba7cbf3a17615e273a0d1273ff9" + integrity sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ== + dependencies: + "@jridgewell/resolve-uri" "^3.0.3" + "@jridgewell/sourcemap-codec" "^1.4.10" + +"@jridgewell/trace-mapping@^0.3.12", "@jridgewell/trace-mapping@^0.3.23", "@jridgewell/trace-mapping@^0.3.24", "@jridgewell/trace-mapping@^0.3.25", "@jridgewell/trace-mapping@^0.3.28": + version "0.3.31" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz#db15d6781c931f3a251a3dac39501c98a6082fd0" + integrity sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw== + dependencies: + "@jridgewell/resolve-uri" "^3.1.0" + "@jridgewell/sourcemap-codec" "^1.4.14" + +"@napi-rs/wasm-runtime@^0.2.11": + version "0.2.12" + resolved "https://registry.yarnpkg.com/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.12.tgz#3e78a8b96e6c33a6c517e1894efbd5385a7cb6f2" + integrity sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ== + dependencies: + "@emnapi/core" "^1.4.3" + "@emnapi/runtime" "^1.4.3" + "@tybys/wasm-util" "^0.10.0" + +"@noble/ciphers@^1.3.0": + version "1.3.0" + resolved "https://registry.yarnpkg.com/@noble/ciphers/-/ciphers-1.3.0.tgz#f64b8ff886c240e644e5573c097f86e5b43676dc" + integrity sha512-2I0gnIVPtfnMw9ee9h1dJG7tp81+8Ob3OJb3Mv37rx5L40/b0i7djjCVvGOVqc9AEIQyvyu1i6ypKdFw8R8gQw== + +"@noble/curves@1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.2.0.tgz#92d7e12e4e49b23105a2555c6984d41733d65c35" + integrity sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw== + dependencies: + "@noble/hashes" "1.3.2" + +"@noble/curves@1.9.1": + version "1.9.1" + resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.9.1.tgz#9654a0bc6c13420ae252ddcf975eaf0f58f0a35c" + integrity sha512-k11yZxZg+t+gWvBbIswW0yoJlu8cHOC7dhunwOzoWH/mXGBiYyR4YY6hAEK/3EUs4UpB8la1RfdRpeGsFHkWsA== + dependencies: + "@noble/hashes" "1.8.0" + +"@noble/curves@^1.3.0", "@noble/curves@~1.9.0": + version "1.9.7" + resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.9.7.tgz#79d04b4758a43e4bca2cbdc62e7771352fa6b951" + integrity sha512-gbKGcRUYIjA3/zCCNaWDciTMFI0dCkvou3TL8Zmy5Nc7sJ47a0jtOeZoTaMxkuqRo9cRhjOdZJXegxYE5FN/xw== + dependencies: + "@noble/hashes" "1.8.0" + +"@noble/hashes@1.3.2": + version "1.3.2" + resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.3.2.tgz#6f26dbc8fbc7205873ce3cee2f690eba0d421b39" + integrity sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ== + +"@noble/hashes@1.8.0", "@noble/hashes@^1.2.0", "@noble/hashes@^1.3.1", "@noble/hashes@^1.3.3", "@noble/hashes@^1.8.0", "@noble/hashes@~1.8.0": + version "1.8.0" + resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.8.0.tgz#cee43d801fcef9644b11b8194857695acd5f815a" + integrity sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A== + +"@pkgjs/parseargs@^0.11.0": + version "0.11.0" + resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33" + integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg== + +"@pkgr/core@^0.2.9": + version "0.2.9" + resolved "https://registry.yarnpkg.com/@pkgr/core/-/core-0.2.9.tgz#d229a7b7f9dac167a156992ef23c7f023653f53b" + integrity sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA== + +"@polkadot-api/json-rpc-provider-proxy@0.0.1": + version "0.0.1" + resolved "https://registry.yarnpkg.com/@polkadot-api/json-rpc-provider-proxy/-/json-rpc-provider-proxy-0.0.1.tgz#bb5c943642cdf0ec7bc48c0a2647558b9fcd7bdb" + integrity sha512-gmVDUP8LpCH0BXewbzqXF2sdHddq1H1q+XrAW2of+KZj4woQkIGBRGTJHeBEVHe30EB+UejR1N2dT4PO/RvDdg== + +"@polkadot-api/json-rpc-provider@0.0.1": + version "0.0.1" + resolved "https://registry.yarnpkg.com/@polkadot-api/json-rpc-provider/-/json-rpc-provider-0.0.1.tgz#333645d40ccd9bccfd1f32503f17e4e63e76e297" + integrity sha512-/SMC/l7foRjpykLTUTacIH05H3mr9ip8b5xxfwXlVezXrNVLp3Cv0GX6uItkKd+ZjzVPf3PFrDF2B2/HLSNESA== + +"@polkadot-api/metadata-builders@0.0.1": + version "0.0.1" + resolved "https://registry.yarnpkg.com/@polkadot-api/metadata-builders/-/metadata-builders-0.0.1.tgz#a76b48febef9ea72be8273d889e2677101045a05" + integrity sha512-GCI78BHDzXAF/L2pZD6Aod/yl82adqQ7ftNmKg51ixRL02JpWUA+SpUKTJE5MY1p8kiJJIo09P2um24SiJHxNA== + dependencies: + "@polkadot-api/substrate-bindings" "0.0.1" + "@polkadot-api/utils" "0.0.1" + +"@polkadot-api/observable-client@0.1.0": + version "0.1.0" + resolved "https://registry.yarnpkg.com/@polkadot-api/observable-client/-/observable-client-0.1.0.tgz#472045ea06a2bc4bccdc2db5c063eadcbf6f5351" + integrity sha512-GBCGDRztKorTLna/unjl/9SWZcRmvV58o9jwU2Y038VuPXZcr01jcw/1O3x+yeAuwyGzbucI/mLTDa1QoEml3A== + dependencies: + "@polkadot-api/metadata-builders" "0.0.1" + "@polkadot-api/substrate-bindings" "0.0.1" + "@polkadot-api/substrate-client" "0.0.1" + "@polkadot-api/utils" "0.0.1" + +"@polkadot-api/substrate-bindings@0.0.1": + version "0.0.1" + resolved "https://registry.yarnpkg.com/@polkadot-api/substrate-bindings/-/substrate-bindings-0.0.1.tgz#c4b7f4d6c3672d2c15cbc6c02964f014b73cbb0b" + integrity sha512-bAe7a5bOPnuFVmpv7y4BBMRpNTnMmE0jtTqRUw/+D8ZlEHNVEJQGr4wu3QQCl7k1GnSV1wfv3mzIbYjErEBocg== + dependencies: + "@noble/hashes" "^1.3.1" + "@polkadot-api/utils" "0.0.1" + "@scure/base" "^1.1.1" + scale-ts "^1.6.0" + +"@polkadot-api/substrate-client@0.0.1": + version "0.0.1" + resolved "https://registry.yarnpkg.com/@polkadot-api/substrate-client/-/substrate-client-0.0.1.tgz#0e8010a0abe2fb47d6fa7ab94e45e1d0de083314" + integrity sha512-9Bg9SGc3AwE+wXONQoW8GC00N3v6lCZLW74HQzqB6ROdcm5VAHM4CB/xRzWSUF9CXL78ugiwtHx3wBcpx4H4Wg== + +"@polkadot-api/utils@0.0.1": + version "0.0.1" + resolved "https://registry.yarnpkg.com/@polkadot-api/utils/-/utils-0.0.1.tgz#908b22becac705149d7cc946532143d0fb003bfc" + integrity sha512-3j+pRmlF9SgiYDabSdZsBSsN5XHbpXOAce1lWj56IEEaFZVjsiCaxDOA7C9nCcgfVXuvnbxqqEGQvnY+QfBAUw== + +"@polkadot/api-augment@11.3.1": + version "11.3.1" + resolved "https://registry.yarnpkg.com/@polkadot/api-augment/-/api-augment-11.3.1.tgz#c7deeac438b017613e244c25505216a9d4c3977e" + integrity sha512-Yj+6rb6h0WwY3yJ+UGhjGW+tyMRFUMsKQuGw+eFsXdjiNU9UoXsAqA2dG7Q1F+oeX/g+y2gLGBezNoCwbl6HfA== + dependencies: + "@polkadot/api-base" "11.3.1" + "@polkadot/rpc-augment" "11.3.1" + "@polkadot/types" "11.3.1" + "@polkadot/types-augment" "11.3.1" + "@polkadot/types-codec" "11.3.1" + "@polkadot/util" "^12.6.2" + tslib "^2.6.2" + +"@polkadot/api-base@11.3.1": + version "11.3.1" + resolved "https://registry.yarnpkg.com/@polkadot/api-base/-/api-base-11.3.1.tgz#6c74c88d4a4b3d22344bb8715a135493f5a3dd33" + integrity sha512-b8UkNL00NN7+3QaLCwL5cKg+7YchHoKCAhwKusWHNBZkkO6Oo2BWilu0dZkPJOyqV9P389Kbd9+oH+SKs9u2VQ== + dependencies: + "@polkadot/rpc-core" "11.3.1" + "@polkadot/types" "11.3.1" + "@polkadot/util" "^12.6.2" + rxjs "^7.8.1" + tslib "^2.6.2" + +"@polkadot/api-derive@11.3.1": + version "11.3.1" + resolved "https://registry.yarnpkg.com/@polkadot/api-derive/-/api-derive-11.3.1.tgz#3617655b6dab56d5beb8efbf7383ab457370df35" + integrity sha512-9dopzrh4cRuft1nANmBvMY/hEhFDu0VICMTOGxQLOl8NMfcOFPTLAN0JhSBUoicGZhV+c4vpv01NBx/7/IL1HA== + dependencies: + "@polkadot/api" "11.3.1" + "@polkadot/api-augment" "11.3.1" + "@polkadot/api-base" "11.3.1" + "@polkadot/rpc-core" "11.3.1" + "@polkadot/types" "11.3.1" + "@polkadot/types-codec" "11.3.1" + "@polkadot/util" "^12.6.2" + "@polkadot/util-crypto" "^12.6.2" + rxjs "^7.8.1" + tslib "^2.6.2" + +"@polkadot/api@11.3.1", "@polkadot/api@^11.2.1": + version "11.3.1" + resolved "https://registry.yarnpkg.com/@polkadot/api/-/api-11.3.1.tgz#6092aea8147ea03873b3f383cceae0390a67f71d" + integrity sha512-q4kFIIHTLvKxM24b0Eo8hJevsPMme+aITJGrDML9BgdZYTRN14+cu5nXiCsQvaEamdyYj+uCXWe2OV9X7pPxsA== + dependencies: + "@polkadot/api-augment" "11.3.1" + "@polkadot/api-base" "11.3.1" + "@polkadot/api-derive" "11.3.1" + "@polkadot/keyring" "^12.6.2" + "@polkadot/rpc-augment" "11.3.1" + "@polkadot/rpc-core" "11.3.1" + "@polkadot/rpc-provider" "11.3.1" + "@polkadot/types" "11.3.1" + "@polkadot/types-augment" "11.3.1" + "@polkadot/types-codec" "11.3.1" + "@polkadot/types-create" "11.3.1" + "@polkadot/types-known" "11.3.1" + "@polkadot/util" "^12.6.2" + "@polkadot/util-crypto" "^12.6.2" + eventemitter3 "^5.0.1" + rxjs "^7.8.1" + tslib "^2.6.2" + +"@polkadot/keyring@^12.6.2": + version "12.6.2" + resolved "https://registry.yarnpkg.com/@polkadot/keyring/-/keyring-12.6.2.tgz#6067e6294fee23728b008ac116e7e9db05cecb9b" + integrity sha512-O3Q7GVmRYm8q7HuB3S0+Yf/q/EB2egKRRU3fv9b3B7V+A52tKzA+vIwEmNVaD1g5FKW9oB97rmpggs0zaKFqHw== + dependencies: + "@polkadot/util" "12.6.2" + "@polkadot/util-crypto" "12.6.2" + tslib "^2.6.2" + +"@polkadot/networks@12.6.2", "@polkadot/networks@^12.6.2": + version "12.6.2" + resolved "https://registry.yarnpkg.com/@polkadot/networks/-/networks-12.6.2.tgz#791779fee1d86cc5b6cd371858eea9b7c3f8720d" + integrity sha512-1oWtZm1IvPWqvMrldVH6NI2gBoCndl5GEwx7lAuQWGr7eNL+6Bdc5K3Z9T0MzFvDGoi2/CBqjX9dRKo39pDC/w== + dependencies: + "@polkadot/util" "12.6.2" + "@substrate/ss58-registry" "^1.44.0" + tslib "^2.6.2" + +"@polkadot/rpc-augment@11.3.1": + version "11.3.1" + resolved "https://registry.yarnpkg.com/@polkadot/rpc-augment/-/rpc-augment-11.3.1.tgz#b589ef5b7ab578cf274077604543071ce9889301" + integrity sha512-2PaDcKNju4QYQpxwVkWbRU3M0t340nMX9cMo+8awgvgL1LliV/fUDZueMKLuSS910JJMTPQ7y2pK4eQgMt08gQ== + dependencies: + "@polkadot/rpc-core" "11.3.1" + "@polkadot/types" "11.3.1" + "@polkadot/types-codec" "11.3.1" + "@polkadot/util" "^12.6.2" + tslib "^2.6.2" + +"@polkadot/rpc-core@11.3.1": + version "11.3.1" + resolved "https://registry.yarnpkg.com/@polkadot/rpc-core/-/rpc-core-11.3.1.tgz#c23e23ee5c403c4edb207d603ae4dc16e69bc710" + integrity sha512-KKNepsDd/mpmXcA6v/h14eFFPEzLGd7nrvx2UUXUxoZ0Fq2MH1hplP3s93k1oduNY/vOXJR2K9S4dKManA6GVQ== + dependencies: + "@polkadot/rpc-augment" "11.3.1" + "@polkadot/rpc-provider" "11.3.1" + "@polkadot/types" "11.3.1" + "@polkadot/util" "^12.6.2" + rxjs "^7.8.1" + tslib "^2.6.2" + +"@polkadot/rpc-provider@11.3.1": + version "11.3.1" + resolved "https://registry.yarnpkg.com/@polkadot/rpc-provider/-/rpc-provider-11.3.1.tgz#1d1289bf42d065b5f04f9baa46ef90d96940819e" + integrity sha512-pqERChoHo45hd3WAgW8UuzarRF+G/o/eXEbl0PXLubiayw4X4qCmIzmtntUcKYgxGNcYGZaG87ZU8OjN97m6UA== + dependencies: + "@polkadot/keyring" "^12.6.2" + "@polkadot/types" "11.3.1" + "@polkadot/types-support" "11.3.1" + "@polkadot/util" "^12.6.2" + "@polkadot/util-crypto" "^12.6.2" + "@polkadot/x-fetch" "^12.6.2" + "@polkadot/x-global" "^12.6.2" + "@polkadot/x-ws" "^12.6.2" + eventemitter3 "^5.0.1" + mock-socket "^9.3.1" + nock "^13.5.0" + tslib "^2.6.2" + optionalDependencies: + "@substrate/connect" "0.8.10" + +"@polkadot/types-augment@11.3.1": + version "11.3.1" + resolved "https://registry.yarnpkg.com/@polkadot/types-augment/-/types-augment-11.3.1.tgz#1f7f553f0ca6eb8fbc0306901edc045fe18729e1" + integrity sha512-eR3HVpvUmB3v7q2jTWVmVfAVfb1/kuNn7ij94Zqadg/fuUq0pKqIOKwkUj3OxRM3A/5BnW3MbgparjKD3r+fyw== + dependencies: + "@polkadot/types" "11.3.1" + "@polkadot/types-codec" "11.3.1" + "@polkadot/util" "^12.6.2" + tslib "^2.6.2" + +"@polkadot/types-codec@11.3.1": + version "11.3.1" + resolved "https://registry.yarnpkg.com/@polkadot/types-codec/-/types-codec-11.3.1.tgz#2767cf482cd49afdd5dce9701615f68ec59cec5e" + integrity sha512-i7IiiuuL+Z/jFoKTA9xeh4wGQnhnNNjMT0+1ohvlOvnFsoKZKFQQOaDPPntGJVL1JDCV+KjkN2uQKZSeW8tguQ== + dependencies: + "@polkadot/util" "^12.6.2" + "@polkadot/x-bigint" "^12.6.2" + tslib "^2.6.2" + +"@polkadot/types-create@11.3.1": + version "11.3.1" + resolved "https://registry.yarnpkg.com/@polkadot/types-create/-/types-create-11.3.1.tgz#3ac2c8283f61555f9e572ca30e3485b95a0a54e2" + integrity sha512-pBXtpz5FehcRJ6j5MzFUIUN8ZWM7z6HbqK1GxBmYbJVRElcGcOg7a/rL2pQVphU0Rx1E8bSO4thzGf4wUxSX7w== + dependencies: + "@polkadot/types-codec" "11.3.1" + "@polkadot/util" "^12.6.2" + tslib "^2.6.2" + +"@polkadot/types-known@11.3.1": + version "11.3.1" + resolved "https://registry.yarnpkg.com/@polkadot/types-known/-/types-known-11.3.1.tgz#fc34ed29ac2474db6b66805a15d12008226346bb" + integrity sha512-3BIof7u6tn9bk3ZCIxA07iNoQ3uj4+vn3DTOjCKECozkRlt6V+kWRvqh16Hc0SHMg/QjcMb2fIu/WZhka1McUQ== + dependencies: + "@polkadot/networks" "^12.6.2" + "@polkadot/types" "11.3.1" + "@polkadot/types-codec" "11.3.1" + "@polkadot/types-create" "11.3.1" + "@polkadot/util" "^12.6.2" + tslib "^2.6.2" + +"@polkadot/types-support@11.3.1": + version "11.3.1" + resolved "https://registry.yarnpkg.com/@polkadot/types-support/-/types-support-11.3.1.tgz#dee02a67784baa13177fe9957f5d8d62e8a7e570" + integrity sha512-jTFz1GKyF7nI29yIOq4v0NiWTOf5yX4HahJNeFD8TcxoLhF+6tH/XXqrUXJEfbaTlSrRWiW1LZYlb+snctqKHA== + dependencies: + "@polkadot/util" "^12.6.2" + tslib "^2.6.2" + +"@polkadot/types@11.3.1": + version "11.3.1" + resolved "https://registry.yarnpkg.com/@polkadot/types/-/types-11.3.1.tgz#bab61b701218158099e3f548d20efc27cbf1287f" + integrity sha512-5c7uRFXQTT11Awi6T0yFIdAfD6xGDAOz06Kp7M5S9OGNZY28wSPk5x6BYfNphWPaIBmHHewYJB5qmnrdYQAWKQ== + dependencies: + "@polkadot/keyring" "^12.6.2" + "@polkadot/types-augment" "11.3.1" + "@polkadot/types-codec" "11.3.1" + "@polkadot/types-create" "11.3.1" + "@polkadot/util" "^12.6.2" + "@polkadot/util-crypto" "^12.6.2" + rxjs "^7.8.1" + tslib "^2.6.2" + +"@polkadot/util-crypto@12.6.2", "@polkadot/util-crypto@^12.6.2": + version "12.6.2" + resolved "https://registry.yarnpkg.com/@polkadot/util-crypto/-/util-crypto-12.6.2.tgz#d2d51010e8e8ca88951b7d864add797dad18bbfc" + integrity sha512-FEWI/dJ7wDMNN1WOzZAjQoIcCP/3vz3wvAp5QQm+lOrzOLj0iDmaIGIcBkz8HVm3ErfSe/uKP0KS4jgV/ib+Mg== + dependencies: + "@noble/curves" "^1.3.0" + "@noble/hashes" "^1.3.3" + "@polkadot/networks" "12.6.2" + "@polkadot/util" "12.6.2" + "@polkadot/wasm-crypto" "^7.3.2" + "@polkadot/wasm-util" "^7.3.2" + "@polkadot/x-bigint" "12.6.2" + "@polkadot/x-randomvalues" "12.6.2" + "@scure/base" "^1.1.5" + tslib "^2.6.2" + +"@polkadot/util@12.6.2", "@polkadot/util@^12.6.2": + version "12.6.2" + resolved "https://registry.yarnpkg.com/@polkadot/util/-/util-12.6.2.tgz#9396eff491221e1f0fd28feac55fc16ecd61a8dc" + integrity sha512-l8TubR7CLEY47240uki0TQzFvtnxFIO7uI/0GoWzpYD/O62EIAMRsuY01N4DuwgKq2ZWD59WhzsLYmA5K6ksdw== + dependencies: + "@polkadot/x-bigint" "12.6.2" + "@polkadot/x-global" "12.6.2" + "@polkadot/x-textdecoder" "12.6.2" + "@polkadot/x-textencoder" "12.6.2" + "@types/bn.js" "^5.1.5" + bn.js "^5.2.1" + tslib "^2.6.2" + +"@polkadot/wasm-bridge@7.5.1": + version "7.5.1" + resolved "https://registry.yarnpkg.com/@polkadot/wasm-bridge/-/wasm-bridge-7.5.1.tgz#f738858213a8a599ae8bf6a6c179b325dcf091f4" + integrity sha512-E+N3CSnX3YaXpAmfIQ+4bTyiAqJQKvVcMaXjkuL8Tp2zYffClWLG5e+RY15Uh+EWfUl9If4y6cLZi3D5NcpAGQ== + dependencies: + "@polkadot/wasm-util" "7.5.1" + tslib "^2.7.0" + +"@polkadot/wasm-crypto-asmjs@7.5.1": + version "7.5.1" + resolved "https://registry.yarnpkg.com/@polkadot/wasm-crypto-asmjs/-/wasm-crypto-asmjs-7.5.1.tgz#87e07aa340249d5c978cd03eb58b395563066a4c" + integrity sha512-jAg7Uusk+xeHQ+QHEH4c/N3b1kEGBqZb51cWe+yM61kKpQwVGZhNdlWetW6U23t/BMyZArIWMsZqmK/Ij0PHog== + dependencies: + tslib "^2.7.0" + +"@polkadot/wasm-crypto-init@7.5.1": + version "7.5.1" + resolved "https://registry.yarnpkg.com/@polkadot/wasm-crypto-init/-/wasm-crypto-init-7.5.1.tgz#0434850b7f05619ff312d5cbfd33629a54f9b31a" + integrity sha512-Obu4ZEo5jYO6sN31eqCNOXo88rPVkP9TrUOyynuFCnXnXr8V/HlmY/YkAd9F87chZnkTJRlzak17kIWr+i7w3A== + dependencies: + "@polkadot/wasm-bridge" "7.5.1" + "@polkadot/wasm-crypto-asmjs" "7.5.1" + "@polkadot/wasm-crypto-wasm" "7.5.1" + "@polkadot/wasm-util" "7.5.1" + tslib "^2.7.0" + +"@polkadot/wasm-crypto-wasm@7.5.1": + version "7.5.1" + resolved "https://registry.yarnpkg.com/@polkadot/wasm-crypto-wasm/-/wasm-crypto-wasm-7.5.1.tgz#b3996007875db6945d29f94f4d4719fce2b3bb8f" + integrity sha512-S2yQSGbOGTcaV6UdipFVyEGanJvG6uD6Tg7XubxpiGbNAblsyYKeFcxyH1qCosk/4qf+GIUwlOL4ydhosZflqg== + dependencies: + "@polkadot/wasm-util" "7.5.1" + tslib "^2.7.0" + +"@polkadot/wasm-crypto@^7.3.2": + version "7.5.1" + resolved "https://registry.yarnpkg.com/@polkadot/wasm-crypto/-/wasm-crypto-7.5.1.tgz#324ebf9a86a30fd19bf4b02a6582367bdddb62c9" + integrity sha512-acjt4VJ3w19v7b/SIPsV/5k9s6JsragHKPnwoZ0KTfBvAFXwzz80jUzVGxA06SKHacfCUe7vBRlz7M5oRby1Pw== + dependencies: + "@polkadot/wasm-bridge" "7.5.1" + "@polkadot/wasm-crypto-asmjs" "7.5.1" + "@polkadot/wasm-crypto-init" "7.5.1" + "@polkadot/wasm-crypto-wasm" "7.5.1" + "@polkadot/wasm-util" "7.5.1" + tslib "^2.7.0" + +"@polkadot/wasm-util@7.5.1", "@polkadot/wasm-util@^7.3.2": + version "7.5.1" + resolved "https://registry.yarnpkg.com/@polkadot/wasm-util/-/wasm-util-7.5.1.tgz#4568a9bf8d02d2d68fc139f331719865300e5233" + integrity sha512-sbvu71isFhPXpvMVX+EkRnUg/+54Tx7Sf9BEMqxxoPj7cG1I/MKeDEwbQz6MaU4gm7xJqvEWCAemLFcXfHQ/2A== + dependencies: + tslib "^2.7.0" + +"@polkadot/x-bigint@12.6.2", "@polkadot/x-bigint@^12.6.2": + version "12.6.2" + resolved "https://registry.yarnpkg.com/@polkadot/x-bigint/-/x-bigint-12.6.2.tgz#59b7a615f205ae65e1ac67194aefde94d3344580" + integrity sha512-HSIk60uFPX4GOFZSnIF7VYJz7WZA7tpFJsne7SzxOooRwMTWEtw3fUpFy5cYYOeLh17/kHH1Y7SVcuxzVLc74Q== + dependencies: + "@polkadot/x-global" "12.6.2" + tslib "^2.6.2" + +"@polkadot/x-fetch@^12.6.2": + version "12.6.2" + resolved "https://registry.yarnpkg.com/@polkadot/x-fetch/-/x-fetch-12.6.2.tgz#b1bca028db90263bafbad2636c18d838d842d439" + integrity sha512-8wM/Z9JJPWN1pzSpU7XxTI1ldj/AfC8hKioBlUahZ8gUiJaOF7K9XEFCrCDLis/A1BoOu7Ne6WMx/vsJJIbDWw== + dependencies: + "@polkadot/x-global" "12.6.2" + node-fetch "^3.3.2" + tslib "^2.6.2" + +"@polkadot/x-global@12.6.2", "@polkadot/x-global@^12.6.2": + version "12.6.2" + resolved "https://registry.yarnpkg.com/@polkadot/x-global/-/x-global-12.6.2.tgz#31d4de1c3d4c44e4be3219555a6d91091decc4ec" + integrity sha512-a8d6m+PW98jmsYDtAWp88qS4dl8DyqUBsd0S+WgyfSMtpEXu6v9nXDgPZgwF5xdDvXhm+P0ZfVkVTnIGrScb5g== + dependencies: + tslib "^2.6.2" + +"@polkadot/x-randomvalues@12.6.2": + version "12.6.2" + resolved "https://registry.yarnpkg.com/@polkadot/x-randomvalues/-/x-randomvalues-12.6.2.tgz#13fe3619368b8bf5cb73781554859b5ff9d900a2" + integrity sha512-Vr8uG7rH2IcNJwtyf5ebdODMcr0XjoCpUbI91Zv6AlKVYOGKZlKLYJHIwpTaKKB+7KPWyQrk4Mlym/rS7v9feg== + dependencies: + "@polkadot/x-global" "12.6.2" + tslib "^2.6.2" + +"@polkadot/x-textdecoder@12.6.2": + version "12.6.2" + resolved "https://registry.yarnpkg.com/@polkadot/x-textdecoder/-/x-textdecoder-12.6.2.tgz#b86da0f8e8178f1ca31a7158257e92aea90b10e4" + integrity sha512-M1Bir7tYvNappfpFWXOJcnxUhBUFWkUFIdJSyH0zs5LmFtFdbKAeiDXxSp2Swp5ddOZdZgPac294/o2TnQKN1w== + dependencies: + "@polkadot/x-global" "12.6.2" + tslib "^2.6.2" + +"@polkadot/x-textencoder@12.6.2": + version "12.6.2" + resolved "https://registry.yarnpkg.com/@polkadot/x-textencoder/-/x-textencoder-12.6.2.tgz#81d23bd904a2c36137a395c865c5fefa21abfb44" + integrity sha512-4N+3UVCpI489tUJ6cv3uf0PjOHvgGp9Dl+SZRLgFGt9mvxnvpW/7+XBADRMtlG4xi5gaRK7bgl5bmY6OMDsNdw== + dependencies: + "@polkadot/x-global" "12.6.2" + tslib "^2.6.2" + +"@polkadot/x-ws@^12.6.2": + version "12.6.2" + resolved "https://registry.yarnpkg.com/@polkadot/x-ws/-/x-ws-12.6.2.tgz#b99094d8e53a03be1de903d13ba59adaaabc767a" + integrity sha512-cGZWo7K5eRRQCRl2LrcyCYsrc3lRbTlixZh3AzgU8uX4wASVGRlNWi/Hf4TtHNe1ExCDmxabJzdIsABIfrr7xw== + dependencies: + "@polkadot/x-global" "12.6.2" + tslib "^2.6.2" + ws "^8.15.1" + +"@scure/base@^1.1.1", "@scure/base@^1.1.5", "@scure/base@~1.2.5": + version "1.2.6" + resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.2.6.tgz#ca917184b8231394dd8847509c67a0be522e59f6" + integrity sha512-g/nm5FgUa//MCj1gV09zTJTaM6KBAHqLN907YVQqf7zC49+DcO4B1so4ZX07Ef10Twr6nuqYEH9GEggFXA4Fmg== + +"@scure/bip32@1.7.0", "@scure/bip32@^1.7.0": + version "1.7.0" + resolved "https://registry.yarnpkg.com/@scure/bip32/-/bip32-1.7.0.tgz#b8683bab172369f988f1589640e53c4606984219" + integrity sha512-E4FFX/N3f4B80AKWp5dP6ow+flD1LQZo/w8UnLGYZO674jS6YnYeepycOOksv+vLPSpgN35wgKgy+ybfTb2SMw== + dependencies: + "@noble/curves" "~1.9.0" + "@noble/hashes" "~1.8.0" + "@scure/base" "~1.2.5" + +"@scure/bip39@1.6.0", "@scure/bip39@^1.6.0": + version "1.6.0" + resolved "https://registry.yarnpkg.com/@scure/bip39/-/bip39-1.6.0.tgz#475970ace440d7be87a6086cbee77cb8f1a684f9" + integrity sha512-+lF0BbLiJNwVlev4eKelw1WWLaiKXw7sSl8T6FvBlWkdX+94aGJ4o8XjUdlyhTCjd8c+B3KT3JfS8P0bLRNU6A== + dependencies: + "@noble/hashes" "~1.8.0" + "@scure/base" "~1.2.5" + +"@sinclair/typebox@^0.34.0": + version "0.34.41" + resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.34.41.tgz#aa51a6c1946df2c5a11494a2cdb9318e026db16c" + integrity sha512-6gS8pZzSXdyRHTIqoqSVknxolr1kzfy4/CeDnrzsVz8TTIWUbOBr6gnzOmTYJ3eXQNh4IYHIGi5aIL7sOZ2G/g== + +"@sinonjs/commons@^3.0.1": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-3.0.1.tgz#1029357e44ca901a615585f6d27738dbc89084cd" + integrity sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ== + dependencies: + type-detect "4.0.8" + +"@sinonjs/fake-timers@^13.0.0": + version "13.0.5" + resolved "https://registry.yarnpkg.com/@sinonjs/fake-timers/-/fake-timers-13.0.5.tgz#36b9dbc21ad5546486ea9173d6bea063eb1717d5" + integrity sha512-36/hTbH2uaWuGVERyC6da9YwGWnzUZXuPro/F2LfsdOsLnCojz/iSH8MxUt/FD2S5XBSVPhmArFUXcpCQ2Hkiw== + dependencies: + "@sinonjs/commons" "^3.0.1" + +"@substrate/connect-extension-protocol@^2.0.0": + version "2.2.2" + resolved "https://registry.yarnpkg.com/@substrate/connect-extension-protocol/-/connect-extension-protocol-2.2.2.tgz#2cf8f2eaf1879308d307a1a08df83cd5db918fe0" + integrity sha512-t66jwrXA0s5Goq82ZtjagLNd7DPGCNjHeehRlE/gcJmJ+G56C0W+2plqOMRicJ8XGR1/YFnUSEqUFiSNbjGrAA== + +"@substrate/connect-known-chains@^1.1.4": + version "1.10.3" + resolved "https://registry.yarnpkg.com/@substrate/connect-known-chains/-/connect-known-chains-1.10.3.tgz#71a89864f13626c412fa0a9d0ffc4f6ca39fdcec" + integrity sha512-OJEZO1Pagtb6bNE3wCikc2wrmvEU5x7GxFFLqqbz1AJYYxSlrPCGu4N2og5YTExo4IcloNMQYFRkBGue0BKZ4w== + +"@substrate/connect@0.8.10": + version "0.8.10" + resolved "https://registry.yarnpkg.com/@substrate/connect/-/connect-0.8.10.tgz#810b6589f848828aa840c731a1f36b84fe0e5956" + integrity sha512-DIyQ13DDlXqVFnLV+S6/JDgiGowVRRrh18kahieJxhgvzcWicw5eLc6jpfQ0moVVLBYkO7rctB5Wreldwpva8w== + dependencies: + "@substrate/connect-extension-protocol" "^2.0.0" + "@substrate/connect-known-chains" "^1.1.4" + "@substrate/light-client-extension-helpers" "^0.0.6" + smoldot "2.0.22" + +"@substrate/light-client-extension-helpers@^0.0.6": + version "0.0.6" + resolved "https://registry.yarnpkg.com/@substrate/light-client-extension-helpers/-/light-client-extension-helpers-0.0.6.tgz#bec1c7997241226db50b44ad85a992b4348d21c3" + integrity sha512-girltEuxQ1BvkJWmc8JJlk4ZxnlGXc/wkLcNguhY+UoDEMBK0LsdtfzQKIfrIehi4QdeSBlFEFBoI4RqPmsZzA== + dependencies: + "@polkadot-api/json-rpc-provider" "0.0.1" + "@polkadot-api/json-rpc-provider-proxy" "0.0.1" + "@polkadot-api/observable-client" "0.1.0" + "@polkadot-api/substrate-client" "0.0.1" + "@substrate/connect-extension-protocol" "^2.0.0" + "@substrate/connect-known-chains" "^1.1.4" + rxjs "^7.8.1" + +"@substrate/ss58-registry@^1.44.0": + version "1.51.0" + resolved "https://registry.yarnpkg.com/@substrate/ss58-registry/-/ss58-registry-1.51.0.tgz#39e0341eb4069c2d3e684b93f0d8cb0bec572383" + integrity sha512-TWDurLiPxndFgKjVavCniytBIw+t4ViOi7TYp9h/D0NMmkEc9klFTo+827eyEJ0lELpqO207Ey7uGxUa+BS1jQ== + +"@tsconfig/node10@^1.0.7": + version "1.0.11" + resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.11.tgz#6ee46400685f130e278128c7b38b7e031ff5b2f2" + integrity sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw== + +"@tsconfig/node12@^1.0.7": + version "1.0.11" + resolved "https://registry.yarnpkg.com/@tsconfig/node12/-/node12-1.0.11.tgz#ee3def1f27d9ed66dac6e46a295cffb0152e058d" + integrity sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag== + +"@tsconfig/node14@^1.0.0": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@tsconfig/node14/-/node14-1.0.3.tgz#e4386316284f00b98435bf40f72f75a09dabf6c1" + integrity sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow== + +"@tsconfig/node16@^1.0.2": + version "1.0.4" + resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.4.tgz#0b92dcc0cc1c81f6f306a381f28e31b1a56536e9" + integrity sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA== + +"@tybys/wasm-util@^0.10.0": + version "0.10.1" + resolved "https://registry.yarnpkg.com/@tybys/wasm-util/-/wasm-util-0.10.1.tgz#ecddd3205cf1e2d5274649ff0eedd2991ed7f414" + integrity sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg== + dependencies: + tslib "^2.4.0" + +"@types/babel__core@^7.20.5": + version "7.20.5" + resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.20.5.tgz#3df15f27ba85319caa07ba08d0721889bb39c017" + integrity sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA== + dependencies: + "@babel/parser" "^7.20.7" + "@babel/types" "^7.20.7" + "@types/babel__generator" "*" + "@types/babel__template" "*" + "@types/babel__traverse" "*" + +"@types/babel__generator@*": + version "7.27.0" + resolved "https://registry.yarnpkg.com/@types/babel__generator/-/babel__generator-7.27.0.tgz#b5819294c51179957afaec341442f9341e4108a9" + integrity sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg== + dependencies: + "@babel/types" "^7.0.0" + +"@types/babel__template@*": + version "7.4.4" + resolved "https://registry.yarnpkg.com/@types/babel__template/-/babel__template-7.4.4.tgz#5672513701c1b2199bc6dad636a9d7491586766f" + integrity sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A== + dependencies: + "@babel/parser" "^7.1.0" + "@babel/types" "^7.0.0" + +"@types/babel__traverse@*": + version "7.28.0" + resolved "https://registry.yarnpkg.com/@types/babel__traverse/-/babel__traverse-7.28.0.tgz#07d713d6cce0d265c9849db0cbe62d3f61f36f74" + integrity sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q== + dependencies: + "@babel/types" "^7.28.2" + +"@types/bn.js@*", "@types/bn.js@^5.1.5": + version "5.2.0" + resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-5.2.0.tgz#4349b9710e98f9ab3cdc50f1c5e4dcbd8ef29c80" + integrity sha512-DLbJ1BPqxvQhIGbeu8VbUC1DiAiahHtAYvA0ZEAa4P31F7IaArc8z3C3BRQdWX4mtLQuABG4yzp76ZrS02Ui1Q== + dependencies: + "@types/node" "*" + +"@types/elliptic@^6.4.18": + version "6.4.18" + resolved "https://registry.yarnpkg.com/@types/elliptic/-/elliptic-6.4.18.tgz#bc96e26e1ccccbabe8b6f0e409c85898635482e1" + integrity sha512-UseG6H5vjRiNpQvrhy4VF/JXdA3V/Fp5amvveaL+fs28BZ6xIKJBPnUPRlEaZpysD9MbpfaLi8lbl7PGUAkpWw== + dependencies: + "@types/bn.js" "*" + +"@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.1", "@types/istanbul-lib-coverage@^2.0.6": + version "2.0.6" + resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz#7739c232a1fee9b4d3ce8985f314c0c6d33549d7" + integrity sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w== + +"@types/istanbul-lib-report@*": + version "3.0.3" + resolved "https://registry.yarnpkg.com/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz#53047614ae72e19fc0401d872de3ae2b4ce350bf" + integrity sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA== + dependencies: + "@types/istanbul-lib-coverage" "*" + +"@types/istanbul-reports@^3.0.4": + version "3.0.4" + resolved "https://registry.yarnpkg.com/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz#0f03e3d2f670fbdac586e34b433783070cc16f54" + integrity sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ== + dependencies: + "@types/istanbul-lib-report" "*" + +"@types/jest@^30.0.0": + version "30.0.0" + resolved "https://registry.yarnpkg.com/@types/jest/-/jest-30.0.0.tgz#5e85ae568006712e4ad66f25433e9bdac8801f1d" + integrity sha512-XTYugzhuwqWjws0CVz8QpM36+T+Dz5mTEBKhNs/esGLnCIlGdRy+Dq78NRjd7ls7r8BC8ZRMOrKlkO1hU0JOwA== + dependencies: + expect "^30.0.0" + pretty-format "^30.0.0" + +"@types/mocha@^10.0.10": + version "10.0.10" + resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-10.0.10.tgz#91f62905e8d23cbd66225312f239454a23bebfa0" + integrity sha512-xPyYSz1cMPnJQhl0CLMH68j3gprKZaTjG3s5Vi+fDgx+uhG9NOXwbVt52eFS8ECyXhyKcjDLCBEqBExKuiZb7Q== + +"@types/node@*": + version "24.4.0" + resolved "https://registry.yarnpkg.com/@types/node/-/node-24.4.0.tgz#4ca9168c016a55ab15b7765ad1674ab807489600" + integrity sha512-gUuVEAK4/u6F9wRLznPUU4WGUacSEBDPoC2TrBkw3GAnOLHBL45QdfHOXp1kJ4ypBGLxTOB+t7NJLpKoC3gznQ== + dependencies: + undici-types "~7.11.0" + +"@types/node@22.7.5": + version "22.7.5" + resolved "https://registry.yarnpkg.com/@types/node/-/node-22.7.5.tgz#cfde981727a7ab3611a481510b473ae54442b92b" + integrity sha512-jML7s2NAzMWc//QSJ1a3prpk78cOPchGvXJsC3C6R6PSMoooztvRVQEz89gmBTBY1SPMaqo5teB4uNHPdetShQ== + dependencies: + undici-types "~6.19.2" + +"@types/node@^20.11.5": + version "20.19.17" + resolved "https://registry.yarnpkg.com/@types/node/-/node-20.19.17.tgz#41b52697373aef8a43b3b92f33b43f329b2d674b" + integrity sha512-gfehUI8N1z92kygssiuWvLiwcbOB3IRktR6hTDgJlXMYh5OvkPSRmgfoBUmfZt+vhwJtX7v1Yw4KvvAf7c5QKQ== + dependencies: + undici-types "~6.21.0" + +"@types/stack-utils@^2.0.3": + version "2.0.3" + resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.3.tgz#6209321eb2c1712a7e7466422b8cb1fc0d9dd5d8" + integrity sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw== + +"@types/yargs-parser@*": + version "21.0.3" + resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-21.0.3.tgz#815e30b786d2e8f0dcd85fd5bcf5e1a04d008f15" + integrity sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ== + +"@types/yargs@^17.0.33": + version "17.0.33" + resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-17.0.33.tgz#8c32303da83eec050a84b3c7ae7b9f922d13e32d" + integrity sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA== + dependencies: + "@types/yargs-parser" "*" + +"@ungap/structured-clone@^1.3.0": + version "1.3.0" + resolved "https://registry.yarnpkg.com/@ungap/structured-clone/-/structured-clone-1.3.0.tgz#d06bbb384ebcf6c505fde1c3d0ed4ddffe0aaff8" + integrity sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g== + +"@unrs/resolver-binding-android-arm-eabi@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-android-arm-eabi/-/resolver-binding-android-arm-eabi-1.11.1.tgz#9f5b04503088e6a354295e8ea8fe3cb99e43af81" + integrity sha512-ppLRUgHVaGRWUx0R0Ut06Mjo9gBaBkg3v/8AxusGLhsIotbBLuRk51rAzqLC8gq6NyyAojEXglNjzf6R948DNw== + +"@unrs/resolver-binding-android-arm64@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-android-arm64/-/resolver-binding-android-arm64-1.11.1.tgz#7414885431bd7178b989aedc4d25cccb3865bc9f" + integrity sha512-lCxkVtb4wp1v+EoN+HjIG9cIIzPkX5OtM03pQYkG+U5O/wL53LC4QbIeazgiKqluGeVEeBlZahHalCaBvU1a2g== + +"@unrs/resolver-binding-darwin-arm64@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-darwin-arm64/-/resolver-binding-darwin-arm64-1.11.1.tgz#b4a8556f42171fb9c9f7bac8235045e82aa0cbdf" + integrity sha512-gPVA1UjRu1Y/IsB/dQEsp2V1pm44Of6+LWvbLc9SDk1c2KhhDRDBUkQCYVWe6f26uJb3fOK8saWMgtX8IrMk3g== + +"@unrs/resolver-binding-darwin-x64@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-darwin-x64/-/resolver-binding-darwin-x64-1.11.1.tgz#fd4d81257b13f4d1a083890a6a17c00de571f0dc" + integrity sha512-cFzP7rWKd3lZaCsDze07QX1SC24lO8mPty9vdP+YVa3MGdVgPmFc59317b2ioXtgCMKGiCLxJ4HQs62oz6GfRQ== + +"@unrs/resolver-binding-freebsd-x64@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-freebsd-x64/-/resolver-binding-freebsd-x64-1.11.1.tgz#d2513084d0f37c407757e22f32bd924a78cfd99b" + integrity sha512-fqtGgak3zX4DCB6PFpsH5+Kmt/8CIi4Bry4rb1ho6Av2QHTREM+47y282Uqiu3ZRF5IQioJQ5qWRV6jduA+iGw== + +"@unrs/resolver-binding-linux-arm-gnueabihf@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-linux-arm-gnueabihf/-/resolver-binding-linux-arm-gnueabihf-1.11.1.tgz#844d2605d057488d77fab09705f2866b86164e0a" + integrity sha512-u92mvlcYtp9MRKmP+ZvMmtPN34+/3lMHlyMj7wXJDeXxuM0Vgzz0+PPJNsro1m3IZPYChIkn944wW8TYgGKFHw== + +"@unrs/resolver-binding-linux-arm-musleabihf@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-linux-arm-musleabihf/-/resolver-binding-linux-arm-musleabihf-1.11.1.tgz#204892995cefb6bd1d017d52d097193bc61ddad3" + integrity sha512-cINaoY2z7LVCrfHkIcmvj7osTOtm6VVT16b5oQdS4beibX2SYBwgYLmqhBjA1t51CarSaBuX5YNsWLjsqfW5Cw== + +"@unrs/resolver-binding-linux-arm64-gnu@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-linux-arm64-gnu/-/resolver-binding-linux-arm64-gnu-1.11.1.tgz#023eb0c3aac46066a10be7a3f362e7b34f3bdf9d" + integrity sha512-34gw7PjDGB9JgePJEmhEqBhWvCiiWCuXsL9hYphDF7crW7UgI05gyBAi6MF58uGcMOiOqSJ2ybEeCvHcq0BCmQ== + +"@unrs/resolver-binding-linux-arm64-musl@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-linux-arm64-musl/-/resolver-binding-linux-arm64-musl-1.11.1.tgz#9e6f9abb06424e3140a60ac996139786f5d99be0" + integrity sha512-RyMIx6Uf53hhOtJDIamSbTskA99sPHS96wxVE/bJtePJJtpdKGXO1wY90oRdXuYOGOTuqjT8ACccMc4K6QmT3w== + +"@unrs/resolver-binding-linux-ppc64-gnu@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-linux-ppc64-gnu/-/resolver-binding-linux-ppc64-gnu-1.11.1.tgz#b111417f17c9d1b02efbec8e08398f0c5527bb44" + integrity sha512-D8Vae74A4/a+mZH0FbOkFJL9DSK2R6TFPC9M+jCWYia/q2einCubX10pecpDiTmkJVUH+y8K3BZClycD8nCShA== + +"@unrs/resolver-binding-linux-riscv64-gnu@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-linux-riscv64-gnu/-/resolver-binding-linux-riscv64-gnu-1.11.1.tgz#92ffbf02748af3e99873945c9a8a5ead01d508a9" + integrity sha512-frxL4OrzOWVVsOc96+V3aqTIQl1O2TjgExV4EKgRY09AJ9leZpEg8Ak9phadbuX0BA4k8U5qtvMSQQGGmaJqcQ== + +"@unrs/resolver-binding-linux-riscv64-musl@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-linux-riscv64-musl/-/resolver-binding-linux-riscv64-musl-1.11.1.tgz#0bec6f1258fc390e6b305e9ff44256cb207de165" + integrity sha512-mJ5vuDaIZ+l/acv01sHoXfpnyrNKOk/3aDoEdLO/Xtn9HuZlDD6jKxHlkN8ZhWyLJsRBxfv9GYM2utQ1SChKew== + +"@unrs/resolver-binding-linux-s390x-gnu@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-linux-s390x-gnu/-/resolver-binding-linux-s390x-gnu-1.11.1.tgz#577843a084c5952f5906770633ccfb89dac9bc94" + integrity sha512-kELo8ebBVtb9sA7rMe1Cph4QHreByhaZ2QEADd9NzIQsYNQpt9UkM9iqr2lhGr5afh885d/cB5QeTXSbZHTYPg== + +"@unrs/resolver-binding-linux-x64-gnu@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-linux-x64-gnu/-/resolver-binding-linux-x64-gnu-1.11.1.tgz#36fb318eebdd690f6da32ac5e0499a76fa881935" + integrity sha512-C3ZAHugKgovV5YvAMsxhq0gtXuwESUKc5MhEtjBpLoHPLYM+iuwSj3lflFwK3DPm68660rZ7G8BMcwSro7hD5w== + +"@unrs/resolver-binding-linux-x64-musl@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-linux-x64-musl/-/resolver-binding-linux-x64-musl-1.11.1.tgz#bfb9af75f783f98f6a22c4244214efe4df1853d6" + integrity sha512-rV0YSoyhK2nZ4vEswT/QwqzqQXw5I6CjoaYMOX0TqBlWhojUf8P94mvI7nuJTeaCkkds3QE4+zS8Ko+GdXuZtA== + +"@unrs/resolver-binding-wasm32-wasi@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-wasm32-wasi/-/resolver-binding-wasm32-wasi-1.11.1.tgz#752c359dd875684b27429500d88226d7cc72f71d" + integrity sha512-5u4RkfxJm+Ng7IWgkzi3qrFOvLvQYnPBmjmZQ8+szTK/b31fQCnleNl1GgEt7nIsZRIf5PLhPwT0WM+q45x/UQ== + dependencies: + "@napi-rs/wasm-runtime" "^0.2.11" + +"@unrs/resolver-binding-win32-arm64-msvc@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-win32-arm64-msvc/-/resolver-binding-win32-arm64-msvc-1.11.1.tgz#ce5735e600e4c2fbb409cd051b3b7da4a399af35" + integrity sha512-nRcz5Il4ln0kMhfL8S3hLkxI85BXs3o8EYoattsJNdsX4YUU89iOkVn7g0VHSRxFuVMdM4Q1jEpIId1Ihim/Uw== + +"@unrs/resolver-binding-win32-ia32-msvc@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-win32-ia32-msvc/-/resolver-binding-win32-ia32-msvc-1.11.1.tgz#72fc57bc7c64ec5c3de0d64ee0d1810317bc60a6" + integrity sha512-DCEI6t5i1NmAZp6pFonpD5m7i6aFrpofcp4LA2i8IIq60Jyo28hamKBxNrZcyOwVOZkgsRp9O2sXWBWP8MnvIQ== + +"@unrs/resolver-binding-win32-x64-msvc@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-win32-x64-msvc/-/resolver-binding-win32-x64-msvc-1.11.1.tgz#538b1e103bf8d9864e7b85cc96fa8d6fb6c40777" + integrity sha512-lrW200hZdbfRtztbygyaq/6jP6AKE8qQN2KvPcJ+x7wiD038YtnYtZ82IMNJ69GJibV7bwL3y9FgK+5w/pYt6g== + +"@uphold/request-logger@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@uphold/request-logger/-/request-logger-2.0.0.tgz#c585c0bdb94210198945c6597e4fe23d6e63e084" + integrity sha512-UvGS+v87C7VTtQDcFHDLfvfl1zaZaLSwSmAnV35Ne7CzAVvotmZqt9lAIoNpMpaoRpdjVIcnUDwPSeIeA//EoQ== + dependencies: + uuid "^3.0.1" + +abitype@1.1.0, abitype@^1.0.9: + version "1.1.0" + resolved "https://registry.yarnpkg.com/abitype/-/abitype-1.1.0.tgz#510c5b3f92901877977af5e864841f443bf55406" + integrity sha512-6Vh4HcRxNMLA0puzPjM5GBgT4aAcFGKZzSgAXvuZ27shJP6NEpielTuqbBmZILR5/xd0PizkBGy5hReKz9jl5A== + +acorn-walk@^8.1.1: + version "8.3.4" + resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.3.4.tgz#794dd169c3977edf4ba4ea47583587c5866236b7" + integrity sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g== + dependencies: + acorn "^8.11.0" + +acorn@^8.11.0, acorn@^8.4.1: + version "8.15.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.15.0.tgz#a360898bc415edaac46c8241f6383975b930b816" + integrity sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg== + +aes-js@4.0.0-beta.5: + version "4.0.0-beta.5" + resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-4.0.0-beta.5.tgz#8d2452c52adedebc3a3e28465d858c11ca315873" + integrity sha512-G965FqalsNyrPqgEGON7nIx1e/OVENSgiEIzyC63haUMuvNnwIgIjMs52hlTCKhkBny7A2ORNlfY9Zu+jmGk1Q== + +ajv@^6.12.3: + version "6.12.6" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" + integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== + dependencies: + fast-deep-equal "^3.1.1" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.2" + +ansi-escapes@^4.3.2: + version "4.3.2" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e" + integrity sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ== + dependencies: + type-fest "^0.21.3" + +ansi-regex@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" + integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== + +ansi-regex@^6.0.1: + version "6.2.2" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-6.2.2.tgz#60216eea464d864597ce2832000738a0589650c1" + integrity sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg== + +ansi-styles@^4.0.0, ansi-styles@^4.1.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" + integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== + dependencies: + color-convert "^2.0.1" + +ansi-styles@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-5.2.0.tgz#07449690ad45777d1924ac2abb2fc8895dba836b" + integrity sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA== + +ansi-styles@^6.1.0: + version "6.2.3" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.2.3.tgz#c044d5dcc521a076413472597a1acb1f103c4041" + integrity sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg== + +anymatch@^3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" + integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== + dependencies: + normalize-path "^3.0.0" + picomatch "^2.0.4" + +arg@^4.1.0: + version "4.1.3" + resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089" + integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA== + +argparse@^1.0.7: + version "1.0.10" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" + integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== + dependencies: + sprintf-js "~1.0.2" + +asn1@~0.2.3: + version "0.2.6" + resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.6.tgz#0d3a7bb6e64e02a90c0303b31f292868ea09a08d" + integrity sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ== + dependencies: + safer-buffer "~2.1.0" + +assert-plus@1.0.0, assert-plus@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" + integrity sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw== + +asynckit@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" + integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== + +aws-sign2@~0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" + integrity sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA== + +aws4@^1.8.0: + version "1.13.2" + resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.13.2.tgz#0aa167216965ac9474ccfa83892cfb6b3e1e52ef" + integrity sha512-lHe62zvbTB5eEABUVi/AwVh0ZKY9rMMDhmm+eeyuuUQbQ3+J+fONVQOZyj+DdrvD4BY33uYniyRJ4UJIaSKAfw== + +babel-jest@30.1.2: + version "30.1.2" + resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-30.1.2.tgz#decd53b3a0cafca49443f93fb7a2c0fba55510da" + integrity sha512-IQCus1rt9kaSh7PQxLYRY5NmkNrNlU2TpabzwV7T2jljnpdHOcmnYYv8QmE04Li4S3a2Lj8/yXyET5pBarPr6g== + dependencies: + "@jest/transform" "30.1.2" + "@types/babel__core" "^7.20.5" + babel-plugin-istanbul "^7.0.0" + babel-preset-jest "30.0.1" + chalk "^4.1.2" + graceful-fs "^4.2.11" + slash "^3.0.0" + +babel-plugin-istanbul@^7.0.0: + version "7.0.1" + resolved "https://registry.yarnpkg.com/babel-plugin-istanbul/-/babel-plugin-istanbul-7.0.1.tgz#d8b518c8ea199364cf84ccc82de89740236daf92" + integrity sha512-D8Z6Qm8jCvVXtIRkBnqNHX0zJ37rQcFJ9u8WOS6tkYOsRdHBzypCstaxWiu5ZIlqQtviRYbgnRLSoCEvjqcqbA== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@istanbuljs/load-nyc-config" "^1.0.0" + "@istanbuljs/schema" "^0.1.3" + istanbul-lib-instrument "^6.0.2" + test-exclude "^6.0.0" + +babel-plugin-jest-hoist@30.0.1: + version "30.0.1" + resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-30.0.1.tgz#f271b2066d2c1fb26a863adb8e13f85b06247125" + integrity sha512-zTPME3pI50NsFW8ZBaVIOeAxzEY7XHlmWeXXu9srI+9kNfzCUTy8MFan46xOGZY8NZThMqq+e3qZUKsvXbasnQ== + dependencies: + "@babel/template" "^7.27.2" + "@babel/types" "^7.27.3" + "@types/babel__core" "^7.20.5" + +babel-preset-current-node-syntax@^1.1.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.2.0.tgz#20730d6cdc7dda5d89401cab10ac6a32067acde6" + integrity sha512-E/VlAEzRrsLEb2+dv8yp3bo4scof3l9nR4lrld+Iy5NyVqgVYUJnDAmunkhPMisRI32Qc4iRiz425d8vM++2fg== + dependencies: + "@babel/plugin-syntax-async-generators" "^7.8.4" + "@babel/plugin-syntax-bigint" "^7.8.3" + "@babel/plugin-syntax-class-properties" "^7.12.13" + "@babel/plugin-syntax-class-static-block" "^7.14.5" + "@babel/plugin-syntax-import-attributes" "^7.24.7" + "@babel/plugin-syntax-import-meta" "^7.10.4" + "@babel/plugin-syntax-json-strings" "^7.8.3" + "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" + "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" + "@babel/plugin-syntax-numeric-separator" "^7.10.4" + "@babel/plugin-syntax-object-rest-spread" "^7.8.3" + "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" + "@babel/plugin-syntax-optional-chaining" "^7.8.3" + "@babel/plugin-syntax-private-property-in-object" "^7.14.5" + "@babel/plugin-syntax-top-level-await" "^7.14.5" + +babel-preset-jest@30.0.1: + version "30.0.1" + resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-30.0.1.tgz#7d28db9531bce264e846c8483d54236244b8ae88" + integrity sha512-+YHejD5iTWI46cZmcc/YtX4gaKBtdqCHCVfuVinizVpbmyjO3zYmeuyFdfA8duRqQZfgCAMlsfmkVbJ+e2MAJw== + dependencies: + babel-plugin-jest-hoist "30.0.1" + babel-preset-current-node-syntax "^1.1.0" + +balanced-match@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" + integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== + +base-x@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/base-x/-/base-x-4.0.1.tgz#817fb7b57143c501f649805cb247617ad016a885" + integrity sha512-uAZ8x6r6S3aUM9rbHGVOIsR15U/ZSc82b3ymnCPsT45Gk1DDvhDPdIgB5MrhirZWt+5K0EEPQH985kNqZgNPFw== + +baseline-browser-mapping@^2.8.3: + version "2.8.6" + resolved "https://registry.yarnpkg.com/baseline-browser-mapping/-/baseline-browser-mapping-2.8.6.tgz#c37dea4291ed8d01682f85661dbe87967028642e" + integrity sha512-wrH5NNqren/QMtKUEEJf7z86YjfqW/2uw3IL3/xpqZUC95SSVIFXYQeeGjL6FT/X68IROu6RMehZQS5foy2BXw== + +bcrypt-pbkdf@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" + integrity sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w== + dependencies: + tweetnacl "^0.14.3" + +bech32@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/bech32/-/bech32-2.0.0.tgz#078d3686535075c8c79709f054b1b226a133b355" + integrity sha512-LcknSilhIGatDAsY1ak2I8VtGaHNhgMSYVxFrGLXv+xLHytaKZKcaUJJUE7qmBr7h33o5YQwP55pMI0xmkpJwg== + +bignumber.js@^9.0.0: + version "9.3.1" + resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-9.3.1.tgz#759c5aaddf2ffdc4f154f7b493e1c8770f88c4d7" + integrity sha512-Ko0uX15oIUS7wJ3Rb30Fs6SkVbLmPBAKdlm7q9+ak9bbIeFf0MwuBsQV6z7+X768/cHsfg+WlysDWJcmthjsjQ== + +bip174@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/bip174/-/bip174-2.1.1.tgz#ef3e968cf76de234a546962bcf572cc150982f9f" + integrity sha512-mdFV5+/v0XyNYXjBS6CQPLo9ekCx4gtKZFnJm5PMto7Fs9hTTDpkkzOB7/FtluRI6JbUUAu+snTYfJRgHLZbZQ== + +bitcoin-core@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/bitcoin-core/-/bitcoin-core-5.0.0.tgz#6ae38e457814f55ee37c5fa6a5b33c48d9ca8f2d" + integrity sha512-XqHsD5LjtshN8yWzRrq2kof57e1eXCGDx3i5+sFKBRi9MktSlXOR4SRLyXLkfzfBmPEs5q/76RotQJuaWg75DQ== + dependencies: + "@uphold/request-logger" "^2.0.0" + debugnyan "^1.0.0" + json-bigint "^1.0.0" + lodash "^4.0.0" + request "^2.53.0" + semver "^5.1.0" + standard-error "^1.1.0" + +bitcoin-regtest@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/bitcoin-regtest/-/bitcoin-regtest-1.0.1.tgz#953591e77cf6db16a459e5565f73350337c8818e" + integrity sha512-BYQuendqQAdBl1jRZ4qytTdCqAoKrQcMHmlLcY/K74BBzrNIJNqlhWbY70zimHnIBFI1vUOV5aMoSm6JQFq6pA== + dependencies: + bitcoin-core "^5.0.0" + +bitcoinjs-lib@^6.1.6: + version "6.1.7" + resolved "https://registry.yarnpkg.com/bitcoinjs-lib/-/bitcoinjs-lib-6.1.7.tgz#0f98dec1333d658574eefa455295668cfae38bb0" + integrity sha512-tlf/r2DGMbF7ky1MgUqXHzypYHakkEnm0SZP23CJKIqNY/5uNAnMbFhMJdhjrL/7anfb/U8+AlpdjPWjPnAalg== + dependencies: + "@noble/hashes" "^1.2.0" + bech32 "^2.0.0" + bip174 "^2.1.1" + bs58check "^3.0.1" + typeforce "^1.11.3" + varuint-bitcoin "^1.1.2" + +bn.js@^4.11.9: + version "4.12.2" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.2.tgz#3d8fed6796c24e177737f7cc5172ee04ef39ec99" + integrity sha512-n4DSx829VRTRByMRGdjQ9iqsN0Bh4OolPsFnaZBLcbi8iXcB+kJ9s7EnRt4wILZNV3kPLHkRVfOc/HvhC3ovDw== + +bn.js@^5.2.1: + version "5.2.2" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.2.tgz#82c09f9ebbb17107cd72cb7fd39bd1f9d0aaa566" + integrity sha512-v2YAxEmKaBLahNwE1mjp4WON6huMNeuDvagFZW+ASCuA/ku0bXR9hSMw0XpiqMoA3+rmnyck/tPRSFQkoC9Cuw== + +brace-expansion@^1.1.7: + version "1.1.12" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.12.tgz#ab9b454466e5a8cc3a187beaad580412a9c5b843" + integrity sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg== + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +brace-expansion@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.2.tgz#54fc53237a613d854c7bd37463aad17df87214e7" + integrity sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ== + dependencies: + balanced-match "^1.0.0" + +braces@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.3.tgz#490332f40919452272d55a8480adc0c441358789" + integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA== + dependencies: + fill-range "^7.1.1" + +brorand@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" + integrity sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w== + +browserslist@^4.24.0: + version "4.26.2" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.26.2.tgz#7db3b3577ec97f1140a52db4936654911078cef3" + integrity sha512-ECFzp6uFOSB+dcZ5BK/IBaGWssbSYBHvuMeMt3MMFyhI0Z8SqGgEkBLARgpRH3hutIgPVsALcMwbDrJqPxQ65A== + dependencies: + baseline-browser-mapping "^2.8.3" + caniuse-lite "^1.0.30001741" + electron-to-chromium "^1.5.218" + node-releases "^2.0.21" + update-browserslist-db "^1.1.3" + +bs-logger@^0.2.6: + version "0.2.6" + resolved "https://registry.yarnpkg.com/bs-logger/-/bs-logger-0.2.6.tgz#eb7d365307a72cf974cc6cda76b68354ad336bd8" + integrity sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog== + dependencies: + fast-json-stable-stringify "2.x" + +bs58@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/bs58/-/bs58-5.0.0.tgz#865575b4d13c09ea2a84622df6c8cbeb54ffc279" + integrity sha512-r+ihvQJvahgYT50JD05dyJNKlmmSlMoOGwn1lCcEzanPglg7TxYjioQUYehQ9mAR/+hOSd2jRc/Z2y5UxBymvQ== + dependencies: + base-x "^4.0.0" + +bs58check@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/bs58check/-/bs58check-3.0.1.tgz#2094d13720a28593de1cba1d8c4e48602fdd841c" + integrity sha512-hjuuJvoWEybo7Hn/0xOrczQKKEKD63WguEjlhLExYs2wUBcebDC1jDNK17eEAD2lYfw82d5ASC1d7K3SWszjaQ== + dependencies: + "@noble/hashes" "^1.2.0" + bs58 "^5.0.0" + +bser@2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/bser/-/bser-2.1.1.tgz#e6787da20ece9d07998533cfd9de6f5c38f4bc05" + integrity sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ== + dependencies: + node-int64 "^0.4.0" + +buffer-from@^1.0.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" + integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== + +bunyan@^1.8.1: + version "1.8.15" + resolved "https://registry.yarnpkg.com/bunyan/-/bunyan-1.8.15.tgz#8ce34ca908a17d0776576ca1b2f6cbd916e93b46" + integrity sha512-0tECWShh6wUysgucJcBAoYegf3JJoZWibxdqhTm7OHPeT42qdjkZ29QCMcKwbgU1kiH+auSIasNRXMLWXafXig== + optionalDependencies: + dtrace-provider "~0.8" + moment "^2.19.3" + mv "~2" + safe-json-stringify "~1" + +callsites@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" + integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== + +camelcase@^5.3.1: + version "5.3.1" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" + integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== + +camelcase@^6.3.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" + integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== + +caniuse-lite@^1.0.30001741: + version "1.0.30001743" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001743.tgz#50ff91a991220a1ee2df5af00650dd5c308ea7cd" + integrity sha512-e6Ojr7RV14Un7dz6ASD0aZDmQPT/A+eZU+nuTNfjqmRrmkmQlnTNWH0SKmqagx9PeW87UVqapSurtAXifmtdmw== + +caseless@~0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" + integrity sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw== + +chalk@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" + integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + +char-regex@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/char-regex/-/char-regex-1.0.2.tgz#d744358226217f981ed58f479b1d6bcc29545dcf" + integrity sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw== + +ci-info@^4.2.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-4.3.0.tgz#c39b1013f8fdbd28cd78e62318357d02da160cd7" + integrity sha512-l+2bNRMiQgcfILUi33labAZYIWlH1kWDp+ecNo5iisRKrbm0xcRyCww71/YU0Fkw0mAFpz9bJayXPjey6vkmaQ== + +cjs-module-lexer@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/cjs-module-lexer/-/cjs-module-lexer-2.1.0.tgz#586e87d4341cb2661850ece5190232ccdebcff8b" + integrity sha512-UX0OwmYRYQQetfrLEZeewIFFI+wSTofC+pMBLNuH3RUuu/xzG1oz84UCEDOSoQlN3fZ4+AzmV50ZYvGqkMh9yA== + +cliui@^8.0.1: + version "8.0.1" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-8.0.1.tgz#0c04b075db02cbfe60dc8e6cf2f5486b1a3608aa" + integrity sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.1" + wrap-ansi "^7.0.0" + +co@^4.6.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" + integrity sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ== + +coinselect@^3.1.13: + version "3.1.13" + resolved "https://registry.yarnpkg.com/coinselect/-/coinselect-3.1.13.tgz#b88c7f9659ed4891d1f1d0c894105b1c10ef89a1" + integrity sha512-iJOrKH/7N9gX0jRkxgOHuGjvzvoxUMSeylDhH1sHn+CjLjdin5R0Hz2WEBu/jrZV5OrHcm+6DMzxwu9zb5mSZg== + +collect-v8-coverage@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz#c0b29bcd33bcd0779a1344c2136051e6afd3d9e9" + integrity sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q== + +color-convert@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" + integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== + dependencies: + color-name "~1.1.4" + +color-name@~1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" + integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== + +combined-stream@^1.0.6, combined-stream@~1.0.6: + version "1.0.8" + resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" + integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== + dependencies: + delayed-stream "~1.0.0" + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== + +convert-source-map@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-2.0.0.tgz#4b560f649fc4e918dd0ab75cf4961e8bc882d82a" + integrity sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg== + +core-util-is@1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" + integrity sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ== + +create-require@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" + integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== + +cross-spawn@^7.0.3, cross-spawn@^7.0.6: + version "7.0.6" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.6.tgz#8a58fe78f00dcd70c370451759dfbfaf03e8ee9f" + integrity sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA== + dependencies: + path-key "^3.1.0" + shebang-command "^2.0.0" + which "^2.0.1" + +dashdash@^1.12.0: + version "1.14.1" + resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" + integrity sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g== + dependencies: + assert-plus "^1.0.0" + +data-uri-to-buffer@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz#d8feb2b2881e6a4f58c2e08acfd0e2834e26222e" + integrity sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A== + +debug@^2.2.0: + version "2.6.9" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" + integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== + dependencies: + ms "2.0.0" + +debug@^4.1.0, debug@^4.1.1, debug@^4.3.1: + version "4.4.3" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.3.tgz#c6ae432d9bd9662582fce08709b038c58e9e3d6a" + integrity sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA== + dependencies: + ms "^2.1.3" + +debugnyan@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/debugnyan/-/debugnyan-1.0.0.tgz#90386d5ebc2c63588f17f272be5c2a93b7665d83" + integrity sha512-dTvKxcLZCammDLFYi31NRVr5g6vjJ33uf1wcdbIPPxPxxnJ9/xj00Mh/YQkhFMw/VGavaG5KpjSC+4o9r/JjRg== + dependencies: + bunyan "^1.8.1" + debug "^2.2.0" + +dedent@^1.6.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/dedent/-/dedent-1.7.0.tgz#c1f9445335f0175a96587be245a282ff451446ca" + integrity sha512-HGFtf8yhuhGhqO07SV79tRp+br4MnbdjeVxotpn1QBl30pcLLCQjX5b2295ll0fv8RKDKsmWYrl05usHM9CewQ== + +deepmerge@^4.3.1: + version "4.3.1" + resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.3.1.tgz#44b5f2147cd3b00d4b56137685966f26fd25dd4a" + integrity sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A== + +delayed-stream@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== + +detect-newline@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-3.1.0.tgz#576f5dfc63ae1a192ff192d8ad3af6308991b651" + integrity sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA== + +diff@^4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" + integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== + +dtrace-provider@~0.8: + version "0.8.8" + resolved "https://registry.yarnpkg.com/dtrace-provider/-/dtrace-provider-0.8.8.tgz#2996d5490c37e1347be263b423ed7b297fb0d97e" + integrity sha512-b7Z7cNtHPhH9EJhNNbbeqTcXB8LGFFZhq1PGgEvpeHlzd36bhbdTWoE/Ba/YguqpBSlAPKnARWhVlhunCMwfxg== + dependencies: + nan "^2.14.0" + +eastasianwidth@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb" + integrity sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA== + +ecc-jsbn@~0.1.1: + version "0.1.2" + resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9" + integrity sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw== + dependencies: + jsbn "~0.1.0" + safer-buffer "^2.1.0" + +electron-to-chromium@^1.5.218: + version "1.5.222" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.222.tgz#965c93783ad989116b74593ae3068b9466fdb237" + integrity sha512-gA7psSwSwQRE60CEoLz6JBCQPIxNeuzB2nL8vE03GK/OHxlvykbLyeiumQy1iH5C2f3YbRAZpGCMT12a/9ih9w== + +elliptic@^6.6.1: + version "6.6.1" + resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.6.1.tgz#3b8ffb02670bf69e382c7f65bf524c97c5405c06" + integrity sha512-RaddvvMatK2LJHqFJ+YA4WysVN5Ita9E35botqIYspQ4TkRAlCicdzKOjlyv/1Za5RyTNn7di//eEV0uTAfe3g== + dependencies: + bn.js "^4.11.9" + brorand "^1.1.0" + hash.js "^1.0.0" + hmac-drbg "^1.0.1" + inherits "^2.0.4" + minimalistic-assert "^1.0.1" + minimalistic-crypto-utils "^1.0.1" + +emittery@^0.13.1: + version "0.13.1" + resolved "https://registry.yarnpkg.com/emittery/-/emittery-0.13.1.tgz#c04b8c3457490e0847ae51fced3af52d338e3dad" + integrity sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ== + +emoji-regex@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" + integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== + +emoji-regex@^9.2.2: + version "9.2.2" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72" + integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg== + +error-ex@^1.3.1: + version "1.3.4" + resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.4.tgz#b3a8d8bb6f92eecc1629e3e27d3c8607a8a32414" + integrity sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ== + dependencies: + is-arrayish "^0.2.1" + +escalade@^3.1.1, escalade@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.2.0.tgz#011a3f69856ba189dffa7dc8fcce99d2a87903e5" + integrity sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA== + +escape-string-regexp@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz#a30304e99daa32e23b2fd20f51babd07cffca344" + integrity sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w== + +esprima@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" + integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== + +ethers@^6.15.0: + version "6.15.0" + resolved "https://registry.yarnpkg.com/ethers/-/ethers-6.15.0.tgz#2980f2a3baf0509749b7e21f8692fa8a8349c0e3" + integrity sha512-Kf/3ZW54L4UT0pZtsY/rf+EkBU7Qi5nnhonjUb8yTXcxH3cdcWrV2cRyk0Xk/4jK6OoHhxxZHriyhje20If2hQ== + dependencies: + "@adraffy/ens-normalize" "1.10.1" + "@noble/curves" "1.2.0" + "@noble/hashes" "1.3.2" + "@types/node" "22.7.5" + aes-js "4.0.0-beta.5" + tslib "2.7.0" + ws "8.17.1" + +eventemitter3@5.0.1, eventemitter3@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-5.0.1.tgz#53f5ffd0a492ac800721bb42c66b841de96423c4" + integrity sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA== + +execa@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd" + integrity sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg== + dependencies: + cross-spawn "^7.0.3" + get-stream "^6.0.0" + human-signals "^2.1.0" + is-stream "^2.0.0" + merge-stream "^2.0.0" + npm-run-path "^4.0.1" + onetime "^5.1.2" + signal-exit "^3.0.3" + strip-final-newline "^2.0.0" + +exit-x@^0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/exit-x/-/exit-x-0.2.2.tgz#1f9052de3b8d99a696b10dad5bced9bdd5c3aa64" + integrity sha512-+I6B/IkJc1o/2tiURyz/ivu/O0nKNEArIUB5O7zBrlDVJr22SCLH3xTeEry428LvFhRzIA1g8izguxJ/gbNcVQ== + +expect@30.1.2, expect@^30.0.0: + version "30.1.2" + resolved "https://registry.yarnpkg.com/expect/-/expect-30.1.2.tgz#094909c2443f76b9e208fafac4a315aaaf924580" + integrity sha512-xvHszRavo28ejws8FpemjhwswGj4w/BetHIL8cU49u4sGyXDw2+p3YbeDbj6xzlxi6kWTjIRSTJ+9sNXPnF0Zg== + dependencies: + "@jest/expect-utils" "30.1.2" + "@jest/get-type" "30.1.0" + jest-matcher-utils "30.1.2" + jest-message-util "30.1.0" + jest-mock "30.0.5" + jest-util "30.0.5" + +extend@~3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" + integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== + +extsprintf@1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" + integrity sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g== + +extsprintf@^1.2.0: + version "1.4.1" + resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.1.tgz#8d172c064867f235c0c84a596806d279bf4bcc07" + integrity sha512-Wrk35e8ydCKDj/ArClo1VrPVmN8zph5V4AtHwIuHhvMXsKf73UT3BOD+azBIW+3wOJ4FhEH7zyaJCFvChjYvMA== + +fast-deep-equal@^3.1.1: + version "3.1.3" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" + integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== + +fast-json-stable-stringify@2.x, fast-json-stable-stringify@^2.0.0, fast-json-stable-stringify@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" + integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== + +fb-watchman@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/fb-watchman/-/fb-watchman-2.0.2.tgz#e9524ee6b5c77e9e5001af0f85f3adbb8623255c" + integrity sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA== + dependencies: + bser "2.1.1" + +fetch-blob@^3.1.2, fetch-blob@^3.1.4: + version "3.2.0" + resolved "https://registry.yarnpkg.com/fetch-blob/-/fetch-blob-3.2.0.tgz#f09b8d4bbd45adc6f0c20b7e787e793e309dcce9" + integrity sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ== + dependencies: + node-domexception "^1.0.0" + web-streams-polyfill "^3.0.3" + +fill-range@^7.1.1: + version "7.1.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292" + integrity sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg== + dependencies: + to-regex-range "^5.0.1" + +find-up@^4.0.0, find-up@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" + integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== + dependencies: + locate-path "^5.0.0" + path-exists "^4.0.0" + +foreground-child@^3.1.0: + version "3.3.1" + resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-3.3.1.tgz#32e8e9ed1b68a3497befb9ac2b6adf92a638576f" + integrity sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw== + dependencies: + cross-spawn "^7.0.6" + signal-exit "^4.0.1" + +forever-agent@~0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" + integrity sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw== + +form-data@~2.3.2: + version "2.3.3" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6" + integrity sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.6" + mime-types "^2.1.12" + +formdata-polyfill@^4.0.10: + version "4.0.10" + resolved "https://registry.yarnpkg.com/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz#24807c31c9d402e002ab3d8c720144ceb8848423" + integrity sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g== + dependencies: + fetch-blob "^3.1.2" + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== + +fsevents@^2.3.3: + version "2.3.3" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" + integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== + +gensync@^1.0.0-beta.2: + version "1.0.0-beta.2" + resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" + integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== + +get-caller-file@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" + integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== + +get-package-type@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/get-package-type/-/get-package-type-0.1.0.tgz#8de2d803cff44df3bc6c456e6668b36c3926e11a" + integrity sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q== + +get-stream@^6.0.0: + version "6.0.1" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7" + integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg== + +getpass@^0.1.1: + version "0.1.7" + resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" + integrity sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng== + dependencies: + assert-plus "^1.0.0" + +glob@^10.3.10: + version "10.4.5" + resolved "https://registry.yarnpkg.com/glob/-/glob-10.4.5.tgz#f4d9f0b90ffdbab09c9d77f5f29b4262517b0956" + integrity sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg== + dependencies: + foreground-child "^3.1.0" + jackspeak "^3.1.2" + minimatch "^9.0.4" + minipass "^7.1.2" + package-json-from-dist "^1.0.0" + path-scurry "^1.11.1" + +glob@^6.0.1: + version "6.0.4" + resolved "https://registry.yarnpkg.com/glob/-/glob-6.0.4.tgz#0f08860f6a155127b2fadd4f9ce24b1aab6e4d22" + integrity sha512-MKZeRNyYZAVVVG1oZeLaWie1uweH40m9AZwIwxyPbTSX4hHrVYSzLg0Ro5Z5R7XKkIX+Cc6oD1rqeDJnwsB8/A== + dependencies: + inflight "^1.0.4" + inherits "2" + minimatch "2 || 3" + once "^1.3.0" + path-is-absolute "^1.0.0" + +glob@^7.1.4: + version "7.2.3" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" + integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.1.1" + once "^1.3.0" + path-is-absolute "^1.0.0" + +graceful-fs@^4.2.11: + version "4.2.11" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" + integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== + +handlebars@^4.7.8: + version "4.7.8" + resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.7.8.tgz#41c42c18b1be2365439188c77c6afae71c0cd9e9" + integrity sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ== + dependencies: + minimist "^1.2.5" + neo-async "^2.6.2" + source-map "^0.6.1" + wordwrap "^1.0.0" + optionalDependencies: + uglify-js "^3.1.4" + +har-schema@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" + integrity sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q== + +har-validator@~5.1.3: + version "5.1.5" + resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.5.tgz#1f0803b9f8cb20c0fa13822df1ecddb36bde1efd" + integrity sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w== + dependencies: + ajv "^6.12.3" + har-schema "^2.0.0" + +has-flag@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" + integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== + +hash.js@^1.0.0, hash.js@^1.0.3: + version "1.1.7" + resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.7.tgz#0babca538e8d4ee4a0f8988d68866537a003cf42" + integrity sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA== + dependencies: + inherits "^2.0.3" + minimalistic-assert "^1.0.1" + +hmac-drbg@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" + integrity sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg== + dependencies: + hash.js "^1.0.3" + minimalistic-assert "^1.0.0" + minimalistic-crypto-utils "^1.0.1" + +html-escaper@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453" + integrity sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg== + +http-signature@~1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" + integrity sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ== + dependencies: + assert-plus "^1.0.0" + jsprim "^1.2.2" + sshpk "^1.7.0" + +human-signals@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" + integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw== + +import-local@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/import-local/-/import-local-3.2.0.tgz#c3d5c745798c02a6f8b897726aba5100186ee260" + integrity sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA== + dependencies: + pkg-dir "^4.2.0" + resolve-cwd "^3.0.0" + +imurmurhash@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" + integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA== + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2, inherits@^2.0.3, inherits@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + +is-arrayish@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" + integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg== + +is-fullwidth-code-point@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" + integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== + +is-generator-fn@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-generator-fn/-/is-generator-fn-2.1.0.tgz#7d140adc389aaf3011a8f2a2a4cfa6faadffb118" + integrity sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ== + +is-number@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" + integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== + +is-stream@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077" + integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg== + +is-typedarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" + integrity sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA== + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== + +isows@1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/isows/-/isows-1.0.7.tgz#1c06400b7eed216fbba3bcbd68f12490fc342915" + integrity sha512-I1fSfDCZL5P0v33sVqeTDSpcstAg/N+wF5HS033mogOVIp4B+oHC7oOCsA3axAbBSGTJ8QubbNmnIRN/h8U7hg== + +isstream@~0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" + integrity sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g== + +istanbul-lib-coverage@^3.0.0, istanbul-lib-coverage@^3.2.0: + version "3.2.2" + resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz#2d166c4b0644d43a39f04bf6c2edd1e585f31756" + integrity sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg== + +istanbul-lib-instrument@^6.0.0, istanbul-lib-instrument@^6.0.2: + version "6.0.3" + resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.3.tgz#fa15401df6c15874bcb2105f773325d78c666765" + integrity sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q== + dependencies: + "@babel/core" "^7.23.9" + "@babel/parser" "^7.23.9" + "@istanbuljs/schema" "^0.1.3" + istanbul-lib-coverage "^3.2.0" + semver "^7.5.4" + +istanbul-lib-report@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz#908305bac9a5bd175ac6a74489eafd0fc2445a7d" + integrity sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw== + dependencies: + istanbul-lib-coverage "^3.0.0" + make-dir "^4.0.0" + supports-color "^7.1.0" + +istanbul-lib-source-maps@^5.0.0: + version "5.0.6" + resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-5.0.6.tgz#acaef948df7747c8eb5fbf1265cb980f6353a441" + integrity sha512-yg2d+Em4KizZC5niWhQaIomgf5WlL4vOOjZ5xGCmF8SnPE/mDWWXgvRExdcpCgh9lLRRa1/fSYp2ymmbJ1pI+A== + dependencies: + "@jridgewell/trace-mapping" "^0.3.23" + debug "^4.1.1" + istanbul-lib-coverage "^3.0.0" + +istanbul-reports@^3.1.3: + version "3.2.0" + resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-3.2.0.tgz#cb4535162b5784aa623cee21a7252cf2c807ac93" + integrity sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA== + dependencies: + html-escaper "^2.0.0" + istanbul-lib-report "^3.0.0" + +jackspeak@^3.1.2: + version "3.4.3" + resolved "https://registry.yarnpkg.com/jackspeak/-/jackspeak-3.4.3.tgz#8833a9d89ab4acde6188942bd1c53b6390ed5a8a" + integrity sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw== + dependencies: + "@isaacs/cliui" "^8.0.2" + optionalDependencies: + "@pkgjs/parseargs" "^0.11.0" + +jest-changed-files@30.0.5: + version "30.0.5" + resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-30.0.5.tgz#ec448f83bd9caa894dd7da8707f207c356a19924" + integrity sha512-bGl2Ntdx0eAwXuGpdLdVYVr5YQHnSZlQ0y9HVDu565lCUAe9sj6JOtBbMmBBikGIegne9piDDIOeiLVoqTkz4A== + dependencies: + execa "^5.1.1" + jest-util "30.0.5" + p-limit "^3.1.0" + +jest-circus@30.1.3: + version "30.1.3" + resolved "https://registry.yarnpkg.com/jest-circus/-/jest-circus-30.1.3.tgz#7ee0089f22b2b3e72ab04aee8e037c364a6d73d1" + integrity sha512-Yf3dnhRON2GJT4RYzM89t/EXIWNxKTpWTL9BfF3+geFetWP4XSvJjiU1vrWplOiUkmq8cHLiwuhz+XuUp9DscA== + dependencies: + "@jest/environment" "30.1.2" + "@jest/expect" "30.1.2" + "@jest/test-result" "30.1.3" + "@jest/types" "30.0.5" + "@types/node" "*" + chalk "^4.1.2" + co "^4.6.0" + dedent "^1.6.0" + is-generator-fn "^2.1.0" + jest-each "30.1.0" + jest-matcher-utils "30.1.2" + jest-message-util "30.1.0" + jest-runtime "30.1.3" + jest-snapshot "30.1.2" + jest-util "30.0.5" + p-limit "^3.1.0" + pretty-format "30.0.5" + pure-rand "^7.0.0" + slash "^3.0.0" + stack-utils "^2.0.6" + +jest-cli@30.1.3: + version "30.1.3" + resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-30.1.3.tgz#3fb8dea88886379eb95a08f954bfc2ed17a9be4f" + integrity sha512-G8E2Ol3OKch1DEeIBl41NP7OiC6LBhfg25Btv+idcusmoUSpqUkbrneMqbW9lVpI/rCKb/uETidb7DNteheuAQ== + dependencies: + "@jest/core" "30.1.3" + "@jest/test-result" "30.1.3" + "@jest/types" "30.0.5" + chalk "^4.1.2" + exit-x "^0.2.2" + import-local "^3.2.0" + jest-config "30.1.3" + jest-util "30.0.5" + jest-validate "30.1.0" + yargs "^17.7.2" + +jest-config@30.1.3: + version "30.1.3" + resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-30.1.3.tgz#10bcf4cd979119bfac6a130fb79d837057ce33d4" + integrity sha512-M/f7gqdQEPgZNA181Myz+GXCe8jXcJsGjCMXUzRj22FIXsZOyHNte84e0exntOvdPaeh9tA0w+B8qlP2fAezfw== + dependencies: + "@babel/core" "^7.27.4" + "@jest/get-type" "30.1.0" + "@jest/pattern" "30.0.1" + "@jest/test-sequencer" "30.1.3" + "@jest/types" "30.0.5" + babel-jest "30.1.2" + chalk "^4.1.2" + ci-info "^4.2.0" + deepmerge "^4.3.1" + glob "^10.3.10" + graceful-fs "^4.2.11" + jest-circus "30.1.3" + jest-docblock "30.0.1" + jest-environment-node "30.1.2" + jest-regex-util "30.0.1" + jest-resolve "30.1.3" + jest-runner "30.1.3" + jest-util "30.0.5" + jest-validate "30.1.0" + micromatch "^4.0.8" + parse-json "^5.2.0" + pretty-format "30.0.5" + slash "^3.0.0" + strip-json-comments "^3.1.1" + +jest-diff@30.1.2: + version "30.1.2" + resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-30.1.2.tgz#8ff4217e5b63fef49a5b37462999d8f5299a4eb4" + integrity sha512-4+prq+9J61mOVXCa4Qp8ZjavdxzrWQXrI80GNxP8f4tkI2syPuPrJgdRPZRrfUTRvIoUwcmNLbqEJy9W800+NQ== + dependencies: + "@jest/diff-sequences" "30.0.1" + "@jest/get-type" "30.1.0" + chalk "^4.1.2" + pretty-format "30.0.5" + +jest-docblock@30.0.1: + version "30.0.1" + resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-30.0.1.tgz#545ff59f2fa88996bd470dba7d3798a8421180b1" + integrity sha512-/vF78qn3DYphAaIc3jy4gA7XSAz167n9Bm/wn/1XhTLW7tTBIzXtCJpb/vcmc73NIIeeohCbdL94JasyXUZsGA== + dependencies: + detect-newline "^3.1.0" + +jest-each@30.1.0: + version "30.1.0" + resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-30.1.0.tgz#228756d5ea9e4dcb462fc2e90a44ec27dd482d23" + integrity sha512-A+9FKzxPluqogNahpCv04UJvcZ9B3HamqpDNWNKDjtxVRYB8xbZLFuCr8JAJFpNp83CA0anGQFlpQna9Me+/tQ== + dependencies: + "@jest/get-type" "30.1.0" + "@jest/types" "30.0.5" + chalk "^4.1.2" + jest-util "30.0.5" + pretty-format "30.0.5" + +jest-environment-node@30.1.2: + version "30.1.2" + resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-30.1.2.tgz#ae2f20442f8abc3c6b20120dc789fa38faff568f" + integrity sha512-w8qBiXtqGWJ9xpJIA98M0EIoq079GOQRQUyse5qg1plShUCQ0Ek1VTTcczqKrn3f24TFAgFtT+4q3aOXvjbsuA== + dependencies: + "@jest/environment" "30.1.2" + "@jest/fake-timers" "30.1.2" + "@jest/types" "30.0.5" + "@types/node" "*" + jest-mock "30.0.5" + jest-util "30.0.5" + jest-validate "30.1.0" + +jest-haste-map@30.1.0: + version "30.1.0" + resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-30.1.0.tgz#e54d84e07fac15ea3a98903b735048e36d7d2ed3" + integrity sha512-JLeM84kNjpRkggcGpQLsV7B8W4LNUWz7oDNVnY1Vjj22b5/fAb3kk3htiD+4Na8bmJmjJR7rBtS2Rmq/NEcADg== + dependencies: + "@jest/types" "30.0.5" + "@types/node" "*" + anymatch "^3.1.3" + fb-watchman "^2.0.2" + graceful-fs "^4.2.11" + jest-regex-util "30.0.1" + jest-util "30.0.5" + jest-worker "30.1.0" + micromatch "^4.0.8" + walker "^1.0.8" + optionalDependencies: + fsevents "^2.3.3" + +jest-leak-detector@30.1.0: + version "30.1.0" + resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-30.1.0.tgz#8b86e7c5f1e3e4f2a32d930ec769103ad0985874" + integrity sha512-AoFvJzwxK+4KohH60vRuHaqXfWmeBATFZpzpmzNmYTtmRMiyGPVhkXpBqxUQunw+dQB48bDf4NpUs6ivVbRv1g== + dependencies: + "@jest/get-type" "30.1.0" + pretty-format "30.0.5" + +jest-matcher-utils@30.1.2: + version "30.1.2" + resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-30.1.2.tgz#3f1b63949f740025aff740c6c6a1b653ae370fbb" + integrity sha512-7ai16hy4rSbDjvPTuUhuV8nyPBd6EX34HkBsBcBX2lENCuAQ0qKCPb/+lt8OSWUa9WWmGYLy41PrEzkwRwoGZQ== + dependencies: + "@jest/get-type" "30.1.0" + chalk "^4.1.2" + jest-diff "30.1.2" + pretty-format "30.0.5" + +jest-message-util@30.1.0: + version "30.1.0" + resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-30.1.0.tgz#653a9bb1a33306eddf13455ce0666ba621b767c4" + integrity sha512-HizKDGG98cYkWmaLUHChq4iN+oCENohQLb7Z5guBPumYs+/etonmNFlg1Ps6yN9LTPyZn+M+b/9BbnHx3WTMDg== + dependencies: + "@babel/code-frame" "^7.27.1" + "@jest/types" "30.0.5" + "@types/stack-utils" "^2.0.3" + chalk "^4.1.2" + graceful-fs "^4.2.11" + micromatch "^4.0.8" + pretty-format "30.0.5" + slash "^3.0.0" + stack-utils "^2.0.6" + +jest-mock@30.0.5: + version "30.0.5" + resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-30.0.5.tgz#ef437e89212560dd395198115550085038570bdd" + integrity sha512-Od7TyasAAQX/6S+QCbN6vZoWOMwlTtzzGuxJku1GhGanAjz9y+QsQkpScDmETvdc9aSXyJ/Op4rhpMYBWW91wQ== + dependencies: + "@jest/types" "30.0.5" + "@types/node" "*" + jest-util "30.0.5" + +jest-pnp-resolver@^1.2.3: + version "1.2.3" + resolved "https://registry.yarnpkg.com/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz#930b1546164d4ad5937d5540e711d4d38d4cad2e" + integrity sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w== + +jest-regex-util@30.0.1: + version "30.0.1" + resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-30.0.1.tgz#f17c1de3958b67dfe485354f5a10093298f2a49b" + integrity sha512-jHEQgBXAgc+Gh4g0p3bCevgRCVRkB4VB70zhoAE48gxeSr1hfUOsM/C2WoJgVL7Eyg//hudYENbm3Ne+/dRVVA== + +jest-resolve-dependencies@30.1.3: + version "30.1.3" + resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-30.1.3.tgz#04bbe95c9f4af51046dde940698d7121b49d0167" + integrity sha512-DNfq3WGmuRyHRHfEet+Zm3QOmVFtIarUOQHHryKPc0YL9ROfgWZxl4+aZq/VAzok2SS3gZdniP+dO4zgo59hBg== + dependencies: + jest-regex-util "30.0.1" + jest-snapshot "30.1.2" + +jest-resolve@30.1.3: + version "30.1.3" + resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-30.1.3.tgz#cc1019b28374ca7bcf7e58d57a4300449f390ec5" + integrity sha512-DI4PtTqzw9GwELFS41sdMK32Ajp3XZQ8iygeDMWkxlRhm7uUTOFSZFVZABFuxr0jvspn8MAYy54NxZCsuCTSOw== + dependencies: + chalk "^4.1.2" + graceful-fs "^4.2.11" + jest-haste-map "30.1.0" + jest-pnp-resolver "^1.2.3" + jest-util "30.0.5" + jest-validate "30.1.0" + slash "^3.0.0" + unrs-resolver "^1.7.11" + +jest-runner@30.1.3: + version "30.1.3" + resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-30.1.3.tgz#3253a0faab8f404aa9e0010911e8acbaf220865b" + integrity sha512-dd1ORcxQraW44Uz029TtXj85W11yvLpDuIzNOlofrC8GN+SgDlgY4BvyxJiVeuabA1t6idjNbX59jLd2oplOGQ== + dependencies: + "@jest/console" "30.1.2" + "@jest/environment" "30.1.2" + "@jest/test-result" "30.1.3" + "@jest/transform" "30.1.2" + "@jest/types" "30.0.5" + "@types/node" "*" + chalk "^4.1.2" + emittery "^0.13.1" + exit-x "^0.2.2" + graceful-fs "^4.2.11" + jest-docblock "30.0.1" + jest-environment-node "30.1.2" + jest-haste-map "30.1.0" + jest-leak-detector "30.1.0" + jest-message-util "30.1.0" + jest-resolve "30.1.3" + jest-runtime "30.1.3" + jest-util "30.0.5" + jest-watcher "30.1.3" + jest-worker "30.1.0" + p-limit "^3.1.0" + source-map-support "0.5.13" + +jest-runtime@30.1.3: + version "30.1.3" + resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-30.1.3.tgz#bca7cb48d53c5b5ae21399e7a65e21271f500004" + integrity sha512-WS8xgjuNSphdIGnleQcJ3AKE4tBKOVP+tKhCD0u+Tb2sBmsU8DxfbBpZX7//+XOz81zVs4eFpJQwBNji2Y07DA== + dependencies: + "@jest/environment" "30.1.2" + "@jest/fake-timers" "30.1.2" + "@jest/globals" "30.1.2" + "@jest/source-map" "30.0.1" + "@jest/test-result" "30.1.3" + "@jest/transform" "30.1.2" + "@jest/types" "30.0.5" + "@types/node" "*" + chalk "^4.1.2" + cjs-module-lexer "^2.1.0" + collect-v8-coverage "^1.0.2" + glob "^10.3.10" + graceful-fs "^4.2.11" + jest-haste-map "30.1.0" + jest-message-util "30.1.0" + jest-mock "30.0.5" + jest-regex-util "30.0.1" + jest-resolve "30.1.3" + jest-snapshot "30.1.2" + jest-util "30.0.5" + slash "^3.0.0" + strip-bom "^4.0.0" + +jest-snapshot@30.1.2: + version "30.1.2" + resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-30.1.2.tgz#4001a94d8394bb077a1c96246f0107c81aba4f12" + integrity sha512-4q4+6+1c8B6Cy5pGgFvjDy/Pa6VYRiGu0yQafKkJ9u6wQx4G5PqI2QR6nxTl43yy7IWsINwz6oT4o6tD12a8Dg== + dependencies: + "@babel/core" "^7.27.4" + "@babel/generator" "^7.27.5" + "@babel/plugin-syntax-jsx" "^7.27.1" + "@babel/plugin-syntax-typescript" "^7.27.1" + "@babel/types" "^7.27.3" + "@jest/expect-utils" "30.1.2" + "@jest/get-type" "30.1.0" + "@jest/snapshot-utils" "30.1.2" + "@jest/transform" "30.1.2" + "@jest/types" "30.0.5" + babel-preset-current-node-syntax "^1.1.0" + chalk "^4.1.2" + expect "30.1.2" + graceful-fs "^4.2.11" + jest-diff "30.1.2" + jest-matcher-utils "30.1.2" + jest-message-util "30.1.0" + jest-util "30.0.5" + pretty-format "30.0.5" + semver "^7.7.2" + synckit "^0.11.8" + +jest-util@30.0.5: + version "30.0.5" + resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-30.0.5.tgz#035d380c660ad5f1748dff71c4105338e05f8669" + integrity sha512-pvyPWssDZR0FlfMxCBoc0tvM8iUEskaRFALUtGQYzVEAqisAztmy+R8LnU14KT4XA0H/a5HMVTXat1jLne010g== + dependencies: + "@jest/types" "30.0.5" + "@types/node" "*" + chalk "^4.1.2" + ci-info "^4.2.0" + graceful-fs "^4.2.11" + picomatch "^4.0.2" + +jest-validate@30.1.0: + version "30.1.0" + resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-30.1.0.tgz#585aae6c9ee1ac138dbacbece8a7838ca7773e60" + integrity sha512-7P3ZlCFW/vhfQ8pE7zW6Oi4EzvuB4sgR72Q1INfW9m0FGo0GADYlPwIkf4CyPq7wq85g+kPMtPOHNAdWHeBOaA== + dependencies: + "@jest/get-type" "30.1.0" + "@jest/types" "30.0.5" + camelcase "^6.3.0" + chalk "^4.1.2" + leven "^3.1.0" + pretty-format "30.0.5" + +jest-watcher@30.1.3: + version "30.1.3" + resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-30.1.3.tgz#2f381da5c2c76a46c46ba2108e6607c585421dc0" + integrity sha512-6jQUZCP1BTL2gvG9E4YF06Ytq4yMb4If6YoQGRR6PpjtqOXSP3sKe2kqwB6SQ+H9DezOfZaSLnmka1NtGm3fCQ== + dependencies: + "@jest/test-result" "30.1.3" + "@jest/types" "30.0.5" + "@types/node" "*" + ansi-escapes "^4.3.2" + chalk "^4.1.2" + emittery "^0.13.1" + jest-util "30.0.5" + string-length "^4.0.2" + +jest-worker@30.1.0: + version "30.1.0" + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-30.1.0.tgz#a89c36772be449d4bdb60697fb695a1673b12ac2" + integrity sha512-uvWcSjlwAAgIu133Tt77A05H7RIk3Ho8tZL50bQM2AkvLdluw9NG48lRCl3Dt+MOH719n/0nnb5YxUwcuJiKRA== + dependencies: + "@types/node" "*" + "@ungap/structured-clone" "^1.3.0" + jest-util "30.0.5" + merge-stream "^2.0.0" + supports-color "^8.1.1" + +jest@^30.1.3: + version "30.1.3" + resolved "https://registry.yarnpkg.com/jest/-/jest-30.1.3.tgz#c962290f65c32d44a0624f785b2d780835525a23" + integrity sha512-Ry+p2+NLk6u8Agh5yVqELfUJvRfV51hhVBRIB5yZPY7mU0DGBmOuFG5GebZbMbm86cdQNK0fhJuDX8/1YorISQ== + dependencies: + "@jest/core" "30.1.3" + "@jest/types" "30.0.5" + import-local "^3.2.0" + jest-cli "30.1.3" + +js-tokens@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" + integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== + +js-yaml@^3.13.1: + version "3.14.1" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" + integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g== + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" + +jsbn@~0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" + integrity sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg== + +jsesc@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-3.1.0.tgz#74d335a234f67ed19907fdadfac7ccf9d409825d" + integrity sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA== + +json-bigint@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/json-bigint/-/json-bigint-1.0.0.tgz#ae547823ac0cad8398667f8cd9ef4730f5b01ff1" + integrity sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ== + dependencies: + bignumber.js "^9.0.0" + +json-parse-even-better-errors@^2.3.0: + version "2.3.1" + resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" + integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== + +json-schema-traverse@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" + integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== + +json-schema@0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.4.0.tgz#f7de4cf6efab838ebaeb3236474cbba5a1930ab5" + integrity sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA== + +json-stringify-safe@^5.0.1, json-stringify-safe@~5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" + integrity sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA== + +json5@^2.2.3: + version "2.2.3" + resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" + integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== + +jsprim@^1.2.2: + version "1.4.2" + resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.2.tgz#712c65533a15c878ba59e9ed5f0e26d5b77c5feb" + integrity sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw== + dependencies: + assert-plus "1.0.0" + extsprintf "1.3.0" + json-schema "0.4.0" + verror "1.10.0" + +leven@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2" + integrity sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A== + +lines-and-columns@^1.1.6: + version "1.2.4" + resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" + integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== + +locate-path@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" + integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== + dependencies: + p-locate "^4.1.0" + +lodash.memoize@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" + integrity sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag== + +lodash@^4.0.0: + version "4.17.21" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" + integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== + +lru-cache@^10.2.0: + version "10.4.3" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.4.3.tgz#410fc8a17b70e598013df257c2446b7f3383f119" + integrity sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ== + +lru-cache@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" + integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w== + dependencies: + yallist "^3.0.2" + +make-dir@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-4.0.0.tgz#c3c2307a771277cd9638305f915c29ae741b614e" + integrity sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw== + dependencies: + semver "^7.5.3" + +make-error@^1.1.1, make-error@^1.3.6: + version "1.3.6" + resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" + integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== + +makeerror@1.0.12: + version "1.0.12" + resolved "https://registry.yarnpkg.com/makeerror/-/makeerror-1.0.12.tgz#3e5dd2079a82e812e983cc6610c4a2cb0eaa801a" + integrity sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg== + dependencies: + tmpl "1.0.5" + +merge-stream@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" + integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== + +micromatch@^4.0.8: + version "4.0.8" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.8.tgz#d66fa18f3a47076789320b9b1af32bd86d9fa202" + integrity sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA== + dependencies: + braces "^3.0.3" + picomatch "^2.3.1" + +mime-db@1.52.0: + version "1.52.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" + integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== + +mime-types@^2.1.12, mime-types@~2.1.19: + version "2.1.35" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" + integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== + dependencies: + mime-db "1.52.0" + +mimic-fn@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" + integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== + +minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" + integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== + +minimalistic-crypto-utils@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" + integrity sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg== + +"minimatch@2 || 3", minimatch@^3.0.4, minimatch@^3.1.1: + version "3.1.2" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" + integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== + dependencies: + brace-expansion "^1.1.7" + +minimatch@^9.0.4: + version "9.0.5" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.5.tgz#d74f9dd6b57d83d8e98cfb82133b03978bc929e5" + integrity sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow== + dependencies: + brace-expansion "^2.0.1" + +minimist@^1.2.5, minimist@^1.2.6: + version "1.2.8" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" + integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== + +"minipass@^5.0.0 || ^6.0.2 || ^7.0.0", minipass@^7.1.2: + version "7.1.2" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-7.1.2.tgz#93a9626ce5e5e66bd4db86849e7515e92340a707" + integrity sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw== + +mkdirp@~0.5.1: + version "0.5.6" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.6.tgz#7def03d2432dcae4ba1d611445c48396062255f6" + integrity sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw== + dependencies: + minimist "^1.2.6" + +mock-socket@^9.3.1: + version "9.3.1" + resolved "https://registry.yarnpkg.com/mock-socket/-/mock-socket-9.3.1.tgz#24fb00c2f573c84812aa4a24181bb025de80cc8e" + integrity sha512-qxBgB7Qa2sEQgHFjj0dSigq7fX4k6Saisd5Nelwp2q8mlbAFh5dHV9JTTlF8viYJLSSWgMCZFUom8PJcMNBoJw== + +moment@^2.19.3: + version "2.30.1" + resolved "https://registry.yarnpkg.com/moment/-/moment-2.30.1.tgz#f8c91c07b7a786e30c59926df530b4eac96974ae" + integrity sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how== + +ms@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" + integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A== + +ms@^2.1.3: + version "2.1.3" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" + integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== + +mv@~2: + version "2.1.1" + resolved "https://registry.yarnpkg.com/mv/-/mv-2.1.1.tgz#ae6ce0d6f6d5e0a4f7d893798d03c1ea9559b6a2" + integrity sha512-at/ZndSy3xEGJ8i0ygALh8ru9qy7gWW1cmkaqBN29JmMlIvM//MEO9y1sk/avxuwnPcfhkejkLsuPxH81BrkSg== + dependencies: + mkdirp "~0.5.1" + ncp "~2.0.0" + rimraf "~2.4.0" + +nan@^2.14.0: + version "2.23.1" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.23.1.tgz#6f86a31dd87e3d1eb77512bf4b9e14c8aded3975" + integrity sha512-r7bBUGKzlqk8oPBDYxt6Z0aEdF1G1rwlMcLk8LCOMbOzf0mG+JUfUzG4fIMWwHWP0iyaLWEQZJmtB7nOHEm/qw== + +napi-postinstall@^0.3.0: + version "0.3.3" + resolved "https://registry.yarnpkg.com/napi-postinstall/-/napi-postinstall-0.3.3.tgz#93d045c6b576803ead126711d3093995198c6eb9" + integrity sha512-uTp172LLXSxuSYHv/kou+f6KW3SMppU9ivthaVTXian9sOt3XM/zHYHpRZiLgQoxeWfYUnslNWQHF1+G71xcow== + +natural-compare@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" + integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== + +ncp@~2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ncp/-/ncp-2.0.0.tgz#195a21d6c46e361d2fb1281ba38b91e9df7bdbb3" + integrity sha512-zIdGUrPRFTUELUvr3Gmc7KZ2Sw/h1PiVM0Af/oHB6zgnV1ikqSfRk+TOufi79aHYCW3NiOXmr1BP5nWbzojLaA== + +neo-async@^2.6.2: + version "2.6.2" + resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" + integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== + +nock@^13.5.0: + version "13.5.6" + resolved "https://registry.yarnpkg.com/nock/-/nock-13.5.6.tgz#5e693ec2300bbf603b61dae6df0225673e6c4997" + integrity sha512-o2zOYiCpzRqSzPj0Zt/dQ/DqZeYoaQ7TUonc/xUPjCGl9WeHpNbxgVvOquXYAaJzI0M9BXV3HTzG0p8IUAbBTQ== + dependencies: + debug "^4.1.0" + json-stringify-safe "^5.0.1" + propagate "^2.0.0" + +node-domexception@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/node-domexception/-/node-domexception-1.0.0.tgz#6888db46a1f71c0b76b3f7555016b63fe64766e5" + integrity sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ== + +node-fetch@^3.3.2: + version "3.3.2" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-3.3.2.tgz#d1e889bacdf733b4ff3b2b243eb7a12866a0b78b" + integrity sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA== + dependencies: + data-uri-to-buffer "^4.0.0" + fetch-blob "^3.1.4" + formdata-polyfill "^4.0.10" + +node-int64@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" + integrity sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw== + +node-releases@^2.0.21: + version "2.0.21" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.21.tgz#f59b018bc0048044be2d4c4c04e4c8b18160894c" + integrity sha512-5b0pgg78U3hwXkCM8Z9b2FJdPZlr9Psr9V2gQPESdGHqbntyFJKFW4r5TeWGFzafGY3hzs1JC62VEQMbl1JFkw== + +normalize-path@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" + integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== + +npm-run-path@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea" + integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw== + dependencies: + path-key "^3.0.0" + +oauth-sign@~0.9.0: + version "0.9.0" + resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" + integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== + +once@^1.3.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== + dependencies: + wrappy "1" + +onetime@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" + integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== + dependencies: + mimic-fn "^2.1.0" + +ox@0.9.3: + version "0.9.3" + resolved "https://registry.yarnpkg.com/ox/-/ox-0.9.3.tgz#92cc1008dcd913e919364fd4175c860b3eeb18db" + integrity sha512-KzyJP+fPV4uhuuqrTZyok4DC7vFzi7HLUFiUNEmpbyh59htKWkOC98IONC1zgXJPbHAhQgqs6B0Z6StCGhmQvg== + dependencies: + "@adraffy/ens-normalize" "^1.11.0" + "@noble/ciphers" "^1.3.0" + "@noble/curves" "1.9.1" + "@noble/hashes" "^1.8.0" + "@scure/bip32" "^1.7.0" + "@scure/bip39" "^1.6.0" + abitype "^1.0.9" + eventemitter3 "5.0.1" + +p-limit@^2.2.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" + integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== + dependencies: + p-try "^2.0.0" + +p-limit@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" + integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== + dependencies: + yocto-queue "^0.1.0" + +p-locate@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" + integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== + dependencies: + p-limit "^2.2.0" + +p-try@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" + integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== + +package-json-from-dist@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz#4f1471a010827a86f94cfd9b0727e36d267de505" + integrity sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw== + +parse-json@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd" + integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg== + dependencies: + "@babel/code-frame" "^7.0.0" + error-ex "^1.3.1" + json-parse-even-better-errors "^2.3.0" + lines-and-columns "^1.1.6" + +path-exists@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" + integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== + +path-is-absolute@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== + +path-key@^3.0.0, path-key@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" + integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== + +path-scurry@^1.11.1: + version "1.11.1" + resolved "https://registry.yarnpkg.com/path-scurry/-/path-scurry-1.11.1.tgz#7960a668888594a0720b12a911d1a742ab9f11d2" + integrity sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA== + dependencies: + lru-cache "^10.2.0" + minipass "^5.0.0 || ^6.0.2 || ^7.0.0" + +performance-now@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" + integrity sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow== + +picocolors@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.1.1.tgz#3d321af3eab939b083c8f929a1d12cda81c26b6b" + integrity sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA== + +picomatch@^2.0.4, picomatch@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" + integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== + +picomatch@^4.0.2: + version "4.0.3" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-4.0.3.tgz#796c76136d1eead715db1e7bad785dedd695a042" + integrity sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q== + +pirates@^4.0.7: + version "4.0.7" + resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.7.tgz#643b4a18c4257c8a65104b73f3049ce9a0a15e22" + integrity sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA== + +pkg-dir@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" + integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ== + dependencies: + find-up "^4.0.0" + +pretty-format@30.0.5, pretty-format@^30.0.0: + version "30.0.5" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-30.0.5.tgz#e001649d472800396c1209684483e18a4d250360" + integrity sha512-D1tKtYvByrBkFLe2wHJl2bwMJIiT8rW+XA+TiataH79/FszLQMrpGEvzUVkzPau7OCO0Qnrhpe87PqtOAIB8Yw== + dependencies: + "@jest/schemas" "30.0.5" + ansi-styles "^5.2.0" + react-is "^18.3.1" + +propagate@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/propagate/-/propagate-2.0.1.tgz#40cdedab18085c792334e64f0ac17256d38f9a45" + integrity sha512-vGrhOavPSTz4QVNuBNdcNXePNdNMaO1xj9yBeH1ScQPjk/rhg9sSlCXPhMkFuaNNW/syTvYqsnbIJxMBfRbbag== + +psl@^1.1.28: + version "1.15.0" + resolved "https://registry.yarnpkg.com/psl/-/psl-1.15.0.tgz#bdace31896f1d97cec6a79e8224898ce93d974c6" + integrity sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w== + dependencies: + punycode "^2.3.1" + +punycode@^2.1.0, punycode@^2.1.1, punycode@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5" + integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg== + +pure-rand@^7.0.0: + version "7.0.1" + resolved "https://registry.yarnpkg.com/pure-rand/-/pure-rand-7.0.1.tgz#6f53a5a9e3e4a47445822af96821ca509ed37566" + integrity sha512-oTUZM/NAZS8p7ANR3SHh30kXB+zK2r2BPcEn/awJIbOvq82WoMN4p62AWWp3Hhw50G0xMsw1mhIBLqHw64EcNQ== + +qs@~6.5.2: + version "6.5.3" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.3.tgz#3aeeffc91967ef6e35c0e488ef46fb296ab76aad" + integrity sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA== + +react-is@^18.3.1: + version "18.3.1" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.3.1.tgz#e83557dc12eae63a99e003a46388b1dcbb44db7e" + integrity sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg== + +request@^2.53.0: + version "2.88.2" + resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3" + integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw== + dependencies: + aws-sign2 "~0.7.0" + aws4 "^1.8.0" + caseless "~0.12.0" + combined-stream "~1.0.6" + extend "~3.0.2" + forever-agent "~0.6.1" + form-data "~2.3.2" + har-validator "~5.1.3" + http-signature "~1.2.0" + is-typedarray "~1.0.0" + isstream "~0.1.2" + json-stringify-safe "~5.0.1" + mime-types "~2.1.19" + oauth-sign "~0.9.0" + performance-now "^2.1.0" + qs "~6.5.2" + safe-buffer "^5.1.2" + tough-cookie "~2.5.0" + tunnel-agent "^0.6.0" + uuid "^3.3.2" + +require-directory@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== + +resolve-cwd@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-3.0.0.tgz#0f0075f1bb2544766cf73ba6a6e2adfebcb13f2d" + integrity sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg== + dependencies: + resolve-from "^5.0.0" + +resolve-from@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" + integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== + +rimraf@~2.4.0: + version "2.4.5" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.4.5.tgz#ee710ce5d93a8fdb856fb5ea8ff0e2d75934b2da" + integrity sha512-J5xnxTyqaiw06JjMftq7L9ouA448dw/E7dKghkP9WpKNuwmARNNg+Gk8/u5ryb9N/Yo2+z3MCwuqFK/+qPOPfQ== + dependencies: + glob "^6.0.1" + +rxjs@^7.8.1: + version "7.8.2" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.8.2.tgz#955bc473ed8af11a002a2be52071bf475638607b" + integrity sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA== + dependencies: + tslib "^2.1.0" + +safe-buffer@^5.0.1, safe-buffer@^5.1.1, safe-buffer@^5.1.2: + version "5.2.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" + integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== + +safe-json-stringify@~1: + version "1.2.0" + resolved "https://registry.yarnpkg.com/safe-json-stringify/-/safe-json-stringify-1.2.0.tgz#356e44bc98f1f93ce45df14bcd7c01cda86e0afd" + integrity sha512-gH8eh2nZudPQO6TytOvbxnuhYBOvDBBLW52tz5q6X58lJcd/tkmqFR+5Z9adS8aJtURSXWThWy/xJtJwixErvg== + +safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: + version "2.1.2" + resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== + +scale-ts@^1.6.0: + version "1.6.1" + resolved "https://registry.yarnpkg.com/scale-ts/-/scale-ts-1.6.1.tgz#45151e156d6c04792223c39d8e7484ce926445f2" + integrity sha512-PBMc2AWc6wSEqJYBDPcyCLUj9/tMKnLX70jLOSndMtcUoLQucP/DM0vnQo1wJAYjTrQiq8iG9rD0q6wFzgjH7g== + +semver@^5.1.0: + version "5.7.2" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8" + integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g== + +semver@^6.3.1: + version "6.3.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" + integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== + +semver@^7.5.3, semver@^7.5.4, semver@^7.7.2: + version "7.7.2" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.7.2.tgz#67d99fdcd35cec21e6f8b87a7fd515a33f982b58" + integrity sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA== + +shebang-command@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" + integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== + dependencies: + shebang-regex "^3.0.0" + +shebang-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" + integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== + +signal-exit@^3.0.3: + version "3.0.7" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" + integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== + +signal-exit@^4.0.1: + version "4.1.0" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-4.1.0.tgz#952188c1cbd546070e2dd20d0f41c0ae0530cb04" + integrity sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw== + +slash@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" + integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== + +smoldot@2.0.22: + version "2.0.22" + resolved "https://registry.yarnpkg.com/smoldot/-/smoldot-2.0.22.tgz#1e924d2011a31c57416e79a2b97a460f462a31c7" + integrity sha512-B50vRgTY6v3baYH6uCgL15tfaag5tcS2o/P5q1OiXcKGv1axZDfz2dzzMuIkVpyMR2ug11F6EAtQlmYBQd292g== + dependencies: + ws "^8.8.1" + +source-map-support@0.5.13: + version "0.5.13" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.13.tgz#31b24a9c2e73c2de85066c0feb7d44767ed52932" + integrity sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w== + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + +source-map@^0.6.0, source-map@^0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== + +sprintf-js@~1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" + integrity sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g== + +sshpk@^1.7.0: + version "1.18.0" + resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.18.0.tgz#1663e55cddf4d688b86a46b77f0d5fe363aba028" + integrity sha512-2p2KJZTSqQ/I3+HX42EpYOa2l3f8Erv8MWKsy2I9uf4wA7yFIkXRffYdsx86y6z4vHtV8u7g+pPlr8/4ouAxsQ== + dependencies: + asn1 "~0.2.3" + assert-plus "^1.0.0" + bcrypt-pbkdf "^1.0.0" + dashdash "^1.12.0" + ecc-jsbn "~0.1.1" + getpass "^0.1.1" + jsbn "~0.1.0" + safer-buffer "^2.0.2" + tweetnacl "~0.14.0" + +stack-utils@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-2.0.6.tgz#aaf0748169c02fc33c8232abccf933f54a1cc34f" + integrity sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ== + dependencies: + escape-string-regexp "^2.0.0" + +standard-error@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/standard-error/-/standard-error-1.1.0.tgz#23e5168fa1c0820189e5812701a79058510d0d34" + integrity sha512-4v7qzU7oLJfMI5EltUSHCaaOd65J6S4BqKRWgzMi4EYaE5fvNabPxmAPGdxpGXqrcWjhDGI/H09CIdEuUOUeXg== + +string-length@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/string-length/-/string-length-4.0.2.tgz#a8a8dc7bd5c1a82b9b3c8b87e125f66871b6e57a" + integrity sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ== + dependencies: + char-regex "^1.0.2" + strip-ansi "^6.0.0" + +"string-width-cjs@npm:string-width@^4.2.0": + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +string-width@^5.0.1, string-width@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794" + integrity sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA== + dependencies: + eastasianwidth "^0.2.0" + emoji-regex "^9.2.2" + strip-ansi "^7.0.1" + +"strip-ansi-cjs@npm:strip-ansi@^6.0.1": + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + +strip-ansi@^6.0.0, strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + +strip-ansi@^7.0.1: + version "7.1.2" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.2.tgz#132875abde678c7ea8d691533f2e7e22bb744dba" + integrity sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA== + dependencies: + ansi-regex "^6.0.1" + +strip-bom@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-4.0.0.tgz#9c3505c1db45bcedca3d9cf7a16f5c5aa3901878" + integrity sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w== + +strip-final-newline@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" + integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== + +strip-json-comments@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" + integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== + +supports-color@^7.1.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" + integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== + dependencies: + has-flag "^4.0.0" + +supports-color@^8.1.1: + version "8.1.1" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" + integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== + dependencies: + has-flag "^4.0.0" + +synckit@^0.11.8: + version "0.11.11" + resolved "https://registry.yarnpkg.com/synckit/-/synckit-0.11.11.tgz#c0b619cf258a97faa209155d9cd1699b5c998cb0" + integrity sha512-MeQTA1r0litLUf0Rp/iisCaL8761lKAZHaimlbGK4j0HysC4PLfqygQj9srcs0m2RdtDYnF8UuYyKpbjHYp7Jw== + dependencies: + "@pkgr/core" "^0.2.9" + +test-exclude@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-6.0.0.tgz#04a8698661d805ea6fa293b6cb9e63ac044ef15e" + integrity sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w== + dependencies: + "@istanbuljs/schema" "^0.1.2" + glob "^7.1.4" + minimatch "^3.0.4" + +tiny-secp256k1@^2.2.4: + version "2.2.4" + resolved "https://registry.yarnpkg.com/tiny-secp256k1/-/tiny-secp256k1-2.2.4.tgz#1d9e45c2facb8607847da71a0a3d9cb2fd027eb2" + integrity sha512-FoDTcToPqZE454Q04hH9o2EhxWsm7pOSpicyHkgTwKhdKWdsTUuqfP5MLq3g+VjAtl2vSx6JpXGdwA2qpYkI0Q== + dependencies: + uint8array-tools "0.0.7" + +tmpl@1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.5.tgz#8683e0b902bb9c20c4f726e3c0b69f36518c07cc" + integrity sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw== + +to-regex-range@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" + integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== + dependencies: + is-number "^7.0.0" + +tough-cookie@~2.5.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2" + integrity sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g== + dependencies: + psl "^1.1.28" + punycode "^2.1.1" + +ts-jest@^29.4.4: + version "29.4.4" + resolved "https://registry.yarnpkg.com/ts-jest/-/ts-jest-29.4.4.tgz#fc6fefe28652ed81b8e1381ef8391901d9f81417" + integrity sha512-ccVcRABct5ZELCT5U0+DZwkXMCcOCLi2doHRrKy1nK/s7J7bch6TzJMsrY09WxgUUIP/ITfmcDS8D2yl63rnXw== + dependencies: + bs-logger "^0.2.6" + fast-json-stable-stringify "^2.1.0" + handlebars "^4.7.8" + json5 "^2.2.3" + lodash.memoize "^4.1.2" + make-error "^1.3.6" + semver "^7.7.2" + type-fest "^4.41.0" + yargs-parser "^21.1.1" + +ts-node@^10.9.2: + version "10.9.2" + resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.9.2.tgz#70f021c9e185bccdca820e26dc413805c101c71f" + integrity sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ== + dependencies: + "@cspotcode/source-map-support" "^0.8.0" + "@tsconfig/node10" "^1.0.7" + "@tsconfig/node12" "^1.0.7" + "@tsconfig/node14" "^1.0.0" + "@tsconfig/node16" "^1.0.2" + acorn "^8.4.1" + acorn-walk "^8.1.1" + arg "^4.1.0" + create-require "^1.1.0" + diff "^4.0.1" + make-error "^1.1.1" + v8-compile-cache-lib "^3.0.1" + yn "3.1.1" + +tslib@2.7.0: + version "2.7.0" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.7.0.tgz#d9b40c5c40ab59e8738f297df3087bf1a2690c01" + integrity sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA== + +tslib@^2.1.0, tslib@^2.4.0, tslib@^2.6.2, tslib@^2.7.0: + version "2.8.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f" + integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w== + +tunnel-agent@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" + integrity sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w== + dependencies: + safe-buffer "^5.0.1" + +tweetnacl@^0.14.3, tweetnacl@~0.14.0: + version "0.14.5" + resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" + integrity sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA== + +type-detect@4.0.8: + version "4.0.8" + resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" + integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== + +type-fest@^0.21.3: + version "0.21.3" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37" + integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w== + +type-fest@^4.41.0: + version "4.41.0" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-4.41.0.tgz#6ae1c8e5731273c2bf1f58ad39cbae2c91a46c58" + integrity sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA== + +typeforce@^1.11.3: + version "1.18.0" + resolved "https://registry.yarnpkg.com/typeforce/-/typeforce-1.18.0.tgz#d7416a2c5845e085034d70fcc5b6cc4a90edbfdc" + integrity sha512-7uc1O8h1M1g0rArakJdf0uLRSSgFcYexrVoKo+bzJd32gd4gDy2L/Z+8/FjPnU9ydY3pEnVPtr9FyscYY60K1g== + +typescript@^5.3.3: + version "5.9.2" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.9.2.tgz#d93450cddec5154a2d5cabe3b8102b83316fb2a6" + integrity sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A== + +uglify-js@^3.1.4: + version "3.19.3" + resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.19.3.tgz#82315e9bbc6f2b25888858acd1fff8441035b77f" + integrity sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ== + +uint8array-tools@0.0.7: + version "0.0.7" + resolved "https://registry.yarnpkg.com/uint8array-tools/-/uint8array-tools-0.0.7.tgz#a7a2bb5d8836eae2fade68c771454e6a438b390d" + integrity sha512-vrrNZJiusLWoFWBqz5Y5KMCgP9W9hnjZHzZiZRT8oNAkq3d5Z5Oe76jAvVVSRh4U8GGR90N2X1dWtrhvx6L8UQ== + +undici-types@~6.19.2: + version "6.19.8" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.19.8.tgz#35111c9d1437ab83a7cdc0abae2f26d88eda0a02" + integrity sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw== + +undici-types@~6.21.0: + version "6.21.0" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.21.0.tgz#691d00af3909be93a7faa13be61b3a5b50ef12cb" + integrity sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ== + +undici-types@~7.11.0: + version "7.11.0" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-7.11.0.tgz#075798115d0bbc4e4fc7c173f38727ca66bfb592" + integrity sha512-kt1ZriHTi7MU+Z/r9DOdAI3ONdaR3M3csEaRc6ewa4f4dTvX4cQCbJ4NkEn0ohE4hHtq85+PhPSTY+pO/1PwgA== + +unrs-resolver@^1.7.11: + version "1.11.1" + resolved "https://registry.yarnpkg.com/unrs-resolver/-/unrs-resolver-1.11.1.tgz#be9cd8686c99ef53ecb96df2a473c64d304048a9" + integrity sha512-bSjt9pjaEBnNiGgc9rUiHGKv5l4/TGzDmYw3RhnkJGtLhbnnA/5qJj7x3dNDCRx/PJxu774LlH8lCOlB4hEfKg== + dependencies: + napi-postinstall "^0.3.0" + optionalDependencies: + "@unrs/resolver-binding-android-arm-eabi" "1.11.1" + "@unrs/resolver-binding-android-arm64" "1.11.1" + "@unrs/resolver-binding-darwin-arm64" "1.11.1" + "@unrs/resolver-binding-darwin-x64" "1.11.1" + "@unrs/resolver-binding-freebsd-x64" "1.11.1" + "@unrs/resolver-binding-linux-arm-gnueabihf" "1.11.1" + "@unrs/resolver-binding-linux-arm-musleabihf" "1.11.1" + "@unrs/resolver-binding-linux-arm64-gnu" "1.11.1" + "@unrs/resolver-binding-linux-arm64-musl" "1.11.1" + "@unrs/resolver-binding-linux-ppc64-gnu" "1.11.1" + "@unrs/resolver-binding-linux-riscv64-gnu" "1.11.1" + "@unrs/resolver-binding-linux-riscv64-musl" "1.11.1" + "@unrs/resolver-binding-linux-s390x-gnu" "1.11.1" + "@unrs/resolver-binding-linux-x64-gnu" "1.11.1" + "@unrs/resolver-binding-linux-x64-musl" "1.11.1" + "@unrs/resolver-binding-wasm32-wasi" "1.11.1" + "@unrs/resolver-binding-win32-arm64-msvc" "1.11.1" + "@unrs/resolver-binding-win32-ia32-msvc" "1.11.1" + "@unrs/resolver-binding-win32-x64-msvc" "1.11.1" + +update-browserslist-db@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz#348377dd245216f9e7060ff50b15a1b740b75420" + integrity sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw== + dependencies: + escalade "^3.2.0" + picocolors "^1.1.1" + +uri-js@^4.2.2: + version "4.4.1" + resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" + integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== + dependencies: + punycode "^2.1.0" + +uuid@^3.0.1, uuid@^3.3.2: + version "3.4.0" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" + integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== + +v8-compile-cache-lib@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz#6336e8d71965cb3d35a1bbb7868445a7c05264bf" + integrity sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg== + +v8-to-istanbul@^9.0.1: + version "9.3.0" + resolved "https://registry.yarnpkg.com/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz#b9572abfa62bd556c16d75fdebc1a411d5ff3175" + integrity sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA== + dependencies: + "@jridgewell/trace-mapping" "^0.3.12" + "@types/istanbul-lib-coverage" "^2.0.1" + convert-source-map "^2.0.0" + +varuint-bitcoin@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/varuint-bitcoin/-/varuint-bitcoin-1.1.2.tgz#e76c138249d06138b480d4c5b40ef53693e24e92" + integrity sha512-4EVb+w4rx+YfVM32HQX42AbbT7/1f5zwAYhIujKXKk8NQK+JfRVl3pqT3hjNn/L+RstigmGGKVwHA/P0wgITZw== + dependencies: + safe-buffer "^5.1.1" + +verror@1.10.0: + version "1.10.0" + resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" + integrity sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw== + dependencies: + assert-plus "^1.0.0" + core-util-is "1.0.2" + extsprintf "^1.2.0" + +viem@^2.37.6: + version "2.37.6" + resolved "https://registry.yarnpkg.com/viem/-/viem-2.37.6.tgz#3b05586555bd4b2c1b7351ed148f9fa98df72027" + integrity sha512-b+1IozQ8TciVQNdQUkOH5xtFR0z7ZxR8pyloENi/a+RA408lv4LoX12ofwoiT3ip0VRhO5ni1em//X0jn/eW0g== + dependencies: + "@noble/curves" "1.9.1" + "@noble/hashes" "1.8.0" + "@scure/bip32" "1.7.0" + "@scure/bip39" "1.6.0" + abitype "1.1.0" + isows "1.0.7" + ox "0.9.3" + ws "8.18.3" + +walker@^1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/walker/-/walker-1.0.8.tgz#bd498db477afe573dc04185f011d3ab8a8d7653f" + integrity sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ== + dependencies: + makeerror "1.0.12" + +web-streams-polyfill@^3.0.3: + version "3.3.3" + resolved "https://registry.yarnpkg.com/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz#2073b91a2fdb1fbfbd401e7de0ac9f8214cecb4b" + integrity sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw== + +which@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" + integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== + dependencies: + isexe "^2.0.0" + +wordwrap@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" + integrity sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q== + +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + +wrap-ansi@^8.1.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" + integrity sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ== + dependencies: + ansi-styles "^6.1.0" + string-width "^5.0.1" + strip-ansi "^7.0.1" + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== + +write-file-atomic@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-5.0.1.tgz#68df4717c55c6fa4281a7860b4c2ba0a6d2b11e7" + integrity sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw== + dependencies: + imurmurhash "^0.1.4" + signal-exit "^4.0.1" + +ws@8.17.1: + version "8.17.1" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.17.1.tgz#9293da530bb548febc95371d90f9c878727d919b" + integrity sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ== + +ws@8.18.3, ws@^8.15.1, ws@^8.8.1: + version "8.18.3" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.18.3.tgz#b56b88abffde62791c639170400c93dcb0c95472" + integrity sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg== + +y18n@^5.0.5: + version "5.0.8" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" + integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== + +yallist@^3.0.2: + version "3.1.1" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" + integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== + +yargs-parser@^21.1.1: + version "21.1.1" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35" + integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== + +yargs@^17.7.2: + version "17.7.2" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269" + integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w== + dependencies: + cliui "^8.0.1" + escalade "^3.1.1" + get-caller-file "^2.0.5" + require-directory "^2.1.1" + string-width "^4.2.3" + y18n "^5.0.5" + yargs-parser "^21.1.1" + +yn@3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50" + integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q== + +yocto-queue@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" + integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== From 9ab30fe0cf71d85848c1d83351953fee0d8d951b Mon Sep 17 00:00:00 2001 From: Osman Abdelnasir Date: Wed, 21 Jan 2026 15:55:52 +0400 Subject: [PATCH 2/3] fix: btc test --- pallets/btc-vault/src/lib.rs | 254 +++- signet-ts-client-scripts/btc-vault.test.ts | 1221 +++++++------------- 2 files changed, 648 insertions(+), 827 deletions(-) diff --git a/pallets/btc-vault/src/lib.rs b/pallets/btc-vault/src/lib.rs index d69f0c79e8..5aca25656e 100644 --- a/pallets/btc-vault/src/lib.rs +++ b/pallets/btc-vault/src/lib.rs @@ -20,15 +20,19 @@ mod tests; pub use pallet::*; /// Bitcoin testnet vault address (P2WPKH pubkey hash - 20 bytes) -/// tb1q38c2sg5nc3v0tkcle2uncdyqspc4kuawjxpf0j +/// Derived from MPC root key + path "root" + sender btcVault pallet account +/// tb1qvakrvjwy5sj8a5q5laf9qulx8wa9cslyl73uwq pub const TESTNET_VAULT_ADDRESS: [u8; 20] = [ - 0x89, 0xf0, 0xa8, 0x23, 0x93, 0x8c, 0x58, 0xcf, 0x5b, 0x17, 0xc8, 0xeb, 0x93, 0xc6, 0x82, 0x80, 0x63, 0x5b, 0x73, - 0x4e, + 0x67, 0x6c, 0x36, 0x49, 0xc4, 0xa4, 0x24, 0x7e, 0xd0, 0x14, 0xff, 0x52, 0x50, 0x73, 0xe6, 0x3b, 0xba, 0x5c, 0x43, + 0xe4, ]; /// Bitcoin testnet CAIP-2 chain ID const BITCOIN_TESTNET_CAIP2: &str = "bip122:000000000933ea01ad0ee984209779ba"; +/// Hardcoded root path for withdrawals (shared vault address on Bitcoin) +const HARDCODED_ROOT_PATH: &[u8] = b"root"; + #[frame_support::pallet] pub mod pallet { use super::*; @@ -82,6 +86,17 @@ pub mod pallet { ValueQuery, >; + /// Pending withdrawals awaiting completion + #[pallet::storage] + #[pallet::getter(fn pending_withdrawals)] + pub type PendingWithdrawals = StorageMap< + _, + Blake2_128Concat, + [u8; 32], // request_id + PendingWithdrawalData, + OptionQuery, + >; + // ========================= Types ========================= #[derive(Encode, Decode, TypeInfo, Clone, Debug, PartialEq, MaxEncodedLen)] @@ -96,6 +111,13 @@ pub mod pallet { pub path: BoundedVec>, } + #[derive(Encode, Decode, TypeInfo, Clone, Debug, MaxEncodedLen)] + pub struct PendingWithdrawalData { + pub requester: AccountId, + pub amount: u64, // satoshis + pub recipient_script_pubkey: BoundedVec>, // Bitcoin recipient script + } + // ========================= Events ========================= #[pallet::event] @@ -123,6 +145,23 @@ pub mod pallet { version: u32, locktime: u32, }, + WithdrawalRequested { + request_id: [u8; 32], + requester: T::AccountId, + amount: u64, + recipient_script_pubkey: Vec, + }, + WithdrawalCompleted { + request_id: [u8; 32], + requester: T::AccountId, + amount: u64, + }, + WithdrawalFailed { + request_id: [u8; 32], + requester: T::AccountId, + amount: u64, + refunded: bool, + }, } // ========================= Errors ========================= @@ -147,6 +186,10 @@ pub mod pallet { InvalidVaultOutput, TooManyInputs, TooManyOutputs, + InsufficientBalance, + Underflow, + WithdrawalNotFound, + InvalidRecipientScript, } // ========================= Hooks ========================= @@ -371,6 +414,211 @@ pub mod pallet { Ok(()) } + + /// Request to withdraw BTC tokens from the vault + /// Uses optimistic decrement - balance is deducted immediately + /// If the withdrawal fails on Bitcoin, it will be refunded in complete_withdraw_btc + #[pallet::call_index(3)] + #[pallet::weight(Weight::from_parts(100_000, 0))] + pub fn withdraw_btc( + origin: OriginFor, + request_id: [u8; 32], + amount: u64, + recipient_script_pubkey: Vec, + inputs: Vec, + outputs: Vec, + lock_time: u32, + ) -> DispatchResult { + let requester = ensure_signed(origin)?; + + // Ensure vault is initialized + ensure!(VaultConfig::::get().is_some(), Error::::NotInitialized); + + // Ensure no duplicate request + ensure!( + PendingWithdrawals::::get(&request_id).is_none(), + Error::::DuplicateRequest + ); + + // Validate recipient script (basic sanity check) + ensure!(!recipient_script_pubkey.is_empty() && recipient_script_pubkey.len() <= 64, Error::::InvalidRecipientScript); + + // Check user has sufficient balance + let current_balance = UserBalances::::get(&requester); + ensure!(current_balance >= amount, Error::::InsufficientBalance); + + // Optimistically decrement the balance + UserBalances::::mutate(&requester, |balance| -> DispatchResult { + *balance = balance.checked_sub(amount).ok_or(Error::::Underflow)?; + Ok(()) + })?; + + // Convert to bounded vecs + let bounded_inputs: BoundedVec = + inputs.clone().try_into().map_err(|_| Error::::TooManyInputs)?; + let bounded_outputs: BoundedVec = + outputs.clone().try_into().map_err(|_| Error::::TooManyOutputs)?; + + // Verify one of the outputs goes to the recipient + let has_recipient_output = outputs.iter().any(|o| o.script_pubkey.to_vec() == recipient_script_pubkey); + ensure!(has_recipient_output, Error::::InvalidRecipientScript); + + // Get signet deposit amount and pallet account + let signet_deposit = pallet_signet::Pallet::::signature_deposit(); + let pallet_account = Self::account_id(); + let existential_deposit = ::Currency::minimum_balance(); + + // Ensure pallet account has sufficient balance + let pallet_balance = ::Currency::free_balance(&pallet_account); + let required_balance = existential_deposit.saturating_add(signet_deposit); + ensure!(pallet_balance >= required_balance, Error::::PalletAccountNotFunded); + + // Transfer signet deposit from requester to pallet account + ::Currency::transfer( + &requester, + &pallet_account, + signet_deposit, + frame_support::traits::ExistenceRequirement::AllowDeath, + )?; + + // Use hardcoded root path for withdrawals (shared vault address on Bitcoin) + let path = HARDCODED_ROOT_PATH.to_vec(); + + // Build PSBT + let psbt_bytes = pallet_signet::Pallet::::build_bitcoin_tx( + frame_system::RawOrigin::Signed(requester.clone()).into(), + bounded_inputs.clone(), + bounded_outputs.clone(), + lock_time, + )?; + + let txid = pallet_signet::Pallet::::get_bitcoin_txid( + frame_system::RawOrigin::Signed(requester.clone()).into(), + bounded_inputs, + bounded_outputs, + lock_time, + )?; + + // Generate and verify request ID + let computed_request_id = Self::generate_request_id( + &Self::account_id(), + &txid, + BITCOIN_TESTNET_CAIP2, + 0, + &path, + b"ecdsa", + b"bitcoin", + b"", + ); + + ensure!(computed_request_id == request_id, Error::::InvalidRequestId); + + // Store pending withdrawal + PendingWithdrawals::::insert( + &request_id, + PendingWithdrawalData { + requester: requester.clone(), + amount, + recipient_script_pubkey: recipient_script_pubkey.clone().try_into().map_err(|_| Error::::InvalidRecipientScript)?, + }, + ); + + // Create schemas for the response + let explorer_schema = + serde_json::to_vec(&serde_json::json!("bool")).map_err(|_| Error::::SerializationError)?; + + let callback_schema = + serde_json::to_vec(&serde_json::json!("bool")).map_err(|_| Error::::SerializationError)?; + + // Call sign_bidirectional from the pallet account + pallet_signet::Pallet::::sign_bidirectional( + frame_system::RawOrigin::Signed(Self::account_id()).into(), + BoundedVec::try_from(psbt_bytes).map_err(|_| Error::::SerializationError)?, + BoundedVec::try_from(BITCOIN_TESTNET_CAIP2.as_bytes().to_vec()) + .map_err(|_| Error::::SerializationError)?, + 0, // key_version + BoundedVec::try_from(path).map_err(|_| Error::::PathTooLong)?, + BoundedVec::try_from(b"ecdsa".to_vec()).map_err(|_| Error::::SerializationError)?, + BoundedVec::try_from(b"bitcoin".to_vec()).map_err(|_| Error::::SerializationError)?, + BoundedVec::try_from(vec![]).map_err(|_| Error::::SerializationError)?, + BoundedVec::try_from(explorer_schema).map_err(|_| Error::::SerializationError)?, + BoundedVec::try_from(callback_schema).map_err(|_| Error::::SerializationError)?, + )?; + + Self::deposit_event(Event::WithdrawalRequested { + request_id, + requester, + amount, + recipient_script_pubkey, + }); + + Ok(()) + } + + /// Complete a withdrawal after MPC signature verification + /// If the withdrawal failed on Bitcoin (error prefix or success=false), refund the balance + #[pallet::call_index(4)] + #[pallet::weight(Weight::from_parts(50_000, 0))] + pub fn complete_withdraw_btc( + origin: OriginFor, + request_id: [u8; 32], + serialized_output: BoundedVec>, + signature: pallet_signet::Signature, + ) -> DispatchResult { + let caller = ensure_signed(origin)?; + + // Get pending withdrawal + let pending = PendingWithdrawals::::get(&request_id).ok_or(Error::::WithdrawalNotFound)?; + + // Verify caller is the original requester + ensure!(pending.requester == caller, Error::::UnauthorizedClaimer); + + // Get vault config + let config = VaultConfig::::get().ok_or(Error::::NotInitialized)?; + + // Verify signature + let message_hash = Self::hash_message(&request_id, &serialized_output); + Self::verify_signature_from_address(&message_hash, &signature, &config.mpc_root_signer_address)?; + + // Check for error magic prefix + const ERROR_PREFIX: [u8; 4] = [0xDE, 0xAD, 0xBE, 0xEF]; + + let should_refund = if serialized_output.len() >= 4 && &serialized_output[..4] == ERROR_PREFIX { + // Error response - refund + true + } else { + // Decode boolean (Borsh serialized) + use borsh::BorshDeserialize; + let success = bool::try_from_slice(&serialized_output).map_err(|_| Error::::InvalidOutput)?; + !success // Refund if not successful + }; + + if should_refund { + // Refund the balance + UserBalances::::mutate(&pending.requester, |balance| -> DispatchResult { + *balance = balance.checked_add(pending.amount).ok_or(Error::::Overflow)?; + Ok(()) + })?; + + Self::deposit_event(Event::WithdrawalFailed { + request_id, + requester: pending.requester.clone(), + amount: pending.amount, + refunded: true, + }); + } else { + Self::deposit_event(Event::WithdrawalCompleted { + request_id, + requester: pending.requester.clone(), + amount: pending.amount, + }); + } + + // Clean up storage + PendingWithdrawals::::remove(&request_id); + + Ok(()) + } } // ========================= Helper Functions ========================= diff --git a/signet-ts-client-scripts/btc-vault.test.ts b/signet-ts-client-scripts/btc-vault.test.ts index 95f25136dd..73b2910bbc 100644 --- a/signet-ts-client-scripts/btc-vault.test.ts +++ b/signet-ts-client-scripts/btc-vault.test.ts @@ -11,153 +11,172 @@ import { KeyDerivation } from "./key-derivation"; import * as ecc from "tiny-secp256k1"; import coinSelect from "coinselect"; -// Initialize tiny-secp256k1 with bitcoinjs-lib bitcoin.initEccLib(ecc); const ROOT_PUBLIC_KEY = "0x044eef776e4f257d68983e45b340c2e9546c5df95447900b6aadfec68fb46fdee257e26b8ba383ddba9914b33c60e869265f859566fff4baef283c54d821ca3b64"; const CHAIN_ID = "bip122:000000000933ea01ad0ee984209779ba"; +const SECP256K1_N = BigInt("0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141"); +const VAULT_PUBKEY_HASH = new Uint8Array([ + 0x67, 0x6c, 0x36, 0x49, 0xc4, 0xa4, 0x24, 0x7e, 0xd0, 0x14, 0xff, 0x52, 0x50, + 0x73, 0xe6, 0x3b, 0xba, 0x5c, 0x43, 0xe4, +]); +const ERROR_PREFIX = Buffer.from([0xDE, 0xAD, 0xBE, 0xEF]); + +// ============ Helper Functions ============ + +function getPalletAccountId(): Uint8Array { + const data = new Uint8Array(32); + data.set(new TextEncoder().encode("modl"), 0); + data.set(new TextEncoder().encode("py/btcvt"), 4); + return data; +} + +function stripScalePrefix(data: Uint8Array): Uint8Array { + if (data.length === 0) return data; + const mode = data[0] & 0b11; + if (mode === 0) return data.slice(1); + if (mode === 1) return data.slice(2); + if (mode === 2) return data.slice(4); + return data; +} + +function compressPubkey(pubKey: string): Buffer { + const uncompressed = Buffer.from(pubKey.slice(4), "hex"); + const full = Buffer.concat([Buffer.from([0x04]), uncompressed]); + return Buffer.from(ecc.pointCompress(full, true)); +} + +function btcAddressFromPubKey(pubKey: string, network: bitcoin.Network): string { + return bitcoin.payments.p2wpkh({ pubkey: compressPubkey(pubKey), network }).address!; +} function normalizeSignature(r: Buffer, s: Buffer): { r: Buffer; s: Buffer } { - const N = BigInt( - "0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141" - ); - const halfN = N / 2n; const sBigInt = BigInt("0x" + s.toString("hex")); - - if (sBigInt > halfN) { - const normalizedS = N - sBigInt; - const sBuffer = Buffer.from( - normalizedS.toString(16).padStart(64, "0"), - "hex" - ); - return { r, s: sBuffer }; + if (sBigInt > SECP256K1_N / 2n) { + return { r, s: Buffer.from((SECP256K1_N - sBigInt).toString(16).padStart(64, "0"), "hex") }; } - return { r, s }; } -const TESTNET_VAULT_ADDRESS_HASH = new Uint8Array([ - 0x89, 0xf0, 0xa8, 0x23, 0x93, 0x8c, 0x58, 0xcf, 0x5b, 0x17, 0xc8, 0xeb, 0x93, - 0xc6, 0x82, 0x80, 0x63, 0x5b, 0x73, 0x4e, -]); +function extractSigBuffers(sig: any): { r: Buffer; s: Buffer } { + const r = typeof sig.bigR.x === "string" + ? Buffer.from(sig.bigR.x.slice(2), "hex") + : Buffer.from(sig.bigR.x); + const s = typeof sig.s === "string" + ? Buffer.from(sig.s.slice(2), "hex") + : Buffer.from(sig.s); + return normalizeSignature(r, s); +} -function getPalletAccountId(): Uint8Array { - const palletId = new TextEncoder().encode("py/btcvt"); - const modl = new TextEncoder().encode("modl"); - const data = new Uint8Array(32); - data.set(modl, 0); - data.set(palletId, 4); - return data; +function encodeDER(r: Buffer, s: Buffer): Buffer { + const toDER = (x: Buffer): Buffer => { + let i = 0; + while (i < x.length - 1 && x[i] === 0 && x[i + 1] < 0x80) i++; + const trimmed = x.subarray(i); + return trimmed[0] >= 0x80 ? Buffer.concat([Buffer.from([0x00]), trimmed]) : trimmed; + }; + const rDER = toDER(r), sDER = toDER(s); + const len = 2 + rDER.length + 2 + sDER.length; + const buf = Buffer.allocUnsafe(2 + len); + buf[0] = 0x30; buf[1] = len; + buf[2] = 0x02; buf[3] = rDER.length; + rDER.copy(buf, 4); + buf[4 + rDER.length] = 0x02; + buf[5 + rDER.length] = sDER.length; + sDER.copy(buf, 6 + rDER.length); + return buf; +} + +function getVaultScript(): Buffer { + return Buffer.concat([Buffer.from([0x00, 0x14]), Buffer.from(VAULT_PUBKEY_HASH)]); +} + +function getScriptCode(witnessScript: Buffer, network: bitcoin.Network): Buffer { + return bitcoin.payments.p2pkh({ hash: witnessScript.subarray(2), network }).output!; } async function submitWithRetry( - tx: any, - signer: any, - api: ApiPromise, - label: string, - maxRetries: number = 1, - timeoutMs: number = 60000 + tx: any, signer: any, api: ApiPromise, label: string, maxRetries = 3, timeoutMs = 60000 ): Promise<{ events: any[] }> { - let attempt = 0; - - while (attempt <= maxRetries) { + for (let attempt = 0; attempt <= maxRetries; attempt++) { try { - console.log(`${label} - Attempt ${attempt + 1}/${maxRetries + 1}`); - - const result = await new Promise<{ events: any[] }>((resolve, reject) => { - let unsubscribe: any; - - const timer = setTimeout(() => { - if (unsubscribe) unsubscribe(); - console.log(`ā±ļø ${label} timed out after ${timeoutMs}ms`); - reject(new Error("TIMEOUT")); - }, timeoutMs); + return await new Promise((resolve, reject) => { + let unsub: any; + const timer = setTimeout(() => { unsub?.(); reject(new Error("TIMEOUT")); }, timeoutMs); tx.signAndSend(signer, (result: ISubmittableResult) => { const { status, events, dispatchError } = result; - if (status.isInBlock) { - clearTimeout(timer); - if (unsubscribe) unsubscribe(); - - console.log( - `āœ… ${label} included in block ${status.asInBlock.toHex()}` - ); - - console.log(`šŸ“‹ All events (${events.length}):`); - for (const record of events) { - const { event } = record; - console.log(` ${event.section}.${event.method}`); - - if ( - event.section === "btcVault" && - event.method === "DebugTxid" - ) { - const palletTxid = event.data[0].toU8a(); - console.log( - `šŸ” PALLET TXID: ${Buffer.from(palletTxid).toString("hex")}` - ); - } - } - + clearTimeout(timer); unsub?.(); if (dispatchError) { - if (dispatchError.isModule) { - const decoded = api.registry.findMetaError( - dispatchError.asModule - ); - reject( - new Error( - `${decoded.section}.${decoded.name}: ${decoded.docs.join( - " " - )}` - ) - ); - } else { - reject(new Error(dispatchError.toString())); - } + const err = dispatchError.isModule + ? api.registry.findMetaError(dispatchError.asModule) + : { section: "", name: dispatchError.toString(), docs: [] }; + reject(new Error(`${err.section}.${err.name}`)); return; } - + console.log(`āœ… ${label} in block`); resolve({ events: Array.from(events) }); - } else if (status.isInvalid) { - clearTimeout(timer); - if (unsubscribe) unsubscribe(); - console.log(`āŒ Transaction INVALID - status:`, JSON.stringify(status.toJSON())); - reject(new Error("INVALID_TX")); - } else if (status.isDropped) { - clearTimeout(timer); - if (unsubscribe) unsubscribe(); - reject(new Error(`${label} dropped`)); + } else if (status.isInvalid || status.isDropped) { + clearTimeout(timer); unsub?.(); + reject(new Error(status.isInvalid ? "INVALID_TX" : "DROPPED")); } - }) - .then((unsub: any) => { - unsubscribe = unsub; - }) - .catch((error: any) => { - clearTimeout(timer); - reject(error); - }); + }).then((u: any) => unsub = u).catch((e: any) => { clearTimeout(timer); reject(e); }); }); - - return result; } catch (error: any) { - if ( - (error.message === "INVALID_TX" || error.message === "TIMEOUT") && - attempt < maxRetries - ) { + const msg = error.message || ""; + if ((msg === "INVALID_TX" || msg === "TIMEOUT" || msg.includes("stale")) && attempt < maxRetries) { console.log(`šŸ”„ Retrying ${label}...`); - attempt++; - await new Promise((resolve) => setTimeout(resolve, 2000)); + await new Promise(r => setTimeout(r, 2000)); continue; } throw error; } } + throw new Error(`${label} failed after retries`); +} - throw new Error(`${label} failed after ${maxRetries + 1} attempts`); +async function waitForSignature(api: ApiPromise, requestId: string, timeout: number): Promise { + return new Promise((resolve, reject) => { + let unsub: any; + const timer = setTimeout(() => { unsub?.(); reject(new Error(`Timeout for ${requestId}`)); }, timeout); + api.query.system.events((events: any) => { + for (const { event } of events) { + if (event.section === "signet" && event.method === "SignatureResponded") { + const [reqId, , signature] = event.data; + if (ethers.hexlify(reqId.toU8a()) === requestId) { + clearTimeout(timer); unsub?.(); + resolve(signature.toJSON()); + return; + } + } + } + }).then((u: any) => unsub = u); + }); +} + +async function waitForResponse(api: ApiPromise, requestId: string, timeout: number): Promise { + return new Promise(resolve => { + let unsub: any; + const timer = setTimeout(() => { unsub?.(); resolve(null); }, timeout); + api.query.system.events((events: any) => { + for (const { event } of events) { + if (event.section === "signet" && event.method === "RespondBidirectionalEvent") { + const [reqId, , output, signature] = event.data; + if (ethers.hexlify(reqId.toU8a()) === requestId) { + clearTimeout(timer); unsub?.(); + resolve({ output: Array.from(output.toU8a()), signature: signature.toJSON() }); + return; + } + } + } + }).then((u: any) => unsub = u); + }); } +// ============ Test Suite ============ + describe("BTC Vault Integration", () => { let api: ApiPromise; let alice: any; @@ -166,28 +185,14 @@ describe("BTC Vault Integration", () => { let derivedBtcAddress: string; let derivedPubKey: string; let network: bitcoin.Network; + let palletSS58: string; + let spentVaultUtxos: Array<{ txid: string; vout: number; value: number; script: Buffer }> = []; beforeAll(async () => { await waitReady(); - console.log("šŸ”— Connecting to Bitcoin regtest..."); - btcClient = new Client({ - host: "http://localhost:18443", - username: "test", - password: "test123", - }); - - try { - const blockCount = await btcClient.command("getblockcount"); - console.log( - `āœ… Connected to Bitcoin regtest (block height: ${blockCount})\n` - ); - } catch (error) { - throw new Error( - "āŒ Cannot connect to Bitcoin regtest. Make sure it's running:\n" + - " cd bitcoin-regtest && yarn docker:dev" - ); - } + btcClient = new Client({ host: "http://localhost:18443", username: "test", password: "test123" }); + await btcClient.command("getblockcount"); // Verify connection api = await ApiPromise.create({ provider: new WsProvider("ws://127.0.0.1:8000"), @@ -199,793 +204,361 @@ describe("BTC Vault Integration", () => { const keyring = new Keyring({ type: "sr25519" }); alice = keyring.addFromUri("//Alice"); - const bob = keyring.addFromUri("//Bob"); - - const { data: bobBalance } = (await api.query.system.account( - bob.address - )) as any; - - if (bobBalance.free.toBigInt() < 1000000000000n) { - console.log("Funding Bob's account for server responses..."); - const bobFundTx = api.tx.balances.transferKeepAlive( - bob.address, - 100000000000000n - ); - await submitWithRetry(bobFundTx, alice, api, "Fund Bob account"); - } - - const palletAccountId = getPalletAccountId(); - const palletSS58 = encodeAddress(palletAccountId, 0); - - const { data: palletBalance } = (await api.query.system.account( - palletSS58 - )) as any; - - const fundingAmount = 10000000000000n; - - if (palletBalance.free.toBigInt() < fundingAmount) { - console.log(`Funding BTC vault pallet account ${palletSS58}...`); - const fundTx = api.tx.balances.transferKeepAlive( - palletSS58, - fundingAmount + palletSS58 = encodeAddress(getPalletAccountId(), 0); + + // Fund pallet if needed + const { data: palletBalance } = (await api.query.system.account(palletSS58)) as any; + if (palletBalance.free.toBigInt() < 10000000000000n) { + await submitWithRetry( + api.tx.balances.transferKeepAlive(palletSS58, 10000000000000n), + alice, api, "Fund pallet" ); - await submitWithRetry(fundTx, alice, api, "Fund pallet account"); } signetClient = new SignetClient(api, alice); await signetClient.ensureInitialized(CHAIN_ID); - const aliceAccountId = keyring.decodeAddress(alice.address); - const aliceHexPath = "0x" + u8aToHex(aliceAccountId).slice(2); - - derivedPubKey = KeyDerivation.derivePublicKey( - ROOT_PUBLIC_KEY, - palletSS58, - aliceHexPath, - "polkadot:2034" - ); - - const compressedForComparison = compressPubkey(derivedPubKey); - console.log( - `šŸ” Test expects compressed pubkey: ${compressedForComparison.toString( - "hex" - )}` - ); - - console.log(`šŸ” Test using path: ${aliceHexPath}`); - console.log(`šŸ” Test using sender: ${palletSS58}`); - console.log(`šŸ” Derived public key: ${derivedPubKey}`); - + const aliceHexPath = "0x" + u8aToHex(keyring.decodeAddress(alice.address)).slice(2); + derivedPubKey = KeyDerivation.derivePublicKey(ROOT_PUBLIC_KEY, palletSS58, aliceHexPath, "polkadot:2034"); network = bitcoin.networks.regtest; derivedBtcAddress = btcAddressFromPubKey(derivedPubKey, network); - console.log(`\nšŸ”‘ Derived Bitcoin Address: ${derivedBtcAddress}`); - - await fundBitcoinAddress(derivedBtcAddress); - }, 180000); - - afterAll(async () => { - if (api) { - await api.disconnect(); - } - }); - - async function fundBitcoinAddress(address: string) { - console.log(`šŸ’° Funding ${address} with 1 BTC...`); - - try { - let walletAddress; - try { - walletAddress = await btcClient.command("getnewaddress"); - } catch (e) { - try { - await btcClient.command("createwallet", "testwallet"); - walletAddress = await btcClient.command("getnewaddress"); - } catch (createErr: any) { - await btcClient.command("loadwallet", "testwallet"); - walletAddress = await btcClient.command("getnewaddress"); - } - } - - await btcClient.command("generatetoaddress", 101, walletAddress); - console.log(` Mined 101 blocks to wallet`); - - const txid = await btcClient.command("sendtoaddress", address, 1.0); - console.log(` Funding txid: ${txid}`); - - await btcClient.command("generatetoaddress", 1, walletAddress); - - const scanResult = await btcClient.command("scantxoutset", "start", [ - `addr(${derivedBtcAddress})`, - ]); - - console.log(`šŸ“¦ Found ${scanResult.unspents.length} UTXO(s)`); - - for (const utxo of scanResult.unspents) { - console.log(`\nšŸ” UTXO ${utxo.txid}:${utxo.vout}`); - console.log(` scriptPubKey: ${utxo.scriptPubKey}`); - console.log(` amount: ${utxo.amount} BTC`); - } - - if (scanResult.unspents.length === 0) { - throw new Error("No UTXOs found after funding"); - } - - console.log("āœ… Funding confirmed\n"); - } catch (error: any) { - console.error("Funding error:", error.message); - throw error; + // Fund Bitcoin address + let walletAddr; + try { walletAddr = await btcClient.command("getnewaddress"); } + catch { + try { await btcClient.command("createwallet", "testwallet"); } + catch { await btcClient.command("loadwallet", "testwallet"); } + walletAddr = await btcClient.command("getnewaddress"); } - } - - it("should complete full deposit and claim flow", async () => { - const mpcEthAddress = ethAddressFromPubKey(ROOT_PUBLIC_KEY); - console.log("Checking vault initialization..."); + await btcClient.command("generatetoaddress", 101, walletAddr); + await btcClient.command("sendtoaddress", derivedBtcAddress, 1.0); + await btcClient.command("generatetoaddress", 1, walletAddr); + console.log(`āœ… Setup complete. Address: ${derivedBtcAddress}`); + }, 180000); - const existingConfig = await api.query.btcVault.vaultConfig(); - const configJson = existingConfig.toJSON(); - - if (configJson !== null) { - console.log("āš ļø Vault already initialized, skipping initialization"); - console.log(" Existing config:", existingConfig.toHuman()); - } else { - console.log("Initializing vault with MPC address hash"); - const initTx = api.tx.btcVault.initialize(Array.from(mpcEthAddress)); - await submitWithRetry(initTx, alice, api, "Initialize vault"); - } + afterAll(async () => { await api?.disconnect(); }); - const scanResult = await btcClient.command("scantxoutset", "start", [ - `addr(${derivedBtcAddress})`, + it("should complete deposit and claim flow", async () => { + // Initialize vault if needed + const mpcEthAddress = new Uint8Array([ + 0x00, 0xa4, 0x0c, 0x26, 0x61, 0x29, 0x3d, 0x51, 0x34, 0xe5, + 0x3d, 0xa5, 0x29, 0x51, 0xa3, 0xf7, 0x76, 0x78, 0x36, 0xef, ]); - - if (scanResult.unspents.length === 0) { - throw new Error("No UTXOs available for derived address"); + const existingConfig = await api.query.btcVault.vaultConfig(); + if (existingConfig.toJSON() === null) { + await submitWithRetry(api.tx.btcVault.initialize(Array.from(mpcEthAddress)), alice, api, "Initialize vault"); } - console.log(`šŸ“¦ Found ${scanResult.unspents.length} UTXO(s)`); + // Get UTXOs and build transaction + const scanResult = await btcClient.command("scantxoutset", "start", [`addr(${derivedBtcAddress})`]); + expect(scanResult.unspents.length).toBeGreaterThan(0); - const depositAmount = 36879690; - const feeRate = 2; // satoshis per vbyte (min relay fee requires slightly more than 1) - - // Convert UTXOs to coinselect format + const depositAmount = 35289790; const utxos = scanResult.unspents.map((u: any) => ({ - txid: u.txid, - vout: u.vout, + txid: u.txid, vout: u.vout, value: Math.floor(u.amount * 100000000), - script: Buffer.from( - bitcoin.address.toOutputScript(derivedBtcAddress, network) - ), + script: Buffer.from(bitcoin.address.toOutputScript(derivedBtcAddress, network)), })); - // Vault output - const vaultScript = Buffer.concat([ - Buffer.from([0x00, 0x14]), - Buffer.from(TESTNET_VAULT_ADDRESS_HASH), - ]); - - const targets = [ - { - script: vaultScript, - value: depositAmount, - }, - ]; - - // Let coinselect pick optimal UTXOs and calculate fee - const { inputs, outputs, fee } = coinSelect(utxos, targets, feeRate); - - if (!inputs || !outputs) { - throw new Error("Insufficient funds for transaction"); - } + const coinSelectResult = coinSelect(utxos, [{ script: getVaultScript(), value: depositAmount }], 2); + if (!coinSelectResult.inputs || !coinSelectResult.outputs) throw new Error("Insufficient funds"); + const { inputs, outputs } = coinSelectResult; - console.log(`šŸ“Š Transaction breakdown:`); - console.log(` Inputs: ${inputs.length}`); - inputs.forEach((inp: any, i: number) => { - console.log( - ` Input ${i}: ${inp.value} sats (${inp.txid.slice(0, 8)}...)` - ); - }); - console.log(` To vault: ${outputs[0].value} sats`); - if (outputs.length > 1) { - console.log(` Change: ${outputs[1].value} sats`); - } - console.log(` Fee: ${fee} sats\n`); - - // Build PSBT with selected inputs/outputs + // Build PSBT const psbt = new bitcoin.Psbt({ network }); - for (const input of inputs) { - const txidBytes = Buffer.from(input.txid, "hex").reverse(); psbt.addInput({ - hash: txidBytes, + hash: Buffer.from(input.txid, "hex").reverse(), index: input.vout, sequence: 0xffffffff, - witnessUtxo: { - script: input.script!, - value: input.value, - }, - }); - } - - for (let i = 0; i < inputs.length; i++) { - psbt.updateInput(i, { - sighashType: bitcoin.Transaction.SIGHASH_ALL, + witnessUtxo: { script: input.script!, value: input.value }, }); + psbt.updateInput(psbt.inputCount - 1, { sighashType: bitcoin.Transaction.SIGHASH_ALL }); } - for (const output of outputs) { - if (output.script) { - psbt.addOutput({ - script: output.script, - value: output.value, - }); - } else { - // Change output - psbt.addOutput({ - address: derivedBtcAddress, - value: output.value, - }); - } + psbt.addOutput(output.script + ? { script: output.script, value: output.value } + : { address: derivedBtcAddress, value: output.value } + ); } - const psbtBytes = psbt.toBuffer(); - console.log(`šŸ“ PSBT bytes length: ${psbtBytes.length}`); - - console.log(`šŸ” Test prevout txid (as sent to pallet): ${inputs[0].txid}`); - console.log( - `šŸ” Test prevout txid (reversed for PSBT): ${Buffer.from( - inputs[0].txid, - "hex" - ) - .reverse() - .toString("hex")}` - ); - - // Extract txid from PSBT - const unsignedTxBuffer = psbt.data.globalMap.unsignedTx.toBuffer(); - const unsignedTx = bitcoin.Transaction.fromBuffer(unsignedTxBuffer); + const unsignedTx = bitcoin.Transaction.fromBuffer(psbt.data.globalMap.unsignedTx.toBuffer()); const txid = Buffer.from(unsignedTx.getId(), "hex"); + const keyring = new Keyring({ type: "sr25519" }); + const aliceHexPath = "0x" + u8aToHex(keyring.decodeAddress(alice.address)).slice(2); - const testUnsignedTx = bitcoin.Transaction.fromBuffer(unsignedTxBuffer); - - const getScriptCode = (witnessScript: Buffer): Buffer => { - // witnessScript is P2WPKH: 00 14 - const pubkeyHash = witnessScript.slice(2); // Skip version byte and push opcode - return bitcoin.payments.p2pkh({ hash: pubkeyHash, network }).output!; - }; - - for (let i = 0; i < inputs.length; i++) { - const scriptCode = getScriptCode(inputs[i].script!); - const testSighash = testUnsignedTx.hashForWitnessV0( - i, - scriptCode, - inputs[i].value, - bitcoin.Transaction.SIGHASH_ALL - ); - console.log(`šŸ” Test Input ${i} sighash: ${testSighash.toString("hex")}`); - } - - console.log(`šŸ”‘ Transaction ID: ${txid.toString("hex")}`); + // Calculate request IDs + const aggregateRequestId = signetClient.calculateSignRespondRequestId(palletSS58, Array.from(txid), { + caip2Id: CHAIN_ID, keyVersion: 0, path: aliceHexPath, algo: "ecdsa", dest: "bitcoin", params: "", + }); - console.log(`šŸ” Test tx version: ${unsignedTx.version}`); - console.log(`šŸ” Test tx locktime: ${unsignedTx.locktime}`); + const perInputRequestIds = inputs.map((_: any, i: number) => { + const indexBuf = Buffer.alloc(4); indexBuf.writeUInt32LE(i, 0); + return ethers.hexlify(signetClient.calculateSignRespondRequestId( + palletSS58, Array.from(Buffer.concat([Buffer.from(unsignedTx.getId(), "hex"), indexBuf])), + { caip2Id: CHAIN_ID, keyVersion: 0, path: aliceHexPath, algo: "ecdsa", dest: "bitcoin", params: "" } + )); + }); - const keyring = new Keyring({ type: "sr25519" }); - const palletAccountId = getPalletAccountId(); - const palletSS58 = encodeAddress(palletAccountId, 0); - const aliceAccountId = keyring.decodeAddress(alice.address); - const aliceHexPath = "0x" + u8aToHex(aliceAccountId).slice(2); - - console.log(`šŸ” Pallet SS58 (sender): ${palletSS58}`); - console.log(`šŸ” Alice hex path: ${aliceHexPath}`); - - // Calculate aggregate request ID (for monitoring) - const aggregateRequestId = signetClient.calculateSignRespondRequestId( - palletSS58, - Array.from(txid), - { - caip2Id: CHAIN_ID, - keyVersion: 0, - path: aliceHexPath, - algo: "ecdsa", - dest: "bitcoin", - params: "", - } - ); + // Submit deposit + const palletInputs = inputs.map((i: any) => ({ + txid: Array.from(Buffer.from(i.txid, "hex")), vout: i.vout, value: i.value, + scriptPubkey: Array.from(i.script), sequence: 0xffffffff, + })); + const palletOutputs = outputs.map((o: any) => ({ + value: o.value, scriptPubkey: Array.from(o.script || bitcoin.address.toOutputScript(derivedBtcAddress, network)), + })); - console.log( - `šŸ“‹ Aggregate Request ID: ${ethers.hexlify(aggregateRequestId)}` + await submitWithRetry( + api.tx.btcVault.depositBtc(Array.from(ethers.getBytes(aggregateRequestId)), palletInputs, palletOutputs, 0), + alice, api, "Deposit BTC" ); - // Generate per-input request IDs - const txidForPerInputRequestId = Buffer.from(unsignedTx.getId(), "hex"); - - // Generate per-input request IDs - const perInputRequestIds: string[] = []; + // Wait for signatures and apply them + const compressedPubkey = compressPubkey(derivedPubKey); for (let i = 0; i < inputs.length; i++) { - const inputIndexBytes = Buffer.alloc(4); - inputIndexBytes.writeUInt32LE(i, 0); - // Use the display order txid reversed (internal order) to match server - const txDataForInput = Buffer.concat([ - txidForPerInputRequestId, - inputIndexBytes, - ]); - - const perInputRequestId = signetClient.calculateSignRespondRequestId( - palletSS58, - Array.from(txDataForInput), - { - caip2Id: CHAIN_ID, - keyVersion: 0, - path: aliceHexPath, - algo: "ecdsa", - dest: "bitcoin", - params: "", - } - ); - - perInputRequestIds.push(ethers.hexlify(perInputRequestId)); - console.log(`šŸ“‹ Input ${i} Request ID: ${perInputRequestIds[i]}`); + const sig = await waitForSignature(api, perInputRequestIds[i], 120000); + const { r, s } = extractSigBuffers(sig); + const scriptCode = getScriptCode(inputs[i].script!, network); + const sighash = unsignedTx.hashForWitnessV0(i, scriptCode, inputs[i].value, bitcoin.Transaction.SIGHASH_ALL); + expect(ecc.verify(sighash, compressedPubkey, Buffer.concat([r, s]))).toBe(true); + psbt.updateInput(i, { + partialSig: [{ pubkey: compressedPubkey, signature: Buffer.concat([encodeDER(r, s), Buffer.from([0x01])]) }], + }); } - console.log(""); // Empty line - - // Convert to pallet format - const palletInputs = inputs.map((input: any) => ({ - txid: Array.from(Buffer.from(input.txid, "hex")), - vout: input.vout, - value: input.value, - scriptPubkey: Array.from(input.script), - sequence: 0xffffffff, - })); - const palletOutputs = outputs.map((output: any) => { - if (output.script) { - return { - value: output.value, - scriptPubkey: Array.from(output.script), - }; - } else { - return { - value: output.value, - scriptPubkey: Array.from( - bitcoin.address.toOutputScript(derivedBtcAddress, network) - ), - }; - } - }); + // Broadcast + psbt.finalizeAllInputs(); + const signedTxHex = psbt.extractTransaction().toHex(); + await btcClient.command("sendrawtransaction", signedTxHex); + await btcClient.command("generatetoaddress", 1, derivedBtcAddress); - const depositTx = api.tx.btcVault.depositBtc( - Array.from(ethers.getBytes(aggregateRequestId)), - palletInputs, - palletOutputs, - 0 - ); + // Wait for read response and claim + const readResponse = await waitForResponse(api, ethers.hexlify(aggregateRequestId), 120000); + expect(readResponse).toBeTruthy(); - console.log("šŸš€ Submitting deposit_btc transaction..."); - const depositResult = await submitWithRetry( - depositTx, - alice, - api, - "Deposit BTC" - ); + const outputBytes = stripScalePrefix(new Uint8Array(readResponse.output)); + const balanceBefore = BigInt((await api.query.btcVault.userBalances(alice.address)).toString()); - const debugEvent = depositResult.events.find( - (record: any) => - record.event.section === "btcVault" && - record.event.method === "DebugTxid" + await submitWithRetry( + api.tx.btcVault.claimBtc(Array.from(ethers.getBytes(aggregateRequestId)), Array.from(outputBytes), readResponse.signature), + alice, api, "Claim BTC" ); - if (debugEvent) { - const palletTxid = debugEvent.event.data[0].toU8a(); - console.log( - `šŸ” Pallet computed txid: ${Buffer.from(palletTxid).toString("hex")}` - ); - console.log( - `šŸ” Test computed txid: ${Buffer.from(txid).toString("hex")}` - ); - console.log( - `šŸ” Match: ${ - Buffer.from(palletTxid).toString("hex") === - Buffer.from(txid).toString("hex") - }` - ); - } else { - console.log("āš ļø DebugTxid event not found"); - } + const balanceAfter = BigInt((await api.query.btcVault.userBalances(alice.address)).toString()); + expect((balanceAfter - balanceBefore).toString()).toBe(depositAmount.toString()); + console.log(`āœ… Deposit claimed: ${balanceAfter - balanceBefore} sats`); + }, 300000); - const debugTxEvent = depositResult.events.find( - (record: any) => - record.event.section === "btcVault" && - record.event.method === "DebugTransaction" - ); + it("should complete successful withdrawal", async () => { + const balanceBefore = BigInt((await api.query.btcVault.userBalances(alice.address)).toString()); + expect(balanceBefore).toBeGreaterThan(0n); - if (debugTxEvent) { - const palletTxHex = debugTxEvent.event.data[0].toHex(); - const palletVersion = debugTxEvent.event.data[1].toNumber(); - const palletLocktime = debugTxEvent.event.data[2].toNumber(); + const vaultScript = getVaultScript(); + const vaultAddress = bitcoin.address.fromOutputScript(vaultScript, network); + const vaultScan = await btcClient.command("scantxoutset", "start", [`addr(${vaultAddress})`]); + if (vaultScan.unspents.length === 0) return; - console.log(`šŸ” Pallet PSBT hex: ${palletTxHex}`); - console.log( - `šŸ” Pallet version: ${palletVersion}, locktime: ${palletLocktime}` - ); - } + const withdrawAmount = 10000000; + const vaultUtxos = vaultScan.unspents.map((u: any) => ({ + txid: u.txid, vout: u.vout, value: Math.floor(u.amount * 100000000), script: vaultScript, + })); + const recipientScript = Buffer.from(bitcoin.address.toOutputScript(derivedBtcAddress, network)); - const signetEvents = depositResult.events.filter( - (record: any) => - record.event.section === "signet" && - record.event.method === "SignBidirectionalRequested" - ); + const coinSelectResult = coinSelect(vaultUtxos, [{ script: recipientScript, value: withdrawAmount }], 2); + if (!coinSelectResult.inputs || !coinSelectResult.outputs) return; + const { inputs, outputs } = coinSelectResult; - console.log( - `šŸ“Š Found ${signetEvents.length} SignBidirectionalRequested event(s)` - ); + spentVaultUtxos = inputs.map((i: any) => ({ txid: i.txid, vout: i.vout, value: i.value, script: i.script })); - if (signetEvents.length > 0) { - console.log( - "āœ… SignBidirectionalRequested event emitted - MPC should pick it up!" - ); + // Build PSBT + const psbt = new bitcoin.Psbt({ network }); + for (const input of inputs) { + psbt.addInput({ + hash: Buffer.from(input.txid, "hex").reverse(), + index: input.vout, sequence: 0xffffffff, + witnessUtxo: { script: input.script!, value: input.value }, + }); + psbt.updateInput(psbt.inputCount - 1, { sighashType: bitcoin.Transaction.SIGHASH_ALL }); + } + for (const output of outputs) { + psbt.addOutput(output.script ? { script: output.script, value: output.value } : { script: vaultScript, value: output.value }); } - console.log("ā³ Waiting for MPC signature(s)..."); + const unsignedTx = bitcoin.Transaction.fromBuffer(psbt.data.globalMap.unsignedTx.toBuffer()); + const txid = Buffer.from(unsignedTx.getId(), "hex"); + const withdrawalPath = "root"; - // Wait for each input's signature separately - const signatures: any[] = []; - for (let i = 0; i < perInputRequestIds.length; i++) { - console.log( - ` Waiting for signature ${i + 1}/${perInputRequestIds.length}...` - ); - const sig = await waitForSingleSignature( - api, - perInputRequestIds[i], - 120000 - ); - signatures.push(sig); - console.log(` āœ… Received signature ${i + 1}`); - } + const aggregateRequestId = signetClient.calculateSignRespondRequestId(palletSS58, Array.from(txid), { + caip2Id: CHAIN_ID, keyVersion: 0, path: withdrawalPath, algo: "ecdsa", dest: "bitcoin", params: "", + }); - console.log( - `\nāœ… Received all ${signatures.length} signature(s) from MPC\n` - ); + const perInputRequestIds = inputs.map((_: any, i: number) => { + const indexBuf = Buffer.alloc(4); indexBuf.writeUInt32LE(i, 0); + return ethers.hexlify(signetClient.calculateSignRespondRequestId( + palletSS58, Array.from(Buffer.concat([Buffer.from(unsignedTx.getId(), "hex"), indexBuf])), + { caip2Id: CHAIN_ID, keyVersion: 0, path: withdrawalPath, algo: "ecdsa", dest: "bitcoin", params: "" } + )); + }); - const compressedPubkey = compressPubkey(derivedPubKey); + const palletInputs = inputs.map((i: any) => ({ + txid: Array.from(Buffer.from(i.txid, "hex")), vout: i.vout, value: i.value, + scriptPubkey: Array.from(i.script), sequence: 0xffffffff, + })); + const palletOutputs = outputs.map((o: any) => ({ + value: o.value, scriptPubkey: Array.from(o.script || vaultScript), + })); - for (let i = 0; i < signatures.length; i++) { - const sig = signatures[i]; - - const rBuf = - typeof sig.bigR.x === "string" - ? Buffer.from(sig.bigR.x.slice(2), "hex") - : Buffer.from(sig.bigR.x); - - const sBuf = - typeof sig.s === "string" - ? Buffer.from(sig.s.slice(2), "hex") - : Buffer.from(sig.s); - - const { r: normalizedR, s: normalizedS } = normalizeSignature(rBuf, sBuf); - - console.log(`šŸ” Signature ${i} verification:`); - console.log(` R: ${normalizedR.toString("hex")}`); - console.log(` S: ${normalizedS.toString("hex")}`); - console.log(` Recovery ID: ${sig.recoveryId}`); - - // VERIFY THE SIGNATURE - use correct BIP-143 scriptCode - const scriptCode = getScriptCode(inputs[i].script!); - const testSighash = testUnsignedTx.hashForWitnessV0( - i, - scriptCode, - inputs[i].value, - bitcoin.Transaction.SIGHASH_ALL - ); + const withdrawResult = await submitWithRetry( + api.tx.btcVault.withdrawBtc( + Array.from(ethers.getBytes(aggregateRequestId)), withdrawAmount, + Array.from(recipientScript), palletInputs, palletOutputs, 0 + ), + alice, api, "Withdraw BTC" + ); + expect(withdrawResult.events.some((r: any) => r.event.section === "btcVault" && r.event.method === "WithdrawalRequested")).toBe(true); - // Verify signature is valid before broadcasting to Bitcoin - const rawSig = Buffer.concat([normalizedR, normalizedS]); - console.log(` Sighash for verify: ${testSighash.toString("hex")}`); - console.log(` Pubkey: ${compressedPubkey.toString("hex")}`); - console.log(` RawSig (64 bytes): ${rawSig.toString("hex")}`); - const isValid = ecc.verify(testSighash, compressedPubkey, rawSig); - console.log(` Signature valid (ecc.verify): ${isValid}`); - expect(isValid).toBe(true); + // Verify optimistic decrement + const balanceAfterWithdraw = BigInt((await api.query.btcVault.userBalances(alice.address)).toString()); + expect(balanceAfterWithdraw).toBe(balanceBefore - BigInt(withdrawAmount)); - const derSig = encodeDER(normalizedR, normalizedS); - const fullSig = Buffer.concat([derSig, Buffer.from([0x01])]); + // Get signatures + const vaultPubKey = KeyDerivation.derivePublicKey(ROOT_PUBLIC_KEY, palletSS58, withdrawalPath, "polkadot:2034"); + const vaultCompressed = compressPubkey(vaultPubKey); + for (let i = 0; i < inputs.length; i++) { + const sig = await waitForSignature(api, perInputRequestIds[i], 120000); + const { r, s } = extractSigBuffers(sig); psbt.updateInput(i, { - partialSig: [ - { - pubkey: compressedPubkey, - signature: fullSig, - }, - ], + partialSig: [{ pubkey: vaultCompressed, signature: Buffer.concat([encodeDER(r, s), Buffer.from([0x01])]) }], }); } - console.log(`šŸ” Input 0 witnessUtxo:`, psbt.data.inputs[0].witnessUtxo); + // Broadcast psbt.finalizeAllInputs(); - const signedTx = psbt.extractTransaction(); - console.log(`šŸ” Witness for input 0:`); - const witness = signedTx.ins[0].witness; - witness.forEach((w, idx) => { - console.log(` Witness ${idx}: ${w.toString("hex")}`); - }); - const signedTxHex = signedTx.toHex(); - - console.log(`\nšŸ” Full signed transaction hex (first 200 chars):`); - console.log(` ${signedTxHex.substring(0, 200)}...`); - console.log( - `šŸ” Transaction input 0 sequence: 0x${signedTx.ins[0].sequence.toString( - 16 - )}` - ); - - console.log(`āœ… Transaction finalized: ${signedTx.getId()}\n`); - - console.log("šŸ“” Broadcasting transaction to regtest..."); - const broadcastTxid = await btcClient.command( - "sendrawtransaction", - signedTxHex - ); - console.log(` Tx Hash: ${broadcastTxid}`); - - console.log("ā›ļø Mining block to confirm transaction..."); + await btcClient.command("sendrawtransaction", psbt.extractTransaction().toHex()); await btcClient.command("generatetoaddress", 1, derivedBtcAddress); - const txDetails = await btcClient.command( - "getrawtransaction", - broadcastTxid, - true - ); + // Complete withdrawal + const readResponse = await waitForResponse(api, ethers.hexlify(aggregateRequestId), 120000); + expect(readResponse).toBeTruthy(); - console.log( - `āœ… Transaction confirmed (${txDetails.confirmations} confirmations)\n` + const outputBytes = stripScalePrefix(new Uint8Array(readResponse.output)); + const completeResult = await submitWithRetry( + api.tx.btcVault.completeWithdrawBtc(Array.from(ethers.getBytes(aggregateRequestId)), Array.from(outputBytes), readResponse.signature), + alice, api, "Complete Withdraw" ); - console.log("ā³ Waiting for MPC to read transaction result..."); - const readResponse = await waitForReadResponse( - api, - ethers.hexlify(aggregateRequestId), - 120000 - ); + expect(completeResult.events.some((r: any) => r.event.section === "btcVault" && r.event.method === "WithdrawalCompleted")).toBe(true); + console.log(`āœ… Withdrawal completed: ${withdrawAmount} sats`); + }, 300000); - if (!readResponse) { - throw new Error("āŒ Timeout waiting for read response"); - } + it("should refund when withdrawal fails", async () => { + if (spentVaultUtxos.length === 0) return; - console.log("āœ… Received read response\n"); + const balanceBefore = BigInt((await api.query.btcVault.userBalances(alice.address)).toString()); + expect(balanceBefore).toBeGreaterThan(0n); - console.log("\nšŸ” Claim Debug:"); - console.log(" Request ID:", ethers.hexlify(aggregateRequestId)); - console.log( - " Output (hex):", - Buffer.from(readResponse.output).toString("hex") - ); - - let outputBytes = new Uint8Array(readResponse.output); - if (outputBytes.length > 0) { - const mode = outputBytes[0] & 0b11; - if (mode === 0) { - outputBytes = outputBytes.slice(1); - } else if (mode === 1) { - outputBytes = outputBytes.slice(2); - } else if (mode === 2) { - outputBytes = outputBytes.slice(4); - } - } + const vaultScript = getVaultScript(); + const recipientScript = Buffer.from(bitcoin.address.toOutputScript(derivedBtcAddress, network)); + const totalValue = spentVaultUtxos.reduce((sum, u) => sum + u.value, 0); + const withdrawAmount = Math.min(5000000, totalValue - 1000); + const fee = 500; - console.log( - " Stripped output (hex):", - Buffer.from(outputBytes).toString("hex") - ); - console.log(" Signature:", JSON.stringify(readResponse.signature)); - - // Verify the signature manually - const requestIdBytes = ethers.getBytes(aggregateRequestId); - const messageForHash = new Uint8Array(requestIdBytes.length + outputBytes.length); - messageForHash.set(requestIdBytes); - messageForHash.set(outputBytes, requestIdBytes.length); - const expectedMessageHash = ethers.keccak256(messageForHash); - console.log(" Expected message hash:", expectedMessageHash); - - // Try to recover address from signature - const sig = readResponse.signature; - // sig.bigR.x can be either a hex string or an array - handle both - const rHex = typeof sig.bigR.x === 'string' - ? sig.bigR.x - : "0x" + Buffer.from(sig.bigR.x).toString("hex"); - const sHex = typeof sig.s === 'string' - ? sig.s - : "0x" + Buffer.from(sig.s).toString("hex"); - const recoveryId = sig.recoveryId; - console.log(" Sig R:", rHex); - console.log(" Sig S:", sHex); - console.log(" Recovery ID:", recoveryId); + const inputs = spentVaultUtxos; + const outputs = [ + { script: recipientScript, value: withdrawAmount }, + { script: vaultScript, value: totalValue - withdrawAmount - fee }, + ]; - try { - const ethSignature = ethers.Signature.from({ - r: rHex, - s: sHex, - v: 27 + recoveryId, + // Build PSBT with spent UTXOs + const psbt = new bitcoin.Psbt({ network }); + for (const input of inputs) { + psbt.addInput({ + hash: Buffer.from(input.txid, "hex").reverse(), + index: input.vout, sequence: 0xffffffff, + witnessUtxo: { script: input.script!, value: input.value }, }); - const recoveredAddress = ethers.recoverAddress(expectedMessageHash, ethSignature); - console.log(" Recovered address:", recoveredAddress.toLowerCase()); - } catch (e: any) { - console.log(" Address recovery failed:", e.message); + psbt.updateInput(psbt.inputCount - 1, { sighashType: bitcoin.Transaction.SIGHASH_ALL }); } - - // Check vault config - const vaultConfig = await api.query.btcVault.vaultConfig(); - console.log(" Vault config:", vaultConfig.toJSON()); - - // Check if pending deposit exists - const pendingDeposit = await api.query.btcVault.pendingDeposits( - Array.from(ethers.getBytes(aggregateRequestId)) - ); - console.log(" Pending deposit exists:", !pendingDeposit.isEmpty); - if (!pendingDeposit.isEmpty) { - console.log(" Pending deposit:", pendingDeposit.toJSON()); - } - - const balanceBefore = await api.query.btcVault.userBalances(alice.address); - - const claimTx = api.tx.btcVault.claimBtc( - Array.from(ethers.getBytes(aggregateRequestId)), - Array.from(outputBytes), - readResponse.signature - ); - - // Try to do a dry run first - console.log("šŸ” Testing claim transaction (dry run)..."); - try { - const paymentInfo = await claimTx.paymentInfo(alice); - console.log(" Payment info:", paymentInfo.toJSON()); - } catch (e: any) { - console.log(" Dry run failed:", e.message); + for (const output of outputs) { + psbt.addOutput({ script: output.script, value: output.value }); } - console.log("šŸš€ Submitting claim transaction..."); - await submitWithRetry(claimTx, alice, api, "Claim BTC"); - - const balanceAfter = await api.query.btcVault.userBalances(alice.address); - - const balanceIncrease = - BigInt(balanceAfter.toString()) - BigInt(balanceBefore.toString()); - - expect(balanceIncrease.toString()).toBe(depositAmount.toString()); - console.log(`āœ… Balance increased by: ${balanceIncrease} sats`); - console.log(` Total balance: ${balanceAfter} sats\n`); - }, 300000); + const unsignedTx = bitcoin.Transaction.fromBuffer(psbt.data.globalMap.unsignedTx.toBuffer()); + const txid = Buffer.from(unsignedTx.getId(), "hex"); + const withdrawalPath = "root"; - function compressPubkey(pubKey: string): Buffer { - const uncompressed = Buffer.from(pubKey.slice(4), "hex"); - const fullUncompressed = Buffer.concat([Buffer.from([0x04]), uncompressed]); - const compressed = ecc.pointCompress(fullUncompressed, true); - return Buffer.from(compressed); - } + const aggregateRequestId = signetClient.calculateSignRespondRequestId(palletSS58, Array.from(txid), { + caip2Id: CHAIN_ID, keyVersion: 0, path: withdrawalPath, algo: "ecdsa", dest: "bitcoin", params: "", + }); - function btcAddressFromPubKey( - pubKey: string, - network: bitcoin.Network - ): string { - const compressedPubkey = compressPubkey(pubKey); - const payment = bitcoin.payments.p2wpkh({ - pubkey: compressedPubkey, - network, + const perInputRequestIds = inputs.map((_, i) => { + const indexBuf = Buffer.alloc(4); indexBuf.writeUInt32LE(i, 0); + return ethers.hexlify(signetClient.calculateSignRespondRequestId( + palletSS58, Array.from(Buffer.concat([Buffer.from(unsignedTx.getId(), "hex"), indexBuf])), + { caip2Id: CHAIN_ID, keyVersion: 0, path: withdrawalPath, algo: "ecdsa", dest: "bitcoin", params: "" } + )); }); - return payment.address!; - } - function ethAddressFromPubKey(pubKey: string): Uint8Array { - const uncompressedPubkey = Buffer.from(pubKey.slice(4), "hex"); - const hash = ethers.keccak256(uncompressedPubkey); - return new Uint8Array(Buffer.from(hash.slice(2), "hex").slice(-20)); - } + const palletInputs = inputs.map((i: any) => ({ + txid: Array.from(Buffer.from(i.txid, "hex")), vout: i.vout, value: i.value, + scriptPubkey: Array.from(i.script), sequence: 0xffffffff, + })); + const palletOutputs = outputs.map((o: any) => ({ value: o.value, scriptPubkey: Array.from(o.script) })); - function encodeDER(r: Buffer, s: Buffer): Buffer { - function toDER(x: Buffer): Buffer { - let i = 0; - while (i < x.length - 1 && x[i] === 0 && x[i + 1] < 0x80) i++; + await submitWithRetry( + api.tx.btcVault.withdrawBtc( + Array.from(ethers.getBytes(aggregateRequestId)), withdrawAmount, + Array.from(recipientScript), palletInputs, palletOutputs, 0 + ), + alice, api, "Withdraw BTC (refund)" + ); - const xDER = x.slice(i); + const balanceAfterWithdraw = BigInt((await api.query.btcVault.userBalances(alice.address)).toString()); + expect(balanceAfterWithdraw).toBe(balanceBefore - BigInt(withdrawAmount)); - if (xDER[0] >= 0x80) { - return Buffer.concat([Buffer.from([0x00]), xDER]); - } + // Get signatures + const vaultPubKey = KeyDerivation.derivePublicKey(ROOT_PUBLIC_KEY, palletSS58, withdrawalPath, "polkadot:2034"); + const vaultCompressed = compressPubkey(vaultPubKey); - return xDER; + for (let i = 0; i < inputs.length; i++) { + const sig = await waitForSignature(api, perInputRequestIds[i], 120000); + const { r, s } = extractSigBuffers(sig); + psbt.updateInput(i, { + partialSig: [{ pubkey: vaultCompressed, signature: Buffer.concat([encodeDER(r, s), Buffer.from([0x01])]) }], + }); } - const rDER = toDER(r); - const sDER = toDER(s); - - const len = 2 + rDER.length + 2 + sDER.length; - const buf = Buffer.allocUnsafe(2 + len); - - buf[0] = 0x30; - buf[1] = len; - buf[2] = 0x02; - buf[3] = rDER.length; - rDER.copy(buf, 4); - buf[4 + rDER.length] = 0x02; - buf[5 + rDER.length] = sDER.length; - sDER.copy(buf, 6 + rDER.length); - - return buf; - } + psbt.finalizeAllInputs(); + const signedTxHex = psbt.extractTransaction().toHex(); + + // Broadcast should fail (spent UTXOs) + let broadcastFailed = false; + try { await btcClient.command("sendrawtransaction", signedTxHex); } + catch { broadcastFailed = true; } + expect(broadcastFailed).toBe(true); + console.log("āœ… Broadcast failed as expected (spent UTXOs)"); + + // Wait for MPC error response + const readResponse = await waitForResponse(api, ethers.hexlify(aggregateRequestId), 300000); + expect(readResponse).toBeTruthy(); + + const outputBytes = stripScalePrefix(new Uint8Array(readResponse.output)); + expect(Buffer.from(outputBytes.slice(0, 4)).equals(ERROR_PREFIX)).toBe(true); + + // Complete withdrawal with error + const completeResult = await submitWithRetry( + api.tx.btcVault.completeWithdrawBtc(Array.from(ethers.getBytes(aggregateRequestId)), Array.from(outputBytes), readResponse.signature), + alice, api, "Complete Withdraw (refund)" + ); - async function waitForSingleSignature( - api: ApiPromise, - requestId: string, - timeout: number - ): Promise { - return new Promise((resolve, reject) => { - let unsubscribe: any; - const timer = setTimeout(() => { - if (unsubscribe) unsubscribe(); - reject( - new Error( - `Timeout waiting for signature with request ID ${requestId}` - ) - ); - }, timeout); - - api.query.system - .events((events: any) => { - events.forEach((record: any) => { - const { event } = record; - if ( - event.section === "signet" && - event.method === "SignatureResponded" - ) { - const [reqId, responder, signature] = event.data; - if (ethers.hexlify(reqId.toU8a()) === requestId) { - clearTimeout(timer); - if (unsubscribe) unsubscribe(); - resolve(signature.toJSON()); - } - } - }); - }) - .then((unsub: any) => { - unsubscribe = unsub; - }); - }); - } + expect(completeResult.events.some((r: any) => r.event.section === "btcVault" && r.event.method === "WithdrawalFailed")).toBe(true); - async function waitForReadResponse( - api: ApiPromise, - requestId: string, - timeout: number - ): Promise { - return new Promise((resolve) => { - let unsubscribe: any; - const timer = setTimeout(() => { - if (unsubscribe) unsubscribe(); - resolve(null); - }, timeout); - - api.query.system - .events((events: any) => { - events.forEach((record: any) => { - const { event } = record; - if ( - event.section === "signet" && - event.method === "RespondBidirectionalEvent" - ) { - const [reqId, responder, output, signature] = event.data; - if (ethers.hexlify(reqId.toU8a()) === requestId) { - clearTimeout(timer); - if (unsubscribe) unsubscribe(); - resolve({ - responder: responder.toString(), - output: Array.from(output.toU8a()), - signature: signature.toJSON(), - }); - } - } - }); - }) - .then((unsub: any) => { - unsubscribe = unsub; - }); - }); - } + // Verify refund + const finalBalance = BigInt((await api.query.btcVault.userBalances(alice.address)).toString()); + expect(finalBalance).toBe(balanceBefore); + console.log(`āœ… Refund verified: balance restored to ${finalBalance} sats`); + }, 360000); }); From 98795ea8db0c354130bc78fbbcfb44336363121b Mon Sep 17 00:00:00 2001 From: Osman Abdelnasir Date: Sun, 25 Jan 2026 11:38:05 +0400 Subject: [PATCH 3/3] fix: dispenser test --- runtime/hydradx/src/assets.rs | 6 +- scripts/dispenser-tests/deploy-faucet.ts | 109 + scripts/dispenser-tests/dispenser.test.ts | 67 +- scripts/dispenser-tests/signet-client.ts | 4 +- scripts/dispenser-tests/yarn.lock | 3432 +++++++++++++++++ signet-ts-client-scripts/check-mpc-chainid.ts | 51 + .../compare-derivations.ts | 59 + .../debug-test-derivation.ts | 75 + .../get-root-eth-address.ts | 26 + .../verify-address-derivation.ts | 114 + .../verify-alice-derivation.ts | 97 + .../verify-all-addresses.ts | 95 + .../verify-pubkey-match.ts | 18 + signet-ts-client-scripts/verify-utxo-match.ts | 41 + 14 files changed, 4162 insertions(+), 32 deletions(-) create mode 100644 scripts/dispenser-tests/deploy-faucet.ts create mode 100644 scripts/dispenser-tests/yarn.lock create mode 100644 signet-ts-client-scripts/check-mpc-chainid.ts create mode 100644 signet-ts-client-scripts/compare-derivations.ts create mode 100644 signet-ts-client-scripts/debug-test-derivation.ts create mode 100644 signet-ts-client-scripts/get-root-eth-address.ts create mode 100644 signet-ts-client-scripts/verify-address-derivation.ts create mode 100644 signet-ts-client-scripts/verify-alice-derivation.ts create mode 100644 signet-ts-client-scripts/verify-all-addresses.ts create mode 100644 signet-ts-client-scripts/verify-pubkey-match.ts create mode 100644 signet-ts-client-scripts/verify-utxo-match.ts diff --git a/runtime/hydradx/src/assets.rs b/runtime/hydradx/src/assets.rs index d76dc1bd34..06e0b6cf56 100644 --- a/runtime/hydradx/src/assets.rs +++ b/runtime/hydradx/src/assets.rs @@ -1901,9 +1901,11 @@ impl frame_support::traits::Get for SigEthFaucetTreasuryAccount { pub struct SigEthFaucetContractAddr; impl frame_support::traits::Get<[u8; 20]> for SigEthFaucetContractAddr { fn get() -> [u8; 20] { + // TODO: revert to production address: 0x52Be077e67496c9763cCEF66c1117dD234Ca8Cfc + // Using test-deployed faucet with correct MPC address [ - 0x52, 0xBE, 0x07, 0x7E, 0x67, 0x49, 0x6C, 0x97, 0x63, 0xCC, 0xEF, 0x66, 0xC1, 0x11, 0x7D, 0xD2, 0x34, 0xCA, - 0x8C, 0xFC, + 0x1a, 0x9a, 0xc4, 0xA7, 0x8b, 0xaE, 0x11, 0x2C, 0xA3, 0xB2, 0x49, 0xd6, 0x13, 0x3d, 0x58, 0xf0, 0xAe, 0x1A, + 0xb3, 0x61, ] } } diff --git a/scripts/dispenser-tests/deploy-faucet.ts b/scripts/dispenser-tests/deploy-faucet.ts new file mode 100644 index 0000000000..0ea211f596 --- /dev/null +++ b/scripts/dispenser-tests/deploy-faucet.ts @@ -0,0 +1,109 @@ +/** + * Deploy GasFaucet contracts to Sepolia + * + * Usage: + * 1. Set DEPLOYER_PRIVATE_KEY below + * 2. Run: npx ts-node deploy-faucet.ts + * 3. Update runtime hardcode with the deployed faucet address + * 4. Rebuild runtime and restart chopsticks + */ + +import { ethers } from 'ethers' +import * as fs from 'fs' +import * as path from 'path' + +// ============================================ +// CONFIGURATION - Update these values +// ============================================ + +// Private key for deployment (with 0x prefix) +const DEPLOYER_PRIVATE_KEY = '0x...' // TODO: Set your deployer private key + +// MPC address that will call fund() - this is the derived caller address +// (pallet account as sender, user account id as path, chainId = polkadot:2034) +const MPC_ADDRESS = '0x508311e567d51cb659df2225c6f32c9f369f9470' + +// Sepolia RPC +const SEPOLIA_RPC = 'https://ethereum-sepolia-rpc.publicnode.com' + +// ============================================ + +const GasFaucetArtifact = JSON.parse( + fs.readFileSync(path.join(__dirname, 'artifacts/GasFaucet.json'), 'utf8') +) +const GasVoucherArtifact = JSON.parse( + fs.readFileSync(path.join(__dirname, 'artifacts/GasVoucher.json'), 'utf8') +) + +async function main() { + console.log('\n=== Faucet Contract Deployment ===\n') + + const provider = new ethers.JsonRpcProvider(SEPOLIA_RPC) + const wallet = new ethers.Wallet(DEPLOYER_PRIVATE_KEY, provider) + const deployerAddress = wallet.address + + console.log(`Deployer: ${deployerAddress}`) + console.log(`MPC Address: ${MPC_ADDRESS}`) + + const balance = await provider.getBalance(deployerAddress) + console.log(`Balance: ${ethers.formatEther(balance)} ETH\n`) + + if (balance < ethers.parseEther('0.02')) { + throw new Error('Insufficient balance. Need at least 0.02 ETH for deployment.') + } + + // Deploy GasVoucher + console.log('šŸ“¦ Deploying GasVoucher...') + const voucherFactory = new ethers.ContractFactory( + GasVoucherArtifact.abi, + GasVoucherArtifact.bytecode.object, + wallet + ) + const voucher = await voucherFactory.deploy(deployerAddress) + await voucher.waitForDeployment() + const voucherAddress = await voucher.getAddress() + console.log(` āœ… GasVoucher deployed at: ${voucherAddress}\n`) + + // Deploy GasFaucet + console.log('šŸ“¦ Deploying GasFaucet...') + const faucetFactory = new ethers.ContractFactory( + GasFaucetArtifact.abi, + GasFaucetArtifact.bytecode.object, + wallet + ) + const faucet = await faucetFactory.deploy( + MPC_ADDRESS, // mpc + voucherAddress, // voucher + ethers.parseEther('0.05'), // threshold + deployerAddress // owner + ) + await faucet.waitForDeployment() + const faucetAddress = await faucet.getAddress() + console.log(` āœ… GasFaucet deployed at: ${faucetAddress}\n`) + + // Set faucet in voucher + console.log('šŸ“ Setting faucet in GasVoucher...') + const voucherContract = new ethers.Contract( + voucherAddress, + ['function setFaucet(address _faucet) external'], + wallet + ) + const tx = await voucherContract.setFaucet(faucetAddress) + await tx.wait() + console.log(' āœ… Faucet set in GasVoucher\n') + + console.log('='.repeat(50)) + console.log('DEPLOYMENT COMPLETE') + console.log('='.repeat(50)) + console.log(`\nGasVoucher: ${voucherAddress}`) + console.log(`GasFaucet: ${faucetAddress}`) + console.log(`MPC: ${MPC_ADDRESS}`) + console.log(`\nšŸ“‹ Next steps:`) + console.log(` 1. Update runtime/hydradx/src/assets.rs with faucet address:`) + console.log(` ${faucetAddress}`) + console.log(` 2. Rebuild runtime: cargo build --release`) + console.log(` 3. Restart chopsticks with new runtime`) + console.log(` 4. Run the dispenser test\n`) +} + +main().catch(console.error) diff --git a/scripts/dispenser-tests/dispenser.test.ts b/scripts/dispenser-tests/dispenser.test.ts index 8879e434fa..dc32e69e9d 100644 --- a/scripts/dispenser-tests/dispenser.test.ts +++ b/scripts/dispenser-tests/dispenser.test.ts @@ -16,17 +16,20 @@ const SEPOLIA_RPC = 'https://ethereum-sepolia-rpc.publicnode.com' const ANVIL_RPC = 'http://localhost:8545' const ANVIL_PUBLIC_KEY = '0x048318535b54105d4a7aae60c08fc45f9687181b4fdfc625bd1a753fa7397fed753547f11ca8696646f2f3acb08e31016afac23e630c5d11f59f61fef57b0d2aa5' +// TODO: revert to production key const SEPOLIA_PUBLIC_KEY = - '0x047ca560e19ef0fb49f046670e50b6ceb394122ddfed5526802e5e438cdd2bc5347963e633398aa8498e8711c416746d87d49a8860e04967761d0a0cea229a5220' + '0x044eef776e4f257d68983e45b340c2e9546c5df95447900b6aadfec68fb46fdee257e26b8ba383ddba9914b33c60e869265f859566fff4baef283c54d821ca3b64' +// ORIGINAL: '0x047ca560e19ef0fb49f046670e50b6ceb394122ddfed5526802e5e438cdd2bc5347963e633398aa8498e8711c416746d87d49a8860e04967761d0a0cea229a5220' const SEPOLIA_CHAIN_ID = 11155111 const ANVIL_CHAIN_ID = 31337 const CHAIN_ID = 'polkadot:2034' const ANVIL_FAUCET_ADDRESS = '0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512' -const SEPOLIA_FAUCET_ADDRESS = '0x52Be077e67496c9763cCEF66c1117dD234Ca8Cfc' +// TODO: revert to production address: 0x52Be077e67496c9763cCEF66c1117dD234Ca8Cfc +const SEPOLIA_FAUCET_ADDRESS = '0x1a9ac4A78baE112CA3B249d6133d58f0Ae1Ab361' const LOCAL_SS58_PREFIX = 0 const RPC_URL = isSepolia ? SEPOLIA_RPC : ANVIL_RPC -const ROOT_PUBLIC_KEY = isSepolia ? SEPOLIA_PUBLIC_KEY : ANVIL_PUBLIC_KEY +const ROOT_PUBLIC_KEY = isSepolia ? SEPOLIA_PUBLIC_KEY : ANVIL_PUBLIC_KEY // replace this with MPC public key if using MPC backend const EVM_CHAIN_ID = isSepolia ? SEPOLIA_CHAIN_ID : ANVIL_CHAIN_ID const FAUCET_ADDRESS = isSepolia ? SEPOLIA_FAUCET_ADDRESS : ANVIL_FAUCET_ADDRESS @@ -60,7 +63,7 @@ export async function submitWithRetry( api: ApiPromise, label: string, maxRetries: number = 1, - timeoutMs: number = 60_000 + timeoutMs: number = 300_000 ): Promise<{ events: any[] }> { let attempt = 0 @@ -304,6 +307,7 @@ async function fundPalletAccounts( ): Promise<{ palletSS58: string }> { const palletAccountId = getPalletAccountId() const palletSS58 = encodeAddress(palletAccountId, LOCAL_SS58_PREFIX) + console.log(`Pallet address: ${palletSS58}`) await transferAsset( api, @@ -379,31 +383,38 @@ async function ensureDerivedEthHasGas( } } -async function initializeVaultIfNeeded(api: ApiPromise, alice: any) { - const existingConfig = await api.query.ethDispenser.dispenserConfig() - const configJson = existingConfig.toJSON() +async function initializeVaultIfNeeded(api: ApiPromise) { + const cfgOpt = await (api.query as any).ethDispenser.dispenserConfig() + const cfg = cfgOpt.toJSON() as any + console.log('Dispenser config JSON ->', cfg) - console.log('Existing dispenser config JSON -> ', configJson) + if (cfg?.paused === true) { + console.log('Dispenser is paused; unpausing via Root...') + const unpauseCall = (api.tx as any).ethDispenser.unpause() + await executeAsRootViaScheduler(api, unpauseCall, 'Unpause ethDispenser via Root') + } + + const current = (await (api.query as any).ethDispenser.faucetBalanceWei()).toBigInt() + const threshold = ((api.consts as any).ethDispenser.minFaucetEthThreshold as any).toBigInt() + + console.log('Current faucetBalanceWei =', current.toString()) + console.log('MinFaucetEthThreshold =', threshold.toString()) - if (configJson !== null) { - console.log('āš ļø Vault already initialized, skipping initialization') - console.log(' Existing config:', existingConfig.toHuman()) + // äæčÆä½™é¢ >= threshold + amount + buffer + const targetMin = threshold + REQUEST_FUND_AMOUNT + ethers.parseEther('1') + if (current >= targetMin) { + console.log('āœ… FaucetBalanceWei already sufficient, skipping top-up') return } - const mpcEthAddress = ethAddressFromPubKey(ROOT_PUBLIC_KEY) - console.log('Initializing vault with MPC address (via Root):', mpcEthAddress) + const addWei = targetMin - current + console.log('Topping up faucet balance via Root, add =', addWei.toString()) - const initCall = api.tx.ethDispenser.initialize(PALLET_FAUCET_FUND) - - await executeAsRootViaScheduler( - api, - initCall, - 'Initialize ethDispenser via Root' - ) + const setBalCall = (api.tx as any).ethDispenser.setFaucetBalance(addWei.toString()) + await executeAsRootViaScheduler(api, setBalCall, 'Top up ethDispenser faucet balance via Root') - const cfg = await api.query.ethDispenser.dispenserConfig() - console.log('Dispenser config after Root init:', cfg.toHuman()) + const after = await (api.query as any).ethDispenser.faucetBalanceWei() + console.log('faucetBalanceWei after =', after.toString()) } describe('ERC20 Vault Integration', () => { @@ -448,13 +459,13 @@ describe('ERC20 Vault Integration', () => { CHAIN_ID ) + // Derive caller address (pallet as sender, alice account id as path) const derived = deriveSubstrateAndEthAddresses(keyring, alice, palletSS58) derivedEthAddress = derived.derivedEthAddress derivedPubKey = derived.derivedPubKey aliceHexPath = derived.aliceHexPath - await ensureDerivedEthHasGas(sepoliaProvider, derivedEthAddress) - }, 120_000) + }, 60_000) afterAll(async () => { if (api) { @@ -463,7 +474,7 @@ describe('ERC20 Vault Integration', () => { }) it('should complete full deposit and claim flow', async () => { - await initializeVaultIfNeeded(api, alice) + await initializeVaultIfNeeded(api) const feeData = await sepoliaProvider.getFeeData() const currentNonce = await sepoliaProvider.getTransactionCount( @@ -514,7 +525,7 @@ describe('ERC20 Vault Integration', () => { palletSS58, Array.from(ethers.getBytes(tx.unsignedSerialized)), { - slip44ChainId: 60, + caip2_id: "eip155:11155111", keyVersion: 0, path: aliceHexPath, algo: 'ecdsa', @@ -623,7 +634,7 @@ describe('ERC20 Vault Integration', () => { const readResponse = await waitForReadResponse( api, ethers.hexlify(requestId), - 120_000 + 60_000 ) if (!readResponse) { @@ -647,7 +658,7 @@ export async function executeAsRootViaReferendum( call: any, // api.tx..(...) label: string, maxRetries = 1, - timeoutMs = 60_000 + timeoutMs = 300_000 ): Promise { console.log(`\n=== ${label}: starting Root execution via Referenda ===`) diff --git a/scripts/dispenser-tests/signet-client.ts b/scripts/dispenser-tests/signet-client.ts index 4c60076f54..ce10eae4c9 100644 --- a/scripts/dispenser-tests/signet-client.ts +++ b/scripts/dispenser-tests/signet-client.ts @@ -150,7 +150,7 @@ export class SignetClient { [ 'string', 'bytes', - 'uint32', + 'string', 'uint32', 'string', 'string', @@ -160,7 +160,7 @@ export class SignetClient { [ sender, txHex, - params.slip44ChainId, + params.caip2_id, params.keyVersion, params.path, params.algo || '', diff --git a/scripts/dispenser-tests/yarn.lock b/scripts/dispenser-tests/yarn.lock new file mode 100644 index 0000000000..cb539f8b08 --- /dev/null +++ b/scripts/dispenser-tests/yarn.lock @@ -0,0 +1,3432 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@adraffy/ens-normalize@1.10.1": + version "1.10.1" + resolved "https://registry.yarnpkg.com/@adraffy/ens-normalize/-/ens-normalize-1.10.1.tgz#63430d04bd8c5e74f8d7d049338f1cd9d4f02069" + integrity sha512-96Z2IP3mYmF1Xg2cDm8f1gWGf/HUVedQ3FMifV4kG/PQ4yEP51xDtRAEfhVNt5f/uzpNkZHwWQuUcu6D6K+Ekw== + +"@adraffy/ens-normalize@^1.11.0": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@adraffy/ens-normalize/-/ens-normalize-1.11.1.tgz#6c2d657d4b2dfb37f8ea811dcb3e60843d4ac24a" + integrity sha512-nhCBV3quEgesuf7c7KYfperqSS14T8bYuvJ8PcLJp6znkZpFc0AuW4qBtr8eKVyPPe/8RSr7sglCWPU5eaxwKQ== + +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.27.1", "@babel/code-frame@^7.28.6": + version "7.28.6" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.28.6.tgz#72499312ec58b1e2245ba4a4f550c132be4982f7" + integrity sha512-JYgintcMjRiCvS8mMECzaEn+m3PfoQiyqukOMCCVQtoJGYJw8j/8LBJEiqkHLkfwCcs74E3pbAUFNg7d9VNJ+Q== + dependencies: + "@babel/helper-validator-identifier" "^7.28.5" + js-tokens "^4.0.0" + picocolors "^1.1.1" + +"@babel/compat-data@^7.28.6": + version "7.28.6" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.28.6.tgz#103f466803fa0f059e82ccac271475470570d74c" + integrity sha512-2lfu57JtzctfIrcGMz992hyLlByuzgIk58+hhGCxjKZ3rWI82NnVLjXcaTqkI2NvlcvOskZaiZ5kjUALo3Lpxg== + +"@babel/core@^7.23.9", "@babel/core@^7.27.4": + version "7.28.6" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.28.6.tgz#531bf883a1126e53501ba46eb3bb414047af507f" + integrity sha512-H3mcG6ZDLTlYfaSNi0iOKkigqMFvkTKlGUYlD8GW7nNOYRrevuA46iTypPyv+06V3fEmvvazfntkBU34L0azAw== + dependencies: + "@babel/code-frame" "^7.28.6" + "@babel/generator" "^7.28.6" + "@babel/helper-compilation-targets" "^7.28.6" + "@babel/helper-module-transforms" "^7.28.6" + "@babel/helpers" "^7.28.6" + "@babel/parser" "^7.28.6" + "@babel/template" "^7.28.6" + "@babel/traverse" "^7.28.6" + "@babel/types" "^7.28.6" + "@jridgewell/remapping" "^2.3.5" + convert-source-map "^2.0.0" + debug "^4.1.0" + gensync "^1.0.0-beta.2" + json5 "^2.2.3" + semver "^6.3.1" + +"@babel/generator@^7.27.5", "@babel/generator@^7.28.6": + version "7.28.6" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.28.6.tgz#48dcc65d98fcc8626a48f72b62e263d25fc3c3f1" + integrity sha512-lOoVRwADj8hjf7al89tvQ2a1lf53Z+7tiXMgpZJL3maQPDxh0DgLMN62B2MKUOFcoodBHLMbDM6WAbKgNy5Suw== + dependencies: + "@babel/parser" "^7.28.6" + "@babel/types" "^7.28.6" + "@jridgewell/gen-mapping" "^0.3.12" + "@jridgewell/trace-mapping" "^0.3.28" + jsesc "^3.0.2" + +"@babel/helper-compilation-targets@^7.28.6": + version "7.28.6" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.28.6.tgz#32c4a3f41f12ed1532179b108a4d746e105c2b25" + integrity sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA== + dependencies: + "@babel/compat-data" "^7.28.6" + "@babel/helper-validator-option" "^7.27.1" + browserslist "^4.24.0" + lru-cache "^5.1.1" + semver "^6.3.1" + +"@babel/helper-globals@^7.28.0": + version "7.28.0" + resolved "https://registry.yarnpkg.com/@babel/helper-globals/-/helper-globals-7.28.0.tgz#b9430df2aa4e17bc28665eadeae8aa1d985e6674" + integrity sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw== + +"@babel/helper-module-imports@^7.28.6": + version "7.28.6" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.28.6.tgz#60632cbd6ffb70b22823187201116762a03e2d5c" + integrity sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw== + dependencies: + "@babel/traverse" "^7.28.6" + "@babel/types" "^7.28.6" + +"@babel/helper-module-transforms@^7.28.6": + version "7.28.6" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.28.6.tgz#9312d9d9e56edc35aeb6e95c25d4106b50b9eb1e" + integrity sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA== + dependencies: + "@babel/helper-module-imports" "^7.28.6" + "@babel/helper-validator-identifier" "^7.28.5" + "@babel/traverse" "^7.28.6" + +"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.28.6", "@babel/helper-plugin-utils@^7.8.0": + version "7.28.6" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.28.6.tgz#6f13ea251b68c8532e985fd532f28741a8af9ac8" + integrity sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug== + +"@babel/helper-string-parser@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz#54da796097ab19ce67ed9f88b47bb2ec49367687" + integrity sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA== + +"@babel/helper-validator-identifier@^7.28.5": + version "7.28.5" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz#010b6938fab7cb7df74aa2bbc06aa503b8fe5fb4" + integrity sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q== + +"@babel/helper-validator-option@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz#fa52f5b1e7db1ab049445b421c4471303897702f" + integrity sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg== + +"@babel/helpers@^7.28.6": + version "7.28.6" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.28.6.tgz#fca903a313ae675617936e8998b814c415cbf5d7" + integrity sha512-xOBvwq86HHdB7WUDTfKfT/Vuxh7gElQ+Sfti2Cy6yIWNW05P8iUslOVcZ4/sKbE+/jQaukQAdz/gf3724kYdqw== + dependencies: + "@babel/template" "^7.28.6" + "@babel/types" "^7.28.6" + +"@babel/parser@^7.1.0", "@babel/parser@^7.20.7", "@babel/parser@^7.23.9", "@babel/parser@^7.28.6": + version "7.28.6" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.28.6.tgz#f01a8885b7fa1e56dd8a155130226cd698ef13fd" + integrity sha512-TeR9zWR18BvbfPmGbLampPMW+uW1NZnJlRuuHso8i87QZNq2JRF9i6RgxRqtEq+wQGsS19NNTWr2duhnE49mfQ== + dependencies: + "@babel/types" "^7.28.6" + +"@babel/plugin-syntax-async-generators@^7.8.4": + version "7.8.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz#a983fb1aeb2ec3f6ed042a210f640e90e786fe0d" + integrity sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-bigint@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz#4c9a6f669f5d0cdf1b90a1671e9a146be5300cea" + integrity sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-class-properties@^7.12.13": + version "7.12.13" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz#b5c987274c4a3a82b89714796931a6b53544ae10" + integrity sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA== + dependencies: + "@babel/helper-plugin-utils" "^7.12.13" + +"@babel/plugin-syntax-class-static-block@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz#195df89b146b4b78b3bf897fd7a257c84659d406" + integrity sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw== + dependencies: + "@babel/helper-plugin-utils" "^7.14.5" + +"@babel/plugin-syntax-import-attributes@^7.24.7": + version "7.28.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.28.6.tgz#b71d5914665f60124e133696f17cd7669062c503" + integrity sha512-jiLC0ma9XkQT3TKJ9uYvlakm66Pamywo+qwL+oL8HJOvc6TWdZXVfhqJr8CCzbSGUAbDOzlGHJC1U+vRfLQDvw== + dependencies: + "@babel/helper-plugin-utils" "^7.28.6" + +"@babel/plugin-syntax-import-meta@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz#ee601348c370fa334d2207be158777496521fd51" + integrity sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-syntax-json-strings@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz#01ca21b668cd8218c9e640cb6dd88c5412b2c96a" + integrity sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-jsx@^7.27.1": + version "7.28.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.28.6.tgz#f8ca28bbd84883b5fea0e447c635b81ba73997ee" + integrity sha512-wgEmr06G6sIpqr8YDwA2dSRTE3bJ+V0IfpzfSY3Lfgd7YWOaAdlykvJi13ZKBt8cZHfgH1IXN+CL656W3uUa4w== + dependencies: + "@babel/helper-plugin-utils" "^7.28.6" + +"@babel/plugin-syntax-logical-assignment-operators@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz#ca91ef46303530448b906652bac2e9fe9941f699" + integrity sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-syntax-nullish-coalescing-operator@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz#167ed70368886081f74b5c36c65a88c03b66d1a9" + integrity sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-numeric-separator@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz#b9b070b3e33570cd9fd07ba7fa91c0dd37b9af97" + integrity sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-syntax-object-rest-spread@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz#60e225edcbd98a640332a2e72dd3e66f1af55871" + integrity sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-optional-catch-binding@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz#6111a265bcfb020eb9efd0fdfd7d26402b9ed6c1" + integrity sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-optional-chaining@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz#4f69c2ab95167e0180cd5336613f8c5788f7d48a" + integrity sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-private-property-in-object@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz#0dc6671ec0ea22b6e94a1114f857970cd39de1ad" + integrity sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg== + dependencies: + "@babel/helper-plugin-utils" "^7.14.5" + +"@babel/plugin-syntax-top-level-await@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz#c1cfdadc35a646240001f06138247b741c34d94c" + integrity sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw== + dependencies: + "@babel/helper-plugin-utils" "^7.14.5" + +"@babel/plugin-syntax-typescript@^7.27.1": + version "7.28.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.28.6.tgz#c7b2ddf1d0a811145b1de800d1abd146af92e3a2" + integrity sha512-+nDNmQye7nlnuuHDboPbGm00Vqg3oO8niRRL27/4LYHUsHYh0zJ1xWOz0uRwNFmM1Avzk8wZbc6rdiYhomzv/A== + dependencies: + "@babel/helper-plugin-utils" "^7.28.6" + +"@babel/template@^7.28.6": + version "7.28.6" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.28.6.tgz#0e7e56ecedb78aeef66ce7972b082fce76a23e57" + integrity sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ== + dependencies: + "@babel/code-frame" "^7.28.6" + "@babel/parser" "^7.28.6" + "@babel/types" "^7.28.6" + +"@babel/traverse@^7.28.6": + version "7.28.6" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.28.6.tgz#871ddc79a80599a5030c53b1cc48cbe3a5583c2e" + integrity sha512-fgWX62k02qtjqdSNTAGxmKYY/7FSL9WAS1o2Hu5+I5m9T0yxZzr4cnrfXQ/MX0rIifthCSs6FKTlzYbJcPtMNg== + dependencies: + "@babel/code-frame" "^7.28.6" + "@babel/generator" "^7.28.6" + "@babel/helper-globals" "^7.28.0" + "@babel/parser" "^7.28.6" + "@babel/template" "^7.28.6" + "@babel/types" "^7.28.6" + debug "^4.3.1" + +"@babel/types@^7.0.0", "@babel/types@^7.20.7", "@babel/types@^7.27.3", "@babel/types@^7.28.2", "@babel/types@^7.28.6": + version "7.28.6" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.28.6.tgz#c3e9377f1b155005bcc4c46020e7e394e13089df" + integrity sha512-0ZrskXVEHSWIqZM/sQZ4EV3jZJXRkio/WCxaqKZP1g//CEWEPSfeZFcms4XeKBCHU0ZKnIkdJeU/kF+eRp5lBg== + dependencies: + "@babel/helper-string-parser" "^7.27.1" + "@babel/helper-validator-identifier" "^7.28.5" + +"@bcoe/v8-coverage@^0.2.3": + version "0.2.3" + resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" + integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== + +"@cspotcode/source-map-support@^0.8.0": + version "0.8.1" + resolved "https://registry.yarnpkg.com/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz#00629c35a688e05a88b1cda684fb9d5e73f000a1" + integrity sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw== + dependencies: + "@jridgewell/trace-mapping" "0.3.9" + +"@emnapi/core@^1.4.3": + version "1.8.1" + resolved "https://registry.yarnpkg.com/@emnapi/core/-/core-1.8.1.tgz#fd9efe721a616288345ffee17a1f26ac5dd01349" + integrity sha512-AvT9QFpxK0Zd8J0jopedNm+w/2fIzvtPKPjqyw9jwvBaReTTqPBk9Hixaz7KbjimP+QNz605/XnjFcDAL2pqBg== + dependencies: + "@emnapi/wasi-threads" "1.1.0" + tslib "^2.4.0" + +"@emnapi/runtime@^1.4.3": + version "1.8.1" + resolved "https://registry.yarnpkg.com/@emnapi/runtime/-/runtime-1.8.1.tgz#550fa7e3c0d49c5fb175a116e8cd70614f9a22a5" + integrity sha512-mehfKSMWjjNol8659Z8KxEMrdSJDDot5SXMq00dM8BN4o+CLNXQ0xH2V7EchNHV4RmbZLmmPdEaXZc5H2FXmDg== + dependencies: + tslib "^2.4.0" + +"@emnapi/wasi-threads@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@emnapi/wasi-threads/-/wasi-threads-1.1.0.tgz#60b2102fddc9ccb78607e4a3cf8403ea69be41bf" + integrity sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ== + dependencies: + tslib "^2.4.0" + +"@isaacs/cliui@^8.0.2": + version "8.0.2" + resolved "https://registry.yarnpkg.com/@isaacs/cliui/-/cliui-8.0.2.tgz#b37667b7bc181c168782259bab42474fbf52b550" + integrity sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA== + dependencies: + string-width "^5.1.2" + string-width-cjs "npm:string-width@^4.2.0" + strip-ansi "^7.0.1" + strip-ansi-cjs "npm:strip-ansi@^6.0.1" + wrap-ansi "^8.1.0" + wrap-ansi-cjs "npm:wrap-ansi@^7.0.0" + +"@istanbuljs/load-nyc-config@^1.0.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz#fd3db1d59ecf7cf121e80650bb86712f9b55eced" + integrity sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ== + dependencies: + camelcase "^5.3.1" + find-up "^4.1.0" + get-package-type "^0.1.0" + js-yaml "^3.13.1" + resolve-from "^5.0.0" + +"@istanbuljs/schema@^0.1.2", "@istanbuljs/schema@^0.1.3": + version "0.1.3" + resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.3.tgz#e45e384e4b8ec16bce2fd903af78450f6bf7ec98" + integrity sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA== + +"@jest/console@30.2.0": + version "30.2.0" + resolved "https://registry.yarnpkg.com/@jest/console/-/console-30.2.0.tgz#c52fcd5b58fdd2e8eb66b2fd8ae56f2f64d05b28" + integrity sha512-+O1ifRjkvYIkBqASKWgLxrpEhQAAE7hY77ALLUufSk5717KfOShg6IbqLmdsLMPdUiFvA2kTs0R7YZy+l0IzZQ== + dependencies: + "@jest/types" "30.2.0" + "@types/node" "*" + chalk "^4.1.2" + jest-message-util "30.2.0" + jest-util "30.2.0" + slash "^3.0.0" + +"@jest/core@30.2.0": + version "30.2.0" + resolved "https://registry.yarnpkg.com/@jest/core/-/core-30.2.0.tgz#813d59faa5abd5510964a8b3a7b17cc77b775275" + integrity sha512-03W6IhuhjqTlpzh/ojut/pDB2LPRygyWX8ExpgHtQA8H/3K7+1vKmcINx5UzeOX1se6YEsBsOHQ1CRzf3fOwTQ== + dependencies: + "@jest/console" "30.2.0" + "@jest/pattern" "30.0.1" + "@jest/reporters" "30.2.0" + "@jest/test-result" "30.2.0" + "@jest/transform" "30.2.0" + "@jest/types" "30.2.0" + "@types/node" "*" + ansi-escapes "^4.3.2" + chalk "^4.1.2" + ci-info "^4.2.0" + exit-x "^0.2.2" + graceful-fs "^4.2.11" + jest-changed-files "30.2.0" + jest-config "30.2.0" + jest-haste-map "30.2.0" + jest-message-util "30.2.0" + jest-regex-util "30.0.1" + jest-resolve "30.2.0" + jest-resolve-dependencies "30.2.0" + jest-runner "30.2.0" + jest-runtime "30.2.0" + jest-snapshot "30.2.0" + jest-util "30.2.0" + jest-validate "30.2.0" + jest-watcher "30.2.0" + micromatch "^4.0.8" + pretty-format "30.2.0" + slash "^3.0.0" + +"@jest/diff-sequences@30.0.1": + version "30.0.1" + resolved "https://registry.yarnpkg.com/@jest/diff-sequences/-/diff-sequences-30.0.1.tgz#0ededeae4d071f5c8ffe3678d15f3a1be09156be" + integrity sha512-n5H8QLDJ47QqbCNn5SuFjCRDrOLEZ0h8vAHCK5RL9Ls7Xa8AQLa/YxAc9UjFqoEDM48muwtBGjtMY5cr0PLDCw== + +"@jest/environment@30.2.0": + version "30.2.0" + resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-30.2.0.tgz#1e673cdb8b93ded707cf6631b8353011460831fa" + integrity sha512-/QPTL7OBJQ5ac09UDRa3EQes4gt1FTEG/8jZ/4v5IVzx+Cv7dLxlVIvfvSVRiiX2drWyXeBjkMSR8hvOWSog5g== + dependencies: + "@jest/fake-timers" "30.2.0" + "@jest/types" "30.2.0" + "@types/node" "*" + jest-mock "30.2.0" + +"@jest/expect-utils@30.2.0": + version "30.2.0" + resolved "https://registry.yarnpkg.com/@jest/expect-utils/-/expect-utils-30.2.0.tgz#4f95413d4748454fdb17404bf1141827d15e6011" + integrity sha512-1JnRfhqpD8HGpOmQp180Fo9Zt69zNtC+9lR+kT7NVL05tNXIi+QC8Csz7lfidMoVLPD3FnOtcmp0CEFnxExGEA== + dependencies: + "@jest/get-type" "30.1.0" + +"@jest/expect@30.2.0": + version "30.2.0" + resolved "https://registry.yarnpkg.com/@jest/expect/-/expect-30.2.0.tgz#9a5968499bb8add2bbb09136f69f7df5ddbf3185" + integrity sha512-V9yxQK5erfzx99Sf+7LbhBwNWEZ9eZay8qQ9+JSC0TrMR1pMDHLMY+BnVPacWU6Jamrh252/IKo4F1Xn/zfiqA== + dependencies: + expect "30.2.0" + jest-snapshot "30.2.0" + +"@jest/fake-timers@30.2.0": + version "30.2.0" + resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-30.2.0.tgz#0941ddc28a339b9819542495b5408622dc9e94ec" + integrity sha512-HI3tRLjRxAbBy0VO8dqqm7Hb2mIa8d5bg/NJkyQcOk7V118ObQML8RC5luTF/Zsg4474a+gDvhce7eTnP4GhYw== + dependencies: + "@jest/types" "30.2.0" + "@sinonjs/fake-timers" "^13.0.0" + "@types/node" "*" + jest-message-util "30.2.0" + jest-mock "30.2.0" + jest-util "30.2.0" + +"@jest/get-type@30.1.0": + version "30.1.0" + resolved "https://registry.yarnpkg.com/@jest/get-type/-/get-type-30.1.0.tgz#4fcb4dc2ebcf0811be1c04fd1cb79c2dba431cbc" + integrity sha512-eMbZE2hUnx1WV0pmURZY9XoXPkUYjpc55mb0CrhtdWLtzMQPFvu/rZkTLZFTsdaVQa+Tr4eWAteqcUzoawq/uA== + +"@jest/globals@30.2.0": + version "30.2.0" + resolved "https://registry.yarnpkg.com/@jest/globals/-/globals-30.2.0.tgz#2f4b696d5862664b89c4ee2e49ae24d2bb7e0988" + integrity sha512-b63wmnKPaK+6ZZfpYhz9K61oybvbI1aMcIs80++JI1O1rR1vaxHUCNqo3ITu6NU0d4V34yZFoHMn/uoKr/Rwfw== + dependencies: + "@jest/environment" "30.2.0" + "@jest/expect" "30.2.0" + "@jest/types" "30.2.0" + jest-mock "30.2.0" + +"@jest/pattern@30.0.1": + version "30.0.1" + resolved "https://registry.yarnpkg.com/@jest/pattern/-/pattern-30.0.1.tgz#d5304147f49a052900b4b853dedb111d080e199f" + integrity sha512-gWp7NfQW27LaBQz3TITS8L7ZCQ0TLvtmI//4OwlQRx4rnWxcPNIYjxZpDcN4+UlGxgm3jS5QPz8IPTCkb59wZA== + dependencies: + "@types/node" "*" + jest-regex-util "30.0.1" + +"@jest/reporters@30.2.0": + version "30.2.0" + resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-30.2.0.tgz#a36b28fcbaf0c4595250b108e6f20e363348fd91" + integrity sha512-DRyW6baWPqKMa9CzeiBjHwjd8XeAyco2Vt8XbcLFjiwCOEKOvy82GJ8QQnJE9ofsxCMPjH4MfH8fCWIHHDKpAQ== + dependencies: + "@bcoe/v8-coverage" "^0.2.3" + "@jest/console" "30.2.0" + "@jest/test-result" "30.2.0" + "@jest/transform" "30.2.0" + "@jest/types" "30.2.0" + "@jridgewell/trace-mapping" "^0.3.25" + "@types/node" "*" + chalk "^4.1.2" + collect-v8-coverage "^1.0.2" + exit-x "^0.2.2" + glob "^10.3.10" + graceful-fs "^4.2.11" + istanbul-lib-coverage "^3.0.0" + istanbul-lib-instrument "^6.0.0" + istanbul-lib-report "^3.0.0" + istanbul-lib-source-maps "^5.0.0" + istanbul-reports "^3.1.3" + jest-message-util "30.2.0" + jest-util "30.2.0" + jest-worker "30.2.0" + slash "^3.0.0" + string-length "^4.0.2" + v8-to-istanbul "^9.0.1" + +"@jest/schemas@30.0.5": + version "30.0.5" + resolved "https://registry.yarnpkg.com/@jest/schemas/-/schemas-30.0.5.tgz#7bdf69fc5a368a5abdb49fd91036c55225846473" + integrity sha512-DmdYgtezMkh3cpU8/1uyXakv3tJRcmcXxBOcO0tbaozPwpmh4YMsnWrQm9ZmZMfa5ocbxzbFk6O4bDPEc/iAnA== + dependencies: + "@sinclair/typebox" "^0.34.0" + +"@jest/snapshot-utils@30.2.0": + version "30.2.0" + resolved "https://registry.yarnpkg.com/@jest/snapshot-utils/-/snapshot-utils-30.2.0.tgz#387858eb90c2f98f67bff327435a532ac5309fbe" + integrity sha512-0aVxM3RH6DaiLcjj/b0KrIBZhSX1373Xci4l3cW5xiUWPctZ59zQ7jj4rqcJQ/Z8JuN/4wX3FpJSa3RssVvCug== + dependencies: + "@jest/types" "30.2.0" + chalk "^4.1.2" + graceful-fs "^4.2.11" + natural-compare "^1.4.0" + +"@jest/source-map@30.0.1": + version "30.0.1" + resolved "https://registry.yarnpkg.com/@jest/source-map/-/source-map-30.0.1.tgz#305ebec50468f13e658b3d5c26f85107a5620aaa" + integrity sha512-MIRWMUUR3sdbP36oyNyhbThLHyJ2eEDClPCiHVbrYAe5g3CHRArIVpBw7cdSB5fr+ofSfIb2Tnsw8iEHL0PYQg== + dependencies: + "@jridgewell/trace-mapping" "^0.3.25" + callsites "^3.1.0" + graceful-fs "^4.2.11" + +"@jest/test-result@30.2.0": + version "30.2.0" + resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-30.2.0.tgz#9c0124377fb7996cdffb86eda3dbc56eacab363d" + integrity sha512-RF+Z+0CCHkARz5HT9mcQCBulb1wgCP3FBvl9VFokMX27acKphwyQsNuWH3c+ojd1LeWBLoTYoxF0zm6S/66mjg== + dependencies: + "@jest/console" "30.2.0" + "@jest/types" "30.2.0" + "@types/istanbul-lib-coverage" "^2.0.6" + collect-v8-coverage "^1.0.2" + +"@jest/test-sequencer@30.2.0": + version "30.2.0" + resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-30.2.0.tgz#bf0066bc72e176d58f5dfa7f212b6e7eee44f221" + integrity sha512-wXKgU/lk8fKXMu/l5Hog1R61bL4q5GCdT6OJvdAFz1P+QrpoFuLU68eoKuVc4RbrTtNnTL5FByhWdLgOPSph+Q== + dependencies: + "@jest/test-result" "30.2.0" + graceful-fs "^4.2.11" + jest-haste-map "30.2.0" + slash "^3.0.0" + +"@jest/transform@30.2.0": + version "30.2.0" + resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-30.2.0.tgz#54bef1a4510dcbd58d5d4de4fe2980a63077ef2a" + integrity sha512-XsauDV82o5qXbhalKxD7p4TZYYdwcaEXC77PPD2HixEFF+6YGppjrAAQurTl2ECWcEomHBMMNS9AH3kcCFx8jA== + dependencies: + "@babel/core" "^7.27.4" + "@jest/types" "30.2.0" + "@jridgewell/trace-mapping" "^0.3.25" + babel-plugin-istanbul "^7.0.1" + chalk "^4.1.2" + convert-source-map "^2.0.0" + fast-json-stable-stringify "^2.1.0" + graceful-fs "^4.2.11" + jest-haste-map "30.2.0" + jest-regex-util "30.0.1" + jest-util "30.2.0" + micromatch "^4.0.8" + pirates "^4.0.7" + slash "^3.0.0" + write-file-atomic "^5.0.1" + +"@jest/types@30.2.0": + version "30.2.0" + resolved "https://registry.yarnpkg.com/@jest/types/-/types-30.2.0.tgz#1c678a7924b8f59eafd4c77d56b6d0ba976d62b8" + integrity sha512-H9xg1/sfVvyfU7o3zMfBEjQ1gcsdeTMgqHoYdN79tuLqfTtuu7WckRA1R5whDwOzxaZAeMKTYWqP+WCAi0CHsg== + dependencies: + "@jest/pattern" "30.0.1" + "@jest/schemas" "30.0.5" + "@types/istanbul-lib-coverage" "^2.0.6" + "@types/istanbul-reports" "^3.0.4" + "@types/node" "*" + "@types/yargs" "^17.0.33" + chalk "^4.1.2" + +"@jridgewell/gen-mapping@^0.3.12", "@jridgewell/gen-mapping@^0.3.5": + version "0.3.13" + resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz#6342a19f44347518c93e43b1ac69deb3c4656a1f" + integrity sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA== + dependencies: + "@jridgewell/sourcemap-codec" "^1.5.0" + "@jridgewell/trace-mapping" "^0.3.24" + +"@jridgewell/remapping@^2.3.5": + version "2.3.5" + resolved "https://registry.yarnpkg.com/@jridgewell/remapping/-/remapping-2.3.5.tgz#375c476d1972947851ba1e15ae8f123047445aa1" + integrity sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ== + dependencies: + "@jridgewell/gen-mapping" "^0.3.5" + "@jridgewell/trace-mapping" "^0.3.24" + +"@jridgewell/resolve-uri@^3.0.3", "@jridgewell/resolve-uri@^3.1.0": + version "3.1.2" + resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz#7a0ee601f60f99a20c7c7c5ff0c80388c1189bd6" + integrity sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw== + +"@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.14", "@jridgewell/sourcemap-codec@^1.5.0": + version "1.5.5" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz#6912b00d2c631c0d15ce1a7ab57cd657f2a8f8ba" + integrity sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og== + +"@jridgewell/trace-mapping@0.3.9": + version "0.3.9" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz#6534fd5933a53ba7cbf3a17615e273a0d1273ff9" + integrity sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ== + dependencies: + "@jridgewell/resolve-uri" "^3.0.3" + "@jridgewell/sourcemap-codec" "^1.4.10" + +"@jridgewell/trace-mapping@^0.3.12", "@jridgewell/trace-mapping@^0.3.23", "@jridgewell/trace-mapping@^0.3.24", "@jridgewell/trace-mapping@^0.3.25", "@jridgewell/trace-mapping@^0.3.28": + version "0.3.31" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz#db15d6781c931f3a251a3dac39501c98a6082fd0" + integrity sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw== + dependencies: + "@jridgewell/resolve-uri" "^3.1.0" + "@jridgewell/sourcemap-codec" "^1.4.14" + +"@napi-rs/wasm-runtime@^0.2.11": + version "0.2.12" + resolved "https://registry.yarnpkg.com/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.12.tgz#3e78a8b96e6c33a6c517e1894efbd5385a7cb6f2" + integrity sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ== + dependencies: + "@emnapi/core" "^1.4.3" + "@emnapi/runtime" "^1.4.3" + "@tybys/wasm-util" "^0.10.0" + +"@noble/ciphers@^1.3.0": + version "1.3.0" + resolved "https://registry.yarnpkg.com/@noble/ciphers/-/ciphers-1.3.0.tgz#f64b8ff886c240e644e5573c097f86e5b43676dc" + integrity sha512-2I0gnIVPtfnMw9ee9h1dJG7tp81+8Ob3OJb3Mv37rx5L40/b0i7djjCVvGOVqc9AEIQyvyu1i6ypKdFw8R8gQw== + +"@noble/curves@1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.2.0.tgz#92d7e12e4e49b23105a2555c6984d41733d65c35" + integrity sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw== + dependencies: + "@noble/hashes" "1.3.2" + +"@noble/curves@1.9.1": + version "1.9.1" + resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.9.1.tgz#9654a0bc6c13420ae252ddcf975eaf0f58f0a35c" + integrity sha512-k11yZxZg+t+gWvBbIswW0yoJlu8cHOC7dhunwOzoWH/mXGBiYyR4YY6hAEK/3EUs4UpB8la1RfdRpeGsFHkWsA== + dependencies: + "@noble/hashes" "1.8.0" + +"@noble/curves@^1.3.0", "@noble/curves@~1.9.0", "@noble/curves@~1.9.2": + version "1.9.7" + resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.9.7.tgz#79d04b4758a43e4bca2cbdc62e7771352fa6b951" + integrity sha512-gbKGcRUYIjA3/zCCNaWDciTMFI0dCkvou3TL8Zmy5Nc7sJ47a0jtOeZoTaMxkuqRo9cRhjOdZJXegxYE5FN/xw== + dependencies: + "@noble/hashes" "1.8.0" + +"@noble/hashes@1.3.2": + version "1.3.2" + resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.3.2.tgz#6f26dbc8fbc7205873ce3cee2f690eba0d421b39" + integrity sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ== + +"@noble/hashes@1.8.0", "@noble/hashes@^1.3.1", "@noble/hashes@^1.3.3", "@noble/hashes@^1.8.0", "@noble/hashes@~1.8.0": + version "1.8.0" + resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.8.0.tgz#cee43d801fcef9644b11b8194857695acd5f815a" + integrity sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A== + +"@pkgjs/parseargs@^0.11.0": + version "0.11.0" + resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33" + integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg== + +"@pkgr/core@^0.2.9": + version "0.2.9" + resolved "https://registry.yarnpkg.com/@pkgr/core/-/core-0.2.9.tgz#d229a7b7f9dac167a156992ef23c7f023653f53b" + integrity sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA== + +"@polkadot-api/json-rpc-provider-proxy@^0.1.0": + version "0.1.0" + resolved "https://registry.yarnpkg.com/@polkadot-api/json-rpc-provider-proxy/-/json-rpc-provider-proxy-0.1.0.tgz#6e191f28e7d0fbbe8b540fc51d12a0adaeba297e" + integrity sha512-8GSFE5+EF73MCuLQm8tjrbCqlgclcHBSRaswvXziJ0ZW7iw3UEMsKkkKvELayWyBuOPa2T5i1nj6gFOeIsqvrg== + +"@polkadot-api/json-rpc-provider@0.0.1", "@polkadot-api/json-rpc-provider@^0.0.1": + version "0.0.1" + resolved "https://registry.yarnpkg.com/@polkadot-api/json-rpc-provider/-/json-rpc-provider-0.0.1.tgz#333645d40ccd9bccfd1f32503f17e4e63e76e297" + integrity sha512-/SMC/l7foRjpykLTUTacIH05H3mr9ip8b5xxfwXlVezXrNVLp3Cv0GX6uItkKd+ZjzVPf3PFrDF2B2/HLSNESA== + +"@polkadot-api/metadata-builders@0.3.2": + version "0.3.2" + resolved "https://registry.yarnpkg.com/@polkadot-api/metadata-builders/-/metadata-builders-0.3.2.tgz#007f158c9e0546cf79ba440befc0c753ab1a6629" + integrity sha512-TKpfoT6vTb+513KDzMBTfCb/ORdgRnsS3TDFpOhAhZ08ikvK+hjHMt5plPiAX/OWkm1Wc9I3+K6W0hX5Ab7MVg== + dependencies: + "@polkadot-api/substrate-bindings" "0.6.0" + "@polkadot-api/utils" "0.1.0" + +"@polkadot-api/observable-client@^0.3.0": + version "0.3.2" + resolved "https://registry.yarnpkg.com/@polkadot-api/observable-client/-/observable-client-0.3.2.tgz#fd91efee350595a6e0ecfd3f294cc80de86c0cf7" + integrity sha512-HGgqWgEutVyOBXoGOPp4+IAq6CNdK/3MfQJmhCJb8YaJiaK4W6aRGrdQuQSTPHfERHCARt9BrOmEvTXAT257Ug== + dependencies: + "@polkadot-api/metadata-builders" "0.3.2" + "@polkadot-api/substrate-bindings" "0.6.0" + "@polkadot-api/utils" "0.1.0" + +"@polkadot-api/substrate-bindings@0.6.0": + version "0.6.0" + resolved "https://registry.yarnpkg.com/@polkadot-api/substrate-bindings/-/substrate-bindings-0.6.0.tgz#889b0c3ba19dc95282286506bf6e370a43ce119a" + integrity sha512-lGuhE74NA1/PqdN7fKFdE5C1gNYX357j1tWzdlPXI0kQ7h3kN0zfxNOpPUN7dIrPcOFZ6C0tRRVrBylXkI6xPw== + dependencies: + "@noble/hashes" "^1.3.1" + "@polkadot-api/utils" "0.1.0" + "@scure/base" "^1.1.1" + scale-ts "^1.6.0" + +"@polkadot-api/substrate-client@^0.1.2": + version "0.1.4" + resolved "https://registry.yarnpkg.com/@polkadot-api/substrate-client/-/substrate-client-0.1.4.tgz#7a808e5cb85ecb9fa2b3a43945090a6c807430ce" + integrity sha512-MljrPobN0ZWTpn++da9vOvt+Ex+NlqTlr/XT7zi9sqPtDJiQcYl+d29hFAgpaeTqbeQKZwz3WDE9xcEfLE8c5A== + dependencies: + "@polkadot-api/json-rpc-provider" "0.0.1" + "@polkadot-api/utils" "0.1.0" + +"@polkadot-api/utils@0.1.0": + version "0.1.0" + resolved "https://registry.yarnpkg.com/@polkadot-api/utils/-/utils-0.1.0.tgz#d36937cdc465c2ea302f3278cf53157340ab33a0" + integrity sha512-MXzWZeuGxKizPx2Xf/47wx9sr/uxKw39bVJUptTJdsaQn/TGq+z310mHzf1RCGvC1diHM8f593KrnDgc9oNbJA== + +"@polkadot/api-augment@16.5.4": + version "16.5.4" + resolved "https://registry.yarnpkg.com/@polkadot/api-augment/-/api-augment-16.5.4.tgz#40084178849c50681b78da1650c55ee2335f2bdf" + integrity sha512-9FTohz13ih458V2JBFjRACKHPqfM6j4bmmTbcSaE7hXcIOYzm4ABFo7xq5osLyvItganjsICErL2vRn2zULycw== + dependencies: + "@polkadot/api-base" "16.5.4" + "@polkadot/rpc-augment" "16.5.4" + "@polkadot/types" "16.5.4" + "@polkadot/types-augment" "16.5.4" + "@polkadot/types-codec" "16.5.4" + "@polkadot/util" "^14.0.1" + tslib "^2.8.1" + +"@polkadot/api-base@16.5.4": + version "16.5.4" + resolved "https://registry.yarnpkg.com/@polkadot/api-base/-/api-base-16.5.4.tgz#4a81109b24ed348aefa388a568f3266e66a1c691" + integrity sha512-V69v3ieg5+91yRUCG1vFRSLr7V7MvHPvo/QrzleIUu8tPXWldJ0kyXbWKHVNZEpVBA9LpjGvII+MHUW7EaKMNg== + dependencies: + "@polkadot/rpc-core" "16.5.4" + "@polkadot/types" "16.5.4" + "@polkadot/util" "^14.0.1" + rxjs "^7.8.1" + tslib "^2.8.1" + +"@polkadot/api-derive@16.5.4": + version "16.5.4" + resolved "https://registry.yarnpkg.com/@polkadot/api-derive/-/api-derive-16.5.4.tgz#d4bdbd09af817003a92cdc2cccb5e315cb3c2970" + integrity sha512-0JP2a6CaqTviacHsmnUKF4VLRsKdYOzQCqdL9JpwY/QBz/ZLqIKKPiSRg285EVLf8n/hWdTfxbWqQCsRa5NL+Q== + dependencies: + "@polkadot/api" "16.5.4" + "@polkadot/api-augment" "16.5.4" + "@polkadot/api-base" "16.5.4" + "@polkadot/rpc-core" "16.5.4" + "@polkadot/types" "16.5.4" + "@polkadot/types-codec" "16.5.4" + "@polkadot/util" "^14.0.1" + "@polkadot/util-crypto" "^14.0.1" + rxjs "^7.8.1" + tslib "^2.8.1" + +"@polkadot/api@16.5.4", "@polkadot/api@latest": + version "16.5.4" + resolved "https://registry.yarnpkg.com/@polkadot/api/-/api-16.5.4.tgz#d46be46f9f2a26650884fb256dae343692cae536" + integrity sha512-mX1fwtXCBAHXEyZLSnSrMDGP+jfU2rr7GfDVQBz0cBY1nmY8N34RqPWGrZWj8o4DxVu1DQ91sGncOmlBwEl0Qg== + dependencies: + "@polkadot/api-augment" "16.5.4" + "@polkadot/api-base" "16.5.4" + "@polkadot/api-derive" "16.5.4" + "@polkadot/keyring" "^14.0.1" + "@polkadot/rpc-augment" "16.5.4" + "@polkadot/rpc-core" "16.5.4" + "@polkadot/rpc-provider" "16.5.4" + "@polkadot/types" "16.5.4" + "@polkadot/types-augment" "16.5.4" + "@polkadot/types-codec" "16.5.4" + "@polkadot/types-create" "16.5.4" + "@polkadot/types-known" "16.5.4" + "@polkadot/util" "^14.0.1" + "@polkadot/util-crypto" "^14.0.1" + eventemitter3 "^5.0.1" + rxjs "^7.8.1" + tslib "^2.8.1" + +"@polkadot/keyring@^12.6.2": + version "12.6.2" + resolved "https://registry.yarnpkg.com/@polkadot/keyring/-/keyring-12.6.2.tgz#6067e6294fee23728b008ac116e7e9db05cecb9b" + integrity sha512-O3Q7GVmRYm8q7HuB3S0+Yf/q/EB2egKRRU3fv9b3B7V+A52tKzA+vIwEmNVaD1g5FKW9oB97rmpggs0zaKFqHw== + dependencies: + "@polkadot/util" "12.6.2" + "@polkadot/util-crypto" "12.6.2" + tslib "^2.6.2" + +"@polkadot/keyring@^14.0.1": + version "14.0.1" + resolved "https://registry.yarnpkg.com/@polkadot/keyring/-/keyring-14.0.1.tgz#3937ebfd1da9f1f6cd008b72270d141e459f9c21" + integrity sha512-kHydQPCeTvJrMC9VQO8LPhAhTUxzxfNF1HEknhZDBPPsxP/XpkYsEy/Ln1QzJmQqD5VsgwzLDE6cExbJ2CT9CA== + dependencies: + "@polkadot/util" "14.0.1" + "@polkadot/util-crypto" "14.0.1" + tslib "^2.8.0" + +"@polkadot/networks@12.6.2": + version "12.6.2" + resolved "https://registry.yarnpkg.com/@polkadot/networks/-/networks-12.6.2.tgz#791779fee1d86cc5b6cd371858eea9b7c3f8720d" + integrity sha512-1oWtZm1IvPWqvMrldVH6NI2gBoCndl5GEwx7lAuQWGr7eNL+6Bdc5K3Z9T0MzFvDGoi2/CBqjX9dRKo39pDC/w== + dependencies: + "@polkadot/util" "12.6.2" + "@substrate/ss58-registry" "^1.44.0" + tslib "^2.6.2" + +"@polkadot/networks@13.5.9": + version "13.5.9" + resolved "https://registry.yarnpkg.com/@polkadot/networks/-/networks-13.5.9.tgz#d5ed8fa0478956835ba489bd3ed10da40881b9c2" + integrity sha512-nmKUKJjiLgcih0MkdlJNMnhEYdwEml2rv/h59ll2+rAvpsVWMTLCb6Cq6q7UC44+8kiWK2UUJMkFU+3PFFxndA== + dependencies: + "@polkadot/util" "13.5.9" + "@substrate/ss58-registry" "^1.51.0" + tslib "^2.8.0" + +"@polkadot/networks@14.0.1", "@polkadot/networks@^14.0.1": + version "14.0.1" + resolved "https://registry.yarnpkg.com/@polkadot/networks/-/networks-14.0.1.tgz#18845225e415b492dda0b1af72e6f5965f004501" + integrity sha512-wGlBtXDkusRAj4P7uxfPz80gLO1+j99MLBaQi3bEym2xrFrFhgIWVHOZlBit/1PfaBjhX2Z8XjRxaM2w1p7w2w== + dependencies: + "@polkadot/util" "14.0.1" + "@substrate/ss58-registry" "^1.51.0" + tslib "^2.8.0" + +"@polkadot/rpc-augment@16.5.4": + version "16.5.4" + resolved "https://registry.yarnpkg.com/@polkadot/rpc-augment/-/rpc-augment-16.5.4.tgz#b861d11a987a6e99fd250f6504a91488288d5787" + integrity sha512-j9v3Ttqv/EYGezHtVksGJAFZhE/4F7LUWooOazh/53ATowMby3lZUdwInrK6bpYmG2whmYMw/Fo283fwDroBtQ== + dependencies: + "@polkadot/rpc-core" "16.5.4" + "@polkadot/types" "16.5.4" + "@polkadot/types-codec" "16.5.4" + "@polkadot/util" "^14.0.1" + tslib "^2.8.1" + +"@polkadot/rpc-core@16.5.4": + version "16.5.4" + resolved "https://registry.yarnpkg.com/@polkadot/rpc-core/-/rpc-core-16.5.4.tgz#bc390b3faf5e8520cf8e17b5ca6e40b7bef71b40" + integrity sha512-92LOSTWujPjtmKOPvfCPs8rAaPFU+18wTtkIzwPwKxvxkN/SWsYSGIxmsoags9ramyHB6jp7Lr59TEuGMxIZzQ== + dependencies: + "@polkadot/rpc-augment" "16.5.4" + "@polkadot/rpc-provider" "16.5.4" + "@polkadot/types" "16.5.4" + "@polkadot/util" "^14.0.1" + rxjs "^7.8.1" + tslib "^2.8.1" + +"@polkadot/rpc-provider@16.5.4": + version "16.5.4" + resolved "https://registry.yarnpkg.com/@polkadot/rpc-provider/-/rpc-provider-16.5.4.tgz#3aaa26f0dec59ca4474c85ac874ff498847a657f" + integrity sha512-mNAIBRA3jMvpnHsuqAX4InHSIqBdgxFD6ayVUFFAzOX8Fh6Xpd4RdI1dqr6a1pCzjnPSby4nbg+VuadWwauVtg== + dependencies: + "@polkadot/keyring" "^14.0.1" + "@polkadot/types" "16.5.4" + "@polkadot/types-support" "16.5.4" + "@polkadot/util" "^14.0.1" + "@polkadot/util-crypto" "^14.0.1" + "@polkadot/x-fetch" "^14.0.1" + "@polkadot/x-global" "^14.0.1" + "@polkadot/x-ws" "^14.0.1" + eventemitter3 "^5.0.1" + mock-socket "^9.3.1" + nock "^13.5.5" + tslib "^2.8.1" + optionalDependencies: + "@substrate/connect" "0.8.11" + +"@polkadot/types-augment@16.5.4": + version "16.5.4" + resolved "https://registry.yarnpkg.com/@polkadot/types-augment/-/types-augment-16.5.4.tgz#24668c1f9e46c16a3fb5468bae0a7eaf13ebd454" + integrity sha512-AGjXR+Q9O9UtVkGw/HuOXlbRqVpvG6H8nr+taXP71wuC6RD9gznFBFBqoNkfWHD2w89esNVQLTvXHVxlLpTXqA== + dependencies: + "@polkadot/types" "16.5.4" + "@polkadot/types-codec" "16.5.4" + "@polkadot/util" "^14.0.1" + tslib "^2.8.1" + +"@polkadot/types-codec@16.5.4": + version "16.5.4" + resolved "https://registry.yarnpkg.com/@polkadot/types-codec/-/types-codec-16.5.4.tgz#df19c54e26b59396c72cd916ebecd9a956eb2577" + integrity sha512-OQtT1pmJu2F3/+Vh1OiXifKoeRy+CU1+Lu7dgTcdO705dnxU4447Zup5JVCJDnxBmMITts/38vbFN2pD225AnA== + dependencies: + "@polkadot/util" "^14.0.1" + "@polkadot/x-bigint" "^14.0.1" + tslib "^2.8.1" + +"@polkadot/types-create@16.5.4": + version "16.5.4" + resolved "https://registry.yarnpkg.com/@polkadot/types-create/-/types-create-16.5.4.tgz#4feb6cbb9ea0f452eef98a098292f975dab1534b" + integrity sha512-URQnvr/sgvgIRSxIW3lmml6HMSTRRj2hTZIm6nhMTlYSVT4rLWx0ZbYUAjoPBbaJ+BmoqZ6Bbs+tA+5cQViv5Q== + dependencies: + "@polkadot/types-codec" "16.5.4" + "@polkadot/util" "^14.0.1" + tslib "^2.8.1" + +"@polkadot/types-known@16.5.4": + version "16.5.4" + resolved "https://registry.yarnpkg.com/@polkadot/types-known/-/types-known-16.5.4.tgz#c6eb756d9158b0600d5876c7732bc73f0ef6d898" + integrity sha512-Dd59y4e3AFCrH9xiqMU4xlG5+Zy0OTy7GQvqJVYXZFyAH+4HYDlxXjJGcSidGAmJcclSYfS3wyEkfw+j1EOVEw== + dependencies: + "@polkadot/networks" "^14.0.1" + "@polkadot/types" "16.5.4" + "@polkadot/types-codec" "16.5.4" + "@polkadot/types-create" "16.5.4" + "@polkadot/util" "^14.0.1" + tslib "^2.8.1" + +"@polkadot/types-support@16.5.4": + version "16.5.4" + resolved "https://registry.yarnpkg.com/@polkadot/types-support/-/types-support-16.5.4.tgz#a8d1543b8cbfd8cadf02faee151bc2016e49caba" + integrity sha512-Ra6keCaO73ibxN6MzA56jFq9EReje7jjE4JQfzV5IpyDZdXcmPyJiEfa2Yps/YSP13Gc2e38t9FFyVau0V+SFQ== + dependencies: + "@polkadot/util" "^14.0.1" + tslib "^2.8.1" + +"@polkadot/types@16.5.4", "@polkadot/types@^16.4.9": + version "16.5.4" + resolved "https://registry.yarnpkg.com/@polkadot/types/-/types-16.5.4.tgz#32372abf736b95924cf0ab8fd5200929f82febf5" + integrity sha512-8Oo1QWaL0DkIc/n2wKBIozPWug/0b2dPVhL+XrXHxJX7rIqS0x8sXDRbM9r166sI0nTqJiUho7pRIkt2PR/DMQ== + dependencies: + "@polkadot/keyring" "^14.0.1" + "@polkadot/types-augment" "16.5.4" + "@polkadot/types-codec" "16.5.4" + "@polkadot/types-create" "16.5.4" + "@polkadot/util" "^14.0.1" + "@polkadot/util-crypto" "^14.0.1" + rxjs "^7.8.1" + tslib "^2.8.1" + +"@polkadot/util-crypto@12.6.2": + version "12.6.2" + resolved "https://registry.yarnpkg.com/@polkadot/util-crypto/-/util-crypto-12.6.2.tgz#d2d51010e8e8ca88951b7d864add797dad18bbfc" + integrity sha512-FEWI/dJ7wDMNN1WOzZAjQoIcCP/3vz3wvAp5QQm+lOrzOLj0iDmaIGIcBkz8HVm3ErfSe/uKP0KS4jgV/ib+Mg== + dependencies: + "@noble/curves" "^1.3.0" + "@noble/hashes" "^1.3.3" + "@polkadot/networks" "12.6.2" + "@polkadot/util" "12.6.2" + "@polkadot/wasm-crypto" "^7.3.2" + "@polkadot/wasm-util" "^7.3.2" + "@polkadot/x-bigint" "12.6.2" + "@polkadot/x-randomvalues" "12.6.2" + "@scure/base" "^1.1.5" + tslib "^2.6.2" + +"@polkadot/util-crypto@14.0.1", "@polkadot/util-crypto@^14.0.1": + version "14.0.1" + resolved "https://registry.yarnpkg.com/@polkadot/util-crypto/-/util-crypto-14.0.1.tgz#51a6cae461620d9f7b5bcb67e4899135ac072643" + integrity sha512-Cu7AKUzBTsUkbOtyuNzXcTpDjR9QW0fVR56o3gBmzfUCmvO1vlsuGzmmPzqpHymQQ3rrfqV78CPs62EGhw0R+A== + dependencies: + "@noble/curves" "^1.3.0" + "@noble/hashes" "^1.3.3" + "@polkadot/networks" "14.0.1" + "@polkadot/util" "14.0.1" + "@polkadot/wasm-crypto" "^7.5.3" + "@polkadot/wasm-util" "^7.5.3" + "@polkadot/x-bigint" "14.0.1" + "@polkadot/x-randomvalues" "14.0.1" + "@scure/base" "^1.1.7" + "@scure/sr25519" "^0.2.0" + tslib "^2.8.0" + +"@polkadot/util-crypto@^13.5.9": + version "13.5.9" + resolved "https://registry.yarnpkg.com/@polkadot/util-crypto/-/util-crypto-13.5.9.tgz#13dfa31f83527b0d486298bd85bbf604304caa20" + integrity sha512-foUesMhxkTk8CZ0/XEcfvHk6I0O+aICqqVJllhOpyp/ZVnrTBKBf59T6RpsXx2pCtBlMsLRvg/6Mw7RND1HqDg== + dependencies: + "@noble/curves" "^1.3.0" + "@noble/hashes" "^1.3.3" + "@polkadot/networks" "13.5.9" + "@polkadot/util" "13.5.9" + "@polkadot/wasm-crypto" "^7.5.3" + "@polkadot/wasm-util" "^7.5.3" + "@polkadot/x-bigint" "13.5.9" + "@polkadot/x-randomvalues" "13.5.9" + "@scure/base" "^1.1.7" + tslib "^2.8.0" + +"@polkadot/util@12.6.2", "@polkadot/util@^12.6.2": + version "12.6.2" + resolved "https://registry.yarnpkg.com/@polkadot/util/-/util-12.6.2.tgz#9396eff491221e1f0fd28feac55fc16ecd61a8dc" + integrity sha512-l8TubR7CLEY47240uki0TQzFvtnxFIO7uI/0GoWzpYD/O62EIAMRsuY01N4DuwgKq2ZWD59WhzsLYmA5K6ksdw== + dependencies: + "@polkadot/x-bigint" "12.6.2" + "@polkadot/x-global" "12.6.2" + "@polkadot/x-textdecoder" "12.6.2" + "@polkadot/x-textencoder" "12.6.2" + "@types/bn.js" "^5.1.5" + bn.js "^5.2.1" + tslib "^2.6.2" + +"@polkadot/util@13.5.9": + version "13.5.9" + resolved "https://registry.yarnpkg.com/@polkadot/util/-/util-13.5.9.tgz#26fb10b6479a6a884101d3ad8a3198c35903481c" + integrity sha512-pIK3XYXo7DKeFRkEBNYhf3GbCHg6dKQisSvdzZwuyzA6m7YxQq4DFw4IE464ve4Z7WsJFt3a6C9uII36hl9EWw== + dependencies: + "@polkadot/x-bigint" "13.5.9" + "@polkadot/x-global" "13.5.9" + "@polkadot/x-textdecoder" "13.5.9" + "@polkadot/x-textencoder" "13.5.9" + "@types/bn.js" "^5.1.6" + bn.js "^5.2.1" + tslib "^2.8.0" + +"@polkadot/util@14.0.1", "@polkadot/util@^14.0.1": + version "14.0.1" + resolved "https://registry.yarnpkg.com/@polkadot/util/-/util-14.0.1.tgz#2587bda312be5809e0dcdd60fd8c5daccff59579" + integrity sha512-764HhxkPV3x5rM0/p6QdynC2dw26n+SaE+jisjx556ViCd4E28Ke4xSPef6C0Spy4aoXf2gt0PuLEcBvd6fVZg== + dependencies: + "@polkadot/x-bigint" "14.0.1" + "@polkadot/x-global" "14.0.1" + "@polkadot/x-textdecoder" "14.0.1" + "@polkadot/x-textencoder" "14.0.1" + "@types/bn.js" "^5.1.6" + bn.js "^5.2.1" + tslib "^2.8.0" + +"@polkadot/wasm-bridge@7.5.4": + version "7.5.4" + resolved "https://registry.yarnpkg.com/@polkadot/wasm-bridge/-/wasm-bridge-7.5.4.tgz#8b938b3def8f6b0bccbe5555c076efafe484fbc5" + integrity sha512-6xaJVvoZbnbgpQYXNw9OHVNWjXmtcoPcWh7hlwx3NpfiLkkjljj99YS+XGZQlq7ks2fVCg7FbfknkNb8PldDaA== + dependencies: + "@polkadot/wasm-util" "7.5.4" + tslib "^2.7.0" + +"@polkadot/wasm-crypto-asmjs@7.5.4": + version "7.5.4" + resolved "https://registry.yarnpkg.com/@polkadot/wasm-crypto-asmjs/-/wasm-crypto-asmjs-7.5.4.tgz#d5ef668e0fa194cec5d54c11388359447b466ad0" + integrity sha512-ZYwxQHAJ8pPt6kYk9XFmyuFuSS+yirJLonvP+DYbxOrARRUHfN4nzp4zcZNXUuaFhpbDobDSFn6gYzye6BUotA== + dependencies: + tslib "^2.7.0" + +"@polkadot/wasm-crypto-init@7.5.4": + version "7.5.4" + resolved "https://registry.yarnpkg.com/@polkadot/wasm-crypto-init/-/wasm-crypto-init-7.5.4.tgz#3ebb59a76a7a2ec05bde3fd619197fb1a164aff9" + integrity sha512-U6s4Eo2rHs2n1iR01vTz/sOQ7eOnRPjaCsGWhPV+ZC/20hkVzwPAhiizu/IqMEol4tO2yiSheD4D6bn0KxUJhg== + dependencies: + "@polkadot/wasm-bridge" "7.5.4" + "@polkadot/wasm-crypto-asmjs" "7.5.4" + "@polkadot/wasm-crypto-wasm" "7.5.4" + "@polkadot/wasm-util" "7.5.4" + tslib "^2.7.0" + +"@polkadot/wasm-crypto-wasm@7.5.4": + version "7.5.4" + resolved "https://registry.yarnpkg.com/@polkadot/wasm-crypto-wasm/-/wasm-crypto-wasm-7.5.4.tgz#bc4fb9aa707cd8218c8143d330ccf2db989a2726" + integrity sha512-PsHgLsVTu43eprwSvUGnxybtOEuHPES6AbApcs7y5ZbM2PiDMzYbAjNul098xJK/CPtrxZ0ePDFnaQBmIJyTFw== + dependencies: + "@polkadot/wasm-util" "7.5.4" + tslib "^2.7.0" + +"@polkadot/wasm-crypto@^7.3.2", "@polkadot/wasm-crypto@^7.5.1", "@polkadot/wasm-crypto@^7.5.3": + version "7.5.4" + resolved "https://registry.yarnpkg.com/@polkadot/wasm-crypto/-/wasm-crypto-7.5.4.tgz#c83b91623e96e168262935a7f2e7c1ffd1875249" + integrity sha512-1seyClxa7Jd7kQjfnCzTTTfYhTa/KUTDUaD3DMHBk5Q4ZUN1D1unJgX+v1aUeXSPxmzocdZETPJJRZjhVOqg9g== + dependencies: + "@polkadot/wasm-bridge" "7.5.4" + "@polkadot/wasm-crypto-asmjs" "7.5.4" + "@polkadot/wasm-crypto-init" "7.5.4" + "@polkadot/wasm-crypto-wasm" "7.5.4" + "@polkadot/wasm-util" "7.5.4" + tslib "^2.7.0" + +"@polkadot/wasm-util@7.5.4", "@polkadot/wasm-util@^7.3.2", "@polkadot/wasm-util@^7.5.3": + version "7.5.4" + resolved "https://registry.yarnpkg.com/@polkadot/wasm-util/-/wasm-util-7.5.4.tgz#dcaad33f44dc18ff22762c4f1572a5c9bfa77579" + integrity sha512-hqPpfhCpRAqCIn/CYbBluhh0TXmwkJnDRjxrU9Bnqtw9nMNa97D8JuOjdd2pi0rxm+eeLQ/f1rQMp71RMM9t4w== + dependencies: + tslib "^2.7.0" + +"@polkadot/x-bigint@12.6.2": + version "12.6.2" + resolved "https://registry.yarnpkg.com/@polkadot/x-bigint/-/x-bigint-12.6.2.tgz#59b7a615f205ae65e1ac67194aefde94d3344580" + integrity sha512-HSIk60uFPX4GOFZSnIF7VYJz7WZA7tpFJsne7SzxOooRwMTWEtw3fUpFy5cYYOeLh17/kHH1Y7SVcuxzVLc74Q== + dependencies: + "@polkadot/x-global" "12.6.2" + tslib "^2.6.2" + +"@polkadot/x-bigint@13.5.9": + version "13.5.9" + resolved "https://registry.yarnpkg.com/@polkadot/x-bigint/-/x-bigint-13.5.9.tgz#a0b665a7c120dba02fbe4f2272762895b39e9d0f" + integrity sha512-JVW6vw3e8fkcRyN9eoc6JIl63MRxNQCP/tuLdHWZts1tcAYao0hpWUzteqJY93AgvmQ91KPsC1Kf3iuuZCi74g== + dependencies: + "@polkadot/x-global" "13.5.9" + tslib "^2.8.0" + +"@polkadot/x-bigint@14.0.1", "@polkadot/x-bigint@^14.0.1": + version "14.0.1" + resolved "https://registry.yarnpkg.com/@polkadot/x-bigint/-/x-bigint-14.0.1.tgz#e34dc77e9e4c3e283b09ba89d9f9a6323ecab9af" + integrity sha512-gfozjGnebr2rqURs31KtaWumbW4rRZpbiluhlmai6luCNrf5u8pB+oLA35kPEntrsLk9PnIG9OsC/n4hEtx4OQ== + dependencies: + "@polkadot/x-global" "14.0.1" + tslib "^2.8.0" + +"@polkadot/x-fetch@^14.0.1": + version "14.0.1" + resolved "https://registry.yarnpkg.com/@polkadot/x-fetch/-/x-fetch-14.0.1.tgz#66c0f949fb11f8fd07f8c78bab36ea335eb1e93b" + integrity sha512-yFsnO0xfkp3bIcvH70ZvmeUINYH1YnjOIS1B430f3w6axkqKhAOWCgzzKGMSRgn4dtm3YgwMBKPQ4nyfIsGOJQ== + dependencies: + "@polkadot/x-global" "14.0.1" + node-fetch "^3.3.2" + tslib "^2.8.0" + +"@polkadot/x-global@12.6.2": + version "12.6.2" + resolved "https://registry.yarnpkg.com/@polkadot/x-global/-/x-global-12.6.2.tgz#31d4de1c3d4c44e4be3219555a6d91091decc4ec" + integrity sha512-a8d6m+PW98jmsYDtAWp88qS4dl8DyqUBsd0S+WgyfSMtpEXu6v9nXDgPZgwF5xdDvXhm+P0ZfVkVTnIGrScb5g== + dependencies: + tslib "^2.6.2" + +"@polkadot/x-global@13.5.9": + version "13.5.9" + resolved "https://registry.yarnpkg.com/@polkadot/x-global/-/x-global-13.5.9.tgz#22d680f036a879a5aef15963f96d71dd115927a3" + integrity sha512-zSRWvELHd3Q+bFkkI1h2cWIqLo1ETm+MxkNXLec3lB56iyq/MjWBxfXnAFFYFayvlEVneo7CLHcp+YTFd9aVSA== + dependencies: + tslib "^2.8.0" + +"@polkadot/x-global@14.0.1", "@polkadot/x-global@^14.0.1": + version "14.0.1" + resolved "https://registry.yarnpkg.com/@polkadot/x-global/-/x-global-14.0.1.tgz#a268dc4b5d380b204c161977f75d0468cfe479d3" + integrity sha512-aCI44DJU4fU0XXqrrSGIpi7JrZXK2kpe0jaQ2p6oDVXOOYEnZYXnMhTTmBE1lF/xtxzX50MnZrrU87jziU0qbA== + dependencies: + tslib "^2.8.0" + +"@polkadot/x-randomvalues@12.6.2": + version "12.6.2" + resolved "https://registry.yarnpkg.com/@polkadot/x-randomvalues/-/x-randomvalues-12.6.2.tgz#13fe3619368b8bf5cb73781554859b5ff9d900a2" + integrity sha512-Vr8uG7rH2IcNJwtyf5ebdODMcr0XjoCpUbI91Zv6AlKVYOGKZlKLYJHIwpTaKKB+7KPWyQrk4Mlym/rS7v9feg== + dependencies: + "@polkadot/x-global" "12.6.2" + tslib "^2.6.2" + +"@polkadot/x-randomvalues@13.5.9": + version "13.5.9" + resolved "https://registry.yarnpkg.com/@polkadot/x-randomvalues/-/x-randomvalues-13.5.9.tgz#5d5e2bdef2bbd6ded99a1ff081d7d67af500c8e7" + integrity sha512-Uuuz3oubf1JCCK97fsnVUnHvk4BGp/W91mQWJlgl5TIOUSSTIRr+lb5GurCfl4kgnQq53Zi5fJV+qR9YumbnZw== + dependencies: + "@polkadot/x-global" "13.5.9" + tslib "^2.8.0" + +"@polkadot/x-randomvalues@14.0.1": + version "14.0.1" + resolved "https://registry.yarnpkg.com/@polkadot/x-randomvalues/-/x-randomvalues-14.0.1.tgz#6cdf67f9afeb98f2f4f2862def4b1d5ae97378af" + integrity sha512-/XkQcvshzJLHITuPrN3zmQKuFIPdKWoaiHhhVLD6rQWV60lTXA3ajw3ocju8ZN7xRxnweMS9Ce0kMPYa0NhRMg== + dependencies: + "@polkadot/x-global" "14.0.1" + tslib "^2.8.0" + +"@polkadot/x-textdecoder@12.6.2": + version "12.6.2" + resolved "https://registry.yarnpkg.com/@polkadot/x-textdecoder/-/x-textdecoder-12.6.2.tgz#b86da0f8e8178f1ca31a7158257e92aea90b10e4" + integrity sha512-M1Bir7tYvNappfpFWXOJcnxUhBUFWkUFIdJSyH0zs5LmFtFdbKAeiDXxSp2Swp5ddOZdZgPac294/o2TnQKN1w== + dependencies: + "@polkadot/x-global" "12.6.2" + tslib "^2.6.2" + +"@polkadot/x-textdecoder@13.5.9": + version "13.5.9" + resolved "https://registry.yarnpkg.com/@polkadot/x-textdecoder/-/x-textdecoder-13.5.9.tgz#ce6dc1177c2d89549ad5bdfe5409cb6b42182c14" + integrity sha512-W2HhVNUbC/tuFdzNMbnXAWsIHSg9SC9QWDNmFD3nXdSzlXNgL8NmuiwN2fkYvCQBtp/XSoy0gDLx0C+Fo19cfw== + dependencies: + "@polkadot/x-global" "13.5.9" + tslib "^2.8.0" + +"@polkadot/x-textdecoder@14.0.1": + version "14.0.1" + resolved "https://registry.yarnpkg.com/@polkadot/x-textdecoder/-/x-textdecoder-14.0.1.tgz#7835f686728b9d1d70f204e843d7f6c0b53c8e1d" + integrity sha512-CcWiPCuPVJsNk4Vq43lgFHqLRBQHb4r9RD7ZIYgmwoebES8TNm4g2ew9ToCzakFKSpzKu6I07Ne9wv/dt5zLuw== + dependencies: + "@polkadot/x-global" "14.0.1" + tslib "^2.8.0" + +"@polkadot/x-textencoder@12.6.2": + version "12.6.2" + resolved "https://registry.yarnpkg.com/@polkadot/x-textencoder/-/x-textencoder-12.6.2.tgz#81d23bd904a2c36137a395c865c5fefa21abfb44" + integrity sha512-4N+3UVCpI489tUJ6cv3uf0PjOHvgGp9Dl+SZRLgFGt9mvxnvpW/7+XBADRMtlG4xi5gaRK7bgl5bmY6OMDsNdw== + dependencies: + "@polkadot/x-global" "12.6.2" + tslib "^2.6.2" + +"@polkadot/x-textencoder@13.5.9": + version "13.5.9" + resolved "https://registry.yarnpkg.com/@polkadot/x-textencoder/-/x-textencoder-13.5.9.tgz#c70f7add6e2c40c04d190160bc5c574674def78f" + integrity sha512-SG0MHnLUgn1ZxFdm0KzMdTHJ47SfqFhdIPMcGA0Mg/jt2rwrfrP3jtEIJMsHfQpHvfsNPfv55XOMmoPWuQnP/Q== + dependencies: + "@polkadot/x-global" "13.5.9" + tslib "^2.8.0" + +"@polkadot/x-textencoder@14.0.1": + version "14.0.1" + resolved "https://registry.yarnpkg.com/@polkadot/x-textencoder/-/x-textencoder-14.0.1.tgz#a07c9b69da4425688af2d131aaf0c154abe69fb2" + integrity sha512-VY51SpQmF1ccmAGLfxhYnAe95Spfz049WZ/+kK4NfsGF9WejxVdU53Im5C80l45r8qHuYQsCWU3+t0FNunh2Kg== + dependencies: + "@polkadot/x-global" "14.0.1" + tslib "^2.8.0" + +"@polkadot/x-ws@^14.0.1": + version "14.0.1" + resolved "https://registry.yarnpkg.com/@polkadot/x-ws/-/x-ws-14.0.1.tgz#1ec2d0832922fc485f5fe490438ec852d6c63ca9" + integrity sha512-Q18hoSuOl7F4aENNGNt9XYxkrjwZlC6xye9OQrPDeHam1SrvflGv9mSZHyo+mwJs0z1PCz2STpPEN9PKfZvHng== + dependencies: + "@polkadot/x-global" "14.0.1" + tslib "^2.8.0" + ws "^8.18.0" + +"@scure/base@^1.1.1", "@scure/base@^1.1.5", "@scure/base@^1.1.7", "@scure/base@~1.2.5": + version "1.2.6" + resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.2.6.tgz#ca917184b8231394dd8847509c67a0be522e59f6" + integrity sha512-g/nm5FgUa//MCj1gV09zTJTaM6KBAHqLN907YVQqf7zC49+DcO4B1so4ZX07Ef10Twr6nuqYEH9GEggFXA4Fmg== + +"@scure/bip32@1.7.0", "@scure/bip32@^1.7.0": + version "1.7.0" + resolved "https://registry.yarnpkg.com/@scure/bip32/-/bip32-1.7.0.tgz#b8683bab172369f988f1589640e53c4606984219" + integrity sha512-E4FFX/N3f4B80AKWp5dP6ow+flD1LQZo/w8UnLGYZO674jS6YnYeepycOOksv+vLPSpgN35wgKgy+ybfTb2SMw== + dependencies: + "@noble/curves" "~1.9.0" + "@noble/hashes" "~1.8.0" + "@scure/base" "~1.2.5" + +"@scure/bip39@1.6.0", "@scure/bip39@^1.6.0": + version "1.6.0" + resolved "https://registry.yarnpkg.com/@scure/bip39/-/bip39-1.6.0.tgz#475970ace440d7be87a6086cbee77cb8f1a684f9" + integrity sha512-+lF0BbLiJNwVlev4eKelw1WWLaiKXw7sSl8T6FvBlWkdX+94aGJ4o8XjUdlyhTCjd8c+B3KT3JfS8P0bLRNU6A== + dependencies: + "@noble/hashes" "~1.8.0" + "@scure/base" "~1.2.5" + +"@scure/sr25519@^0.2.0": + version "0.2.0" + resolved "https://registry.yarnpkg.com/@scure/sr25519/-/sr25519-0.2.0.tgz#b2de2407a2d59522d7d0f26fafbac260fd9314d2" + integrity sha512-uUuLP7Z126XdSizKtrCGqYyR3b3hYtJ6Fg/XFUXmc2//k2aXHDLqZwFeXxL97gg4XydPROPVnuaHGF2+xriSKg== + dependencies: + "@noble/curves" "~1.9.2" + "@noble/hashes" "~1.8.0" + +"@sinclair/typebox@^0.34.0": + version "0.34.48" + resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.34.48.tgz#75b0ead87e59e1adbd6dccdc42bad4fddee73b59" + integrity sha512-kKJTNuK3AQOrgjjotVxMrCn1sUJwM76wMszfq1kdU4uYVJjvEWuFQ6HgvLt4Xz3fSmZlTOxJ/Ie13KnIcWQXFA== + +"@sinonjs/commons@^3.0.1": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-3.0.1.tgz#1029357e44ca901a615585f6d27738dbc89084cd" + integrity sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ== + dependencies: + type-detect "4.0.8" + +"@sinonjs/fake-timers@^13.0.0": + version "13.0.5" + resolved "https://registry.yarnpkg.com/@sinonjs/fake-timers/-/fake-timers-13.0.5.tgz#36b9dbc21ad5546486ea9173d6bea063eb1717d5" + integrity sha512-36/hTbH2uaWuGVERyC6da9YwGWnzUZXuPro/F2LfsdOsLnCojz/iSH8MxUt/FD2S5XBSVPhmArFUXcpCQ2Hkiw== + dependencies: + "@sinonjs/commons" "^3.0.1" + +"@substrate/connect-extension-protocol@^2.0.0": + version "2.2.2" + resolved "https://registry.yarnpkg.com/@substrate/connect-extension-protocol/-/connect-extension-protocol-2.2.2.tgz#2cf8f2eaf1879308d307a1a08df83cd5db918fe0" + integrity sha512-t66jwrXA0s5Goq82ZtjagLNd7DPGCNjHeehRlE/gcJmJ+G56C0W+2plqOMRicJ8XGR1/YFnUSEqUFiSNbjGrAA== + +"@substrate/connect-known-chains@^1.1.5": + version "1.10.3" + resolved "https://registry.yarnpkg.com/@substrate/connect-known-chains/-/connect-known-chains-1.10.3.tgz#71a89864f13626c412fa0a9d0ffc4f6ca39fdcec" + integrity sha512-OJEZO1Pagtb6bNE3wCikc2wrmvEU5x7GxFFLqqbz1AJYYxSlrPCGu4N2og5YTExo4IcloNMQYFRkBGue0BKZ4w== + +"@substrate/connect@0.8.11": + version "0.8.11" + resolved "https://registry.yarnpkg.com/@substrate/connect/-/connect-0.8.11.tgz#983ec69a05231636e217b573b8130a6b942af69f" + integrity sha512-ofLs1PAO9AtDdPbdyTYj217Pe+lBfTLltdHDs3ds8no0BseoLeAGxpz1mHfi7zB4IxI3YyAiLjH6U8cw4pj4Nw== + dependencies: + "@substrate/connect-extension-protocol" "^2.0.0" + "@substrate/connect-known-chains" "^1.1.5" + "@substrate/light-client-extension-helpers" "^1.0.0" + smoldot "2.0.26" + +"@substrate/light-client-extension-helpers@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@substrate/light-client-extension-helpers/-/light-client-extension-helpers-1.0.0.tgz#7b60368c57e06e5cf798c6557422d12e6d81f1ff" + integrity sha512-TdKlni1mBBZptOaeVrKnusMg/UBpWUORNDv5fdCaJklP4RJiFOzBCrzC+CyVI5kQzsXBisZ+2pXm+rIjS38kHg== + dependencies: + "@polkadot-api/json-rpc-provider" "^0.0.1" + "@polkadot-api/json-rpc-provider-proxy" "^0.1.0" + "@polkadot-api/observable-client" "^0.3.0" + "@polkadot-api/substrate-client" "^0.1.2" + "@substrate/connect-extension-protocol" "^2.0.0" + "@substrate/connect-known-chains" "^1.1.5" + rxjs "^7.8.1" + +"@substrate/ss58-registry@^1.44.0", "@substrate/ss58-registry@^1.51.0": + version "1.51.0" + resolved "https://registry.yarnpkg.com/@substrate/ss58-registry/-/ss58-registry-1.51.0.tgz#39e0341eb4069c2d3e684b93f0d8cb0bec572383" + integrity sha512-TWDurLiPxndFgKjVavCniytBIw+t4ViOi7TYp9h/D0NMmkEc9klFTo+827eyEJ0lELpqO207Ey7uGxUa+BS1jQ== + +"@tsconfig/node10@^1.0.7": + version "1.0.12" + resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.12.tgz#be57ceac1e4692b41be9de6be8c32a106636dba4" + integrity sha512-UCYBaeFvM11aU2y3YPZ//O5Rhj+xKyzy7mvcIoAjASbigy8mHMryP5cK7dgjlz2hWxh1g5pLw084E0a/wlUSFQ== + +"@tsconfig/node12@^1.0.7": + version "1.0.11" + resolved "https://registry.yarnpkg.com/@tsconfig/node12/-/node12-1.0.11.tgz#ee3def1f27d9ed66dac6e46a295cffb0152e058d" + integrity sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag== + +"@tsconfig/node14@^1.0.0": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@tsconfig/node14/-/node14-1.0.3.tgz#e4386316284f00b98435bf40f72f75a09dabf6c1" + integrity sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow== + +"@tsconfig/node16@^1.0.2": + version "1.0.4" + resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.4.tgz#0b92dcc0cc1c81f6f306a381f28e31b1a56536e9" + integrity sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA== + +"@tybys/wasm-util@^0.10.0": + version "0.10.1" + resolved "https://registry.yarnpkg.com/@tybys/wasm-util/-/wasm-util-0.10.1.tgz#ecddd3205cf1e2d5274649ff0eedd2991ed7f414" + integrity sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg== + dependencies: + tslib "^2.4.0" + +"@types/babel__core@^7.20.5": + version "7.20.5" + resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.20.5.tgz#3df15f27ba85319caa07ba08d0721889bb39c017" + integrity sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA== + dependencies: + "@babel/parser" "^7.20.7" + "@babel/types" "^7.20.7" + "@types/babel__generator" "*" + "@types/babel__template" "*" + "@types/babel__traverse" "*" + +"@types/babel__generator@*": + version "7.27.0" + resolved "https://registry.yarnpkg.com/@types/babel__generator/-/babel__generator-7.27.0.tgz#b5819294c51179957afaec341442f9341e4108a9" + integrity sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg== + dependencies: + "@babel/types" "^7.0.0" + +"@types/babel__template@*": + version "7.4.4" + resolved "https://registry.yarnpkg.com/@types/babel__template/-/babel__template-7.4.4.tgz#5672513701c1b2199bc6dad636a9d7491586766f" + integrity sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A== + dependencies: + "@babel/parser" "^7.1.0" + "@babel/types" "^7.0.0" + +"@types/babel__traverse@*": + version "7.28.0" + resolved "https://registry.yarnpkg.com/@types/babel__traverse/-/babel__traverse-7.28.0.tgz#07d713d6cce0d265c9849db0cbe62d3f61f36f74" + integrity sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q== + dependencies: + "@babel/types" "^7.28.2" + +"@types/bn.js@*", "@types/bn.js@^5.1.5", "@types/bn.js@^5.1.6": + version "5.2.0" + resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-5.2.0.tgz#4349b9710e98f9ab3cdc50f1c5e4dcbd8ef29c80" + integrity sha512-DLbJ1BPqxvQhIGbeu8VbUC1DiAiahHtAYvA0ZEAa4P31F7IaArc8z3C3BRQdWX4mtLQuABG4yzp76ZrS02Ui1Q== + dependencies: + "@types/node" "*" + +"@types/elliptic@^6.4.18": + version "6.4.18" + resolved "https://registry.yarnpkg.com/@types/elliptic/-/elliptic-6.4.18.tgz#bc96e26e1ccccbabe8b6f0e409c85898635482e1" + integrity sha512-UseG6H5vjRiNpQvrhy4VF/JXdA3V/Fp5amvveaL+fs28BZ6xIKJBPnUPRlEaZpysD9MbpfaLi8lbl7PGUAkpWw== + dependencies: + "@types/bn.js" "*" + +"@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.1", "@types/istanbul-lib-coverage@^2.0.6": + version "2.0.6" + resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz#7739c232a1fee9b4d3ce8985f314c0c6d33549d7" + integrity sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w== + +"@types/istanbul-lib-report@*": + version "3.0.3" + resolved "https://registry.yarnpkg.com/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz#53047614ae72e19fc0401d872de3ae2b4ce350bf" + integrity sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA== + dependencies: + "@types/istanbul-lib-coverage" "*" + +"@types/istanbul-reports@^3.0.4": + version "3.0.4" + resolved "https://registry.yarnpkg.com/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz#0f03e3d2f670fbdac586e34b433783070cc16f54" + integrity sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ== + dependencies: + "@types/istanbul-lib-report" "*" + +"@types/jest@^30.0.0": + version "30.0.0" + resolved "https://registry.yarnpkg.com/@types/jest/-/jest-30.0.0.tgz#5e85ae568006712e4ad66f25433e9bdac8801f1d" + integrity sha512-XTYugzhuwqWjws0CVz8QpM36+T+Dz5mTEBKhNs/esGLnCIlGdRy+Dq78NRjd7ls7r8BC8ZRMOrKlkO1hU0JOwA== + dependencies: + expect "^30.0.0" + pretty-format "^30.0.0" + +"@types/mocha@^10.0.10": + version "10.0.10" + resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-10.0.10.tgz#91f62905e8d23cbd66225312f239454a23bebfa0" + integrity sha512-xPyYSz1cMPnJQhl0CLMH68j3gprKZaTjG3s5Vi+fDgx+uhG9NOXwbVt52eFS8ECyXhyKcjDLCBEqBExKuiZb7Q== + +"@types/node@*": + version "25.0.10" + resolved "https://registry.yarnpkg.com/@types/node/-/node-25.0.10.tgz#4864459c3c9459376b8b75fd051315071c8213e7" + integrity sha512-zWW5KPngR/yvakJgGOmZ5vTBemDoSqF3AcV/LrO5u5wTWyEAVVh+IT39G4gtyAkh3CtTZs8aX/yRM82OfzHJRg== + dependencies: + undici-types "~7.16.0" + +"@types/node@22.7.5": + version "22.7.5" + resolved "https://registry.yarnpkg.com/@types/node/-/node-22.7.5.tgz#cfde981727a7ab3611a481510b473ae54442b92b" + integrity sha512-jML7s2NAzMWc//QSJ1a3prpk78cOPchGvXJsC3C6R6PSMoooztvRVQEz89gmBTBY1SPMaqo5teB4uNHPdetShQ== + dependencies: + undici-types "~6.19.2" + +"@types/node@^20.11.5": + version "20.19.30" + resolved "https://registry.yarnpkg.com/@types/node/-/node-20.19.30.tgz#84fa87498ade5cd2b6ba8f8eec01d3b138ca60d0" + integrity sha512-WJtwWJu7UdlvzEAUm484QNg5eAoq5QR08KDNx7g45Usrs2NtOPiX8ugDqmKdXkyL03rBqU5dYNYVQetEpBHq2g== + dependencies: + undici-types "~6.21.0" + +"@types/stack-utils@^2.0.3": + version "2.0.3" + resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.3.tgz#6209321eb2c1712a7e7466422b8cb1fc0d9dd5d8" + integrity sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw== + +"@types/yargs-parser@*": + version "21.0.3" + resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-21.0.3.tgz#815e30b786d2e8f0dcd85fd5bcf5e1a04d008f15" + integrity sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ== + +"@types/yargs@^17.0.33": + version "17.0.35" + resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-17.0.35.tgz#07013e46aa4d7d7d50a49e15604c1c5340d4eb24" + integrity sha512-qUHkeCyQFxMXg79wQfTtfndEC+N9ZZg76HJftDJp+qH2tV7Gj4OJi7l+PiWwJ+pWtW8GwSmqsDj/oymhrTWXjg== + dependencies: + "@types/yargs-parser" "*" + +"@ungap/structured-clone@^1.3.0": + version "1.3.0" + resolved "https://registry.yarnpkg.com/@ungap/structured-clone/-/structured-clone-1.3.0.tgz#d06bbb384ebcf6c505fde1c3d0ed4ddffe0aaff8" + integrity sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g== + +"@unrs/resolver-binding-android-arm-eabi@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-android-arm-eabi/-/resolver-binding-android-arm-eabi-1.11.1.tgz#9f5b04503088e6a354295e8ea8fe3cb99e43af81" + integrity sha512-ppLRUgHVaGRWUx0R0Ut06Mjo9gBaBkg3v/8AxusGLhsIotbBLuRk51rAzqLC8gq6NyyAojEXglNjzf6R948DNw== + +"@unrs/resolver-binding-android-arm64@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-android-arm64/-/resolver-binding-android-arm64-1.11.1.tgz#7414885431bd7178b989aedc4d25cccb3865bc9f" + integrity sha512-lCxkVtb4wp1v+EoN+HjIG9cIIzPkX5OtM03pQYkG+U5O/wL53LC4QbIeazgiKqluGeVEeBlZahHalCaBvU1a2g== + +"@unrs/resolver-binding-darwin-arm64@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-darwin-arm64/-/resolver-binding-darwin-arm64-1.11.1.tgz#b4a8556f42171fb9c9f7bac8235045e82aa0cbdf" + integrity sha512-gPVA1UjRu1Y/IsB/dQEsp2V1pm44Of6+LWvbLc9SDk1c2KhhDRDBUkQCYVWe6f26uJb3fOK8saWMgtX8IrMk3g== + +"@unrs/resolver-binding-darwin-x64@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-darwin-x64/-/resolver-binding-darwin-x64-1.11.1.tgz#fd4d81257b13f4d1a083890a6a17c00de571f0dc" + integrity sha512-cFzP7rWKd3lZaCsDze07QX1SC24lO8mPty9vdP+YVa3MGdVgPmFc59317b2ioXtgCMKGiCLxJ4HQs62oz6GfRQ== + +"@unrs/resolver-binding-freebsd-x64@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-freebsd-x64/-/resolver-binding-freebsd-x64-1.11.1.tgz#d2513084d0f37c407757e22f32bd924a78cfd99b" + integrity sha512-fqtGgak3zX4DCB6PFpsH5+Kmt/8CIi4Bry4rb1ho6Av2QHTREM+47y282Uqiu3ZRF5IQioJQ5qWRV6jduA+iGw== + +"@unrs/resolver-binding-linux-arm-gnueabihf@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-linux-arm-gnueabihf/-/resolver-binding-linux-arm-gnueabihf-1.11.1.tgz#844d2605d057488d77fab09705f2866b86164e0a" + integrity sha512-u92mvlcYtp9MRKmP+ZvMmtPN34+/3lMHlyMj7wXJDeXxuM0Vgzz0+PPJNsro1m3IZPYChIkn944wW8TYgGKFHw== + +"@unrs/resolver-binding-linux-arm-musleabihf@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-linux-arm-musleabihf/-/resolver-binding-linux-arm-musleabihf-1.11.1.tgz#204892995cefb6bd1d017d52d097193bc61ddad3" + integrity sha512-cINaoY2z7LVCrfHkIcmvj7osTOtm6VVT16b5oQdS4beibX2SYBwgYLmqhBjA1t51CarSaBuX5YNsWLjsqfW5Cw== + +"@unrs/resolver-binding-linux-arm64-gnu@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-linux-arm64-gnu/-/resolver-binding-linux-arm64-gnu-1.11.1.tgz#023eb0c3aac46066a10be7a3f362e7b34f3bdf9d" + integrity sha512-34gw7PjDGB9JgePJEmhEqBhWvCiiWCuXsL9hYphDF7crW7UgI05gyBAi6MF58uGcMOiOqSJ2ybEeCvHcq0BCmQ== + +"@unrs/resolver-binding-linux-arm64-musl@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-linux-arm64-musl/-/resolver-binding-linux-arm64-musl-1.11.1.tgz#9e6f9abb06424e3140a60ac996139786f5d99be0" + integrity sha512-RyMIx6Uf53hhOtJDIamSbTskA99sPHS96wxVE/bJtePJJtpdKGXO1wY90oRdXuYOGOTuqjT8ACccMc4K6QmT3w== + +"@unrs/resolver-binding-linux-ppc64-gnu@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-linux-ppc64-gnu/-/resolver-binding-linux-ppc64-gnu-1.11.1.tgz#b111417f17c9d1b02efbec8e08398f0c5527bb44" + integrity sha512-D8Vae74A4/a+mZH0FbOkFJL9DSK2R6TFPC9M+jCWYia/q2einCubX10pecpDiTmkJVUH+y8K3BZClycD8nCShA== + +"@unrs/resolver-binding-linux-riscv64-gnu@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-linux-riscv64-gnu/-/resolver-binding-linux-riscv64-gnu-1.11.1.tgz#92ffbf02748af3e99873945c9a8a5ead01d508a9" + integrity sha512-frxL4OrzOWVVsOc96+V3aqTIQl1O2TjgExV4EKgRY09AJ9leZpEg8Ak9phadbuX0BA4k8U5qtvMSQQGGmaJqcQ== + +"@unrs/resolver-binding-linux-riscv64-musl@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-linux-riscv64-musl/-/resolver-binding-linux-riscv64-musl-1.11.1.tgz#0bec6f1258fc390e6b305e9ff44256cb207de165" + integrity sha512-mJ5vuDaIZ+l/acv01sHoXfpnyrNKOk/3aDoEdLO/Xtn9HuZlDD6jKxHlkN8ZhWyLJsRBxfv9GYM2utQ1SChKew== + +"@unrs/resolver-binding-linux-s390x-gnu@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-linux-s390x-gnu/-/resolver-binding-linux-s390x-gnu-1.11.1.tgz#577843a084c5952f5906770633ccfb89dac9bc94" + integrity sha512-kELo8ebBVtb9sA7rMe1Cph4QHreByhaZ2QEADd9NzIQsYNQpt9UkM9iqr2lhGr5afh885d/cB5QeTXSbZHTYPg== + +"@unrs/resolver-binding-linux-x64-gnu@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-linux-x64-gnu/-/resolver-binding-linux-x64-gnu-1.11.1.tgz#36fb318eebdd690f6da32ac5e0499a76fa881935" + integrity sha512-C3ZAHugKgovV5YvAMsxhq0gtXuwESUKc5MhEtjBpLoHPLYM+iuwSj3lflFwK3DPm68660rZ7G8BMcwSro7hD5w== + +"@unrs/resolver-binding-linux-x64-musl@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-linux-x64-musl/-/resolver-binding-linux-x64-musl-1.11.1.tgz#bfb9af75f783f98f6a22c4244214efe4df1853d6" + integrity sha512-rV0YSoyhK2nZ4vEswT/QwqzqQXw5I6CjoaYMOX0TqBlWhojUf8P94mvI7nuJTeaCkkds3QE4+zS8Ko+GdXuZtA== + +"@unrs/resolver-binding-wasm32-wasi@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-wasm32-wasi/-/resolver-binding-wasm32-wasi-1.11.1.tgz#752c359dd875684b27429500d88226d7cc72f71d" + integrity sha512-5u4RkfxJm+Ng7IWgkzi3qrFOvLvQYnPBmjmZQ8+szTK/b31fQCnleNl1GgEt7nIsZRIf5PLhPwT0WM+q45x/UQ== + dependencies: + "@napi-rs/wasm-runtime" "^0.2.11" + +"@unrs/resolver-binding-win32-arm64-msvc@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-win32-arm64-msvc/-/resolver-binding-win32-arm64-msvc-1.11.1.tgz#ce5735e600e4c2fbb409cd051b3b7da4a399af35" + integrity sha512-nRcz5Il4ln0kMhfL8S3hLkxI85BXs3o8EYoattsJNdsX4YUU89iOkVn7g0VHSRxFuVMdM4Q1jEpIId1Ihim/Uw== + +"@unrs/resolver-binding-win32-ia32-msvc@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-win32-ia32-msvc/-/resolver-binding-win32-ia32-msvc-1.11.1.tgz#72fc57bc7c64ec5c3de0d64ee0d1810317bc60a6" + integrity sha512-DCEI6t5i1NmAZp6pFonpD5m7i6aFrpofcp4LA2i8IIq60Jyo28hamKBxNrZcyOwVOZkgsRp9O2sXWBWP8MnvIQ== + +"@unrs/resolver-binding-win32-x64-msvc@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-win32-x64-msvc/-/resolver-binding-win32-x64-msvc-1.11.1.tgz#538b1e103bf8d9864e7b85cc96fa8d6fb6c40777" + integrity sha512-lrW200hZdbfRtztbygyaq/6jP6AKE8qQN2KvPcJ+x7wiD038YtnYtZ82IMNJ69GJibV7bwL3y9FgK+5w/pYt6g== + +abitype@1.2.3, abitype@^1.2.3: + version "1.2.3" + resolved "https://registry.yarnpkg.com/abitype/-/abitype-1.2.3.tgz#bec3e09dea97d99ef6c719140bee663a329ad1f4" + integrity sha512-Ofer5QUnuUdTFsBRwARMoWKOH1ND5ehwYhJ3OJ/BQO+StkwQjHw0XyVh4vDttzHB7QOFhPHa/o413PJ82gU/Tg== + +acorn-walk@^8.1.1: + version "8.3.4" + resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.3.4.tgz#794dd169c3977edf4ba4ea47583587c5866236b7" + integrity sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g== + dependencies: + acorn "^8.11.0" + +acorn@^8.11.0, acorn@^8.4.1: + version "8.15.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.15.0.tgz#a360898bc415edaac46c8241f6383975b930b816" + integrity sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg== + +aes-js@4.0.0-beta.5: + version "4.0.0-beta.5" + resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-4.0.0-beta.5.tgz#8d2452c52adedebc3a3e28465d858c11ca315873" + integrity sha512-G965FqalsNyrPqgEGON7nIx1e/OVENSgiEIzyC63haUMuvNnwIgIjMs52hlTCKhkBny7A2ORNlfY9Zu+jmGk1Q== + +ansi-escapes@^4.3.2: + version "4.3.2" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e" + integrity sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ== + dependencies: + type-fest "^0.21.3" + +ansi-regex@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" + integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== + +ansi-regex@^6.0.1: + version "6.2.2" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-6.2.2.tgz#60216eea464d864597ce2832000738a0589650c1" + integrity sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg== + +ansi-styles@^4.0.0, ansi-styles@^4.1.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" + integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== + dependencies: + color-convert "^2.0.1" + +ansi-styles@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-5.2.0.tgz#07449690ad45777d1924ac2abb2fc8895dba836b" + integrity sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA== + +ansi-styles@^6.1.0: + version "6.2.3" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.2.3.tgz#c044d5dcc521a076413472597a1acb1f103c4041" + integrity sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg== + +anymatch@^3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" + integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== + dependencies: + normalize-path "^3.0.0" + picomatch "^2.0.4" + +arg@^4.1.0: + version "4.1.3" + resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089" + integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA== + +argparse@^1.0.7: + version "1.0.10" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" + integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== + dependencies: + sprintf-js "~1.0.2" + +babel-jest@30.2.0: + version "30.2.0" + resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-30.2.0.tgz#fd44a1ec9552be35ead881f7381faa7d8f3b95ac" + integrity sha512-0YiBEOxWqKkSQWL9nNGGEgndoeL0ZpWrbLMNL5u/Kaxrli3Eaxlt3ZtIDktEvXt4L/R9r3ODr2zKwGM/2BjxVw== + dependencies: + "@jest/transform" "30.2.0" + "@types/babel__core" "^7.20.5" + babel-plugin-istanbul "^7.0.1" + babel-preset-jest "30.2.0" + chalk "^4.1.2" + graceful-fs "^4.2.11" + slash "^3.0.0" + +babel-plugin-istanbul@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/babel-plugin-istanbul/-/babel-plugin-istanbul-7.0.1.tgz#d8b518c8ea199364cf84ccc82de89740236daf92" + integrity sha512-D8Z6Qm8jCvVXtIRkBnqNHX0zJ37rQcFJ9u8WOS6tkYOsRdHBzypCstaxWiu5ZIlqQtviRYbgnRLSoCEvjqcqbA== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@istanbuljs/load-nyc-config" "^1.0.0" + "@istanbuljs/schema" "^0.1.3" + istanbul-lib-instrument "^6.0.2" + test-exclude "^6.0.0" + +babel-plugin-jest-hoist@30.2.0: + version "30.2.0" + resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-30.2.0.tgz#94c250d36b43f95900f3a219241e0f4648191ce2" + integrity sha512-ftzhzSGMUnOzcCXd6WHdBGMyuwy15Wnn0iyyWGKgBDLxf9/s5ABuraCSpBX2uG0jUg4rqJnxsLc5+oYBqoxVaA== + dependencies: + "@types/babel__core" "^7.20.5" + +babel-preset-current-node-syntax@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.2.0.tgz#20730d6cdc7dda5d89401cab10ac6a32067acde6" + integrity sha512-E/VlAEzRrsLEb2+dv8yp3bo4scof3l9nR4lrld+Iy5NyVqgVYUJnDAmunkhPMisRI32Qc4iRiz425d8vM++2fg== + dependencies: + "@babel/plugin-syntax-async-generators" "^7.8.4" + "@babel/plugin-syntax-bigint" "^7.8.3" + "@babel/plugin-syntax-class-properties" "^7.12.13" + "@babel/plugin-syntax-class-static-block" "^7.14.5" + "@babel/plugin-syntax-import-attributes" "^7.24.7" + "@babel/plugin-syntax-import-meta" "^7.10.4" + "@babel/plugin-syntax-json-strings" "^7.8.3" + "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" + "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" + "@babel/plugin-syntax-numeric-separator" "^7.10.4" + "@babel/plugin-syntax-object-rest-spread" "^7.8.3" + "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" + "@babel/plugin-syntax-optional-chaining" "^7.8.3" + "@babel/plugin-syntax-private-property-in-object" "^7.14.5" + "@babel/plugin-syntax-top-level-await" "^7.14.5" + +babel-preset-jest@30.2.0: + version "30.2.0" + resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-30.2.0.tgz#04717843e561347781d6d7f69c81e6bcc3ed11ce" + integrity sha512-US4Z3NOieAQumwFnYdUWKvUKh8+YSnS/gB3t6YBiz0bskpu7Pine8pPCheNxlPEW4wnUkma2a94YuW2q3guvCQ== + dependencies: + babel-plugin-jest-hoist "30.2.0" + babel-preset-current-node-syntax "^1.2.0" + +balanced-match@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" + integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== + +baseline-browser-mapping@^2.9.0: + version "2.9.18" + resolved "https://registry.yarnpkg.com/baseline-browser-mapping/-/baseline-browser-mapping-2.9.18.tgz#c8281693035a9261b10d662a5379650a6c2d1ff7" + integrity sha512-e23vBV1ZLfjb9apvfPk4rHVu2ry6RIr2Wfs+O324okSidrX7pTAnEJPCh/O5BtRlr7QtZI7ktOP3vsqr7Z5XoA== + +bn.js@^4.11.9: + version "4.12.2" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.2.tgz#3d8fed6796c24e177737f7cc5172ee04ef39ec99" + integrity sha512-n4DSx829VRTRByMRGdjQ9iqsN0Bh4OolPsFnaZBLcbi8iXcB+kJ9s7EnRt4wILZNV3kPLHkRVfOc/HvhC3ovDw== + +bn.js@^5.2.1: + version "5.2.2" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.2.tgz#82c09f9ebbb17107cd72cb7fd39bd1f9d0aaa566" + integrity sha512-v2YAxEmKaBLahNwE1mjp4WON6huMNeuDvagFZW+ASCuA/ku0bXR9hSMw0XpiqMoA3+rmnyck/tPRSFQkoC9Cuw== + +brace-expansion@^1.1.7: + version "1.1.12" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.12.tgz#ab9b454466e5a8cc3a187beaad580412a9c5b843" + integrity sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg== + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +brace-expansion@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.2.tgz#54fc53237a613d854c7bd37463aad17df87214e7" + integrity sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ== + dependencies: + balanced-match "^1.0.0" + +braces@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.3.tgz#490332f40919452272d55a8480adc0c441358789" + integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA== + dependencies: + fill-range "^7.1.1" + +brorand@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" + integrity sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w== + +browserslist@^4.24.0: + version "4.28.1" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.28.1.tgz#7f534594628c53c63101079e27e40de490456a95" + integrity sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA== + dependencies: + baseline-browser-mapping "^2.9.0" + caniuse-lite "^1.0.30001759" + electron-to-chromium "^1.5.263" + node-releases "^2.0.27" + update-browserslist-db "^1.2.0" + +bs-logger@^0.2.6: + version "0.2.6" + resolved "https://registry.yarnpkg.com/bs-logger/-/bs-logger-0.2.6.tgz#eb7d365307a72cf974cc6cda76b68354ad336bd8" + integrity sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog== + dependencies: + fast-json-stable-stringify "2.x" + +bser@2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/bser/-/bser-2.1.1.tgz#e6787da20ece9d07998533cfd9de6f5c38f4bc05" + integrity sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ== + dependencies: + node-int64 "^0.4.0" + +buffer-from@^1.0.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" + integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== + +callsites@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" + integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== + +camelcase@^5.3.1: + version "5.3.1" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" + integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== + +camelcase@^6.3.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" + integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== + +caniuse-lite@^1.0.30001759: + version "1.0.30001766" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001766.tgz#b6f6b55cb25a2d888d9393104d14751c6a7d6f7a" + integrity sha512-4C0lfJ0/YPjJQHagaE9x2Elb69CIqEPZeG0anQt9SIvIoOH4a4uaRl73IavyO+0qZh6MDLH//DrXThEYKHkmYA== + +chalk@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" + integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + +char-regex@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/char-regex/-/char-regex-1.0.2.tgz#d744358226217f981ed58f479b1d6bcc29545dcf" + integrity sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw== + +ci-info@^4.2.0: + version "4.3.1" + resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-4.3.1.tgz#355ad571920810b5623e11d40232f443f16f1daa" + integrity sha512-Wdy2Igu8OcBpI2pZePZ5oWjPC38tmDVx5WKUXKwlLYkA0ozo85sLsLvkBbBn/sZaSCMFOGZJ14fvW9t5/d7kdA== + +cjs-module-lexer@^2.1.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/cjs-module-lexer/-/cjs-module-lexer-2.2.0.tgz#b3ca5101843389259ade7d88c77bd06ce55849ca" + integrity sha512-4bHTS2YuzUvtoLjdy+98ykbNB5jS0+07EvFNXerqZQJ89F7DI6ET7OQo/HJuW6K0aVsKA9hj9/RVb2kQVOrPDQ== + +cliui@^8.0.1: + version "8.0.1" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-8.0.1.tgz#0c04b075db02cbfe60dc8e6cf2f5486b1a3608aa" + integrity sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.1" + wrap-ansi "^7.0.0" + +co@^4.6.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" + integrity sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ== + +collect-v8-coverage@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/collect-v8-coverage/-/collect-v8-coverage-1.0.3.tgz#cc1f01eb8d02298cbc9a437c74c70ab4e5210b80" + integrity sha512-1L5aqIkwPfiodaMgQunkF1zRhNqifHBmtbbbxcr6yVxxBnliw4TDOW6NxpO8DJLgJ16OT+Y4ztZqP6p/FtXnAw== + +color-convert@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" + integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== + dependencies: + color-name "~1.1.4" + +color-name@~1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" + integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== + +convert-source-map@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-2.0.0.tgz#4b560f649fc4e918dd0ab75cf4961e8bc882d82a" + integrity sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg== + +create-require@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" + integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== + +cross-spawn@^7.0.3, cross-spawn@^7.0.6: + version "7.0.6" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.6.tgz#8a58fe78f00dcd70c370451759dfbfaf03e8ee9f" + integrity sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA== + dependencies: + path-key "^3.1.0" + shebang-command "^2.0.0" + which "^2.0.1" + +data-uri-to-buffer@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz#d8feb2b2881e6a4f58c2e08acfd0e2834e26222e" + integrity sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A== + +debug@^4.1.0, debug@^4.1.1, debug@^4.3.1: + version "4.4.3" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.3.tgz#c6ae432d9bd9662582fce08709b038c58e9e3d6a" + integrity sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA== + dependencies: + ms "^2.1.3" + +dedent@^1.6.0: + version "1.7.1" + resolved "https://registry.yarnpkg.com/dedent/-/dedent-1.7.1.tgz#364661eea3d73f3faba7089214420ec2f8f13e15" + integrity sha512-9JmrhGZpOlEgOLdQgSm0zxFaYoQon408V1v49aqTWuXENVlnCuY9JBZcXZiCsZQWDjTm5Qf/nIvAy77mXDAjEg== + +deepmerge@^4.3.1: + version "4.3.1" + resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.3.1.tgz#44b5f2147cd3b00d4b56137685966f26fd25dd4a" + integrity sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A== + +detect-newline@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-3.1.0.tgz#576f5dfc63ae1a192ff192d8ad3af6308991b651" + integrity sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA== + +diff@^4.0.1: + version "4.0.4" + resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.4.tgz#7a6dbfda325f25f07517e9b518f897c08332e07d" + integrity sha512-X07nttJQkwkfKfvTPG/KSnE2OMdcUCao6+eXF3wmnIQRn2aPAHH3VxDbDOdegkd6JbPsXqShpvEOHfAT+nCNwQ== + +eastasianwidth@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb" + integrity sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA== + +electron-to-chromium@^1.5.263: + version "1.5.278" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.278.tgz#807a5e321f012a41bfd64e653f35993c9af95493" + integrity sha512-dQ0tM1svDRQOwxnXxm+twlGTjr9Upvt8UFWAgmLsxEzFQxhbti4VwxmMjsDxVC51Zo84swW7FVCXEV+VAkhuPw== + +elliptic@^6.6.1: + version "6.6.1" + resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.6.1.tgz#3b8ffb02670bf69e382c7f65bf524c97c5405c06" + integrity sha512-RaddvvMatK2LJHqFJ+YA4WysVN5Ita9E35botqIYspQ4TkRAlCicdzKOjlyv/1Za5RyTNn7di//eEV0uTAfe3g== + dependencies: + bn.js "^4.11.9" + brorand "^1.1.0" + hash.js "^1.0.0" + hmac-drbg "^1.0.1" + inherits "^2.0.4" + minimalistic-assert "^1.0.1" + minimalistic-crypto-utils "^1.0.1" + +emittery@^0.13.1: + version "0.13.1" + resolved "https://registry.yarnpkg.com/emittery/-/emittery-0.13.1.tgz#c04b8c3457490e0847ae51fced3af52d338e3dad" + integrity sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ== + +emoji-regex@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" + integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== + +emoji-regex@^9.2.2: + version "9.2.2" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72" + integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg== + +error-ex@^1.3.1: + version "1.3.4" + resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.4.tgz#b3a8d8bb6f92eecc1629e3e27d3c8607a8a32414" + integrity sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ== + dependencies: + is-arrayish "^0.2.1" + +escalade@^3.1.1, escalade@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.2.0.tgz#011a3f69856ba189dffa7dc8fcce99d2a87903e5" + integrity sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA== + +escape-string-regexp@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz#a30304e99daa32e23b2fd20f51babd07cffca344" + integrity sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w== + +esprima@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" + integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== + +ethers@^6.15.0: + version "6.16.0" + resolved "https://registry.yarnpkg.com/ethers/-/ethers-6.16.0.tgz#fff9b4f05d7a359c774ad6e91085a800f7fccf65" + integrity sha512-U1wulmetNymijEhpSEQ7Ct/P/Jw9/e7R1j5XIbPRydgV2DjLVMsULDlNksq3RQnFgKoLlZf88ijYtWEXcPa07A== + dependencies: + "@adraffy/ens-normalize" "1.10.1" + "@noble/curves" "1.2.0" + "@noble/hashes" "1.3.2" + "@types/node" "22.7.5" + aes-js "4.0.0-beta.5" + tslib "2.7.0" + ws "8.17.1" + +eventemitter3@5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-5.0.1.tgz#53f5ffd0a492ac800721bb42c66b841de96423c4" + integrity sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA== + +eventemitter3@^5.0.1: + version "5.0.4" + resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-5.0.4.tgz#a86d66170433712dde814707ac52b5271ceb1feb" + integrity sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw== + +execa@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd" + integrity sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg== + dependencies: + cross-spawn "^7.0.3" + get-stream "^6.0.0" + human-signals "^2.1.0" + is-stream "^2.0.0" + merge-stream "^2.0.0" + npm-run-path "^4.0.1" + onetime "^5.1.2" + signal-exit "^3.0.3" + strip-final-newline "^2.0.0" + +exit-x@^0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/exit-x/-/exit-x-0.2.2.tgz#1f9052de3b8d99a696b10dad5bced9bdd5c3aa64" + integrity sha512-+I6B/IkJc1o/2tiURyz/ivu/O0nKNEArIUB5O7zBrlDVJr22SCLH3xTeEry428LvFhRzIA1g8izguxJ/gbNcVQ== + +expect@30.2.0, expect@^30.0.0: + version "30.2.0" + resolved "https://registry.yarnpkg.com/expect/-/expect-30.2.0.tgz#d4013bed267013c14bc1199cec8aa57cee9b5869" + integrity sha512-u/feCi0GPsI+988gU2FLcsHyAHTU0MX1Wg68NhAnN7z/+C5wqG+CY8J53N9ioe8RXgaoz0nBR/TYMf3AycUuPw== + dependencies: + "@jest/expect-utils" "30.2.0" + "@jest/get-type" "30.1.0" + jest-matcher-utils "30.2.0" + jest-message-util "30.2.0" + jest-mock "30.2.0" + jest-util "30.2.0" + +fast-json-stable-stringify@2.x, fast-json-stable-stringify@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" + integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== + +fb-watchman@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/fb-watchman/-/fb-watchman-2.0.2.tgz#e9524ee6b5c77e9e5001af0f85f3adbb8623255c" + integrity sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA== + dependencies: + bser "2.1.1" + +fetch-blob@^3.1.2, fetch-blob@^3.1.4: + version "3.2.0" + resolved "https://registry.yarnpkg.com/fetch-blob/-/fetch-blob-3.2.0.tgz#f09b8d4bbd45adc6f0c20b7e787e793e309dcce9" + integrity sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ== + dependencies: + node-domexception "^1.0.0" + web-streams-polyfill "^3.0.3" + +fill-range@^7.1.1: + version "7.1.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292" + integrity sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg== + dependencies: + to-regex-range "^5.0.1" + +find-up@^4.0.0, find-up@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" + integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== + dependencies: + locate-path "^5.0.0" + path-exists "^4.0.0" + +foreground-child@^3.1.0: + version "3.3.1" + resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-3.3.1.tgz#32e8e9ed1b68a3497befb9ac2b6adf92a638576f" + integrity sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw== + dependencies: + cross-spawn "^7.0.6" + signal-exit "^4.0.1" + +formdata-polyfill@^4.0.10: + version "4.0.10" + resolved "https://registry.yarnpkg.com/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz#24807c31c9d402e002ab3d8c720144ceb8848423" + integrity sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g== + dependencies: + fetch-blob "^3.1.2" + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== + +fsevents@^2.3.3: + version "2.3.3" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" + integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== + +gensync@^1.0.0-beta.2: + version "1.0.0-beta.2" + resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" + integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== + +get-caller-file@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" + integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== + +get-package-type@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/get-package-type/-/get-package-type-0.1.0.tgz#8de2d803cff44df3bc6c456e6668b36c3926e11a" + integrity sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q== + +get-stream@^6.0.0: + version "6.0.1" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7" + integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg== + +glob@^10.3.10: + version "10.5.0" + resolved "https://registry.yarnpkg.com/glob/-/glob-10.5.0.tgz#8ec0355919cd3338c28428a23d4f24ecc5fe738c" + integrity sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg== + dependencies: + foreground-child "^3.1.0" + jackspeak "^3.1.2" + minimatch "^9.0.4" + minipass "^7.1.2" + package-json-from-dist "^1.0.0" + path-scurry "^1.11.1" + +glob@^7.1.4: + version "7.2.3" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" + integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.1.1" + once "^1.3.0" + path-is-absolute "^1.0.0" + +graceful-fs@^4.2.11: + version "4.2.11" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" + integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== + +handlebars@^4.7.8: + version "4.7.8" + resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.7.8.tgz#41c42c18b1be2365439188c77c6afae71c0cd9e9" + integrity sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ== + dependencies: + minimist "^1.2.5" + neo-async "^2.6.2" + source-map "^0.6.1" + wordwrap "^1.0.0" + optionalDependencies: + uglify-js "^3.1.4" + +has-flag@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" + integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== + +hash.js@^1.0.0, hash.js@^1.0.3: + version "1.1.7" + resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.7.tgz#0babca538e8d4ee4a0f8988d68866537a003cf42" + integrity sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA== + dependencies: + inherits "^2.0.3" + minimalistic-assert "^1.0.1" + +hmac-drbg@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" + integrity sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg== + dependencies: + hash.js "^1.0.3" + minimalistic-assert "^1.0.0" + minimalistic-crypto-utils "^1.0.1" + +html-escaper@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453" + integrity sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg== + +human-signals@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" + integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw== + +import-local@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/import-local/-/import-local-3.2.0.tgz#c3d5c745798c02a6f8b897726aba5100186ee260" + integrity sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA== + dependencies: + pkg-dir "^4.2.0" + resolve-cwd "^3.0.0" + +imurmurhash@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" + integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA== + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2, inherits@^2.0.3, inherits@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + +is-arrayish@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" + integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg== + +is-fullwidth-code-point@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" + integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== + +is-generator-fn@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-generator-fn/-/is-generator-fn-2.1.0.tgz#7d140adc389aaf3011a8f2a2a4cfa6faadffb118" + integrity sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ== + +is-number@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" + integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== + +is-stream@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077" + integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg== + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== + +isows@1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/isows/-/isows-1.0.7.tgz#1c06400b7eed216fbba3bcbd68f12490fc342915" + integrity sha512-I1fSfDCZL5P0v33sVqeTDSpcstAg/N+wF5HS033mogOVIp4B+oHC7oOCsA3axAbBSGTJ8QubbNmnIRN/h8U7hg== + +istanbul-lib-coverage@^3.0.0, istanbul-lib-coverage@^3.2.0: + version "3.2.2" + resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz#2d166c4b0644d43a39f04bf6c2edd1e585f31756" + integrity sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg== + +istanbul-lib-instrument@^6.0.0, istanbul-lib-instrument@^6.0.2: + version "6.0.3" + resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.3.tgz#fa15401df6c15874bcb2105f773325d78c666765" + integrity sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q== + dependencies: + "@babel/core" "^7.23.9" + "@babel/parser" "^7.23.9" + "@istanbuljs/schema" "^0.1.3" + istanbul-lib-coverage "^3.2.0" + semver "^7.5.4" + +istanbul-lib-report@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz#908305bac9a5bd175ac6a74489eafd0fc2445a7d" + integrity sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw== + dependencies: + istanbul-lib-coverage "^3.0.0" + make-dir "^4.0.0" + supports-color "^7.1.0" + +istanbul-lib-source-maps@^5.0.0: + version "5.0.6" + resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-5.0.6.tgz#acaef948df7747c8eb5fbf1265cb980f6353a441" + integrity sha512-yg2d+Em4KizZC5niWhQaIomgf5WlL4vOOjZ5xGCmF8SnPE/mDWWXgvRExdcpCgh9lLRRa1/fSYp2ymmbJ1pI+A== + dependencies: + "@jridgewell/trace-mapping" "^0.3.23" + debug "^4.1.1" + istanbul-lib-coverage "^3.0.0" + +istanbul-reports@^3.1.3: + version "3.2.0" + resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-3.2.0.tgz#cb4535162b5784aa623cee21a7252cf2c807ac93" + integrity sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA== + dependencies: + html-escaper "^2.0.0" + istanbul-lib-report "^3.0.0" + +jackspeak@^3.1.2: + version "3.4.3" + resolved "https://registry.yarnpkg.com/jackspeak/-/jackspeak-3.4.3.tgz#8833a9d89ab4acde6188942bd1c53b6390ed5a8a" + integrity sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw== + dependencies: + "@isaacs/cliui" "^8.0.2" + optionalDependencies: + "@pkgjs/parseargs" "^0.11.0" + +jest-changed-files@30.2.0: + version "30.2.0" + resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-30.2.0.tgz#602266e478ed554e1e1469944faa7efd37cee61c" + integrity sha512-L8lR1ChrRnSdfeOvTrwZMlnWV8G/LLjQ0nG9MBclwWZidA2N5FviRki0Bvh20WRMOX31/JYvzdqTJrk5oBdydQ== + dependencies: + execa "^5.1.1" + jest-util "30.2.0" + p-limit "^3.1.0" + +jest-circus@30.2.0: + version "30.2.0" + resolved "https://registry.yarnpkg.com/jest-circus/-/jest-circus-30.2.0.tgz#98b8198b958748a2f322354311023d1d02e7603f" + integrity sha512-Fh0096NC3ZkFx05EP2OXCxJAREVxj1BcW/i6EWqqymcgYKWjyyDpral3fMxVcHXg6oZM7iULer9wGRFvfpl+Tg== + dependencies: + "@jest/environment" "30.2.0" + "@jest/expect" "30.2.0" + "@jest/test-result" "30.2.0" + "@jest/types" "30.2.0" + "@types/node" "*" + chalk "^4.1.2" + co "^4.6.0" + dedent "^1.6.0" + is-generator-fn "^2.1.0" + jest-each "30.2.0" + jest-matcher-utils "30.2.0" + jest-message-util "30.2.0" + jest-runtime "30.2.0" + jest-snapshot "30.2.0" + jest-util "30.2.0" + p-limit "^3.1.0" + pretty-format "30.2.0" + pure-rand "^7.0.0" + slash "^3.0.0" + stack-utils "^2.0.6" + +jest-cli@30.2.0: + version "30.2.0" + resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-30.2.0.tgz#1780f8e9d66bf84a10b369aea60aeda7697dcc67" + integrity sha512-Os9ukIvADX/A9sLt6Zse3+nmHtHaE6hqOsjQtNiugFTbKRHYIYtZXNGNK9NChseXy7djFPjndX1tL0sCTlfpAA== + dependencies: + "@jest/core" "30.2.0" + "@jest/test-result" "30.2.0" + "@jest/types" "30.2.0" + chalk "^4.1.2" + exit-x "^0.2.2" + import-local "^3.2.0" + jest-config "30.2.0" + jest-util "30.2.0" + jest-validate "30.2.0" + yargs "^17.7.2" + +jest-config@30.2.0: + version "30.2.0" + resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-30.2.0.tgz#29df8c50e2ad801cc59c406b50176c18c362a90b" + integrity sha512-g4WkyzFQVWHtu6uqGmQR4CQxz/CH3yDSlhzXMWzNjDx843gYjReZnMRanjRCq5XZFuQrGDxgUaiYWE8BRfVckA== + dependencies: + "@babel/core" "^7.27.4" + "@jest/get-type" "30.1.0" + "@jest/pattern" "30.0.1" + "@jest/test-sequencer" "30.2.0" + "@jest/types" "30.2.0" + babel-jest "30.2.0" + chalk "^4.1.2" + ci-info "^4.2.0" + deepmerge "^4.3.1" + glob "^10.3.10" + graceful-fs "^4.2.11" + jest-circus "30.2.0" + jest-docblock "30.2.0" + jest-environment-node "30.2.0" + jest-regex-util "30.0.1" + jest-resolve "30.2.0" + jest-runner "30.2.0" + jest-util "30.2.0" + jest-validate "30.2.0" + micromatch "^4.0.8" + parse-json "^5.2.0" + pretty-format "30.2.0" + slash "^3.0.0" + strip-json-comments "^3.1.1" + +jest-diff@30.2.0: + version "30.2.0" + resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-30.2.0.tgz#e3ec3a6ea5c5747f605c9e874f83d756cba36825" + integrity sha512-dQHFo3Pt4/NLlG5z4PxZ/3yZTZ1C7s9hveiOj+GCN+uT109NC2QgsoVZsVOAvbJ3RgKkvyLGXZV9+piDpWbm6A== + dependencies: + "@jest/diff-sequences" "30.0.1" + "@jest/get-type" "30.1.0" + chalk "^4.1.2" + pretty-format "30.2.0" + +jest-docblock@30.2.0: + version "30.2.0" + resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-30.2.0.tgz#42cd98d69f887e531c7352309542b1ce4ee10256" + integrity sha512-tR/FFgZKS1CXluOQzZvNH3+0z9jXr3ldGSD8bhyuxvlVUwbeLOGynkunvlTMxchC5urrKndYiwCFC0DLVjpOCA== + dependencies: + detect-newline "^3.1.0" + +jest-each@30.2.0: + version "30.2.0" + resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-30.2.0.tgz#39e623ae71641c2ac3ee69b3ba3d258fce8e768d" + integrity sha512-lpWlJlM7bCUf1mfmuqTA8+j2lNURW9eNafOy99knBM01i5CQeY5UH1vZjgT9071nDJac1M4XsbyI44oNOdhlDQ== + dependencies: + "@jest/get-type" "30.1.0" + "@jest/types" "30.2.0" + chalk "^4.1.2" + jest-util "30.2.0" + pretty-format "30.2.0" + +jest-environment-node@30.2.0: + version "30.2.0" + resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-30.2.0.tgz#3def7980ebd2fd86e74efd4d2e681f55ab38da0f" + integrity sha512-ElU8v92QJ9UrYsKrxDIKCxu6PfNj4Hdcktcn0JX12zqNdqWHB0N+hwOnnBBXvjLd2vApZtuLUGs1QSY+MsXoNA== + dependencies: + "@jest/environment" "30.2.0" + "@jest/fake-timers" "30.2.0" + "@jest/types" "30.2.0" + "@types/node" "*" + jest-mock "30.2.0" + jest-util "30.2.0" + jest-validate "30.2.0" + +jest-haste-map@30.2.0: + version "30.2.0" + resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-30.2.0.tgz#808e3889f288603ac70ff0ac047598345a66022e" + integrity sha512-sQA/jCb9kNt+neM0anSj6eZhLZUIhQgwDt7cPGjumgLM4rXsfb9kpnlacmvZz3Q5tb80nS+oG/if+NBKrHC+Xw== + dependencies: + "@jest/types" "30.2.0" + "@types/node" "*" + anymatch "^3.1.3" + fb-watchman "^2.0.2" + graceful-fs "^4.2.11" + jest-regex-util "30.0.1" + jest-util "30.2.0" + jest-worker "30.2.0" + micromatch "^4.0.8" + walker "^1.0.8" + optionalDependencies: + fsevents "^2.3.3" + +jest-leak-detector@30.2.0: + version "30.2.0" + resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-30.2.0.tgz#292fdca7b7c9cf594e1e570ace140b01d8beb736" + integrity sha512-M6jKAjyzjHG0SrQgwhgZGy9hFazcudwCNovY/9HPIicmNSBuockPSedAP9vlPK6ONFJ1zfyH/M2/YYJxOz5cdQ== + dependencies: + "@jest/get-type" "30.1.0" + pretty-format "30.2.0" + +jest-matcher-utils@30.2.0: + version "30.2.0" + resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-30.2.0.tgz#69a0d4c271066559ec8b0d8174829adc3f23a783" + integrity sha512-dQ94Nq4dbzmUWkQ0ANAWS9tBRfqCrn0bV9AMYdOi/MHW726xn7eQmMeRTpX2ViC00bpNaWXq+7o4lIQ3AX13Hg== + dependencies: + "@jest/get-type" "30.1.0" + chalk "^4.1.2" + jest-diff "30.2.0" + pretty-format "30.2.0" + +jest-message-util@30.2.0: + version "30.2.0" + resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-30.2.0.tgz#fc97bf90d11f118b31e6131e2b67fc4f39f92152" + integrity sha512-y4DKFLZ2y6DxTWD4cDe07RglV88ZiNEdlRfGtqahfbIjfsw1nMCPx49Uev4IA/hWn3sDKyAnSPwoYSsAEdcimw== + dependencies: + "@babel/code-frame" "^7.27.1" + "@jest/types" "30.2.0" + "@types/stack-utils" "^2.0.3" + chalk "^4.1.2" + graceful-fs "^4.2.11" + micromatch "^4.0.8" + pretty-format "30.2.0" + slash "^3.0.0" + stack-utils "^2.0.6" + +jest-mock@30.2.0: + version "30.2.0" + resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-30.2.0.tgz#69f991614eeb4060189459d3584f710845bff45e" + integrity sha512-JNNNl2rj4b5ICpmAcq+WbLH83XswjPbjH4T7yvGzfAGCPh1rw+xVNbtk+FnRslvt9lkCcdn9i1oAoKUuFsOxRw== + dependencies: + "@jest/types" "30.2.0" + "@types/node" "*" + jest-util "30.2.0" + +jest-pnp-resolver@^1.2.3: + version "1.2.3" + resolved "https://registry.yarnpkg.com/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz#930b1546164d4ad5937d5540e711d4d38d4cad2e" + integrity sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w== + +jest-regex-util@30.0.1: + version "30.0.1" + resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-30.0.1.tgz#f17c1de3958b67dfe485354f5a10093298f2a49b" + integrity sha512-jHEQgBXAgc+Gh4g0p3bCevgRCVRkB4VB70zhoAE48gxeSr1hfUOsM/C2WoJgVL7Eyg//hudYENbm3Ne+/dRVVA== + +jest-resolve-dependencies@30.2.0: + version "30.2.0" + resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-30.2.0.tgz#3370e2c0b49cc560f6a7e8ec3a59dd99525e1a55" + integrity sha512-xTOIGug/0RmIe3mmCqCT95yO0vj6JURrn1TKWlNbhiAefJRWINNPgwVkrVgt/YaerPzY3iItufd80v3lOrFJ2w== + dependencies: + jest-regex-util "30.0.1" + jest-snapshot "30.2.0" + +jest-resolve@30.2.0: + version "30.2.0" + resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-30.2.0.tgz#2e2009cbd61e8f1f003355d5ec87225412cebcd7" + integrity sha512-TCrHSxPlx3tBY3hWNtRQKbtgLhsXa1WmbJEqBlTBrGafd5fiQFByy2GNCEoGR+Tns8d15GaL9cxEzKOO3GEb2A== + dependencies: + chalk "^4.1.2" + graceful-fs "^4.2.11" + jest-haste-map "30.2.0" + jest-pnp-resolver "^1.2.3" + jest-util "30.2.0" + jest-validate "30.2.0" + slash "^3.0.0" + unrs-resolver "^1.7.11" + +jest-runner@30.2.0: + version "30.2.0" + resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-30.2.0.tgz#c62b4c3130afa661789705e13a07bdbcec26a114" + integrity sha512-PqvZ2B2XEyPEbclp+gV6KO/F1FIFSbIwewRgmROCMBo/aZ6J1w8Qypoj2pEOcg3G2HzLlaP6VUtvwCI8dM3oqQ== + dependencies: + "@jest/console" "30.2.0" + "@jest/environment" "30.2.0" + "@jest/test-result" "30.2.0" + "@jest/transform" "30.2.0" + "@jest/types" "30.2.0" + "@types/node" "*" + chalk "^4.1.2" + emittery "^0.13.1" + exit-x "^0.2.2" + graceful-fs "^4.2.11" + jest-docblock "30.2.0" + jest-environment-node "30.2.0" + jest-haste-map "30.2.0" + jest-leak-detector "30.2.0" + jest-message-util "30.2.0" + jest-resolve "30.2.0" + jest-runtime "30.2.0" + jest-util "30.2.0" + jest-watcher "30.2.0" + jest-worker "30.2.0" + p-limit "^3.1.0" + source-map-support "0.5.13" + +jest-runtime@30.2.0: + version "30.2.0" + resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-30.2.0.tgz#395ea792cde048db1b0cd1a92dc9cb9f1921bf8a" + integrity sha512-p1+GVX/PJqTucvsmERPMgCPvQJpFt4hFbM+VN3n8TMo47decMUcJbt+rgzwrEme0MQUA/R+1de2axftTHkKckg== + dependencies: + "@jest/environment" "30.2.0" + "@jest/fake-timers" "30.2.0" + "@jest/globals" "30.2.0" + "@jest/source-map" "30.0.1" + "@jest/test-result" "30.2.0" + "@jest/transform" "30.2.0" + "@jest/types" "30.2.0" + "@types/node" "*" + chalk "^4.1.2" + cjs-module-lexer "^2.1.0" + collect-v8-coverage "^1.0.2" + glob "^10.3.10" + graceful-fs "^4.2.11" + jest-haste-map "30.2.0" + jest-message-util "30.2.0" + jest-mock "30.2.0" + jest-regex-util "30.0.1" + jest-resolve "30.2.0" + jest-snapshot "30.2.0" + jest-util "30.2.0" + slash "^3.0.0" + strip-bom "^4.0.0" + +jest-snapshot@30.2.0: + version "30.2.0" + resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-30.2.0.tgz#266fbbb4b95fc4665ce6f32f1f38eeb39f4e26d0" + integrity sha512-5WEtTy2jXPFypadKNpbNkZ72puZCa6UjSr/7djeecHWOu7iYhSXSnHScT8wBz3Rn8Ena5d5RYRcsyKIeqG1IyA== + dependencies: + "@babel/core" "^7.27.4" + "@babel/generator" "^7.27.5" + "@babel/plugin-syntax-jsx" "^7.27.1" + "@babel/plugin-syntax-typescript" "^7.27.1" + "@babel/types" "^7.27.3" + "@jest/expect-utils" "30.2.0" + "@jest/get-type" "30.1.0" + "@jest/snapshot-utils" "30.2.0" + "@jest/transform" "30.2.0" + "@jest/types" "30.2.0" + babel-preset-current-node-syntax "^1.2.0" + chalk "^4.1.2" + expect "30.2.0" + graceful-fs "^4.2.11" + jest-diff "30.2.0" + jest-matcher-utils "30.2.0" + jest-message-util "30.2.0" + jest-util "30.2.0" + pretty-format "30.2.0" + semver "^7.7.2" + synckit "^0.11.8" + +jest-util@30.2.0: + version "30.2.0" + resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-30.2.0.tgz#5142adbcad6f4e53c2776c067a4db3c14f913705" + integrity sha512-QKNsM0o3Xe6ISQU869e+DhG+4CK/48aHYdJZGlFQVTjnbvgpcKyxpzk29fGiO7i/J8VENZ+d2iGnSsvmuHywlA== + dependencies: + "@jest/types" "30.2.0" + "@types/node" "*" + chalk "^4.1.2" + ci-info "^4.2.0" + graceful-fs "^4.2.11" + picomatch "^4.0.2" + +jest-validate@30.2.0: + version "30.2.0" + resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-30.2.0.tgz#273eaaed4c0963b934b5b31e96289edda6e0a2ef" + integrity sha512-FBGWi7dP2hpdi8nBoWxSsLvBFewKAg0+uSQwBaof4Y4DPgBabXgpSYC5/lR7VmnIlSpASmCi/ntRWPbv7089Pw== + dependencies: + "@jest/get-type" "30.1.0" + "@jest/types" "30.2.0" + camelcase "^6.3.0" + chalk "^4.1.2" + leven "^3.1.0" + pretty-format "30.2.0" + +jest-watcher@30.2.0: + version "30.2.0" + resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-30.2.0.tgz#f9c055de48e18c979e7756a3917e596e2d69b07b" + integrity sha512-PYxa28dxJ9g777pGm/7PrbnMeA0Jr7osHP9bS7eJy9DuAjMgdGtxgf0uKMyoIsTWAkIbUW5hSDdJ3urmgXBqxg== + dependencies: + "@jest/test-result" "30.2.0" + "@jest/types" "30.2.0" + "@types/node" "*" + ansi-escapes "^4.3.2" + chalk "^4.1.2" + emittery "^0.13.1" + jest-util "30.2.0" + string-length "^4.0.2" + +jest-worker@30.2.0: + version "30.2.0" + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-30.2.0.tgz#fd5c2a36ff6058ec8f74366ec89538cc99539d26" + integrity sha512-0Q4Uk8WF7BUwqXHuAjc23vmopWJw5WH7w2tqBoUOZpOjW/ZnR44GXXd1r82RvnmI2GZge3ivrYXk/BE2+VtW2g== + dependencies: + "@types/node" "*" + "@ungap/structured-clone" "^1.3.0" + jest-util "30.2.0" + merge-stream "^2.0.0" + supports-color "^8.1.1" + +jest@^30.1.3: + version "30.2.0" + resolved "https://registry.yarnpkg.com/jest/-/jest-30.2.0.tgz#9f0a71e734af968f26952b5ae4b724af82681630" + integrity sha512-F26gjC0yWN8uAA5m5Ss8ZQf5nDHWGlN/xWZIh8S5SRbsEKBovwZhxGd6LJlbZYxBgCYOtreSUyb8hpXyGC5O4A== + dependencies: + "@jest/core" "30.2.0" + "@jest/types" "30.2.0" + import-local "^3.2.0" + jest-cli "30.2.0" + +js-tokens@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" + integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== + +js-yaml@^3.13.1: + version "3.14.2" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.2.tgz#77485ce1dd7f33c061fd1b16ecea23b55fcb04b0" + integrity sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg== + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" + +jsesc@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-3.1.0.tgz#74d335a234f67ed19907fdadfac7ccf9d409825d" + integrity sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA== + +json-parse-even-better-errors@^2.3.0: + version "2.3.1" + resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" + integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== + +json-stringify-safe@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" + integrity sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA== + +json5@^2.2.3: + version "2.2.3" + resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" + integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== + +leven@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2" + integrity sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A== + +lines-and-columns@^1.1.6: + version "1.2.4" + resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" + integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== + +locate-path@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" + integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== + dependencies: + p-locate "^4.1.0" + +lodash.memoize@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" + integrity sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag== + +lru-cache@^10.2.0: + version "10.4.3" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.4.3.tgz#410fc8a17b70e598013df257c2446b7f3383f119" + integrity sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ== + +lru-cache@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" + integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w== + dependencies: + yallist "^3.0.2" + +make-dir@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-4.0.0.tgz#c3c2307a771277cd9638305f915c29ae741b614e" + integrity sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw== + dependencies: + semver "^7.5.3" + +make-error@^1.1.1, make-error@^1.3.6: + version "1.3.6" + resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" + integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== + +makeerror@1.0.12: + version "1.0.12" + resolved "https://registry.yarnpkg.com/makeerror/-/makeerror-1.0.12.tgz#3e5dd2079a82e812e983cc6610c4a2cb0eaa801a" + integrity sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg== + dependencies: + tmpl "1.0.5" + +merge-stream@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" + integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== + +micromatch@^4.0.8: + version "4.0.8" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.8.tgz#d66fa18f3a47076789320b9b1af32bd86d9fa202" + integrity sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA== + dependencies: + braces "^3.0.3" + picomatch "^2.3.1" + +mimic-fn@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" + integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== + +minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" + integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== + +minimalistic-crypto-utils@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" + integrity sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg== + +minimatch@^3.0.4, minimatch@^3.1.1: + version "3.1.2" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" + integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== + dependencies: + brace-expansion "^1.1.7" + +minimatch@^9.0.4: + version "9.0.5" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.5.tgz#d74f9dd6b57d83d8e98cfb82133b03978bc929e5" + integrity sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow== + dependencies: + brace-expansion "^2.0.1" + +minimist@^1.2.5: + version "1.2.8" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" + integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== + +"minipass@^5.0.0 || ^6.0.2 || ^7.0.0", minipass@^7.1.2: + version "7.1.2" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-7.1.2.tgz#93a9626ce5e5e66bd4db86849e7515e92340a707" + integrity sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw== + +mock-socket@^9.3.1: + version "9.3.1" + resolved "https://registry.yarnpkg.com/mock-socket/-/mock-socket-9.3.1.tgz#24fb00c2f573c84812aa4a24181bb025de80cc8e" + integrity sha512-qxBgB7Qa2sEQgHFjj0dSigq7fX4k6Saisd5Nelwp2q8mlbAFh5dHV9JTTlF8viYJLSSWgMCZFUom8PJcMNBoJw== + +ms@^2.1.3: + version "2.1.3" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" + integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== + +napi-postinstall@^0.3.0: + version "0.3.4" + resolved "https://registry.yarnpkg.com/napi-postinstall/-/napi-postinstall-0.3.4.tgz#7af256d6588b5f8e952b9190965d6b019653bbb9" + integrity sha512-PHI5f1O0EP5xJ9gQmFGMS6IZcrVvTjpXjz7Na41gTE7eE2hK11lg04CECCYEEjdc17EV4DO+fkGEtt7TpTaTiQ== + +natural-compare@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" + integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== + +neo-async@^2.6.2: + version "2.6.2" + resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" + integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== + +nock@^13.5.5: + version "13.5.6" + resolved "https://registry.yarnpkg.com/nock/-/nock-13.5.6.tgz#5e693ec2300bbf603b61dae6df0225673e6c4997" + integrity sha512-o2zOYiCpzRqSzPj0Zt/dQ/DqZeYoaQ7TUonc/xUPjCGl9WeHpNbxgVvOquXYAaJzI0M9BXV3HTzG0p8IUAbBTQ== + dependencies: + debug "^4.1.0" + json-stringify-safe "^5.0.1" + propagate "^2.0.0" + +node-domexception@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/node-domexception/-/node-domexception-1.0.0.tgz#6888db46a1f71c0b76b3f7555016b63fe64766e5" + integrity sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ== + +node-fetch@^3.3.2: + version "3.3.2" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-3.3.2.tgz#d1e889bacdf733b4ff3b2b243eb7a12866a0b78b" + integrity sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA== + dependencies: + data-uri-to-buffer "^4.0.0" + fetch-blob "^3.1.4" + formdata-polyfill "^4.0.10" + +node-int64@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" + integrity sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw== + +node-releases@^2.0.27: + version "2.0.27" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.27.tgz#eedca519205cf20f650f61d56b070db111231e4e" + integrity sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA== + +normalize-path@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" + integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== + +npm-run-path@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea" + integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw== + dependencies: + path-key "^3.0.0" + +once@^1.3.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== + dependencies: + wrappy "1" + +onetime@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" + integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== + dependencies: + mimic-fn "^2.1.0" + +ox@0.11.3: + version "0.11.3" + resolved "https://registry.yarnpkg.com/ox/-/ox-0.11.3.tgz#f50be1cae88822f5111b1e3f4a324c4c07eed422" + integrity sha512-1bWYGk/xZel3xro3l8WGg6eq4YEKlaqvyMtVhfMFpbJzK2F6rj4EDRtqDCWVEJMkzcmEi9uW2QxsqELokOlarw== + dependencies: + "@adraffy/ens-normalize" "^1.11.0" + "@noble/ciphers" "^1.3.0" + "@noble/curves" "1.9.1" + "@noble/hashes" "^1.8.0" + "@scure/bip32" "^1.7.0" + "@scure/bip39" "^1.6.0" + abitype "^1.2.3" + eventemitter3 "5.0.1" + +p-limit@^2.2.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" + integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== + dependencies: + p-try "^2.0.0" + +p-limit@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" + integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== + dependencies: + yocto-queue "^0.1.0" + +p-locate@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" + integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== + dependencies: + p-limit "^2.2.0" + +p-try@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" + integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== + +package-json-from-dist@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz#4f1471a010827a86f94cfd9b0727e36d267de505" + integrity sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw== + +parse-json@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd" + integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg== + dependencies: + "@babel/code-frame" "^7.0.0" + error-ex "^1.3.1" + json-parse-even-better-errors "^2.3.0" + lines-and-columns "^1.1.6" + +path-exists@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" + integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== + +path-is-absolute@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== + +path-key@^3.0.0, path-key@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" + integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== + +path-scurry@^1.11.1: + version "1.11.1" + resolved "https://registry.yarnpkg.com/path-scurry/-/path-scurry-1.11.1.tgz#7960a668888594a0720b12a911d1a742ab9f11d2" + integrity sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA== + dependencies: + lru-cache "^10.2.0" + minipass "^5.0.0 || ^6.0.2 || ^7.0.0" + +picocolors@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.1.1.tgz#3d321af3eab939b083c8f929a1d12cda81c26b6b" + integrity sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA== + +picomatch@^2.0.4, picomatch@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" + integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== + +picomatch@^4.0.2: + version "4.0.3" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-4.0.3.tgz#796c76136d1eead715db1e7bad785dedd695a042" + integrity sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q== + +pirates@^4.0.7: + version "4.0.7" + resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.7.tgz#643b4a18c4257c8a65104b73f3049ce9a0a15e22" + integrity sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA== + +pkg-dir@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" + integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ== + dependencies: + find-up "^4.0.0" + +pretty-format@30.2.0, pretty-format@^30.0.0: + version "30.2.0" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-30.2.0.tgz#2d44fe6134529aed18506f6d11509d8a62775ebe" + integrity sha512-9uBdv/B4EefsuAL+pWqueZyZS2Ba+LxfFeQ9DN14HU4bN8bhaxKdkpjpB6fs9+pSjIBu+FXQHImEg8j/Lw0+vA== + dependencies: + "@jest/schemas" "30.0.5" + ansi-styles "^5.2.0" + react-is "^18.3.1" + +propagate@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/propagate/-/propagate-2.0.1.tgz#40cdedab18085c792334e64f0ac17256d38f9a45" + integrity sha512-vGrhOavPSTz4QVNuBNdcNXePNdNMaO1xj9yBeH1ScQPjk/rhg9sSlCXPhMkFuaNNW/syTvYqsnbIJxMBfRbbag== + +pure-rand@^7.0.0: + version "7.0.1" + resolved "https://registry.yarnpkg.com/pure-rand/-/pure-rand-7.0.1.tgz#6f53a5a9e3e4a47445822af96821ca509ed37566" + integrity sha512-oTUZM/NAZS8p7ANR3SHh30kXB+zK2r2BPcEn/awJIbOvq82WoMN4p62AWWp3Hhw50G0xMsw1mhIBLqHw64EcNQ== + +react-is@^18.3.1: + version "18.3.1" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.3.1.tgz#e83557dc12eae63a99e003a46388b1dcbb44db7e" + integrity sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg== + +require-directory@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== + +resolve-cwd@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-3.0.0.tgz#0f0075f1bb2544766cf73ba6a6e2adfebcb13f2d" + integrity sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg== + dependencies: + resolve-from "^5.0.0" + +resolve-from@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" + integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== + +rxjs@^7.8.1: + version "7.8.2" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.8.2.tgz#955bc473ed8af11a002a2be52071bf475638607b" + integrity sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA== + dependencies: + tslib "^2.1.0" + +scale-ts@^1.6.0: + version "1.6.1" + resolved "https://registry.yarnpkg.com/scale-ts/-/scale-ts-1.6.1.tgz#45151e156d6c04792223c39d8e7484ce926445f2" + integrity sha512-PBMc2AWc6wSEqJYBDPcyCLUj9/tMKnLX70jLOSndMtcUoLQucP/DM0vnQo1wJAYjTrQiq8iG9rD0q6wFzgjH7g== + +semver@^6.3.1: + version "6.3.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" + integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== + +semver@^7.5.3, semver@^7.5.4, semver@^7.7.2, semver@^7.7.3: + version "7.7.3" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.7.3.tgz#4b5f4143d007633a8dc671cd0a6ef9147b8bb946" + integrity sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q== + +shebang-command@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" + integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== + dependencies: + shebang-regex "^3.0.0" + +shebang-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" + integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== + +signal-exit@^3.0.3: + version "3.0.7" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" + integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== + +signal-exit@^4.0.1: + version "4.1.0" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-4.1.0.tgz#952188c1cbd546070e2dd20d0f41c0ae0530cb04" + integrity sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw== + +slash@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" + integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== + +smoldot@2.0.26: + version "2.0.26" + resolved "https://registry.yarnpkg.com/smoldot/-/smoldot-2.0.26.tgz#0e64c7fcd26240fbe4c8d6b6e4b9a9aca77e00f6" + integrity sha512-F+qYmH4z2s2FK+CxGj8moYcd1ekSIKH8ywkdqlOz88Dat35iB1DIYL11aILN46YSGMzQW/lbJNS307zBSDN5Ig== + dependencies: + ws "^8.8.1" + +source-map-support@0.5.13: + version "0.5.13" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.13.tgz#31b24a9c2e73c2de85066c0feb7d44767ed52932" + integrity sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w== + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + +source-map@^0.6.0, source-map@^0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== + +sprintf-js@~1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" + integrity sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g== + +stack-utils@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-2.0.6.tgz#aaf0748169c02fc33c8232abccf933f54a1cc34f" + integrity sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ== + dependencies: + escape-string-regexp "^2.0.0" + +string-length@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/string-length/-/string-length-4.0.2.tgz#a8a8dc7bd5c1a82b9b3c8b87e125f66871b6e57a" + integrity sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ== + dependencies: + char-regex "^1.0.2" + strip-ansi "^6.0.0" + +"string-width-cjs@npm:string-width@^4.2.0": + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +string-width@^5.0.1, string-width@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794" + integrity sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA== + dependencies: + eastasianwidth "^0.2.0" + emoji-regex "^9.2.2" + strip-ansi "^7.0.1" + +"strip-ansi-cjs@npm:strip-ansi@^6.0.1": + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + +strip-ansi@^6.0.0, strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + +strip-ansi@^7.0.1: + version "7.1.2" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.2.tgz#132875abde678c7ea8d691533f2e7e22bb744dba" + integrity sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA== + dependencies: + ansi-regex "^6.0.1" + +strip-bom@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-4.0.0.tgz#9c3505c1db45bcedca3d9cf7a16f5c5aa3901878" + integrity sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w== + +strip-final-newline@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" + integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== + +strip-json-comments@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" + integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== + +supports-color@^7.1.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" + integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== + dependencies: + has-flag "^4.0.0" + +supports-color@^8.1.1: + version "8.1.1" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" + integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== + dependencies: + has-flag "^4.0.0" + +synckit@^0.11.8: + version "0.11.12" + resolved "https://registry.yarnpkg.com/synckit/-/synckit-0.11.12.tgz#abe74124264fbc00a48011b0d98bdc1cffb64a7b" + integrity sha512-Bh7QjT8/SuKUIfObSXNHNSK6WHo6J1tHCqJsuaFDP7gP0fkzSfTxI8y85JrppZ0h8l0maIgc2tfuZQ6/t3GtnQ== + dependencies: + "@pkgr/core" "^0.2.9" + +test-exclude@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-6.0.0.tgz#04a8698661d805ea6fa293b6cb9e63ac044ef15e" + integrity sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w== + dependencies: + "@istanbuljs/schema" "^0.1.2" + glob "^7.1.4" + minimatch "^3.0.4" + +tmpl@1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.5.tgz#8683e0b902bb9c20c4f726e3c0b69f36518c07cc" + integrity sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw== + +to-regex-range@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" + integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== + dependencies: + is-number "^7.0.0" + +ts-jest@^29.4.4: + version "29.4.6" + resolved "https://registry.yarnpkg.com/ts-jest/-/ts-jest-29.4.6.tgz#51cb7c133f227396818b71297ad7409bb77106e9" + integrity sha512-fSpWtOO/1AjSNQguk43hb/JCo16oJDnMJf3CdEGNkqsEX3t0KX96xvyX1D7PfLCpVoKu4MfVrqUkFyblYoY4lA== + dependencies: + bs-logger "^0.2.6" + fast-json-stable-stringify "^2.1.0" + handlebars "^4.7.8" + json5 "^2.2.3" + lodash.memoize "^4.1.2" + make-error "^1.3.6" + semver "^7.7.3" + type-fest "^4.41.0" + yargs-parser "^21.1.1" + +ts-node@^10.9.2: + version "10.9.2" + resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.9.2.tgz#70f021c9e185bccdca820e26dc413805c101c71f" + integrity sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ== + dependencies: + "@cspotcode/source-map-support" "^0.8.0" + "@tsconfig/node10" "^1.0.7" + "@tsconfig/node12" "^1.0.7" + "@tsconfig/node14" "^1.0.0" + "@tsconfig/node16" "^1.0.2" + acorn "^8.4.1" + acorn-walk "^8.1.1" + arg "^4.1.0" + create-require "^1.1.0" + diff "^4.0.1" + make-error "^1.1.1" + v8-compile-cache-lib "^3.0.1" + yn "3.1.1" + +tslib@2.7.0: + version "2.7.0" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.7.0.tgz#d9b40c5c40ab59e8738f297df3087bf1a2690c01" + integrity sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA== + +tslib@^2.1.0, tslib@^2.4.0, tslib@^2.6.2, tslib@^2.7.0, tslib@^2.8.0, tslib@^2.8.1: + version "2.8.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f" + integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w== + +type-detect@4.0.8: + version "4.0.8" + resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" + integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== + +type-fest@^0.21.3: + version "0.21.3" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37" + integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w== + +type-fest@^4.41.0: + version "4.41.0" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-4.41.0.tgz#6ae1c8e5731273c2bf1f58ad39cbae2c91a46c58" + integrity sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA== + +typescript@^5.3.3: + version "5.9.3" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.9.3.tgz#5b4f59e15310ab17a216f5d6cf53ee476ede670f" + integrity sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw== + +uglify-js@^3.1.4: + version "3.19.3" + resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.19.3.tgz#82315e9bbc6f2b25888858acd1fff8441035b77f" + integrity sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ== + +undici-types@~6.19.2: + version "6.19.8" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.19.8.tgz#35111c9d1437ab83a7cdc0abae2f26d88eda0a02" + integrity sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw== + +undici-types@~6.21.0: + version "6.21.0" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.21.0.tgz#691d00af3909be93a7faa13be61b3a5b50ef12cb" + integrity sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ== + +undici-types@~7.16.0: + version "7.16.0" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-7.16.0.tgz#ffccdff36aea4884cbfce9a750a0580224f58a46" + integrity sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw== + +unrs-resolver@^1.7.11: + version "1.11.1" + resolved "https://registry.yarnpkg.com/unrs-resolver/-/unrs-resolver-1.11.1.tgz#be9cd8686c99ef53ecb96df2a473c64d304048a9" + integrity sha512-bSjt9pjaEBnNiGgc9rUiHGKv5l4/TGzDmYw3RhnkJGtLhbnnA/5qJj7x3dNDCRx/PJxu774LlH8lCOlB4hEfKg== + dependencies: + napi-postinstall "^0.3.0" + optionalDependencies: + "@unrs/resolver-binding-android-arm-eabi" "1.11.1" + "@unrs/resolver-binding-android-arm64" "1.11.1" + "@unrs/resolver-binding-darwin-arm64" "1.11.1" + "@unrs/resolver-binding-darwin-x64" "1.11.1" + "@unrs/resolver-binding-freebsd-x64" "1.11.1" + "@unrs/resolver-binding-linux-arm-gnueabihf" "1.11.1" + "@unrs/resolver-binding-linux-arm-musleabihf" "1.11.1" + "@unrs/resolver-binding-linux-arm64-gnu" "1.11.1" + "@unrs/resolver-binding-linux-arm64-musl" "1.11.1" + "@unrs/resolver-binding-linux-ppc64-gnu" "1.11.1" + "@unrs/resolver-binding-linux-riscv64-gnu" "1.11.1" + "@unrs/resolver-binding-linux-riscv64-musl" "1.11.1" + "@unrs/resolver-binding-linux-s390x-gnu" "1.11.1" + "@unrs/resolver-binding-linux-x64-gnu" "1.11.1" + "@unrs/resolver-binding-linux-x64-musl" "1.11.1" + "@unrs/resolver-binding-wasm32-wasi" "1.11.1" + "@unrs/resolver-binding-win32-arm64-msvc" "1.11.1" + "@unrs/resolver-binding-win32-ia32-msvc" "1.11.1" + "@unrs/resolver-binding-win32-x64-msvc" "1.11.1" + +update-browserslist-db@^1.2.0: + version "1.2.3" + resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz#64d76db58713136acbeb4c49114366cc6cc2e80d" + integrity sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w== + dependencies: + escalade "^3.2.0" + picocolors "^1.1.1" + +v8-compile-cache-lib@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz#6336e8d71965cb3d35a1bbb7868445a7c05264bf" + integrity sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg== + +v8-to-istanbul@^9.0.1: + version "9.3.0" + resolved "https://registry.yarnpkg.com/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz#b9572abfa62bd556c16d75fdebc1a411d5ff3175" + integrity sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA== + dependencies: + "@jridgewell/trace-mapping" "^0.3.12" + "@types/istanbul-lib-coverage" "^2.0.1" + convert-source-map "^2.0.0" + +viem@^2.37.6: + version "2.44.4" + resolved "https://registry.yarnpkg.com/viem/-/viem-2.44.4.tgz#f749f038f9bd5a93b959319a35a1554803a09c2e" + integrity sha512-sJDLVl2EsS5Fo7GSWZME5CXEV7QRYkUJPeBw7ac+4XI3D4ydvMw/gjulTsT5pgqcpu70BploFnOAC6DLpan1Yg== + dependencies: + "@noble/curves" "1.9.1" + "@noble/hashes" "1.8.0" + "@scure/bip32" "1.7.0" + "@scure/bip39" "1.6.0" + abitype "1.2.3" + isows "1.0.7" + ox "0.11.3" + ws "8.18.3" + +walker@^1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/walker/-/walker-1.0.8.tgz#bd498db477afe573dc04185f011d3ab8a8d7653f" + integrity sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ== + dependencies: + makeerror "1.0.12" + +web-streams-polyfill@^3.0.3: + version "3.3.3" + resolved "https://registry.yarnpkg.com/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz#2073b91a2fdb1fbfbd401e7de0ac9f8214cecb4b" + integrity sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw== + +which@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" + integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== + dependencies: + isexe "^2.0.0" + +wordwrap@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" + integrity sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q== + +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + +wrap-ansi@^8.1.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" + integrity sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ== + dependencies: + ansi-styles "^6.1.0" + string-width "^5.0.1" + strip-ansi "^7.0.1" + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== + +write-file-atomic@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-5.0.1.tgz#68df4717c55c6fa4281a7860b4c2ba0a6d2b11e7" + integrity sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw== + dependencies: + imurmurhash "^0.1.4" + signal-exit "^4.0.1" + +ws@8.17.1: + version "8.17.1" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.17.1.tgz#9293da530bb548febc95371d90f9c878727d919b" + integrity sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ== + +ws@8.18.3: + version "8.18.3" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.18.3.tgz#b56b88abffde62791c639170400c93dcb0c95472" + integrity sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg== + +ws@^8.18.0, ws@^8.8.1: + version "8.19.0" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.19.0.tgz#ddc2bdfa5b9ad860204f5a72a4863a8895fd8c8b" + integrity sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg== + +y18n@^5.0.5: + version "5.0.8" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" + integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== + +yallist@^3.0.2: + version "3.1.1" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" + integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== + +yargs-parser@^21.1.1: + version "21.1.1" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35" + integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== + +yargs@^17.7.2: + version "17.7.2" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269" + integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w== + dependencies: + cliui "^8.0.1" + escalade "^3.1.1" + get-caller-file "^2.0.5" + require-directory "^2.1.1" + string-width "^4.2.3" + y18n "^5.0.5" + yargs-parser "^21.1.1" + +yn@3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50" + integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q== + +yocto-queue@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" + integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== diff --git a/signet-ts-client-scripts/check-mpc-chainid.ts b/signet-ts-client-scripts/check-mpc-chainid.ts new file mode 100644 index 0000000000..9f514bc676 --- /dev/null +++ b/signet-ts-client-scripts/check-mpc-chainid.ts @@ -0,0 +1,51 @@ +import { ethers } from 'ethers'; +import * as ecc from 'tiny-secp256k1'; + +const CONFIG = { + EPSILON_DERIVATION_PREFIX: 'sig.network v1.0.0 epsilon derivation', + SECP256K1_N: '0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141', +}; + +const MPC_ROOT_KEY = '0xf967622b74b7b619a0f4477118cf39c57c4a179a808526ac6fa1c41372512dad'; +const PALLET_SS58 = '13UVJyLnbVp6z97TrCZZCWMfADQddP3JkNruog9pbUF4Tomm'; +const ALICE_HEX_PATH = '0xd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d'; + +function derivePrivateKey(path: string, sender: string, basePrivateKey: string, chainId: string): string { + const derivationPath = `${CONFIG.EPSILON_DERIVATION_PREFIX},${chainId},${sender},${path}`; + console.log(` Derivation path: ${derivationPath}`); + const hash = ethers.keccak256(ethers.toUtf8Bytes(derivationPath)); + const epsilon = BigInt(hash); + const privateKeyBigInt = BigInt(basePrivateKey); + const derivedPrivateKey = (privateKeyBigInt + epsilon) % BigInt(CONFIG.SECP256K1_N); + return '0x' + derivedPrivateKey.toString(16).padStart(64, '0'); +} + +console.log('MPC shows derived private key starts with: 0x77921eab88...'); +console.log(''); + +// Try with different chainIds +const chainIds = [ + 'polkadot:2034', + 'bip122:000000000933ea01ad0ee984209779ba', + 'polkadot:2034', // without leading 0 +]; + +for (const chainId of chainIds) { + console.log(`\n--- ChainId: ${chainId} ---`); + const derivedKey = derivePrivateKey(ALICE_HEX_PATH, PALLET_SS58, MPC_ROOT_KEY, chainId); + console.log(` Derived key: ${derivedKey}`); + console.log(` Starts with 0x77921eab88: ${derivedKey.startsWith('0x77921eab88')}`); +} + +// Also try with the UTXO's scriptPubKey address to see if that gives us a clue +// The UTXO was at bcrt1qmr8q7udefh6e3mld7xpahh7g652pq3zurswrxz = d8ce0f71b94df598efedf183dbdfc8d51410445c + +// Try different orderings of parameters +console.log('\n--- Trying different parameter orderings ---'); + +// Maybe MPC uses path,sender instead of sender,path? +const altPath1 = `${CONFIG.EPSILON_DERIVATION_PREFIX},polkadot:2034,${ALICE_HEX_PATH},${PALLET_SS58}`; +console.log(`Path: ${altPath1}`); +const altHash1 = ethers.keccak256(ethers.toUtf8Bytes(altPath1)); +const altKey1 = (BigInt(MPC_ROOT_KEY) + BigInt(altHash1)) % BigInt(CONFIG.SECP256K1_N); +console.log(`Derived key: 0x${altKey1.toString(16).padStart(64, '0')}`); diff --git a/signet-ts-client-scripts/compare-derivations.ts b/signet-ts-client-scripts/compare-derivations.ts new file mode 100644 index 0000000000..661f66e3d9 --- /dev/null +++ b/signet-ts-client-scripts/compare-derivations.ts @@ -0,0 +1,59 @@ +import { ethers } from 'ethers'; +import * as ecc from 'tiny-secp256k1'; +import { ec as EC } from 'elliptic'; + +const EPSILON_PREFIX = "sig.network v1.0.0 epsilon derivation"; +const MPC_ROOT_KEY = '0xf967622b74b7b619a0f4477118cf39c57c4a179a808526ac6fa1c41372512dad'; +const ROOT_PUBLIC_KEY = "0x044eef776e4f257d68983e45b340c2e9546c5df95447900b6aadfec68fb46fdee257e26b8ba383ddba9914b33c60e869265f859566fff4baef283c54d821ca3b64"; +const PALLET_SS58 = '13UVJyLnbVp6z97TrCZZCWMfADQddP3JkNruog9pbUF4Tomm'; +const ALICE_HEX_PATH = '0xd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d'; +const CHAIN_ID = 'polkadot:2034'; +const SECP256K1_N = '0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141'; + +console.log('='.repeat(70)); +console.log('COMPARING DERIVATION METHODS'); +console.log('='.repeat(70)); +console.log(''); + +// Build derivation path +const derivationPath = `${EPSILON_PREFIX},${CHAIN_ID},${PALLET_SS58},${ALICE_HEX_PATH}`; +console.log('Derivation path:'); +console.log(` ${derivationPath}`); +console.log(''); + +// Compute epsilon hash +const hash = ethers.keccak256(ethers.toUtf8Bytes(derivationPath)); +console.log('Epsilon hash:', hash); +console.log(''); + +// Method 1: Test's KeyDerivation (public key point addition) +console.log('--- Method 1: Public key point addition (KeyDerivation) ---'); +const ec = new EC("secp256k1"); +const uncompressedRoot = ROOT_PUBLIC_KEY.slice(4); +const scalarHex = hash.slice(2); +const x = uncompressedRoot.substring(0, 64); +const y = uncompressedRoot.substring(64); +const oldPoint = ec.curve.point(x, y); +const scalarTimesG = ec.g.mul(scalarHex); +const newPoint = oldPoint.add(scalarTimesG); +const method1Pubkey = `04${newPoint.getX().toString(16).padStart(64, "0")}${newPoint.getY().toString(16).padStart(64, "0")}`; +const method1Compressed = newPoint.encode('hex', true); +console.log(' Compressed pubkey:', method1Compressed); + +// Method 2: MPC style (private key scalar addition) +console.log(''); +console.log('--- Method 2: Private key scalar addition (MPC style) ---'); +const epsilon = BigInt(hash); +const privateKeyBigInt = BigInt(MPC_ROOT_KEY); +const derivedPrivateKey = (privateKeyBigInt + epsilon) % BigInt(SECP256K1_N); +const derivedPrivKeyHex = '0x' + derivedPrivateKey.toString(16).padStart(64, '0'); +console.log(' Derived private key:', derivedPrivKeyHex.slice(0, 20) + '...'); +const privateKeyBytes = Buffer.from(derivedPrivKeyHex.slice(2), 'hex'); +const method2Pubkey = ecc.pointFromScalar(privateKeyBytes, true)!; +console.log(' Compressed pubkey:', Buffer.from(method2Pubkey).toString('hex')); + +console.log(''); +console.log('--- Comparison ---'); +console.log(' Method 1 (point addition):', method1Compressed); +console.log(' Method 2 (scalar addition):', Buffer.from(method2Pubkey).toString('hex')); +console.log(' Match:', method1Compressed === Buffer.from(method2Pubkey).toString('hex')); diff --git a/signet-ts-client-scripts/debug-test-derivation.ts b/signet-ts-client-scripts/debug-test-derivation.ts new file mode 100644 index 0000000000..0d5df24e89 --- /dev/null +++ b/signet-ts-client-scripts/debug-test-derivation.ts @@ -0,0 +1,75 @@ +import { KeyDerivation } from './key-derivation'; +import * as bitcoin from 'bitcoinjs-lib'; +import * as ecc from 'tiny-secp256k1'; +import { createHash } from 'crypto'; + +bitcoin.initEccLib(ecc); + +const ROOT_PUBLIC_KEY = + "0x044eef776e4f257d68983e45b340c2e9546c5df95447900b6aadfec68fb46fdee257e26b8ba383ddba9914b33c60e869265f859566fff4baef283c54d821ca3b64"; +const PALLET_SS58 = '13UVJyLnbVp6z97TrCZZCWMfADQddP3JkNruog9pbUF4Tomm'; +const ALICE_HEX_PATH = '0xd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d'; + +function compressPubkey(pubKey: string): Buffer { + const uncompressedHex = pubKey.startsWith("0x") ? pubKey.slice(4) : pubKey; + const x = Buffer.from(uncompressedHex.slice(0, 64), "hex"); + const y = Buffer.from(uncompressedHex.slice(64), "hex"); + const prefix = y[31] % 2 === 0 ? 0x02 : 0x03; + return Buffer.concat([Buffer.from([prefix]), x]); +} + +function hash160(buffer: Buffer): Buffer { + const sha256 = createHash('sha256').update(buffer).digest(); + return createHash('ripemd160').update(sha256).digest(); +} + +function btcAddressFromPubKey(pubKey: string, network: bitcoin.Network): string { + const compressedPubkey = compressPubkey(pubKey); + const payment = bitcoin.payments.p2wpkh({ + pubkey: compressedPubkey, + network, + }); + return payment.address!; +} + +console.log('='.repeat(70)); +console.log('DEBUG: Test KeyDerivation Output'); +console.log('='.repeat(70)); +console.log(''); +console.log('Inputs:'); +console.log(' ROOT_PUBLIC_KEY:', ROOT_PUBLIC_KEY.slice(0, 40) + '...'); +console.log(' PALLET_SS58:', PALLET_SS58); +console.log(' ALICE_HEX_PATH:', ALICE_HEX_PATH); +console.log(''); + +// Test with polkadot:2034 +const derivedPubKey = KeyDerivation.derivePublicKey( + ROOT_PUBLIC_KEY, + PALLET_SS58, + ALICE_HEX_PATH, + "polkadot:2034" +); + +const compressed = compressPubkey(derivedPubKey); +const pubkeyHash = hash160(compressed); +const network = bitcoin.networks.regtest; +const address = btcAddressFromPubKey(derivedPubKey, network); + +console.log('Output with polkadot:2034:'); +console.log(' Uncompressed pubkey:', derivedPubKey.slice(0, 40) + '...'); +console.log(' Compressed pubkey: ', compressed.toString('hex')); +console.log(' Pubkey hash: ', pubkeyHash.toString('hex')); +console.log(' Bitcoin address: ', address); +console.log(''); + +// Compare with what we expect +console.log('Expected (from earlier verification):'); +console.log(' Compressed pubkey: 028a78c0282061fc5f3d1b595b0bbe877b0fcf235744fdab3597e7ac257f736ae9'); +console.log(' Pubkey hash: 14f6e14c2f3cf3ff5641a06263c89344a9540e03'); +console.log(' Bitcoin address: bcrt1qznmwznp08nel74jp5p3x8jyngj54grsr99rthj'); +console.log(''); + +// Also show what the OLD UTXOs have +console.log('OLD UTXOs have:'); +console.log(' Pubkey hash: d8ce0f71b94df598efedf183dbdfc8d51410445c'); +console.log(' Bitcoin address: bcrt1qmr8q7udefh6e3mld7xpahh7g652pq3zurswrxz'); diff --git a/signet-ts-client-scripts/get-root-eth-address.ts b/signet-ts-client-scripts/get-root-eth-address.ts new file mode 100644 index 0000000000..806e3fa8ef --- /dev/null +++ b/signet-ts-client-scripts/get-root-eth-address.ts @@ -0,0 +1,26 @@ +import { ethers } from 'ethers'; +import * as ecc from 'tiny-secp256k1'; + +const MPC_ROOT_KEY = '0xf967622b74b7b619a0f4477118cf39c57c4a179a808526ac6fa1c41372512dad'; + +function ethAddressFromPrivateKey(privateKeyHex: string): string { + const privateKeyBytes = Buffer.from(privateKeyHex.slice(2), 'hex'); + const publicKey = ecc.pointFromScalar(privateKeyBytes, false); + if (!publicKey) throw new Error('Failed to derive public key'); + // Uncompressed pubkey without prefix (64 bytes) + const uncompressedPubkey = publicKey.slice(1, 65); + const hash = ethers.keccak256(uncompressedPubkey); + return hash.slice(-40); // last 20 bytes = 40 hex chars +} + +console.log('MPC Root Key:', MPC_ROOT_KEY); +console.log(''); + +// Ethereum address from ROOT key directly (no derivation) +const rootEthAddr = ethAddressFromPrivateKey(MPC_ROOT_KEY); +console.log('Ethereum address from ROOT key (no derivation):'); +console.log(' 0x' + rootEthAddr); +console.log(''); +console.log('As byte array for mpc_root_signer_address:'); +const bytes = Buffer.from(rootEthAddr, 'hex'); +console.log(' [' + Array.from(bytes).map(b => '0x' + b.toString(16).padStart(2, '0')).join(', ') + ']'); diff --git a/signet-ts-client-scripts/verify-address-derivation.ts b/signet-ts-client-scripts/verify-address-derivation.ts new file mode 100644 index 0000000000..86a1ab02b4 --- /dev/null +++ b/signet-ts-client-scripts/verify-address-derivation.ts @@ -0,0 +1,114 @@ +import { ethers } from 'ethers'; +import * as bitcoin from 'bitcoinjs-lib'; +import * as ecc from 'tiny-secp256k1'; + +// Initialize ECC for bitcoinjs-lib +bitcoin.initEccLib(ecc); + +const CONFIG = { + EPSILON_DERIVATION_PREFIX: 'sig.network v1.0.0 epsilon derivation', + SECP256K1_N: '0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141', +}; + +// MPC Root Key from .env +const MPC_ROOT_KEY = '0xf967622b74b7b619a0f4477118cf39c57c4a179a808526ac6fa1c41372512dad'; + +// Expected vault address from pallet (TESTNET_VAULT_ADDRESS) - UPDATED +const EXPECTED_VAULT_ADDRESS_HASH = Buffer.from([ + 0x67, 0x6c, 0x36, 0x49, 0xc4, 0xa4, 0x24, 0x7e, 0xd0, 0x14, + 0xff, 0x52, 0x50, 0x73, 0xe6, 0x3b, 0xba, 0x5c, 0x43, 0xe4 +]); + +// btcVault pallet account (derived from PalletId b"py/btcvt") +// This is what the sender would be for withdrawals +const BTC_VAULT_PALLET_ACCOUNT = '13UVJyLnbVp6z97TrCZZCWMfADQddP3JkNruog9pbUF4Tomm'; + +// Path for withdrawals +const ROOT_PATH = 'root'; + +// Chain ID used for key derivation +const CHAIN_ID = 'polkadot:2034'; + +function deriveEpsilonWithChainId(requester: string, path: string, chainId: string): bigint { + const derivationPath = `${CONFIG.EPSILON_DERIVATION_PREFIX},${chainId},${requester},${path}`; + console.log('\nšŸ“‹ Derivation path:', derivationPath); + const hash = ethers.keccak256(ethers.toUtf8Bytes(derivationPath)); + console.log('šŸ“‹ Epsilon hash:', hash); + return BigInt(hash); +} + +async function deriveSigningKeyWithChainId( + path: string, + predecessor: string, + basePrivateKey: string, + chainId: string +): Promise { + const epsilon = deriveEpsilonWithChainId(predecessor, path, chainId); + const privateKeyBigInt = BigInt(basePrivateKey); + const derivedPrivateKey = (privateKeyBigInt + epsilon) % BigInt(CONFIG.SECP256K1_N); + return '0x' + derivedPrivateKey.toString(16).padStart(64, '0'); +} + +async function main() { + console.log('='.repeat(60)); + console.log('šŸ” VERIFYING ADDRESS DERIVATION FOR BTC VAULT'); + console.log('='.repeat(60)); + + console.log('\nšŸ“Œ Parameters:'); + console.log(' MPC Root Key:', MPC_ROOT_KEY); + console.log(' Path:', ROOT_PATH); + console.log(' Sender (Pallet Account):', BTC_VAULT_PALLET_ACCOUNT); + console.log(' Chain ID:', CHAIN_ID); + console.log(' Expected Vault Address Hash:', EXPECTED_VAULT_ADDRESS_HASH.toString('hex')); + + // Derive the private key + const derivedPrivateKey = await deriveSigningKeyWithChainId( + ROOT_PATH, + BTC_VAULT_PALLET_ACCOUNT, + MPC_ROOT_KEY, + CHAIN_ID + ); + + console.log('\nšŸ”‘ Derived Private Key:', derivedPrivateKey); + + // Get the public key from the derived private key + const privateKeyBuffer = Buffer.from(derivedPrivateKey.slice(2), 'hex'); + const publicKey = ecc.pointFromScalar(privateKeyBuffer, true); + + if (!publicKey) { + throw new Error('Failed to derive public key'); + } + + console.log('šŸ”‘ Derived Public Key (compressed):', Buffer.from(publicKey).toString('hex')); + + // Create P2WPKH address + const { address: bech32Address, output } = bitcoin.payments.p2wpkh({ + pubkey: Buffer.from(publicKey), + network: bitcoin.networks.testnet, + }); + + console.log('\nšŸ“ Derived Bitcoin Address (Bech32):', bech32Address); + + // The output script for P2WPKH is: OP_0 <20-byte-pubkey-hash> + // Extract the pubkey hash (last 20 bytes after OP_0 and push byte) + const derivedPubkeyHash = output!.slice(2); // Skip OP_0 (0x00) and push byte (0x14) + + console.log('šŸ“ Derived Pubkey Hash:', derivedPubkeyHash.toString('hex')); + console.log('šŸ“ Expected Pubkey Hash:', EXPECTED_VAULT_ADDRESS_HASH.toString('hex')); + + // Compare + const matches = derivedPubkeyHash.equals(EXPECTED_VAULT_ADDRESS_HASH); + + console.log('\n' + '='.repeat(60)); + if (matches) { + console.log('āœ… VERIFICATION PASSED: Derived address matches expected vault address!'); + console.log(' Vault Address (tb1q...):', bech32Address); + } else { + console.log('āŒ VERIFICATION FAILED: Addresses do not match!'); + console.log(' Derived: ', derivedPubkeyHash.toString('hex')); + console.log(' Expected: ', EXPECTED_VAULT_ADDRESS_HASH.toString('hex')); + } + console.log('='.repeat(60)); +} + +main().catch(console.error); diff --git a/signet-ts-client-scripts/verify-alice-derivation.ts b/signet-ts-client-scripts/verify-alice-derivation.ts new file mode 100644 index 0000000000..99f8ca659f --- /dev/null +++ b/signet-ts-client-scripts/verify-alice-derivation.ts @@ -0,0 +1,97 @@ +import { ethers } from 'ethers'; +import * as ecc from 'tiny-secp256k1'; +import { ec as EC } from 'elliptic'; + +const CONFIG = { + EPSILON_DERIVATION_PREFIX: 'sig.network v1.0.0 epsilon derivation', + SECP256K1_N: '0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141', +}; + +const MPC_ROOT_KEY = '0xf967622b74b7b619a0f4477118cf39c57c4a179a808526ac6fa1c41372512dad'; +const ROOT_PUBLIC_KEY = "0x044eef776e4f257d68983e45b340c2e9546c5df95447900b6aadfec68fb46fdee257e26b8ba383ddba9914b33c60e869265f859566fff4baef283c54d821ca3b64"; + +const PALLET_SS58 = '13UVJyLnbVp6z97TrCZZCWMfADQddP3JkNruog9pbUF4Tomm'; +const ALICE_HEX_PATH = '0xd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d'; +const CHAIN_ID = 'bip122:000000000933ea01ad0ee984209779ba'; + +// MPC derivation (using private key) +function derivePrivateKey(path: string, sender: string, basePrivateKey: string, chainId: string): string { + const derivationPath = `${CONFIG.EPSILON_DERIVATION_PREFIX},${chainId},${sender},${path}`; + console.log('Derivation path:', derivationPath); + const hash = ethers.keccak256(ethers.toUtf8Bytes(derivationPath)); + console.log('Epsilon hash:', hash); + const epsilon = BigInt(hash); + const privateKeyBigInt = BigInt(basePrivateKey); + const derivedPrivateKey = (privateKeyBigInt + epsilon) % BigInt(CONFIG.SECP256K1_N); + return '0x' + derivedPrivateKey.toString(16).padStart(64, '0'); +} + +// Test's KeyDerivation (using public key with point addition) +function derivePublicKey(rootPublicKey: string, predecessorId: string, path: string, chainId: string): string { + const ec = new EC("secp256k1"); + const EPSILON_PREFIX = "sig.network v1.0.0 epsilon derivation"; + + const uncompressedRoot = rootPublicKey.slice(4); + + const derivationPath = `${EPSILON_PREFIX},${chainId},${predecessorId},${path}`; + console.log('Test derivation path:', derivationPath); + const hash = ethers.keccak256(ethers.toUtf8Bytes(derivationPath)); + console.log('Test epsilon hash:', hash); + const scalarHex = hash.slice(2); + + const x = uncompressedRoot.substring(0, 64); + const y = uncompressedRoot.substring(64); + + const oldPoint = ec.curve.point(x, y); + const scalarTimesG = ec.g.mul(scalarHex); + const newPoint = oldPoint.add(scalarTimesG); + + return `0x04${newPoint.getX().toString(16).padStart(64, "0")}${newPoint.getY().toString(16).padStart(64, "0")}`; +} + +console.log('='.repeat(70)); +console.log('VERIFYING ALICE DERIVATION'); +console.log('='.repeat(70)); +console.log(''); +console.log('Parameters:'); +console.log(' MPC_ROOT_KEY:', MPC_ROOT_KEY); +console.log(' PALLET_SS58:', PALLET_SS58); +console.log(' ALICE_HEX_PATH:', ALICE_HEX_PATH); +console.log(' CHAIN_ID:', CHAIN_ID); +console.log(''); + +console.log('--- MPC derivation (private key method) ---'); +const derivedPrivateKey = derivePrivateKey(ALICE_HEX_PATH, PALLET_SS58, MPC_ROOT_KEY, CHAIN_ID); +console.log('Derived private key:', derivedPrivateKey); + +// Get public key from derived private key +const privateKeyBytes = Buffer.from(derivedPrivateKey.slice(2), 'hex'); +const mpcDerivedUncompressed = ecc.pointFromScalar(privateKeyBytes, false)!; +const mpcDerivedCompressed = ecc.pointFromScalar(privateKeyBytes, true)!; +console.log('MPC derived pubkey (uncompressed):', '0x' + Buffer.from(mpcDerivedUncompressed).toString('hex')); +console.log('MPC derived pubkey (compressed): ', Buffer.from(mpcDerivedCompressed).toString('hex')); + +console.log(''); +console.log('--- Test derivation (public key point addition method) ---'); +const testDerivedPubKey = derivePublicKey(ROOT_PUBLIC_KEY, PALLET_SS58, ALICE_HEX_PATH, CHAIN_ID); +console.log('Test derived pubkey (uncompressed):', testDerivedPubKey); + +// Compress test pubkey +const ec = new EC("secp256k1"); +const testUncompressed = testDerivedPubKey.slice(4); +const testX = testUncompressed.substring(0, 64); +const testY = testUncompressed.substring(64); +const testPoint = ec.curve.point(testX, testY); +const testCompressed = testPoint.encode('hex', true); +console.log('Test derived pubkey (compressed): ', testCompressed); + +console.log(''); +console.log('--- Comparison ---'); +const match = Buffer.from(mpcDerivedCompressed).toString('hex') === testCompressed; +console.log('Compressed pubkeys match:', match); + +if (!match) { + console.log(''); + console.log('MISMATCH! Expected:', Buffer.from(mpcDerivedCompressed).toString('hex')); + console.log(' Got: ', testCompressed); +} diff --git a/signet-ts-client-scripts/verify-all-addresses.ts b/signet-ts-client-scripts/verify-all-addresses.ts new file mode 100644 index 0000000000..8ce2a756d3 --- /dev/null +++ b/signet-ts-client-scripts/verify-all-addresses.ts @@ -0,0 +1,95 @@ +import { ethers } from 'ethers'; +import * as bitcoin from 'bitcoinjs-lib'; +import * as ecc from 'tiny-secp256k1'; + +bitcoin.initEccLib(ecc); + +const CONFIG = { + EPSILON_DERIVATION_PREFIX: 'sig.network v1.0.0 epsilon derivation', + SECP256K1_N: '0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141', +}; + +const MPC_ROOT_KEY = '0xf967622b74b7b619a0f4477118cf39c57c4a179a808526ac6fa1c41372512dad'; +const PALLET_SS58 = '13UVJyLnbVp6z97TrCZZCWMfADQddP3JkNruog9pbUF4Tomm'; +const ROOT_PATH = 'root'; +const CHAIN_ID = 'polkadot:2034'; + +// Derive private key using the same method as MPC server +function derivePrivateKey(path: string, sender: string, basePrivateKey: string, chainId: string): string { + const derivationPath = `${CONFIG.EPSILON_DERIVATION_PREFIX},${chainId},${sender},${path}`; + const hash = ethers.keccak256(ethers.toUtf8Bytes(derivationPath)); + const epsilon = BigInt(hash); + const privateKeyBigInt = BigInt(basePrivateKey); + const derivedPrivateKey = (privateKeyBigInt + epsilon) % BigInt(CONFIG.SECP256K1_N); + return '0x' + derivedPrivateKey.toString(16).padStart(64, '0'); +} + +function ethAddressFromPrivateKey(privateKeyHex: string): Uint8Array { + const privateKeyBytes = Buffer.from(privateKeyHex.slice(2), 'hex'); + const publicKey = ecc.pointFromScalar(privateKeyBytes, false); + if (!publicKey) throw new Error('Failed to derive public key'); + // Uncompressed pubkey without prefix (64 bytes) + const uncompressedPubkey = publicKey.slice(1, 65); + const hash = ethers.keccak256(uncompressedPubkey); + return new Uint8Array(Buffer.from(hash.slice(2), 'hex').slice(-20)); +} + +async function main() { + console.log('='.repeat(70)); + console.log('VERIFYING ALL ADDRESS DERIVATIONS'); + console.log('='.repeat(70)); + + // Derive private key at path "root" + const derivedPrivateKey = derivePrivateKey(ROOT_PATH, PALLET_SS58, MPC_ROOT_KEY, CHAIN_ID); + console.log('\n1. Derived private key at path "root":'); + console.log(' Private key:', derivedPrivateKey); + + // Get public key from derived private key + const privateKeyBytes = Buffer.from(derivedPrivateKey.slice(2), 'hex'); + const uncompressedPubKey = ecc.pointFromScalar(privateKeyBytes, false)!; + const compressedPubKey = ecc.pointFromScalar(privateKeyBytes, true)!; + + console.log('\n2. Derived public keys:'); + console.log(' Uncompressed:', Buffer.from(uncompressedPubKey).toString('hex')); + console.log(' Compressed: ', Buffer.from(compressedPubKey).toString('hex')); + + // Ethereum address from derived key (CORRECT for mpc_root_signer_address) + const derivedEthAddr = ethAddressFromPrivateKey(derivedPrivateKey); + console.log('\n3. Ethereum address from derived key (for mpc_root_signer_address):'); + console.log(' Address:', Buffer.from(derivedEthAddr).toString('hex')); + + // Bitcoin P2WPKH address from derived key + const { address, output } = bitcoin.payments.p2wpkh({ + pubkey: Buffer.from(compressedPubKey), + network: bitcoin.networks.regtest, + }); + const btcPubkeyHash = output!.slice(2); + console.log('\n4. Bitcoin P2WPKH from derived key (for TESTNET_VAULT_ADDRESS):'); + console.log(' Address:', address); + console.log(' Pubkey hash:', btcPubkeyHash.toString('hex')); + + // Compare with what we set in pallet + const TESTNET_VAULT_ADDRESS_HASH = Buffer.from([ + 0x67, 0x6c, 0x36, 0x49, 0xc4, 0xa4, 0x24, 0x7e, 0xd0, 0x14, 0xff, 0x52, 0x50, + 0x73, 0xe6, 0x3b, 0xba, 0x5c, 0x43, 0xe4, + ]); + + console.log('\n' + '='.repeat(70)); + console.log('SUMMARY:'); + console.log('='.repeat(70)); + + console.log('\nBitcoin vault address (TESTNET_VAULT_ADDRESS):'); + console.log(' Derived: ', btcPubkeyHash.toString('hex')); + console.log(' In pallet:', TESTNET_VAULT_ADDRESS_HASH.toString('hex')); + console.log(' Match: ', btcPubkeyHash.equals(TESTNET_VAULT_ADDRESS_HASH) ? 'āœ… CORRECT' : 'āŒ WRONG'); + + console.log('\nmpc_root_signer_address (for signature verification):'); + console.log(' Should be:', Buffer.from(derivedEthAddr).toString('hex')); + + console.log('\n' + '='.repeat(70)); + console.log('FOR VAULT INITIALIZATION, use this 20-byte array:'); + console.log('='.repeat(70)); + console.log(' [' + Array.from(derivedEthAddr).map(b => '0x' + b.toString(16).padStart(2, '0')).join(', ') + ']'); +} + +main().catch(console.error); diff --git a/signet-ts-client-scripts/verify-pubkey-match.ts b/signet-ts-client-scripts/verify-pubkey-match.ts new file mode 100644 index 0000000000..96674b486d --- /dev/null +++ b/signet-ts-client-scripts/verify-pubkey-match.ts @@ -0,0 +1,18 @@ +import * as ecc from 'tiny-secp256k1'; + +const MPC_ROOT_KEY = '0xf967622b74b7b619a0f4477118cf39c57c4a179a808526ac6fa1c41372512dad'; +const ROOT_PUBLIC_KEY = "0x044eef776e4f257d68983e45b340c2e9546c5df95447900b6aadfec68fb46fdee257e26b8ba383ddba9914b33c60e869265f859566fff4baef283c54d821ca3b64"; + +// Derive public key from private key +const privateKeyBytes = Buffer.from(MPC_ROOT_KEY.slice(2), 'hex'); +const derivedUncompressed = ecc.pointFromScalar(privateKeyBytes, false)!; +const derivedCompressed = ecc.pointFromScalar(privateKeyBytes, true)!; + +console.log('MPC_ROOT_KEY (private): ', MPC_ROOT_KEY); +console.log(''); +console.log('ROOT_PUBLIC_KEY (from test): ', ROOT_PUBLIC_KEY); +console.log('Derived pubkey (uncompressed): ', '0x' + Buffer.from(derivedUncompressed).toString('hex')); +console.log(''); +console.log('Match: ', ROOT_PUBLIC_KEY.toLowerCase() === ('0x' + Buffer.from(derivedUncompressed).toString('hex'))); +console.log(''); +console.log('Derived pubkey (compressed): ', '0x' + Buffer.from(derivedCompressed).toString('hex')); diff --git a/signet-ts-client-scripts/verify-utxo-match.ts b/signet-ts-client-scripts/verify-utxo-match.ts new file mode 100644 index 0000000000..dc3484ecbd --- /dev/null +++ b/signet-ts-client-scripts/verify-utxo-match.ts @@ -0,0 +1,41 @@ +import * as bitcoin from 'bitcoinjs-lib'; +import * as ecc from 'tiny-secp256k1'; +import { createHash } from 'crypto'; + +bitcoin.initEccLib(ecc); + +// From test output - the pubkey used for verification +const compressedPubkey = Buffer.from('028a78c0282061fc5f3d1b595b0bbe877b0fcf235744fdab3597e7ac257f736ae9', 'hex'); + +// From test output - the UTXO scriptPubKey +// script: +const utxoScript = Buffer.from('0014d8ce0f71b94df598efedf183dbdfc8d51410445c', 'hex'); +const utxoPubkeyHash = utxoScript.slice(2); // Skip OP_0 and push byte + +// Compute HASH160 of the pubkey we're signing with +function hash160(buffer: Buffer): Buffer { + const sha256 = createHash('sha256').update(buffer).digest(); + return createHash('ripemd160').update(sha256).digest(); +} + +const derivedPubkeyHash = hash160(compressedPubkey); + +console.log('Pubkey (compressed): ', compressedPubkey.toString('hex')); +console.log('HASH160(pubkey): ', derivedPubkeyHash.toString('hex')); +console.log('UTXO pubkey hash: ', utxoPubkeyHash.toString('hex')); +console.log(''); +console.log('Match:', derivedPubkeyHash.equals(utxoPubkeyHash)); + +// Also show what Bitcoin addresses these correspond to +const network = bitcoin.networks.regtest; + +const addressFromPubkey = bitcoin.payments.p2wpkh({ + pubkey: compressedPubkey, + network, +}).address; + +const addressFromScript = bitcoin.address.fromOutputScript(utxoScript, network); + +console.log(''); +console.log('Address from pubkey: ', addressFromPubkey); +console.log('Address from UTXO: ', addressFromScript);