From 707e3c4753f96ab3a4b29f9ba8e7ce81936ca06b Mon Sep 17 00:00:00 2001 From: nazreen Date: Sat, 15 Mar 2025 01:16:03 +0800 Subject: [PATCH 01/12] add in solana omnicounter --- examples/oapp-solana-counter/.gitignore | 3 + examples/oapp-solana-counter/Anchor.toml | 16 + examples/oapp-solana-counter/Cargo.lock | 1787 +++++++++++++++++ examples/oapp-solana-counter/Cargo.toml | 14 + .../ordered-execution-implementation.md | 284 +++ examples/oapp-solana-counter/package.json | 39 + .../programs/counter/Cargo.toml | 22 + .../programs/counter/Xargo.toml | 2 + .../programs/counter/build.rs | 3 + .../programs/counter/readme.md | 1 + .../programs/counter/src/errors.rs | 7 + .../counter/src/instructions/increment.rs | 56 + .../counter/src/instructions/init_count.rs | 68 + .../counter/src/instructions/lz_compose.rs | 34 + .../src/instructions/lz_compose_types.rs | 43 + .../counter/src/instructions/lz_receive.rs | 95 + .../src/instructions/lz_receive_types.rs | 74 + .../programs/counter/src/instructions/mod.rs | 23 + .../counter/src/instructions/next_nonce.rs | 33 + .../counter/src/instructions/quote.rs | 40 + .../src/instructions/set_ordered_nonce.rs | 22 + .../counter/src/instructions/set_peer.rs | 44 + .../src/instructions/skip_inbound_nonce.rs | 52 + .../programs/counter/src/lib.rs | 83 + .../programs/counter/src/msg_codec.rs | 25 + .../programs/counter/src/state/count.rs | 38 + .../programs/counter/src/state/mod.rs | 7 + .../programs/counter/src/state/nonce.rs | 11 + .../programs/counter/src/state/peer.rs | 11 + .../oapp-solana-counter/rust-toolchain.toml | 5 + examples/oapp-solana-counter/rustfmt.toml | 23 + examples/oapp-solana-counter/turbo.json | 25 + packages/create-lz-oapp/src/config.ts | 17 +- turbo.json | 1 + 34 files changed, 3006 insertions(+), 2 deletions(-) create mode 100644 examples/oapp-solana-counter/.gitignore create mode 100644 examples/oapp-solana-counter/Anchor.toml create mode 100644 examples/oapp-solana-counter/Cargo.lock create mode 100644 examples/oapp-solana-counter/Cargo.toml create mode 100644 examples/oapp-solana-counter/ordered-execution-implementation.md create mode 100644 examples/oapp-solana-counter/package.json create mode 100644 examples/oapp-solana-counter/programs/counter/Cargo.toml create mode 100644 examples/oapp-solana-counter/programs/counter/Xargo.toml create mode 100644 examples/oapp-solana-counter/programs/counter/build.rs create mode 100644 examples/oapp-solana-counter/programs/counter/readme.md create mode 100644 examples/oapp-solana-counter/programs/counter/src/errors.rs create mode 100644 examples/oapp-solana-counter/programs/counter/src/instructions/increment.rs create mode 100644 examples/oapp-solana-counter/programs/counter/src/instructions/init_count.rs create mode 100644 examples/oapp-solana-counter/programs/counter/src/instructions/lz_compose.rs create mode 100644 examples/oapp-solana-counter/programs/counter/src/instructions/lz_compose_types.rs create mode 100644 examples/oapp-solana-counter/programs/counter/src/instructions/lz_receive.rs create mode 100644 examples/oapp-solana-counter/programs/counter/src/instructions/lz_receive_types.rs create mode 100644 examples/oapp-solana-counter/programs/counter/src/instructions/mod.rs create mode 100644 examples/oapp-solana-counter/programs/counter/src/instructions/next_nonce.rs create mode 100644 examples/oapp-solana-counter/programs/counter/src/instructions/quote.rs create mode 100644 examples/oapp-solana-counter/programs/counter/src/instructions/set_ordered_nonce.rs create mode 100644 examples/oapp-solana-counter/programs/counter/src/instructions/set_peer.rs create mode 100644 examples/oapp-solana-counter/programs/counter/src/instructions/skip_inbound_nonce.rs create mode 100644 examples/oapp-solana-counter/programs/counter/src/lib.rs create mode 100644 examples/oapp-solana-counter/programs/counter/src/msg_codec.rs create mode 100644 examples/oapp-solana-counter/programs/counter/src/state/count.rs create mode 100644 examples/oapp-solana-counter/programs/counter/src/state/mod.rs create mode 100644 examples/oapp-solana-counter/programs/counter/src/state/nonce.rs create mode 100644 examples/oapp-solana-counter/programs/counter/src/state/peer.rs create mode 100644 examples/oapp-solana-counter/rust-toolchain.toml create mode 100644 examples/oapp-solana-counter/rustfmt.toml create mode 100644 examples/oapp-solana-counter/turbo.json diff --git a/examples/oapp-solana-counter/.gitignore b/examples/oapp-solana-counter/.gitignore new file mode 100644 index 0000000000..1243301b64 --- /dev/null +++ b/examples/oapp-solana-counter/.gitignore @@ -0,0 +1,3 @@ +target +.anchor +test-ledger \ No newline at end of file diff --git a/examples/oapp-solana-counter/Anchor.toml b/examples/oapp-solana-counter/Anchor.toml new file mode 100644 index 0000000000..70633b3929 --- /dev/null +++ b/examples/oapp-solana-counter/Anchor.toml @@ -0,0 +1,16 @@ +[features] +seeds = false +skip-lint = false + +[programs.localnet] +omnicounter = 'HFyiETGKEUS9tr87K1HXmVJHkqQRtw8wShRNTMkKKxay' + +[registry] +url = "https://api.apr.dev" + +[provider] +cluster = "localnet" +wallet = "~/.config/solana/id.json" + +[scripts] +test = "yarn run ts-mocha -b -p ./tsconfig.json -t 10000000 sdk/tests/**/*.test.ts" diff --git a/examples/oapp-solana-counter/Cargo.lock b/examples/oapp-solana-counter/Cargo.lock new file mode 100644 index 0000000000..c989b191ea --- /dev/null +++ b/examples/oapp-solana-counter/Cargo.lock @@ -0,0 +1,1787 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "ahash" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "891477e0c6a8957309ee5c45a6368af3ae14bb510732d2684ffa19af310920f9" +dependencies = [ + "getrandom 0.2.14", + "once_cell", + "version_check", +] + +[[package]] +name = "ahash" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd7d5a2cecb58716e47d67d5703a249964b14c7be1ec3cad3affc295b2d1c35d" +dependencies = [ + "cfg-if", + "getrandom 0.2.14", + "once_cell", + "version_check", + "zerocopy", +] + +[[package]] +name = "anchor-attribute-access-control" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5f619f1d04f53621925ba8a2e633ba5a6081f2ae14758cbb67f38fd823e0a3e" +dependencies = [ + "anchor-syn", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "anchor-attribute-account" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7f2a3e1df4685f18d12a943a9f2a7456305401af21a07c9fe076ef9ecd6e400" +dependencies = [ + "anchor-syn", + "bs58 0.5.1", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "anchor-attribute-constant" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9423945cb55627f0b30903288e78baf6f62c6c8ab28fb344b6b25f1ffee3dca7" +dependencies = [ + "anchor-syn", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "anchor-attribute-error" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93ed12720033cc3c3bf3cfa293349c2275cd5ab99936e33dd4bf283aaad3e241" +dependencies = [ + "anchor-syn", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "anchor-attribute-event" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eef4dc0371eba2d8c8b54794b0b0eb786a234a559b77593d6f80825b6d2c77a2" +dependencies = [ + "anchor-syn", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "anchor-attribute-program" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b18c4f191331e078d4a6a080954d1576241c29c56638783322a18d308ab27e4f" +dependencies = [ + "anchor-syn", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "anchor-derive-accounts" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5de10d6e9620d3bcea56c56151cad83c5992f50d5960b3a9bebc4a50390ddc3c" +dependencies = [ + "anchor-syn", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "anchor-derive-serde" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4e2e5be518ec6053d90a2a7f26843dbee607583c779e6c8395951b9739bdfbe" +dependencies = [ + "anchor-syn", + "borsh-derive-internal 0.10.3", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "anchor-derive-space" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ecc31d19fa54840e74b7a979d44bcea49d70459de846088a1d71e87ba53c419" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "anchor-lang" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35da4785497388af0553586d55ebdc08054a8b1724720ef2749d313494f2b8ad" +dependencies = [ + "anchor-attribute-access-control", + "anchor-attribute-account", + "anchor-attribute-constant", + "anchor-attribute-error", + "anchor-attribute-event", + "anchor-attribute-program", + "anchor-derive-accounts", + "anchor-derive-serde", + "anchor-derive-space", + "anchor-syn", + "arrayref", + "base64 0.13.1", + "bincode", + "borsh 0.10.3", + "bytemuck", + "getrandom 0.2.14", + "solana-program", + "thiserror", +] + +[[package]] +name = "anchor-syn" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9101b84702fed2ea57bd22992f75065da5648017135b844283a2f6d74f27825" +dependencies = [ + "anyhow", + "bs58 0.5.1", + "heck", + "proc-macro2", + "quote", + "serde", + "serde_json", + "sha2 0.10.8", + "syn 1.0.109", + "thiserror", +] + +[[package]] +name = "anyhow" +version = "1.0.82" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f538837af36e6f6a9be0faa67f9a314f8119e4e4b5867c6ab40ed60360142519" + +[[package]] +name = "ark-bn254" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a22f4561524cd949590d78d7d4c5df8f592430d221f7f3c9497bbafd8972120f" +dependencies = [ + "ark-ec", + "ark-ff", + "ark-std", +] + +[[package]] +name = "ark-ec" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "defd9a439d56ac24968cca0571f598a61bc8c55f71d50a89cda591cb750670ba" +dependencies = [ + "ark-ff", + "ark-poly", + "ark-serialize", + "ark-std", + "derivative", + "hashbrown 0.13.2", + "itertools", + "num-traits", + "zeroize", +] + +[[package]] +name = "ark-ff" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec847af850f44ad29048935519032c33da8aa03340876d351dfab5660d2966ba" +dependencies = [ + "ark-ff-asm", + "ark-ff-macros", + "ark-serialize", + "ark-std", + "derivative", + "digest 0.10.7", + "itertools", + "num-bigint", + "num-traits", + "paste", + "rustc_version", + "zeroize", +] + +[[package]] +name = "ark-ff-asm" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ed4aa4fe255d0bc6d79373f7e31d2ea147bcf486cba1be5ba7ea85abdb92348" +dependencies = [ + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-ff-macros" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7abe79b0e4288889c4574159ab790824d0033b9fdcb2a112a3182fac2e514565" +dependencies = [ + "num-bigint", + "num-traits", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-poly" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d320bfc44ee185d899ccbadfa8bc31aab923ce1558716e1997a1e74057fe86bf" +dependencies = [ + "ark-ff", + "ark-serialize", + "ark-std", + "derivative", + "hashbrown 0.13.2", +] + +[[package]] +name = "ark-serialize" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adb7b85a02b83d2f22f89bd5cac66c9c89474240cb6207cb1efc16d098e822a5" +dependencies = [ + "ark-serialize-derive", + "ark-std", + "digest 0.10.7", + "num-bigint", +] + +[[package]] +name = "ark-serialize-derive" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae3281bc6d0fd7e549af32b52511e1302185bd688fd3359fa36423346ff682ea" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-std" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94893f1e0c6eeab764ade8dc4c0db24caf4fe7cbbaafc0eba0a9030f447b5185" +dependencies = [ + "num-traits", + "rand 0.8.5", +] + +[[package]] +name = "arrayref" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b4930d2cb77ce62f89ee5d5289b4ac049559b1c45539271f5ed4fdc7db34545" + +[[package]] +name = "arrayvec" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" + +[[package]] +name = "autocfg" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80" + +[[package]] +name = "base64" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3441f0f7b02788e948e47f457ca01f1d7e6d92c693bc132c22b087d3141c03ff" + +[[package]] +name = "base64" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" + +[[package]] +name = "base64" +version = "0.21.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" + +[[package]] +name = "bincode" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" +dependencies = [ + "serde", +] + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" +dependencies = [ + "serde", +] + +[[package]] +name = "bitmaps" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "031043d04099746d8db04daf1fa424b2bc8bd69d92b25962dcde24da39ab64a2" +dependencies = [ + "typenum", +] + +[[package]] +name = "blake3" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30cca6d3674597c30ddf2c587bf8d9d65c9a84d2326d941cc79c9842dfe0ef52" +dependencies = [ + "arrayref", + "arrayvec", + "cc", + "cfg-if", + "constant_time_eq", + "digest 0.10.7", +] + +[[package]] +name = "block-buffer" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" +dependencies = [ + "generic-array", +] + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "borsh" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15bf3650200d8bffa99015595e10f1fbd17de07abbc25bb067da79e769939bfa" +dependencies = [ + "borsh-derive 0.9.3", + "hashbrown 0.11.2", +] + +[[package]] +name = "borsh" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4114279215a005bc675e386011e594e1d9b800918cea18fcadadcce864a2046b" +dependencies = [ + "borsh-derive 0.10.3", + "hashbrown 0.13.2", +] + +[[package]] +name = "borsh-derive" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6441c552f230375d18e3cc377677914d2ca2b0d36e52129fe15450a2dce46775" +dependencies = [ + "borsh-derive-internal 0.9.3", + "borsh-schema-derive-internal 0.9.3", + "proc-macro-crate", + "proc-macro2", + "syn 1.0.109", +] + +[[package]] +name = "borsh-derive" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0754613691538d51f329cce9af41d7b7ca150bc973056f1156611489475f54f7" +dependencies = [ + "borsh-derive-internal 0.10.3", + "borsh-schema-derive-internal 0.10.3", + "proc-macro-crate", + "proc-macro2", + "syn 1.0.109", +] + +[[package]] +name = "borsh-derive-internal" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5449c28a7b352f2d1e592a8a28bf139bc71afb0764a14f3c02500935d8c44065" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "borsh-derive-internal" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "afb438156919598d2c7bad7e1c0adf3d26ed3840dbc010db1a882a65583ca2fb" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "borsh-schema-derive-internal" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdbd5696d8bfa21d53d9fe39a714a18538bad11492a42d066dbbc395fb1951c0" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "borsh-schema-derive-internal" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "634205cc43f74a1b9046ef87c4540ebda95696ec0f315024860cad7c5b0f5ccd" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "bs58" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "771fe0050b883fcc3ea2359b1a96bcfbc090b7116eae7c3c512c7a083fdf23d3" + +[[package]] +name = "bs58" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf88ba1141d185c399bee5288d850d63b8369520c1eafc32a0430b5b6c287bf4" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "bumpalo" +version = "3.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" + +[[package]] +name = "bv" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8834bb1d8ee5dc048ee3124f2c7c1afcc6bc9aed03f11e9dfd8c69470a5db340" +dependencies = [ + "feature-probe", + "serde", +] + +[[package]] +name = "bytemuck" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d6d68c57235a3a081186990eca2867354726650f42f7516ca50c28d6281fd15" +dependencies = [ + "bytemuck_derive", +] + +[[package]] +name = "bytemuck_derive" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4da9a32f3fed317401fa3c862968128267c3106685286e15d5aaa3d7389c2f60" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.58", +] + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "cc" +version = "1.0.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2678b2e3449475e95b0aa6f9b506a28e61b3dc8996592b983695e8ebb58a8b41" +dependencies = [ + "jobserver", + "libc", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "console_error_panic_hook" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc" +dependencies = [ + "cfg-if", + "wasm-bindgen", +] + +[[package]] +name = "console_log" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e89f72f65e8501878b8a004d5a1afb780987e2ce2b4532c562e367a72c57499f" +dependencies = [ + "log", + "web-sys", +] + +[[package]] +name = "constant_time_eq" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7144d30dcf0fafbce74250a3963025d8d52177934239851c917d29f1df280c2" + +[[package]] +name = "cpi-helper" +version = "0.1.0" +dependencies = [ + "bs58 0.5.1", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "cpufeatures" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" +dependencies = [ + "libc", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" + +[[package]] +name = "crunchy" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "crypto-mac" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b584a330336237c1eecd3e94266efb216c56ed91225d634cb2991c5f3fd1aeab" +dependencies = [ + "generic-array", + "subtle", +] + +[[package]] +name = "curve25519-dalek" +version = "3.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90f9d052967f590a76e62eb387bd0bbb1b000182c3cefe5364db6b7211651bc0" +dependencies = [ + "byteorder", + "digest 0.9.0", + "rand_core 0.5.1", + "serde", + "subtle", + "zeroize", +] + +[[package]] +name = "derivative" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "digest" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" +dependencies = [ + "generic-array", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer 0.10.4", + "crypto-common", + "subtle", +] + +[[package]] +name = "either" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a" + +[[package]] +name = "endpoint" +version = "0.1.0" +dependencies = [ + "anchor-lang", + "cpi-helper", + "messagelib-interface", + "solana-helper", + "solana-program", + "utils", +] + +[[package]] +name = "feature-probe" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "835a3dc7d1ec9e75e2b5fb4ba75396837112d2060b03f7d43bc1897c7f7211da" + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "serde", + "typenum", + "version_check", +] + +[[package]] +name = "getrandom" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "wasi 0.9.0+wasi-snapshot-preview1", + "wasm-bindgen", +] + +[[package]] +name = "getrandom" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94b22e06ecb0110981051723910cbf0b5f5e09a2062dd7663334ee79a9d1286c" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "wasi 0.11.0+wasi-snapshot-preview1", + "wasm-bindgen", +] + +[[package]] +name = "hashbrown" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" +dependencies = [ + "ahash 0.7.8", +] + +[[package]] +name = "hashbrown" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" +dependencies = [ + "ahash 0.8.5", +] + +[[package]] +name = "heck" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c" +dependencies = [ + "unicode-segmentation", +] + +[[package]] +name = "hmac" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "126888268dcc288495a26bf004b38c5fdbb31682f992c84ceb046a1f0fe38840" +dependencies = [ + "crypto-mac", + "digest 0.9.0", +] + +[[package]] +name = "hmac-drbg" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17ea0a1394df5b6574da6e0c1ade9e78868c9fb0a4e5ef4428e32da4676b85b1" +dependencies = [ + "digest 0.9.0", + "generic-array", + "hmac", +] + +[[package]] +name = "im" +version = "15.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0acd33ff0285af998aaf9b57342af478078f53492322fafc47450e09397e0e9" +dependencies = [ + "bitmaps", + "rand_core 0.6.4", + "rand_xoshiro", + "rayon", + "serde", + "sized-chunks", + "typenum", + "version_check", +] + +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" + +[[package]] +name = "jobserver" +version = "0.1.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab46a6e9526ddef3ae7f787c06f0f2600639ba80ea3eade3d8e670a2230f51d6" +dependencies = [ + "libc", +] + +[[package]] +name = "js-sys" +version = "0.3.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "keccak" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecc2af9a1119c51f12a14607e783cb977bde58bc069ff0c3da1095e635d70654" +dependencies = [ + "cpufeatures", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "libc" +version = "0.2.153" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" + +[[package]] +name = "libsecp256k1" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9d220bc1feda2ac231cb78c3d26f27676b8cf82c96971f7aeef3d0cf2797c73" +dependencies = [ + "arrayref", + "base64 0.12.3", + "digest 0.9.0", + "hmac-drbg", + "libsecp256k1-core", + "libsecp256k1-gen-ecmult", + "libsecp256k1-gen-genmult", + "rand 0.7.3", + "serde", + "sha2 0.9.9", + "typenum", +] + +[[package]] +name = "libsecp256k1-core" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0f6ab710cec28cef759c5f18671a27dae2a5f952cdaaee1d8e2908cb2478a80" +dependencies = [ + "crunchy", + "digest 0.9.0", + "subtle", +] + +[[package]] +name = "libsecp256k1-gen-ecmult" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccab96b584d38fac86a83f07e659f0deafd0253dc096dab5a36d53efe653c5c3" +dependencies = [ + "libsecp256k1-core", +] + +[[package]] +name = "libsecp256k1-gen-genmult" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67abfe149395e3aa1c48a2beb32b068e2334402df8181f818d3aee2b304c4f5d" +dependencies = [ + "libsecp256k1-core", +] + +[[package]] +name = "light-poseidon" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c9a85a9752c549ceb7578064b4ed891179d20acd85f27318573b64d2d7ee7ee" +dependencies = [ + "ark-bn254", + "ark-ff", + "num-bigint", + "thiserror", +] + +[[package]] +name = "lock_api" +version = "0.4.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" + +[[package]] +name = "memmap2" +version = "0.5.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83faa42c0a078c393f6b29d5db232d8be22776a891f8f56e5284faee4a20b327" +dependencies = [ + "libc", +] + +[[package]] +name = "memoffset" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" +dependencies = [ + "autocfg", +] + +[[package]] +name = "messagelib-interface" +version = "0.1.0" +dependencies = [ + "anchor-lang", +] + +[[package]] +name = "num-bigint" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "608e7659b5c3d7cba262d894801b9ec9d00de989e8a82bd4bef91d08da45cdc0" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-derive" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "876a53fff98e03a936a674b29568b0e605f06b29372c2489ff4de23f1949743d" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a" +dependencies = [ + "autocfg", +] + +[[package]] +name = "oapp" +version = "0.1.0" +dependencies = [ + "anchor-lang", + "endpoint", +] + +[[package]] +name = "omnicounter" +version = "0.1.0" +dependencies = [ + "anchor-lang", + "oapp", + "solana-helper", +] + +[[package]] +name = "once_cell" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" + +[[package]] +name = "opaque-debug" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" + +[[package]] +name = "parking_lot" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-targets", +] + +[[package]] +name = "paste" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" + +[[package]] +name = "pbkdf2" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "216eaa586a190f0a738f2f918511eecfa90f13295abec0e457cdebcceda80cbd" +dependencies = [ + "crypto-mac", +] + +[[package]] +name = "ppv-lite86" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" + +[[package]] +name = "proc-macro-crate" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d6ea3c4595b96363c13943497db34af4460fb474a95c43f4446ad341b8c9785" +dependencies = [ + "toml", +] + +[[package]] +name = "proc-macro2" +version = "1.0.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e835ff2298f5721608eb1a980ecaee1aef2c132bf95ecc026a11b7bf3c01c02e" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" +dependencies = [ + "getrandom 0.1.16", + "libc", + "rand_chacha 0.2.2", + "rand_core 0.5.1", + "rand_hc", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha 0.3.1", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_chacha" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" +dependencies = [ + "ppv-lite86", + "rand_core 0.5.1", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_core" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" +dependencies = [ + "getrandom 0.1.16", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom 0.2.14", +] + +[[package]] +name = "rand_hc" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" +dependencies = [ + "rand_core 0.5.1", +] + +[[package]] +name = "rand_xoshiro" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f97cdb2a36ed4183de61b2f824cc45c9f1037f28afe0a322e9fff4c108b5aaa" +dependencies = [ + "rand_core 0.6.4", +] + +[[package]] +name = "rayon" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + +[[package]] +name = "redox_syscall" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" +dependencies = [ + "bitflags 1.3.2", +] + +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + +[[package]] +name = "rustc_version" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +dependencies = [ + "semver", +] + +[[package]] +name = "rustversion" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80af6f9131f277a45a3fba6ce8e2258037bb0477a67e610d3c1fe046ab31de47" + +[[package]] +name = "ryu" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "semver" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca" + +[[package]] +name = "serde" +version = "1.0.197" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_bytes" +version = "0.11.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b8497c313fd43ab992087548117643f6fcd935cbf36f176ffda0aacf9591734" +dependencies = [ + "serde", +] + +[[package]] +name = "serde_derive" +version = "1.0.197" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.58", +] + +[[package]] +name = "serde_json" +version = "1.0.115" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12dc5c46daa8e9fdf4f5e71b6cf9a53f2487da0e86e55808e2d35539666497dd" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "sha2" +version = "0.9.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" +dependencies = [ + "block-buffer 0.9.0", + "cfg-if", + "cpufeatures", + "digest 0.9.0", + "opaque-debug", +] + +[[package]] +name = "sha2" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest 0.10.7", +] + +[[package]] +name = "sha3" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60" +dependencies = [ + "digest 0.10.7", + "keccak", +] + +[[package]] +name = "sized-chunks" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16d69225bde7a69b235da73377861095455d298f2b970996eec25ddbb42b3d1e" +dependencies = [ + "bitmaps", + "typenum", +] + +[[package]] +name = "smallvec" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" + +[[package]] +name = "solana-frozen-abi" +version = "1.17.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96734b05823c8b515f8e3cc02641a27aee2c9760b1a43c74cb20f2a1ab0ab76c" +dependencies = [ + "ahash 0.8.5", + "blake3", + "block-buffer 0.10.4", + "bs58 0.4.0", + "bv", + "byteorder", + "cc", + "either", + "generic-array", + "im", + "lazy_static", + "log", + "memmap2", + "rustc_version", + "serde", + "serde_bytes", + "serde_derive", + "serde_json", + "sha2 0.10.8", + "solana-frozen-abi-macro", + "subtle", + "thiserror", +] + +[[package]] +name = "solana-frozen-abi-macro" +version = "1.17.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a0f1291a464fd046135d019d57a81be165ee3d23aa7df880b47dac683a0582a" +dependencies = [ + "proc-macro2", + "quote", + "rustc_version", + "syn 2.0.58", +] + +[[package]] +name = "solana-helper" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09c6deff8c48efb84b5828db064ad9873ef3445f129f888b4b6a664bd5220e35" +dependencies = [ + "bs58 0.5.1", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "solana-program" +version = "1.17.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6412447793f8a3ef7526655906728325093b472e481791ac5c584e8d272166dc" +dependencies = [ + "ark-bn254", + "ark-ec", + "ark-ff", + "ark-serialize", + "base64 0.21.7", + "bincode", + "bitflags 2.5.0", + "blake3", + "borsh 0.10.3", + "borsh 0.9.3", + "bs58 0.4.0", + "bv", + "bytemuck", + "cc", + "console_error_panic_hook", + "console_log", + "curve25519-dalek", + "getrandom 0.2.14", + "itertools", + "js-sys", + "lazy_static", + "libc", + "libsecp256k1", + "light-poseidon", + "log", + "memoffset", + "num-bigint", + "num-derive", + "num-traits", + "parking_lot", + "rand 0.8.5", + "rustc_version", + "rustversion", + "serde", + "serde_bytes", + "serde_derive", + "serde_json", + "sha2 0.10.8", + "sha3", + "solana-frozen-abi", + "solana-frozen-abi-macro", + "solana-sdk-macro", + "thiserror", + "tiny-bip39", + "wasm-bindgen", + "zeroize", +] + +[[package]] +name = "solana-sdk-macro" +version = "1.17.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc5cc46bbda0a5472d8d0a4c846b22941436ac45c31456d3e885a387a5f264f7" +dependencies = [ + "bs58 0.4.0", + "proc-macro2", + "quote", + "rustversion", + "syn 2.0.58", +] + +[[package]] +name = "subtle" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.58" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44cfb93f38070beee36b3fef7d4f5a16f27751d94b187b666a5cc5e9b0d30687" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "thiserror" +version = "1.0.58" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03468839009160513471e86a034bb2c5c0e4baae3b43f79ffc55c4a5427b3297" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.58" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c61f3ba182994efc43764a46c018c347bc492c79f024e705f46567b418f6d4f7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.58", +] + +[[package]] +name = "tiny-bip39" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffc59cb9dfc85bb312c3a78fd6aa8a8582e310b0fa885d5bb877f6dcc601839d" +dependencies = [ + "anyhow", + "hmac", + "once_cell", + "pbkdf2", + "rand 0.7.3", + "rustc-hash", + "sha2 0.9.9", + "thiserror", + "unicode-normalization", + "wasm-bindgen", + "zeroize", +] + +[[package]] +name = "tinyvec" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "toml" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" +dependencies = [ + "serde", +] + +[[package]] +name = "typenum" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "unicode-normalization" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "unicode-segmentation" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" + +[[package]] +name = "utils" +version = "0.1.0" +dependencies = [ + "anchor-lang", +] + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "wasi" +version = "0.9.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasm-bindgen" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn 2.0.58", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.58", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" + +[[package]] +name = "web-sys" +version = "0.3.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77afa9a11836342370f4817622a2f0f418b134426d91a82dfb48f532d2ec13ef" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + +[[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", + "quote", + "syn 2.0.58", +] + +[[package]] +name = "zeroize" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4756f7db3f7b5574938c3eb1c117038b8e07f95ee6718c0efad4ac21508f1efd" +dependencies = [ + "zeroize_derive", +] + +[[package]] +name = "zeroize_derive" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.58", +] diff --git a/examples/oapp-solana-counter/Cargo.toml b/examples/oapp-solana-counter/Cargo.toml new file mode 100644 index 0000000000..bf5f2391b2 --- /dev/null +++ b/examples/oapp-solana-counter/Cargo.toml @@ -0,0 +1,14 @@ +[workspace] +members = [ + "programs/*", +] + +[profile.release] +overflow-checks = true +lto = "fat" +codegen-units = 20 + +[profile.release.build-override] +opt-level = 0 +incremental = false +codegen-units = 20 \ No newline at end of file diff --git a/examples/oapp-solana-counter/ordered-execution-implementation.md b/examples/oapp-solana-counter/ordered-execution-implementation.md new file mode 100644 index 0000000000..a82ad3d387 --- /dev/null +++ b/examples/oapp-solana-counter/ordered-execution-implementation.md @@ -0,0 +1,284 @@ +# Implementing Ordered Execution in OApp + +## Overview + +This document outlines how to implement ordered message execution in a LayerZero OApp on Solana. Ordered execution ensures that messages from a specific source are processed in the exact sequence they were sent, preventing out-of-order execution which can lead to inconsistent states. + +## Key Implementation Requirements + +To implement ordered execution, an OApp must implement several essential components: + +### 1. The `next_nonce` Instruction + +The cornerstone of ordered execution is the `next_nonce` instruction. This instruction allows offchain executor to determine the next expected nonce for a message from a specific source. All other related instructions exist primarily to support this functionality. + +**Required Implementation**: + +```rust +use crate::*; + +#[derive(Accounts)] +#[instruction(params: NextNonceParams)] +pub struct NextNonce<'info> { + pub oapp: UncheckedAccount<'info>, + #[account( + seeds = [NONCE_SEED, ¶ms.receiver.as_ref(), ¶ms.src_eid.to_be_bytes(), ¶ms.sender], + bump = nonce_account.bump + )] + pub nonce_account: Account<'info, Nonce>, +} + +impl NextNonce<'_> { + pub fn apply(ctx: &Context, _params: &NextNonceParams) -> Result { + return Ok(ctx.accounts.nonce_account.max_received_nonce + 1); + // return Ok(0); // path nonce starts from 1. if 0 it means that there is no specific nonce enforcement + } +} + +#[derive(Clone, AnchorSerialize, AnchorDeserialize)] +pub struct NextNonceParams { + pub src_eid: u32, + pub sender: [u8; 32], + pub receiver: Pubkey, +} +``` + +**Critical Requirements**: + +1. The `NextNonceParams` struct must be defined exactly as shown, with fields in this precise order. This structure cannot be modified as offchain executor relies on this exact definition. +2. The `next_nonce` instruction structure must include exactly 2 accounts in this specific order: + + - First account: OApp PDA (receiver) - can be an unchecked account if not used + - Second account: Nonce account PDA + +3. The instruction must return `Result` with the next expected nonce value. + +### 2. Nonce Account + +#### 2.1 PDA Seed Structure + +The Nonce account PDA must use these specific seeds in this exact order: + +```rust +seeds = [NONCE_SEED, ¶ms.receiver.as_ref(), ¶ms.src_eid.to_be_bytes(), ¶ms.sender] +``` + +Where: + +- `NONCE_SEED` is a constant byte array (e.g., b"Nonce") +- `params.receiver` is the receiver's public key (32 bytes) +- `params.src_eid` is the source endpoint ID (as bytes) +- `params.sender` is the sender's address (32 bytes) + +**Critical Note**: This precise seed structure is essential for the offchain executor to derive the nonce account correctly. Any changes to this structure would prevent offchain executor from calling the `next_nonce` instruction properly. + +#### 2.2 Account Structure + +The internal structure of the Nonce account is flexible. The only requirement is that it must store a value representing the current maximum nonce. How this value is stored and what additional fields exist in the account is up to the OApp implementation. + +For example, your Nonce account might look like: + +```rust +pub struct Nonce { + // You can include any fields needed for your application + // The only requirement is to have a field storing the max nonce + pub max_received_nonce: u64, // This field name can be different in your implementation +} +``` + +What matters is that the `next_nonce` instruction can read the current maximum nonce value, increment it, and return it as a `u64`. + +### 3. The `skip_inbound_nonce` Instruction + +This instruction allows administrators to handle missing messages by advancing the nonce counter: + +```rust +use oapp::endpoint::{instructions::SkipParams, ID as ENDPOINT_ID}; + +use crate::*; + +#[derive(Accounts)] +#[instruction(params: SkipInboundNonceParams)] +pub struct SkipInboundNonce<'info> { + // .... Add additional accounts as needed for your OApp + #[account( + mut, + seeds = [NONCE_SEED, ¶ms.receiver.as_ref(), ¶ms.src_eid.to_be_bytes(), ¶ms.sender], + bump = nonce_account.bump + )] + pub nonce_account: Account<'info, Nonce>, +} + +impl SkipInboundNonce<'_> { + pub fn apply( + ctx: &mut Context, + params: &SkipInboundNonceParams, + ) -> Result<()> { + // .... OApp-specific business logic + let _ = oapp::endpoint_cpi::skip_nonce( + ENDPOINT_ID, + ctx.remaining_accounts, + seeds, + SkipParams { + receiver: params.receiver, + src_eid: params.src_eid, + sender: params.sender, + nonce: params.nonce, + }, + )?; + + // Update the max nonce value in your Nonce account + // This line will vary based on your Nonce account's structure + ctx.accounts.nonce_account.max_received_nonce += 1; + + return Ok(()); + } +} + +#[derive(Clone, AnchorSerialize, AnchorDeserialize)] +pub struct SkipInboundNonceParams { + pub receiver: Pubkey, + pub src_eid: u32, + pub sender: [u8; 32], + pub nonce: u64, +} +``` + +**Implementation Requirements**: + +1. Must call the endpoint's `skip_nonce` CPI +2. Must update the maximum nonce value in the nonce account + +### 4. Nonce Validation in `lz_receive` + +Your OApp must validate and update nonces in the `lz_receive` instruction. This is typically done with a helper function similar to: + +```rust +fn accept_nonce<'info>(nonce_acc: &mut Account<'info, Nonce>, nonce: u64) -> Result<()> { + // Access your nonce account's maximum nonce value + // This might look different depending on your Nonce account structure + let current_nonce = nonce_acc.max_received_nonce; + + // enforce strict ordering + require!(nonce == current_nonce + 1, ErrorCode::InvalidNonce); + + // Always update the max nonce if the new one is greater + if nonce > current_nonce { + nonce_acc.max_received_nonce = nonce; + } + + Ok(()) +} +``` + +**Critical Note**: This function must be called in the `lz_receive` instruction to ensure the nonce state is correctly maintained. Without proper nonce updates, the `next_nonce` instruction would return incorrect values, leading to message delivery failures or out-of-order execution. + +## Implementation Steps + +Here are the general steps needed to implement ordered execution in your OApp: + +1. **Create Nonce Account Structure**: + + - Define a Nonce account structure with a field to store the maximum received nonce + - The specific structure is flexible as long as it can store the max nonce value + +2. **Implement Required Instructions**: + + - Implement `next_nonce` with the exact parameter and account structure + - Implement `skip_inbound_nonce` for administrative recovery + +3. **Update Message Receiving Logic**: + + - Add nonce validation to your `lz_receive` implementation + - Ensure your `lz_receive` instruction validates and updates nonces + - Add proper error handling for invalid nonces + +4. **Add Account Derivation in Types Instruction**: + - Update your `lz_receive_types` instruction to include the nonce account with the proper seed derivation + +## Offchain Workflow with LayerZero + +When a message includes the `ExecutorOrderedExecutionOption`, the LayerZero Executor will call the `next_nonce` instruction before delivering a message to determine if it should be executed. The Executor checks if the message's nonce matches the next expected nonce (returned by `next_nonce`). If it matches or if ordered execution is disabled (when `next_nonce` returns 0), the message is delivered immediately. Otherwise, the message is queued for later delivery. + +> Reference: https://docs.layerzero.network/v2/developers/evm/oapp/message-design-patterns#message-ordering + +## Example: Omnicounter Implementation + +The following is an example of how ordered execution is implemented in the Omnicounter app: + +### 1. State Structures + +```rust +pub struct Count { + // ... other fields + pub ordered_nonce: bool, // Flag to enable/disable ordered execution +} + +// This is just one possible implementation of the Nonce account +pub struct Nonce { + pub bump: u8, + pub max_received_nonce: u64, // Tracks the highest received nonce +} +``` + +### 2. NextNonce Implementation + +```rust +#[derive(Accounts)] +#[instruction(params: NextNonceParams)] +pub struct NextNonce<'info> { + #[account( + seeds = [COUNT_SEED, &count.id.to_be_bytes()], + bump = count.bump, + constraint = params.receiver == count.key() + )] + pub count: Account<'info, Count>, + #[account( + seeds = [NONCE_SEED, ¶ms.receiver.as_ref(), ¶ms.src_eid.to_be_bytes(), ¶ms.sender], + bump = nonce_account.bump + )] + pub nonce_account: Account<'info, Nonce>, +} + +impl NextNonce<'_> { + pub fn apply(ctx: &Context, _params: &NextNonceParams) -> Result { + if ctx.accounts.count.ordered_nonce { + return Ok(ctx.accounts.nonce_account.max_received_nonce + 1); + } + return Ok(0); // Return 0 if ordered mode is disabled + } +} +``` + +### 3. Message Receiving Logic + +```rust +impl LzReceive<'_> { + pub fn apply(ctx: &mut Context, params: &LzReceiveParams) -> Result<()> { + // ... handle message clearing ... + + // Validate and update nonce + accept_nonce(&ctx.accounts.count, &mut ctx.accounts.nonce_account, params.nonce)?; + + // ... process message ... + Ok(()) + } +} + +fn accept_nonce<'info>( + count_acc: &Account<'info, Count>, + nonce_acc: &mut Account<'info, Nonce>, + nonce: u64, +) -> Result<()> { + let current_nonce = nonce_acc.max_received_nonce; + if count_acc.ordered_nonce { + require!(nonce == current_nonce + 1, CounterError::InvalidNonce); + } + if nonce > current_nonce { + nonce_acc.max_received_nonce = nonce; + } + Ok(()) +} +``` + +This example shows how the Omnicounter app implements the required components while adding application-specific logic (like the `ordered_nonce` flag for toggling the feature). diff --git a/examples/oapp-solana-counter/package.json b/examples/oapp-solana-counter/package.json new file mode 100644 index 0000000000..4991c102d0 --- /dev/null +++ b/examples/oapp-solana-counter/package.json @@ -0,0 +1,39 @@ +{ + "name": "@layerzerolabs/counter-v2-solana", + "private": true, + "license": "BUSL-1.1", + "exports": { + ".": { + "types": "./dist/index.d.ts", + "import": "./dist/index.mjs", + "require": "./dist/index.cjs" + }, + "./package.json": "./package.json" + }, + "main": "./dist/index.cjs", + "types": "./dist/index.d.ts", + "scripts": { + "build": "$npm_execpath clean-prebuild && anchor build", + "clean": "$npm_execpath clean-prebuild", + "clean-prebuild": "rimraf target", + "test": "cargo-test-sbf" + }, + "devDependencies": { + "rimraf": "^5.0.5" + }, + "ensureVersions": { + "envFiles": [ + "$PROJECT_CWD/.versions" + ], + "executables": { + "solana": [ + "echo env:SOLANA_VERSION", + "solana --version | awk '{print $2}'" + ], + "anchor": [ + "echo env:ANCHOR_VERSION", + "anchor --version | awk '{print $2}'" + ] + } + } +} diff --git a/examples/oapp-solana-counter/programs/counter/Cargo.toml b/examples/oapp-solana-counter/programs/counter/Cargo.toml new file mode 100644 index 0000000000..10e0130954 --- /dev/null +++ b/examples/oapp-solana-counter/programs/counter/Cargo.toml @@ -0,0 +1,22 @@ +[package] +name = "omnicounter" +version = "0.1.0" +description = "Created with Anchor" +edition = "2021" + +[lib] +crate-type = ["cdylib", "lib"] +name = "omnicounter" + +[features] +no-entrypoint = [] +no-idl = [] +no-log-ix-name = [] +cpi = ["no-entrypoint"] +default = [] +idl-build = ["oapp/idl-build"] + +[dependencies] +anchor-lang = { version = "0.29.0", features = ["init-if-needed"] } +solana-helper = "0.1.0" +oapp = { path = "../../../../../../../packages/layerzero-v2/solana/contracts/libs/oapp" } diff --git a/examples/oapp-solana-counter/programs/counter/Xargo.toml b/examples/oapp-solana-counter/programs/counter/Xargo.toml new file mode 100644 index 0000000000..475fb71ed1 --- /dev/null +++ b/examples/oapp-solana-counter/programs/counter/Xargo.toml @@ -0,0 +1,2 @@ +[target.bpfel-unknown-unknown.dependencies.std] +features = [] diff --git a/examples/oapp-solana-counter/programs/counter/build.rs b/examples/oapp-solana-counter/programs/counter/build.rs new file mode 100644 index 0000000000..3a907a13c6 --- /dev/null +++ b/examples/oapp-solana-counter/programs/counter/build.rs @@ -0,0 +1,3 @@ +fn main() { + println!("cargo:rerun-if-env-changed=OMNICOUNTER_ID"); +} diff --git a/examples/oapp-solana-counter/programs/counter/readme.md b/examples/oapp-solana-counter/programs/counter/readme.md new file mode 100644 index 0000000000..a4c57371f8 --- /dev/null +++ b/examples/oapp-solana-counter/programs/counter/readme.md @@ -0,0 +1 @@ +### solana counter program diff --git a/examples/oapp-solana-counter/programs/counter/src/errors.rs b/examples/oapp-solana-counter/programs/counter/src/errors.rs new file mode 100644 index 0000000000..73048734dd --- /dev/null +++ b/examples/oapp-solana-counter/programs/counter/src/errors.rs @@ -0,0 +1,7 @@ +use anchor_lang::prelude::error_code; + +#[error_code] +pub enum CounterError { + InvalidMessageType, + InvalidNonce, +} diff --git a/examples/oapp-solana-counter/programs/counter/src/instructions/increment.rs b/examples/oapp-solana-counter/programs/counter/src/instructions/increment.rs new file mode 100644 index 0000000000..605d28ce7c --- /dev/null +++ b/examples/oapp-solana-counter/programs/counter/src/instructions/increment.rs @@ -0,0 +1,56 @@ +use crate::*; +use anchor_lang::prelude::*; +use oapp::endpoint::{ + instructions::SendParams, state::EndpointSettings, ENDPOINT_SEED, ID as ENDPOINT_ID, +}; + +#[derive(Accounts)] +#[instruction(params: IncrementParams)] +pub struct Increment<'info> { + #[account( + seeds = [ + PEER_SEED, + &count.key().to_bytes(), + ¶ms.dst_eid.to_be_bytes() + ], + bump = peer.bump + )] + pub peer: Account<'info, Peer>, + #[account(seeds = [COUNT_SEED, &count.id.to_be_bytes()], bump = count.bump)] + pub count: Account<'info, Count>, + #[account(seeds = [ENDPOINT_SEED], bump = endpoint.bump, seeds::program = ENDPOINT_ID)] + pub endpoint: Account<'info, EndpointSettings>, +} +impl<'info> Increment<'info> { + pub fn apply(ctx: &mut Context, params: &IncrementParams) -> Result<()> { + let message = msg_codec::encode(params.msg_type, ctx.accounts.endpoint.eid); + let seeds: &[&[u8]] = &[COUNT_SEED, &[ctx.accounts.count.id], &[ctx.accounts.count.bump]]; + + // calling endpoint cpi + let send_params = SendParams { + dst_eid: params.dst_eid, + receiver: ctx.accounts.peer.address, + message, + options: params.options.clone(), + native_fee: params.native_fee, + lz_token_fee: params.lz_token_fee, + }; + oapp::endpoint_cpi::send( + ENDPOINT_ID, + ctx.accounts.count.key(), + ctx.remaining_accounts, + seeds, + send_params, + )?; + Ok(()) + } +} + +#[derive(Clone, AnchorSerialize, AnchorDeserialize)] +pub struct IncrementParams { + pub dst_eid: u32, + pub msg_type: u8, + pub options: Vec, + pub native_fee: u64, + pub lz_token_fee: u64, +} diff --git a/examples/oapp-solana-counter/programs/counter/src/instructions/init_count.rs b/examples/oapp-solana-counter/programs/counter/src/instructions/init_count.rs new file mode 100644 index 0000000000..a7b086c548 --- /dev/null +++ b/examples/oapp-solana-counter/programs/counter/src/instructions/init_count.rs @@ -0,0 +1,68 @@ +use crate::*; +use oapp::endpoint::{instructions::RegisterOAppParams, ID as ENDPOINT_ID}; + +#[derive(Accounts)] +#[instruction(params: InitCountParams)] +pub struct InitCount<'info> { + #[account(mut)] + pub payer: Signer<'info>, + #[account( + init, + payer = payer, + space = Count::SIZE, + seeds = [COUNT_SEED, ¶ms.id.to_be_bytes()], + bump + )] + pub count: Account<'info, Count>, + #[account( + init, + payer = payer, + space = LzReceiveTypesAccounts::SIZE, + seeds = [LZ_RECEIVE_TYPES_SEED, &count.key().to_bytes()], + bump + )] + pub lz_receive_types_accounts: Account<'info, LzReceiveTypesAccounts>, + #[account( + init, + payer = payer, + space = LzComposeTypesAccounts::SIZE, + seeds = [LZ_COMPOSE_TYPES_SEED, &count.key().to_bytes()], + bump + )] + pub lz_compose_types_accounts: Account<'info, LzComposeTypesAccounts>, + pub system_program: Program<'info, System>, +} + +impl InitCount<'_> { + pub fn apply(ctx: &mut Context, params: &InitCountParams) -> Result<()> { + ctx.accounts.count.id = params.id; + ctx.accounts.count.admin = params.admin; + ctx.accounts.count.bump = ctx.bumps.count; + ctx.accounts.count.endpoint_program = params.endpoint; + ctx.accounts.count.ordered_nonce = params.ordered_nonce; + + ctx.accounts.lz_receive_types_accounts.count = ctx.accounts.count.key(); + ctx.accounts.lz_compose_types_accounts.count = ctx.accounts.count.key(); + + // calling endpoint cpi + let register_params = RegisterOAppParams { delegate: ctx.accounts.count.admin }; + let seeds: &[&[u8]] = &[COUNT_SEED, &[ctx.accounts.count.id], &[ctx.accounts.count.bump]]; + oapp::endpoint_cpi::register_oapp( + ENDPOINT_ID, + ctx.accounts.count.key(), + ctx.remaining_accounts, + seeds, + register_params, + )?; + + Ok(()) + } +} + +#[derive(Clone, AnchorSerialize, AnchorDeserialize)] +pub struct InitCountParams { + pub id: u8, + pub admin: Pubkey, + pub endpoint: Pubkey, + pub ordered_nonce: bool, +} diff --git a/examples/oapp-solana-counter/programs/counter/src/instructions/lz_compose.rs b/examples/oapp-solana-counter/programs/counter/src/instructions/lz_compose.rs new file mode 100644 index 0000000000..9369acd9c1 --- /dev/null +++ b/examples/oapp-solana-counter/programs/counter/src/instructions/lz_compose.rs @@ -0,0 +1,34 @@ +use crate::*; +use anchor_lang::prelude::*; +use oapp::{ + endpoint::{instructions::ClearComposeParams, ID as ENDPOINT_ID}, + LzComposeParams, +}; + +#[derive(Accounts)] +pub struct LzCompose<'info> { + #[account(mut, seeds = [COUNT_SEED, &count.id.to_be_bytes()], bump = count.bump)] + pub count: Account<'info, Count>, +} + +impl LzCompose<'_> { + pub fn apply(ctx: &mut Context, params: &LzComposeParams) -> Result<()> { + ctx.accounts.count.composed_count += 1; + + let seeds: &[&[u8]] = + &[COUNT_SEED, &ctx.accounts.count.id.to_be_bytes(), &[ctx.accounts.count.bump]]; + let params = ClearComposeParams { + from: params.from, + guid: params.guid, + index: params.index, + message: params.message.clone(), + }; + oapp::endpoint_cpi::clear_compose( + ENDPOINT_ID, + ctx.accounts.count.key(), + &ctx.remaining_accounts, + seeds, + params, + ) + } +} diff --git a/examples/oapp-solana-counter/programs/counter/src/instructions/lz_compose_types.rs b/examples/oapp-solana-counter/programs/counter/src/instructions/lz_compose_types.rs new file mode 100644 index 0000000000..6d7c71b36b --- /dev/null +++ b/examples/oapp-solana-counter/programs/counter/src/instructions/lz_compose_types.rs @@ -0,0 +1,43 @@ +use crate::*; +use oapp::endpoint_cpi::{get_accounts_for_clear_compose, LzAccount}; +use oapp::{endpoint::ID as ENDPOINT_ID, LzComposeParams}; + +/// LzComposeTypes instruction provides a list of accounts that are used in the LzCompose +/// instruction. The list of accounts required by this LzComposeTypes instruction can be found +/// from the specific PDA account that is generated by the LZ_COMPOSE_TYPES_SEED. +#[derive(Accounts)] +pub struct LzComposeTypes<'info> { + #[account(seeds = [COUNT_SEED, &count.id.to_be_bytes()], bump = count.bump)] + pub count: Account<'info, Count>, +} + +impl LzComposeTypes<'_> { + /// The list of accounts should follow the rules below: + /// 1. Include all the accounts that are used in the LzCompose instruction, including the + /// accounts that are used by the Endpoint program. + /// 2. Set the account is a signer with ZERO address if the LzCompose instruction needs a payer + /// to pay fee, like rent. + /// 3. Set the account is writable if the LzCompose instruction needs to modify the account. + pub fn apply( + ctx: &Context, + params: &LzComposeParams, + ) -> Result> { + let mut accounts = vec![ + // count + LzAccount { pubkey: ctx.accounts.count.key(), is_signer: false, is_writable: true }, + ]; + + let accounts_for_composing = get_accounts_for_clear_compose( + ENDPOINT_ID, + ¶ms.from, + &ctx.accounts.count.key(), // self + ¶ms.guid, + params.index, + ¶ms.message, + ); + + accounts.extend(accounts_for_composing); + + Ok(accounts) + } +} diff --git a/examples/oapp-solana-counter/programs/counter/src/instructions/lz_receive.rs b/examples/oapp-solana-counter/programs/counter/src/instructions/lz_receive.rs new file mode 100644 index 0000000000..cad1e603aa --- /dev/null +++ b/examples/oapp-solana-counter/programs/counter/src/instructions/lz_receive.rs @@ -0,0 +1,95 @@ +use crate::*; +use anchor_lang::prelude::*; +use oapp::{ + endpoint::{ + cpi::accounts::Clear, + instructions::{ClearParams, SendComposeParams}, + ConstructCPIContext, ID as ENDPOINT_ID, + }, + LzReceiveParams, +}; + +#[derive(Accounts)] +#[instruction(params: LzReceiveParams)] +pub struct LzReceive<'info> { + #[account(mut, seeds = [COUNT_SEED, &count.id.to_be_bytes()], bump = count.bump)] + pub count: Account<'info, Count>, + #[account( + seeds = [PEER_SEED, &count.key().to_bytes(), ¶ms.src_eid.to_be_bytes()], + bump = peer.bump, + constraint = params.sender == peer.address + )] + pub peer: Account<'info, Peer>, + #[account( + mut, + seeds = [NONCE_SEED, &count.key().to_bytes(), ¶ms.src_eid.to_be_bytes(), ¶ms.sender], + bump = nonce_account.bump + )] + pub nonce_account: Account<'info, Nonce>, +} + +impl LzReceive<'_> { + pub fn apply(ctx: &mut Context, params: &LzReceiveParams) -> Result<()> { + let seeds: &[&[u8]] = + &[COUNT_SEED, &ctx.accounts.count.id.to_be_bytes(), &[ctx.accounts.count.bump]]; + + // the first 9 accounts are for clear() + let accounts_for_clear = &ctx.remaining_accounts[0..Clear::MIN_ACCOUNTS_LEN]; + let _ = oapp::endpoint_cpi::clear( + ENDPOINT_ID, + ctx.accounts.count.key(), + accounts_for_clear, + seeds, + ClearParams { + receiver: ctx.accounts.count.key(), + src_eid: params.src_eid, + sender: params.sender, + nonce: params.nonce, + guid: params.guid, + message: params.message.clone(), + }, + )?; + + accept_nonce(&ctx.accounts.count, &mut ctx.accounts.nonce_account, params.nonce)?; + + let msg_type = msg_codec::msg_type(¶ms.message); + match msg_type { + msg_codec::VANILLA_TYPE => ctx.accounts.count.count += 1, + msg_codec::COMPOSED_TYPE => { + ctx.accounts.count.count += 1; + + oapp::endpoint_cpi::send_compose( + ENDPOINT_ID, + ctx.accounts.count.key(), + &ctx.remaining_accounts[Clear::MIN_ACCOUNTS_LEN..], + seeds, + SendComposeParams { + to: ctx.accounts.count.key(), // self + guid: params.guid, + index: 0, + message: params.message.clone(), + }, + )?; + }, + // ABA_TYPE & COMPOSED_ABA_TYPE are not supported + _ => return Err(CounterError::InvalidMessageType.into()), + } + Ok(()) + } +} + +fn accept_nonce<'info>( + count_acc: &Account<'info, Count>, + nonce_acc: &mut Account<'info, Nonce>, + nonce: u64, +) -> Result<()> { + let current_nonce = nonce_acc.max_received_nonce; + if count_acc.ordered_nonce { + require!(nonce == current_nonce + 1, CounterError::InvalidNonce); + } + // update the max nonce anyway. once the ordered mode is turned on, missing early nonces will be rejected + if nonce > current_nonce { + nonce_acc.max_received_nonce = nonce; + } + Ok(()) +} diff --git a/examples/oapp-solana-counter/programs/counter/src/instructions/lz_receive_types.rs b/examples/oapp-solana-counter/programs/counter/src/instructions/lz_receive_types.rs new file mode 100644 index 0000000000..45d7199481 --- /dev/null +++ b/examples/oapp-solana-counter/programs/counter/src/instructions/lz_receive_types.rs @@ -0,0 +1,74 @@ +use crate::*; +use oapp::endpoint_cpi::{get_accounts_for_clear, get_accounts_for_send_compose, LzAccount}; +use oapp::{endpoint::ID as ENDPOINT_ID, LzReceiveParams}; + +/// LzReceiveTypes instruction provides a list of accounts that are used in the LzReceive +/// instruction. The list of accounts required by this LzReceiveTypes instruction can be found +/// from the specific PDA account that is generated by the LZ_RECEIVE_TYPES_SEED. +#[derive(Accounts)] +pub struct LzReceiveTypes<'info> { + #[account(seeds = [COUNT_SEED, &count.id.to_be_bytes()], bump = count.bump)] + pub count: Account<'info, Count>, +} + +impl LzReceiveTypes<'_> { + /// The list of accounts should follow the rules below: + /// 1. Include all the accounts that are used in the LzReceive instruction, including the + /// accounts that are used by the Endpoint program. + /// 2. Set the account is a signer with ZERO address if the LzReceive instruction needs a payer + /// to pay fee, like rent. + /// 3. Set the account is writable if the LzReceive instruction needs to modify the account. + pub fn apply( + ctx: &Context, + params: &LzReceiveParams, + ) -> Result> { + // There are two accounts that are used in the LzReceive instruction, + // except those accounts for endpoint program. + // The first account is the count account, that is the fixed one. + let count = ctx.accounts.count.key(); + + // The second account is the peer account, we find it by the params.src_eid. + let peer_seeds = [PEER_SEED, &count.to_bytes(), ¶ms.src_eid.to_be_bytes()]; + let (peer, _) = Pubkey::find_program_address(&peer_seeds, ctx.program_id); + + // The third account is the nonce account, we find it by the params.src_eid and params.sender. + let nonce_seeds = + [NONCE_SEED, &count.to_bytes(), ¶ms.src_eid.to_be_bytes(), ¶ms.sender]; + let (nonce_account, _) = Pubkey::find_program_address(&nonce_seeds, ctx.program_id); + + let mut accounts = vec![ + // count + LzAccount { pubkey: count, is_signer: false, is_writable: true }, + // peer + LzAccount { pubkey: peer, is_signer: false, is_writable: false }, + // nonce_account + LzAccount { pubkey: nonce_account, is_signer: false, is_writable: true }, + ]; + + // append the accounts for the clear ix + let accounts_for_clear = get_accounts_for_clear( + ENDPOINT_ID, + &count, + params.src_eid, + ¶ms.sender, + params.nonce, + ); + accounts.extend(accounts_for_clear); + + // if the message type is composed, we need to append the accounts for the composing ix + let is_composed = msg_codec::msg_type(¶ms.message) == msg_codec::COMPOSED_TYPE; + if is_composed { + let accounts_for_composing = get_accounts_for_send_compose( + ENDPOINT_ID, + &count, + &count, // self + ¶ms.guid, + 0, + ¶ms.message, + ); + accounts.extend(accounts_for_composing); + } + + Ok(accounts) + } +} diff --git a/examples/oapp-solana-counter/programs/counter/src/instructions/mod.rs b/examples/oapp-solana-counter/programs/counter/src/instructions/mod.rs new file mode 100644 index 0000000000..51e04fb319 --- /dev/null +++ b/examples/oapp-solana-counter/programs/counter/src/instructions/mod.rs @@ -0,0 +1,23 @@ +pub mod increment; +pub mod init_count; +pub mod lz_compose; +pub mod lz_compose_types; +pub mod lz_receive; +pub mod lz_receive_types; +pub mod next_nonce; +pub mod quote; +pub mod set_ordered_nonce; +pub mod set_peer; +pub mod skip_inbound_nonce; + +pub use increment::*; +pub use init_count::*; +pub use lz_compose::*; +pub use lz_compose_types::*; +pub use lz_receive::*; +pub use lz_receive_types::*; +pub use next_nonce::*; +pub use quote::*; +pub use set_ordered_nonce::*; +pub use set_peer::*; +pub use skip_inbound_nonce::*; diff --git a/examples/oapp-solana-counter/programs/counter/src/instructions/next_nonce.rs b/examples/oapp-solana-counter/programs/counter/src/instructions/next_nonce.rs new file mode 100644 index 0000000000..ffc97420c2 --- /dev/null +++ b/examples/oapp-solana-counter/programs/counter/src/instructions/next_nonce.rs @@ -0,0 +1,33 @@ +use crate::*; + +#[derive(Accounts)] +#[instruction(params: NextNonceParams)] +pub struct NextNonce<'info> { + #[account( + seeds = [COUNT_SEED, &count.id.to_be_bytes()], + bump = count.bump, + constraint = params.receiver == count.key() + )] + pub count: Account<'info, Count>, + #[account( + seeds = [NONCE_SEED, ¶ms.receiver.as_ref(), ¶ms.src_eid.to_be_bytes(), ¶ms.sender], + bump = nonce_account.bump + )] + pub nonce_account: Account<'info, Nonce>, +} + +impl NextNonce<'_> { + pub fn apply(ctx: &Context, _params: &NextNonceParams) -> Result { + if ctx.accounts.count.ordered_nonce { + return Ok(ctx.accounts.nonce_account.max_received_nonce + 1); + } + return Ok(0); // path nonce starts from 1. if 0 it means that there is no specific nonce enforcement + } +} + +#[derive(Clone, AnchorSerialize, AnchorDeserialize)] +pub struct NextNonceParams { + pub src_eid: u32, + pub sender: [u8; 32], + pub receiver: Pubkey, +} diff --git a/examples/oapp-solana-counter/programs/counter/src/instructions/quote.rs b/examples/oapp-solana-counter/programs/counter/src/instructions/quote.rs new file mode 100644 index 0000000000..9d9af2af8a --- /dev/null +++ b/examples/oapp-solana-counter/programs/counter/src/instructions/quote.rs @@ -0,0 +1,40 @@ +use crate::*; +use anchor_lang::prelude::*; +use oapp::endpoint::{ + instructions::QuoteParams as EndpointQuoteParams, state::EndpointSettings, ENDPOINT_SEED, + ID as ENDPOINT_ID, +}; + +#[derive(Accounts)] +#[instruction(params: QuoteParams)] +pub struct Quote<'info> { + #[account(seeds = [COUNT_SEED, &count.id.to_be_bytes()], bump = count.bump)] + pub count: Account<'info, Count>, + #[account(seeds = [ENDPOINT_SEED], bump = endpoint.bump, seeds::program = ENDPOINT_ID)] + pub endpoint: Account<'info, EndpointSettings>, +} +impl<'info> Quote<'info> { + pub fn apply(ctx: &Context, params: &QuoteParams) -> Result { + let message = msg_codec::encode(params.msg_type, ctx.accounts.endpoint.eid); + + // calling endpoint cpi + let quote_params = EndpointQuoteParams { + sender: ctx.accounts.count.key(), + dst_eid: params.dst_eid, + receiver: params.receiver, + message, + pay_in_lz_token: params.pay_in_lz_token, + options: params.options.clone(), + }; + oapp::endpoint_cpi::quote(ENDPOINT_ID, ctx.remaining_accounts, quote_params) + } +} + +#[derive(Clone, AnchorSerialize, AnchorDeserialize)] +pub struct QuoteParams { + pub dst_eid: u32, + pub receiver: [u8; 32], + pub msg_type: u8, + pub options: Vec, + pub pay_in_lz_token: bool, +} diff --git a/examples/oapp-solana-counter/programs/counter/src/instructions/set_ordered_nonce.rs b/examples/oapp-solana-counter/programs/counter/src/instructions/set_ordered_nonce.rs new file mode 100644 index 0000000000..5594249fc3 --- /dev/null +++ b/examples/oapp-solana-counter/programs/counter/src/instructions/set_ordered_nonce.rs @@ -0,0 +1,22 @@ +use crate::*; + +#[derive(Accounts)] +#[instruction(params: SetOrderedNonceParams)] +pub struct SetOrderedNonce<'info> { + #[account(address = count.admin)] + pub admin: Signer<'info>, + #[account(mut, seeds = [COUNT_SEED, &count.id.to_be_bytes()], bump = count.bump)] + pub count: Account<'info, Count>, +} + +impl SetOrderedNonce<'_> { + pub fn apply(ctx: &mut Context, params: &SetOrderedNonceParams) -> Result<()> { + ctx.accounts.count.ordered_nonce = params.ordered_nonce; + Ok(()) + } +} + +#[derive(Clone, AnchorSerialize, AnchorDeserialize)] +pub struct SetOrderedNonceParams { + pub ordered_nonce: bool, +} diff --git a/examples/oapp-solana-counter/programs/counter/src/instructions/set_peer.rs b/examples/oapp-solana-counter/programs/counter/src/instructions/set_peer.rs new file mode 100644 index 0000000000..58c7db0605 --- /dev/null +++ b/examples/oapp-solana-counter/programs/counter/src/instructions/set_peer.rs @@ -0,0 +1,44 @@ +use crate::*; +use anchor_lang::prelude::*; + +#[derive(Accounts)] +#[instruction(params: SetPeerParams)] +pub struct SetPeer<'info> { + #[account(mut, address = count.admin)] + pub admin: Signer<'info>, + #[account( + init_if_needed, + payer = admin, + space = Peer::SIZE, + seeds = [PEER_SEED, &count.key().to_bytes(), ¶ms.remote_eid.to_be_bytes()], + bump + )] + pub peer: Account<'info, Peer>, + #[account( + init_if_needed, + payer = admin, + space = Nonce::SIZE, + seeds = [NONCE_SEED, &count.key().to_bytes(), ¶ms.remote_eid.to_be_bytes(), ¶ms.peer], + bump + )] + pub nonce_account: Account<'info, Nonce>, + #[account(seeds = [COUNT_SEED, &count.id.to_be_bytes()], bump = count.bump)] + pub count: Account<'info, Count>, + pub system_program: Program<'info, System>, +} + +impl SetPeer<'_> { + pub fn apply(ctx: &mut Context, params: &SetPeerParams) -> Result<()> { + ctx.accounts.peer.address = params.peer; + ctx.accounts.peer.bump = ctx.bumps.peer; + ctx.accounts.nonce_account.bump = ctx.bumps.nonce_account; + Ok(()) + } +} + +#[derive(Clone, AnchorSerialize, AnchorDeserialize)] +pub struct SetPeerParams { + pub id: u8, + pub remote_eid: u32, + pub peer: [u8; 32], +} diff --git a/examples/oapp-solana-counter/programs/counter/src/instructions/skip_inbound_nonce.rs b/examples/oapp-solana-counter/programs/counter/src/instructions/skip_inbound_nonce.rs new file mode 100644 index 0000000000..a08285999a --- /dev/null +++ b/examples/oapp-solana-counter/programs/counter/src/instructions/skip_inbound_nonce.rs @@ -0,0 +1,52 @@ +use oapp::endpoint::{instructions::SkipParams, ID as ENDPOINT_ID}; + +use crate::*; + +#[derive(Accounts)] +#[instruction(params: SkipInboundNonceParams)] +pub struct SkipInboundNonce<'info> { + #[account(address = count.admin)] + pub admin: Signer<'info>, + #[account(seeds = [COUNT_SEED, &count.id.to_be_bytes()], bump = count.bump)] + pub count: Account<'info, Count>, + #[account( + mut, + seeds = [NONCE_SEED, ¶ms.receiver.as_ref(), ¶ms.src_eid.to_be_bytes(), ¶ms.sender], + bump = nonce_account.bump + )] + pub nonce_account: Account<'info, Nonce>, +} + +impl SkipInboundNonce<'_> { + pub fn apply( + ctx: &mut Context, + params: &SkipInboundNonceParams, + ) -> Result<()> { + let seeds: &[&[u8]] = + &[COUNT_SEED, &ctx.accounts.count.id.to_be_bytes(), &[ctx.accounts.count.bump]]; + + let _ = oapp::endpoint_cpi::skip_nonce( + ENDPOINT_ID, + ctx.remaining_accounts, + seeds, + SkipParams { + receiver: params.receiver, + src_eid: params.src_eid, + sender: params.sender, + nonce: params.nonce, + }, + )?; + if ctx.accounts.count.ordered_nonce { + ctx.accounts.nonce_account.max_received_nonce += 1; + } + return Ok(()); + } +} + +#[derive(Clone, AnchorSerialize, AnchorDeserialize)] +pub struct SkipInboundNonceParams { + pub receiver: Pubkey, + pub src_eid: u32, + pub sender: [u8; 32], + pub nonce: u64, +} diff --git a/examples/oapp-solana-counter/programs/counter/src/lib.rs b/examples/oapp-solana-counter/programs/counter/src/lib.rs new file mode 100644 index 0000000000..f52940a412 --- /dev/null +++ b/examples/oapp-solana-counter/programs/counter/src/lib.rs @@ -0,0 +1,83 @@ +mod errors; +mod instructions; +mod msg_codec; +mod state; + +use anchor_lang::prelude::*; +use errors::*; +use instructions::*; +use oapp::{endpoint::MessagingFee, endpoint_cpi::LzAccount, LzComposeParams, LzReceiveParams}; +use solana_helper::program_id_from_env; +use state::*; + +declare_id!(anchor_lang::solana_program::pubkey::Pubkey::new_from_array(program_id_from_env!( + "OMNICOUNTER_ID", + "HFyiETGKEUS9tr87K1HXmVJHkqQRtw8wShRNTMkKKxay" +))); + +const LZ_RECEIVE_TYPES_SEED: &[u8] = b"LzReceiveTypes"; +const LZ_COMPOSE_TYPES_SEED: &[u8] = b"LzComposeTypes"; +const COUNT_SEED: &[u8] = b"Count"; +const PEER_SEED: &[u8] = b"Peer"; +const NONCE_SEED: &[u8] = b"Nonce"; + +#[program] +pub mod omnicounter { + use super::*; + + pub fn init_count(mut ctx: Context, params: InitCountParams) -> Result<()> { + InitCount::apply(&mut ctx, ¶ms) + } + + pub fn set_peer(mut ctx: Context, params: SetPeerParams) -> Result<()> { + SetPeer::apply(&mut ctx, ¶ms) + } + + pub fn quote(ctx: Context, params: QuoteParams) -> Result { + Quote::apply(&ctx, ¶ms) + } + + pub fn increment(mut ctx: Context, params: IncrementParams) -> Result<()> { + Increment::apply(&mut ctx, ¶ms) + } + + pub fn lz_receive(mut ctx: Context, params: LzReceiveParams) -> Result<()> { + LzReceive::apply(&mut ctx, ¶ms) + } + + pub fn lz_receive_types( + ctx: Context, + params: LzReceiveParams, + ) -> Result> { + LzReceiveTypes::apply(&ctx, ¶ms) + } + + pub fn lz_compose(mut ctx: Context, params: LzComposeParams) -> Result<()> { + LzCompose::apply(&mut ctx, ¶ms) + } + + pub fn lz_compose_types( + ctx: Context, + params: LzComposeParams, + ) -> Result> { + LzComposeTypes::apply(&ctx, ¶ms) + } + + pub fn next_nonce(ctx: Context, params: NextNonceParams) -> Result { + NextNonce::apply(&ctx, ¶ms) + } + + pub fn skip_inbound_nonce( + mut ctx: Context, + params: SkipInboundNonceParams, + ) -> Result<()> { + SkipInboundNonce::apply(&mut ctx, ¶ms) + } + + pub fn set_ordered_nonce( + mut ctx: Context, + params: SetOrderedNonceParams, + ) -> Result<()> { + SetOrderedNonce::apply(&mut ctx, ¶ms) + } +} diff --git a/examples/oapp-solana-counter/programs/counter/src/msg_codec.rs b/examples/oapp-solana-counter/programs/counter/src/msg_codec.rs new file mode 100644 index 0000000000..388eff2a09 --- /dev/null +++ b/examples/oapp-solana-counter/programs/counter/src/msg_codec.rs @@ -0,0 +1,25 @@ +pub const VANILLA_TYPE: u8 = 1; +pub const COMPOSED_TYPE: u8 = 2; +// ABA_TYPE & COMPOSED_ABA_TYPE are not supported +// pub const ABA_TYPE: u8 = 3; +// pub const COMPOSED_ABA_TYPE: u8 = 4; + +pub const MSG_TYPE_OFFSET: usize = 0; +pub const SRC_EID_OFFSET: usize = 1; + +pub fn encode(msg_type: u8, src_eid: u32) -> Vec { + let mut encoded = Vec::new(); + encoded.push(msg_type); + encoded.extend_from_slice(&src_eid.to_be_bytes()); + encoded +} + +pub fn msg_type(message: &[u8]) -> u8 { + message[MSG_TYPE_OFFSET] +} + +pub fn src_eid(message: &[u8]) -> u32 { + let mut eid_bytes = [0; 4]; + eid_bytes.copy_from_slice(&message[SRC_EID_OFFSET..]); + u32::from_be_bytes(eid_bytes) +} diff --git a/examples/oapp-solana-counter/programs/counter/src/state/count.rs b/examples/oapp-solana-counter/programs/counter/src/state/count.rs new file mode 100644 index 0000000000..c970d8d6a3 --- /dev/null +++ b/examples/oapp-solana-counter/programs/counter/src/state/count.rs @@ -0,0 +1,38 @@ +use crate::*; + +#[account] +pub struct Count { + pub id: u8, + pub admin: Pubkey, + pub count: u64, + pub composed_count: u64, + pub bump: u8, + pub endpoint_program: Pubkey, + pub ordered_nonce: bool, +} + +impl Count { + pub const SIZE: usize = 8 + std::mem::size_of::(); +} + +/// LzReceiveTypesAccounts includes accounts that are used in the LzReceiveTypes +/// instruction. +#[account] +pub struct LzReceiveTypesAccounts { + pub count: Pubkey, +} + +impl LzReceiveTypesAccounts { + pub const SIZE: usize = 8 + std::mem::size_of::(); +} + +/// LzComposeTypesAccounts includes accounts that are used in the LzComposeTypes +/// instruction. +#[account] +pub struct LzComposeTypesAccounts { + pub count: Pubkey, +} + +impl LzComposeTypesAccounts { + pub const SIZE: usize = 8 + std::mem::size_of::(); +} diff --git a/examples/oapp-solana-counter/programs/counter/src/state/mod.rs b/examples/oapp-solana-counter/programs/counter/src/state/mod.rs new file mode 100644 index 0000000000..6720233b3a --- /dev/null +++ b/examples/oapp-solana-counter/programs/counter/src/state/mod.rs @@ -0,0 +1,7 @@ +pub mod count; +mod nonce; +mod peer; + +pub use count::*; +pub use nonce::*; +pub use peer::*; diff --git a/examples/oapp-solana-counter/programs/counter/src/state/nonce.rs b/examples/oapp-solana-counter/programs/counter/src/state/nonce.rs new file mode 100644 index 0000000000..255082b09e --- /dev/null +++ b/examples/oapp-solana-counter/programs/counter/src/state/nonce.rs @@ -0,0 +1,11 @@ +use crate::*; + +#[account] +pub struct Nonce { + pub bump: u8, + pub max_received_nonce: u64, +} + +impl Nonce { + pub const SIZE: usize = 8 + std::mem::size_of::(); +} diff --git a/examples/oapp-solana-counter/programs/counter/src/state/peer.rs b/examples/oapp-solana-counter/programs/counter/src/state/peer.rs new file mode 100644 index 0000000000..1a406c4e8c --- /dev/null +++ b/examples/oapp-solana-counter/programs/counter/src/state/peer.rs @@ -0,0 +1,11 @@ +use crate::*; + +#[account] +pub struct Peer { + pub address: [u8; 32], + pub bump: u8, +} + +impl Peer { + pub const SIZE: usize = 8 + std::mem::size_of::(); +} diff --git a/examples/oapp-solana-counter/rust-toolchain.toml b/examples/oapp-solana-counter/rust-toolchain.toml new file mode 100644 index 0000000000..114aa97509 --- /dev/null +++ b/examples/oapp-solana-counter/rust-toolchain.toml @@ -0,0 +1,5 @@ +[toolchain] +channel = "1.75.0" +# rustup install nightly +# channel = "nightly-2024-02-04" # if you want to expand the macro, you need to use nightly version +components = ["rustfmt", "clippy"] diff --git a/examples/oapp-solana-counter/rustfmt.toml b/examples/oapp-solana-counter/rustfmt.toml new file mode 100644 index 0000000000..e9f667f2e9 --- /dev/null +++ b/examples/oapp-solana-counter/rustfmt.toml @@ -0,0 +1,23 @@ +# Basic +hard_tabs = false +max_width = 100 +use_small_heuristics = "Max" +# Imports +imports_granularity = "Preserve" +reorder_imports = true +# Consistency +newline_style = "Unix" +# Format comments +comment_width = 100 +wrap_comments = true +# Misc +chain_width = 80 +spaces_around_ranges = false +binop_separator = "Front" +reorder_impl_items = false +match_arm_leading_pipes = "Preserve" +match_arm_blocks = true +match_block_trailing_comma = true +trailing_comma = "Vertical" +trailing_semicolon = true +use_field_init_shorthand = true \ No newline at end of file diff --git a/examples/oapp-solana-counter/turbo.json b/examples/oapp-solana-counter/turbo.json new file mode 100644 index 0000000000..5161b5b98c --- /dev/null +++ b/examples/oapp-solana-counter/turbo.json @@ -0,0 +1,25 @@ +{ + "extends": ["//"], + "tasks": { + "build": { + "dependsOn": ["^build"], + "inputs": [ + "libs/**", + "programs/**", + "Cargo.toml", + "Cargo.lock", + "rust-toolchain.toml", + "Anchor.toml" + ], + "outputs": ["target/deploy/**", "target/idl/**"], + "cache": true + }, + "test": { + "dependsOn": ["build"], + // No need to cache test outputs + "outputs": [], + "inputs": [], + "cache": true + } + } +} diff --git a/packages/create-lz-oapp/src/config.ts b/packages/create-lz-oapp/src/config.ts index 1ef25da295..bf9fae94ab 100644 --- a/packages/create-lz-oapp/src/config.ts +++ b/packages/create-lz-oapp/src/config.ts @@ -1,6 +1,10 @@ import type { Example, PackageManager } from '@/types' import { isPackageManagerAvailable } from './utilities/installation' +function flaggedExample(envVar: string, example: Example): Example | undefined { + return process.env[envVar] ? example : undefined +} + export const getExamples = (): Example[] => { /** * To enable example development in a custom repository @@ -17,7 +21,8 @@ export const getExamples = (): Example[] => { */ const ref = process.env.LAYERZERO_EXAMPLES_REPOSITORY_REF || '' - return [ + // TODO: apply flaggedExample to all conditional examples + const result = [ { id: 'oapp', label: 'OApp', @@ -46,7 +51,7 @@ export const getExamples = (): Example[] => { directory: 'examples/onft721', ref, }, - // ZK-Solc examples are feature flagged for the time being + // Migration example is feature flagged for the time being ...(process.env.LZ_ENABLE_MIGRATION_EXAMPLE ? [ { @@ -123,6 +128,13 @@ export const getExamples = (): Example[] => { }, ] : []), + flaggedExample('LZ_ENABLE_SOLANA_COUNTER_EXAMPLE', { + id: 'oapp-solana-counter', + label: 'Solana OmniCounter', + repository, + directory: 'examples/oapp-solana-counter', + ref, + }), // Move OFT examples are feature flagged for the time being ...(process.env.LZ_ENABLE_EXPERIMENTAL_MOVE_VM_EXAMPLES ? [ @@ -150,6 +162,7 @@ export const getExamples = (): Example[] => { ] : []), ] + return result.filter((example) => example != undefined) } const PACKAGE_MANAGERS: PackageManager[] = [ diff --git a/turbo.json b/turbo.json index 795375099a..5bc9704c30 100644 --- a/turbo.json +++ b/turbo.json @@ -52,6 +52,7 @@ "LZ_ENABLE_EXPERIMENTAL_RETRY", "LZ_ENABLE_EXPERIMENTAL_SIMULATION", "LZ_ENABLE_SOLANA_OFT_EXAMPLE", + "LZ_ENABLE_SOLANA_COUNTER_EXAMPLE", "LZ_ENABLE_READ_EXAMPLE", "LZ_ENABLE_ZKSOLC_EXAMPLE", "LZ_ENABLE_NATIVE_EXAMPLE", From 23730bd782283ea8e78c1d82f83e1373a13a7fd5 Mon Sep 17 00:00:00 2001 From: nazreen Date: Sat, 15 Mar 2025 01:23:30 +0800 Subject: [PATCH 02/12] fix --- packages/create-lz-oapp/src/config.ts | 2 +- tests-user/tests/create-lz-oapp.bats | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/packages/create-lz-oapp/src/config.ts b/packages/create-lz-oapp/src/config.ts index bf9fae94ab..8ca8d5328c 100644 --- a/packages/create-lz-oapp/src/config.ts +++ b/packages/create-lz-oapp/src/config.ts @@ -162,7 +162,7 @@ export const getExamples = (): Example[] => { ] : []), ] - return result.filter((example) => example != undefined) + return result.filter((example) => example !== undefined) } const PACKAGE_MANAGERS: PackageManager[] = [ diff --git a/tests-user/tests/create-lz-oapp.bats b/tests-user/tests/create-lz-oapp.bats index be670d8eba..8eadd6b9b4 100644 --- a/tests-user/tests/create-lz-oapp.bats +++ b/tests-user/tests/create-lz-oapp.bats @@ -189,6 +189,15 @@ teardown() { pnpm test } +@test "should work with pnpm & oft solana omnicounter example in CI mode" { + local DESTINATION="$PROJECTS_DIRECTORY/pnpm-oft-solana" + + LZ_ENABLE_SOLANA_COUNTER_EXAMPLE=1 npx --yes create-lz-oapp --ci --example oft-solana --destination $DESTINATION --package-manager pnpm + cd "$DESTINATION" + pnpm compile + pnpm test +} + @test "should work with pnpm & oapp read example in CI mode" { local DESTINATION="$PROJECTS_DIRECTORY/pnpm-oapp-read" From b90fbf588e90de7e0866d18f232cc2dc5b99ff91 Mon Sep 17 00:00:00 2001 From: nazreen Date: Sat, 15 Mar 2025 01:25:10 +0800 Subject: [PATCH 03/12] temp log --- packages/create-lz-oapp/src/config.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/create-lz-oapp/src/config.ts b/packages/create-lz-oapp/src/config.ts index 8ca8d5328c..1357a79e9a 100644 --- a/packages/create-lz-oapp/src/config.ts +++ b/packages/create-lz-oapp/src/config.ts @@ -2,6 +2,7 @@ import type { Example, PackageManager } from '@/types' import { isPackageManagerAvailable } from './utilities/installation' function flaggedExample(envVar: string, example: Example): Example | undefined { + console.log({ envVar }, process.env[envVar]) return process.env[envVar] ? example : undefined } From 2902fed4293aeae0049e9a8176a1e32d23a90689 Mon Sep 17 00:00:00 2001 From: nazreen Date: Sat, 15 Mar 2025 01:33:52 +0800 Subject: [PATCH 04/12] tests --- packages/create-lz-oapp/src/config.ts | 1 - packages/create-lz-oapp/test/config.test.ts | 12 ++++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/packages/create-lz-oapp/src/config.ts b/packages/create-lz-oapp/src/config.ts index 1357a79e9a..8ca8d5328c 100644 --- a/packages/create-lz-oapp/src/config.ts +++ b/packages/create-lz-oapp/src/config.ts @@ -2,7 +2,6 @@ import type { Example, PackageManager } from '@/types' import { isPackageManagerAvailable } from './utilities/installation' function flaggedExample(envVar: string, example: Example): Example | undefined { - console.log({ envVar }, process.env[envVar]) return process.env[envVar] ? example : undefined } diff --git a/packages/create-lz-oapp/test/config.test.ts b/packages/create-lz-oapp/test/config.test.ts index 4d40a5bded..1a0ee61b8b 100644 --- a/packages/create-lz-oapp/test/config.test.ts +++ b/packages/create-lz-oapp/test/config.test.ts @@ -52,6 +52,18 @@ describe('config', () => { expect(getExamples()).toContainEqual(expect.objectContaining({ id: 'oft-solana' })) }) + it('should not include Solana Counter example if LZ_ENABLE_SOLANA_COUNTER_EXAMPLE is empty', () => { + process.env.LZ_ENABLE_SOLANA_COUNTER_EXAMPLE = '' + + expect(getExamples()).not.toContainEqual(expect.objectContaining({ id: 'oapp-solana-counter' })) + }) + + it('should include Solana Counter example if LZ_ENABLE_SOLANA_COUNTER_EXAMPLE is defined', () => { + process.env.LZ_ENABLE_SOLANA_COUNTER_EXAMPLE = 'yes' + + expect(getExamples()).toContainEqual(expect.objectContaining({ id: 'oapp-solana-counter' })) + }) + it('should not include OApp Read example if LZ_ENABLE_READ_EXAMPLE is empty', () => { process.env.LZ_ENABLE_READ_EXAMPLE = '' From 99b2fbc81e9a3c2a3650b1d381df42188c3babb6 Mon Sep 17 00:00:00 2001 From: nazreen Date: Sat, 15 Mar 2025 01:36:06 +0800 Subject: [PATCH 05/12] try bool --- packages/create-lz-oapp/src/config.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/create-lz-oapp/src/config.ts b/packages/create-lz-oapp/src/config.ts index 8ca8d5328c..1ccdd0bcc3 100644 --- a/packages/create-lz-oapp/src/config.ts +++ b/packages/create-lz-oapp/src/config.ts @@ -1,8 +1,8 @@ import type { Example, PackageManager } from '@/types' import { isPackageManagerAvailable } from './utilities/installation' -function flaggedExample(envVar: string, example: Example): Example | undefined { - return process.env[envVar] ? example : undefined +function flaggedExample(flag: boolean, example: Example): Example | undefined { + return flag ? example : undefined } export const getExamples = (): Example[] => { @@ -128,7 +128,7 @@ export const getExamples = (): Example[] => { }, ] : []), - flaggedExample('LZ_ENABLE_SOLANA_COUNTER_EXAMPLE', { + flaggedExample(!!process.env.LZ_ENABLE_SOLANA_COUNTER_EXAMPLE, { id: 'oapp-solana-counter', label: 'Solana OmniCounter', repository, From dbd9f8aa7d33088d3e0e6982bbea11d11e1d3249 Mon Sep 17 00:00:00 2001 From: nazreen Date: Sat, 15 Mar 2025 01:39:45 +0800 Subject: [PATCH 06/12] tmp try old way --- packages/create-lz-oapp/src/config.ts | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/packages/create-lz-oapp/src/config.ts b/packages/create-lz-oapp/src/config.ts index 1ccdd0bcc3..1b78e01687 100644 --- a/packages/create-lz-oapp/src/config.ts +++ b/packages/create-lz-oapp/src/config.ts @@ -1,9 +1,9 @@ import type { Example, PackageManager } from '@/types' import { isPackageManagerAvailable } from './utilities/installation' -function flaggedExample(flag: boolean, example: Example): Example | undefined { - return flag ? example : undefined -} +// function flaggedExample(flag: boolean, example: Example): Example | undefined { +// return flag ? example : undefined +// } export const getExamples = (): Example[] => { /** @@ -128,13 +128,17 @@ export const getExamples = (): Example[] => { }, ] : []), - flaggedExample(!!process.env.LZ_ENABLE_SOLANA_COUNTER_EXAMPLE, { - id: 'oapp-solana-counter', - label: 'Solana OmniCounter', - repository, - directory: 'examples/oapp-solana-counter', - ref, - }), + ...(process.env.LZ_ENABLE_SOLANA_COUNTER_EXAMPLE + ? [ + { + id: 'oapp-solana-counter', + label: 'Solana OmniCounter', + repository, + directory: 'examples/oapp-solana-counter', + ref, + }, + ] + : []), // Move OFT examples are feature flagged for the time being ...(process.env.LZ_ENABLE_EXPERIMENTAL_MOVE_VM_EXAMPLES ? [ From 1578767a516aa9d8910f57090b95326a720edb31 Mon Sep 17 00:00:00 2001 From: nazreen Date: Sat, 15 Mar 2025 01:44:33 +0800 Subject: [PATCH 07/12] tmp remove filter --- packages/create-lz-oapp/src/config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/create-lz-oapp/src/config.ts b/packages/create-lz-oapp/src/config.ts index 1b78e01687..edf7ba56d0 100644 --- a/packages/create-lz-oapp/src/config.ts +++ b/packages/create-lz-oapp/src/config.ts @@ -166,7 +166,7 @@ export const getExamples = (): Example[] => { ] : []), ] - return result.filter((example) => example !== undefined) + return result } const PACKAGE_MANAGERS: PackageManager[] = [ From 1ca0da340c91a9d58614909a61e16319639ae2d7 Mon Sep 17 00:00:00 2001 From: nazreen Date: Sat, 15 Mar 2025 01:50:57 +0800 Subject: [PATCH 08/12] lockfile --- pnpm-lock.yaml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d60ba26149..e863acc896 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -884,6 +884,12 @@ importers: specifier: ^5.4.4 version: 5.5.3 + examples/oapp-solana-counter: + devDependencies: + rimraf: + specifier: ^5.0.5 + version: 5.0.9 + examples/oft: devDependencies: '@babel/core': @@ -19608,6 +19614,7 @@ packages: /rimraf@3.0.2: resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} + deprecated: Rimraf versions prior to v4 are no longer supported hasBin: true dependencies: glob: 7.2.3 From 56d27ca82e3b01913e1efb58c498a1d730eb43c1 Mon Sep 17 00:00:00 2001 From: nazreen Date: Sat, 15 Mar 2025 01:55:57 +0800 Subject: [PATCH 09/12] update name --- examples/oapp-solana-counter/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/oapp-solana-counter/package.json b/examples/oapp-solana-counter/package.json index 4991c102d0..aa81ff8f81 100644 --- a/examples/oapp-solana-counter/package.json +++ b/examples/oapp-solana-counter/package.json @@ -1,5 +1,5 @@ { - "name": "@layerzerolabs/counter-v2-solana", + "name": "@layerzerolabs/oapp-counter-solana-example", "private": true, "license": "BUSL-1.1", "exports": { From 307253480329c07957361a43439acd4655a712f6 Mon Sep 17 00:00:00 2001 From: nazreen Date: Sat, 15 Mar 2025 01:57:29 +0800 Subject: [PATCH 10/12] tmp force include --- packages/create-lz-oapp/src/config.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/packages/create-lz-oapp/src/config.ts b/packages/create-lz-oapp/src/config.ts index edf7ba56d0..9624b24f9f 100644 --- a/packages/create-lz-oapp/src/config.ts +++ b/packages/create-lz-oapp/src/config.ts @@ -51,6 +51,13 @@ export const getExamples = (): Example[] => { directory: 'examples/onft721', ref, }, + { + id: 'oapp-solana-counter', + label: 'Solana OmniCounter', + repository, + directory: 'examples/oapp-solana-counter', + ref, + }, // Migration example is feature flagged for the time being ...(process.env.LZ_ENABLE_MIGRATION_EXAMPLE ? [ From 6089dba56033adb93145060f653c88df2e34c804 Mon Sep 17 00:00:00 2001 From: nazreen Date: Sat, 15 Mar 2025 01:58:08 +0800 Subject: [PATCH 11/12] rm force include --- packages/create-lz-oapp/src/config.ts | 7 ------- 1 file changed, 7 deletions(-) diff --git a/packages/create-lz-oapp/src/config.ts b/packages/create-lz-oapp/src/config.ts index 9624b24f9f..edf7ba56d0 100644 --- a/packages/create-lz-oapp/src/config.ts +++ b/packages/create-lz-oapp/src/config.ts @@ -51,13 +51,6 @@ export const getExamples = (): Example[] => { directory: 'examples/onft721', ref, }, - { - id: 'oapp-solana-counter', - label: 'Solana OmniCounter', - repository, - directory: 'examples/oapp-solana-counter', - ref, - }, // Migration example is feature flagged for the time being ...(process.env.LZ_ENABLE_MIGRATION_EXAMPLE ? [ From 85dd2aeab43becdf8f4ddbd2448c1c27ae36fe47 Mon Sep 17 00:00:00 2001 From: nazreen Date: Sat, 15 Mar 2025 02:17:32 +0800 Subject: [PATCH 12/12] revert --- packages/create-lz-oapp/src/config.ts | 26 +++++++++++--------------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/packages/create-lz-oapp/src/config.ts b/packages/create-lz-oapp/src/config.ts index edf7ba56d0..8ca8d5328c 100644 --- a/packages/create-lz-oapp/src/config.ts +++ b/packages/create-lz-oapp/src/config.ts @@ -1,9 +1,9 @@ import type { Example, PackageManager } from '@/types' import { isPackageManagerAvailable } from './utilities/installation' -// function flaggedExample(flag: boolean, example: Example): Example | undefined { -// return flag ? example : undefined -// } +function flaggedExample(envVar: string, example: Example): Example | undefined { + return process.env[envVar] ? example : undefined +} export const getExamples = (): Example[] => { /** @@ -128,17 +128,13 @@ export const getExamples = (): Example[] => { }, ] : []), - ...(process.env.LZ_ENABLE_SOLANA_COUNTER_EXAMPLE - ? [ - { - id: 'oapp-solana-counter', - label: 'Solana OmniCounter', - repository, - directory: 'examples/oapp-solana-counter', - ref, - }, - ] - : []), + flaggedExample('LZ_ENABLE_SOLANA_COUNTER_EXAMPLE', { + id: 'oapp-solana-counter', + label: 'Solana OmniCounter', + repository, + directory: 'examples/oapp-solana-counter', + ref, + }), // Move OFT examples are feature flagged for the time being ...(process.env.LZ_ENABLE_EXPERIMENTAL_MOVE_VM_EXAMPLES ? [ @@ -166,7 +162,7 @@ export const getExamples = (): Example[] => { ] : []), ] - return result + return result.filter((example) => example !== undefined) } const PACKAGE_MANAGERS: PackageManager[] = [