diff --git a/Api.Dockerfile b/Api.Dockerfile index e52a0c220..602abfa81 100644 --- a/Api.Dockerfile +++ b/Api.Dockerfile @@ -1,14 +1,17 @@ -FROM rust:1.73-bullseye AS chef +FROM rust:1.75-bullseye AS chef RUN cargo install cargo-chef FROM chef AS planner RUN mkdir /rust COPY Cargo.toml /rust +COPY core /rust/core COPY das_api /rust/das_api COPY digital_asset_types /rust/digital_asset_types +COPY integration_tests /rust/integration_tests COPY metaplex-rpc-proxy /rust/metaplex-rpc-proxy COPY migration /rust/migration COPY nft_ingester /rust/nft_ingester +COPY ops /rust/ops COPY tools /rust/tools WORKDIR /rust/das_api @@ -20,11 +23,14 @@ RUN apt-get update -y && \ RUN mkdir /rust COPY Cargo.toml /rust +COPY core /rust/core COPY das_api /rust/das_api COPY digital_asset_types /rust/digital_asset_types +COPY integration_tests /rust/integration_tests COPY metaplex-rpc-proxy /rust/metaplex-rpc-proxy COPY migration /rust/migration COPY nft_ingester /rust/nft_ingester +COPY ops /rust/ops COPY tools /rust/tools WORKDIR /rust/das_api @@ -39,7 +45,7 @@ COPY --from=planner /rust/das_api/recipe.json recipe.json # Build application RUN cargo build --release -FROM rust:1.73-slim-bullseye +FROM rust:1.75-slim-bullseye ARG APP=/usr/src/app RUN apt update \ && apt install -y curl ca-certificates tzdata \ diff --git a/Cargo.lock b/Cargo.lock index 7fe2160d5..dad018aca 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -18,8 +18,8 @@ version = "0.7.12" dependencies = [ "anyhow", "bs58 0.4.0", - "clap 4.4.8", - "env_logger 0.10.0", + "clap 4.4.18", + "env_logger 0.10.2", "figment", "flatbuffers", "futures", @@ -35,7 +35,7 @@ dependencies = [ "solana-client", "solana-sdk", "solana-transaction-status", - "spl-token 4.0.0", + "spl-token", "tokio", "txn_forwarder", ] @@ -93,25 +93,26 @@ dependencies = [ [[package]] name = "ahash" -version = "0.7.6" +version = "0.7.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" +checksum = "5a824f2aa7e75a0c98c5a504fceb80649e9c35265d44525b5f94de4771a395cd" dependencies = [ - "getrandom 0.2.10", + "getrandom 0.2.12", "once_cell", "version_check", ] [[package]] name = "ahash" -version = "0.8.3" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c99f64d1e06488f620f932677e24bc6e2897582980441ae90a671415bd7ec2f" +checksum = "77c3a9648d43b9cd48db467b3f87fdd6e146bcc88ab0180006cef2179fe11d01" dependencies = [ "cfg-if", - "getrandom 0.2.10", + "getrandom 0.2.12", "once_cell", "version_check", + "zerocopy", ] [[package]] @@ -158,8 +159,8 @@ checksum = "faa5be5b72abea167f87c868379ba3c2be356bfca9e6f474fd055fa0f7eeb4f2" dependencies = [ "anchor-syn", "anyhow", - "proc-macro2 1.0.69", - "quote 1.0.33", + "proc-macro2 1.0.78", + "quote 1.0.35", "regex", "syn 1.0.109", ] @@ -173,8 +174,8 @@ dependencies = [ "anchor-syn", "anyhow", "bs58 0.5.0", - "proc-macro2 1.0.69", - "quote 1.0.33", + "proc-macro2 1.0.78", + "quote 1.0.35", "rustversion", "syn 1.0.109", ] @@ -186,7 +187,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "59948e7f9ef8144c2aefb3f32a40c5fce2798baeec765ba038389e82301017ef" dependencies = [ "anchor-syn", - "proc-macro2 1.0.69", + "proc-macro2 1.0.78", "syn 1.0.109", ] @@ -197,8 +198,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc753c9d1c7981cb8948cf7e162fb0f64558999c0413058e2d43df1df5448086" dependencies = [ "anchor-syn", - "proc-macro2 1.0.69", - "quote 1.0.33", + "proc-macro2 1.0.78", + "quote 1.0.35", "syn 1.0.109", ] @@ -210,8 +211,8 @@ checksum = "f38b4e172ba1b52078f53fdc9f11e3dc0668ad27997838a0aad2d148afac8c97" dependencies = [ "anchor-syn", "anyhow", - "proc-macro2 1.0.69", - "quote 1.0.33", + "proc-macro2 1.0.78", + "quote 1.0.35", "syn 1.0.109", ] @@ -223,8 +224,8 @@ checksum = "4eebd21543606ab61e2d83d9da37d24d3886a49f390f9c43a1964735e8c0f0d5" dependencies = [ "anchor-syn", "anyhow", - "proc-macro2 1.0.69", - "quote 1.0.33", + "proc-macro2 1.0.78", + "quote 1.0.35", "syn 1.0.109", ] @@ -255,8 +256,8 @@ checksum = "ec4720d899b3686396cced9508f23dab420f1308344456ec78ef76f98fda42af" dependencies = [ "anchor-syn", "anyhow", - "proc-macro2 1.0.69", - "quote 1.0.33", + "proc-macro2 1.0.78", + "quote 1.0.35", "syn 1.0.109", ] @@ -266,8 +267,8 @@ version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f495e85480bd96ddeb77b71d499247c7d4e8b501e75ecb234e9ef7ae7bd6552a" dependencies = [ - "proc-macro2 1.0.69", - "quote 1.0.33", + "proc-macro2 1.0.78", + "quote 1.0.35", "syn 1.0.109", ] @@ -290,7 +291,7 @@ dependencies = [ "bincode", "borsh 0.10.3", "bytemuck", - "getrandom 0.2.10", + "getrandom 0.2.12", "solana-program", "thiserror", ] @@ -304,8 +305,8 @@ dependencies = [ "anyhow", "bs58 0.5.0", "heck 0.3.3", - "proc-macro2 1.0.69", - "quote 1.0.33", + "proc-macro2 1.0.78", + "quote 1.0.35", "serde", "serde_json", "sha2 0.10.8", @@ -339,9 +340,9 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.4" +version = "0.6.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ab91ebe16eb252986481c5b62f6098f3b698a45e34b5b98200cf20dd2484a44" +checksum = "6e2e1ebcb11de5c03c67de28a7df593d32191b44939c482e97702baaaa6ab6a5" dependencies = [ "anstyle", "anstyle-parse", @@ -353,43 +354,43 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.4" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7079075b41f533b8c61d2a4d073c4676e1f8b249ff94a393b0595db304e0dd87" +checksum = "8901269c6307e8d93993578286ac0edf7f195079ffff5ebdeea6a59ffb7e36bc" [[package]] name = "anstyle-parse" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "317b9a89c1868f5ea6ff1d9539a69f45dffc21ce321ac1fd1160dfa48c8e2140" +checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.0.0" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b" +checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648" dependencies = [ - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] name = "anstyle-wincon" -version = "3.0.1" +version = "3.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0699d10d2f4d628a98ee7b57b289abbc98ff3bad977cb3152709d4bf2330628" +checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7" dependencies = [ "anstyle", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] name = "anyhow" -version = "1.0.75" +version = "1.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" +checksum = "080e9890a082662b09c1ad45f567faeeb47f22b5fb23895fbe1e651e718e25ca" [[package]] name = "arc-swap" @@ -451,7 +452,7 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3ed4aa4fe255d0bc6d79373f7e31d2ea147bcf486cba1be5ba7ea85abdb92348" dependencies = [ - "quote 1.0.33", + "quote 1.0.35", "syn 1.0.109", ] @@ -463,8 +464,8 @@ checksum = "7abe79b0e4288889c4574159ab790824d0033b9fdcb2a112a3182fac2e514565" dependencies = [ "num-bigint 0.4.4", "num-traits", - "proc-macro2 1.0.69", - "quote 1.0.33", + "proc-macro2 1.0.78", + "quote 1.0.35", "syn 1.0.109", ] @@ -499,8 +500,8 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ae3281bc6d0fd7e549af32b52511e1302185bd688fd3359fa36423346ff682ea" dependencies = [ - "proc-macro2 1.0.69", - "quote 1.0.33", + "proc-macro2 1.0.78", + "quote 1.0.35", "syn 1.0.109", ] @@ -551,7 +552,7 @@ dependencies = [ "num-traits", "rusticata-macros", "thiserror", - "time 0.3.29", + "time 0.3.34", ] [[package]] @@ -560,8 +561,8 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "726535892e8eae7e70657b4c8ea93d26b8553afb1ce617caee529ef96d7dee6c" dependencies = [ - "proc-macro2 1.0.69", - "quote 1.0.33", + "proc-macro2 1.0.78", + "quote 1.0.35", "syn 1.0.109", "synstructure", ] @@ -572,8 +573,8 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2777730b2039ac0f95f093556e61b6d26cebed5393ca6f152717777cec3a42ed" dependencies = [ - "proc-macro2 1.0.69", - "quote 1.0.33", + "proc-macro2 1.0.78", + "quote 1.0.35", "syn 1.0.109", ] @@ -589,7 +590,7 @@ version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a3203e79f4dd9bdda415ed03cf14dae5a2bf775c683a00f94e9cd1faf0f596e5" dependencies = [ - "quote 1.0.33", + "quote 1.0.35", "syn 1.0.109", ] @@ -606,12 +607,12 @@ dependencies = [ [[package]] name = "async-channel" -version = "2.1.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d37875bd9915b7d67c2f117ea2c30a0989874d0b2cb694fe25403c85763c0c9e" +checksum = "1ca33f4bc4ed1babef42cad36cc1f51fa88be00420404e5b1e80ab1b18f7678c" dependencies = [ "concurrent-queue", - "event-listener 3.1.0", + "event-listener 4.0.3", "event-listener-strategy", "futures-core", "pin-project-lite", @@ -619,9 +620,9 @@ dependencies = [ [[package]] name = "async-compression" -version = "0.4.3" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb42b2197bf15ccb092b62c74515dbd8b86d0effd934795f6687c93b6e679a2c" +checksum = "a116f46a969224200a0a97f29cfd4c50e7534e4b4826bd23ea2c3c533039c82c" dependencies = [ "brotli", "flate2", @@ -633,30 +634,30 @@ dependencies = [ [[package]] name = "async-executor" -version = "1.7.2" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc5ea910c42e5ab19012bab31f53cb4d63d54c3a27730f9a833a88efcf4bb52d" +checksum = "17ae5ebefcc48e7452b4987947920dac9450be1110cadf34d1b8c116bdbaf97c" dependencies = [ - "async-lock 3.1.1", + "async-lock 3.3.0", "async-task", "concurrent-queue", "fastrand 2.0.1", - "futures-lite 2.0.1", + "futures-lite 2.2.0", "slab", ] [[package]] name = "async-global-executor" -version = "2.3.1" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1b6f5d7df27bd294849f8eec66ecfc63d11814df7a4f5d74168a2394467b776" +checksum = "05b1b633a2115cd122d73b955eadd9916c18c8f510ec9cd1686404c60ad1c29c" dependencies = [ - "async-channel 1.9.0", + "async-channel 2.1.1", "async-executor", - "async-io", - "async-lock 2.8.0", + "async-io 2.3.1", + "async-lock 3.3.0", "blocking", - "futures-lite 1.13.0", + "futures-lite 2.2.0", "once_cell", "tokio", ] @@ -674,13 +675,32 @@ dependencies = [ "futures-lite 1.13.0", "log", "parking", - "polling", + "polling 2.8.0", "rustix 0.37.27", "slab", - "socket2 0.4.9", + "socket2 0.4.10", "waker-fn", ] +[[package]] +name = "async-io" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f97ab0c5b00a7cdbe5a371b9a782ee7be1316095885c8a4ea1daf490eb0ef65" +dependencies = [ + "async-lock 3.3.0", + "cfg-if", + "concurrent-queue", + "futures-io", + "futures-lite 2.2.0", + "parking", + "polling 3.4.0", + "rustix 0.38.31", + "slab", + "tracing", + "windows-sys 0.52.0", +] + [[package]] name = "async-lock" version = "2.8.0" @@ -692,11 +712,11 @@ dependencies = [ [[package]] name = "async-lock" -version = "3.1.1" +version = "3.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "655b9c7fe787d3b25cc0f804a1a8401790f0c5bc395beb5a64dc77d8de079105" +checksum = "d034b430882f8381900d3fe6f0aaa3ad94f2cb4ac519b429692a1bc2dda4ae7b" dependencies = [ - "event-listener 3.1.0", + "event-listener 4.0.3", "event-listener-strategy", "pin-project-lite", ] @@ -719,7 +739,7 @@ dependencies = [ "async-attributes", "async-channel 1.9.0", "async-global-executor", - "async-io", + "async-io 1.13.0", "async-lock 2.8.0", "crossbeam-utils", "futures-channel", @@ -754,26 +774,26 @@ version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" dependencies = [ - "proc-macro2 1.0.69", - "quote 1.0.33", - "syn 2.0.38", + "proc-macro2 1.0.78", + "quote 1.0.35", + "syn 2.0.48", ] [[package]] name = "async-task" -version = "4.5.0" +version = "4.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4eb2cdb97421e01129ccb49169d8279ed21e829929144f4a22a6e54ac549ca1" +checksum = "fbb36e985947064623dbd357f727af08ffd077f93d696782f3c56365fa2e2799" [[package]] name = "async-trait" -version = "0.1.73" +version = "0.1.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc00ceb34980c03614e35a3a4e218276a0a824e911d07651cd0d858a51e8c0f0" +checksum = "c980ee35e870bd1a4d2c8294d4c04d0499e67bca1e4b5cefcc693c2fa00caea9" dependencies = [ - "proc-macro2 1.0.69", - "quote 1.0.33", - "syn 2.0.38", + "proc-macro2 1.0.78", + "quote 1.0.35", + "syn 2.0.48", ] [[package]] @@ -823,6 +843,18 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +[[package]] +name = "backon" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c1a6197b2120bb2185a267f6515038558b019e92b832bb0320e96d66268dcf9" +dependencies = [ + "fastrand 1.9.0", + "futures-core", + "pin-project", + "tokio", +] + [[package]] name = "backtrace" version = "0.3.69" @@ -846,8 +878,8 @@ checksum = "33b8de67cc41132507eeece2584804efcb15f85ba516e34c944b7667f480397a" dependencies = [ "heck 0.3.3", "proc-macro-error", - "proc-macro2 1.0.69", - "quote 1.0.33", + "proc-macro2 1.0.78", + "quote 1.0.35", "syn 1.0.109", ] @@ -865,9 +897,9 @@ checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" [[package]] name = "base64" -version = "0.21.4" +version = "0.21.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ba43ea6f343b788c8764558649e08df62f86c6ef251fdaeb1ffd010a9ae50a2" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" [[package]] name = "base64ct" @@ -889,7 +921,7 @@ name = "bgtask_creator" version = "0.7.12" dependencies = [ "anyhow", - "clap 4.4.8", + "clap 4.4.18", "digital_asset_types", "futures", "lazy_static", @@ -921,9 +953,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.4.0" +version = "2.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635" +checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf" [[package]] name = "bitmaps" @@ -987,9 +1019,9 @@ checksum = "8d696c370c750c948ada61c69a0ee2cbbb9c50b1019ddb86d9317157a99c2cae" [[package]] name = "blockbuster" -version = "0.9.0-beta.5" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a32a0edd58b3aaaf55684bc9ad82e012b3345cb46a25fcae507b3b9034b83d44" +checksum = "92e71e288e73543fddc5c0f099ef7cdca8d01ca278996f73f386b9ab6d65c2b4" dependencies = [ "anchor-lang", "async-trait", @@ -999,14 +1031,12 @@ dependencies = [ "lazy_static", "log", "mpl-bubblegum", - "mpl-candy-guard", - "mpl-candy-machine-core", "mpl-token-metadata", "plerkle_serialization", "solana-sdk", "spl-account-compression", "spl-noop", - "spl-token 4.0.0", + "spl-token", "thiserror", ] @@ -1016,12 +1046,12 @@ version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a37913e8dc4ddcc604f0c6d3bf2887c995153af3611de9e23c352b44c1b9118" dependencies = [ - "async-channel 2.1.0", - "async-lock 3.1.1", + "async-channel 2.1.1", + "async-lock 3.3.0", "async-task", "fastrand 2.0.1", "futures-io", - "futures-lite 2.0.1", + "futures-lite 2.2.0", "piper", "tracing", ] @@ -1046,6 +1076,16 @@ dependencies = [ "hashbrown 0.13.2", ] +[[package]] +name = "borsh" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f58b559fd6448c6e2fd0adb5720cd98a2506594cafa4737ff98c396f3e82f667" +dependencies = [ + "borsh-derive 1.3.1", + "cfg_aliases", +] + [[package]] name = "borsh-derive" version = "0.9.3" @@ -1055,7 +1095,7 @@ dependencies = [ "borsh-derive-internal 0.9.3", "borsh-schema-derive-internal 0.9.3", "proc-macro-crate 0.1.5", - "proc-macro2 1.0.69", + "proc-macro2 1.0.78", "syn 1.0.109", ] @@ -1068,18 +1108,32 @@ dependencies = [ "borsh-derive-internal 0.10.3", "borsh-schema-derive-internal 0.10.3", "proc-macro-crate 0.1.5", - "proc-macro2 1.0.69", + "proc-macro2 1.0.78", "syn 1.0.109", ] +[[package]] +name = "borsh-derive" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7aadb5b6ccbd078890f6d7003694e33816e6b784358f18e15e7e6d9f065a57cd" +dependencies = [ + "once_cell", + "proc-macro-crate 3.1.0", + "proc-macro2 1.0.78", + "quote 1.0.35", + "syn 2.0.48", + "syn_derive", +] + [[package]] name = "borsh-derive-internal" version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5449c28a7b352f2d1e592a8a28bf139bc71afb0764a14f3c02500935d8c44065" dependencies = [ - "proc-macro2 1.0.69", - "quote 1.0.33", + "proc-macro2 1.0.78", + "quote 1.0.35", "syn 1.0.109", ] @@ -1089,8 +1143,8 @@ version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "afb438156919598d2c7bad7e1c0adf3d26ed3840dbc010db1a882a65583ca2fb" dependencies = [ - "proc-macro2 1.0.69", - "quote 1.0.33", + "proc-macro2 1.0.78", + "quote 1.0.35", "syn 1.0.109", ] @@ -1100,8 +1154,8 @@ version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cdbd5696d8bfa21d53d9fe39a714a18538bad11492a42d066dbbc395fb1951c0" dependencies = [ - "proc-macro2 1.0.69", - "quote 1.0.33", + "proc-macro2 1.0.78", + "quote 1.0.35", "syn 1.0.109", ] @@ -1111,8 +1165,8 @@ version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "634205cc43f74a1b9046ef87c4540ebda95696ec0f315024860cad7c5b0f5ccd" dependencies = [ - "proc-macro2 1.0.69", - "quote 1.0.33", + "proc-macro2 1.0.78", + "quote 1.0.35", "syn 1.0.109", ] @@ -1129,9 +1183,9 @@ dependencies = [ [[package]] name = "brotli-decompressor" -version = "2.5.0" +version = "2.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da74e2b81409b1b743f8f0c62cc6254afefb8b8e50bbfe3735550f7aeefa3448" +checksum = "4e2e4afe60d7dd600fdd3de8d0f08c2b7ec039712e3b6137ff98b7004e82de4f" dependencies = [ "alloc-no-stdlib", "alloc-stdlib", @@ -1154,9 +1208,9 @@ dependencies = [ [[package]] name = "bstr" -version = "1.8.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "542f33a8835a0884b006a0c3df3dadd99c0c3f296ed26c2fdc8028e01ad6230c" +checksum = "c48f0051a4b4c5e0b6d365cd04af53aeaa209e3cc15ec2cdb69e73cc87fbd0dc" dependencies = [ "memchr", "serde", @@ -1180,9 +1234,9 @@ dependencies = [ [[package]] name = "bytecheck" -version = "0.6.11" +version = "0.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b6372023ac861f6e6dc89c8344a8f398fb42aaba2b5dbc649ca0c0e9dbcb627" +checksum = "23cdc57ce23ac53c931e88a43d06d070a6fd142f2617be5855eb75efc9beb1c2" dependencies = [ "bytecheck_derive", "ptr_meta", @@ -1191,20 +1245,20 @@ dependencies = [ [[package]] name = "bytecheck_derive" -version = "0.6.11" +version = "0.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7ec4c6f261935ad534c0c22dbef2201b45918860eb1c574b972bd213a76af61" +checksum = "3db406d29fbcd95542e92559bed4d8ad92636d1ca8b3b72ede10b4bcc010e659" dependencies = [ - "proc-macro2 1.0.69", - "quote 1.0.33", + "proc-macro2 1.0.78", + "quote 1.0.35", "syn 1.0.109", ] [[package]] name = "bytemuck" -version = "1.14.0" +version = "1.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "374d28ec25809ee0e23827c2ab573d729e293f281dfe393500e7ad618baa61c6" +checksum = "ed2490600f404f2b94c167e31d3ed1d5f3c225a0f3b80230053b3e0b7b962bd9" dependencies = [ "bytemuck_derive", ] @@ -1215,9 +1269,9 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "965ab7eb5f8f97d2a083c799f3a1b994fc397b2fe2da5d1da1626ce15a39f2b1" dependencies = [ - "proc-macro2 1.0.69", - "quote 1.0.33", - "syn 2.0.38", + "proc-macro2 1.0.78", + "quote 1.0.35", + "syn 2.0.48", ] [[package]] @@ -1276,11 +1330,17 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "cfg_aliases" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" + [[package]] name = "chrono" -version = "0.4.31" +version = "0.4.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f2c685bad3eb3d45a01354cedb7d5faa66194d1d58ba6e267a8de788f79db38" +checksum = "9f13690e35a5e4ace198e7beea2895d29f3a9cc55015fcebe6336bd2010af9eb" dependencies = [ "android-tzdata", "iana-time-zone", @@ -1288,7 +1348,7 @@ dependencies = [ "num-traits", "serde", "wasm-bindgen", - "windows-targets 0.48.5", + "windows-targets 0.52.0", ] [[package]] @@ -1334,9 +1394,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.4.8" +version = "4.4.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2275f18819641850fa26c89acc84d465c1bf91ce57bc2748b28c420473352f64" +checksum = "1e578d6ec4194633722ccf9544794b71b1385c3c027efe0c55db226fc880865c" dependencies = [ "clap_builder", "clap_derive 4.4.7", @@ -1344,9 +1404,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.4.8" +version = "4.4.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07cdf1b148b25c1e1f7a42225e30a0d99a615cd4637eae7365548dd4529b95bc" +checksum = "4df4df40ec50c46000231c914968278b1eb05098cf8f1b3a518a95030e71d1c7" dependencies = [ "anstream", "anstyle", @@ -1362,8 +1422,8 @@ checksum = "ae6371b8bdc8b7d3959e9cf7b22d4435ef3e79e138688421ec654acf8c81b008" dependencies = [ "heck 0.4.1", "proc-macro-error", - "proc-macro2 1.0.69", - "quote 1.0.33", + "proc-macro2 1.0.78", + "quote 1.0.35", "syn 1.0.109", ] @@ -1374,9 +1434,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442" dependencies = [ "heck 0.4.1", - "proc-macro2 1.0.69", - "quote 1.0.33", - "syn 2.0.38", + "proc-macro2 1.0.78", + "quote 1.0.35", + "syn 2.0.48", ] [[package]] @@ -1429,24 +1489,24 @@ dependencies = [ [[package]] name = "concurrent-queue" -version = "2.3.0" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f057a694a54f12365049b0958a1685bb52d567f5593b355fbf685838e873d400" +checksum = "d16048cd947b08fa32c24458a22f5dc5e835264f689f4f5653210c69fd107363" dependencies = [ "crossbeam-utils", ] [[package]] name = "console" -version = "0.15.7" +version = "0.15.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c926e00cc70edefdc64d3a5ff31cc65bb97a3460097762bd23afb4d8145fccf8" +checksum = "0e1f83fc076bd6dd27517eacdf25fef6c4dfe5f1d7448bafaaf3a26f13b5e4eb" dependencies = [ "encode_unicode", "lazy_static", "libc", "unicode-width", - "windows-sys 0.45.0", + "windows-sys 0.52.0", ] [[package]] @@ -1483,9 +1543,9 @@ checksum = "f7144d30dcf0fafbce74250a3963025d8d52177934239851c917d29f1df280c2" [[package]] name = "core-foundation" -version = "0.9.3" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" dependencies = [ "core-foundation-sys", "libc", @@ -1493,15 +1553,15 @@ dependencies = [ [[package]] name = "core-foundation-sys" -version = "0.8.4" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" +checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" [[package]] name = "cpufeatures" -version = "0.2.9" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a17b76ff3a4162b0b27f354a0c87015ddad39d35f9c0c36607a3bdd175dde1f1" +checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" dependencies = [ "libc", ] @@ -1517,9 +1577,9 @@ dependencies = [ [[package]] name = "crc-catalog" -version = "2.2.0" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cace84e55f07e7301bae1c519df89cdad8cc3cd868413d3fdbdeca9ff3db484" +checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" [[package]] name = "crc32fast" @@ -1532,56 +1592,46 @@ dependencies = [ [[package]] name = "crossbeam-channel" -version = "0.5.8" +version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200" +checksum = "176dc175b78f56c0f321911d9c8eb2b77a78a4860b9c19db83835fea1a46649b" dependencies = [ - "cfg-if", "crossbeam-utils", ] [[package]] name = "crossbeam-deque" -version = "0.8.3" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef" +checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" dependencies = [ - "cfg-if", "crossbeam-epoch", "crossbeam-utils", ] [[package]] name = "crossbeam-epoch" -version = "0.9.15" +version = "0.9.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" dependencies = [ - "autocfg", - "cfg-if", "crossbeam-utils", - "memoffset 0.9.0", - "scopeguard", ] [[package]] name = "crossbeam-queue" -version = "0.3.8" +version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1cfb3ea8a53f37c40dea2c7bedcbd88bdfae54f5e2175d6ecaff1c988353add" +checksum = "df0346b5d5e76ac2fe4e327c5fd1118d6be7c51dfb18f9b7922923f287471e35" dependencies = [ - "cfg-if", "crossbeam-utils", ] [[package]] name = "crossbeam-utils" -version = "0.8.16" +version = "0.8.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294" -dependencies = [ - "cfg-if", -] +checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" [[package]] name = "crunchy" @@ -1634,72 +1684,98 @@ dependencies = [ [[package]] name = "darling" -version = "0.13.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a01d95850c592940db9b8194bc39f4bc0e89dee5c4265e4b1807c34a9aba453c" -dependencies = [ - "darling_core 0.13.4", - "darling_macro 0.13.4", -] - -[[package]] -name = "darling" -version = "0.20.3" +version = "0.20.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0209d94da627ab5605dcccf08bb18afa5009cfbef48d8a8b7d7bdbc79be25c5e" +checksum = "fc5d6b04b3fd0ba9926f945895de7d806260a2d7431ba82e7edaecb043c4c6b8" dependencies = [ - "darling_core 0.20.3", - "darling_macro 0.20.3", + "darling_core", + "darling_macro", ] [[package]] name = "darling_core" -version = "0.13.4" +version = "0.20.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "859d65a907b6852c9361e3185c862aae7fafd2887876799fa55f5f99dc40d610" +checksum = "04e48a959bcd5c761246f5d090ebc2fbf7b9cd527a492b07a67510c108f1e7e3" dependencies = [ "fnv", "ident_case", - "proc-macro2 1.0.69", - "quote 1.0.33", + "proc-macro2 1.0.78", + "quote 1.0.35", "strsim 0.10.0", - "syn 1.0.109", + "syn 2.0.48", ] [[package]] -name = "darling_core" -version = "0.20.3" +name = "darling_macro" +version = "0.20.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "177e3443818124b357d8e76f53be906d60937f0d3a90773a664fa63fa253e621" +checksum = "1d1545d67a2149e1d93b7e5c7752dce5a7426eb5d1357ddcfd89336b94444f77" dependencies = [ - "fnv", - "ident_case", - "proc-macro2 1.0.69", - "quote 1.0.33", - "strsim 0.10.0", - "syn 2.0.38", + "darling_core", + "quote 1.0.35", + "syn 2.0.48", ] [[package]] -name = "darling_macro" -version = "0.13.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c972679f83bdf9c42bd905396b6c3588a843a17f0f16dfcfa3e2c5d57441835" +name = "das-core" +version = "0.7.2" dependencies = [ - "darling_core 0.13.4", - "quote 1.0.33", - "syn 1.0.109", + "anyhow", + "cadence", + "cadence-macros", + "clap 4.4.18", + "sqlx", ] [[package]] -name = "darling_macro" -version = "0.20.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "836a9bbc7ad63342d6d6e7b815ccab164bc77a2d95d84bc3117a8c0d5c98e2d5" +name = "das-ops" +version = "0.7.2" dependencies = [ - "darling_core 0.20.3", - "quote 1.0.33", - "syn 2.0.38", + "anchor-client", + "anchor-lang", + "anyhow", + "backon", + "base64 0.21.7", + "borsh 0.10.3", + "bs58 0.4.0", + "cadence", + "cadence-macros", + "chrono", + "clap 4.4.18", + "das-core", + "digital_asset_types", + "env_logger 0.10.2", + "figment", + "flatbuffers", + "futures", + "futures-util", + "indicatif", + "lazy_static", + "log", + "mpl-bubblegum", + "plerkle_messenger", + "plerkle_serialization", + "redis", + "regex", + "reqwest", + "rust-crypto", + "sea-orm", + "sea-query 0.28.5", + "serde", + "serde_json", + "solana-account-decoder", + "solana-client", + "solana-sdk", + "solana-transaction-status", + "spl-account-compression", + "spl-concurrent-merkle-tree", + "sqlx", + "thiserror", + "tokio", + "tokio-postgres", + "url", + "uuid", ] [[package]] @@ -1713,7 +1789,7 @@ dependencies = [ "cadence", "cadence-macros", "digital_asset_types", - "env_logger 0.10.0", + "env_logger 0.10.2", "figment", "hyper", "jsonrpsee", @@ -1721,8 +1797,6 @@ dependencies = [ "log", "metrics", "mpl-bubblegum", - "mpl-candy-guard", - "mpl-candy-machine-core", "mpl-token-metadata", "open-rpc-derive", "open-rpc-schema", @@ -1741,11 +1815,24 @@ dependencies = [ "tracing", ] +[[package]] +name = "dashmap" +version = "5.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" +dependencies = [ + "cfg-if", + "hashbrown 0.14.3", + "lock_api", + "once_cell", + "parking_lot_core 0.9.9", +] + [[package]] name = "data-encoding" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2e66c9d817f1720209181c316d28635c050fa304f9c79e47a520882661b7308" +checksum = "7e962a19be5cfc3f3bf6dd8f61eb50107f356ad6270fbb3ed41476571db78be5" [[package]] name = "der" @@ -1772,10 +1859,11 @@ dependencies = [ [[package]] name = "deranged" -version = "0.3.8" +version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2696e8a945f658fd14dc3b87242e6b80cd0f36ff04ea560fa39082368847946" +checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" dependencies = [ + "powerfmt", "serde", ] @@ -1791,16 +1879,16 @@ version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" dependencies = [ - "proc-macro2 1.0.69", - "quote 1.0.33", + "proc-macro2 1.0.78", + "quote 1.0.35", "syn 1.0.109", ] [[package]] name = "deunicode" -version = "1.4.1" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a1abaf4d861455be59f64fd2b55606cb151fce304ede7165f410243ce96bde6" +checksum = "3ae2a35373c5c74340b79ae6780b498b2b183915ec5dacf263aac5a099bf485a" [[package]] name = "dialoguer" @@ -1889,9 +1977,9 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d" dependencies = [ - "proc-macro2 1.0.69", - "quote 1.0.33", - "syn 2.0.38", + "proc-macro2 1.0.78", + "quote 1.0.35", + "syn 2.0.48", ] [[package]] @@ -1925,9 +2013,9 @@ checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b" [[package]] name = "dyn-clone" -version = "1.0.14" +version = "1.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23d2f3407d9a573d666de4b5bdf10569d73ca9478087346697dcbae6244bfbcd" +checksum = "545b22097d44f8a9581187cdf93de7a71e4722bf51200cfaba810865b49a495d" [[package]] name = "eager" @@ -1996,22 +2084,22 @@ dependencies = [ [[package]] name = "enum-iterator" -version = "1.4.1" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7add3873b5dd076766ee79c8e406ad1a472c385476b9e38849f8eec24f1be689" +checksum = "9fd242f399be1da0a5354aa462d57b4ab2b4ee0683cc552f7c007d2d12d36e94" dependencies = [ "enum-iterator-derive", ] [[package]] name = "enum-iterator-derive" -version = "1.2.1" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eecf8589574ce9b895052fa12d69af7a233f99e6107f5cb8dd1044f2a17bfdcb" +checksum = "03cdc46ec28bd728e67540c528013c6a10eb69a02eb31078a1bda695438cbfb8" dependencies = [ - "proc-macro2 1.0.69", - "quote 1.0.33", - "syn 2.0.38", + "proc-macro2 1.0.78", + "quote 1.0.35", + "syn 2.0.48", ] [[package]] @@ -2029,9 +2117,9 @@ dependencies = [ [[package]] name = "env_logger" -version = "0.10.0" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85cdab6a89accf66733ad5a1693a4dcced6aeff64602b634530dd73c1f3ee9f0" +checksum = "4cd405aab171cb85d6735e5c8d9db038c17d3ca007a4d2c25f337935c3d90580" dependencies = [ "humantime", "is-terminal", @@ -2048,12 +2136,12 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "errno" -version = "0.3.5" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3e13f66a2f95e32a39eaa81f6b95d42878ca0e1db0c7543723dfe12557e860" +checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" dependencies = [ "libc", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -2064,9 +2152,9 @@ checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" [[package]] name = "event-listener" -version = "3.1.0" +version = "4.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d93877bcde0eb80ca09131a08d23f0a5c18a620b01db137dba666d18cd9b30c2" +checksum = "67b215c49b2b248c855fb73579eb1f4f26c38ffdc12973e20e07b91d78d5646e" dependencies = [ "concurrent-queue", "parking", @@ -2075,19 +2163,19 @@ dependencies = [ [[package]] name = "event-listener-strategy" -version = "0.3.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d96b852f1345da36d551b9473fa1e2b1eb5c5195585c6c018118bc92a8d91160" +checksum = "958e4d70b6d5e81971bebec42271ec641e7ff4e170a6fa605f2b8a8b65cb97d3" dependencies = [ - "event-listener 3.1.0", + "event-listener 4.0.3", "pin-project-lite", ] [[package]] name = "fake" -version = "2.9.1" +version = "2.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26221445034074d46b276e13eb97a265ebdb8ed8da705c4dddd3dd20b66b45d2" +checksum = "1c25829bde82205da46e1823b2259db6273379f626fc211f126f65654a2669be" dependencies = [ "deunicode", "rand 0.8.5", @@ -2127,7 +2215,7 @@ dependencies = [ "anyhow", "async-trait", "borsh 0.10.3", - "clap 4.4.8", + "clap 4.4.18", "mpl-bubblegum", "solana-account-decoder", "solana-client", @@ -2138,15 +2226,15 @@ dependencies = [ [[package]] name = "figment" -version = "0.10.11" +version = "0.10.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a014ac935975a70ad13a3bff2463b1c1b083b35ae4cb6309cfc59476aa7a181f" +checksum = "2b6e5bc7bd59d60d0d45a6ccab6cf0f4ce28698fb4e81e750ddf229c9b824026" dependencies = [ "atomic 0.6.0", "pear", "serde", "serde_yaml", - "toml 0.8.8", + "toml 0.8.10", "uncased", "version_check", ] @@ -2169,9 +2257,9 @@ dependencies = [ [[package]] name = "flate2" -version = "1.0.27" +version = "1.0.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6c98ee8095e9d1dcbf2fcc6d95acccb90d1c81db1e44725c6a984b1dbdfb010" +checksum = "46303f565772937ffe1d394a4fac6f411c6013172fadde9dcdb1e147a086940e" dependencies = [ "crc32fast", "miniz_oxide", @@ -2200,9 +2288,9 @@ checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" [[package]] name = "form_urlencoded" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" dependencies = [ "percent-encoding", ] @@ -2213,6 +2301,21 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" +[[package]] +name = "function_name" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1ab577a896d09940b5fe12ec5ae71f9d8211fff62c919c03a3750a9901e98a7" +dependencies = [ + "function_name-proc-macro", +] + +[[package]] +name = "function_name-proc-macro" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "673464e1e314dd67a0fd9544abc99e8eb28d0c7e3b69b033bcff9b2d00b87333" + [[package]] name = "funty" version = "2.0.0" @@ -2221,9 +2324,9 @@ checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" [[package]] name = "futures" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23342abe12aba583913b2e62f22225ff9c950774065e4bfb61a19cd9770fec40" +checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" dependencies = [ "futures-channel", "futures-core", @@ -2236,9 +2339,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2" +checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" dependencies = [ "futures-core", "futures-sink", @@ -2246,15 +2349,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c" +checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" [[package]] name = "futures-executor" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccecee823288125bd88b4d7f565c9e58e41858e47ab72e8ea2d64e93624386e0" +checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" dependencies = [ "futures-core", "futures-task", @@ -2274,9 +2377,9 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964" +checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" [[package]] name = "futures-lite" @@ -2295,46 +2398,45 @@ dependencies = [ [[package]] name = "futures-lite" -version = "2.0.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3831c2651acb5177cbd83943f3d9c8912c5ad03c76afcc0e9511ba568ec5ebb" +checksum = "445ba825b27408685aaecefd65178908c36c6e96aaf6d8599419d46e624192ba" dependencies = [ "fastrand 2.0.1", "futures-core", "futures-io", - "memchr", "parking", "pin-project-lite", ] [[package]] name = "futures-macro" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" +checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ - "proc-macro2 1.0.69", - "quote 1.0.33", - "syn 2.0.38", + "proc-macro2 1.0.78", + "quote 1.0.35", + "syn 2.0.48", ] [[package]] name = "futures-sink" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e" +checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" [[package]] name = "futures-task" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65" +checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" [[package]] name = "futures-util" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533" +checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" dependencies = [ "futures-channel", "futures-core", @@ -2390,9 +2492,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.10" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" +checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" dependencies = [ "cfg-if", "js-sys", @@ -2403,21 +2505,21 @@ dependencies = [ [[package]] name = "gimli" -version = "0.28.0" +version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" [[package]] name = "globset" -version = "0.4.13" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "759c97c1e17c55525b57192c06a267cda0ac5210b222d6b82189a2338fa1c13d" +checksum = "57da3b9b5b85bd66f31093f8c408b90a74431672542466497dcbdfdc02034be1" dependencies = [ "aho-corasick", "bstr", - "fnv", "log", - "regex", + "regex-automata 0.4.5", + "regex-syntax 0.8.2", ] [[package]] @@ -2445,9 +2547,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.3.21" +version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91fc23aa11be92976ef4729127f1a74adf36d8436f7816b185d18df956790833" +checksum = "bb2c4422095b67ee78da96fbb51a4cc413b3b25883c7717ff7ca1ab31022c9c9" dependencies = [ "bytes", "fnv", @@ -2455,7 +2557,7 @@ dependencies = [ "futures-sink", "futures-util", "http", - "indexmap 1.9.3", + "indexmap 2.2.2", "slab", "tokio", "tokio-util", @@ -2477,7 +2579,7 @@ version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" dependencies = [ - "ahash 0.7.6", + "ahash 0.7.7", ] [[package]] @@ -2486,7 +2588,7 @@ version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" dependencies = [ - "ahash 0.7.6", + "ahash 0.7.7", ] [[package]] @@ -2495,16 +2597,16 @@ version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" dependencies = [ - "ahash 0.8.3", + "ahash 0.8.7", ] [[package]] name = "hashbrown" -version = "0.14.1" +version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7dfda62a12f55daeae5015f81b0baea145391cb4520f86c248fc615d72640d12" +checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" dependencies = [ - "ahash 0.8.3", + "ahash 0.8.7", "allocator-api2", ] @@ -2514,7 +2616,7 @@ version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e8094feaf31ff591f651a2664fb9cfd92bba7a60ce3197265e9482ebe753c8f7" dependencies = [ - "hashbrown 0.14.1", + "hashbrown 0.14.3", ] [[package]] @@ -2546,9 +2648,9 @@ dependencies = [ [[package]] name = "hermit-abi" -version = "0.3.3" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7" +checksum = "d0c62115964e08cb8039170eb33c1d0e2388a256930279edca206fff675f82c3" [[package]] name = "hex" @@ -2564,9 +2666,9 @@ checksum = "12cb882ccb290b8646e554b157ab0b71e64e8d5bef775cd66b6531e52d302669" [[package]] name = "hkdf" -version = "0.12.3" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "791a029f6b9fc27657f6f188ec6e5e43f6911f6f878e0dc5501396e09809d437" +checksum = "7b5f8eb2ad728638ea2c7d47a21db23b7b58a72ed6a38256b8a1849f15fbbdf7" dependencies = [ "hmac 0.12.1", ] @@ -2603,9 +2705,9 @@ dependencies = [ [[package]] name = "http" -version = "0.2.9" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd6effc99afb63425aff9b05836f029929e345a6148a14b7ecd5ab67af944482" +checksum = "8947b1a6fad4393052c7ba1f4cd97bed3e953a95c79c92ad9b051a04611d9fbb" dependencies = [ "bytes", "fnv", @@ -2614,9 +2716,9 @@ dependencies = [ [[package]] name = "http-body" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" +checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" dependencies = [ "bytes", "http", @@ -2649,9 +2751,9 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "hyper" -version = "0.14.27" +version = "0.14.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffb1cfd654a8219eaef89881fdb3bb3b1cdc5fa75ded05d6933b2b382e395468" +checksum = "bf96e135eb83a2a8ddf766e426a841d8ddd7449d5f00d34ea02b41d2f19eef80" dependencies = [ "bytes", "futures-channel", @@ -2664,7 +2766,7 @@ dependencies = [ "httpdate", "itoa", "pin-project-lite", - "socket2 0.4.9", + "socket2 0.5.5", "tokio", "tower-service", "tracing", @@ -2673,14 +2775,14 @@ dependencies = [ [[package]] name = "hyper-rustls" -version = "0.24.1" +version = "0.24.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d78e1e73ec14cf7375674f74d7dde185c8206fd9dea6fb6295e8a98098aaa97" +checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" dependencies = [ "futures-util", "http", "hyper", - "rustls 0.21.7", + "rustls 0.21.10", "tokio", "tokio-rustls 0.24.1", ] @@ -2700,16 +2802,16 @@ dependencies = [ [[package]] name = "iana-time-zone" -version = "0.1.57" +version = "0.1.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fad5b825842d2b38bd206f3e81d6957625fd7f0a361e345c30e01a0ae2dd613" +checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" dependencies = [ "android_system_properties", "core-foundation-sys", "iana-time-zone-haiku", "js-sys", "wasm-bindgen", - "windows", + "windows-core", ] [[package]] @@ -2729,9 +2831,9 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" [[package]] name = "idna" -version = "0.4.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c" +checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" dependencies = [ "unicode-bidi", "unicode-normalization", @@ -2761,16 +2863,18 @@ checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" dependencies = [ "autocfg", "hashbrown 0.12.3", + "serde", ] [[package]] name = "indexmap" -version = "2.0.2" +version = "2.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8adf3ddd720272c6ea8bf59463c04e0f93d0bbf7c5439b691bca2987e0270897" +checksum = "824b2ae422412366ba479e8111fd301f7b5faece8149317bb81925979a53f520" dependencies = [ "equivalent", - "hashbrown 0.14.1", + "hashbrown 0.14.3", + "serde", ] [[package]] @@ -2782,7 +2886,7 @@ dependencies = [ "console", "instant", "number_prefix", - "portable-atomic 1.4.3", + "portable-atomic 1.6.0", "unicode-width", ] @@ -2792,6 +2896,20 @@ version = "0.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c8fae54786f62fb2918dcfae3d568594e50eb9b5c25bf04371af6fe7516452fb" +[[package]] +name = "insta" +version = "1.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d64600be34b2fcfc267740a243fa7744441bb4947a619ac4e5bb6507f35fbfc" +dependencies = [ + "console", + "lazy_static", + "linked-hash-map", + "serde", + "similar", + "yaml-rust", +] + [[package]] name = "instant" version = "0.1.12" @@ -2801,32 +2919,68 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "integration_tests" +version = "0.1.0" +dependencies = [ + "anyhow", + "borsh 0.10.3", + "das_api", + "digital_asset_types", + "env_logger 0.10.2", + "figment", + "flatbuffers", + "function_name", + "futures-util", + "insta", + "itertools 0.10.5", + "log", + "migration", + "mpl-token-metadata", + "nft_ingester", + "once_cell", + "plerkle_messenger", + "plerkle_serialization", + "sea-orm", + "serde", + "serde_json", + "serial_test", + "solana-account-decoder", + "solana-client", + "solana-sdk", + "solana-transaction-status", + "spl-token", + "sqlx", + "tokio", + "tokio-stream", +] + [[package]] name = "io-lifetimes" version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" dependencies = [ - "hermit-abi 0.3.3", + "hermit-abi 0.3.5", "libc", "windows-sys 0.48.0", ] [[package]] name = "ipnet" -version = "2.8.0" +version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28b29a3cd74f0f4598934efe3aeba42bae0eb4680554128851ebbecb02af14e6" +checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" [[package]] name = "is-terminal" -version = "0.4.9" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" +checksum = "0bad00257d07be169d870ab665980b06cdb366d792ad690bf2e76876dc503455" dependencies = [ - "hermit-abi 0.3.3", - "rustix 0.38.18", - "windows-sys 0.48.0", + "hermit-abi 0.3.5", + "rustix 0.38.31", + "windows-sys 0.52.0", ] [[package]] @@ -2840,33 +2994,33 @@ dependencies = [ [[package]] name = "itertools" -version = "0.11.0" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" dependencies = [ "either", ] [[package]] name = "itoa" -version = "1.0.9" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" +checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" [[package]] name = "jobserver" -version = "0.1.26" +version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "936cfd212a0155903bcbc060e316fb6cc7cbf2e1907329391ebadc1fe0ce77c2" +checksum = "8c37f63953c4c63420ed5fd3d6d398c719489b9f872b9fa683262f8edd363c7d" dependencies = [ "libc", ] [[package]] name = "js-sys" -version = "0.3.64" +version = "0.3.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a" +checksum = "406cda4b368d531c842222cf9d2600a9a4acce8d29423695379c6868a143a9ee" dependencies = [ "wasm-bindgen", ] @@ -2944,8 +3098,8 @@ checksum = "44e8ab85614a08792b9bff6c8feee23be78c98d0182d4c622c05256ab553892a" dependencies = [ "heck 0.4.1", "proc-macro-crate 1.3.1", - "proc-macro2 1.0.69", - "quote 1.0.33", + "proc-macro2 1.0.78", + "quote 1.0.35", "syn 1.0.109", ] @@ -2987,18 +3141,18 @@ dependencies = [ [[package]] name = "kaigan" -version = "0.2.2" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a26f49495f94a283312e7ef45a243540ef20c9356bb01c8d84a61ac8ba5339b" +checksum = "e623cca1f0e2a0919032c1bdabbf81dd9aa34658d5066aca7bb90d608317ab91" dependencies = [ "borsh 0.10.3", ] [[package]] name = "keccak" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f6d5ed8676d904364de097082f4e7d240b571b67989ced0240f08b7f966f940" +checksum = "ecc2af9a1119c51f12a14607e783cb977bde58bc069ff0c3da1095e635d70654" dependencies = [ "cpufeatures", ] @@ -3020,9 +3174,20 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.149" +version = "0.2.153" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" + +[[package]] +name = "libredox" +version = "0.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a08173bc88b7955d1b3145aa561539096c421ac8debde8cbc3612ec635fee29b" +checksum = "85c833ca1e66078851dba29046874e38f08b2c883700aa29a03ddd3b23814ee8" +dependencies = [ + "bitflags 2.4.2", + "libc", + "redox_syscall 0.4.1", +] [[package]] name = "libsecp256k1" @@ -3072,6 +3237,12 @@ dependencies = [ "libsecp256k1-core", ] +[[package]] +name = "linked-hash-map" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" + [[package]] name = "linux-raw-sys" version = "0.3.8" @@ -3080,9 +3251,9 @@ checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" [[package]] name = "linux-raw-sys" -version = "0.4.10" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da2479e8c062e40bf0066ffa0bc823de0a9368974af99c9f6df941d2c231e03f" +checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" [[package]] name = "load_generation" @@ -3095,15 +3266,15 @@ dependencies = [ "solana-program", "solana-sdk", "spl-associated-token-account", - "spl-token 4.0.0", + "spl-token", "tokio", ] [[package]] name = "lock_api" -version = "0.4.10" +version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16" +checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" dependencies = [ "autocfg", "scopeguard", @@ -3139,9 +3310,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.6.4" +version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" +checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" [[package]] name = "memmap2" @@ -3200,7 +3371,7 @@ version = "0.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7b9b8653cec6897f73b519a43fba5ee3d50f62fe9af80b428accdcc093b4a849" dependencies = [ - "ahash 0.7.6", + "ahash 0.7.7", "metrics-macros", "portable-atomic 0.3.20", ] @@ -3211,8 +3382,8 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "731f8ecebd9f3a4aa847dfe75455e4757a45da40a7793d2f0b1f9b6ed18b23f3" dependencies = [ - "proc-macro2 1.0.69", - "quote 1.0.33", + "proc-macro2 1.0.78", + "quote 1.0.35", "syn 1.0.109", ] @@ -3250,18 +3421,18 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" +checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" dependencies = [ "adler", ] [[package]] name = "mio" -version = "0.8.8" +version = "0.8.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2" +checksum = "8f3d0b296e374a4e6f3c7b0a1f5a51d748a0d34c85e7dc48fc3fa9a87657fe09" dependencies = [ "libc", "wasi 0.11.0+wasi-snapshot-preview1", @@ -3270,9 +3441,9 @@ dependencies = [ [[package]] name = "mpl-bubblegum" -version = "1.0.1-beta.4" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e59d102fe6f8b063a06a226874ea815b269316390ce3bf991b29ea9c54ccc467" +checksum = "b3cbca5deb859e66a1a21ada94f2eaab3eb5caa4584c0c8ade0efac29a5414b8" dependencies = [ "borsh 0.10.3", "kaigan", @@ -3282,122 +3453,21 @@ dependencies = [ "thiserror", ] -[[package]] -name = "mpl-candy-guard" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59c5c2ffb233226e0c531f1cf800909e46120e98722eeb53dae68b0996303a38" -dependencies = [ - "anchor-lang", - "arrayref", - "mpl-candy-guard-derive", - "mpl-candy-machine-core", - "mpl-token-auth-rules", - "mpl-token-metadata", - "solana-gateway", - "solana-program", - "spl-associated-token-account", - "spl-token 4.0.0", - "spl-token-2022 0.9.0", -] - -[[package]] -name = "mpl-candy-guard-derive" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18e4d3002ea881e94a238798faf87a006a687297a24bd4b3f810fbb63611173d" -dependencies = [ - "quote 1.0.33", - "syn 1.0.109", -] - -[[package]] -name = "mpl-candy-machine-core" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4db99e1aac3bdebf907338aec5f1785701b8a82e6bdac5f42a270750d37c5264" -dependencies = [ - "anchor-lang", - "arrayref", - "mpl-token-auth-rules", - "mpl-token-metadata", - "solana-program", - "spl-associated-token-account", - "spl-token 4.0.0", -] - -[[package]] -name = "mpl-token-auth-rules" -version = "1.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66b1ec5ee0570f688cc84ff4624c5c50732f1a2bfc789f6b34af5b563428d971" -dependencies = [ - "borsh 0.10.3", - "bytemuck", - "mpl-token-metadata-context-derive 0.2.1", - "num-derive 0.3.3", - "num-traits", - "rmp-serde", - "serde", - "shank", - "solana-program", - "solana-zk-token-sdk", - "thiserror", -] - [[package]] name = "mpl-token-metadata" -version = "2.0.0-beta.1" +version = "4.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3545bd5fe73416f6514cd93899612e0e138619e72df8bc7d19906a12688c69e" +checksum = "b4b2de608098eb2ef2a5392069dea83084967e25a4d69d0380a6bb02454fc0fe" dependencies = [ - "arrayref", "borsh 0.10.3", - "mpl-token-auth-rules", - "mpl-token-metadata-context-derive 0.3.0", - "mpl-utils", "num-derive 0.3.3", "num-traits", "serde", - "serde_with 1.14.0", - "shank", + "serde_with 3.6.0", "solana-program", - "spl-associated-token-account", - "spl-token 4.0.0", "thiserror", ] -[[package]] -name = "mpl-token-metadata-context-derive" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12989bc45715b0ee91944855130131479f9c772e198a910c3eb0ea327d5bffc3" -dependencies = [ - "quote 1.0.33", - "syn 1.0.109", -] - -[[package]] -name = "mpl-token-metadata-context-derive" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5a739019e11d93661a64ef5fe108ab17c79b35961e944442ff6efdd460ad01a" -dependencies = [ - "quote 1.0.33", - "syn 1.0.109", -] - -[[package]] -name = "mpl-utils" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f2e4f92aec317d5853c0cc4c03c55f5178511c45bb3dbb441aea63117bf3dc9" -dependencies = [ - "arrayref", - "solana-program", - "spl-token-2022 0.6.1", -] - [[package]] name = "native-tls" version = "0.2.11" @@ -3422,16 +3492,16 @@ version = "0.7.2" dependencies = [ "anchor-lang", "async-trait", - "base64 0.21.4", + "base64 0.21.7", "blockbuster", "borsh 0.10.3", "bs58 0.4.0", "cadence", "cadence-macros", "chrono", - "clap 4.4.8", + "clap 4.4.18", "digital_asset_types", - "env_logger 0.10.0", + "env_logger 0.10.2", "figment", "flatbuffers", "futures", @@ -3461,7 +3531,7 @@ dependencies = [ "solana-transaction-status", "spl-account-compression", "spl-concurrent-merkle-tree", - "spl-token 4.0.0", + "spl-token", "sqlx", "stretto", "thiserror", @@ -3552,26 +3622,32 @@ dependencies = [ "num-traits", ] +[[package]] +name = "num-conv" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" + [[package]] name = "num-derive" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "876a53fff98e03a936a674b29568b0e605f06b29372c2489ff4de23f1949743d" dependencies = [ - "proc-macro2 1.0.69", - "quote 1.0.33", + "proc-macro2 1.0.78", + "quote 1.0.35", "syn 1.0.109", ] [[package]] name = "num-derive" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfb77679af88f8b125209d354a202862602672222e7f2313fdd6dc349bad4712" +checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" dependencies = [ - "proc-macro2 1.0.69", - "quote 1.0.33", - "syn 2.0.38", + "proc-macro2 1.0.78", + "quote 1.0.35", + "syn 2.0.48", ] [[package]] @@ -3622,19 +3698,10 @@ version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" dependencies = [ - "hermit-abi 0.3.3", + "hermit-abi 0.3.5", "libc", ] -[[package]] -name = "num_enum" -version = "0.5.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f646caf906c20226733ed5b1374287eb97e3c2a5c227ce668c1f2ce20ae57c9" -dependencies = [ - "num_enum_derive 0.5.11", -] - [[package]] name = "num_enum" version = "0.6.1" @@ -3646,23 +3713,11 @@ dependencies = [ [[package]] name = "num_enum" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70bf6736f74634d299d00086f02986875b3c2d924781a6a2cb6c201e73da0ceb" -dependencies = [ - "num_enum_derive 0.7.0", -] - -[[package]] -name = "num_enum_derive" -version = "0.5.11" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcbff9bc912032c62bf65ef1d5aea88983b420f4f839db1e9b0c281a25c9c799" +checksum = "02339744ee7253741199f897151b38e72257d13802d4ee837285cc2990a90845" dependencies = [ - "proc-macro-crate 1.3.1", - "proc-macro2 1.0.69", - "quote 1.0.33", - "syn 1.0.109", + "num_enum_derive 0.7.2", ] [[package]] @@ -3672,21 +3727,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96667db765a921f7b295ffee8b60472b686a51d4f21c2ee4ffdb94c7013b65a6" dependencies = [ "proc-macro-crate 1.3.1", - "proc-macro2 1.0.69", - "quote 1.0.33", - "syn 2.0.38", + "proc-macro2 1.0.78", + "quote 1.0.35", + "syn 2.0.48", ] [[package]] name = "num_enum_derive" -version = "0.7.0" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56ea360eafe1022f7cc56cd7b869ed57330fb2453d0c7831d99b74c65d2f5597" +checksum = "681030a937600a36906c185595136d26abfebb4aa9c65701cefcaf8578bb982b" dependencies = [ - "proc-macro-crate 1.3.1", - "proc-macro2 1.0.69", - "quote 1.0.33", - "syn 2.0.38", + "proc-macro-crate 3.1.0", + "proc-macro2 1.0.78", + "quote 1.0.35", + "syn 2.0.48", ] [[package]] @@ -3697,9 +3752,9 @@ checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" [[package]] name = "object" -version = "0.32.1" +version = "0.32.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0" +checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" dependencies = [ "memchr", ] @@ -3715,9 +3770,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.18.0" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" [[package]] name = "opaque-debug" @@ -3732,8 +3787,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ae3de03a56750973a83c76a40fb4b81969d42fad152cd0e787e25c79dcf54e3f" dependencies = [ "open-rpc-schema", - "proc-macro2 1.0.69", - "quote 1.0.33", + "proc-macro2 1.0.78", + "quote 1.0.35", "syn 1.0.109", ] @@ -3751,11 +3806,11 @@ dependencies = [ [[package]] name = "openssl" -version = "0.10.57" +version = "0.10.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bac25ee399abb46215765b1cb35bc0212377e58a061560d8b29b024fd0430e7c" +checksum = "15c9d69dd87a29568d4d017cfe8ec518706046a05184e5aea92d0af890b803c8" dependencies = [ - "bitflags 2.4.0", + "bitflags 2.4.2", "cfg-if", "foreign-types", "libc", @@ -3770,9 +3825,9 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ - "proc-macro2 1.0.69", - "quote 1.0.33", - "syn 2.0.38", + "proc-macro2 1.0.78", + "quote 1.0.35", + "syn 2.0.48", ] [[package]] @@ -3783,9 +3838,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-sys" -version = "0.9.93" +version = "0.9.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db4d56a4c0478783083cfafcc42493dd4a981d41669da64b4572a2a089b51b1d" +checksum = "22e1bf214306098e4832460f797824c05d25aacdf896f64a985fb0fd992454ae" dependencies = [ "cc", "libc", @@ -3817,8 +3872,8 @@ checksum = "5f7d21ccd03305a674437ee1248f3ab5d4b1db095cf1caf49f1713ddf61956b7" dependencies = [ "Inflector", "proc-macro-error", - "proc-macro2 1.0.69", - "quote 1.0.33", + "proc-macro2 1.0.78", + "quote 1.0.35", "syn 1.0.109", ] @@ -3852,7 +3907,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" dependencies = [ "lock_api", - "parking_lot_core 0.9.8", + "parking_lot_core 0.9.9", ] [[package]] @@ -3871,13 +3926,13 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.8" +version = "0.9.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447" +checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.3.5", + "redox_syscall 0.4.1", "smallvec", "windows-targets 0.48.5", ] @@ -3908,9 +3963,9 @@ dependencies = [ [[package]] name = "pear" -version = "0.2.7" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61a386cd715229d399604b50d1361683fe687066f42d56f54be995bc6868f71c" +checksum = "4ccca0f6c17acc81df8e242ed473ec144cbf5c98037e69aa6d144780aad103c8" dependencies = [ "inlinable_string", "pear_codegen", @@ -3919,14 +3974,14 @@ dependencies = [ [[package]] name = "pear_codegen" -version = "0.2.7" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da9f0f13dac8069c139e8300a6510e3f4143ecf5259c60b116a9b271b4ca0d54" +checksum = "2e22670e8eb757cff11d6c199ca7b987f352f0346e0be4dd23869ec72cb53c77" dependencies = [ - "proc-macro2 1.0.69", + "proc-macro2 1.0.78", "proc-macro2-diagnostics", - "quote 1.0.33", - "syn 2.0.38", + "quote 1.0.35", + "syn 2.0.48", ] [[package]] @@ -3940,9 +3995,9 @@ dependencies = [ [[package]] name = "percent-encoding" -version = "2.3.0" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "percentage" @@ -3971,6 +4026,26 @@ dependencies = [ "siphasher", ] +[[package]] +name = "pin-project" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0302c4a0442c456bd56f841aee5c3bfd17967563f6fadc9ceb9f9c23cf3807e0" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "266c042b60c9c76b8d53061e52b2e0d1116abc57cefc8c5cd671619a56ac3690" +dependencies = [ + "proc-macro2 1.0.78", + "quote 1.0.35", + "syn 2.0.48", +] + [[package]] name = "pin-project-lite" version = "0.2.13" @@ -4007,9 +4082,9 @@ dependencies = [ [[package]] name = "pkg-config" -version = "0.3.27" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" +checksum = "2900ede94e305130c13ddd391e0ab7cbaeb783945ae07a279c268cb05109c6cb" [[package]] name = "plain" @@ -4067,6 +4142,20 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "polling" +version = "3.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30054e72317ab98eddd8561db0f6524df3367636884b7b21b703e4b280a84a14" +dependencies = [ + "cfg-if", + "concurrent-queue", + "pin-project-lite", + "rustix 0.38.31", + "tracing", + "windows-sys 0.52.0", +] + [[package]] name = "polyval" version = "0.5.3" @@ -4085,14 +4174,14 @@ version = "0.3.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e30165d31df606f5726b090ec7592c308a0eaf61721ff64c9a3018e344a8753e" dependencies = [ - "portable-atomic 1.4.3", + "portable-atomic 1.6.0", ] [[package]] name = "portable-atomic" -version = "1.4.3" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31114a898e107c51bb1609ffaf55a0e011cf6a4d7f1170d0015a165082c0338b" +checksum = "7170ef9988bc169ba16dd36a7fa041e5c4cbeb6a35b76d4c03daded371eae7c0" [[package]] name = "postgres-protocol" @@ -4100,7 +4189,7 @@ version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49b6c5ef183cd3ab4ba005f1ca64c21e8bd97ce4699cfea9e8d9a2c4958ca520" dependencies = [ - "base64 0.21.4", + "base64 0.21.7", "byteorder", "bytes", "fallible-iterator", @@ -4123,6 +4212,12 @@ dependencies = [ "postgres-protocol", ] +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + [[package]] name = "ppv-lite86" version = "0.2.17" @@ -4148,6 +4243,15 @@ dependencies = [ "toml_edit 0.19.15", ] +[[package]] +name = "proc-macro-crate" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d37c51ca738a55da99dc0c4a34860fd675453b8b36209178c2249bb13651284" +dependencies = [ + "toml_edit 0.21.1", +] + [[package]] name = "proc-macro-error" version = "1.0.4" @@ -4155,8 +4259,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" dependencies = [ "proc-macro-error-attr", - "proc-macro2 1.0.69", - "quote 1.0.33", + "proc-macro2 1.0.78", + "quote 1.0.35", "syn 1.0.109", "version_check", ] @@ -4167,8 +4271,8 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" dependencies = [ - "proc-macro2 1.0.69", - "quote 1.0.33", + "proc-macro2 1.0.78", + "quote 1.0.35", "version_check", ] @@ -4183,9 +4287,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.69" +version = "1.0.78" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da" +checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae" dependencies = [ "unicode-ident", ] @@ -4196,9 +4300,9 @@ version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "af066a9c399a26e020ada66a034357a868728e72cd426f3adcd35f80d88d88c8" dependencies = [ - "proc-macro2 1.0.69", - "quote 1.0.33", - "syn 2.0.38", + "proc-macro2 1.0.78", + "quote 1.0.35", + "syn 2.0.48", "version_check", "yansi", ] @@ -4249,8 +4353,8 @@ version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "16b845dbfca988fa33db069c0e230574d15a3088f147a87b64c7589eb662c9ac" dependencies = [ - "proc-macro2 1.0.69", - "quote 1.0.33", + "proc-macro2 1.0.78", + "quote 1.0.35", "syn 1.0.109", ] @@ -4308,7 +4412,7 @@ checksum = "641538578b21f5e5c8ea733b736895576d0fe329bb883b937db6f4d163dbaaf4" dependencies = [ "libc", "quinn-proto", - "socket2 0.4.9", + "socket2 0.4.10", "tracing", "windows-sys 0.42.0", ] @@ -4324,11 +4428,11 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.33" +version = "1.0.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" dependencies = [ - "proc-macro2 1.0.69", + "proc-macro2 1.0.78", ] [[package]] @@ -4434,7 +4538,7 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom 0.2.10", + "getrandom 0.2.12", ] [[package]] @@ -4457,9 +4561,9 @@ dependencies = [ [[package]] name = "rayon" -version = "1.8.0" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c27db03db7734835b3f53954b534c91069375ce6ccaa2e065441e07d9b6cdb1" +checksum = "fa7237101a77a10773db45d62004a272517633fbcc3df19d96455ede1122e051" dependencies = [ "either", "rayon-core", @@ -4467,9 +4571,9 @@ dependencies = [ [[package]] name = "rayon-core" -version = "1.12.0" +version = "1.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ce3fb6ad83f861aac485e76e1985cd109d9a3713802152be56c3b1f0e0658ed" +checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" dependencies = [ "crossbeam-deque", "crossbeam-utils", @@ -4483,7 +4587,7 @@ checksum = "ffbe84efe2f38dea12e9bfc1f65377fdf03e53a18cb3b995faedf7934c7e785b" dependencies = [ "pem", "ring 0.16.20", - "time 0.3.29", + "time 0.3.34", "yasna", ] @@ -4531,34 +4635,34 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.3.5" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" +checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" dependencies = [ "bitflags 1.3.2", ] [[package]] name = "redox_users" -version = "0.4.3" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" +checksum = "a18479200779601e498ada4e8c1e1f50e3ee19deb0259c25825a98b5603b2cb4" dependencies = [ - "getrandom 0.2.10", - "redox_syscall 0.2.16", + "getrandom 0.2.12", + "libredox", "thiserror", ] [[package]] name = "regex" -version = "1.9.6" +version = "1.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebee201405406dbf528b8b672104ae6d6d63e6d118cb10e4d51abbc7b58044ff" +checksum = "b62dbe01f0b06f9d8dc7d49e05a0785f153b00b2c227856282f671e0318c9b15" dependencies = [ "aho-corasick", "memchr", - "regex-automata 0.3.9", - "regex-syntax 0.7.5", + "regex-automata 0.4.5", + "regex-syntax 0.8.2", ] [[package]] @@ -4572,13 +4676,13 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.3.9" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59b23e92ee4318893fa3fe3e6fb365258efbfe6ac6ab30f090cdcbb7aa37efa9" +checksum = "5bb987efffd3c6d0d8f5f89510bb458559eab11e4f869acb20bf845e016259cd" dependencies = [ "aho-corasick", "memchr", - "regex-syntax 0.7.5", + "regex-syntax 0.8.2", ] [[package]] @@ -4589,27 +4693,27 @@ checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" [[package]] name = "regex-syntax" -version = "0.7.5" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da" +checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" [[package]] name = "rend" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2571463863a6bd50c32f94402933f03457a3fbaf697a707c5be741e459f08fd" +checksum = "71fe3824f5629716b1589be05dacd749f6aa084c87e00e016714a8cdfccc997c" dependencies = [ "bytecheck", ] [[package]] name = "reqwest" -version = "0.11.22" +version = "0.11.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "046cd98826c46c2ac8ddecae268eb5c2e58628688a5fc7a2643704a73faba95b" +checksum = "c6920094eb85afde5e4a138be3f2de8bbdf28000f0029e72c45025a56b042251" dependencies = [ "async-compression", - "base64 0.21.4", + "base64 0.21.7", "bytes", "encoding_rs", "futures-core", @@ -4628,11 +4732,12 @@ dependencies = [ "once_cell", "percent-encoding", "pin-project-lite", - "rustls 0.21.7", + "rustls 0.21.10", "rustls-pemfile", "serde", "serde_json", "serde_urlencoded", + "sync_wrapper", "system-configuration", "tokio", "tokio-native-tls", @@ -4643,7 +4748,7 @@ dependencies = [ "wasm-bindgen", "wasm-bindgen-futures", "web-sys", - "webpki-roots 0.25.2", + "webpki-roots 0.25.4", "winreg", ] @@ -4664,12 +4769,12 @@ dependencies = [ [[package]] name = "ring" -version = "0.17.2" +version = "0.17.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "911b295d2d302948838c8ac142da1ee09fa7863163b44e6715bc9357905878b8" +checksum = "688c63d65483050968b2a8937f7995f443e27041a0f7700aa59b0822aedebb74" dependencies = [ "cc", - "getrandom 0.2.10", + "getrandom 0.2.12", "libc", "spin 0.9.8", "untrusted 0.9.0", @@ -4678,52 +4783,31 @@ dependencies = [ [[package]] name = "rkyv" -version = "0.7.42" +version = "0.7.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0200c8230b013893c0b2d6213d6ec64ed2b9be2e0e016682b7224ff82cff5c58" +checksum = "5cba464629b3394fc4dbc6f940ff8f5b4ff5c7aef40f29166fd4ad12acbc99c0" dependencies = [ "bitvec", "bytecheck", - "hashbrown 0.12.3", - "ptr_meta", - "rend", - "rkyv_derive", - "seahash", - "tinyvec", - "uuid", -] - -[[package]] -name = "rkyv_derive" -version = "0.7.42" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2e06b915b5c230a17d7a736d1e2e63ee753c256a8614ef3f5147b13a4f5541d" -dependencies = [ - "proc-macro2 1.0.69", - "quote 1.0.33", - "syn 1.0.109", -] - -[[package]] -name = "rmp" -version = "0.8.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f9860a6cc38ed1da53456442089b4dfa35e7cedaa326df63017af88385e6b20" -dependencies = [ - "byteorder", - "num-traits", - "paste", + "bytes", + "hashbrown 0.12.3", + "ptr_meta", + "rend", + "rkyv_derive", + "seahash", + "tinyvec", + "uuid", ] [[package]] -name = "rmp-serde" -version = "1.1.2" +name = "rkyv_derive" +version = "0.7.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bffea85eea980d8a74453e5d02a8d93028f3c34725de143085a844ebe953258a" +checksum = "a7dddfff8de25e6f62b9d64e6e432bf1c6736c57d20323e15ee10435fbda7c65" dependencies = [ - "byteorder", - "rmp", - "serde", + "proc-macro2 1.0.78", + "quote 1.0.35", + "syn 1.0.109", ] [[package]] @@ -4762,12 +4846,12 @@ dependencies = [ [[package]] name = "rust_decimal" -version = "1.32.0" +version = "1.34.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4c4216490d5a413bc6d10fa4742bd7d4955941d062c0ef873141d6b0e7b30fd" +checksum = "755392e1a2f77afd95580d3f0d0e94ac83eeeb7167552c9b5bca549e61a94d83" dependencies = [ "arrayvec", - "borsh 0.10.3", + "borsh 1.3.1", "bytes", "num-traits", "rand 0.8.5", @@ -4790,9 +4874,9 @@ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" [[package]] name = "rustc-serialize" -version = "0.3.24" +version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" +checksum = "fe834bc780604f4674073badbad26d7219cadfb4a2275802db12cbae17498401" [[package]] name = "rustc_version" @@ -4828,15 +4912,15 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.18" +version = "0.38.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a74ee2d7c2581cd139b42447d7d9389b889bdaad3a73f1ebb16f2a3237bb19c" +checksum = "6ea3e1a662af26cd7a3ba09c0297a31af215563ecf42817c98df621387f4e949" dependencies = [ - "bitflags 2.4.0", + "bitflags 2.4.2", "errno", "libc", - "linux-raw-sys 0.4.10", - "windows-sys 0.48.0", + "linux-raw-sys 0.4.13", + "windows-sys 0.52.0", ] [[package]] @@ -4853,12 +4937,12 @@ dependencies = [ [[package]] name = "rustls" -version = "0.21.7" +version = "0.21.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd8d6c9f025a446bc4d18ad9632e69aec8f287aa84499ee335599fabd20c3fd8" +checksum = "f9d5a6813c0759e4609cd494e8e725babae6a2ca7b62a5536a13daaec6fcb7ba" dependencies = [ "log", - "ring 0.16.20", + "ring 0.17.7", "rustls-webpki", "sct", ] @@ -4877,21 +4961,21 @@ dependencies = [ [[package]] name = "rustls-pemfile" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d3987094b1d07b653b7dfdc3f70ce9a1da9c51ac18c1b06b662e4f9a0e9f4b2" +checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" dependencies = [ - "base64 0.21.4", + "base64 0.21.7", ] [[package]] name = "rustls-webpki" -version = "0.101.6" +version = "0.101.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c7d5dece342910d9ba34d259310cae3e0154b873b35408b787b59bce53d34fe" +checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" dependencies = [ - "ring 0.16.20", - "untrusted 0.7.1", + "ring 0.17.7", + "untrusted 0.9.0", ] [[package]] @@ -4902,24 +4986,24 @@ checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" [[package]] name = "ryu" -version = "1.0.15" +version = "1.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" +checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c" [[package]] name = "schannel" -version = "0.1.22" +version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c3733bf4cf7ea0880754e19cb5a462007c4a8c1914bff372ccc95b464f1df88" +checksum = "fbc91545643bcf3a0bbb6569265615222618bdf33ce4ffbbd13c4bbd4c093534" dependencies = [ - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] name = "schemars" -version = "0.8.15" +version = "0.8.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f7b0ce13155372a76ee2e1c5ffba1fe61ede73fbea5630d61eee6fac4929c0c" +checksum = "45a28f4c49489add4ce10783f7911893516f15afe45d015608d41faca6bc4d29" dependencies = [ "dyn-clone", "schemars_derive", @@ -4929,12 +5013,12 @@ dependencies = [ [[package]] name = "schemars_derive" -version = "0.8.15" +version = "0.8.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e85e2a16b12bdb763244c69ab79363d71db2b4b918a2def53f80b02e0574b13c" +checksum = "c767fd6fa65d9ccf9cf026122c1b555f2ef9a4f0cea69da4d7dbc3e258d30967" dependencies = [ - "proc-macro2 1.0.69", - "quote 1.0.33", + "proc-macro2 1.0.78", + "quote 1.0.35", "serde_derive_internals", "syn 1.0.109", ] @@ -4960,19 +5044,19 @@ version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1db149f81d46d2deba7cd3c50772474707729550221e69588478ebf9ada425ae" dependencies = [ - "proc-macro2 1.0.69", - "quote 1.0.33", - "syn 2.0.38", + "proc-macro2 1.0.78", + "quote 1.0.35", + "syn 2.0.48", ] [[package]] name = "sct" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4" +checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" dependencies = [ - "ring 0.16.20", - "untrusted 0.7.1", + "ring 0.17.7", + "untrusted 0.9.0", ] [[package]] @@ -4997,7 +5081,7 @@ dependencies = [ "serde_json", "sqlx", "thiserror", - "time 0.3.29", + "time 0.3.34", "tracing", "url", "uuid", @@ -5027,8 +5111,8 @@ checksum = "7216195de9c6b2474fd0efab486173dccd0eff21f28cc54aa4c0205d52fb3af0" dependencies = [ "bae", "heck 0.3.3", - "proc-macro2 1.0.69", - "quote 1.0.33", + "proc-macro2 1.0.78", + "quote 1.0.35", "syn 1.0.109", ] @@ -5058,7 +5142,7 @@ dependencies = [ "rust_decimal", "sea-query-derive 0.2.0", "serde_json", - "time 0.3.29", + "time 0.3.34", "uuid", ] @@ -5082,7 +5166,7 @@ dependencies = [ "sea-query 0.27.2", "serde_json", "sqlx", - "time 0.3.29", + "time 0.3.34", "uuid", ] @@ -5093,8 +5177,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34cdc022b4f606353fe5dc85b09713a04e433323b70163e81513b141c6ae6eb5" dependencies = [ "heck 0.3.3", - "proc-macro2 1.0.69", - "quote 1.0.33", + "proc-macro2 1.0.78", + "quote 1.0.35", "syn 1.0.109", "thiserror", ] @@ -5106,8 +5190,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "63f62030c60f3a691f5fe251713b4e220b306e50a71e1d6f9cce1f24bb781978" dependencies = [ "heck 0.4.1", - "proc-macro2 1.0.69", - "quote 1.0.33", + "proc-macro2 1.0.78", + "quote 1.0.35", "syn 1.0.109", "thiserror", ] @@ -5130,8 +5214,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56821b7076f5096b8f726e2791ad255a99c82498e08ec477a65a96c461ff1927" dependencies = [ "heck 0.3.3", - "proc-macro2 1.0.69", - "quote 1.0.33", + "proc-macro2 1.0.78", + "quote 1.0.35", "syn 1.0.109", ] @@ -5151,8 +5235,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69b4397b825df6ccf1e98bcdabef3bbcfc47ff5853983467850eeab878384f21" dependencies = [ "heck 0.3.3", - "proc-macro2 1.0.69", - "quote 1.0.33", + "proc-macro2 1.0.78", + "quote 1.0.35", "rustversion", "syn 1.0.109", ] @@ -5188,37 +5272,37 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.19" +version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad977052201c6de01a8ef2aa3378c4bd23217a056337d1d6da40468d267a4fb0" +checksum = "b97ed7a9823b74f99c7742f5336af7be5ecd3eeafcb1507d1fa93347b1d589b0" [[package]] name = "serde" -version = "1.0.188" +version = "1.0.196" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf9e0fcba69a370eed61bcf2b728575f726b50b55cba78064753d708ddc7549e" +checksum = "870026e60fa08c69f064aa766c10f10b1d62db9ccd4d0abb206472bee0ce3b32" dependencies = [ "serde_derive", ] [[package]] name = "serde_bytes" -version = "0.11.12" +version = "0.11.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab33ec92f677585af6d88c65593ae2375adde54efdbf16d597f2cbc7a6d368ff" +checksum = "8b8497c313fd43ab992087548117643f6fcd935cbf36f176ffda0aacf9591734" dependencies = [ "serde", ] [[package]] name = "serde_derive" -version = "1.0.188" +version = "1.0.196" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2" +checksum = "33c85360c95e7d137454dc81d9a4ed2b8efd8fbe19cee57357b32b9771fccb67" dependencies = [ - "proc-macro2 1.0.69", - "quote 1.0.33", - "syn 2.0.38", + "proc-macro2 1.0.78", + "quote 1.0.35", + "syn 2.0.48", ] [[package]] @@ -5227,18 +5311,18 @@ version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85bf8229e7920a9f636479437026331ce11aa132b4dde37d121944a44d6e5f3c" dependencies = [ - "proc-macro2 1.0.69", - "quote 1.0.33", + "proc-macro2 1.0.78", + "quote 1.0.35", "syn 1.0.109", ] [[package]] name = "serde_json" -version = "1.0.107" +version = "1.0.113" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b420ce6e3d8bd882e9b243c6eed35dbc9a6110c9769e74b584e0d68d1f20c65" +checksum = "69801b70b1c3dac963ecb03a364ba0ceda9cf60c71cfe475e99864759c8b8a79" dependencies = [ - "indexmap 2.0.2", + "indexmap 2.2.2", "itoa", "ryu", "serde", @@ -5246,9 +5330,9 @@ dependencies = [ [[package]] name = "serde_spanned" -version = "0.6.4" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12022b835073e5b11e90a14f86838ceb1c8fb0325b72416845c487ac0fa95e80" +checksum = "eb3622f419d1296904700073ea6cc23ad690adbd66f13ea683df73298736f0c1" dependencies = [ "serde", ] @@ -5267,61 +5351,93 @@ dependencies = [ [[package]] name = "serde_with" -version = "1.14.0" +version = "2.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "678b5a069e50bf00ecd22d0cd8ddf7c236f68581b03db652061ed5eb13a312ff" +checksum = "07ff71d2c147a7b57362cead5e22f772cd52f6ab31cfcd9edcd7f6aeb2a0afbe" dependencies = [ "serde", - "serde_with_macros 1.5.2", + "serde_with_macros 2.3.3", ] [[package]] name = "serde_with" -version = "2.3.3" +version = "3.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07ff71d2c147a7b57362cead5e22f772cd52f6ab31cfcd9edcd7f6aeb2a0afbe" +checksum = "1b0ed1662c5a68664f45b76d18deb0e234aff37207086803165c961eb695e981" dependencies = [ + "base64 0.21.7", + "chrono", + "hex", + "indexmap 1.9.3", + "indexmap 2.2.2", "serde", - "serde_with_macros 2.3.3", + "serde_json", + "serde_with_macros 3.6.0", + "time 0.3.34", ] [[package]] name = "serde_with_macros" -version = "1.5.2" +version = "2.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e182d6ec6f05393cc0e5ed1bf81ad6db3a8feedf8ee515ecdd369809bcce8082" +checksum = "881b6f881b17d13214e5d494c939ebab463d01264ce1811e9d4ac3a882e7695f" dependencies = [ - "darling 0.13.4", - "proc-macro2 1.0.69", - "quote 1.0.33", - "syn 1.0.109", + "darling", + "proc-macro2 1.0.78", + "quote 1.0.35", + "syn 2.0.48", ] [[package]] name = "serde_with_macros" -version = "2.3.3" +version = "3.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "881b6f881b17d13214e5d494c939ebab463d01264ce1811e9d4ac3a882e7695f" +checksum = "568577ff0ef47b879f736cd66740e022f3672788cdf002a05a4e609ea5a6fb15" dependencies = [ - "darling 0.20.3", - "proc-macro2 1.0.69", - "quote 1.0.33", - "syn 2.0.38", + "darling", + "proc-macro2 1.0.78", + "quote 1.0.35", + "syn 2.0.48", ] [[package]] name = "serde_yaml" -version = "0.9.25" +version = "0.9.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a49e178e4452f45cb61d0cd8cebc1b0fafd3e41929e996cef79aa3aca91f574" +checksum = "adf8a49373e98a4c5f0ceb5d05aa7c648d75f63774981ed95b7c7443bbd50c6e" dependencies = [ - "indexmap 2.0.2", + "indexmap 2.2.2", "itoa", "ryu", "serde", "unsafe-libyaml", ] +[[package]] +name = "serial_test" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e56dd856803e253c8f298af3f4d7eb0ae5e23a737252cd90bb4f3b435033b2d" +dependencies = [ + "dashmap", + "futures", + "lazy_static", + "log", + "parking_lot 0.12.1", + "serial_test_derive", +] + +[[package]] +name = "serial_test_derive" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91d129178576168c589c9ec973feedf7d3126c01ac2bf08795109aa35b69fb8f" +dependencies = [ + "proc-macro2 1.0.78", + "quote 1.0.35", + "syn 2.0.48", +] + [[package]] name = "sha-1" version = "0.9.8" @@ -5409,40 +5525,6 @@ dependencies = [ "keccak", ] -[[package]] -name = "shank" -version = "0.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b63e565b5e95ad88ab38f312e89444c749360641c509ef2de0093b49f55974a5" -dependencies = [ - "shank_macro", -] - -[[package]] -name = "shank_macro" -version = "0.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63927d22a1e8b74bda98cc6e151fcdf178b7abb0dc6c4f81e0bbf5ffe2fc4ec8" -dependencies = [ - "proc-macro2 1.0.69", - "quote 1.0.33", - "shank_macro_impl", - "syn 1.0.109", -] - -[[package]] -name = "shank_macro_impl" -version = "0.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40ce03403df682f80f4dc1efafa87a4d0cb89b03726d0565e6364bdca5b9a441" -dependencies = [ - "anyhow", - "proc-macro2 1.0.69", - "quote 1.0.33", - "serde", - "syn 1.0.109", -] - [[package]] name = "sharded-slab" version = "0.1.7" @@ -5479,6 +5561,12 @@ version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f27f6278552951f1f2b8cf9da965d10969b2efdea95a6ec47987ab46edfe263a" +[[package]] +name = "similar" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32fea41aca09ee824cc9724996433064c89f7777e60762749a4170a14abbfa21" + [[package]] name = "siphasher" version = "0.3.11" @@ -5506,15 +5594,15 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.11.1" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "942b4a808e05215192e39f4ab80813e599068285906cc91aa64f923db842bd5a" +checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7" [[package]] name = "socket2" -version = "0.4.9" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662" +checksum = "9f7916fc008ca5542385b89a3d3ce689953c143e9304a9bf8beec1de48994c0d" dependencies = [ "libc", "winapi", @@ -5522,9 +5610,9 @@ dependencies = [ [[package]] name = "socket2" -version = "0.5.4" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4031e820eb552adee9295814c0ced9e5cf38ddf1e8b7d566d6de8e2538ea989e" +checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9" dependencies = [ "libc", "windows-sys 0.48.0", @@ -5548,12 +5636,12 @@ dependencies = [ [[package]] name = "solana-account-decoder" -version = "1.16.16" +version = "1.16.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f52aec62a85932e26d1085864b0f7b99b31934aec8dd132429bfef6d7fb1d3a6" +checksum = "b5763ba7519b166b152ca2c6f8defa22cd07d3aea42a3a86b74519857fc3d464" dependencies = [ "Inflector", - "base64 0.21.4", + "base64 0.21.7", "bincode", "bs58 0.4.0", "bv", @@ -5564,8 +5652,8 @@ dependencies = [ "solana-address-lookup-table-program", "solana-config-program", "solana-sdk", - "spl-token 4.0.0", - "spl-token-2022 0.9.0", + "spl-token", + "spl-token-2022", "spl-token-metadata-interface", "thiserror", "zstd", @@ -5573,9 +5661,9 @@ dependencies = [ [[package]] name = "solana-address-lookup-table-program" -version = "1.16.16" +version = "1.16.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee0bd25f4ba0a15fc16c57b41b1e1b14f5271b83214fda158fdedb58758d394e" +checksum = "18a216474b9d25153d629aa7f4fb2246bc875ebe90e1155380e0436c209e62d5" dependencies = [ "bincode", "bytemuck", @@ -5594,9 +5682,9 @@ dependencies = [ [[package]] name = "solana-clap-utils" -version = "1.16.16" +version = "1.16.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e963043668c640183d48472b281ebb9f713e0c36df0271961d23e6a394e09070" +checksum = "2bef7e2234cf1179b8ceadfae922d38d79f82932a762ff62b0051e0b3205984f" dependencies = [ "chrono", "clap 2.34.0", @@ -5612,9 +5700,9 @@ dependencies = [ [[package]] name = "solana-client" -version = "1.16.16" +version = "1.16.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52ccf7bb34fb81c74582a9011babaa2e0220da56c71186e77f45a6f352017fdb" +checksum = "2644f5a0c91f8c44db175d35d52bf772799597dbedf6a5d9f138d61e2b52b826" dependencies = [ "async-trait", "bincode", @@ -5645,9 +5733,9 @@ dependencies = [ [[package]] name = "solana-config-program" -version = "1.16.16" +version = "1.16.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fd0fc1efb91a1661aeb1ff6a691156c3b1bffdaed0aa096589499dd83f9e50b" +checksum = "3bb9b6d2c575e1eecd85380cb6442525a0d2639afa627552264eaa7050f47fb3" dependencies = [ "bincode", "chrono", @@ -5659,9 +5747,9 @@ dependencies = [ [[package]] name = "solana-connection-cache" -version = "1.16.16" +version = "1.16.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8759e9cb9b1e92a94c31812169ecb5e65b5e215fb70fb68691e03655de5b7b6c" +checksum = "dcd27f413c3702ee20bbf1152e928f9adff0a37fef0f36b956d4eb34aae2be71" dependencies = [ "async-trait", "bincode", @@ -5680,11 +5768,11 @@ dependencies = [ [[package]] name = "solana-frozen-abi" -version = "1.16.16" +version = "1.16.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02eb4f0ed3eade20f4abdcc0031167344237cd6e16808bd0f33945f9db7861fe" +checksum = "a7077f6495ccc313dff49c3e3f3ed03e49058258bae7fee77ac29ba0a474ba82" dependencies = [ - "ahash 0.8.3", + "ahash 0.8.7", "blake3", "block-buffer 0.10.4", "bs58 0.4.0", @@ -5713,34 +5801,21 @@ dependencies = [ [[package]] name = "solana-frozen-abi-macro" -version = "1.16.16" +version = "1.16.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f28514761a285944cbad5b3d7930546369b80a713ba37d84bcf6ed2753611765" +checksum = "f516f992211a2ab70de5c367190575c97e02d156f9f1d8b76886d673f30e88a2" dependencies = [ - "proc-macro2 1.0.69", - "quote 1.0.33", + "proc-macro2 1.0.78", + "quote 1.0.35", "rustc_version", - "syn 2.0.38", -] - -[[package]] -name = "solana-gateway" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d148eb75d0799f6825dc2a840b85c065e3d6d12212845add3e059163f98770e" -dependencies = [ - "borsh 0.10.3", - "num-derive 0.4.1", - "num-traits", - "solana-program", - "thiserror", + "syn 2.0.48", ] [[package]] name = "solana-geyser-plugin-interface" -version = "1.16.16" +version = "1.16.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "512372f741974113777872cecd560beee189cf79c3fb2eb84e1c28be69f011d1" +checksum = "57308818e006abd20d06b49a658f2affc8efee446a7f5ea96c02418af96b3476" dependencies = [ "log", "solana-sdk", @@ -5750,9 +5825,9 @@ dependencies = [ [[package]] name = "solana-logger" -version = "1.16.16" +version = "1.16.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c310c6749435ce1ea25a9ae3edfb2fd2c2aed2aa4d4f7e0487a8077a0b1ee30" +checksum = "7b64def674bfaa4a3f8be7ba19c03c9caec4ec028ba62b9a427ec1bf608a2486" dependencies = [ "env_logger 0.9.3", "lazy_static", @@ -5761,9 +5836,9 @@ dependencies = [ [[package]] name = "solana-measure" -version = "1.16.16" +version = "1.16.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d171357580e62aa4ca19c780e25f4e74de064e2780cb8b9f6b6901d986fcd23" +checksum = "932db6604bcf8ba3bba68e80564d7eaa0dd7b9667407e15c3557caa83203aee7" dependencies = [ "log", "solana-sdk", @@ -5771,9 +5846,9 @@ dependencies = [ [[package]] name = "solana-metrics" -version = "1.16.16" +version = "1.16.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "013cbb3c82588278d2be18d3317ece5286cb54a3a06d5d38fc31e2a76a6d5e2d" +checksum = "5d81931f224798c0e52062b0683a07eebe1c1904954c8765773c9802a28fbd0c" dependencies = [ "crossbeam-channel", "gethostname", @@ -5785,9 +5860,9 @@ dependencies = [ [[package]] name = "solana-net-utils" -version = "1.16.16" +version = "1.16.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c50d7cac0694b1fe07499de25404a0c7d6836457e359aba3b08c3983c3dc5eb6" +checksum = "7ea3420fa9da3789548f31b3c68e6a090bfd1320c735289851b711546d38e3b0" dependencies = [ "bincode", "clap 3.2.25", @@ -5797,7 +5872,7 @@ dependencies = [ "rand 0.7.3", "serde", "serde_derive", - "socket2 0.4.9", + "socket2 0.4.10", "solana-logger", "solana-sdk", "solana-version", @@ -5807,11 +5882,11 @@ dependencies = [ [[package]] name = "solana-perf" -version = "1.16.16" +version = "1.16.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "395d559e5be2c439551298e9fa95561807f24921fd9a1e08bb82a3dc05c02dea" +checksum = "5859de708bd12fb189f3c161cda03fdd341ffcf6be4fe787c7d730a30d589ac6" dependencies = [ - "ahash 0.8.3", + "ahash 0.8.7", "bincode", "bv", "caps", @@ -5834,16 +5909,16 @@ dependencies = [ [[package]] name = "solana-program" -version = "1.16.16" +version = "1.16.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cff2aa5434a77413e9d43e971ceb47bdb003f2e8bbc0365a25b684aca2605c25" +checksum = "3e92350aa5b42564681655331e7e0b9d5c99a442de317ceeb4741efbbe9a6c05" dependencies = [ "ark-bn254", "ark-ec", "ark-ff", "ark-serialize", "array-bytes", - "base64 0.21.4", + "base64 0.21.7", "bincode", "bitflags 1.3.2", "blake3", @@ -5856,7 +5931,7 @@ dependencies = [ "console_error_panic_hook", "console_log", "curve25519-dalek", - "getrandom 0.2.10", + "getrandom 0.2.12", "itertools 0.10.5", "js-sys", "lazy_static", @@ -5889,11 +5964,11 @@ dependencies = [ [[package]] name = "solana-program-runtime" -version = "1.16.16" +version = "1.16.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d1832fefc2187142dac169812518ec20da68b09abad86e4a78f8ae1787e4f56" +checksum = "3da0e9dd63326ded2055b42e54aa37baa6aeb8adaea658a0059c234af6d05c02" dependencies = [ - "base64 0.21.4", + "base64 0.21.7", "bincode", "eager", "enum-iterator", @@ -5917,9 +5992,9 @@ dependencies = [ [[package]] name = "solana-pubsub-client" -version = "1.16.16" +version = "1.16.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89388addbc3192407d948634f82c95c4dbe1efbe578582abfd136720e059556e" +checksum = "b9d1ad6fa8f0e154b91e67969fdf5478e74b75a87d5e3dce14ab83f4cb2f60f1" dependencies = [ "crossbeam-channel", "futures-util", @@ -5942,9 +6017,9 @@ dependencies = [ [[package]] name = "solana-quic-client" -version = "1.16.16" +version = "1.16.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7897b876a6df2d97b3a5ddfd764155c0591e3497e863fd7fdf32b54de4e2644" +checksum = "de9426ee9c0f98522242d6656db18175a022959af0b8ed3f170729e29933cf08" dependencies = [ "async-mutex", "async-trait", @@ -5970,9 +6045,9 @@ dependencies = [ [[package]] name = "solana-rayon-threadlimit" -version = "1.16.16" +version = "1.16.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ba17a930f9974a17a9a6c6e82e7f89b40127e9cc0f9c17cfc29fc5b149d2c38" +checksum = "c3e6c7a43e34d7db0ad158690b331df15b92f6996e3b9b03629591a54fc3e97f" dependencies = [ "lazy_static", "num_cpus", @@ -5980,9 +6055,9 @@ dependencies = [ [[package]] name = "solana-remote-wallet" -version = "1.16.16" +version = "1.16.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80fb35e3fa78ef1d08a6a1d852e2c357e6ae388cb307d24fad359f57c34429f0" +checksum = "ed87a28ede1536be71352e13965b1fe7a2cf205e3e4fae2eef8a3407219ba1cd" dependencies = [ "console", "dialoguer", @@ -5999,12 +6074,12 @@ dependencies = [ [[package]] name = "solana-rpc-client" -version = "1.16.16" +version = "1.16.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c512944689d747a87f76936c89bb59f5be6c9a3189631857f49746cfa47d5bd1" +checksum = "f273acbce4493bc1de8174b94cfaee112b72263ae1684a6e13890f5004be53fb" dependencies = [ "async-trait", - "base64 0.21.4", + "base64 0.21.7", "bincode", "bs58 0.4.0", "indicatif", @@ -6025,11 +6100,11 @@ dependencies = [ [[package]] name = "solana-rpc-client-api" -version = "1.16.16" +version = "1.16.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e918b75f8ac4c358a6b512bf8b7dafc8166ddcb52ded5164c6235e0693ccb09" +checksum = "4462198830687b83870985db945c5d49c720d83abf516c8206fefba12cca689d" dependencies = [ - "base64 0.21.4", + "base64 0.21.7", "bs58 0.4.0", "jsonrpc-core", "reqwest", @@ -6041,15 +6116,15 @@ dependencies = [ "solana-sdk", "solana-transaction-status", "solana-version", - "spl-token-2022 0.9.0", + "spl-token-2022", "thiserror", ] [[package]] name = "solana-rpc-client-nonce-utils" -version = "1.16.16" +version = "1.16.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6e360ea2f3a756bdf6256c1f6ef13f8b01b5d2a7855b4f16cafb4a4017f0557" +checksum = "91b3abad7b1ffd4b29d33b7525ebbc2ec8d0ca5928e4d8f28e364928d68a8dd9" dependencies = [ "clap 2.34.0", "solana-clap-utils", @@ -6060,12 +6135,12 @@ dependencies = [ [[package]] name = "solana-sdk" -version = "1.16.16" +version = "1.16.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b1002048941cedbd7dd6a96fdaa3dc5238b998aaa70b81946b1e3ec108cc2be" +checksum = "2087e15c92d4d6b3f085dc12fbe9614141c811f90a54cc418240ac30b608133f" dependencies = [ "assert_matches", - "base64 0.21.4", + "base64 0.21.7", "bincode", "bitflags 1.3.2", "borsh 0.10.3", @@ -6113,22 +6188,22 @@ dependencies = [ [[package]] name = "solana-sdk-macro" -version = "1.16.16" +version = "1.16.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b41b63b2da4a37ce323aba108db21f4c7bfa638dd1bf58fdc870f83bdce48ba" +checksum = "2e0e0e7ee984b0f9179a1d4f4e9e67ce675de2324b5a98b61d2bdb61be3c19bb" dependencies = [ "bs58 0.4.0", - "proc-macro2 1.0.69", - "quote 1.0.33", + "proc-macro2 1.0.78", + "quote 1.0.35", "rustversion", - "syn 2.0.38", + "syn 2.0.48", ] [[package]] name = "solana-streamer" -version = "1.16.16" +version = "1.16.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f00e575f2bd5ae2776870fbd1d7379d4ad392c015e2a4e2a328953b821a9d36d" +checksum = "a868a782cab696677cd12deacda1862dbeeba903a4a8d8404a4d6bf45e8a556c" dependencies = [ "async-channel 1.9.0", "bytes", @@ -6159,9 +6234,9 @@ dependencies = [ [[package]] name = "solana-thin-client" -version = "1.16.16" +version = "1.16.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df328e2624cce68c9949a53eac317a264eceb997131cb9bd22175698a5f5dc74" +checksum = "222f5539a4b01a5374c919e78aca5d4472fa5af6e551bf9f4ddd97ca59374f6d" dependencies = [ "bincode", "log", @@ -6174,9 +6249,9 @@ dependencies = [ [[package]] name = "solana-tpu-client" -version = "1.16.16" +version = "1.16.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a8ce6fe221c0e1fd8aa3078b8fcb0cc3f4c27942f1256b57a60608d81ae5348" +checksum = "8c0f954b48dda0a907dbdb54387459c8eb7e9c702f278bf70a2caf3ebc417c88" dependencies = [ "async-trait", "bincode", @@ -6199,12 +6274,12 @@ dependencies = [ [[package]] name = "solana-transaction-status" -version = "1.16.16" +version = "1.16.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db0b811793e78a908119cc02edca3ff8b54d5660104ebd06cc0e2e7e2f66900b" +checksum = "7992d9605a65967b5e40e6ef8e285a953888e4789f0f5e3fb7339bf018cbb677" dependencies = [ "Inflector", - "base64 0.21.4", + "base64 0.21.7", "bincode", "borsh 0.10.3", "bs58 0.4.0", @@ -6217,17 +6292,17 @@ dependencies = [ "solana-address-lookup-table-program", "solana-sdk", "spl-associated-token-account", - "spl-memo 4.0.0", - "spl-token 4.0.0", - "spl-token-2022 0.9.0", + "spl-memo", + "spl-token", + "spl-token-2022", "thiserror", ] [[package]] name = "solana-udp-client" -version = "1.16.16" +version = "1.16.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "897ff303a15ba956e80573dee4cf96d94d41a69adc5362898b98851e347505ad" +checksum = "4329dfe364cb276c7137b459e3737a27d6ae180f60d0aa2274d8be86cac3472c" dependencies = [ "async-trait", "solana-connection-cache", @@ -6240,9 +6315,9 @@ dependencies = [ [[package]] name = "solana-version" -version = "1.16.16" +version = "1.16.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9513754d3b2203a0e1045a211c5d68e72e4ed135e477344c21d096897fd2bf70" +checksum = "1931390daf0938c072c167611a263a8b95c13476d7fff7c8eb12789a981685b3" dependencies = [ "log", "rustc_version", @@ -6256,9 +6331,9 @@ dependencies = [ [[package]] name = "solana-vote-program" -version = "1.16.16" +version = "1.16.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b6bfc5302ce0383eb129aa3a916705a20d22c4ad448144ef684b7b028d4053f" +checksum = "25669860e2c5e821a8caa5372589289fbb6ac3084096133fdd1c6af6546536a2" dependencies = [ "bincode", "log", @@ -6278,12 +6353,12 @@ dependencies = [ [[package]] name = "solana-zk-token-sdk" -version = "1.16.16" +version = "1.16.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d1fe77918563768a65fd5d6cd2fa06cf0aeb11e529a1ef8c230b0fe018600e3" +checksum = "1457c85ab70a518438b9ac2b0c56037b9f6693060dfb617bbb93c7116e4f0c22" dependencies = [ "aes-gcm-siv", - "base64 0.21.4", + "base64 0.21.7", "bincode", "bytemuck", "byteorder", @@ -6366,11 +6441,11 @@ checksum = "385e31c29981488f2820b2022d8e731aae3b02e6e18e2fd854e4c9a94dc44fc3" dependencies = [ "assert_matches", "borsh 0.10.3", - "num-derive 0.4.1", + "num-derive 0.4.2", "num-traits", "solana-program", - "spl-token 4.0.0", - "spl-token-2022 0.9.0", + "spl-token", + "spl-token-2022", "thiserror", ] @@ -6398,37 +6473,28 @@ dependencies = [ [[package]] name = "spl-discriminator-derive" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fadbefec4f3c678215ca72bd71862697bb06b41fd77c0088902dd3203354387b" +checksum = "07fd7858fc4ff8fb0e34090e41d7eb06a823e1057945c26d480bfc21d2338a93" dependencies = [ - "quote 1.0.33", + "quote 1.0.35", "spl-discriminator-syn", - "syn 2.0.38", + "syn 2.0.48", ] [[package]] name = "spl-discriminator-syn" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e5f2044ca42c8938d54d1255ce599c79a1ffd86b677dfab695caa20f9ffc3f2" +checksum = "18fea7be851bd98d10721782ea958097c03a0c2a07d8d4997041d0ece6319a63" dependencies = [ - "proc-macro2 1.0.69", - "quote 1.0.33", + "proc-macro2 1.0.78", + "quote 1.0.35", "sha2 0.10.8", - "syn 2.0.38", + "syn 2.0.48", "thiserror", ] -[[package]] -name = "spl-memo" -version = "3.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd0dc6f70db6bacea7ff25870b016a65ba1d1b6013536f08e4fd79a8f9005325" -dependencies = [ - "solana-program", -] - [[package]] name = "spl-memo" version = "4.0.0" @@ -6466,7 +6532,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "249e0318493b6bcf27ae9902600566c689b7dfba9f1bdff5893e92253374e78c" dependencies = [ - "num-derive 0.4.1", + "num-derive 0.4.2", "num-traits", "solana-program", "spl-program-error-derive", @@ -6475,14 +6541,14 @@ dependencies = [ [[package]] name = "spl-program-error-derive" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab5269c8e868da17b6552ef35a51355a017bd8e0eae269c201fef830d35fa52c" +checksum = "1845dfe71fd68f70382232742e758557afe973ae19e6c06807b2c30f5d5cb474" dependencies = [ - "proc-macro2 1.0.69", - "quote 1.0.33", + "proc-macro2 1.0.78", + "quote 1.0.35", "sha2 0.10.8", - "syn 2.0.38", + "syn 2.0.48", ] [[package]] @@ -6499,21 +6565,6 @@ dependencies = [ "spl-type-length-value", ] -[[package]] -name = "spl-token" -version = "3.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e85e168a785e82564160dcb87b2a8e04cee9bfd1f4d488c729d53d6a4bd300d" -dependencies = [ - "arrayref", - "bytemuck", - "num-derive 0.3.3", - "num-traits", - "num_enum 0.5.11", - "solana-program", - "thiserror", -] - [[package]] name = "spl-token" version = "4.0.0" @@ -6529,24 +6580,6 @@ dependencies = [ "thiserror", ] -[[package]] -name = "spl-token-2022" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0043b590232c400bad5ee9eb983ced003d15163c4c5d56b090ac6d9a57457b47" -dependencies = [ - "arrayref", - "bytemuck", - "num-derive 0.3.3", - "num-traits", - "num_enum 0.5.11", - "solana-program", - "solana-zk-token-sdk", - "spl-memo 3.0.1", - "spl-token 3.5.0", - "thiserror", -] - [[package]] name = "spl-token-2022" version = "0.9.0" @@ -6555,14 +6588,14 @@ checksum = "e4abf34a65ba420584a0c35f3903f8d727d1f13ababbdc3f714c6b065a686e86" dependencies = [ "arrayref", "bytemuck", - "num-derive 0.4.1", + "num-derive 0.4.2", "num-traits", - "num_enum 0.7.0", + "num_enum 0.7.2", "solana-program", "solana-zk-token-sdk", - "spl-memo 4.0.0", + "spl-memo", "spl-pod", - "spl-token 4.0.0", + "spl-token", "spl-token-metadata-interface", "spl-transfer-hook-interface", "spl-type-length-value", @@ -6614,11 +6647,11 @@ dependencies = [ [[package]] name = "sqlformat" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b7b278788e7be4d0d29c0f39497a0eef3fba6bbc8e70d8bf7fde46edeaa9e85" +checksum = "ce81b7bd7c4493975347ef60d8c7e8b742d4694f4c49f93e0a12ea263938176c" dependencies = [ - "itertools 0.11.0", + "itertools 0.12.1", "nom", "unicode_categories", ] @@ -6639,7 +6672,7 @@ version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fa8241483a83a3f33aa5fff7e7d9def398ff9990b2752b6c6112b83c6d246029" dependencies = [ - "ahash 0.7.6", + "ahash 0.7.7", "atoi", "base64 0.13.1", "bitflags 1.3.2", @@ -6683,7 +6716,7 @@ dependencies = [ "sqlx-rt", "stringprep", "thiserror", - "time 0.3.29", + "time 0.3.34", "tokio-stream", "url", "uuid", @@ -6702,8 +6735,8 @@ dependencies = [ "heck 0.4.1", "hex", "once_cell", - "proc-macro2 1.0.69", - "quote 1.0.33", + "proc-macro2 1.0.78", + "quote 1.0.35", "serde", "serde_json", "sha2 0.10.8", @@ -6737,7 +6770,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6bcb902b974bc20b50c3ad3148022a366a46c9a676b587684ff46c237a3329e" dependencies = [ "async-channel 1.9.0", - "async-io", + "async-io 1.13.0", "atomic 0.5.3", "crossbeam-channel", "futures", @@ -6795,30 +6828,48 @@ version = "1.0.109" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" dependencies = [ - "proc-macro2 1.0.69", - "quote 1.0.33", + "proc-macro2 1.0.78", + "quote 1.0.35", "unicode-ident", ] [[package]] name = "syn" -version = "2.0.38" +version = "2.0.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e96b79aaa137db8f61e26363a0c9b47d8b4ec75da28b7d1d614c2303e232408b" +checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f" dependencies = [ - "proc-macro2 1.0.69", - "quote 1.0.33", + "proc-macro2 1.0.78", + "quote 1.0.35", "unicode-ident", ] +[[package]] +name = "syn_derive" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1329189c02ff984e9736652b1631330da25eaa6bc639089ed4915d25446cbe7b" +dependencies = [ + "proc-macro-error", + "proc-macro2 1.0.78", + "quote 1.0.35", + "syn 2.0.48", +] + +[[package]] +name = "sync_wrapper" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" + [[package]] name = "synstructure" version = "0.12.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" dependencies = [ - "proc-macro2 1.0.69", - "quote 1.0.33", + "proc-macro2 1.0.78", + "quote 1.0.35", "syn 1.0.109", "unicode-xid 0.2.4", ] @@ -6852,22 +6903,21 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] name = "tempfile" -version = "3.8.0" +version = "3.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb94d2f3cc536af71caac6b6fcebf65860b347e7ce0cc9ebe8f70d3e521054ef" +checksum = "a365e8cd18e44762ef95d87f284f4b5cd04107fec2ff3052bd6a3e6069669e67" dependencies = [ "cfg-if", "fastrand 2.0.1", - "redox_syscall 0.3.5", - "rustix 0.38.18", - "windows-sys 0.48.0", + "rustix 0.38.31", + "windows-sys 0.52.0", ] [[package]] name = "termcolor" -version = "1.3.0" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6093bad37da69aab9d123a8091e4be0aa4a03e4d601ec641c327398315f62b64" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" dependencies = [ "winapi-util", ] @@ -6889,22 +6939,22 @@ checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d" [[package]] name = "thiserror" -version = "1.0.49" +version = "1.0.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1177e8c6d7ede7afde3585fd2513e611227efd6481bd78d2e82ba1ce16557ed4" +checksum = "d54378c645627613241d077a3a79db965db602882668f9136ac42af9ecb730ad" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.49" +version = "1.0.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10712f02019e9288794769fba95cd6847df9874d49d871d062172f9dd41bc4cc" +checksum = "fa0faa943b50f3db30a20aa7e265dbc66076993efed8463e8de414e5d06d3471" dependencies = [ - "proc-macro2 1.0.69", - "quote 1.0.33", - "syn 2.0.38", + "proc-macro2 1.0.78", + "quote 1.0.35", + "syn 2.0.48", ] [[package]] @@ -6930,12 +6980,14 @@ dependencies = [ [[package]] name = "time" -version = "0.3.29" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "426f806f4089c493dcac0d24c29c01e2c38baf8e30f1b716ee37e83d200b18fe" +checksum = "c8248b6521bb14bc45b4067159b9b6ad792e2d6d754d6c41fb50e29fefe38749" dependencies = [ "deranged", "itoa", + "num-conv", + "powerfmt", "serde", "time-core", "time-macros", @@ -6949,10 +7001,11 @@ checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" [[package]] name = "time-macros" -version = "0.2.15" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ad70d68dba9e1f8aceda7aa6711965dfec1cac869f311a51bd08b3a2ccbce20" +checksum = "7ba3a3ef41e6672a2f0f001392bb5dcd3ff0a9992d618ca761a11c3121547774" dependencies = [ + "num-conv", "time-core", ] @@ -6992,9 +7045,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.33.0" +version = "1.36.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f38200e3ef7995e5ef13baec2f432a6da0aa9ac495b2c0e8f3b7eec2c92d653" +checksum = "61285f6515fa018fb2d1e46eb21223fff441ee8db5d0f1435e8ab4f5cdb80931" dependencies = [ "backtrace", "bytes", @@ -7004,7 +7057,7 @@ dependencies = [ "parking_lot 0.12.1", "pin-project-lite", "signal-hook-registry", - "socket2 0.5.4", + "socket2 0.5.5", "tokio-macros", "tracing", "windows-sys 0.48.0", @@ -7012,13 +7065,13 @@ dependencies = [ [[package]] name = "tokio-macros" -version = "2.1.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" +checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" dependencies = [ - "proc-macro2 1.0.69", - "quote 1.0.33", - "syn 2.0.38", + "proc-macro2 1.0.78", + "quote 1.0.35", + "syn 2.0.48", ] [[package]] @@ -7051,7 +7104,7 @@ dependencies = [ "postgres-protocol", "postgres-types", "rand 0.8.5", - "socket2 0.5.4", + "socket2 0.5.5", "tokio", "tokio-util", "whoami", @@ -7074,7 +7127,7 @@ version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" dependencies = [ - "rustls 0.21.7", + "rustls 0.21.10", "tokio", ] @@ -7107,9 +7160,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.9" +version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d68074620f57a0b21594d9735eb2e98ab38b17f80d3fcb189fca266771ca60d" +checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15" dependencies = [ "bytes", "futures-core", @@ -7131,14 +7184,14 @@ dependencies = [ [[package]] name = "toml" -version = "0.8.8" +version = "0.8.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1a195ec8c9da26928f773888e0742ca3ca1040c6cd859c919c9f59c1954ab35" +checksum = "9a9aad4a3066010876e8dcf5a8a06e70a558751117a145c6ce2b82c2e2054290" dependencies = [ "serde", "serde_spanned", "toml_datetime", - "toml_edit 0.21.0", + "toml_edit 0.22.4", ] [[package]] @@ -7156,18 +7209,29 @@ version = "0.19.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" dependencies = [ - "indexmap 2.0.2", + "indexmap 2.2.2", "toml_datetime", "winnow", ] [[package]] name = "toml_edit" -version = "0.21.0" +version = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1" +dependencies = [ + "indexmap 2.2.2", + "toml_datetime", + "winnow", +] + +[[package]] +name = "toml_edit" +version = "0.22.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d34d383cd00a163b4a5b85053df514d45bc330f6de7737edfe0a93311d1eaa03" +checksum = "0c9ffdf896f8daaabf9b66ba8e77ea1ed5ed0f72821b398aba62352e95062951" dependencies = [ - "indexmap 2.0.2", + "indexmap 2.2.2", "serde", "serde_spanned", "toml_datetime", @@ -7217,11 +7281,10 @@ checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" [[package]] name = "tracing" -version = "0.1.37" +version = "0.1.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" dependencies = [ - "cfg-if", "log", "pin-project-lite", "tracing-attributes", @@ -7230,20 +7293,20 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.26" +version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ - "proc-macro2 1.0.69", - "quote 1.0.33", - "syn 2.0.38", + "proc-macro2 1.0.78", + "quote 1.0.35", + "syn 2.0.48", ] [[package]] name = "tracing-core" -version = "0.1.31" +version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0955b8137a1df6f1a2e9a37d8a6656291ff0297c1a97c24e0d8425fe2312f79a" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" dependencies = [ "once_cell", "valuable", @@ -7298,9 +7361,9 @@ dependencies = [ "anchor-client", "anyhow", "bs58 0.4.0", - "clap 4.4.8", + "clap 4.4.18", "digital_asset_types", - "env_logger 0.10.0", + "env_logger 0.10.2", "flatbuffers", "futures", "hex", @@ -7322,9 +7385,9 @@ dependencies = [ [[package]] name = "triomphe" -version = "0.1.9" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0eee8098afad3fb0c54a9007aab6804558410503ad676d4633f9c2559a00ac0f" +checksum = "859eb650cfee7434994602c3a68b25d77ad9e68c8a6cd491616ef86661382eb3" dependencies = [ "serde", "stable_deref_trait", @@ -7332,9 +7395,9 @@ dependencies = [ [[package]] name = "try-lock" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" [[package]] name = "tungstenite" @@ -7363,8 +7426,8 @@ name = "txn_forwarder" version = "0.7.12" dependencies = [ "anyhow", - "clap 4.4.8", - "env_logger 0.10.0", + "clap 4.4.18", + "env_logger 0.10.2", "figment", "flatbuffers", "futures", @@ -7391,9 +7454,9 @@ checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" [[package]] name = "uncased" -version = "0.9.9" +version = "0.9.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b9bc53168a4be7402ab86c3aad243a84dd7381d09be0eddc81280c1da95ca68" +checksum = "e1b88fcfe09e89d3866a5c11019378088af2d24c3fbd4f0543f96b479ec90697" dependencies = [ "version_check", ] @@ -7409,9 +7472,9 @@ dependencies = [ [[package]] name = "unicode-bidi" -version = "0.3.13" +version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" +checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" [[package]] name = "unicode-ident" @@ -7479,9 +7542,9 @@ dependencies = [ [[package]] name = "unsafe-libyaml" -version = "0.2.9" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f28467d3e1d3c6586d8f25fa243f544f5800fec42d97032474e17222c2b75cfa" +checksum = "ab4c90930b95a82d00dc9e9ac071b4991924390d46cbd0dfe566148667605e4b" [[package]] name = "untrusted" @@ -7507,9 +7570,9 @@ dependencies = [ [[package]] name = "url" -version = "2.4.1" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "143b538f18257fac9cad154828a57c6bf5157e1aa604d4816b5995bf6de87ae5" +checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" dependencies = [ "form_urlencoded", "idna", @@ -7530,11 +7593,11 @@ checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" [[package]] name = "uuid" -version = "1.4.1" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79daa5ed5740825c40b389c5e50312b9c86df53fccd33f281df655642b43869d" +checksum = "f00cc9702ca12d3c81455259621e676d0f7251cec66a21e98fe2e9a37db93b2a" dependencies = [ - "getrandom 0.2.10", + "getrandom 0.2.12", "serde", ] @@ -7546,9 +7609,9 @@ checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" [[package]] name = "value-bag" -version = "1.4.2" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a72e1902dde2bd6441347de2b70b7f5d59bf157c6c62f0c44572607a1d55bbe" +checksum = "126e423afe2dd9ac52142e7e9d5ce4135d7e13776c529d27fd6bc49f19e3280b" [[package]] name = "vcpkg" @@ -7615,9 +7678,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.87" +version = "0.2.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342" +checksum = "c1e124130aee3fb58c5bdd6b639a0509486b0338acaaae0c84a5124b0f588b7f" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -7625,24 +7688,24 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.87" +version = "0.2.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd" +checksum = "c9e7e1900c352b609c8488ad12639a311045f40a35491fb69ba8c12f758af70b" dependencies = [ "bumpalo", "log", "once_cell", - "proc-macro2 1.0.69", - "quote 1.0.33", - "syn 2.0.38", + "proc-macro2 1.0.78", + "quote 1.0.35", + "syn 2.0.48", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.37" +version = "0.4.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c02dbc21516f9f1f04f187958890d7e6026df8d16540b7ad9492bc34a67cea03" +checksum = "877b9c3f61ceea0e56331985743b13f3d25c406a7098d45180fb5f09bc19ed97" dependencies = [ "cfg-if", "js-sys", @@ -7652,38 +7715,38 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.87" +version = "0.2.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d" +checksum = "b30af9e2d358182b5c7449424f017eba305ed32a7010509ede96cdc4696c46ed" dependencies = [ - "quote 1.0.33", + "quote 1.0.35", "wasm-bindgen-macro-support", ] [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.87" +version = "0.2.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" +checksum = "642f325be6301eb8107a83d12a8ac6c1e1c54345a7ef1a9261962dfefda09e66" dependencies = [ - "proc-macro2 1.0.69", - "quote 1.0.33", - "syn 2.0.38", + "proc-macro2 1.0.78", + "quote 1.0.35", + "syn 2.0.48", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.87" +version = "0.2.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" +checksum = "4f186bd2dcf04330886ce82d6f33dd75a7bfcf69ecf5763b89fcde53b6ac9838" [[package]] name = "web-sys" -version = "0.3.64" +version = "0.3.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b85cbef8c220a6abc02aefd892dfc0fc23afb1c6a426316ec33253a3877249b" +checksum = "96565907687f7aceb35bc5fc03770a8a0471d82e479f25832f54a0e3f4b28446" dependencies = [ "js-sys", "wasm-bindgen", @@ -7695,7 +7758,7 @@ version = "0.22.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed63aea5ce73d0ff405984102c42de94fc55a6b75765d621c65262469b3c9b53" dependencies = [ - "ring 0.17.2", + "ring 0.17.7", "untrusted 0.9.0", ] @@ -7710,9 +7773,9 @@ dependencies = [ [[package]] name = "webpki-roots" -version = "0.25.2" +version = "0.25.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14247bb57be4f377dfb94c72830b8ce8fc6beac03cf4bf7b9732eadd414123fc" +checksum = "5f20c57d8d7db6d3b86154206ae5d8fba62dd39573114de97c2cb0578251f8e1" [[package]] name = "wg" @@ -7767,12 +7830,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] -name = "windows" -version = "0.48.0" +name = "windows-core" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" dependencies = [ - "windows-targets 0.48.5", + "windows-targets 0.52.0", ] [[package]] @@ -7790,15 +7853,6 @@ dependencies = [ "windows_x86_64_msvc 0.42.2", ] -[[package]] -name = "windows-sys" -version = "0.45.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" -dependencies = [ - "windows-targets 0.42.2", -] - [[package]] name = "windows-sys" version = "0.48.0" @@ -7809,18 +7863,12 @@ dependencies = [ ] [[package]] -name = "windows-targets" -version = "0.42.2" +name = "windows-sys" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows_aarch64_gnullvm 0.42.2", - "windows_aarch64_msvc 0.42.2", - "windows_i686_gnu 0.42.2", - "windows_i686_msvc 0.42.2", - "windows_x86_64_gnu 0.42.2", - "windows_x86_64_gnullvm 0.42.2", - "windows_x86_64_msvc 0.42.2", + "windows-targets 0.52.0", ] [[package]] @@ -7838,6 +7886,21 @@ dependencies = [ "windows_x86_64_msvc 0.48.5", ] +[[package]] +name = "windows-targets" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" +dependencies = [ + "windows_aarch64_gnullvm 0.52.0", + "windows_aarch64_msvc 0.52.0", + "windows_i686_gnu 0.52.0", + "windows_i686_msvc 0.52.0", + "windows_x86_64_gnu 0.52.0", + "windows_x86_64_gnullvm 0.52.0", + "windows_x86_64_msvc 0.52.0", +] + [[package]] name = "windows_aarch64_gnullvm" version = "0.42.2" @@ -7850,6 +7913,12 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" + [[package]] name = "windows_aarch64_msvc" version = "0.42.2" @@ -7862,6 +7931,12 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" + [[package]] name = "windows_i686_gnu" version = "0.42.2" @@ -7874,6 +7949,12 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" +[[package]] +name = "windows_i686_gnu" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" + [[package]] name = "windows_i686_msvc" version = "0.42.2" @@ -7886,6 +7967,12 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" +[[package]] +name = "windows_i686_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" + [[package]] name = "windows_x86_64_gnu" version = "0.42.2" @@ -7898,6 +7985,12 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" + [[package]] name = "windows_x86_64_gnullvm" version = "0.42.2" @@ -7910,6 +8003,12 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" + [[package]] name = "windows_x86_64_msvc" version = "0.42.2" @@ -7922,11 +8021,17 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" + [[package]] name = "winnow" -version = "0.5.16" +version = "0.5.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "037711d82167854aff2018dfd193aa0fef5370f456732f0d5a0c59b0f1b4b907" +checksum = "5389a154b01683d28c77f8f68f49dea75f0a4da32557a58f68ee51ebba472d29" dependencies = [ "memchr", ] @@ -7965,14 +8070,23 @@ dependencies = [ "oid-registry", "rusticata-macros", "thiserror", - "time 0.3.29", + "time 0.3.34", ] [[package]] name = "xxhash-rust" -version = "0.8.7" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53be06678ed9e83edb1745eb72efc0bbcd7b5c3c35711a860906aed827a13d61" + +[[package]] +name = "yaml-rust" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9828b178da53440fa9c766a3d2f73f7cf5d0ac1fe3980c1e5018d899fd19e07b" +checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85" +dependencies = [ + "linked-hash-map", +] [[package]] name = "yansi" @@ -7986,7 +8100,27 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e17bb3549cc1321ae1296b9cdc2698e2b6cb1992adfa19a8c72e5b7a738f44cd" dependencies = [ - "time 0.3.29", + "time 0.3.34", +] + +[[package]] +name = "zerocopy" +version = "0.7.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" +dependencies = [ + "proc-macro2 1.0.78", + "quote 1.0.35", + "syn 2.0.48", ] [[package]] @@ -8004,9 +8138,9 @@ version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ - "proc-macro2 1.0.69", - "quote 1.0.33", - "syn 2.0.38", + "proc-macro2 1.0.78", + "quote 1.0.35", + "syn 2.0.48", ] [[package]] @@ -8030,11 +8164,10 @@ dependencies = [ [[package]] name = "zstd-sys" -version = "2.0.8+zstd.1.5.5" +version = "2.0.9+zstd.1.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5556e6ee25d32df2586c098bbfa278803692a20d0ab9565e049480d52707ec8c" +checksum = "9e16efa8a874a0481a574084d34cc26fdb3b99627480f785888deb6386506656" dependencies = [ "cc", - "libc", "pkg-config", ] diff --git a/Cargo.toml b/Cargo.toml index 376aff9ae..af24d6965 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,24 +1,27 @@ [workspace] -resolver = "2" members = [ + "core", "das_api", "digital_asset_types", "metaplex-rpc-proxy", "migration", "nft_ingester", + "ops", "tools/acc_forwarder", "tools/bgtask_creator", "tools/fetch_trees", "tools/load_generation", "tools/tree-status", "tools/txn_forwarder", + "integration_tests", ] +resolver = "2" [workspace.package] -version = "0.7.2" edition = "2021" -repository = "https://github.com/metaplex-foundation/digital-asset-rpc-infrastructure" publish = false +repository = "https://github.com/metaplex-foundation/digital-asset-rpc-infrastructure" +version = "0.7.2" [workspace.dependencies] anchor-client = "0.28.0" @@ -27,7 +30,7 @@ anyhow = "1.0.75" async-std = "1.0.0" async-trait = "0.1.60" base64 = "0.21.0" -blockbuster = "=0.9.0-beta.5" +blockbuster = "1.0.1" borsh = "~0.10.3" borsh-derive = "~0.10.3" bs58 = "0.4.0" @@ -35,6 +38,8 @@ cadence = "0.29.0" cadence-macros = "0.29.0" chrono = "0.4.19" clap = "4.2.2" +das_api = { path = "das_api" } +das-core = { path = "core" } digital_asset_types = { path = "digital_asset_types" } enum-iterator = "1.2.0" enum-iterator-derive = "1.1.0" @@ -42,26 +47,29 @@ env_logger = "0.10.0" fake = "2.5.0" figment = "0.10.8" flatbuffers = "23.1.21" +function_name = "0.3.0" futures = "0.3.28" futures-util = "0.3.27" hex = "0.4.3" hyper = "0.14.23" indexmap = "1.9.3" +insta = { version = "1.34.0", features = ["json"] } +itertools = "0.10.1" jsonpath_lib = "0.3.0" jsonrpsee = "0.16.2" jsonrpsee-core = "0.16.2" lazy_static = "1.4.0" log = "0.4.17" metrics = "0.20.1" +migration = { path = "migration" } mime_guess = "2.0.4" -mpl-bubblegum = "=1.0.1-beta.4" -mpl-candy-guard = "2.0.0" -mpl-candy-machine-core = "2.0.1" -mpl-token-metadata = "=2.0.0-beta.1" +mpl-bubblegum = "1.2.0" +mpl-token-metadata = "4.1.1" nft_ingester = { path = "nft_ingester" } num-derive = "0.3.3" num-integer = { version = "0.1.44", default_features = false } num-traits = "0.2.15" +once_cell = "1.19.0" open-rpc-derive = "0.0.4" open-rpc-schema = "0.0.4" plerkle_messenger = "1.6.0" @@ -75,11 +83,18 @@ reqwest = "0.11.13" rust-crypto = "0.2.36" schemars = "0.8.6" schemars_derive = "0.8.6" -sea-orm = "0.10.6" +sea-orm = { version = "0.10.6", features = [ + "macros", + "runtime-tokio-rustls", + "sqlx-postgres", + "with-chrono", + "mock", +] } sea-orm-migration = "0.10.6" sea-query = "0.28.1" serde = "1.0.137" serde_json = "1.0.81" +serial_test = "2.0.0" solana-account-decoder = "~1.16.16" solana-client = "~1.16.16" solana-geyser-plugin-interface = "~1.16.16" @@ -91,11 +106,18 @@ spl-account-compression = "0.2.0" spl-associated-token-account = ">= 1.1.3, < 3.0" spl-concurrent-merkle-tree = "0.2.0" spl-noop = "0.2.0" -spl-token = ">= 3.5.0, < 5.0" -sqlx = "0.6.2" +spl-token = { version = ">= 3.5.0, < 5.0", features = ["no-entrypoint"] } +sqlx = { version = "0.6.2", features = [ + "macros", + "runtime-tokio-rustls", + "postgres", + "uuid", + "offline", + "json", +] } stretto = "0.7.2" thiserror = "1.0.31" -tokio = "1.30.0" +tokio = { version = "1.30.0", features = ["macros", "rt-multi-thread"] } tokio-postgres = "0.7.7" tokio-stream = "0.1.14" tower = "0.4.13" @@ -114,5 +136,5 @@ missing_const_for_fn = "deny" trivially_copy_pass_by_ref = "deny" [profile.release] -lto = true codegen-units = 1 +lto = true diff --git a/Ingest.Dockerfile b/Ingest.Dockerfile index 7597f24c4..c2037d9ee 100644 --- a/Ingest.Dockerfile +++ b/Ingest.Dockerfile @@ -1,14 +1,17 @@ -FROM rust:1.73-bullseye AS chef +FROM rust:1.75-bullseye AS chef RUN cargo install cargo-chef FROM chef AS planner RUN mkdir /rust COPY Cargo.toml /rust +COPY core /rust/core COPY das_api /rust/das_api COPY digital_asset_types /rust/digital_asset_types +COPY integration_tests /rust/integration_tests COPY metaplex-rpc-proxy /rust/metaplex-rpc-proxy COPY migration /rust/migration COPY nft_ingester /rust/nft_ingester +COPY ops /rust/ops COPY tools /rust/tools WORKDIR /rust/nft_ingester @@ -20,11 +23,14 @@ RUN apt-get update -y && \ RUN mkdir /rust COPY Cargo.toml /rust +COPY core /rust/core COPY das_api /rust/das_api COPY digital_asset_types /rust/digital_asset_types +COPY integration_tests /rust/integration_tests COPY metaplex-rpc-proxy /rust/metaplex-rpc-proxy COPY migration /rust/migration COPY nft_ingester /rust/nft_ingester +COPY ops /rust/ops COPY tools /rust/tools WORKDIR /rust/nft_ingester @@ -39,7 +45,7 @@ COPY --from=planner /rust/nft_ingester/recipe.json recipe.json # Build application RUN cargo build --release -FROM rust:1.73-slim-bullseye +FROM rust:1.75-slim-bullseye ARG APP=/usr/src/app RUN apt update \ && apt install -y curl ca-certificates tzdata \ diff --git a/Load.Dockerfile b/Load.Dockerfile index e256cacf7..a52eee921 100644 --- a/Load.Dockerfile +++ b/Load.Dockerfile @@ -1,14 +1,17 @@ -FROM rust:1.73-bullseye AS chef +FROM rust:1.75-bullseye AS chef RUN cargo install cargo-chef FROM chef AS planner RUN mkdir /rust COPY Cargo.toml /rust +COPY core /rust/core COPY das_api /rust/das_api COPY digital_asset_types /rust/digital_asset_types +COPY integration_tests /rust/integration_tests COPY metaplex-rpc-proxy /rust/metaplex-rpc-proxy COPY migration /rust/migration COPY nft_ingester /rust/nft_ingester +COPY ops /rust/ops COPY tools /rust/tools WORKDIR /rust/tools/load_generation @@ -20,11 +23,14 @@ RUN apt-get update -y && \ RUN mkdir /rust COPY Cargo.toml /rust +COPY core /rust/core COPY das_api /rust/das_api COPY digital_asset_types /rust/digital_asset_types +COPY integration_tests /rust/integration_tests COPY metaplex-rpc-proxy /rust/metaplex-rpc-proxy COPY migration /rust/migration COPY nft_ingester /rust/nft_ingester +COPY ops /rust/ops COPY tools /rust/tools WORKDIR /rust/tools/load_generation @@ -36,7 +42,7 @@ RUN cargo chef cook --release --recipe-path recipe.json --target-dir /rust/targe # Build application RUN cargo build --release -FROM rust:1.73-slim-bullseye +FROM rust:1.75-slim-bullseye ARG APP=/usr/src/app RUN apt update \ && apt install -y curl ca-certificates tzdata \ diff --git a/Migrator.Dockerfile b/Migrator.Dockerfile index ac83e4945..044a4ee1e 100644 --- a/Migrator.Dockerfile +++ b/Migrator.Dockerfile @@ -1,13 +1,16 @@ -FROM rust:1.73-bullseye +FROM rust:1.75-bullseye COPY init.sql /init.sql ENV INIT_FILE_PATH=/init.sql COPY Cargo.toml / +COPY ./core /core COPY ./das_api /das_api COPY ./digital_asset_types /digital_asset_types +COPY ./integration_tests /integration_tests COPY ./metaplex-rpc-proxy /metaplex-rpc-proxy COPY ./migration /migration COPY ./nft_ingester /nft_ingester +COPY ./ops /ops COPY ./tools /tools WORKDIR /migration diff --git a/Proxy.Dockerfile b/Proxy.Dockerfile index 73c01fcf5..4691e2412 100644 --- a/Proxy.Dockerfile +++ b/Proxy.Dockerfile @@ -1,12 +1,15 @@ -FROM rust:1.73-bullseye AS builder +FROM rust:1.75-bullseye AS builder RUN mkdir /rust COPY ./Cargo.toml /rust +COPY ./core /rust/core COPY ./das_api /rust/das_api COPY ./digital_asset_types /rust/digital_asset_types +COPY ./integration_tests /rust/integration_tests COPY ./metaplex-rpc-proxy /rust/metaplex-rpc-proxy COPY ./migration /rust/migration COPY ./nft_ingester /rust/nft_ingester +COPY ./ops /rust/ops COPY ./tools /rust/tools WORKDIR /rust/metaplex-rpc-proxy diff --git a/core/Cargo.toml b/core/Cargo.toml new file mode 100644 index 000000000..f9b6d1daf --- /dev/null +++ b/core/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "das-core" +version.workspace = true +edition.workspace = true +repository.workspace = true +publish.workspace = true + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +clap = { workspace = true } +anyhow = { workspace = true } +sqlx = { workspace = true } +cadence = { workspace = true } +cadence-macros = { workspace = true } + +[lints] +workspace = true diff --git a/core/src/db.rs b/core/src/db.rs new file mode 100644 index 000000000..3037f670d --- /dev/null +++ b/core/src/db.rs @@ -0,0 +1,38 @@ +use anyhow::Result; +use clap::Parser; +use sqlx::{ + postgres::{PgConnectOptions, PgPoolOptions}, + PgPool, +}; + +#[derive(Debug, Parser, Clone)] +pub struct PoolArgs { + /// The database URL. + #[arg(long, env)] + pub database_url: String, + /// The maximum number of connections to the database. + #[arg(long, env, default_value = "125")] + pub database_max_connections: u32, + /// The minimum number of connections to the database. + #[arg(long, env, default_value = "5")] + pub database_min_connections: u32, +} + +///// Establishes a connection to the database using the provided configuration. +///// +///// # Arguments +///// +///// * `config` - A `PoolArgs` struct containing the database URL and the minimum and maximum number of connections. +///// +///// # Returns +///// +///// * `Result` - On success, returns a `DatabaseConnection`. On failure, returns a `DbErr`. +pub async fn connect_db(config: PoolArgs) -> Result { + let options: PgConnectOptions = config.database_url.parse()?; + + PgPoolOptions::new() + .min_connections(config.database_min_connections) + .max_connections(config.database_max_connections) + .connect_with(options) + .await +} diff --git a/core/src/lib.rs b/core/src/lib.rs new file mode 100644 index 000000000..7041fb4b3 --- /dev/null +++ b/core/src/lib.rs @@ -0,0 +1,5 @@ +mod db; +mod metrics; + +pub use db::*; +pub use metrics::*; diff --git a/core/src/metrics.rs b/core/src/metrics.rs new file mode 100644 index 000000000..9c0d3c531 --- /dev/null +++ b/core/src/metrics.rs @@ -0,0 +1,31 @@ +use anyhow::Result; +use cadence::{BufferedUdpMetricSink, QueuingMetricSink, StatsdClient}; +use cadence_macros::set_global_default; +use clap::Parser; +use std::net::UdpSocket; + +#[derive(Clone, Parser, Debug)] +pub struct MetricsArgs { + #[arg(long, env, default_value = "127.0.0.1")] + pub metrics_host: String, + #[arg(long, env, default_value = "8125")] + pub metrics_port: u16, + #[arg(long, env, default_value = "das.backfiller")] + pub metrics_prefix: String, +} + +pub fn setup_metrics(config: MetricsArgs) -> Result<()> { + let host = (config.metrics_host, config.metrics_port); + + let socket = UdpSocket::bind("0.0.0.0:0")?; + socket.set_nonblocking(true)?; + + let udp_sink = BufferedUdpMetricSink::from(host, socket)?; + let queuing_sink = QueuingMetricSink::from(udp_sink); + + let client = StatsdClient::from_sink(&config.metrics_prefix, queuing_sink); + + set_global_default(client); + + Ok(()) +} diff --git a/das_api/Cargo.toml b/das_api/Cargo.toml index c56afe88f..b54152424 100644 --- a/das_api/Cargo.toml +++ b/das_api/Cargo.toml @@ -21,9 +21,7 @@ jsonrpsee-core = { workspace = true, features =["server"]} log = { workspace = true } metrics = { workspace = true } mpl-bubblegum = { workspace = true } -mpl-candy-guard = { workspace = true, features = ["no-entrypoint"] } -mpl-candy-machine-core = { workspace = true, features = ["no-entrypoint"] } -mpl-token-metadata = { workspace = true, features = ["serde-feature"] } +mpl-token-metadata = { workspace = true, features = ["serde"] } open-rpc-derive = { workspace = true } open-rpc-schema = { workspace = true } schemars = { workspace = true } diff --git a/das_api/src/api/api_impl.rs b/das_api/src/api/api_impl.rs index 7456c5ec2..4b55f43d8 100644 --- a/das_api/src/api/api_impl.rs +++ b/das_api/src/api/api_impl.rs @@ -20,13 +20,13 @@ use digital_asset_types::{ use open_rpc_derive::document_rpc; use sea_orm::{sea_query::ConditionType, ConnectionTrait, DbBackend, Statement}; +use crate::error::DasApiError; use crate::validation::{validate_opt_pubkey, validate_search_with_name}; use open_rpc_schema::document::OpenrpcDocument; use { crate::api::*, crate::config::Config, crate::validation::validate_pubkey, - crate::DasApiError, async_trait::async_trait, digital_asset_types::rpc::{response::AssetList, Asset, AssetProof}, sea_orm::{DatabaseConnection, DbErr, SqlxPostgresConnector}, diff --git a/das_api/src/api/mod.rs b/das_api/src/api/mod.rs index 53959b19c..2e1da73ca 100644 --- a/das_api/src/api/mod.rs +++ b/das_api/src/api/mod.rs @@ -1,4 +1,4 @@ -use crate::DasApiError; +use crate::error::DasApiError; use async_trait::async_trait; use digital_asset_types::rpc::filter::{AssetSortDirection, SearchConditionType}; use digital_asset_types::rpc::options::Options; @@ -44,7 +44,7 @@ pub struct GetAssetsByOwner { pub cursor: Option, } -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)] +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema, Default)] #[serde(deny_unknown_fields, rename_all = "camelCase")] pub struct GetAsset { pub id: String, @@ -88,7 +88,7 @@ pub struct GetAssetsByCreator { pub cursor: Option, } -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)] +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema, Default)] #[serde(deny_unknown_fields, rename_all = "camelCase")] pub struct SearchAssets { pub negate: Option, diff --git a/das_api/src/builder.rs b/das_api/src/builder.rs index 9e3da1c81..25edb0aa2 100644 --- a/das_api/src/builder.rs +++ b/das_api/src/builder.rs @@ -1,6 +1,8 @@ +use jsonrpsee::RpcModule; use log::debug; -use crate::{api::*, DasApiError, RpcModule}; +use crate::{api::*, error::DasApiError}; + pub struct RpcApiBuilder; impl RpcApiBuilder { diff --git a/das_api/src/config.rs b/das_api/src/config.rs index 1a48c7a2a..ae08346e4 100644 --- a/das_api/src/config.rs +++ b/das_api/src/config.rs @@ -4,7 +4,7 @@ use { serde::Deserialize, }; -#[derive(Deserialize)] +#[derive(Deserialize, Default)] pub struct Config { pub database_url: String, pub metrics_port: Option, diff --git a/das_api/src/lib.rs b/das_api/src/lib.rs new file mode 100644 index 000000000..e783c79c2 --- /dev/null +++ b/das_api/src/lib.rs @@ -0,0 +1,6 @@ +pub mod api; + +pub mod builder; +pub mod config; +pub mod error; +pub mod validation; diff --git a/das_api/src/main.rs b/das_api/src/main.rs index 860ffd733..a8105358a 100644 --- a/das_api/src/main.rs +++ b/das_api/src/main.rs @@ -25,7 +25,7 @@ use tower_http::cors::{Any, CorsLayer}; use jsonrpsee::server::{ logger::{Logger, TransportProtocol}, middleware::proxy_get_request::ProxyGetRequestLayer, - RpcModule, ServerBuilder, + ServerBuilder, }; use cadence_macros::{is_global_default_set, statsd_time}; diff --git a/das_api/src/validation.rs b/das_api/src/validation.rs index 394463208..cf7424627 100644 --- a/das_api/src/validation.rs +++ b/das_api/src/validation.rs @@ -1,4 +1,4 @@ -use crate::DasApiError; +use crate::error::DasApiError; use solana_sdk::pubkey::Pubkey; use std::str::FromStr; diff --git a/digital_asset_types/src/dao/extensions/asset.rs b/digital_asset_types/src/dao/extensions/asset.rs index ed3757bf2..8b5b8b8dd 100644 --- a/digital_asset_types/src/dao/extensions/asset.rs +++ b/digital_asset_types/src/dao/extensions/asset.rs @@ -94,6 +94,10 @@ impl Default for asset::Model { created_at: None, burnt: Default::default(), slot_updated: None, + slot_updated_metadata_account: None, + slot_updated_mint_account: None, + slot_updated_token_account: None, + slot_updated_cnft_transaction: None, data_hash: None, creator_hash: None, owner_delegate_seq: None, diff --git a/digital_asset_types/src/dao/generated/asset.rs b/digital_asset_types/src/dao/generated/asset.rs index e03ae6866..fb2ef9557 100644 --- a/digital_asset_types/src/dao/generated/asset.rs +++ b/digital_asset_types/src/dao/generated/asset.rs @@ -41,6 +41,10 @@ pub struct Model { pub created_at: Option, pub burnt: bool, pub slot_updated: Option, + pub slot_updated_metadata_account: Option, + pub slot_updated_mint_account: Option, + pub slot_updated_token_account: Option, + pub slot_updated_cnft_transaction: Option, pub data_hash: Option, pub creator_hash: Option, pub owner_delegate_seq: Option, @@ -73,6 +77,10 @@ pub enum Column { CreatedAt, Burnt, SlotUpdated, + SlotUpdatedMetadataAccount, + SlotUpdatedMintAccount, + SlotUpdatedTokenAccount, + SlotUpdatedCnftTransaction, DataHash, CreatorHash, OwnerDelegateSeq, @@ -122,6 +130,10 @@ impl ColumnTrait for Column { Self::CreatedAt => ColumnType::TimestampWithTimeZone.def().null(), Self::Burnt => ColumnType::Boolean.def(), Self::SlotUpdated => ColumnType::BigInteger.def().null(), + Self::SlotUpdatedMetadataAccount => ColumnType::BigInteger.def().null(), + Self::SlotUpdatedMintAccount => ColumnType::BigInteger.def().null(), + Self::SlotUpdatedTokenAccount => ColumnType::BigInteger.def().null(), + Self::SlotUpdatedCnftTransaction => ColumnType::BigInteger.def().null(), Self::DataHash => ColumnType::Char(Some(50u32)).def().null(), Self::CreatorHash => ColumnType::Char(Some(50u32)).def().null(), Self::OwnerDelegateSeq => ColumnType::BigInteger.def().null(), diff --git a/digital_asset_types/src/dao/generated/prelude.rs b/digital_asset_types/src/dao/generated/prelude.rs index 070ecee41..4eabcb4a7 100644 --- a/digital_asset_types/src/dao/generated/prelude.rs +++ b/digital_asset_types/src/dao/generated/prelude.rs @@ -1,5 +1,7 @@ //! SeaORM Entity. Generated by sea-orm-codegen 0.9.3 +#![allow(unused_imports)] + pub use super::asset::Entity as Asset; pub use super::asset_authority::Entity as AssetAuthority; pub use super::asset_creators::Entity as AssetCreators; diff --git a/digital_asset_types/src/json/chain_data.rs b/digital_asset_types/src/json/chain_data.rs index aebbb7383..f12fc0d6f 100644 --- a/digital_asset_types/src/json/chain_data.rs +++ b/digital_asset_types/src/json/chain_data.rs @@ -1,4 +1,4 @@ -use blockbuster::token_metadata::state::{TokenStandard, Uses}; +use blockbuster::token_metadata::types::{TokenStandard, Uses}; use serde::{Deserialize, Serialize}; pub enum ChainData { diff --git a/digital_asset_types/tests/common.rs b/digital_asset_types/tests/common.rs index e486ef289..39d32118f 100644 --- a/digital_asset_types/tests/common.rs +++ b/digital_asset_types/tests/common.rs @@ -1,4 +1,4 @@ -use blockbuster::token_metadata::state::*; +use blockbuster::token_metadata::types::{Collection, Creator, TokenStandard, Uses}; use digital_asset_types::dao::sea_orm_active_enums::{ SpecificationAssetClass, SpecificationVersions, }; @@ -152,6 +152,10 @@ pub fn create_asset( created_at: None, specification_asset_class: Some(SpecificationAssetClass::Nft), slot_updated: Some(0), + slot_updated_metadata_account: Some(0), + slot_updated_mint_account: None, + slot_updated_token_account: None, + slot_updated_cnft_transaction: None, data_hash: None, alt_id: None, creator_hash: None, diff --git a/digital_asset_types/tests/get_asset_by_id.rs b/digital_asset_types/tests/get_asset_by_id.rs index f20b443d9..7af4ecae0 100644 --- a/digital_asset_types/tests/get_asset_by_id.rs +++ b/digital_asset_types/tests/get_asset_by_id.rs @@ -1,7 +1,7 @@ #[cfg(test)] mod common; -use blockbuster::token_metadata::state::*; +use blockbuster::token_metadata::types::{Creator, TokenStandard}; use common::*; use digital_asset_types::dao::sea_orm_active_enums::*; use digital_asset_types::dao::{ diff --git a/digital_asset_types/tests/get_assets_by_authority.rs b/digital_asset_types/tests/get_assets_by_authority.rs index 5796c6c55..4735b9149 100644 --- a/digital_asset_types/tests/get_assets_by_authority.rs +++ b/digital_asset_types/tests/get_assets_by_authority.rs @@ -4,7 +4,7 @@ mod common; use sea_orm::{entity::prelude::*, DatabaseBackend, MockDatabase}; use solana_sdk::{signature::Keypair, signer::Signer}; -use blockbuster::token_metadata::state::*; +use blockbuster::token_metadata::types::{Creator, TokenStandard}; use common::*; use digital_asset_types::dao::sea_orm_active_enums::*; use digital_asset_types::dao::{ diff --git a/digital_asset_types/tests/get_assets_by_creator.rs b/digital_asset_types/tests/get_assets_by_creator.rs index 6bcf85c9c..bbc4c0eea 100644 --- a/digital_asset_types/tests/get_assets_by_creator.rs +++ b/digital_asset_types/tests/get_assets_by_creator.rs @@ -6,7 +6,7 @@ use sea_orm::{ }; use solana_sdk::{signature::Keypair, signer::Signer}; -use blockbuster::token_metadata::state::*; +use blockbuster::token_metadata::types::{Creator, TokenStandard}; use common::*; use digital_asset_types::dao::sea_orm_active_enums::*; use digital_asset_types::dao::{ diff --git a/digital_asset_types/tests/get_assets_by_group.rs b/digital_asset_types/tests/get_assets_by_group.rs index b8bdb35ad..2ff0ec7a8 100644 --- a/digital_asset_types/tests/get_assets_by_group.rs +++ b/digital_asset_types/tests/get_assets_by_group.rs @@ -6,7 +6,7 @@ use sea_orm::{ }; use solana_sdk::{signature::Keypair, signer::Signer}; -use blockbuster::token_metadata::state::*; +use blockbuster::token_metadata::types::{Creator, TokenStandard}; use common::*; use digital_asset_types::dao::sea_orm_active_enums::*; use digital_asset_types::dao::{ diff --git a/digital_asset_types/tests/get_assets_by_owner.rs b/digital_asset_types/tests/get_assets_by_owner.rs index 5796c6c55..4735b9149 100644 --- a/digital_asset_types/tests/get_assets_by_owner.rs +++ b/digital_asset_types/tests/get_assets_by_owner.rs @@ -4,7 +4,7 @@ mod common; use sea_orm::{entity::prelude::*, DatabaseBackend, MockDatabase}; use solana_sdk::{signature::Keypair, signer::Signer}; -use blockbuster::token_metadata::state::*; +use blockbuster::token_metadata::types::{Creator, TokenStandard}; use common::*; use digital_asset_types::dao::sea_orm_active_enums::*; use digital_asset_types::dao::{ diff --git a/digital_asset_types/tests/json_parsing.rs b/digital_asset_types/tests/json_parsing.rs index 571bfc199..e630c91ff 100644 --- a/digital_asset_types/tests/json_parsing.rs +++ b/digital_asset_types/tests/json_parsing.rs @@ -1,5 +1,5 @@ #[cfg(test)] -use blockbuster::token_metadata::state::TokenStandard as TSBlockbuster; +use blockbuster::token_metadata::types::TokenStandard as TSBlockbuster; use digital_asset_types::dao::asset_data; use digital_asset_types::dao::sea_orm_active_enums::{ChainMutability, Mutability}; use digital_asset_types::dapi::common::v1_content_from_json; diff --git a/integration_tests/Cargo.toml b/integration_tests/Cargo.toml new file mode 100644 index 000000000..aab6896dd --- /dev/null +++ b/integration_tests/Cargo.toml @@ -0,0 +1,37 @@ +[package] +edition = "2021" +name = "integration_tests" +publish = false +version = "0.1.0" + +[dev-dependencies] +anyhow = {workspace = true} +borsh = {workspace = true} +das_api = {workspace = true} +digital_asset_types = {workspace = true} +env_logger = {workspace = true} +figment = {workspace = true} +flatbuffers = {workspace = true} +function_name = {workspace = true} +futures-util = {workspace = true} +insta = {workspace = true} +itertools = {workspace = true} +log = {workspace = true} +migration = {workspace = true} +mpl-token-metadata = {workspace = true} +nft_ingester = {workspace = true} +once_cell = {workspace = true} +plerkle_messenger = {workspace = true, features = ["redis"]} +plerkle_serialization = {workspace = true} +sea-orm = {workspace = true} +serde = {workspace = true} +serde_json = {workspace = true} +serial_test = {workspace = true} +solana-account-decoder = {workspace = true} +solana-client = {workspace = true} +solana-sdk = {workspace = true} +solana-transaction-status = {workspace = true} +spl-token = {workspace = true} +sqlx = {workspace = true} +tokio = {workspace = true} +tokio-stream = {workspace = true} diff --git a/integration_tests/README.md b/integration_tests/README.md new file mode 100644 index 000000000..93b349dbb --- /dev/null +++ b/integration_tests/README.md @@ -0,0 +1,35 @@ +# Integration Tests + +This Cargo package helps us run multi-package tests in our workspace. This setup is inspired by the tokio integration test setup. + +## Setup + +First setup a local Postgres database and export the postgres database URL as follows: +```export DATABASE_TEST_URL=postgres://postgres@localhost/``` + +Also gain access to mainnet RPCs and devnet RPCs and export the URLs as follows. Currently, +we only use these URLs for reading data and storing it locally. + +``` +export DEVNET_RPC_URL=... +export MAINNET_RPC_URL=... +``` + +Afterwards, you can simply run the following command to run tests: +```cargo test``` + +The tests run migrations from fresh and populates the data. You don't need to any other setup. + +## How do tests work? + +Most tests currently are configured to run as "scenario" tests. They pull test input data from mainnet/devnet +and store it locally to avoid tests breaking if mainnet/devnet data ever changes. Afterwards, they feed +the tests to the `handle_account_update` and `handle_transaction` functions of the ingester and populate +the indexed data in the database. Finally, they create an instance of the `DasApi` struct, run queries against +this struct, store the results of these queries as snapshots through the `insta` testing library and assert that +future runs of the same test produce the same snapshot. + +Note that tests do not actually run the ingester binaries and the API binaries and only test the primary internal functions +of each, e.g. `handle_account_update` and `handle_transaction` for the ingester and functions like `search_assets` +and `get_asset` for the binary. By following this approach, we are able to test the vast majority of the code +in a way that's easy to setup and fast to run -- avoiding to have to compile and run multiple binaries. diff --git a/integration_tests/lib.rs b/integration_tests/lib.rs new file mode 100644 index 000000000..550592cc3 --- /dev/null +++ b/integration_tests/lib.rs @@ -0,0 +1 @@ +// This file is needed to avoid rust-analyzer errors. diff --git a/integration_tests/tests/data/accounts/account_updates/6cQEeDKhobxxsvPKcAsdHZbDrPgQtEpo8PFzayDu5Gi5 b/integration_tests/tests/data/accounts/account_updates/6cQEeDKhobxxsvPKcAsdHZbDrPgQtEpo8PFzayDu5Gi5 new file mode 100644 index 000000000..cc666a0d0 Binary files /dev/null and b/integration_tests/tests/data/accounts/account_updates/6cQEeDKhobxxsvPKcAsdHZbDrPgQtEpo8PFzayDu5Gi5 differ diff --git a/integration_tests/tests/data/accounts/account_updates/843gdpsTE4DoJz3ZoBsEjAqT8UgAcyF5YojygGgGZE1f b/integration_tests/tests/data/accounts/account_updates/843gdpsTE4DoJz3ZoBsEjAqT8UgAcyF5YojygGgGZE1f new file mode 100644 index 000000000..71361ffeb Binary files /dev/null and b/integration_tests/tests/data/accounts/account_updates/843gdpsTE4DoJz3ZoBsEjAqT8UgAcyF5YojygGgGZE1f differ diff --git a/integration_tests/tests/data/accounts/account_updates/DPBEGb2DajfkannVZ6J4NxRY2ovz1yn1j36i1WVdZVpW b/integration_tests/tests/data/accounts/account_updates/DPBEGb2DajfkannVZ6J4NxRY2ovz1yn1j36i1WVdZVpW new file mode 100644 index 000000000..f9826c63c Binary files /dev/null and b/integration_tests/tests/data/accounts/account_updates/DPBEGb2DajfkannVZ6J4NxRY2ovz1yn1j36i1WVdZVpW differ diff --git a/integration_tests/tests/data/accounts/asset_decompress/5AgDPkMLtW7dxK4vo4Sbhgj2ek2Xxqe6k9HMSfwz7JrE b/integration_tests/tests/data/accounts/asset_decompress/5AgDPkMLtW7dxK4vo4Sbhgj2ek2Xxqe6k9HMSfwz7JrE new file mode 100644 index 000000000..9c35b7ecf Binary files /dev/null and b/integration_tests/tests/data/accounts/asset_decompress/5AgDPkMLtW7dxK4vo4Sbhgj2ek2Xxqe6k9HMSfwz7JrE differ diff --git a/integration_tests/tests/data/accounts/asset_decompress/Az9QTysJj1LW1F7zkYF21HgBj3FRpq3zpxTFdPnAJYm8 b/integration_tests/tests/data/accounts/asset_decompress/Az9QTysJj1LW1F7zkYF21HgBj3FRpq3zpxTFdPnAJYm8 new file mode 100644 index 000000000..8d56745df Binary files /dev/null and b/integration_tests/tests/data/accounts/asset_decompress/Az9QTysJj1LW1F7zkYF21HgBj3FRpq3zpxTFdPnAJYm8 differ diff --git a/integration_tests/tests/data/accounts/asset_decompress/B5PfwkTK4WQtm5wqmb8ViTXiw9bvQgaJwVSbtssbmRvJ b/integration_tests/tests/data/accounts/asset_decompress/B5PfwkTK4WQtm5wqmb8ViTXiw9bvQgaJwVSbtssbmRvJ new file mode 100644 index 000000000..78999c3de Binary files /dev/null and b/integration_tests/tests/data/accounts/asset_decompress/B5PfwkTK4WQtm5wqmb8ViTXiw9bvQgaJwVSbtssbmRvJ differ diff --git a/integration_tests/tests/data/accounts/asset_parsing/6cQEeDKhobxxsvPKcAsdHZbDrPgQtEpo8PFzayDu5Gi5 b/integration_tests/tests/data/accounts/asset_parsing/6cQEeDKhobxxsvPKcAsdHZbDrPgQtEpo8PFzayDu5Gi5 new file mode 100644 index 000000000..890016a0c Binary files /dev/null and b/integration_tests/tests/data/accounts/asset_parsing/6cQEeDKhobxxsvPKcAsdHZbDrPgQtEpo8PFzayDu5Gi5 differ diff --git a/integration_tests/tests/data/accounts/asset_parsing/843gdpsTE4DoJz3ZoBsEjAqT8UgAcyF5YojygGgGZE1f b/integration_tests/tests/data/accounts/asset_parsing/843gdpsTE4DoJz3ZoBsEjAqT8UgAcyF5YojygGgGZE1f new file mode 100644 index 000000000..ce9ccbf8e Binary files /dev/null and b/integration_tests/tests/data/accounts/asset_parsing/843gdpsTE4DoJz3ZoBsEjAqT8UgAcyF5YojygGgGZE1f differ diff --git a/integration_tests/tests/data/accounts/asset_parsing/DPBEGb2DajfkannVZ6J4NxRY2ovz1yn1j36i1WVdZVpW b/integration_tests/tests/data/accounts/asset_parsing/DPBEGb2DajfkannVZ6J4NxRY2ovz1yn1j36i1WVdZVpW new file mode 100644 index 000000000..54ccbe8ae Binary files /dev/null and b/integration_tests/tests/data/accounts/asset_parsing/DPBEGb2DajfkannVZ6J4NxRY2ovz1yn1j36i1WVdZVpW differ diff --git a/integration_tests/tests/data/accounts/creators_reordering/3mM2EwVk23dZ1SfNQBvhLJhAwuMAJcm5XFg9f8wpHYTP b/integration_tests/tests/data/accounts/creators_reordering/3mM2EwVk23dZ1SfNQBvhLJhAwuMAJcm5XFg9f8wpHYTP new file mode 100644 index 000000000..a5ff8b3ba Binary files /dev/null and b/integration_tests/tests/data/accounts/creators_reordering/3mM2EwVk23dZ1SfNQBvhLJhAwuMAJcm5XFg9f8wpHYTP differ diff --git a/integration_tests/tests/data/accounts/creators_reordering/ANt9HygtvFmFJ1UcAHFLnM62JJWjk8fujMzjGfpKBfzk b/integration_tests/tests/data/accounts/creators_reordering/ANt9HygtvFmFJ1UcAHFLnM62JJWjk8fujMzjGfpKBfzk new file mode 100644 index 000000000..692a5978c Binary files /dev/null and b/integration_tests/tests/data/accounts/creators_reordering/ANt9HygtvFmFJ1UcAHFLnM62JJWjk8fujMzjGfpKBfzk differ diff --git a/integration_tests/tests/data/accounts/creators_reordering/CejAywG35pUojBh9ghjDMcUphEBCW8CidFymDAkubzhq b/integration_tests/tests/data/accounts/creators_reordering/CejAywG35pUojBh9ghjDMcUphEBCW8CidFymDAkubzhq new file mode 100644 index 000000000..719aaa97b Binary files /dev/null and b/integration_tests/tests/data/accounts/creators_reordering/CejAywG35pUojBh9ghjDMcUphEBCW8CidFymDAkubzhq differ diff --git a/integration_tests/tests/data/accounts/reg_get_asset/52J4tmbP9o3GHQrkts8vhXm84CLzM7KSXboKGnrw3YTW b/integration_tests/tests/data/accounts/reg_get_asset/52J4tmbP9o3GHQrkts8vhXm84CLzM7KSXboKGnrw3YTW new file mode 100644 index 000000000..a54f37db0 Binary files /dev/null and b/integration_tests/tests/data/accounts/reg_get_asset/52J4tmbP9o3GHQrkts8vhXm84CLzM7KSXboKGnrw3YTW differ diff --git a/integration_tests/tests/data/accounts/reg_get_asset/CMVuYDS9nTeujfTPJb8ik7CRhAqZv4DfjfdamFLkJgxE b/integration_tests/tests/data/accounts/reg_get_asset/CMVuYDS9nTeujfTPJb8ik7CRhAqZv4DfjfdamFLkJgxE new file mode 100644 index 000000000..669172249 Binary files /dev/null and b/integration_tests/tests/data/accounts/reg_get_asset/CMVuYDS9nTeujfTPJb8ik7CRhAqZv4DfjfdamFLkJgxE differ diff --git a/integration_tests/tests/data/accounts/reg_get_asset/Fc1MSqW3eifoMuDupvimtu2DbSYmGUtSQ7wBUoz87uK5 b/integration_tests/tests/data/accounts/reg_get_asset/Fc1MSqW3eifoMuDupvimtu2DbSYmGUtSQ7wBUoz87uK5 new file mode 100644 index 000000000..aa06c326e Binary files /dev/null and b/integration_tests/tests/data/accounts/reg_get_asset/Fc1MSqW3eifoMuDupvimtu2DbSYmGUtSQ7wBUoz87uK5 differ diff --git a/integration_tests/tests/data/accounts/reg_get_asset_batch/13YBWA4DyLJc8QZPAAajNLefise35GZ2pVG2R97n5NYa b/integration_tests/tests/data/accounts/reg_get_asset_batch/13YBWA4DyLJc8QZPAAajNLefise35GZ2pVG2R97n5NYa new file mode 100644 index 000000000..ea6fe39dc Binary files /dev/null and b/integration_tests/tests/data/accounts/reg_get_asset_batch/13YBWA4DyLJc8QZPAAajNLefise35GZ2pVG2R97n5NYa differ diff --git a/integration_tests/tests/data/accounts/reg_get_asset_batch/2NqdYX6kJmMUoChnDXU2UrP9BsoPZivRw3uJG8iDhRRd b/integration_tests/tests/data/accounts/reg_get_asset_batch/2NqdYX6kJmMUoChnDXU2UrP9BsoPZivRw3uJG8iDhRRd new file mode 100644 index 000000000..5a04b7c77 Binary files /dev/null and b/integration_tests/tests/data/accounts/reg_get_asset_batch/2NqdYX6kJmMUoChnDXU2UrP9BsoPZivRw3uJG8iDhRRd differ diff --git a/integration_tests/tests/data/accounts/reg_get_asset_batch/2iMQVnGpJfSRfyPSyDgnnGMwiCa9ap5j29VZvHuoABpp b/integration_tests/tests/data/accounts/reg_get_asset_batch/2iMQVnGpJfSRfyPSyDgnnGMwiCa9ap5j29VZvHuoABpp new file mode 100644 index 000000000..082dfc494 Binary files /dev/null and b/integration_tests/tests/data/accounts/reg_get_asset_batch/2iMQVnGpJfSRfyPSyDgnnGMwiCa9ap5j29VZvHuoABpp differ diff --git a/integration_tests/tests/data/accounts/reg_get_asset_batch/5rEeYv8R25b8j6YTHJvYuCKEzq44UCw1Wx1Wx2VPPLz1 b/integration_tests/tests/data/accounts/reg_get_asset_batch/5rEeYv8R25b8j6YTHJvYuCKEzq44UCw1Wx1Wx2VPPLz1 new file mode 100644 index 000000000..73a594c5c Binary files /dev/null and b/integration_tests/tests/data/accounts/reg_get_asset_batch/5rEeYv8R25b8j6YTHJvYuCKEzq44UCw1Wx1Wx2VPPLz1 differ diff --git a/integration_tests/tests/data/accounts/reg_get_asset_batch/AhbbU3exDvvM9cBzHxEjpYt4sMfFsXuQ3FUXv9VPE4F7 b/integration_tests/tests/data/accounts/reg_get_asset_batch/AhbbU3exDvvM9cBzHxEjpYt4sMfFsXuQ3FUXv9VPE4F7 new file mode 100644 index 000000000..9cd0184fd Binary files /dev/null and b/integration_tests/tests/data/accounts/reg_get_asset_batch/AhbbU3exDvvM9cBzHxEjpYt4sMfFsXuQ3FUXv9VPE4F7 differ diff --git a/integration_tests/tests/data/accounts/reg_get_asset_batch/CxYMsK8m52REmAv8mre7TNJx2QLfHnVEdhnt4vht37q4 b/integration_tests/tests/data/accounts/reg_get_asset_batch/CxYMsK8m52REmAv8mre7TNJx2QLfHnVEdhnt4vht37q4 new file mode 100644 index 000000000..046932d30 Binary files /dev/null and b/integration_tests/tests/data/accounts/reg_get_asset_batch/CxYMsK8m52REmAv8mre7TNJx2QLfHnVEdhnt4vht37q4 differ diff --git a/integration_tests/tests/data/accounts/reg_get_asset_batch/EjkMvnYTrmpAWLVz55HHL3UxcZcPYwiSooLNPheLP1kk b/integration_tests/tests/data/accounts/reg_get_asset_batch/EjkMvnYTrmpAWLVz55HHL3UxcZcPYwiSooLNPheLP1kk new file mode 100644 index 000000000..13e128c71 Binary files /dev/null and b/integration_tests/tests/data/accounts/reg_get_asset_batch/EjkMvnYTrmpAWLVz55HHL3UxcZcPYwiSooLNPheLP1kk differ diff --git a/integration_tests/tests/data/accounts/reg_get_asset_batch/HTKAVZZrDdyecCxzm3WEkCsG1GUmiqKm73PvngfuYRNK b/integration_tests/tests/data/accounts/reg_get_asset_batch/HTKAVZZrDdyecCxzm3WEkCsG1GUmiqKm73PvngfuYRNK new file mode 100644 index 000000000..e3257069d Binary files /dev/null and b/integration_tests/tests/data/accounts/reg_get_asset_batch/HTKAVZZrDdyecCxzm3WEkCsG1GUmiqKm73PvngfuYRNK differ diff --git a/integration_tests/tests/data/accounts/reg_get_asset_batch/cpdh48eio3EZFc3rZw7HR6P3thRr22qbcNXtvC9dC18 b/integration_tests/tests/data/accounts/reg_get_asset_batch/cpdh48eio3EZFc3rZw7HR6P3thRr22qbcNXtvC9dC18 new file mode 100644 index 000000000..b769d8d4b Binary files /dev/null and b/integration_tests/tests/data/accounts/reg_get_asset_batch/cpdh48eio3EZFc3rZw7HR6P3thRr22qbcNXtvC9dC18 differ diff --git a/integration_tests/tests/data/accounts/reg_get_asset_by_group/4uTRch4H3kVSWdrQjUe1W5jEoEAxvw9KpYDGRSWUdeW9 b/integration_tests/tests/data/accounts/reg_get_asset_by_group/4uTRch4H3kVSWdrQjUe1W5jEoEAxvw9KpYDGRSWUdeW9 new file mode 100644 index 000000000..f7c0ea54f Binary files /dev/null and b/integration_tests/tests/data/accounts/reg_get_asset_by_group/4uTRch4H3kVSWdrQjUe1W5jEoEAxvw9KpYDGRSWUdeW9 differ diff --git a/integration_tests/tests/data/accounts/reg_get_asset_by_group/5yF7HbXnjAy2BEq2EC3twan5yuVVXiAx22gbKy5Zi5qk b/integration_tests/tests/data/accounts/reg_get_asset_by_group/5yF7HbXnjAy2BEq2EC3twan5yuVVXiAx22gbKy5Zi5qk new file mode 100644 index 000000000..742f01010 Binary files /dev/null and b/integration_tests/tests/data/accounts/reg_get_asset_by_group/5yF7HbXnjAy2BEq2EC3twan5yuVVXiAx22gbKy5Zi5qk differ diff --git a/integration_tests/tests/data/accounts/reg_get_asset_by_group/7jFuJ73mBPDdLMvCYxzrpFTD9FeDudRxdXGDALP5Cp2W b/integration_tests/tests/data/accounts/reg_get_asset_by_group/7jFuJ73mBPDdLMvCYxzrpFTD9FeDudRxdXGDALP5Cp2W new file mode 100644 index 000000000..8ad0f5e51 Binary files /dev/null and b/integration_tests/tests/data/accounts/reg_get_asset_by_group/7jFuJ73mBPDdLMvCYxzrpFTD9FeDudRxdXGDALP5Cp2W differ diff --git a/integration_tests/tests/data/accounts/reg_get_asset_by_group/7om2zA1iCQ3FCm8pTUBTHi8M9p2oVai4FsxJFN8asgjg b/integration_tests/tests/data/accounts/reg_get_asset_by_group/7om2zA1iCQ3FCm8pTUBTHi8M9p2oVai4FsxJFN8asgjg new file mode 100644 index 000000000..c5a542f94 Binary files /dev/null and b/integration_tests/tests/data/accounts/reg_get_asset_by_group/7om2zA1iCQ3FCm8pTUBTHi8M9p2oVai4FsxJFN8asgjg differ diff --git a/integration_tests/tests/data/accounts/reg_get_asset_by_group/9B5ygnnZno5UnSuM14feYqCKESRawPfVnVc1CgcAR9QH b/integration_tests/tests/data/accounts/reg_get_asset_by_group/9B5ygnnZno5UnSuM14feYqCKESRawPfVnVc1CgcAR9QH new file mode 100644 index 000000000..431ec8be7 Binary files /dev/null and b/integration_tests/tests/data/accounts/reg_get_asset_by_group/9B5ygnnZno5UnSuM14feYqCKESRawPfVnVc1CgcAR9QH differ diff --git a/integration_tests/tests/data/accounts/reg_get_asset_by_group/BioVudBTjJnuDW22q62XPhGP87sVwZKcQ46MPSNz4gqi b/integration_tests/tests/data/accounts/reg_get_asset_by_group/BioVudBTjJnuDW22q62XPhGP87sVwZKcQ46MPSNz4gqi new file mode 100644 index 000000000..aac046093 Binary files /dev/null and b/integration_tests/tests/data/accounts/reg_get_asset_by_group/BioVudBTjJnuDW22q62XPhGP87sVwZKcQ46MPSNz4gqi differ diff --git a/integration_tests/tests/data/accounts/reg_get_asset_by_group/Eft9Evw7Jqd5ZeDhpTXHbpv5ZrZ3tvc1paSXAqHd51cy b/integration_tests/tests/data/accounts/reg_get_asset_by_group/Eft9Evw7Jqd5ZeDhpTXHbpv5ZrZ3tvc1paSXAqHd51cy new file mode 100644 index 000000000..033b52062 Binary files /dev/null and b/integration_tests/tests/data/accounts/reg_get_asset_by_group/Eft9Evw7Jqd5ZeDhpTXHbpv5ZrZ3tvc1paSXAqHd51cy differ diff --git a/integration_tests/tests/data/accounts/reg_get_asset_by_group/Fm9S3FL23z3ii3EBBv8ozqLninLvhWDYmcHcHaZy6nie b/integration_tests/tests/data/accounts/reg_get_asset_by_group/Fm9S3FL23z3ii3EBBv8ozqLninLvhWDYmcHcHaZy6nie new file mode 100644 index 000000000..0a6f3855f Binary files /dev/null and b/integration_tests/tests/data/accounts/reg_get_asset_by_group/Fm9S3FL23z3ii3EBBv8ozqLninLvhWDYmcHcHaZy6nie differ diff --git a/integration_tests/tests/data/accounts/reg_get_asset_by_group/GcvCfh1V4YYUwDLs2KBKxFxKggLNxaUSWkSxnpDCRUVA b/integration_tests/tests/data/accounts/reg_get_asset_by_group/GcvCfh1V4YYUwDLs2KBKxFxKggLNxaUSWkSxnpDCRUVA new file mode 100644 index 000000000..0ed721dee Binary files /dev/null and b/integration_tests/tests/data/accounts/reg_get_asset_by_group/GcvCfh1V4YYUwDLs2KBKxFxKggLNxaUSWkSxnpDCRUVA differ diff --git a/integration_tests/tests/data/accounts/reg_search_assets/2PfAwPb2hdgsf7xCKyU2kAWUGKnkxYZLfg5SMf4YP1h2 b/integration_tests/tests/data/accounts/reg_search_assets/2PfAwPb2hdgsf7xCKyU2kAWUGKnkxYZLfg5SMf4YP1h2 new file mode 100644 index 000000000..002bd8814 Binary files /dev/null and b/integration_tests/tests/data/accounts/reg_search_assets/2PfAwPb2hdgsf7xCKyU2kAWUGKnkxYZLfg5SMf4YP1h2 differ diff --git a/integration_tests/tests/data/accounts/reg_search_assets/398rsAE6qxtkMPdMBqpVz7Ca52BdQrvPLs95pYrPRqnB b/integration_tests/tests/data/accounts/reg_search_assets/398rsAE6qxtkMPdMBqpVz7Ca52BdQrvPLs95pYrPRqnB new file mode 100644 index 000000000..d2b9902b8 Binary files /dev/null and b/integration_tests/tests/data/accounts/reg_search_assets/398rsAE6qxtkMPdMBqpVz7Ca52BdQrvPLs95pYrPRqnB differ diff --git a/integration_tests/tests/data/accounts/reg_search_assets/3XePvcrVVbGNKNuK7jrtAfeK8KUjCpXebL95RqGceYP8 b/integration_tests/tests/data/accounts/reg_search_assets/3XePvcrVVbGNKNuK7jrtAfeK8KUjCpXebL95RqGceYP8 new file mode 100644 index 000000000..49b6c5a47 Binary files /dev/null and b/integration_tests/tests/data/accounts/reg_search_assets/3XePvcrVVbGNKNuK7jrtAfeK8KUjCpXebL95RqGceYP8 differ diff --git a/integration_tests/tests/data/accounts/reg_search_assets/7DS81LourvNXo5PiWZp6G3vaSHZhY1rxT9VpG8YuFBiq b/integration_tests/tests/data/accounts/reg_search_assets/7DS81LourvNXo5PiWZp6G3vaSHZhY1rxT9VpG8YuFBiq new file mode 100644 index 000000000..0640eec9c Binary files /dev/null and b/integration_tests/tests/data/accounts/reg_search_assets/7DS81LourvNXo5PiWZp6G3vaSHZhY1rxT9VpG8YuFBiq differ diff --git a/integration_tests/tests/data/accounts/reg_search_assets/A7gxL4pMsck1WuwfZx4XhnL8FVBBzuameBcQnX45gWeq b/integration_tests/tests/data/accounts/reg_search_assets/A7gxL4pMsck1WuwfZx4XhnL8FVBBzuameBcQnX45gWeq new file mode 100644 index 000000000..687cfc543 Binary files /dev/null and b/integration_tests/tests/data/accounts/reg_search_assets/A7gxL4pMsck1WuwfZx4XhnL8FVBBzuameBcQnX45gWeq differ diff --git a/integration_tests/tests/data/accounts/reg_search_assets/Dt3XDSAdXAJbHqvuycgCTHykKCC7tntMFGMmSvfBbpTL b/integration_tests/tests/data/accounts/reg_search_assets/Dt3XDSAdXAJbHqvuycgCTHykKCC7tntMFGMmSvfBbpTL new file mode 100644 index 000000000..51792b5e2 Binary files /dev/null and b/integration_tests/tests/data/accounts/reg_search_assets/Dt3XDSAdXAJbHqvuycgCTHykKCC7tntMFGMmSvfBbpTL differ diff --git a/integration_tests/tests/data/largest_token_account_ids/2NqdYX6kJmMUoChnDXU2UrP9BsoPZivRw3uJG8iDhRRd/2NqdYX6kJmMUoChnDXU2UrP9BsoPZivRw3uJG8iDhRRd b/integration_tests/tests/data/largest_token_account_ids/2NqdYX6kJmMUoChnDXU2UrP9BsoPZivRw3uJG8iDhRRd/2NqdYX6kJmMUoChnDXU2UrP9BsoPZivRw3uJG8iDhRRd new file mode 100644 index 000000000..f2691f365 --- /dev/null +++ b/integration_tests/tests/data/largest_token_account_ids/2NqdYX6kJmMUoChnDXU2UrP9BsoPZivRw3uJG8iDhRRd/2NqdYX6kJmMUoChnDXU2UrP9BsoPZivRw3uJG8iDhRRd @@ -0,0 +1 @@ +±ªõ•Oé%ú› 5=¶<ã‹BbáZ#Òhû \ No newline at end of file diff --git a/integration_tests/tests/data/largest_token_account_ids/2PfAwPb2hdgsf7xCKyU2kAWUGKnkxYZLfg5SMf4YP1h2/2PfAwPb2hdgsf7xCKyU2kAWUGKnkxYZLfg5SMf4YP1h2 b/integration_tests/tests/data/largest_token_account_ids/2PfAwPb2hdgsf7xCKyU2kAWUGKnkxYZLfg5SMf4YP1h2/2PfAwPb2hdgsf7xCKyU2kAWUGKnkxYZLfg5SMf4YP1h2 new file mode 100644 index 000000000..4dc65b878 --- /dev/null +++ b/integration_tests/tests/data/largest_token_account_ids/2PfAwPb2hdgsf7xCKyU2kAWUGKnkxYZLfg5SMf4YP1h2/2PfAwPb2hdgsf7xCKyU2kAWUGKnkxYZLfg5SMf4YP1h2 @@ -0,0 +1 @@ +%‘ÀÞôÖ+[ƒþ`Úûcu¢”…‰‡ëáP¾U3¹ Ù· \ No newline at end of file diff --git a/integration_tests/tests/data/largest_token_account_ids/5rEeYv8R25b8j6YTHJvYuCKEzq44UCw1Wx1Wx2VPPLz1/5rEeYv8R25b8j6YTHJvYuCKEzq44UCw1Wx1Wx2VPPLz1 b/integration_tests/tests/data/largest_token_account_ids/5rEeYv8R25b8j6YTHJvYuCKEzq44UCw1Wx1Wx2VPPLz1/5rEeYv8R25b8j6YTHJvYuCKEzq44UCw1Wx1Wx2VPPLz1 new file mode 100644 index 000000000..db364f166 --- /dev/null +++ b/integration_tests/tests/data/largest_token_account_ids/5rEeYv8R25b8j6YTHJvYuCKEzq44UCw1Wx1Wx2VPPLz1/5rEeYv8R25b8j6YTHJvYuCKEzq44UCw1Wx1Wx2VPPLz1 @@ -0,0 +1 @@ +‡Ñq œv5.²hÂäæ.|§tz‹¶W'as(D~Ž \ No newline at end of file diff --git a/integration_tests/tests/data/largest_token_account_ids/7jFuJ73mBPDdLMvCYxzrpFTD9FeDudRxdXGDALP5Cp2W/7jFuJ73mBPDdLMvCYxzrpFTD9FeDudRxdXGDALP5Cp2W b/integration_tests/tests/data/largest_token_account_ids/7jFuJ73mBPDdLMvCYxzrpFTD9FeDudRxdXGDALP5Cp2W/7jFuJ73mBPDdLMvCYxzrpFTD9FeDudRxdXGDALP5Cp2W new file mode 100644 index 000000000..dded31ff5 --- /dev/null +++ b/integration_tests/tests/data/largest_token_account_ids/7jFuJ73mBPDdLMvCYxzrpFTD9FeDudRxdXGDALP5Cp2W/7jFuJ73mBPDdLMvCYxzrpFTD9FeDudRxdXGDALP5Cp2W @@ -0,0 +1 @@ +ËÓÊÀF+761ŸÍòtW¹‚Ë™5Ýaàðõ56I¯† \ No newline at end of file diff --git a/integration_tests/tests/data/largest_token_account_ids/843gdpsTE4DoJz3ZoBsEjAqT8UgAcyF5YojygGgGZE1f/843gdpsTE4DoJz3ZoBsEjAqT8UgAcyF5YojygGgGZE1f b/integration_tests/tests/data/largest_token_account_ids/843gdpsTE4DoJz3ZoBsEjAqT8UgAcyF5YojygGgGZE1f/843gdpsTE4DoJz3ZoBsEjAqT8UgAcyF5YojygGgGZE1f new file mode 100644 index 000000000..15185d084 --- /dev/null +++ b/integration_tests/tests/data/largest_token_account_ids/843gdpsTE4DoJz3ZoBsEjAqT8UgAcyF5YojygGgGZE1f/843gdpsTE4DoJz3ZoBsEjAqT8UgAcyF5YojygGgGZE1f @@ -0,0 +1 @@ +·ú–-Îh™Þ„È9⦠~íÃŒ LÞÒ>•,ê¡k³ \ No newline at end of file diff --git a/integration_tests/tests/data/largest_token_account_ids/ANt9HygtvFmFJ1UcAHFLnM62JJWjk8fujMzjGfpKBfzk/ANt9HygtvFmFJ1UcAHFLnM62JJWjk8fujMzjGfpKBfzk b/integration_tests/tests/data/largest_token_account_ids/ANt9HygtvFmFJ1UcAHFLnM62JJWjk8fujMzjGfpKBfzk/ANt9HygtvFmFJ1UcAHFLnM62JJWjk8fujMzjGfpKBfzk new file mode 100644 index 000000000..584f9f841 Binary files /dev/null and b/integration_tests/tests/data/largest_token_account_ids/ANt9HygtvFmFJ1UcAHFLnM62JJWjk8fujMzjGfpKBfzk/ANt9HygtvFmFJ1UcAHFLnM62JJWjk8fujMzjGfpKBfzk differ diff --git a/integration_tests/tests/data/largest_token_account_ids/Az9QTysJj1LW1F7zkYF21HgBj3FRpq3zpxTFdPnAJYm8/Az9QTysJj1LW1F7zkYF21HgBj3FRpq3zpxTFdPnAJYm8 b/integration_tests/tests/data/largest_token_account_ids/Az9QTysJj1LW1F7zkYF21HgBj3FRpq3zpxTFdPnAJYm8/Az9QTysJj1LW1F7zkYF21HgBj3FRpq3zpxTFdPnAJYm8 new file mode 100644 index 000000000..14027b7ca --- /dev/null +++ b/integration_tests/tests/data/largest_token_account_ids/Az9QTysJj1LW1F7zkYF21HgBj3FRpq3zpxTFdPnAJYm8/Az9QTysJj1LW1F7zkYF21HgBj3FRpq3zpxTFdPnAJYm8 @@ -0,0 +1 @@ +•´Ó‰àó¤Áös{xc»º…Âü—Îö<†K¬ª×Ödz \ No newline at end of file diff --git a/integration_tests/tests/data/largest_token_account_ids/BioVudBTjJnuDW22q62XPhGP87sVwZKcQ46MPSNz4gqi/BioVudBTjJnuDW22q62XPhGP87sVwZKcQ46MPSNz4gqi b/integration_tests/tests/data/largest_token_account_ids/BioVudBTjJnuDW22q62XPhGP87sVwZKcQ46MPSNz4gqi/BioVudBTjJnuDW22q62XPhGP87sVwZKcQ46MPSNz4gqi new file mode 100644 index 000000000..251d00821 --- /dev/null +++ b/integration_tests/tests/data/largest_token_account_ids/BioVudBTjJnuDW22q62XPhGP87sVwZKcQ46MPSNz4gqi/BioVudBTjJnuDW22q62XPhGP87sVwZKcQ46MPSNz4gqi @@ -0,0 +1 @@ +I×9´:+HÇ{žf¡Ø²Ã©™é^h”ÃÈäö]ž7ƒ \ No newline at end of file diff --git a/integration_tests/tests/data/largest_token_account_ids/CMVuYDS9nTeujfTPJb8ik7CRhAqZv4DfjfdamFLkJgxE/CMVuYDS9nTeujfTPJb8ik7CRhAqZv4DfjfdamFLkJgxE b/integration_tests/tests/data/largest_token_account_ids/CMVuYDS9nTeujfTPJb8ik7CRhAqZv4DfjfdamFLkJgxE/CMVuYDS9nTeujfTPJb8ik7CRhAqZv4DfjfdamFLkJgxE new file mode 100644 index 000000000..1f698e0b5 --- /dev/null +++ b/integration_tests/tests/data/largest_token_account_ids/CMVuYDS9nTeujfTPJb8ik7CRhAqZv4DfjfdamFLkJgxE/CMVuYDS9nTeujfTPJb8ik7CRhAqZv4DfjfdamFLkJgxE @@ -0,0 +1,2 @@ +ØûXÂP|ÇÞº½†Ñûçù få +²‘‚‹ «8S9h \ No newline at end of file diff --git a/integration_tests/tests/data/largest_token_account_ids/Dt3XDSAdXAJbHqvuycgCTHykKCC7tntMFGMmSvfBbpTL/Dt3XDSAdXAJbHqvuycgCTHykKCC7tntMFGMmSvfBbpTL b/integration_tests/tests/data/largest_token_account_ids/Dt3XDSAdXAJbHqvuycgCTHykKCC7tntMFGMmSvfBbpTL/Dt3XDSAdXAJbHqvuycgCTHykKCC7tntMFGMmSvfBbpTL new file mode 100644 index 000000000..8cb0a8835 --- /dev/null +++ b/integration_tests/tests/data/largest_token_account_ids/Dt3XDSAdXAJbHqvuycgCTHykKCC7tntMFGMmSvfBbpTL/Dt3XDSAdXAJbHqvuycgCTHykKCC7tntMFGMmSvfBbpTL @@ -0,0 +1 @@ +\U~Ôçi¨JY–I4‹qîòñWï«m¦ŸCG…­_ò \ No newline at end of file diff --git a/integration_tests/tests/data/largest_token_account_ids/Fm9S3FL23z3ii3EBBv8ozqLninLvhWDYmcHcHaZy6nie/Fm9S3FL23z3ii3EBBv8ozqLninLvhWDYmcHcHaZy6nie b/integration_tests/tests/data/largest_token_account_ids/Fm9S3FL23z3ii3EBBv8ozqLninLvhWDYmcHcHaZy6nie/Fm9S3FL23z3ii3EBBv8ozqLninLvhWDYmcHcHaZy6nie new file mode 100644 index 000000000..734685480 --- /dev/null +++ b/integration_tests/tests/data/largest_token_account_ids/Fm9S3FL23z3ii3EBBv8ozqLninLvhWDYmcHcHaZy6nie/Fm9S3FL23z3ii3EBBv8ozqLninLvhWDYmcHcHaZy6nie @@ -0,0 +1 @@ +:$ÆïÜɆt(™¼¢«ª¡;!ÓÖ,ç«´0?¡~ \ No newline at end of file diff --git a/integration_tests/tests/data/largest_token_account_ids/HTKAVZZrDdyecCxzm3WEkCsG1GUmiqKm73PvngfuYRNK/HTKAVZZrDdyecCxzm3WEkCsG1GUmiqKm73PvngfuYRNK b/integration_tests/tests/data/largest_token_account_ids/HTKAVZZrDdyecCxzm3WEkCsG1GUmiqKm73PvngfuYRNK/HTKAVZZrDdyecCxzm3WEkCsG1GUmiqKm73PvngfuYRNK new file mode 100644 index 000000000..13cdc4193 Binary files /dev/null and b/integration_tests/tests/data/largest_token_account_ids/HTKAVZZrDdyecCxzm3WEkCsG1GUmiqKm73PvngfuYRNK/HTKAVZZrDdyecCxzm3WEkCsG1GUmiqKm73PvngfuYRNK differ diff --git a/integration_tests/tests/data/transactions/asset_decompress/3Ct9n9hv5PWEYbsrgDdUDqegzsnX2n5jYRxkq5YafFAueup8mTYmN4nHhNCaEwVyVAVqNssr4fizdg9wRavT7ydE b/integration_tests/tests/data/transactions/asset_decompress/3Ct9n9hv5PWEYbsrgDdUDqegzsnX2n5jYRxkq5YafFAueup8mTYmN4nHhNCaEwVyVAVqNssr4fizdg9wRavT7ydE new file mode 100644 index 000000000..015b543df Binary files /dev/null and b/integration_tests/tests/data/transactions/asset_decompress/3Ct9n9hv5PWEYbsrgDdUDqegzsnX2n5jYRxkq5YafFAueup8mTYmN4nHhNCaEwVyVAVqNssr4fizdg9wRavT7ydE differ diff --git a/integration_tests/tests/data/transactions/asset_decompress/4FQRV38NSP6gDo8qDbTBfy8UDHUd6Lzu4GXbHtfvWbtCArkVcbGQwinZ7M61eCmPEF5L8xu4tLAXL7ozbh5scfRi b/integration_tests/tests/data/transactions/asset_decompress/4FQRV38NSP6gDo8qDbTBfy8UDHUd6Lzu4GXbHtfvWbtCArkVcbGQwinZ7M61eCmPEF5L8xu4tLAXL7ozbh5scfRi new file mode 100644 index 000000000..ca99e06a4 Binary files /dev/null and b/integration_tests/tests/data/transactions/asset_decompress/4FQRV38NSP6gDo8qDbTBfy8UDHUd6Lzu4GXbHtfvWbtCArkVcbGQwinZ7M61eCmPEF5L8xu4tLAXL7ozbh5scfRi differ diff --git a/integration_tests/tests/data/transactions/asset_decompress/55tQCoLUtHyu4i6Dny6SMdq4dVD61nuuLxXvRLeeQqE6xdm66Ajm4so39MXcJ2VaTmCNDEFBpitzLkiFaF7rNtHi b/integration_tests/tests/data/transactions/asset_decompress/55tQCoLUtHyu4i6Dny6SMdq4dVD61nuuLxXvRLeeQqE6xdm66Ajm4so39MXcJ2VaTmCNDEFBpitzLkiFaF7rNtHi new file mode 100644 index 000000000..73c54cb19 Binary files /dev/null and b/integration_tests/tests/data/transactions/asset_decompress/55tQCoLUtHyu4i6Dny6SMdq4dVD61nuuLxXvRLeeQqE6xdm66Ajm4so39MXcJ2VaTmCNDEFBpitzLkiFaF7rNtHi differ diff --git a/integration_tests/tests/data/transactions/cnft_owners_table/25djDqCTka7wEnNMRVwsqSsVHqQMknPReTUCmvF4XGD9bUD494jZ1FsPaPjbAK45TxpdVuF2RwVCK9Jq7oxZAtMB b/integration_tests/tests/data/transactions/cnft_owners_table/25djDqCTka7wEnNMRVwsqSsVHqQMknPReTUCmvF4XGD9bUD494jZ1FsPaPjbAK45TxpdVuF2RwVCK9Jq7oxZAtMB new file mode 100644 index 000000000..4f57eac09 Binary files /dev/null and b/integration_tests/tests/data/transactions/cnft_owners_table/25djDqCTka7wEnNMRVwsqSsVHqQMknPReTUCmvF4XGD9bUD494jZ1FsPaPjbAK45TxpdVuF2RwVCK9Jq7oxZAtMB differ diff --git a/integration_tests/tests/data/transactions/cnft_owners_table/3UrxyfoJKH2jvVkzZZuCMXxtyaFUtgjhoQmirwhyiFjZXA8oM3QCBixCSBj9b53t5scvsm3qpuq5Qm4cGbNuwQP7 b/integration_tests/tests/data/transactions/cnft_owners_table/3UrxyfoJKH2jvVkzZZuCMXxtyaFUtgjhoQmirwhyiFjZXA8oM3QCBixCSBj9b53t5scvsm3qpuq5Qm4cGbNuwQP7 new file mode 100644 index 000000000..ca454df25 Binary files /dev/null and b/integration_tests/tests/data/transactions/cnft_owners_table/3UrxyfoJKH2jvVkzZZuCMXxtyaFUtgjhoQmirwhyiFjZXA8oM3QCBixCSBj9b53t5scvsm3qpuq5Qm4cGbNuwQP7 differ diff --git a/integration_tests/tests/data/transactions/cnft_owners_table/4fzBjTaXmrrJReLLSYPzn1fhPfuiU2EU1hGUddtHV1B49pvRewGyyzvMMpssi7K4Y5ZYj5xS9DrJuxqJDZRMZqY1 b/integration_tests/tests/data/transactions/cnft_owners_table/4fzBjTaXmrrJReLLSYPzn1fhPfuiU2EU1hGUddtHV1B49pvRewGyyzvMMpssi7K4Y5ZYj5xS9DrJuxqJDZRMZqY1 new file mode 100644 index 000000000..6520e2dc0 Binary files /dev/null and b/integration_tests/tests/data/transactions/cnft_owners_table/4fzBjTaXmrrJReLLSYPzn1fhPfuiU2EU1hGUddtHV1B49pvRewGyyzvMMpssi7K4Y5ZYj5xS9DrJuxqJDZRMZqY1 differ diff --git a/integration_tests/tests/data/transactions/cnft_scenario_mint_update_metadata/2DP84v6Pi3e4v5i7KSvzmK4Ufbzof3TAiEqDbm9gg8jZpBRF9f1Cy6x54kvZoHPX9k1XfqbsG1FTv2KVP9fvNrN6 b/integration_tests/tests/data/transactions/cnft_scenario_mint_update_metadata/2DP84v6Pi3e4v5i7KSvzmK4Ufbzof3TAiEqDbm9gg8jZpBRF9f1Cy6x54kvZoHPX9k1XfqbsG1FTv2KVP9fvNrN6 new file mode 100644 index 000000000..a25f1b837 Binary files /dev/null and b/integration_tests/tests/data/transactions/cnft_scenario_mint_update_metadata/2DP84v6Pi3e4v5i7KSvzmK4Ufbzof3TAiEqDbm9gg8jZpBRF9f1Cy6x54kvZoHPX9k1XfqbsG1FTv2KVP9fvNrN6 differ diff --git a/integration_tests/tests/data/transactions/cnft_scenario_mint_update_metadata/3bsL5zmLKvhN9Je4snTKxjFSpmXEEg2cvMHm2rCNgaEYkNXBqJTA4N7QmvBSWPiNUQPtzJSYzpQYX92NowV3L7vN b/integration_tests/tests/data/transactions/cnft_scenario_mint_update_metadata/3bsL5zmLKvhN9Je4snTKxjFSpmXEEg2cvMHm2rCNgaEYkNXBqJTA4N7QmvBSWPiNUQPtzJSYzpQYX92NowV3L7vN new file mode 100644 index 000000000..0223d8bcf Binary files /dev/null and b/integration_tests/tests/data/transactions/cnft_scenario_mint_update_metadata/3bsL5zmLKvhN9Je4snTKxjFSpmXEEg2cvMHm2rCNgaEYkNXBqJTA4N7QmvBSWPiNUQPtzJSYzpQYX92NowV3L7vN differ diff --git a/integration_tests/tests/data/transactions/cnft_scenario_mint_update_metadata_remove_creators/2qMQrXfRE7pdnjwobWeqDkEhsv6MYmv3JdgvNxTVaL1VrMCZ4JYkUnu7jiJb2etX3W9WyQgSxktUgn9skxCeqTo5 b/integration_tests/tests/data/transactions/cnft_scenario_mint_update_metadata_remove_creators/2qMQrXfRE7pdnjwobWeqDkEhsv6MYmv3JdgvNxTVaL1VrMCZ4JYkUnu7jiJb2etX3W9WyQgSxktUgn9skxCeqTo5 new file mode 100644 index 000000000..bda639523 Binary files /dev/null and b/integration_tests/tests/data/transactions/cnft_scenario_mint_update_metadata_remove_creators/2qMQrXfRE7pdnjwobWeqDkEhsv6MYmv3JdgvNxTVaL1VrMCZ4JYkUnu7jiJb2etX3W9WyQgSxktUgn9skxCeqTo5 differ diff --git a/integration_tests/tests/data/transactions/cnft_scenario_mint_update_metadata_remove_creators/41YW187sn6Z2dXfqz6zSbnPtQoE826cCSgTLnMLKa9rH1xrCqAXBQNwKnzjGc9wjU5RtMCqKhy2eMN2TjuYC8veB b/integration_tests/tests/data/transactions/cnft_scenario_mint_update_metadata_remove_creators/41YW187sn6Z2dXfqz6zSbnPtQoE826cCSgTLnMLKa9rH1xrCqAXBQNwKnzjGc9wjU5RtMCqKhy2eMN2TjuYC8veB new file mode 100644 index 000000000..fc26c68a9 Binary files /dev/null and b/integration_tests/tests/data/transactions/cnft_scenario_mint_update_metadata_remove_creators/41YW187sn6Z2dXfqz6zSbnPtQoE826cCSgTLnMLKa9rH1xrCqAXBQNwKnzjGc9wjU5RtMCqKhy2eMN2TjuYC8veB differ diff --git a/integration_tests/tests/data/transactions/mint_delegate_transfer/3B1sASkuToCWuGFRG47axQDm1SpgLi8qDDGnRFeR7LB6oa5C3ZmkEuX98373gdMTBXED44FkwT227kBBAGSw7e8M b/integration_tests/tests/data/transactions/mint_delegate_transfer/3B1sASkuToCWuGFRG47axQDm1SpgLi8qDDGnRFeR7LB6oa5C3ZmkEuX98373gdMTBXED44FkwT227kBBAGSw7e8M new file mode 100644 index 000000000..69de59cad Binary files /dev/null and b/integration_tests/tests/data/transactions/mint_delegate_transfer/3B1sASkuToCWuGFRG47axQDm1SpgLi8qDDGnRFeR7LB6oa5C3ZmkEuX98373gdMTBXED44FkwT227kBBAGSw7e8M differ diff --git a/integration_tests/tests/data/transactions/mint_delegate_transfer/5Q8TAMMkMTHEM2BHyD2fp2sVdYKByFeATzM2mHF6Xbbar33WaeuygPKGYCWiDEt3MZU1mUrq1ePnT9o4Pa318p8w b/integration_tests/tests/data/transactions/mint_delegate_transfer/5Q8TAMMkMTHEM2BHyD2fp2sVdYKByFeATzM2mHF6Xbbar33WaeuygPKGYCWiDEt3MZU1mUrq1ePnT9o4Pa318p8w new file mode 100644 index 000000000..666b8b685 Binary files /dev/null and b/integration_tests/tests/data/transactions/mint_delegate_transfer/5Q8TAMMkMTHEM2BHyD2fp2sVdYKByFeATzM2mHF6Xbbar33WaeuygPKGYCWiDEt3MZU1mUrq1ePnT9o4Pa318p8w differ diff --git a/integration_tests/tests/data/transactions/mint_delegate_transfer/KNWsAYPo3mm1HuFxRyEwBBMUZ2hqTnFXjoPVFo7WxGTfmfRwz6K8eERc4dnJpHyuoDkAZu1czK55iB1SbtCsdW2 b/integration_tests/tests/data/transactions/mint_delegate_transfer/KNWsAYPo3mm1HuFxRyEwBBMUZ2hqTnFXjoPVFo7WxGTfmfRwz6K8eERc4dnJpHyuoDkAZu1czK55iB1SbtCsdW2 new file mode 100644 index 000000000..78a48c184 Binary files /dev/null and b/integration_tests/tests/data/transactions/mint_delegate_transfer/KNWsAYPo3mm1HuFxRyEwBBMUZ2hqTnFXjoPVFo7WxGTfmfRwz6K8eERc4dnJpHyuoDkAZu1czK55iB1SbtCsdW2 differ diff --git a/integration_tests/tests/data/transactions/mint_no_json_uri/4ASu45ELoTmvwhNqokGQrh2VH8p5zeUepYLbkcULMeXSCZJGrJa7ojgdVh5JUxBjAMF9Lrp55EgUUFPaPeWKejNQ b/integration_tests/tests/data/transactions/mint_no_json_uri/4ASu45ELoTmvwhNqokGQrh2VH8p5zeUepYLbkcULMeXSCZJGrJa7ojgdVh5JUxBjAMF9Lrp55EgUUFPaPeWKejNQ new file mode 100644 index 000000000..566aab62a Binary files /dev/null and b/integration_tests/tests/data/transactions/mint_no_json_uri/4ASu45ELoTmvwhNqokGQrh2VH8p5zeUepYLbkcULMeXSCZJGrJa7ojgdVh5JUxBjAMF9Lrp55EgUUFPaPeWKejNQ differ diff --git a/integration_tests/tests/data/transactions/mint_redeem/3Ct9n9hv5PWEYbsrgDdUDqegzsnX2n5jYRxkq5YafFAueup8mTYmN4nHhNCaEwVyVAVqNssr4fizdg9wRavT7ydE b/integration_tests/tests/data/transactions/mint_redeem/3Ct9n9hv5PWEYbsrgDdUDqegzsnX2n5jYRxkq5YafFAueup8mTYmN4nHhNCaEwVyVAVqNssr4fizdg9wRavT7ydE new file mode 100644 index 000000000..ede4fe3ec Binary files /dev/null and b/integration_tests/tests/data/transactions/mint_redeem/3Ct9n9hv5PWEYbsrgDdUDqegzsnX2n5jYRxkq5YafFAueup8mTYmN4nHhNCaEwVyVAVqNssr4fizdg9wRavT7ydE differ diff --git a/integration_tests/tests/data/transactions/mint_redeem/4FQRV38NSP6gDo8qDbTBfy8UDHUd6Lzu4GXbHtfvWbtCArkVcbGQwinZ7M61eCmPEF5L8xu4tLAXL7ozbh5scfRi b/integration_tests/tests/data/transactions/mint_redeem/4FQRV38NSP6gDo8qDbTBfy8UDHUd6Lzu4GXbHtfvWbtCArkVcbGQwinZ7M61eCmPEF5L8xu4tLAXL7ozbh5scfRi new file mode 100644 index 000000000..ef1c09b03 Binary files /dev/null and b/integration_tests/tests/data/transactions/mint_redeem/4FQRV38NSP6gDo8qDbTBfy8UDHUd6Lzu4GXbHtfvWbtCArkVcbGQwinZ7M61eCmPEF5L8xu4tLAXL7ozbh5scfRi differ diff --git a/integration_tests/tests/data/transactions/mint_redeem/55tQCoLUtHyu4i6Dny6SMdq4dVD61nuuLxXvRLeeQqE6xdm66Ajm4so39MXcJ2VaTmCNDEFBpitzLkiFaF7rNtHi b/integration_tests/tests/data/transactions/mint_redeem/55tQCoLUtHyu4i6Dny6SMdq4dVD61nuuLxXvRLeeQqE6xdm66Ajm4so39MXcJ2VaTmCNDEFBpitzLkiFaF7rNtHi new file mode 100644 index 000000000..695e5a280 Binary files /dev/null and b/integration_tests/tests/data/transactions/mint_redeem/55tQCoLUtHyu4i6Dny6SMdq4dVD61nuuLxXvRLeeQqE6xdm66Ajm4so39MXcJ2VaTmCNDEFBpitzLkiFaF7rNtHi differ diff --git a/integration_tests/tests/data/transactions/mint_redeem_cancel_redeem/32FpSe6r9jnFNjjvbx2PPQdZqs5KpMoF6yawiRW1F6ctu1kmx2B4sLDBGjsthVQtmnhaJVrqdtmUP893FwXCbqY5 b/integration_tests/tests/data/transactions/mint_redeem_cancel_redeem/32FpSe6r9jnFNjjvbx2PPQdZqs5KpMoF6yawiRW1F6ctu1kmx2B4sLDBGjsthVQtmnhaJVrqdtmUP893FwXCbqY5 new file mode 100644 index 000000000..d439c59f2 Binary files /dev/null and b/integration_tests/tests/data/transactions/mint_redeem_cancel_redeem/32FpSe6r9jnFNjjvbx2PPQdZqs5KpMoF6yawiRW1F6ctu1kmx2B4sLDBGjsthVQtmnhaJVrqdtmUP893FwXCbqY5 differ diff --git a/integration_tests/tests/data/transactions/mint_redeem_cancel_redeem/3uzWoVgLGVd9cGXaF3JW7znpWgKse3obCa2Vvdoe59kaziX84mEXTwecUoZ49PkJDjReRMSXksKzyfj7pf3ekAGR b/integration_tests/tests/data/transactions/mint_redeem_cancel_redeem/3uzWoVgLGVd9cGXaF3JW7znpWgKse3obCa2Vvdoe59kaziX84mEXTwecUoZ49PkJDjReRMSXksKzyfj7pf3ekAGR new file mode 100644 index 000000000..5a1694149 Binary files /dev/null and b/integration_tests/tests/data/transactions/mint_redeem_cancel_redeem/3uzWoVgLGVd9cGXaF3JW7znpWgKse3obCa2Vvdoe59kaziX84mEXTwecUoZ49PkJDjReRMSXksKzyfj7pf3ekAGR differ diff --git a/integration_tests/tests/data/transactions/mint_redeem_cancel_redeem/49bJ8U3cK9htmLvA1mhXXcjKdpV2YN5JQBrb3Quh7wxENz1BP9F8fE9CKsje41aMbZwzgomnkXirKx2Xpdvprtak b/integration_tests/tests/data/transactions/mint_redeem_cancel_redeem/49bJ8U3cK9htmLvA1mhXXcjKdpV2YN5JQBrb3Quh7wxENz1BP9F8fE9CKsje41aMbZwzgomnkXirKx2Xpdvprtak new file mode 100644 index 000000000..4a073e5de Binary files /dev/null and b/integration_tests/tests/data/transactions/mint_redeem_cancel_redeem/49bJ8U3cK9htmLvA1mhXXcjKdpV2YN5JQBrb3Quh7wxENz1BP9F8fE9CKsje41aMbZwzgomnkXirKx2Xpdvprtak differ diff --git a/integration_tests/tests/data/transactions/mint_transfer_burn/5coWPFty37s7haT3SVyMf6PkTaABEnhCRhfDjXeMNS58czHB5dCFPY6VrsZNwxBnqypmNic1LbLp1j5qjbdnZAc8 b/integration_tests/tests/data/transactions/mint_transfer_burn/5coWPFty37s7haT3SVyMf6PkTaABEnhCRhfDjXeMNS58czHB5dCFPY6VrsZNwxBnqypmNic1LbLp1j5qjbdnZAc8 new file mode 100644 index 000000000..2fab26b71 Binary files /dev/null and b/integration_tests/tests/data/transactions/mint_transfer_burn/5coWPFty37s7haT3SVyMf6PkTaABEnhCRhfDjXeMNS58czHB5dCFPY6VrsZNwxBnqypmNic1LbLp1j5qjbdnZAc8 differ diff --git a/integration_tests/tests/data/transactions/mint_transfer_burn/KHNhLijkAMeKeKm6kpbk3go6q9uMF3zmfCoYSBgERe8qJDW8q5ANpnkyBuyVkychXCeWzRY8i5EtKfeGaDDU23w b/integration_tests/tests/data/transactions/mint_transfer_burn/KHNhLijkAMeKeKm6kpbk3go6q9uMF3zmfCoYSBgERe8qJDW8q5ANpnkyBuyVkychXCeWzRY8i5EtKfeGaDDU23w new file mode 100644 index 000000000..3e2026e46 Binary files /dev/null and b/integration_tests/tests/data/transactions/mint_transfer_burn/KHNhLijkAMeKeKm6kpbk3go6q9uMF3zmfCoYSBgERe8qJDW8q5ANpnkyBuyVkychXCeWzRY8i5EtKfeGaDDU23w differ diff --git a/integration_tests/tests/data/transactions/mint_transfer_burn/k6jmJcurgBQ6F2bVa86Z1vGb7ievzxwRZ8GAqzFEG8HicDizxceYPUm1KTzWZ3QKtGgy1EuFWUGCRqBeKU9SAoJ b/integration_tests/tests/data/transactions/mint_transfer_burn/k6jmJcurgBQ6F2bVa86Z1vGb7ievzxwRZ8GAqzFEG8HicDizxceYPUm1KTzWZ3QKtGgy1EuFWUGCRqBeKU9SAoJ new file mode 100644 index 000000000..acd42a476 Binary files /dev/null and b/integration_tests/tests/data/transactions/mint_transfer_burn/k6jmJcurgBQ6F2bVa86Z1vGb7ievzxwRZ8GAqzFEG8HicDizxceYPUm1KTzWZ3QKtGgy1EuFWUGCRqBeKU9SAoJ differ diff --git a/integration_tests/tests/data/transactions/mint_transfer_noop/4URwUGBjbsF7UBUYdSC546tnBy7nD67txsso8D9CR9kGLtbbYh9NkGw15tEp16LLasmJX5VQR4Seh8gDjTrtdpoC b/integration_tests/tests/data/transactions/mint_transfer_noop/4URwUGBjbsF7UBUYdSC546tnBy7nD67txsso8D9CR9kGLtbbYh9NkGw15tEp16LLasmJX5VQR4Seh8gDjTrtdpoC new file mode 100644 index 000000000..a9f81afe7 Binary files /dev/null and b/integration_tests/tests/data/transactions/mint_transfer_noop/4URwUGBjbsF7UBUYdSC546tnBy7nD67txsso8D9CR9kGLtbbYh9NkGw15tEp16LLasmJX5VQR4Seh8gDjTrtdpoC differ diff --git a/integration_tests/tests/data/transactions/mint_transfer_noop/4nKDSvw2kGpccZWLEPnfdP7J1SEexQFRP3xWc9NBtQ1qQeGu3bu5WnAdpcLbjQ4iyX6BQ5QGF69wevE8ZeeY5poA b/integration_tests/tests/data/transactions/mint_transfer_noop/4nKDSvw2kGpccZWLEPnfdP7J1SEexQFRP3xWc9NBtQ1qQeGu3bu5WnAdpcLbjQ4iyX6BQ5QGF69wevE8ZeeY5poA new file mode 100644 index 000000000..23b8337f4 Binary files /dev/null and b/integration_tests/tests/data/transactions/mint_transfer_noop/4nKDSvw2kGpccZWLEPnfdP7J1SEexQFRP3xWc9NBtQ1qQeGu3bu5WnAdpcLbjQ4iyX6BQ5QGF69wevE8ZeeY5poA differ diff --git a/integration_tests/tests/data/transactions/mint_transfer_noop/5bNyZfmxLVP9cKc6GjvozExrSt4F1QFt4PP992pQwT8FFHdWsX3ZFNvwurfU2xpDYtQ7qAUxVahGCraXMevRH8p1 b/integration_tests/tests/data/transactions/mint_transfer_noop/5bNyZfmxLVP9cKc6GjvozExrSt4F1QFt4PP992pQwT8FFHdWsX3ZFNvwurfU2xpDYtQ7qAUxVahGCraXMevRH8p1 new file mode 100644 index 000000000..d61d4ac70 Binary files /dev/null and b/integration_tests/tests/data/transactions/mint_transfer_noop/5bNyZfmxLVP9cKc6GjvozExrSt4F1QFt4PP992pQwT8FFHdWsX3ZFNvwurfU2xpDYtQ7qAUxVahGCraXMevRH8p1 differ diff --git a/integration_tests/tests/data/transactions/mint_transfer_transfer/34xjcNf3rZFKz381hKpFLqxpojaDgXEpCqH5qcpTXLaJnDbtqRz35wiuMF1cAgvJGLzYYrwaMvCK1D7LxYsdpMU1 b/integration_tests/tests/data/transactions/mint_transfer_transfer/34xjcNf3rZFKz381hKpFLqxpojaDgXEpCqH5qcpTXLaJnDbtqRz35wiuMF1cAgvJGLzYYrwaMvCK1D7LxYsdpMU1 new file mode 100644 index 000000000..40bcf40eb Binary files /dev/null and b/integration_tests/tests/data/transactions/mint_transfer_transfer/34xjcNf3rZFKz381hKpFLqxpojaDgXEpCqH5qcpTXLaJnDbtqRz35wiuMF1cAgvJGLzYYrwaMvCK1D7LxYsdpMU1 differ diff --git a/integration_tests/tests/data/transactions/mint_transfer_transfer/5VC3Jqr5X1N8NB8zuSahHpayekLVozYkDiPjJLqU6H5M6fq9ExVLGYYKKCPbeksMPXTjy65sdEQGPzDWAYPs8QjP b/integration_tests/tests/data/transactions/mint_transfer_transfer/5VC3Jqr5X1N8NB8zuSahHpayekLVozYkDiPjJLqU6H5M6fq9ExVLGYYKKCPbeksMPXTjy65sdEQGPzDWAYPs8QjP new file mode 100644 index 000000000..e2866921f Binary files /dev/null and b/integration_tests/tests/data/transactions/mint_transfer_transfer/5VC3Jqr5X1N8NB8zuSahHpayekLVozYkDiPjJLqU6H5M6fq9ExVLGYYKKCPbeksMPXTjy65sdEQGPzDWAYPs8QjP differ diff --git a/integration_tests/tests/data/transactions/mint_transfer_transfer/5bq936UgGs4RnxM78iXp1PwVhr8sTYoEsHCWpr8QBFtc2YtS3ieYHcsPG46G2ikwrS3tXYnUK93PzseT52AR81RR b/integration_tests/tests/data/transactions/mint_transfer_transfer/5bq936UgGs4RnxM78iXp1PwVhr8sTYoEsHCWpr8QBFtc2YtS3ieYHcsPG46G2ikwrS3tXYnUK93PzseT52AR81RR new file mode 100644 index 000000000..c6d8e6d10 Binary files /dev/null and b/integration_tests/tests/data/transactions/mint_transfer_transfer/5bq936UgGs4RnxM78iXp1PwVhr8sTYoEsHCWpr8QBFtc2YtS3ieYHcsPG46G2ikwrS3tXYnUK93PzseT52AR81RR differ diff --git a/integration_tests/tests/data/transactions/mint_verify_collection/5ZKjPxm3WAZzuqqkCDjgKpm9b5XjB9cuvv68JvXxWThvJaJxcMJgpSbYs4gDA9dGJyeLzsgNtnS6oubANF1KbBmt b/integration_tests/tests/data/transactions/mint_verify_collection/5ZKjPxm3WAZzuqqkCDjgKpm9b5XjB9cuvv68JvXxWThvJaJxcMJgpSbYs4gDA9dGJyeLzsgNtnS6oubANF1KbBmt new file mode 100644 index 000000000..acc78c53a Binary files /dev/null and b/integration_tests/tests/data/transactions/mint_verify_collection/5ZKjPxm3WAZzuqqkCDjgKpm9b5XjB9cuvv68JvXxWThvJaJxcMJgpSbYs4gDA9dGJyeLzsgNtnS6oubANF1KbBmt differ diff --git a/integration_tests/tests/data/transactions/mint_verify_collection/63xhs5bXcuMR3uMACXWkkFMm7BJ9Thknh7WNMPzV8HJBNwpyxJTr98NrLFHnTZDHdSUFD42VFQx8rjSaGynWbaRs b/integration_tests/tests/data/transactions/mint_verify_collection/63xhs5bXcuMR3uMACXWkkFMm7BJ9Thknh7WNMPzV8HJBNwpyxJTr98NrLFHnTZDHdSUFD42VFQx8rjSaGynWbaRs new file mode 100644 index 000000000..bd15ff8fd Binary files /dev/null and b/integration_tests/tests/data/transactions/mint_verify_collection/63xhs5bXcuMR3uMACXWkkFMm7BJ9Thknh7WNMPzV8HJBNwpyxJTr98NrLFHnTZDHdSUFD42VFQx8rjSaGynWbaRs differ diff --git a/integration_tests/tests/data/transactions/mint_verify_creator/37ts5SqpNazPTp26VfC4oeuXpXezKYkD9oarczPNaE8TUGG8msifnTYTBJiBZNBeAUGrNw85EEfwnR1t9SieKTdq b/integration_tests/tests/data/transactions/mint_verify_creator/37ts5SqpNazPTp26VfC4oeuXpXezKYkD9oarczPNaE8TUGG8msifnTYTBJiBZNBeAUGrNw85EEfwnR1t9SieKTdq new file mode 100644 index 000000000..f6aabfb2b Binary files /dev/null and b/integration_tests/tests/data/transactions/mint_verify_creator/37ts5SqpNazPTp26VfC4oeuXpXezKYkD9oarczPNaE8TUGG8msifnTYTBJiBZNBeAUGrNw85EEfwnR1t9SieKTdq differ diff --git a/integration_tests/tests/data/transactions/mint_verify_creator/4xrw5UwQSxxPzVxge6fbtmgLNsT2amaGrwpZFE95peRbnHGpxWtS2fF7whXW2xma4i2KDXdneztJZCAtgGZKTw11 b/integration_tests/tests/data/transactions/mint_verify_creator/4xrw5UwQSxxPzVxge6fbtmgLNsT2amaGrwpZFE95peRbnHGpxWtS2fF7whXW2xma4i2KDXdneztJZCAtgGZKTw11 new file mode 100644 index 000000000..83fecdc97 Binary files /dev/null and b/integration_tests/tests/data/transactions/mint_verify_creator/4xrw5UwQSxxPzVxge6fbtmgLNsT2amaGrwpZFE95peRbnHGpxWtS2fF7whXW2xma4i2KDXdneztJZCAtgGZKTw11 differ diff --git a/integration_tests/tests/integration_tests/account_update_tests.rs b/integration_tests/tests/integration_tests/account_update_tests.rs new file mode 100644 index 000000000..90fb9f529 --- /dev/null +++ b/integration_tests/tests/integration_tests/account_update_tests.rs @@ -0,0 +1,240 @@ +use borsh::BorshSerialize; +use function_name::named; + +use das_api::api::{self, ApiContract}; + +use plerkle_serialization::{ + root_as_account_info, serializer::serialize_account, + solana_geyser_plugin_interface_shims::ReplicaAccountInfoV2, +}; +use serial_test::serial; +use solana_sdk::pubkey::Pubkey; +use solana_sdk::{program_option::COption, program_pack::Pack}; +use spl_token::state::{Account as TokenAccount, AccountState, Mint}; + +use super::common::*; + +#[derive(Debug, Clone)] +// TODO: Add amount +struct TokenAccountUpdate { + owner: Pubkey, + delegate: COption, + state: AccountState, +} + +#[derive(Debug, Clone)] +struct MintAccountUpdate { + supply: u64, +} + +#[derive(Debug, Clone)] +struct MetadataAccountUpdate { + primary_sale_happened: bool, + is_mutable: bool, +} + +#[derive(Debug, Clone)] +enum AccountUpdate { + TokenAccount(TokenAccountUpdate), + #[allow(dead_code)] + MintAccount(MintAccountUpdate), + MetadataAccount(MetadataAccountUpdate), + None, +} + +macro_rules! update_field { + ($field:expr, $value:expr) => { + assert_ne!($field, $value); + $field = $value; + }; +} + +async fn index_account_update(setup: &TestSetup, pubkey: Pubkey, update: AccountUpdate, slot: u64) { + let account_bytes = cached_fetch_account(setup, pubkey, None).await; + + let account_info = root_as_account_info(&account_bytes).unwrap(); + let account_data = account_info.data().unwrap().iter().collect::>(); + + let modified_account_data = match update { + AccountUpdate::TokenAccount(TokenAccountUpdate { + owner, + delegate, + state, + }) => { + let mut account = TokenAccount::unpack(&account_data).unwrap(); + + update_field!(account.owner, owner); + update_field!(account.delegate, delegate); + update_field!(account.state, state); + + let mut data = vec![0; TokenAccount::LEN]; + TokenAccount::pack(account, data.as_mut_slice()).unwrap(); + data + } + AccountUpdate::MintAccount(MintAccountUpdate { supply }) => { + let mut account = Mint::unpack(&account_data).unwrap(); + + update_field!(account.supply, supply); + + let mut data = vec![0; Mint::LEN]; + Mint::pack(account, data.as_mut_slice()).unwrap(); + data + } + AccountUpdate::MetadataAccount(MetadataAccountUpdate { + primary_sale_happened, + is_mutable, + }) => { + let mut account: mpl_token_metadata::accounts::Metadata = + mpl_token_metadata::accounts::Metadata::from_bytes(&account_data).unwrap(); + + update_field!(account.primary_sale_happened, primary_sale_happened); + update_field!(account.is_mutable, is_mutable); + + account.try_to_vec().unwrap() + } + AccountUpdate::None => account_data, + }; + + let fbb = flatbuffers::FlatBufferBuilder::new(); + + let account_info = ReplicaAccountInfoV2 { + pubkey: &account_info.pubkey().unwrap().0, + lamports: account_info.lamports(), + owner: account_info.owner().unwrap().0.as_ref(), + executable: account_info.executable(), + rent_epoch: account_info.rent_epoch(), + data: &modified_account_data, + write_version: 0, + txn_signature: None, + }; + let is_startup = false; + + let fbb = serialize_account(fbb, &account_info, slot, is_startup); + index_account_bytes(setup, fbb.finished_data().to_vec()).await; +} + +#[tokio::test] +#[serial] +#[named] +async fn test_account_updates() { + let name = trim_test_name(function_name!()); + let setup = TestSetup::new(name.clone()).await; + let mint = Pubkey::try_from("843gdpsTE4DoJz3ZoBsEjAqT8UgAcyF5YojygGgGZE1f").unwrap(); + + let nft_accounts = get_nft_accounts(&setup, mint).await; + + let request = api::GetAsset { + id: mint.to_string(), + ..api::GetAsset::default() + }; + + let random_pub_key = Pubkey::try_from("1111111QLbz7JHiBTspS962RLKV8GndWFwiEaqKM").unwrap(); + let random_pub_key2 = Pubkey::try_from("1111111ogCyDbaRMvkdsHB3qfdyFYaG1WtRUAfdh").unwrap(); + + #[derive(Clone)] + struct NamedUpdate { + name: String, + account: Pubkey, + update: AccountUpdate, + } + + let token_updated = NamedUpdate { + name: "token".to_string(), + account: nft_accounts.token, + update: AccountUpdate::TokenAccount(TokenAccountUpdate { + owner: random_pub_key, + delegate: COption::Some(random_pub_key2), + state: AccountState::Initialized, + }), + }; + let mint_updated = NamedUpdate { + name: "mint".to_string(), + account: nft_accounts.mint, + // You can't easily change an NFT's mint account. The supply is fixed to 1 unless you burn + // the token account, the decimals are fixed at 0 and the freeze authority is not displayed + // in the API. + update: AccountUpdate::None, + }; + let metadata_updated = NamedUpdate { + name: "metadata".to_string(), + account: nft_accounts.metadata, + update: AccountUpdate::MetadataAccount(MetadataAccountUpdate { + primary_sale_happened: true, + is_mutable: false, + }), + }; + let named_updates = vec![token_updated, mint_updated, metadata_updated]; + + // Test that stale updates are rejected and new updates are accepted + for named_update in named_updates.clone() { + if let AccountUpdate::None = named_update.update { + continue; + } + apply_migrations_and_delete_data(setup.db.clone()).await; + index_nft(&setup, mint).await; + + let response = setup.das_api.get_asset(request.clone()).await.unwrap(); + insta::assert_json_snapshot!(name.clone(), response); + + index_account_update( + &setup, + named_update.account, + named_update.update.clone(), + DEFAULT_SLOT - 1, + ) + .await; + let response_stale_lot = setup.das_api.get_asset(request.clone()).await.unwrap(); + assert_eq!( + response, response_stale_lot, + "Update for {} account was not rejected", + named_update.name + ); + + index_account_update( + &setup, + named_update.account, + named_update.update.clone(), + DEFAULT_SLOT + 1, + ) + .await; + let response_new_slot = setup.das_api.get_asset(request.clone()).await.unwrap(); + + assert_ne!(response, response_new_slot); + insta::assert_json_snapshot!( + format!("{}-{}-updated", name, named_update.name), + response_new_slot + ); + } + + // Test that the different metadata/mint/token updates use different slots and don't interfere + // with each other + for named_update in named_updates.clone() { + apply_migrations_and_delete_data(setup.db.clone()).await; + index_nft(&setup, mint).await; + + let other_named_updates = named_updates + .clone() + .into_iter() + .filter(|u| u.name != named_update.name) + .collect::>(); + + let ordered_name_updates = other_named_updates + .into_iter() + .chain(vec![named_update]) + .collect::>(); + + for (i, named_update) in ordered_name_updates.into_iter().enumerate() { + index_account_update( + &setup, + named_update.account, + named_update.update.clone(), + DEFAULT_SLOT + named_updates.len() as u64 - i as u64, + ) + .await; + } + insta::assert_json_snapshot!( + format!("{}-with-all-updates", name), + setup.das_api.get_asset(request.clone()).await.unwrap() + ); + } +} diff --git a/integration_tests/tests/integration_tests/cnft_tests.rs b/integration_tests/tests/integration_tests/cnft_tests.rs new file mode 100644 index 000000000..5c772d30d --- /dev/null +++ b/integration_tests/tests/integration_tests/cnft_tests.rs @@ -0,0 +1,350 @@ +use function_name::named; +use std::str::FromStr; + +use das_api::api::{self, ApiContract}; + +use itertools::Itertools; + +use serial_test::serial; + +use solana_sdk::signature::Signature; + +use super::common::*; + +// TODO: Adjust this so that it can be run from anywhere. +// Do not move this test name or tests will break because the snapshot name and location will change. +pub async fn run_get_asset_scenario_test( + setup: &TestSetup, + asset_id: &str, + seeds: Vec, + order: Order, +) { + let seed_permutations: Vec> = match order { + Order::AllPermutations => seeds.iter().permutations(seeds.len()).collect::>(), + Order::Forward => vec![seeds.iter().collect_vec()], + }; + + for events in seed_permutations { + apply_migrations_and_delete_data(setup.db.clone()).await; + index_seed_events(setup, events).await; + let request = api::GetAsset { + id: asset_id.to_string(), + ..api::GetAsset::default() + }; + + let response = setup.das_api.get_asset(request).await.unwrap(); + insta::assert_json_snapshot!(setup.name.clone(), response); + } +} + +#[tokio::test] +#[serial] +#[named] +async fn test_asset_decompress() { + let name = trim_test_name(function_name!()); + let setup = TestSetup::new(name.clone()).await; + let asset_id = "Az9QTysJj1LW1F7zkYF21HgBj3FRpq3zpxTFdPnAJYm8"; + + // Mint a compressed NFT and then decompress it. In production, we would receive account updates for the newly minted NFT. + // This test guarentees consistent results if we index the events in different orders. + let seeds: Vec = vec![ + // mint cNFT + seed_txn("55tQCoLUtHyu4i6Dny6SMdq4dVD61nuuLxXvRLeeQqE6xdm66Ajm4so39MXcJ2VaTmCNDEFBpitzLkiFaF7rNtHi"), + // redeem + seed_txn("4FQRV38NSP6gDo8qDbTBfy8UDHUd6Lzu4GXbHtfvWbtCArkVcbGQwinZ7M61eCmPEF5L8xu4tLAXL7ozbh5scfRi"), + // decompress + seed_txn("3Ct9n9hv5PWEYbsrgDdUDqegzsnX2n5jYRxkq5YafFAueup8mTYmN4nHhNCaEwVyVAVqNssr4fizdg9wRavT7ydE"), + // regular nft mint + seed_nft("Az9QTysJj1LW1F7zkYF21HgBj3FRpq3zpxTFdPnAJYm8"), + ]; + + run_get_asset_scenario_test(&setup, asset_id, seeds, Order::AllPermutations).await; +} + +#[tokio::test] +#[serial] +#[named] +async fn test_cnft_scenario_mint_update_metadata() { + let name = trim_test_name(function_name!()); + let setup = TestSetup::new_with_options( + name.clone(), + TestSetupOptions { + network: Some(Network::Devnet), + }, + ) + .await; + + // Mint a compressed NFT and then update its metadata. Verify correct state regardless of order. + let asset_id = "FLFoCw2RBbxiw9rbEeqPWJ5rasArD9kTCKWEJirTexsU"; + let seeds: Vec = vec![ + // mint cNFT + seed_txn("2DP84v6Pi3e4v5i7KSvzmK4Ufbzof3TAiEqDbm9gg8jZpBRF9f1Cy6x54kvZoHPX9k1XfqbsG1FTv2KVP9fvNrN6"), + // update metadata + seed_txn("3bsL5zmLKvhN9Je4snTKxjFSpmXEEg2cvMHm2rCNgaEYkNXBqJTA4N7QmvBSWPiNUQPtzJSYzpQYX92NowV3L7vN"), + ]; + + run_get_asset_scenario_test(&setup, asset_id, seeds, Order::AllPermutations).await; +} + +#[tokio::test] +#[serial] +#[named] +async fn test_cnft_scenario_mint_update_metadata_remove_creators() { + let name = trim_test_name(function_name!()); + let setup = TestSetup::new_with_options( + name.clone(), + TestSetupOptions { + network: Some(Network::Devnet), + }, + ) + .await; + + // Mint a compressed NFT and then update its metadata to remove creators. + // Creator removal inserts a placeholder creator to handle out-of-order updates. + // This test explicitly verifies this behaviour. + let asset_id = "Gi4fAXJdnWYrEPjQm3wnW9ctgG7zJjB67zHDQtRGRWyZ"; + let seeds: Vec = vec![ + // mint cNFT + seed_txn("2qMQrXfRE7pdnjwobWeqDkEhsv6MYmv3JdgvNxTVaL1VrMCZ4JYkUnu7jiJb2etX3W9WyQgSxktUgn9skxCeqTo5"), + // update metadata (no creators) + seed_txn("41YW187sn6Z2dXfqz6zSbnPtQoE826cCSgTLnMLKa9rH1xrCqAXBQNwKnzjGc9wjU5RtMCqKhy2eMN2TjuYC8veB"), + ]; + + run_get_asset_scenario_test(&setup, asset_id, seeds, Order::AllPermutations).await; +} + +#[tokio::test] +#[serial] +#[named] +async fn test_cnft_owners_table() { + let name = trim_test_name(function_name!()); + let setup = TestSetup::new(name.clone()).await; + apply_migrations_and_delete_data(setup.db.clone()).await; + let transactions = vec![ + "25djDqCTka7wEnNMRVwsqSsVHqQMknPReTUCmvF4XGD9bUD494jZ1FsPaPjbAK45TxpdVuF2RwVCK9Jq7oxZAtMB", + "3UrxyfoJKH2jvVkzZZuCMXxtyaFUtgjhoQmirwhyiFjZXA8oM3QCBixCSBj9b53t5scvsm3qpuq5Qm4cGbNuwQP7", + "4fzBjTaXmrrJReLLSYPzn1fhPfuiU2EU1hGUddtHV1B49pvRewGyyzvMMpssi7K4Y5ZYj5xS9DrJuxqJDZRMZqY1", + ]; + for txn in transactions { + index_transaction(&setup, Signature::from_str(txn).unwrap()).await; + } + for (request, individual_test_name) in [ + ( + api::SearchAssets { + owner_address: Some("F3MdnVQkRSy56FSKroYawfMk1RJFo42Quzz8VTmFzPVz".to_string()), + page: Some(1), + limit: Some(5), + ..api::SearchAssets::default() + }, + "base", + ), + ( + api::SearchAssets { + owner_address: Some("3jnP4utL1VvjNhkxstYJ5MNayZfK4qHjFBDHNKEBpXCH".to_string()), + page: Some(1), + limit: Some(5), + ..api::SearchAssets::default() + }, + "with_different_owner", + ), + ] { + let response = setup.das_api.search_assets(request.clone()).await.unwrap(); + insta::assert_json_snapshot!(format!("{}-{}", name, individual_test_name), response); + } +} + +#[tokio::test] +#[serial] +#[named] +async fn test_mint_no_json_uri() { + let name = trim_test_name(function_name!()); + let setup = TestSetup::new(name.clone()).await; + let seeds = vec![seed_txn( + "4ASu45ELoTmvwhNqokGQrh2VH8p5zeUepYLbkcULMeXSCZJGrJa7ojgdVh5JUxBjAMF9Lrp55EgUUFPaPeWKejNQ", + )]; + run_get_asset_scenario_test( + &setup, + "DFRJ4PwAze1mMQccRmdyc46yQpEVd4FPiwtAVgzGCs7g", + seeds, + Order::Forward, + ) + .await; +} + +#[tokio::test] +#[serial] +#[named] +async fn test_mint_delegate_transfer() { + let name = trim_test_name(function_name!()); + let setup = TestSetup::new_with_options( + name.clone(), + TestSetupOptions { + network: Some(Network::Devnet), + }, + ) + .await; + + let asset_id = "77wWrvhgEkkQZQVA2hoka1JTsjG3w7BVzvcmqxDrVPWE"; + + let seeds: Vec = seed_txns([ + "KNWsAYPo3mm1HuFxRyEwBBMUZ2hqTnFXjoPVFo7WxGTfmfRwz6K8eERc4dnJpHyuoDkAZu1czK55iB1SbtCsdW2", + "3B1sASkuToCWuGFRG47axQDm1SpgLi8qDDGnRFeR7LB6oa5C3ZmkEuX98373gdMTBXED44FkwT227kBBAGSw7e8M", + "5Q8TAMMkMTHEM2BHyD2fp2sVdYKByFeATzM2mHF6Xbbar33WaeuygPKGYCWiDEt3MZU1mUrq1ePnT9o4Pa318p8w", + ]); + + run_get_asset_scenario_test(&setup, asset_id, seeds, Order::AllPermutations).await; +} + +#[tokio::test] +#[serial] +#[named] +async fn test_mint_redeem_cancel_redeem() { + let name = trim_test_name(function_name!()); + let setup = TestSetup::new_with_options( + name.clone(), + TestSetupOptions { + network: Some(Network::Devnet), + }, + ) + .await; + + let asset_id = "5WaPA7HLZKGg56bcKiroMXAzHmB1mdxK3QTeCDepLkiK"; + + let seeds: Vec = seed_txns([ + "3uzWoVgLGVd9cGXaF3JW7znpWgKse3obCa2Vvdoe59kaziX84mEXTwecUoZ49PkJDjReRMSXksKzyfj7pf3ekAGR", + "49bJ8U3cK9htmLvA1mhXXcjKdpV2YN5JQBrb3Quh7wxENz1BP9F8fE9CKsje41aMbZwzgomnkXirKx2Xpdvprtak", + "32FpSe6r9jnFNjjvbx2PPQdZqs5KpMoF6yawiRW1F6ctu1kmx2B4sLDBGjsthVQtmnhaJVrqdtmUP893FwXCbqY5", + ]); + + run_get_asset_scenario_test(&setup, asset_id, seeds, Order::AllPermutations).await; +} + +#[tokio::test] +#[serial] +#[named] +async fn test_mint_redeem() { + let name = trim_test_name(function_name!()); + let setup = TestSetup::new(name.clone()).await; + + let asset_id = "Az9QTysJj1LW1F7zkYF21HgBj3FRpq3zpxTFdPnAJYm8"; + + let seeds: Vec = seed_txns([ + "55tQCoLUtHyu4i6Dny6SMdq4dVD61nuuLxXvRLeeQqE6xdm66Ajm4so39MXcJ2VaTmCNDEFBpitzLkiFaF7rNtHi", + "4FQRV38NSP6gDo8qDbTBfy8UDHUd6Lzu4GXbHtfvWbtCArkVcbGQwinZ7M61eCmPEF5L8xu4tLAXL7ozbh5scfRi", + "3Ct9n9hv5PWEYbsrgDdUDqegzsnX2n5jYRxkq5YafFAueup8mTYmN4nHhNCaEwVyVAVqNssr4fizdg9wRavT7ydE", + ]); + + run_get_asset_scenario_test(&setup, asset_id, seeds, Order::AllPermutations).await; +} + +#[tokio::test] +#[serial] +#[named] +async fn test_mint_transfer_burn() { + let name = trim_test_name(function_name!()); + let setup = TestSetup::new_with_options( + name.clone(), + TestSetupOptions { + network: Some(Network::Devnet), + }, + ) + .await; + + let asset_id = "8vw7tdLGE3FBjaetsJrZAarwsbc8UESsegiLyvWXxs5A"; + + let seeds: Vec = seed_txns([ + "5coWPFty37s7haT3SVyMf6PkTaABEnhCRhfDjXeMNS58czHB5dCFPY6VrsZNwxBnqypmNic1LbLp1j5qjbdnZAc8", + "k6jmJcurgBQ6F2bVa86Z1vGb7ievzxwRZ8GAqzFEG8HicDizxceYPUm1KTzWZ3QKtGgy1EuFWUGCRqBeKU9SAoJ", + "KHNhLijkAMeKeKm6kpbk3go6q9uMF3zmfCoYSBgERe8qJDW8q5ANpnkyBuyVkychXCeWzRY8i5EtKfeGaDDU23w", + ]); + + run_get_asset_scenario_test(&setup, asset_id, seeds, Order::AllPermutations).await; +} + +#[tokio::test] +#[serial] +#[named] +async fn test_mint_transfer_noop() { + let name = trim_test_name(function_name!()); + let setup = TestSetup::new(name.clone()).await; + + let asset_id = "7myVr8fEG52mZ3jAwgz88iQRWsuzuVR2nfH8n2AXnBxE"; + + let seeds: Vec = seed_txns([ + "4nKDSvw2kGpccZWLEPnfdP7J1SEexQFRP3xWc9NBtQ1qQeGu3bu5WnAdpcLbjQ4iyX6BQ5QGF69wevE8ZeeY5poA", + "4URwUGBjbsF7UBUYdSC546tnBy7nD67txsso8D9CR9kGLtbbYh9NkGw15tEp16LLasmJX5VQR4Seh8gDjTrtdpoC", + "5bNyZfmxLVP9cKc6GjvozExrSt4F1QFt4PP992pQwT8FFHdWsX3ZFNvwurfU2xpDYtQ7qAUxVahGCraXMevRH8p1", + ]); + + run_get_asset_scenario_test(&setup, asset_id, seeds, Order::AllPermutations).await; +} + +#[tokio::test] +#[serial] +#[named] +async fn test_mint_transfer_transfer() { + let name = trim_test_name(function_name!()); + let setup = TestSetup::new_with_options( + name.clone(), + TestSetupOptions { + network: Some(Network::Devnet), + }, + ) + .await; + + let asset_id = "EcLv3bbLYr2iH5PVEuf9pJMRdDCvCqwSx3Srz6AeKjAe"; + + let seeds: Vec = seed_txns([ + "5bq936UgGs4RnxM78iXp1PwVhr8sTYoEsHCWpr8QBFtc2YtS3ieYHcsPG46G2ikwrS3tXYnUK93PzseT52AR81RR", + "5VC3Jqr5X1N8NB8zuSahHpayekLVozYkDiPjJLqU6H5M6fq9ExVLGYYKKCPbeksMPXTjy65sdEQGPzDWAYPs8QjP", + "34xjcNf3rZFKz381hKpFLqxpojaDgXEpCqH5qcpTXLaJnDbtqRz35wiuMF1cAgvJGLzYYrwaMvCK1D7LxYsdpMU1", + ]); + + run_get_asset_scenario_test(&setup, asset_id, seeds, Order::AllPermutations).await; +} + +#[tokio::test] +#[serial] +#[named] +async fn test_mint_verify_creator() { + let name = trim_test_name(function_name!()); + let setup = TestSetup::new_with_options( + name.clone(), + TestSetupOptions { + network: Some(Network::Devnet), + }, + ) + .await; + + let asset_id = "5rmTyghEuZhRTB77L3KqGMy6h5RpSNWNLj14avbxGNKB"; + + let seeds: Vec = seed_txns([ + "37ts5SqpNazPTp26VfC4oeuXpXezKYkD9oarczPNaE8TUGG8msifnTYTBJiBZNBeAUGrNw85EEfwnR1t9SieKTdq", + "4xrw5UwQSxxPzVxge6fbtmgLNsT2amaGrwpZFE95peRbnHGpxWtS2fF7whXW2xma4i2KDXdneztJZCAtgGZKTw11", + ]); + + run_get_asset_scenario_test(&setup, asset_id, seeds, Order::AllPermutations).await; +} + +#[tokio::test] +#[serial] +#[named] +async fn test_mint_verify_collection() { + let name = trim_test_name(function_name!()); + let setup = TestSetup::new_with_options( + name.clone(), + TestSetupOptions { + network: Some(Network::Devnet), + }, + ) + .await; + + let asset_id = "2WjoMU1hBGXv8sKcxQDGnu1tgMduzdZEmEEGjh8MZYfC"; + + let seeds: Vec = seed_txns([ + "63xhs5bXcuMR3uMACXWkkFMm7BJ9Thknh7WNMPzV8HJBNwpyxJTr98NrLFHnTZDHdSUFD42VFQx8rjSaGynWbaRs", + "5ZKjPxm3WAZzuqqkCDjgKpm9b5XjB9cuvv68JvXxWThvJaJxcMJgpSbYs4gDA9dGJyeLzsgNtnS6oubANF1KbBmt", + ]); + + run_get_asset_scenario_test(&setup, asset_id, seeds, Order::AllPermutations).await; +} diff --git a/integration_tests/tests/integration_tests/common.rs b/integration_tests/tests/integration_tests/common.rs new file mode 100644 index 000000000..3ba1b9862 --- /dev/null +++ b/integration_tests/tests/integration_tests/common.rs @@ -0,0 +1,605 @@ +use std::path::Path; + +use std::str::FromStr; + +use das_api::api::DasApi; + +use das_api::config::Config; + +use migration::sea_orm::{ + ConnectionTrait, DatabaseConnection, ExecResult, SqlxPostgresConnector, Statement, +}; +use migration::{Migrator, MigratorTrait}; +use mpl_token_metadata::accounts::Metadata; + +use nft_ingester::config::{self, rand_string}; +use nft_ingester::program_transformers::ProgramTransformer; +use nft_ingester::tasks::TaskManager; +use once_cell::sync::Lazy; +use plerkle_serialization::root_as_account_info; +use plerkle_serialization::root_as_transaction_info; +use plerkle_serialization::serializer::serialize_account; +use plerkle_serialization::solana_geyser_plugin_interface_shims::ReplicaAccountInfoV2; + +use solana_client::nonblocking::rpc_client::RpcClient; +use solana_sdk::pubkey::Pubkey; +use solana_sdk::signature::Signature; +use sqlx::postgres::{PgConnectOptions, PgPoolOptions}; +use sqlx::PgPool; +use std::sync::Arc; +use tokio::sync::Mutex; + +use futures_util::StreamExt as FuturesStreamExt; +use futures_util::TryStreamExt; +use tokio_stream::{self as stream}; + +use log::{error, info}; +use plerkle_serialization::serializer::seralize_encoded_transaction_with_status; +// use rand::seq::SliceRandom; +use serde::de::DeserializeOwned; +use solana_account_decoder::{UiAccount, UiAccountEncoding}; +use solana_client::{ + client_error::ClientError, + client_error::Result as RpcClientResult, + rpc_config::{RpcAccountInfoConfig, RpcTransactionConfig}, + rpc_request::RpcRequest, + rpc_response::{Response as RpcResponse, RpcTokenAccountBalance}, +}; +use solana_sdk::{ + account::Account, + commitment_config::{CommitmentConfig, CommitmentLevel}, +}; +use solana_transaction_status::{EncodedConfirmedTransactionWithStatusMeta, UiTransactionEncoding}; +use std::{fmt, time::Duration}; + +use std::path::PathBuf; + +use tokio::time::sleep; + +pub const DEFAULT_SLOT: u64 = 1; + +pub struct TestSetup { + pub name: String, + pub client: RpcClient, + pub db: Arc, + pub transformer: ProgramTransformer, + pub das_api: DasApi, +} + +impl TestSetup { + pub async fn new(name: String) -> Self { + Self::new_with_options(name, TestSetupOptions::default()).await + } + + pub async fn new_with_options(name: String, opts: TestSetupOptions) -> Self { + let database_test_url = std::env::var("DATABASE_TEST_URL").unwrap(); + let mut database_config = config::DatabaseConfig::new(); + database_config.insert("database_url".to_string(), database_test_url.clone().into()); + + if !(database_test_url.contains("localhost") || database_test_url.contains("127.0.0.1")) { + panic!("Tests can only be run on a local database"); + } + + let pool = setup_pg_pool(database_test_url.clone()).await; + let db = SqlxPostgresConnector::from_sqlx_postgres_pool(pool.clone()); + let transformer = load_ingest_program_transformer(pool.clone()).await; + + let rpc_url = match opts.network.unwrap_or_default() { + Network::Mainnet => std::env::var("MAINNET_RPC_URL").unwrap(), + Network::Devnet => std::env::var("DEVNET_RPC_URL").unwrap(), + }; + let client = RpcClient::new(rpc_url.to_string()); + + let das_api_config: Config = das_api::config::Config { + database_url: database_test_url.to_string(), + ..Default::default() + }; + let das_api = das_api::api::DasApi::from_config(das_api_config) + .await + .unwrap(); + + TestSetup { + name, + client, + db: Arc::new(db), + transformer, + das_api, + } + } +} + +#[derive(Clone, Copy, Default)] +pub struct TestSetupOptions { + pub network: Option, +} + +pub async fn setup_pg_pool(database_url: String) -> PgPool { + let options: PgConnectOptions = database_url.parse().unwrap(); + PgPoolOptions::new() + .min_connections(1) + .connect_with(options) + .await + .unwrap() +} + +pub async fn truncate_table( + db: Arc, + table: String, +) -> Result { + let raw_sql = format!("TRUNCATE TABLE {} CASCADE", table); + db.execute(Statement::from_string(db.get_database_backend(), raw_sql)) + .await +} + +static INIT: Lazy>> = Lazy::new(|| Mutex::new(None)); + +pub async fn apply_migrations_and_delete_data(db: Arc) { + let mut init = INIT.lock().await; + if init.is_none() { + std::env::set_var("INIT_FILE_PATH", "../init.sql"); + Migrator::fresh(&db).await.unwrap(); + *init = Some(()); + // Mutex will dropped once it goes out of scope. + return; + } + + let tables: Vec = db + .query_all(Statement::from_string(db.get_database_backend(), "SELECT tablename FROM pg_catalog.pg_tables WHERE schemaname != 'pg_catalog' AND schemaname != 'information_schema' AND tablename != 'seaql_migrations'".to_string())) + .await + .unwrap().into_iter() + .map(|row| row.try_get("", "tablename").unwrap()).collect::>(); + + let max_concurrency = 10; + + stream::iter(tables.into_iter()) + .map(|table| truncate_table(db.clone(), table.clone())) + .buffer_unordered(max_concurrency) + .try_collect::>() + .await + .unwrap(); +} + +async fn load_ingest_program_transformer(pool: sqlx::Pool) -> ProgramTransformer { + // HACK: We don't really use this background task handler but we need it to create the sender + let mut background_task_manager = TaskManager::new(rand_string(), pool.clone(), vec![]); + background_task_manager.start_listener(true); + let bg_task_sender = background_task_manager.get_sender().unwrap(); + ProgramTransformer::new(pool, bg_task_sender, false) +} + +pub async fn get_transaction( + client: &RpcClient, + signature: Signature, + max_retries: u8, +) -> Result { + let mut retries = 0; + let mut delay = Duration::from_millis(500); + + const CONFIG: RpcTransactionConfig = RpcTransactionConfig { + encoding: Some(UiTransactionEncoding::Base64), + commitment: Some(CommitmentConfig { + commitment: CommitmentLevel::Confirmed, + }), + max_supported_transaction_version: Some(0), + }; + + loop { + let response = client + .send( + RpcRequest::GetTransaction, + serde_json::json!([signature.to_string(), CONFIG,]), + ) + .await; + + if let Err(error) = response { + if retries < max_retries { + error!("failed to get transaction {:?}: {:?}", signature, error); + sleep(delay).await; + delay *= 2; + retries += 1; + continue; + } else { + return Err(error); + } + } + return response; + } +} + +pub async fn fetch_and_serialize_transaction( + client: &RpcClient, + sig: Signature, +) -> anyhow::Result>> { + let max_retries = 5; + let tx: EncodedConfirmedTransactionWithStatusMeta = + get_transaction(client, sig, max_retries).await?; + + // Ignore if tx failed or meta is missed + let meta = tx.transaction.meta.as_ref(); + if meta.map(|meta| meta.status.is_err()).unwrap_or(true) { + info!("Ignoring failed transaction: {}", sig); + return Ok(None); + } + let fbb = flatbuffers::FlatBufferBuilder::new(); + let fbb = seralize_encoded_transaction_with_status(fbb, tx)?; + let serialized = fbb.finished_data(); + + Ok(Some(serialized.to_vec())) +} + +// Util functions for accounts +pub async fn rpc_tx_with_retries( + client: &RpcClient, + request: RpcRequest, + value: serde_json::Value, + max_retries: u8, + error_key: E, +) -> RpcClientResult +where + T: DeserializeOwned, + E: fmt::Debug, +{ + let mut retries = 0; + let mut delay = Duration::from_millis(500); + loop { + match client.send(request, value.clone()).await { + Ok(value) => return Ok(value), + Err(error) => { + if retries < max_retries { + error!("retrying {request} {error_key:?}: {error}"); + sleep(delay).await; + delay *= 2; + retries += 1; + } else { + return Err(error); + } + } + } + } +} + +pub async fn fetch_account( + pubkey: Pubkey, + client: &RpcClient, + max_retries: u8, +) -> anyhow::Result<(Account, u64)> { + const CONFIG: RpcAccountInfoConfig = RpcAccountInfoConfig { + encoding: Some(UiAccountEncoding::Base64Zstd), + commitment: Some(CommitmentConfig { + commitment: CommitmentLevel::Finalized, + }), + data_slice: None, + min_context_slot: None, + }; + + let response: RpcResponse> = rpc_tx_with_retries( + client, + RpcRequest::GetAccountInfo, + serde_json::json!([pubkey.to_string(), CONFIG]), + max_retries, + pubkey, + ) + .await?; + + let account: Account = response + .value + .ok_or_else(|| anyhow::anyhow!("failed to get account {pubkey}"))? + .decode() + .ok_or_else(|| anyhow::anyhow!("failed to parse account {pubkey}"))?; + + Ok((account, response.context.slot)) +} + +pub async fn fetch_and_serialize_account( + client: &RpcClient, + pubkey: Pubkey, + slot: Option, +) -> anyhow::Result> { + let max_retries = 5; + + let fetch_result = fetch_account(pubkey, client, max_retries).await; + + let (account, actual_slot) = match fetch_result { + Ok((account, actual_slot)) => (account, actual_slot), + Err(e) => { + return Err(anyhow::anyhow!("Failed to fetch account: {:?}", e)); + } + }; + + let fbb = flatbuffers::FlatBufferBuilder::new(); + let account_info = ReplicaAccountInfoV2 { + pubkey: &pubkey.to_bytes(), + lamports: account.lamports, + owner: &account.owner.to_bytes(), + executable: account.executable, + rent_epoch: account.rent_epoch, + data: &account.data, + write_version: 0, + txn_signature: None, + }; + let is_startup = false; + + let fbb = serialize_account( + fbb, + &account_info, + match slot { + Some(slot) => slot, + None => actual_slot, + }, + is_startup, + ); + Ok(fbb.finished_data().to_vec()) +} + +pub async fn get_token_largest_account(client: &RpcClient, mint: Pubkey) -> anyhow::Result { + let response: RpcResponse> = rpc_tx_with_retries( + client, + RpcRequest::Custom { + method: "getTokenLargestAccounts", + }, + serde_json::json!([mint.to_string(),]), + 5, + mint, + ) + .await?; + + match response.value.first() { + Some(account) => { + let pubkey = Pubkey::from_str(&account.address); + match pubkey { + Ok(pubkey) => Ok(pubkey), + Err(e) => anyhow::bail!("failed to parse pubkey: {:?}", e), + } + } + None => anyhow::bail!("no accounts for mint {mint}: burned nft?"), + } +} + +pub async fn index_account_bytes(setup: &TestSetup, account_bytes: Vec) { + let account = root_as_account_info(&account_bytes).unwrap(); + + setup + .transformer + .handle_account_update(account) + .await + .unwrap(); +} + +pub async fn cached_fetch_account( + setup: &TestSetup, + account: Pubkey, + slot: Option, +) -> Vec { + cached_fetch_account_with_error_handling(setup, account, slot) + .await + .unwrap() +} + +fn get_relative_project_path(path: &str) -> PathBuf { + PathBuf::from(env!("CARGO_MANIFEST_DIR")).join(path) +} + +async fn cached_fetch_account_with_error_handling( + setup: &TestSetup, + account: Pubkey, + slot: Option, +) -> anyhow::Result> { + let dir = get_relative_project_path(&format!("tests/data/accounts/{}", setup.name)); + + if !Path::new(&dir).exists() { + std::fs::create_dir(&dir).unwrap(); + } + let file_path = dir.join(format!("{}", account)); + + if file_path.exists() { + Ok(std::fs::read(file_path).unwrap()) + } else { + let account_bytes = fetch_and_serialize_account(&setup.client, account, slot).await?; + std::fs::write(file_path, &account_bytes).unwrap(); + Ok(account_bytes) + } +} + +async fn cached_fetch_transaction(setup: &TestSetup, sig: Signature) -> Vec { + let dir = get_relative_project_path(&format!("tests/data/transactions/{}", setup.name)); + + if !Path::new(&dir).exists() { + std::fs::create_dir(&dir).unwrap(); + } + let file_path = dir.join(format!("{}", sig)); + + if file_path.exists() { + std::fs::read(file_path).unwrap() + } else { + let txn_bytes = fetch_and_serialize_transaction(&setup.client, sig) + .await + .unwrap() + .unwrap(); + std::fs::write(file_path, &txn_bytes).unwrap(); + txn_bytes + } +} + +pub async fn index_transaction(setup: &TestSetup, sig: Signature) { + let txn_bytes: Vec = cached_fetch_transaction(setup, sig).await; + let txn = root_as_transaction_info(&txn_bytes).unwrap(); + setup.transformer.handle_transaction(&txn).await.unwrap(); +} + +async fn cached_fetch_largest_token_account_id(client: &RpcClient, mint: Pubkey) -> Pubkey { + let dir = get_relative_project_path(&format!("tests/data/largest_token_account_ids/{}", mint)); + + if !Path::new(&dir).exists() { + std::fs::create_dir(&dir).unwrap(); + } + let file_path = dir.join(format!("{}", mint)); + + if file_path.exists() { + Pubkey::try_from(std::fs::read(file_path).unwrap()).unwrap() + } else { + let token_account = get_token_largest_account(client, mint).await.unwrap(); + std::fs::write(file_path, token_account.to_bytes()).unwrap(); + token_account + } +} + +#[allow(unused)] +#[derive(Clone, Copy, Debug)] +pub enum SeedEvent { + Account(Pubkey), + Nft(Pubkey), + TokenMint(Pubkey), + Signature(Signature), +} + +#[derive(Clone, Copy, Debug, Default)] +pub enum Network { + #[default] + Mainnet, + Devnet, +} + +#[derive(Clone, Copy, Debug)] +pub enum Order { + Forward, + AllPermutations, +} + +pub async fn index_seed_events(setup: &TestSetup, events: Vec<&SeedEvent>) { + for event in events { + match event { + SeedEvent::Account(account) => { + index_account_with_ordered_slot(setup, *account).await; + } + SeedEvent::Nft(mint) => { + index_nft(setup, *mint).await; + } + SeedEvent::Signature(sig) => { + index_transaction(setup, *sig).await; + } + SeedEvent::TokenMint(mint) => { + index_token_mint(setup, *mint).await; + } + } + } +} + +#[allow(unused)] +pub fn seed_account(str: &str) -> SeedEvent { + SeedEvent::Account(Pubkey::from_str(str).unwrap()) +} + +pub fn seed_nft(str: &str) -> SeedEvent { + SeedEvent::Nft(Pubkey::from_str(str).unwrap()) +} + +#[allow(unused)] +pub fn seed_token_mint(str: &str) -> SeedEvent { + SeedEvent::TokenMint(Pubkey::from_str(str).unwrap()) +} + +pub fn seed_txn(str: &str) -> SeedEvent { + SeedEvent::Signature(Signature::from_str(str).unwrap()) +} + +pub fn seed_txns(strs: I) -> Vec +where + I: IntoIterator, + I::Item: AsRef, +{ + strs.into_iter().map(|s| seed_txn(s.as_ref())).collect() +} + +#[allow(unused)] +pub fn seed_accounts(strs: I) -> Vec +where + I: IntoIterator, + I::Item: AsRef, +{ + strs.into_iter().map(|s| seed_account(s.as_ref())).collect() +} + +pub fn seed_nfts(strs: I) -> Vec +where + I: IntoIterator, + I::Item: AsRef, +{ + strs.into_iter().map(|s| seed_nft(s.as_ref())).collect() +} + +#[allow(unused)] +pub fn seed_token_mints(strs: I) -> Vec +where + I: IntoIterator, + I::Item: AsRef, +{ + strs.into_iter() + .map(|s| seed_token_mint(s.as_ref())) + .collect() +} + +pub async fn index_account(setup: &TestSetup, account: Pubkey) { + // If we used different slots for accounts, then it becomes harder to test updates of related + // accounts because we need to factor the fact that some updates can be disregarded because + // they are "stale". + let slot = Some(DEFAULT_SLOT); + let account_bytes = cached_fetch_account(setup, account, slot).await; + index_account_bytes(setup, account_bytes).await; +} + +#[derive(Clone, Copy)] +pub struct NftAccounts { + pub mint: Pubkey, + pub metadata: Pubkey, + pub token: Pubkey, +} + +pub async fn get_nft_accounts(setup: &TestSetup, mint: Pubkey) -> NftAccounts { + let metadata_account = Metadata::find_pda(&mint).0; + let token_account = cached_fetch_largest_token_account_id(&setup.client, mint).await; + NftAccounts { + mint, + metadata: metadata_account, + token: token_account, + } +} + +async fn index_account_with_ordered_slot(setup: &TestSetup, account: Pubkey) { + let slot = None; + let account_bytes = cached_fetch_account(setup, account, slot).await; + index_account_bytes(setup, account_bytes).await; +} + +async fn index_token_mint(setup: &TestSetup, mint: Pubkey) { + let token_account = cached_fetch_largest_token_account_id(&setup.client, mint).await; + index_account(setup, mint).await; + index_account(setup, token_account).await; + + // If we used different slots for accounts, then it becomes harder to test updates of related + // accounts because we need to factor the fact that some updates can be disregarded because + // they are "stale". + let slot = Some(1); + let metadata_account = Metadata::find_pda(&mint).0; + match cached_fetch_account_with_error_handling(setup, metadata_account, slot).await { + Ok(account_bytes) => { + index_account_bytes(setup, account_bytes).await; + } + Err(_) => { + // If we can't find the metadata account, then we assume that the mint is not an NFT. + } + } +} + +pub async fn index_nft(setup: &TestSetup, mint: Pubkey) { + index_nft_accounts(setup, get_nft_accounts(setup, mint).await).await; +} + +pub async fn index_nft_accounts(setup: &TestSetup, nft_accounts: NftAccounts) { + for account in [nft_accounts.mint, nft_accounts.metadata, nft_accounts.token] { + index_account(setup, account).await; + } +} + +pub fn trim_test_name(name: &str) -> String { + name.replace("test_", "") +} diff --git a/integration_tests/tests/integration_tests/general_scenario_tests.rs b/integration_tests/tests/integration_tests/general_scenario_tests.rs new file mode 100644 index 000000000..6229c95d0 --- /dev/null +++ b/integration_tests/tests/integration_tests/general_scenario_tests.rs @@ -0,0 +1,101 @@ +use function_name::named; +use std::str::FromStr; + +use das_api::api::{self, ApiContract}; +use digital_asset_types::dao::asset_creators; +use migration::sea_orm::{ConnectionTrait, EntityTrait}; + +use mpl_token_metadata::types::Creator; +use sea_orm::{DbBackend, QueryTrait, Set}; +use serial_test::serial; +use solana_sdk::pubkey::Pubkey; + +use super::common::*; + +#[tokio::test] +#[serial] +#[named] +async fn test_asset_parsing() { + let name = trim_test_name(function_name!()); + let setup = TestSetup::new(name.clone()).await; + apply_migrations_and_delete_data(setup.db.clone()).await; + let mint: Pubkey = Pubkey::try_from("843gdpsTE4DoJz3ZoBsEjAqT8UgAcyF5YojygGgGZE1f").unwrap(); + index_nft(&setup, mint).await; + let request = api::GetAsset { + id: mint.to_string(), + ..api::GetAsset::default() + }; + let response = setup.das_api.get_asset(request).await.unwrap(); + insta::assert_json_snapshot!(name, response); +} + +#[tokio::test] +#[serial] +#[named] +async fn test_creators_reordering() { + // This test covers a failure scenario we found in production where an NFT changed + // the positions of its creators, leading to conflict errors in the DB. + let name = trim_test_name(function_name!()); + let setup = TestSetup::new(name.clone()).await; + let asset_id = "ANt9HygtvFmFJ1UcAHFLnM62JJWjk8fujMzjGfpKBfzk"; + let asset_pubkey = Pubkey::from_str(asset_id).unwrap(); + apply_migrations_and_delete_data(setup.db.clone()).await; + + // Insert the original creators + let original_creators = vec![ + Creator { + address: Pubkey::from_str("8Jhy62JeG4rgPu4Q2tn3Q3eZ8XUZmHhYDKpVJkQ8RFhe").unwrap(), + verified: true, + share: 0, + }, + Creator { + address: Pubkey::from_str("9sJ3GKyTpBaNJ9CVFV6DecV556G1jU9L32kJASxzWsQA").unwrap(), + verified: false, + share: 10, + }, + Creator { + address: Pubkey::from_str("yX9uyojU5uwBnDUJg5wX1n7T4w7KyU6r9brszXX2yKa").unwrap(), + verified: false, + share: 10, + }, + Creator { + address: Pubkey::from_str("BDaobvsTU8Eu3R4sx1vLufKiToaZL3MDTHxPgHgvGWC7").unwrap(), + verified: false, + share: 10, + }, + Creator { + address: Pubkey::from_str("F9xfmpggwgqH7ASZzNre8TxZztZwCogPBE8aQCNBLkBn").unwrap(), + verified: false, + share: 70, + }, + ] + .into_iter() + .enumerate() + .map(|(i, c)| asset_creators::ActiveModel { + asset_id: Set(asset_pubkey.to_bytes().to_vec()), + position: Set(i as i16), + creator: Set(c.address.to_bytes().to_vec()), + share: Set(c.share as i32), + verified: Set(c.verified), + slot_updated: Set(Some(0)), + seq: Set(Some(0)), + ..Default::default() + }) + .collect::>(); + setup + .db + .execute(asset_creators::Entity::insert_many(original_creators).build(DbBackend::Postgres)) + .await + .unwrap(); + + // Index the current NFT. + index_nft(&setup, asset_pubkey).await; + + // Verify creators + let request = api::GetAsset { + id: asset_id.to_string(), + ..api::GetAsset::default() + }; + let response = setup.das_api.get_asset(request.clone()).await.unwrap(); + insta::assert_json_snapshot!(name, response); +} diff --git a/integration_tests/tests/integration_tests/main.rs b/integration_tests/tests/integration_tests/main.rs new file mode 100644 index 000000000..983e131ba --- /dev/null +++ b/integration_tests/tests/integration_tests/main.rs @@ -0,0 +1,5 @@ +mod account_update_tests; +mod cnft_tests; +mod common; +mod general_scenario_tests; +mod regular_nft_tests; diff --git a/integration_tests/tests/integration_tests/regular_nft_tests.rs b/integration_tests/tests/integration_tests/regular_nft_tests.rs new file mode 100644 index 000000000..a837f27cf --- /dev/null +++ b/integration_tests/tests/integration_tests/regular_nft_tests.rs @@ -0,0 +1,146 @@ +use function_name::named; + +use das_api::api::{self, ApiContract}; + +use itertools::Itertools; + +use serial_test::serial; + +use super::common::*; + +#[tokio::test] +#[serial] +#[named] +async fn test_reg_get_asset() { + let name = trim_test_name(function_name!()); + let setup = TestSetup::new(name.clone()).await; + + let seeds: Vec = seed_nfts(["CMVuYDS9nTeujfTPJb8ik7CRhAqZv4DfjfdamFLkJgxE"]); + + apply_migrations_and_delete_data(setup.db.clone()).await; + index_seed_events(&setup, seeds.iter().collect_vec()).await; + + let request = r#" + { + "id": "CMVuYDS9nTeujfTPJb8ik7CRhAqZv4DfjfdamFLkJgxE" + } + "#; + + let request: api::GetAsset = serde_json::from_str(request).unwrap(); + let response = setup.das_api.get_asset(request).await.unwrap(); + insta::assert_json_snapshot!(name, response); +} + +#[tokio::test] +#[serial] +#[named] +async fn test_reg_get_asset_batch() { + let name = trim_test_name(function_name!()); + let setup = TestSetup::new(name.clone()).await; + + let seeds: Vec = seed_nfts([ + "HTKAVZZrDdyecCxzm3WEkCsG1GUmiqKm73PvngfuYRNK", + "2NqdYX6kJmMUoChnDXU2UrP9BsoPZivRw3uJG8iDhRRd", + "5rEeYv8R25b8j6YTHJvYuCKEzq44UCw1Wx1Wx2VPPLz1", + ]); + + apply_migrations_and_delete_data(setup.db.clone()).await; + index_seed_events(&setup, seeds.iter().collect_vec()).await; + + for (request, individual_test_name) in [ + ( + r#" + { + "ids": ["HTKAVZZrDdyecCxzm3WEkCsG1GUmiqKm73PvngfuYRNK", "2NqdYX6kJmMUoChnDXU2UrP9BsoPZivRw3uJG8iDhRRd"] + } + "#, + "only-2", + ), + ( + r#" + { + "ids": ["2NqdYX6kJmMUoChnDXU2UrP9BsoPZivRw3uJG8iDhRRd", "5rEeYv8R25b8j6YTHJvYuCKEzq44UCw1Wx1Wx2VPPLz1"] + } + "#, + "only-2-different-2", + ), + ( + r#" + { + "ids": [ + "2NqdYX6kJmMUoChnDXU2UrP9BsoPZivRw3uJG8iDhRRd", + "JECLQnbo2CCL8Ygn6vTFn7yeKn8qc7i51bAa9BCAJnWG", + "5rEeYv8R25b8j6YTHJvYuCKEzq44UCw1Wx1Wx2VPPLz1" + ] + } + "#, + "2-and-a-missing-1", + ), + ] { + let request: api::GetAssets = serde_json::from_str(request).unwrap(); + let response = setup.das_api.get_assets(request).await.unwrap(); + insta::assert_json_snapshot!(format!("{}-{}", name, individual_test_name), response); + } +} + +#[tokio::test] +#[serial] +#[named] +async fn test_reg_get_asset_by_group() { + let name = trim_test_name(function_name!()); + let setup = TestSetup::new(name.clone()).await; + + let seeds: Vec = seed_nfts([ + "7jFuJ73mBPDdLMvCYxzrpFTD9FeDudRxdXGDALP5Cp2W", + "BioVudBTjJnuDW22q62XPhGP87sVwZKcQ46MPSNz4gqi", + "Fm9S3FL23z3ii3EBBv8ozqLninLvhWDYmcHcHaZy6nie", + ]); + + apply_migrations_and_delete_data(setup.db.clone()).await; + index_seed_events(&setup, seeds.iter().collect_vec()).await; + + let request = r#" + { + "groupKey": "collection", + "groupValue": "8Rt3Ayqth4DAiPnW9MDFi63TiQJHmohfTWLMQFHi4KZH", + "sortBy": { + "sortBy": "updated", + "sortDirection": "asc" + }, + "page": 1, + "limit": 1 + } + "#; + + let request: api::GetAssetsByGroup = serde_json::from_str(request).unwrap(); + let response = setup.das_api.get_assets_by_group(request).await.unwrap(); + insta::assert_json_snapshot!(name, response); +} + +#[tokio::test] +#[serial] +#[named] +async fn test_reg_search_assets() { + let name = trim_test_name(function_name!()); + let setup = TestSetup::new(name.clone()).await; + + let seeds: Vec = seed_nfts([ + "2PfAwPb2hdgsf7xCKyU2kAWUGKnkxYZLfg5SMf4YP1h2", + "Dt3XDSAdXAJbHqvuycgCTHykKCC7tntMFGMmSvfBbpTL", + ]); + + apply_migrations_and_delete_data(setup.db.clone()).await; + index_seed_events(&setup, seeds.iter().collect_vec()).await; + + let request = r#" + { + "ownerAddress": "6Cr66AabRYymhZgYQSfTCo6FVpH18wXrMZswAbcErpyX", + "page": 1, + "limit": 2 + } + "#; + + let request: api::SearchAssets = serde_json::from_str(request).unwrap(); + let response = setup.das_api.search_assets(request).await.unwrap(); + insta::assert_json_snapshot!(name, response); +} diff --git a/integration_tests/tests/integration_tests/snapshots/integration_tests__account_update_tests__account_updates-metadata-updated.snap b/integration_tests/tests/integration_tests/snapshots/integration_tests__account_update_tests__account_updates-metadata-updated.snap new file mode 100644 index 000000000..fe306fab3 --- /dev/null +++ b/integration_tests/tests/integration_tests/snapshots/integration_tests__account_update_tests__account_updates-metadata-updated.snap @@ -0,0 +1,68 @@ +--- +source: integration_tests/tests/integration_tests/account_update_tests.rs +expression: response_new_slot +--- +{ + "interface": "ProgrammableNFT", + "id": "843gdpsTE4DoJz3ZoBsEjAqT8UgAcyF5YojygGgGZE1f", + "content": { + "$schema": "https://schema.metaplex.com/nft1.0.json", + "json_uri": "https://nftstorage.link/ipfs/bafybeihaky4htq6obur3ziksyanpdoqmrnefben3dbecddru52xh2sdkii/1232.json", + "files": [], + "metadata": { + "name": "Phantom Mage #1233", + "symbol": "PM", + "token_standard": "ProgrammableNonFungible" + }, + "links": {} + }, + "authorities": [ + { + "address": "GMhP98kXvfziKNfq1nP99AbWtZAweLu3DFz5Vs5ZaVTy", + "scopes": [ + "full" + ] + } + ], + "compression": { + "eligible": false, + "compressed": false, + "data_hash": "", + "creator_hash": "", + "asset_hash": "", + "tree": "", + "seq": 0, + "leaf_id": 0 + }, + "grouping": [], + "royalty": { + "royalty_model": "creators", + "target": null, + "percent": 0.0555, + "basis_points": 555, + "primary_sale_happened": true, + "locked": false + }, + "creators": [ + { + "address": "5KtTmcxYYzK5mR7gEtjVX2eBBK1g7YjVbvsMBAbyf9uK", + "share": 0, + "verified": true + }, + { + "address": "HmkCMBPdY6MixHP8hxsM8G1UwJH3fBN2itWagnYoXASR", + "share": 100, + "verified": false + } + ], + "ownership": { + "frozen": true, + "delegated": false, + "delegate": null, + "ownership_model": "single", + "owner": "BzbdvwEkQKeghTY53aZxTYjUienhdbkNVkgrLV6cErke" + }, + "supply": null, + "mutable": false, + "burnt": false +} diff --git a/integration_tests/tests/integration_tests/snapshots/integration_tests__account_update_tests__account_updates-token-updated.snap b/integration_tests/tests/integration_tests/snapshots/integration_tests__account_update_tests__account_updates-token-updated.snap new file mode 100644 index 000000000..5dac7346d --- /dev/null +++ b/integration_tests/tests/integration_tests/snapshots/integration_tests__account_update_tests__account_updates-token-updated.snap @@ -0,0 +1,68 @@ +--- +source: integration_tests/tests/integration_tests/account_update_tests.rs +expression: response_new_slot +--- +{ + "interface": "ProgrammableNFT", + "id": "843gdpsTE4DoJz3ZoBsEjAqT8UgAcyF5YojygGgGZE1f", + "content": { + "$schema": "https://schema.metaplex.com/nft1.0.json", + "json_uri": "https://nftstorage.link/ipfs/bafybeihaky4htq6obur3ziksyanpdoqmrnefben3dbecddru52xh2sdkii/1232.json", + "files": [], + "metadata": { + "name": "Phantom Mage #1233", + "symbol": "PM", + "token_standard": "ProgrammableNonFungible" + }, + "links": {} + }, + "authorities": [ + { + "address": "GMhP98kXvfziKNfq1nP99AbWtZAweLu3DFz5Vs5ZaVTy", + "scopes": [ + "full" + ] + } + ], + "compression": { + "eligible": false, + "compressed": false, + "data_hash": "", + "creator_hash": "", + "asset_hash": "", + "tree": "", + "seq": 0, + "leaf_id": 0 + }, + "grouping": [], + "royalty": { + "royalty_model": "creators", + "target": null, + "percent": 0.0555, + "basis_points": 555, + "primary_sale_happened": false, + "locked": false + }, + "creators": [ + { + "address": "5KtTmcxYYzK5mR7gEtjVX2eBBK1g7YjVbvsMBAbyf9uK", + "share": 0, + "verified": true + }, + { + "address": "HmkCMBPdY6MixHP8hxsM8G1UwJH3fBN2itWagnYoXASR", + "share": 100, + "verified": false + } + ], + "ownership": { + "frozen": false, + "delegated": true, + "delegate": "1111111ogCyDbaRMvkdsHB3qfdyFYaG1WtRUAfdh", + "ownership_model": "single", + "owner": "1111111QLbz7JHiBTspS962RLKV8GndWFwiEaqKM" + }, + "supply": null, + "mutable": true, + "burnt": false +} diff --git a/integration_tests/tests/integration_tests/snapshots/integration_tests__account_update_tests__account_updates-with-all-updates.snap b/integration_tests/tests/integration_tests/snapshots/integration_tests__account_update_tests__account_updates-with-all-updates.snap new file mode 100644 index 000000000..d0978550e --- /dev/null +++ b/integration_tests/tests/integration_tests/snapshots/integration_tests__account_update_tests__account_updates-with-all-updates.snap @@ -0,0 +1,68 @@ +--- +source: integration_tests/tests/integration_tests/account_update_tests.rs +expression: setup.das_api.get_asset(request.clone()).await.unwrap() +--- +{ + "interface": "ProgrammableNFT", + "id": "843gdpsTE4DoJz3ZoBsEjAqT8UgAcyF5YojygGgGZE1f", + "content": { + "$schema": "https://schema.metaplex.com/nft1.0.json", + "json_uri": "https://nftstorage.link/ipfs/bafybeihaky4htq6obur3ziksyanpdoqmrnefben3dbecddru52xh2sdkii/1232.json", + "files": [], + "metadata": { + "name": "Phantom Mage #1233", + "symbol": "PM", + "token_standard": "ProgrammableNonFungible" + }, + "links": {} + }, + "authorities": [ + { + "address": "GMhP98kXvfziKNfq1nP99AbWtZAweLu3DFz5Vs5ZaVTy", + "scopes": [ + "full" + ] + } + ], + "compression": { + "eligible": false, + "compressed": false, + "data_hash": "", + "creator_hash": "", + "asset_hash": "", + "tree": "", + "seq": 0, + "leaf_id": 0 + }, + "grouping": [], + "royalty": { + "royalty_model": "creators", + "target": null, + "percent": 0.0555, + "basis_points": 555, + "primary_sale_happened": true, + "locked": false + }, + "creators": [ + { + "address": "5KtTmcxYYzK5mR7gEtjVX2eBBK1g7YjVbvsMBAbyf9uK", + "share": 0, + "verified": true + }, + { + "address": "HmkCMBPdY6MixHP8hxsM8G1UwJH3fBN2itWagnYoXASR", + "share": 100, + "verified": false + } + ], + "ownership": { + "frozen": false, + "delegated": true, + "delegate": "1111111ogCyDbaRMvkdsHB3qfdyFYaG1WtRUAfdh", + "ownership_model": "single", + "owner": "1111111QLbz7JHiBTspS962RLKV8GndWFwiEaqKM" + }, + "supply": null, + "mutable": false, + "burnt": false +} diff --git a/integration_tests/tests/integration_tests/snapshots/integration_tests__account_update_tests__account_updates.snap b/integration_tests/tests/integration_tests/snapshots/integration_tests__account_update_tests__account_updates.snap new file mode 100644 index 000000000..2deeb3b43 --- /dev/null +++ b/integration_tests/tests/integration_tests/snapshots/integration_tests__account_update_tests__account_updates.snap @@ -0,0 +1,68 @@ +--- +source: integration_tests/tests/integration_tests/account_update_tests.rs +expression: response +--- +{ + "interface": "ProgrammableNFT", + "id": "843gdpsTE4DoJz3ZoBsEjAqT8UgAcyF5YojygGgGZE1f", + "content": { + "$schema": "https://schema.metaplex.com/nft1.0.json", + "json_uri": "https://nftstorage.link/ipfs/bafybeihaky4htq6obur3ziksyanpdoqmrnefben3dbecddru52xh2sdkii/1232.json", + "files": [], + "metadata": { + "name": "Phantom Mage #1233", + "symbol": "PM", + "token_standard": "ProgrammableNonFungible" + }, + "links": {} + }, + "authorities": [ + { + "address": "GMhP98kXvfziKNfq1nP99AbWtZAweLu3DFz5Vs5ZaVTy", + "scopes": [ + "full" + ] + } + ], + "compression": { + "eligible": false, + "compressed": false, + "data_hash": "", + "creator_hash": "", + "asset_hash": "", + "tree": "", + "seq": 0, + "leaf_id": 0 + }, + "grouping": [], + "royalty": { + "royalty_model": "creators", + "target": null, + "percent": 0.0555, + "basis_points": 555, + "primary_sale_happened": false, + "locked": false + }, + "creators": [ + { + "address": "5KtTmcxYYzK5mR7gEtjVX2eBBK1g7YjVbvsMBAbyf9uK", + "share": 0, + "verified": true + }, + { + "address": "HmkCMBPdY6MixHP8hxsM8G1UwJH3fBN2itWagnYoXASR", + "share": 100, + "verified": false + } + ], + "ownership": { + "frozen": true, + "delegated": false, + "delegate": null, + "ownership_model": "single", + "owner": "BzbdvwEkQKeghTY53aZxTYjUienhdbkNVkgrLV6cErke" + }, + "supply": null, + "mutable": true, + "burnt": false +} diff --git a/integration_tests/tests/integration_tests/snapshots/integration_tests__cnft_tests__asset_decompress.snap b/integration_tests/tests/integration_tests/snapshots/integration_tests__cnft_tests__asset_decompress.snap new file mode 100644 index 000000000..adaf63596 --- /dev/null +++ b/integration_tests/tests/integration_tests/snapshots/integration_tests__cnft_tests__asset_decompress.snap @@ -0,0 +1,82 @@ +--- +source: integration_tests/tests/integration_tests/cnft_tests.rs +expression: response +--- +{ + "interface": "V1_NFT", + "id": "Az9QTysJj1LW1F7zkYF21HgBj3FRpq3zpxTFdPnAJYm8", + "content": { + "$schema": "https://schema.metaplex.com/nft1.0.json", + "json_uri": "https://baze.one/posts/rMb9dU7X2lSu/m", + "files": [], + "metadata": { + "name": "B-BCKSNW-4", + "symbol": "BCKSNW", + "token_standard": "NonFungible" + }, + "links": {} + }, + "authorities": [ + { + "address": "5S5CHHQ69Q2gdRVRV45TVnZpy6eExzq5Zw5BRQozC3Ap", + "scopes": [ + "full" + ] + } + ], + "compression": { + "eligible": false, + "compressed": false, + "data_hash": "", + "creator_hash": "", + "asset_hash": "", + "tree": "", + "seq": 0, + "leaf_id": 0 + }, + "grouping": [ + { + "group_key": "collection", + "group_value": "2MJeqBXcRmy3PXvQP5RRPqeig2CTfnXv5nGT3wRD1xW5" + } + ], + "royalty": { + "royalty_model": "creators", + "target": null, + "percent": 0.1, + "basis_points": 1000, + "primary_sale_happened": false, + "locked": false + }, + "creators": [ + { + "address": "8dpwoPxMkCd9LnsDEbrRuBL5sw3mqcWLf9vPcwgpeRMS", + "share": 100, + "verified": false + }, + { + "address": "2kKisVa2VmNk6iA2avQpZdDXtDGBWgzEE9ib7iWmKemw", + "share": 0, + "verified": false + }, + { + "address": "94huX4Ya45pA41AfeBkqadbBFjgFDrv5riZQXVLqsoVT", + "share": 0, + "verified": true + } + ], + "ownership": { + "frozen": false, + "delegated": false, + "delegate": null, + "ownership_model": "single", + "owner": "HkdmoXct4zKyAfgZgpuavKzmuvf2Z5UZ35v1UUW3Z9Jk" + }, + "supply": { + "print_max_supply": 0, + "print_current_supply": 0, + "edition_nonce": 253 + }, + "mutable": true, + "burnt": false +} diff --git a/integration_tests/tests/integration_tests/snapshots/integration_tests__cnft_tests__cnft_owners_table-base.snap b/integration_tests/tests/integration_tests/snapshots/integration_tests__cnft_tests__cnft_owners_table-base.snap new file mode 100644 index 000000000..048809c0d --- /dev/null +++ b/integration_tests/tests/integration_tests/snapshots/integration_tests__cnft_tests__cnft_owners_table-base.snap @@ -0,0 +1,89 @@ +--- +source: integration_tests/tests/integration_tests/cnft_tests.rs +expression: response +--- +{ + "total": 1, + "limit": 5, + "page": 1, + "items": [ + { + "interface": "V1_NFT", + "id": "4k41XV45LUyX2iRSdw8bvwPmKF9y7SNLi9imUGWc3ADS", + "content": { + "$schema": "https://schema.metaplex.com/nft1.0.json", + "json_uri": "https://arweave.net/rtwIkSB6YhNjaUjnSxUiiDV6BwJ_W2pLw8Mfhj6lvBo", + "files": [], + "metadata": { + "name": "Rolling Canvas #1 | Sketch Paper", + "symbol": "", + "token_standard": "NonFungible" + }, + "links": {} + }, + "authorities": [ + { + "address": "EZ2pnS9heCAV7V6evtWeucEKdUaB6Y4Vca4W6ZuBJN81", + "scopes": [ + "full" + ] + } + ], + "compression": { + "eligible": false, + "compressed": true, + "data_hash": "APHE858V4tkWqVATytfgTupRJBeg8aQfwCEvssd9kZVc", + "creator_hash": "8KdDUqVPXcyvBch2atwAxEyf8Ym3TfB5khSkZRSgoYxR", + "asset_hash": "3TP6JZ2e3CPzoktSC1cx5K8GM2dWrS6F8xuM51m78Tqr", + "tree": "8Uyk1cZGDcytRBdyKkqHJhTAvSPzSNDDEJTacWUEW8p6", + "seq": 258421, + "leaf_id": 170433 + }, + "grouping": [ + { + "group_key": "collection", + "group_value": "STKM3PzeFc6kdJiMXyQ3pRDa3ERCEGgM9NbPPGb2Rft" + } + ], + "royalty": { + "royalty_model": "creators", + "target": null, + "percent": 0.065, + "basis_points": 650, + "primary_sale_happened": false, + "locked": false + }, + "creators": [ + { + "address": "STK8wk9npcTtCLHEeLc3MkfqvTQ3Pai37qbZBxuKV2Z", + "share": 0, + "verified": true + }, + { + "address": "WoMbXFtdfH8crq2Zi7bQhfGx2Gv8EN4saP13gcdUGog", + "share": 23, + "verified": false + }, + { + "address": "6sYxGBdpzfABtHRrHERFvS92y9yv4Sxwo8EFCvjU2vv7", + "share": 77, + "verified": false + } + ], + "ownership": { + "frozen": false, + "delegated": false, + "delegate": null, + "ownership_model": "single", + "owner": "F3MdnVQkRSy56FSKroYawfMk1RJFo42Quzz8VTmFzPVz" + }, + "supply": { + "print_max_supply": 0, + "print_current_supply": 0, + "edition_nonce": null + }, + "mutable": true, + "burnt": false + } + ] +} diff --git a/integration_tests/tests/integration_tests/snapshots/integration_tests__cnft_tests__cnft_owners_table-with_different_owner.snap b/integration_tests/tests/integration_tests/snapshots/integration_tests__cnft_tests__cnft_owners_table-with_different_owner.snap new file mode 100644 index 000000000..2508f8d05 --- /dev/null +++ b/integration_tests/tests/integration_tests/snapshots/integration_tests__cnft_tests__cnft_owners_table-with_different_owner.snap @@ -0,0 +1,10 @@ +--- +source: integration_tests/tests/integration_tests/cnft_tests.rs +expression: response +--- +{ + "total": 0, + "limit": 5, + "page": 1, + "items": [] +} diff --git a/integration_tests/tests/integration_tests/snapshots/integration_tests__cnft_tests__cnft_scenario_mint_update_metadata.snap b/integration_tests/tests/integration_tests/snapshots/integration_tests__cnft_tests__cnft_scenario_mint_update_metadata.snap new file mode 100644 index 000000000..7247be262 --- /dev/null +++ b/integration_tests/tests/integration_tests/snapshots/integration_tests__cnft_tests__cnft_scenario_mint_update_metadata.snap @@ -0,0 +1,72 @@ +--- +source: integration_tests/tests/integration_tests/cnft_tests.rs +expression: response +--- +{ + "interface": "V1_NFT", + "id": "FLFoCw2RBbxiw9rbEeqPWJ5rasArD9kTCKWEJirTexsU", + "content": { + "$schema": "https://schema.metaplex.com/nft1.0.json", + "json_uri": "https://metaplex.com", + "files": [], + "metadata": { + "name": "test", + "symbol": "TST", + "token_standard": "NonFungible" + }, + "links": {} + }, + "authorities": [ + { + "address": "9K8HEU5zynrCyL9CyuvCX9qUU58avinJsu5E59gyRnB8", + "scopes": [ + "full" + ] + } + ], + "compression": { + "eligible": false, + "compressed": true, + "data_hash": "3TV3EEhP7QrfHJ1GnsuqVo3mTbPsLMgtmqV3tLnh3HQq", + "creator_hash": "2gYtfk9rgoFMgepLuQkMiPAmXnmG7kFh9VgMDPPcHMjY", + "asset_hash": "4Un9hicHokmeRx3mcqzuVd1k1zAzjqXymm7xo8xqJTeK", + "tree": "EzppnpWWMKg4egUkfe86aQQyYabFL9jPPWTrZjniDHxv", + "seq": 2, + "leaf_id": 0 + }, + "grouping": [], + "royalty": { + "royalty_model": "creators", + "target": null, + "percent": 0.0, + "basis_points": 0, + "primary_sale_happened": false, + "locked": false + }, + "creators": [ + { + "address": "Fq4HDXfutKjEZ7zZP2JmKboSm2ZsYsKEJ7BLQAfrpNcc", + "share": 50, + "verified": true + }, + { + "address": "3Le8mq2Y7kpAwAKmTRyr7n6vcM9hdDuxmiWA3tUYi4Nw", + "share": 50, + "verified": false + } + ], + "ownership": { + "frozen": false, + "delegated": false, + "delegate": null, + "ownership_model": "single", + "owner": "Fq4HDXfutKjEZ7zZP2JmKboSm2ZsYsKEJ7BLQAfrpNcc" + }, + "supply": { + "print_max_supply": 0, + "print_current_supply": 0, + "edition_nonce": 0 + }, + "mutable": true, + "burnt": false +} diff --git a/integration_tests/tests/integration_tests/snapshots/integration_tests__cnft_tests__cnft_scenario_mint_update_metadata_remove_creators.snap b/integration_tests/tests/integration_tests/snapshots/integration_tests__cnft_tests__cnft_scenario_mint_update_metadata_remove_creators.snap new file mode 100644 index 000000000..713adb096 --- /dev/null +++ b/integration_tests/tests/integration_tests/snapshots/integration_tests__cnft_tests__cnft_scenario_mint_update_metadata_remove_creators.snap @@ -0,0 +1,61 @@ +--- +source: integration_tests/tests/integration_tests/cnft_tests.rs +expression: response +--- +{ + "interface": "V1_NFT", + "id": "Gi4fAXJdnWYrEPjQm3wnW9ctgG7zJjB67zHDQtRGRWyZ", + "content": { + "$schema": "https://schema.metaplex.com/nft1.0.json", + "json_uri": "https://metaplex.com", + "files": [], + "metadata": { + "name": "test", + "symbol": "TST", + "token_standard": "NonFungible" + }, + "links": {} + }, + "authorities": [ + { + "address": "2GuRg5JGumFcgKmZvp7fc5be9UsaNihP42WPEziZ9mEA", + "scopes": [ + "full" + ] + } + ], + "compression": { + "eligible": false, + "compressed": true, + "data_hash": "FsRoJdPqF4xJczL35QG1aQQG7g7DBZK1VF9Qs8zexssc", + "creator_hash": "EKDHSGbrGztomDfuiV4iqiZ6LschDJPsFiXjZ83f92Md", + "asset_hash": "CbsvyFdcQ8SyGaVpqNE5zjLfSbgnuKDnJZEyQgC4P5Wt", + "tree": "8PkWaY1BYd6ysBZt3JEwuAXjNrZE6omW18cKEJzbyaw4", + "seq": 2, + "leaf_id": 0 + }, + "grouping": [], + "royalty": { + "royalty_model": "creators", + "target": null, + "percent": 0.0, + "basis_points": 0, + "primary_sale_happened": false, + "locked": false + }, + "creators": [], + "ownership": { + "frozen": false, + "delegated": false, + "delegate": null, + "ownership_model": "single", + "owner": "Fq4HDXfutKjEZ7zZP2JmKboSm2ZsYsKEJ7BLQAfrpNcc" + }, + "supply": { + "print_max_supply": 0, + "print_current_supply": 0, + "edition_nonce": 0 + }, + "mutable": true, + "burnt": false +} diff --git a/integration_tests/tests/integration_tests/snapshots/integration_tests__cnft_tests__mint_delegate_transfer.snap b/integration_tests/tests/integration_tests/snapshots/integration_tests__cnft_tests__mint_delegate_transfer.snap new file mode 100644 index 000000000..db4ea6f15 --- /dev/null +++ b/integration_tests/tests/integration_tests/snapshots/integration_tests__cnft_tests__mint_delegate_transfer.snap @@ -0,0 +1,72 @@ +--- +source: integration_tests/tests/integration_tests/cnft_tests.rs +expression: response +--- +{ + "interface": "V1_NFT", + "id": "77wWrvhgEkkQZQVA2hoka1JTsjG3w7BVzvcmqxDrVPWE", + "content": { + "$schema": "https://schema.metaplex.com/nft1.0.json", + "json_uri": "https://metaplex.com", + "files": [], + "metadata": { + "name": "test", + "symbol": "TST", + "token_standard": "NonFungible" + }, + "links": {} + }, + "authorities": [ + { + "address": "E9uEW5uMNDhLGracp5XtvarF3udV3p6hemoXfBDB82QF", + "scopes": [ + "full" + ] + } + ], + "compression": { + "eligible": false, + "compressed": true, + "data_hash": "F5iDDHxd2DVZa5eZCqE2a91QLadea4ygJwM18UUut6dj", + "creator_hash": "EF57j46BT5Cynwija675rq59iDN1ZapYsJDnMHqta463", + "asset_hash": "BvK9Z52tdghAc8ohBdSbeJfbfHgirzJEKkaNdexBHHQ9", + "tree": "2AsVtpcSDi4nUhMEvtZPApGvucu6kP4qrKV6SZ9hG3WT", + "seq": 3, + "leaf_id": 0 + }, + "grouping": [], + "royalty": { + "royalty_model": "creators", + "target": null, + "percent": 0.0, + "basis_points": 0, + "primary_sale_happened": false, + "locked": false + }, + "creators": [ + { + "address": "Fq4HDXfutKjEZ7zZP2JmKboSm2ZsYsKEJ7BLQAfrpNcc", + "share": 55, + "verified": false + }, + { + "address": "GLUJH72y4ZoBU8qqHrQnDBtFsocF9DpeQNM1NS1q87rU", + "share": 45, + "verified": false + } + ], + "ownership": { + "frozen": false, + "delegated": false, + "delegate": null, + "ownership_model": "single", + "owner": "DjpoGceP1EJa2qEaZq8kS1GHTeDDL3AXJcSwLtrwqNj3" + }, + "supply": { + "print_max_supply": 0, + "print_current_supply": 0, + "edition_nonce": 0 + }, + "mutable": false, + "burnt": false +} diff --git a/integration_tests/tests/integration_tests/snapshots/integration_tests__cnft_tests__mint_no_json_uri.snap b/integration_tests/tests/integration_tests/snapshots/integration_tests__cnft_tests__mint_no_json_uri.snap new file mode 100644 index 000000000..b166b6375 --- /dev/null +++ b/integration_tests/tests/integration_tests/snapshots/integration_tests__cnft_tests__mint_no_json_uri.snap @@ -0,0 +1,72 @@ +--- +source: integration_tests/tests/integration_tests/cnft_tests.rs +expression: response +--- +{ + "interface": "V1_NFT", + "id": "DFRJ4PwAze1mMQccRmdyc46yQpEVd4FPiwtAVgzGCs7g", + "content": { + "$schema": "https://schema.metaplex.com/nft1.0.json", + "json_uri": "", + "files": [], + "metadata": { + "name": "", + "symbol": "", + "token_standard": "NonFungible" + }, + "links": {} + }, + "authorities": [ + { + "address": "GMdA1G1CDKNaiE1xGNJnB2KyNJVLCzvEcZ6P62SYSL3Z", + "scopes": [ + "full" + ] + } + ], + "compression": { + "eligible": false, + "compressed": true, + "data_hash": "6V4Uaz1QF1cnwAPGegnAZXd1oHcG3vydcXPDz2Rzpnzi", + "creator_hash": "AVgJYLS3Mex1pAkfXikHzfWF4Pvf924ESXswRTXRVMik", + "asset_hash": "HKvUDBDmeFo727WTYiE9SdR7bqpkQeJecZQoJbUep9Pg", + "tree": "67B3xvadpVeBJ6MT5tQqBqntrBeLNjrWbcF6uEAH1EEi", + "seq": 4, + "leaf_id": 3 + }, + "grouping": [ + { + "group_key": "collection", + "group_value": "GG6KuiAjG4hhg2AYdtjSoCG1QesgRFjTaok5MLxmAF3k" + } + ], + "royalty": { + "royalty_model": "creators", + "target": null, + "percent": 0.0, + "basis_points": 0, + "primary_sale_happened": false, + "locked": false + }, + "creators": [ + { + "address": "7WS6MiWdcqN7woEu8Vw8vGTmwxudPqQFts84jkvsDx9W", + "share": 100, + "verified": false + } + ], + "ownership": { + "frozen": false, + "delegated": false, + "delegate": null, + "ownership_model": "single", + "owner": "347kSWBNPm6Z3VFZZXAcKnT4T7v4WVQYw5b2xPJxp6zA" + }, + "supply": { + "print_max_supply": 0, + "print_current_supply": 0, + "edition_nonce": null + }, + "mutable": true, + "burnt": false +} diff --git a/integration_tests/tests/integration_tests/snapshots/integration_tests__cnft_tests__mint_redeem.snap b/integration_tests/tests/integration_tests/snapshots/integration_tests__cnft_tests__mint_redeem.snap new file mode 100644 index 000000000..7e01ca6ed --- /dev/null +++ b/integration_tests/tests/integration_tests/snapshots/integration_tests__cnft_tests__mint_redeem.snap @@ -0,0 +1,82 @@ +--- +source: integration_tests/tests/integration_tests/cnft_tests.rs +expression: response +--- +{ + "interface": "V1_NFT", + "id": "Az9QTysJj1LW1F7zkYF21HgBj3FRpq3zpxTFdPnAJYm8", + "content": { + "$schema": "https://schema.metaplex.com/nft1.0.json", + "json_uri": "https://baze.one/posts/rMb9dU7X2lSu/m", + "files": [], + "metadata": { + "name": "B-BCKSNW-4", + "symbol": "BCKSNW", + "token_standard": "NonFungible" + }, + "links": {} + }, + "authorities": [ + { + "address": "6uqVdTq4MSmr6FKdy5CCFnCzNNLZTw8ro7TdxC9UeKNr", + "scopes": [ + "full" + ] + } + ], + "compression": { + "eligible": false, + "compressed": true, + "data_hash": "11111111111111111111111111111111", + "creator_hash": "11111111111111111111111111111111", + "asset_hash": "11111111111111111111111111111111", + "tree": "tree9kmh23Qwa9K8sZ9rQtYshSwKA85CTEvw5bvTrau", + "seq": 62, + "leaf_id": 58 + }, + "grouping": [ + { + "group_key": "collection", + "group_value": "2MJeqBXcRmy3PXvQP5RRPqeig2CTfnXv5nGT3wRD1xW5" + } + ], + "royalty": { + "royalty_model": "creators", + "target": null, + "percent": 0.1, + "basis_points": 1000, + "primary_sale_happened": true, + "locked": false + }, + "creators": [ + { + "address": "8dpwoPxMkCd9LnsDEbrRuBL5sw3mqcWLf9vPcwgpeRMS", + "share": 100, + "verified": false + }, + { + "address": "2kKisVa2VmNk6iA2avQpZdDXtDGBWgzEE9ib7iWmKemw", + "share": 0, + "verified": false + }, + { + "address": "94huX4Ya45pA41AfeBkqadbBFjgFDrv5riZQXVLqsoVT", + "share": 0, + "verified": true + } + ], + "ownership": { + "frozen": false, + "delegated": false, + "delegate": null, + "ownership_model": "single", + "owner": "HkdmoXct4zKyAfgZgpuavKzmuvf2Z5UZ35v1UUW3Z9Jk" + }, + "supply": { + "print_max_supply": 0, + "print_current_supply": 0, + "edition_nonce": null + }, + "mutable": true, + "burnt": false +} diff --git a/integration_tests/tests/integration_tests/snapshots/integration_tests__cnft_tests__mint_redeem_cancel_redeem.snap b/integration_tests/tests/integration_tests/snapshots/integration_tests__cnft_tests__mint_redeem_cancel_redeem.snap new file mode 100644 index 000000000..10beb8031 --- /dev/null +++ b/integration_tests/tests/integration_tests/snapshots/integration_tests__cnft_tests__mint_redeem_cancel_redeem.snap @@ -0,0 +1,72 @@ +--- +source: integration_tests/tests/integration_tests/cnft_tests.rs +expression: response +--- +{ + "interface": "V1_NFT", + "id": "5WaPA7HLZKGg56bcKiroMXAzHmB1mdxK3QTeCDepLkiK", + "content": { + "$schema": "https://schema.metaplex.com/nft1.0.json", + "json_uri": "https://metaplex.com", + "files": [], + "metadata": { + "name": "test", + "symbol": "TST", + "token_standard": "NonFungible" + }, + "links": {} + }, + "authorities": [ + { + "address": "JBLMxYC5JMW9v2yGuSM2xtFqsD7omw2gQS2YmcXPz3dL", + "scopes": [ + "full" + ] + } + ], + "compression": { + "eligible": false, + "compressed": true, + "data_hash": "DLrNQJ6gJbfsqBLe3QXMVc8j2kjVtFqFbXd6rFsoFVyG", + "creator_hash": "58PDE6bzJweEP4NauMXugPYfjkZMzGGptDyH7rP4ZSEq", + "asset_hash": "AqMe3832WCXHbaaKAPs5MFo55oWBEKKN5iigTaoRtHFr", + "tree": "Hk1644vHxBJ33ZZ1QW5P1zpex9qJ22RdHCwk46aaR16k", + "seq": 3, + "leaf_id": 0 + }, + "grouping": [], + "royalty": { + "royalty_model": "creators", + "target": null, + "percent": 0.0, + "basis_points": 0, + "primary_sale_happened": false, + "locked": false + }, + "creators": [ + { + "address": "Fq4HDXfutKjEZ7zZP2JmKboSm2ZsYsKEJ7BLQAfrpNcc", + "share": 55, + "verified": false + }, + { + "address": "GXxPiX5aAQJPSnNoJ4WwwNwbjmUEPdeCiSQoDgXkg2X7", + "share": 45, + "verified": false + } + ], + "ownership": { + "frozen": false, + "delegated": false, + "delegate": null, + "ownership_model": "single", + "owner": "Fq4HDXfutKjEZ7zZP2JmKboSm2ZsYsKEJ7BLQAfrpNcc" + }, + "supply": { + "print_max_supply": 0, + "print_current_supply": 0, + "edition_nonce": 0 + }, + "mutable": false, + "burnt": false +} diff --git a/integration_tests/tests/integration_tests/snapshots/integration_tests__cnft_tests__mint_transfer_burn.snap b/integration_tests/tests/integration_tests/snapshots/integration_tests__cnft_tests__mint_transfer_burn.snap new file mode 100644 index 000000000..1b3a83390 --- /dev/null +++ b/integration_tests/tests/integration_tests/snapshots/integration_tests__cnft_tests__mint_transfer_burn.snap @@ -0,0 +1,72 @@ +--- +source: integration_tests/tests/integration_tests/cnft_tests.rs +expression: response +--- +{ + "interface": "V1_NFT", + "id": "8vw7tdLGE3FBjaetsJrZAarwsbc8UESsegiLyvWXxs5A", + "content": { + "$schema": "https://schema.metaplex.com/nft1.0.json", + "json_uri": "https://metaplex.com", + "files": [], + "metadata": { + "name": "test", + "symbol": "TST", + "token_standard": "NonFungible" + }, + "links": {} + }, + "authorities": [ + { + "address": "9nyYr9vyDZU8SnVNgQ58kcEtcpXUj57vkzwd4UjbZrS8", + "scopes": [ + "full" + ] + } + ], + "compression": { + "eligible": false, + "compressed": true, + "data_hash": "GFsq2BCwZdQaErGkQD5my36tpC8Cg38HFuMvbM6ShC2h", + "creator_hash": "2ct1dcDUbFDHfpdtuZ5vdkPB1ewjFg9pxRi58Yj4huCj", + "asset_hash": "4R8dTjLuyetziKZFeM45Qa1XuGn3vd4LdJkGPEJhotAq", + "tree": "CnBt2TJrw1dXUBfVBf2Ah4Cz5s84jhBG7cejdPF19Eyh", + "seq": 3, + "leaf_id": 0 + }, + "grouping": [], + "royalty": { + "royalty_model": "creators", + "target": null, + "percent": 0.0, + "basis_points": 0, + "primary_sale_happened": false, + "locked": false + }, + "creators": [ + { + "address": "Fq4HDXfutKjEZ7zZP2JmKboSm2ZsYsKEJ7BLQAfrpNcc", + "share": 55, + "verified": false + }, + { + "address": "CXiFtmdyYxeX5hydprYLaMjH4h2r8NBQ8NTezzfemGv5", + "share": 45, + "verified": false + } + ], + "ownership": { + "frozen": false, + "delegated": false, + "delegate": null, + "ownership_model": "single", + "owner": "BJ5jYD1AGSTR7fvZyvUoj59PY7cF8Ki2j1gB36PJFuTD" + }, + "supply": { + "print_max_supply": 0, + "print_current_supply": 0, + "edition_nonce": 0 + }, + "mutable": false, + "burnt": true +} diff --git a/integration_tests/tests/integration_tests/snapshots/integration_tests__cnft_tests__mint_transfer_noop.snap b/integration_tests/tests/integration_tests/snapshots/integration_tests__cnft_tests__mint_transfer_noop.snap new file mode 100644 index 000000000..ba10ce477 --- /dev/null +++ b/integration_tests/tests/integration_tests/snapshots/integration_tests__cnft_tests__mint_transfer_noop.snap @@ -0,0 +1,72 @@ +--- +source: integration_tests/tests/integration_tests/cnft_tests.rs +expression: response +--- +{ + "interface": "V1_NFT", + "id": "7myVr8fEG52mZ3jAwgz88iQRWsuzuVR2nfH8n2AXnBxE", + "content": { + "$schema": "https://schema.metaplex.com/nft1.0.json", + "json_uri": "https://arweave.net/S40vvBVuCvZhAWI3kvk3QreUqVAvR0AaUDObOhB8WIY", + "files": [], + "metadata": { + "name": "Golden Azurite", + "symbol": "OEAs", + "token_standard": "NonFungible" + }, + "links": {} + }, + "authorities": [ + { + "address": "EDAR6p4AUbv9SpD1pDm3gxdSAivdqsHxsf6V9pBc532U", + "scopes": [ + "full" + ] + } + ], + "compression": { + "eligible": false, + "compressed": true, + "data_hash": "B2tu4duCUPequnXh7DxbMnLeLcACHbDCQn3g34s5Cvbx", + "creator_hash": "6UiSCAv4r66MALaqhNE7qdTK84qKk1yJqR4UYtT8qEQ1", + "asset_hash": "45gbVkkwEaKhFatRQf1GPbkJVdhtVwefEzdCi9aNpHG8", + "tree": "4r2zZHZvC4Se1KUcCcyCM4ZoFQNGZm2M5FMmUypFocAP", + "seq": 43, + "leaf_id": 5 + }, + "grouping": [ + { + "group_key": "collection", + "group_value": "BwwjnxTHeVWdFieDWmoezta19q1NiwcNNyoon9S38bkM" + } + ], + "royalty": { + "royalty_model": "creators", + "target": null, + "percent": 0.05, + "basis_points": 500, + "primary_sale_happened": true, + "locked": false + }, + "creators": [ + { + "address": "4gETqgEwFLkXX9yk6qBszA6LMjC2kRyyERXsAr2rwhwf", + "share": 100, + "verified": false + } + ], + "ownership": { + "frozen": false, + "delegated": false, + "delegate": null, + "ownership_model": "single", + "owner": "4fzLUnMx7CrmzVqgySNFkup1ACgZNnBWLx9sfpsaLEcK" + }, + "supply": { + "print_max_supply": 0, + "print_current_supply": 0, + "edition_nonce": null + }, + "mutable": true, + "burnt": false +} diff --git a/integration_tests/tests/integration_tests/snapshots/integration_tests__cnft_tests__mint_transfer_transfer.snap b/integration_tests/tests/integration_tests/snapshots/integration_tests__cnft_tests__mint_transfer_transfer.snap new file mode 100644 index 000000000..28a0ca830 --- /dev/null +++ b/integration_tests/tests/integration_tests/snapshots/integration_tests__cnft_tests__mint_transfer_transfer.snap @@ -0,0 +1,72 @@ +--- +source: integration_tests/tests/integration_tests/cnft_tests.rs +expression: response +--- +{ + "interface": "V1_NFT", + "id": "EcLv3bbLYr2iH5PVEuf9pJMRdDCvCqwSx3Srz6AeKjAe", + "content": { + "$schema": "https://schema.metaplex.com/nft1.0.json", + "json_uri": "https://metaplex.com", + "files": [], + "metadata": { + "name": "test", + "symbol": "TST", + "token_standard": "NonFungible" + }, + "links": {} + }, + "authorities": [ + { + "address": "J6uMQYzyeFXE5tvnKtmAUyHeiKEWiELARceY8HhSuBF6", + "scopes": [ + "full" + ] + } + ], + "compression": { + "eligible": false, + "compressed": true, + "data_hash": "68ZcMZF52Bv3mayj4AjPFdVoMhrE9Ap18CQRuUhB2pWu", + "creator_hash": "2RsQnw2DXTrKWT2GAd7LEnvgHuL8gZ8C2wk89dcW31yb", + "asset_hash": "5gZXmV7yzWMcKk2n24t4tXECHJffRX179ZoxVaheADpp", + "tree": "AdKerrR54h9H1zNoyex9f6svuQQSeKrSEufiGtA5zu8v", + "seq": 3, + "leaf_id": 0 + }, + "grouping": [], + "royalty": { + "royalty_model": "creators", + "target": null, + "percent": 0.0, + "basis_points": 0, + "primary_sale_happened": false, + "locked": false + }, + "creators": [ + { + "address": "Fq4HDXfutKjEZ7zZP2JmKboSm2ZsYsKEJ7BLQAfrpNcc", + "share": 55, + "verified": false + }, + { + "address": "AhKyxn99oZN7MhdWfU8S9qmmBZBkQYgr2KaNQEJWVHcd", + "share": 45, + "verified": false + } + ], + "ownership": { + "frozen": false, + "delegated": false, + "delegate": null, + "ownership_model": "single", + "owner": "8WUbLiKgdqA2jcA8xR2Qm1nxeQTHSiz2HTyZDb7nZu6n" + }, + "supply": { + "print_max_supply": 0, + "print_current_supply": 0, + "edition_nonce": 0 + }, + "mutable": false, + "burnt": false +} diff --git a/integration_tests/tests/integration_tests/snapshots/integration_tests__cnft_tests__mint_verify_collection.snap b/integration_tests/tests/integration_tests/snapshots/integration_tests__cnft_tests__mint_verify_collection.snap new file mode 100644 index 000000000..806741e32 --- /dev/null +++ b/integration_tests/tests/integration_tests/snapshots/integration_tests__cnft_tests__mint_verify_collection.snap @@ -0,0 +1,77 @@ +--- +source: integration_tests/tests/integration_tests/cnft_tests.rs +expression: response +--- +{ + "interface": "V1_NFT", + "id": "2WjoMU1hBGXv8sKcxQDGnu1tgMduzdZEmEEGjh8MZYfC", + "content": { + "$schema": "https://schema.metaplex.com/nft1.0.json", + "json_uri": "https://metaplex.com", + "files": [], + "metadata": { + "name": "test", + "symbol": "TST", + "token_standard": "NonFungible" + }, + "links": {} + }, + "authorities": [ + { + "address": "2322PBMYe82eqDMmzJzUdWYWjhDzr1qGaujs32sNnHp1", + "scopes": [ + "full" + ] + } + ], + "compression": { + "eligible": false, + "compressed": true, + "data_hash": "5qnPtMuhWzj8rRviKV1YRitUxgt4iFqFkpvyuBn5rTKW", + "creator_hash": "FM4zS99NvwRZm5UGgcJW1pQEWDtpgH4jaiCaTkMn6mxD", + "asset_hash": "DaxPr3AmJoqwJxgeeTSXZjM8eXzj2aEkbAWChJEhh53e", + "tree": "F7gUS2b9mMKHWz6yebb447tAt9wUZbwtwqFabJbhi4V2", + "seq": 2, + "leaf_id": 0 + }, + "grouping": [ + { + "group_key": "collection", + "group_value": "4zapNXifB7Lz5XGUtsYQ3gsEujK2dqFw4mE9NY57NrtD" + } + ], + "royalty": { + "royalty_model": "creators", + "target": null, + "percent": 0.0, + "basis_points": 0, + "primary_sale_happened": false, + "locked": false + }, + "creators": [ + { + "address": "Fq4HDXfutKjEZ7zZP2JmKboSm2ZsYsKEJ7BLQAfrpNcc", + "share": 55, + "verified": false + }, + { + "address": "8xJtnbXezwkUwvj5tMUUK7ortAPa3Sm5sJPvTUhXhKR5", + "share": 45, + "verified": false + } + ], + "ownership": { + "frozen": false, + "delegated": false, + "delegate": null, + "ownership_model": "single", + "owner": "Fq4HDXfutKjEZ7zZP2JmKboSm2ZsYsKEJ7BLQAfrpNcc" + }, + "supply": { + "print_max_supply": 0, + "print_current_supply": 0, + "edition_nonce": 0 + }, + "mutable": false, + "burnt": false +} diff --git a/integration_tests/tests/integration_tests/snapshots/integration_tests__cnft_tests__mint_verify_creator.snap b/integration_tests/tests/integration_tests/snapshots/integration_tests__cnft_tests__mint_verify_creator.snap new file mode 100644 index 000000000..a579b883f --- /dev/null +++ b/integration_tests/tests/integration_tests/snapshots/integration_tests__cnft_tests__mint_verify_creator.snap @@ -0,0 +1,72 @@ +--- +source: integration_tests/tests/integration_tests/cnft_tests.rs +expression: response +--- +{ + "interface": "V1_NFT", + "id": "5rmTyghEuZhRTB77L3KqGMy6h5RpSNWNLj14avbxGNKB", + "content": { + "$schema": "https://schema.metaplex.com/nft1.0.json", + "json_uri": "https://metaplex.com", + "files": [], + "metadata": { + "name": "test", + "symbol": "TST", + "token_standard": "NonFungible" + }, + "links": {} + }, + "authorities": [ + { + "address": "CytP31N7oz9etRF9ddgav6JzEhcWuZXTSTwh3jP7zRa", + "scopes": [ + "full" + ] + } + ], + "compression": { + "eligible": false, + "compressed": true, + "data_hash": "31vt7MSZzRykZN1FjQktuk8oaWCVL9SzfMyX9Q2RtTaa", + "creator_hash": "4GAv4MMcgC7xjLuLHSMxxoRpp2cCbz52f9vhYK7GNZMX", + "asset_hash": "6mfR173y5dNp19LzqQXruUWrbPbFFC9TGbqUN1ArNsBm", + "tree": "6XLLEYd2AtUFAP2ysaTGoUj3QmzPumqH1MX2n7DzFrBU", + "seq": 2, + "leaf_id": 0 + }, + "grouping": [], + "royalty": { + "royalty_model": "creators", + "target": null, + "percent": 0.0, + "basis_points": 0, + "primary_sale_happened": false, + "locked": false + }, + "creators": [ + { + "address": "Fq4HDXfutKjEZ7zZP2JmKboSm2ZsYsKEJ7BLQAfrpNcc", + "share": 55, + "verified": false + }, + { + "address": "rU9dhXotNmpzzBHmQZKAGHGSvcLN6VB2j4TC5rTHPz3", + "share": 45, + "verified": true + } + ], + "ownership": { + "frozen": false, + "delegated": false, + "delegate": null, + "ownership_model": "single", + "owner": "Fq4HDXfutKjEZ7zZP2JmKboSm2ZsYsKEJ7BLQAfrpNcc" + }, + "supply": { + "print_max_supply": 0, + "print_current_supply": 0, + "edition_nonce": 0 + }, + "mutable": false, + "burnt": false +} diff --git a/integration_tests/tests/integration_tests/snapshots/integration_tests__general_scenario_tests__asset_parsing.snap b/integration_tests/tests/integration_tests/snapshots/integration_tests__general_scenario_tests__asset_parsing.snap new file mode 100644 index 000000000..27d495e3a --- /dev/null +++ b/integration_tests/tests/integration_tests/snapshots/integration_tests__general_scenario_tests__asset_parsing.snap @@ -0,0 +1,68 @@ +--- +source: integration_tests/tests/integration_tests/general_scenario_tests.rs +expression: response +--- +{ + "interface": "ProgrammableNFT", + "id": "843gdpsTE4DoJz3ZoBsEjAqT8UgAcyF5YojygGgGZE1f", + "content": { + "$schema": "https://schema.metaplex.com/nft1.0.json", + "json_uri": "https://nftstorage.link/ipfs/bafybeihaky4htq6obur3ziksyanpdoqmrnefben3dbecddru52xh2sdkii/1232.json", + "files": [], + "metadata": { + "name": "Phantom Mage #1233", + "symbol": "PM", + "token_standard": "ProgrammableNonFungible" + }, + "links": {} + }, + "authorities": [ + { + "address": "GMhP98kXvfziKNfq1nP99AbWtZAweLu3DFz5Vs5ZaVTy", + "scopes": [ + "full" + ] + } + ], + "compression": { + "eligible": false, + "compressed": false, + "data_hash": "", + "creator_hash": "", + "asset_hash": "", + "tree": "", + "seq": 0, + "leaf_id": 0 + }, + "grouping": [], + "royalty": { + "royalty_model": "creators", + "target": null, + "percent": 0.0555, + "basis_points": 555, + "primary_sale_happened": false, + "locked": false + }, + "creators": [ + { + "address": "5KtTmcxYYzK5mR7gEtjVX2eBBK1g7YjVbvsMBAbyf9uK", + "share": 0, + "verified": true + }, + { + "address": "HmkCMBPdY6MixHP8hxsM8G1UwJH3fBN2itWagnYoXASR", + "share": 100, + "verified": false + } + ], + "ownership": { + "frozen": true, + "delegated": false, + "delegate": null, + "ownership_model": "single", + "owner": "BzbdvwEkQKeghTY53aZxTYjUienhdbkNVkgrLV6cErke" + }, + "supply": null, + "mutable": true, + "burnt": false +} diff --git a/integration_tests/tests/integration_tests/snapshots/integration_tests__general_scenario_tests__creators_reordering.snap b/integration_tests/tests/integration_tests/snapshots/integration_tests__general_scenario_tests__creators_reordering.snap new file mode 100644 index 000000000..2ed4bf732 --- /dev/null +++ b/integration_tests/tests/integration_tests/snapshots/integration_tests__general_scenario_tests__creators_reordering.snap @@ -0,0 +1,83 @@ +--- +source: integration_tests/tests/integration_tests/general_scenario_tests.rs +expression: response +--- +{ + "interface": "ProgrammableNFT", + "id": "ANt9HygtvFmFJ1UcAHFLnM62JJWjk8fujMzjGfpKBfzk", + "content": { + "$schema": "https://schema.metaplex.com/nft1.0.json", + "json_uri": "https://shdw-drive.genesysgo.net/3sRtma7VsvgUrGroHkfQga8ipBmv4PAySFwS6rayXxbU/761158362554895.json", + "files": [], + "metadata": { + "name": "BVDCAT #5129", + "symbol": "BVD", + "token_standard": "ProgrammableNonFungible" + }, + "links": {} + }, + "authorities": [ + { + "address": "4xJDyBw7RHgfzG2inyTHs8FP7wyqFSywcLKwX8GK6X55", + "scopes": [ + "full" + ] + } + ], + "compression": { + "eligible": false, + "compressed": false, + "data_hash": "", + "creator_hash": "", + "asset_hash": "", + "tree": "", + "seq": 0, + "leaf_id": 0 + }, + "grouping": [ + { + "group_key": "collection", + "group_value": "HEAKpy99JuLhfinuLgji757JxHvPizBo7WaXvWBYc3kz" + } + ], + "royalty": { + "royalty_model": "creators", + "target": null, + "percent": 0.05, + "basis_points": 500, + "primary_sale_happened": true, + "locked": false + }, + "creators": [ + { + "address": "8Jhy62JeG4rgPu4Q2tn3Q3eZ8XUZmHhYDKpVJkQ8RFhe", + "share": 0, + "verified": true + }, + { + "address": "9sJ3GKyTpBaNJ9CVFV6DecV556G1jU9L32kJASxzWsQA", + "share": 10, + "verified": false + }, + { + "address": "BDaobvsTU8Eu3R4sx1vLufKiToaZL3MDTHxPgHgvGWC7", + "share": 10, + "verified": false + }, + { + "address": "F9xfmpggwgqH7ASZzNre8TxZztZwCogPBE8aQCNBLkBn", + "share": 80, + "verified": false + } + ], + "ownership": { + "frozen": true, + "delegated": false, + "delegate": null, + "ownership_model": "single", + "owner": "AZgXpkRSetUJHy6C3NBvG6jNe49MpgrkZ2RkdMkjCjkW" + }, + "supply": null, + "mutable": true, + "burnt": false +} diff --git a/integration_tests/tests/integration_tests/snapshots/integration_tests__regular_nft_tests__reg_get_asset.snap b/integration_tests/tests/integration_tests/snapshots/integration_tests__regular_nft_tests__reg_get_asset.snap new file mode 100644 index 000000000..c62b3de1c --- /dev/null +++ b/integration_tests/tests/integration_tests/snapshots/integration_tests__regular_nft_tests__reg_get_asset.snap @@ -0,0 +1,73 @@ +--- +source: integration_tests/tests/integration_tests/regular_nft_tests.rs +expression: response +--- +{ + "interface": "ProgrammableNFT", + "id": "CMVuYDS9nTeujfTPJb8ik7CRhAqZv4DfjfdamFLkJgxE", + "content": { + "$schema": "https://schema.metaplex.com/nft1.0.json", + "json_uri": "https://madlads.s3.us-west-2.amazonaws.com/json/9964.json", + "files": [], + "metadata": { + "name": "Mad Lads #9964", + "symbol": "MAD", + "token_standard": "ProgrammableNonFungible" + }, + "links": {} + }, + "authorities": [ + { + "address": "2RtGg6fsFiiF1EQzHqbd66AhW7R5bWeQGpTbv2UMkCdW", + "scopes": [ + "full" + ] + } + ], + "compression": { + "eligible": false, + "compressed": false, + "data_hash": "", + "creator_hash": "", + "asset_hash": "", + "tree": "", + "seq": 0, + "leaf_id": 0 + }, + "grouping": [ + { + "group_key": "collection", + "group_value": "J1S9H3QjnRtBbbuD4HjPV6RpRhwuk4zKbxsnCHuTgh9w" + } + ], + "royalty": { + "royalty_model": "creators", + "target": null, + "percent": 0.042, + "basis_points": 420, + "primary_sale_happened": true, + "locked": false + }, + "creators": [ + { + "address": "5XvhfmRjwXkGp3jHGmaKpqeerNYjkuZZBYLVQYdeVcRv", + "share": 0, + "verified": true + }, + { + "address": "2RtGg6fsFiiF1EQzHqbd66AhW7R5bWeQGpTbv2UMkCdW", + "share": 100, + "verified": true + } + ], + "ownership": { + "frozen": true, + "delegated": true, + "delegate": "GBkD9WsmSPNBF7bnFxyC4BCC2ZiBzYq9iWStPZ9Kj9cU", + "ownership_model": "single", + "owner": "A59E2tNJEqNN9TDnzgGnmLmnTsdRDoPocGx3n1w2dqZw" + }, + "supply": null, + "mutable": true, + "burnt": false +} diff --git a/integration_tests/tests/integration_tests/snapshots/integration_tests__regular_nft_tests__reg_get_asset_batch-2-and-a-missing-1.snap b/integration_tests/tests/integration_tests/snapshots/integration_tests__regular_nft_tests__reg_get_asset_batch-2-and-a-missing-1.snap new file mode 100644 index 000000000..0825ec1b2 --- /dev/null +++ b/integration_tests/tests/integration_tests/snapshots/integration_tests__regular_nft_tests__reg_get_asset_batch-2-and-a-missing-1.snap @@ -0,0 +1,145 @@ +--- +source: integration_tests/tests/integration_tests/regular_nft_tests.rs +expression: response +--- +[ + { + "interface": "ProgrammableNFT", + "id": "2NqdYX6kJmMUoChnDXU2UrP9BsoPZivRw3uJG8iDhRRd", + "content": { + "$schema": "https://schema.metaplex.com/nft1.0.json", + "json_uri": "https://madlads.s3.us-west-2.amazonaws.com/json/9959.json", + "files": [], + "metadata": { + "name": "Mad Lads #9959", + "symbol": "MAD", + "token_standard": "ProgrammableNonFungible" + }, + "links": {} + }, + "authorities": [ + { + "address": "2RtGg6fsFiiF1EQzHqbd66AhW7R5bWeQGpTbv2UMkCdW", + "scopes": [ + "full" + ] + } + ], + "compression": { + "eligible": false, + "compressed": false, + "data_hash": "", + "creator_hash": "", + "asset_hash": "", + "tree": "", + "seq": 0, + "leaf_id": 0 + }, + "grouping": [ + { + "group_key": "collection", + "group_value": "J1S9H3QjnRtBbbuD4HjPV6RpRhwuk4zKbxsnCHuTgh9w" + } + ], + "royalty": { + "royalty_model": "creators", + "target": null, + "percent": 0.042, + "basis_points": 420, + "primary_sale_happened": true, + "locked": false + }, + "creators": [ + { + "address": "5XvhfmRjwXkGp3jHGmaKpqeerNYjkuZZBYLVQYdeVcRv", + "share": 0, + "verified": true + }, + { + "address": "2RtGg6fsFiiF1EQzHqbd66AhW7R5bWeQGpTbv2UMkCdW", + "share": 100, + "verified": true + } + ], + "ownership": { + "frozen": true, + "delegated": true, + "delegate": "CimD28VvDSHcGdErmLbbPimnkfwrKHvstNiQUutZDxWS", + "ownership_model": "single", + "owner": "9PacVenjPyQYiWBha89UYRM1nn6mf9bGY7vi32zY6DLn" + }, + "supply": null, + "mutable": true, + "burnt": false + }, + null, + { + "interface": "ProgrammableNFT", + "id": "5rEeYv8R25b8j6YTHJvYuCKEzq44UCw1Wx1Wx2VPPLz1", + "content": { + "$schema": "https://schema.metaplex.com/nft1.0.json", + "json_uri": "https://madlads.s3.us-west-2.amazonaws.com/json/9963.json", + "files": [], + "metadata": { + "name": "Mad Lads #9963", + "symbol": "MAD", + "token_standard": "ProgrammableNonFungible" + }, + "links": {} + }, + "authorities": [ + { + "address": "2RtGg6fsFiiF1EQzHqbd66AhW7R5bWeQGpTbv2UMkCdW", + "scopes": [ + "full" + ] + } + ], + "compression": { + "eligible": false, + "compressed": false, + "data_hash": "", + "creator_hash": "", + "asset_hash": "", + "tree": "", + "seq": 0, + "leaf_id": 0 + }, + "grouping": [ + { + "group_key": "collection", + "group_value": "J1S9H3QjnRtBbbuD4HjPV6RpRhwuk4zKbxsnCHuTgh9w" + } + ], + "royalty": { + "royalty_model": "creators", + "target": null, + "percent": 0.042, + "basis_points": 420, + "primary_sale_happened": true, + "locked": false + }, + "creators": [ + { + "address": "5XvhfmRjwXkGp3jHGmaKpqeerNYjkuZZBYLVQYdeVcRv", + "share": 0, + "verified": true + }, + { + "address": "2RtGg6fsFiiF1EQzHqbd66AhW7R5bWeQGpTbv2UMkCdW", + "share": 100, + "verified": true + } + ], + "ownership": { + "frozen": true, + "delegated": true, + "delegate": "CcYTgeWQhsdyGYbJAzUuuPG6jvNhfyzXmNWVSrxbdC9a", + "ownership_model": "single", + "owner": "3H3d3hfpZVVdVwuFAxDtDSFN2AdR7kwiDA3ynbnbkhc9" + }, + "supply": null, + "mutable": true, + "burnt": false + } +] diff --git a/integration_tests/tests/integration_tests/snapshots/integration_tests__regular_nft_tests__reg_get_asset_batch-only-2-different-2.snap b/integration_tests/tests/integration_tests/snapshots/integration_tests__regular_nft_tests__reg_get_asset_batch-only-2-different-2.snap new file mode 100644 index 000000000..36c9961f9 --- /dev/null +++ b/integration_tests/tests/integration_tests/snapshots/integration_tests__regular_nft_tests__reg_get_asset_batch-only-2-different-2.snap @@ -0,0 +1,144 @@ +--- +source: integration_tests/tests/integration_tests/regular_nft_tests.rs +expression: response +--- +[ + { + "interface": "ProgrammableNFT", + "id": "2NqdYX6kJmMUoChnDXU2UrP9BsoPZivRw3uJG8iDhRRd", + "content": { + "$schema": "https://schema.metaplex.com/nft1.0.json", + "json_uri": "https://madlads.s3.us-west-2.amazonaws.com/json/9959.json", + "files": [], + "metadata": { + "name": "Mad Lads #9959", + "symbol": "MAD", + "token_standard": "ProgrammableNonFungible" + }, + "links": {} + }, + "authorities": [ + { + "address": "2RtGg6fsFiiF1EQzHqbd66AhW7R5bWeQGpTbv2UMkCdW", + "scopes": [ + "full" + ] + } + ], + "compression": { + "eligible": false, + "compressed": false, + "data_hash": "", + "creator_hash": "", + "asset_hash": "", + "tree": "", + "seq": 0, + "leaf_id": 0 + }, + "grouping": [ + { + "group_key": "collection", + "group_value": "J1S9H3QjnRtBbbuD4HjPV6RpRhwuk4zKbxsnCHuTgh9w" + } + ], + "royalty": { + "royalty_model": "creators", + "target": null, + "percent": 0.042, + "basis_points": 420, + "primary_sale_happened": true, + "locked": false + }, + "creators": [ + { + "address": "5XvhfmRjwXkGp3jHGmaKpqeerNYjkuZZBYLVQYdeVcRv", + "share": 0, + "verified": true + }, + { + "address": "2RtGg6fsFiiF1EQzHqbd66AhW7R5bWeQGpTbv2UMkCdW", + "share": 100, + "verified": true + } + ], + "ownership": { + "frozen": true, + "delegated": true, + "delegate": "CimD28VvDSHcGdErmLbbPimnkfwrKHvstNiQUutZDxWS", + "ownership_model": "single", + "owner": "9PacVenjPyQYiWBha89UYRM1nn6mf9bGY7vi32zY6DLn" + }, + "supply": null, + "mutable": true, + "burnt": false + }, + { + "interface": "ProgrammableNFT", + "id": "5rEeYv8R25b8j6YTHJvYuCKEzq44UCw1Wx1Wx2VPPLz1", + "content": { + "$schema": "https://schema.metaplex.com/nft1.0.json", + "json_uri": "https://madlads.s3.us-west-2.amazonaws.com/json/9963.json", + "files": [], + "metadata": { + "name": "Mad Lads #9963", + "symbol": "MAD", + "token_standard": "ProgrammableNonFungible" + }, + "links": {} + }, + "authorities": [ + { + "address": "2RtGg6fsFiiF1EQzHqbd66AhW7R5bWeQGpTbv2UMkCdW", + "scopes": [ + "full" + ] + } + ], + "compression": { + "eligible": false, + "compressed": false, + "data_hash": "", + "creator_hash": "", + "asset_hash": "", + "tree": "", + "seq": 0, + "leaf_id": 0 + }, + "grouping": [ + { + "group_key": "collection", + "group_value": "J1S9H3QjnRtBbbuD4HjPV6RpRhwuk4zKbxsnCHuTgh9w" + } + ], + "royalty": { + "royalty_model": "creators", + "target": null, + "percent": 0.042, + "basis_points": 420, + "primary_sale_happened": true, + "locked": false + }, + "creators": [ + { + "address": "5XvhfmRjwXkGp3jHGmaKpqeerNYjkuZZBYLVQYdeVcRv", + "share": 0, + "verified": true + }, + { + "address": "2RtGg6fsFiiF1EQzHqbd66AhW7R5bWeQGpTbv2UMkCdW", + "share": 100, + "verified": true + } + ], + "ownership": { + "frozen": true, + "delegated": true, + "delegate": "CcYTgeWQhsdyGYbJAzUuuPG6jvNhfyzXmNWVSrxbdC9a", + "ownership_model": "single", + "owner": "3H3d3hfpZVVdVwuFAxDtDSFN2AdR7kwiDA3ynbnbkhc9" + }, + "supply": null, + "mutable": true, + "burnt": false + } +] diff --git a/integration_tests/tests/integration_tests/snapshots/integration_tests__regular_nft_tests__reg_get_asset_batch-only-2.snap b/integration_tests/tests/integration_tests/snapshots/integration_tests__regular_nft_tests__reg_get_asset_batch-only-2.snap new file mode 100644 index 000000000..f07052af1 --- /dev/null +++ b/integration_tests/tests/integration_tests/snapshots/integration_tests__regular_nft_tests__reg_get_asset_batch-only-2.snap @@ -0,0 +1,144 @@ +--- +source: integration_tests/tests/integration_tests/regular_nft_tests.rs +expression: response +--- +[ + { + "interface": "ProgrammableNFT", + "id": "HTKAVZZrDdyecCxzm3WEkCsG1GUmiqKm73PvngfuYRNK", + "content": { + "$schema": "https://schema.metaplex.com/nft1.0.json", + "json_uri": "https://madlads.s3.us-west-2.amazonaws.com/json/9965.json", + "files": [], + "metadata": { + "name": "Mad Lads #9965", + "symbol": "MAD", + "token_standard": "ProgrammableNonFungible" + }, + "links": {} + }, + "authorities": [ + { + "address": "2RtGg6fsFiiF1EQzHqbd66AhW7R5bWeQGpTbv2UMkCdW", + "scopes": [ + "full" + ] + } + ], + "compression": { + "eligible": false, + "compressed": false, + "data_hash": "", + "creator_hash": "", + "asset_hash": "", + "tree": "", + "seq": 0, + "leaf_id": 0 + }, + "grouping": [ + { + "group_key": "collection", + "group_value": "J1S9H3QjnRtBbbuD4HjPV6RpRhwuk4zKbxsnCHuTgh9w" + } + ], + "royalty": { + "royalty_model": "creators", + "target": null, + "percent": 0.042, + "basis_points": 420, + "primary_sale_happened": true, + "locked": false + }, + "creators": [ + { + "address": "5XvhfmRjwXkGp3jHGmaKpqeerNYjkuZZBYLVQYdeVcRv", + "share": 0, + "verified": true + }, + { + "address": "2RtGg6fsFiiF1EQzHqbd66AhW7R5bWeQGpTbv2UMkCdW", + "share": 100, + "verified": true + } + ], + "ownership": { + "frozen": true, + "delegated": true, + "delegate": "Hys4KoEw32y4sLHb96K2PqYT5jUHqUWdh6qS9EACEB4Y", + "ownership_model": "single", + "owner": "BaBQKh34KrqZzd4ifSHQYMf86HiBGASN6TWUi1ZwfyKv" + }, + "supply": null, + "mutable": true, + "burnt": false + }, + { + "interface": "ProgrammableNFT", + "id": "2NqdYX6kJmMUoChnDXU2UrP9BsoPZivRw3uJG8iDhRRd", + "content": { + "$schema": "https://schema.metaplex.com/nft1.0.json", + "json_uri": "https://madlads.s3.us-west-2.amazonaws.com/json/9959.json", + "files": [], + "metadata": { + "name": "Mad Lads #9959", + "symbol": "MAD", + "token_standard": "ProgrammableNonFungible" + }, + "links": {} + }, + "authorities": [ + { + "address": "2RtGg6fsFiiF1EQzHqbd66AhW7R5bWeQGpTbv2UMkCdW", + "scopes": [ + "full" + ] + } + ], + "compression": { + "eligible": false, + "compressed": false, + "data_hash": "", + "creator_hash": "", + "asset_hash": "", + "tree": "", + "seq": 0, + "leaf_id": 0 + }, + "grouping": [ + { + "group_key": "collection", + "group_value": "J1S9H3QjnRtBbbuD4HjPV6RpRhwuk4zKbxsnCHuTgh9w" + } + ], + "royalty": { + "royalty_model": "creators", + "target": null, + "percent": 0.042, + "basis_points": 420, + "primary_sale_happened": true, + "locked": false + }, + "creators": [ + { + "address": "5XvhfmRjwXkGp3jHGmaKpqeerNYjkuZZBYLVQYdeVcRv", + "share": 0, + "verified": true + }, + { + "address": "2RtGg6fsFiiF1EQzHqbd66AhW7R5bWeQGpTbv2UMkCdW", + "share": 100, + "verified": true + } + ], + "ownership": { + "frozen": true, + "delegated": true, + "delegate": "CimD28VvDSHcGdErmLbbPimnkfwrKHvstNiQUutZDxWS", + "ownership_model": "single", + "owner": "9PacVenjPyQYiWBha89UYRM1nn6mf9bGY7vi32zY6DLn" + }, + "supply": null, + "mutable": true, + "burnt": false + } +] diff --git a/integration_tests/tests/integration_tests/snapshots/integration_tests__regular_nft_tests__reg_get_asset_by_group.snap b/integration_tests/tests/integration_tests/snapshots/integration_tests__regular_nft_tests__reg_get_asset_by_group.snap new file mode 100644 index 000000000..87920f33b --- /dev/null +++ b/integration_tests/tests/integration_tests/snapshots/integration_tests__regular_nft_tests__reg_get_asset_by_group.snap @@ -0,0 +1,85 @@ +--- +source: integration_tests/tests/integration_tests/regular_nft_tests.rs +expression: response +--- +{ + "total": 1, + "limit": 1, + "page": 1, + "items": [ + { + "interface": "ProgrammableNFT", + "id": "7jFuJ73mBPDdLMvCYxzrpFTD9FeDudRxdXGDALP5Cp2W", + "content": { + "$schema": "https://schema.metaplex.com/nft1.0.json", + "json_uri": "https://nftstorage.link/ipfs/bafybeidbjja4gycfx2ywaicfpdv2czog6qp75zasluknexukidqgnzby3y/5517.json", + "files": [], + "metadata": { + "name": "SMB Gen3 #5518", + "symbol": "", + "token_standard": "ProgrammableNonFungible" + }, + "links": {} + }, + "authorities": [ + { + "address": "GfELr1GA9bLmgiMymUm7h8nDkZLG2Ls6txSsANopeVEW", + "scopes": [ + "full" + ] + } + ], + "compression": { + "eligible": false, + "compressed": false, + "data_hash": "", + "creator_hash": "", + "asset_hash": "", + "tree": "", + "seq": 0, + "leaf_id": 0 + }, + "grouping": [ + { + "group_key": "collection", + "group_value": "8Rt3Ayqth4DAiPnW9MDFi63TiQJHmohfTWLMQFHi4KZH" + } + ], + "royalty": { + "royalty_model": "creators", + "target": null, + "percent": 0.05, + "basis_points": 500, + "primary_sale_happened": true, + "locked": false + }, + "creators": [ + { + "address": "HV4Nvm9zHfNA43JYYkjZu8vwqiuE8bfEhwcKFfyQ65o5", + "share": 0, + "verified": true + }, + { + "address": "smbBn7Votkw2upiVZtX9WgkmC7fNW2QabfVFuPLhu3C", + "share": 0, + "verified": false + }, + { + "address": "HqqiyJcm3yWPyzwisRKAQa2bJAj14V837yJRGaxwRFaG", + "share": 100, + "verified": false + } + ], + "ownership": { + "frozen": true, + "delegated": false, + "delegate": null, + "ownership_model": "single", + "owner": "9qUcfdADyrrTSetFjNjF9Ro7LKAqzJkzZV6WKLHfv5MU" + }, + "supply": null, + "mutable": true, + "burnt": false + } + ] +} diff --git a/integration_tests/tests/integration_tests/snapshots/integration_tests__regular_nft_tests__reg_search_assets.snap b/integration_tests/tests/integration_tests/snapshots/integration_tests__regular_nft_tests__reg_search_assets.snap new file mode 100644 index 000000000..bd321f698 --- /dev/null +++ b/integration_tests/tests/integration_tests/snapshots/integration_tests__regular_nft_tests__reg_search_assets.snap @@ -0,0 +1,80 @@ +--- +source: integration_tests/tests/integration_tests/regular_nft_tests.rs +expression: response +--- +{ + "total": 1, + "limit": 2, + "page": 1, + "items": [ + { + "interface": "ProgrammableNFT", + "id": "Dt3XDSAdXAJbHqvuycgCTHykKCC7tntMFGMmSvfBbpTL", + "content": { + "$schema": "https://schema.metaplex.com/nft1.0.json", + "json_uri": "https://arweave.net/3EM4n3RvYwji7FqwqZ5FX2ULDsLMV5R_AXXlNcI5ls4", + "files": [], + "metadata": { + "name": "Claynosaurz: Call of Saga #1887", + "symbol": "DINO", + "token_standard": "ProgrammableNonFungible" + }, + "links": {} + }, + "authorities": [ + { + "address": "G2R7KKR9aycrMDzR2EK2Cs69f2NNBRK8AZUuaohQBg2r", + "scopes": [ + "full" + ] + } + ], + "compression": { + "eligible": false, + "compressed": false, + "data_hash": "", + "creator_hash": "", + "asset_hash": "", + "tree": "", + "seq": 0, + "leaf_id": 0 + }, + "grouping": [ + { + "group_key": "collection", + "group_value": "1yPMtWU5aqcF72RdyRD5yipmcMRC8NGNK59NvYubLkZ" + } + ], + "royalty": { + "royalty_model": "creators", + "target": null, + "percent": 0.05, + "basis_points": 500, + "primary_sale_happened": true, + "locked": false + }, + "creators": [ + { + "address": "47besT5AjYkf8bdtzxt7k8rZbKr612Z3cayEx2wHCtLn", + "share": 0, + "verified": true + }, + { + "address": "36tfiBtaDGjAMKd6smPacHQhe4MXycLL6f9ww9CD1naT", + "share": 100, + "verified": false + } + ], + "ownership": { + "frozen": true, + "delegated": false, + "delegate": null, + "ownership_model": "single", + "owner": "6Cr66AabRYymhZgYQSfTCo6FVpH18wXrMZswAbcErpyX" + }, + "supply": null, + "mutable": true, + "burnt": false + } + ] +} diff --git a/migration/src/lib.rs b/migration/src/lib.rs index f3b1752b6..9f26c51a4 100644 --- a/migration/src/lib.rs +++ b/migration/src/lib.rs @@ -36,6 +36,8 @@ mod m20240104_203133_add_cl_audits_v2; mod m20240104_203328_remove_cl_audits; mod m20240116_130744_add_update_metadata_ix; mod m20240117_120101_alter_creator_indices; +mod m20240124_173104_add_tree_seq_index_to_cl_audits_v2; +mod m20240124_181900_add_slot_updated_column_per_update_type; pub mod model; @@ -81,6 +83,8 @@ impl MigratorTrait for Migrator { Box::new(m20240104_203328_remove_cl_audits::Migration), Box::new(m20240116_130744_add_update_metadata_ix::Migration), Box::new(m20240117_120101_alter_creator_indices::Migration), + Box::new(m20240124_173104_add_tree_seq_index_to_cl_audits_v2::Migration), + Box::new(m20240124_181900_add_slot_updated_column_per_update_type::Migration), ] } } diff --git a/migration/src/m20240124_173104_add_tree_seq_index_to_cl_audits_v2.rs b/migration/src/m20240124_173104_add_tree_seq_index_to_cl_audits_v2.rs new file mode 100644 index 000000000..959f87c95 --- /dev/null +++ b/migration/src/m20240124_173104_add_tree_seq_index_to_cl_audits_v2.rs @@ -0,0 +1,35 @@ +use super::model::table::ClAuditsV2; +use sea_orm::{ConnectionTrait, DatabaseBackend, Statement}; +use sea_orm_migration::prelude::*; + +#[derive(DeriveMigrationName)] +pub struct Migration; + +#[async_trait::async_trait] +impl MigrationTrait for Migration { + async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> { + let conn = manager.get_connection(); + + conn.execute(Statement::from_string( + DatabaseBackend::Postgres, + "CREATE INDEX CONCURRENTLY IF NOT EXISTS tree_seq_idx ON cl_audits_v2 (tree, seq);" + .to_string(), + )) + .await?; + + Ok(()) + } + + async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> { + manager + .drop_index( + Index::drop() + .name("tree_seq_idx") + .table(ClAuditsV2::Table) + .to_owned(), + ) + .await?; + + Ok(()) + } +} diff --git a/migration/src/m20240124_181900_add_slot_updated_column_per_update_type.rs b/migration/src/m20240124_181900_add_slot_updated_column_per_update_type.rs new file mode 100644 index 000000000..a742952c8 --- /dev/null +++ b/migration/src/m20240124_181900_add_slot_updated_column_per_update_type.rs @@ -0,0 +1,160 @@ +use sea_orm_migration::{ + prelude::*, + sea_orm::{ConnectionTrait, DatabaseBackend, Statement}, +}; + +use crate::model::table::Asset; + +#[derive(DeriveMigrationName)] +pub struct Migration; + +#[async_trait::async_trait] +impl MigrationTrait for Migration { + async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> { + manager + .alter_table( + Table::alter() + .table(Asset::Table) + .add_column( + ColumnDef::new(Asset::SlotUpdatedMetadataAccount) + .big_integer() + .null(), + ) + .to_owned(), + ) + .await?; + + manager + .alter_table( + Table::alter() + .table(Asset::Table) + .add_column( + ColumnDef::new(Asset::SlotUpdatedTokenAccount) + .big_integer() + .null(), + ) + .to_owned(), + ) + .await?; + + manager + .alter_table( + Table::alter() + .table(Asset::Table) + .add_column( + ColumnDef::new(Asset::SlotUpdatedMintAccount) + .big_integer() + .null(), + ) + .to_owned(), + ) + .await?; + + manager + .alter_table( + Table::alter() + .table(Asset::Table) + .add_column( + ColumnDef::new(Asset::SlotUpdatedCnftTransaction) + .big_integer() + .null(), + ) + .to_owned(), + ) + .await?; + + let connection = manager.get_connection(); + connection + .execute(Statement::from_string( + DatabaseBackend::Postgres, + " + CREATE OR REPLACE FUNCTION update_slot_updated() + RETURNS TRIGGER AS $$ + BEGIN + NEW.slot_updated = GREATEST(NEW.slot_updated_token_account, NEW.slot_updated_mint_account, NEW.slot_updated_metadata_account, NEW.slot_updated_cnft_transaction); + RETURN NEW; + END; + $$ language 'plpgsql'; + " + .to_string(), + )) + .await?; + + connection + .execute(Statement::from_string( + DatabaseBackend::Postgres, + " + CREATE TRIGGER update_slot_updated_trigger + BEFORE UPDATE ON asset + FOR EACH ROW + EXECUTE PROCEDURE update_slot_updated(); + " + .to_string(), + )) + .await?; + + Ok(()) + } + + async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> { + manager + .alter_table( + Table::alter() + .table(Asset::Table) + .drop_column(Asset::SlotUpdatedMetadataAccount) + .to_owned(), + ) + .await?; + + manager + .alter_table( + Table::alter() + .table(Asset::Table) + .drop_column(Asset::SlotUpdatedTokenAccount) + .to_owned(), + ) + .await?; + + manager + .alter_table( + Table::alter() + .table(Asset::Table) + .drop_column(Asset::SlotUpdatedMintAccount) + .to_owned(), + ) + .await?; + + manager + .alter_table( + Table::alter() + .table(Asset::Table) + .drop_column(Asset::SlotUpdatedCnftTransaction) + .to_owned(), + ) + .await?; + + let connection = manager.get_connection(); + + connection + .execute(Statement::from_string( + DatabaseBackend::Postgres, + " + DROP TRIGGER IF EXISTS update_slot_updated_trigger ON asset; + " + .to_string(), + )) + .await?; + + connection + .execute(Statement::from_string( + DatabaseBackend::Postgres, + " + DROP FUNCTION IF EXISTS update_slot_updated(); + " + .to_string(), + )) + .await?; + + Ok(()) + } +} diff --git a/migration/src/model/table.rs b/migration/src/model/table.rs index a77e4abc0..bfa3da61c 100644 --- a/migration/src/model/table.rs +++ b/migration/src/model/table.rs @@ -74,6 +74,10 @@ pub enum Asset { CreatedAt, Burnt, SlotUpdated, + SlotUpdatedMetadataAccount, + SlotUpdatedMintAccount, + SlotUpdatedTokenAccount, + SlotUpdatedCnftTransaction, DataHash, CreatorHash, OwnerDelegateSeq, diff --git a/nft_ingester/src/config.rs b/nft_ingester/src/config.rs index 9fd89285a..ab1f3cd38 100644 --- a/nft_ingester/src/config.rs +++ b/nft_ingester/src/config.rs @@ -15,7 +15,7 @@ use tracing_subscriber::fmt; use crate::{error::IngesterError, tasks::BackgroundTaskRunnerConfig}; -#[derive(Deserialize, PartialEq, Debug, Clone)] +#[derive(Deserialize, PartialEq, Debug, Clone, Default)] pub struct IngesterConfig { pub database_config: DatabaseConfig, pub messenger_config: MessengerConfig, diff --git a/nft_ingester/src/program_transformers/asset_upserts.rs b/nft_ingester/src/program_transformers/asset_upserts.rs new file mode 100644 index 000000000..8bf172ec0 --- /dev/null +++ b/nft_ingester/src/program_transformers/asset_upserts.rs @@ -0,0 +1,154 @@ +use digital_asset_types::dao::{ + asset, + sea_orm_active_enums::{ + OwnerType, RoyaltyTargetType, SpecificationAssetClass, SpecificationVersions, + }, +}; +use sea_orm::{ + sea_query::OnConflict, ConnectionTrait, DbBackend, DbErr, EntityTrait, QueryTrait, Set, + TransactionTrait, +}; + +pub struct AssetTokenAccountColumns { + pub mint: Vec, + pub owner: Option>, + pub frozen: bool, + pub delegate: Option>, + pub slot_updated_token_account: Option, +} + +pub async fn upsert_assets_token_account_columns( + columns: AssetTokenAccountColumns, + txn_or_conn: &T, +) -> Result<(), DbErr> { + let active_model = asset::ActiveModel { + id: Set(columns.mint), + owner: Set(columns.owner), + frozen: Set(columns.frozen), + delegate: Set(columns.delegate), + slot_updated_token_account: Set(columns.slot_updated_token_account), + ..Default::default() + }; + let mut query = asset::Entity::insert(active_model) + .on_conflict( + OnConflict::columns([asset::Column::Id]) + .update_columns([ + asset::Column::Owner, + asset::Column::Frozen, + asset::Column::Delegate, + asset::Column::SlotUpdatedTokenAccount, + ]) + .to_owned(), + ) + .build(DbBackend::Postgres); + + query.sql = format!( + "{} WHERE excluded.slot_updated_token_account >= asset.slot_updated_token_account OR asset.slot_updated_token_account IS NULL", + query.sql); + txn_or_conn.execute(query).await?; + Ok(()) +} + +pub struct AssetMintAccountColumns { + pub mint: Vec, + pub supply: u64, + pub suppply_mint: Option>, + pub slot_updated_mint_account: u64, +} + +pub async fn upsert_assets_mint_account_columns( + columns: AssetMintAccountColumns, + txn_or_conn: &T, +) -> Result<(), DbErr> { + let active_model = asset::ActiveModel { + id: Set(columns.mint), + supply: Set(columns.supply as i64), + supply_mint: Set(columns.suppply_mint), + slot_updated_mint_account: Set(Some(columns.slot_updated_mint_account as i64)), + ..Default::default() + }; + let mut query = asset::Entity::insert(active_model) + .on_conflict( + OnConflict::columns([asset::Column::Id]) + .update_columns([ + asset::Column::Supply, + asset::Column::SupplyMint, + asset::Column::SlotUpdatedMintAccount, + ]) + .to_owned(), + ) + .build(DbBackend::Postgres); + + query.sql = format!( + "{} WHERE excluded.slot_updated_mint_account >= asset.slot_updated_mint_account OR asset.slot_updated_mint_account IS NULL", + query.sql); + txn_or_conn.execute(query).await?; + Ok(()) +} + +pub struct AssetMetadataAccountColumns { + pub mint: Vec, + pub owner_type: OwnerType, + pub specification_asset_class: Option, + pub royalty_amount: i32, + pub asset_data: Option>, + pub slot_updated_metadata_account: u64, +} + +pub async fn upsert_assets_metadata_account_columns( + columns: AssetMetadataAccountColumns, + txn_or_conn: &T, +) -> Result<(), DbErr> { + let active_model = asset::ActiveModel { + id: Set(columns.mint), + owner_type: Set(columns.owner_type), + specification_version: Set(Some(SpecificationVersions::V1)), + specification_asset_class: Set(columns.specification_asset_class), + tree_id: Set(None), + nonce: Set(Some(0)), + seq: Set(Some(0)), + leaf: Set(None), + data_hash: Set(None), + creator_hash: Set(None), + compressed: Set(false), + compressible: Set(false), + royalty_target_type: Set(RoyaltyTargetType::Creators), + royalty_target: Set(None), + royalty_amount: Set(columns.royalty_amount), + asset_data: Set(columns.asset_data), + slot_updated_metadata_account: Set(Some(columns.slot_updated_metadata_account as i64)), + burnt: Set(false), + ..Default::default() + }; + let mut query = asset::Entity::insert(active_model) + .on_conflict( + OnConflict::columns([asset::Column::Id]) + .update_columns([ + asset::Column::OwnerType, + asset::Column::SpecificationVersion, + asset::Column::SpecificationAssetClass, + asset::Column::TreeId, + asset::Column::Nonce, + asset::Column::Seq, + asset::Column::Leaf, + asset::Column::DataHash, + asset::Column::CreatorHash, + asset::Column::Compressed, + asset::Column::Compressible, + asset::Column::RoyaltyTargetType, + asset::Column::RoyaltyTarget, + asset::Column::RoyaltyAmount, + asset::Column::AssetData, + asset::Column::SlotUpdatedMetadataAccount, + asset::Column::Burnt, + ]) + .to_owned(), + ) + .build(DbBackend::Postgres); + + query.sql = format!( + "{} WHERE excluded.slot_updated_metadata_account >= asset.slot_updated_metadata_account OR asset.slot_updated_metadata_account IS NULL", + query.sql); + txn_or_conn.execute(query).await?; + Ok(()) +} diff --git a/nft_ingester/src/program_transformers/bubblegum/db.rs b/nft_ingester/src/program_transformers/bubblegum/db.rs index 7e5aafc83..1d3efadc5 100644 --- a/nft_ingester/src/program_transformers/bubblegum/db.rs +++ b/nft_ingester/src/program_transformers/bubblegum/db.rs @@ -2,7 +2,6 @@ use crate::error::IngesterError; use digital_asset_types::dao::{ asset, asset_authority, asset_creators, asset_data, asset_grouping, backfill_items, cl_audits_v2, cl_items, - extensions::instruction::PascalCase, sea_orm_active_enums::{ ChainMutability, Instruction, Mutability, OwnerType, RoyaltyTargetType, SpecificationAssetClass, SpecificationVersions, @@ -14,7 +13,6 @@ use sea_orm::{ query::*, sea_query::OnConflict, ActiveValue::Set, ColumnTrait, DbBackend, EntityTrait, }; use spl_account_compression::events::ChangeLogEventV1; -use std::collections::HashSet; pub async fn save_changelog_event<'c, T>( change_log_event: &ChangeLogEventV1, @@ -485,7 +483,7 @@ where royalty_target: Set(royalty_target), royalty_amount: Set(royalty_amount), asset_data: Set(Some(id.clone())), - slot_updated: Set(Some(slot_updated)), + slot_updated_cnft_transaction: Set(Some(slot_updated)), base_info_seq: Set(Some(seq)), ..Default::default() }; @@ -503,7 +501,7 @@ where asset::Column::RoyaltyTarget, asset::Column::RoyaltyAmount, asset::Column::AssetData, - asset::Column::SlotUpdated, + asset::Column::SlotUpdatedCnftTransaction, asset::Column::BaseInfoSeq, ]) .to_owned(), diff --git a/nft_ingester/src/program_transformers/bubblegum/mint_v1.rs b/nft_ingester/src/program_transformers/bubblegum/mint_v1.rs index 25a69d472..5ea330cd8 100644 --- a/nft_ingester/src/program_transformers/bubblegum/mint_v1.rs +++ b/nft_ingester/src/program_transformers/bubblegum/mint_v1.rs @@ -1,17 +1,17 @@ use crate::{ error::IngesterError, program_transformers::bubblegum::{ - save_changelog_event, upsert_asset_authority, upsert_asset_base_info, - upsert_asset_creators, upsert_asset_data, upsert_asset_with_compression_info, - upsert_asset_with_leaf_info, upsert_asset_with_owner_and_delegate_info, - upsert_asset_with_seq, upsert_collection_info, + bgum_use_method_to_token_metadata_use_method, save_changelog_event, upsert_asset_authority, + upsert_asset_base_info, upsert_asset_creators, upsert_asset_data, + upsert_asset_with_compression_info, upsert_asset_with_leaf_info, + upsert_asset_with_owner_and_delegate_info, upsert_asset_with_seq, upsert_collection_info, }, tasks::{DownloadMetadata, IntoTaskData, TaskData}, }; use blockbuster::{ instruction::InstructionBundle, programs::bubblegum::{BubblegumInstruction, LeafSchema, Payload}, - token_metadata::state::{TokenStandard, UseMethod, Uses}, + token_metadata::types::{TokenStandard, Uses}, }; use chrono::Utc; use digital_asset_types::{ @@ -22,7 +22,6 @@ use digital_asset_types::{ json::ChainDataV1, }; use log::warn; -use num_traits::FromPrimitive; use sea_orm::{query::*, ConnectionTrait, JsonValue}; pub async fn mint_v1<'c, T>( @@ -72,7 +71,7 @@ where primary_sale_happened: metadata.primary_sale_happened, token_standard: Some(TokenStandard::NonFungible), uses: metadata.uses.clone().map(|u| Uses { - use_method: UseMethod::from_u8(u.use_method as u8).unwrap(), + use_method: bgum_use_method_to_token_metadata_use_method(u.use_method), remaining: u.remaining, total: u.total, }), diff --git a/nft_ingester/src/program_transformers/bubblegum/mod.rs b/nft_ingester/src/program_transformers/bubblegum/mod.rs index 4a4484f12..8e1522072 100644 --- a/nft_ingester/src/program_transformers/bubblegum/mod.rs +++ b/nft_ingester/src/program_transformers/bubblegum/mod.rs @@ -1,7 +1,8 @@ use blockbuster::{ self, instruction::InstructionBundle, - programs::bubblegum::{BubblegumInstruction, InstructionName}, + programs::bubblegum::{BubblegumInstruction, InstructionName, UseMethod as BubblegumUseMethod}, + token_metadata::types::UseMethod as TokenMetadataUseMethod, }; use log::{debug, info}; use sea_orm::{ConnectionTrait, TransactionTrait}; @@ -115,3 +116,13 @@ fn u32_to_u8_array(value: u32) -> [u8; 8] { result[..4].copy_from_slice(&bytes); result } + +const fn bgum_use_method_to_token_metadata_use_method( + bubblegum_use_method: BubblegumUseMethod, +) -> TokenMetadataUseMethod { + match bubblegum_use_method { + BubblegumUseMethod::Burn => TokenMetadataUseMethod::Burn, + BubblegumUseMethod::Multiple => TokenMetadataUseMethod::Multiple, + BubblegumUseMethod::Single => TokenMetadataUseMethod::Single, + } +} diff --git a/nft_ingester/src/program_transformers/bubblegum/update_metadata.rs b/nft_ingester/src/program_transformers/bubblegum/update_metadata.rs index 54f1b87e0..586a0a18d 100644 --- a/nft_ingester/src/program_transformers/bubblegum/update_metadata.rs +++ b/nft_ingester/src/program_transformers/bubblegum/update_metadata.rs @@ -1,15 +1,16 @@ use crate::{ error::IngesterError, program_transformers::bubblegum::{ - save_changelog_event, upsert_asset_base_info, upsert_asset_creators, upsert_asset_data, - upsert_asset_with_leaf_info, upsert_asset_with_seq, + bgum_use_method_to_token_metadata_use_method, save_changelog_event, upsert_asset_base_info, + upsert_asset_creators, upsert_asset_data, upsert_asset_with_leaf_info, + upsert_asset_with_seq, }, tasks::{DownloadMetadata, IntoTaskData, TaskData}, }; use blockbuster::{ instruction::InstructionBundle, programs::bubblegum::{BubblegumInstruction, LeafSchema, Payload}, - token_metadata::state::{TokenStandard, UseMethod, Uses}, + token_metadata::types::{TokenStandard, Uses}, }; use chrono::Utc; use digital_asset_types::{ @@ -20,7 +21,6 @@ use digital_asset_types::{ json::ChainDataV1, }; use log::warn; -use num_traits::FromPrimitive; use sea_orm::{query::*, ConnectionTrait, JsonValue}; pub async fn update_metadata<'c, T>( @@ -60,11 +60,6 @@ where } else { current_metadata.uri.replace('\0', "") }; - if uri.is_empty() { - return Err(IngesterError::DeserializationError( - "URI is empty".to_string(), - )); - } let name = if let Some(name) = update_args.name.clone() { name @@ -92,7 +87,7 @@ where primary_sale_happened, token_standard: Some(TokenStandard::NonFungible), uses: current_metadata.uses.clone().map(|u| Uses { - use_method: UseMethod::from_u8(u.use_method as u8).unwrap(), + use_method: bgum_use_method_to_token_metadata_use_method(u.use_method), remaining: u.remaining, total: u.total, }), diff --git a/nft_ingester/src/program_transformers/mod.rs b/nft_ingester/src/program_transformers/mod.rs index 14e262b0f..7d68c358d 100644 --- a/nft_ingester/src/program_transformers/mod.rs +++ b/nft_ingester/src/program_transformers/mod.rs @@ -20,6 +20,7 @@ use crate::program_transformers::{ token_metadata::handle_token_metadata_account, }; +mod asset_upserts; mod bubblegum; mod token; mod token_metadata; diff --git a/nft_ingester/src/program_transformers/token/mod.rs b/nft_ingester/src/program_transformers/token/mod.rs index 12589dc5e..a8b9fd964 100644 --- a/nft_ingester/src/program_transformers/token/mod.rs +++ b/nft_ingester/src/program_transformers/token/mod.rs @@ -10,6 +10,11 @@ use solana_sdk::program_option::COption; use spl_token::state::AccountState; use tokio::sync::mpsc::UnboundedSender; +use super::asset_upserts::{ + upsert_assets_mint_account_columns, upsert_assets_token_account_columns, + AssetMintAccountColumns, AssetTokenAccountColumns, +}; + pub async fn handle_token_program_account<'a, 'b, 'c>( account_update: &'a AccountInfo<'a>, parsing_result: &'b TokenProgramAccount, @@ -64,20 +69,26 @@ pub async fn handle_token_program_account<'a, 'b, 'c>( ); db.execute(query).await?; let txn = db.begin().await?; - let asset_update: Option = asset::Entity::find_by_id(mint) + let asset_update: Option = asset::Entity::find_by_id(mint.clone()) .filter(asset::Column::OwnerType.eq("single")) .one(&txn) .await?; - if let Some(asset) = asset_update { + if let Some(_asset) = asset_update { // will only update owner if token account balance is non-zero // since the asset is marked as single then the token account balance can only be 1. Greater implies a fungible token in which case no si // TODO: this does not guarantee in case when wallet receives an amount of 1 for a token but its supply is more. is unlikely since mints often have a decimal if ta.amount == 1 { - let mut active: asset::ActiveModel = asset.into(); - active.owner = Set(Some(owner)); - active.delegate = Set(delegate); - active.frozen = Set(frozen); - active.save(&txn).await?; + upsert_assets_token_account_columns( + AssetTokenAccountColumns { + mint: mint.clone(), + owner: Some(owner.clone()), + frozen, + delegate, + slot_updated_token_account: Some(account_update.slot() as i64), + }, + &txn, + ) + .await?; } } txn.commit().await?; @@ -136,21 +147,17 @@ pub async fn handle_token_program_account<'a, 'b, 'c>( ) .one(db) .await?; - if let Some(asset) = asset_update { - let mut active: asset::ActiveModel = asset.clone().into(); - active.supply = Set(m.supply as i64); - active.supply_mint = Set(Some(key_bytes)); - - // Update owner_type based on the supply. - if asset.owner_type == OwnerType::Unknown { - active.owner_type = match m.supply.cmp(&1) { - std::cmp::Ordering::Equal => Set(OwnerType::Single), - std::cmp::Ordering::Greater => Set(OwnerType::Token), - _ => NotSet, - } - } - - active.save(db).await?; + if let Some(_asset) = asset_update { + upsert_assets_mint_account_columns( + AssetMintAccountColumns { + mint: key_bytes.clone(), + suppply_mint: Some(key_bytes), + supply: m.supply, + slot_updated_mint_account: account_update.slot(), + }, + db, + ) + .await?; } Ok(()) diff --git a/nft_ingester/src/program_transformers/token_metadata/master_edition.rs b/nft_ingester/src/program_transformers/token_metadata/master_edition.rs index ebb3ad942..063703993 100644 --- a/nft_ingester/src/program_transformers/token_metadata/master_edition.rs +++ b/nft_ingester/src/program_transformers/token_metadata/master_edition.rs @@ -1,5 +1,8 @@ use crate::error::IngesterError; -use blockbuster::token_metadata::state::{Key, MasterEditionV1, MasterEditionV2}; +use blockbuster::token_metadata::{ + accounts::{DeprecatedMasterEditionV1, MasterEdition}, + types::Key, +}; use digital_asset_types::dao::{ asset, asset_v1_account_attachments, extensions, sea_orm_active_enums::{SpecificationAssetClass, V1AccountAttachments}, @@ -13,7 +16,7 @@ use sea_orm::{ pub async fn save_v2_master_edition( id: FBPubkey, slot: u64, - me_data: &MasterEditionV2, + me_data: &MasterEdition, txn: &DatabaseTransaction, ) -> Result<(), IngesterError> { save_master_edition( @@ -29,13 +32,15 @@ pub async fn save_v2_master_edition( pub async fn save_v1_master_edition( id: FBPubkey, slot: u64, - me_data: &MasterEditionV1, + me_data: &DeprecatedMasterEditionV1, txn: &DatabaseTransaction, ) -> Result<(), IngesterError> { - let bridge = MasterEditionV2 { + // This discards the deprecated `MasterEditionV1` fields + // but sets the `Key`` as `MasterEditionV1`. + let bridge = MasterEdition { supply: me_data.supply, max_supply: me_data.max_supply, - key: Key::MasterEditionV1, // is this weird? + key: Key::MasterEditionV1, }; save_master_edition( V1AccountAttachments::MasterEditionV1, @@ -47,10 +52,10 @@ pub async fn save_v1_master_edition( .await } pub async fn save_master_edition( - _version: V1AccountAttachments, + version: V1AccountAttachments, id: FBPubkey, slot: u64, - me_data: &MasterEditionV2, + me_data: &MasterEdition, txn: &DatabaseTransaction, ) -> Result<(), IngesterError> { let id_bytes = id.0.to_vec(); @@ -68,7 +73,7 @@ pub async fn save_master_edition( let model = asset_v1_account_attachments::ActiveModel { id: Set(id_bytes), - attachment_type: Set(V1AccountAttachments::MasterEditionV1), + attachment_type: Set(version), data: Set(Some(ser)), slot_updated: Set(slot as i64), ..Default::default() diff --git a/nft_ingester/src/program_transformers/token_metadata/v1_asset.rs b/nft_ingester/src/program_transformers/token_metadata/v1_asset.rs index 8533c8949..2ed3cbec8 100644 --- a/nft_ingester/src/program_transformers/token_metadata/v1_asset.rs +++ b/nft_ingester/src/program_transformers/token_metadata/v1_asset.rs @@ -1,8 +1,13 @@ +use crate::program_transformers::asset_upserts::{ + upsert_assets_metadata_account_columns, upsert_assets_mint_account_columns, + upsert_assets_token_account_columns, AssetMetadataAccountColumns, AssetMintAccountColumns, + AssetTokenAccountColumns, +}; use crate::tasks::{DownloadMetadata, IntoTaskData}; use crate::{error::IngesterError, metric, tasks::TaskData}; use blockbuster::token_metadata::{ - pda::find_master_edition_account, - state::{Metadata, TokenStandard, UseMethod, Uses}, + accounts::{MasterEdition, Metadata}, + types::TokenStandard, }; use cadence_macros::{is_global_default_set, statsd_count}; use chrono::Utc; @@ -11,8 +16,8 @@ use digital_asset_types::{ dao::{ asset, asset_creators, asset_v1_account_attachments, sea_orm_active_enums::{ - ChainMutability, Mutability, OwnerType, RoyaltyTargetType, SpecificationAssetClass, - SpecificationVersions, V1AccountAttachments, + ChainMutability, Mutability, OwnerType, SpecificationAssetClass, SpecificationVersions, + V1AccountAttachments, }, tokens, }, @@ -20,14 +25,12 @@ use digital_asset_types::{ }; use lazy_static::lazy_static; use log::warn; -use num_traits::FromPrimitive; use plerkle_serialization::Pubkey as FBPubkey; use sea_orm::{ entity::*, query::*, sea_query::OnConflict, ActiveValue::Set, ConnectionTrait, DbBackend, DbErr, EntityTrait, JsonValue, }; use solana_sdk::pubkey::Pubkey; -use std::collections::HashSet; use std::str::FromStr; use std::time::Duration; use tokio::time::sleep; @@ -67,22 +70,99 @@ lazy_static! { Pubkey::from_str(WSOL_ADDRESS).expect("Invalid public key format"); } +pub async fn index_and_fetch_mint_data( + conn: &T, + mint_pubkey_vec: Vec, +) -> Result, IngesterError> { + // Gets the token and token account for the mint to populate the asset. + // This is required when the token and token account are indexed, but not the metadata account. + // If the metadata account is indexed, then the token and ta ingester will update the asset with the correct data. + let token: Option = find_model_with_retry( + conn, + "token", + &tokens::Entity::find_by_id(mint_pubkey_vec.clone()), + RETRY_INTERVALS, + ) + .await?; + + if let Some(token) = token { + upsert_assets_mint_account_columns( + AssetMintAccountColumns { + mint: mint_pubkey_vec.clone(), + suppply_mint: Some(token.mint.clone()), + supply: token.supply as u64, + slot_updated_mint_account: token.slot_updated as u64, + }, + conn, + ) + .await + .map_err(|db_err| IngesterError::AssetIndexError(db_err.to_string()))?; + Ok(Some(token)) + } else { + warn!( + target: "Mint not found", + "Mint not found in 'tokens' table for mint {}", + bs58::encode(&mint_pubkey_vec).into_string() + ); + Ok(None) + } +} + +async fn index_token_account_data( + conn: &T, + mint_pubkey_vec: Vec, +) -> Result<(), IngesterError> { + let token_account: Option = find_model_with_retry( + conn, + "owners", + &token_accounts::Entity::find() + .filter(token_accounts::Column::Mint.eq(mint_pubkey_vec.clone())) + .filter(token_accounts::Column::Amount.gt(0)) + .order_by(token_accounts::Column::SlotUpdated, Order::Desc), + RETRY_INTERVALS, + ) + .await + .map_err(|e: DbErr| IngesterError::DatabaseError(e.to_string()))?; + + if let Some(token_account) = token_account { + upsert_assets_token_account_columns( + AssetTokenAccountColumns { + mint: mint_pubkey_vec.clone(), + owner: Some(token_account.owner), + delegate: token_account.delegate, + frozen: token_account.frozen, + slot_updated_token_account: Some(token_account.slot_updated), + }, + conn, + ) + .await + .map_err(|db_err| IngesterError::AssetIndexError(db_err.to_string()))?; + } else { + warn!( + target: "Account not found", + "Token acc not found in 'owners' table for mint {}", + bs58::encode(&mint_pubkey_vec).into_string() + ); + } + + Ok(()) +} + pub async fn save_v1_asset( conn: &T, metadata: &Metadata, slot: u64, ) -> Result, IngesterError> { let metadata = metadata.clone(); - let data = metadata.data; let mint_pubkey = metadata.mint; let mint_pubkey_array = mint_pubkey.to_bytes(); let mint_pubkey_vec = mint_pubkey_array.to_vec(); - let (edition_attachment_address, _) = find_master_edition_account(&mint_pubkey); + let (edition_attachment_address, _) = MasterEdition::find_pda(&mint_pubkey); let authority = metadata.update_authority.to_bytes().to_vec(); let slot_i = slot as i64; - let uri = data.uri.trim().replace('\0', ""); + let uri = metadata.uri.trim().replace('\0', ""); let _spec = SpecificationVersions::V1; let mut class = match metadata.token_standard { Some(TokenStandard::NonFungible) => SpecificationAssetClass::Nft, @@ -111,29 +191,11 @@ pub async fn save_v1_asset( class = SpecificationAssetClass::FungibleToken; } - // Gets the token and token account for the mint to populate the asset. - // This is required when the token and token account are indexed, but not the metadata account. - // If the metadata account is indexed, then the token and ta ingester will update the asset with the correct data. - let token: Option = find_model_with_retry( - conn, - "token", - &tokens::Entity::find_by_id(mint_pubkey_vec.clone()), - RETRY_INTERVALS, - ) - .await?; + let token: Option = + index_and_fetch_mint_data(conn, mint_pubkey_vec.clone()).await?; // get supply of token, default to 1 since most cases will be NFTs. Token mint ingester will properly set supply if token_result is None - let (supply, supply_mint) = match token { - Some(t) => (t.supply, Some(t.mint)), - None => { - warn!( - target: "Account not found", - "Token/Mint not found in 'tokens' table for mint {}", - bs58::encode(&mint_pubkey_vec).into_string() - ); - (1, None) - } - }; + let supply = token.map(|t| t.supply).unwrap_or(1); // Map unknown ownership types based on the supply. if ownership_type == OwnerType::Unknown { @@ -141,57 +203,22 @@ pub async fn save_v1_asset( std::cmp::Ordering::Equal => OwnerType::Single, std::cmp::Ordering::Greater => OwnerType::Token, _ => OwnerType::Unknown, - } - } - - let token_account: Option = match ownership_type { - OwnerType::Single | OwnerType::Unknown => { - // query for token account associated with mint with positive balance with latest slot - let token_account: Option = find_model_with_retry( - conn, - "token_accounts", - &token_accounts::Entity::find() - .filter(token_accounts::Column::Mint.eq(mint_pubkey_vec.clone())) - .filter(token_accounts::Column::Amount.gt(0)) - .order_by(token_accounts::Column::SlotUpdated, Order::Desc), - RETRY_INTERVALS, - ) - .await - .map_err(|e: DbErr| IngesterError::DatabaseError(e.to_string()))?; - - token_account - } - _ => None, + }; }; - // owner and delegate should be from the token account with the mint - let (owner, delegate) = match token_account { - Some(ta) => (Set(Some(ta.owner)), Set(ta.delegate)), - None => { - if supply == 1 && ownership_type == OwnerType::Single { - warn!( - target: "Account not found", - "Token acc not found in 'token_accounts' table for mint {}", - bs58::encode(&mint_pubkey_vec).into_string() - ); - } - (NotSet, NotSet) - } - }; + if (ownership_type == OwnerType::Single) | (ownership_type == OwnerType::Unknown) { + index_token_account_data(conn, mint_pubkey_vec.clone()).await?; + } - let name = data.name.clone().into_bytes(); - let symbol = data.symbol.clone().into_bytes(); + let name = metadata.name.clone().into_bytes(); + let symbol = metadata.symbol.clone().into_bytes(); let mut chain_data = ChainDataV1 { - name: data.name.clone(), - symbol: data.symbol.clone(), + name: metadata.name.clone(), + symbol: metadata.symbol.clone(), edition_nonce: metadata.edition_nonce, primary_sale_happened: metadata.primary_sale_happened, token_standard: metadata.token_standard, - uses: metadata.uses.map(|u| Uses { - use_method: UseMethod::from_u8(u.use_method as u8).unwrap(), - remaining: u.remaining, - total: u.total, - }), + uses: metadata.uses, }; chain_data.sanitize(); let chain_data_json = serde_json::to_value(chain_data) @@ -239,69 +266,18 @@ pub async fn save_v1_asset( .await .map_err(|db_err| IngesterError::AssetIndexError(db_err.to_string()))?; - let model = asset::ActiveModel { - id: Set(mint_pubkey_vec.clone()), - owner, - owner_type: Set(ownership_type), - delegate, - frozen: Set(false), - supply: Set(supply), - supply_mint: Set(supply_mint), - specification_version: Set(Some(SpecificationVersions::V1)), - specification_asset_class: Set(Some(class)), - tree_id: Set(None), - nonce: Set(Some(0)), - seq: Set(Some(0)), - leaf: Set(None), - data_hash: Set(None), - creator_hash: Set(None), - compressed: Set(false), - compressible: Set(false), - royalty_target_type: Set(RoyaltyTargetType::Creators), - royalty_target: Set(None), - royalty_amount: Set(data.seller_fee_basis_points as i32), //basis points - asset_data: Set(Some(mint_pubkey_vec.clone())), - slot_updated: Set(Some(slot_i)), - burnt: Set(false), - ..Default::default() - }; - let mut query = asset::Entity::insert(model) - .on_conflict( - OnConflict::columns([asset::Column::Id]) - .update_columns([ - asset::Column::Owner, - asset::Column::OwnerType, - asset::Column::Delegate, - asset::Column::Frozen, - asset::Column::Supply, - asset::Column::SupplyMint, - asset::Column::SpecificationVersion, - asset::Column::SpecificationAssetClass, - asset::Column::TreeId, - asset::Column::Nonce, - asset::Column::Seq, - asset::Column::Leaf, - asset::Column::DataHash, - asset::Column::CreatorHash, - asset::Column::Compressed, - asset::Column::Compressible, - asset::Column::RoyaltyTargetType, - asset::Column::RoyaltyTarget, - asset::Column::RoyaltyAmount, - asset::Column::AssetData, - asset::Column::SlotUpdated, - asset::Column::Burnt, - ]) - .to_owned(), - ) - .build(DbBackend::Postgres); - query.sql = format!( - "{} WHERE excluded.slot_updated >= asset.slot_updated OR asset.slot_updated IS NULL", - query.sql - ); - txn.execute(query) - .await - .map_err(|db_err| IngesterError::AssetIndexError(db_err.to_string()))?; + upsert_assets_metadata_account_columns( + AssetMetadataAccountColumns { + mint: mint_pubkey_vec.clone(), + owner_type: ownership_type, + specification_asset_class: Some(class), + royalty_amount: metadata.seller_fee_basis_points as i32, + asset_data: Some(mint_pubkey_vec.clone()), + slot_updated_metadata_account: slot_i as u64, + }, + &txn, + ) + .await?; let attachment = asset_v1_account_attachments::ActiveModel { id: Set(edition_attachment_address.to_bytes().to_vec()), @@ -380,7 +356,7 @@ pub async fn save_v1_asset( .map_err(|db_err| IngesterError::AssetIndexError(db_err.to_string()))?; } - let creators = data + let creators = metadata .creators .unwrap_or_default() .iter() diff --git a/ops/Cargo.toml b/ops/Cargo.toml new file mode 100644 index 000000000..022bf2e92 --- /dev/null +++ b/ops/Cargo.toml @@ -0,0 +1,56 @@ +[package] +name = "das-ops" +version.workspace = true +edition.workspace = true +repository.workspace = true +publish.workspace = true + +[[bin]] +name = "das-ops" + +[dependencies] + +clap = { workspace = true, features = ["derive", "cargo", "env"] } +das-core = { workspace = true } +backon = "0.4.1" +log = { workspace = true } +env_logger = { workspace = true } +anyhow = { workspace = true } +redis = { workspace = true } +futures = { workspace = true } +futures-util = { workspace = true } +base64 = { workspace = true } +indicatif = "0.17.5" +thiserror = { workspace = true } +serde_json = { workspace = true } +cadence = { workspace = true } +cadence-macros = { workspace = true } +anchor-client = { workspace = true } +tokio = { workspace = true } +sqlx = { workspace = true } +sea-orm = { workspace = true } +sea-query = { workspace = true } +chrono = { workspace = true } +tokio-postgres = { workspace = true } +serde = { workspace = true } +bs58 = { workspace = true } +reqwest = { workspace = true } +plerkle_messenger = { workspace = true } +plerkle_serialization = { workspace = true } +flatbuffers = { workspace = true } +lazy_static = { workspace = true } +regex = { workspace = true } +digital_asset_types = { workspace = true } +mpl-bubblegum = { workspace = true } +spl-account-compression = { workspace = true } +spl-concurrent-merkle-tree = { workspace = true } +uuid = { workspace = true } +figment = { workspace = true } +solana-sdk = { workspace = true } +solana-client = { workspace = true } +solana-transaction-status = { workspace = true } +solana-account-decoder = { workspace = true } +rust-crypto = { workspace = true } +url = { workspace = true } +anchor-lang = { workspace = true } +borsh = { workspace = true } diff --git a/ops/src/bubblegum/README.md b/ops/src/bubblegum/README.md new file mode 100644 index 000000000..d1dc5772b --- /dev/null +++ b/ops/src/bubblegum/README.md @@ -0,0 +1,86 @@ +# Bubblegum + +The bubblegum CLI assists in detecting and indexing missing updates for compression trees that are managed by the MPL bubblegum program. + +## Commands + +Command line arguments can also be set through environment variables. + +### Backfill + +The `backfill` command initiates the crawling and backfilling process. It requires the Solana RPC URL, the database URL, and the messenger Redis URL. + +**warning**: The command expects full archive access to transactions. Before proceeding ensure your RPC is able to serve complete transaction history for Solana. + +```mermaid +flowchart + start((Start)) -->init[Initialize RPC, DB] + init --> fetchTreesDB[Fetch Trees from DB] + fetchTreesDB --> findGapsDB[Find Gaps in DB] + findGapsDB --> enqueueGapFills[Enqueue Gap Fills] + enqueueGapFills --> gapWorkerManager[Gap Worker Manager] + gapWorkerManager --> crawlSignatures[Crawl Solana RPC] + crawlSignatures --> enqueueSignatures[Enqueue Signatures] + enqueueSignatures --> transactionWorkerManager[Transaction Worker Manager] + transactionWorkerManager --> fetchTransactionsRPC[Fetch Transactions RPC] + fetchTransactionsRPC --> processTransactions[Push Transaction to Messenger] + processTransactions ---> Finished +``` + +``` +Usage: das-ops bubblegum backfill [OPTIONS] --database-url --messenger-redis-url --solana-rpc-url + +Options: + --tree-crawler-count + Number of tree crawler workers [env: TREE_CRAWLER_COUNT=] [default: 20] + --signature-channel-size + The size of the signature channel [env: SIGNATURE_CHANNEL_SIZE=] [default: 10000] + --gap-channel-size + The size of the signature channel [env: GAP_CHANNEL_SIZE=] [default: 1000] + --transaction-worker-count + The number of transaction workers [env: TRANSACTION_WORKER_COUNT=] [default: 100] + --gap-worker-count + The number of gap workers [env: GAP_WORKER_COUNT=] [default: 25] + --only-trees + The list of trees to crawl. If not specified, all trees will be crawled [env: ONLY_TREES=] + --database-url + The database URL [env: DATABASE_URL=] + --database-max-connections + The maximum number of connections to the database [env: DATABASE_MAX_CONNECTIONS=] [default: 125] + --database-min-connections + The minimum number of connections to the database [env: DATABASE_MIN_CONNECTIONS=] [default: 5] + --messenger-redis-url + [env: MESSENGER_REDIS_URL=] + --messenger-redis-batch-size + [env: MESSENGER_REDIS_BATCH_SIZE=] [default: 100] + --messenger-queue-connections + [env: MESSENGER_QUEUE_CONNECTIONS=] [default: 25] + --messenger-queue-stream + [env: MESSENGER_QUEUE_STREAM=] [default: TXNFILL] + --metrics-host + [env: METRICS_HOST=] [default: 127.0.0.1] + --metrics-port + [env: METRICS_PORT=] [default: 8125] + --metrics-prefix + [env: METRICS_PREFIX=] [default: das.backfiller] + --solana-rpc-url + [env: SOLANA_RPC_URL=] + -h, --help + Print help +``` + +### Metrics + +The bubblegum command provides several metrics for monitoring performance and status: + +Metric | Description +--- | --- +transaction.failed | Count of failed transaction +transaction.succeeded | Count of successfully queued transaction +transaction.queued | Time for a transaction to be queued +gap.failed | Count of failed gap crawling +gap.succeeded | Count of successfully crawled gaps +gap.queued | Time for a gap to be queued +tree.succeeded | Count of completed tree crawl +tree.crawled | Time to crawl a tree +job.completed | Time to complete the job diff --git a/ops/src/bubblegum/backfiller.rs b/ops/src/bubblegum/backfiller.rs new file mode 100644 index 000000000..d6d00405e --- /dev/null +++ b/ops/src/bubblegum/backfiller.rs @@ -0,0 +1,325 @@ +use super::{ + queue::{QueueArgs, QueuePool}, + rpc::{Rpc, SolanaRpcArgs}, + tree::{TreeErrorKind, TreeGapFill, TreeGapModel, TreeResponse}, +}; +use anyhow::Result; +use cadence_macros::{statsd_count, statsd_time}; +use clap::Parser; +use das_core::{connect_db, setup_metrics, MetricsArgs, PoolArgs}; +use digital_asset_types::dao::cl_audits_v2; +use flatbuffers::FlatBufferBuilder; +use futures::{stream::FuturesUnordered, StreamExt}; +use indicatif::HumanDuration; +use log::{error, info}; +use plerkle_serialization::serializer::seralize_encoded_transaction_with_status; +use sea_orm::{ + ColumnTrait, DatabaseConnection, EntityTrait, QueryFilter, QueryOrder, SqlxPostgresConnector, +}; +use solana_sdk::signature::Signature; +use std::time::Instant; +use tokio::{sync::mpsc, task::JoinHandle}; + +#[derive(Debug, Parser, Clone)] +pub struct Args { + /// Number of tree crawler workers + #[arg(long, env, default_value = "20")] + pub tree_crawler_count: usize, + + /// The size of the signature channel. + #[arg(long, env, default_value = "10000")] + pub signature_channel_size: usize, + + /// The size of the signature channel. + #[arg(long, env, default_value = "1000")] + pub gap_channel_size: usize, + + /// The number of transaction workers. + #[arg(long, env, default_value = "100")] + pub transaction_worker_count: usize, + + /// The number of gap workers. + #[arg(long, env, default_value = "25")] + pub gap_worker_count: usize, + + /// The list of trees to crawl. If not specified, all trees will be crawled. + #[arg(long, env, use_value_delimiter = true)] + pub only_trees: Option>, + + /// Database configuration + #[clap(flatten)] + pub database: PoolArgs, + + /// Redis configuration + #[clap(flatten)] + pub queue: QueueArgs, + + /// Metrics configuration + #[clap(flatten)] + pub metrics: MetricsArgs, + + /// Solana configuration + #[clap(flatten)] + pub solana: SolanaRpcArgs, +} + +/// Runs the backfilling process for the tree crawler. +/// +/// This function initializes the necessary components for the backfilling process, +/// including database connections, RPC clients, and worker managers for handling +/// transactions and gaps. It then proceeds to fetch the trees that need to be crawled +/// and manages the crawling process across multiple workers. +/// +/// The function handles the following major tasks: +/// - Establishing connections to the database and initializing RPC clients. +/// - Setting up channels for communication between different parts of the system. +/// - Spawning worker managers for processing transactions and gaps. +/// - Fetching trees from the database and managing their crawling process. +/// - Reporting metrics and logging information throughout the process. +/// +/// # Arguments +/// +/// * `config` - A configuration object containing settings for the backfilling process, +/// including database, RPC, and worker configurations. +/// +/// # Returns +/// +/// This function returns a `Result` which is `Ok` if the backfilling process completes +/// successfully, or an `Err` with an appropriate error message if any part of the process +/// fails. +/// +/// # Errors +/// +/// This function can return errors related to database connectivity, RPC failures, +/// or issues with spawning and managing worker tasks. +pub async fn run(config: Args) -> Result<()> { + let pool = connect_db(config.database).await?; + + let solana_rpc = Rpc::from_config(config.solana); + let transaction_solana_rpc = solana_rpc.clone(); + let gap_solana_rpc = solana_rpc.clone(); + + setup_metrics(config.metrics)?; + + let (sig_sender, mut sig_receiver) = mpsc::channel::(config.signature_channel_size); + let gap_sig_sender = sig_sender.clone(); + let (gap_sender, mut gap_receiver) = mpsc::channel::(config.gap_channel_size); + + let queue = QueuePool::try_from_config(config.queue).await?; + + let transaction_worker_count = config.transaction_worker_count; + + let transaction_worker_manager = tokio::spawn(async move { + let mut handlers = FuturesUnordered::new(); + + while let Some(signature) = sig_receiver.recv().await { + if handlers.len() >= transaction_worker_count { + handlers.next().await; + } + + let solana_rpc = transaction_solana_rpc.clone(); + let queue = queue.clone(); + + let handle = spawn_transaction_worker(solana_rpc, queue, signature); + + handlers.push(handle); + } + + futures::future::join_all(handlers).await; + }); + + let gap_worker_count = config.gap_worker_count; + + let gap_worker_manager = tokio::spawn(async move { + let mut handlers = FuturesUnordered::new(); + + while let Some(gap) = gap_receiver.recv().await { + if handlers.len() >= gap_worker_count { + handlers.next().await; + } + + let client = gap_solana_rpc.clone(); + let sender = gap_sig_sender.clone(); + + let handle = spawn_crawl_worker(client, sender, gap); + + handlers.push(handle); + } + + futures::future::join_all(handlers).await; + }); + + let started = Instant::now(); + + let trees = if let Some(only_trees) = config.only_trees { + TreeResponse::find(&solana_rpc, only_trees).await? + } else { + TreeResponse::all(&solana_rpc).await? + }; + + let tree_count = trees.len(); + + info!( + "fetched {} trees in {}", + tree_count, + HumanDuration(started.elapsed()) + ); + + let tree_crawler_count = config.tree_crawler_count; + let mut crawl_handles = FuturesUnordered::new(); + + for tree in trees { + if crawl_handles.len() >= tree_crawler_count { + crawl_handles.next().await; + } + + let sender = gap_sender.clone(); + let pool = pool.clone(); + let conn = SqlxPostgresConnector::from_sqlx_postgres_pool(pool); + + let handle = spawn_gap_worker(conn, sender, tree); + + crawl_handles.push(handle); + } + + futures::future::try_join_all(crawl_handles).await?; + drop(gap_sender); + info!("crawled all trees"); + + gap_worker_manager.await?; + drop(sig_sender); + info!("all gaps processed"); + + transaction_worker_manager.await?; + info!("all transactions queued"); + + statsd_time!("job.completed", started.elapsed()); + + info!( + "crawled {} trees in {}", + tree_count, + HumanDuration(started.elapsed()) + ); + + Ok(()) +} + +fn spawn_gap_worker( + conn: DatabaseConnection, + sender: mpsc::Sender, + tree: TreeResponse, +) -> JoinHandle> { + tokio::spawn(async move { + let timing = Instant::now(); + + let mut gaps = TreeGapModel::find(&conn, tree.pubkey) + .await? + .into_iter() + .map(TryInto::try_into) + .collect::, _>>()?; + + let upper_known_seq = cl_audits_v2::Entity::find() + .filter(cl_audits_v2::Column::Tree.eq(tree.pubkey.as_ref().to_vec())) + .order_by_desc(cl_audits_v2::Column::Seq) + .one(&conn) + .await?; + + let lower_known_seq = cl_audits_v2::Entity::find() + .filter(cl_audits_v2::Column::Tree.eq(tree.pubkey.as_ref().to_vec())) + .order_by_asc(cl_audits_v2::Column::Seq) + .one(&conn) + .await?; + + if let Some(upper_seq) = upper_known_seq { + let signature = Signature::try_from(upper_seq.tx.as_ref())?; + info!( + "tree {} has known highest seq {} filling tree from {}", + tree.pubkey, upper_seq.seq, signature + ); + gaps.push(TreeGapFill::new(tree.pubkey, None, Some(signature))); + } else if tree.seq > 0 { + info!( + "tree {} has no known highest seq but the actual seq is {} filling whole tree", + tree.pubkey, tree.seq + ); + gaps.push(TreeGapFill::new(tree.pubkey, None, None)); + } + + if let Some(lower_seq) = lower_known_seq.filter(|seq| seq.seq > 1) { + let signature = Signature::try_from(lower_seq.tx.as_ref())?; + + info!( + "tree {} has known lowest seq {} filling tree starting at {}", + tree.pubkey, lower_seq.seq, signature + ); + + gaps.push(TreeGapFill::new(tree.pubkey, Some(signature), None)); + } + + let gap_count = gaps.len(); + + for gap in gaps { + if let Err(e) = sender.send(gap).await { + statsd_count!("gap.failed", 1); + error!("send gap: {:?}", e); + } + } + + info!("crawling tree {} with {} gaps", tree.pubkey, gap_count); + + statsd_count!("tree.succeeded", 1); + statsd_time!("tree.crawled", timing.elapsed()); + + Ok::<(), anyhow::Error>(()) + }) +} + +fn spawn_crawl_worker( + client: Rpc, + sender: mpsc::Sender, + gap: TreeGapFill, +) -> JoinHandle<()> { + tokio::spawn(async move { + let timing = Instant::now(); + + if let Err(e) = gap.crawl(client, sender).await { + error!("tree transaction: {:?}", e); + + statsd_count!("gap.failed", 1); + } else { + statsd_count!("gap.succeeded", 1); + } + + statsd_time!("gap.queued", timing.elapsed()); + }) +} + +async fn queue_transaction<'a>( + client: Rpc, + queue: QueuePool, + signature: Signature, +) -> Result<(), TreeErrorKind> { + let transaction = client.get_transaction(&signature).await?; + + let message = seralize_encoded_transaction_with_status(FlatBufferBuilder::new(), transaction)?; + + queue.push(message.finished_data()).await?; + + Ok(()) +} + +fn spawn_transaction_worker(client: Rpc, queue: QueuePool, signature: Signature) -> JoinHandle<()> { + tokio::spawn(async move { + let timing = Instant::now(); + + if let Err(e) = queue_transaction(client, queue, signature).await { + error!("queue transaction: {:?}", e); + + statsd_count!("transaction.failed", 1); + } else { + statsd_count!("transaction.succeeded", 1); + } + + statsd_time!("transaction.queued", timing.elapsed()); + }) +} diff --git a/ops/src/bubblegum/cmd.rs b/ops/src/bubblegum/cmd.rs new file mode 100644 index 000000000..1004a227d --- /dev/null +++ b/ops/src/bubblegum/cmd.rs @@ -0,0 +1,27 @@ +use super::backfiller; +use anyhow::Result; +use clap::{Args, Subcommand}; + +#[derive(Debug, Clone, Subcommand)] +pub enum Commands { + /// The 'backfill' command is used to cross-reference the index against on-chain accounts. + /// It crawls through trees and backfills any missed tree transactions. + #[clap(name = "backfill")] + Backfill(backfiller::Args), +} + +#[derive(Debug, Clone, Args)] +pub struct BubblegumCommand { + #[clap(subcommand)] + pub action: Commands, +} + +pub async fn subcommand(subcommand: BubblegumCommand) -> Result<()> { + match subcommand.action { + Commands::Backfill(args) => { + backfiller::run(args).await?; + } + } + + Ok(()) +} diff --git a/ops/src/bubblegum/mod.rs b/ops/src/bubblegum/mod.rs new file mode 100644 index 000000000..f86724b79 --- /dev/null +++ b/ops/src/bubblegum/mod.rs @@ -0,0 +1,7 @@ +mod backfiller; +mod cmd; +mod queue; +mod rpc; +mod tree; + +pub use cmd::*; diff --git a/ops/src/bubblegum/queue.rs b/ops/src/bubblegum/queue.rs new file mode 100644 index 000000000..52105316f --- /dev/null +++ b/ops/src/bubblegum/queue.rs @@ -0,0 +1,103 @@ +use anyhow::Result; +use clap::Parser; +use figment::value::{Dict, Value}; +use plerkle_messenger::{Messenger, MessengerConfig, MessengerType}; +use std::num::TryFromIntError; +use std::sync::Arc; +use tokio::sync::mpsc; +use tokio::sync::{mpsc::error::TrySendError, Mutex}; + +const TRANSACTION_BACKFILL_STREAM: &str = "TXNFILL"; + +#[derive(Clone, Debug, Parser)] +pub struct QueueArgs { + #[arg(long, env)] + pub messenger_redis_url: String, + #[arg(long, env, default_value = "100")] + pub messenger_redis_batch_size: String, + #[arg(long, env, default_value = "25")] + pub messenger_queue_connections: u64, + #[arg(long, env, default_value = "TXNFILL")] + pub messenger_queue_stream: String, +} + +impl From for MessengerConfig { + fn from(args: QueueArgs) -> Self { + let mut connection_config = Dict::new(); + + connection_config.insert( + "redis_connection_str".to_string(), + Value::from(args.messenger_redis_url), + ); + connection_config.insert( + "batch_size".to_string(), + Value::from(args.messenger_redis_batch_size), + ); + connection_config.insert( + "pipeline_size_bytes".to_string(), + Value::from(1u128.to_string()), + ); + + Self { + messenger_type: MessengerType::Redis, + connection_config, + } + } +} + +#[derive(thiserror::Error, Debug)] +pub enum QueuePoolError { + #[error("messenger")] + Messenger(#[from] plerkle_messenger::MessengerError), + #[error("tokio try send to channel")] + TrySendMessengerChannel(#[from] TrySendError>), + #[error("revc messenger connection")] + RecvMessengerConnection, + #[error("try from int")] + TryFromInt(#[from] TryFromIntError), + #[error("tokio send to channel")] + SendMessengerChannel(#[from] mpsc::error::SendError>), +} + +#[derive(Debug, Clone)] +pub struct QueuePool { + tx: mpsc::Sender>, + rx: Arc>>>, +} + +impl QueuePool { + pub async fn try_from_config(config: QueueArgs) -> anyhow::Result { + let size = usize::try_from(config.messenger_queue_connections)?; + let (tx, rx) = mpsc::channel(size); + + for _ in 0..config.messenger_queue_connections { + let messenger_config: MessengerConfig = config.clone().into(); + let mut messenger = plerkle_messenger::select_messenger(messenger_config).await?; + messenger.add_stream(TRANSACTION_BACKFILL_STREAM).await?; + messenger + .set_buffer_size(TRANSACTION_BACKFILL_STREAM, 10_000_000) + .await; + + tx.try_send(messenger)?; + } + + Ok(Self { + tx, + rx: Arc::new(Mutex::new(rx)), + }) + } + + pub async fn push(&self, message: &[u8]) -> Result<(), QueuePoolError> { + let mut rx = self.rx.lock().await; + let mut messenger = rx + .recv() + .await + .ok_or(QueuePoolError::RecvMessengerConnection)?; + + messenger.send(TRANSACTION_BACKFILL_STREAM, message).await?; + + self.tx.send(messenger).await?; + + Ok(()) + } +} diff --git a/ops/src/bubblegum/rpc.rs b/ops/src/bubblegum/rpc.rs new file mode 100644 index 000000000..0b4856401 --- /dev/null +++ b/ops/src/bubblegum/rpc.rs @@ -0,0 +1,135 @@ +use anyhow::Result; +use backon::ExponentialBuilder; +use backon::Retryable; +use clap::Parser; +use solana_account_decoder::UiAccountEncoding; +use solana_client::rpc_response::RpcConfirmedTransactionStatusWithSignature; +use solana_client::{ + client_error::ClientError, + nonblocking::rpc_client::RpcClient, + rpc_client::GetConfirmedSignaturesForAddress2Config, + rpc_config::{RpcAccountInfoConfig, RpcProgramAccountsConfig, RpcTransactionConfig}, + rpc_filter::RpcFilterType, +}; +use solana_sdk::{ + account::Account, + commitment_config::{CommitmentConfig, CommitmentLevel}, + pubkey::Pubkey, + signature::Signature, +}; +use solana_transaction_status::EncodedConfirmedTransactionWithStatusMeta; +use solana_transaction_status::UiTransactionEncoding; +use std::sync::Arc; + +#[derive(Clone, Parser, Debug)] +pub struct SolanaRpcArgs { + #[arg(long, env)] + pub solana_rpc_url: String, +} + +#[derive(Clone)] +pub struct Rpc(Arc); + +impl Rpc { + pub fn from_config(config: SolanaRpcArgs) -> Self { + Rpc(Arc::new(RpcClient::new(config.solana_rpc_url))) + } + + pub async fn get_transaction( + &self, + signature: &Signature, + ) -> Result { + (|| async { + self.0 + .get_transaction_with_config( + signature, + RpcTransactionConfig { + encoding: Some(UiTransactionEncoding::Base58), + max_supported_transaction_version: Some(0), + commitment: Some(CommitmentConfig { + commitment: CommitmentLevel::Finalized, + }), + }, + ) + .await + }) + .retry(&ExponentialBuilder::default()) + .await + } + + pub async fn get_signatures_for_address( + &self, + pubkey: &Pubkey, + before: Option, + until: Option, + ) -> Result, ClientError> { + (|| async { + self.0 + .get_signatures_for_address_with_config( + pubkey, + GetConfirmedSignaturesForAddress2Config { + before, + until, + commitment: Some(CommitmentConfig { + commitment: CommitmentLevel::Finalized, + }), + ..GetConfirmedSignaturesForAddress2Config::default() + }, + ) + .await + }) + .retry(&ExponentialBuilder::default()) + .await + } + + pub async fn get_program_accounts( + &self, + program: &Pubkey, + filters: Option>, + ) -> Result, ClientError> { + (|| async { + let filters = filters.clone(); + + self.0 + .get_program_accounts_with_config( + program, + RpcProgramAccountsConfig { + filters, + account_config: RpcAccountInfoConfig { + encoding: Some(UiAccountEncoding::Base64), + commitment: Some(CommitmentConfig { + commitment: CommitmentLevel::Finalized, + }), + ..RpcAccountInfoConfig::default() + }, + ..RpcProgramAccountsConfig::default() + }, + ) + .await + }) + .retry(&ExponentialBuilder::default()) + .await + } + + pub async fn get_multiple_accounts( + &self, + pubkeys: &[Pubkey], + ) -> Result>, ClientError> { + Ok((|| async { + self.0 + .get_multiple_accounts_with_config( + pubkeys, + RpcAccountInfoConfig { + commitment: Some(CommitmentConfig { + commitment: CommitmentLevel::Finalized, + }), + ..RpcAccountInfoConfig::default() + }, + ) + .await + }) + .retry(&ExponentialBuilder::default()) + .await? + .value) + } +} diff --git a/ops/src/bubblegum/tree.rs b/ops/src/bubblegum/tree.rs new file mode 100644 index 000000000..358477c9d --- /dev/null +++ b/ops/src/bubblegum/tree.rs @@ -0,0 +1,272 @@ +use anyhow::Result; +use borsh::BorshDeserialize; +use clap::Args; +use log::error; +use sea_orm::{DatabaseConnection, DbBackend, FromQueryResult, Statement, Value}; +use solana_client::rpc_filter::{Memcmp, RpcFilterType}; +use solana_sdk::{account::Account, pubkey::Pubkey, signature::Signature}; +use spl_account_compression::id; +use spl_account_compression::state::{ + merkle_tree_get_size, ConcurrentMerkleTreeHeader, CONCURRENT_MERKLE_TREE_HEADER_SIZE_V1, +}; +use std::str::FromStr; +use thiserror::Error as ThisError; +use tokio::sync::mpsc::Sender; + +use super::{queue::QueuePoolError, rpc::Rpc}; + +const GET_SIGNATURES_FOR_ADDRESS_LIMIT: usize = 1000; + +#[derive(Debug, Clone, Args)] +pub struct ConfigBackfiller { + /// Solana RPC URL + #[arg(long, env)] + pub solana_rpc_url: String, +} + +#[derive(ThisError, Debug)] +pub enum TreeErrorKind { + #[error("solana rpc")] + Rpc(#[from] solana_client::client_error::ClientError), + #[error("anchor")] + Achor(#[from] anchor_client::anchor_lang::error::Error), + #[error("perkle serialize")] + PerkleSerialize(#[from] plerkle_serialization::error::PlerkleSerializationError), + #[error("perkle messenger")] + PlerkleMessenger(#[from] plerkle_messenger::MessengerError), + #[error("queue pool")] + QueuePool(#[from] QueuePoolError), + #[error("parse pubkey")] + ParsePubkey(#[from] solana_sdk::pubkey::ParsePubkeyError), + #[error("serialize tree response")] + SerializeTreeResponse, + #[error("sea orm")] + Database(#[from] sea_orm::DbErr), + #[error("try from pubkey")] + TryFromPubkey, + #[error("try from signature")] + TryFromSignature, +} + +const TREE_GAP_SQL: &str = r#" +WITH sequenced_data AS ( + SELECT + tree, + seq, + LEAD(seq) OVER (ORDER BY seq ASC) AS next_seq, + tx AS current_tx, + LEAD(tx) OVER (ORDER BY seq ASC) AS next_tx + FROM + cl_audits_v2 + WHERE + tree = $1 +), +gaps AS ( + SELECT + tree, + seq AS gap_start_seq, + next_seq AS gap_end_seq, + current_tx AS lower_bound_tx, + next_tx AS upper_bound_tx + FROM + sequenced_data + WHERE + next_seq IS NOT NULL AND + next_seq - seq > 1 +) +SELECT + tree, + gap_start_seq, + gap_end_seq, + lower_bound_tx, + upper_bound_tx +FROM + gaps +ORDER BY + gap_start_seq; +"#; + +#[derive(Debug, FromQueryResult, PartialEq, Clone)] +pub struct TreeGapModel { + pub tree: Vec, + pub gap_start_seq: i64, + pub gap_end_seq: i64, + pub lower_bound_tx: Vec, + pub upper_bound_tx: Vec, +} + +impl TreeGapModel { + pub async fn find(conn: &DatabaseConnection, tree: Pubkey) -> Result, TreeErrorKind> { + let statement = Statement::from_sql_and_values( + DbBackend::Postgres, + TREE_GAP_SQL, + vec![Value::Bytes(Some(Box::new(tree.as_ref().to_vec())))], + ); + + TreeGapModel::find_by_statement(statement) + .all(conn) + .await + .map_err(Into::into) + } +} + +impl TryFrom for TreeGapFill { + type Error = TreeErrorKind; + + fn try_from(model: TreeGapModel) -> Result { + let tree = Pubkey::try_from(model.tree).map_err(|_| TreeErrorKind::TryFromPubkey)?; + let upper = Signature::try_from(model.upper_bound_tx) + .map_err(|_| TreeErrorKind::TryFromSignature)?; + let lower = Signature::try_from(model.lower_bound_tx) + .map_err(|_| TreeErrorKind::TryFromSignature)?; + + Ok(Self::new(tree, Some(upper), Some(lower))) + } +} + +pub struct TreeGapFill { + tree: Pubkey, + before: Option, + until: Option, +} + +impl TreeGapFill { + pub fn new(tree: Pubkey, before: Option, until: Option) -> Self { + Self { + tree, + before, + until, + } + } + + pub async fn crawl(&self, client: Rpc, sender: Sender) -> Result<()> { + let mut before = self.before; + + loop { + let sigs = client + .get_signatures_for_address(&self.tree, before, self.until) + .await?; + + for sig in sigs.iter() { + let sig = Signature::from_str(&sig.signature)?; + + sender.send(sig).await?; + + before = Some(sig); + } + + if sigs.len() < GET_SIGNATURES_FOR_ADDRESS_LIMIT { + break; + } + } + + Ok(()) + } +} + +#[derive(Debug, Clone)] +pub struct TreeHeaderResponse { + pub max_depth: u32, + pub max_buffer_size: u32, + pub creation_slot: u64, + pub size: usize, +} + +impl TryFrom for TreeHeaderResponse { + type Error = TreeErrorKind; + + fn try_from(payload: ConcurrentMerkleTreeHeader) -> Result { + let size = merkle_tree_get_size(&payload)?; + + Ok(Self { + max_depth: payload.get_max_depth(), + max_buffer_size: payload.get_max_buffer_size(), + creation_slot: payload.get_creation_slot(), + size, + }) + } +} + +#[derive(Debug, Clone)] +pub struct TreeResponse { + pub pubkey: Pubkey, + pub tree_header: TreeHeaderResponse, + pub seq: u64, +} + +impl TreeResponse { + pub fn try_from_rpc(pubkey: Pubkey, account: Account) -> Result { + let bytes = account.data.as_slice(); + + let (header_bytes, rest) = bytes.split_at(CONCURRENT_MERKLE_TREE_HEADER_SIZE_V1); + let header: ConcurrentMerkleTreeHeader = + ConcurrentMerkleTreeHeader::try_from_slice(header_bytes)?; + + let merkle_tree_size = merkle_tree_get_size(&header)?; + let (tree_bytes, _canopy_bytes) = rest.split_at(merkle_tree_size); + + let seq_bytes = tree_bytes[0..8].try_into()?; + let seq = u64::from_le_bytes(seq_bytes); + + let (auth, _) = Pubkey::find_program_address(&[pubkey.as_ref()], &mpl_bubblegum::ID); + + header.assert_valid_authority(&auth)?; + + let tree_header = header.try_into()?; + + Ok(Self { + pubkey, + tree_header, + seq, + }) + } + + pub async fn all(client: &Rpc) -> Result, TreeErrorKind> { + Ok(client + .get_program_accounts( + &id(), + Some(vec![RpcFilterType::Memcmp(Memcmp::new_raw_bytes( + 0, + vec![1u8], + ))]), + ) + .await? + .into_iter() + .filter_map(|(pubkey, account)| Self::try_from_rpc(pubkey, account).ok()) + .collect()) + } + + pub async fn find(client: &Rpc, pubkeys: Vec) -> Result, TreeErrorKind> { + let pubkeys: Vec = pubkeys + .into_iter() + .map(|p| Pubkey::from_str(&p)) + .collect::, _>>()?; + let pubkey_batches = pubkeys.chunks(100); + let pubkey_batches_count = pubkey_batches.len(); + + let mut gma_handles = Vec::with_capacity(pubkey_batches_count); + + for batch in pubkey_batches { + gma_handles.push(async move { + let accounts = client.get_multiple_accounts(batch).await?; + + let results: Vec<(&Pubkey, Option)> = batch.iter().zip(accounts).collect(); + + Ok::<_, TreeErrorKind>(results) + }) + } + + let result = futures::future::try_join_all(gma_handles).await?; + + let trees = result + .into_iter() + .flatten() + .filter_map(|(pubkey, account)| { + account.map(|account| Self::try_from_rpc(*pubkey, account)) + }) + .collect::, _>>() + .map_err(|_| TreeErrorKind::SerializeTreeResponse)?; + + Ok(trees) + } +} diff --git a/ops/src/main.rs b/ops/src/main.rs new file mode 100644 index 000000000..197b130ca --- /dev/null +++ b/ops/src/main.rs @@ -0,0 +1,31 @@ +mod bubblegum; + +use anyhow::Result; +use bubblegum::{subcommand as bubblegum_subcommand, BubblegumCommand}; +use clap::{Parser, Subcommand}; + +#[derive(Debug, Parser)] +#[clap(author, version)] +struct Args { + #[command(subcommand)] + command: Command, +} + +#[derive(Debug, Subcommand)] +enum Command { + #[clap(name = "bubblegum")] + Bubblegum(BubblegumCommand), +} + +#[tokio::main] +async fn main() -> Result<()> { + let args = Args::parse(); + + env_logger::init(); + + match args.command { + Command::Bubblegum(subcommand) => bubblegum_subcommand(subcommand).await?, + } + + Ok(()) +} diff --git a/tools/acc_forwarder/src/main.rs b/tools/acc_forwarder/src/main.rs index f90655c16..3c7c96279 100644 --- a/tools/acc_forwarder/src/main.rs +++ b/tools/acc_forwarder/src/main.rs @@ -4,7 +4,7 @@ use { figment::{map, value::Value}, futures::{future::try_join_all, stream::StreamExt}, log::{info, warn}, - mpl_token_metadata::{pda::find_metadata_account, state::Metadata}, + mpl_token_metadata::accounts::Metadata, plerkle_messenger::{MessengerConfig, ACCOUNT_BACKFILL_STREAM}, plerkle_serialization::{ serializer::serialize_account, solana_geyser_plugin_interface_shims::ReplicaAccountInfoV2, @@ -150,7 +150,7 @@ async fn main() -> anyhow::Result<()> { Action::Mint { mint } => { let mint = Pubkey::from_str(&mint).with_context(|| format!("failed to parse mint {mint}"))?; - let metadata_account = find_metadata_account(&mint).0; + let metadata_account = Metadata::find_pda(&mint).0; let token_account = get_token_largest_account(&client, mint).await; match token_account { diff --git a/tools/load_generation/src/main.rs b/tools/load_generation/src/main.rs index d6bf340bf..c8f1e48c2 100644 --- a/tools/load_generation/src/main.rs +++ b/tools/load_generation/src/main.rs @@ -1,5 +1,12 @@ use { - mpl_token_metadata::state::Creator, + mpl_token_metadata::{ + accounts::{MasterEdition, Metadata}, + instructions::{ + CreateMasterEditionV3Builder, CreateMetadataAccountV3Builder, + SetAndVerifyCollectionBuilder, UpdateMetadataAccountV2Builder, + }, + types::{Creator, DataV2}, + }, solana_client::{ client_error::ClientError, nonblocking::rpc_client::RpcClient, rpc_request::RpcError::RpcRequestError, @@ -171,82 +178,70 @@ pub async fn make_a_nft_thing( 1, ) .await?; - let prg_uid = mpl_token_metadata::id(); - let _metadata_seeds = &[ - mpl_token_metadata::state::PREFIX.as_bytes(), - prg_uid.to_bytes().as_ref(), - mint.as_ref(), - ]; - let (pubkey, _) = mpl_token_metadata::pda::find_metadata_account(&mint); - let (edition_pubkey, _) = mpl_token_metadata::pda::find_master_edition_account(&mint); + let prg_uid = mpl_token_metadata::ID; + let _metadata_seeds = &[Metadata::PREFIX, prg_uid.to_bytes().as_ref(), mint.as_ref()]; + let (pubkey, _) = Metadata::find_pda(&mint); + let (edition_pubkey, _) = MasterEdition::find_pda(&mint); let tx = Transaction::new_signed_with_payer( - &[ - mpl_token_metadata::instruction::create_metadata_accounts_v3( - prg_uid, - pubkey, - mint, - payer.pubkey(), - payer.pubkey(), - payer.pubkey(), - "fake".to_string(), - "fake".to_string(), - "https://usd363wqbeq4xmuyddhbicmvm5yzegh4ulnsmp67jebxi6mqe45q.arweave.net/pIe_btAJIcuymBjOFAmVZ3GSGPyi2yY_30kDdHmQJzs".to_string(), - Some(vec![Creator { - address: payer.pubkey(), - verified: true, - share: 100, - }]), - 0, - true, - true, - None, - None, - None, - ), - mpl_token_metadata::instruction::create_master_edition_v3( - prg_uid, - edition_pubkey, - mint, - payer.pubkey(), - payer.pubkey(), - pubkey, - payer.pubkey(), - Some(0), - ), + &[CreateMetadataAccountV3Builder::new() + .metadata(pubkey) + .mint(mint) + .mint_authority(payer.pubkey()) + .payer(payer.pubkey()) + .update_authority(payer.pubkey(), true) + .data(DataV2 { + name: "fake".to_string(), + symbol: "fake".to_string(), + uri: "https://usd363wqbeq4xmuyddhbicmvm5yzegh4ulnsmp67jebxi6mqe45q.arweave.net/pIe_btAJIcuymBjOFAmVZ3GSGPyi2yY_30kDdHmQJzs".to_string(), + creators: Some(vec![Creator { + address: payer.pubkey(), + verified: true, + share: 100, + }]), + collection: None, + seller_fee_basis_points: 0, + uses: None, + }) + .is_mutable(true) + .instruction(), + + CreateMasterEditionV3Builder::new() + .edition(edition_pubkey) + .mint(mint) + .update_authority(payer.pubkey()) + .mint_authority(payer.pubkey()) + .metadata(pubkey) + .payer(payer.pubkey()) + .max_supply(0) + .instruction() ], Some(&payer.pubkey()), &[payer.as_ref()], solana_client.get_latest_blockhash().await?, ); solana_client.send_and_confirm_transaction(&tx).await?; - let mut ix = vec![ - mpl_token_metadata::instruction::update_metadata_accounts_v2( - prg_uid, - pubkey, - payer.pubkey(), - None, - None, - None, - Some(false), - ), - ]; + let mut ix = vec![UpdateMetadataAccountV2Builder::new() + .metadata(pubkey) + .update_authority(payer.pubkey()) + .is_mutable(false) + .instruction()]; if let Some(collection_mint) = collection_mint { - let (collection_metadata, _u8) = - mpl_token_metadata::pda::find_metadata_account(&collection_mint); - let (collection_master_edition, _u8) = - mpl_token_metadata::pda::find_master_edition_account(&collection_mint); - ix.push(mpl_token_metadata::instruction::set_and_verify_collection( - prg_uid, - pubkey, - payer.pubkey(), - payer.pubkey(), - payer.pubkey(), - collection_mint, - collection_metadata, - collection_master_edition, - None, - )); + let (collection_metadata, _u8) = Metadata::find_pda(&collection_mint); + let (collection_master_edition, _u8) = MasterEdition::find_pda(&collection_mint); + + ix.push( + SetAndVerifyCollectionBuilder::new() + .metadata(pubkey) + .collection_authority(payer.pubkey()) + .payer(payer.pubkey()) + .update_authority(payer.pubkey()) + .collection_mint(collection_mint) + .collection(collection_metadata) + .collection_master_edition_account(collection_master_edition) + .collection_authority_record(None) + .instruction(), + ); } let tx = Transaction::new_signed_with_payer( &ix,