diff --git a/Cargo.lock b/Cargo.lock
index 301a4776..31457034 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -2,12 +2,107 @@
# It is not intended for manual editing.
version = 4
+[[package]]
+name = "Inflector"
+version = "0.11.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fe438c63458706e03479442743baae6c88256498e6431708f6dfc520a26515d3"
+dependencies = [
+ "lazy_static",
+ "regex",
+]
+
[[package]]
name = "adler2"
version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa"
+[[package]]
+name = "aead"
+version = "0.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0"
+dependencies = [
+ "crypto-common",
+ "generic-array",
+]
+
+[[package]]
+name = "aes"
+version = "0.8.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0"
+dependencies = [
+ "cfg-if",
+ "cipher",
+ "cpufeatures",
+]
+
+[[package]]
+name = "aes-gcm-siv"
+version = "0.11.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ae0784134ba9375416d469ec31e7c5f9fa94405049cf08c5ce5b4698be673e0d"
+dependencies = [
+ "aead",
+ "aes",
+ "cipher",
+ "ctr",
+ "polyval",
+ "subtle",
+ "zeroize",
+]
+
+[[package]]
+name = "agave-feature-set"
+version = "2.3.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d52a2c365c0245cbb8959de725fc2b44c754b673fdf34c9a7f9d4a25c35a7bf1"
+dependencies = [
+ "ahash 0.8.12",
+ "solana-epoch-schedule",
+ "solana-hash",
+ "solana-pubkey",
+ "solana-sha256-hasher",
+ "solana-svm-feature-set",
+]
+
+[[package]]
+name = "agave-reserved-account-keys"
+version = "2.3.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8289c8a8a2ef5aa10ce49a070f360f4e035ee3410b8d8f3580fb39d8cf042581"
+dependencies = [
+ "agave-feature-set",
+ "solana-pubkey",
+ "solana-sdk-ids",
+]
+
+[[package]]
+name = "ahash"
+version = "0.7.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "891477e0c6a8957309ee5c45a6368af3ae14bb510732d2684ffa19af310920f9"
+dependencies = [
+ "getrandom 0.2.16",
+ "once_cell",
+ "version_check",
+]
+
+[[package]]
+name = "ahash"
+version = "0.8.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75"
+dependencies = [
+ "cfg-if",
+ "getrandom 0.3.4",
+ "once_cell",
+ "version_check",
+ "zerocopy",
+]
+
[[package]]
name = "aho-corasick"
version = "1.1.4"
@@ -88,6 +183,18 @@ version = "1.0.100"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61"
+[[package]]
+name = "arrayref"
+version = "0.3.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb"
+
+[[package]]
+name = "arrayvec"
+version = "0.7.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50"
+
[[package]]
name = "async-stream"
version = "0.3.6"
@@ -107,7 +214,7 @@ checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.113",
]
[[package]]
@@ -118,7 +225,7 @@ checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.113",
]
[[package]]
@@ -277,6 +384,12 @@ dependencies = [
"tower-service",
]
+[[package]]
+name = "base64"
+version = "0.12.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3441f0f7b02788e948e47f457ca01f1d7e6d92c693bc132c22b087d3141c03ff"
+
[[package]]
name = "base64"
version = "0.21.7"
@@ -289,6 +402,15 @@ version = "0.22.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
+[[package]]
+name = "bincode"
+version = "1.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad"
+dependencies = [
+ "serde",
+]
+
[[package]]
name = "bitflags"
version = "1.3.2"
@@ -301,6 +423,30 @@ version = "2.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3"
+[[package]]
+name = "blake3"
+version = "1.8.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2468ef7d57b3fb7e16b576e8377cdbde2320c60e1491e961d11da40fc4f02a2d"
+dependencies = [
+ "arrayref",
+ "arrayvec",
+ "cc",
+ "cfg-if",
+ "constant_time_eq",
+ "cpufeatures",
+ "digest 0.10.7",
+]
+
+[[package]]
+name = "block-buffer"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4"
+dependencies = [
+ "generic-array",
+]
+
[[package]]
name = "block-buffer"
version = "0.10.4"
@@ -310,15 +456,74 @@ dependencies = [
"generic-array",
]
+[[package]]
+name = "borsh"
+version = "0.10.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "115e54d64eb62cdebad391c19efc9dce4981c690c85a33a12199d99bb9546fee"
+dependencies = [
+ "borsh-derive 0.10.4",
+ "hashbrown 0.12.3",
+]
+
[[package]]
name = "borsh"
version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d1da5ab77c1437701eeff7c88d968729e7766172279eab0676857b3d63af7a6f"
dependencies = [
+ "borsh-derive 1.6.0",
"cfg_aliases",
]
+[[package]]
+name = "borsh-derive"
+version = "0.10.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "831213f80d9423998dd696e2c5345aba6be7a0bd8cd19e31c5243e13df1cef89"
+dependencies = [
+ "borsh-derive-internal",
+ "borsh-schema-derive-internal",
+ "proc-macro-crate 0.1.5",
+ "proc-macro2",
+ "syn 1.0.109",
+]
+
+[[package]]
+name = "borsh-derive"
+version = "1.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0686c856aa6aac0c4498f936d7d6a02df690f614c03e4d906d1018062b5c5e2c"
+dependencies = [
+ "once_cell",
+ "proc-macro-crate 3.5.0",
+ "proc-macro2",
+ "quote",
+ "syn 2.0.113",
+]
+
+[[package]]
+name = "borsh-derive-internal"
+version = "0.10.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "65d6ba50644c98714aa2a70d13d7df3cd75cd2b523a2b452bf010443800976b3"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 1.0.109",
+]
+
+[[package]]
+name = "borsh-schema-derive-internal"
+version = "0.10.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "276691d96f063427be83e6692b86148e488ebba9f48f77788724ca027ba3b6d4"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 1.0.109",
+]
+
[[package]]
name = "bs58"
version = "0.5.1"
@@ -334,6 +539,16 @@ version = "3.19.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5dd9dc738b7a8311c7ade152424974d8115f2cdad61e8dab8dac9f2362298510"
+[[package]]
+name = "bv"
+version = "0.11.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8834bb1d8ee5dc048ee3124f2c7c1afcc6bc9aed03f11e9dfd8c69470a5db340"
+dependencies = [
+ "feature-probe",
+ "serde",
+]
+
[[package]]
name = "bytemuck"
version = "1.25.0"
@@ -351,7 +566,7 @@ checksum = "f9abbd1bc6865053c427f7198e6af43bfdedc55ab791faed4fbd361d789575ff"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.113",
]
[[package]]
@@ -403,6 +618,16 @@ dependencies = [
"windows-link",
]
+[[package]]
+name = "cipher"
+version = "0.4.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad"
+dependencies = [
+ "crypto-common",
+ "inout",
+]
+
[[package]]
name = "clap"
version = "4.5.54"
@@ -444,7 +669,7 @@ dependencies = [
"heck",
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.113",
]
[[package]]
@@ -482,6 +707,32 @@ dependencies = [
"windows-sys 0.59.0",
]
+[[package]]
+name = "console_error_panic_hook"
+version = "0.1.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc"
+dependencies = [
+ "cfg-if",
+ "wasm-bindgen",
+]
+
+[[package]]
+name = "console_log"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e89f72f65e8501878b8a004d5a1afb780987e2ce2b4532c562e367a72c57499f"
+dependencies = [
+ "log",
+ "web-sys",
+]
+
+[[package]]
+name = "constant_time_eq"
+version = "0.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3d52eff69cd5e647efe296129160853a42795992097e8af39800e1060caeea9b"
+
[[package]]
name = "core-foundation"
version = "0.9.4"
@@ -582,6 +833,12 @@ version = "0.8.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28"
+[[package]]
+name = "crunchy"
+version = "0.2.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5"
+
[[package]]
name = "crypto-common"
version = "0.1.7"
@@ -589,9 +846,61 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a"
dependencies = [
"generic-array",
+ "rand_core 0.6.4",
"typenum",
]
+[[package]]
+name = "ctr"
+version = "0.9.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0369ee1ad671834580515889b80f2ea915f23b8be8d0daa4bbaf2ac5c7590835"
+dependencies = [
+ "cipher",
+]
+
+[[package]]
+name = "curve25519-dalek"
+version = "3.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0b9fdf9972b2bd6af2d913799d9ebc165ea4d2e65878e329d9c6b372c4491b61"
+dependencies = [
+ "byteorder",
+ "digest 0.9.0",
+ "rand_core 0.5.1",
+ "subtle",
+ "zeroize",
+]
+
+[[package]]
+name = "curve25519-dalek"
+version = "4.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be"
+dependencies = [
+ "cfg-if",
+ "cpufeatures",
+ "curve25519-dalek-derive",
+ "digest 0.10.7",
+ "fiat-crypto",
+ "rand_core 0.6.4",
+ "rustc_version",
+ "serde",
+ "subtle",
+ "zeroize",
+]
+
+[[package]]
+name = "curve25519-dalek-derive"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.113",
+]
+
[[package]]
name = "dashmap"
version = "6.1.0"
@@ -612,6 +921,12 @@ version = "2.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2a2330da5de22e8a3cb63252ce2abb30116bf5265e89c0e01bc17015ce30a476"
+[[package]]
+name = "derivation-path"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6e5c37193a1db1d8ed868c03ec7b152175f26160a5b740e5e484143877e0adf0"
+
[[package]]
name = "dialoguer"
version = "0.11.0"
@@ -625,14 +940,24 @@ dependencies = [
"zeroize",
]
+[[package]]
+name = "digest"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066"
+dependencies = [
+ "generic-array",
+]
+
[[package]]
name = "digest"
version = "0.10.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
dependencies = [
- "block-buffer",
+ "block-buffer 0.10.4",
"crypto-common",
+ "subtle",
]
[[package]]
@@ -664,7 +989,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.113",
]
[[package]]
@@ -684,7 +1009,7 @@ checksum = "c32e3e8ab1b6ee2e06418f40f94f315d82b35157eb1d2322a6e20a4b15106b84"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.113",
]
[[package]]
@@ -693,6 +1018,29 @@ version = "0.15.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b"
+[[package]]
+name = "ed25519"
+version = "1.5.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "91cff35c70bba8a626e3185d8cd48cc11b5437e1a5bcd15b9b5fa3c64b6dfee7"
+dependencies = [
+ "signature",
+]
+
+[[package]]
+name = "ed25519-dalek"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c762bae6dcaf24c4c84667b8579785430908723d5c889f469d76a41d59cc7a9d"
+dependencies = [
+ "curve25519-dalek 3.2.0",
+ "ed25519",
+ "rand 0.7.3",
+ "serde",
+ "sha2 0.9.9",
+ "zeroize",
+]
+
[[package]]
name = "either"
version = "1.15.0"
@@ -736,6 +1084,18 @@ version = "2.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be"
+[[package]]
+name = "feature-probe"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "835a3dc7d1ec9e75e2b5fb4ba75396837112d2060b03f7d43bc1897c7f7211da"
+
+[[package]]
+name = "fiat-crypto"
+version = "0.2.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d"
+
[[package]]
name = "filetime"
version = "0.2.27"
@@ -885,7 +1245,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.113",
]
[[package]]
@@ -928,6 +1288,17 @@ dependencies = [
"version_check",
]
+[[package]]
+name = "getrandom"
+version = "0.1.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "wasi 0.9.0+wasi-snapshot-preview1",
+]
+
[[package]]
name = "getrandom"
version = "0.2.16"
@@ -937,7 +1308,7 @@ dependencies = [
"cfg-if",
"js-sys",
"libc",
- "wasi",
+ "wasi 0.11.1+wasi-snapshot-preview1",
"wasm-bindgen",
]
@@ -1004,6 +1375,9 @@ name = "hashbrown"
version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
+dependencies = [
+ "ahash 0.7.8",
+]
[[package]]
name = "hashbrown"
@@ -1047,12 +1421,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
[[package]]
-name = "http"
-version = "0.2.12"
+name = "hmac"
+version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1"
+checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e"
dependencies = [
- "bytes",
+ "digest 0.10.7",
+]
+
+[[package]]
+name = "http"
+version = "0.2.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1"
+dependencies = [
+ "bytes",
"fnv",
"itoa",
]
@@ -1256,9 +1639,12 @@ dependencies = [
"reqwest 0.11.27",
"serde",
"serde_json",
+ "sha3",
"smallvec",
"tokio",
"tracing",
+ "yellowstone-grpc-client",
+ "yellowstone-grpc-proto",
"yellowstone-vixen",
"yellowstone-vixen-core",
"yellowstone-vixen-yellowstone-grpc-source",
@@ -1286,7 +1672,7 @@ dependencies = [
"serde",
"serde_json",
"tar",
- "toml",
+ "toml 0.8.23",
"uuid",
]
@@ -1296,8 +1682,9 @@ version = "0.1.2"
dependencies = [
"serde",
"serde_json",
- "sha2",
+ "sha2 0.10.9",
"strsim",
+ "tracing",
]
[[package]]
@@ -1311,6 +1698,7 @@ dependencies = [
"hyperstack-idl",
"hyperstack-macros",
"lru",
+ "once_cell",
"opentelemetry",
"opentelemetry-otlp",
"opentelemetry_sdk",
@@ -1321,8 +1709,10 @@ dependencies = [
"reqwest 0.12.28",
"serde",
"serde_json",
- "sha2",
+ "sha2 0.10.9",
+ "sha3",
"solana-pubkey",
+ "tokio",
"tonic 0.12.3",
"tracing",
"tracing-opentelemetry",
@@ -1339,8 +1729,8 @@ dependencies = [
"quote",
"serde",
"serde_json",
- "sha2",
- "syn",
+ "sha2 0.10.9",
+ "syn 2.0.113",
]
[[package]]
@@ -1377,6 +1767,7 @@ dependencies = [
"hyper-util",
"hyperstack-interpreter",
"lru",
+ "once_cell",
"opentelemetry",
"opentelemetry-otlp",
"opentelemetry_sdk",
@@ -1565,6 +1956,15 @@ dependencies = [
"web-time",
]
+[[package]]
+name = "inout"
+version = "0.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01"
+dependencies = [
+ "generic-array",
+]
+
[[package]]
name = "instant"
version = "0.1.13"
@@ -1640,6 +2040,25 @@ dependencies = [
"wasm-bindgen",
]
+[[package]]
+name = "kaigan"
+version = "0.2.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2ba15de5aeb137f0f65aa3bf82187647f1285abfe5b20c80c2c37f7007ad519a"
+dependencies = [
+ "borsh 0.10.4",
+ "serde",
+]
+
+[[package]]
+name = "keccak"
+version = "0.1.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cb26cec98cce3a3d96cbb7bced3c4b16e3d13f27ec56dbd62cbc8f39cfb9d653"
+dependencies = [
+ "cpufeatures",
+]
+
[[package]]
name = "lazy_static"
version = "1.5.0"
@@ -1663,6 +2082,52 @@ dependencies = [
"redox_syscall 0.7.0",
]
+[[package]]
+name = "libsecp256k1"
+version = "0.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c9d220bc1feda2ac231cb78c3d26f27676b8cf82c96971f7aeef3d0cf2797c73"
+dependencies = [
+ "arrayref",
+ "base64 0.12.3",
+ "digest 0.9.0",
+ "libsecp256k1-core",
+ "libsecp256k1-gen-ecmult",
+ "libsecp256k1-gen-genmult",
+ "rand 0.7.3",
+ "serde",
+ "sha2 0.9.9",
+]
+
+[[package]]
+name = "libsecp256k1-core"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d0f6ab710cec28cef759c5f18671a27dae2a5f952cdaaee1d8e2908cb2478a80"
+dependencies = [
+ "crunchy",
+ "digest 0.9.0",
+ "subtle",
+]
+
+[[package]]
+name = "libsecp256k1-gen-ecmult"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ccab96b584d38fac86a83f07e659f0deafd0253dc096dab5a36d53efe653c5c3"
+dependencies = [
+ "libsecp256k1-core",
+]
+
+[[package]]
+name = "libsecp256k1-gen-genmult"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "67abfe149395e3aa1c48a2beb32b068e2334402df8181f818d3aee2b304c4f5d"
+dependencies = [
+ "libsecp256k1-core",
+]
+
[[package]]
name = "linux-raw-sys"
version = "0.11.0"
@@ -1732,6 +2197,27 @@ version = "2.7.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273"
+[[package]]
+name = "memoffset"
+version = "0.9.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a"
+dependencies = [
+ "autocfg",
+]
+
+[[package]]
+name = "merlin"
+version = "3.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "58c38e2799fc0978b65dfff8023ec7843e2330bb462f19198840b34b6582397d"
+dependencies = [
+ "byteorder",
+ "keccak",
+ "rand_core 0.6.4",
+ "zeroize",
+]
+
[[package]]
name = "mime"
version = "0.3.17"
@@ -1755,7 +2241,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a69bcab0ad47271a0234d9422b131806bf3968021e5dc9328caf2d4cd58557fc"
dependencies = [
"libc",
- "wasi",
+ "wasi 0.11.1+wasi-snapshot-preview1",
"windows-sys 0.61.2",
]
@@ -1791,6 +2277,36 @@ dependencies = [
"windows-sys 0.61.2",
]
+[[package]]
+name = "num-bigint"
+version = "0.4.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9"
+dependencies = [
+ "num-integer",
+ "num-traits",
+]
+
+[[package]]
+name = "num-derive"
+version = "0.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.113",
+]
+
+[[package]]
+name = "num-integer"
+version = "0.1.46"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f"
+dependencies = [
+ "num-traits",
+]
+
[[package]]
name = "num-traits"
version = "0.2.19"
@@ -1810,6 +2326,28 @@ dependencies = [
"libc",
]
+[[package]]
+name = "num_enum"
+version = "0.7.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b1207a7e20ad57b847bbddc6776b968420d38292bbfe2089accff5e19e82454c"
+dependencies = [
+ "num_enum_derive",
+ "rustversion",
+]
+
+[[package]]
+name = "num_enum_derive"
+version = "0.7.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ff32365de1b6743cb203b710788263c44a03de03802daf96092f2da4fe6ba4d7"
+dependencies = [
+ "proc-macro-crate 3.5.0",
+ "proc-macro2",
+ "quote",
+ "syn 2.0.113",
+]
+
[[package]]
name = "number_prefix"
version = "0.4.0"
@@ -1828,6 +2366,12 @@ version = "1.70.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe"
+[[package]]
+name = "opaque-debug"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381"
+
[[package]]
name = "openssl"
version = "0.10.75"
@@ -1851,7 +2395,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.113",
]
[[package]]
@@ -2015,6 +2559,15 @@ dependencies = [
"windows-link",
]
+[[package]]
+name = "pbkdf2"
+version = "0.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "83a0692ec44e4cf1ef28ca317f14f8f07da2d95ec3fa01f86e4467b725e60917"
+dependencies = [
+ "digest 0.10.7",
+]
+
[[package]]
name = "percent-encoding"
version = "2.3.2"
@@ -2048,7 +2601,7 @@ checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.113",
]
[[package]]
@@ -2069,6 +2622,18 @@ version = "0.3.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c"
+[[package]]
+name = "polyval"
+version = "0.6.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9d1fe60d06143b2430aa532c94cfe9e29783047f06c0d7fd359a9a51b729fa25"
+dependencies = [
+ "cfg-if",
+ "cpufeatures",
+ "opaque-debug",
+ "universal-hash",
+]
+
[[package]]
name = "portable-atomic"
version = "1.13.0"
@@ -2100,7 +2665,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b"
dependencies = [
"proc-macro2",
- "syn",
+ "syn 2.0.113",
+]
+
+[[package]]
+name = "proc-macro-crate"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1d6ea3c4595b96363c13943497db34af4460fb474a95c43f4446ad341b8c9785"
+dependencies = [
+ "toml 0.5.11",
+]
+
+[[package]]
+name = "proc-macro-crate"
+version = "3.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e67ba7e9b2b56446f1d419b1d807906278ffa1a658a8a5d8a39dcb1f5a78614f"
+dependencies = [
+ "toml_edit 0.25.4+spec-1.1.0",
]
[[package]]
@@ -2158,7 +2741,7 @@ dependencies = [
"prost 0.13.5",
"prost-types 0.13.5",
"regex",
- "syn",
+ "syn 2.0.113",
"tempfile",
]
@@ -2180,7 +2763,7 @@ dependencies = [
"pulldown-cmark",
"pulldown-cmark-to-cmark",
"regex",
- "syn",
+ "syn 2.0.113",
"tempfile",
]
@@ -2194,7 +2777,7 @@ dependencies = [
"itertools 0.12.1",
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.113",
]
[[package]]
@@ -2207,7 +2790,7 @@ dependencies = [
"itertools 0.14.0",
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.113",
]
[[package]]
@@ -2220,7 +2803,7 @@ dependencies = [
"itertools 0.14.0",
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.113",
]
[[package]]
@@ -2280,6 +2863,15 @@ dependencies = [
"pulldown-cmark",
]
+[[package]]
+name = "qstring"
+version = "0.7.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d464fae65fff2680baf48019211ce37aaec0c78e9264c84a3e484717f965104e"
+dependencies = [
+ "percent-encoding",
+]
+
[[package]]
name = "quinn"
version = "0.11.9"
@@ -2293,7 +2885,7 @@ dependencies = [
"quinn-udp",
"rustc-hash",
"rustls 0.23.36",
- "socket2 0.5.10",
+ "socket2 0.6.1",
"thiserror 2.0.17",
"tokio",
"tracing",
@@ -2330,9 +2922,9 @@ dependencies = [
"cfg_aliases",
"libc",
"once_cell",
- "socket2 0.5.10",
+ "socket2 0.6.1",
"tracing",
- "windows-sys 0.52.0",
+ "windows-sys 0.60.2",
]
[[package]]
@@ -2350,6 +2942,19 @@ version = "5.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f"
+[[package]]
+name = "rand"
+version = "0.7.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03"
+dependencies = [
+ "getrandom 0.1.16",
+ "libc",
+ "rand_chacha 0.2.2",
+ "rand_core 0.5.1",
+ "rand_hc",
+]
+
[[package]]
name = "rand"
version = "0.8.5"
@@ -2371,6 +2976,16 @@ dependencies = [
"rand_core 0.9.3",
]
+[[package]]
+name = "rand_chacha"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402"
+dependencies = [
+ "ppv-lite86",
+ "rand_core 0.5.1",
+]
+
[[package]]
name = "rand_chacha"
version = "0.3.1"
@@ -2391,6 +3006,15 @@ dependencies = [
"rand_core 0.9.3",
]
+[[package]]
+name = "rand_core"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19"
+dependencies = [
+ "getrandom 0.1.16",
+]
+
[[package]]
name = "rand_core"
version = "0.6.4"
@@ -2409,6 +3033,15 @@ dependencies = [
"getrandom 0.3.4",
]
+[[package]]
+name = "rand_hc"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c"
+dependencies = [
+ "rand_core 0.5.1",
+]
+
[[package]]
name = "redox_syscall"
version = "0.2.16"
@@ -2596,6 +3229,15 @@ version = "2.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d"
+[[package]]
+name = "rustc_version"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92"
+dependencies = [
+ "semver",
+]
+
[[package]]
name = "rustix"
version = "1.1.3"
@@ -2786,6 +3428,12 @@ dependencies = [
"libc",
]
+[[package]]
+name = "semver"
+version = "1.0.27"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2"
+
[[package]]
name = "serde"
version = "1.0.228"
@@ -2796,6 +3444,25 @@ dependencies = [
"serde_derive",
]
+[[package]]
+name = "serde-big-array"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "11fc7cc2c76d73e0f27ee52abbd64eec84d46f370c88371120433196934e4b7f"
+dependencies = [
+ "serde",
+]
+
+[[package]]
+name = "serde_bytes"
+version = "0.11.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a5d440709e79d88e51ac01c4b72fc6cb7314017bb7da9eeff678aa94c10e3ea8"
+dependencies = [
+ "serde",
+ "serde_core",
+]
+
[[package]]
name = "serde_core"
version = "1.0.228"
@@ -2813,205 +3480,1665 @@ checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.113",
]
[[package]]
name = "serde_json"
version = "1.0.149"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86"
+checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86"
+dependencies = [
+ "itoa",
+ "memchr",
+ "serde",
+ "serde_core",
+ "zmij",
+]
+
+[[package]]
+name = "serde_spanned"
+version = "0.6.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bf41e0cfaf7226dca15e8197172c295a782857fcb97fad1808a166870dee75a3"
+dependencies = [
+ "serde",
+]
+
+[[package]]
+name = "serde_urlencoded"
+version = "0.7.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd"
+dependencies = [
+ "form_urlencoded",
+ "itoa",
+ "ryu",
+ "serde",
+]
+
+[[package]]
+name = "sha1"
+version = "0.10.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba"
+dependencies = [
+ "cfg-if",
+ "cpufeatures",
+ "digest 0.10.7",
+]
+
+[[package]]
+name = "sha2"
+version = "0.9.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800"
+dependencies = [
+ "block-buffer 0.9.0",
+ "cfg-if",
+ "cpufeatures",
+ "digest 0.9.0",
+ "opaque-debug",
+]
+
+[[package]]
+name = "sha2"
+version = "0.10.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283"
+dependencies = [
+ "cfg-if",
+ "cpufeatures",
+ "digest 0.10.7",
+]
+
+[[package]]
+name = "sha3"
+version = "0.10.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60"
+dependencies = [
+ "digest 0.10.7",
+ "keccak",
+]
+
+[[package]]
+name = "sharded-slab"
+version = "0.1.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6"
+dependencies = [
+ "lazy_static",
+]
+
+[[package]]
+name = "shell-words"
+version = "1.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dc6fe69c597f9c37bfeeeeeb33da3530379845f10be461a66d16d03eca2ded77"
+
+[[package]]
+name = "shlex"
+version = "1.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
+
+[[package]]
+name = "signal-hook-registry"
+version = "1.4.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c4db69cba1110affc0e9f7bcd48bbf87b3f4fc7c61fc9155afd4c469eb3d6c1b"
+dependencies = [
+ "errno",
+ "libc",
+]
+
+[[package]]
+name = "signature"
+version = "1.6.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "74233d3b3b2f6d4b006dc19dee745e73e2a6bfb6f93607cd3b02bd5b00797d7c"
+
+[[package]]
+name = "simd-adler32"
+version = "0.3.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e320a6c5ad31d271ad523dcf3ad13e2767ad8b1cb8f047f75a8aeaf8da139da2"
+
+[[package]]
+name = "slab"
+version = "0.4.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589"
+
+[[package]]
+name = "smallvec"
+version = "1.15.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03"
+
+[[package]]
+name = "socket2"
+version = "0.5.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e22376abed350d73dd1cd119b57ffccad95b4e585a7cda43e286245ce23c0678"
+dependencies = [
+ "libc",
+ "windows-sys 0.52.0",
+]
+
+[[package]]
+name = "socket2"
+version = "0.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "17129e116933cf371d018bb80ae557e889637989d8638274fb25622827b03881"
+dependencies = [
+ "libc",
+ "windows-sys 0.60.2",
+]
+
+[[package]]
+name = "solana-account"
+version = "2.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0f949fe4edaeaea78c844023bfc1c898e0b1f5a100f8a8d2d0f85d0a7b090258"
+dependencies = [
+ "bincode",
+ "serde",
+ "serde_bytes",
+ "serde_derive",
+ "solana-account-info",
+ "solana-clock",
+ "solana-instruction",
+ "solana-pubkey",
+ "solana-sdk-ids",
+ "solana-sysvar",
+]
+
+[[package]]
+name = "solana-account-decoder"
+version = "2.3.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ba71c97fa4d85ce4a1e0e79044ad0406c419382be598c800202903a7688ce71a"
+dependencies = [
+ "Inflector",
+ "base64 0.22.1",
+ "bincode",
+ "bs58",
+ "bv",
+ "serde",
+ "serde_derive",
+ "serde_json",
+ "solana-account",
+ "solana-account-decoder-client-types",
+ "solana-address-lookup-table-interface",
+ "solana-clock",
+ "solana-config-program-client",
+ "solana-epoch-schedule",
+ "solana-fee-calculator",
+ "solana-instruction",
+ "solana-loader-v3-interface",
+ "solana-nonce",
+ "solana-program-option",
+ "solana-program-pack",
+ "solana-pubkey",
+ "solana-rent",
+ "solana-sdk-ids",
+ "solana-slot-hashes",
+ "solana-slot-history",
+ "solana-stake-interface",
+ "solana-sysvar",
+ "solana-vote-interface",
+ "spl-generic-token",
+ "spl-token",
+ "spl-token-2022",
+ "spl-token-group-interface",
+ "spl-token-metadata-interface",
+ "thiserror 2.0.17",
+ "zstd",
+]
+
+[[package]]
+name = "solana-account-decoder-client-types"
+version = "2.3.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5519e8343325b707f17fbed54fcefb325131b692506d0af9e08a539d15e4f8cf"
+dependencies = [
+ "base64 0.22.1",
+ "bs58",
+ "serde",
+ "serde_derive",
+ "serde_json",
+ "solana-account",
+ "solana-pubkey",
+ "zstd",
+]
+
+[[package]]
+name = "solana-account-info"
+version = "2.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c8f5152a288ef1912300fc6efa6c2d1f9bb55d9398eb6c72326360b8063987da"
+dependencies = [
+ "bincode",
+ "serde",
+ "solana-program-error",
+ "solana-program-memory",
+ "solana-pubkey",
+]
+
+[[package]]
+name = "solana-address-lookup-table-interface"
+version = "2.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d1673f67efe870b64a65cb39e6194be5b26527691ce5922909939961a6e6b395"
+dependencies = [
+ "bincode",
+ "bytemuck",
+ "serde",
+ "serde_derive",
+ "solana-clock",
+ "solana-instruction",
+ "solana-pubkey",
+ "solana-sdk-ids",
+ "solana-slot-hashes",
+]
+
+[[package]]
+name = "solana-atomic-u64"
+version = "2.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d52e52720efe60465b052b9e7445a01c17550666beec855cce66f44766697bc2"
+dependencies = [
+ "parking_lot 0.12.5",
+]
+
+[[package]]
+name = "solana-big-mod-exp"
+version = "2.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "75db7f2bbac3e62cfd139065d15bcda9e2428883ba61fc8d27ccb251081e7567"
+dependencies = [
+ "num-bigint",
+ "num-traits",
+ "solana-define-syscall",
+]
+
+[[package]]
+name = "solana-bincode"
+version = "2.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "19a3787b8cf9c9fe3dd360800e8b70982b9e5a8af9e11c354b6665dd4a003adc"
+dependencies = [
+ "bincode",
+ "serde",
+ "solana-instruction",
+]
+
+[[package]]
+name = "solana-blake3-hasher"
+version = "2.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a1a0801e25a1b31a14494fc80882a036be0ffd290efc4c2d640bfcca120a4672"
+dependencies = [
+ "blake3",
+ "solana-define-syscall",
+ "solana-hash",
+ "solana-sanitize",
+]
+
+[[package]]
+name = "solana-borsh"
+version = "2.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "718333bcd0a1a7aed6655aa66bef8d7fb047944922b2d3a18f49cbc13e73d004"
+dependencies = [
+ "borsh 0.10.4",
+ "borsh 1.6.0",
+]
+
+[[package]]
+name = "solana-clock"
+version = "2.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f8584296123df8fe229b95e2ebfd37ae637fe9db9b7d4dd677ac5a78e80dbfce"
+dependencies = [
+ "serde",
+ "serde_derive",
+ "solana-sdk-ids",
+ "solana-sdk-macro",
+ "solana-sysvar-id",
+]
+
+[[package]]
+name = "solana-commitment-config"
+version = "2.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ac49c4dde3edfa832de1697e9bcdb7c3b3f7cb7a1981b7c62526c8bb6700fb73"
+
+[[package]]
+name = "solana-config-program-client"
+version = "0.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "53aceac36f105fd4922e29b4f0c1f785b69d7b3e7e387e384b8985c8e0c3595e"
+dependencies = [
+ "bincode",
+ "borsh 0.10.4",
+ "kaigan",
+ "serde",
+ "solana-program",
+]
+
+[[package]]
+name = "solana-cpi"
+version = "2.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8dc71126edddc2ba014622fc32d0f5e2e78ec6c5a1e0eb511b85618c09e9ea11"
+dependencies = [
+ "solana-account-info",
+ "solana-define-syscall",
+ "solana-instruction",
+ "solana-program-error",
+ "solana-pubkey",
+ "solana-stable-layout",
+]
+
+[[package]]
+name = "solana-curve25519"
+version = "2.3.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "eae4261b9a8613d10e77ac831a8fa60b6fa52b9b103df46d641deff9f9812a23"
+dependencies = [
+ "bytemuck",
+ "bytemuck_derive",
+ "curve25519-dalek 4.1.3",
+ "solana-define-syscall",
+ "subtle",
+ "thiserror 2.0.17",
+]
+
+[[package]]
+name = "solana-decode-error"
+version = "2.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8c781686a18db2f942e70913f7ca15dc120ec38dcab42ff7557db2c70c625a35"
+dependencies = [
+ "num-traits",
+]
+
+[[package]]
+name = "solana-define-syscall"
+version = "2.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2ae3e2abcf541c8122eafe9a625d4d194b4023c20adde1e251f94e056bb1aee2"
+
+[[package]]
+name = "solana-derivation-path"
+version = "2.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "939756d798b25c5ec3cca10e06212bdca3b1443cb9bb740a38124f58b258737b"
+dependencies = [
+ "derivation-path",
+ "qstring",
+ "uriparse",
+]
+
+[[package]]
+name = "solana-epoch-rewards"
+version = "2.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "86b575d3dd323b9ea10bb6fe89bf6bf93e249b215ba8ed7f68f1a3633f384db7"
+dependencies = [
+ "serde",
+ "serde_derive",
+ "solana-hash",
+ "solana-sdk-ids",
+ "solana-sdk-macro",
+ "solana-sysvar-id",
+]
+
+[[package]]
+name = "solana-epoch-schedule"
+version = "2.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3fce071fbddecc55d727b1d7ed16a629afe4f6e4c217bc8d00af3b785f6f67ed"
+dependencies = [
+ "serde",
+ "serde_derive",
+ "solana-sdk-ids",
+ "solana-sdk-macro",
+ "solana-sysvar-id",
+]
+
+[[package]]
+name = "solana-example-mocks"
+version = "2.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "84461d56cbb8bb8d539347151e0525b53910102e4bced875d49d5139708e39d3"
+dependencies = [
+ "serde",
+ "serde_derive",
+ "solana-address-lookup-table-interface",
+ "solana-clock",
+ "solana-hash",
+ "solana-instruction",
+ "solana-keccak-hasher",
+ "solana-message",
+ "solana-nonce",
+ "solana-pubkey",
+ "solana-sdk-ids",
+ "solana-system-interface",
+ "thiserror 2.0.17",
+]
+
+[[package]]
+name = "solana-feature-gate-interface"
+version = "2.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "43f5c5382b449e8e4e3016fb05e418c53d57782d8b5c30aa372fc265654b956d"
+dependencies = [
+ "bincode",
+ "serde",
+ "serde_derive",
+ "solana-account",
+ "solana-account-info",
+ "solana-instruction",
+ "solana-program-error",
+ "solana-pubkey",
+ "solana-rent",
+ "solana-sdk-ids",
+ "solana-system-interface",
+]
+
+[[package]]
+name = "solana-fee-calculator"
+version = "2.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d89bc408da0fb3812bc3008189d148b4d3e08252c79ad810b245482a3f70cd8d"
+dependencies = [
+ "log",
+ "serde",
+ "serde_derive",
+]
+
+[[package]]
+name = "solana-hash"
+version = "2.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b5b96e9f0300fa287b545613f007dfe20043d7812bee255f418c1eb649c93b63"
+dependencies = [
+ "borsh 1.6.0",
+ "bytemuck",
+ "bytemuck_derive",
+ "five8",
+ "js-sys",
+ "serde",
+ "serde_derive",
+ "solana-atomic-u64",
+ "solana-sanitize",
+ "wasm-bindgen",
+]
+
+[[package]]
+name = "solana-instruction"
+version = "2.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bab5682934bd1f65f8d2c16f21cb532526fcc1a09f796e2cacdb091eee5774ad"
+dependencies = [
+ "bincode",
+ "borsh 1.6.0",
+ "getrandom 0.2.16",
+ "js-sys",
+ "num-traits",
+ "serde",
+ "serde_derive",
+ "serde_json",
+ "solana-define-syscall",
+ "solana-pubkey",
+ "wasm-bindgen",
+]
+
+[[package]]
+name = "solana-instructions-sysvar"
+version = "2.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e0e85a6fad5c2d0c4f5b91d34b8ca47118fc593af706e523cdbedf846a954f57"
+dependencies = [
+ "bitflags 2.10.0",
+ "solana-account-info",
+ "solana-instruction",
+ "solana-program-error",
+ "solana-pubkey",
+ "solana-sanitize",
+ "solana-sdk-ids",
+ "solana-serialize-utils",
+ "solana-sysvar-id",
+]
+
+[[package]]
+name = "solana-keccak-hasher"
+version = "2.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c7aeb957fbd42a451b99235df4942d96db7ef678e8d5061ef34c9b34cae12f79"
+dependencies = [
+ "sha3",
+ "solana-define-syscall",
+ "solana-hash",
+ "solana-sanitize",
+]
+
+[[package]]
+name = "solana-keypair"
+version = "2.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bd3f04aa1a05c535e93e121a95f66e7dcccf57e007282e8255535d24bf1e98bb"
+dependencies = [
+ "ed25519-dalek",
+ "five8",
+ "rand 0.7.3",
+ "solana-pubkey",
+ "solana-seed-phrase",
+ "solana-signature",
+ "solana-signer",
+ "wasm-bindgen",
+]
+
+[[package]]
+name = "solana-last-restart-slot"
+version = "2.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4a6360ac2fdc72e7463565cd256eedcf10d7ef0c28a1249d261ec168c1b55cdd"
+dependencies = [
+ "serde",
+ "serde_derive",
+ "solana-sdk-ids",
+ "solana-sdk-macro",
+ "solana-sysvar-id",
+]
+
+[[package]]
+name = "solana-loader-v2-interface"
+version = "2.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d8ab08006dad78ae7cd30df8eea0539e207d08d91eaefb3e1d49a446e1c49654"
+dependencies = [
+ "serde",
+ "serde_bytes",
+ "serde_derive",
+ "solana-instruction",
+ "solana-pubkey",
+ "solana-sdk-ids",
+]
+
+[[package]]
+name = "solana-loader-v3-interface"
+version = "5.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6f7162a05b8b0773156b443bccd674ea78bb9aa406325b467ea78c06c99a63a2"
+dependencies = [
+ "serde",
+ "serde_bytes",
+ "serde_derive",
+ "solana-instruction",
+ "solana-pubkey",
+ "solana-sdk-ids",
+ "solana-system-interface",
+]
+
+[[package]]
+name = "solana-loader-v4-interface"
+version = "2.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "706a777242f1f39a83e2a96a2a6cb034cb41169c6ecbee2cf09cb873d9659e7e"
+dependencies = [
+ "serde",
+ "serde_bytes",
+ "serde_derive",
+ "solana-instruction",
+ "solana-pubkey",
+ "solana-sdk-ids",
+ "solana-system-interface",
+]
+
+[[package]]
+name = "solana-message"
+version = "2.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1796aabce376ff74bf89b78d268fa5e683d7d7a96a0a4e4813ec34de49d5314b"
+dependencies = [
+ "bincode",
+ "blake3",
+ "lazy_static",
+ "serde",
+ "serde_derive",
+ "solana-bincode",
+ "solana-hash",
+ "solana-instruction",
+ "solana-pubkey",
+ "solana-sanitize",
+ "solana-sdk-ids",
+ "solana-short-vec",
+ "solana-system-interface",
+ "solana-transaction-error",
+ "wasm-bindgen",
+]
+
+[[package]]
+name = "solana-msg"
+version = "2.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f36a1a14399afaabc2781a1db09cb14ee4cc4ee5c7a5a3cfcc601811379a8092"
+dependencies = [
+ "solana-define-syscall",
+]
+
+[[package]]
+name = "solana-native-token"
+version = "2.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "61515b880c36974053dd499c0510066783f0cc6ac17def0c7ef2a244874cf4a9"
+
+[[package]]
+name = "solana-nonce"
+version = "2.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "703e22eb185537e06204a5bd9d509b948f0066f2d1d814a6f475dafb3ddf1325"
+dependencies = [
+ "serde",
+ "serde_derive",
+ "solana-fee-calculator",
+ "solana-hash",
+ "solana-pubkey",
+ "solana-sha256-hasher",
+]
+
+[[package]]
+name = "solana-program"
+version = "2.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "98eca145bd3545e2fbb07166e895370576e47a00a7d824e325390d33bf467210"
+dependencies = [
+ "bincode",
+ "blake3",
+ "borsh 0.10.4",
+ "borsh 1.6.0",
+ "bs58",
+ "bytemuck",
+ "console_error_panic_hook",
+ "console_log",
+ "getrandom 0.2.16",
+ "lazy_static",
+ "log",
+ "memoffset",
+ "num-bigint",
+ "num-derive",
+ "num-traits",
+ "rand 0.8.5",
+ "serde",
+ "serde_bytes",
+ "serde_derive",
+ "solana-account-info",
+ "solana-address-lookup-table-interface",
+ "solana-atomic-u64",
+ "solana-big-mod-exp",
+ "solana-bincode",
+ "solana-blake3-hasher",
+ "solana-borsh",
+ "solana-clock",
+ "solana-cpi",
+ "solana-decode-error",
+ "solana-define-syscall",
+ "solana-epoch-rewards",
+ "solana-epoch-schedule",
+ "solana-example-mocks",
+ "solana-feature-gate-interface",
+ "solana-fee-calculator",
+ "solana-hash",
+ "solana-instruction",
+ "solana-instructions-sysvar",
+ "solana-keccak-hasher",
+ "solana-last-restart-slot",
+ "solana-loader-v2-interface",
+ "solana-loader-v3-interface",
+ "solana-loader-v4-interface",
+ "solana-message",
+ "solana-msg",
+ "solana-native-token",
+ "solana-nonce",
+ "solana-program-entrypoint",
+ "solana-program-error",
+ "solana-program-memory",
+ "solana-program-option",
+ "solana-program-pack",
+ "solana-pubkey",
+ "solana-rent",
+ "solana-sanitize",
+ "solana-sdk-ids",
+ "solana-sdk-macro",
+ "solana-secp256k1-recover",
+ "solana-serde-varint",
+ "solana-serialize-utils",
+ "solana-sha256-hasher",
+ "solana-short-vec",
+ "solana-slot-hashes",
+ "solana-slot-history",
+ "solana-stable-layout",
+ "solana-stake-interface",
+ "solana-system-interface",
+ "solana-sysvar",
+ "solana-sysvar-id",
+ "solana-vote-interface",
+ "thiserror 2.0.17",
+ "wasm-bindgen",
+]
+
+[[package]]
+name = "solana-program-entrypoint"
+version = "2.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "32ce041b1a0ed275290a5008ee1a4a6c48f5054c8a3d78d313c08958a06aedbd"
+dependencies = [
+ "solana-account-info",
+ "solana-msg",
+ "solana-program-error",
+ "solana-pubkey",
+]
+
+[[package]]
+name = "solana-program-error"
+version = "2.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9ee2e0217d642e2ea4bee237f37bd61bb02aec60da3647c48ff88f6556ade775"
+dependencies = [
+ "borsh 1.6.0",
+ "num-traits",
+ "serde",
+ "serde_derive",
+ "solana-decode-error",
+ "solana-instruction",
+ "solana-msg",
+ "solana-pubkey",
+]
+
+[[package]]
+name = "solana-program-memory"
+version = "2.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3a5426090c6f3fd6cfdc10685322fede9ca8e5af43cd6a59e98bfe4e91671712"
+dependencies = [
+ "solana-define-syscall",
+]
+
+[[package]]
+name = "solana-program-option"
+version = "2.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dc677a2e9bc616eda6dbdab834d463372b92848b2bfe4a1ed4e4b4adba3397d0"
+
+[[package]]
+name = "solana-program-pack"
+version = "2.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "319f0ef15e6e12dc37c597faccb7d62525a509fec5f6975ecb9419efddeb277b"
+dependencies = [
+ "solana-program-error",
+]
+
+[[package]]
+name = "solana-pubkey"
+version = "2.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9b62adb9c3261a052ca1f999398c388f1daf558a1b492f60a6d9e64857db4ff1"
+dependencies = [
+ "borsh 0.10.4",
+ "borsh 1.6.0",
+ "bytemuck",
+ "bytemuck_derive",
+ "curve25519-dalek 4.1.3",
+ "five8",
+ "five8_const",
+ "getrandom 0.2.16",
+ "js-sys",
+ "num-traits",
+ "serde",
+ "serde_derive",
+ "solana-atomic-u64",
+ "solana-decode-error",
+ "solana-define-syscall",
+ "solana-sanitize",
+ "solana-sha256-hasher",
+ "wasm-bindgen",
+]
+
+[[package]]
+name = "solana-rent"
+version = "2.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d1aea8fdea9de98ca6e8c2da5827707fb3842833521b528a713810ca685d2480"
+dependencies = [
+ "serde",
+ "serde_derive",
+ "solana-sdk-ids",
+ "solana-sdk-macro",
+ "solana-sysvar-id",
+]
+
+[[package]]
+name = "solana-reward-info"
+version = "2.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "18205b69139b1ae0ab8f6e11cdcb627328c0814422ad2482000fa2ca54ae4a2f"
+dependencies = [
+ "serde",
+ "serde_derive",
+]
+
+[[package]]
+name = "solana-sanitize"
+version = "2.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "61f1bc1357b8188d9c4a3af3fc55276e56987265eb7ad073ae6f8180ee54cecf"
+
+[[package]]
+name = "solana-sdk-ids"
+version = "2.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5c5d8b9cc68d5c88b062a33e23a6466722467dde0035152d8fb1afbcdf350a5f"
+dependencies = [
+ "solana-pubkey",
+]
+
+[[package]]
+name = "solana-sdk-macro"
+version = "2.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "86280da8b99d03560f6ab5aca9de2e38805681df34e0bb8f238e69b29433b9df"
+dependencies = [
+ "bs58",
+ "proc-macro2",
+ "quote",
+ "syn 2.0.113",
+]
+
+[[package]]
+name = "solana-secp256k1-recover"
+version = "2.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "baa3120b6cdaa270f39444f5093a90a7b03d296d362878f7a6991d6de3bbe496"
+dependencies = [
+ "libsecp256k1",
+ "solana-define-syscall",
+ "thiserror 2.0.17",
+]
+
+[[package]]
+name = "solana-security-txt"
+version = "1.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "468aa43b7edb1f9b7b7b686d5c3aeb6630dc1708e86e31343499dd5c4d775183"
+
+[[package]]
+name = "solana-seed-derivable"
+version = "2.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3beb82b5adb266c6ea90e5cf3967235644848eac476c5a1f2f9283a143b7c97f"
+dependencies = [
+ "solana-derivation-path",
+]
+
+[[package]]
+name = "solana-seed-phrase"
+version = "2.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "36187af2324f079f65a675ec22b31c24919cb4ac22c79472e85d819db9bbbc15"
+dependencies = [
+ "hmac",
+ "pbkdf2",
+ "sha2 0.10.9",
+]
+
+[[package]]
+name = "solana-serde-varint"
+version = "2.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2a7e155eba458ecfb0107b98236088c3764a09ddf0201ec29e52a0be40857113"
+dependencies = [
+ "serde",
+]
+
+[[package]]
+name = "solana-serialize-utils"
+version = "2.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "817a284b63197d2b27afdba829c5ab34231da4a9b4e763466a003c40ca4f535e"
+dependencies = [
+ "solana-instruction",
+ "solana-pubkey",
+ "solana-sanitize",
+]
+
+[[package]]
+name = "solana-sha256-hasher"
+version = "2.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5aa3feb32c28765f6aa1ce8f3feac30936f16c5c3f7eb73d63a5b8f6f8ecdc44"
+dependencies = [
+ "sha2 0.10.9",
+ "solana-define-syscall",
+ "solana-hash",
+]
+
+[[package]]
+name = "solana-short-vec"
+version = "2.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5c54c66f19b9766a56fa0057d060de8378676cb64987533fa088861858fc5a69"
+dependencies = [
+ "serde",
+]
+
+[[package]]
+name = "solana-signature"
+version = "2.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "64c8ec8e657aecfc187522fc67495142c12f35e55ddeca8698edbb738b8dbd8c"
+dependencies = [
+ "ed25519-dalek",
+ "five8",
+ "serde",
+ "serde-big-array",
+ "serde_derive",
+ "solana-sanitize",
+]
+
+[[package]]
+name = "solana-signer"
+version = "2.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7c41991508a4b02f021c1342ba00bcfa098630b213726ceadc7cb032e051975b"
+dependencies = [
+ "solana-pubkey",
+ "solana-signature",
+ "solana-transaction-error",
+]
+
+[[package]]
+name = "solana-slot-hashes"
+version = "2.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0c8691982114513763e88d04094c9caa0376b867a29577939011331134c301ce"
+dependencies = [
+ "serde",
+ "serde_derive",
+ "solana-hash",
+ "solana-sdk-ids",
+ "solana-sysvar-id",
+]
+
+[[package]]
+name = "solana-slot-history"
+version = "2.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "97ccc1b2067ca22754d5283afb2b0126d61eae734fc616d23871b0943b0d935e"
+dependencies = [
+ "bv",
+ "serde",
+ "serde_derive",
+ "solana-sdk-ids",
+ "solana-sysvar-id",
+]
+
+[[package]]
+name = "solana-stable-layout"
+version = "2.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9f14f7d02af8f2bc1b5efeeae71bc1c2b7f0f65cd75bcc7d8180f2c762a57f54"
+dependencies = [
+ "solana-instruction",
+ "solana-pubkey",
+]
+
+[[package]]
+name = "solana-stake-interface"
+version = "1.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5269e89fde216b4d7e1d1739cf5303f8398a1ff372a81232abbee80e554a838c"
+dependencies = [
+ "borsh 0.10.4",
+ "borsh 1.6.0",
+ "num-traits",
+ "serde",
+ "serde_derive",
+ "solana-clock",
+ "solana-cpi",
+ "solana-decode-error",
+ "solana-instruction",
+ "solana-program-error",
+ "solana-pubkey",
+ "solana-system-interface",
+ "solana-sysvar-id",
+]
+
+[[package]]
+name = "solana-svm-feature-set"
+version = "2.3.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3f24b836eb4d74ec255217bdbe0f24f64a07adeac31aca61f334f91cd4a3b1d5"
+
+[[package]]
+name = "solana-system-interface"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "94d7c18cb1a91c6be5f5a8ac9276a1d7c737e39a21beba9ea710ab4b9c63bc90"
+dependencies = [
+ "js-sys",
+ "num-traits",
+ "serde",
+ "serde_derive",
+ "solana-decode-error",
+ "solana-instruction",
+ "solana-pubkey",
+ "wasm-bindgen",
+]
+
+[[package]]
+name = "solana-sysvar"
+version = "2.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b8c3595f95069f3d90f275bb9bd235a1973c4d059028b0a7f81baca2703815db"
+dependencies = [
+ "base64 0.22.1",
+ "bincode",
+ "bytemuck",
+ "bytemuck_derive",
+ "lazy_static",
+ "serde",
+ "serde_derive",
+ "solana-account-info",
+ "solana-clock",
+ "solana-define-syscall",
+ "solana-epoch-rewards",
+ "solana-epoch-schedule",
+ "solana-fee-calculator",
+ "solana-hash",
+ "solana-instruction",
+ "solana-instructions-sysvar",
+ "solana-last-restart-slot",
+ "solana-program-entrypoint",
+ "solana-program-error",
+ "solana-program-memory",
+ "solana-pubkey",
+ "solana-rent",
+ "solana-sanitize",
+ "solana-sdk-ids",
+ "solana-sdk-macro",
+ "solana-slot-hashes",
+ "solana-slot-history",
+ "solana-stake-interface",
+ "solana-sysvar-id",
+]
+
+[[package]]
+name = "solana-sysvar-id"
+version = "2.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5762b273d3325b047cfda250787f8d796d781746860d5d0a746ee29f3e8812c1"
+dependencies = [
+ "solana-pubkey",
+ "solana-sdk-ids",
+]
+
+[[package]]
+name = "solana-transaction"
+version = "2.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "80657d6088f721148f5d889c828ca60c7daeedac9a8679f9ec215e0c42bcbf41"
+dependencies = [
+ "serde",
+ "serde_derive",
+ "solana-hash",
+ "solana-instruction",
+ "solana-keypair",
+ "solana-message",
+ "solana-pubkey",
+ "solana-sanitize",
+ "solana-sdk-ids",
+ "solana-short-vec",
+ "solana-signature",
+ "solana-transaction-error",
+ "wasm-bindgen",
+]
+
+[[package]]
+name = "solana-transaction-context"
+version = "2.3.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "54a312304361987a85b2ef2293920558e6612876a639dd1309daf6d0d59ef2fe"
+dependencies = [
+ "bincode",
+ "serde",
+ "serde_derive",
+ "solana-account",
+ "solana-instruction",
+ "solana-instructions-sysvar",
+ "solana-pubkey",
+ "solana-rent",
+ "solana-sdk-ids",
+]
+
+[[package]]
+name = "solana-transaction-error"
+version = "2.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "222a9dc8fdb61c6088baab34fc3a8b8473a03a7a5fd404ed8dd502fa79b67cb1"
+dependencies = [
+ "serde",
+ "serde_derive",
+ "solana-instruction",
+ "solana-sanitize",
+]
+
+[[package]]
+name = "solana-transaction-status"
+version = "2.3.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "135f92f4192cc68900c665becf97fc0a6500ae5a67ff347bf2cbc20ecfefa821"
+dependencies = [
+ "Inflector",
+ "agave-reserved-account-keys",
+ "base64 0.22.1",
+ "bincode",
+ "borsh 1.6.0",
+ "bs58",
+ "log",
+ "serde",
+ "serde_derive",
+ "serde_json",
+ "solana-account-decoder",
+ "solana-address-lookup-table-interface",
+ "solana-clock",
+ "solana-hash",
+ "solana-instruction",
+ "solana-loader-v2-interface",
+ "solana-loader-v3-interface",
+ "solana-message",
+ "solana-program-option",
+ "solana-pubkey",
+ "solana-reward-info",
+ "solana-sdk-ids",
+ "solana-signature",
+ "solana-stake-interface",
+ "solana-system-interface",
+ "solana-transaction",
+ "solana-transaction-error",
+ "solana-transaction-status-client-types",
+ "solana-vote-interface",
+ "spl-associated-token-account",
+ "spl-memo",
+ "spl-token",
+ "spl-token-2022",
+ "spl-token-group-interface",
+ "spl-token-metadata-interface",
+ "thiserror 2.0.17",
+]
+
+[[package]]
+name = "solana-transaction-status-client-types"
+version = "2.3.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "51f1d7c2387c35850848212244d2b225847666cb52d3bd59a5c409d2c300303d"
+dependencies = [
+ "base64 0.22.1",
+ "bincode",
+ "bs58",
+ "serde",
+ "serde_derive",
+ "serde_json",
+ "solana-account-decoder-client-types",
+ "solana-commitment-config",
+ "solana-message",
+ "solana-reward-info",
+ "solana-signature",
+ "solana-transaction",
+ "solana-transaction-context",
+ "solana-transaction-error",
+ "thiserror 2.0.17",
+]
+
+[[package]]
+name = "solana-vote-interface"
+version = "2.2.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b80d57478d6599d30acc31cc5ae7f93ec2361a06aefe8ea79bc81739a08af4c3"
+dependencies = [
+ "bincode",
+ "num-derive",
+ "num-traits",
+ "serde",
+ "serde_derive",
+ "solana-clock",
+ "solana-decode-error",
+ "solana-hash",
+ "solana-instruction",
+ "solana-pubkey",
+ "solana-rent",
+ "solana-sdk-ids",
+ "solana-serde-varint",
+ "solana-serialize-utils",
+ "solana-short-vec",
+ "solana-system-interface",
+]
+
+[[package]]
+name = "solana-zk-sdk"
+version = "2.3.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "97b9fc6ec37d16d0dccff708ed1dd6ea9ba61796700c3bb7c3b401973f10f63b"
+dependencies = [
+ "aes-gcm-siv",
+ "base64 0.22.1",
+ "bincode",
+ "bytemuck",
+ "bytemuck_derive",
+ "curve25519-dalek 4.1.3",
+ "itertools 0.12.1",
+ "js-sys",
+ "merlin",
+ "num-derive",
+ "num-traits",
+ "rand 0.8.5",
+ "serde",
+ "serde_derive",
+ "serde_json",
+ "sha3",
+ "solana-derivation-path",
+ "solana-instruction",
+ "solana-pubkey",
+ "solana-sdk-ids",
+ "solana-seed-derivable",
+ "solana-seed-phrase",
+ "solana-signature",
+ "solana-signer",
+ "subtle",
+ "thiserror 2.0.17",
+ "wasm-bindgen",
+ "zeroize",
+]
+
+[[package]]
+name = "spl-associated-token-account"
+version = "7.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ae179d4a26b3c7a20c839898e6aed84cb4477adf108a366c95532f058aea041b"
dependencies = [
- "itoa",
- "memchr",
- "serde",
- "serde_core",
- "zmij",
+ "borsh 1.6.0",
+ "num-derive",
+ "num-traits",
+ "solana-program",
+ "spl-associated-token-account-client",
+ "spl-token",
+ "spl-token-2022",
+ "thiserror 2.0.17",
]
[[package]]
-name = "serde_spanned"
-version = "0.6.9"
+name = "spl-associated-token-account-client"
+version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bf41e0cfaf7226dca15e8197172c295a782857fcb97fad1808a166870dee75a3"
+checksum = "d6f8349dbcbe575f354f9a533a21f272f3eb3808a49e2fdc1c34393b88ba76cb"
dependencies = [
- "serde",
+ "solana-instruction",
+ "solana-pubkey",
]
[[package]]
-name = "serde_urlencoded"
-version = "0.7.1"
+name = "spl-discriminator"
+version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd"
+checksum = "a7398da23554a31660f17718164e31d31900956054f54f52d5ec1be51cb4f4b3"
dependencies = [
- "form_urlencoded",
- "itoa",
- "ryu",
- "serde",
+ "bytemuck",
+ "solana-program-error",
+ "solana-sha256-hasher",
+ "spl-discriminator-derive",
]
[[package]]
-name = "sha1"
-version = "0.10.6"
+name = "spl-discriminator-derive"
+version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba"
+checksum = "d9e8418ea6269dcfb01c712f0444d2c75542c04448b480e87de59d2865edc750"
dependencies = [
- "cfg-if",
- "cpufeatures",
- "digest",
+ "quote",
+ "spl-discriminator-syn",
+ "syn 2.0.113",
]
[[package]]
-name = "sha2"
-version = "0.10.9"
+name = "spl-discriminator-syn"
+version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283"
+checksum = "5d1dbc82ab91422345b6df40a79e2b78c7bce1ebb366da323572dd60b7076b67"
dependencies = [
- "cfg-if",
- "cpufeatures",
- "digest",
+ "proc-macro2",
+ "quote",
+ "sha2 0.10.9",
+ "syn 2.0.113",
+ "thiserror 1.0.69",
]
[[package]]
-name = "sharded-slab"
-version = "0.1.7"
+name = "spl-elgamal-registry"
+version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6"
+checksum = "65edfeed09cd4231e595616aa96022214f9c9d2be02dea62c2b30d5695a6833a"
dependencies = [
- "lazy_static",
+ "bytemuck",
+ "solana-account-info",
+ "solana-cpi",
+ "solana-instruction",
+ "solana-msg",
+ "solana-program-entrypoint",
+ "solana-program-error",
+ "solana-pubkey",
+ "solana-rent",
+ "solana-sdk-ids",
+ "solana-system-interface",
+ "solana-sysvar",
+ "solana-zk-sdk",
+ "spl-pod",
+ "spl-token-confidential-transfer-proof-extraction",
]
[[package]]
-name = "shell-words"
-version = "1.1.1"
+name = "spl-generic-token"
+version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dc6fe69c597f9c37bfeeeeeb33da3530379845f10be461a66d16d03eca2ded77"
+checksum = "741a62a566d97c58d33f9ed32337ceedd4e35109a686e31b1866c5dfa56abddc"
+dependencies = [
+ "bytemuck",
+ "solana-pubkey",
+]
[[package]]
-name = "shlex"
-version = "1.3.0"
+name = "spl-memo"
+version = "6.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
+checksum = "9f09647c0974e33366efeb83b8e2daebb329f0420149e74d3a4bd2c08cf9f7cb"
+dependencies = [
+ "solana-account-info",
+ "solana-instruction",
+ "solana-msg",
+ "solana-program-entrypoint",
+ "solana-program-error",
+ "solana-pubkey",
+]
[[package]]
-name = "signal-hook-registry"
-version = "1.4.8"
+name = "spl-pod"
+version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c4db69cba1110affc0e9f7bcd48bbf87b3f4fc7c61fc9155afd4c469eb3d6c1b"
+checksum = "d994afaf86b779104b4a95ba9ca75b8ced3fdb17ee934e38cb69e72afbe17799"
dependencies = [
- "errno",
- "libc",
+ "borsh 1.6.0",
+ "bytemuck",
+ "bytemuck_derive",
+ "num-derive",
+ "num-traits",
+ "solana-decode-error",
+ "solana-msg",
+ "solana-program-error",
+ "solana-program-option",
+ "solana-pubkey",
+ "solana-zk-sdk",
+ "thiserror 2.0.17",
]
[[package]]
-name = "simd-adler32"
-version = "0.3.8"
+name = "spl-program-error"
+version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e320a6c5ad31d271ad523dcf3ad13e2767ad8b1cb8f047f75a8aeaf8da139da2"
+checksum = "9cdebc8b42553070b75aa5106f071fef2eb798c64a7ec63375da4b1f058688c6"
+dependencies = [
+ "num-derive",
+ "num-traits",
+ "solana-decode-error",
+ "solana-msg",
+ "solana-program-error",
+ "spl-program-error-derive",
+ "thiserror 2.0.17",
+]
[[package]]
-name = "slab"
-version = "0.4.11"
+name = "spl-program-error-derive"
+version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589"
+checksum = "2a2539e259c66910d78593475540e8072f0b10f0f61d7607bbf7593899ed52d0"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "sha2 0.10.9",
+ "syn 2.0.113",
+]
[[package]]
-name = "smallvec"
-version = "1.15.1"
+name = "spl-tlv-account-resolution"
+version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03"
+checksum = "1408e961215688715d5a1063cbdcf982de225c45f99c82b4f7d7e1dd22b998d7"
+dependencies = [
+ "bytemuck",
+ "num-derive",
+ "num-traits",
+ "solana-account-info",
+ "solana-decode-error",
+ "solana-instruction",
+ "solana-msg",
+ "solana-program-error",
+ "solana-pubkey",
+ "spl-discriminator",
+ "spl-pod",
+ "spl-program-error",
+ "spl-type-length-value",
+ "thiserror 2.0.17",
+]
[[package]]
-name = "socket2"
-version = "0.5.10"
+name = "spl-token"
+version = "8.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e22376abed350d73dd1cd119b57ffccad95b4e585a7cda43e286245ce23c0678"
+checksum = "053067c6a82c705004f91dae058b11b4780407e9ccd6799dc9e7d0fab5f242da"
dependencies = [
- "libc",
- "windows-sys 0.52.0",
+ "arrayref",
+ "bytemuck",
+ "num-derive",
+ "num-traits",
+ "num_enum",
+ "solana-account-info",
+ "solana-cpi",
+ "solana-decode-error",
+ "solana-instruction",
+ "solana-msg",
+ "solana-program-entrypoint",
+ "solana-program-error",
+ "solana-program-memory",
+ "solana-program-option",
+ "solana-program-pack",
+ "solana-pubkey",
+ "solana-rent",
+ "solana-sdk-ids",
+ "solana-sysvar",
+ "thiserror 2.0.17",
]
[[package]]
-name = "socket2"
-version = "0.6.1"
+name = "spl-token-2022"
+version = "8.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "17129e116933cf371d018bb80ae557e889637989d8638274fb25622827b03881"
+checksum = "31f0dfbb079eebaee55e793e92ca5f433744f4b71ee04880bfd6beefba5973e5"
dependencies = [
- "libc",
- "windows-sys 0.60.2",
+ "arrayref",
+ "bytemuck",
+ "num-derive",
+ "num-traits",
+ "num_enum",
+ "solana-account-info",
+ "solana-clock",
+ "solana-cpi",
+ "solana-decode-error",
+ "solana-instruction",
+ "solana-msg",
+ "solana-native-token",
+ "solana-program-entrypoint",
+ "solana-program-error",
+ "solana-program-memory",
+ "solana-program-option",
+ "solana-program-pack",
+ "solana-pubkey",
+ "solana-rent",
+ "solana-sdk-ids",
+ "solana-security-txt",
+ "solana-system-interface",
+ "solana-sysvar",
+ "solana-zk-sdk",
+ "spl-elgamal-registry",
+ "spl-memo",
+ "spl-pod",
+ "spl-token",
+ "spl-token-confidential-transfer-ciphertext-arithmetic",
+ "spl-token-confidential-transfer-proof-extraction",
+ "spl-token-confidential-transfer-proof-generation",
+ "spl-token-group-interface",
+ "spl-token-metadata-interface",
+ "spl-transfer-hook-interface",
+ "spl-type-length-value",
+ "thiserror 2.0.17",
]
[[package]]
-name = "solana-atomic-u64"
-version = "2.2.1"
+name = "spl-token-confidential-transfer-ciphertext-arithmetic"
+version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d52e52720efe60465b052b9e7445a01c17550666beec855cce66f44766697bc2"
+checksum = "cddd52bfc0f1c677b41493dafa3f2dbbb4b47cf0990f08905429e19dc8289b35"
dependencies = [
- "parking_lot 0.12.5",
+ "base64 0.22.1",
+ "bytemuck",
+ "solana-curve25519",
+ "solana-zk-sdk",
]
[[package]]
-name = "solana-decode-error"
-version = "2.3.0"
+name = "spl-token-confidential-transfer-proof-extraction"
+version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8c781686a18db2f942e70913f7ca15dc120ec38dcab42ff7557db2c70c625a35"
+checksum = "fe2629860ff04c17bafa9ba4bed8850a404ecac81074113e1f840dbd0ebb7bd6"
dependencies = [
- "num-traits",
+ "bytemuck",
+ "solana-account-info",
+ "solana-curve25519",
+ "solana-instruction",
+ "solana-instructions-sysvar",
+ "solana-msg",
+ "solana-program-error",
+ "solana-pubkey",
+ "solana-sdk-ids",
+ "solana-zk-sdk",
+ "spl-pod",
+ "thiserror 2.0.17",
]
[[package]]
-name = "solana-define-syscall"
-version = "2.3.0"
+name = "spl-token-confidential-transfer-proof-generation"
+version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2ae3e2abcf541c8122eafe9a625d4d194b4023c20adde1e251f94e056bb1aee2"
+checksum = "fa27b9174bea869a7ebf31e0be6890bce90b1a4288bc2bbf24bd413f80ae3fde"
+dependencies = [
+ "curve25519-dalek 4.1.3",
+ "solana-zk-sdk",
+ "thiserror 2.0.17",
+]
[[package]]
-name = "solana-hash"
-version = "2.3.0"
+name = "spl-token-group-interface"
+version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b5b96e9f0300fa287b545613f007dfe20043d7812bee255f418c1eb649c93b63"
+checksum = "5597b4cd76f85ce7cd206045b7dc22da8c25516573d42d267c8d1fd128db5129"
dependencies = [
- "five8",
- "js-sys",
- "solana-atomic-u64",
- "solana-sanitize",
- "wasm-bindgen",
+ "bytemuck",
+ "num-derive",
+ "num-traits",
+ "solana-decode-error",
+ "solana-instruction",
+ "solana-msg",
+ "solana-program-error",
+ "solana-pubkey",
+ "spl-discriminator",
+ "spl-pod",
+ "thiserror 2.0.17",
]
[[package]]
-name = "solana-pubkey"
-version = "2.4.0"
+name = "spl-token-metadata-interface"
+version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9b62adb9c3261a052ca1f999398c388f1daf558a1b492f60a6d9e64857db4ff1"
+checksum = "304d6e06f0de0c13a621464b1fd5d4b1bebf60d15ca71a44d3839958e0da16ee"
dependencies = [
- "five8",
- "five8_const",
- "getrandom 0.2.16",
- "js-sys",
+ "borsh 1.6.0",
+ "num-derive",
"num-traits",
- "solana-atomic-u64",
+ "solana-borsh",
"solana-decode-error",
- "solana-define-syscall",
- "solana-sanitize",
- "solana-sha256-hasher",
- "wasm-bindgen",
+ "solana-instruction",
+ "solana-msg",
+ "solana-program-error",
+ "solana-pubkey",
+ "spl-discriminator",
+ "spl-pod",
+ "spl-type-length-value",
+ "thiserror 2.0.17",
]
[[package]]
-name = "solana-sanitize"
-version = "2.2.1"
+name = "spl-transfer-hook-interface"
+version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "61f1bc1357b8188d9c4a3af3fc55276e56987265eb7ad073ae6f8180ee54cecf"
+checksum = "a7e905b849b6aba63bde8c4badac944ebb6c8e6e14817029cbe1bc16829133bd"
+dependencies = [
+ "arrayref",
+ "bytemuck",
+ "num-derive",
+ "num-traits",
+ "solana-account-info",
+ "solana-cpi",
+ "solana-decode-error",
+ "solana-instruction",
+ "solana-msg",
+ "solana-program-error",
+ "solana-pubkey",
+ "spl-discriminator",
+ "spl-pod",
+ "spl-program-error",
+ "spl-tlv-account-resolution",
+ "spl-type-length-value",
+ "thiserror 2.0.17",
+]
[[package]]
-name = "solana-sha256-hasher"
-version = "2.3.0"
+name = "spl-type-length-value"
+version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5aa3feb32c28765f6aa1ce8f3feac30936f16c5c3f7eb73d63a5b8f6f8ecdc44"
+checksum = "d417eb548214fa822d93f84444024b4e57c13ed6719d4dcc68eec24fb481e9f5"
dependencies = [
- "sha2",
- "solana-define-syscall",
- "solana-hash",
+ "bytemuck",
+ "num-derive",
+ "num-traits",
+ "solana-account-info",
+ "solana-decode-error",
+ "solana-msg",
+ "solana-program-error",
+ "spl-discriminator",
+ "spl-pod",
+ "thiserror 2.0.17",
]
[[package]]
@@ -3032,6 +5159,17 @@ version = "2.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
+[[package]]
+name = "syn"
+version = "1.0.109"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
[[package]]
name = "syn"
version = "2.0.113"
@@ -3066,7 +5204,7 @@ checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.113",
]
[[package]]
@@ -3150,7 +5288,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.113",
]
[[package]]
@@ -3161,7 +5299,7 @@ checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.113",
]
[[package]]
@@ -3233,7 +5371,7 @@ checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.113",
]
[[package]]
@@ -3332,6 +5470,15 @@ dependencies = [
"tokio",
]
+[[package]]
+name = "toml"
+version = "0.5.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234"
+dependencies = [
+ "serde",
+]
+
[[package]]
name = "toml"
version = "0.8.23"
@@ -3340,8 +5487,8 @@ checksum = "dc1beb996b9d83529a9e75c17a1686767d148d70663143c7854d8b4a09ced362"
dependencies = [
"serde",
"serde_spanned",
- "toml_datetime",
- "toml_edit",
+ "toml_datetime 0.6.11",
+ "toml_edit 0.22.27",
]
[[package]]
@@ -3353,6 +5500,15 @@ dependencies = [
"serde",
]
+[[package]]
+name = "toml_datetime"
+version = "1.0.0+spec-1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "32c2555c699578a4f59f0cc68e5116c8d7cabbd45e1409b989d4be085b53f13e"
+dependencies = [
+ "serde_core",
+]
+
[[package]]
name = "toml_edit"
version = "0.22.27"
@@ -3362,11 +5518,32 @@ dependencies = [
"indexmap 2.12.1",
"serde",
"serde_spanned",
- "toml_datetime",
+ "toml_datetime 0.6.11",
"toml_write",
"winnow",
]
+[[package]]
+name = "toml_edit"
+version = "0.25.4+spec-1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7193cbd0ce53dc966037f54351dbbcf0d5a642c7f0038c382ef9e677ce8c13f2"
+dependencies = [
+ "indexmap 2.12.1",
+ "toml_datetime 1.0.0+spec-1.1.0",
+ "toml_parser",
+ "winnow",
+]
+
+[[package]]
+name = "toml_parser"
+version = "1.0.9+spec-1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "702d4415e08923e7e1ef96cd5727c0dfed80b4d2fa25db9647fe5eb6f7c5a4c4"
+dependencies = [
+ "winnow",
+]
+
[[package]]
name = "toml_write"
version = "0.1.2"
@@ -3476,7 +5653,7 @@ dependencies = [
"prost-build 0.13.5",
"prost-types 0.13.5",
"quote",
- "syn",
+ "syn 2.0.113",
]
[[package]]
@@ -3488,7 +5665,7 @@ dependencies = [
"prettyplease",
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.113",
]
[[package]]
@@ -3526,7 +5703,7 @@ dependencies = [
"prost-build 0.14.1",
"prost-types 0.14.1",
"quote",
- "syn",
+ "syn 2.0.113",
"tempfile",
"tonic-build 0.14.2",
]
@@ -3649,7 +5826,7 @@ checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.113",
]
[[package]]
@@ -3791,12 +5968,32 @@ version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254"
+[[package]]
+name = "universal-hash"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea"
+dependencies = [
+ "crypto-common",
+ "subtle",
+]
+
[[package]]
name = "untrusted"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1"
+[[package]]
+name = "uriparse"
+version = "0.6.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0200d0fc04d809396c2ad43f3c95da3582a2556eba8d453c1087f4120ee352ff"
+dependencies = [
+ "fnv",
+ "lazy_static",
+]
+
[[package]]
name = "url"
version = "2.5.8"
@@ -3872,6 +6069,12 @@ dependencies = [
"try-lock",
]
+[[package]]
+name = "wasi"
+version = "0.9.0+wasi-snapshot-preview1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519"
+
[[package]]
name = "wasi"
version = "0.11.1+wasi-snapshot-preview1"
@@ -3932,7 +6135,7 @@ dependencies = [
"bumpalo",
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.113",
"wasm-bindgen-shared",
]
@@ -4032,7 +6235,7 @@ checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.113",
]
[[package]]
@@ -4043,7 +6246,7 @@ checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.113",
]
[[package]]
@@ -4363,9 +6566,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dbba21b6046eff1c9be2366a70d7264763b10004306e874b54409503a39e5f1e"
dependencies = [
"anyhow",
+ "bincode",
"prost 0.14.1",
"prost-types 0.14.1",
"protobuf-src",
+ "solana-account",
+ "solana-account-decoder",
+ "solana-clock",
+ "solana-hash",
+ "solana-message",
+ "solana-pubkey",
+ "solana-signature",
+ "solana-transaction",
+ "solana-transaction-context",
+ "solana-transaction-error",
+ "solana-transaction-status",
"tonic 0.14.2",
"tonic-build 0.14.2",
"tonic-prost",
@@ -4399,7 +6614,7 @@ version = "0.6.0-alpha.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e2760099b3e0810026ec77bb886bbe62bffa70819eea4defb62d480366d828b"
dependencies = [
- "borsh",
+ "borsh 1.6.0",
"bs58",
"clap",
"serde",
@@ -4458,7 +6673,7 @@ checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.113",
"synstructure",
]
@@ -4479,7 +6694,7 @@ checksum = "d8a8d209fdf45cf5138cbb5a506f6b52522a25afccc534d1475dad8e31105c6a"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.113",
]
[[package]]
@@ -4499,7 +6714,7 @@ checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.113",
"synstructure",
]
@@ -4508,6 +6723,20 @@ name = "zeroize"
version = "1.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0"
+dependencies = [
+ "zeroize_derive",
+]
+
+[[package]]
+name = "zeroize_derive"
+version = "1.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "85a5b4158499876c763cb03bc4e49185d3cccbabb15b33c627f7884f43db852e"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.113",
+]
[[package]]
name = "zerotrie"
@@ -4539,7 +6768,7 @@ checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.113",
]
[[package]]
diff --git a/Cargo.toml b/Cargo.toml
index 941c862f..081dbd54 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -29,3 +29,6 @@ yellowstone-vixen = "0.6.0-alpha.0"
yellowstone-vixen-core = "0.6.0-alpha.0"
yellowstone-vixen-proto = "0.6.0-alpha.0"
yellowstone-vixen-yellowstone-grpc-source = "0.6.0-alpha.0"
+# Yellowstone gRPC client (for standalone slot subscriptions)
+yellowstone-grpc-client = "9.1.0"
+yellowstone-grpc-proto = "9.1.0"
diff --git a/examples/ore-react/src/components/BlockGrid.tsx b/examples/ore-react/src/components/BlockGrid.tsx
index 2f1bc212..1df97b44 100644
--- a/examples/ore-react/src/components/BlockGrid.tsx
+++ b/examples/ore-react/src/components/BlockGrid.tsx
@@ -7,11 +7,11 @@ interface BlockGridProps {
export function BlockGrid({ round }: BlockGridProps) {
const blocks = round
- ? round.state.deployed_per_square_ui.map((deployedUi, i) => ({
+ ? (round.state?.deployed_per_square_ui || []).map((deployedUi, i) => ({
id: i + 1,
- minerCount: round.state.count_per_square[i],
+ minerCount: round.state?.count_per_square?.[i],
deployedUi,
- isWinner: round.results?.winning_square === i,
+ isWinner: (round.results?.winning_square === i) || (round.results?.pre_reveal_winning_square === i),
}))
: Array.from({ length: 25 }, (_, i) => ({
id: i + 1,
@@ -21,9 +21,9 @@ export function BlockGrid({ round }: BlockGridProps) {
}));
return (
-
('00:00');
useEffect(() => {
- const expiresAtUnix = round?.state.estimated_expires_at_unix;
+ const expiresAtUnix = round?.state?.estimated_expires_at_unix;
if (!expiresAtUnix) {
setTimeRemaining('00:00');
return;
@@ -35,7 +35,7 @@ export function StatsPanel({ round, treasuryMotherlode, isConnected }: StatsPane
updateTimer();
const interval = setInterval(updateTimer, 1000);
return () => clearInterval(interval);
- }, [round?.state.estimated_expires_at_unix]);
+ }, [round?.state?.estimated_expires_at_unix]);
return (
@@ -56,7 +56,7 @@ export function StatsPanel({ round, treasuryMotherlode, isConnected }: StatsPane
- {round ? round.state.total_deployed.toFixed(4) : '0.0000'}
+ {round ? round.state?.total_deployed?.toFixed(4) : '0.0000'}
Total deployed
@@ -70,11 +70,11 @@ export function StatsPanel({ round, treasuryMotherlode, isConnected }: StatsPane
- Round {round?.id.round_id ?? '–'}
+ Round {round?.id?.round_id ?? '–'}
{round && (
<>
·
- {round.state.total_miners} miners
+ {round.state?.total_miners} miners
>
)}
diff --git a/examples/ore-server/Cargo.lock b/examples/ore-server/Cargo.lock
index 956c0a4b..4a61a85d 100644
--- a/examples/ore-server/Cargo.lock
+++ b/examples/ore-server/Cargo.lock
@@ -2,12 +2,83 @@
# It is not intended for manual editing.
version = 4
+[[package]]
+name = "Inflector"
+version = "0.11.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fe438c63458706e03479442743baae6c88256498e6431708f6dfc520a26515d3"
+dependencies = [
+ "lazy_static",
+ "regex",
+]
+
[[package]]
name = "adler2"
version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa"
+[[package]]
+name = "aead"
+version = "0.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0"
+dependencies = [
+ "crypto-common",
+ "generic-array",
+]
+
+[[package]]
+name = "aes"
+version = "0.8.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0"
+dependencies = [
+ "cfg-if",
+ "cipher",
+ "cpufeatures",
+]
+
+[[package]]
+name = "aes-gcm-siv"
+version = "0.11.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ae0784134ba9375416d469ec31e7c5f9fa94405049cf08c5ce5b4698be673e0d"
+dependencies = [
+ "aead",
+ "aes",
+ "cipher",
+ "ctr",
+ "polyval",
+ "subtle",
+ "zeroize",
+]
+
+[[package]]
+name = "agave-feature-set"
+version = "2.3.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d52a2c365c0245cbb8959de725fc2b44c754b673fdf34c9a7f9d4a25c35a7bf1"
+dependencies = [
+ "ahash",
+ "solana-epoch-schedule",
+ "solana-hash",
+ "solana-pubkey",
+ "solana-sha256-hasher",
+ "solana-svm-feature-set",
+]
+
+[[package]]
+name = "agave-reserved-account-keys"
+version = "2.3.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8289c8a8a2ef5aa10ce49a070f360f4e035ee3410b8d8f3580fb39d8cf042581"
+dependencies = [
+ "agave-feature-set",
+ "solana-pubkey",
+ "solana-sdk-ids",
+]
+
[[package]]
name = "ahash"
version = "0.8.12"
@@ -15,6 +86,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75"
dependencies = [
"cfg-if",
+ "getrandom 0.3.4",
"once_cell",
"version_check",
"zerocopy",
@@ -37,9 +109,9 @@ checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923"
[[package]]
name = "anstream"
-version = "0.6.21"
+version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "43d5b281e737544384e969a5ccad3f1cdd24b48086a0fc1b2a5262a26b8f4f4a"
+checksum = "824a212faf96e9acacdbd09febd34438f8f711fb84e09a8916013cd7815ca28d"
dependencies = [
"anstyle",
"anstyle-parse",
@@ -52,15 +124,15 @@ dependencies = [
[[package]]
name = "anstyle"
-version = "1.0.13"
+version = "1.0.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5192cca8006f1fd4f7237516f40fa183bb07f8fbdfedaa0036de5ea9b0b45e78"
+checksum = "940b3a0ca603d1eade50a4846a2afffd5ef57a9feac2c0e2ec2e14f9ead76000"
[[package]]
name = "anstyle-parse"
-version = "0.2.7"
+version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2"
+checksum = "52ce7f38b242319f7cabaa6813055467063ecdc9d355bbb4ce0c68908cd8130e"
dependencies = [
"utf8parse",
]
@@ -87,9 +159,21 @@ dependencies = [
[[package]]
name = "anyhow"
-version = "1.0.100"
+version = "1.0.102"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61"
+checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c"
+
+[[package]]
+name = "arrayref"
+version = "0.3.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb"
+
+[[package]]
+name = "arrayvec"
+version = "0.7.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50"
[[package]]
name = "async-stream"
@@ -110,7 +194,7 @@ checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.114",
+ "syn 2.0.117",
]
[[package]]
@@ -121,7 +205,7 @@ checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.114",
+ "syn 2.0.117",
]
[[package]]
@@ -235,6 +319,12 @@ dependencies = [
"tower-service",
]
+[[package]]
+name = "base64"
+version = "0.12.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3441f0f7b02788e948e47f457ca01f1d7e6d92c693bc132c22b087d3141c03ff"
+
[[package]]
name = "base64"
version = "0.21.7"
@@ -247,6 +337,15 @@ version = "0.22.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
+[[package]]
+name = "bincode"
+version = "1.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad"
+dependencies = [
+ "serde",
+]
+
[[package]]
name = "bitflags"
version = "1.3.2"
@@ -255,9 +354,33 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "bitflags"
-version = "2.10.0"
+version = "2.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af"
+
+[[package]]
+name = "blake3"
+version = "1.8.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2468ef7d57b3fb7e16b576e8377cdbde2320c60e1491e961d11da40fc4f02a2d"
+dependencies = [
+ "arrayref",
+ "arrayvec",
+ "cc",
+ "cfg-if",
+ "constant_time_eq",
+ "cpufeatures",
+ "digest 0.10.7",
+]
+
+[[package]]
+name = "block-buffer"
+version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3"
+checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4"
+dependencies = [
+ "generic-array",
+]
[[package]]
name = "block-buffer"
@@ -308,10 +431,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0686c856aa6aac0c4498f936d7d6a02df690f614c03e4d906d1018062b5c5e2c"
dependencies = [
"once_cell",
- "proc-macro-crate 3.4.0",
+ "proc-macro-crate 3.5.0",
"proc-macro2",
"quote",
- "syn 2.0.114",
+ "syn 2.0.117",
]
[[package]]
@@ -347,9 +470,19 @@ dependencies = [
[[package]]
name = "bumpalo"
-version = "3.19.1"
+version = "3.20.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb"
+
+[[package]]
+name = "bv"
+version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5dd9dc738b7a8311c7ade152424974d8115f2cdad61e8dab8dac9f2362298510"
+checksum = "8834bb1d8ee5dc048ee3124f2c7c1afcc6bc9aed03f11e9dfd8c69470a5db340"
+dependencies = [
+ "feature-probe",
+ "serde",
+]
[[package]]
name = "bytemuck"
@@ -368,7 +501,7 @@ checksum = "f9abbd1bc6865053c427f7198e6af43bfdedc55ab791faed4fbd361d789575ff"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.114",
+ "syn 2.0.117",
]
[[package]]
@@ -379,15 +512,15 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
[[package]]
name = "bytes"
-version = "1.11.0"
+version = "1.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b35204fbdc0b3f4446b89fc1ac2cf84a8a68971995d0bf2e925ec7cd960f9cb3"
+checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33"
[[package]]
name = "cc"
-version = "1.2.53"
+version = "1.2.57"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "755d2fce177175ffca841e9a06afdb2c4ab0f593d53b4dee48147dfaade85932"
+checksum = "7a0dd1ca384932ff3641c8718a02769f1698e7563dc6974ffd03346116310423"
dependencies = [
"find-msvc-tools",
"jobserver",
@@ -407,11 +540,21 @@ version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724"
+[[package]]
+name = "cipher"
+version = "0.4.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad"
+dependencies = [
+ "crypto-common",
+ "inout",
+]
+
[[package]]
name = "clap"
-version = "4.5.54"
+version = "4.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c6e6ff9dcd79cff5cd969a17a545d79e84ab086e444102a591e288a8aa3ce394"
+checksum = "b193af5b67834b676abd72466a96c1024e6a6ad978a1f484bd90b85c94041351"
dependencies = [
"clap_builder",
"clap_derive",
@@ -419,9 +562,9 @@ dependencies = [
[[package]]
name = "clap_builder"
-version = "4.5.54"
+version = "4.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fa42cf4d2b7a41bc8f663a7cab4031ebafa1bf3875705bfaf8466dc60ab52c00"
+checksum = "714a53001bf66416adb0e2ef5ac857140e7dc3a0c48fb28b2f10762fc4b5069f"
dependencies = [
"anstream",
"anstyle",
@@ -432,27 +575,53 @@ dependencies = [
[[package]]
name = "clap_derive"
-version = "4.5.49"
+version = "4.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2a0b5487afeab2deb2ff4e03a807ad1a03ac532ff5a2cee5d86884440c7f7671"
+checksum = "1110bd8a634a1ab8cb04345d8d878267d57c3cf1b38d91b71af6686408bbca6a"
dependencies = [
"heck",
"proc-macro2",
"quote",
- "syn 2.0.114",
+ "syn 2.0.117",
]
[[package]]
name = "clap_lex"
-version = "0.7.7"
+version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c3e64b0cc0439b12df2fa678eae89a1c56a529fd067a9115f7827f1fffd22b32"
+checksum = "c8d4a3bb8b1e0c1050499d1815f5ab16d04f0959b233085fb31653fbfc9d98f9"
[[package]]
name = "colorchoice"
-version = "1.0.4"
+version = "1.0.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1d07550c9036bf2ae0c684c4297d503f838287c83c53686d05370d0e139ae570"
+
+[[package]]
+name = "console_error_panic_hook"
+version = "0.1.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc"
+dependencies = [
+ "cfg-if",
+ "wasm-bindgen",
+]
+
+[[package]]
+name = "console_log"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e89f72f65e8501878b8a004d5a1afb780987e2ce2b4532c562e367a72c57499f"
+dependencies = [
+ "log",
+ "web-sys",
+]
+
+[[package]]
+name = "constant_time_eq"
+version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75"
+checksum = "3d52eff69cd5e647efe296129160853a42795992097e8af39800e1060caeea9b"
[[package]]
name = "core-foundation"
@@ -554,6 +723,12 @@ version = "0.8.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28"
+[[package]]
+name = "crunchy"
+version = "0.2.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5"
+
[[package]]
name = "crypto-common"
version = "0.1.7"
@@ -561,9 +736,61 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a"
dependencies = [
"generic-array",
+ "rand_core 0.6.4",
"typenum",
]
+[[package]]
+name = "ctr"
+version = "0.9.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0369ee1ad671834580515889b80f2ea915f23b8be8d0daa4bbaf2ac5c7590835"
+dependencies = [
+ "cipher",
+]
+
+[[package]]
+name = "curve25519-dalek"
+version = "3.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0b9fdf9972b2bd6af2d913799d9ebc165ea4d2e65878e329d9c6b372c4491b61"
+dependencies = [
+ "byteorder",
+ "digest 0.9.0",
+ "rand_core 0.5.1",
+ "subtle",
+ "zeroize",
+]
+
+[[package]]
+name = "curve25519-dalek"
+version = "4.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be"
+dependencies = [
+ "cfg-if",
+ "cpufeatures",
+ "curve25519-dalek-derive",
+ "digest 0.10.7",
+ "fiat-crypto",
+ "rand_core 0.6.4",
+ "rustc_version",
+ "serde",
+ "subtle",
+ "zeroize",
+]
+
+[[package]]
+name = "curve25519-dalek-derive"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.117",
+]
+
[[package]]
name = "dashmap"
version = "6.1.0"
@@ -584,14 +811,30 @@ version = "2.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d7a1e2f27636f116493b8b860f5546edb47c8d8f8ea73e1d2a20be88e28d1fea"
+[[package]]
+name = "derivation-path"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6e5c37193a1db1d8ed868c03ec7b152175f26160a5b740e5e484143877e0adf0"
+
+[[package]]
+name = "digest"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066"
+dependencies = [
+ "generic-array",
+]
+
[[package]]
name = "digest"
version = "0.10.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
dependencies = [
- "block-buffer",
+ "block-buffer 0.10.4",
"crypto-common",
+ "subtle",
]
[[package]]
@@ -602,7 +845,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.114",
+ "syn 2.0.117",
]
[[package]]
@@ -622,7 +865,7 @@ checksum = "c32e3e8ab1b6ee2e06418f40f94f315d82b35157eb1d2322a6e20a4b15106b84"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.114",
+ "syn 2.0.117",
]
[[package]]
@@ -631,6 +874,29 @@ version = "0.15.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b"
+[[package]]
+name = "ed25519"
+version = "1.5.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "91cff35c70bba8a626e3185d8cd48cc11b5437e1a5bcd15b9b5fa3c64b6dfee7"
+dependencies = [
+ "signature",
+]
+
+[[package]]
+name = "ed25519-dalek"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c762bae6dcaf24c4c84667b8579785430908723d5c889f469d76a41d59cc7a9d"
+dependencies = [
+ "curve25519-dalek 3.2.0",
+ "ed25519",
+ "rand 0.7.3",
+ "serde",
+ "sha2 0.9.9",
+ "zeroize",
+]
+
[[package]]
name = "either"
version = "1.15.0"
@@ -668,11 +934,23 @@ version = "2.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be"
+[[package]]
+name = "feature-probe"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "835a3dc7d1ec9e75e2b5fb4ba75396837112d2060b03f7d43bc1897c7f7211da"
+
+[[package]]
+name = "fiat-crypto"
+version = "0.2.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d"
+
[[package]]
name = "find-msvc-tools"
-version = "0.1.8"
+version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8591b0bcc8a98a64310a2fae1bb3e9b8564dd10e381e6e28010fde8e8e8568db"
+checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582"
[[package]]
name = "five8"
@@ -706,9 +984,9 @@ checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99"
[[package]]
name = "flate2"
-version = "1.1.8"
+version = "1.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b375d6465b98090a5f25b1c7703f3859783755aa9a80433b36e0379a3ec2f369"
+checksum = "843fba2746e448b37e26a819579957415c8cef339bf08564fe8b7ddbd959573c"
dependencies = [
"crc32fast",
"miniz_oxide",
@@ -737,9 +1015,9 @@ dependencies = [
[[package]]
name = "futures"
-version = "0.3.31"
+version = "0.3.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876"
+checksum = "8b147ee9d1f6d097cef9ce628cd2ee62288d963e16fb287bd9286455b241382d"
dependencies = [
"futures-channel",
"futures-core",
@@ -752,9 +1030,9 @@ dependencies = [
[[package]]
name = "futures-channel"
-version = "0.3.31"
+version = "0.3.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10"
+checksum = "07bbe89c50d7a535e539b8c17bc0b49bdb77747034daa8087407d655f3f7cc1d"
dependencies = [
"futures-core",
"futures-sink",
@@ -762,15 +1040,15 @@ dependencies = [
[[package]]
name = "futures-core"
-version = "0.3.31"
+version = "0.3.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e"
+checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d"
[[package]]
name = "futures-executor"
-version = "0.3.31"
+version = "0.3.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f"
+checksum = "baf29c38818342a3b26b5b923639e7b1f4a61fc5e76102d4b1981c6dc7a7579d"
dependencies = [
"futures-core",
"futures-task",
@@ -779,38 +1057,38 @@ dependencies = [
[[package]]
name = "futures-io"
-version = "0.3.31"
+version = "0.3.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6"
+checksum = "cecba35d7ad927e23624b22ad55235f2239cfa44fd10428eecbeba6d6a717718"
[[package]]
name = "futures-macro"
-version = "0.3.31"
+version = "0.3.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650"
+checksum = "e835b70203e41293343137df5c0664546da5745f82ec9b84d40be8336958447b"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.114",
+ "syn 2.0.117",
]
[[package]]
name = "futures-sink"
-version = "0.3.31"
+version = "0.3.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7"
+checksum = "c39754e157331b013978ec91992bde1ac089843443c49cbc7f46150b0fad0893"
[[package]]
name = "futures-task"
-version = "0.3.31"
+version = "0.3.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988"
+checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393"
[[package]]
name = "futures-util"
-version = "0.3.31"
+version = "0.3.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81"
+checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6"
dependencies = [
"futures-channel",
"futures-core",
@@ -820,7 +1098,6 @@ dependencies = [
"futures-task",
"memchr",
"pin-project-lite",
- "pin-utils",
"slab",
]
@@ -834,6 +1111,17 @@ dependencies = [
"version_check",
]
+[[package]]
+name = "getrandom"
+version = "0.1.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "wasi 0.9.0+wasi-snapshot-preview1",
+]
+
[[package]]
name = "getrandom"
version = "0.2.17"
@@ -843,7 +1131,7 @@ dependencies = [
"cfg-if",
"js-sys",
"libc",
- "wasi",
+ "wasi 0.11.1+wasi-snapshot-preview1",
"wasm-bindgen",
]
@@ -856,11 +1144,24 @@ dependencies = [
"cfg-if",
"js-sys",
"libc",
- "r-efi",
+ "r-efi 5.3.0",
"wasip2",
"wasm-bindgen",
]
+[[package]]
+name = "getrandom"
+version = "0.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "r-efi 6.0.0",
+ "wasip2",
+ "wasip3",
+]
+
[[package]]
name = "h2"
version = "0.3.27"
@@ -955,6 +1256,15 @@ version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
+[[package]]
+name = "hmac"
+version = "0.12.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e"
+dependencies = [
+ "digest 0.10.7",
+]
+
[[package]]
name = "http"
version = "0.2.12"
@@ -1092,12 +1402,12 @@ dependencies = [
"http 1.4.0",
"hyper 1.8.1",
"hyper-util",
- "rustls 0.23.36",
+ "rustls 0.23.37",
"rustls-pki-types",
"tokio",
"tokio-rustls 0.26.4",
"tower-service",
- "webpki-roots 1.0.5",
+ "webpki-roots 1.0.6",
]
[[package]]
@@ -1115,14 +1425,13 @@ dependencies = [
[[package]]
name = "hyper-util"
-version = "0.1.19"
+version = "0.1.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "727805d60e7938b76b826a6ef209eb70eaa1812794f9424d4a4e2d740662df5f"
+checksum = "96547c2556ec9d12fb1578c4eaf448b04993e7fb79cbaad930a656880a6bdfa0"
dependencies = [
"base64 0.22.1",
"bytes",
"futures-channel",
- "futures-core",
"futures-util",
"http 1.4.0",
"http-body 1.0.1",
@@ -1131,7 +1440,7 @@ dependencies = [
"libc",
"percent-encoding",
"pin-project-lite",
- "socket2 0.6.1",
+ "socket2 0.6.3",
"tokio",
"tower-service",
"tracing",
@@ -1139,12 +1448,13 @@ dependencies = [
[[package]]
name = "hyperstack"
-version = "0.5.3"
+version = "0.5.5"
dependencies = [
"anyhow",
"bs58",
"bytemuck",
"dotenvy",
+ "futures",
"hyperstack-interpreter",
"hyperstack-macros",
"hyperstack-sdk",
@@ -1152,9 +1462,12 @@ dependencies = [
"reqwest 0.11.27",
"serde",
"serde_json",
+ "sha3",
"smallvec",
"tokio",
"tracing",
+ "yellowstone-grpc-client",
+ "yellowstone-grpc-proto",
"yellowstone-vixen",
"yellowstone-vixen-core",
"yellowstone-vixen-yellowstone-grpc-source",
@@ -1162,17 +1475,17 @@ dependencies = [
[[package]]
name = "hyperstack-idl"
-version = "0.1.0"
+version = "0.1.2"
dependencies = [
"serde",
"serde_json",
- "sha2",
+ "sha2 0.10.9",
"strsim",
]
[[package]]
name = "hyperstack-interpreter"
-version = "0.5.3"
+version = "0.5.5"
dependencies = [
"bs58",
"dashmap",
@@ -1181,21 +1494,25 @@ dependencies = [
"hyperstack-idl",
"hyperstack-macros",
"lru",
+ "once_cell",
+ "percent-encoding",
"prost 0.13.5",
"prost-reflect",
"prost-types 0.13.5",
"reqwest 0.12.28",
"serde",
"serde_json",
- "sha2",
+ "sha2 0.10.9",
+ "sha3",
"solana-pubkey",
+ "tokio",
"tonic 0.12.3",
"tracing",
]
[[package]]
name = "hyperstack-macros"
-version = "0.5.3"
+version = "0.5.5"
dependencies = [
"bs58",
"hex",
@@ -1204,13 +1521,13 @@ dependencies = [
"quote",
"serde",
"serde_json",
- "sha2",
- "syn 2.0.114",
+ "sha2 0.10.9",
+ "syn 2.0.117",
]
[[package]]
name = "hyperstack-sdk"
-version = "0.5.3"
+version = "0.5.5"
dependencies = [
"anyhow",
"flate2",
@@ -1227,7 +1544,7 @@ dependencies = [
[[package]]
name = "hyperstack-server"
-version = "0.5.3"
+version = "0.5.5"
dependencies = [
"anyhow",
"base64 0.22.1",
@@ -1241,6 +1558,7 @@ dependencies = [
"hyper-util",
"hyperstack-interpreter",
"lru",
+ "once_cell",
"serde",
"serde_json",
"smallvec",
@@ -1338,6 +1656,12 @@ dependencies = [
"zerovec",
]
+[[package]]
+name = "id-arena"
+version = "2.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954"
+
[[package]]
name = "idna"
version = "1.1.0"
@@ -1377,6 +1701,17 @@ checksum = "7714e70437a7dc3ac8eb7e6f8df75fd8eb422675fc7678aff7364301092b1017"
dependencies = [
"equivalent",
"hashbrown 0.16.1",
+ "serde",
+ "serde_core",
+]
+
+[[package]]
+name = "inout"
+version = "0.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01"
+dependencies = [
+ "generic-array",
]
[[package]]
@@ -1390,9 +1725,9 @@ dependencies = [
[[package]]
name = "ipnet"
-version = "2.11.0"
+version = "2.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130"
+checksum = "d98f6fed1fde3f8c21bc40a1abb88dd75e67924f9cffc3ef95607bad8017f8e2"
[[package]]
name = "iri-string"
@@ -1412,7 +1747,16 @@ checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695"
[[package]]
name = "itertools"
-version = "0.14.0"
+version = "0.12.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569"
+dependencies = [
+ "either",
+]
+
+[[package]]
+name = "itertools"
+version = "0.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285"
dependencies = [
@@ -1437,31 +1781,102 @@ dependencies = [
[[package]]
name = "js-sys"
-version = "0.3.85"
+version = "0.3.91"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8c942ebf8e95485ca0d52d97da7c5a2c387d0e7f0ba4c35e93bfcaee045955b3"
+checksum = "b49715b7073f385ba4bc528e5747d02e66cb39c6146efb66b781f131f0fb399c"
dependencies = [
"once_cell",
"wasm-bindgen",
]
+[[package]]
+name = "kaigan"
+version = "0.2.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2ba15de5aeb137f0f65aa3bf82187647f1285abfe5b20c80c2c37f7007ad519a"
+dependencies = [
+ "borsh 0.10.4",
+ "serde",
+]
+
+[[package]]
+name = "keccak"
+version = "0.1.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cb26cec98cce3a3d96cbb7bced3c4b16e3d13f27ec56dbd62cbc8f39cfb9d653"
+dependencies = [
+ "cpufeatures",
+]
+
[[package]]
name = "lazy_static"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
+[[package]]
+name = "leb128fmt"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2"
+
[[package]]
name = "libc"
-version = "0.2.180"
+version = "0.2.183"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b5b646652bf6661599e1da8901b3b9522896f01e736bad5f723fe7a3a27f899d"
+
+[[package]]
+name = "libsecp256k1"
+version = "0.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c9d220bc1feda2ac231cb78c3d26f27676b8cf82c96971f7aeef3d0cf2797c73"
+dependencies = [
+ "arrayref",
+ "base64 0.12.3",
+ "digest 0.9.0",
+ "libsecp256k1-core",
+ "libsecp256k1-gen-ecmult",
+ "libsecp256k1-gen-genmult",
+ "rand 0.7.3",
+ "serde",
+ "sha2 0.9.9",
+]
+
+[[package]]
+name = "libsecp256k1-core"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d0f6ab710cec28cef759c5f18671a27dae2a5f952cdaaee1d8e2908cb2478a80"
+dependencies = [
+ "crunchy",
+ "digest 0.9.0",
+ "subtle",
+]
+
+[[package]]
+name = "libsecp256k1-gen-ecmult"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ccab96b584d38fac86a83f07e659f0deafd0253dc096dab5a36d53efe653c5c3"
+dependencies = [
+ "libsecp256k1-core",
+]
+
+[[package]]
+name = "libsecp256k1-gen-genmult"
+version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bcc35a38544a891a5f7c865aca548a982ccb3b8650a5b06d0fd33a10283c56fc"
+checksum = "67abfe149395e3aa1c48a2beb32b068e2334402df8181f818d3aee2b304c4f5d"
+dependencies = [
+ "libsecp256k1-core",
+]
[[package]]
name = "linux-raw-sys"
-version = "0.11.0"
+version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039"
+checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53"
[[package]]
name = "litemap"
@@ -1522,9 +1937,30 @@ checksum = "47e1ffaa40ddd1f3ed91f717a33c8c0ee23fff369e3aa8772b9605cc1d22f4c3"
[[package]]
name = "memchr"
-version = "2.7.6"
+version = "2.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79"
+
+[[package]]
+name = "memoffset"
+version = "0.9.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a"
+dependencies = [
+ "autocfg",
+]
+
+[[package]]
+name = "merlin"
+version = "3.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273"
+checksum = "58c38e2799fc0978b65dfff8023ec7843e2330bb462f19198840b34b6582397d"
+dependencies = [
+ "byteorder",
+ "keccak",
+ "rand_core 0.6.4",
+ "zeroize",
+]
[[package]]
name = "mime"
@@ -1549,7 +1985,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a69bcab0ad47271a0234d9422b131806bf3968021e5dc9328caf2d4cd58557fc"
dependencies = [
"libc",
- "wasi",
+ "wasi 0.11.1+wasi-snapshot-preview1",
"windows-sys 0.61.2",
]
@@ -1568,6 +2004,36 @@ dependencies = [
"windows-sys 0.61.2",
]
+[[package]]
+name = "num-bigint"
+version = "0.4.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9"
+dependencies = [
+ "num-integer",
+ "num-traits",
+]
+
+[[package]]
+name = "num-derive"
+version = "0.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.117",
+]
+
+[[package]]
+name = "num-integer"
+version = "0.1.46"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f"
+dependencies = [
+ "num-traits",
+]
+
[[package]]
name = "num-traits"
version = "0.2.19"
@@ -1587,11 +2053,33 @@ dependencies = [
"libc",
]
+[[package]]
+name = "num_enum"
+version = "0.7.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5d0bca838442ec211fa11de3a8b0e0e8f3a4522575b5c4c06ed722e005036f26"
+dependencies = [
+ "num_enum_derive",
+ "rustversion",
+]
+
+[[package]]
+name = "num_enum_derive"
+version = "0.7.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "680998035259dcfcafe653688bf2aa6d3e2dc05e98be6ab46afb089dc84f1df8"
+dependencies = [
+ "proc-macro-crate 3.5.0",
+ "proc-macro2",
+ "quote",
+ "syn 2.0.117",
+]
+
[[package]]
name = "once_cell"
-version = "1.21.3"
+version = "1.21.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
+checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50"
[[package]]
name = "once_cell_polyfill"
@@ -1599,11 +2087,17 @@ version = "1.70.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe"
+[[package]]
+name = "opaque-debug"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381"
+
[[package]]
name = "openssl-probe"
-version = "0.2.0"
+version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9f50d9b3dabb09ecd771ad0aa242ca6894994c130308ca3d7684634df8037391"
+checksum = "7c87def4c32ab89d880effc9e097653c8da5d6ef28e6b539d313baaacfbafcbe"
[[package]]
name = "ore-server"
@@ -1613,7 +2107,7 @@ dependencies = [
"dotenvy",
"hyperstack-server",
"ore-stack",
- "rustls 0.23.36",
+ "rustls 0.23.37",
"tokio",
"tracing-subscriber",
]
@@ -1676,6 +2170,15 @@ dependencies = [
"windows-link",
]
+[[package]]
+name = "pbkdf2"
+version = "0.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "83a0692ec44e4cf1ef28ca317f14f8f07da2d95ec3fa01f86e4467b725e60917"
+dependencies = [
+ "digest 0.10.7",
+]
+
[[package]]
name = "percent-encoding"
version = "2.3.2"
@@ -1705,29 +2208,29 @@ dependencies = [
[[package]]
name = "pin-project"
-version = "1.1.10"
+version = "1.1.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "677f1add503faace112b9f1373e43e9e054bfdd22ff1a63c1bc485eaec6a6a8a"
+checksum = "f1749c7ed4bcaf4c3d0a3efc28538844fb29bcdd7d2b67b2be7e20ba861ff517"
dependencies = [
"pin-project-internal",
]
[[package]]
name = "pin-project-internal"
-version = "1.1.10"
+version = "1.1.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861"
+checksum = "d9b20ed30f105399776b9c883e68e536ef602a16ae6f596d2c473591d6ad64c6"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.114",
+ "syn 2.0.117",
]
[[package]]
name = "pin-project-lite"
-version = "0.2.16"
+version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b"
+checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd"
[[package]]
name = "pin-utils"
@@ -1741,6 +2244,18 @@ version = "0.3.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c"
+[[package]]
+name = "polyval"
+version = "0.6.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9d1fe60d06143b2430aa532c94cfe9e29783047f06c0d7fd359a9a51b729fa25"
+dependencies = [
+ "cfg-if",
+ "cpufeatures",
+ "opaque-debug",
+ "universal-hash",
+]
+
[[package]]
name = "potential_utf"
version = "0.1.4"
@@ -1766,7 +2281,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b"
dependencies = [
"proc-macro2",
- "syn 2.0.114",
+ "syn 2.0.117",
]
[[package]]
@@ -1780,18 +2295,18 @@ dependencies = [
[[package]]
name = "proc-macro-crate"
-version = "3.4.0"
+version = "3.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "219cb19e96be00ab2e37d6e299658a0cfa83e52429179969b0f0121b4ac46983"
+checksum = "e67ba7e9b2b56446f1d419b1d807906278ffa1a658a8a5d8a39dcb1f5a78614f"
dependencies = [
"toml_edit",
]
[[package]]
name = "proc-macro2"
-version = "1.0.105"
+version = "1.0.106"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "535d180e0ecab6268a3e718bb9fd44db66bbbc256257165fc699dadf70d16fe7"
+checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934"
dependencies = [
"unicode-ident",
]
@@ -1823,7 +2338,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "be769465445e8c1474e9c5dac2018218498557af32d9ed057325ec9a41ae81bf"
dependencies = [
"heck",
- "itertools",
+ "itertools 0.14.0",
"log",
"multimap",
"once_cell",
@@ -1832,7 +2347,7 @@ dependencies = [
"prost 0.13.5",
"prost-types 0.13.5",
"regex",
- "syn 2.0.114",
+ "syn 2.0.117",
"tempfile",
]
@@ -1843,7 +2358,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "343d3bd7056eda839b03204e68deff7d1b13aba7af2b2fd16890697274262ee7"
dependencies = [
"heck",
- "itertools",
+ "itertools 0.14.0",
"log",
"multimap",
"petgraph 0.8.3",
@@ -1853,7 +2368,7 @@ dependencies = [
"pulldown-cmark",
"pulldown-cmark-to-cmark",
"regex",
- "syn 2.0.114",
+ "syn 2.0.117",
"tempfile",
]
@@ -1864,10 +2379,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a56d757972c98b346a9b766e3f02746cde6dd1cd1d1d563472929fdd74bec4d"
dependencies = [
"anyhow",
- "itertools",
+ "itertools 0.14.0",
"proc-macro2",
"quote",
- "syn 2.0.114",
+ "syn 2.0.117",
]
[[package]]
@@ -1877,10 +2392,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "27c6023962132f4b30eb4c172c91ce92d933da334c59c23cddee82358ddafb0b"
dependencies = [
"anyhow",
- "itertools",
+ "itertools 0.14.0",
"proc-macro2",
"quote",
- "syn 2.0.114",
+ "syn 2.0.117",
]
[[package]]
@@ -1922,11 +2437,11 @@ dependencies = [
[[package]]
name = "pulldown-cmark"
-version = "0.13.0"
+version = "0.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1e8bbe1a966bd2f362681a44f6edce3c2310ac21e4d5067a6e7ec396297a6ea0"
+checksum = "83c41efbf8f90ac44de7f3a868f0867851d261b56291732d0cbf7cceaaeb55a6"
dependencies = [
- "bitflags 2.10.0",
+ "bitflags 2.11.0",
"memchr",
"unicase",
]
@@ -1940,6 +2455,15 @@ dependencies = [
"pulldown-cmark",
]
+[[package]]
+name = "qstring"
+version = "0.7.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d464fae65fff2680baf48019211ce37aaec0c78e9264c84a3e484717f965104e"
+dependencies = [
+ "percent-encoding",
+]
+
[[package]]
name = "quinn"
version = "0.11.9"
@@ -1952,8 +2476,8 @@ dependencies = [
"quinn-proto",
"quinn-udp",
"rustc-hash",
- "rustls 0.23.36",
- "socket2 0.5.10",
+ "rustls 0.23.37",
+ "socket2 0.6.3",
"thiserror 2.0.18",
"tokio",
"tracing",
@@ -1972,7 +2496,7 @@ dependencies = [
"rand 0.9.2",
"ring",
"rustc-hash",
- "rustls 0.23.36",
+ "rustls 0.23.37",
"rustls-pki-types",
"slab",
"thiserror 2.0.18",
@@ -1990,16 +2514,16 @@ dependencies = [
"cfg_aliases",
"libc",
"once_cell",
- "socket2 0.5.10",
+ "socket2 0.6.3",
"tracing",
- "windows-sys 0.52.0",
+ "windows-sys 0.60.2",
]
[[package]]
name = "quote"
-version = "1.0.43"
+version = "1.0.45"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dc74d9a594b72ae6656596548f56f667211f8a97b3d4c3d467150794690dc40a"
+checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924"
dependencies = [
"proc-macro2",
]
@@ -2010,6 +2534,25 @@ version = "5.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f"
+[[package]]
+name = "r-efi"
+version = "6.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf"
+
+[[package]]
+name = "rand"
+version = "0.7.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03"
+dependencies = [
+ "getrandom 0.1.16",
+ "libc",
+ "rand_chacha 0.2.2",
+ "rand_core 0.5.1",
+ "rand_hc",
+]
+
[[package]]
name = "rand"
version = "0.8.5"
@@ -2031,6 +2574,16 @@ dependencies = [
"rand_core 0.9.5",
]
+[[package]]
+name = "rand_chacha"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402"
+dependencies = [
+ "ppv-lite86",
+ "rand_core 0.5.1",
+]
+
[[package]]
name = "rand_chacha"
version = "0.3.1"
@@ -2051,6 +2604,15 @@ dependencies = [
"rand_core 0.9.5",
]
+[[package]]
+name = "rand_core"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19"
+dependencies = [
+ "getrandom 0.1.16",
+]
+
[[package]]
name = "rand_core"
version = "0.6.4"
@@ -2069,6 +2631,15 @@ dependencies = [
"getrandom 0.3.4",
]
+[[package]]
+name = "rand_hc"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c"
+dependencies = [
+ "rand_core 0.5.1",
+]
+
[[package]]
name = "redox_syscall"
version = "0.2.16"
@@ -2084,14 +2655,14 @@ version = "0.5.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d"
dependencies = [
- "bitflags 2.10.0",
+ "bitflags 2.11.0",
]
[[package]]
name = "regex"
-version = "1.12.2"
+version = "1.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "843bc0191f75f3e22651ae5f1e72939ab2f72a4bc30fa80a066bd66edefc24d4"
+checksum = "e10754a14b9137dd7b1e3e5b0493cc9171fdd105e0ab477f51b72e7f3ac0e276"
dependencies = [
"aho-corasick",
"memchr",
@@ -2101,9 +2672,9 @@ dependencies = [
[[package]]
name = "regex-automata"
-version = "0.4.13"
+version = "0.4.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5276caf25ac86c8d810222b3dbb938e512c55c6831a10f3e6ed1c93b84041f1c"
+checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f"
dependencies = [
"aho-corasick",
"memchr",
@@ -2112,9 +2683,9 @@ dependencies = [
[[package]]
name = "regex-syntax"
-version = "0.8.8"
+version = "0.8.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58"
+checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a"
[[package]]
name = "reqwest"
@@ -2177,7 +2748,7 @@ dependencies = [
"percent-encoding",
"pin-project-lite",
"quinn",
- "rustls 0.23.36",
+ "rustls 0.23.37",
"rustls-pki-types",
"serde",
"serde_json",
@@ -2192,7 +2763,7 @@ dependencies = [
"wasm-bindgen",
"wasm-bindgen-futures",
"web-sys",
- "webpki-roots 1.0.5",
+ "webpki-roots 1.0.6",
]
[[package]]
@@ -2215,13 +2786,22 @@ version = "2.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d"
+[[package]]
+name = "rustc_version"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92"
+dependencies = [
+ "semver",
+]
+
[[package]]
name = "rustix"
-version = "1.1.3"
+version = "1.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "146c9e247ccc180c1f61615433868c99f3de3ae256a30a43b49f67c2d9171f34"
+checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190"
dependencies = [
- "bitflags 2.10.0",
+ "bitflags 2.11.0",
"errno",
"libc",
"linux-raw-sys",
@@ -2256,9 +2836,9 @@ dependencies = [
[[package]]
name = "rustls"
-version = "0.23.36"
+version = "0.23.37"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c665f33d38cea657d9614f766881e4d510e0eda4239891eea56b4cadcf01801b"
+checksum = "758025cb5fccfd3bc2fd74708fd4682be41d99e5dff73c377c0646c6012c73a4"
dependencies = [
"log",
"once_cell",
@@ -2340,15 +2920,15 @@ checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d"
[[package]]
name = "ryu"
-version = "1.0.22"
+version = "1.0.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a50f4cf475b65d88e057964e0e9bb1f0aa9bbb2036dc65c64596b42932536984"
+checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f"
[[package]]
name = "schannel"
-version = "0.1.28"
+version = "0.1.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "891d81b926048e76efe18581bf793546b4c0eaf8448d72be8de2bbee5fd166e1"
+checksum = "91c1b7e4904c873ef0710c1f407dde2e6287de2bebc1bbbf7d430bb7cbffd939"
dependencies = [
"windows-sys 0.61.2",
]
@@ -2371,11 +2951,11 @@ dependencies = [
[[package]]
name = "security-framework"
-version = "3.5.1"
+version = "3.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b3297343eaf830f66ede390ea39da1d462b6b0c1b000f420d0a83f898bbbe6ef"
+checksum = "b7f4bc775c73d9a02cde8bf7b2ec4c9d12743edf609006c7facc23998404cd1d"
dependencies = [
- "bitflags 2.10.0",
+ "bitflags 2.11.0",
"core-foundation 0.10.1",
"core-foundation-sys",
"libc",
@@ -2384,14 +2964,20 @@ dependencies = [
[[package]]
name = "security-framework-sys"
-version = "2.15.0"
+version = "2.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cc1f0cbffaac4852523ce30d8bd3c5cdc873501d96ff467ca09b6767bb8cd5c0"
+checksum = "6ce2691df843ecc5d231c0b14ece2acc3efb62c0a398c7e1d875f3983ce020e3"
dependencies = [
"core-foundation-sys",
"libc",
]
+[[package]]
+name = "semver"
+version = "1.0.27"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2"
+
[[package]]
name = "serde"
version = "1.0.228"
@@ -2402,6 +2988,25 @@ dependencies = [
"serde_derive",
]
+[[package]]
+name = "serde-big-array"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "11fc7cc2c76d73e0f27ee52abbd64eec84d46f370c88371120433196934e4b7f"
+dependencies = [
+ "serde",
+]
+
+[[package]]
+name = "serde_bytes"
+version = "0.11.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a5d440709e79d88e51ac01c4b72fc6cb7314017bb7da9eeff678aa94c10e3ea8"
+dependencies = [
+ "serde",
+ "serde_core",
+]
+
[[package]]
name = "serde_core"
version = "1.0.228"
@@ -2419,7 +3024,7 @@ checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.114",
+ "syn 2.0.117",
]
[[package]]
@@ -2455,7 +3060,20 @@ checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba"
dependencies = [
"cfg-if",
"cpufeatures",
- "digest",
+ "digest 0.10.7",
+]
+
+[[package]]
+name = "sha2"
+version = "0.9.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800"
+dependencies = [
+ "block-buffer 0.9.0",
+ "cfg-if",
+ "cpufeatures",
+ "digest 0.9.0",
+ "opaque-debug",
]
[[package]]
@@ -2466,7 +3084,17 @@ checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283"
dependencies = [
"cfg-if",
"cpufeatures",
- "digest",
+ "digest 0.10.7",
+]
+
+[[package]]
+name = "sha3"
+version = "0.10.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60"
+dependencies = [
+ "digest 0.10.7",
+ "keccak",
]
[[package]]
@@ -2475,138 +3103,1571 @@ version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6"
dependencies = [
- "lazy_static",
+ "lazy_static",
+]
+
+[[package]]
+name = "shlex"
+version = "1.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
+
+[[package]]
+name = "signal-hook-registry"
+version = "1.4.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c4db69cba1110affc0e9f7bcd48bbf87b3f4fc7c61fc9155afd4c469eb3d6c1b"
+dependencies = [
+ "errno",
+ "libc",
+]
+
+[[package]]
+name = "signature"
+version = "1.6.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "74233d3b3b2f6d4b006dc19dee745e73e2a6bfb6f93607cd3b02bd5b00797d7c"
+
+[[package]]
+name = "simd-adler32"
+version = "0.3.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e320a6c5ad31d271ad523dcf3ad13e2767ad8b1cb8f047f75a8aeaf8da139da2"
+
+[[package]]
+name = "slab"
+version = "0.4.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5"
+
+[[package]]
+name = "smallvec"
+version = "1.15.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03"
+
+[[package]]
+name = "socket2"
+version = "0.5.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e22376abed350d73dd1cd119b57ffccad95b4e585a7cda43e286245ce23c0678"
+dependencies = [
+ "libc",
+ "windows-sys 0.52.0",
+]
+
+[[package]]
+name = "socket2"
+version = "0.6.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3a766e1110788c36f4fa1c2b71b387a7815aa65f88ce0229841826633d93723e"
+dependencies = [
+ "libc",
+ "windows-sys 0.61.2",
+]
+
+[[package]]
+name = "solana-account"
+version = "2.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0f949fe4edaeaea78c844023bfc1c898e0b1f5a100f8a8d2d0f85d0a7b090258"
+dependencies = [
+ "bincode",
+ "serde",
+ "serde_bytes",
+ "serde_derive",
+ "solana-account-info",
+ "solana-clock",
+ "solana-instruction",
+ "solana-pubkey",
+ "solana-sdk-ids",
+ "solana-sysvar",
+]
+
+[[package]]
+name = "solana-account-decoder"
+version = "2.3.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ba71c97fa4d85ce4a1e0e79044ad0406c419382be598c800202903a7688ce71a"
+dependencies = [
+ "Inflector",
+ "base64 0.22.1",
+ "bincode",
+ "bs58",
+ "bv",
+ "serde",
+ "serde_derive",
+ "serde_json",
+ "solana-account",
+ "solana-account-decoder-client-types",
+ "solana-address-lookup-table-interface",
+ "solana-clock",
+ "solana-config-program-client",
+ "solana-epoch-schedule",
+ "solana-fee-calculator",
+ "solana-instruction",
+ "solana-loader-v3-interface",
+ "solana-nonce",
+ "solana-program-option",
+ "solana-program-pack",
+ "solana-pubkey",
+ "solana-rent",
+ "solana-sdk-ids",
+ "solana-slot-hashes",
+ "solana-slot-history",
+ "solana-stake-interface",
+ "solana-sysvar",
+ "solana-vote-interface",
+ "spl-generic-token",
+ "spl-token",
+ "spl-token-2022",
+ "spl-token-group-interface",
+ "spl-token-metadata-interface",
+ "thiserror 2.0.18",
+ "zstd",
+]
+
+[[package]]
+name = "solana-account-decoder-client-types"
+version = "2.3.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5519e8343325b707f17fbed54fcefb325131b692506d0af9e08a539d15e4f8cf"
+dependencies = [
+ "base64 0.22.1",
+ "bs58",
+ "serde",
+ "serde_derive",
+ "serde_json",
+ "solana-account",
+ "solana-pubkey",
+ "zstd",
+]
+
+[[package]]
+name = "solana-account-info"
+version = "2.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c8f5152a288ef1912300fc6efa6c2d1f9bb55d9398eb6c72326360b8063987da"
+dependencies = [
+ "bincode",
+ "serde",
+ "solana-program-error",
+ "solana-program-memory",
+ "solana-pubkey",
+]
+
+[[package]]
+name = "solana-address-lookup-table-interface"
+version = "2.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d1673f67efe870b64a65cb39e6194be5b26527691ce5922909939961a6e6b395"
+dependencies = [
+ "bincode",
+ "bytemuck",
+ "serde",
+ "serde_derive",
+ "solana-clock",
+ "solana-instruction",
+ "solana-pubkey",
+ "solana-sdk-ids",
+ "solana-slot-hashes",
+]
+
+[[package]]
+name = "solana-atomic-u64"
+version = "2.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d52e52720efe60465b052b9e7445a01c17550666beec855cce66f44766697bc2"
+dependencies = [
+ "parking_lot 0.12.5",
+]
+
+[[package]]
+name = "solana-big-mod-exp"
+version = "2.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "75db7f2bbac3e62cfd139065d15bcda9e2428883ba61fc8d27ccb251081e7567"
+dependencies = [
+ "num-bigint",
+ "num-traits",
+ "solana-define-syscall",
+]
+
+[[package]]
+name = "solana-bincode"
+version = "2.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "19a3787b8cf9c9fe3dd360800e8b70982b9e5a8af9e11c354b6665dd4a003adc"
+dependencies = [
+ "bincode",
+ "serde",
+ "solana-instruction",
+]
+
+[[package]]
+name = "solana-blake3-hasher"
+version = "2.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a1a0801e25a1b31a14494fc80882a036be0ffd290efc4c2d640bfcca120a4672"
+dependencies = [
+ "blake3",
+ "solana-define-syscall",
+ "solana-hash",
+ "solana-sanitize",
+]
+
+[[package]]
+name = "solana-borsh"
+version = "2.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "718333bcd0a1a7aed6655aa66bef8d7fb047944922b2d3a18f49cbc13e73d004"
+dependencies = [
+ "borsh 0.10.4",
+ "borsh 1.6.0",
+]
+
+[[package]]
+name = "solana-clock"
+version = "2.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f8584296123df8fe229b95e2ebfd37ae637fe9db9b7d4dd677ac5a78e80dbfce"
+dependencies = [
+ "serde",
+ "serde_derive",
+ "solana-sdk-ids",
+ "solana-sdk-macro",
+ "solana-sysvar-id",
+]
+
+[[package]]
+name = "solana-commitment-config"
+version = "2.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ac49c4dde3edfa832de1697e9bcdb7c3b3f7cb7a1981b7c62526c8bb6700fb73"
+
+[[package]]
+name = "solana-config-program-client"
+version = "0.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "53aceac36f105fd4922e29b4f0c1f785b69d7b3e7e387e384b8985c8e0c3595e"
+dependencies = [
+ "bincode",
+ "borsh 0.10.4",
+ "kaigan",
+ "serde",
+ "solana-program",
+]
+
+[[package]]
+name = "solana-cpi"
+version = "2.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8dc71126edddc2ba014622fc32d0f5e2e78ec6c5a1e0eb511b85618c09e9ea11"
+dependencies = [
+ "solana-account-info",
+ "solana-define-syscall",
+ "solana-instruction",
+ "solana-program-error",
+ "solana-pubkey",
+ "solana-stable-layout",
+]
+
+[[package]]
+name = "solana-curve25519"
+version = "2.3.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "eae4261b9a8613d10e77ac831a8fa60b6fa52b9b103df46d641deff9f9812a23"
+dependencies = [
+ "bytemuck",
+ "bytemuck_derive",
+ "curve25519-dalek 4.1.3",
+ "solana-define-syscall",
+ "subtle",
+ "thiserror 2.0.18",
+]
+
+[[package]]
+name = "solana-decode-error"
+version = "2.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8c781686a18db2f942e70913f7ca15dc120ec38dcab42ff7557db2c70c625a35"
+dependencies = [
+ "num-traits",
+]
+
+[[package]]
+name = "solana-define-syscall"
+version = "2.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2ae3e2abcf541c8122eafe9a625d4d194b4023c20adde1e251f94e056bb1aee2"
+
+[[package]]
+name = "solana-derivation-path"
+version = "2.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "939756d798b25c5ec3cca10e06212bdca3b1443cb9bb740a38124f58b258737b"
+dependencies = [
+ "derivation-path",
+ "qstring",
+ "uriparse",
+]
+
+[[package]]
+name = "solana-epoch-rewards"
+version = "2.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "86b575d3dd323b9ea10bb6fe89bf6bf93e249b215ba8ed7f68f1a3633f384db7"
+dependencies = [
+ "serde",
+ "serde_derive",
+ "solana-hash",
+ "solana-sdk-ids",
+ "solana-sdk-macro",
+ "solana-sysvar-id",
+]
+
+[[package]]
+name = "solana-epoch-schedule"
+version = "2.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3fce071fbddecc55d727b1d7ed16a629afe4f6e4c217bc8d00af3b785f6f67ed"
+dependencies = [
+ "serde",
+ "serde_derive",
+ "solana-sdk-ids",
+ "solana-sdk-macro",
+ "solana-sysvar-id",
+]
+
+[[package]]
+name = "solana-example-mocks"
+version = "2.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "84461d56cbb8bb8d539347151e0525b53910102e4bced875d49d5139708e39d3"
+dependencies = [
+ "serde",
+ "serde_derive",
+ "solana-address-lookup-table-interface",
+ "solana-clock",
+ "solana-hash",
+ "solana-instruction",
+ "solana-keccak-hasher",
+ "solana-message",
+ "solana-nonce",
+ "solana-pubkey",
+ "solana-sdk-ids",
+ "solana-system-interface",
+ "thiserror 2.0.18",
+]
+
+[[package]]
+name = "solana-feature-gate-interface"
+version = "2.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "43f5c5382b449e8e4e3016fb05e418c53d57782d8b5c30aa372fc265654b956d"
+dependencies = [
+ "bincode",
+ "serde",
+ "serde_derive",
+ "solana-account",
+ "solana-account-info",
+ "solana-instruction",
+ "solana-program-error",
+ "solana-pubkey",
+ "solana-rent",
+ "solana-sdk-ids",
+ "solana-system-interface",
+]
+
+[[package]]
+name = "solana-fee-calculator"
+version = "2.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d89bc408da0fb3812bc3008189d148b4d3e08252c79ad810b245482a3f70cd8d"
+dependencies = [
+ "log",
+ "serde",
+ "serde_derive",
+]
+
+[[package]]
+name = "solana-hash"
+version = "2.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b5b96e9f0300fa287b545613f007dfe20043d7812bee255f418c1eb649c93b63"
+dependencies = [
+ "borsh 1.6.0",
+ "bytemuck",
+ "bytemuck_derive",
+ "five8",
+ "js-sys",
+ "serde",
+ "serde_derive",
+ "solana-atomic-u64",
+ "solana-sanitize",
+ "wasm-bindgen",
+]
+
+[[package]]
+name = "solana-instruction"
+version = "2.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bab5682934bd1f65f8d2c16f21cb532526fcc1a09f796e2cacdb091eee5774ad"
+dependencies = [
+ "bincode",
+ "borsh 1.6.0",
+ "getrandom 0.2.17",
+ "js-sys",
+ "num-traits",
+ "serde",
+ "serde_derive",
+ "serde_json",
+ "solana-define-syscall",
+ "solana-pubkey",
+ "wasm-bindgen",
+]
+
+[[package]]
+name = "solana-instructions-sysvar"
+version = "2.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e0e85a6fad5c2d0c4f5b91d34b8ca47118fc593af706e523cdbedf846a954f57"
+dependencies = [
+ "bitflags 2.11.0",
+ "solana-account-info",
+ "solana-instruction",
+ "solana-program-error",
+ "solana-pubkey",
+ "solana-sanitize",
+ "solana-sdk-ids",
+ "solana-serialize-utils",
+ "solana-sysvar-id",
+]
+
+[[package]]
+name = "solana-keccak-hasher"
+version = "2.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c7aeb957fbd42a451b99235df4942d96db7ef678e8d5061ef34c9b34cae12f79"
+dependencies = [
+ "sha3",
+ "solana-define-syscall",
+ "solana-hash",
+ "solana-sanitize",
+]
+
+[[package]]
+name = "solana-keypair"
+version = "2.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bd3f04aa1a05c535e93e121a95f66e7dcccf57e007282e8255535d24bf1e98bb"
+dependencies = [
+ "ed25519-dalek",
+ "five8",
+ "rand 0.7.3",
+ "solana-pubkey",
+ "solana-seed-phrase",
+ "solana-signature",
+ "solana-signer",
+ "wasm-bindgen",
+]
+
+[[package]]
+name = "solana-last-restart-slot"
+version = "2.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4a6360ac2fdc72e7463565cd256eedcf10d7ef0c28a1249d261ec168c1b55cdd"
+dependencies = [
+ "serde",
+ "serde_derive",
+ "solana-sdk-ids",
+ "solana-sdk-macro",
+ "solana-sysvar-id",
+]
+
+[[package]]
+name = "solana-loader-v2-interface"
+version = "2.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d8ab08006dad78ae7cd30df8eea0539e207d08d91eaefb3e1d49a446e1c49654"
+dependencies = [
+ "serde",
+ "serde_bytes",
+ "serde_derive",
+ "solana-instruction",
+ "solana-pubkey",
+ "solana-sdk-ids",
+]
+
+[[package]]
+name = "solana-loader-v3-interface"
+version = "5.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6f7162a05b8b0773156b443bccd674ea78bb9aa406325b467ea78c06c99a63a2"
+dependencies = [
+ "serde",
+ "serde_bytes",
+ "serde_derive",
+ "solana-instruction",
+ "solana-pubkey",
+ "solana-sdk-ids",
+ "solana-system-interface",
+]
+
+[[package]]
+name = "solana-loader-v4-interface"
+version = "2.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "706a777242f1f39a83e2a96a2a6cb034cb41169c6ecbee2cf09cb873d9659e7e"
+dependencies = [
+ "serde",
+ "serde_bytes",
+ "serde_derive",
+ "solana-instruction",
+ "solana-pubkey",
+ "solana-sdk-ids",
+ "solana-system-interface",
+]
+
+[[package]]
+name = "solana-message"
+version = "2.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1796aabce376ff74bf89b78d268fa5e683d7d7a96a0a4e4813ec34de49d5314b"
+dependencies = [
+ "bincode",
+ "blake3",
+ "lazy_static",
+ "serde",
+ "serde_derive",
+ "solana-bincode",
+ "solana-hash",
+ "solana-instruction",
+ "solana-pubkey",
+ "solana-sanitize",
+ "solana-sdk-ids",
+ "solana-short-vec",
+ "solana-system-interface",
+ "solana-transaction-error",
+ "wasm-bindgen",
+]
+
+[[package]]
+name = "solana-msg"
+version = "2.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f36a1a14399afaabc2781a1db09cb14ee4cc4ee5c7a5a3cfcc601811379a8092"
+dependencies = [
+ "solana-define-syscall",
+]
+
+[[package]]
+name = "solana-native-token"
+version = "2.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "61515b880c36974053dd499c0510066783f0cc6ac17def0c7ef2a244874cf4a9"
+
+[[package]]
+name = "solana-nonce"
+version = "2.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "703e22eb185537e06204a5bd9d509b948f0066f2d1d814a6f475dafb3ddf1325"
+dependencies = [
+ "serde",
+ "serde_derive",
+ "solana-fee-calculator",
+ "solana-hash",
+ "solana-pubkey",
+ "solana-sha256-hasher",
+]
+
+[[package]]
+name = "solana-program"
+version = "2.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "98eca145bd3545e2fbb07166e895370576e47a00a7d824e325390d33bf467210"
+dependencies = [
+ "bincode",
+ "blake3",
+ "borsh 0.10.4",
+ "borsh 1.6.0",
+ "bs58",
+ "bytemuck",
+ "console_error_panic_hook",
+ "console_log",
+ "getrandom 0.2.17",
+ "lazy_static",
+ "log",
+ "memoffset",
+ "num-bigint",
+ "num-derive",
+ "num-traits",
+ "rand 0.8.5",
+ "serde",
+ "serde_bytes",
+ "serde_derive",
+ "solana-account-info",
+ "solana-address-lookup-table-interface",
+ "solana-atomic-u64",
+ "solana-big-mod-exp",
+ "solana-bincode",
+ "solana-blake3-hasher",
+ "solana-borsh",
+ "solana-clock",
+ "solana-cpi",
+ "solana-decode-error",
+ "solana-define-syscall",
+ "solana-epoch-rewards",
+ "solana-epoch-schedule",
+ "solana-example-mocks",
+ "solana-feature-gate-interface",
+ "solana-fee-calculator",
+ "solana-hash",
+ "solana-instruction",
+ "solana-instructions-sysvar",
+ "solana-keccak-hasher",
+ "solana-last-restart-slot",
+ "solana-loader-v2-interface",
+ "solana-loader-v3-interface",
+ "solana-loader-v4-interface",
+ "solana-message",
+ "solana-msg",
+ "solana-native-token",
+ "solana-nonce",
+ "solana-program-entrypoint",
+ "solana-program-error",
+ "solana-program-memory",
+ "solana-program-option",
+ "solana-program-pack",
+ "solana-pubkey",
+ "solana-rent",
+ "solana-sanitize",
+ "solana-sdk-ids",
+ "solana-sdk-macro",
+ "solana-secp256k1-recover",
+ "solana-serde-varint",
+ "solana-serialize-utils",
+ "solana-sha256-hasher",
+ "solana-short-vec",
+ "solana-slot-hashes",
+ "solana-slot-history",
+ "solana-stable-layout",
+ "solana-stake-interface",
+ "solana-system-interface",
+ "solana-sysvar",
+ "solana-sysvar-id",
+ "solana-vote-interface",
+ "thiserror 2.0.18",
+ "wasm-bindgen",
+]
+
+[[package]]
+name = "solana-program-entrypoint"
+version = "2.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "32ce041b1a0ed275290a5008ee1a4a6c48f5054c8a3d78d313c08958a06aedbd"
+dependencies = [
+ "solana-account-info",
+ "solana-msg",
+ "solana-program-error",
+ "solana-pubkey",
+]
+
+[[package]]
+name = "solana-program-error"
+version = "2.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9ee2e0217d642e2ea4bee237f37bd61bb02aec60da3647c48ff88f6556ade775"
+dependencies = [
+ "borsh 1.6.0",
+ "num-traits",
+ "serde",
+ "serde_derive",
+ "solana-decode-error",
+ "solana-instruction",
+ "solana-msg",
+ "solana-pubkey",
+]
+
+[[package]]
+name = "solana-program-memory"
+version = "2.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3a5426090c6f3fd6cfdc10685322fede9ca8e5af43cd6a59e98bfe4e91671712"
+dependencies = [
+ "solana-define-syscall",
+]
+
+[[package]]
+name = "solana-program-option"
+version = "2.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dc677a2e9bc616eda6dbdab834d463372b92848b2bfe4a1ed4e4b4adba3397d0"
+
+[[package]]
+name = "solana-program-pack"
+version = "2.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "319f0ef15e6e12dc37c597faccb7d62525a509fec5f6975ecb9419efddeb277b"
+dependencies = [
+ "solana-program-error",
+]
+
+[[package]]
+name = "solana-pubkey"
+version = "2.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9b62adb9c3261a052ca1f999398c388f1daf558a1b492f60a6d9e64857db4ff1"
+dependencies = [
+ "borsh 0.10.4",
+ "borsh 1.6.0",
+ "bytemuck",
+ "bytemuck_derive",
+ "curve25519-dalek 4.1.3",
+ "five8",
+ "five8_const",
+ "getrandom 0.2.17",
+ "js-sys",
+ "num-traits",
+ "serde",
+ "serde_derive",
+ "solana-atomic-u64",
+ "solana-decode-error",
+ "solana-define-syscall",
+ "solana-sanitize",
+ "solana-sha256-hasher",
+ "wasm-bindgen",
+]
+
+[[package]]
+name = "solana-rent"
+version = "2.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d1aea8fdea9de98ca6e8c2da5827707fb3842833521b528a713810ca685d2480"
+dependencies = [
+ "serde",
+ "serde_derive",
+ "solana-sdk-ids",
+ "solana-sdk-macro",
+ "solana-sysvar-id",
+]
+
+[[package]]
+name = "solana-reward-info"
+version = "2.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "18205b69139b1ae0ab8f6e11cdcb627328c0814422ad2482000fa2ca54ae4a2f"
+dependencies = [
+ "serde",
+ "serde_derive",
+]
+
+[[package]]
+name = "solana-sanitize"
+version = "2.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "61f1bc1357b8188d9c4a3af3fc55276e56987265eb7ad073ae6f8180ee54cecf"
+
+[[package]]
+name = "solana-sdk-ids"
+version = "2.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5c5d8b9cc68d5c88b062a33e23a6466722467dde0035152d8fb1afbcdf350a5f"
+dependencies = [
+ "solana-pubkey",
+]
+
+[[package]]
+name = "solana-sdk-macro"
+version = "2.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "86280da8b99d03560f6ab5aca9de2e38805681df34e0bb8f238e69b29433b9df"
+dependencies = [
+ "bs58",
+ "proc-macro2",
+ "quote",
+ "syn 2.0.117",
+]
+
+[[package]]
+name = "solana-secp256k1-recover"
+version = "2.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "baa3120b6cdaa270f39444f5093a90a7b03d296d362878f7a6991d6de3bbe496"
+dependencies = [
+ "libsecp256k1",
+ "solana-define-syscall",
+ "thiserror 2.0.18",
+]
+
+[[package]]
+name = "solana-security-txt"
+version = "1.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "468aa43b7edb1f9b7b7b686d5c3aeb6630dc1708e86e31343499dd5c4d775183"
+
+[[package]]
+name = "solana-seed-derivable"
+version = "2.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3beb82b5adb266c6ea90e5cf3967235644848eac476c5a1f2f9283a143b7c97f"
+dependencies = [
+ "solana-derivation-path",
+]
+
+[[package]]
+name = "solana-seed-phrase"
+version = "2.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "36187af2324f079f65a675ec22b31c24919cb4ac22c79472e85d819db9bbbc15"
+dependencies = [
+ "hmac",
+ "pbkdf2",
+ "sha2 0.10.9",
+]
+
+[[package]]
+name = "solana-serde-varint"
+version = "2.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2a7e155eba458ecfb0107b98236088c3764a09ddf0201ec29e52a0be40857113"
+dependencies = [
+ "serde",
+]
+
+[[package]]
+name = "solana-serialize-utils"
+version = "2.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "817a284b63197d2b27afdba829c5ab34231da4a9b4e763466a003c40ca4f535e"
+dependencies = [
+ "solana-instruction",
+ "solana-pubkey",
+ "solana-sanitize",
+]
+
+[[package]]
+name = "solana-sha256-hasher"
+version = "2.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5aa3feb32c28765f6aa1ce8f3feac30936f16c5c3f7eb73d63a5b8f6f8ecdc44"
+dependencies = [
+ "sha2 0.10.9",
+ "solana-define-syscall",
+ "solana-hash",
+]
+
+[[package]]
+name = "solana-short-vec"
+version = "2.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5c54c66f19b9766a56fa0057d060de8378676cb64987533fa088861858fc5a69"
+dependencies = [
+ "serde",
+]
+
+[[package]]
+name = "solana-signature"
+version = "2.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "64c8ec8e657aecfc187522fc67495142c12f35e55ddeca8698edbb738b8dbd8c"
+dependencies = [
+ "ed25519-dalek",
+ "five8",
+ "serde",
+ "serde-big-array",
+ "serde_derive",
+ "solana-sanitize",
+]
+
+[[package]]
+name = "solana-signer"
+version = "2.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7c41991508a4b02f021c1342ba00bcfa098630b213726ceadc7cb032e051975b"
+dependencies = [
+ "solana-pubkey",
+ "solana-signature",
+ "solana-transaction-error",
+]
+
+[[package]]
+name = "solana-slot-hashes"
+version = "2.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0c8691982114513763e88d04094c9caa0376b867a29577939011331134c301ce"
+dependencies = [
+ "serde",
+ "serde_derive",
+ "solana-hash",
+ "solana-sdk-ids",
+ "solana-sysvar-id",
+]
+
+[[package]]
+name = "solana-slot-history"
+version = "2.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "97ccc1b2067ca22754d5283afb2b0126d61eae734fc616d23871b0943b0d935e"
+dependencies = [
+ "bv",
+ "serde",
+ "serde_derive",
+ "solana-sdk-ids",
+ "solana-sysvar-id",
+]
+
+[[package]]
+name = "solana-stable-layout"
+version = "2.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9f14f7d02af8f2bc1b5efeeae71bc1c2b7f0f65cd75bcc7d8180f2c762a57f54"
+dependencies = [
+ "solana-instruction",
+ "solana-pubkey",
+]
+
+[[package]]
+name = "solana-stake-interface"
+version = "1.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5269e89fde216b4d7e1d1739cf5303f8398a1ff372a81232abbee80e554a838c"
+dependencies = [
+ "borsh 0.10.4",
+ "borsh 1.6.0",
+ "num-traits",
+ "serde",
+ "serde_derive",
+ "solana-clock",
+ "solana-cpi",
+ "solana-decode-error",
+ "solana-instruction",
+ "solana-program-error",
+ "solana-pubkey",
+ "solana-system-interface",
+ "solana-sysvar-id",
+]
+
+[[package]]
+name = "solana-svm-feature-set"
+version = "2.3.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3f24b836eb4d74ec255217bdbe0f24f64a07adeac31aca61f334f91cd4a3b1d5"
+
+[[package]]
+name = "solana-system-interface"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "94d7c18cb1a91c6be5f5a8ac9276a1d7c737e39a21beba9ea710ab4b9c63bc90"
+dependencies = [
+ "js-sys",
+ "num-traits",
+ "serde",
+ "serde_derive",
+ "solana-decode-error",
+ "solana-instruction",
+ "solana-pubkey",
+ "wasm-bindgen",
+]
+
+[[package]]
+name = "solana-sysvar"
+version = "2.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b8c3595f95069f3d90f275bb9bd235a1973c4d059028b0a7f81baca2703815db"
+dependencies = [
+ "base64 0.22.1",
+ "bincode",
+ "bytemuck",
+ "bytemuck_derive",
+ "lazy_static",
+ "serde",
+ "serde_derive",
+ "solana-account-info",
+ "solana-clock",
+ "solana-define-syscall",
+ "solana-epoch-rewards",
+ "solana-epoch-schedule",
+ "solana-fee-calculator",
+ "solana-hash",
+ "solana-instruction",
+ "solana-instructions-sysvar",
+ "solana-last-restart-slot",
+ "solana-program-entrypoint",
+ "solana-program-error",
+ "solana-program-memory",
+ "solana-pubkey",
+ "solana-rent",
+ "solana-sanitize",
+ "solana-sdk-ids",
+ "solana-sdk-macro",
+ "solana-slot-hashes",
+ "solana-slot-history",
+ "solana-stake-interface",
+ "solana-sysvar-id",
+]
+
+[[package]]
+name = "solana-sysvar-id"
+version = "2.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5762b273d3325b047cfda250787f8d796d781746860d5d0a746ee29f3e8812c1"
+dependencies = [
+ "solana-pubkey",
+ "solana-sdk-ids",
+]
+
+[[package]]
+name = "solana-transaction"
+version = "2.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "80657d6088f721148f5d889c828ca60c7daeedac9a8679f9ec215e0c42bcbf41"
+dependencies = [
+ "serde",
+ "serde_derive",
+ "solana-hash",
+ "solana-instruction",
+ "solana-keypair",
+ "solana-message",
+ "solana-pubkey",
+ "solana-sanitize",
+ "solana-sdk-ids",
+ "solana-short-vec",
+ "solana-signature",
+ "solana-transaction-error",
+ "wasm-bindgen",
+]
+
+[[package]]
+name = "solana-transaction-context"
+version = "2.3.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "54a312304361987a85b2ef2293920558e6612876a639dd1309daf6d0d59ef2fe"
+dependencies = [
+ "bincode",
+ "serde",
+ "serde_derive",
+ "solana-account",
+ "solana-instruction",
+ "solana-instructions-sysvar",
+ "solana-pubkey",
+ "solana-rent",
+ "solana-sdk-ids",
+]
+
+[[package]]
+name = "solana-transaction-error"
+version = "2.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "222a9dc8fdb61c6088baab34fc3a8b8473a03a7a5fd404ed8dd502fa79b67cb1"
+dependencies = [
+ "serde",
+ "serde_derive",
+ "solana-instruction",
+ "solana-sanitize",
+]
+
+[[package]]
+name = "solana-transaction-status"
+version = "2.3.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "135f92f4192cc68900c665becf97fc0a6500ae5a67ff347bf2cbc20ecfefa821"
+dependencies = [
+ "Inflector",
+ "agave-reserved-account-keys",
+ "base64 0.22.1",
+ "bincode",
+ "borsh 1.6.0",
+ "bs58",
+ "log",
+ "serde",
+ "serde_derive",
+ "serde_json",
+ "solana-account-decoder",
+ "solana-address-lookup-table-interface",
+ "solana-clock",
+ "solana-hash",
+ "solana-instruction",
+ "solana-loader-v2-interface",
+ "solana-loader-v3-interface",
+ "solana-message",
+ "solana-program-option",
+ "solana-pubkey",
+ "solana-reward-info",
+ "solana-sdk-ids",
+ "solana-signature",
+ "solana-stake-interface",
+ "solana-system-interface",
+ "solana-transaction",
+ "solana-transaction-error",
+ "solana-transaction-status-client-types",
+ "solana-vote-interface",
+ "spl-associated-token-account",
+ "spl-memo",
+ "spl-token",
+ "spl-token-2022",
+ "spl-token-group-interface",
+ "spl-token-metadata-interface",
+ "thiserror 2.0.18",
+]
+
+[[package]]
+name = "solana-transaction-status-client-types"
+version = "2.3.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "51f1d7c2387c35850848212244d2b225847666cb52d3bd59a5c409d2c300303d"
+dependencies = [
+ "base64 0.22.1",
+ "bincode",
+ "bs58",
+ "serde",
+ "serde_derive",
+ "serde_json",
+ "solana-account-decoder-client-types",
+ "solana-commitment-config",
+ "solana-message",
+ "solana-reward-info",
+ "solana-signature",
+ "solana-transaction",
+ "solana-transaction-context",
+ "solana-transaction-error",
+ "thiserror 2.0.18",
+]
+
+[[package]]
+name = "solana-vote-interface"
+version = "2.2.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b80d57478d6599d30acc31cc5ae7f93ec2361a06aefe8ea79bc81739a08af4c3"
+dependencies = [
+ "bincode",
+ "num-derive",
+ "num-traits",
+ "serde",
+ "serde_derive",
+ "solana-clock",
+ "solana-decode-error",
+ "solana-hash",
+ "solana-instruction",
+ "solana-pubkey",
+ "solana-rent",
+ "solana-sdk-ids",
+ "solana-serde-varint",
+ "solana-serialize-utils",
+ "solana-short-vec",
+ "solana-system-interface",
+]
+
+[[package]]
+name = "solana-zk-sdk"
+version = "2.3.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "97b9fc6ec37d16d0dccff708ed1dd6ea9ba61796700c3bb7c3b401973f10f63b"
+dependencies = [
+ "aes-gcm-siv",
+ "base64 0.22.1",
+ "bincode",
+ "bytemuck",
+ "bytemuck_derive",
+ "curve25519-dalek 4.1.3",
+ "itertools 0.12.1",
+ "js-sys",
+ "merlin",
+ "num-derive",
+ "num-traits",
+ "rand 0.8.5",
+ "serde",
+ "serde_derive",
+ "serde_json",
+ "sha3",
+ "solana-derivation-path",
+ "solana-instruction",
+ "solana-pubkey",
+ "solana-sdk-ids",
+ "solana-seed-derivable",
+ "solana-seed-phrase",
+ "solana-signature",
+ "solana-signer",
+ "subtle",
+ "thiserror 2.0.18",
+ "wasm-bindgen",
+ "zeroize",
+]
+
+[[package]]
+name = "spl-associated-token-account"
+version = "7.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ae179d4a26b3c7a20c839898e6aed84cb4477adf108a366c95532f058aea041b"
+dependencies = [
+ "borsh 1.6.0",
+ "num-derive",
+ "num-traits",
+ "solana-program",
+ "spl-associated-token-account-client",
+ "spl-token",
+ "spl-token-2022",
+ "thiserror 2.0.18",
+]
+
+[[package]]
+name = "spl-associated-token-account-client"
+version = "2.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d6f8349dbcbe575f354f9a533a21f272f3eb3808a49e2fdc1c34393b88ba76cb"
+dependencies = [
+ "solana-instruction",
+ "solana-pubkey",
+]
+
+[[package]]
+name = "spl-discriminator"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a7398da23554a31660f17718164e31d31900956054f54f52d5ec1be51cb4f4b3"
+dependencies = [
+ "bytemuck",
+ "solana-program-error",
+ "solana-sha256-hasher",
+ "spl-discriminator-derive",
+]
+
+[[package]]
+name = "spl-discriminator-derive"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d9e8418ea6269dcfb01c712f0444d2c75542c04448b480e87de59d2865edc750"
+dependencies = [
+ "quote",
+ "spl-discriminator-syn",
+ "syn 2.0.117",
+]
+
+[[package]]
+name = "spl-discriminator-syn"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5d1dbc82ab91422345b6df40a79e2b78c7bce1ebb366da323572dd60b7076b67"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "sha2 0.10.9",
+ "syn 2.0.117",
+ "thiserror 1.0.69",
+]
+
+[[package]]
+name = "spl-elgamal-registry"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "65edfeed09cd4231e595616aa96022214f9c9d2be02dea62c2b30d5695a6833a"
+dependencies = [
+ "bytemuck",
+ "solana-account-info",
+ "solana-cpi",
+ "solana-instruction",
+ "solana-msg",
+ "solana-program-entrypoint",
+ "solana-program-error",
+ "solana-pubkey",
+ "solana-rent",
+ "solana-sdk-ids",
+ "solana-system-interface",
+ "solana-sysvar",
+ "solana-zk-sdk",
+ "spl-pod",
+ "spl-token-confidential-transfer-proof-extraction",
+]
+
+[[package]]
+name = "spl-generic-token"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "741a62a566d97c58d33f9ed32337ceedd4e35109a686e31b1866c5dfa56abddc"
+dependencies = [
+ "bytemuck",
+ "solana-pubkey",
]
[[package]]
-name = "shlex"
-version = "1.3.0"
+name = "spl-memo"
+version = "6.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
+checksum = "9f09647c0974e33366efeb83b8e2daebb329f0420149e74d3a4bd2c08cf9f7cb"
+dependencies = [
+ "solana-account-info",
+ "solana-instruction",
+ "solana-msg",
+ "solana-program-entrypoint",
+ "solana-program-error",
+ "solana-pubkey",
+]
[[package]]
-name = "signal-hook-registry"
-version = "1.4.8"
+name = "spl-pod"
+version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c4db69cba1110affc0e9f7bcd48bbf87b3f4fc7c61fc9155afd4c469eb3d6c1b"
+checksum = "d994afaf86b779104b4a95ba9ca75b8ced3fdb17ee934e38cb69e72afbe17799"
dependencies = [
- "errno",
- "libc",
+ "borsh 1.6.0",
+ "bytemuck",
+ "bytemuck_derive",
+ "num-derive",
+ "num-traits",
+ "solana-decode-error",
+ "solana-msg",
+ "solana-program-error",
+ "solana-program-option",
+ "solana-pubkey",
+ "solana-zk-sdk",
+ "thiserror 2.0.18",
]
[[package]]
-name = "simd-adler32"
-version = "0.3.8"
+name = "spl-program-error"
+version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e320a6c5ad31d271ad523dcf3ad13e2767ad8b1cb8f047f75a8aeaf8da139da2"
+checksum = "9cdebc8b42553070b75aa5106f071fef2eb798c64a7ec63375da4b1f058688c6"
+dependencies = [
+ "num-derive",
+ "num-traits",
+ "solana-decode-error",
+ "solana-msg",
+ "solana-program-error",
+ "spl-program-error-derive",
+ "thiserror 2.0.18",
+]
[[package]]
-name = "slab"
-version = "0.4.11"
+name = "spl-program-error-derive"
+version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589"
+checksum = "2a2539e259c66910d78593475540e8072f0b10f0f61d7607bbf7593899ed52d0"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "sha2 0.10.9",
+ "syn 2.0.117",
+]
[[package]]
-name = "smallvec"
-version = "1.15.1"
+name = "spl-tlv-account-resolution"
+version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03"
+checksum = "1408e961215688715d5a1063cbdcf982de225c45f99c82b4f7d7e1dd22b998d7"
+dependencies = [
+ "bytemuck",
+ "num-derive",
+ "num-traits",
+ "solana-account-info",
+ "solana-decode-error",
+ "solana-instruction",
+ "solana-msg",
+ "solana-program-error",
+ "solana-pubkey",
+ "spl-discriminator",
+ "spl-pod",
+ "spl-program-error",
+ "spl-type-length-value",
+ "thiserror 2.0.18",
+]
[[package]]
-name = "socket2"
-version = "0.5.10"
+name = "spl-token"
+version = "8.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e22376abed350d73dd1cd119b57ffccad95b4e585a7cda43e286245ce23c0678"
+checksum = "053067c6a82c705004f91dae058b11b4780407e9ccd6799dc9e7d0fab5f242da"
dependencies = [
- "libc",
- "windows-sys 0.52.0",
+ "arrayref",
+ "bytemuck",
+ "num-derive",
+ "num-traits",
+ "num_enum",
+ "solana-account-info",
+ "solana-cpi",
+ "solana-decode-error",
+ "solana-instruction",
+ "solana-msg",
+ "solana-program-entrypoint",
+ "solana-program-error",
+ "solana-program-memory",
+ "solana-program-option",
+ "solana-program-pack",
+ "solana-pubkey",
+ "solana-rent",
+ "solana-sdk-ids",
+ "solana-sysvar",
+ "thiserror 2.0.18",
]
[[package]]
-name = "socket2"
-version = "0.6.1"
+name = "spl-token-2022"
+version = "8.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "17129e116933cf371d018bb80ae557e889637989d8638274fb25622827b03881"
+checksum = "31f0dfbb079eebaee55e793e92ca5f433744f4b71ee04880bfd6beefba5973e5"
dependencies = [
- "libc",
- "windows-sys 0.60.2",
+ "arrayref",
+ "bytemuck",
+ "num-derive",
+ "num-traits",
+ "num_enum",
+ "solana-account-info",
+ "solana-clock",
+ "solana-cpi",
+ "solana-decode-error",
+ "solana-instruction",
+ "solana-msg",
+ "solana-native-token",
+ "solana-program-entrypoint",
+ "solana-program-error",
+ "solana-program-memory",
+ "solana-program-option",
+ "solana-program-pack",
+ "solana-pubkey",
+ "solana-rent",
+ "solana-sdk-ids",
+ "solana-security-txt",
+ "solana-system-interface",
+ "solana-sysvar",
+ "solana-zk-sdk",
+ "spl-elgamal-registry",
+ "spl-memo",
+ "spl-pod",
+ "spl-token",
+ "spl-token-confidential-transfer-ciphertext-arithmetic",
+ "spl-token-confidential-transfer-proof-extraction",
+ "spl-token-confidential-transfer-proof-generation",
+ "spl-token-group-interface",
+ "spl-token-metadata-interface",
+ "spl-transfer-hook-interface",
+ "spl-type-length-value",
+ "thiserror 2.0.18",
]
[[package]]
-name = "solana-atomic-u64"
-version = "2.2.1"
+name = "spl-token-confidential-transfer-ciphertext-arithmetic"
+version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d52e52720efe60465b052b9e7445a01c17550666beec855cce66f44766697bc2"
+checksum = "cddd52bfc0f1c677b41493dafa3f2dbbb4b47cf0990f08905429e19dc8289b35"
dependencies = [
- "parking_lot 0.12.5",
+ "base64 0.22.1",
+ "bytemuck",
+ "solana-curve25519",
+ "solana-zk-sdk",
]
[[package]]
-name = "solana-decode-error"
-version = "2.3.0"
+name = "spl-token-confidential-transfer-proof-extraction"
+version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8c781686a18db2f942e70913f7ca15dc120ec38dcab42ff7557db2c70c625a35"
+checksum = "fe2629860ff04c17bafa9ba4bed8850a404ecac81074113e1f840dbd0ebb7bd6"
dependencies = [
- "num-traits",
+ "bytemuck",
+ "solana-account-info",
+ "solana-curve25519",
+ "solana-instruction",
+ "solana-instructions-sysvar",
+ "solana-msg",
+ "solana-program-error",
+ "solana-pubkey",
+ "solana-sdk-ids",
+ "solana-zk-sdk",
+ "spl-pod",
+ "thiserror 2.0.18",
]
[[package]]
-name = "solana-define-syscall"
-version = "2.3.0"
+name = "spl-token-confidential-transfer-proof-generation"
+version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2ae3e2abcf541c8122eafe9a625d4d194b4023c20adde1e251f94e056bb1aee2"
+checksum = "fa27b9174bea869a7ebf31e0be6890bce90b1a4288bc2bbf24bd413f80ae3fde"
+dependencies = [
+ "curve25519-dalek 4.1.3",
+ "solana-zk-sdk",
+ "thiserror 2.0.18",
+]
[[package]]
-name = "solana-hash"
-version = "2.3.0"
+name = "spl-token-group-interface"
+version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b5b96e9f0300fa287b545613f007dfe20043d7812bee255f418c1eb649c93b63"
+checksum = "5597b4cd76f85ce7cd206045b7dc22da8c25516573d42d267c8d1fd128db5129"
dependencies = [
- "five8",
- "js-sys",
- "solana-atomic-u64",
- "solana-sanitize",
- "wasm-bindgen",
+ "bytemuck",
+ "num-derive",
+ "num-traits",
+ "solana-decode-error",
+ "solana-instruction",
+ "solana-msg",
+ "solana-program-error",
+ "solana-pubkey",
+ "spl-discriminator",
+ "spl-pod",
+ "thiserror 2.0.18",
]
[[package]]
-name = "solana-pubkey"
-version = "2.4.0"
+name = "spl-token-metadata-interface"
+version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9b62adb9c3261a052ca1f999398c388f1daf558a1b492f60a6d9e64857db4ff1"
+checksum = "304d6e06f0de0c13a621464b1fd5d4b1bebf60d15ca71a44d3839958e0da16ee"
dependencies = [
- "borsh 0.10.4",
"borsh 1.6.0",
- "five8",
- "five8_const",
- "getrandom 0.2.17",
- "js-sys",
+ "num-derive",
"num-traits",
- "serde",
- "serde_derive",
- "solana-atomic-u64",
+ "solana-borsh",
"solana-decode-error",
- "solana-define-syscall",
- "solana-sanitize",
- "solana-sha256-hasher",
- "wasm-bindgen",
+ "solana-instruction",
+ "solana-msg",
+ "solana-program-error",
+ "solana-pubkey",
+ "spl-discriminator",
+ "spl-pod",
+ "spl-type-length-value",
+ "thiserror 2.0.18",
]
[[package]]
-name = "solana-sanitize"
-version = "2.2.1"
+name = "spl-transfer-hook-interface"
+version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "61f1bc1357b8188d9c4a3af3fc55276e56987265eb7ad073ae6f8180ee54cecf"
+checksum = "a7e905b849b6aba63bde8c4badac944ebb6c8e6e14817029cbe1bc16829133bd"
+dependencies = [
+ "arrayref",
+ "bytemuck",
+ "num-derive",
+ "num-traits",
+ "solana-account-info",
+ "solana-cpi",
+ "solana-decode-error",
+ "solana-instruction",
+ "solana-msg",
+ "solana-program-error",
+ "solana-pubkey",
+ "spl-discriminator",
+ "spl-pod",
+ "spl-program-error",
+ "spl-tlv-account-resolution",
+ "spl-type-length-value",
+ "thiserror 2.0.18",
+]
[[package]]
-name = "solana-sha256-hasher"
-version = "2.3.0"
+name = "spl-type-length-value"
+version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5aa3feb32c28765f6aa1ce8f3feac30936f16c5c3f7eb73d63a5b8f6f8ecdc44"
+checksum = "d417eb548214fa822d93f84444024b4e57c13ed6719d4dcc68eec24fb481e9f5"
dependencies = [
- "sha2",
- "solana-define-syscall",
- "solana-hash",
+ "bytemuck",
+ "num-derive",
+ "num-traits",
+ "solana-account-info",
+ "solana-decode-error",
+ "solana-msg",
+ "solana-program-error",
+ "spl-discriminator",
+ "spl-pod",
+ "thiserror 2.0.18",
]
[[package]]
@@ -2640,9 +4701,9 @@ dependencies = [
[[package]]
name = "syn"
-version = "2.0.114"
+version = "2.0.117"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d4d107df263a3013ef9b1879b0df87d706ff80f65a86ea879bd9c31f9b307c2a"
+checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99"
dependencies = [
"proc-macro2",
"quote",
@@ -2672,7 +4733,7 @@ checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.114",
+ "syn 2.0.117",
]
[[package]]
@@ -2698,12 +4759,12 @@ dependencies = [
[[package]]
name = "tempfile"
-version = "3.24.0"
+version = "3.27.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "655da9c7eb6305c55742045d5a8d2037996d61d8de95806335c7c86ce0f82e9c"
+checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd"
dependencies = [
"fastrand",
- "getrandom 0.3.4",
+ "getrandom 0.4.2",
"once_cell",
"rustix",
"windows-sys 0.61.2",
@@ -2745,7 +4806,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.114",
+ "syn 2.0.117",
]
[[package]]
@@ -2756,7 +4817,7 @@ checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.114",
+ "syn 2.0.117",
]
[[package]]
@@ -2780,9 +4841,9 @@ dependencies = [
[[package]]
name = "tinyvec"
-version = "1.10.0"
+version = "1.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bfa5fdc3bce6191a1dbc8c02d5c8bffcf557bafa17c124c5264a458f1b0613fa"
+checksum = "3e61e67053d25a4e82c844e8424039d9745781b3fc4f32b8d55ed50f5f667ef3"
dependencies = [
"tinyvec_macros",
]
@@ -2795,9 +4856,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
[[package]]
name = "tokio"
-version = "1.49.0"
+version = "1.50.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "72a2903cd7736441aac9df9d7688bd0ce48edccaadf181c3b90be801e81d3d86"
+checksum = "27ad5e34374e03cfffefc301becb44e9dc3c17584f414349ebe29ed26661822d"
dependencies = [
"bytes",
"libc",
@@ -2805,20 +4866,20 @@ dependencies = [
"parking_lot 0.12.5",
"pin-project-lite",
"signal-hook-registry",
- "socket2 0.6.1",
+ "socket2 0.6.3",
"tokio-macros",
"windows-sys 0.61.2",
]
[[package]]
name = "tokio-macros"
-version = "2.6.0"
+version = "2.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5"
+checksum = "5c55a2eff8b69ce66c84f85e1da1c233edc36ceb85a2058d11b0d6a3c7e7569c"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.114",
+ "syn 2.0.117",
]
[[package]]
@@ -2848,7 +4909,7 @@ version = "0.26.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1729aa945f29d91ba541258c8df89027d5792d85a8841fb65e8bf0f4ede4ef61"
dependencies = [
- "rustls 0.23.36",
+ "rustls 0.23.37",
"tokio",
]
@@ -2916,18 +4977,18 @@ dependencies = [
[[package]]
name = "toml_datetime"
-version = "0.7.5+spec-1.1.0"
+version = "1.0.0+spec-1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "92e1cfed4a3038bc5a127e35a2d360f145e1f4b971b551a2ba5fd7aedf7e1347"
+checksum = "32c2555c699578a4f59f0cc68e5116c8d7cabbd45e1409b989d4be085b53f13e"
dependencies = [
"serde_core",
]
[[package]]
name = "toml_edit"
-version = "0.23.10+spec-1.0.0"
+version = "0.25.4+spec-1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "84c8b9f757e028cee9fa244aea147aab2a9ec09d5325a9b01e0a49730c2b5269"
+checksum = "7193cbd0ce53dc966037f54351dbbcf0d5a642c7f0038c382ef9e677ce8c13f2"
dependencies = [
"indexmap 2.13.0",
"toml_datetime",
@@ -2937,9 +4998,9 @@ dependencies = [
[[package]]
name = "toml_parser"
-version = "1.0.6+spec-1.1.0"
+version = "1.0.9+spec-1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a3198b4b0a8e11f09dd03e133c0280504d0801269e9afa46362ffde1cbeebf44"
+checksum = "702d4415e08923e7e1ef96cd5727c0dfed80b4d2fa25db9647fe5eb6f7c5a4c4"
dependencies = [
"winnow",
]
@@ -2978,9 +5039,9 @@ dependencies = [
[[package]]
name = "tonic"
-version = "0.14.2"
+version = "0.14.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "eb7613188ce9f7df5bfe185db26c5814347d110db17920415cf2fbcad85e7203"
+checksum = "fec7c61a0695dc1887c1b53952990f3ad2e3a31453e1f49f10e75424943a93ec"
dependencies = [
"async-trait",
"axum 0.8.8",
@@ -2997,7 +5058,7 @@ dependencies = [
"percent-encoding",
"pin-project",
"rustls-native-certs",
- "socket2 0.6.1",
+ "socket2 0.6.3",
"sync_wrapper 1.0.2",
"tokio",
"tokio-rustls 0.26.4",
@@ -3020,59 +5081,59 @@ dependencies = [
"prost-build 0.13.5",
"prost-types 0.13.5",
"quote",
- "syn 2.0.114",
+ "syn 2.0.117",
]
[[package]]
name = "tonic-build"
-version = "0.14.2"
+version = "0.14.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4c40aaccc9f9eccf2cd82ebc111adc13030d23e887244bc9cfa5d1d636049de3"
+checksum = "1882ac3bf5ef12877d7ed57aad87e75154c11931c2ba7e6cde5e22d63522c734"
dependencies = [
"prettyplease",
"proc-macro2",
"quote",
- "syn 2.0.114",
+ "syn 2.0.117",
]
[[package]]
name = "tonic-health"
-version = "0.14.2"
+version = "0.14.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2a82868bf299e0a1d2e8dce0dc33a46c02d6f045b2c1f1d6cc8dc3d0bf1812ef"
+checksum = "f4ff0636fef47afb3ec02818f5bceb4377b8abb9d6a386aeade18bd6212f8eb7"
dependencies = [
"prost 0.14.3",
"tokio",
"tokio-stream",
- "tonic 0.14.2",
+ "tonic 0.14.5",
"tonic-prost",
]
[[package]]
name = "tonic-prost"
-version = "0.14.2"
+version = "0.14.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "66bd50ad6ce1252d87ef024b3d64fe4c3cf54a86fb9ef4c631fdd0ded7aeaa67"
+checksum = "a55376a0bbaa4975a3f10d009ad763d8f4108f067c7c2e74f3001fb49778d309"
dependencies = [
"bytes",
"prost 0.14.3",
- "tonic 0.14.2",
+ "tonic 0.14.5",
]
[[package]]
name = "tonic-prost-build"
-version = "0.14.2"
+version = "0.14.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b4a16cba4043dc3ff43fcb3f96b4c5c154c64cbd18ca8dce2ab2c6a451d058a2"
+checksum = "f3144df636917574672e93d0f56d7edec49f90305749c668df5101751bb8f95a"
dependencies = [
"prettyplease",
"proc-macro2",
"prost-build 0.14.3",
"prost-types 0.14.3",
"quote",
- "syn 2.0.114",
+ "syn 2.0.117",
"tempfile",
- "tonic-build 0.14.2",
+ "tonic-build 0.14.5",
]
[[package]]
@@ -3150,7 +5211,7 @@ version = "0.6.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d4e6559d53cc268e5031cd8429d05415bc4cb4aefc4aa5d6cc35fbf5b924a1f8"
dependencies = [
- "bitflags 2.10.0",
+ "bitflags 2.11.0",
"bytes",
"futures-util",
"http 1.4.0",
@@ -3193,7 +5254,7 @@ checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.114",
+ "syn 2.0.117",
]
[[package]]
@@ -3229,9 +5290,9 @@ dependencies = [
[[package]]
name = "tracing-subscriber"
-version = "0.3.22"
+version = "0.3.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2f30143827ddab0d256fd843b7a66d164e9f271cfa0dde49142c5ca0ca291f1e"
+checksum = "cb7f578e5945fb242538965c2d0b04418d38ec25c79d160cd279bf0731c8d319"
dependencies = [
"matchers",
"nu-ansi-term",
@@ -3306,9 +5367,25 @@ checksum = "dbc4bc3a9f746d862c45cb89d705aa10f187bb96c76001afab07a0d35ce60142"
[[package]]
name = "unicode-ident"
-version = "1.0.22"
+version = "1.0.24"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
+
+[[package]]
+name = "unicode-xid"
+version = "0.2.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853"
+
+[[package]]
+name = "universal-hash"
+version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5"
+checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea"
+dependencies = [
+ "crypto-common",
+ "subtle",
+]
[[package]]
name = "untrusted"
@@ -3316,6 +5393,16 @@ version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1"
+[[package]]
+name = "uriparse"
+version = "0.6.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0200d0fc04d809396c2ad43f3c95da3582a2556eba8d453c1087f4120ee352ff"
+dependencies = [
+ "fnv",
+ "lazy_static",
+]
+
[[package]]
name = "url"
version = "2.5.8"
@@ -3348,11 +5435,11 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
[[package]]
name = "uuid"
-version = "1.19.0"
+version = "1.22.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e2e054861b4bd027cd373e18e8d8d8e6548085000e41290d95ce0c373a654b4a"
+checksum = "a68d3c8f01c0cfa54a75291d83601161799e4a89a39e0929f4b0354d88757a37"
dependencies = [
- "getrandom 0.3.4",
+ "getrandom 0.4.2",
"js-sys",
"serde_core",
"wasm-bindgen",
@@ -3379,6 +5466,12 @@ dependencies = [
"try-lock",
]
+[[package]]
+name = "wasi"
+version = "0.9.0+wasi-snapshot-preview1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519"
+
[[package]]
name = "wasi"
version = "0.11.1+wasi-snapshot-preview1"
@@ -3394,11 +5487,20 @@ dependencies = [
"wit-bindgen",
]
+[[package]]
+name = "wasip3"
+version = "0.4.0+wasi-0.3.0-rc-2026-01-06"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5"
+dependencies = [
+ "wit-bindgen",
+]
+
[[package]]
name = "wasm-bindgen"
-version = "0.2.108"
+version = "0.2.114"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "64024a30ec1e37399cf85a7ffefebdb72205ca1c972291c51512360d90bd8566"
+checksum = "6532f9a5c1ece3798cb1c2cfdba640b9b3ba884f5db45973a6f442510a87d38e"
dependencies = [
"cfg-if",
"once_cell",
@@ -3409,9 +5511,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-futures"
-version = "0.4.58"
+version = "0.4.64"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "70a6e77fd0ae8029c9ea0063f87c46fde723e7d887703d74ad2616d792e51e6f"
+checksum = "e9c5522b3a28661442748e09d40924dfb9ca614b21c00d3fd135720e48b67db8"
dependencies = [
"cfg-if",
"futures-util",
@@ -3423,9 +5525,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro"
-version = "0.2.108"
+version = "0.2.114"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "008b239d9c740232e71bd39e8ef6429d27097518b6b30bdf9086833bd5b6d608"
+checksum = "18a2d50fcf105fb33bb15f00e7a77b772945a2ee45dcf454961fd843e74c18e6"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
@@ -3433,31 +5535,65 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro-support"
-version = "0.2.108"
+version = "0.2.114"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5256bae2d58f54820e6490f9839c49780dff84c65aeab9e772f15d5f0e913a55"
+checksum = "03ce4caeaac547cdf713d280eda22a730824dd11e6b8c3ca9e42247b25c631e3"
dependencies = [
"bumpalo",
"proc-macro2",
"quote",
- "syn 2.0.114",
+ "syn 2.0.117",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-shared"
-version = "0.2.108"
+version = "0.2.114"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1f01b580c9ac74c8d8f0c0e4afb04eeef2acf145458e52c03845ee9cd23e3d12"
+checksum = "75a326b8c223ee17883a4251907455a2431acc2791c98c26279376490c378c16"
dependencies = [
"unicode-ident",
]
+[[package]]
+name = "wasm-encoder"
+version = "0.244.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "990065f2fe63003fe337b932cfb5e3b80e0b4d0f5ff650e6985b1048f62c8319"
+dependencies = [
+ "leb128fmt",
+ "wasmparser",
+]
+
+[[package]]
+name = "wasm-metadata"
+version = "0.244.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909"
+dependencies = [
+ "anyhow",
+ "indexmap 2.13.0",
+ "wasm-encoder",
+ "wasmparser",
+]
+
+[[package]]
+name = "wasmparser"
+version = "0.244.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe"
+dependencies = [
+ "bitflags 2.11.0",
+ "hashbrown 0.15.5",
+ "indexmap 2.13.0",
+ "semver",
+]
+
[[package]]
name = "web-sys"
-version = "0.3.85"
+version = "0.3.91"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "312e32e551d92129218ea9a2452120f4aabc03529ef03e4d0d82fb2780608598"
+checksum = "854ba17bb104abfb26ba36da9729addc7ce7f06f5c0f90f3c391f8461cca21f9"
dependencies = [
"js-sys",
"wasm-bindgen",
@@ -3485,14 +5621,14 @@ version = "0.26.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "521bc38abb08001b01866da9f51eb7c5d647a19260e00054a8c7fd5f9e57f7a9"
dependencies = [
- "webpki-roots 1.0.5",
+ "webpki-roots 1.0.6",
]
[[package]]
name = "webpki-roots"
-version = "1.0.5"
+version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "12bed680863276c63889429bfd6cab3b99943659923822de1c8a39c49e4d722c"
+checksum = "22cfaf3c063993ff62e73cb4311efde4db1efb31ab78a3e5c457939ad5cc0bed"
dependencies = [
"rustls-pki-types",
]
@@ -3749,9 +5885,9 @@ checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650"
[[package]]
name = "winnow"
-version = "0.7.14"
+version = "0.7.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5a5364e9d77fcdeeaa6062ced926ee3381faa2ee02d3eb83a5c27a8825540829"
+checksum = "df79d97927682d2fd8adb29682d1140b343be4ac0f08fd68b7765d9c059d3945"
dependencies = [
"memchr",
]
@@ -3771,6 +5907,88 @@ name = "wit-bindgen"
version = "0.51.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5"
+dependencies = [
+ "wit-bindgen-rust-macro",
+]
+
+[[package]]
+name = "wit-bindgen-core"
+version = "0.51.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ea61de684c3ea68cb082b7a88508a8b27fcc8b797d738bfc99a82facf1d752dc"
+dependencies = [
+ "anyhow",
+ "heck",
+ "wit-parser",
+]
+
+[[package]]
+name = "wit-bindgen-rust"
+version = "0.51.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21"
+dependencies = [
+ "anyhow",
+ "heck",
+ "indexmap 2.13.0",
+ "prettyplease",
+ "syn 2.0.117",
+ "wasm-metadata",
+ "wit-bindgen-core",
+ "wit-component",
+]
+
+[[package]]
+name = "wit-bindgen-rust-macro"
+version = "0.51.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0c0f9bfd77e6a48eccf51359e3ae77140a7f50b1e2ebfe62422d8afdaffab17a"
+dependencies = [
+ "anyhow",
+ "prettyplease",
+ "proc-macro2",
+ "quote",
+ "syn 2.0.117",
+ "wit-bindgen-core",
+ "wit-bindgen-rust",
+]
+
+[[package]]
+name = "wit-component"
+version = "0.244.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2"
+dependencies = [
+ "anyhow",
+ "bitflags 2.11.0",
+ "indexmap 2.13.0",
+ "log",
+ "serde",
+ "serde_derive",
+ "serde_json",
+ "wasm-encoder",
+ "wasm-metadata",
+ "wasmparser",
+ "wit-parser",
+]
+
+[[package]]
+name = "wit-parser"
+version = "0.244.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736"
+dependencies = [
+ "anyhow",
+ "id-arena",
+ "indexmap 2.13.0",
+ "log",
+ "semver",
+ "serde",
+ "serde_derive",
+ "serde_json",
+ "unicode-xid",
+ "wasmparser",
+]
[[package]]
name = "writeable"
@@ -3787,7 +6005,7 @@ dependencies = [
"bytes",
"futures",
"thiserror 1.0.69",
- "tonic 0.14.2",
+ "tonic 0.14.5",
"tonic-health",
"yellowstone-grpc-proto",
]
@@ -3799,11 +6017,23 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dbba21b6046eff1c9be2366a70d7264763b10004306e874b54409503a39e5f1e"
dependencies = [
"anyhow",
+ "bincode",
"prost 0.14.3",
"prost-types 0.14.3",
"protobuf-src",
- "tonic 0.14.2",
- "tonic-build 0.14.2",
+ "solana-account",
+ "solana-account-decoder",
+ "solana-clock",
+ "solana-hash",
+ "solana-message",
+ "solana-pubkey",
+ "solana-signature",
+ "solana-transaction",
+ "solana-transaction-context",
+ "solana-transaction-error",
+ "solana-transaction-status",
+ "tonic 0.14.5",
+ "tonic-build 0.14.5",
"tonic-prost",
"tonic-prost-build",
]
@@ -3894,28 +6124,28 @@ checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.114",
+ "syn 2.0.117",
"synstructure",
]
[[package]]
name = "zerocopy"
-version = "0.8.33"
+version = "0.8.42"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "668f5168d10b9ee831de31933dc111a459c97ec93225beb307aed970d1372dfd"
+checksum = "f2578b716f8a7a858b7f02d5bd870c14bf4ddbbcf3a4c05414ba6503640505e3"
dependencies = [
"zerocopy-derive",
]
[[package]]
name = "zerocopy-derive"
-version = "0.8.33"
+version = "0.8.42"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2c7962b26b0a8685668b671ee4b54d007a67d4eaf05fda79ac0ecf41e32270f1"
+checksum = "7e6cc098ea4d3bd6246687de65af3f920c430e236bee1e3bf2e441463f08a02f"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.114",
+ "syn 2.0.117",
]
[[package]]
@@ -3935,7 +6165,7 @@ checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.114",
+ "syn 2.0.117",
"synstructure",
]
@@ -3944,6 +6174,20 @@ name = "zeroize"
version = "1.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0"
+dependencies = [
+ "zeroize_derive",
+]
+
+[[package]]
+name = "zeroize_derive"
+version = "1.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "85a5b4158499876c763cb03bc4e49185d3cccbabb15b33c627f7884f43db852e"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.117",
+]
[[package]]
name = "zerotrie"
@@ -3975,14 +6219,14 @@ checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.114",
+ "syn 2.0.117",
]
[[package]]
name = "zmij"
-version = "1.0.16"
+version = "1.0.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dfcd145825aace48cff44a8844de64bf75feec3080e0aa5cdbde72961ae51a65"
+checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa"
[[package]]
name = "zstd"
diff --git a/examples/ore-server/Cargo.toml b/examples/ore-server/Cargo.toml
index bc2d9006..b6b47b21 100644
--- a/examples/ore-server/Cargo.toml
+++ b/examples/ore-server/Cargo.toml
@@ -9,6 +9,7 @@ name = "ore-server"
path = "src/main.rs"
[workspace]
+resolver = "2"
[dependencies]
ore-stack = { path = "../../stacks/ore" }
diff --git a/examples/ore-typescript/src/main.ts b/examples/ore-typescript/src/main.ts
index b13b81f3..a248a0be 100644
--- a/examples/ore-typescript/src/main.ts
+++ b/examples/ore-typescript/src/main.ts
@@ -9,13 +9,12 @@ import {
} from 'hyperstack-stacks/ore';
const OreRoundWithIdSchema = OreRoundSchema.extend({
- id: OreRoundIdSchema.required(),
+ id: OreRoundIdSchema.partial(),
});
const OreTreasuryWithIdSchema = OreTreasurySchema.extend({
- id: OreTreasuryIdSchema.required(),
+ id: OreTreasuryIdSchema.partial(),
});
-
type OreRoundWithId = z.infer
;
type OreTreasuryWithId = z.infer;
@@ -41,7 +40,7 @@ function printTreasury(treasury: OreTreasuryWithId) {
}
async function main() {
- const hs = await HyperStack.connect(ORE_STREAM_STACK);
+ const hs = await HyperStack.connect(ORE_STREAM_STACK, { url: 'http://localhost:8878' });
console.log('--- Streaming OreRound and OreTreasury updates ---\n');
diff --git a/hyperstack-idl/Cargo.toml b/hyperstack-idl/Cargo.toml
index 5df1fc6b..0d040afc 100644
--- a/hyperstack-idl/Cargo.toml
+++ b/hyperstack-idl/Cargo.toml
@@ -16,3 +16,4 @@ serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
sha2 = "0.10"
strsim = "0.11"
+tracing = "0.1"
diff --git a/hyperstack-idl/src/parse.rs b/hyperstack-idl/src/parse.rs
index bd6f1dc0..de90ff37 100644
--- a/hyperstack-idl/src/parse.rs
+++ b/hyperstack-idl/src/parse.rs
@@ -177,14 +177,8 @@ mod tests {
}"#;
let idl = parse_idl_content(json).unwrap();
- assert_eq!(
- idl.instructions[0].get_discriminator(),
- vec![0, 0, 0, 0, 0, 0, 0, 0]
- );
- assert_eq!(
- idl.instructions[1].get_discriminator(),
- vec![1, 0, 0, 0, 0, 0, 0, 0]
- );
+ assert_eq!(idl.instructions[0].get_discriminator(), vec![0]);
+ assert_eq!(idl.instructions[1].get_discriminator(), vec![1]);
}
#[test]
diff --git a/hyperstack-idl/src/snapshot.rs b/hyperstack-idl/src/snapshot.rs
index 68448d15..66a60933 100644
--- a/hyperstack-idl/src/snapshot.rs
+++ b/hyperstack-idl/src/snapshot.rs
@@ -1,11 +1,13 @@
//! Snapshot type definitions
-use serde::{de::Error, Deserialize, Deserializer, Serialize};
+use serde::{de::Error as DeError, Deserialize, Deserializer, Serialize};
-#[derive(Debug, Clone, Serialize, Deserialize)]
+use crate::types::SteelDiscriminant;
+
+#[derive(Debug, Clone, Serialize)]
pub struct IdlSnapshot {
pub name: String,
- #[serde(default, skip_serializing_if = "Option::is_none")]
+ #[serde(default, skip_serializing_if = "Option::is_none", alias = "address")]
pub program_id: Option,
pub version: String,
pub accounts: Vec,
@@ -16,34 +18,180 @@ pub struct IdlSnapshot {
pub events: Vec,
#[serde(default)]
pub errors: Vec,
- #[serde(default = "default_discriminant_size")]
pub discriminant_size: usize,
}
-fn default_discriminant_size() -> usize {
- 8
+impl<'de> Deserialize<'de> for IdlSnapshot {
+ fn deserialize(deserializer: D) -> Result
+ where
+ D: Deserializer<'de>,
+ {
+ // First deserialize to a generic Value to inspect instructions
+ let value = serde_json::Value::deserialize(deserializer)?;
+
+ // Check if any instruction has discriminant (Steel-style) vs discriminator (Anchor-style)
+ let discriminant_size = value
+ .get("instructions")
+ .and_then(|instrs| instrs.as_array())
+ .map(|instrs| {
+ if instrs.is_empty() {
+ return false;
+ }
+ instrs.iter().all(|ix| {
+ // Steel-style: has discriminant field, no discriminator or empty discriminator
+ let has_discriminant = ix.get("discriminant").is_some();
+ let discriminator = ix.get("discriminator");
+ let has_discriminator = discriminator
+ .map(|d| {
+ !d.is_null() && d.as_array().map(|a| !a.is_empty()).unwrap_or(true)
+ })
+ .unwrap_or(false);
+ has_discriminant && !has_discriminator
+ })
+ })
+ .map(|is_steel| if is_steel { 1 } else { 8 })
+ .unwrap_or(8); // Default to 8 if no instructions
+
+ // Now deserialize the full struct
+ let mut intermediate: IdlSnapshotIntermediate = serde_json::from_value(value)
+ .map_err(|e| DeError::custom(format!("Failed to deserialize IDL: {}", e)))?;
+ intermediate.discriminant_size = discriminant_size;
+
+ Ok(IdlSnapshot {
+ name: intermediate.name,
+ program_id: intermediate.program_id,
+ version: intermediate.version,
+ accounts: intermediate.accounts,
+ instructions: intermediate.instructions,
+ types: intermediate.types,
+ events: intermediate.events,
+ errors: intermediate.errors,
+ discriminant_size: intermediate.discriminant_size,
+ })
+ }
}
-#[derive(Debug, Clone, Serialize, Deserialize)]
+// Intermediate struct for deserialization
+#[derive(Debug, Clone, Deserialize)]
+struct IdlSnapshotIntermediate {
+ pub name: String,
+ #[serde(default, alias = "address")]
+ pub program_id: Option,
+ pub version: String,
+ pub accounts: Vec,
+ pub instructions: Vec,
+ #[serde(default)]
+ pub types: Vec,
+ #[serde(default)]
+ pub events: Vec,
+ #[serde(default)]
+ pub errors: Vec,
+ #[serde(default)]
+ pub discriminant_size: usize,
+}
+
+#[derive(Debug, Clone, Serialize)]
pub struct IdlAccountSnapshot {
+ pub name: String,
+ pub discriminator: Vec,
+ pub docs: Vec,
+ pub serialization: Option,
+ /// Account fields - populated from inline type definition
+ pub fields: Vec,
+ /// Inline type definition (for Steel format with type.fields structure)
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub type_def: Option,
+}
+
+// Intermediate struct for deserialization
+#[derive(Deserialize)]
+struct IdlAccountSnapshotIntermediate {
pub name: String,
pub discriminator: Vec,
#[serde(default)]
pub docs: Vec,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub serialization: Option,
+ #[serde(default)]
+ pub fields: Vec,
+ #[serde(rename = "type", default, skip_serializing_if = "Option::is_none")]
+ pub type_def: Option,
+}
+
+impl<'de> Deserialize<'de> for IdlAccountSnapshot {
+ fn deserialize(deserializer: D) -> Result
+ where
+ D: Deserializer<'de>,
+ {
+ let intermediate = IdlAccountSnapshotIntermediate::deserialize(deserializer)?;
+
+ // Normalize fields: if empty but type_def has fields, use those
+ let fields = if intermediate.fields.is_empty() {
+ if let Some(type_def) = intermediate.type_def.as_ref() {
+ type_def.fields.clone()
+ } else {
+ intermediate.fields
+ }
+ } else {
+ intermediate.fields
+ };
+
+ Ok(IdlAccountSnapshot {
+ name: intermediate.name,
+ discriminator: intermediate.discriminator,
+ docs: intermediate.docs,
+ serialization: intermediate.serialization,
+ fields,
+ type_def: intermediate.type_def,
+ })
+ }
+}
+
+/// Inline type definition for account fields (Steel format)
+#[derive(Debug, Clone, Serialize, Deserialize)]
+pub struct IdlInlineTypeDef {
+ pub kind: String,
+ pub fields: Vec,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct IdlInstructionSnapshot {
pub name: String,
+ #[serde(default)]
pub discriminator: Vec,
#[serde(default)]
+ pub discriminant: Option,
+ #[serde(default)]
pub docs: Vec,
pub accounts: Vec,
pub args: Vec,
}
+impl IdlInstructionSnapshot {
+ /// Get the computed 8-byte discriminator.
+ /// Returns the explicit discriminator if present, otherwise computes from discriminant.
+ pub fn get_discriminator(&self) -> Vec {
+ if !self.discriminator.is_empty() {
+ return self.discriminator.clone();
+ }
+
+ if let Some(disc) = &self.discriminant {
+ match u8::try_from(disc.value) {
+ Ok(value) => return vec![value],
+ Err(_) => {
+ tracing::warn!(
+ instruction = %self.name,
+ value = disc.value,
+ "Steel discriminant exceeds u8::MAX; falling back to Anchor hash"
+ );
+ }
+ }
+ }
+
+ crate::discriminator::anchor_discriminator(&format!("global:{}", self.name))
+ }
+}
+
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct IdlInstructionAccountSnapshot {
pub name: String,
@@ -89,6 +237,7 @@ fn deserialize_hash_map<'de, D>(
where
D: Deserializer<'de>,
{
+ use serde::de::Error;
let values: Vec = Vec::deserialize(deserializer)?;
if values.len() != 2 {
return Err(D::Error::custom("hashMap must have exactly 2 elements"));
@@ -208,10 +357,13 @@ mod tests {
discriminator: vec![1, 2, 3, 4, 5, 6, 7, 8],
docs: vec!["Example account".to_string()],
serialization: Some(IdlSerializationSnapshot::Borsh),
+ fields: vec![],
+ type_def: None,
}],
instructions: vec![IdlInstructionSnapshot {
name: "example_instruction".to_string(),
discriminator: vec![8, 7, 6, 5, 4, 3, 2, 1],
+ discriminant: None,
docs: vec!["Example instruction".to_string()],
accounts: vec![IdlInstructionAccountSnapshot {
name: "payer".to_string(),
@@ -253,7 +405,7 @@ mod tests {
name: "ExampleError".to_string(),
msg: Some("example".to_string()),
}],
- discriminant_size: default_discriminant_size(),
+ discriminant_size: 8,
};
let serialized = serde_json::to_value(&snapshot).expect("serialize snapshot");
diff --git a/hyperstack-idl/src/types.rs b/hyperstack-idl/src/types.rs
index 6255ceef..870b74a3 100644
--- a/hyperstack-idl/src/types.rs
+++ b/hyperstack-idl/src/types.rs
@@ -78,7 +78,7 @@ impl IdlInstruction {
if let Some(disc) = &self.discriminant {
let value = disc.value as u8;
- return vec![value, 0, 0, 0, 0, 0, 0, 0];
+ return vec![value];
}
crate::discriminator::anchor_discriminator(&format!("global:{}", self.name))
diff --git a/hyperstack-idl/tests/fixtures/ore.json b/hyperstack-idl/tests/fixtures/ore.json
index e4485200..41bdd617 100644
--- a/hyperstack-idl/tests/fixtures/ore.json
+++ b/hyperstack-idl/tests/fixtures/ore.json
@@ -1,6 +1,7 @@
{
"version": "3.7.22",
"name": "ore",
+ "address": "oreV3EG1i9BEgiAJ8b177Z2S2rMarzak4NMv1kULvWv",
"instructions": [
{
"name": "automate",
diff --git a/hyperstack-idl/tests/parse_fixtures.rs b/hyperstack-idl/tests/parse_fixtures.rs
index e75552a1..bd65d9d8 100644
--- a/hyperstack-idl/tests/parse_fixtures.rs
+++ b/hyperstack-idl/tests/parse_fixtures.rs
@@ -1,4 +1,6 @@
use hyperstack_idl::parse::parse_idl_file;
+use hyperstack_idl::snapshot::IdlSnapshot;
+use std::fs;
use std::path::PathBuf;
fn fixture_path(name: &str) -> PathBuf {
@@ -18,6 +20,63 @@ fn test_parse_ore_legacy() {
assert!(idl.name.is_some(), "ore should have a name");
}
+#[test]
+fn test_ore_instructions_have_discriminators() {
+ // Test that ore.json instructions have proper discriminators when parsed as IdlSnapshot
+ // This tests the fix for Steel-style discriminant format
+ let idl_json = fs::read_to_string(fixture_path("ore.json")).expect("should read ore.json");
+ let snapshot: IdlSnapshot =
+ serde_json::from_str(&idl_json).expect("should parse as IdlSnapshot");
+
+ assert_eq!(
+ snapshot.instructions.len(),
+ 19,
+ "ore should have 19 instructions"
+ );
+
+ // All instructions should have non-empty discriminators via get_discriminator()
+ let empty_count = snapshot
+ .instructions
+ .iter()
+ .filter(|ix| ix.get_discriminator().is_empty())
+ .count();
+
+ assert_eq!(
+ empty_count, 0,
+ "All ore instructions should have discriminators computed from discriminant field"
+ );
+
+ // Verify specific instruction
+ let automate = snapshot
+ .instructions
+ .iter()
+ .find(|ix| ix.name == "automate")
+ .expect("should find automate instruction");
+
+ assert_eq!(
+ automate.get_discriminator(),
+ vec![0],
+ "automate instruction should have discriminator [0]"
+ );
+
+ // Verify program_id is parsed from address field (using ore.json fixture)
+ let original_idl_json =
+ fs::read_to_string(fixture_path("ore.json")).expect("should read ore.json");
+ let original_snapshot: IdlSnapshot =
+ serde_json::from_str(&original_idl_json).expect("should parse ore.json as IdlSnapshot");
+
+ assert_eq!(
+ original_snapshot.program_id,
+ Some("oreV3EG1i9BEgiAJ8b177Z2S2rMarzak4NMv1kULvWv".to_string()),
+ "program_id should be parsed from address field"
+ );
+
+ assert_eq!(
+ original_snapshot.discriminant_size, 1,
+ "Steel-style IDL should use 1-byte discriminants"
+ );
+}
+
#[test]
fn test_parse_entropy_legacy() {
let idl = parse_idl_file(&fixture_path("entropy.json")).expect("should parse entropy.json");
diff --git a/hyperstack-macros/src/ast/types.rs b/hyperstack-macros/src/ast/types.rs
index 9fadb515..b01f437d 100644
--- a/hyperstack-macros/src/ast/types.rs
+++ b/hyperstack-macros/src/ast/types.rs
@@ -60,7 +60,6 @@ pub enum PopulationStrategy {
UniqueCount,
}
-
/// Default discriminant size (8 bytes for Anchor).
/// Used by InstructionDef serde default.
fn default_discriminant_size() -> usize {
@@ -261,6 +260,12 @@ pub enum ComputedExpr {
// Context access - slot and timestamp from the update that triggered evaluation
ContextSlot,
ContextTimestamp,
+
+ /// Keccak256 hash function for computing Ethereum-compatible hashes
+ /// Takes a byte array expression and returns the 32-byte hash as a Vec
+ Keccak256 {
+ expr: Box,
+ },
}
#[derive(Debug, Clone, Serialize, Deserialize)]
@@ -374,6 +379,9 @@ pub enum SourceSpec {
type_name: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
serialization: Option,
+ /// True when this handler listens to an account-state event.
+ #[serde(default)]
+ is_account: bool,
},
}
diff --git a/hyperstack-macros/src/ast/writer.rs b/hyperstack-macros/src/ast/writer.rs
index fc3d513a..37ab0252 100644
--- a/hyperstack-macros/src/ast/writer.rs
+++ b/hyperstack-macros/src/ast/writer.rs
@@ -230,6 +230,21 @@ pub fn convert_idl_to_snapshot(idl: &idl_parser::IdlSpec) -> IdlSnapshot {
discriminator: acc.get_discriminator(),
docs: acc.docs.clone(),
serialization,
+ // Extract fields from inline type definition if present
+ fields: acc.type_def.as_ref().map_or_else(
+ Vec::new,
+ |type_def| match type_def {
+ idl_parser::IdlTypeDefKind::Struct { fields, .. } => fields
+ .iter()
+ .map(|f| IdlFieldSnapshot {
+ name: f.name.clone(),
+ type_: convert_idl_type(&f.type_),
+ })
+ .collect(),
+ _ => Vec::new(),
+ },
+ ),
+ type_def: None, // Fields are extracted above, no need to keep type_def
}
})
.collect(),
@@ -239,6 +254,7 @@ pub fn convert_idl_to_snapshot(idl: &idl_parser::IdlSpec) -> IdlSnapshot {
.map(|instr| IdlInstructionSnapshot {
name: instr.name.clone(),
discriminator: instr.get_discriminator(),
+ discriminant: None,
docs: instr.docs.clone(),
accounts: instr
.accounts
@@ -602,6 +618,7 @@ pub fn build_handlers_from_sources(
discriminator: None,
type_name,
serialization,
+ is_account: !is_instruction && !is_cpi_event,
},
key_resolution,
mappings: serializable_mappings,
diff --git a/hyperstack-macros/src/codegen/computed.rs b/hyperstack-macros/src/codegen/computed.rs
index 8b823a0f..274510dd 100644
--- a/hyperstack-macros/src/codegen/computed.rs
+++ b/hyperstack-macros/src/codegen/computed.rs
@@ -93,6 +93,9 @@ fn extract_deps_recursive(expr: &ComputedExpr, section: &str, deps: &mut HashSet
extract_deps_recursive(expr, section, deps);
}
ComputedExpr::ContextSlot | ComputedExpr::ContextTimestamp => {}
+ ComputedExpr::Keccak256 { expr } => {
+ extract_deps_recursive(expr, section, deps);
+ }
}
}
@@ -115,6 +118,7 @@ fn contains_resolver_computed(expr: &ComputedExpr) -> bool {
| ComputedExpr::U64FromLeBytes { bytes: expr }
| ComputedExpr::U64FromBeBytes { bytes: expr }
| ComputedExpr::JsonToBytes { expr }
+ | ComputedExpr::Keccak256 { expr }
| ComputedExpr::Unary { expr, .. } => contains_resolver_computed(expr),
ComputedExpr::Binary { left, right, .. } => {
contains_resolver_computed(left) || contains_resolver_computed(right)
@@ -447,13 +451,16 @@ pub fn generate_computed_expr_code(expr: &ComputedExpr) -> TokenStream {
let param_ident = format_ident!("{}", param);
if contains_resolver_computed(body) {
+ // For closures with resolver calls, pass the element as JSON value
+ // and let the resolver extract what it needs
let body_code = generate_option_safe_expr_code(body);
return quote! {
#inner.as_ref().and_then(|v| {
v.as_array().map(|arr| {
arr.iter()
.filter_map(|elem| {
- let #param_ident = elem.as_f64()?;
+ // Pass element as serde_json::Value for resolvers
+ let #param_ident = elem;
#body_code
})
.collect::>()
@@ -492,20 +499,23 @@ pub fn generate_computed_expr_code(expr: &ComputedExpr) -> TokenStream {
let method_name = method.as_str();
let arg_codes: Vec =
args.iter().map(generate_computed_expr_code).collect();
+ // Wrap in an immediately-invoked closure returning Option so that
+ // .ok()? works regardless of whether the surrounding context returns
+ // Result or Option.
quote! {
- {
- let resolver_args = vec![#(hyperstack::runtime::serde_json::to_value(#arg_codes)?),*];
+ (|| -> Option {
+ let resolver_args = vec![#(hyperstack::runtime::serde_json::to_value(#arg_codes).ok()?),*];
let resolver_value = hyperstack::runtime::hyperstack_interpreter::resolvers::evaluate_resolver_computed(
#resolver_name,
#method_name,
&resolver_args,
- )?;
+ ).ok()?;
if resolver_value.is_null() {
None
} else {
Some(resolver_value)
}
- }
+ })()
}
}
ComputedExpr::Literal { value } => {
@@ -646,5 +656,419 @@ pub fn generate_computed_expr_code(expr: &ComputedExpr) -> TokenStream {
// __context_timestamp is i64, use directly
quote! { __context_timestamp }
}
+ ComputedExpr::Keccak256 { expr } => {
+ let inner = generate_computed_expr_code(expr);
+ quote! {
+ {
+ use hyperstack::runtime::sha3::{Digest, Keccak256};
+ let bytes = #inner;
+ let hash = Keccak256::digest(&bytes);
+ hash.to_vec()
+ }
+ }
+ }
+ }
+}
+
+/// Generate code for a computed expression that uses a local cache for intra-section field references.
+/// This ensures dependent computed fields see the newly computed values within the same evaluation cycle.
+pub fn generate_computed_expr_code_with_cache(
+ expr: &ComputedExpr,
+ section: &str,
+ computed_field_names: &[String],
+) -> TokenStream {
+ match expr {
+ ComputedExpr::FieldRef { path } => {
+ let parts: Vec<&str> = path.split('.').collect();
+ if parts.len() >= 2 && parts[0] == section {
+ // This is a field reference within the same section
+ let field_name = parts[1];
+ if computed_field_names.contains(&field_name.to_string()) {
+ // It's a computed field - read from cache to get the latest value
+ let remaining_path: Vec<&str> = parts[2..].to_vec();
+ if remaining_path.is_empty() {
+ return quote! {
+ computed_cache.get(#field_name).cloned()
+ };
+ } else {
+ let path_tokens: Vec<_> = remaining_path
+ .iter()
+ .map(|p| quote! { .and_then(|v| v.get(#p)) })
+ .collect();
+ return quote! {
+ computed_cache.get(#field_name).cloned()#(#path_tokens)*
+ };
+ }
+ }
+ }
+ // Not a computed field in this section - delegate to original implementation
+ generate_computed_expr_code(expr)
+ }
+ ComputedExpr::Binary { op, left, right } => {
+ let left_code =
+ generate_computed_expr_code_with_cache(left, section, computed_field_names);
+ let right_code =
+ generate_computed_expr_code_with_cache(right, section, computed_field_names);
+ let op_code = match op {
+ BinaryOp::Add => quote! { + },
+ BinaryOp::Sub => quote! { - },
+ BinaryOp::Mul => quote! { * },
+ BinaryOp::Div => quote! { / },
+ BinaryOp::Mod => quote! { % },
+ BinaryOp::Gt => quote! { > },
+ BinaryOp::Lt => quote! { < },
+ BinaryOp::Gte => quote! { >= },
+ BinaryOp::Lte => quote! { <= },
+ BinaryOp::Eq => quote! { == },
+ BinaryOp::Ne => quote! { != },
+ BinaryOp::And => quote! { && },
+ BinaryOp::Or => quote! { || },
+ BinaryOp::Xor => quote! { ^ },
+ BinaryOp::BitAnd => quote! { & },
+ BinaryOp::BitOr => quote! { | },
+ BinaryOp::Shl => quote! { << },
+ BinaryOp::Shr => quote! { >> },
+ };
+ quote! { (#left_code #op_code #right_code) }
+ }
+ ComputedExpr::MethodCall {
+ expr: inner,
+ method,
+ args,
+ } => {
+ let inner_code =
+ generate_computed_expr_code_with_cache(inner, section, computed_field_names);
+ let method_ident = format_ident!("{}", method);
+
+ // Special handling for .map() with closures - check if closure body references computed fields
+ if method == "map" && args.len() == 1 {
+ if let ComputedExpr::Closure { param, body } = &args[0] {
+ let param_ident = format_ident!("{}", param);
+ // Check if the closure body references any computed fields in this section
+ let body_deps = extract_field_dependencies(body, section);
+ let has_computed_deps: std::collections::HashSet = body_deps
+ .intersection(&computed_field_names.iter().cloned().collect())
+ .cloned()
+ .collect();
+
+ // Closures in .map() return Option, so use option-safe code generation
+ let body_code = if has_computed_deps.is_empty() {
+ generate_option_safe_expr_code(body)
+ } else {
+ generate_computed_expr_code_with_cache_option_safe(
+ body,
+ section,
+ computed_field_names,
+ )
+ };
+
+ return quote! {
+ {
+ let inner_result = #inner_code;
+ // Handle both arrays (Vec) and single values (u64)
+ let map_result: Option = inner_result.and_then(|v| {
+ if let Some(arr) = v.as_array() {
+ // Handle array: map over each element
+ let mapped: Vec<_> = arr
+ .iter()
+ .filter_map(|elem| {
+ elem.as_u64().and_then(|#param_ident| {
+ let result = #body_code;
+ hyperstack::runtime::serde_json::to_value(result).ok()
+ })
+ })
+ .collect();
+ hyperstack::runtime::serde_json::to_value(mapped).ok()
+ } else {
+ // Handle single value
+ v.as_u64().and_then(|#param_ident| {
+ let result = #body_code;
+ hyperstack::runtime::serde_json::to_value(result).ok()
+ })
+ }
+ });
+ map_result
+ }
+ };
+ }
+ }
+
+ let arg_codes: Vec = args
+ .iter()
+ .map(|arg| {
+ generate_computed_expr_code_with_cache(arg, section, computed_field_names)
+ })
+ .collect();
+
+ quote! { #inner_code.#method_ident(#(#arg_codes),*) }
+ }
+ ComputedExpr::Cast {
+ expr: inner,
+ to_type,
+ } => {
+ let inner_code =
+ generate_computed_expr_code_with_cache(inner, section, computed_field_names);
+ let type_ident = format_ident!("{}", to_type);
+ quote! { (#inner_code as #type_ident) }
+ }
+ ComputedExpr::Paren { expr: inner } => {
+ let inner_code =
+ generate_computed_expr_code_with_cache(inner, section, computed_field_names);
+ quote! { (#inner_code) }
+ }
+ ComputedExpr::UnwrapOr {
+ expr: inner,
+ default,
+ } => {
+ let inner_code =
+ generate_computed_expr_code_with_cache(inner, section, computed_field_names);
+ let default_num = match default {
+ serde_json::Value::Number(n) => {
+ if let Some(i) = n.as_i64() {
+ quote! { #i }
+ } else if let Some(u) = n.as_u64() {
+ quote! { #u }
+ } else {
+ let f = n.as_f64().unwrap_or(0.0);
+ quote! { #f }
+ }
+ }
+ serde_json::Value::Bool(b) => {
+ if *b {
+ quote! { 1i64 }
+ } else {
+ quote! { 0i64 }
+ }
+ }
+ _ => quote! { 0i64 },
+ };
+ quote! {
+ #inner_code.and_then(|v| v.as_i64().or_else(|| v.as_u64().map(|u| u as i64))).unwrap_or(#default_num)
+ }
+ }
+ ComputedExpr::Some { value } => {
+ let inner =
+ generate_computed_expr_code_with_cache(value, section, computed_field_names);
+ quote! { Some(#inner) }
+ }
+ ComputedExpr::None => {
+ quote! { None }
+ }
+ ComputedExpr::Unary { op, expr: inner } => {
+ let inner_code =
+ generate_computed_expr_code_with_cache(inner, section, computed_field_names);
+ match op {
+ UnaryOp::Not => quote! { !#inner_code },
+ UnaryOp::ReverseBits => quote! { #inner_code.reverse_bits() },
+ }
+ }
+ ComputedExpr::Keccak256 { expr: inner } => {
+ let inner_code =
+ generate_computed_expr_code_with_cache(inner, section, computed_field_names);
+ quote! {
+ {
+ use hyperstack::runtime::sha3::{Digest, Keccak256};
+ let bytes = #inner_code;
+ let hash = Keccak256::digest(&bytes);
+ hash.to_vec()
+ }
+ }
+ }
+ ComputedExpr::U64FromLeBytes { bytes } => {
+ let bytes_code =
+ generate_computed_expr_code_with_cache(bytes, section, computed_field_names);
+ quote! {
+ {
+ let slice = #bytes_code;
+ let arr: [u8; 8] = slice.try_into().unwrap_or([0u8; 8]);
+ u64::from_le_bytes(arr)
+ }
+ }
+ }
+ ComputedExpr::ByteArray { bytes } => {
+ let byte_literals: Vec = bytes
+ .iter()
+ .map(|b| {
+ let byte_val = *b;
+ quote! { #byte_val }
+ })
+ .collect();
+ quote! { vec![#(#byte_literals),*] }
+ }
+ ComputedExpr::Var { name } => {
+ let name_ident = format_ident!("{}", name);
+ quote! { #name_ident }
+ }
+ ComputedExpr::Literal { value } => match value {
+ serde_json::Value::Number(n) => {
+ if let Some(u) = n.as_u64() {
+ quote! { #u }
+ } else if let Some(i) = n.as_i64() {
+ quote! { #i }
+ } else {
+ let num = n.as_f64().unwrap_or(0.0);
+ quote! { #num }
+ }
+ }
+ serde_json::Value::Bool(b) => {
+ quote! { #b }
+ }
+ serde_json::Value::Null => {
+ quote! { () }
+ }
+ _ => quote! { 0.0_f64 },
+ },
+ ComputedExpr::ResolverComputed {
+ resolver,
+ method,
+ args,
+ } => {
+ let resolver_name = resolver.as_str();
+ let method_name = method.as_str();
+ // Use cache-aware codegen for args so that intra-section computed
+ // field references (e.g. results.expires_at_slot_hash) read from
+ // computed_cache instead of the stale section_parent_state snapshot.
+ let arg_codes: Vec = args
+ .iter()
+ .map(|arg| {
+ generate_computed_expr_code_with_cache(arg, section, computed_field_names)
+ })
+ .collect();
+ quote! {
+ (|| -> Option {
+ let resolver_args = vec![#(hyperstack::runtime::serde_json::to_value(#arg_codes).ok()?),*];
+ let resolver_value = hyperstack::runtime::hyperstack_interpreter::resolvers::evaluate_resolver_computed(
+ #resolver_name,
+ #method_name,
+ &resolver_args,
+ ).ok()?;
+ if resolver_value.is_null() {
+ None
+ } else {
+ Some(resolver_value)
+ }
+ })()
+ }
+ }
+ ComputedExpr::Closure { param, body } => {
+ let param_ident = format_ident!("{}", param);
+ let body_code =
+ generate_computed_expr_code_with_cache(body, section, computed_field_names);
+ quote! { |#param_ident| #body_code }
+ }
+ // Fallback for any unhandled expressions
+ _ => generate_computed_expr_code(expr),
+ }
+}
+
+/// Option-safe version of generate_computed_expr_code_with_cache.
+/// Use this when the generated code will be used inside a closure that returns Option.
+fn generate_computed_expr_code_with_cache_option_safe(
+ expr: &ComputedExpr,
+ section: &str,
+ computed_field_names: &[String],
+) -> TokenStream {
+ match expr {
+ ComputedExpr::FieldRef { path } => {
+ let parts: Vec<&str> = path.split('.').collect();
+ if parts.len() >= 2 && parts[0] == section {
+ let field_name = parts[1];
+ if computed_field_names.contains(&field_name.to_string()) {
+ let remaining_path: Vec<&str> = parts[2..].to_vec();
+ if remaining_path.is_empty() {
+ return quote! {
+ computed_cache.get(#field_name).cloned()
+ };
+ } else {
+ let path_tokens: Vec<_> = remaining_path
+ .iter()
+ .map(|p| quote! { .and_then(|v| v.get(#p)) })
+ .collect();
+ return quote! {
+ computed_cache.get(#field_name).cloned()#(#path_tokens)*
+ };
+ }
+ }
+ }
+ generate_option_safe_expr_code(expr)
+ }
+ ComputedExpr::Binary { op, left, right } => {
+ let left_code = generate_computed_expr_code_with_cache_option_safe(
+ left,
+ section,
+ computed_field_names,
+ );
+ let right_code = generate_computed_expr_code_with_cache_option_safe(
+ right,
+ section,
+ computed_field_names,
+ );
+ let op_code = match op {
+ BinaryOp::Add => quote! { + },
+ BinaryOp::Sub => quote! { - },
+ BinaryOp::Mul => quote! { * },
+ BinaryOp::Div => quote! { / },
+ BinaryOp::Mod => quote! { % },
+ BinaryOp::Gt => quote! { > },
+ BinaryOp::Lt => quote! { < },
+ BinaryOp::Gte => quote! { >= },
+ BinaryOp::Lte => quote! { <= },
+ BinaryOp::Eq => quote! { == },
+ BinaryOp::Ne => quote! { != },
+ BinaryOp::And => quote! { && },
+ BinaryOp::Or => quote! { || },
+ BinaryOp::Xor => quote! { ^ },
+ BinaryOp::BitAnd => quote! { & },
+ BinaryOp::BitOr => quote! { | },
+ BinaryOp::Shl => quote! { << },
+ BinaryOp::Shr => quote! { >> },
+ };
+ quote! { (#left_code #op_code #right_code) }
+ }
+ ComputedExpr::ResolverComputed {
+ resolver,
+ method,
+ args,
+ } => {
+ let resolver_name = resolver.as_str();
+ let method_name = method.as_str();
+ let arg_codes: Vec =
+ args.iter().map(generate_option_safe_expr_code).collect();
+ quote! {
+ {
+ let resolver_args = vec![#(hyperstack::runtime::serde_json::to_value(#arg_codes).ok()?),*];
+ let resolver_value = hyperstack::runtime::hyperstack_interpreter::resolvers::evaluate_resolver_computed(
+ #resolver_name,
+ #method_name,
+ &resolver_args,
+ ).ok()?;
+ if resolver_value.is_null() {
+ None
+ } else {
+ Some(resolver_value)
+ }
+ }
+ }
+ }
+ ComputedExpr::Var { name } => {
+ let name_ident = format_ident!("{}", name);
+ quote! { #name_ident }
+ }
+ ComputedExpr::Literal { value } => match value {
+ serde_json::Value::Number(n) => {
+ if let Some(u) = n.as_u64() {
+ quote! { #u }
+ } else if let Some(i) = n.as_i64() {
+ quote! { #i }
+ } else {
+ let num = n.as_f64().unwrap_or(0.0);
+ quote! { #num }
+ }
+ }
+ serde_json::Value::Bool(b) => quote! { #b },
+ serde_json::Value::Null => quote! { () },
+ _ => quote! { 0.0_f64 },
+ },
+ _ => generate_option_safe_expr_code(expr),
}
}
diff --git a/hyperstack-macros/src/codegen/handlers.rs b/hyperstack-macros/src/codegen/handlers.rs
index 1e0e2d20..08112665 100644
--- a/hyperstack-macros/src/codegen/handlers.rs
+++ b/hyperstack-macros/src/codegen/handlers.rs
@@ -92,6 +92,7 @@ fn build_source_spec_code(source: &SourceSpec) -> TokenStream {
discriminator,
type_name,
serialization,
+ is_account,
} => {
let program_id_code = match program_id {
Some(id) => quote! { Some(#id.to_string()) },
@@ -125,6 +126,7 @@ fn build_source_spec_code(source: &SourceSpec) -> TokenStream {
discriminator: #discriminator_code,
type_name: #type_name.to_string(),
serialization: #serialization_code,
+ is_account: #is_account,
}
}
}
diff --git a/hyperstack-macros/src/codegen/mod.rs b/hyperstack-macros/src/codegen/mod.rs
index aea630d4..74d70b81 100644
--- a/hyperstack-macros/src/codegen/mod.rs
+++ b/hyperstack-macros/src/codegen/mod.rs
@@ -19,7 +19,7 @@ pub(crate) mod vixen_runtime;
// Internal re-exports for use within this crate only
pub(crate) use bytecode::generate_bytecode_from_spec;
pub(crate) use computed::generate_computed_evaluator;
-pub(crate) use computed::generate_computed_expr_code;
+pub(crate) use computed::generate_computed_expr_code_with_cache;
pub(crate) use field_accessors::generate_field_accessors;
pub(crate) use handlers::generate_handlers_from_specs;
pub(crate) use multi_entity::generate_multi_entity_builder;
diff --git a/hyperstack-macros/src/codegen/vixen_runtime.rs b/hyperstack-macros/src/codegen/vixen_runtime.rs
index ef75199e..72d9243b 100644
--- a/hyperstack-macros/src/codegen/vixen_runtime.rs
+++ b/hyperstack-macros/src/codegen/vixen_runtime.rs
@@ -61,9 +61,15 @@ fn generate_slot_scheduler_task() -> TokenStream {
"SlotScheduler: started (in-memory only, pending callbacks will not survive restarts)"
);
loop {
+ // Wait for a slot advance notification, or fall back to polling
+ // every 5s in case notifications are missed.
+ hyperstack::runtime::tokio::select! {
+ _ = slot_tracker.notified() => {},
+ _ = hyperstack::runtime::tokio::time::sleep(std::time::Duration::from_secs(5)) => {},
+ }
+
let current_slot = slot_tracker.get();
if current_slot == 0 {
- hyperstack::runtime::tokio::time::sleep(std::time::Duration::from_millis(400)).await;
continue;
}
@@ -77,6 +83,14 @@ fn generate_slot_scheduler_task() -> TokenStream {
const MAX_RETRIES: u32 = hyperstack::runtime::hyperstack_interpreter::scheduler::MAX_RETRIES;
+ if !due.is_empty() {
+ hyperstack::runtime::tracing::info!(
+ current_slot = current_slot,
+ due_count = due.len(),
+ "[SCHEDULER] Processing due callbacks"
+ );
+ }
+
for mut callback in due {
let state = {
let vm_guard = vm.lock().unwrap_or_else(|e| e.into_inner());
@@ -102,12 +116,17 @@ fn generate_slot_scheduler_task() -> TokenStream {
};
if let Some(ref condition) = callback.condition {
- if !hyperstack::runtime::hyperstack_interpreter::scheduler::evaluate_condition(condition, &state) {
- hyperstack::runtime::tracing::debug!(
- entity = %callback.entity_name,
- key = ?callback.primary_key,
- "SlotScheduler: condition no longer met, skipping callback"
- );
+ let condition_met = hyperstack::runtime::hyperstack_interpreter::scheduler::evaluate_condition(condition, &state);
+ let field_val = hyperstack::runtime::hyperstack_interpreter::scheduler::get_value_at_path(&state, &condition.field_path);
+ hyperstack::runtime::tracing::info!(
+ entity = %callback.entity_name,
+ key = ?callback.primary_key,
+ condition_field = %condition.field_path,
+ condition_met = condition_met,
+ field_value = ?field_val,
+ "[SCHEDULER] Re-evaluating condition at callback fire time"
+ );
+ if !condition_met {
continue;
}
}
@@ -117,11 +136,16 @@ fn generate_slot_scheduler_task() -> TokenStream {
// Already-set fields are protected from overwrite by the
// SetOnce guard in VmContext::set_value_at_path.
let already_resolved = callback.extracts.iter().all(|ext| {
- hyperstack::runtime::hyperstack_interpreter::scheduler::get_value_at_path(&state, &ext.target_path)
- .map(|v| !v.is_null())
- .unwrap_or(false)
+ let val = hyperstack::runtime::hyperstack_interpreter::scheduler::get_value_at_path(&state, &ext.target_path);
+ val.map(|v| !v.is_null()).unwrap_or(false)
});
if already_resolved {
+ hyperstack::runtime::tracing::info!(
+ entity = %callback.entity_name,
+ key = ?callback.primary_key,
+ targets = ?callback.extracts.iter().map(|e| &e.target_path).collect::>(),
+ "[SCHEDULER] SetOnce guard: all targets already populated, skipping"
+ );
continue;
}
}
@@ -229,8 +253,184 @@ fn generate_slot_scheduler_task() -> TokenStream {
"SlotScheduler: tick panicked, continuing"
);
}
+ }
+ });
+ }
+ }
+}
+
+/// Generate the `tokio::spawn` block for the gRPC slot subscription.
+///
+/// Opens a dedicated gRPC connection to stream slot updates, updating the
+/// `SlotTracker` on each new slot. This drives the scheduler to fire callbacks
+/// immediately when the target slot arrives, rather than waiting for the next
+/// account/instruction event.
+fn generate_slot_subscription_task() -> TokenStream {
+ quote! {
+ // Helper function to parse SlotHashes sysvar data
+ fn parse_and_cache_slot_hashes(current_slot: u64, data: &[u8]) -> Result<(), Box> {
+ if data.len() < 8 {
+ return Err("Data too short".into());
+ }
+
+ let len = u64::from_le_bytes([
+ data[0], data[1], data[2], data[3],
+ data[4], data[5], data[6], data[7],
+ ]) as usize;
+
+ let entry_size: usize = 40;
+ let expected_size = 8_usize
+ .checked_add(len.checked_mul(entry_size).ok_or("len * entry_size overflow")?)
+ .ok_or("expected_size overflow")?;
+
+ if data.len() < expected_size {
+ return Err(format!("Data too short: expected {}, got {}", expected_size, data.len()).into());
+ }
+
+ for i in 0..len {
+ let offset = 8 + (i * entry_size);
+ let slot = u64::from_le_bytes([
+ data[offset], data[offset + 1], data[offset + 2], data[offset + 3],
+ data[offset + 4], data[offset + 5], data[offset + 6], data[offset + 7],
+ ]);
+ let hash_bytes = &data[offset + 8..offset + 40];
+ let hash = hyperstack::runtime::bs58::encode(hash_bytes).into_string();
+ hyperstack::runtime::hyperstack_interpreter::record_slot_hash(slot, hash);
+ hyperstack::runtime::tracing::debug!(slot = slot, current_slot = current_slot, "[SLOT_SUB] Cached slot hash");
+ }
+ Ok(())
+ }
+
+ {
+ let slot_tracker = slot_tracker.clone();
+ let endpoint = endpoint.clone();
+ let x_token = x_token.clone();
+
+ hyperstack::runtime::tokio::spawn(async move {
+ hyperstack::runtime::tracing::info!("[SLOT_SUB] Starting dedicated gRPC slot subscription");
+
+ loop {
+ let result: Result<(), Box> = async {
+ use hyperstack::runtime::yellowstone_grpc_proto::geyser::{
+ SubscribeRequest, SubscribeRequestFilterSlots, SubscribeRequestFilterAccounts,
+ subscribe_update::UpdateOneof,
+ };
+ use hyperstack::runtime::futures::StreamExt;
+
+ let mut builder = hyperstack::runtime::yellowstone_grpc_client::GeyserGrpcClient
+ ::build_from_shared(endpoint.clone())?
+ .x_token(x_token.clone())?
+ .max_decoding_message_size(usize::MAX)
+ .accept_compressed(
+ hyperstack::runtime::yellowstone_grpc_proto::tonic::codec::CompressionEncoding::Zstd
+ )
+ .connect_timeout(std::time::Duration::from_secs(30))
+ .timeout(std::time::Duration::from_secs(60));
+
+ if endpoint.starts_with("https://") || endpoint.starts_with("grpcs://") {
+ builder = builder.tls_config(
+ hyperstack::runtime::yellowstone_grpc_proto::tonic::transport::ClientTlsConfig::new()
+ .with_native_roots()
+ )?;
+ }
+
+ let mut client = builder.connect().await?;
+
+ // Solana SlotHashes sysvar address
+ let slot_hashes_sysvar = "SysvarS1otHashes111111111111111111111111111".to_string();
+
+ let subscribe_request = SubscribeRequest {
+ slots: std::collections::HashMap::from([(
+ "slot_sub".to_string(),
+ SubscribeRequestFilterSlots {
+ filter_by_commitment: Some(true),
+ interslot_updates: None,
+ },
+ )]),
+ // Subscribe to SlotHashes sysvar to capture slot hashes
+ accounts: std::collections::HashMap::from([(
+ "slot_hashes_sysvar".to_string(),
+ SubscribeRequestFilterAccounts {
+ account: vec![slot_hashes_sysvar.clone()],
+ owner: vec![],
+ filters: vec![],
+ nonempty_txn_signature: None,
+ },
+ )]),
+ transactions: std::collections::HashMap::new(),
+ transactions_status: std::collections::HashMap::new(),
+ blocks: std::collections::HashMap::new(),
+ blocks_meta: std::collections::HashMap::new(),
+ entry: std::collections::HashMap::new(),
+ commitment: Some(
+ hyperstack::runtime::yellowstone_grpc_proto::geyser::CommitmentLevel::Processed as i32
+ ),
+ accounts_data_slice: vec![],
+ ping: None,
+ from_slot: None,
+ };
+
+ let (sub_tx, mut stream) = client
+ .subscribe_with_request(Some(subscribe_request))
+ .await?;
+ // Keep sender alive for the duration of the stream
+ let _keep_alive = sub_tx;
+
+ hyperstack::runtime::tracing::info!("[SLOT_SUB] Connected and subscribed to slot and SlotHashes updates");
+
+ while let Some(msg) = stream.next().await {
+ match msg {
+ Ok(update) => {
+ match update.update_oneof {
+ Some(UpdateOneof::Slot(slot_update)) => {
+ slot_tracker.record(slot_update.slot);
+ }
+ Some(UpdateOneof::Account(account_update)) => {
+ // Process SlotHashes sysvar update
+ if let Some(account) = account_update.account {
+ if hyperstack::runtime::bs58::encode(&account.pubkey).into_string() == slot_hashes_sysvar {
+ hyperstack::runtime::tracing::debug!(
+ slot = account_update.slot,
+ "[SLOT_SUB] Received SlotHashes sysvar update"
+ );
+ // Parse slot hashes from account data
+ // The SlotHashes sysvar contains a vector of (slot, hash) pairs
+ if let Err(e) = parse_and_cache_slot_hashes(
+ account_update.slot,
+ &account.data,
+ ) {
+ hyperstack::runtime::tracing::warn!(
+ error = %e,
+ "[SLOT_SUB] Failed to parse SlotHashes"
+ );
+ }
+ }
+ }
+ }
+ _ => {}
+ }
+ }
+ Err(e) => {
+ hyperstack::runtime::tracing::warn!(
+ error = %e,
+ "[SLOT_SUB] Stream error, will reconnect"
+ );
+ break;
+ }
+ }
+ }
+
+ Ok(())
+ }.await;
+
+ if let Err(e) = result {
+ hyperstack::runtime::tracing::warn!(
+ error = %e,
+ "[SLOT_SUB] Connection failed, reconnecting in 2s"
+ );
+ }
- hyperstack::runtime::tokio::time::sleep(std::time::Duration::from_millis(400)).await;
+ hyperstack::runtime::tokio::time::sleep(std::time::Duration::from_secs(2)).await;
}
});
}
@@ -714,6 +914,13 @@ pub fn generate_vm_handler(
match resolver_result {
hyperstack::runtime::hyperstack_interpreter::resolvers::KeyResolution::Found(resolved_key) => {
+ hyperstack::runtime::tracing::info!(
+ event_type = %event_type,
+ account = %account_address,
+ resolved_key = %resolved_key,
+ slot = slot,
+ "[PDA] Account key resolution: Found"
+ );
if !resolved_key.is_empty() {
if let Some(obj) = event_value.as_object_mut() {
obj.insert("__resolved_primary_key".to_string(), hyperstack::runtime::serde_json::json!(resolved_key));
@@ -722,7 +929,7 @@ pub fn generate_vm_handler(
}
hyperstack::runtime::hyperstack_interpreter::resolvers::KeyResolution::QueueUntil(_discriminators) => {
let mut vm = self.vm.lock().unwrap_or_else(|e| e.into_inner());
- tracing::info!(
+ hyperstack::runtime::tracing::info!(
event_type = %event_type,
pda = %account_address,
slot = slot,
@@ -752,9 +959,43 @@ pub fn generate_vm_handler(
let context = hyperstack::runtime::hyperstack_interpreter::UpdateContext::new_account(slot, signature.clone(), write_version);
+ // Clone event data before process_event so we can cache it
+ // for reprocessing when a PDA mapping changes at round boundaries.
+ let event_value_for_cache = event_value.clone();
+
let result = vm.process_event(&self.bytecode, event_value, event_type, Some(&context), Some(&mut log))
.map_err(|e| e.to_string());
+ // Cache the last account data per PDA address. When a PDA
+ // mapping later changes (same PDA, different seed) the cached
+ // data is returned for reprocessing with the corrected mapping.
+ if result.is_ok() {
+ // Cache under every state_id that routes this event_type so that
+ // register_pda_reverse_lookup finds data for all participating entities.
+ let state_ids: std::collections::HashSet = self.bytecode.event_routing
+ .get(event_type)
+ .map(|entities| entities.iter()
+ .filter_map(|name| self.bytecode.entities.get(name).map(|eb| eb.state_id))
+ .collect())
+ .unwrap_or_default();
+ let pending = hyperstack::runtime::hyperstack_interpreter::PendingAccountUpdate {
+ account_type: event_type.to_string(),
+ pda_address: account_address.clone(),
+ account_data: event_value_for_cache,
+ slot,
+ write_version,
+ signature: signature.clone(),
+ queued_at: std::time::SystemTime::now()
+ .duration_since(std::time::UNIX_EPOCH)
+ .unwrap_or_default()
+ .as_secs() as i64,
+ is_stale_reprocess: false,
+ };
+ for state_id in state_ids {
+ vm.cache_last_account_data(state_id, &account_address, pending.clone());
+ }
+ }
+
let requests = if result.is_ok() {
vm.take_resolver_requests()
} else {
@@ -904,44 +1145,73 @@ pub fn generate_vm_handler(
// Process pending account updates from instruction hooks
if !pending_updates.is_empty() {
- tracing::info!(
+ hyperstack::runtime::tracing::info!(
count = pending_updates.len(),
event_type = %event_type,
- "Flushing pending account updates from instruction hooks"
+ "[PDA] Flushing pending account updates from instruction hooks"
);
for update in pending_updates {
- let resolved_key = vm.try_pda_reverse_lookup(0, "default_pda_lookup", &update.pda_address);
+ hyperstack::runtime::tracing::info!(
+ account_type = %update.account_type,
+ pda = %update.pda_address,
+ update_slot = update.slot,
+ current_instruction_slot = slot,
+ "[PDA] Reprocessing flushed update"
+ );
+ let resolved_key = vm.try_chained_pda_lookup(0, "default_pda_lookup", &update.pda_address);
let mut account_data = update.account_data;
- if let Some(key) = resolved_key {
+ if let Some(ref key) = resolved_key {
+ hyperstack::runtime::tracing::info!(
+ pda = %update.pda_address,
+ resolved_key = %key,
+ "[PDA] Chained PDA lookup resolved for reprocessed update"
+ );
if let Some(obj) = account_data.as_object_mut() {
obj.insert("__resolved_primary_key".to_string(), hyperstack::runtime::serde_json::json!(key));
}
+ } else {
+ hyperstack::runtime::tracing::warn!(
+ pda = %update.pda_address,
+ "[PDA] Chained PDA lookup returned None for reprocessed update"
+ );
}
- let update_context = hyperstack::runtime::hyperstack_interpreter::UpdateContext::new_account(
- update.slot,
- update.signature.clone(),
- update.write_version,
- );
+ let update_context = if update.is_stale_reprocess {
+ hyperstack::runtime::tracing::info!(
+ pda = %update.pda_address,
+ "[PDA] Using reprocessed context (empty sig, skip resolvers)"
+ );
+ hyperstack::runtime::hyperstack_interpreter::UpdateContext::new_reprocessed(
+ update.slot,
+ update.write_version,
+ )
+ } else {
+ hyperstack::runtime::hyperstack_interpreter::UpdateContext::new_account(
+ update.slot,
+ update.signature.clone(),
+ update.write_version,
+ )
+ };
match vm.process_event(&bytecode, account_data, &update.account_type, Some(&update_context), None) {
Ok(pending_mutations) => {
- tracing::info!(
+ hyperstack::runtime::tracing::info!(
account_type = %update.account_type,
pda = %update.pda_address,
mutations = pending_mutations.len(),
- "Reprocessed flushed account update"
+ is_stale = update.is_stale_reprocess,
+ "[PDA] Reprocessed flushed account update"
);
if let Ok(ref mut mutations) = result {
mutations.extend(pending_mutations);
}
}
Err(e) => {
- tracing::warn!(
+ hyperstack::runtime::tracing::warn!(
account_type = %update.account_type,
error = %e,
- "Failed to reprocess flushed account update"
+ "[PDA] Failed to reprocess flushed account update"
);
}
}
@@ -1063,6 +1333,7 @@ pub fn generate_spec_function(
};
let slot_scheduler_task = generate_slot_scheduler_task();
+ let slot_subscription_task = generate_slot_subscription_task();
quote! {
pub fn spec() -> hyperstack::runtime::hyperstack_server::Spec {
@@ -1143,6 +1414,9 @@ pub fn generate_spec_function(
// Spawn slot scheduler background task
#slot_scheduler_task
+ // Spawn dedicated gRPC slot subscription to drive the scheduler in real-time
+ #slot_subscription_task
+
loop {
let from_slot = {
let last = slot_tracker.get();
@@ -1714,6 +1988,13 @@ pub fn generate_account_handler_impl(
match resolver_result {
hyperstack::runtime::hyperstack_interpreter::resolvers::KeyResolution::Found(resolved_key) => {
+ hyperstack::runtime::tracing::info!(
+ event_type = %event_type,
+ account = %account_address,
+ resolved_key = %resolved_key,
+ slot = slot,
+ "[PDA] Account key resolution: Found"
+ );
if !resolved_key.is_empty() {
if let Some(obj) = event_value.as_object_mut() {
obj.insert("__resolved_primary_key".to_string(), hyperstack::runtime::serde_json::json!(resolved_key));
@@ -1745,9 +2026,38 @@ pub fn generate_account_handler_impl(
let context = hyperstack::runtime::hyperstack_interpreter::UpdateContext::new_account(slot, signature.clone(), write_version);
+ let event_value_for_cache = event_value.clone();
+
let result = vm.process_event(&self.bytecode, event_value, event_type, Some(&context), Some(&mut log))
.map_err(|e| e.to_string());
+ if result.is_ok() {
+ // Cache under every state_id that routes this event_type so that
+ // register_pda_reverse_lookup finds data for all participating entities.
+ let state_ids: std::collections::HashSet = self.bytecode.event_routing
+ .get(event_type)
+ .map(|entities| entities.iter()
+ .filter_map(|name| self.bytecode.entities.get(name).map(|eb| eb.state_id))
+ .collect())
+ .unwrap_or_default();
+ let pending = hyperstack::runtime::hyperstack_interpreter::PendingAccountUpdate {
+ account_type: event_type.to_string(),
+ pda_address: account_address.clone(),
+ account_data: event_value_for_cache,
+ slot,
+ write_version,
+ signature: signature.clone(),
+ queued_at: std::time::SystemTime::now()
+ .duration_since(std::time::UNIX_EPOCH)
+ .unwrap_or_default()
+ .as_secs() as i64,
+ is_stale_reprocess: false,
+ };
+ for state_id in state_ids {
+ vm.cache_last_account_data(state_id, &account_address, pending.clone());
+ }
+ }
+
let requests = if result.is_ok() {
vm.take_resolver_requests()
} else {
@@ -1900,24 +2210,64 @@ pub fn generate_instruction_handler_impl(
drop(ctx);
if !pending_updates.is_empty() {
+ hyperstack::runtime::tracing::info!(
+ count = pending_updates.len(),
+ event_type = %event_type,
+ "[PDA] Flushing pending account updates from instruction hooks"
+ );
for update in pending_updates {
- let resolved_key = vm.try_pda_reverse_lookup(0, "default_pda_lookup", &update.pda_address);
+ hyperstack::runtime::tracing::info!(
+ account_type = %update.account_type,
+ pda = %update.pda_address,
+ update_slot = update.slot,
+ current_instruction_slot = slot,
+ "[PDA] Reprocessing flushed update"
+ );
+ let resolved_key = vm.try_chained_pda_lookup(0, "default_pda_lookup", &update.pda_address);
let mut account_data = update.account_data;
- if let Some(key) = resolved_key {
+ if let Some(ref key) = resolved_key {
+ hyperstack::runtime::tracing::info!(
+ pda = %update.pda_address,
+ resolved_key = %key,
+ "[PDA] Chained PDA lookup resolved for reprocessed update"
+ );
if let Some(obj) = account_data.as_object_mut() {
obj.insert("__resolved_primary_key".to_string(), hyperstack::runtime::serde_json::json!(key));
}
+ } else {
+ hyperstack::runtime::tracing::warn!(
+ pda = %update.pda_address,
+ "[PDA] Chained PDA lookup returned None for reprocessed update"
+ );
}
- let update_context = hyperstack::runtime::hyperstack_interpreter::UpdateContext::new_account(
- update.slot,
- update.signature.clone(),
- update.write_version,
- );
+ let update_context = if update.is_stale_reprocess {
+ hyperstack::runtime::tracing::info!(
+ pda = %update.pda_address,
+ "[PDA] Using reprocessed context (empty sig, skip resolvers)"
+ );
+ hyperstack::runtime::hyperstack_interpreter::UpdateContext::new_reprocessed(
+ update.slot,
+ update.write_version,
+ )
+ } else {
+ hyperstack::runtime::hyperstack_interpreter::UpdateContext::new_account(
+ update.slot,
+ update.signature.clone(),
+ update.write_version,
+ )
+ };
match vm.process_event(&bytecode, account_data, &update.account_type, Some(&update_context), None) {
Ok(pending_mutations) => {
+ hyperstack::runtime::tracing::info!(
+ account_type = %update.account_type,
+ pda = %update.pda_address,
+ mutations = pending_mutations.len(),
+ is_stale = update.is_stale_reprocess,
+ "[PDA] Reprocessed flushed account update"
+ );
if let Ok(ref mut mutations) = result {
mutations.extend(pending_mutations);
}
@@ -1926,7 +2276,7 @@ pub fn generate_instruction_handler_impl(
hyperstack::runtime::tracing::warn!(
account_type = %update.account_type,
error = %e,
- "Flushed account reprocessing failed"
+ "[PDA] Flushed account reprocessing failed"
);
}
}
@@ -2103,6 +2453,7 @@ pub fn generate_multi_pipeline_spec_function(
}).collect();
let slot_scheduler_task = generate_slot_scheduler_task();
+ let slot_subscription_task = generate_slot_subscription_task();
quote! {
pub fn spec() -> hyperstack::runtime::hyperstack_server::Spec {
@@ -2182,6 +2533,9 @@ pub fn generate_multi_pipeline_spec_function(
// Spawn slot scheduler background task
#slot_scheduler_task
+ // Spawn dedicated gRPC slot subscription to drive the scheduler in real-time
+ #slot_subscription_task
+
loop {
let from_slot = {
let last = slot_tracker.get();
diff --git a/hyperstack-macros/src/idl_codegen.rs b/hyperstack-macros/src/idl_codegen.rs
index 1af60a39..96ec62fc 100644
--- a/hyperstack-macros/src/idl_codegen.rs
+++ b/hyperstack-macros/src/idl_codegen.rs
@@ -404,13 +404,13 @@ fn generate_account_type(
if use_bytemuck {
let bytemuck_try_from = quote! {
impl #name {
- pub const DISCRIMINATOR: [u8; 8] = #disc_array;
+ pub const DISCRIMINATOR: &'static [u8] = disc_array;
pub fn try_from_bytes(data: &[u8]) -> Result> {
- if data.len() < 8 {
+ if data.len() < Self::DISCRIMINATOR.len() {
return Err("Data too short for discriminator".into());
}
- let body = &data[8..];
+ let body = &data[Self::DISCRIMINATOR.len()..];
let struct_size = std::mem::size_of::();
if body.len() < struct_size {
return Err(format!(
@@ -478,13 +478,13 @@ fn generate_account_type(
}
impl #name {
- pub const DISCRIMINATOR: [u8; 8] = #disc_array;
+ pub const DISCRIMINATOR: &'static [u8] = disc_array;
pub fn try_from_bytes(data: &[u8]) -> Result> {
- if data.len() < 8 {
+ if data.len() < Self::DISCRIMINATOR.len() {
return Err("Data too short for discriminator".into());
}
- let mut reader = &data[8..];
+ let mut reader = &data[Self::DISCRIMINATOR.len()..];
borsh::BorshDeserialize::deserialize_reader(&mut reader)
.map_err(|e| e.into())
}
@@ -534,7 +534,7 @@ fn generate_instruction_type(
}
impl #name {
- pub const DISCRIMINATOR: [u8; 8] = #disc_array;
+ pub const DISCRIMINATOR: &'static [u8] = disc_array;
pub fn try_from_bytes(data: &[u8]) -> Result> {
let mut reader = data;
@@ -605,21 +605,21 @@ fn generate_event_type(
}
impl #name {
- pub const DISCRIMINATOR: [u8; 8] = #disc_array;
+ pub const DISCRIMINATOR: &'static [u8] = disc_array;
/// Decode a CPI event from raw instruction data.
- /// Anchor CPI events: 8-byte discriminator followed by Borsh-encoded payload.
+ /// Anchor CPI events: discriminator followed by Borsh-encoded payload.
pub fn try_from_bytes(data: &[u8]) -> Result> {
- if data.len() < 8 {
+ if data.len() < Self::DISCRIMINATOR.len() {
return Err("Data too short for event discriminator".into());
}
- if data[..8] != Self::DISCRIMINATOR {
+ if &data[..Self::DISCRIMINATOR.len()] != Self::DISCRIMINATOR {
return Err(format!(
"Discriminator mismatch: expected {:?}, got {:?}",
- Self::DISCRIMINATOR, &data[..8]
+ Self::DISCRIMINATOR, &data[..Self::DISCRIMINATOR.len()]
).into());
}
- let mut reader = &data[8..];
+ let mut reader = &data[Self::DISCRIMINATOR.len()..];
borsh::BorshDeserialize::deserialize_reader(&mut reader).map_err(|e| e.into())
}
diff --git a/hyperstack-macros/src/stream_spec/ast_writer.rs b/hyperstack-macros/src/stream_spec/ast_writer.rs
index adbb5f00..eb50026c 100644
--- a/hyperstack-macros/src/stream_spec/ast_writer.rs
+++ b/hyperstack-macros/src/stream_spec/ast_writer.rs
@@ -13,8 +13,8 @@ use crate::ast::writer::{
convert_idl_to_snapshot, parse_population_strategy, parse_transformation,
};
use crate::ast::{
- ComparisonOp, ComputedFieldSpec, ConditionExpr, EntitySection, FieldPath, HookAction,
- IdentitySpec, IdlSerializationSnapshot, InstructionHook, KeyResolutionStrategy,
+ ComparisonOp, ComputedFieldSpec, ConditionExpr, EntitySection, FieldPath, FieldTypeInfo,
+ HookAction, IdentitySpec, IdlSerializationSnapshot, InstructionHook, KeyResolutionStrategy,
LookupIndexSpec, MappingSource, ResolveStrategy, ResolverCondition, ResolverExtractSpec,
ResolverHook, ResolverSpec, ResolverStrategy, ResolverType, SerializableFieldMapping,
SerializableHandlerSpec, SerializableStreamSpec, SourceSpec,
@@ -25,7 +25,10 @@ use crate::parse::conditions as condition_parser;
use crate::parse::idl as idl_parser;
use crate::utils::path_to_string;
-use super::computed::{parse_computed_expression, qualify_field_refs};
+use super::computed::{
+ expr_contains_u64_from_bytes, extract_resolver_type_from_computed_expr,
+ parse_computed_expression, qualify_field_refs,
+};
use super::handlers::{find_field_in_instruction, get_join_on_field};
// ============================================================================
@@ -149,6 +152,54 @@ pub fn build_ast(
}
}
+ // Add computed fields to field_mappings with resolver type information
+ // This ensures computed fields that use resolvers get proper TypeScript schema generation
+ for computed_spec in &computed_field_specs {
+ // Determine the TypeScript type override for this computed field.
+ // Priority 1: explicit resolver method (e.g. .keccak_rng(...)) → its declared output type.
+ // Priority 2: expression assembles a u64 from raw bytes → "KeccakRngValue" (string),
+ // because values span [0, 2^64-1] and exceed Number.MAX_SAFE_INTEGER.
+ let resolver_type: Option<&'static str> =
+ extract_resolver_type_from_computed_expr(&computed_spec.expression).or_else(|| {
+ let result_type = &computed_spec.result_type;
+ let is_u64 = result_type == "u64"
+ || result_type == "Option < u64 >"
+ || result_type == "Option";
+ if is_u64 && expr_contains_u64_from_bytes(&computed_spec.expression) {
+ Some("KeccakRngValue")
+ } else {
+ None
+ }
+ });
+
+ if let Some(resolver_type) = resolver_type {
+ // Parse the result type to determine if it's optional and if it's an array
+ let result_type = &computed_spec.result_type;
+ let is_optional =
+ result_type.starts_with("Option <") || result_type.starts_with("Option<");
+ let is_array = result_type.contains("Vec <")
+ || result_type.contains("Vec<")
+ || result_type.contains("[");
+
+ let field_info = FieldTypeInfo {
+ field_name: computed_spec.target_path.clone(),
+ rust_type_name: computed_spec.result_type.clone(),
+ base_type: if is_array {
+ crate::ast::BaseType::Array
+ } else {
+ crate::ast::BaseType::Any
+ },
+ is_optional,
+ is_array,
+ inner_type: Some(resolver_type.to_string()),
+ source_path: None,
+ resolved_type: None,
+ emit: true,
+ };
+ field_mappings.insert(computed_spec.target_path.clone(), field_info);
+ }
+ }
+
let mut spec = SerializableStreamSpec {
state_name: entity_name.to_string(),
program_id,
@@ -714,6 +765,7 @@ fn build_source_handler(
discriminator: None,
type_name,
serialization,
+ is_account: !is_instruction && !is_cpi_event,
},
key_resolution,
mappings: serializable_mappings,
@@ -938,6 +990,7 @@ fn build_event_handler(
discriminator: None,
type_name,
serialization: None,
+ is_account: false,
},
key_resolution,
mappings: serializable_mappings,
diff --git a/hyperstack-macros/src/stream_spec/computed.rs b/hyperstack-macros/src/stream_spec/computed.rs
index 542eac92..564ea089 100644
--- a/hyperstack-macros/src/stream_spec/computed.rs
+++ b/hyperstack-macros/src/stream_spec/computed.rs
@@ -34,6 +34,74 @@ pub fn parse_computed_expression(tokens: &proc_macro2::TokenStream) -> ComputedE
fn resolver_for_method(method: &str) -> Option<&'static str> {
match method {
"ui_amount" | "raw_amount" => Some("TokenMetadata"),
+ "slot_hash" | "keccak_rng" => Some("SlotHash"),
+ _ => None,
+ }
+}
+
+/// Get the output type name for a resolver method.
+/// This maps resolver method names to their TypeScript output type names.
+pub fn resolver_output_type(method: &str) -> Option<&'static str> {
+ match method {
+ "slot_hash" => Some("SlotHashBytes"),
+ "keccak_rng" => Some("KeccakRngValue"),
+ "ui_amount" => Some("TokenUiAmount"),
+ "raw_amount" => Some("TokenRawAmount"),
+ _ => None,
+ }
+}
+
+/// Returns true if the expression tree contains any U64FromLeBytes or U64FromBeBytes node.
+/// Used to detect full-range u64 computations that must be serialized as strings in TypeScript.
+pub fn expr_contains_u64_from_bytes(expr: &crate::ast::ComputedExpr) -> bool {
+ use crate::ast::ComputedExpr;
+ match expr {
+ ComputedExpr::U64FromLeBytes { .. } | ComputedExpr::U64FromBeBytes { .. } => true,
+ ComputedExpr::Some { value } => expr_contains_u64_from_bytes(value),
+ ComputedExpr::Paren { expr } => expr_contains_u64_from_bytes(expr),
+ ComputedExpr::Binary { left, right, .. } => {
+ expr_contains_u64_from_bytes(left) || expr_contains_u64_from_bytes(right)
+ }
+ ComputedExpr::Unary { expr, .. } => expr_contains_u64_from_bytes(expr),
+ ComputedExpr::MethodCall { expr, args, .. } => {
+ expr_contains_u64_from_bytes(expr) || args.iter().any(expr_contains_u64_from_bytes)
+ }
+ ComputedExpr::Cast { expr, .. } => expr_contains_u64_from_bytes(expr),
+ ComputedExpr::UnwrapOr { expr, .. } => expr_contains_u64_from_bytes(expr),
+ ComputedExpr::Slice { expr, .. } => expr_contains_u64_from_bytes(expr),
+ ComputedExpr::Index { expr, .. } => expr_contains_u64_from_bytes(expr),
+ ComputedExpr::Let { value, body, .. } => {
+ expr_contains_u64_from_bytes(value) || expr_contains_u64_from_bytes(body)
+ }
+ ComputedExpr::If {
+ condition: _,
+ then_branch,
+ else_branch,
+ } => expr_contains_u64_from_bytes(then_branch) || expr_contains_u64_from_bytes(else_branch),
+ ComputedExpr::Keccak256 { expr } => expr_contains_u64_from_bytes(expr),
+ ComputedExpr::JsonToBytes { expr } => expr_contains_u64_from_bytes(expr),
+ ComputedExpr::Closure { body, .. } => expr_contains_u64_from_bytes(body),
+ ComputedExpr::ResolverComputed { .. }
+ | ComputedExpr::FieldRef { .. }
+ | ComputedExpr::Var { .. }
+ | ComputedExpr::Literal { .. }
+ | ComputedExpr::ByteArray { .. }
+ | ComputedExpr::None
+ | ComputedExpr::ContextSlot
+ | ComputedExpr::ContextTimestamp => false,
+ }
+}
+
+/// Extract the resolver output type from a computed expression.
+/// Returns the type name if the expression is a ResolverComputed call.
+pub fn extract_resolver_type_from_computed_expr(
+ expr: &crate::ast::ComputedExpr,
+) -> Option<&'static str> {
+ use crate::ast::ComputedExpr;
+ match expr {
+ ComputedExpr::ResolverComputed { method, .. } => resolver_output_type(method),
+ ComputedExpr::Some { value } => extract_resolver_type_from_computed_expr(value),
+ ComputedExpr::Paren { expr } => extract_resolver_type_from_computed_expr(expr),
_ => None,
}
}
@@ -141,6 +209,9 @@ pub fn qualify_field_refs(expr: ComputedExpr, section: &str) -> ComputedExpr {
},
ComputedExpr::ContextSlot => ComputedExpr::ContextSlot,
ComputedExpr::ContextTimestamp => ComputedExpr::ContextTimestamp,
+ ComputedExpr::Keccak256 { expr } => ComputedExpr::Keccak256 {
+ expr: Box::new(qualify_field_refs(*expr, section)),
+ },
}
}
@@ -380,6 +451,9 @@ fn resolve_bindings_in_expr(expr: ComputedExpr, bindings: &HashSet) -> C
ComputedExpr::JsonToBytes { expr } => ComputedExpr::JsonToBytes {
expr: Box::new(resolve_bindings_in_expr(*expr, bindings)),
},
+ ComputedExpr::Keccak256 { expr } => ComputedExpr::Keccak256 {
+ expr: Box::new(resolve_bindings_in_expr(*expr, bindings)),
+ },
ComputedExpr::Closure { param, body } => {
// The closure param is also a binding
let mut new_bindings = bindings.clone();
diff --git a/hyperstack-macros/src/stream_spec/entity.rs b/hyperstack-macros/src/stream_spec/entity.rs
index b43bf5d0..80da9d67 100644
--- a/hyperstack-macros/src/stream_spec/entity.rs
+++ b/hyperstack-macros/src/stream_spec/entity.rs
@@ -1005,7 +1005,13 @@ fn generate_computed_fields_hook(
// Get dependencies for this section
let deps = section_dependencies.get(section).cloned().unwrap_or_default();
- let _section_str = section.as_str();
+ let section_str = section.as_str();
+
+ // Collect all computed field names in this section for cache tracking
+ let computed_field_names: Vec = fields.iter().map(|(field_name, _expression, _field_type)| {
+ field_name.clone()
+ }).collect();
+
let field_evaluations: Vec<_> = fields.iter().map(|(field_name, expression, field_type)| {
let field_str = field_name.as_str();
let field_ident = format_ident!("{}", field_name);
@@ -1016,16 +1022,19 @@ fn generate_computed_fields_hook(
let parsed_expr = parse_computed_expression(expression);
// Qualify the expression with the section prefix for unqualified field refs
let qualified_expr = qualify_field_refs(parsed_expr, section);
- let expr_code = crate::codegen::generate_computed_expr_code(&qualified_expr);
+ // Use cache-aware code generation for intra-section dependencies
+ let expr_code = crate::codegen::generate_computed_expr_code_with_cache(&qualified_expr, section_str, &computed_field_names);
quote! {
// Evaluate: #field_name
let computed_value = {
- // state is the full entity JSON state
+ // state is the full entity JSON state (for cross-section references)
let state = §ion_parent_state;
#expr_code
};
let serialized_value = hyperstack::runtime::serde_json::to_value(&computed_value)?;
+ // Update cache so dependent fields can read this value
+ computed_cache.insert(#field_str.to_string(), serialized_value.clone());
section_obj.insert(#field_str.to_string(), serialized_value);
let #field_ident: #field_type = section_obj
@@ -1076,7 +1085,13 @@ fn generate_computed_fields_hook(
extract_field!(whale_trade_count, u64);
extract_field!(average_trade_size, f64);
- // Evaluate computed fields
+ // Initialize cache with current section values for intra-section computed field dependencies
+ let mut computed_cache: std::collections::HashMap = std::collections::HashMap::new();
+ for (key, value) in section_obj.iter() {
+ computed_cache.insert(key.clone(), value.clone());
+ }
+
+ // Evaluate computed fields (they read from cache for intra-section dependencies)
#(#field_evaluations)*
Ok(())
@@ -1095,7 +1110,8 @@ fn generate_computed_fields_hook(
// Generate pre-extraction of cross-section data
// These return Option so we can gracefully skip evaluation if a dependency doesn't exist yet
let dep_extractions: Vec<_> = deps.iter().map(|dep_section| {
- let dep_section_ident = format_ident!("{}", dep_section);
+ // Use a unique variable name to avoid shadowing issues
+ let dep_section_ident = format_ident!("{}_section", dep_section);
let dep_section_str = dep_section.as_str();
let section_struct_ident = format_ident!("{}Section", dep_section);
quote! {
@@ -1119,13 +1135,14 @@ fn generate_computed_fields_hook(
} else {
// Has cross-section dependencies - extract first, then compute
// If ANY dependency is missing, skip evaluation (the computed fields will remain None)
- let dep_param_names: Vec<_> = deps.iter().map(|dep| format_ident!("{}", dep)).collect();
+ let dep_param_names: Vec<_> = deps.iter().map(|dep| format_ident!("{}_section", dep)).collect();
let dep_checks: Vec<_> = deps.iter().map(|dep| {
- let dep_ident = format_ident!("{}", dep);
+ let dep_ident = format_ident!("{}_section", dep);
quote! { #dep_ident.is_some() }
}).collect();
let dep_unwraps: Vec<_> = deps.iter().map(|dep| {
- let dep_ident = format_ident!("{}", dep);
+ // Use consistent variable naming
+ let dep_ident = format_ident!("{}_section", dep);
quote! { let #dep_ident = #dep_ident.unwrap(); }
}).collect();
quote! {
diff --git a/hyperstack-macros/src/stream_spec/proto_struct.rs b/hyperstack-macros/src/stream_spec/proto_struct.rs
index 3869fe40..c1353282 100644
--- a/hyperstack-macros/src/stream_spec/proto_struct.rs
+++ b/hyperstack-macros/src/stream_spec/proto_struct.rs
@@ -368,6 +368,7 @@ pub fn process_struct_with_context(
};
let type_suffix = if is_instruction { "IxState" } else { "State" };
+ let is_account_source = !is_instruction;
handler_fns.push(quote! {
fn #handler_name() -> hyperstack::runtime::hyperstack_interpreter::ast::TypedHandlerSpec<#state_name> {
hyperstack::runtime::hyperstack_interpreter::ast::TypedHandlerSpec::new(
@@ -376,6 +377,7 @@ pub fn process_struct_with_context(
discriminator: None,
type_name: format!("{}{}", #account_type, #type_suffix),
serialization: None,
+ is_account: #is_account_source,
},
#key_resolution,
vec![
diff --git a/hyperstack-macros/src/stream_spec/sections.rs b/hyperstack-macros/src/stream_spec/sections.rs
index 45dec2d0..96cde9ca 100644
--- a/hyperstack-macros/src/stream_spec/sections.rs
+++ b/hyperstack-macros/src/stream_spec/sections.rs
@@ -632,7 +632,7 @@ pub fn process_nested_struct(
}
});
- let resolver = if let Some(ref _url_path) = qualified_url {
+ let resolver = if let Some(ref url_path) = qualified_url {
let method = resolve_attr
.method
.as_deref()
@@ -644,16 +644,10 @@ pub fn process_nested_struct(
let url_source = if resolve_attr.url_is_template {
crate::ast::UrlSource::Template(super::entity::parse_url_template(
- resolve_attr.url.as_deref().unwrap(),
+ url_path,
))
} else {
- let url_path_raw = resolve_attr.url.as_deref().unwrap();
- let qualified = if url_path_raw.contains('.') {
- url_path_raw.to_string()
- } else {
- format!("{}.{}", section_name, url_path_raw)
- };
- crate::ast::UrlSource::FieldPath(qualified)
+ crate::ast::UrlSource::FieldPath(url_path.clone())
};
crate::ast::ResolverType::Url(crate::ast::UrlResolverConfig {
@@ -677,14 +671,7 @@ pub fn process_nested_struct(
let from = if resolve_attr.url_is_template {
None
} else {
- let qualified_url = resolve_attr.url.as_deref().map(|url_path_raw| {
- if url_path_raw.contains('.') {
- url_path_raw.to_string()
- } else {
- format!("{}.{}", section_name, url_path_raw)
- }
- });
- qualified_url.or(resolve_attr.from)
+ qualified_url.or(resolve_attr.from.clone())
};
resolve_specs.push(parse::ResolveSpec {
diff --git a/hyperstack/Cargo.toml b/hyperstack/Cargo.toml
index cd86185f..b3fbfb6a 100644
--- a/hyperstack/Cargo.toml
+++ b/hyperstack/Cargo.toml
@@ -37,8 +37,11 @@ bytemuck = { version = "1.21", features = ["derive", "min_const_generics"], opti
yellowstone-vixen = { workspace = true, optional = true }
yellowstone-vixen-core = { workspace = true, optional = true }
yellowstone-vixen-yellowstone-grpc-source = { workspace = true, optional = true }
+yellowstone-grpc-client = { workspace = true, optional = true }
+yellowstone-grpc-proto = { workspace = true, optional = true }
reqwest = { version = "0.11", default-features = false, features = ["json", "rustls-tls"], optional = true }
futures = { version = "0.3", optional = true }
+sha3 = { version = "0.10", optional = true }
[features]
default = ["interpreter", "macros", "server"]
@@ -60,6 +63,9 @@ runtime = [
"dep:yellowstone-vixen",
"dep:yellowstone-vixen-core",
"dep:yellowstone-vixen-yellowstone-grpc-source",
+ "dep:yellowstone-grpc-client",
+ "dep:yellowstone-grpc-proto",
"dep:reqwest",
"dep:futures",
+ "dep:sha3",
]
diff --git a/hyperstack/src/lib.rs b/hyperstack/src/lib.rs
index 24d69802..97e6be94 100644
--- a/hyperstack/src/lib.rs
+++ b/hyperstack/src/lib.rs
@@ -69,9 +69,12 @@ pub mod runtime {
pub use reqwest;
pub use serde;
pub use serde_json;
+ pub use sha3;
pub use smallvec;
pub use tokio;
pub use tracing;
+ pub use yellowstone_grpc_client;
+ pub use yellowstone_grpc_proto;
pub use yellowstone_vixen;
pub use yellowstone_vixen_core;
pub use yellowstone_vixen_yellowstone_grpc_source;
diff --git a/interpreter/Cargo.toml b/interpreter/Cargo.toml
index 60dbaaf5..d86f258d 100644
--- a/interpreter/Cargo.toml
+++ b/interpreter/Cargo.toml
@@ -24,7 +24,10 @@ hex = "0.4"
bs58 = "0.5"
lru = "0.12"
sha2 = "0.10"
+sha3 = "0.10"
tracing = "0.1"
+tokio = { version = "1.0", features = ["sync", "rt-multi-thread"] }
+once_cell = "1.20"
percent-encoding = "2"
reqwest = { version = "0.12", default-features = false, features = ["json", "rustls-tls"] }
futures = "0.3"
diff --git a/interpreter/src/ast.rs b/interpreter/src/ast.rs
index bf50da0e..74e1293e 100644
--- a/interpreter/src/ast.rs
+++ b/interpreter/src/ast.rs
@@ -332,6 +332,12 @@ pub enum ComputedExpr {
ContextSlot,
/// Access the unix timestamp from the current update context
ContextTimestamp,
+
+ /// Keccak256 hash function for computing Ethereum-compatible hashes
+ /// Takes a byte array expression and returns the 32-byte hash as a Vec
+ Keccak256 {
+ expr: Box,
+ },
}
/// Binary operators for computed expressions
@@ -733,6 +739,12 @@ pub enum SourceSpec {
type_name: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
serialization: Option,
+ /// True when this handler listens to an account-state event (not an
+ /// instruction or custom event). Set at code-generation time from
+ /// the structural source kind so the compiler does not need to rely
+ /// on naming-convention heuristics.
+ #[serde(default)]
+ is_account: bool,
},
}
diff --git a/interpreter/src/compiler.rs b/interpreter/src/compiler.rs
index 65dc1a4e..7816d91a 100644
--- a/interpreter/src/compiler.rs
+++ b/interpreter/src/compiler.rs
@@ -11,6 +11,16 @@ fn stop_field_path(target_path: &str) -> String {
#[derive(Debug, Clone)]
pub enum OpCode {
+ /// Abort the handler with empty mutations when the key register is null
+ /// and the event is an account-state update (not IxState / CpiEvent).
+ /// Placed immediately after key resolution so that downstream opcodes
+ /// (index updates, field mappings, resolvers, emit) never execute with
+ /// a garbage key. The null-key event is then eligible for queueing by
+ /// process_event's miss-handling logic.
+ AbortIfNullKey {
+ key: Register,
+ is_account_event: bool,
+ },
LoadEventField {
path: FieldPath,
dest: Register,
@@ -664,6 +674,23 @@ impl TypedCompiler {
ops.extend(self.compile_key_loading(&spec.key_resolution, key_reg, &spec.mappings));
+ // Guard: if key resolved to null on an account-state event, abort
+ // early with empty mutations so process_event can queue the update
+ // for later reprocessing. Without this, downstream opcodes would
+ // create a phantom entity keyed by null and produce non-empty
+ // mutations that prevent queueing.
+ let is_account_event = matches!(
+ spec.source,
+ SourceSpec::Source {
+ is_account: true,
+ ..
+ }
+ );
+ ops.push(OpCode::AbortIfNullKey {
+ key: key_reg,
+ is_account_event,
+ });
+
ops.push(OpCode::ReadOrInitState {
state_id: self.state_id,
key: key_reg,
@@ -1196,7 +1223,11 @@ impl TypedCompiler {
let lookup_reg = 15;
let result_reg = 17;
- // Prefer resolver-provided key as lookup input
+ // Prefer resolver-provided key as lookup input.
+ // When __resolved_primary_key is set (e.g. round_address from
+ // PDA reverse lookup), use it directly — this gives a one-hop
+ // lookup (round_address → round_id) instead of a two-hop chain
+ // (Var address → PDA → round_address → round_id).
ops.push(OpCode::CopyRegister {
source: resolved_key_reg,
dest: lookup_reg,
@@ -1223,6 +1254,16 @@ impl TypedCompiler {
lookup_value: lookup_reg,
dest: result_reg,
});
+ // CRITICAL: For Lookup resolution, we ONLY use the lookup result.
+ // If the lookup fails (result_reg is null), the mutation will be skipped.
+ // We do NOT fall back to __resolved_primary_key or the raw lookup value,
+ // because that would create a separate entity with the wrong key.
+ // The resolver-provided key (e.g., PDA address) is only used as the lookup input,
+ // NOT as the entity key. The entity key must come from the lookup index.
+ ops.push(OpCode::CopyRegister {
+ source: result_reg,
+ dest: key_reg,
+ });
// NOTE: We intentionally do NOT fall back to lookup_reg when LookupIndex returns null.
// If the lookup fails (because the RoundState account hasn't been processed yet),
// the result_reg will remain null, and the mutation will be skipped.
@@ -1230,18 +1271,14 @@ impl TypedCompiler {
// which caused the PDA address to be used as the key instead of the round_id.
// This resulted in mutations with key = PDA address instead of key = primary_key.
- // First, set key_reg to __resolved_primary_key (may be null).
- // When the flush path provides a resolved key via PDA reverse lookup,
- // this gives it priority over the LookupIndex result.
- // This matches the pattern used by Embedded and Computed strategies.
+ // Use LookupIndex result as the primary key. Do NOT fall back to
+ // resolved_key_reg (__resolved_primary_key) because for Lookup handlers
+ // it contains the PDA reverse-lookup result (e.g. round_address), which
+ // is an intermediate value, not the actual primary key (e.g. round_id).
+ // If the LookupIndex chain returns null (round not yet indexed), key
+ // stays null so the update is queued and reprocessed once the lookup
+ // index is populated—matching the pre-23503ac behaviour.
ops.push(OpCode::CopyRegister {
- source: resolved_key_reg,
- dest: key_reg,
- });
- // If key_reg is still null (no resolved key from flush), use the LookupIndex result.
- // This preserves the original behavior for first-arrival events where
- // __resolved_primary_key is not yet set.
- ops.push(OpCode::CopyRegisterIfNull {
source: result_reg,
dest: key_reg,
});
diff --git a/interpreter/src/lib.rs b/interpreter/src/lib.rs
index ca20233c..a29cfec3 100644
--- a/interpreter/src/lib.rs
+++ b/interpreter/src/lib.rs
@@ -33,11 +33,15 @@ pub mod proto_router;
pub mod resolvers;
pub mod rust;
pub mod scheduler;
+pub mod slot_hash_cache;
pub mod spec_trait;
pub mod typescript;
pub mod vm;
pub mod vm_metrics;
+// Re-export slot hash cache functions
+pub use slot_hash_cache::{get_slot_hash, record_slot_hash};
+
pub use canonical_log::{CanonicalLog, LogLevel};
pub use metrics_context::{FieldAccessor, FieldRef, MetricsContext};
pub use resolvers::{
diff --git a/interpreter/src/resolvers.rs b/interpreter/src/resolvers.rs
index b8226195..d3667bd3 100644
--- a/interpreter/src/resolvers.rs
+++ b/interpreter/src/resolvers.rs
@@ -1,4 +1,4 @@
-use std::collections::{HashMap, HashSet};
+use std::collections::{BTreeMap, HashMap, HashSet};
use std::sync::OnceLock;
use futures::future::join_all;
@@ -126,10 +126,13 @@ pub trait ResolverDefinition: Send + Sync {
fn typescript_schema(&self) -> Option {
None
}
+ fn extra_output_types(&self) -> &'static [&'static str] {
+ &[]
+ }
}
pub struct ResolverRegistry {
- resolvers: HashMap>,
+ resolvers: BTreeMap>,
}
impl Default for ResolverRegistry {
@@ -141,7 +144,7 @@ impl Default for ResolverRegistry {
impl ResolverRegistry {
pub fn new() -> Self {
Self {
- resolvers: HashMap::new(),
+ resolvers: BTreeMap::new(),
}
}
@@ -158,9 +161,10 @@ impl ResolverRegistry {
}
pub fn is_output_type(&self, type_name: &str) -> bool {
- self.resolvers
- .values()
- .any(|resolver| resolver.output_type() == type_name)
+ self.resolvers.values().any(|resolver| {
+ resolver.output_type() == type_name
+ || resolver.extra_output_types().contains(&type_name)
+ })
}
pub fn evaluate_computed(
@@ -252,9 +256,10 @@ impl ResolverRegistry {
| crate::ast::ComputedExpr::Some { value: expr }
| crate::ast::ComputedExpr::Slice { expr, .. }
| crate::ast::ComputedExpr::Index { expr, .. }
- | crate::ast::ComputedExpr::U64FromLeBytes { bytes: expr }
+ | crate::ast::ComputedExpr::U64FromLeBytes { bytes: expr }
| crate::ast::ComputedExpr::U64FromBeBytes { bytes: expr }
| crate::ast::ComputedExpr::JsonToBytes { expr }
+ | crate::ast::ComputedExpr::Keccak256 { expr }
| crate::ast::ComputedExpr::Unary { expr, .. } => {
self.validate_computed_expr(expr, errors);
}
@@ -291,6 +296,7 @@ impl ResolverRegistry {
static BUILTIN_RESOLVER_REGISTRY: OnceLock = OnceLock::new();
pub fn register_builtin_resolvers(registry: &mut ResolverRegistry) {
+ registry.register(Box::new(SlotHashResolver));
registry.register(Box::new(TokenMetadataResolver));
}
@@ -706,7 +712,9 @@ pub async fn resolve_url_batch(
match results.get(&entry.url) {
Some(resolved_value) => {
match vm.apply_resolver_result(bytecode, &entry.request.cache_key, resolved_value.clone()) {
- Ok(mut new_mutations) => mutations.append(&mut new_mutations),
+ Ok(mut new_mutations) => {
+ mutations.append(&mut new_mutations)
+ }
Err(err) => {
tracing::warn!(url = %entry.url, "Failed to apply URL resolver result: {}", err);
}
@@ -726,6 +734,177 @@ pub async fn resolve_url_batch(
mutations
}
+/// Resolver for looking up slot hashes by slot number
+/// Uses the global slot hash cache populated from gRPC stream
+struct SlotHashResolver;
+
+const SLOT_HASH_METHODS: &[ResolverComputedMethod] = &[
+ ResolverComputedMethod {
+ name: "slot_hash",
+ arg_count: 1,
+ },
+ ResolverComputedMethod {
+ name: "keccak_rng",
+ arg_count: 3,
+ },
+];
+
+impl SlotHashResolver {
+ /// Compute keccak256(slot_hash || seed || samples_le_bytes) and XOR-fold into a u64.
+ /// args[0] = slot_hash bytes (JSON array of 32 bytes)
+ /// args[1] = seed bytes (JSON array of 32 bytes)
+ /// args[2] = samples (u64 number)
+ fn evaluate_keccak_rng(args: &[Value]) -> Result> {
+ if args.len() != 3 {
+ return Ok(Value::Null);
+ }
+
+ let slot_hash = Self::json_array_to_bytes(&args[0], 32);
+ let seed = Self::json_array_to_bytes(&args[1], 32);
+ let samples = match &args[2] {
+ Value::Number(n) => n.as_u64(),
+ _ => None,
+ };
+
+ let (slot_hash, seed, samples) = match (slot_hash, seed, samples) {
+ (Some(s), Some(sd), Some(sm)) => (s, sd, sm),
+ _ => return Ok(Value::Null),
+ };
+
+ // Build input: slot_hash[32] || seed[32] || samples_le_bytes[8]
+ let mut input = Vec::with_capacity(72);
+ input.extend_from_slice(&slot_hash);
+ input.extend_from_slice(&seed);
+ input.extend_from_slice(&samples.to_le_bytes());
+
+ // keccak256
+ use sha3::{Digest, Keccak256};
+ let hash = Keccak256::digest(&input);
+
+ // XOR-fold four u64 chunks
+ let r1 = u64::from_le_bytes(hash[0..8].try_into()?);
+ let r2 = u64::from_le_bytes(hash[8..16].try_into()?);
+ let r3 = u64::from_le_bytes(hash[16..24].try_into()?);
+ let r4 = u64::from_le_bytes(hash[24..32].try_into()?);
+ let rng = r1 ^ r2 ^ r3 ^ r4;
+
+ Ok(Value::String(rng.to_string()))
+ }
+
+ /// Extract a byte array of expected length from a JSON array value.
+ fn json_array_to_bytes(value: &Value, expected_len: usize) -> Option> {
+ let arr = value.as_array()?;
+ let bytes: Vec = arr
+ .iter()
+ .filter_map(|v| v.as_u64().and_then(|n| u8::try_from(n).ok()))
+ .collect();
+ if bytes.len() == expected_len {
+ Some(bytes)
+ } else {
+ tracing::debug!(
+ got = bytes.len(),
+ expected = expected_len,
+ "json_array_to_bytes: length mismatch or out-of-range element"
+ );
+ None
+ }
+ }
+
+ fn evaluate_slot_hash(args: &[Value]) -> Result> {
+ if args.len() != 1 {
+ return Ok(Value::Null);
+ }
+
+ let slot = match &args[0] {
+ Value::Number(n) => n.as_u64().unwrap_or(0),
+ _ => return Ok(Value::Null),
+ };
+
+ if slot == 0 {
+ return Ok(Value::Null);
+ }
+
+ // Try to get the slot hash from the global cache
+ let slot_hash = crate::slot_hash_cache::get_slot_hash(slot);
+
+ match slot_hash {
+ Some(hash) => {
+ // Convert the base58 encoded slot hash to bytes
+ // The slot hash is a 32-byte value base58 encoded
+ match bs58::decode(&hash).into_vec() {
+ Ok(bytes) if bytes.len() == 32 => {
+ // Return as { bytes: [...] } to match the SlotHashBytes TypeScript interface
+ let json_bytes: Vec = bytes.into_iter().map(|b| Value::Number(b.into())).collect();
+ let mut obj = serde_json::Map::new();
+ obj.insert("bytes".to_string(), Value::Array(json_bytes));
+ Ok(Value::Object(obj))
+ }
+ _ => {
+ tracing::warn!(slot = slot, hash = hash, "Failed to decode slot hash");
+ Ok(Value::Null)
+ }
+ }
+ }
+ None => {
+ tracing::debug!(slot = slot, "Slot hash not found in cache");
+ Ok(Value::Null)
+ }
+ }
+ }
+}
+
+impl ResolverDefinition for SlotHashResolver {
+ fn name(&self) -> &'static str {
+ "SlotHash"
+ }
+
+ fn output_type(&self) -> &'static str {
+ "SlotHash"
+ }
+
+ fn computed_methods(&self) -> &'static [ResolverComputedMethod] {
+ SLOT_HASH_METHODS
+ }
+
+ fn evaluate_computed(
+ &self,
+ method: &str,
+ args: &[Value],
+ ) -> std::result::Result> {
+ match method {
+ "slot_hash" => Self::evaluate_slot_hash(args),
+ "keccak_rng" => Self::evaluate_keccak_rng(args),
+ _ => Err(format!("Unknown SlotHash method '{}'", method).into()),
+ }
+ }
+
+ fn typescript_interface(&self) -> Option<&'static str> {
+ Some(
+ r#"export interface SlotHashBytes {
+ /** 32-byte slot hash as array of numbers (0-255) */
+ bytes: number[];
+}
+
+export type KeccakRngValue = string;"#,
+ )
+ }
+
+ fn extra_output_types(&self) -> &'static [&'static str] {
+ &["SlotHashBytes", "KeccakRngValue"]
+ }
+
+ fn typescript_schema(&self) -> Option {
+ Some(ResolverTypeScriptSchema {
+ name: "SlotHashTypes",
+ definition: r#"export const SlotHashBytesSchema = z.object({
+ bytes: z.array(z.number().int().min(0).max(255)).length(32),
+});
+
+export const KeccakRngValueSchema = z.string();"#,
+ })
+ }
+}
+
struct TokenMetadataResolver;
const TOKEN_METADATA_METHODS: &[ResolverComputedMethod] = &[
diff --git a/interpreter/src/scheduler.rs b/interpreter/src/scheduler.rs
index 0f4e3957..9d286433 100644
--- a/interpreter/src/scheduler.rs
+++ b/interpreter/src/scheduler.rs
@@ -74,11 +74,17 @@ impl SlotScheduler {
fn dedup_key(cb: &ScheduledCallback) -> DedupKey {
let resolver_key = serde_json::to_string(&cb.resolver).unwrap_or_default();
- let condition_key = cb.condition.as_ref()
+ let condition_key = cb
+ .condition
+ .as_ref()
.map(|c| serde_json::to_string(c).unwrap_or_default())
.unwrap_or_default();
let pk_key = cb.primary_key.to_string();
- (cb.entity_name.clone(), pk_key, format!("{}:{}", resolver_key, condition_key))
+ (
+ cb.entity_name.clone(),
+ pk_key,
+ format!("{}:{}", resolver_key, condition_key),
+ )
}
}
@@ -92,7 +98,11 @@ pub fn evaluate_condition(condition: &ResolverCondition, state: &Value) -> bool
/// parameter positions. Query strings permit additional chars (`!`, `$`, `'`, `(`, `)`, `+`, etc.)
/// that will be over-encoded. This is safe for the current numeric/base58 use-cases but may need
/// a path-vs-query split if general-purpose URL templates are needed.
-const URL_SEGMENT_SET: &AsciiSet = &NON_ALPHANUMERIC.remove(b'-').remove(b'.').remove(b'_').remove(b'~');
+const URL_SEGMENT_SET: &AsciiSet = &NON_ALPHANUMERIC
+ .remove(b'-')
+ .remove(b'.')
+ .remove(b'_')
+ .remove(b'~');
pub fn build_url_from_template(template: &[UrlTemplatePart], state: &Value) -> Option {
let mut url = String::new();
@@ -130,10 +140,34 @@ fn evaluate_comparison(field_value: &Value, op: &ComparisonOp, condition_value:
match op {
ComparisonOp::Equal => field_value == condition_value,
ComparisonOp::NotEqual => field_value != condition_value,
- ComparisonOp::GreaterThan => compare_numeric(field_value, condition_value, |a, b| a > b, |a, b| a > b, |a, b| a > b),
- ComparisonOp::GreaterThanOrEqual => compare_numeric(field_value, condition_value, |a, b| a >= b, |a, b| a >= b, |a, b| a >= b),
- ComparisonOp::LessThan => compare_numeric(field_value, condition_value, |a, b| a < b, |a, b| a < b, |a, b| a < b),
- ComparisonOp::LessThanOrEqual => compare_numeric(field_value, condition_value, |a, b| a <= b, |a, b| a <= b, |a, b| a <= b),
+ ComparisonOp::GreaterThan => compare_numeric(
+ field_value,
+ condition_value,
+ |a, b| a > b,
+ |a, b| a > b,
+ |a, b| a > b,
+ ),
+ ComparisonOp::GreaterThanOrEqual => compare_numeric(
+ field_value,
+ condition_value,
+ |a, b| a >= b,
+ |a, b| a >= b,
+ |a, b| a >= b,
+ ),
+ ComparisonOp::LessThan => compare_numeric(
+ field_value,
+ condition_value,
+ |a, b| a < b,
+ |a, b| a < b,
+ |a, b| a < b,
+ ),
+ ComparisonOp::LessThanOrEqual => compare_numeric(
+ field_value,
+ condition_value,
+ |a, b| a <= b,
+ |a, b| a <= b,
+ |a, b| a <= b,
+ ),
}
}
diff --git a/interpreter/src/slot_hash_cache.rs b/interpreter/src/slot_hash_cache.rs
new file mode 100644
index 00000000..c6d91a67
--- /dev/null
+++ b/interpreter/src/slot_hash_cache.rs
@@ -0,0 +1,53 @@
+//! Shared slot hash cache accessible from both server and interpreter
+//!
+//! This module provides a global cache for slot hashes that is populated
+//! by the gRPC stream and accessed by computed field resolvers.
+
+use std::collections::BTreeMap;
+use std::sync::{Arc, RwLock};
+
+/// Global slot hash cache
+static SLOT_HASH_CACHE: once_cell::sync::Lazy>>> =
+ once_cell::sync::Lazy::new(|| Arc::new(RwLock::new(BTreeMap::new())));
+
+/// Maximum number of slot hashes to keep in cache (prevent unbounded growth)
+const MAX_CACHE_SIZE: usize = 1000;
+
+/// Record a slot hash in the global cache
+pub fn record_slot_hash(slot: u64, slot_hash: String) {
+ let mut cache = SLOT_HASH_CACHE.write().expect("RwLock poisoned");
+ cache.insert(slot, slot_hash);
+
+ // Prune old entries if cache is too large
+ if cache.len() > MAX_CACHE_SIZE {
+ // Remove oldest 25% of entries using pop_first for O(log n) per removal
+ let target_size = cache.len() - cache.len() / 4;
+ while cache.len() > target_size {
+ cache.pop_first();
+ }
+ }
+}
+
+/// Get a slot hash from the global cache
+pub fn get_slot_hash(slot: u64) -> Option {
+ let cache = SLOT_HASH_CACHE.read().expect("RwLock poisoned");
+ cache.get(&slot).cloned()
+}
+
+/// Check if a slot hash is in the cache
+pub fn has_slot_hash(slot: u64) -> bool {
+ let cache = SLOT_HASH_CACHE.read().expect("RwLock poisoned");
+ cache.contains_key(&slot)
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn test_slot_hash_cache() {
+ record_slot_hash(100, "test_hash".to_string());
+ assert_eq!(get_slot_hash(100), Some("test_hash".to_string()));
+ assert_eq!(get_slot_hash(101), None);
+ }
+}
diff --git a/interpreter/src/typescript.rs b/interpreter/src/typescript.rs
index d7544e8b..079f6591 100644
--- a/interpreter/src/typescript.rs
+++ b/interpreter/src/typescript.rs
@@ -289,9 +289,27 @@ function listView(view: string): ViewDef {
.any(|f| f.name == field_info.field_name);
if !already_exists {
+ // For computed fields, check field_mappings for resolver type info
+ let field_path = format!("{}.{}", section.name, field_info.field_name);
+ let effective_field_info =
+ if let Some(mapping) = self.spec.field_mappings.get(&field_path) {
+ // Use mapping's inner_type if it's a resolver output type
+ if mapping
+ .inner_type
+ .as_ref()
+ .is_some_and(|t| is_builtin_resolver_type(t))
+ {
+ mapping
+ } else {
+ field_info
+ }
+ } else {
+ field_info
+ };
+
section_fields.push(TypeScriptField {
name: field_info.field_name.clone(),
- ts_type: self.field_type_info_to_typescript(field_info),
+ ts_type: self.field_type_info_to_typescript(effective_field_info),
optional: field_info.is_optional,
description: None,
});
@@ -540,8 +558,35 @@ function listView(view: string): ViewDef {
let registry = crate::resolvers::builtin_resolver_registry();
for resolver in registry.definitions() {
- if self.uses_builtin_type(resolver.output_type())
- && !self.already_emitted_types.contains(resolver.output_type())
+ let output_type = resolver.output_type();
+ let should_emit = self.uses_builtin_type(output_type)
+ && !self.already_emitted_types.contains(output_type);
+
+ // Also check if any types from the resolver's typescript_schema are used
+ let extra_types_used = if let Some(ts_schema) = resolver.typescript_schema() {
+ // Extract type names from export statements (simple string parsing)
+ ts_schema.definition.lines().any(|line| {
+ let line = line.trim();
+ // Match "export const TypeNameSchema"
+ if let Some(rest) = line.strip_prefix("export const ") {
+ let parts: Vec<&str> = rest.split_whitespace().collect();
+ if parts.len() >= 2 && parts[1] == "=" {
+ // Extract the base type name from "TypeNameSchema"
+ let schema_name = parts[0];
+ if let Some(type_name) = schema_name.strip_suffix("Schema") {
+ return self.uses_builtin_type(type_name)
+ && !self.already_emitted_types.contains(type_name);
+ }
+ }
+ }
+ false
+ })
+ } else {
+ false
+ };
+
+ if (should_emit || extra_types_used)
+ && !self.already_emitted_types.contains(output_type)
{
if let Some(schema) = resolver.typescript_schema() {
schemas.push((schema.name.to_string(), schema.definition.to_string()));
@@ -553,6 +598,7 @@ function listView(view: string): ViewDef {
}
fn uses_builtin_type(&self, type_name: &str) -> bool {
+ // Check section fields
for section in &self.spec.sections {
for field in §ion.fields {
if field.inner_type.as_deref() == Some(type_name) {
@@ -560,6 +606,12 @@ function listView(view: string): ViewDef {
}
}
}
+ // Check field_mappings for computed fields (they may have resolver types not in sections)
+ for field_info in self.spec.field_mappings.values() {
+ if field_info.inner_type.as_deref() == Some(type_name) {
+ return true;
+ }
+ }
false
}
@@ -568,9 +620,34 @@ function listView(view: string): ViewDef {
let registry = crate::resolvers::builtin_resolver_registry();
for resolver in registry.definitions() {
- if self.uses_builtin_type(resolver.output_type())
- && !self.already_emitted_types.contains(resolver.output_type())
- {
+ let output_type = resolver.output_type();
+ let should_emit = self.uses_builtin_type(output_type)
+ && !self.already_emitted_types.contains(output_type);
+
+ // Also check if any types from the resolver's typescript_interface are used
+ let extra_types_used = if let Some(ts_interface) = resolver.typescript_interface() {
+ // Extract type names from export statements (simple string parsing)
+ ts_interface.lines().any(|line| {
+ let line = line.trim();
+ // Match "export type TypeName" or "export interface TypeName"
+ if let Some(rest) = line.strip_prefix("export type ") {
+ if let Some(type_name) = rest.split_whitespace().next() {
+ return self.uses_builtin_type(type_name)
+ && !self.already_emitted_types.contains(type_name);
+ }
+ } else if let Some(rest) = line.strip_prefix("export interface ") {
+ if let Some(type_name) = rest.split_whitespace().next() {
+ return self.uses_builtin_type(type_name)
+ && !self.already_emitted_types.contains(type_name);
+ }
+ }
+ false
+ })
+ } else {
+ false
+ };
+
+ if should_emit || extra_types_used {
if let Some(interface) = resolver.typescript_interface() {
interfaces.push(interface.to_string());
}
@@ -949,9 +1026,14 @@ function listView(view: string): ViewDef {
} else {
let schema_entries: Vec = unique_schemas
.iter()
+ .filter(|name| name.ends_with("Schema"))
.map(|name| format!(" {}: {},", name.trim_end_matches("Schema"), name))
.collect();
- format!("\n schemas: {{\n{}\n }},", schema_entries.join("\n"))
+ if schema_entries.is_empty() {
+ String::new()
+ } else {
+ format!("\n schemas: {{\n{}\n }},", schema_entries.join("\n"))
+ }
};
// Generate URL line - either actual URL or placeholder comment
@@ -2067,9 +2149,14 @@ fn generate_stack_definition_multi(
} else {
let schema_entries: Vec = unique_schemas
.iter()
+ .filter(|name| name.ends_with("Schema"))
.map(|name| format!(" {}: {},", name.trim_end_matches("Schema"), name))
.collect();
- format!("\n schemas: {{\n{}\n }},", schema_entries.join("\n"))
+ if schema_entries.is_empty() {
+ String::new()
+ } else {
+ format!("\n schemas: {{\n{}\n }},", schema_entries.join("\n"))
+ }
};
let entity_types: Vec = entity_names.iter().map(|n| to_pascal_case(n)).collect();
diff --git a/interpreter/src/vm.rs b/interpreter/src/vm.rs
index 44c4e438..fcc4d67c 100644
--- a/interpreter/src/vm.rs
+++ b/interpreter/src/vm.rs
@@ -29,6 +29,10 @@ pub struct UpdateContext {
/// Transaction index for instruction updates (orders transactions within a slot)
/// Used for staleness detection to reject out-of-order updates
pub txn_index: Option,
+ /// When true, QueueResolver opcodes are skipped during handler execution.
+ /// Set for reprocessed cached data from PDA mapping changes to prevent
+ /// stale data from triggering resolvers or locking in wrong values via SetOnce.
+ pub skip_resolvers: bool,
/// Additional custom metadata that can be added without breaking changes
pub metadata: HashMap,
}
@@ -42,6 +46,7 @@ impl UpdateContext {
timestamp: None,
write_version: None,
txn_index: None,
+ skip_resolvers: false,
metadata: HashMap::new(),
}
}
@@ -54,6 +59,7 @@ impl UpdateContext {
timestamp: Some(timestamp),
write_version: None,
txn_index: None,
+ skip_resolvers: false,
metadata: HashMap::new(),
}
}
@@ -66,6 +72,7 @@ impl UpdateContext {
timestamp: None,
write_version: Some(write_version),
txn_index: None,
+ skip_resolvers: false,
metadata: HashMap::new(),
}
}
@@ -78,6 +85,22 @@ impl UpdateContext {
timestamp: None,
write_version: None,
txn_index: Some(txn_index),
+ skip_resolvers: false,
+ metadata: HashMap::new(),
+ }
+ }
+
+ /// Create context for reprocessed cached account data from PDA mapping changes.
+ /// Uses empty signature to prevent `when` guards from matching stale instructions,
+ /// and sets skip_resolvers to prevent stale scheduling/SetOnce lock-in.
+ pub fn new_reprocessed(slot: u64, write_version: u64) -> Self {
+ Self {
+ slot: Some(slot),
+ signature: None,
+ timestamp: None,
+ write_version: Some(write_version),
+ txn_index: None,
+ skip_resolvers: true,
metadata: HashMap::new(),
}
}
@@ -352,6 +375,13 @@ impl LookupIndex {
self.index.lock().unwrap().put(key, primary_key);
}
+ /// Remove an entry by lookup value. Used when a PDA mapping changes to
+ /// clear stale entries that would otherwise shadow the updated PDA mapping.
+ pub fn remove(&self, lookup_value: &Value) {
+ let key = value_to_cache_key(lookup_value);
+ self.index.lock().unwrap().pop(&key);
+ }
+
pub fn len(&self) -> usize {
self.index.lock().unwrap().len()
}
@@ -562,6 +592,12 @@ pub struct PendingAccountUpdate {
pub write_version: u64,
pub signature: String,
pub queued_at: i64,
+ /// When true, this update was pulled from the `last_account_data` cache
+ /// during a PDA mapping change. It carries stale data from a previous
+ /// entity mapping and should use `UpdateContext::new_reprocessed` to
+ /// prevent `when` guards from matching stale instruction signatures
+ /// and to skip resolver scheduling.
+ pub is_stale_reprocess: bool,
}
/// Input for queueing an instruction event when PDA lookup fails.
@@ -769,6 +805,10 @@ pub struct StateTable {
pub pda_reverse_lookups: HashMap,
pub pending_updates: DashMap>,
pub pending_instruction_events: DashMap>,
+ /// Cache of the most recent account data per PDA address. When a PDA
+ /// mapping changes (same PDA, different seed) the cached data is returned
+ /// for reprocessing so cross-account Lookup handlers resolve to the new key.
+ pub last_account_data: DashMap,
version_tracker: VersionTracker,
instruction_dedup_cache: VersionTracker,
config: StateTableConfig,
@@ -946,21 +986,52 @@ impl VmContext {
pda_reverse_lookups: HashMap::new(),
pending_updates: DashMap::new(),
pending_instruction_events: DashMap::new(),
+ last_account_data: DashMap::new(),
version_tracker: VersionTracker::new(),
instruction_dedup_cache: VersionTracker::with_capacity(
DEFAULT_MAX_INSTRUCTION_DEDUP_ENTRIES,
),
config: StateTableConfig::default(),
- entity_name: "default".to_string(),
+ entity_name: String::new(),
recent_tx_instructions: std::sync::Mutex::new(LruCache::new(
NonZeroUsize::new(1000).unwrap(),
)),
deferred_when_ops: DashMap::new(),
},
);
+
vm
}
+ /// Create a new VmContext specifically for multi-entity operation.
+ pub fn new_multi_entity() -> Self {
+ VmContext {
+ registers: vec![Value::Null; 256],
+ states: HashMap::new(),
+ instructions_executed: 0,
+ cache_hits: 0,
+ path_cache: HashMap::new(),
+ pda_cache_hits: 0,
+ pda_cache_misses: 0,
+ pending_queue_size: 0,
+ resolver_requests: VecDeque::new(),
+ resolver_pending: HashMap::new(),
+ resolver_cache: LruCache::new(
+ NonZeroUsize::new(DEFAULT_MAX_RESOLVER_CACHE_ENTRIES)
+ .expect("capacity must be > 0"),
+ ),
+ resolver_cache_hits: 0,
+ resolver_cache_misses: 0,
+ current_context: None,
+ warnings: Vec::new(),
+ last_pda_lookup_miss: None,
+ last_lookup_index_miss: None,
+ last_pda_registered: None,
+ last_lookup_index_keys: Vec::new(),
+ scheduled_callbacks: Vec::new(),
+ }
+ }
+
pub fn new_with_config(state_config: StateTableConfig) -> Self {
let mut vm = VmContext {
registers: vec![Value::Null; 256],
@@ -997,6 +1068,7 @@ impl VmContext {
pda_reverse_lookups: HashMap::new(),
pending_updates: DashMap::new(),
pending_instruction_events: DashMap::new(),
+ last_account_data: DashMap::new(),
version_tracker: VersionTracker::new(),
instruction_dedup_cache: VersionTracker::with_capacity(
DEFAULT_MAX_INSTRUCTION_DEDUP_ENTRIES,
@@ -1097,13 +1169,19 @@ impl VmContext {
.as_secs() as i64
});
let eval_result = evaluator(&mut entity_state, context_slot, context_timestamp);
+
if eval_result.is_ok() {
+ let mut changed_fields = Vec::new();
for (path, old_value) in
entity_bytecode.computed_paths.iter().zip(old_values.iter())
{
let new_value = Self::get_value_at_path(&entity_state, path);
- if new_value != *old_value && should_emit(path) {
+ let changed = new_value != *old_value;
+ let will_emit = should_emit(path);
+
+ if changed && will_emit {
dirty_tracker.mark_replaced(path);
+ changed_fields.push(path.clone());
}
}
}
@@ -1484,7 +1562,24 @@ impl VmContext {
"flushing deferred when-ops"
);
for op in deferred_ops {
- match self.apply_deferred_when_op(state_id, &op) {
+ // Look up the entity bytecode to get the computed fields evaluator
+ let (evaluator, computed_paths) = bytecode
+ .entities
+ .get(&op.entity_name)
+ .map(|eb| {
+ (
+ eb.computed_fields_evaluator.as_ref(),
+ eb.computed_paths.as_slice(),
+ )
+ })
+ .unwrap_or((None, &[]));
+
+ match self.apply_deferred_when_op(
+ state_id,
+ &op,
+ evaluator,
+ Some(computed_paths),
+ ) {
Ok(mutations) => all_mutations.extend(mutations),
Err(e) => tracing::warn!(
"Failed to apply deferred when-op: {}",
@@ -1647,6 +1742,10 @@ impl VmContext {
match self.apply_deferred_when_op(
entity_bytecode.state_id,
&op,
+ entity_bytecode
+ .computed_fields_evaluator
+ .as_ref(),
+ Some(&entity_bytecode.computed_paths),
) {
Ok(mutations) => {
all_mutations.extend(mutations)
@@ -1889,6 +1988,22 @@ impl VmContext {
self.registers[*dest] = value;
pc += 1;
}
+ OpCode::AbortIfNullKey {
+ key,
+ is_account_event,
+ } => {
+ let key_value = &self.registers[*key];
+ if key_value.is_null() && *is_account_event {
+ tracing::debug!(
+ event_type = %event_type,
+ "AbortIfNullKey: key is null for account state event, \
+ returning empty mutations for queueing"
+ );
+ return Ok(Vec::new());
+ }
+
+ pc += 1;
+ }
OpCode::ReadOrInitState {
state_id: _,
key,
@@ -1907,6 +2022,7 @@ impl VmContext {
pda_reverse_lookups: HashMap::new(),
pending_updates: DashMap::new(),
pending_instruction_events: DashMap::new(),
+ last_account_data: DashMap::new(),
version_tracker: VersionTracker::new(),
instruction_dedup_cache: VersionTracker::with_capacity(
DEFAULT_MAX_INSTRUCTION_DEDUP_ENTRIES,
@@ -1940,19 +2056,28 @@ impl VmContext {
if !key_value.is_null() {
if let Some(ctx) = &self.current_context {
// Account updates: use recency check to discard stale updates
+ // IMPORTANT: Use account address (PDA) as the key, not entity key,
+ // because multiple accounts can update the same entity and each
+ // has its own independent write_version
if ctx.is_account_update() {
if let (Some(slot), Some(write_version)) =
(ctx.slot, ctx.write_version)
{
+ // Get account address from event_value for proper tracking
+ let account_address = event_value
+ .get("__account_address")
+ .cloned()
+ .unwrap_or_else(|| key_value.clone());
+
if !state.is_fresh_update(
- &key_value,
+ &account_address,
event_type,
slot,
write_version,
) {
self.add_warning(format!(
- "Stale account update skipped: slot={}, write_version={}",
- slot, write_version
+ "Stale account update skipped: slot={}, write_version={}, account={}",
+ slot, write_version, account_address
));
return Ok(Vec::new());
}
@@ -2642,12 +2767,28 @@ impl VmContext {
} => {
let actual_state_id = override_state_id;
+ // Skip resolvers for reprocessed cached data from PDA mapping changes.
+ // Stale data can carry wrong field values (e.g. old entropy_value) and
+ // wrong schedule_at slots that would lock in incorrect results via SetOnce.
+ if self
+ .current_context
+ .as_ref()
+ .map(|c| c.skip_resolvers)
+ .unwrap_or(false)
+ {
+ pc += 1;
+ continue;
+ }
+
// Evaluate condition if present
if let Some(cond) = condition {
let field_val =
Self::get_value_at_path(&self.registers[*state], &cond.field_path)
.unwrap_or(Value::Null);
- if !self.evaluate_comparison(&field_val, &cond.op, &cond.value)? {
+ let condition_met =
+ self.evaluate_comparison(&field_val, &cond.op, &cond.value)?;
+
+ if !condition_met {
pc += 1;
continue;
}
@@ -2694,12 +2835,6 @@ impl VmContext {
// schedule_at path is missing or value is not a u64 —
// skip resolver entirely rather than executing immediately,
// since the state likely hasn't been fully populated yet.
- tracing::warn!(
- schedule_at_path = %schedule_path,
- entity = %entity_name,
- "schedule_at field path is missing or not a valid u64 in state; \
- skipping resolver (state may not be fully populated yet)"
- );
pc += 1;
continue;
}
@@ -2722,16 +2857,6 @@ impl VmContext {
let key_value = &self.registers[*key];
if input.is_null() || key_value.is_null() {
- tracing::warn!(
- entity = %entity_name,
- resolver = ?resolver,
- input_path = %input_path.as_deref().unwrap_or(""),
- input_is_null = input.is_null(),
- key_is_null = key_value.is_null(),
- input = ?input,
- key = ?key_value,
- "Resolver skipped: null input or key"
- );
pc += 1;
continue;
}
@@ -2782,14 +2907,6 @@ impl VmContext {
target,
);
}
- } else {
- tracing::warn!(
- entity = %entity_name,
- resolver = ?resolver,
- input_path = %input_path.as_deref().unwrap_or(""),
- state = ?self.registers[*state],
- "Resolver skipped: input path not found in state"
- );
}
pc += 1;
@@ -3441,10 +3558,15 @@ impl VmContext {
false
}
+ #[allow(clippy::type_complexity)]
fn apply_deferred_when_op(
&mut self,
state_id: u32,
op: &DeferredWhenOperation,
+ entity_evaluator: Option<
+ &Box, i64) -> Result<()> + Send + Sync>,
+ >,
+ computed_paths: Option<&[String]>,
) -> Result> {
let state = self.states.get(&state_id).ok_or("State not found")?;
@@ -3456,9 +3578,50 @@ impl VmContext {
.get_and_touch(&op.primary_key)
.unwrap_or_else(|| json!({}));
+ // Track old values of computed fields before setting the new value
+ let old_computed_values: Vec<_> = computed_paths
+ .map(|paths| {
+ paths
+ .iter()
+ .map(|path| Self::get_value_at_path(&entity_state, path))
+ .collect()
+ })
+ .unwrap_or_default();
+
Self::set_nested_field_value(&mut entity_state, &op.field_path, op.field_value.clone())?;
- state.insert_with_eviction(op.primary_key.clone(), entity_state);
+ // Re-evaluate computed fields if an evaluator is provided
+ if let Some(evaluator) = entity_evaluator {
+ let context_slot = self.current_context.as_ref().and_then(|c| c.slot);
+ let context_timestamp = self
+ .current_context
+ .as_ref()
+ .map(|c| c.timestamp())
+ .unwrap_or_else(|| {
+ std::time::SystemTime::now()
+ .duration_since(std::time::UNIX_EPOCH)
+ .unwrap()
+ .as_secs() as i64
+ });
+
+ tracing::debug!(
+ entity_name = %op.entity_name,
+ primary_key = %op.primary_key,
+ field_path = %op.field_path,
+ "Re-evaluating computed fields after deferred when-op"
+ );
+
+ if let Err(e) = evaluator(&mut entity_state, context_slot, context_timestamp) {
+ tracing::warn!(
+ entity_name = %op.entity_name,
+ primary_key = %op.primary_key,
+ error = %e,
+ "Failed to evaluate computed fields after deferred when-op"
+ );
+ }
+ }
+
+ state.insert_with_eviction(op.primary_key.clone(), entity_state.clone());
if !op.emit {
return Ok(vec![]);
@@ -3467,6 +3630,38 @@ impl VmContext {
let mut patch = json!({});
Self::set_nested_field_value(&mut patch, &op.field_path, op.field_value.clone())?;
+ // Add computed field changes to the patch
+ if let Some(paths) = computed_paths {
+ tracing::debug!(
+ entity_name = %op.entity_name,
+ primary_key = %op.primary_key,
+ computed_paths_count = paths.len(),
+ "Checking computed fields for changes after deferred when-op"
+ );
+ for (path, old_value) in paths.iter().zip(old_computed_values.iter()) {
+ let new_value = Self::get_value_at_path(&entity_state, path);
+ tracing::debug!(
+ entity_name = %op.entity_name,
+ primary_key = %op.primary_key,
+ field_path = %path,
+ old_value = ?old_value,
+ new_value = ?new_value,
+ "Comparing computed field values"
+ );
+ if let Some(ref new_val) = new_value {
+ if Some(new_val) != old_value.as_ref() {
+ Self::set_nested_field_value(&mut patch, path, new_val.clone())?;
+ tracing::info!(
+ entity_name = %op.entity_name,
+ primary_key = %op.primary_key,
+ field_path = %path,
+ "Computed field changed after deferred when-op, including in mutation"
+ );
+ }
+ }
+ }
+ }
+
Ok(vec![Mutation {
export: op.entity_name.clone(),
key: op.primary_key.clone(),
@@ -3555,7 +3750,30 @@ impl VmContext {
.entry(lookup_name.to_string())
.or_insert_with(|| PdaReverseLookup::new(DEFAULT_MAX_PDA_REVERSE_LOOKUP_ENTRIES));
- let evicted_pda = lookup.insert(pda_address.clone(), seed_value);
+ // Detect if the PDA mapping is CHANGING (same PDA, different seed).
+ // This happens at round boundaries when e.g. entropyVar is remapped
+ // from old_round to new_round by a Reset instruction.
+ let old_seed = lookup.index.peek(&pda_address).cloned();
+ let mapping_changed = old_seed
+ .as_ref()
+ .map(|old| old != &seed_value)
+ .unwrap_or(false);
+
+ if !mapping_changed && old_seed.is_none() {
+ tracing::info!(
+ pda = %pda_address,
+ seed = %seed_value,
+ "[PDA] First-time PDA reverse lookup established"
+ );
+ } else if !mapping_changed {
+ tracing::debug!(
+ pda = %pda_address,
+ seed = %seed_value,
+ "[PDA] PDA reverse lookup re-registered (same mapping)"
+ );
+ }
+
+ let evicted_pda = lookup.insert(pda_address.clone(), seed_value.clone());
if let Some(ref evicted) = evicted_pda {
if let Some((_, evicted_updates)) = state.pending_updates.remove(evicted) {
@@ -3564,8 +3782,38 @@ impl VmContext {
}
}
- // Flush and return pending updates for this PDA
- self.flush_pending_updates(state_id, &pda_address)
+ // Flush pending updates from QueueUntil for this PDA
+ let mut pending = self.flush_pending_updates(state_id, &pda_address)?;
+
+ // When the mapping changed, the last account update for this PDA was
+ // processed with the OLD seed (wrong key). We need to:
+ // 1. Remove stale lookup-index entries that map this PDA address to the
+ // old primary key — otherwise LookupIndex resolves the stale entry
+ // before PDA reverse lookup is even tried.
+ // 2. Pull the cached account data and return it for reprocessing with
+ // the new mapping.
+ if mapping_changed {
+ if let Some(state) = self.states.get(&state_id) {
+ // Clear stale lookup-index entries for this PDA address
+ for index in state.lookup_indexes.values() {
+ index.remove(&Value::String(pda_address.clone()));
+ }
+
+ if let Some((_, mut cached)) = state.last_account_data.remove(&pda_address) {
+ tracing::info!(
+ pda = %pda_address,
+ old_seed = ?old_seed,
+ new_seed = %seed_value,
+ account_type = %cached.account_type,
+ "PDA mapping changed — clearing stale indexes and reprocessing cached data"
+ );
+ cached.is_stale_reprocess = true;
+ pending.push(cached);
+ }
+ }
+ }
+
+ Ok(pending)
}
/// Clean up expired pending updates that are older than the TTL
@@ -3682,6 +3930,7 @@ impl VmContext {
.duration_since(std::time::UNIX_EPOCH)
.unwrap()
.as_secs() as i64,
+ is_stale_reprocess: false,
};
let pda_address = pending.pda_address.clone();
@@ -3980,6 +4229,24 @@ impl VmContext {
}
}
+ /// Cache the most recent account data for a PDA address.
+ /// Called by the vixen runtime after a Lookup-handler account update is
+ /// successfully processed. When a PDA mapping later changes (e.g. at a
+ /// round boundary), the cached data is returned for reprocessing with the
+ /// new mapping.
+ pub fn cache_last_account_data(
+ &mut self,
+ state_id: u32,
+ pda_address: &str,
+ update: PendingAccountUpdate,
+ ) {
+ if let Some(state) = self.states.get(&state_id) {
+ state
+ .last_account_data
+ .insert(pda_address.to_string(), update);
+ }
+ }
+
/// Try to resolve a primary key via PDA reverse lookup
pub fn try_pda_reverse_lookup(
&mut self,
@@ -4000,6 +4267,44 @@ impl VmContext {
None
}
+ /// Try to resolve a value through lookup indexes.
+ /// This attempts to resolve the value using any lookup index in the state.
+ pub fn try_lookup_index_resolution(&self, state_id: u32, value: &Value) -> Option {
+ let state = self.states.get(&state_id)?;
+
+ for index in state.lookup_indexes.values() {
+ if let Some(resolved) = index.lookup(value) {
+ return Some(resolved);
+ }
+ }
+
+ None
+ }
+
+ /// Try to resolve a primary key via chained PDA + lookup index resolution.
+ /// First tries PDA reverse lookup, then tries to resolve the result through lookup indexes.
+ /// This is useful when the PDA maps to an intermediate value (e.g., round address)
+ /// that needs to be resolved to the actual primary key (e.g., round_id).
+ pub fn try_chained_pda_lookup(
+ &mut self,
+ state_id: u32,
+ lookup_name: &str,
+ pda_address: &str,
+ ) -> Option {
+ // First, try PDA reverse lookup
+ let pda_result = self.try_pda_reverse_lookup(state_id, lookup_name, pda_address)?;
+
+ // Try to resolve the PDA result through lookup indexes
+ // (e.g., round address -> round_id)
+ let pda_value = Value::String(pda_result.clone());
+ if let Some(resolved) = self.try_lookup_index_resolution(state_id, &pda_value) {
+ resolved.as_str().map(|s| s.to_string())
+ } else {
+ // Return the PDA result if we can't resolve further
+ pda_value.as_str().map(|s| s.to_string())
+ }
+ }
+
// ============================================================================
// Computed Expression Evaluator (Task 5)
// ============================================================================
@@ -4081,7 +4386,7 @@ impl VmContext {
let arr: [u8; 8] = byte_vec[..8]
.try_into()
.map_err(|_| "Failed to convert to [u8; 8]")?;
- Ok(json!(u64::from_le_bytes(arr)))
+ Ok(Value::String(u64::from_le_bytes(arr).to_string()))
}
ComputedExpr::U64FromBeBytes { bytes } => {
@@ -4097,7 +4402,7 @@ impl VmContext {
let arr: [u8; 8] = byte_vec[..8]
.try_into()
.map_err(|_| "Failed to convert to [u8; 8]")?;
- Ok(json!(u64::from_be_bytes(arr)))
+ Ok(Value::String(u64::from_be_bytes(arr).to_string()))
}
ComputedExpr::ByteArray { bytes } => {
@@ -4209,6 +4514,16 @@ impl VmContext {
.as_ref()
.map(|ctx| json!(ctx.timestamp()))
.unwrap_or(Value::Null)),
+
+ ComputedExpr::Keccak256 { expr } => {
+ let val = self.evaluate_computed_expr_with_env(expr, state, env)?;
+ let bytes = self.value_to_bytes(&val)?;
+ use sha3::{Digest, Keccak256};
+ let hash = Keccak256::digest(&bytes);
+ Ok(Value::Array(
+ hash.to_vec().iter().map(|b| json!(*b)).collect(),
+ ))
+ }
}
}
@@ -4626,9 +4941,18 @@ impl VmContext {
crate::resolvers::validate_resolver_computed_specs(computed_field_specs)?;
for spec in computed_field_specs {
- if let Ok(result) = self.evaluate_computed_expr(&spec.expression, state) {
- self.set_field_in_state(state, &spec.target_path, result)?;
- updated_paths.push(spec.target_path.clone());
+ match self.evaluate_computed_expr(&spec.expression, state) {
+ Ok(result) => {
+ self.set_field_in_state(state, &spec.target_path, result)?;
+ updated_paths.push(spec.target_path.clone());
+ }
+ Err(e) => {
+ tracing::warn!(
+ target_path = %spec.target_path,
+ error = %e,
+ "Failed to evaluate computed field"
+ );
+ }
}
}
@@ -5043,7 +5367,7 @@ mod tests {
let deferred = state.deferred_when_ops.remove(&key).unwrap().1;
for op in deferred {
- vm.apply_deferred_when_op(0, &op).unwrap();
+ vm.apply_deferred_when_op(0, &op, None, None).unwrap();
}
let state = vm.states.get(&0).unwrap();
@@ -5084,4 +5408,143 @@ mod tests {
"Deferred ops should be empty after cleanup"
);
}
+
+ #[test]
+ fn test_deferred_when_op_recomputes_dependent_fields() {
+ use crate::ast::{BinaryOp, ComputedExpr, ComputedFieldSpec};
+
+ let mut vm = VmContext::new();
+
+ // Create computed field specs similar to the ore stack:
+ // pre_reveal_rng depends on base_value
+ // pre_reveal_winning_square depends on pre_reveal_rng
+ let computed_specs = vec![
+ ComputedFieldSpec {
+ target_path: "results.pre_reveal_rng".to_string(),
+ result_type: "Option".to_string(),
+ expression: ComputedExpr::FieldRef {
+ path: "entropy.base_value".to_string(),
+ },
+ },
+ ComputedFieldSpec {
+ target_path: "results.pre_reveal_winning_square".to_string(),
+ result_type: "Option".to_string(),
+ expression: ComputedExpr::MethodCall {
+ expr: Box::new(ComputedExpr::FieldRef {
+ path: "results.pre_reveal_rng".to_string(),
+ }),
+ method: "map".to_string(),
+ args: vec![ComputedExpr::Closure {
+ param: "r".to_string(),
+ body: Box::new(ComputedExpr::Binary {
+ op: BinaryOp::Mod,
+ left: Box::new(ComputedExpr::Var {
+ name: "r".to_string(),
+ }),
+ right: Box::new(ComputedExpr::Literal {
+ value: serde_json::json!(25),
+ }),
+ }),
+ }],
+ },
+ },
+ ];
+
+ let evaluator: Box, i64) -> Result<()> + Send + Sync> =
+ Box::new(VmContext::create_evaluator_from_specs(computed_specs));
+
+ // Test that when we set entropy.base_value via deferred when-op,
+ // both computed fields are updated
+ let primary_key = json!("test_pk");
+ let op = DeferredWhenOperation {
+ entity_name: "TestEntity".to_string(),
+ primary_key: primary_key.clone(),
+ field_path: "entropy.base_value".to_string(),
+ field_value: json!(100),
+ when_instruction: "TestIxState".to_string(),
+ signature: "test_sig".to_string(),
+ slot: 100,
+ deferred_at: 0,
+ emit: true,
+ };
+
+ // Store the entity in state first
+ let initial_state = json!({
+ "results": {}
+ });
+ vm.states
+ .get(&0)
+ .unwrap()
+ .insert_with_eviction(primary_key.clone(), initial_state);
+
+ // Apply the deferred when-op with the evaluator
+ let mutations = vm
+ .apply_deferred_when_op(
+ 0,
+ &op,
+ Some(&evaluator),
+ Some(&[
+ "results.pre_reveal_rng".to_string(),
+ "results.pre_reveal_winning_square".to_string(),
+ ]),
+ )
+ .unwrap();
+
+ // Check the entity state
+ let state = vm.states.get(&0).unwrap();
+ let entity = state.data.get(&primary_key).unwrap();
+
+ println!(
+ "Entity state: {}",
+ serde_json::to_string_pretty(&*entity).unwrap()
+ );
+
+ // Verify base value was set
+ assert_eq!(
+ entity.get("entropy").and_then(|e| e.get("base_value")),
+ Some(&json!(100)),
+ "Base value should be set"
+ );
+
+ // Verify computed fields were calculated
+ let pre_reveal_rng = entity
+ .get("results")
+ .and_then(|r| r.get("pre_reveal_rng"))
+ .cloned();
+ let pre_reveal_winning_square = entity
+ .get("results")
+ .and_then(|r| r.get("pre_reveal_winning_square"))
+ .cloned();
+
+ assert_eq!(
+ pre_reveal_rng,
+ Some(json!(100)),
+ "pre_reveal_rng should be computed"
+ );
+ assert_eq!(
+ pre_reveal_winning_square,
+ Some(json!(0)),
+ "pre_reveal_winning_square should be 100 % 25 = 0"
+ );
+
+ // Verify mutations include computed fields
+ assert!(!mutations.is_empty(), "Should have mutations");
+ let mutation = &mutations[0];
+ let patch = &mutation.patch;
+
+ assert!(
+ patch
+ .get("results")
+ .and_then(|r| r.get("pre_reveal_rng"))
+ .is_some(),
+ "Mutation should include pre_reveal_rng"
+ );
+ assert!(
+ patch
+ .get("results")
+ .and_then(|r| r.get("pre_reveal_winning_square"))
+ .is_some(),
+ "Mutation should include pre_reveal_winning_square"
+ );
+ }
}
diff --git a/rust/hyperstack-server/Cargo.toml b/rust/hyperstack-server/Cargo.toml
index ad58dd1c..424e8dfa 100644
--- a/rust/hyperstack-server/Cargo.toml
+++ b/rust/hyperstack-server/Cargo.toml
@@ -40,6 +40,7 @@ lru = "0.12"
dashmap = "6.1"
flate2 = "1.0"
base64 = "0.22"
+once_cell = "1.20"
# HTTP server for health endpoint
hyper = { version = "1.6", features = ["server", "http1"] }
diff --git a/rust/hyperstack-server/src/health.rs b/rust/hyperstack-server/src/health.rs
index 488728cc..b6c046ac 100644
--- a/rust/hyperstack-server/src/health.rs
+++ b/rust/hyperstack-server/src/health.rs
@@ -1,3 +1,4 @@
+use std::collections::HashMap;
use std::sync::atomic::{AtomicU64, Ordering};
use std::sync::Arc;
use std::time::{Duration, Instant, SystemTime};
@@ -5,26 +6,66 @@ use tokio::sync::RwLock;
use tokio::time::interval;
use tracing::{error, info, warn};
-/// Tracks the last processed slot for stream resumption after reconnection
+/// Tracks the last processed slot for stream resumption after reconnection.
+///
+/// Includes a `Notify` that wakes waiters whenever the slot advances,
+/// allowing the scheduler to react immediately to new slots instead of polling.
+/// Also maintains a cache of slot hashes indexed by slot number.
#[derive(Clone)]
pub struct SlotTracker {
last_slot: Arc,
+ notify: Arc,
+ /// Cache of slot hashes indexed by slot number
+ slot_hashes: Arc>>,
}
impl SlotTracker {
pub fn new() -> Self {
Self {
last_slot: Arc::new(AtomicU64::new(0)),
+ notify: Arc::new(tokio::sync::Notify::new()),
+ slot_hashes: Arc::new(RwLock::new(HashMap::new())),
}
}
pub fn record(&self, slot: u64) {
- self.last_slot.fetch_max(slot, Ordering::Relaxed);
+ let old = self.last_slot.fetch_max(slot, Ordering::Relaxed);
+ if slot > old {
+ self.notify.notify_waiters();
+ }
+ }
+
+ /// Record a slot hash for a specific slot
+ pub async fn record_slot_hash(&self, slot: u64, slot_hash: String) {
+ let mut hashes = self.slot_hashes.write().await;
+ hashes.insert(slot, slot_hash);
+
+ // Prune old entries to prevent unbounded growth (keep last 10000 slots)
+ let slots_to_remove: Vec = hashes
+ .keys()
+ .filter(|&&s| s < slot.saturating_sub(10000))
+ .copied()
+ .collect();
+ for s in slots_to_remove {
+ hashes.remove(&s);
+ }
+ }
+
+ /// Get the slot hash for a specific slot (if cached)
+ pub async fn get_slot_hash(&self, slot: u64) -> Option {
+ let hashes = self.slot_hashes.read().await;
+ hashes.get(&slot).cloned()
}
pub fn get(&self) -> u64 {
self.last_slot.load(Ordering::Relaxed)
}
+
+ /// Returns a future that resolves when the slot advances.
+ /// Use with `tokio::select!` and a fallback timeout.
+ pub fn notified(&self) -> impl std::future::Future