diff --git a/.github/workflows/publish-crates-and-sdk.yml b/.github/workflows/publish-crates-and-sdk.yml index e633db6..1fcf2b2 100644 --- a/.github/workflows/publish-crates-and-sdk.yml +++ b/.github/workflows/publish-crates-and-sdk.yml @@ -1,10 +1,10 @@ name: Publish Crates & SDKs on: release: - types: [ published ] + types: [published] push: branches: - - 'release/v*' + - "release/v*" workflow_dispatch: concurrency: group: ${{ github.workflow }}-${{ github.ref }} @@ -71,7 +71,7 @@ jobs: if [ "${DRY_RUN}" = "true" ]; then DRY_RUN_FLAG="--dry-run" fi - + if [ "${DRY_RUN}" = "true" ]; then NO_VERIFY_FLAG="--no-verify" fi @@ -79,7 +79,8 @@ jobs: cargo publish $DRY_RUN_FLAG --manifest-path=ephemeral/Cargo.toml --token $CRATES_TOKEN $NO_VERIFY_FLAG cargo publish $DRY_RUN_FLAG --manifest-path=delegate/Cargo.toml --token $CRATES_TOKEN $NO_VERIFY_FLAG cargo publish $DRY_RUN_FLAG --manifest-path=commit-attribute/Cargo.toml --token $CRATES_TOKEN $NO_VERIFY_FLAG - + cargo publish $DRY_RUN_FLAG --manifest-path=action-attribute/Cargo.toml --token $CRATES_TOKEN $NO_VERIFY_FLAG + if [ "${DRY_RUN}" != "true" ]; then cargo publish $DRY_RUN_FLAG --manifest-path=sdk/Cargo.toml --token $CRATES_TOKEN $NO_VERIFY_FLAG cargo publish $DRY_RUN_FLAG --manifest-path=resolver/Cargo.toml --token $CRATES_TOKEN $NO_VERIFY_FLAG @@ -125,4 +126,4 @@ jobs: npm publish --access public fi env: - NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} \ No newline at end of file + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} diff --git a/rust/Cargo.lock b/rust/Cargo.lock index 7d42e72..6484e62 100644 --- a/rust/Cargo.lock +++ b/rust/Cargo.lock @@ -10,16 +10,15 @@ checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" [[package]] name = "agave-feature-set" -version = "2.3.13" +version = "2.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d52a2c365c0245cbb8959de725fc2b44c754b673fdf34c9a7f9d4a25c35a7bf1" +checksum = "81071c030078429f000741da9ea84e34c432614f1b64dba741e1a572beeece3b" dependencies = [ "ahash", "solana-epoch-schedule", "solana-hash", "solana-pubkey", "solana-sha256-hasher", - "solana-svm-feature-set", ] [[package]] @@ -469,6 +468,12 @@ 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.10.0" @@ -1029,6 +1034,7 @@ dependencies = [ "base64ct", "bincode", "borsh 1.5.7", + "ephemeral-rollups-sdk-attribute-action", "ephemeral-rollups-sdk-attribute-commit", "ephemeral-rollups-sdk-attribute-delegate", "ephemeral-rollups-sdk-attribute-ephemeral", @@ -1047,6 +1053,14 @@ dependencies = [ "solana-sysvar", ] +[[package]] +name = "ephemeral-rollups-sdk-attribute-action" +version = "0.4.1" +dependencies = [ + "quote", + "syn 1.0.109", +] + [[package]] name = "ephemeral-rollups-sdk-attribute-commit" version = "0.4.1" @@ -1321,11 +1335,28 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" dependencies = [ "cfg-if", - "js-sys", "libc", "r-efi", "wasip2", - "wasm-bindgen", +] + +[[package]] +name = "h2" +version = "0.3.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0beca50380b1fc32983fc1cb4587bfa4bb9e78fc259aad4a0032d2080309222d" +dependencies = [ + "bytes", + "fnv", + "futures-core", + "futures-sink", + "futures-util", + "http 0.2.12", + "indexmap", + "slab", + "tokio", + "tokio-util", + "tracing", ] [[package]] @@ -1339,7 +1370,7 @@ dependencies = [ "fnv", "futures-core", "futures-sink", - "http", + "http 1.3.1", "indexmap", "slab", "tokio", @@ -1416,6 +1447,17 @@ dependencies = [ "hmac 0.8.1", ] +[[package]] +name = "http" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + [[package]] name = "http" version = "1.3.1" @@ -1427,6 +1469,17 @@ dependencies = [ "itoa", ] +[[package]] +name = "http-body" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" +dependencies = [ + "bytes", + "http 0.2.12", + "pin-project-lite", +] + [[package]] name = "http-body" version = "1.0.1" @@ -1434,7 +1487,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" dependencies = [ "bytes", - "http", + "http 1.3.1", ] [[package]] @@ -1445,8 +1498,8 @@ checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" dependencies = [ "bytes", "futures-core", - "http", - "http-body", + "http 1.3.1", + "http-body 1.0.1", "pin-project-lite", ] @@ -1456,12 +1509,42 @@ version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" +[[package]] +name = "httpdate" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" + [[package]] name = "humantime" version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "135b12329e5e3ce057a9f972339ea52bc954fe1e9358ef27f95e89716fbc5424" +[[package]] +name = "hyper" +version = "0.14.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41dfc780fdec9373c01bae43289ea34c972e40ee3c9f6b3c8801a35f35586ce7" +dependencies = [ + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "h2 0.3.27", + "http 0.2.12", + "http-body 0.4.6", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "socket2 0.5.10", + "tokio", + "tower-service", + "tracing", + "want", +] + [[package]] name = "hyper" version = "1.7.0" @@ -1472,9 +1555,9 @@ dependencies = [ "bytes", "futures-channel", "futures-core", - "h2", - "http", - "http-body", + "h2 0.4.12", + "http 1.3.1", + "http-body 1.0.1", "httparse", "itoa", "pin-project-lite", @@ -1484,21 +1567,34 @@ dependencies = [ "want", ] +[[package]] +name = "hyper-rustls" +version = "0.24.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" +dependencies = [ + "futures-util", + "http 0.2.12", + "hyper 0.14.32", + "rustls 0.21.12", + "tokio", + "tokio-rustls 0.24.1", +] + [[package]] name = "hyper-rustls" version = "0.27.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3c93eb611681b207e1fe55d5a71ecf91572ec8a6705cdb6857f7d8d5242cf58" dependencies = [ - "http", - "hyper", + "http 1.3.1", + "hyper 1.7.0", "hyper-util", - "rustls", + "rustls 0.23.34", "rustls-pki-types", "tokio", - "tokio-rustls", + "tokio-rustls 0.26.4", "tower-service", - "webpki-roots", ] [[package]] @@ -1509,7 +1605,7 @@ checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" dependencies = [ "bytes", "http-body-util", - "hyper", + "hyper 1.7.0", "hyper-util", "native-tls", "tokio", @@ -1528,15 +1624,15 @@ dependencies = [ "futures-channel", "futures-core", "futures-util", - "http", - "http-body", - "hyper", + "http 1.3.1", + "http-body 1.0.1", + "hyper 1.7.0", "ipnet", "libc", "percent-encoding", "pin-project-lite", - "socket2", - "system-configuration", + "socket2 0.6.1", + "system-configuration 0.6.1", "tokio", "tower-service", "tracing", @@ -1836,12 +1932,6 @@ version = "0.4.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432" -[[package]] -name = "lru-slab" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154" - [[package]] name = "magic-domain-program" version = "0.0.3" @@ -1868,7 +1958,7 @@ dependencies = [ "humantime", "magic-domain-program", "parking_lot", - "reqwest", + "reqwest 0.12.24", "scc", "serde", "smallvec", @@ -1939,6 +2029,16 @@ version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" +[[package]] +name = "mime_guess" +version = "2.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7c44f8e672c00fe5308fa235f821cb4198414e1c77935c1ab6948d3fd78550e" +dependencies = [ + "mime", + "unicase", +] + [[package]] name = "miniz_oxide" version = "0.8.9" @@ -2082,7 +2182,7 @@ version = "0.10.74" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24ad14dd45412269e1a30f52ad8f0664f0f4f4a89ee8fe28c3b3527021ebb654" dependencies = [ - "bitflags", + "bitflags 2.10.0", "cfg-if", "foreign-types", "libc", @@ -2304,61 +2404,6 @@ dependencies = [ "percent-encoding", ] -[[package]] -name = "quinn" -version = "0.11.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9e20a958963c291dc322d98411f541009df2ced7b5a4f2bd52337638cfccf20" -dependencies = [ - "bytes", - "cfg_aliases", - "pin-project-lite", - "quinn-proto", - "quinn-udp", - "rustc-hash", - "rustls", - "socket2", - "thiserror 2.0.17", - "tokio", - "tracing", - "web-time", -] - -[[package]] -name = "quinn-proto" -version = "0.11.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1906b49b0c3bc04b5fe5d86a77925ae6524a19b816ae38ce1e426255f1d8a31" -dependencies = [ - "bytes", - "getrandom 0.3.4", - "lru-slab", - "rand 0.9.2", - "ring", - "rustc-hash", - "rustls", - "rustls-pki-types", - "slab", - "thiserror 2.0.17", - "tinyvec", - "tracing", - "web-time", -] - -[[package]] -name = "quinn-udp" -version = "0.5.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "addec6a0dcad8a8d96a771f815f0eaf55f9d1805756410b39f5fa81332574cbd" -dependencies = [ - "cfg_aliases", - "libc", - "once_cell", - "socket2", - "tracing", - "windows-sys 0.60.2", -] - [[package]] name = "quote" version = "1.0.41" @@ -2407,16 +2452,6 @@ dependencies = [ "rand_core 0.6.4", ] -[[package]] -name = "rand" -version = "0.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" -dependencies = [ - "rand_chacha 0.9.0", - "rand_core 0.9.3", -] - [[package]] name = "rand_chacha" version = "0.2.2" @@ -2437,16 +2472,6 @@ dependencies = [ "rand_core 0.6.4", ] -[[package]] -name = "rand_chacha" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" -dependencies = [ - "ppv-lite86", - "rand_core 0.9.3", -] - [[package]] name = "rand_core" version = "0.5.1" @@ -2465,15 +2490,6 @@ dependencies = [ "getrandom 0.2.16", ] -[[package]] -name = "rand_core" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" -dependencies = [ - "getrandom 0.3.4", -] - [[package]] name = "rand_hc" version = "0.2.0" @@ -2489,7 +2505,7 @@ version = "0.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" dependencies = [ - "bitflags", + "bitflags 2.10.0", ] [[package]] @@ -2547,25 +2563,66 @@ version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cadadef317c2f20755a64d7fdc48f9e7178ee6b0e1f7fce33fa60f1d68a276e6" +[[package]] +name = "reqwest" +version = "0.11.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd67538700a17451e7cba03ac727fb961abb7607553461627b97de0b89cf4a62" +dependencies = [ + "async-compression", + "base64 0.21.7", + "bytes", + "encoding_rs", + "futures-core", + "futures-util", + "h2 0.3.27", + "http 0.2.12", + "http-body 0.4.6", + "hyper 0.14.32", + "hyper-rustls 0.24.2", + "ipnet", + "js-sys", + "log", + "mime", + "mime_guess", + "once_cell", + "percent-encoding", + "pin-project-lite", + "rustls 0.21.12", + "rustls-pemfile", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper 0.1.2", + "system-configuration 0.5.1", + "tokio", + "tokio-rustls 0.24.1", + "tokio-util", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "webpki-roots", + "winreg", +] + [[package]] name = "reqwest" version = "0.12.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d0946410b9f7b082a427e4ef5c8ff541a88b357bc6c637c40db3a68ac70a36f" dependencies = [ - "async-compression", "base64 0.22.1", "bytes", "encoding_rs", - "futures-channel", "futures-core", - "futures-util", - "h2", - "http", - "http-body", + "h2 0.4.12", + "http 1.3.1", + "http-body 1.0.1", "http-body-util", - "hyper", - "hyper-rustls", + "hyper 1.7.0", + "hyper-rustls 0.27.7", "hyper-tls", "hyper-util", "js-sys", @@ -2574,17 +2631,13 @@ dependencies = [ "native-tls", "percent-encoding", "pin-project-lite", - "quinn", - "rustls", "rustls-pki-types", "serde", "serde_json", "serde_urlencoded", - "sync_wrapper", + "sync_wrapper 1.0.2", "tokio", "tokio-native-tls", - "tokio-rustls", - "tokio-util", "tower", "tower-http", "tower-service", @@ -2592,22 +2645,21 @@ dependencies = [ "wasm-bindgen", "wasm-bindgen-futures", "web-sys", - "webpki-roots", ] [[package]] name = "reqwest-middleware" -version = "0.4.2" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57f17d28a6e6acfe1733fe24bcd30774d13bffa4b8a22535b4c8c98423088d4e" +checksum = "5a735987236a8e238bf0296c7e351b999c188ccc11477f311b82b55c93984216" dependencies = [ "anyhow", "async-trait", - "http", - "reqwest", + "http 0.2.12", + "reqwest 0.11.27", "serde", + "task-local-extensions", "thiserror 1.0.69", - "tower-service", ] [[package]] @@ -2653,12 +2705,6 @@ dependencies = [ "syn 2.0.108", ] -[[package]] -name = "rustc-hash" -version = "2.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" - [[package]] name = "rustc_version" version = "0.4.1" @@ -2674,13 +2720,25 @@ version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cd15f8a2c5551a84d56efdc1cd049089e409ac19a3072d5037a17fd70719ff3e" dependencies = [ - "bitflags", + "bitflags 2.10.0", "errno", "libc", "linux-raw-sys", "windows-sys 0.61.2", ] +[[package]] +name = "rustls" +version = "0.21.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f56a14d1f48b391359b22f731fd4bd7e43c97f3c50eee276f3aa09c94784d3e" +dependencies = [ + "log", + "ring", + "rustls-webpki 0.101.7", + "sct", +] + [[package]] name = "rustls" version = "0.23.34" @@ -2688,23 +2746,40 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a9586e9ee2b4f8fab52a0048ca7334d7024eef48e2cb9407e3497bb7cab7fa7" dependencies = [ "once_cell", - "ring", "rustls-pki-types", - "rustls-webpki", + "rustls-webpki 0.103.8", "subtle", "zeroize", ] +[[package]] +name = "rustls-pemfile" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" +dependencies = [ + "base64 0.21.7", +] + [[package]] name = "rustls-pki-types" version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94182ad936a0c91c324cd46c6511b9510ed16af436d7b5bab34beab0afd55f7a" dependencies = [ - "web-time", "zeroize", ] +[[package]] +name = "rustls-webpki" +version = "0.101.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" +dependencies = [ + "ring", + "untrusted", +] + [[package]] name = "rustls-webpki" version = "0.103.8" @@ -2752,6 +2827,16 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" +[[package]] +name = "sct" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" +dependencies = [ + "ring", + "untrusted", +] + [[package]] name = "sdd" version = "3.0.10" @@ -2764,7 +2849,7 @@ version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" dependencies = [ - "bitflags", + "bitflags 2.10.0", "core-foundation", "core-foundation-sys", "libc", @@ -2981,6 +3066,16 @@ dependencies = [ "serde", ] +[[package]] +name = "socket2" +version = "0.5.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e22376abed350d73dd1cd119b57ffccad95b4e585a7cda43e286245ce23c0678" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + [[package]] name = "socket2" version = "0.6.1" @@ -3011,9 +3106,9 @@ dependencies = [ [[package]] name = "solana-account-decoder-client-types" -version = "2.3.13" +version = "2.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5519e8343325b707f17fbed54fcefb325131b692506d0af9e08a539d15e4f8cf" +checksum = "ee049978c5bbbb5213e4f0e924a76d98d89c771220539bd411b392bf4e3d373a" dependencies = [ "base64 0.22.1", "bs58", @@ -3439,6 +3534,16 @@ dependencies = [ "serde_derive", ] +[[package]] +name = "solana-inline-spl" +version = "2.2.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14191c3b9de9f62e9ffb81ae53b3aecade34aebcb22d695e93fea70b1cec8cbe" +dependencies = [ + "bytemuck", + "solana-pubkey", +] + [[package]] name = "solana-instruction" version = "2.3.1" @@ -3464,7 +3569,7 @@ version = "2.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e0e85a6fad5c2d0c4f5b91d34b8ca47118fc593af706e523cdbedf846a954f57" dependencies = [ - "bitflags", + "bitflags 2.10.0", "solana-account-info", "solana-instruction", "solana-program-error", @@ -3691,7 +3796,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "004f2d2daf407b3ec1a1ca5ec34b3ccdfd6866dd2d3c7d0715004a96e4b6d127" dependencies = [ "bincode", - "bitflags", + "bitflags 2.10.0", "cfg_eval", "serde", "serde_derive", @@ -3880,16 +3985,16 @@ dependencies = [ [[package]] name = "solana-pubkey" -version = "2.4.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b62adb9c3261a052ca1f999398c388f1daf558a1b492f60a6d9e64857db4ff1" +checksum = "cad77cf9f30b971a1eec48dde6a863dcac60ba005a34dfde23736afa5c7ac667" dependencies = [ "borsh 0.10.4", "borsh 1.5.7", + "bs58", "bytemuck", "bytemuck_derive", "curve25519-dalek 4.1.3", - "five8", "five8_const", "getrandom 0.2.16", "js-sys", @@ -3978,18 +4083,17 @@ dependencies = [ [[package]] name = "solana-rpc-client" -version = "2.3.13" +version = "2.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8d3161ac0918178e674c1f7f1bfac40de3e7ed0383bd65747d63113c156eaeb" +checksum = "01ba3b0d458380c045675b1f55b472501c0ddf7f20fb87a71e73a0bda281f584" dependencies = [ "async-trait", "base64 0.22.1", "bincode", "bs58", - "futures", "indicatif", "log", - "reqwest", + "reqwest 0.11.27", "reqwest-middleware", "semver", "serde", @@ -4012,40 +4116,21 @@ dependencies = [ "solana-transaction-error", "solana-transaction-status-client-types", "solana-version", - "solana-vote-interface", "tokio", ] [[package]] name = "solana-rpc-client-api" -version = "2.3.13" +version = "2.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dbc138685c79d88a766a8fd825057a74ea7a21e1dd7f8de275ada899540fff7" +checksum = "9084cfe53a41e3dc322cda81a98c7f162c96113cc82ff508d5f580253e5fffde" dependencies = [ "anyhow", - "jsonrpc-core", - "reqwest", - "reqwest-middleware", - "serde", - "serde_derive", - "serde_json", - "solana-account-decoder-client-types", - "solana-clock", - "solana-rpc-client-types", - "solana-signer", - "solana-transaction-error", - "solana-transaction-status-client-types", - "thiserror 2.0.17", -] - -[[package]] -name = "solana-rpc-client-types" -version = "2.3.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ea428a81729255d895ea47fba9b30fd4dacbfe571a080448121bd0592751676" -dependencies = [ "base64 0.22.1", "bs58", + "jsonrpc-core", + "reqwest 0.11.27", + "reqwest-middleware", "semver", "serde", "serde_derive", @@ -4056,11 +4141,12 @@ dependencies = [ "solana-commitment-config", "solana-fee-calculator", "solana-inflation", + "solana-inline-spl", "solana-pubkey", + "solana-signer", "solana-transaction-error", "solana-transaction-status-client-types", "solana-version", - "spl-generic-token", "thiserror 2.0.17", ] @@ -4376,12 +4462,6 @@ dependencies = [ "solana-sysvar-id", ] -[[package]] -name = "solana-svm-feature-set" -version = "2.3.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f24b836eb4d74ec255217bdbe0f24f64a07adeac31aca61f334f91cd4a3b1d5" - [[package]] name = "solana-system-interface" version = "1.0.0" @@ -4495,9 +4575,9 @@ dependencies = [ [[package]] name = "solana-transaction-context" -version = "2.3.13" +version = "2.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54a312304361987a85b2ef2293920558e6612876a639dd1309daf6d0d59ef2fe" +checksum = "37a936e58ff94d222e333216a26dbef4ca63ca01332cb0a997c2138a7a59b8dd" dependencies = [ "bincode", "serde", @@ -4507,7 +4587,6 @@ dependencies = [ "solana-instructions-sysvar", "solana-pubkey", "solana-rent", - "solana-sdk-ids", ] [[package]] @@ -4524,9 +4603,9 @@ dependencies = [ [[package]] name = "solana-transaction-status-client-types" -version = "2.3.13" +version = "2.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51f1d7c2387c35850848212244d2b225847666cb52d3bd59a5c409d2c300303d" +checksum = "37272b1efc4dc10be4a2feddf3fa93fabb9ec5ee5d50f1204a0abfa4340768a9" dependencies = [ "base64 0.22.1", "bincode", @@ -4553,12 +4632,11 @@ checksum = "7bbf6d7a3c0b28dd5335c52c0e9eae49d0ae489a8f324917faf0ded65a812c1d" [[package]] name = "solana-version" -version = "2.3.13" +version = "2.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3324d46c7f7b7f5d34bf7dc71a2883bdc072c7b28ca81d0b2167ecec4cf8da9f" +checksum = "a609298041c26bc7903c797e46fef22714a2f07ed4120fbf9432f6a615a49752" dependencies = [ "agave-feature-set", - "rand 0.8.5", "semver", "serde", "serde_derive", @@ -4628,16 +4706,6 @@ dependencies = [ "cfg-if", ] -[[package]] -name = "spl-generic-token" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "741a62a566d97c58d33f9ed32337ceedd4e35109a686e31b1866c5dfa56abddc" -dependencies = [ - "bytemuck", - "solana-pubkey", -] - [[package]] name = "stable_deref_trait" version = "1.2.1" @@ -4684,6 +4752,12 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "sync_wrapper" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" + [[package]] name = "sync_wrapper" version = "1.0.2" @@ -4704,15 +4778,36 @@ dependencies = [ "syn 2.0.108", ] +[[package]] +name = "system-configuration" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" +dependencies = [ + "bitflags 1.3.2", + "core-foundation", + "system-configuration-sys 0.5.0", +] + [[package]] name = "system-configuration" version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" dependencies = [ - "bitflags", + "bitflags 2.10.0", "core-foundation", - "system-configuration-sys", + "system-configuration-sys 0.6.0", +] + +[[package]] +name = "system-configuration-sys" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9" +dependencies = [ + "core-foundation-sys", + "libc", ] [[package]] @@ -4725,6 +4820,15 @@ dependencies = [ "libc", ] +[[package]] +name = "task-local-extensions" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba323866e5d033818e3240feeb9f7db2c4296674e4d9e16b97b7bf8f490434e8" +dependencies = [ + "pin-utils", +] + [[package]] name = "tempfile" version = "3.23.0" @@ -4824,7 +4928,7 @@ dependencies = [ "parking_lot", "pin-project-lite", "signal-hook-registry", - "socket2", + "socket2 0.6.1", "tokio-macros", "windows-sys 0.61.2", ] @@ -4850,13 +4954,23 @@ dependencies = [ "tokio", ] +[[package]] +name = "tokio-rustls" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" +dependencies = [ + "rustls 0.21.12", + "tokio", +] + [[package]] name = "tokio-rustls" version = "0.26.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1729aa945f29d91ba541258c8df89027d5792d85a8841fb65e8bf0f4ede4ef61" dependencies = [ - "rustls", + "rustls 0.23.34", "tokio", ] @@ -4884,7 +4998,7 @@ dependencies = [ "fastrand", "futures-core", "futures-sink", - "http", + "http 1.3.1", "httparse", "openssl", "simdutf8", @@ -4941,7 +5055,7 @@ dependencies = [ "futures-core", "futures-util", "pin-project-lite", - "sync_wrapper", + "sync_wrapper 1.0.2", "tokio", "tower-layer", "tower-service", @@ -4953,11 +5067,11 @@ version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "adc82fd73de2a9722ac5da747f12383d2bfdb93591ee6c58486e0097890f05f2" dependencies = [ - "bitflags", + "bitflags 2.10.0", "bytes", "futures-util", - "http", - "http-body", + "http 1.3.1", + "http-body 1.0.1", "iri-string", "pin-project-lite", "tower", @@ -5020,6 +5134,12 @@ version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" +[[package]] +name = "unicase" +version = "2.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75b844d17643ee918803943289730bec8aac480150456169e647ed0b576ba539" + [[package]] name = "unicode-ident" version = "1.0.22" @@ -5204,12 +5324,9 @@ dependencies = [ [[package]] name = "webpki-roots" -version = "1.0.4" +version = "0.25.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2878ef029c47c6e8cf779119f20fcf52bde7ad42a731b2a304bc221df17571e" -dependencies = [ - "rustls-pki-types", -] +checksum = "5f20c57d8d7db6d3b86154206ae5d8fba62dd39573114de97c2cb0578251f8e1" [[package]] name = "winapi" @@ -5283,6 +5400,15 @@ dependencies = [ "windows-link 0.1.3", ] +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.5", +] + [[package]] name = "windows-sys" version = "0.52.0" @@ -5319,6 +5445,21 @@ dependencies = [ "windows-link 0.2.1", ] +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + [[package]] name = "windows-targets" version = "0.52.6" @@ -5352,6 +5493,12 @@ dependencies = [ "windows_x86_64_msvc 0.53.1", ] +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + [[package]] name = "windows_aarch64_gnullvm" version = "0.52.6" @@ -5364,6 +5511,12 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + [[package]] name = "windows_aarch64_msvc" version = "0.52.6" @@ -5376,6 +5529,12 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + [[package]] name = "windows_i686_gnu" version = "0.52.6" @@ -5400,6 +5559,12 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + [[package]] name = "windows_i686_msvc" version = "0.52.6" @@ -5412,6 +5577,12 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + [[package]] name = "windows_x86_64_gnu" version = "0.52.6" @@ -5424,6 +5595,12 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + [[package]] name = "windows_x86_64_gnullvm" version = "0.52.6" @@ -5436,6 +5613,12 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + [[package]] name = "windows_x86_64_msvc" version = "0.52.6" @@ -5457,6 +5640,16 @@ dependencies = [ "memchr", ] +[[package]] +name = "winreg" +version = "0.50.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" +dependencies = [ + "cfg-if", + "windows-sys 0.48.0", +] + [[package]] name = "wit-bindgen" version = "0.46.0" diff --git a/rust/Cargo.toml b/rust/Cargo.toml index 7f363e3..57529b8 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -4,6 +4,7 @@ members = [ "ephemeral", "delegate", "commit-attribute", + "action-attribute", "resolver", "pinocchio", ] @@ -26,9 +27,11 @@ ephemeral-rollups-sdk = { path = "sdk", version = "=0.4.1" } ephemeral-rollups-sdk-attribute-ephemeral = { path = "ephemeral", version = "=0.4.1" } ephemeral-rollups-sdk-attribute-delegate = { path = "delegate", version = "=0.4.1" } ephemeral-rollups-sdk-attribute-commit = { path = "commit-attribute", version = "=0.4.1" } +ephemeral-rollups-sdk-attribute-action = { path = "action-attribute", version = "=0.4.1" } # Magicblock magicblock-delegation-program = { version = "1.1.3", features = ["no-entrypoint", "core"], default-features = false } +# magicblock-delegation-program = { version = "1.1.3", features = ["no-entrypoint", "sdk"], default-features = false } // updating from "core" to "sdk" magicblock-magic-program-api = { version = "0.2.3", default-features = false } ## External crates @@ -51,11 +54,11 @@ websocket = { package = "tokio-websockets", version = "0.10", features = [ "clie reqwest = { version = "0.12" } # solana -solana-program = { version = ">=1.16", default-features = false } +solana-program = { version = ">=1.16, <3.0.0", default-features = false } solana-account = { version = ">=2" } solana-account-info = { version = ">=2 " } solana-cpi= { version = ">=2" } -solana-pubkey = { version = ">=2" } +solana-pubkey = { version = ">=2, <=2.3" } solana-program-error = { version = ">=2" } solana-program-memory = { version = ">=2" } solana-system-interface = { version = ">=1", features = ["bincode"]} diff --git a/rust/action-attribute/Cargo.toml b/rust/action-attribute/Cargo.toml new file mode 100644 index 0000000..94023fb --- /dev/null +++ b/rust/action-attribute/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "ephemeral-rollups-sdk-attribute-action" +description = "ephemeral-rollups-sdk-attribute-action" +version = { workspace = true } +authors = { workspace = true } +repository = { workspace = true } +homepage = { workspace = true } +license = { workspace = true } +edition = { workspace = true } + +[dependencies] +syn = { workspace = true, features = ["full"] } +quote = { workspace = true } + +[lib] +proc-macro = true diff --git a/rust/action-attribute/README.md b/rust/action-attribute/README.md new file mode 100644 index 0000000..f3d9ef1 --- /dev/null +++ b/rust/action-attribute/README.md @@ -0,0 +1,6 @@ +# ephemeral-rollups-sdk-attribute-action + +Procedural macro attribute for committing accounts in Ephemeral Rollups. + +Quickstart and integration guide: +https://docs.magicblock.gg/pages/get-started/how-integrate-your-program/quickstart diff --git a/rust/action-attribute/src/lib.rs b/rust/action-attribute/src/lib.rs new file mode 100644 index 0000000..d758396 --- /dev/null +++ b/rust/action-attribute/src/lib.rs @@ -0,0 +1,64 @@ +extern crate proc_macro; +use proc_macro::TokenStream; +use quote::quote; +use syn::parse::Parser; +use syn::{parse_macro_input, Field, Fields, ItemStruct}; + +#[proc_macro_attribute] +pub fn action(_attr: TokenStream, item: TokenStream) -> TokenStream { + let input = parse_macro_input!(item as ItemStruct); + + let name = &input.ident; + let attrs = &input.attrs; // Capture all attributes + let expanded = if let Fields::Named(fields_named) = &input.fields { + let mut has_escrow_auth = false; + let mut has_escrow = false; + + for field in &fields_named.named { + if let Some(ident) = &field.ident { + if ident == "escrow_auth" { + has_escrow_auth = true; + } else if ident == "escrow" { + has_escrow = true; + } + } + } + + let mut new_fields = fields_named.named.clone(); + + if !has_escrow_auth { + new_fields.push( + Field::parse_named + .parse2(quote! { + /// CHECK: Escrow Authority is an account used to derive `escrow` with `escrow_index`, it is used to verify that action is scheduled with expected authority + pub escrow_auth: UncheckedAccount<'info> + }) + .unwrap(), + ); + } + + if !has_escrow { + new_fields.push( + Field::parse_named + .parse2(quote! { + /// CHECK: Escrow account that is a `signer` in callback, it is derived from `escrow_auth` and `escrow_index` one specified in `ActionArgs` + pub escrow: UncheckedAccount<'info> + }) + .unwrap(), + ); + } + + quote! { + #(#attrs)* + pub struct #name<'info> { + #new_fields + } + } + } else { + quote! { + compile_error!("Action attribute can only be used with structs with named fields"); + } + }; + + TokenStream::from(expanded) +} diff --git a/rust/sdk/Cargo.toml b/rust/sdk/Cargo.toml index ddd7f57..55b6977 100644 --- a/rust/sdk/Cargo.toml +++ b/rust/sdk/Cargo.toml @@ -32,6 +32,7 @@ borsh = { workspace = true } ephemeral-rollups-sdk-attribute-delegate = { workspace = true } ephemeral-rollups-sdk-attribute-ephemeral = { workspace = true } ephemeral-rollups-sdk-attribute-commit = { workspace = true } +ephemeral-rollups-sdk-attribute-action = { workspace = true } solana-program = { workspace = true, optional = true } solana-account = { workspace = true, optional = true } solana-account-info = { workspace = true, optional = true } @@ -44,6 +45,7 @@ solana-system-interface = { workspace = true, optional = true } solana-sysvar = { workspace = true, optional = true } magicblock-magic-program-api = { workspace = true } magicblock-delegation-program = { workspace = true, features = ["no-entrypoint", "core"], default-features = false } +# magicblock-delegation-program = { workspace = true, features = ["no-entrypoint", "sdk"], default-features = false } // updating from "core" to "sdk" # Fix for older toolchain base64ct = { workspace = true } diff --git a/rust/sdk/src/anchor.rs b/rust/sdk/src/anchor.rs index 2112552..e963228 100644 --- a/rust/sdk/src/anchor.rs +++ b/rust/sdk/src/anchor.rs @@ -4,6 +4,9 @@ pub use ephemeral_rollups_sdk_attribute_ephemeral::ephemeral; #[cfg(feature = "anchor")] pub use ephemeral_rollups_sdk_attribute_commit::commit; +#[cfg(feature = "anchor")] +pub use ephemeral_rollups_sdk_attribute_action::action; + #[cfg(feature = "anchor")] pub use ephemeral_rollups_sdk_attribute_delegate::delegate; diff --git a/ts/kit/package.json b/ts/kit/package.json index 052d6f4..fef9ddc 100644 --- a/ts/kit/package.json +++ b/ts/kit/package.json @@ -41,7 +41,6 @@ "vitest": "^3.2.4" }, "dependencies": { - "@metaplex-foundation/beet": "^0.7.2", "@phala/dcap-qvl-web": "^0.2.7", "@solana-program/system": "^0.9.0", "@solana/kit": "^4.0.0", diff --git a/ts/kit/src/__test__/generated.test.ts b/ts/kit/src/__test__/generated.test.ts new file mode 100644 index 0000000..f2d178d --- /dev/null +++ b/ts/kit/src/__test__/generated.test.ts @@ -0,0 +1,150 @@ +import { describe, it, expect } from "vitest"; +import { + createDelegateInstruction, + serializeDelegateInstructionData, + createTopUpEscrowInstruction, + serializeTopUpEscrowInstructionData, + createCloseEscrowInstruction, + serializeCloseEscrowInstructionData, +} from "../generated/delegation-program-instructions"; +import { getAddressFromPublicKey } from "@solana/kit"; + +describe("Generated Instructions (@solana/kit)", () => { + const mockAddress = "11111111111111111111111111111111" as any; + + describe("delegate instruction", () => { + it("should create a delegate instruction", () => { + const instruction = createDelegateInstruction( + { + payer: mockAddress, + delegatedAccount: mockAddress, + ownerProgram: mockAddress, + delegateBuffer: mockAddress, + delegationRecord: mockAddress, + delegationMetadata: mockAddress, + systemProgram: mockAddress, + }, + { + commitFrequencyMs: 1000, + seeds: [new Uint8Array([1, 2, 3])], + validator: null, + } + ); + + expect(instruction.accounts).toHaveLength(7); + expect(instruction.data).toBeDefined(); + }); + + it("should serialize delegate instruction data with correct discriminator", () => { + const [data] = serializeDelegateInstructionData({ + commitFrequencyMs: 1000, + seeds: [new Uint8Array([1, 2, 3])], + validator: null, + }); + + // Check discriminator + expect(data[0]).toBe(0); + expect(data[1]).toBe(0); + expect(data[2]).toBe(0); + expect(data[3]).toBe(0); + expect(data[4]).toBe(0); + expect(data[5]).toBe(0); + expect(data[6]).toBe(0); + expect(data[7]).toBe(0); + + // Check commit_frequency_ms (u32 at offset 8) + const frequency = new DataView(data.buffer, 8, 4).getUint32(0, true); + expect(frequency).toBe(1000); + }); + + it("should include validator in serialized data when provided", () => { + const validatorKey = mockAddress; + const [data] = serializeDelegateInstructionData({ + commitFrequencyMs: 500, + seeds: [], + validator: validatorKey, + }); + + expect(data.length).toBeGreaterThan(17); + }); + }); + + describe("topUpEscrow instruction", () => { + it("should create a topUpEscrow instruction", () => { + const instruction = createTopUpEscrowInstruction( + { + payer: mockAddress, + pubkey: mockAddress, + ephemeralBalanceAccount: mockAddress, + systemProgram: mockAddress, + }, + { + amount: BigInt(1000000), + index: 255, + } + ); + + expect(instruction.accounts).toHaveLength(4); + expect(instruction.data).toBeDefined(); + expect(instruction.data?.length).toBe(17); + }); + + it("should serialize topUpEscrow instruction data correctly", () => { + const [data] = serializeTopUpEscrowInstructionData({ + amount: BigInt(5000000), + index: 255, + }); + + expect(data.length).toBe(17); + + // Check discriminator + expect(data[0]).toBe(9); + for (let i = 1; i < 8; i++) { + expect(data[i]).toBe(0); + } + + // Check amount (u64 at offset 8) + const amount = new DataView(data.buffer, 8, 8).getBigUint64(0, true); + expect(amount).toBe(BigInt(5000000)); + + // Check index (u8 at offset 16) + expect(data[16]).toBe(255); + }); + }); + + describe("closeEscrow instruction", () => { + it("should create a closeEscrow instruction", () => { + const instruction = createCloseEscrowInstruction( + { + payer: mockAddress, + ephemeralBalanceAccount: mockAddress, + systemProgram: mockAddress, + }, + { + index: 255, + } + ); + + expect(instruction.accounts).toHaveLength(3); + expect(instruction.data).toBeDefined(); + expect(instruction.data?.length).toBe(9); + }); + + it("should serialize closeEscrow instruction data correctly", () => { + const [data] = serializeCloseEscrowInstructionData({ + index: 255, + }); + + expect(data.length).toBe(9); + + // Check discriminator + expect(data[0]).toBe(11); + for (let i = 1; i < 8; i++) { + expect(data[i]).toBe(0); + } + + // Check index (u8 at offset 8) + expect(data[8]).toBe(255); + }); + }); +}); diff --git a/ts/kit/src/generated/README.md b/ts/kit/src/generated/README.md new file mode 100644 index 0000000..bf78a19 --- /dev/null +++ b/ts/kit/src/generated/README.md @@ -0,0 +1,28 @@ +# Generated Code from IDL (@solana/kit) + +This directory contains instruction types and serialization code generated from the delegation program IDL for @solana/kit. + +## Generated Instructions + +- `instructions/delegate.ts` - Delegate instruction (discriminator: [0,0,0,0,0,0,0,0]) +- `instructions/topUpEphemeralBalance.ts` - TopUpEphemeralBalance instruction (discriminator: [9,0,0,0,0,0,0,0]) +- `instructions/closeEphemeralBalance.ts` - CloseEphemeralBalance instruction (discriminator: [11,0,0,0,0,0,0,0]) + +## Adding New Instructions + +To add a new instruction from the IDL: + +1. Create a new file in `instructions/` directory (e.g., `myInstruction.ts`) +2. Follow the pattern from existing instructions: + - Export the instruction args type + - Implement `create{InstructionName}Instruction()` function that returns an `Instruction` + - Implement `serialize{InstructionName}InstructionData()` function that returns `[Uint8Array]` +3. Export from `instructions/index.ts` + +## Note + +Code for @solana/kit is manually maintained since Solita doesn't support the @solana/kit API. For web3.js instructions, use the Solita code generation tool from the `web3js/` folder. + +## IDL Reference + +The IDL is fetched from: `https://raw.githubusercontent.com/magicblock-labs/delegation-program/main/idl/delegation.json` diff --git a/ts/kit/src/generated/delegation-program-instructions/closeEphemeralBalance.ts b/ts/kit/src/generated/delegation-program-instructions/closeEphemeralBalance.ts new file mode 100644 index 0000000..1c71cbd --- /dev/null +++ b/ts/kit/src/generated/delegation-program-instructions/closeEphemeralBalance.ts @@ -0,0 +1,68 @@ +import { + AccountMeta, + Address, + AccountRole, + Instruction, +} from "@solana/kit"; +import { DELEGATION_PROGRAM_ID } from "../../constants"; + +/** + * CloseEscrow instruction arguments + */ +export type CloseEscrowInstructionArgs = { + index?: number; // defaults to 255 +}; + +/** + * Instruction: CloseEscrow + * Discriminator: [11,0,0,0,0,0,0,0] + */ +export function createCloseEscrowInstruction( + accounts: { + payer: Address; + ephemeralBalanceAccount: Address; + systemProgram: Address; + }, + args?: CloseEscrowInstructionArgs +): Instruction { + const [data] = serializeCloseEscrowInstructionData(args ?? {}); + + const accounts_: AccountMeta[] = [ + { + address: accounts.payer, + role: AccountRole.READONLY_SIGNER, + }, + { + address: accounts.ephemeralBalanceAccount, + role: AccountRole.WRITABLE, + }, + { + address: accounts.systemProgram, + role: AccountRole.READONLY, + }, + ]; + + return { + accounts: accounts_, + data, + programAddress: DELEGATION_PROGRAM_ID, + }; +} + +export function serializeCloseEscrowInstructionData( + args?: CloseEscrowInstructionArgs +): [Uint8Array] { + const discriminator = [11, 0, 0, 0, 0, 0, 0, 0]; + const data = new Uint8Array(9); + let offset = 0; + + // Write discriminator + for (let i = 0; i < 8; i++) { + data[offset++] = discriminator[i]; + } + + // Write index as u8 + data[offset] = args?.index ?? 255; + + return [data]; +} diff --git a/ts/kit/src/generated/delegation-program-instructions/delegate.ts b/ts/kit/src/generated/delegation-program-instructions/delegate.ts new file mode 100644 index 0000000..9b6abfa --- /dev/null +++ b/ts/kit/src/generated/delegation-program-instructions/delegate.ts @@ -0,0 +1,118 @@ +import { + AccountMeta, + Address, + AccountRole, + Instruction, +} from "@solana/kit"; +import { DELEGATION_PROGRAM_ID } from "../../constants"; + +/** + * Delegate instruction arguments + */ +export type DelegateInstructionArgs = { + commitFrequencyMs: number; + seeds: Uint8Array[]; + validator: Address | null; +}; + +/** + * Instruction: Delegate + * Discriminator: [0,0,0,0,0,0,0,0] + */ +export function createDelegateInstruction( + accounts: { + payer: Address; + delegatedAccount: Address; + ownerProgram: Address; + delegateBuffer: Address; + delegationRecord: Address; + delegationMetadata: Address; + systemProgram: Address; + }, + args: DelegateInstructionArgs +): Instruction { + const [data] = serializeDelegateInstructionData(args); + + const accounts_: AccountMeta[] = [ + { + address: accounts.payer, + role: AccountRole.WRITABLE_SIGNER, + }, + { + address: accounts.delegatedAccount, + role: AccountRole.WRITABLE_SIGNER, + }, + { + address: accounts.ownerProgram, + role: AccountRole.READONLY, + }, + { + address: accounts.delegateBuffer, + role: AccountRole.WRITABLE, + }, + { + address: accounts.delegationRecord, + role: AccountRole.WRITABLE, + }, + { + address: accounts.delegationMetadata, + role: AccountRole.WRITABLE, + }, + { + address: accounts.systemProgram, + role: AccountRole.READONLY, + }, + ]; + + return { + accounts: accounts_, + data, + programAddress: DELEGATION_PROGRAM_ID, + }; +} + +export function serializeDelegateInstructionData( + args: DelegateInstructionArgs +): [Uint8Array] { + const discriminator = [0, 0, 0, 0, 0, 0, 0, 0]; + let offset = 0; + let buffer = new ArrayBuffer(1024); // Initial size, will adjust + const view = new DataView(buffer); + + // Write discriminator + for (let i = 0; i < 8; i++) { + view.setUint8(offset++, discriminator[i]); + } + + // Write commit_frequency_ms (u32) + view.setUint32(offset, args.commitFrequencyMs, true); + offset += 4; + + // Write seeds (vec>) + // Format: u32 length, then each inner vec as u32 length + data + view.setUint32(offset, args.seeds.length, true); + offset += 4; + + for (const seed of args.seeds) { + view.setUint32(offset, seed.length, true); + offset += 4; + const seedBytes = new Uint8Array(buffer, offset, seed.length); + seedBytes.set(seed); + offset += seed.length; + } + + // Write validator (option) + if (args.validator !== null) { + view.setUint8(offset, 1); // Some discriminant + offset += 1; + // Note: This assumes pubkey is 32 bytes. In practice, you'd need to + // decode the Address to its bytes representation + // For now, this is a placeholder + offset += 32; + } else { + view.setUint8(offset, 0); // None discriminant + offset += 1; + } + + return [new Uint8Array(buffer, 0, offset)]; +} diff --git a/ts/kit/src/generated/delegation-program-instructions/index.ts b/ts/kit/src/generated/delegation-program-instructions/index.ts new file mode 100644 index 0000000..54a0d44 --- /dev/null +++ b/ts/kit/src/generated/delegation-program-instructions/index.ts @@ -0,0 +1,3 @@ +export * from './delegate'; +export * from './topUpEphemeralBalance'; +export * from './closeEphemeralBalance'; diff --git a/ts/kit/src/generated/delegation-program-instructions/topUpEphemeralBalance.ts b/ts/kit/src/generated/delegation-program-instructions/topUpEphemeralBalance.ts new file mode 100644 index 0000000..fb4baa5 --- /dev/null +++ b/ts/kit/src/generated/delegation-program-instructions/topUpEphemeralBalance.ts @@ -0,0 +1,79 @@ +import { + AccountMeta, + Address, + AccountRole, + Instruction, +} from "@solana/kit"; +import { DELEGATION_PROGRAM_ID } from "../../constants"; + +/** + * TopUpEscrow instruction arguments + */ +export type TopUpEscrowInstructionArgs = { + amount: bigint; + index?: number; // defaults to 255 +}; + +/** + * Instruction: TopUpEscrow + * Discriminator: [9,0,0,0,0,0,0,0] + */ +export function createTopUpEscrowInstruction( + accounts: { + payer: Address; + pubkey: Address; + ephemeralBalanceAccount: Address; + systemProgram: Address; + }, + args: TopUpEscrowInstructionArgs +): Instruction { + const [data] = serializeTopUpEscrowInstructionData(args); + + const accounts_: AccountMeta[] = [ + { + address: accounts.payer, + role: AccountRole.WRITABLE_SIGNER, + }, + { + address: accounts.pubkey, + role: AccountRole.READONLY, + }, + { + address: accounts.ephemeralBalanceAccount, + role: AccountRole.WRITABLE, + }, + { + address: accounts.systemProgram, + role: AccountRole.READONLY, + }, + ]; + + return { + accounts: accounts_, + data, + programAddress: DELEGATION_PROGRAM_ID, + }; +} + +export function serializeTopUpEscrowInstructionData( + args: TopUpEscrowInstructionArgs +): [Uint8Array] { + const discriminator = [9, 0, 0, 0, 0, 0, 0, 0]; + const data = new Uint8Array(17); + let offset = 0; + + // Write discriminator + for (let i = 0; i < 8; i++) { + data[offset++] = discriminator[i]; + } + + // Write amount as u64 little-endian + const amountView = new DataView(data.buffer, offset, 8); + amountView.setBigUint64(0, args.amount, true); + offset += 8; + + // Write index as u8 + data[offset] = args.index ?? 255; + + return [data]; +} diff --git a/ts/kit/src/index.ts b/ts/kit/src/index.ts index 5ba67dc..690bf11 100644 --- a/ts/kit/src/index.ts +++ b/ts/kit/src/index.ts @@ -1,5 +1,5 @@ export * from "./constants.js"; -export * from "./instructions/delegate.js"; +export * from "./generated/delegation-program-instructions/index.js"; export * from "./pda.js"; export * from "./utils.js"; export * from "./resolver.js"; diff --git a/ts/kit/src/instructions/delegate.ts b/ts/kit/src/instructions/delegate.ts deleted file mode 100644 index 176cd8a..0000000 --- a/ts/kit/src/instructions/delegate.ts +++ /dev/null @@ -1,118 +0,0 @@ -import * as beet from "@metaplex-foundation/beet"; -import { AccountMeta, Address, AccountRole, Instruction } from "@solana/kit"; -import { SYSTEM_PROGRAM_ADDRESS } from "@solana-program/system"; -import { DELEGATION_PROGRAM_ID } from "../constants"; -import { - delegateBufferPdaFromDelegatedAccountAndOwnerProgram, - delegationMetadataPdaFromDelegatedAccount, - delegationRecordPdaFromDelegatedAccount, -} from "../pda"; - -export const delegateStruct = new beet.FixableBeetArgsStruct<{ - instructionDiscriminator: number[]; - commit_frequency_ms: beet.bignum; - seeds: number[][]; - validator?: beet.COption; -}>( - [ - ["instructionDiscriminator", beet.uniformFixedSizeArray(beet.u8, 8)], - ["commit_frequency_ms", beet.u32], - ["seeds", beet.array(beet.array(beet.u8))], - ["validator", beet.coption(beet.uniformFixedSizeArray(beet.u8, 32))], - ], - "DelegateInstructionArgs", -); -export const delegateInstructionDiscriminator = [0, 0, 0, 0, 0, 0, 0, 0]; - -// Define the DelegateAccountArgs structure -interface DelegateAccountArgs { - commit_frequency_ms: number; - seeds: Uint8Array[][]; - validator?: Address; -} -// Function to create a delegate instruction -export async function createDelegateInstruction( - accountsInput: { - payer: Address; - delegatedAccount: Address; - ownerProgram: Address; - delegationRecord?: Address; - delegationMetadata?: Address; - systemProgram?: Address; - validator?: Address; - }, - args?: DelegateAccountArgs, - programId = DELEGATION_PROGRAM_ID, -) { - const delegateBufferPda = - await delegateBufferPdaFromDelegatedAccountAndOwnerProgram( - accountsInput.delegatedAccount, - accountsInput.ownerProgram, - ); - - const delegationRecordPda = await delegationRecordPdaFromDelegatedAccount( - accountsInput.delegatedAccount, - ); - const delegationMetadataPda = await delegationMetadataPdaFromDelegatedAccount( - accountsInput.delegatedAccount, - ); - - args = args ?? { - commit_frequency_ms: 4294967295, // 2 ** 4 - 1, - seeds: [], - }; - - const accounts: AccountMeta[] = [ - { - address: accountsInput.payer, - role: AccountRole.READONLY_SIGNER, - }, - { - address: accountsInput.delegatedAccount, - role: AccountRole.WRITABLE_SIGNER, - }, - { - address: accountsInput.ownerProgram, - role: AccountRole.READONLY, - }, - { - address: delegateBufferPda, - role: AccountRole.WRITABLE, - }, - { - address: accountsInput.delegationRecord ?? delegationRecordPda, - role: AccountRole.WRITABLE, - }, - { - address: accountsInput.delegationMetadata ?? delegationMetadataPda, - role: AccountRole.WRITABLE, - }, - { - address: accountsInput.systemProgram ?? SYSTEM_PROGRAM_ADDRESS, - role: AccountRole.READONLY, - }, - // Only add validator if it exists - ...(accountsInput.validator - ? [ - { - address: accountsInput.validator, - role: AccountRole.READONLY, - }, - ] - : []), - ]; - - const [data] = delegateStruct.serialize({ - instructionDiscriminator: delegateInstructionDiscriminator, - commit_frequency_ms: args.commit_frequency_ms, - seeds: args.seeds.map((seed) => seed.map(Number)), - }); - - const delegateInstruction: Instruction = { - accounts, - data, - programAddress: programId, - }; - - return delegateInstruction; -} diff --git a/ts/kit/src/pda.ts b/ts/kit/src/pda.ts index fb040b2..b042142 100644 --- a/ts/kit/src/pda.ts +++ b/ts/kit/src/pda.ts @@ -42,3 +42,25 @@ export async function delegateBufferPdaFromDelegatedAccountAndOwnerProgram( }); return delegateBufferPda; } + +/** + * Derives the escrow PDA from a payer address + * @param payer The payer address + * @param index The index of the ephemeral balance account + * @param programId The delegation program ID + * @returns The derived ephemeral balance PDA + */ +export async function escrowPdaFromEscrowAuthority( + escrowAuthority: Address, + index: number = 255, +) { + if (index < 0 || index > 255) { + throw new Error("Index must be between 0 and 255"); + } + const addressEncoder = getAddressEncoder(); + const [escrowPda] = await getProgramDerivedAddress({ + programAddress: escrowAuthority, + seeds: [Buffer.from("balance"), addressEncoder.encode(escrowAuthority), Buffer.from([index])], + }); + return escrowPda +} \ No newline at end of file diff --git a/ts/kit/yarn.lock b/ts/kit/yarn.lock index 1ae72f2..c2b9c8a 100644 --- a/ts/kit/yarn.lock +++ b/ts/kit/yarn.lock @@ -2,6 +2,11 @@ # yarn lockfile v1 +"@babel/runtime@^7.25.0": + version "7.28.4" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.28.4.tgz#a70226016fabe25c5783b2f22d3e1c9bc5ca3326" + integrity sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ== + "@esbuild/aix-ppc64@0.25.11": version "0.25.11" resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.25.11.tgz#2ae33300598132cc4cf580dbbb28d30fed3c5c49" @@ -188,7 +193,17 @@ resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz#6912b00d2c631c0d15ce1a7ab57cd657f2a8f8ba" integrity sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og== -"@metaplex-foundation/beet@^0.7.2": +"@metaplex-foundation/beet-solana@^0.3.1": + version "0.3.1" + resolved "https://registry.yarnpkg.com/@metaplex-foundation/beet-solana/-/beet-solana-0.3.1.tgz#4b37cda5c7f32ffd2bdd8b3164edc05c6463ab35" + integrity sha512-tgyEl6dvtLln8XX81JyBvWjIiEcjTkUwZbrM5dIobTmoqMuGewSyk9CClno8qsMsFdB5T3jC91Rjeqmu/6xk2g== + dependencies: + "@metaplex-foundation/beet" ">=0.1.0" + "@solana/web3.js" "^1.56.2" + bs58 "^5.0.0" + debug "^4.3.4" + +"@metaplex-foundation/beet@>=0.1.0", "@metaplex-foundation/beet@^0.7.1": version "0.7.2" resolved "https://registry.yarnpkg.com/@metaplex-foundation/beet/-/beet-0.7.2.tgz#fa4726e4cfd4fb6fed6cddc9b5213c1c2a2d0b77" integrity sha512-K+g3WhyFxKPc0xIvcIjNyV1eaTVJTiuaHZpig7Xx0MuYRMoJLLvhLTnUXhFdR5Tu2l2QSyKwfyXDgZlzhULqFg== @@ -198,6 +213,45 @@ bn.js "^5.2.0" debug "^4.3.3" +"@metaplex-foundation/rustbin@^0.3.0": + version "0.3.5" + resolved "https://registry.yarnpkg.com/@metaplex-foundation/rustbin/-/rustbin-0.3.5.tgz#56d028afd96c2b56ad3bbea22ff454adde900e8c" + integrity sha512-m0wkRBEQB/8krwMwKBvFugufZtYwMXiGHud2cTDAv+aGXK4M90y0Hx67/wpu+AqqoQfdV8VM9YezUOHKD+Z5kA== + dependencies: + debug "^4.3.3" + semver "^7.3.7" + text-table "^0.2.0" + toml "^3.0.0" + +"@metaplex-foundation/solita@^0.20.1": + version "0.20.1" + resolved "https://registry.yarnpkg.com/@metaplex-foundation/solita/-/solita-0.20.1.tgz#a92cfa6696b6cddd6a95db050e9c999293d68ce4" + integrity sha512-E2bHGzT6wA/sXWBLgJ50ZQNvukPnQlH6kRU6m6lmatJdEOjNWhR1lLI7ESIk/i4ZiSdHZkc/Q6ile8eIlXOzNQ== + dependencies: + "@metaplex-foundation/beet" "^0.7.1" + "@metaplex-foundation/beet-solana" "^0.3.1" + "@metaplex-foundation/rustbin" "^0.3.0" + "@solana/web3.js" "^1.56.2" + ansi-colors "^4.1.3" + camelcase "^6.2.1" + debug "^4.3.3" + js-sha256 "^0.9.0" + prettier "^2.5.1" + snake-case "^3.0.4" + spok "^1.4.3" + +"@noble/curves@^1.4.2": + version "1.9.7" + resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.9.7.tgz#79d04b4758a43e4bca2cbdc62e7771352fa6b951" + integrity sha512-gbKGcRUYIjA3/zCCNaWDciTMFI0dCkvou3TL8Zmy5Nc7sJ47a0jtOeZoTaMxkuqRo9cRhjOdZJXegxYE5FN/xw== + dependencies: + "@noble/hashes" "1.8.0" + +"@noble/hashes@1.8.0", "@noble/hashes@^1.4.0": + version "1.8.0" + resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.8.0.tgz#cee43d801fcef9644b11b8194857695acd5f815a" + integrity sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A== + "@nodelib/fs.scandir@2.1.5": version "2.1.5" resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" @@ -379,6 +433,20 @@ dependencies: "@solana/errors" "4.0.0" +"@solana/buffer-layout@^4.0.1": + version "4.0.1" + resolved "https://registry.yarnpkg.com/@solana/buffer-layout/-/buffer-layout-4.0.1.tgz#b996235eaec15b1e0b5092a8ed6028df77fa6c15" + integrity sha512-E1ImOIAD1tBZFRdjeM4/pzTiTApC0AOBGwyAMS4fwIodCWArzJ3DWdoh8cKxeFM2fElkxBh2Aqts1BPC373rHA== + dependencies: + buffer "~6.0.3" + +"@solana/codecs-core@2.3.0": + version "2.3.0" + resolved "https://registry.yarnpkg.com/@solana/codecs-core/-/codecs-core-2.3.0.tgz#6bf2bb565cb1ae880f8018635c92f751465d8695" + integrity sha512-oG+VZzN6YhBHIoSKgS5ESM9VIGzhWjEHEGNPSibiDTxFhsFWxNaz8LbMDPjBUE69r9wmdGLkrQ+wVPbnJcZPvw== + dependencies: + "@solana/errors" "2.3.0" + "@solana/codecs-core@4.0.0": version "4.0.0" resolved "https://registry.yarnpkg.com/@solana/codecs-core/-/codecs-core-4.0.0.tgz#0668b964df5a3e278ff276b5aa812bd739e29510" @@ -403,6 +471,14 @@ "@solana/codecs-core" "4.0.0" "@solana/errors" "4.0.0" +"@solana/codecs-numbers@^2.1.0": + version "2.3.0" + resolved "https://registry.yarnpkg.com/@solana/codecs-numbers/-/codecs-numbers-2.3.0.tgz#ac7e7f38aaf7fcd22ce2061fbdcd625e73828dc6" + integrity sha512-jFvvwKJKffvG7Iz9dmN51OGB7JBcy2CJ6Xf3NqD/VP90xak66m/Lg48T01u5IQ/hc15mChVHiBm+HHuOFDUrQg== + dependencies: + "@solana/codecs-core" "2.3.0" + "@solana/errors" "2.3.0" + "@solana/codecs-strings@4.0.0": version "4.0.0" resolved "https://registry.yarnpkg.com/@solana/codecs-strings/-/codecs-strings-4.0.0.tgz#b4c77d6ff6eeec868a71e5b0cb42bdb9f0c6b500" @@ -423,6 +499,14 @@ "@solana/codecs-strings" "4.0.0" "@solana/options" "4.0.0" +"@solana/errors@2.3.0": + version "2.3.0" + resolved "https://registry.yarnpkg.com/@solana/errors/-/errors-2.3.0.tgz#4ac9380343dbeffb9dffbcb77c28d0e457c5fa31" + integrity sha512-66RI9MAbwYV0UtP7kGcTBVLxJgUxoZGm8Fbc0ah+lGiAw17Gugco6+9GrJCV83VyF2mDWyYnYM9qdI3yjgpnaQ== + dependencies: + chalk "^5.4.1" + commander "^14.0.0" + "@solana/errors@4.0.0": version "4.0.0" resolved "https://registry.yarnpkg.com/@solana/errors/-/errors-4.0.0.tgz#7fa9e8b69c4a199acab1b863b234be69772b1914" @@ -738,6 +822,27 @@ "@solana/rpc-types" "4.0.0" "@solana/transaction-messages" "4.0.0" +"@solana/web3.js@^1.56.2": + version "1.98.4" + resolved "https://registry.yarnpkg.com/@solana/web3.js/-/web3.js-1.98.4.tgz#df51d78be9d865181ec5138b4e699d48e6895bbe" + integrity sha512-vv9lfnvjUsRiq//+j5pBdXig0IQdtzA0BRZ3bXEP4KaIyF1CcaydWqgyzQgfZMNIsWNWmG+AUHwPy4AHOD6gpw== + dependencies: + "@babel/runtime" "^7.25.0" + "@noble/curves" "^1.4.2" + "@noble/hashes" "^1.4.0" + "@solana/buffer-layout" "^4.0.1" + "@solana/codecs-numbers" "^2.1.0" + agentkeepalive "^4.5.0" + bn.js "^5.2.1" + borsh "^0.7.0" + bs58 "^4.0.1" + buffer "6.0.3" + fast-stable-stringify "^1.0.0" + jayson "^4.1.1" + node-fetch "^2.7.0" + rpc-websockets "^9.0.2" + superstruct "^2.0.2" + "@swc/helpers@^0.5.11": version "0.5.17" resolved "https://registry.yarnpkg.com/@swc/helpers/-/helpers-0.5.17.tgz#5a7be95ac0f0bf186e7e6e890e7a6f6cda6ce971" @@ -752,6 +857,13 @@ dependencies: "@types/deep-eql" "*" +"@types/connect@^3.4.33": + version "3.4.38" + resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.38.tgz#5ba7f3bc4fbbdeaff8dded952e5ff2cc53f8d858" + integrity sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug== + dependencies: + "@types/node" "*" + "@types/deep-eql@*": version "4.0.2" resolved "https://registry.yarnpkg.com/@types/deep-eql/-/deep-eql-4.0.2.tgz#334311971d3a07121e7eb91b684a605e7eea9cbd" @@ -779,6 +891,11 @@ dependencies: undici-types "~7.14.0" +"@types/node@^12.12.54": + version "12.20.55" + resolved "https://registry.yarnpkg.com/@types/node/-/node-12.20.55.tgz#c329cbd434c42164f846b909bd6f85b5537f6240" + integrity sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ== + "@types/semver@^7.5.0": version "7.7.1" resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.7.1.tgz#3ce3af1a5524ef327d2da9e4fd8b6d95c8d70528" @@ -789,6 +906,13 @@ resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-8.3.4.tgz#bd86a43617df0594787d38b735f55c805becf1bc" integrity sha512-c/I8ZRb51j+pYGAu5CrFMRxqZ2ke4y2grEBO5AUjgSkSk+qT2Ea+OdWElz/OiMf5MNpn2b17kuVBwZLQJXzihw== +"@types/ws@^7.4.4": + version "7.4.7" + resolved "https://registry.yarnpkg.com/@types/ws/-/ws-7.4.7.tgz#f7c390a36f7a0679aa69de2d501319f4f8d9b702" + integrity sha512-JQbbmxZTZehdc2iszGKs5oC3NFnjeay7mtAWrdt7qNtAVK0g19muApzAy4bm9byz79xa2ZnO/BOBC2R8RC5Lww== + dependencies: + "@types/node" "*" + "@types/ws@^8.2.2": version "8.18.1" resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.18.1.tgz#48464e4bf2ddfd17db13d845467f6070ffea4aa9" @@ -958,6 +1082,13 @@ acorn@^8.9.0: resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.15.0.tgz#a360898bc415edaac46c8241f6383975b930b816" integrity sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg== +agentkeepalive@^4.5.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/agentkeepalive/-/agentkeepalive-4.6.0.tgz#35f73e94b3f40bf65f105219c623ad19c136ea6a" + integrity sha512-kja8j7PjmncONqaTsB8fQ+wE2mSU2DJ9D4XKoJ5PFWIdRMa6SLSN1ff4mOr4jCbfRSsxR4keIiySJU0N9T5hIQ== + dependencies: + humanize-ms "^1.2.1" + ajv@^6.12.4: version "6.12.6" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" @@ -968,6 +1099,11 @@ ajv@^6.12.4: json-schema-traverse "^0.4.1" uri-js "^4.2.2" +ansi-colors@^4.1.3: + version "4.1.3" + resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.3.tgz#37611340eb2243e70cc604cad35d63270d48781b" + integrity sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw== + ansi-regex@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" @@ -980,7 +1116,7 @@ ansi-styles@^4.1.0: dependencies: color-convert "^2.0.1" -ansicolors@^0.3.2: +ansicolors@^0.3.2, ansicolors@~0.3.2: version "0.3.2" resolved "https://registry.yarnpkg.com/ansicolors/-/ansicolors-0.3.2.tgz#665597de86a9ffe3aa9bfbe6cae5c6ea426b4979" integrity sha512-QXu7BPrP29VllRxH8GwB7x5iX5qWKAAMLqKQGWTeLWVlNHNOpVMJ91dsxQAIWXpjuW5wqvxu3Jd/nRjrJ+0pqg== @@ -1096,6 +1232,18 @@ balanced-match@^1.0.0: resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== +base-x@^3.0.2: + version "3.0.11" + resolved "https://registry.yarnpkg.com/base-x/-/base-x-3.0.11.tgz#40d80e2a1aeacba29792ccc6c5354806421287ff" + integrity sha512-xz7wQ8xDhdyP7tQxwdteLYeFfS68tSMNCZ/Y37WJ4bhGfKPpqEIlmIyueQHqOyoPhE6xNUqjzRr8ra0eF9VRvA== + dependencies: + safe-buffer "^5.0.1" + +base-x@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/base-x/-/base-x-4.0.1.tgz#817fb7b57143c501f649805cb247617ad016a885" + integrity sha512-uAZ8x6r6S3aUM9rbHGVOIsR15U/ZSc82b3ymnCPsT45Gk1DDvhDPdIgB5MrhirZWt+5K0EEPQH985kNqZgNPFw== + base-x@^5.0.0: version "5.0.1" resolved "https://registry.yarnpkg.com/base-x/-/base-x-5.0.1.tgz#16bf35254be1df8aca15e36b7c1dda74b2aa6b03" @@ -1106,11 +1254,20 @@ base64-js@^1.3.1: resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== -bn.js@^5.2.0: +bn.js@^5.2.0, bn.js@^5.2.1: version "5.2.2" resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.2.tgz#82c09f9ebbb17107cd72cb7fd39bd1f9d0aaa566" integrity sha512-v2YAxEmKaBLahNwE1mjp4WON6huMNeuDvagFZW+ASCuA/ku0bXR9hSMw0XpiqMoA3+rmnyck/tPRSFQkoC9Cuw== +borsh@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/borsh/-/borsh-0.7.0.tgz#6e9560d719d86d90dc589bca60ffc8a6c51fec2a" + integrity sha512-CLCsZGIBCFnPtkNnieW/a8wmreDmfUtjU2m9yHrzPXIlNbqVs0AQrSatSG6vdNYUqdc83tkQi2eHfF98ubzQLA== + dependencies: + bn.js "^5.2.0" + bs58 "^4.0.0" + text-encoding-utf-8 "^1.0.2" + brace-expansion@^1.1.7: version "1.1.12" resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.12.tgz#ab9b454466e5a8cc3a187beaad580412a9c5b843" @@ -1133,6 +1290,20 @@ braces@^3.0.3: dependencies: fill-range "^7.1.1" +bs58@^4.0.0, bs58@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/bs58/-/bs58-4.0.1.tgz#be161e76c354f6f788ae4071f63f34e8c4f0a42a" + integrity sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw== + dependencies: + base-x "^3.0.2" + +bs58@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/bs58/-/bs58-5.0.0.tgz#865575b4d13c09ea2a84622df6c8cbeb54ffc279" + integrity sha512-r+ihvQJvahgYT50JD05dyJNKlmmSlMoOGwn1lCcEzanPglg7TxYjioQUYehQ9mAR/+hOSd2jRc/Z2y5UxBymvQ== + dependencies: + base-x "^4.0.0" + bs58@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/bs58/-/bs58-6.0.0.tgz#a2cda0130558535dd281a2f8697df79caaf425d8" @@ -1140,7 +1311,7 @@ bs58@^6.0.0: dependencies: base-x "^5.0.0" -buffer@^6.0.3: +buffer@6.0.3, buffer@^6.0.3, buffer@~6.0.3: version "6.0.3" resolved "https://registry.yarnpkg.com/buffer/-/buffer-6.0.3.tgz#2ace578459cc8fbe2a70aaa8f52ee63b6a74c6c6" integrity sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA== @@ -1203,6 +1374,11 @@ callsites@^3.0.0: resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== +camelcase@^6.2.1: + version "6.3.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" + integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== + chai@^5.2.0: version "5.3.3" resolved "https://registry.yarnpkg.com/chai/-/chai-5.3.3.tgz#dd3da955e270916a4bd3f625f4b919996ada7e06" @@ -1214,12 +1390,12 @@ chai@^5.2.0: loupe "^3.1.0" pathval "^2.0.0" -chalk@5.6.2: +chalk@5.6.2, chalk@^5.4.1: version "5.6.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-5.6.2.tgz#b1238b6e23ea337af71c7f8a295db5af0c158aea" integrity sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA== -chalk@^4.0.0: +chalk@^4.0.0, chalk@~4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== @@ -1249,6 +1425,21 @@ commander@14.0.1: resolved "https://registry.yarnpkg.com/commander/-/commander-14.0.1.tgz#2f9225c19e6ebd0dc4404dd45821b2caa17ea09b" integrity sha512-2JkV3gUZUVrbNA+1sjBOYLsMZ5cEEl8GTFP2a4AVz5hvasAMCQ1D2l2le/cX+pV4N6ZU17zjUahLpIXRrnWL8A== +commander@^12.1.0: + version "12.1.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-12.1.0.tgz#01423b36f501259fdaac4d0e4d60c96c991585d3" + integrity sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA== + +commander@^14.0.0: + version "14.0.2" + resolved "https://registry.yarnpkg.com/commander/-/commander-14.0.2.tgz#b71fd37fe4069e4c3c7c13925252ada4eba14e8e" + integrity sha512-TywoWNNRbhoD0BXs1P3ZEScW8W5iKrnbithIl0YH+uCmBd0QpPOA8yc82DS3BIE5Ma6FnBVUsJ7wVUDz4dvOWQ== + +commander@^2.20.3: + version "2.20.3" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" + integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== + concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" @@ -1332,6 +1523,11 @@ define-properties@^1.1.3, define-properties@^1.2.1: has-property-descriptors "^1.0.0" object-keys "^1.1.1" +delay@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/delay/-/delay-5.0.0.tgz#137045ef1b96e5071060dd5be60bf9334436bd1d" + integrity sha512-ReEBKkIfe4ya47wlPYf/gu5ib6yUG0/Aez0JQZQz94kiWtRQvZIQbTiehsnwHvLSWJnQdhVeqYue7Id1dKr0qw== + dir-glob@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" @@ -1353,6 +1549,14 @@ doctrine@^3.0.0: dependencies: esutils "^2.0.2" +dot-case@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/dot-case/-/dot-case-3.0.4.tgz#9b2b670d00a431667a8a75ba29cd1b98809ce751" + integrity sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w== + dependencies: + no-case "^3.0.4" + tslib "^2.0.3" + dunder-proto@^1.0.0, dunder-proto@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/dunder-proto/-/dunder-proto-1.0.1.tgz#d7ae667e1dc83482f8b70fd0f6eefc50da30f58a" @@ -1470,6 +1674,18 @@ es-to-primitive@^1.3.0: is-date-object "^1.0.5" is-symbol "^1.0.4" +es6-promise@^4.0.3: + version "4.2.8" + resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.8.tgz#4eb21594c972bc40553d276e510539143db53e0a" + integrity sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w== + +es6-promisify@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/es6-promisify/-/es6-promisify-5.0.0.tgz#5109d62f3e56ea967c4b63505aef08291c8a5203" + integrity sha512-C+d6UdsYDk0lMebHNR4S2NybQMMngAOnOwYBQjTOiv0MkoJMP0Myw2mgpDLBcpfCmRLxyFqYhS/CfOENq4SJhQ== + dependencies: + es6-promise "^4.0.3" + esbuild@^0.25.0: version "0.25.11" resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.25.11.tgz#0f31b82f335652580f75ef6897bba81962d9ae3d" @@ -1719,6 +1935,11 @@ expect-type@^1.2.1: resolved "https://registry.yarnpkg.com/expect-type/-/expect-type-1.2.2.tgz#c030a329fb61184126c8447585bc75a7ec6fbff3" integrity sha512-JhFGDVJ7tmDJItKhYgJCGLOWjuK9vPxiXoUFLwLDc99NlmklilbiQJwoctZtt13+xMw91MCk/REan6MWHqDjyA== +eyes@^0.1.8: + version "0.1.8" + resolved "https://registry.yarnpkg.com/eyes/-/eyes-0.1.8.tgz#62cf120234c683785d902348a800ef3e0cc20bc0" + integrity sha512-GipyPsXO1anza0AOZdy69Im7hGFCNB7Y/NGjDlZGJ3GJJLtwNSb2vrzYrTYJRrRloVx7pl+bhUaTB8yiccPvFQ== + fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: version "3.1.3" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" @@ -1750,6 +1971,11 @@ fast-levenshtein@^2.0.6: resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== +fast-stable-stringify@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fast-stable-stringify/-/fast-stable-stringify-1.0.0.tgz#5c5543462b22aeeefd36d05b34e51c78cb86d313" + integrity sha512-wpYMUmFu5f00Sm0cj2pfivpmawLZ0NKdviQ4w9zJeR8JVtOpOxHmLaJuj0vxvGqMJQWyP/COUkF75/57OKyRag== + fastq@^1.6.0: version "1.19.1" resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.19.1.tgz#d50eaba803c8846a883c16492821ebcd2cda55f5" @@ -1776,6 +2002,15 @@ fill-range@^7.1.1: dependencies: to-regex-range "^5.0.1" +find-process@^1.4.7: + version "1.4.11" + resolved "https://registry.yarnpkg.com/find-process/-/find-process-1.4.11.tgz#f7246251d396b35b9ae41fff7b87137673567fcc" + integrity sha512-mAOh9gGk9WZ4ip5UjV0o6Vb4SrfnAmtsFNzkMRH9HQiFXVQnDyQFrSHTK5UoG6E+KV+s+cIznbtwpfN41l2nFA== + dependencies: + chalk "~4.1.2" + commander "^12.1.0" + loglevel "^1.9.2" + find-up@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" @@ -1988,6 +2223,13 @@ hasown@^2.0.2: dependencies: function-bind "^1.1.2" +humanize-ms@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/humanize-ms/-/humanize-ms-1.2.1.tgz#c46e3159a293f6b896da29316d8b6fe8bb79bbed" + integrity sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ== + dependencies: + ms "^2.0.0" + ieee754@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" @@ -2254,6 +2496,34 @@ isexe@^2.0.0: resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== +isomorphic-ws@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/isomorphic-ws/-/isomorphic-ws-4.0.1.tgz#55fd4cd6c5e6491e76dc125938dd863f5cd4f2dc" + integrity sha512-BhBvN2MBpWTaSHdWRb/bwdZJ1WaehQ2L1KngkCkfLUGF0mAWAT1sQUQacEmQ0jXkFw/czDXPNQSL5u2/Krsz1w== + +jayson@^4.1.1: + version "4.2.0" + resolved "https://registry.yarnpkg.com/jayson/-/jayson-4.2.0.tgz#b71762393fa40bc9637eaf734ca6f40d3b8c0c93" + integrity sha512-VfJ9t1YLwacIubLhONk0KFeosUBwstRWQ0IRT1KDjEjnVnSOVHC3uwugyV7L0c7R9lpVyrUGT2XWiBA1UTtpyg== + dependencies: + "@types/connect" "^3.4.33" + "@types/node" "^12.12.54" + "@types/ws" "^7.4.4" + commander "^2.20.3" + delay "^5.0.0" + es6-promisify "^5.0.0" + eyes "^0.1.8" + isomorphic-ws "^4.0.1" + json-stringify-safe "^5.0.1" + stream-json "^1.9.1" + uuid "^8.3.2" + ws "^7.5.10" + +js-sha256@^0.9.0: + version "0.9.0" + resolved "https://registry.yarnpkg.com/js-sha256/-/js-sha256-0.9.0.tgz#0b89ac166583e91ef9123644bd3c5334ce9d0966" + integrity sha512-sga3MHh9sgQN2+pJ9VYZ+1LPwXOxuBJBA5nrR5/ofPfuiJBE2hnjsaN8se8JznOmGLN2p49Pe5U/ttafcs/apA== + js-tokens@^9.0.1: version "9.0.1" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-9.0.1.tgz#2ec43964658435296f6761b34e10671c2d9527f4" @@ -2281,6 +2551,11 @@ json-stable-stringify-without-jsonify@^1.0.1: resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw== +json-stringify-safe@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" + integrity sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA== + json5@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.2.tgz#63d98d60f21b313b77c4d6da18bfa69d80e1d593" @@ -2315,11 +2590,23 @@ lodash.merge@^4.6.2: resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== +loglevel@^1.9.2: + version "1.9.2" + resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.9.2.tgz#c2e028d6c757720107df4e64508530db6621ba08" + integrity sha512-HgMmCqIJSAKqo68l0rS2AanEWfkxaZ5wNiEFb5ggm08lDs9Xl2KxBlX3PTcaD2chBM1gXAYf491/M2Rv8Jwayg== + loupe@^3.1.0, loupe@^3.1.4: version "3.2.1" resolved "https://registry.yarnpkg.com/loupe/-/loupe-3.2.1.tgz#0095cf56dc5b7a9a7c08ff5b1a8796ec8ad17e76" integrity sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ== +lower-case@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/lower-case/-/lower-case-2.0.2.tgz#6fa237c63dbdc4a82ca0fd882e4722dc5e634e28" + integrity sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg== + dependencies: + tslib "^2.0.3" + magic-string@^0.30.17: version "0.30.19" resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.30.19.tgz#cebe9f104e565602e5d2098c5f2e79a77cc86da9" @@ -2364,7 +2651,7 @@ minimist@^1.2.0, minimist@^1.2.6: resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== -ms@^2.1.1, ms@^2.1.3: +ms@^2.0.0, ms@^2.1.1, ms@^2.1.3: version "2.1.3" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== @@ -2379,6 +2666,21 @@ natural-compare@^1.4.0: resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== +no-case@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/no-case/-/no-case-3.0.4.tgz#d361fd5c9800f558551a8369fc0dcd4662b6124d" + integrity sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg== + dependencies: + lower-case "^2.0.2" + tslib "^2.0.3" + +node-fetch@^2.7.0: + version "2.7.0" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d" + integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A== + dependencies: + whatwg-url "^5.0.0" + node-gyp-build@^4.3.0: version "4.8.4" resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.8.4.tgz#8a70ee85464ae52327772a90d66c6077a900cfc8" @@ -2568,6 +2870,11 @@ prettier-linter-helpers@^1.0.0: dependencies: fast-diff "^1.1.2" +prettier@^2.5.1: + version "2.8.8" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.8.8.tgz#e8c5d7e98a4305ffe3de2e1fc4aca1a71c28b1da" + integrity sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q== + prettier@^3.3.2: version "3.6.2" resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.6.2.tgz#ccda02a1003ebbb2bfda6f83a074978f608b9393" @@ -2671,6 +2978,22 @@ rollup@^4.43.0: "@rollup/rollup-win32-x64-msvc" "4.52.5" fsevents "~2.3.2" +rpc-websockets@^9.0.2: + version "9.3.1" + resolved "https://registry.yarnpkg.com/rpc-websockets/-/rpc-websockets-9.3.1.tgz#d817a59d812f68bae1215740a3f78fcdd3813698" + integrity sha512-bY6a+i/lEtBJ/mUxwsCTgevoV1P0foXTVA7UoThzaIWbM+3NDqorf8NBWs5DmqKTFeA1IoNzgvkWjFCPgnzUiQ== + dependencies: + "@swc/helpers" "^0.5.11" + "@types/uuid" "^8.3.4" + "@types/ws" "^8.2.2" + buffer "^6.0.3" + eventemitter3 "^5.0.1" + uuid "^8.3.2" + ws "^8.5.0" + optionalDependencies: + bufferutil "^4.0.1" + utf-8-validate "^5.0.2" + rpc-websockets@^9.0.4: version "9.2.0" resolved "https://registry.yarnpkg.com/rpc-websockets/-/rpc-websockets-9.2.0.tgz#c95633929ca92c311ed6e169f4c986623f001505" @@ -2705,6 +3028,11 @@ safe-array-concat@^1.1.3: has-symbols "^1.1.0" isarray "^2.0.5" +safe-buffer@^5.0.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" + integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== + safe-push-apply@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/safe-push-apply/-/safe-push-apply-1.0.0.tgz#01850e981c1602d398c85081f360e4e6d03d27f5" @@ -2727,7 +3055,7 @@ semver@^6.3.1: resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== -semver@^7.0.0, semver@^7.5.3, semver@^7.5.4: +semver@^7.0.0, semver@^7.3.7, semver@^7.5.3, semver@^7.5.4: version "7.7.3" resolved "https://registry.yarnpkg.com/semver/-/semver-7.7.3.tgz#4b5f4143d007633a8dc671cd0a6ef9147b8bb946" integrity sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q== @@ -2825,11 +3153,27 @@ slash@^3.0.0: resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== +snake-case@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/snake-case/-/snake-case-3.0.4.tgz#4f2bbd568e9935abdfd593f34c691dadb49c452c" + integrity sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg== + dependencies: + dot-case "^3.0.4" + tslib "^2.0.3" + source-map-js@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.2.1.tgz#1ce5650fddd87abc099eda37dcff024c2667ae46" integrity sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA== +spok@^1.4.3: + version "1.5.5" + resolved "https://registry.yarnpkg.com/spok/-/spok-1.5.5.tgz#a51f7f290a53131d7b7a922dfedc461dda0aed72" + integrity sha512-IrJIXY54sCNFASyHPOY+jEirkiJ26JDqsGiI0Dvhwcnkl0PEWi1PSsrkYql0rzDw8LFVTcA7rdUCAJdE2HE+2Q== + dependencies: + ansicolors "~0.3.2" + find-process "^1.4.7" + stackback@0.0.2: version "0.0.2" resolved "https://registry.yarnpkg.com/stackback/-/stackback-0.0.2.tgz#1ac8a0d9483848d1695e418b6d031a3c3ce68e3b" @@ -2848,6 +3192,18 @@ stop-iteration-iterator@^1.1.0: es-errors "^1.3.0" internal-slot "^1.1.0" +stream-chain@^2.2.5: + version "2.2.5" + resolved "https://registry.yarnpkg.com/stream-chain/-/stream-chain-2.2.5.tgz#b30967e8f14ee033c5b9a19bbe8a2cba90ba0d09" + integrity sha512-1TJmBx6aSWqZ4tx7aTpBDXK0/e2hhcNSTV8+CbFJtDjbb+I1mZ8lHit0Grw9GRT+6JbIrrDd8esncgBi8aBXGA== + +stream-json@^1.9.1: + version "1.9.1" + resolved "https://registry.yarnpkg.com/stream-json/-/stream-json-1.9.1.tgz#e3fec03e984a503718946c170db7d74556c2a187" + integrity sha512-uWkjJ+2Nt/LO9Z/JyKZbMusL8Dkh97uUBTv3AJQ74y07lVahLY4eEFsPsE97pxYBwr8nnjMAIch5eqI0gPShyw== + dependencies: + stream-chain "^2.2.5" + string.prototype.trim@^1.2.10: version "1.2.10" resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.2.10.tgz#40b2dd5ee94c959b4dcfb1d65ce72e90da480c81" @@ -2904,6 +3260,11 @@ strip-literal@^3.0.0: dependencies: js-tokens "^9.0.1" +superstruct@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/superstruct/-/superstruct-2.0.2.tgz#3f6d32fbdc11c357deff127d591a39b996300c54" + integrity sha512-uV+TFRZdXsqXTL2pRvujROjdZQ4RAlBUS5BTh9IGm+jTqQntYThciG/qu57Gs69yjnVUSqdxF9YLmSnpupBW9A== + supports-color@^7.1.0: version "7.2.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" @@ -2923,6 +3284,11 @@ synckit@^0.11.7: dependencies: "@pkgr/core" "^0.2.9" +text-encoding-utf-8@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/text-encoding-utf-8/-/text-encoding-utf-8-1.0.2.tgz#585b62197b0ae437e3c7b5d0af27ac1021e10d13" + integrity sha512-8bw4MY9WjdsD2aMtO0OzOCY3pXGYNx2d2FfHRVUKkiCPDWjKuOlhLVASS+pD7VkLTVjW268LYJHwsnPFlBpbAg== + text-table@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" @@ -2968,6 +3334,16 @@ to-regex-range@^5.0.1: dependencies: is-number "^7.0.0" +toml@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/toml/-/toml-3.0.0.tgz#342160f1af1904ec9d204d03a5d61222d762c5ee" + integrity sha512-y/mWCZinnvxjTKYhJ+pYxwD0mRLVvOtdS2Awbgxln6iEnt4rk0yBxeSBHkGJcPucRiG0e55mwWp+g/05rsrd6w== + +tr46@~0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" + integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== + ts-api-utils@^1.0.1: version "1.4.3" resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-1.4.3.tgz#bfc2215fe6528fecab2b0fba570a2e8a4263b064" @@ -2983,7 +3359,7 @@ tsconfig-paths@^3.15.0: minimist "^1.2.6" strip-bom "^3.0.0" -tslib@^2.8.0: +tslib@^2.0.3, tslib@^2.8.0: version "2.8.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f" integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w== @@ -3154,6 +3530,19 @@ vitest@^3.2.4: vite-node "3.2.4" why-is-node-running "^2.3.0" +webidl-conversions@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" + integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ== + +whatwg-url@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" + integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw== + dependencies: + tr46 "~0.0.3" + webidl-conversions "^3.0.0" + which-boxed-primitive@^1.1.0, which-boxed-primitive@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz#d76ec27df7fa165f18d5808374a5fe23c29b176e" @@ -3232,6 +3621,11 @@ wrappy@1: resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== +ws@^7.5.10: + version "7.5.10" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.10.tgz#58b5c20dc281633f6c19113f39b349bd8bd558d9" + integrity sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ== + ws@^8.5.0: version "8.18.3" resolved "https://registry.yarnpkg.com/ws/-/ws-8.18.3.tgz#b56b88abffde62791c639170400c93dcb0c95472" diff --git a/ts/web3js/.solitarc.js b/ts/web3js/.solitarc.js new file mode 100644 index 0000000..3839d8a --- /dev/null +++ b/ts/web3js/.solitarc.js @@ -0,0 +1,10 @@ +const path = require('path'); + +module.exports = { + idlUrl: 'https://raw.githubusercontent.com/magicblock-labs/delegation-program/main/idl/delegation.json', + programId: 'DELeGGvXpWV2fqJUhqcF5ZSYMS4JTLjteaAMARRSaeSh', + idlGenerator: 'anchor', + accountsDir: path.join(__dirname, 'src/generated/delegation-program-instructions'), + instructionsDir: path.join(__dirname, 'src/generated/delegation-program-instructions'), + typesDir: path.join(__dirname, 'src/generated/delegation-program-instructions'), +}; diff --git a/ts/web3js/package.json b/ts/web3js/package.json index 8fd6a30..5a996b3 100644 --- a/ts/web3js/package.json +++ b/ts/web3js/package.json @@ -21,12 +21,14 @@ "lint:fix": "eslint -c .eslintrc.yml --ext .ts,.tsx src --fix", "pretest": "tsc", "test": "vitest run --reporter verbose", + "generate": "solita", "prepare": "npm run build" }, "files": [ "lib" ], "devDependencies": { + "@metaplex-foundation/solita": "^0.20.1", "@typescript-eslint/eslint-plugin": "^6.21.0", "@typescript-eslint/parser": "^6.21.0", "eslint": "^8.55.0", diff --git a/ts/web3js/src/__test__/generated.test.ts b/ts/web3js/src/__test__/generated.test.ts new file mode 100644 index 0000000..5076249 --- /dev/null +++ b/ts/web3js/src/__test__/generated.test.ts @@ -0,0 +1,151 @@ +import { describe, it, expect } from "vitest"; +import { PublicKey, SystemProgram } from "@solana/web3.js"; +import { + createDelegateInstruction, + serializeDelegateInstructionData, + createTopUpEscrowInstruction, + serializeTopUpEscrowInstructionData, + createCloseEscrowInstruction, + serializeCloseEscrowInstructionData, +} from "../generated/delegation-program-instructions"; + +describe("Generated Instructions (web3.js)", () => { + const mockPublicKey = new PublicKey( + "11111111111111111111111111111111" + ); + + describe("delegate instruction", () => { + it("should create a delegate instruction", () => { + const instruction = createDelegateInstruction( + { + payer: mockPublicKey, + delegatedAccount: mockPublicKey, + ownerProgram: mockPublicKey, + delegateBuffer: mockPublicKey, + delegationRecord: mockPublicKey, + delegationMetadata: mockPublicKey, + systemProgram: SystemProgram.programId, + }, + { + commitFrequencyMs: 1000, + seeds: [new Uint8Array([1, 2, 3])], + validator: null, + } + ); + + expect(instruction.keys).toHaveLength(7); + expect(instruction.data).toBeDefined(); + expect(instruction.programId.equals(instruction.programId)).toBe(true); + }); + + it("should serialize delegate instruction data with correct discriminator", () => { + const data = serializeDelegateInstructionData({ + commitFrequencyMs: 1000, + seeds: [new Uint8Array([1, 2, 3])], + validator: null, + }); + + // Check discriminator + expect(data[0]).toBe(0); + expect(data[1]).toBe(0); + expect(data[2]).toBe(0); + expect(data[3]).toBe(0); + expect(data[4]).toBe(0); + expect(data[5]).toBe(0); + expect(data[6]).toBe(0); + expect(data[7]).toBe(0); + + // Check commit_frequency_ms (u32 at offset 8) + const frequency = data.readUInt32LE(8); + expect(frequency).toBe(1000); + }); + + it("should include validator in serialized data when provided", () => { + const validatorKey = mockPublicKey; + const data = serializeDelegateInstructionData({ + commitFrequencyMs: 500, + seeds: [], + validator: validatorKey, + }); + + expect(data.length).toBeGreaterThan(17); + }); + }); + + describe("topUpEscrow instruction", () => { + it("should create a topUpEscrow instruction", () => { + const instruction = createTopUpEscrowInstruction( + { + payer: mockPublicKey, + pubkey: mockPublicKey, + ephemeralBalanceAccount: mockPublicKey, + systemProgram: SystemProgram.programId, + }, + { + amount: BigInt(1000000), + index: 255, + } + ); + + expect(instruction.keys).toHaveLength(4); + expect(instruction.data.length).toBe(17); + }); + + it("should serialize topUpEscrow instruction data correctly", () => { + const data = serializeTopUpEscrowInstructionData({ + amount: BigInt(5000000), + index: 255, + }); + + expect(data.length).toBe(17); + + // Check discriminator + expect(data[0]).toBe(9); + for (let i = 1; i < 8; i++) { + expect(data[i]).toBe(0); + } + + // Check amount (u64 at offset 8) + const amount = data.readBigUInt64LE(8); + expect(amount).toBe(BigInt(5000000)); + + // Check index (u8 at offset 16) + expect(data[16]).toBe(255); + }); + }); + + describe("closeEscrow instruction", () => { + it("should create a closeEscrow instruction", () => { + const instruction = createCloseEscrowInstruction( + { + payer: mockPublicKey, + ephemeralBalanceAccount: mockPublicKey, + systemProgram: SystemProgram.programId, + }, + { + index: 255, + } + ); + + expect(instruction.keys).toHaveLength(3); + expect(instruction.data.length).toBe(9); + }); + + it("should serialize closeEscrow instruction data correctly", () => { + const data = serializeCloseEscrowInstructionData({ + index: 255, + }); + + expect(data.length).toBe(9); + + // Check discriminator + expect(data[0]).toBe(11); + for (let i = 1; i < 8; i++) { + expect(data[i]).toBe(0); + } + + // Check index (u8 at offset 8) + expect(data[8]).toBe(255); + }); + }); +}); diff --git a/ts/web3js/src/generated/README.md b/ts/web3js/src/generated/README.md new file mode 100644 index 0000000..a4ad463 --- /dev/null +++ b/ts/web3js/src/generated/README.md @@ -0,0 +1,49 @@ +# Generated Code from IDL (web3.js) + +This directory contains instruction types and serialization code generated from the delegation program IDL for web3.js. + +## Generated Instructions + +- `delegate.ts` - Delegate instruction (discriminator: [0,0,0,0,0,0,0,0]) +- `topUpEphemeralBalance.ts` - TopUpEphemeralBalance instruction (discriminator: [9,0,0,0,0,0,0,0]) +- `closeEphemeralBalance.ts` - CloseEphemeralBalance instruction (discriminator: [11,0,0,0,0,0,0,0]) + +## Usage + +All instructions follow a similar pattern: + +```typescript +import { createDelegateInstruction } from './generated'; +import { SystemProgram } from '@solana/web3.js'; + +const instruction = createDelegateInstruction( + { + payer: payerPublicKey, + delegatedAccount: delegatedAccountKey, + ownerProgram: ownerProgramKey, + delegateBuffer: delegateBufferKey, + delegationRecord: delegationRecordKey, + delegationMetadata: delegationMetadataKey, + systemProgram: SystemProgram.programId, + }, + { + commitFrequencyMs: 1000, + seeds: [new Uint8Array([1, 2, 3])], + validator: validatorPublicKey, + } +); +``` + +## Code Generation + +To regenerate code from the IDL, run from the `web3js/` folder: + +```bash +yarn generate +``` + +This uses Metaplex Solita with the configuration in `.solitarc.js`. + +## IDL Reference + +The IDL is fetched from: `https://raw.githubusercontent.com/magicblock-labs/delegation-program/main/idl/delegation.json` diff --git a/ts/web3js/src/generated/delegation-program-instructions/closeEphemeralBalance.ts b/ts/web3js/src/generated/delegation-program-instructions/closeEphemeralBalance.ts new file mode 100644 index 0000000..098fb72 --- /dev/null +++ b/ts/web3js/src/generated/delegation-program-instructions/closeEphemeralBalance.ts @@ -0,0 +1,55 @@ +import { PublicKey, TransactionInstruction, AccountMeta } from "@solana/web3.js"; +import { DELEGATION_PROGRAM_ID } from "../../constants"; + +/** + * CloseEscrow instruction arguments + */ +export type CloseEscrowInstructionArgs = { + index?: number; // defaults to 255 +}; + +/** + * Instruction: CloseEscrow + * Discriminator: [11,0,0,0,0,0,0,0] + */ +export function createCloseEscrowInstruction( + accounts: { + payer: PublicKey; + ephemeralBalanceAccount: PublicKey; + systemProgram: PublicKey; + }, + args?: CloseEscrowInstructionArgs, + programId = DELEGATION_PROGRAM_ID +): TransactionInstruction { + const keys: AccountMeta[] = [ + { pubkey: accounts.payer, isWritable: false, isSigner: true }, + { pubkey: accounts.ephemeralBalanceAccount, isWritable: true, isSigner: false }, + { pubkey: accounts.systemProgram, isWritable: false, isSigner: false }, + ]; + + const data = serializeCloseEscrowInstructionData(args ?? {}); + + return new TransactionInstruction({ + programId, + keys, + data, + }); +} + +export function serializeCloseEscrowInstructionData( + args?: CloseEscrowInstructionArgs +): Buffer { + const discriminator = [11, 0, 0, 0, 0, 0, 0, 0]; + const buffer = Buffer.alloc(9); + let offset = 0; + + // Write discriminator + for (let i = 0; i < 8; i++) { + buffer[offset++] = discriminator[i]; + } + + // Write index (u8) + buffer[offset] = args?.index ?? 255; + + return buffer; +} diff --git a/ts/web3js/src/generated/delegation-program-instructions/delegate.ts b/ts/web3js/src/generated/delegation-program-instructions/delegate.ts new file mode 100644 index 0000000..34104cb --- /dev/null +++ b/ts/web3js/src/generated/delegation-program-instructions/delegate.ts @@ -0,0 +1,92 @@ +import { PublicKey, TransactionInstruction, AccountMeta } from "@solana/web3.js"; +import { DELEGATION_PROGRAM_ID } from "../../constants"; + +/** + * Delegate instruction arguments + */ +export type DelegateInstructionArgs = { + commitFrequencyMs: number; + seeds: Uint8Array[]; + validator: PublicKey | null; +}; + +/** + * Instruction: Delegate + * Discriminator: [0,0,0,0,0,0,0,0] + */ +export function createDelegateInstruction( + accounts: { + payer: PublicKey; + delegatedAccount: PublicKey; + ownerProgram: PublicKey; + delegateBuffer: PublicKey; + delegationRecord: PublicKey; + delegationMetadata: PublicKey; + systemProgram: PublicKey; + }, + args: DelegateInstructionArgs, + programId = DELEGATION_PROGRAM_ID +): TransactionInstruction { + const keys: AccountMeta[] = [ + { pubkey: accounts.payer, isWritable: true, isSigner: true }, + { pubkey: accounts.delegatedAccount, isWritable: true, isSigner: true }, + { pubkey: accounts.ownerProgram, isWritable: false, isSigner: false }, + { pubkey: accounts.delegateBuffer, isWritable: true, isSigner: false }, + { pubkey: accounts.delegationRecord, isWritable: true, isSigner: false }, + { + pubkey: accounts.delegationMetadata, + isWritable: true, + isSigner: false, + }, + { pubkey: accounts.systemProgram, isWritable: false, isSigner: false }, + ]; + + const data = serializeDelegateInstructionData(args); + + return new TransactionInstruction({ + programId, + keys, + data, + }); +} + +export function serializeDelegateInstructionData( + args: DelegateInstructionArgs +): Buffer { + const discriminator = [0, 0, 0, 0, 0, 0, 0, 0]; + let offset = 0; + const buffer = Buffer.alloc(1024); + + // Write discriminator + for (let i = 0; i < 8; i++) { + buffer[offset++] = discriminator[i]; + } + + // Write commit_frequency_ms (u32) + buffer.writeUInt32LE(args.commitFrequencyMs, offset); + offset += 4; + + // Write seeds (vec>) + buffer.writeUInt32LE(args.seeds.length, offset); + offset += 4; + + for (const seed of args.seeds) { + buffer.writeUInt32LE(seed.length, offset); + offset += 4; + Buffer.from(seed).copy(buffer, offset); + offset += seed.length; + } + + // Write validator (option) + if (args.validator !== null) { + buffer[offset] = 1; // Some discriminant + offset += 1; + args.validator.toBuffer().copy(buffer, offset); + offset += 32; + } else { + buffer[offset] = 0; // None discriminant + offset += 1; + } + + return buffer.slice(0, offset); +} diff --git a/ts/web3js/src/generated/delegation-program-instructions/index.ts b/ts/web3js/src/generated/delegation-program-instructions/index.ts new file mode 100644 index 0000000..54a0d44 --- /dev/null +++ b/ts/web3js/src/generated/delegation-program-instructions/index.ts @@ -0,0 +1,3 @@ +export * from './delegate'; +export * from './topUpEphemeralBalance'; +export * from './closeEphemeralBalance'; diff --git a/ts/web3js/src/generated/delegation-program-instructions/topUpEphemeralBalance.ts b/ts/web3js/src/generated/delegation-program-instructions/topUpEphemeralBalance.ts new file mode 100644 index 0000000..d4bc3f8 --- /dev/null +++ b/ts/web3js/src/generated/delegation-program-instructions/topUpEphemeralBalance.ts @@ -0,0 +1,66 @@ +import { PublicKey, TransactionInstruction, AccountMeta } from "@solana/web3.js"; +import { DELEGATION_PROGRAM_ID } from "../../constants"; + +/** + * TopUpEscrow instruction arguments + */ +export type TopUpEscrowInstructionArgs = { + amount: bigint; + index?: number; // defaults to 255 +}; + +/** + * Instruction: TopUpEscrow + * Discriminator: [9,0,0,0,0,0,0,0] + */ +export function createTopUpEscrowInstruction( + accounts: { + payer: PublicKey; + pubkey: PublicKey; + ephemeralBalanceAccount: PublicKey; + systemProgram: PublicKey; + }, + args: TopUpEscrowInstructionArgs, + programId = DELEGATION_PROGRAM_ID +): TransactionInstruction { + const keys: AccountMeta[] = [ + { pubkey: accounts.payer, isWritable: true, isSigner: true }, + { pubkey: accounts.pubkey, isWritable: false, isSigner: false }, + { + pubkey: accounts.ephemeralBalanceAccount, + isWritable: true, + isSigner: false, + }, + { pubkey: accounts.systemProgram, isWritable: false, isSigner: false }, + ]; + + const data = serializeTopUpEscrowInstructionData(args); + + return new TransactionInstruction({ + programId, + keys, + data, + }); +} + +export function serializeTopUpEscrowInstructionData( + args: TopUpEscrowInstructionArgs +): Buffer { + const discriminator = [9, 0, 0, 0, 0, 0, 0, 0]; + const buffer = Buffer.alloc(17); + let offset = 0; + + // Write discriminator + for (let i = 0; i < 8; i++) { + buffer[offset++] = discriminator[i]; + } + + // Write amount (u64) + buffer.writeBigUInt64LE(args.amount, offset); + offset += 8; + + // Write index (u8) + buffer[offset] = args.index ?? 255; + + return buffer; +} diff --git a/ts/web3js/src/index.ts b/ts/web3js/src/index.ts index eee4ec5..dfc4a20 100644 --- a/ts/web3js/src/index.ts +++ b/ts/web3js/src/index.ts @@ -1,5 +1,5 @@ export * from "./constants.js"; -export * from "./instructions/delegate.js"; +export * from "./generated/delegation-program-instructions/index.js"; export * from "./pda.js"; export * from "./utils.js"; export * from "./resolver.js"; diff --git a/ts/web3js/src/instructions/delegate.ts b/ts/web3js/src/instructions/delegate.ts deleted file mode 100644 index b1d2cd4..0000000 --- a/ts/web3js/src/instructions/delegate.ts +++ /dev/null @@ -1,110 +0,0 @@ -import * as beet from "@metaplex-foundation/beet"; -import * as web3 from "@solana/web3.js"; -import { DELEGATION_PROGRAM_ID } from "../constants"; -import { - delegateBufferPdaFromDelegatedAccountAndOwnerProgram, - delegationMetadataPdaFromDelegatedAccount, - delegationRecordPdaFromDelegatedAccount, -} from "../pda"; - -export const delegateStruct = new beet.FixableBeetArgsStruct<{ - instructionDiscriminator: number[]; - commit_frequency_ms: beet.bignum; - seeds: number[][]; - validator?: beet.COption; -}>( - [ - ["instructionDiscriminator", beet.uniformFixedSizeArray(beet.u8, 8)], - ["commit_frequency_ms", beet.u32], - ["seeds", beet.array(beet.array(beet.u8))], - ["validator", beet.coption(beet.uniformFixedSizeArray(beet.u8, 32))], - ], - "DelegateInstructionArgs", -); -export const delegateInstructionDiscriminator = [0, 0, 0, 0, 0, 0, 0, 0]; - -// Define the DelegateAccountArgs structure -interface DelegateAccountArgs { - commit_frequency_ms: number; - seeds: Uint8Array[][]; -} -// Function to create a delegate instruction -export function createDelegateInstruction( - accounts: { - payer: web3.PublicKey; - delegatedAccount: web3.PublicKey; - ownerProgram: web3.PublicKey; - delegationRecord?: web3.PublicKey; - delegationMetadata?: web3.PublicKey; - systemProgram?: web3.PublicKey; - validator?: web3.PublicKey; - }, - args?: DelegateAccountArgs, - programId = DELEGATION_PROGRAM_ID, -) { - const delegateBufferPda = - delegateBufferPdaFromDelegatedAccountAndOwnerProgram( - accounts.delegatedAccount, - accounts.ownerProgram, - ); - - const delegationRecordPda = delegationRecordPdaFromDelegatedAccount( - accounts.delegatedAccount, - ); - const delegationMetadataPda = delegationMetadataPdaFromDelegatedAccount( - accounts.delegatedAccount, - ); - - args = args ?? { - commit_frequency_ms: 4294967295, // 2 ** 4 - 1, - seeds: [], - }; - - const keys: web3.AccountMeta[] = [ - { pubkey: accounts.payer, isWritable: false, isSigner: true }, - { pubkey: accounts.delegatedAccount, isWritable: true, isSigner: true }, - { pubkey: accounts.ownerProgram, isWritable: false, isSigner: false }, - { - pubkey: delegateBufferPda, - isWritable: true, - isSigner: false, - }, - { - pubkey: accounts.delegationRecord ?? delegationRecordPda, - isWritable: true, - isSigner: false, - }, - { - pubkey: accounts.delegationMetadata ?? delegationMetadataPda, - isWritable: true, - isSigner: false, - }, - { - pubkey: accounts.systemProgram ?? web3.SystemProgram.programId, - isWritable: false, - isSigner: false, - }, - // Only add validator if it exists - ...(accounts.validator - ? [ - { - pubkey: accounts.validator, - isWritable: false, - isSigner: false, - }, - ] - : []), - ]; - - const [data] = delegateStruct.serialize({ - instructionDiscriminator: delegateInstructionDiscriminator, - commit_frequency_ms: args.commit_frequency_ms, - seeds: args.seeds.map((seed) => seed.map(Number)), - }); - - return new web3.TransactionInstruction({ - programId, - keys, - data, - }); -} diff --git a/ts/web3js/src/pda.ts b/ts/web3js/src/pda.ts index 06efb72..e836d90 100644 --- a/ts/web3js/src/pda.ts +++ b/ts/web3js/src/pda.ts @@ -29,3 +29,16 @@ export function delegateBufferPdaFromDelegatedAccountAndOwnerProgram( ownerProgramId, )[0]; } + +export function escrowPdaFromEscrowAuthority( + escrowAuthority: PublicKey, + index: number = 255, +) { + if (index < 0 || index > 255) { + throw new Error("Index must be between 0 and 255"); + } + return PublicKey.findProgramAddressSync( + [Buffer.from("balance"), escrowAuthority.toBytes(), Buffer.from([index])], + DELEGATION_PROGRAM_ID, + )[0]; +} \ No newline at end of file