diff --git a/.gitignore b/.gitignore index f9fa99e..9b8c6b5 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ /target *.sqlite +node_modules/ +test-data/ \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index f298ec3..b08daae 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -47,6 +47,12 @@ version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" +[[package]] +name = "alphanumeric-sort" +version = "1.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d67c60c5f10f11c6ee04de72b2dd98bb9d2548cbc314d22a609bfa8bd9e87e8f" + [[package]] name = "android_system_properties" version = "0.1.5" @@ -472,6 +478,26 @@ dependencies = [ "subtle", ] +[[package]] +name = "dirs" +version = "4.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059" +dependencies = [ + "dirs-sys", +] + +[[package]] +name = "dirs-sys" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6" +dependencies = [ + "libc", + "redox_users", + "winapi", +] + [[package]] name = "displaydoc" version = "0.2.5" @@ -495,7 +521,7 @@ dependencies = [ [[package]] name = "dojo-introspect-events" version = "0.1.0" -source = "git+https://github.com/dojoengine/dojo-introspect?branch=main#490003ea57afdaea72c85c90be07c73c63f45604" +source = "git+https://github.com/dojoengine/dojo-introspect?branch=next#45ce54d11c8f7860aec11e4c3733fe699dd37d45" dependencies = [ "introspect-types", "introspect-value", @@ -506,8 +532,10 @@ dependencies = [ [[package]] name = "dojo-introspect-types" version = "0.1.0" -source = "git+https://github.com/dojoengine/dojo-introspect?branch=main#490003ea57afdaea72c85c90be07c73c63f45604" +source = "git+https://github.com/dojoengine/dojo-introspect?branch=next#45ce54d11c8f7860aec11e4c3733fe699dd37d45" dependencies = [ + "anyhow", + "async-trait", "cainome-cairo-serde", "dojo-introspect-utils", "introspect-events", @@ -523,7 +551,7 @@ dependencies = [ [[package]] name = "dojo-introspect-utils" version = "0.1.0" -source = "git+https://github.com/dojoengine/dojo-introspect?branch=main#490003ea57afdaea72c85c90be07c73c63f45604" +source = "git+https://github.com/dojoengine/dojo-introspect?branch=next#45ce54d11c8f7860aec11e4c3733fe699dd37d45" dependencies = [ "anyhow", "cainome-cairo-serde", @@ -594,6 +622,17 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "etcetera" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "136d1b5283a1ab77bd9257427ffd09d8667ced0570b6f938942bc7568ed5b943" +dependencies = [ + "cfg-if", + "home", + "windows-sys 0.48.0", +] + [[package]] name = "eth-keystore" version = "0.5.0" @@ -876,6 +915,15 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +[[package]] +name = "hkdf" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b5f8eb2ad728638ea2c7d47a21db23b7b58a72ed6a38256b8a1849f15fbbdf7" +dependencies = [ + "hmac", +] + [[package]] name = "hmac" version = "0.12.1" @@ -885,6 +933,15 @@ dependencies = [ "digest", ] +[[package]] +name = "home" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589533453244b0995c858700322199b2becb13b627df2851f64a2775d024abcf" +dependencies = [ + "windows-sys 0.59.0", +] + [[package]] name = "http" version = "1.3.1" @@ -1215,7 +1272,7 @@ dependencies = [ [[package]] name = "introspect-events" version = "0.1.2" -source = "git+https://github.com/cartridge-gg/introspect?branch=main#5025c1e8d465bf1282cb1a8cce914f935f912989" +source = "git+https://github.com/cartridge-gg/introspect?branch=next#ba3b47c5976e2126d584800ecb1e8193e0cc9369" dependencies = [ "cainome-cairo-serde", "introspect-types", @@ -1227,7 +1284,7 @@ dependencies = [ [[package]] name = "introspect-types" version = "0.1.2" -source = "git+https://github.com/cartridge-gg/introspect?branch=main#5025c1e8d465bf1282cb1a8cce914f935f912989" +source = "git+https://github.com/cartridge-gg/introspect?branch=next#ba3b47c5976e2126d584800ecb1e8193e0cc9369" dependencies = [ "cainome-cairo-serde", "introspect-value", @@ -1240,7 +1297,7 @@ dependencies = [ [[package]] name = "introspect-value" version = "0.1.2" -source = "git+https://github.com/cartridge-gg/introspect?branch=main#5025c1e8d465bf1282cb1a8cce914f935f912989" +source = "git+https://github.com/cartridge-gg/introspect?branch=next#ba3b47c5976e2126d584800ecb1e8193e0cc9369" dependencies = [ "cainome-cairo-serde", "convert_case 0.8.0", @@ -1342,6 +1399,17 @@ version = "0.2.177" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976" +[[package]] +name = "libredox" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "416f7e718bdb06000964960ffa43b4335ad4012ae8b99060261aa4a8088d5ccb" +dependencies = [ + "bitflags", + "libc", + "redox_syscall", +] + [[package]] name = "libsqlite3-sys" version = "0.27.0" @@ -1395,6 +1463,16 @@ dependencies = [ "regex-automata", ] +[[package]] +name = "md-5" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf" +dependencies = [ + "cfg-if", + "digest", +] + [[package]] name = "memchr" version = "2.7.6" @@ -1419,13 +1497,13 @@ dependencies = [ [[package]] name = "mio" -version = "1.0.4" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78bed444cc8a2160f01cbcf811ef18cac863ad68ae8ca62092e8db51d51c761c" +checksum = "69d83b0086dc8ecf3ce9ae2874b2d1290252e2a30720bea58a5c6639b0092873" dependencies = [ "libc", "wasi", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -1847,6 +1925,17 @@ dependencies = [ "bitflags", ] +[[package]] +name = "redox_users" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" +dependencies = [ + "getrandom 0.2.16", + "libredox", + "thiserror 1.0.69", +] + [[package]] name = "ref-cast" version = "1.0.25" @@ -1922,6 +2011,15 @@ dependencies = [ "webpki-roots", ] +[[package]] +name = "resolve-path" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "321e5e41b3b192dab6f1e75b9deacb6688b4b8c5e68906a78e8f43e7c2887bb5" +dependencies = [ + "dirs", +] + [[package]] name = "rfc6979" version = "0.4.0" @@ -2005,9 +2103,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.32" +version = "0.23.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd3c25631629d034ce7cd9940adc9d45762d46de2b0f57193c4443b92c6d4d40" +checksum = "751e04a496ca00bb97a5e043158d23d66b5aabf2e1d5aa2a0aaebb1aafe6f82c" dependencies = [ "once_cell", "ring", @@ -2313,6 +2411,7 @@ checksum = "c9a2ccff1a000a5a59cd33da541d9f2fdcd9e6e8229cc200565942bff36d0aaa" dependencies = [ "sqlx-core", "sqlx-macros", + "sqlx-postgres", "sqlx-sqlite", ] @@ -2344,6 +2443,7 @@ dependencies = [ "paste", "percent-encoding", "serde", + "serde_json", "sha2", "smallvec", "sqlformat", @@ -2384,6 +2484,7 @@ dependencies = [ "serde_json", "sha2", "sqlx-core", + "sqlx-postgres", "sqlx-sqlite", "syn 1.0.109", "tempfile", @@ -2391,6 +2492,44 @@ dependencies = [ "url", ] +[[package]] +name = "sqlx-postgres" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c824eb80b894f926f89a0b9da0c7f435d27cdd35b8c655b114e58223918577e" +dependencies = [ + "atoi", + "base64 0.21.7", + "bitflags", + "byteorder", + "crc", + "dotenvy", + "etcetera", + "futures-channel", + "futures-core", + "futures-io", + "futures-util", + "hex", + "hkdf", + "hmac", + "home", + "itoa", + "log", + "md-5", + "memchr", + "once_cell", + "rand 0.8.5", + "serde", + "serde_json", + "sha2", + "smallvec", + "sqlx-core", + "stringprep", + "thiserror 1.0.69", + "tracing", + "whoami", +] + [[package]] name = "sqlx-sqlite" version = "0.7.4" @@ -2600,6 +2739,17 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" +[[package]] +name = "stringprep" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b4df3d392d81bd458a8a621b8bffbd2302a12ffe288a9d931670948749463b1" +dependencies = [ + "unicode-bidi", + "unicode-normalization", + "unicode-properties", +] + [[package]] name = "strsim" version = "0.11.1" @@ -2986,6 +3136,22 @@ dependencies = [ "url", ] +[[package]] +name = "torii-json-test" +version = "0.1.0" +dependencies = [ + "anyhow", + "dojo-introspect-events", + "dojo-types-manager", + "resolve-path", + "starknet", + "tokio", + "torii-core", + "torii-decoder-introspect", + "torii-sink-json", + "torii-test-utils", +] + [[package]] name = "torii-registry" version = "0.1.0" @@ -3051,6 +3217,43 @@ dependencies = [ "tracing", ] +[[package]] +name = "torii-sqlite-test" +version = "0.1.0" +dependencies = [ + "anyhow", + "dojo-introspect-events", + "dojo-types-manager", + "resolve-path", + "starknet", + "starknet-types-core", + "tokio", + "torii-core", + "torii-decoder-introspect", + "torii-sink-sqlite", + "torii-test-utils", +] + +[[package]] +name = "torii-test-utils" +version = "0.1.0" +dependencies = [ + "alphanumeric-sort", + "anyhow", + "async-trait", + "dojo-introspect-types", + "dojo-types-manager", + "introspect-types", + "resolve-path", + "serde", + "serde_json", + "starknet", + "starknet-types-core", + "thiserror 2.0.17", + "torii-utils", + "tracing", +] + [[package]] name = "torii-types-erc20" version = "0.1.0" @@ -3082,6 +3285,22 @@ dependencies = [ "torii-core", ] +[[package]] +name = "torii-utils" +version = "0.1.0" +dependencies = [ + "anyhow", + "dojo-introspect-utils", + "introspect-events", + "introspect-types", + "introspect-value", + "serde", + "serde_json", + "starknet", + "starknet-types-core", + "thiserror 2.0.17", +] + [[package]] name = "tower" version = "0.5.2" @@ -3231,12 +3450,33 @@ dependencies = [ "static_assertions", ] +[[package]] +name = "unicode-bidi" +version = "0.3.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c1cb5db39152898a79168971543b1cb5020dff7fe43c8dc468b0885f5e29df5" + [[package]] name = "unicode-ident" version = "1.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f63a545481291138910575129486daeaf8ac54aee4387fe7906919f7830c7d9d" +[[package]] +name = "unicode-normalization" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "unicode-properties" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e70f2a8b45122e719eb623c01822704c4e0907e7e426a05927e1a1cfff5b75d0" + [[package]] name = "unicode-segmentation" version = "1.12.0" @@ -3337,6 +3577,12 @@ dependencies = [ "wit-bindgen", ] +[[package]] +name = "wasite" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855b" + [[package]] name = "wasm-bindgen" version = "0.2.104" @@ -3438,6 +3684,38 @@ dependencies = [ "rustls-pki-types", ] +[[package]] +name = "whoami" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d4a4db5077702ca3015d3d02d74974948aba2ad9e12ab7df718ee64ccd7e97d" +dependencies = [ + "libredox", + "wasite", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + [[package]] name = "windows-core" version = "0.62.2" @@ -3497,6 +3775,15 @@ dependencies = [ "windows-link", ] +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.5", +] + [[package]] name = "windows-sys" version = "0.52.0" @@ -3533,6 +3820,21 @@ dependencies = [ "windows-link", ] +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + [[package]] name = "windows-targets" version = "0.52.6" @@ -3566,6 +3868,12 @@ dependencies = [ "windows_x86_64_msvc 0.53.1", ] +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + [[package]] name = "windows_aarch64_gnullvm" version = "0.52.6" @@ -3578,6 +3886,12 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + [[package]] name = "windows_aarch64_msvc" version = "0.52.6" @@ -3590,6 +3904,12 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + [[package]] name = "windows_i686_gnu" version = "0.52.6" @@ -3614,6 +3934,12 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + [[package]] name = "windows_i686_msvc" version = "0.52.6" @@ -3626,6 +3952,12 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + [[package]] name = "windows_x86_64_gnu" version = "0.52.6" @@ -3638,6 +3970,12 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + [[package]] name = "windows_x86_64_gnullvm" version = "0.52.6" @@ -3650,6 +3988,12 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + [[package]] name = "windows_x86_64_msvc" version = "0.52.6" diff --git a/Cargo.toml b/Cargo.toml index 5e8d879..1473c21 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,6 @@ [workspace] members = [ + "crates/utils", "crates/core/torii-core", "crates/core/torii-registry", "crates/fetchers/torii-fetcher-jsonrpc", @@ -14,6 +15,7 @@ members = [ "crates/types/torii-types-erc721", "crates/types/dojo-types-manager", "bins/*", + "tests/*", ] resolver = "2" @@ -26,9 +28,11 @@ repository = "https://github.com/dojoengine/torii-core" publish = false [workspace.dependencies] +alphanumeric-sort = "1.5.3" anyhow = "1" async-trait = "0.1" bytes = "1" +resolve-path = "0.1.0" starknet = "0.17" tokio = { version = "1", features = [ "macros", @@ -44,15 +48,29 @@ config = "0.14" sqlx = { version = "0.7", default-features = false, features = [ "runtime-tokio", "sqlite", + "postgres", ] } url = "2" -introspect-value = { git = "https://github.com/cartridge-gg/introspect", branch = "main" } -introspect-types = { git = "https://github.com/cartridge-gg/introspect", branch = "main" } -introspect-events = { git = "https://github.com/cartridge-gg/introspect", branch = "main" } -dojo-introspect-types = { git = "https://github.com/dojoengine/dojo-introspect", branch = "main" } -dojo-introspect-utils = { git = "https://github.com/dojoengine/dojo-introspect", branch = "main" } -dojo-introspect-events = { git = "https://github.com/dojoengine/dojo-introspect", branch = "main" } +introspect-value = { git = "https://github.com/cartridge-gg/introspect", branch = "next" } +introspect-types = { git = "https://github.com/cartridge-gg/introspect", branch = "next" } +introspect-events = { git = "https://github.com/cartridge-gg/introspect", branch = "next" } +# introspect-value = { path = "../introspect/crates/value" } +# introspect-types = { path = "../introspect/crates/types" } +# introspect-events = { path = "../introspect/crates/events" } +dojo-introspect-types = { git = "https://github.com/dojoengine/dojo-introspect", branch = "next" } +dojo-introspect-utils = { git = "https://github.com/dojoengine/dojo-introspect", branch = "next" } +dojo-introspect-events = { git = "https://github.com/dojoengine/dojo-introspect", branch = "next" } +# dojo-introspect-types = { path = "../dojo-introspect/crates/types" } +# dojo-introspect-utils = { path = "../dojo-introspect/crates/utils" } +# dojo-introspect-events = { path = "../dojo-introspect/crates/events" } dojo-types-manager = { path = "crates/types/dojo-types-manager" } -torii-types-introspect = { path = "crates/types/torii-types-introspect" } starknet-types-core = "0.2.0" thiserror = "2.0.17" +torii-core = { path = "crates/core/torii-core" } +torii-registry = { path = "crates/core/torii-registry" } +torii-types-introspect = { path = "crates/types/torii-types-introspect" } +torii-decoder-introspect = { path = "crates/decoders/torii-decoder-introspect" } +torii-sink-json = { path = "crates/sinks/torii-sink-json" } +torii-sink-sqlite = { path = "crates/sinks/torii-sink-sqlite" } +torii-utils = { path = "crates/utils" } +torii-test-utils = { path = "tests/test_utils" } diff --git a/crates/decoders/torii-decoder-introspect/src/builders.rs b/crates/decoders/torii-decoder-introspect/src/builders.rs index f42b5a3..dba8ea7 100644 --- a/crates/decoders/torii-decoder-introspect/src/builders.rs +++ b/crates/decoders/torii-decoder-introspect/src/builders.rs @@ -3,10 +3,10 @@ use dojo_introspect_events::{ DojoEvent, EventEmitted, EventRegistered, EventUpgraded, ModelRegistered, ModelUpgraded, StoreDelRecord, StoreSetRecord, StoreUpdateMember, StoreUpdateRecord, }; -use dojo_introspect_types::{DojoSchemaFetcher, DojoSchemaFetcherError}; +use dojo_introspect_types::DojoSchemaFetcher; use dojo_types_manager::{DojoManagerError, DojoTable, DojoTableErrors}; use introspect_value::{Field, Value}; -use starknet::{core::types::EmittedEvent, providers::Provider}; +use starknet::core::types::EmittedEvent; use starknet_types_core::felt::Felt; use std::collections::hash_map::DefaultHasher; use std::hash::{Hash, Hasher}; @@ -22,7 +22,7 @@ fn make_entity_id_field(entity_id: Felt) -> Field { } } -fn make_entity_id_for_event(keys: Vec) -> Field { +fn make_entity_id_for_event(keys: &Vec) -> Field { let mut hasher = DefaultHasher::new(); keys.hash(&mut hasher); let entity_id = hasher.finish(); @@ -39,8 +39,9 @@ pub enum DojoEventBuilderError { #[error("Table Error: {0}")] TableError(#[from] DojoTableErrors), #[error("Schema fetch error: {0}")] - SchemaFetchError(#[from] DojoSchemaFetcherError), + SchemaFetchError(#[from] anyhow::Error), } + pub type Result = std::result::Result; pub trait DojoEventBuilder { @@ -66,20 +67,20 @@ where .ok_or_else(|| DojoEventBuilderError::RawEventDecodeError(T::NAME.to_string())) } -impl

DojoEventBuilder for IntrospectDecoder

+impl DojoEventBuilder for IntrospectDecoder where - P: Provider, + F: DojoSchemaFetcher + Sync + Send, { - fn with_table(&self, id: Felt, f: F) -> Result + fn with_table(&self, id: Felt, f: Fn) -> Result where - F: FnOnce(&DojoTable) -> Result, + Fn: FnOnce(&DojoTable) -> Result, { self.manager.with_table(id, f)? } async fn build_model_registered(&self, raw: &EmittedEvent) -> Result { let event = raw_event_to_event::(raw)?; - let struct_def = self.provider.schema(event.address).await?; + let struct_def = self.fetcher.schema(event.address).await?; let schema = self.manager.register_table( event.namespace, event.name, @@ -98,7 +99,7 @@ where async fn build_model_upgraded(&self, raw: &EmittedEvent) -> Result { let event = raw_event_to_event::(raw)?; - let struct_def = self.provider.schema(event.address).await?; + let struct_def = self.fetcher.schema(event.address).await?; let schema = self .manager .update_table(event.selector, struct_def.fields)?; @@ -114,7 +115,7 @@ where async fn build_event_registered(&self, raw: &EmittedEvent) -> Result { let event = raw_event_to_event::(raw)?; - let struct_def = self.provider.schema(event.address).await?; + let struct_def = self.fetcher.schema(event.address).await?; let schema = self.manager.register_table( event.namespace, event.name, @@ -133,7 +134,7 @@ where async fn build_event_upgraded(&self, raw: &EmittedEvent) -> Result { let event = raw_event_to_event::(raw)?; - let struct_def = self.provider.schema(event.address).await?; + let struct_def = self.fetcher.schema(event.address).await?; let schema = self .manager .update_table(event.selector, struct_def.fields)?; @@ -192,11 +193,24 @@ where fn build_emit_event(&self, raw: &EmittedEvent) -> Result { let event = raw_event_to_event::(raw)?; - let (table_id, table_name, fields) = self.with_table(event.selector, |table| { - let fields = table.parse_values(event.values)?; + let id_field = make_entity_id_for_event(&event.keys); + let EventEmitted { + keys, + values, + selector, + .. + } = event; + let (table_id, table_name, fields) = self.with_table(selector, |table| { + let fields = match table.parse_key_values(keys.clone(), values.clone()) { + Ok(fields) => fields, + Err(e) => { + println!("\nError Parsing keys: {keys:#?} values: {values:#?}"); + println!("\nError Parsing table: {table:#?}"); + return Err(DojoEventBuilderError::TableError(e)); + } + }; Ok((table.id, table.name.clone(), fields)) })?; - let id_field = make_entity_id_for_event(event.keys); let data = UpdateRecordFieldsV1::new(table_id, table_name, id_field, fields); Ok(data.to_envelope(raw)) } diff --git a/crates/decoders/torii-decoder-introspect/src/lib.rs b/crates/decoders/torii-decoder-introspect/src/lib.rs index 6d5440c..be03d20 100644 --- a/crates/decoders/torii-decoder-introspect/src/lib.rs +++ b/crates/decoders/torii-decoder-introspect/src/lib.rs @@ -4,11 +4,12 @@ use dojo_introspect_events::{ DojoEvent, EventEmitted, EventRegistered, EventUpgraded, ModelRegistered, ModelUpgraded, StoreDelRecord, StoreSetRecord, StoreUpdateMember, StoreUpdateRecord, }; +use dojo_introspect_types::DojoSchemaFetcher; use dojo_types_manager::{DojoManager, JsonStore}; use serde::{Deserialize, Serialize}; use starknet::{ core::types::EmittedEvent, - providers::{jsonrpc::HttpTransport, JsonRpcClient, Provider, Url}, + providers::{jsonrpc::HttpTransport, JsonRpcClient, Url}, }; use std::collections::{HashMap, HashSet}; use std::path::PathBuf; @@ -46,13 +47,10 @@ pub struct IntrospectDecoderConfig { } /// Implementation of the introspect decoder. -struct IntrospectDecoder

-where - P: Provider, -{ +pub struct IntrospectDecoder { pub filter: DecoderFilter, pub manager: DojoManager, - pub provider: P, + pub fetcher: F, } impl IntrospectDecoder> { @@ -82,7 +80,7 @@ impl IntrospectDecoder> { } let provider = JsonRpcClient::new(HttpTransport::new(cfg.rpc_url)); - let store = JsonStore::new(cfg.store_path.as_path()); + let store = JsonStore::new(&cfg.store_path); let manager = DojoManager::new(store)?; let filter = DecoderFilter { @@ -94,15 +92,15 @@ impl IntrospectDecoder> { Ok(Self { filter, manager, - provider, + fetcher: provider, }) } } #[async_trait] -impl

Decoder for IntrospectDecoder

+impl Decoder for IntrospectDecoder where - P: Provider + Sync + Send, + F: DojoSchemaFetcher + Sync + Send + 'static, { fn name(&self) -> &'static str { DECODER_NAME diff --git a/crates/fetchers/torii-fetcher-jsonrpc/src/lib.rs b/crates/fetchers/torii-fetcher-jsonrpc/src/lib.rs index 8a92a99..800b228 100644 --- a/crates/fetchers/torii-fetcher-jsonrpc/src/lib.rs +++ b/crates/fetchers/torii-fetcher-jsonrpc/src/lib.rs @@ -3,7 +3,7 @@ use std::time::Duration; use anyhow::{anyhow, Result}; use async_trait::async_trait; use serde::Deserialize; -use starknet::core::types::{BlockId, BlockTag, EmittedEvent, EventFilter, EventsPage, Felt}; +use starknet::core::types::{EmittedEvent, EventFilter, EventsPage}; use starknet::providers::{jsonrpc::HttpTransport, JsonRpcClient, Provider}; use tokio::time::sleep; use torii_core::{FetchPlan, Fetcher}; diff --git a/crates/sinks/torii-sink-json/src/lib.rs b/crates/sinks/torii-sink-json/src/lib.rs index 01b693d..52383f7 100644 --- a/crates/sinks/torii-sink-json/src/lib.rs +++ b/crates/sinks/torii-sink-json/src/lib.rs @@ -1,10 +1,9 @@ -use std::{fs::create_dir_all, path::PathBuf}; - use anyhow::{Context, Result}; use async_trait::async_trait; use introspect_value::{Field, ToPrimitiveString}; use serde::{Deserialize, Serialize}; use serde_json::{Map, Value as JsonValue}; +use std::{fs, fs::create_dir_all, path::PathBuf}; use torii_core::{Batch, Envelope, Event, Sink}; use torii_types_introspect::{DeclareTableV1, DeleteRecordsV1, UpdateRecordFieldsV1}; @@ -26,6 +25,28 @@ impl ToJson for PathBuf { } } +pub fn read_json_file(path: &PathBuf) -> Result +where + T: for<'de> Deserialize<'de>, +{ + let data = fs::read_to_string(path) + .with_context(|| format!("Failed to read file at path: {:?}", path))?; + let value = serde_json::from_str(&data) + .with_context(|| format!("Failed to parse JSON from file at path: {:?}", path))?; + Ok(value) +} + +pub fn write_json_file(path: &PathBuf, value: &T) -> Result<()> +where + T: Serialize, +{ + let file = fs::File::create(path) + .with_context(|| format!("Failed to create file at path: {:?}", path))?; + serde_json::to_writer_pretty(file, value) + .with_context(|| format!("Failed to write JSON to file at path: {:?}", path))?; + Ok(()) +} + pub struct JsonSink { pub path: PathBuf, pub label: String, @@ -33,6 +54,13 @@ pub struct JsonSink { pub record_path: PathBuf, } +fn fields_to_json_array(fields: Vec) -> Vec<(String, JsonValue)> { + fields + .into_iter() + .map(|field| (field.name, field.value.into())) + .collect() +} + fn to_json_object(fields: Vec) -> Map { let mut map = Map::new(); for Field { @@ -51,6 +79,8 @@ impl JsonSink { create_dir_all(&path)?; let table_path = path.join(TABLE_DIR); let record_path = path.join(RECORD_DIR); + create_dir_all(&table_path)?; + create_dir_all(&record_path)?; Ok(Self { path, label, @@ -98,13 +128,8 @@ impl JsonSink { let path = self.table_path(&event.name); if path.exists() { } else { - let file = std::fs::File::create(&path) - .with_context(|| format!("Failed to create table file at path: {:?}", path))?; - serde_json::to_writer_pretty(file, &event).with_context(|| { - format!("Failed to write table data to file at path: {:?}", path) - })?; + write_json_file(&path, &event)?; } - Ok(()) } @@ -120,15 +145,17 @@ impl JsonSink { .to_primitive_string() .context("Failed to convert id_field value to string")?, ); - if path.exists() { + + let data = if path.exists() { + let mut data: Map = read_json_file(&path)?; + for (key, value) in fields_to_json_array(event.fields.clone()) { + data.insert(key, value); + } + data } else { - let file = std::fs::File::create(&path) - .with_context(|| format!("Failed to create record file at path: {:?}", path))?; - let json = to_json_object(event.fields.clone()); - serde_json::to_writer_pretty(file, &json).with_context(|| { - format!("Failed to write record data to file at path: {:?}", path) - })?; - } + to_json_object(event.fields.clone()) + }; + write_json_file(&path, &data)?; Ok(()) } diff --git a/crates/sinks/torii-sink-sqlite/src/lib.rs b/crates/sinks/torii-sink-sqlite/src/lib.rs index d06754a..2ea8dea 100644 --- a/crates/sinks/torii-sink-sqlite/src/lib.rs +++ b/crates/sinks/torii-sink-sqlite/src/lib.rs @@ -13,7 +13,10 @@ use introspect_types::ColumnDef; use introspect_value::{Field, Value}; use serde::{Deserialize, Serialize}; use serde_json::Value as JsonValue; -use sqlx::sqlite::{SqliteArguments, SqliteConnectOptions, SqlitePoolOptions}; +use sqlx::{ + sqlite::{SqliteArguments, SqliteConnectOptions, SqlitePoolOptions}, + Sqlite, Transaction, +}; use sqlx::{Arguments, Row, SqlitePool}; use tokio::sync::RwLock; use torii_core::{ @@ -233,7 +236,11 @@ impl SqliteSink { Ok(()) } - async fn persist_schema(&self, schema: &TableSchema) -> Result<()> { + async fn persist_schema( + &self, + tx: &mut Transaction<'_, Sqlite>, + schema: &TableSchema, + ) -> Result<()> { let schema_json = serde_json::to_string(&schema.declare)?; sqlx::query( r#" @@ -244,12 +251,16 @@ impl SqliteSink { ) .bind(schema.table_name()) .bind(schema_json) - .execute(&self.pool) + .execute(&mut **tx) .await?; Ok(()) } - async fn ensure_table(&self, schema: &TableSchema) -> Result<()> { + async fn ensure_table( + &self, + tx: &mut Transaction<'_, Sqlite>, + schema: &TableSchema, + ) -> Result<()> { let table_ident = quote_ident(schema.table_name()); let pk_ident = quote_ident(&schema.id_column().name); let columns = schema.all_columns(); @@ -263,7 +274,7 @@ impl SqliteSink { "CREATE TABLE IF NOT EXISTS {} ({}, PRIMARY KEY ({}))", table_ident, column_defs, pk_ident ); - sqlx::query(&create_sql).execute(&self.pool).await?; + sqlx::query(&create_sql).execute(&mut **tx).await?; let pragma_sql = format!("PRAGMA table_info({})", table_ident); let rows = sqlx::query(&pragma_sql).fetch_all(&self.pool).await?; @@ -283,13 +294,17 @@ impl SqliteSink { quote_ident(&column.name), column.sql_type.as_sql() ); - sqlx::query(&alter_sql).execute(&self.pool).await?; + sqlx::query(&alter_sql).execute(&mut **tx).await?; } Ok(()) } - async fn load_schema(&self, storage_name: &str) -> Result> { + async fn load_schema( + &self, + tx: &mut Transaction<'_, Sqlite>, + storage_name: &str, + ) -> Result> { if let Some(schema) = self.schemas.read().await.get(storage_name).cloned() { return Ok(schema); } @@ -312,21 +327,26 @@ impl SqliteSink { declare, storage_name.to_string(), )?); - self.ensure_table(&schema).await?; + self.ensure_table(tx, &schema).await?; let mut cache = self.schemas.write().await; cache.insert(storage_name.to_string(), schema.clone()); Ok(schema) } - async fn handle_declare(&self, env: &Envelope, event: &DeclareTableV1) -> Result<()> { + async fn handle_declare( + &self, + tx: &mut Transaction<'_, Sqlite>, + env: &Envelope, + event: &DeclareTableV1, + ) -> Result<()> { let storage_name = self.storage_table_name(&env.raw.from_address, event.name.as_str()); let schema = Arc::new(TableSchema::from_declare( event.clone(), storage_name.clone(), )?); - self.persist_schema(&schema).await?; - self.ensure_table(&schema).await?; + self.persist_schema(tx, &schema).await?; + self.ensure_table(tx, &schema).await?; { let mut cache = self.schemas.write().await; @@ -345,12 +365,13 @@ impl SqliteSink { async fn handle_update_record( &self, + tx: &mut Transaction<'_, Sqlite>, env: &Envelope, event: &UpdateRecordFieldsV1, ) -> Result<()> { let storage_name = self.storage_table_name(&env.raw.from_address, event.table_name.as_str()); - let schema = self.load_schema(&storage_name).await?; + let schema = self.load_schema(tx, &storage_name).await?; let id_value = format_id_field(&event.id_field)?; let column_types: HashMap<_, _> = schema @@ -433,7 +454,7 @@ impl SqliteSink { sql.push_str(&format!(" ON CONFLICT({}) DO NOTHING", pk_ident)); } - sqlx::query_with(&sql, args).execute(&self.pool).await?; + sqlx::query_with(&sql, args).execute(&mut **tx).await?; tracing::debug!( sink = %self.label, @@ -446,7 +467,12 @@ impl SqliteSink { Ok(()) } - async fn handle_erc20(&self, env: &Envelope, event: &Erc20Transfer) -> Result<()> { + async fn handle_erc20( + &self, + tx: &mut Transaction<'_, Sqlite>, + env: &Envelope, + event: &Erc20Transfer, + ) -> Result<()> { let contract = felt_to_padded_hex(&event.contract); let from = felt_to_padded_hex(&event.from); let to = felt_to_padded_hex(&event.to); @@ -464,13 +490,18 @@ impl SqliteSink { .bind(from) .bind(to) .bind(amount) - .execute(&self.pool) + .execute(&mut **tx) .await?; Ok(()) } - async fn handle_erc721(&self, env: &Envelope, event: &Erc721Transfer) -> Result<()> { + async fn handle_erc721( + &self, + tx: &mut Transaction<'_, Sqlite>, + env: &Envelope, + event: &Erc721Transfer, + ) -> Result<()> { let contract = felt_to_padded_hex(&event.contract); let from = felt_to_padded_hex(&event.from); let to = felt_to_padded_hex(&event.to); @@ -488,7 +519,7 @@ impl SqliteSink { .bind(from) .bind(to) .bind(token_id) - .execute(&self.pool) + .execute(&mut **tx) .await?; Ok(()) @@ -502,25 +533,27 @@ impl Sink for SqliteSink { } async fn handle_batch(&self, batch: Batch) -> Result<()> { + let mut tx = self.pool.begin().await?; for env in &batch.items { if env.type_id == DeclareTableV1::TYPE_ID { if let Some(event) = env.downcast::() { - self.handle_declare(env, event).await?; + self.handle_declare(&mut tx, env, event).await?; } } else if env.type_id == UpdateRecordFieldsV1::TYPE_ID { if let Some(event) = env.downcast::() { - self.handle_update_record(env, event).await?; + self.handle_update_record(&mut tx, env, event).await?; } } else if env.type_id == Erc20Transfer::TYPE_ID { if let Some(event) = env.downcast::() { - self.handle_erc20(env, event).await?; + self.handle_erc20(&mut tx, env, event).await?; } } else if env.type_id == Erc721Transfer::TYPE_ID { if let Some(event) = env.downcast::() { - self.handle_erc721(env, event).await?; + self.handle_erc721(&mut tx, env, event).await?; } } } + tx.commit().await?; tracing::info!(sink = %self.label, processed = batch.items.len(), "sqlite sink processed batch"); Ok(()) } diff --git a/crates/types/dojo-types-manager/src/lib.rs b/crates/types/dojo-types-manager/src/lib.rs index 30c2fa6..818ba9e 100644 --- a/crates/types/dojo-types-manager/src/lib.rs +++ b/crates/types/dojo-types-manager/src/lib.rs @@ -9,7 +9,7 @@ use std::collections::HashMap; use std::fs; use std::ops::Deref; -use std::path::{Path, PathBuf}; +use std::path::PathBuf; use std::sync::RwLock; use thiserror::Error; @@ -195,7 +195,7 @@ pub struct JsonStore { } impl JsonStore { - pub fn new(path: &Path) -> Self { + pub fn new(path: &PathBuf) -> Self { if !path.exists() { std::fs::create_dir_all(path).expect("Unable to create directory"); } @@ -243,7 +243,7 @@ impl StoreTrait for JsonStore { type Error = serde_json::Error; fn dump(&self, table_id: Felt, data: &Self::Table) -> Result<(), Self::Error> { let file_path = self.path.join(felt_to_json_file_name(&table_id)); - std::fs::write(file_path, serde_json::to_string(data).unwrap()) + std::fs::write(file_path, serde_json::to_string_pretty(data).unwrap()) .expect("Unable to write file"); Ok(()) } diff --git a/crates/utils/Cargo.toml b/crates/utils/Cargo.toml new file mode 100644 index 0000000..8afea76 --- /dev/null +++ b/crates/utils/Cargo.toml @@ -0,0 +1,19 @@ +[package] +name = "torii-utils" +version = "0.1.0" +edition = "2021" +description = "Event type manager for Torii" +authors = ["Torii Runtime "] +license = "Apache-2.0" + +[dependencies] +serde.workspace = true +starknet-types-core.workspace = true +dojo-introspect-utils.workspace = true +introspect-types.workspace = true +introspect-events.workspace = true +introspect-value.workspace = true +serde_json.workspace = true +starknet.workspace = true +anyhow.workspace = true +thiserror.workspace = true diff --git a/crates/utils/src/json.rs b/crates/utils/src/json.rs new file mode 100644 index 0000000..61b7a98 --- /dev/null +++ b/crates/utils/src/json.rs @@ -0,0 +1,21 @@ +use std::{fs, path::PathBuf}; + +use serde::Deserialize; +use thiserror::Error; + +#[derive(Debug, Error)] +pub enum JsonFsErrors { + #[error("IO Error: {0}")] + IoError(#[from] std::io::Error), + #[error("JSON Deserialize Error: {0}")] + JsonDeserializeError(#[from] serde_json::Error), +} + +pub fn read_json_file(path: &PathBuf) -> Result +where + T: for<'de> Deserialize<'de>, +{ + let data = fs::read_to_string(path)?; + let value = serde_json::from_str(&data)?; + Ok(value) +} diff --git a/crates/utils/src/lib.rs b/crates/utils/src/lib.rs new file mode 100644 index 0000000..7fd6688 --- /dev/null +++ b/crates/utils/src/lib.rs @@ -0,0 +1,2 @@ +mod json; +pub use json::{read_json_file, JsonFsErrors}; diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..aed9d73 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,1466 @@ +{ + "name": "torii-core", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "dependencies": { + "camelcase": "^8.0.0", + "case": "^1.6.3", + "command-line-args": "^6.0.1", + "dotenv": "^16.4.5", + "js-toml": "^1.0.1", + "pascal-case": "^3.1.2", + "requirejs": "^2.3.7", + "smol-toml": "^1.4.1", + "starknet": "^8.5.3", + "toml": "^3.0.0", + "web3-eth-accounts": "^4.3.1", + "yargs": "^18.0.0" + } + }, + "node_modules/@babel/runtime-corejs3": { + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.28.4.tgz", + "integrity": "sha512-h7iEYiW4HebClDEhtvFObtPmIvrd1SSfpI9EhOeKk4CtIK/ngBWFpuhCzhdmRKtg71ylcue+9I6dv54XYO1epQ==", + "license": "MIT", + "dependencies": { + "core-js-pure": "^3.43.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@chevrotain/cst-dts-gen": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/@chevrotain/cst-dts-gen/-/cst-dts-gen-11.0.3.tgz", + "integrity": "sha512-BvIKpRLeS/8UbfxXxgC33xOumsacaeCKAjAeLyOn7Pcp95HiRbrpl14S+9vaZLolnbssPIUuiUd8IvgkRyt6NQ==", + "license": "Apache-2.0", + "dependencies": { + "@chevrotain/gast": "11.0.3", + "@chevrotain/types": "11.0.3", + "lodash-es": "4.17.21" + } + }, + "node_modules/@chevrotain/gast": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/@chevrotain/gast/-/gast-11.0.3.tgz", + "integrity": "sha512-+qNfcoNk70PyS/uxmj3li5NiECO+2YKZZQMbmjTqRI3Qchu8Hig/Q9vgkHpI3alNjr7M+a2St5pw5w5F6NL5/Q==", + "license": "Apache-2.0", + "dependencies": { + "@chevrotain/types": "11.0.3", + "lodash-es": "4.17.21" + } + }, + "node_modules/@chevrotain/regexp-to-ast": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/@chevrotain/regexp-to-ast/-/regexp-to-ast-11.0.3.tgz", + "integrity": "sha512-1fMHaBZxLFvWI067AVbGJav1eRY7N8DDvYCTwGBiE/ytKBgP8azTdgyrKyWZ9Mfh09eHWb5PgTSO8wi7U824RA==", + "license": "Apache-2.0" + }, + "node_modules/@chevrotain/types": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/@chevrotain/types/-/types-11.0.3.tgz", + "integrity": "sha512-gsiM3G8b58kZC2HaWR50gu6Y1440cHiJ+i3JUvcp/35JchYejb2+5MVeJK0iKThYpAa/P2PYFV4hoi44HD+aHQ==", + "license": "Apache-2.0" + }, + "node_modules/@chevrotain/utils": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/@chevrotain/utils/-/utils-11.0.3.tgz", + "integrity": "sha512-YslZMgtJUyuMbZ+aKvfF3x1f5liK4mWNxghFRv7jqRR9C3R3fAOGTTKvxXDa2Y1s9zSbcpuO0cAxDYsc9SrXoQ==", + "license": "Apache-2.0" + }, + "node_modules/@ethereumjs/rlp": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@ethereumjs/rlp/-/rlp-4.0.1.tgz", + "integrity": "sha512-tqsQiBQDQdmPWE1xkkBq4rlSW5QZpLOUJ5RJh2/9fug+q9tnUhuZoVLk7s0scUIKTOzEtR72DFBXI4WiZcMpvw==", + "license": "MPL-2.0", + "bin": { + "rlp": "bin/rlp" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@noble/curves": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.7.0.tgz", + "integrity": "sha512-UTMhXK9SeDhFJVrHeUJ5uZlI6ajXg10O6Ddocf9S6GjbSBVZsJo88HzKwXznNfGpMTRDyJkqMjNDPYgf0qFWnw==", + "license": "MIT", + "dependencies": { + "@noble/hashes": "1.6.0" + }, + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@noble/curves/node_modules/@noble/hashes": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.6.0.tgz", + "integrity": "sha512-YUULf0Uk4/mAA89w+k3+yUYh6NrEvxZa5T6SY3wlMvE2chHkxFUUIDI8/XW1QSC357iA5pSnqt7XEhvFOqmDyQ==", + "license": "MIT", + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@noble/hashes": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.6.1.tgz", + "integrity": "sha512-pq5D8h10hHBjyqX+cfBm0i8JUXJ0UhczFc4r74zbuT9XgewFo2E3J1cOaGtdZynILNmQ685YWGzGE1Zv6io50w==", + "license": "MIT", + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@scure/base": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.2.6.tgz", + "integrity": "sha512-g/nm5FgUa//MCj1gV09zTJTaM6KBAHqLN907YVQqf7zC49+DcO4B1so4ZX07Ef10Twr6nuqYEH9GEggFXA4Fmg==", + "license": "MIT", + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@scure/bip32": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.4.0.tgz", + "integrity": "sha512-sVUpc0Vq3tXCkDGYVWGIZTRfnvu8LoTDaev7vbwh0omSvVORONr960MQWdKqJDCReIEmTj3PAr73O3aoxz7OPg==", + "license": "MIT", + "dependencies": { + "@noble/curves": "~1.4.0", + "@noble/hashes": "~1.4.0", + "@scure/base": "~1.1.6" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@scure/bip32/node_modules/@noble/curves": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.4.2.tgz", + "integrity": "sha512-TavHr8qycMChk8UwMld0ZDRvatedkzWfH8IiaeGCfymOP5i0hSCozz9vHOL0nkwk7HRMlFnAiKpS2jrUmSybcw==", + "license": "MIT", + "dependencies": { + "@noble/hashes": "1.4.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@scure/bip32/node_modules/@noble/hashes": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.4.0.tgz", + "integrity": "sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==", + "license": "MIT", + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@scure/bip32/node_modules/@scure/base": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.9.tgz", + "integrity": "sha512-8YKhl8GHiNI/pU2VMaofa2Tor7PJRAjwQLBBuilkJ9L5+13yVbC7JO/wS7piioAvPSwR3JKM1IJ/u4xQzbcXKg==", + "license": "MIT", + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@scure/bip39": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.3.0.tgz", + "integrity": "sha512-disdg7gHuTDZtY+ZdkmLpPCk7fxZSu3gBiEGuoC1XYxv9cGx3Z6cpTggCgW6odSOOIXCiDjuGejW+aJKCY/pIQ==", + "license": "MIT", + "dependencies": { + "@noble/hashes": "~1.4.0", + "@scure/base": "~1.1.6" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@scure/bip39/node_modules/@noble/hashes": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.4.0.tgz", + "integrity": "sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==", + "license": "MIT", + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@scure/bip39/node_modules/@scure/base": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.9.tgz", + "integrity": "sha512-8YKhl8GHiNI/pU2VMaofa2Tor7PJRAjwQLBBuilkJ9L5+13yVbC7JO/wS7piioAvPSwR3JKM1IJ/u4xQzbcXKg==", + "license": "MIT", + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@scure/starknet": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@scure/starknet/-/starknet-1.1.0.tgz", + "integrity": "sha512-83g3M6Ix2qRsPN4wqLDqiRZ2GBNbjVWfboJE/9UjfG+MHr6oDSu/CWgy8hsBSJejr09DkkL+l0Ze4KVrlCIdtQ==", + "license": "MIT", + "dependencies": { + "@noble/curves": "~1.7.0", + "@noble/hashes": "~1.6.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@starknet-io/starknet-types-08": { + "name": "@starknet-io/types-js", + "version": "0.8.4", + "resolved": "https://registry.npmjs.org/@starknet-io/types-js/-/types-js-0.8.4.tgz", + "integrity": "sha512-0RZ3TZHcLsUTQaq1JhDSCM8chnzO4/XNsSCozwDET64JK5bjFDIf2ZUkta+tl5Nlbf4usoU7uZiDI/Q57kt2SQ==", + "license": "MIT" + }, + "node_modules/@starknet-io/starknet-types-09": { + "name": "@starknet-io/types-js", + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/@starknet-io/types-js/-/types-js-0.9.2.tgz", + "integrity": "sha512-vWOc0FVSn+RmabozIEWcEny1I73nDGTvOrLYJsR1x7LGA3AZmqt4i/aW69o/3i2NN5CVP8Ok6G1ayRQJKye3Wg==", + "license": "MIT" + }, + "node_modules/abi-wan-kanabi": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/abi-wan-kanabi/-/abi-wan-kanabi-2.2.4.tgz", + "integrity": "sha512-0aA81FScmJCPX+8UvkXLki3X1+yPQuWxEkqXBVKltgPAK79J+NB+Lp5DouMXa7L6f+zcRlIA/6XO7BN/q9fnvg==", + "license": "ISC", + "dependencies": { + "ansicolors": "^0.3.2", + "cardinal": "^2.1.1", + "fs-extra": "^10.0.0", + "yargs": "^17.7.2" + }, + "bin": { + "generate": "dist/generate.js" + } + }, + "node_modules/abi-wan-kanabi/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/abi-wan-kanabi/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/abi-wan-kanabi/node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/abi-wan-kanabi/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT" + }, + "node_modules/abi-wan-kanabi/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/abi-wan-kanabi/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/abi-wan-kanabi/node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/abi-wan-kanabi/node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "license": "MIT", + "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" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/abi-wan-kanabi/node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/ansicolors": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/ansicolors/-/ansicolors-0.3.2.tgz", + "integrity": "sha512-QXu7BPrP29VllRxH8GwB7x5iX5qWKAAMLqKQGWTeLWVlNHNOpVMJ91dsxQAIWXpjuW5wqvxu3Jd/nRjrJ+0pqg==", + "license": "MIT" + }, + "node_modules/array-back": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-6.2.2.tgz", + "integrity": "sha512-gUAZ7HPyb4SJczXAMUXMGAvI976JoK3qEx9v1FTmeYuJj0IBiaKttG1ydtGKdkfqWkIkouke7nG8ufGy77+Cvw==", + "license": "MIT", + "engines": { + "node": ">=12.17" + } + }, + "node_modules/available-typed-arrays": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "license": "MIT", + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/call-bind": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", + "integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.0", + "es-define-property": "^1.0.0", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/camelcase": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-8.0.0.tgz", + "integrity": "sha512-8WB3Jcas3swSvjIeA2yvCJ+Miyz5l1ZmB6HFb9R1317dt9LCQoswg/BGrmAmkWVEszSrrg4RwmO46qIm2OEnSA==", + "license": "MIT", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cardinal": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/cardinal/-/cardinal-2.1.1.tgz", + "integrity": "sha512-JSr5eOgoEymtYHBjNWyjrMqet9Am2miJhlfKNdqLp6zoeAh0KN5dRAcxlecj5mAJrmQomgiOBj35xHLrFjqBpw==", + "license": "MIT", + "dependencies": { + "ansicolors": "~0.3.2", + "redeyed": "~2.1.0" + }, + "bin": { + "cdl": "bin/cdl.js" + } + }, + "node_modules/case": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/case/-/case-1.6.3.tgz", + "integrity": "sha512-mzDSXIPaFwVDvZAHqZ9VlbyF4yyXRuX6IvB06WvPYkqJVO24kX1PPhv9bfpKNFZyxYFmmgo03HUiD8iklmJYRQ==", + "license": "(MIT OR GPL-3.0-or-later)", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/chevrotain": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/chevrotain/-/chevrotain-11.0.3.tgz", + "integrity": "sha512-ci2iJH6LeIkvP9eJW6gpueU8cnZhv85ELY8w8WiFtNjMHA5ad6pQLaJo9mEly/9qUyCpvqX8/POVUTf18/HFdw==", + "license": "Apache-2.0", + "dependencies": { + "@chevrotain/cst-dts-gen": "11.0.3", + "@chevrotain/gast": "11.0.3", + "@chevrotain/regexp-to-ast": "11.0.3", + "@chevrotain/types": "11.0.3", + "@chevrotain/utils": "11.0.3", + "lodash-es": "4.17.21" + } + }, + "node_modules/cliui": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-9.0.1.tgz", + "integrity": "sha512-k7ndgKhwoQveBL+/1tqGJYNz097I7WOvwbmmU2AR5+magtbjPWQTS1C5vzGkBC8Ym8UWRzfKUzUUqFLypY4Q+w==", + "license": "ISC", + "dependencies": { + "string-width": "^7.2.0", + "strip-ansi": "^7.1.0", + "wrap-ansi": "^9.0.0" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "license": "MIT" + }, + "node_modules/command-line-args": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/command-line-args/-/command-line-args-6.0.1.tgz", + "integrity": "sha512-Jr3eByUjqyK0qd8W0SGFW1nZwqCaNCtbXjRo2cRJC1OYxWl3MZ5t1US3jq+cO4sPavqgw4l9BMGX0CBe+trepg==", + "license": "MIT", + "dependencies": { + "array-back": "^6.2.2", + "find-replace": "^5.0.2", + "lodash.camelcase": "^4.3.0", + "typical": "^7.2.0" + }, + "engines": { + "node": ">=12.20" + }, + "peerDependencies": { + "@75lb/nature": "latest" + }, + "peerDependenciesMeta": { + "@75lb/nature": { + "optional": true + } + } + }, + "node_modules/core-js-pure": { + "version": "3.46.0", + "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.46.0.tgz", + "integrity": "sha512-NMCW30bHNofuhwLhYPt66OLOKTMbOhgTTatKVbaQC3KRHpTCiRIBYvtshr+NBYSnBxwAFhjW/RfJ0XbIjS16rw==", + "hasInstallScript": true, + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/crc-32": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz", + "integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==", + "license": "Apache-2.0", + "bin": { + "crc32": "bin/crc32.njs" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/dotenv": { + "version": "16.6.1", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.6.1.tgz", + "integrity": "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/emoji-regex": { + "version": "10.6.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz", + "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==", + "license": "MIT" + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "license": "BSD-2-Clause", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/ethereum-cryptography": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-2.2.1.tgz", + "integrity": "sha512-r/W8lkHSiTLxUxW8Rf3u4HGB0xQweG2RyETjywylKZSzLWoWAijRz8WCuOtJ6wah+avllXBqZuk29HCCvhEIRg==", + "license": "MIT", + "dependencies": { + "@noble/curves": "1.4.2", + "@noble/hashes": "1.4.0", + "@scure/bip32": "1.4.0", + "@scure/bip39": "1.3.0" + } + }, + "node_modules/ethereum-cryptography/node_modules/@noble/curves": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.4.2.tgz", + "integrity": "sha512-TavHr8qycMChk8UwMld0ZDRvatedkzWfH8IiaeGCfymOP5i0hSCozz9vHOL0nkwk7HRMlFnAiKpS2jrUmSybcw==", + "license": "MIT", + "dependencies": { + "@noble/hashes": "1.4.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/ethereum-cryptography/node_modules/@noble/hashes": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.4.0.tgz", + "integrity": "sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==", + "license": "MIT", + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/eventemitter3": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", + "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", + "license": "MIT" + }, + "node_modules/find-replace": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/find-replace/-/find-replace-5.0.2.tgz", + "integrity": "sha512-Y45BAiE3mz2QsrN2fb5QEtO4qb44NcS7en/0y9PEVsg351HsLeVclP8QPMH79Le9sH3rs5RSwJu99W0WPZO43Q==", + "license": "MIT", + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@75lb/nature": "latest" + }, + "peerDependenciesMeta": { + "@75lb/nature": { + "optional": true + } + } + }, + "node_modules/for-each": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz", + "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==", + "license": "MIT", + "dependencies": { + "is-callable": "^1.2.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/generator-function": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/generator-function/-/generator-function-2.0.1.tgz", + "integrity": "sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-east-asian-width": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.4.0.tgz", + "integrity": "sha512-QZjmEOC+IT1uk6Rx0sX22V6uHWVwbdbxf1faPqJ1QhLdGgsRGCZoyaQBm/piRdJy/D2um6hM1UP7ZEeQ4EkP+Q==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "license": "ISC" + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" + }, + "node_modules/is-arguments": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.2.0.tgz", + "integrity": "sha512-7bVbi0huj/wrIAOzb8U1aszg9kdi3KN/CyU19CTI7tAoZYEZoL9yCDXpbXN+uPsuWnP02cyug1gleqq+TU+YCA==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-generator-function": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.2.tgz", + "integrity": "sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.4", + "generator-function": "^2.0.0", + "get-proto": "^1.0.1", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-regex": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", + "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz", + "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==", + "license": "MIT", + "dependencies": { + "which-typed-array": "^1.1.16" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/js-toml": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/js-toml/-/js-toml-1.0.2.tgz", + "integrity": "sha512-/7IQ//bzn2a/5IDazPUNzlW7bsjxS51cxciYZDR+Z+3Le60yzT0YfI8KOWqTtBcZkXXVklhWd2OuGd8ZksB0wQ==", + "license": "MIT", + "dependencies": { + "chevrotain": "^11.0.3", + "xregexp": "^5.1.1" + } + }, + "node_modules/jsonfile": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", + "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/lodash-es": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", + "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==", + "license": "MIT" + }, + "node_modules/lodash.camelcase": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", + "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==", + "license": "MIT" + }, + "node_modules/lossless-json": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lossless-json/-/lossless-json-4.3.0.tgz", + "integrity": "sha512-ToxOC+SsduRmdSuoLZLYAr5zy1Qu7l5XhmPWM3zefCZ5IcrzW/h108qbJUKfOlDlhvhjUK84+8PSVX0kxnit0g==", + "license": "MIT" + }, + "node_modules/lower-case": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", + "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", + "license": "MIT", + "dependencies": { + "tslib": "^2.0.3" + } + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/no-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", + "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", + "license": "MIT", + "dependencies": { + "lower-case": "^2.0.2", + "tslib": "^2.0.3" + } + }, + "node_modules/pako": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/pako/-/pako-2.1.0.tgz", + "integrity": "sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug==", + "license": "(MIT AND Zlib)" + }, + "node_modules/pascal-case": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz", + "integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==", + "license": "MIT", + "dependencies": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/possible-typed-array-names": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", + "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/redeyed": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/redeyed/-/redeyed-2.1.1.tgz", + "integrity": "sha512-FNpGGo1DycYAdnrKFxCMmKYgo/mILAqtRYbkdQD8Ep/Hk2PQ5+aEAEx+IU713RTDmuBaH0c8P5ZozurNu5ObRQ==", + "license": "MIT", + "dependencies": { + "esprima": "~4.0.0" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/requirejs": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/requirejs/-/requirejs-2.3.7.tgz", + "integrity": "sha512-DouTG8T1WanGok6Qjg2SXuCMzszOo0eHeH9hDZ5Y4x8Je+9JB38HdTLT4/VA8OaUhBa0JPVHJ0pyBkM1z+pDsw==", + "license": "MIT", + "bin": { + "r_js": "bin/r.js", + "r.js": "bin/r.js" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/safe-regex-test": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz", + "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "is-regex": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/smol-toml": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/smol-toml/-/smol-toml-1.4.2.tgz", + "integrity": "sha512-rInDH6lCNiEyn3+hH8KVGFdbjc099j47+OSgbMrfDYX1CmXLfdKd7qi6IfcWj2wFxvSVkuI46M+wPGYfEOEj6g==", + "license": "BSD-3-Clause", + "engines": { + "node": ">= 18" + }, + "funding": { + "url": "https://github.com/sponsors/cyyynthia" + } + }, + "node_modules/starknet": { + "version": "8.5.5", + "resolved": "https://registry.npmjs.org/starknet/-/starknet-8.5.5.tgz", + "integrity": "sha512-YbAoOUx8cGcpaCPt/KuIYNyQIEWNr1iUJFVibpaxg/C8+ubAClqy6U498HgCVbxMbTg6UaYMc6xnh0RpeMYlcA==", + "license": "MIT", + "dependencies": { + "@noble/curves": "~1.7.0", + "@noble/hashes": "~1.6.0", + "@scure/base": "~1.2.1", + "@scure/starknet": "1.1.0", + "@starknet-io/starknet-types-08": "npm:@starknet-io/types-js@~0.8.4", + "@starknet-io/starknet-types-09": "npm:@starknet-io/types-js@~0.9.1", + "abi-wan-kanabi": "2.2.4", + "lossless-json": "^4.2.0", + "pako": "^2.0.4", + "ts-mixer": "^6.0.3" + }, + "engines": { + "node": ">=22" + } + }, + "node_modules/string-width": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/strip-ansi": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", + "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/toml": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/toml/-/toml-3.0.0.tgz", + "integrity": "sha512-y/mWCZinnvxjTKYhJ+pYxwD0mRLVvOtdS2Awbgxln6iEnt4rk0yBxeSBHkGJcPucRiG0e55mwWp+g/05rsrd6w==", + "license": "MIT" + }, + "node_modules/ts-mixer": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/ts-mixer/-/ts-mixer-6.0.4.tgz", + "integrity": "sha512-ufKpbmrugz5Aou4wcr5Wc1UUFWOLhq+Fm6qa6P0w0K5Qw2yhaUoiWszhCVuNQyNwrlGiscHOmqYoAox1PtvgjA==", + "license": "MIT" + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/typical": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/typical/-/typical-7.3.0.tgz", + "integrity": "sha512-ya4mg/30vm+DOWfBg4YK3j2WD6TWtRkCbasOJr40CseYENzCUby/7rIvXA99JGsQHeNxLbnXdyLLxKSv3tauFw==", + "license": "MIT", + "engines": { + "node": ">=12.17" + } + }, + "node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/util": { + "version": "0.12.5", + "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz", + "integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "is-arguments": "^1.0.4", + "is-generator-function": "^1.0.7", + "is-typed-array": "^1.1.3", + "which-typed-array": "^1.1.2" + } + }, + "node_modules/web3-errors": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/web3-errors/-/web3-errors-1.3.1.tgz", + "integrity": "sha512-w3NMJujH+ZSW4ltIZZKtdbkbyQEvBzyp3JRn59Ckli0Nz4VMsVq8aF1bLWM7A2kuQ+yVEm3ySeNU+7mSRwx7RQ==", + "license": "LGPL-3.0", + "dependencies": { + "web3-types": "^1.10.0" + }, + "engines": { + "node": ">=14", + "npm": ">=6.12.0" + } + }, + "node_modules/web3-eth-accounts": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/web3-eth-accounts/-/web3-eth-accounts-4.3.1.tgz", + "integrity": "sha512-rTXf+H9OKze6lxi7WMMOF1/2cZvJb2AOnbNQxPhBDssKOllAMzLhg1FbZ4Mf3lWecWfN6luWgRhaeSqO1l+IBQ==", + "license": "LGPL-3.0", + "dependencies": { + "@ethereumjs/rlp": "^4.0.1", + "crc-32": "^1.2.2", + "ethereum-cryptography": "^2.0.0", + "web3-errors": "^1.3.1", + "web3-types": "^1.10.0", + "web3-utils": "^4.3.3", + "web3-validator": "^2.0.6" + }, + "engines": { + "node": ">=14", + "npm": ">=6.12.0" + } + }, + "node_modules/web3-types": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/web3-types/-/web3-types-1.10.0.tgz", + "integrity": "sha512-0IXoaAFtFc8Yin7cCdQfB9ZmjafrbP6BO0f0KT/khMhXKUpoJ6yShrVhiNpyRBo8QQjuOagsWzwSK2H49I7sbw==", + "license": "LGPL-3.0", + "engines": { + "node": ">=14", + "npm": ">=6.12.0" + } + }, + "node_modules/web3-utils": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-4.3.3.tgz", + "integrity": "sha512-kZUeCwaQm+RNc2Bf1V3BYbF29lQQKz28L0y+FA4G0lS8IxtJVGi5SeDTUkpwqqkdHHC7JcapPDnyyzJ1lfWlOw==", + "license": "LGPL-3.0", + "dependencies": { + "ethereum-cryptography": "^2.0.0", + "eventemitter3": "^5.0.1", + "web3-errors": "^1.3.1", + "web3-types": "^1.10.0", + "web3-validator": "^2.0.6" + }, + "engines": { + "node": ">=14", + "npm": ">=6.12.0" + } + }, + "node_modules/web3-validator": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/web3-validator/-/web3-validator-2.0.6.tgz", + "integrity": "sha512-qn9id0/l1bWmvH4XfnG/JtGKKwut2Vokl6YXP5Kfg424npysmtRLe9DgiNBM9Op7QL/aSiaA0TVXibuIuWcizg==", + "license": "LGPL-3.0", + "dependencies": { + "ethereum-cryptography": "^2.0.0", + "util": "^0.12.5", + "web3-errors": "^1.2.0", + "web3-types": "^1.6.0", + "zod": "^3.21.4" + }, + "engines": { + "node": ">=14", + "npm": ">=6.12.0" + } + }, + "node_modules/which-typed-array": { + "version": "1.1.19", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.19.tgz", + "integrity": "sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==", + "license": "MIT", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "for-each": "^0.3.5", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/wrap-ansi": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.2.tgz", + "integrity": "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.2.1", + "string-width": "^7.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/xregexp": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/xregexp/-/xregexp-5.1.2.tgz", + "integrity": "sha512-6hGgEMCGhqCTFEJbqmWrNIPqfpdirdGWkqshu7fFZddmTSfgv5Sn9D2SaKloR79s5VUiUlpwzg3CM3G6D3VIlw==", + "license": "MIT", + "dependencies": { + "@babel/runtime-corejs3": "^7.26.9" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs": { + "version": "18.0.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-18.0.0.tgz", + "integrity": "sha512-4UEqdc2RYGHZc7Doyqkrqiln3p9X2DZVxaGbwhn2pi7MrRagKaOcIKe8L3OxYcbhXLgLFUS3zAYuQjKBQgmuNg==", + "license": "MIT", + "dependencies": { + "cliui": "^9.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "string-width": "^7.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^22.0.0" + }, + "engines": { + "node": "^20.19.0 || ^22.12.0 || >=23" + } + }, + "node_modules/yargs-parser": { + "version": "22.0.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-22.0.0.tgz", + "integrity": "sha512-rwu/ClNdSMpkSrUb+d6BRsSkLUq1fmfsY6TOpYzTwvwkg1/NRG85KBy3kq++A8LKQwX6lsu+aWad+2khvuXrqw==", + "license": "ISC", + "engines": { + "node": "^20.19.0 || ^22.12.0 || >=23" + } + }, + "node_modules/zod": { + "version": "3.25.76", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", + "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..9e8ceb9 --- /dev/null +++ b/package.json @@ -0,0 +1,17 @@ +{ + "dependencies": { + "camelcase": "^8.0.0", + "case": "^1.6.3", + "command-line-args": "^6.0.1", + "dotenv": "^16.4.5", + "js-toml": "^1.0.1", + "pascal-case": "^3.1.2", + "requirejs": "^2.3.7", + "smol-toml": "^1.4.1", + "starknet": "^8.5.3", + "toml": "^3.0.0", + "web3-eth-accounts": "^4.3.1", + "yargs": "^18.0.0" + }, + "type": "module" +} diff --git a/scripts/all-contract-events.js b/scripts/all-contract-events.js new file mode 100644 index 0000000..1ec9bd1 --- /dev/null +++ b/scripts/all-contract-events.js @@ -0,0 +1,38 @@ +import { Provider } from "starknet"; +import fs from "fs"; +// const CONTRACT_ADDRESS = +// "0x02d26295d6c541d64740e1ae56abc079b82b22c35ab83985ef8bd15dc0f9edfb"; // Replace with your contract address +const CONTRACT_ADDRESS = + "0x8b4838140a3cbd36ebe64d4b5aaf56a30cc3753c928a79338bf56c53f506c5"; //Pistols +const RPC_URL = "https://starknet-mainnet.public.blastapi.io"; +// const from_block = 1376383; +const provider = new Provider({ nodeUrl: RPC_URL }); + +const dirPath = "/home/ben/tc-tests/pistols/events-2"; +const writeToFile = (data, index) => { + fs.writeFileSync( + `${dirPath}/${index.toString().padStart(4, "0")}.json`, + JSON.stringify(data, null, 2) + ); +}; +let n = 0; +let continuation_token = undefined; +while (true) { + const result = await provider.getEvents({ + continuation_token, + address: CONTRACT_ADDRESS, + chunk_size: 1024, + // from_block: { block_number: from_block }, + }); + if (result.events.length) { + writeToFile(result, n); + } + continuation_token = result.continuation_token; + console.log( + `n: ${n}, continuation_token: ${continuation_token} length: ${result.events.length}` + ); + if (continuation_token === undefined) { + break; + } + n++; +} diff --git a/scripts/get-models.js b/scripts/get-models.js new file mode 100644 index 0000000..8171796 --- /dev/null +++ b/scripts/get-models.js @@ -0,0 +1,93 @@ +import { Provider, selector, Contract } from "starknet"; +import fs from "fs"; +import * as path from "path"; + +export const resolvePath = (rpath) => { + return path.resolve(__dirname, rpath); +}; +const __dirname = process.cwd(); +// const CONTRACT_ADDRESS = +// "0x02d26295d6c541d64740e1ae56abc079b82b22c35ab83985ef8bd15dc0f9edfb"; +const CONTRACT_ADDRESS = + "0x8b4838140a3cbd36ebe64d4b5aaf56a30cc3753c928a79338bf56c53f506c5"; //Pistols +const RPC_URL = "https://starknet-mainnet.public.blastapi.io"; +const from_block = 1376382; +const provider = new Provider({ nodeUrl: RPC_URL }); +const modelRegisteredSelector = selector.getSelector("ModelRegistered"); +const eventRegisteredSelector = selector.getSelector("EventRegistered"); +const modelUpgradedSelector = selector.getSelector("ModelUpgraded"); +const eventUpgradedSelector = selector.getSelector("EventUpgraded"); +const dirPath = resolvePath("/home/ben/tc-tests/pistols/model-contracts"); + +const writeToFile = (data, index) => { + fs.writeFileSync(`${dirPath}/${index}.json`, JSON.stringify(data, null, 2)); +}; + +const getAllEvents = async (address, keys, block_number) => { + let events = []; + let continuation_token = undefined; + while (true) { + const result = await provider.getEvents({ + address, + keys, + chunk_size: 1024, + continuation_token, + from_block: { block_number }, + }); + events.push(...result.events); + continuation_token = result.continuation_token; + if (continuation_token === undefined) { + break; + } + } + return events; +}; + +const declareEvents = await getAllEvents( + CONTRACT_ADDRESS, + [[modelRegisteredSelector, eventRegisteredSelector]], + from_block +); +for (const event of declareEvents) { + const [class_hash, address] = event.data; + console.log({ class_hash, address }); + let schema = await provider.callContract({ + contractAddress: address, + entrypoint: "schema", + }); + let use_legacy_storage = true; + try { + let legacy_result = await provider.callContract({ + contractAddress: address, + entrypoint: "use_legacy_storage", + }); + use_legacy_storage = Boolean(BigInt(legacy_result[0])); + } catch (e) {} + + writeToFile({ schema, use_legacy_storage }, address); +} + +const upgradeEvents = await getAllEvents( + CONTRACT_ADDRESS, + [[modelUpgradedSelector, eventUpgradedSelector]], + from_block +); + +for (const event of upgradeEvents) { + const [class_hash, address, previous_address] = event.data; + console.log({ class_hash, address, previous_address }); + let schema = await provider.callContract({ + contractAddress: address, + entrypoint: "schema", + }); + let use_legacy_storage = true; + try { + let legacy_result = await provider.callContract({ + contractAddress: address, + entrypoint: "use_legacy_storage", + }); + console.log(legacy_result); + } catch (e) {} + + writeToFile({ schema, use_legacy_storage }, address); +} diff --git a/tests/blob-arena.tar.gz b/tests/blob-arena.tar.gz new file mode 100644 index 0000000..6fbf034 Binary files /dev/null and b/tests/blob-arena.tar.gz differ diff --git a/tests/json_test/Cargo.toml b/tests/json_test/Cargo.toml new file mode 100644 index 0000000..28852e3 --- /dev/null +++ b/tests/json_test/Cargo.toml @@ -0,0 +1,19 @@ +[package] +name = "torii-json-test" +version = "0.1.0" +edition = "2021" +description = "Introspect decoder for Torii runtime" +authors = ["Torii Runtime "] +license = "Apache-2.0" + +[dependencies] +anyhow.workspace = true +dojo-introspect-events.workspace = true +dojo-types-manager.workspace = true +resolve-path.workspace = true +starknet.workspace = true +tokio.workspace = true +torii-core.workspace = true +torii-decoder-introspect.workspace = true +torii-sink-json.workspace = true +torii-test-utils.workspace = true diff --git a/tests/json_test/src/main.rs b/tests/json_test/src/main.rs new file mode 100644 index 0000000..737a898 --- /dev/null +++ b/tests/json_test/src/main.rs @@ -0,0 +1,117 @@ +use anyhow::Error; +use dojo_introspect_events::{ + DojoEvent, EventEmitted, EventRegistered, EventUpgraded, ModelRegistered, ModelUpgraded, + StoreDelRecord, StoreSetRecord, StoreUpdateMember, StoreUpdateRecord, +}; +use dojo_types_manager::{DojoManager, JsonStore}; +use resolve_path::PathResolveExt; +use starknet::core::types::EmittedEvent; +use std::path::PathBuf; +use std::time::Instant; +use torii_core::Decoder; +use torii_decoder_introspect::IntrospectDecoder; +use torii_sink_json::JsonSink; +use torii_test_utils::{EventIterator, FakeProvider}; +const DATA_PATH: &str = "~/tc-tests/pistols"; + +fn get_event_type(event: &EmittedEvent) -> (String, String) { + let selector = event.keys[0]; + if selector == ModelRegistered::SELECTOR { + ("ModelRegistered".to_string(), "Mr".to_string()) + } else if selector == ModelUpgraded::SELECTOR { + ("ModelUpgraded".to_string(), "Mu".to_string()) + } else if selector == EventRegistered::SELECTOR { + ("EventRegistered".to_string(), "Er".to_string()) + } else if selector == EventUpgraded::SELECTOR { + ("EventUpgraded".to_string(), "Eu".to_string()) + } else if selector == StoreSetRecord::SELECTOR { + ("StoreSetRecord".to_string(), "Rs".to_string()) + } else if selector == StoreUpdateRecord::SELECTOR { + ("StoreUpdateRecord".to_string(), "Ru".to_string()) + } else if selector == StoreUpdateMember::SELECTOR { + ("StoreUpdateMember".to_string(), "Fu".to_string()) + } else if selector == StoreDelRecord::SELECTOR { + ("StoreDelRecord".to_string(), "Rd".to_string()) + } else if selector == EventEmitted::SELECTOR { + ("EventEmitted".to_string(), "E".to_string()) + } else { + ("Unknown".to_string(), "Un".to_string()) + } +} + +#[tokio::main] +async fn main() { + let data_path = PathBuf::from(DATA_PATH).resolve().into_owned(); + let manager_path = data_path.join("manager"); + let model_contracts_path = data_path.join("model-contracts"); + let json_sink_path = data_path.join("json-sink"); + let events_path = data_path.join("events"); + println!("Manager Path: {manager_path:#?}"); + println!("Model Contracts Path: {model_contracts_path:#?}"); + println!("JSON Sink Path: {json_sink_path:#?}"); + println!("Events Path: {events_path:#?}"); + let manager = DojoManager::new(JsonStore::new(&manager_path)).unwrap(); + let fetcher = FakeProvider { + file_path: model_contracts_path, + }; + let decoder = IntrospectDecoder { + filter: Default::default(), + manager, + fetcher, + }; + let sink = JsonSink::new(json_sink_path, "json-sink".to_string()).unwrap(); + + let mut decoder_errors: Vec = vec![]; + let mut sink_errors: Vec = vec![]; + + let events = EventIterator::new(events_path); + let now = Instant::now(); + + for event in events { + let (name, _) = get_event_type(&event); + if name == "Unknown" { + continue; + } + match decoder.decode(&event).await { + Ok(envelope) => match sink.handle_envelope(&envelope) { + Err(err) => { + println!("\nError Handling event: {name:#?}"); + println!("Error: {err:#?}"); + sink_errors.push(err); + } + _ => (), + }, + Err(err) => { + println!("\nError Decoding event: {name:#?}"); + println!("Error: {:#?}", &err); + println!("---------------"); + println!("{event:#?}"); + println!("---------------"); + decoder_errors.push(err); + } + } + } + let elapsed = now.elapsed(); + println!( + "\nElapsed: {elapsed:.2?} decoder errors: {} sink errors: {}", + decoder_errors.len(), + sink_errors.len() + ); + println!("Decoder Errors:"); + println!("{:#?}", decoder_errors); + println!("Sink Errors:"); + println!("{:#?}", sink_errors); +} + +// fn main() { +// let contracts_path = +// canonicalize(PathBuf::from("./test-data/blob-arena/model-contracts")).unwrap(); +// let schema = read_model_schema( +// &contracts_path, +// Felt::from_hex_unchecked( +// "0x39da8317e138fead2fe5a894ab103cd73a9173707183a8b7c404533ac4d301d", +// ), +// ) +// .unwrap(); +// println!("{schema:#?}"); +// } diff --git a/tests/pistols.tar.gz b/tests/pistols.tar.gz new file mode 100644 index 0000000..92461b0 Binary files /dev/null and b/tests/pistols.tar.gz differ diff --git a/tests/sqlite_test/Cargo.toml b/tests/sqlite_test/Cargo.toml new file mode 100644 index 0000000..c262e57 --- /dev/null +++ b/tests/sqlite_test/Cargo.toml @@ -0,0 +1,20 @@ +[package] +name = "torii-sqlite-test" +version = "0.1.0" +edition = "2021" +description = "Introspect decoder for Torii runtime" +authors = ["Torii Runtime "] +license = "Apache-2.0" + +[dependencies] +anyhow.workspace = true +dojo-introspect-events.workspace = true +dojo-types-manager.workspace = true +resolve-path.workspace = true +starknet.workspace = true +starknet-types-core.workspace = true +tokio.workspace = true +torii-core.workspace = true +torii-decoder-introspect.workspace = true +torii-test-utils.workspace = true +torii-sink-sqlite.workspace = true diff --git a/tests/sqlite_test/src/main.rs b/tests/sqlite_test/src/main.rs new file mode 100644 index 0000000..f9fcb4b --- /dev/null +++ b/tests/sqlite_test/src/main.rs @@ -0,0 +1,144 @@ +use anyhow::Error; +use dojo_introspect_events::{ + DojoEvent, EventEmitted, EventRegistered, EventUpgraded, ModelRegistered, ModelUpgraded, + StoreDelRecord, StoreSetRecord, StoreUpdateMember, StoreUpdateRecord, +}; +use dojo_types_manager::{DojoManager, JsonStore}; +use resolve_path::PathResolveExt; +use starknet_types_core::felt::Felt; +use std::time::Instant; +use std::{collections::HashMap, path::PathBuf}; +use torii_core::{Batch, Decoder, Sink}; +use torii_decoder_introspect::IntrospectDecoder; +use torii_sink_sqlite::SqliteSink; +use torii_test_utils::{EventIterator, FakeProvider}; +const DATA_PATH: &str = "~/tc-tests/blob-arena"; + +fn get_event_type(event: &starknet::core::types::EmittedEvent) -> (String, String) { + let selector = event.keys[0]; + if selector == ModelRegistered::SELECTOR { + ("ModelRegistered".to_string(), "Mr".to_string()) + } else if selector == ModelUpgraded::SELECTOR { + ("ModelUpgraded".to_string(), "Mu".to_string()) + } else if selector == EventRegistered::SELECTOR { + ("EventRegistered".to_string(), "Er".to_string()) + } else if selector == EventUpgraded::SELECTOR { + ("EventUpgraded".to_string(), "Eu".to_string()) + } else if selector == StoreSetRecord::SELECTOR { + ("StoreSetRecord".to_string(), "Rs".to_string()) + } else if selector == StoreUpdateRecord::SELECTOR { + ("StoreUpdateRecord".to_string(), "Ru".to_string()) + } else if selector == StoreUpdateMember::SELECTOR { + ("StoreUpdateMember".to_string(), "Fu".to_string()) + } else if selector == StoreDelRecord::SELECTOR { + ("StoreDelRecord".to_string(), "Rd".to_string()) + } else if selector == EventEmitted::SELECTOR { + ("EventEmitted".to_string(), "E".to_string()) + } else { + ("Unknown".to_string(), "Un".to_string()) + } +} + +#[tokio::main] +async fn main() { + let data_path = PathBuf::from(DATA_PATH).resolve().into_owned(); + let manager_path = data_path.join("manager"); + let model_contracts_path = data_path.join("model-contracts"); + let sql_sink_path = data_path.join("sql-sink"); + let events_path = data_path.join("events"); + println!("Manager Path: {manager_path:#?}"); + println!("Model Contracts Path: {model_contracts_path:#?}"); + println!("SQL Sink Path: {sql_sink_path:#?}"); + println!("Events Path: {events_path:#?}"); + let manager = DojoManager::new(JsonStore::new(&manager_path)).unwrap(); + let fetcher = FakeProvider { + file_path: model_contracts_path, + }; + let decoder = IntrospectDecoder { + filter: Default::default(), + manager, + fetcher, + }; + let mut contract_labels: HashMap = HashMap::new(); + contract_labels.insert( + Felt::from_hex_unchecked( + "0x2d26295d6c541d64740e1ae56abc079b82b22c35ab83985ef8bd15dc0f9edfb", + ), + "BlobArena".to_string(), + ); + let sink = SqliteSink::connect( + "sql-sink".to_string(), + &sql_sink_path.into_os_string().to_str().unwrap(), + None, + contract_labels, + ) + .await + .unwrap(); + + let mut decoder_errors: Vec = vec![]; + let mut sink_errors: Vec = vec![]; + + let mut events = EventIterator::new(events_path); + let now = Instant::now(); + let mut running = true; + while running { + let mut batch = Vec::new(); + for _ in 0..10000 { + let event = match events.next() { + Some(event) => event, + None => { + running = false; + break; + } + }; + let (name, _) = get_event_type(&event); + if name == "Unknown" { + continue; + } + match decoder.decode(&event).await { + Ok(envelope) => { + batch.push(envelope); + } + Err(err) => { + println!("\nError Decoding event: {name:#?}"); + println!("Error: {:#?}", &err); + println!("---------------"); + println!("{event:#?}"); + println!("---------------"); + decoder_errors.push(err); + } + } + } + + match sink.handle_batch(Batch { items: batch }).await { + Err(err) => { + println!("Error: {err:#?}"); + sink_errors.push(err); + } + _ => (), + } + } + let elapsed = now.elapsed(); + println!( + "\nElapsed: {elapsed:.2?} decoder errors: {} sink errors: {}", + decoder_errors.len(), + sink_errors.len() + ); + println!("Decoder Errors:"); + println!("{:#?}", decoder_errors); + println!("Sink Errors:"); + println!("{:#?}", sink_errors); +} + +// fn main() { +// let contracts_path = +// canonicalize(PathBuf::from("./test-data/blob-arena/model-contracts")).unwrap(); +// let schema = read_model_schema( +// &contracts_path, +// Felt::from_hex_unchecked( +// "0x39da8317e138fead2fe5a894ab103cd73a9173707183a8b7c404533ac4d301d", +// ), +// ) +// .unwrap(); +// println!("{schema:#?}"); +// } diff --git a/tests/test_utils/Cargo.toml b/tests/test_utils/Cargo.toml new file mode 100644 index 0000000..b44b8b7 --- /dev/null +++ b/tests/test_utils/Cargo.toml @@ -0,0 +1,23 @@ +[package] +name = "torii-test-utils" +version = "0.1.0" +edition = "2021" +description = "Test utilities for Torii runtime" +authors = ["Torii Runtime "] +license = "Apache-2.0" + +[dependencies] +alphanumeric-sort.workspace = true +anyhow.workspace = true +async-trait.workspace = true +resolve-path.workspace = true +serde.workspace = true +serde_json.workspace = true +starknet.workspace = true +tracing.workspace = true +dojo-introspect-types.workspace = true +dojo-types-manager.workspace = true +introspect-types.workspace = true +starknet-types-core.workspace = true +thiserror.workspace = true +torii-utils.workspace = true diff --git a/tests/test_utils/src/event_reader.rs b/tests/test_utils/src/event_reader.rs new file mode 100644 index 0000000..f234ef0 --- /dev/null +++ b/tests/test_utils/src/event_reader.rs @@ -0,0 +1,83 @@ +use serde::Deserialize; +use starknet::core::types::EmittedEvent; +use starknet_types_core::felt::Felt; +use std::collections::VecDeque; +use std::fs::read_dir; +use std::path::PathBuf; +use torii_utils::read_json_file; + +#[derive(Deserialize)] +pub struct Event { + block_hash: Felt, + block_number: u64, + data: Vec, + from_address: Felt, + keys: Vec, + transaction_hash: Felt, +} + +impl Into for Event { + fn into(self) -> EmittedEvent { + EmittedEvent { + block_hash: Some(self.block_hash), + block_number: Some(self.block_number), + data: self.data, + from_address: self.from_address, + keys: self.keys, + transaction_hash: self.transaction_hash, + } + } +} + +#[derive(Deserialize)] +pub struct EventBatch { + #[allow(dead_code)] + pub continuation_token: Option, + pub events: VecDeque, +} + +pub struct EventIterator { + pub events: VecDeque, + pub files: VecDeque, + #[allow(dead_code)] + pub batch: usize, + #[allow(dead_code)] + pub event: usize, +} + +impl EventIterator { + pub fn new(path: PathBuf) -> Self { + let path = path; + let mut paths = read_dir(&path) + .unwrap() + .map(|p| p.unwrap().path()) + .collect::>(); + alphanumeric_sort::sort_path_slice(&mut paths); + + Self { + events: VecDeque::new(), + files: paths.into(), + batch: 0, + event: 0, + } + } +} + +impl Iterator for EventIterator { + type Item = EmittedEvent; + + fn next(&mut self) -> Option { + self.event += 1; + match self.events.pop_front() { + Some(event) => Some(event.into()), + None => { + self.events = read_json_file::(&self.files.pop_front()?) + .unwrap() + .events; + self.batch += 1; + self.event = 0; + Some(self.events.pop_front()?.into()) + } + } + } +} diff --git a/tests/test_utils/src/lib.rs b/tests/test_utils/src/lib.rs new file mode 100644 index 0000000..622e1af --- /dev/null +++ b/tests/test_utils/src/lib.rs @@ -0,0 +1,4 @@ +mod event_reader; +mod schema_fetcher; +pub use event_reader::EventIterator; +pub use schema_fetcher::FakeProvider; diff --git a/tests/test_utils/src/schema_fetcher.rs b/tests/test_utils/src/schema_fetcher.rs new file mode 100644 index 0000000..75fbc9c --- /dev/null +++ b/tests/test_utils/src/schema_fetcher.rs @@ -0,0 +1,35 @@ +use anyhow::{Context, Result}; +use async_trait::async_trait; +use dojo_introspect_types::{DojoSchemaFetcher, DojoTypeDefSerde}; +use introspect_types::StructDef; +use serde::{Deserialize, Serialize}; +use starknet_types_core::felt::Felt; +use std::path::PathBuf; +use torii_utils::read_json_file; + +pub struct FakeProvider { + pub file_path: PathBuf, +} + +#[derive(Deserialize, Serialize)] +struct ModelContract { + schema: Vec, + use_legacy_storage: bool, +} + +fn read_model_schema(path: &PathBuf, contract_address: Felt) -> Result { + let contract: ModelContract = + read_json_file(&path.join(format!("{contract_address:#x}.json"))).unwrap(); + StructDef::dojo_deserialize( + &mut contract.schema.into_iter(), + contract.use_legacy_storage, + ) + .context("Failed to deserialize schema") +} + +#[async_trait] +impl DojoSchemaFetcher for FakeProvider { + async fn schema(&self, contract_address: Felt) -> Result { + read_model_schema(&self.file_path, contract_address) + } +}