From 7a01f3c650be9d9e056452a1ab5b4118c020018e Mon Sep 17 00:00:00 2001 From: Ilia <56516965+bezrazli4n0@users.noreply.github.com> Date: Fri, 30 Jul 2021 18:33:22 +0300 Subject: [PATCH] feature: success tests for token-metadata (#173) * feature: update borsh version, wip testing module * Fixed signatures for create metadata in tests * feature: success test for create_metadata_account * feature: success test for update_metadata_account, added is_mutable param to create method * feature: success test for update_primary_sale_happened_via_token, added token account creation in test metadata structure * feature: success test for create_master_edition * feature: success test for mint_new_edition_from_master_edition_via_token * feature: added more success tests checks, wip: added necessary accounts * feature: added more internal mocks, added mint_new_edition_from_master_edition_via_vault_proxy Co-authored-by: Yuriy Savchenko --- rust/Cargo.lock | 365 +++++++++++------- rust/auction/program/Cargo.toml | 2 +- rust/metaplex/program/Cargo.toml | 2 +- rust/token-metadata/program/Cargo.toml | 6 +- .../program/tests/create_master_edition.rs | 44 +++ .../program/tests/create_metadata_account.rs | 39 ++ ...w_edition_from_master_edition_via_token.rs | 38 ++ ...ion_from_master_edition_via_vault_proxy.rs | 75 ++++ .../program/tests/update_metadata_account.rs | 51 +++ .../update_primary_sale_happened_via_token.rs | 44 +++ .../program/tests/utils/edition_marker.rs | 187 +++++++++ .../program/tests/utils/external_price.rs | 82 ++++ .../program/tests/utils/master_edition_v2.rs | 76 ++++ .../program/tests/utils/metadata.rs | 146 +++++++ .../token-metadata/program/tests/utils/mod.rs | 128 ++++++ .../program/tests/utils/vault.rs | 223 +++++++++++ rust/token-vault/program/Cargo.toml | 2 +- 17 files changed, 1359 insertions(+), 151 deletions(-) create mode 100644 rust/token-metadata/program/tests/create_master_edition.rs create mode 100644 rust/token-metadata/program/tests/create_metadata_account.rs create mode 100644 rust/token-metadata/program/tests/mint_new_edition_from_master_edition_via_token.rs create mode 100644 rust/token-metadata/program/tests/mint_new_edition_from_master_edition_via_vault_proxy.rs create mode 100644 rust/token-metadata/program/tests/update_metadata_account.rs create mode 100644 rust/token-metadata/program/tests/update_primary_sale_happened_via_token.rs create mode 100644 rust/token-metadata/program/tests/utils/edition_marker.rs create mode 100644 rust/token-metadata/program/tests/utils/external_price.rs create mode 100644 rust/token-metadata/program/tests/utils/master_edition_v2.rs create mode 100644 rust/token-metadata/program/tests/utils/metadata.rs create mode 100644 rust/token-metadata/program/tests/utils/mod.rs create mode 100644 rust/token-metadata/program/tests/utils/vault.rs diff --git a/rust/Cargo.lock b/rust/Cargo.lock index 99b65ef..43e2963 100644 --- a/rust/Cargo.lock +++ b/rust/Cargo.lock @@ -1,5 +1,7 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +version = 3 + [[package]] name = "Inflector" version = "0.11.4" @@ -40,6 +42,12 @@ dependencies = [ "memchr", ] +[[package]] +name = "aliasable" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "250f629c0161ad8107cf89319e990051fae62832fd343083bea452d93e2205fd" + [[package]] name = "ansi_term" version = "0.11.0" @@ -219,7 +227,17 @@ version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09a7111f797cc721407885a323fb071636aee57f750b1a4ddc27397eba168a74" dependencies = [ - "borsh-derive", + "borsh-derive 0.8.2", + "hashbrown", +] + +[[package]] +name = "borsh" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18dda7dc709193c0d86a1a51050a926dc3df1cf262ec46a23a25dba421ea1924" +dependencies = [ + "borsh-derive 0.9.1", "hashbrown", ] @@ -229,8 +247,21 @@ version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "307f3740906bac2c118a8122fe22681232b244f1369273e45f1156b45c43d2dd" dependencies = [ - "borsh-derive-internal", - "borsh-schema-derive-internal", + "borsh-derive-internal 0.8.2", + "borsh-schema-derive-internal 0.8.2", + "proc-macro-crate", + "proc-macro2 1.0.27", + "syn 1.0.72", +] + +[[package]] +name = "borsh-derive" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "684155372435f578c0fa1acd13ebbb182cc19d6b38b64ae7901da4393217d264" +dependencies = [ + "borsh-derive-internal 0.9.1", + "borsh-schema-derive-internal 0.9.1", "proc-macro-crate", "proc-macro2 1.0.27", "syn 1.0.72", @@ -247,6 +278,17 @@ dependencies = [ "syn 1.0.72", ] +[[package]] +name = "borsh-derive-internal" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2102f62f8b6d3edeab871830782285b64cc1830168094db05c8e458f209bc5c3" +dependencies = [ + "proc-macro2 1.0.27", + "quote 1.0.9", + "syn 1.0.72", +] + [[package]] name = "borsh-schema-derive-internal" version = "0.8.2" @@ -258,6 +300,17 @@ dependencies = [ "syn 1.0.72", ] +[[package]] +name = "borsh-schema-derive-internal" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "196c978c4c9b0b142d446ef3240690bf5a8a33497074a113ff9a337ccb750483" +dependencies = [ + "proc-macro2 1.0.27", + "quote 1.0.9", + "syn 1.0.72", +] + [[package]] name = "bs58" version = "0.3.1" @@ -597,16 +650,6 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" -[[package]] -name = "crypto-mac" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4434400df11d95d556bac068ddfedd482915eb18fe8bea89bc80b6e4b1c179e5" -dependencies = [ - "generic-array 0.12.4", - "subtle 1.0.0", -] - [[package]] name = "crypto-mac" version = "0.8.0" @@ -614,7 +657,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b584a330336237c1eecd3e94266efb216c56ed91225d634cb2991c5f3fd1aeab" dependencies = [ "generic-array 0.14.4", - "subtle 2.4.0", + "subtle", ] [[package]] @@ -624,7 +667,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "58bcd97a54c7ca5ce2f6eb16f6bede5b0ab5f0055fedc17d2f0b4466e21671ca" dependencies = [ "generic-array 0.14.4", - "subtle 2.4.0", + "subtle", ] [[package]] @@ -634,7 +677,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4857fd85a0c34b3c3297875b747c1e02e06b6a0ea32dd892d8192b9ce0813ea6" dependencies = [ "generic-array 0.14.4", - "subtle 2.4.0", + "subtle", ] [[package]] @@ -646,7 +689,7 @@ dependencies = [ "byteorder", "digest 0.8.1", "rand_core 0.5.1", - "subtle 2.4.0", + "subtle", "zeroize", ] @@ -659,7 +702,7 @@ dependencies = [ "byteorder", "digest 0.9.0", "rand_core 0.5.1", - "subtle 2.4.0", + "subtle", "zeroize", ] @@ -780,7 +823,7 @@ dependencies = [ "rand 0.7.3", "serde", "serde_bytes", - "sha2 0.9.5", + "sha2", "zeroize", ] @@ -794,7 +837,7 @@ dependencies = [ "ed25519-dalek", "failure", "hmac 0.9.0", - "sha2 0.9.5", + "sha2", ] [[package]] @@ -1199,16 +1242,6 @@ dependencies = [ "pkg-config", ] -[[package]] -name = "hmac" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dcb5e64cda4c23119ab41ba960d1e170a774c8e4b9d9e6a9bc18aabf5e59695" -dependencies = [ - "crypto-mac 0.7.0", - "digest 0.8.1", -] - [[package]] name = "hmac" version = "0.8.1" @@ -1241,13 +1274,13 @@ dependencies = [ [[package]] name = "hmac-drbg" -version = "0.2.0" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6e570451493f10f6581b48cdd530413b63ea9e780f544bfd3bdcaa0d89d1a7b" +checksum = "17ea0a1394df5b6574da6e0c1ade9e78868c9fb0a4e5ef4428e32da4676b85b1" dependencies = [ - "digest 0.8.1", - "generic-array 0.12.4", - "hmac 0.7.1", + "digest 0.9.0", + "generic-array 0.14.4", + "hmac 0.8.1", ] [[package]] @@ -1486,20 +1519,52 @@ dependencies = [ [[package]] name = "libsecp256k1" -version = "0.3.5" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fc1e2c808481a63dc6da2074752fdd4336a3c8fcc68b83db6f1fd5224ae7962" +checksum = "bd1137239ab33b41aa9637a88a28249e5e70c40a42ccc92db7f12cc356c1fcd7" dependencies = [ "arrayref", - "crunchy", - "digest 0.8.1", + "base64 0.12.3", + "digest 0.9.0", "hmac-drbg", + "libsecp256k1-core", + "libsecp256k1-gen-ecmult", + "libsecp256k1-gen-genmult", "rand 0.7.3", - "sha2 0.8.2", - "subtle 2.4.0", + "serde", + "sha2", "typenum", ] +[[package]] +name = "libsecp256k1-core" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0f6ab710cec28cef759c5f18671a27dae2a5f952cdaaee1d8e2908cb2478a80" +dependencies = [ + "crunchy", + "digest 0.9.0", + "subtle", +] + +[[package]] +name = "libsecp256k1-gen-ecmult" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccab96b584d38fac86a83f07e659f0deafd0253dc096dab5a36d53efe653c5c3" +dependencies = [ + "libsecp256k1-core", +] + +[[package]] +name = "libsecp256k1-gen-genmult" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67abfe149395e3aa1c48a2beb32b068e2334402df8181f818d3aee2b304c4f5d" +dependencies = [ + "libsecp256k1-core", +] + [[package]] name = "linked-hash-map" version = "0.5.4" @@ -1849,21 +1914,23 @@ dependencies = [ [[package]] name = "ouroboros" -version = "0.5.1" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc04551635026d3ac7bc646698ea1836a85ed2a26b7094fe1d15d8b14854c4a2" +checksum = "84236d64f1718c387232287cf036eb6632a5ecff226f4ff9dccb8c2b79ba0bde" dependencies = [ + "aliasable", "ouroboros_macro", "stable_deref_trait", ] [[package]] name = "ouroboros_macro" -version = "0.5.1" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cec33dfceabec83cd0e95a5ce9d20e76ab3a5cbfef59659b8c927f69b93ed8ae" +checksum = "f463857a6eb96c0136b1d56e56c718350cef30412ec065b48294799a088bca68" dependencies = [ "Inflector", + "proc-macro-error", "proc-macro2 1.0.27", "quote 1.0.9", "syn 1.0.72", @@ -2036,6 +2103,30 @@ dependencies = [ "toml", ] +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2 1.0.27", + "quote 1.0.9", + "syn 1.0.72", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2 1.0.27", + "quote 1.0.9", + "version_check", +] + [[package]] name = "proc-macro-hack" version = "0.5.19" @@ -2554,18 +2645,6 @@ dependencies = [ "opaque-debug 0.2.3", ] -[[package]] -name = "sha2" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a256f46ea78a0c0d9ff00077504903ac881a1dafdc20da66545699e7776b3e69" -dependencies = [ - "block-buffer 0.7.3", - "digest 0.8.1", - "fake-simd", - "opaque-debug 0.2.3", -] - [[package]] name = "sha2" version = "0.9.5" @@ -2650,9 +2729,9 @@ dependencies = [ [[package]] name = "solana-account-decoder" -version = "1.7.3" +version = "1.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e49c9e97fbaa91220924064f23ce367c02af1a3bc8cc514f84168b47cbb075c7" +checksum = "a67e4a537eccc21f8b942f60990d57f76980638db834161747e47cfba4b8f050" dependencies = [ "Inflector", "base64 0.12.3", @@ -2673,13 +2752,13 @@ dependencies = [ [[package]] name = "solana-banks-client" -version = "1.7.3" +version = "1.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "570ed9c8e78fabbd2f93140f731c9361b7aa6292341e03811e5b6d3ed2470c5a" +checksum = "a51c83e33eb5fc2a688db5e7e19a8c5b481385e1d9f30b012962e9bcdb002629" dependencies = [ "bincode", - "borsh", - "borsh-derive", + "borsh 0.9.1", + "borsh-derive 0.9.1", "futures 0.3.15", "mio 0.7.11", "solana-banks-interface", @@ -2692,9 +2771,9 @@ dependencies = [ [[package]] name = "solana-banks-interface" -version = "1.7.3" +version = "1.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3b253e4d53eef373ab186829988a9ad4f7bfce886cf0e1fade1ad866c294df2" +checksum = "f73a34a243df509dfde8fe42129aa34a3db9913e90b7c7eb290f597361016268" dependencies = [ "mio 0.7.11", "serde", @@ -2704,9 +2783,9 @@ dependencies = [ [[package]] name = "solana-banks-server" -version = "1.7.3" +version = "1.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a350a47e84f4e28a28e985e96150a222559b0e23f71a3b34760b7463091d0877" +checksum = "3929ed2f73a4a9c80ddff4b1b49ecc81fa6e8689ca475e9e625034aaebc22516" dependencies = [ "bincode", "futures 0.3.15", @@ -2724,12 +2803,13 @@ dependencies = [ [[package]] name = "solana-bpf-loader-program" -version = "1.7.3" +version = "1.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7305c923737fc515d88454dd991b8c21c5e9270f72db3cd52da888d4d233fe07" +checksum = "d848ee15b984d2703750a52e3cbe23024256184b11426a1677bc98934087f8c7" dependencies = [ "bincode", "byteorder", + "libsecp256k1", "log", "num-derive", "num-traits", @@ -2744,9 +2824,9 @@ dependencies = [ [[package]] name = "solana-clap-utils" -version = "1.7.3" +version = "1.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29dca103fa63d4fa564c719d2f043feb4a116722362cbcbf027d4404fc65e7b3" +checksum = "97d2792f093f28b0a7403443225494c0d75215253784897a6f8b8e6fb83ce91a" dependencies = [ "chrono", "clap", @@ -2761,9 +2841,9 @@ dependencies = [ [[package]] name = "solana-cli-config" -version = "1.7.3" +version = "1.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f22f4acf359df9e859878fc456bb98cfd3d008ee239a6300259c439a2356d1c9" +checksum = "d1c3982b00bf2ac283c86e760aae127d395ab8b610cc3690a0a6ff500ae561e7" dependencies = [ "dirs-next", "lazy_static", @@ -2775,9 +2855,9 @@ dependencies = [ [[package]] name = "solana-client" -version = "1.7.3" +version = "1.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15a149653548051cdcfdfb3494ad46a9810e647cbf004b0f65dccafd92eec152" +checksum = "023263a79a3356532549c9e0555c6e1b2a2e94205b5d58c7041703bbd455133d" dependencies = [ "base64 0.13.0", "bincode", @@ -2809,9 +2889,9 @@ dependencies = [ [[package]] name = "solana-config-program" -version = "1.7.3" +version = "1.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "056a9300b5e2665d0f6cf1dfbc5f9778ec616485adbe35af01fec234e1f9b288" +checksum = "9b5348055cf52ab01efc1578d4159ec40bb39c3913df4365787c3e1382c101c1" dependencies = [ "bincode", "chrono", @@ -2824,9 +2904,9 @@ dependencies = [ [[package]] name = "solana-crate-features" -version = "1.7.3" +version = "1.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "887ff45393b195ab7d93cdc94511c7cc2319a379b659e8008de77028c2326846" +checksum = "5c9b446eea7a5af7d4631ce3fd0625439fdc68eda4557223233f1c6bba3e847a" dependencies = [ "backtrace", "bytes 0.4.12", @@ -2849,9 +2929,9 @@ dependencies = [ [[package]] name = "solana-faucet" -version = "1.7.3" +version = "1.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "981359d3f0f420dfa6d5eee4d33357d619817425a64ad090f2f88e521c9a24bd" +checksum = "d58750a03b49940f486c0dcb5744bb6ee5da82ced6636000a90af7618a67dd1b" dependencies = [ "bincode", "byteorder", @@ -2872,9 +2952,9 @@ dependencies = [ [[package]] name = "solana-frozen-abi" -version = "1.7.3" +version = "1.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc00a9f7c3eb2fb8687d34ce6d8672fbf7bd8f67002a5f75ccd6f6c4e8cd8a91" +checksum = "45c6760c1dd139c202ef6df28bff467c904aa35b1aa1a59be268c47aec8bc6c0" dependencies = [ "bs58", "bv", @@ -2884,7 +2964,7 @@ dependencies = [ "rustc_version", "serde", "serde_derive", - "sha2 0.9.5", + "sha2", "solana-frozen-abi-macro", "solana-logger", "thiserror", @@ -2892,9 +2972,9 @@ dependencies = [ [[package]] name = "solana-frozen-abi-macro" -version = "1.7.3" +version = "1.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc381a29ab68515e69dcfad633ab78dd98d83c0b959c2cae9a9a98df6e265acf" +checksum = "a4dbe296c16dec41e8e6f4e6c2694c6224820d34c0ab11a2d3ff9683f44878ef" dependencies = [ "proc-macro2 1.0.27", "quote 1.0.9", @@ -2904,9 +2984,9 @@ dependencies = [ [[package]] name = "solana-logger" -version = "1.7.3" +version = "1.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62f8e4921602f61681d8d29d2606d4f8e1c848d4f6b9964813bfc1b457dfd7ce" +checksum = "80af1959b520c0fc99bc6583ba9d82bfa15b1ac007516795bceeb4a951af77c7" dependencies = [ "env_logger", "lazy_static", @@ -2915,9 +2995,9 @@ dependencies = [ [[package]] name = "solana-measure" -version = "1.7.3" +version = "1.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "958b8dab77246d9c71c78a4e9c5c31a1092dafb70294ce0334acf572442b9d84" +checksum = "db2915d20f35948b35deffa8624cb189385f13758bd171d8d4a966ae8bf360a4" dependencies = [ "log", "solana-metrics", @@ -2926,9 +3006,9 @@ dependencies = [ [[package]] name = "solana-metrics" -version = "1.7.3" +version = "1.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77968c10909ef49d7a3cccc3ca8de9415e8750411ad917889ef8ba9ae8692d94" +checksum = "8d87867f1f9e399274e08902eb72c9158bef5399e2566161dbe831abeaaa7d14" dependencies = [ "env_logger", "gethostname", @@ -2940,9 +3020,9 @@ dependencies = [ [[package]] name = "solana-net-utils" -version = "1.7.3" +version = "1.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9de765ffc78c8068b9efce0ff08b399a94105b004588c90a4b0835995dfc4712" +checksum = "cc7dd877b66b4436b9fcb6d2c2e6055a1dd18b0dcf5938ea1f20efa0b7f09159" dependencies = [ "bincode", "clap", @@ -2962,20 +3042,21 @@ dependencies = [ [[package]] name = "solana-program" -version = "1.7.3" +version = "1.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f9c454274436aac77286369e35835fafa1f79d1da1c4b7a1c662b2c41705f77" +checksum = "fe5e5dd99d642b5e89eeb20457310c3c23f20dbf44e67c64e473a02fbc50d646" dependencies = [ "bincode", "blake3", - "borsh", - "borsh-derive", + "borsh 0.9.1", + "borsh-derive 0.9.1", "bs58", "bv", "curve25519-dalek 2.1.2", "hex", "itertools", "lazy_static", + "libsecp256k1", "log", "num-derive", "num-traits", @@ -2985,7 +3066,7 @@ dependencies = [ "serde", "serde_bytes", "serde_derive", - "sha2 0.9.5", + "sha2", "sha3", "solana-frozen-abi", "solana-frozen-abi-macro", @@ -2996,9 +3077,9 @@ dependencies = [ [[package]] name = "solana-program-test" -version = "1.7.3" +version = "1.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4cd5922e4a9a7437a19ff5d79f60bac64ea2636a365586cb3511f4d562a20cf7" +checksum = "20a2961354afb2ef3ed35ec477961f1f6f0113291c83b993a30382180c496d96" dependencies = [ "async-trait", "base64 0.12.3", @@ -3022,9 +3103,9 @@ dependencies = [ [[package]] name = "solana-rayon-threadlimit" -version = "1.7.3" +version = "1.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d837161f598afd30c445a7f9c39d640cd4cdf362c30062ed0831b71daaf63a45" +checksum = "30c3a0037afa0b03e0aad9f8fb451d1008d5538023919835cf86c9833bc93103" dependencies = [ "lazy_static", "num_cpus", @@ -3032,9 +3113,9 @@ dependencies = [ [[package]] name = "solana-remote-wallet" -version = "1.7.3" +version = "1.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24087b3048534e154db68c4cdd8233f3a35dd6f860d97e5ad1008c44e0d311f5" +checksum = "083d31e6510a746ecc4ce8d151a232324056c7a124a218948060947b668d6db8" dependencies = [ "base32", "console 0.14.1", @@ -3053,9 +3134,9 @@ dependencies = [ [[package]] name = "solana-runtime" -version = "1.7.3" +version = "1.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "224e6ef5ea772d9636493dd4fd196cf3b167ff73b7d54e7f591b2f2d452c70d6" +checksum = "f047727075c3434f17d33467bd26033fea3b4e71e7c23caa261015507b162581" dependencies = [ "arrayref", "bincode", @@ -3104,9 +3185,9 @@ dependencies = [ [[package]] name = "solana-sdk" -version = "1.7.3" +version = "1.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "339cc1a9d437ae2f5f05d2d678c8f6d19ea6cf57cbdf719b7726156d294487bd" +checksum = "0048d346fdf3629dca2bccc2ed63320da9d0291c32b816911ed63d34c65286a5" dependencies = [ "assert_matches", "bincode", @@ -3139,7 +3220,7 @@ dependencies = [ "serde_bytes", "serde_derive", "serde_json", - "sha2 0.9.5", + "sha2", "sha3", "solana-crate-features", "solana-frozen-abi", @@ -3153,9 +3234,9 @@ dependencies = [ [[package]] name = "solana-sdk-macro" -version = "1.7.3" +version = "1.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85ee9c0af66098ec40bf9012b7910c8cdb1ce8b95fc9fad90e6a0cbe692a48fe" +checksum = "fee909dcddb5b4d349b3e5e1ae92f6660cd2f783dea392ae2e73210776aadc9b" dependencies = [ "bs58", "proc-macro2 1.0.27", @@ -3166,24 +3247,18 @@ dependencies = [ [[package]] name = "solana-secp256k1-program" -version = "1.7.3" +version = "1.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2666ffed520bff7d0eb6747da156435def7f97341634e72af39fefc0d27496f1" +checksum = "bbd4c29c6b269800898610da38de45d28fd56b24cb4030c588ffd6acc11a7443" dependencies = [ - "bincode", - "digest 0.9.0", - "libsecp256k1", - "rand 0.7.3", - "sha3", - "solana-logger", "solana-sdk", ] [[package]] name = "solana-stake-program" -version = "1.7.3" +version = "1.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42f9e0309f95b3160c4961f11a3940d98126a86a7410b04bf88ff79448984257" +checksum = "3c01fa18bedd1773c9abf86fc58b87ed6e1117ce9f42c9a703becc1d351d810d" dependencies = [ "bincode", "log", @@ -3203,9 +3278,9 @@ dependencies = [ [[package]] name = "solana-transaction-status" -version = "1.7.3" +version = "1.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "952083e52e835be5c0f10707d9019df84f3be5f0c524391848d4c8c7e05151da" +checksum = "b6ea7cfdeff6ff1fba74096f3bb94688f0fdb780524e08676323108352532dfa" dependencies = [ "Inflector", "base64 0.12.3", @@ -3227,9 +3302,9 @@ dependencies = [ [[package]] name = "solana-version" -version = "1.7.3" +version = "1.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "797f12524e5ea25d18f345cd4c34a4839dea83e979a9ccb43a02b486ba9d913c" +checksum = "978569fec8c913d798f5e3dad2c8b6d03a6a30e8e04da633ac356ddde832f933" dependencies = [ "log", "rustc_version", @@ -3243,9 +3318,9 @@ dependencies = [ [[package]] name = "solana-vote-program" -version = "1.7.3" +version = "1.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8583f429404acb3ab8eb255cd9cb1c65496dda7a8be3d73058d63b7d26cc1c3d" +checksum = "506df67749a343d9f9a48b7b5566faf2bc43d0611b520467664a58cd78d4b1be" dependencies = [ "bincode", "log", @@ -3289,9 +3364,9 @@ checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" [[package]] name = "spl-associated-token-account" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4adc47eebe5d2b662cbaaba1843719c28a67e5ec5d0460bc3ca60900a51f74e2" +checksum = "393e2240d521c3dd770806bff25c2c00d761ac962be106e14e22dd912007f428" dependencies = [ "solana-program", "spl-token", @@ -3302,7 +3377,7 @@ name = "spl-auction" version = "0.0.1" dependencies = [ "arrayref", - "borsh", + "borsh 0.9.1", "num-derive", "num-traits", "solana-program", @@ -3317,7 +3392,7 @@ name = "spl-auction-test-client" version = "0.1.0" dependencies = [ "bincode", - "borsh", + "borsh 0.8.2", "clap", "rand 0.8.3", "solana-clap-utils", @@ -3343,7 +3418,7 @@ name = "spl-metaplex" version = "0.0.1" dependencies = [ "arrayref", - "borsh", + "borsh 0.9.1", "num-derive", "num-traits", "solana-program", @@ -3360,7 +3435,7 @@ version = "0.1.0" dependencies = [ "arrayref", "bincode", - "borsh", + "borsh 0.8.2", "clap", "serde", "serde_derive", @@ -3379,9 +3454,9 @@ dependencies = [ [[package]] name = "spl-token" -version = "3.1.1" +version = "3.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbfa8fd791aeb4d7ad5fedb7872478de9f4e8b4fcb02dfd9e7f2f9ae3f3ddd73" +checksum = "93bfdd5bd7c869cb565c7d7635c4fafe189b988a0bdef81063cd9585c6b8dc01" dependencies = [ "arrayref", "num-derive", @@ -3396,10 +3471,12 @@ name = "spl-token-metadata" version = "0.0.1" dependencies = [ "arrayref", - "borsh", + "borsh 0.9.1", "num-derive", "num-traits", "solana-program", + "solana-program-test", + "solana-sdk", "spl-token", "spl-token-vault", "thiserror", @@ -3410,7 +3487,7 @@ name = "spl-token-metadata-test-client" version = "0.1.0" dependencies = [ "bincode", - "borsh", + "borsh 0.8.2", "clap", "solana-clap-utils", "solana-cli-config", @@ -3425,7 +3502,7 @@ dependencies = [ name = "spl-token-vault" version = "0.0.1" dependencies = [ - "borsh", + "borsh 0.9.1", "num-derive", "num-traits", "solana-program", @@ -3438,7 +3515,7 @@ name = "spl-token-vault-test-client" version = "0.1.0" dependencies = [ "bincode", - "borsh", + "borsh 0.8.2", "clap", "solana-clap-utils", "solana-cli-config", @@ -3467,12 +3544,6 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" -[[package]] -name = "subtle" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d67a5a62ba6e01cb2192ff309324cb4875d0c451d55fe2319433abe7a05a8ee" - [[package]] name = "subtle" version = "2.4.0" @@ -3656,7 +3727,7 @@ dependencies = [ "pbkdf2 0.4.0", "rand 0.7.3", "rustc-hash", - "sha2 0.9.5", + "sha2", "thiserror", "unicode-normalization", "zeroize", diff --git a/rust/auction/program/Cargo.toml b/rust/auction/program/Cargo.toml index f37238f..0abe9a7 100644 --- a/rust/auction/program/Cargo.toml +++ b/rust/auction/program/Cargo.toml @@ -13,7 +13,7 @@ no-entrypoint = [] test-bpf = [] [dependencies] -borsh = "0.8.2" +borsh = "0.9.1" num-derive = "0.3" num-traits = "0.2" arrayref = "0.3.6" diff --git a/rust/metaplex/program/Cargo.toml b/rust/metaplex/program/Cargo.toml index c6aef3e..df0d623 100644 --- a/rust/metaplex/program/Cargo.toml +++ b/rust/metaplex/program/Cargo.toml @@ -22,7 +22,7 @@ spl-token = { version="3.1.1", features = [ "no-entrypoint" ] } spl-token-vault = { path = "../../token-vault/program", features = [ "no-entrypoint" ] } spl-token-metadata = { path = "../../token-metadata/program", features = [ "no-entrypoint" ] } thiserror = "1.0" -borsh = "0.8.2" +borsh = "0.9.1" [lib] crate-type = ["cdylib", "lib"] diff --git a/rust/token-metadata/program/Cargo.toml b/rust/token-metadata/program/Cargo.toml index 384fc19..bc8200d 100644 --- a/rust/token-metadata/program/Cargo.toml +++ b/rust/token-metadata/program/Cargo.toml @@ -20,7 +20,11 @@ solana-program = "1.6.10" spl-token-vault = { path = "../../token-vault/program", features = [ "no-entrypoint" ] } spl-token = { version="3.1.1", features = [ "no-entrypoint" ] } thiserror = "1.0" -borsh = "0.8.2" +borsh = "0.9.1" + +[dev-dependencies] +solana-sdk = "1.7.8" +solana-program-test = "1.7.8" [lib] crate-type = ["cdylib", "lib"] diff --git a/rust/token-metadata/program/tests/create_master_edition.rs b/rust/token-metadata/program/tests/create_master_edition.rs new file mode 100644 index 0000000..631851f --- /dev/null +++ b/rust/token-metadata/program/tests/create_master_edition.rs @@ -0,0 +1,44 @@ +mod utils; + +use solana_program_test::*; +use spl_token_metadata::state::Key; +use utils::*; + +#[tokio::test] +async fn success() { + let mut context = program_test().start_with_context().await; + let test_metadata = Metadata::new(); + let test_master_edition = MasterEditionV2::new(&test_metadata); + + test_metadata + .create( + &mut context, + "Test".to_string(), + "TST".to_string(), + "uri".to_string(), + None, + 10, + false, + ) + .await + .unwrap(); + + let mint = get_mint(&mut context, &test_master_edition.mint_pubkey).await; + let old_authority = mint.mint_authority.unwrap(); + + test_master_edition + .create(&mut context, Some(10)) + .await + .unwrap(); + + let master_edition = test_master_edition.get_data(&mut context).await; + + let mint = get_mint(&mut context, &test_master_edition.mint_pubkey).await; + let new_authority = mint.mint_authority.unwrap(); + + assert_eq!(new_authority, new_authority); + assert_ne!(old_authority, new_authority); + assert_eq!(master_edition.supply, 0); + assert_eq!(master_edition.max_supply.unwrap(), 10); + assert_eq!(master_edition.key, Key::MasterEditionV2); +} diff --git a/rust/token-metadata/program/tests/create_metadata_account.rs b/rust/token-metadata/program/tests/create_metadata_account.rs new file mode 100644 index 0000000..5d7b904 --- /dev/null +++ b/rust/token-metadata/program/tests/create_metadata_account.rs @@ -0,0 +1,39 @@ +mod utils; + +use solana_program_test::*; +use solana_sdk::signature::Signer; +use spl_token_metadata::state::Key; +use utils::*; + +#[tokio::test] +async fn success() { + let mut context = program_test().start_with_context().await; + let test_metadata = Metadata::new(); + + test_metadata + .create( + &mut context, + "Test".to_string(), + "TST".to_string(), + "uri".to_string(), + None, + 10, + false, + ) + .await + .unwrap(); + + let metadata = test_metadata.get_data(&mut context).await; + + assert_eq!(metadata.data.name, "Test"); + assert_eq!(metadata.data.symbol, "TST"); + assert_eq!(metadata.data.uri, "uri"); + assert_eq!(metadata.data.seller_fee_basis_points, 10); + assert_eq!(metadata.data.creators, None); + + assert_eq!(metadata.primary_sale_happened, false); + assert_eq!(metadata.is_mutable, false); + assert_eq!(metadata.mint, test_metadata.mint.pubkey()); + assert_eq!(metadata.update_authority, context.payer.pubkey()); + assert_eq!(metadata.key, Key::MetadataV1); +} diff --git a/rust/token-metadata/program/tests/mint_new_edition_from_master_edition_via_token.rs b/rust/token-metadata/program/tests/mint_new_edition_from_master_edition_via_token.rs new file mode 100644 index 0000000..bd93085 --- /dev/null +++ b/rust/token-metadata/program/tests/mint_new_edition_from_master_edition_via_token.rs @@ -0,0 +1,38 @@ +mod utils; + +use solana_program_test::*; +use spl_token_metadata::state::Key; +use utils::*; + +#[tokio::test] +async fn success() { + let mut context = program_test().start_with_context().await; + let test_metadata = Metadata::new(); + let test_master_edition = MasterEditionV2::new(&test_metadata); + let test_edition_marker = EditionMarker::new(&test_metadata, &test_master_edition, 1); + + test_metadata + .create( + &mut context, + "Test".to_string(), + "TST".to_string(), + "uri".to_string(), + None, + 10, + false, + ) + .await + .unwrap(); + + test_master_edition + .create(&mut context, Some(10)) + .await + .unwrap(); + + test_edition_marker.create(&mut context).await.unwrap(); + + let edition_marker = test_edition_marker.get_data(&mut context).await; + + assert_eq!(edition_marker.ledger[0], 64); + assert_eq!(edition_marker.key, Key::EditionMarker); +} diff --git a/rust/token-metadata/program/tests/mint_new_edition_from_master_edition_via_vault_proxy.rs b/rust/token-metadata/program/tests/mint_new_edition_from_master_edition_via_vault_proxy.rs new file mode 100644 index 0000000..8cbf186 --- /dev/null +++ b/rust/token-metadata/program/tests/mint_new_edition_from_master_edition_via_vault_proxy.rs @@ -0,0 +1,75 @@ +mod utils; + +use solana_program_test::*; +use solana_sdk::signature::Signer; +use spl_token_metadata::state::Key; +use utils::*; + +#[tokio::test] +async fn success() { + let mut program_test = program_test(); + program_test.add_program("spl_token_vault", spl_token_vault::id(), None); + let mut context = program_test.start_with_context().await; + + let test_metadata = Metadata::new(); + let test_master_edition = MasterEditionV2::new(&test_metadata); + let test_external_price = ExternalPrice::new(); + let test_vault = Vault::new(); + let test_edition_marker = EditionMarker::new(&test_metadata, &test_master_edition, 10); + + test_metadata + .create( + &mut context, + "Test".to_string(), + "TST".to_string(), + "uri".to_string(), + None, + 10, + false, + ) + .await + .unwrap(); + + test_master_edition + .create(&mut context, Some(10)) + .await + .unwrap(); + + test_external_price.create(&mut context).await.unwrap(); + test_external_price + .update( + &mut context, + 1, + &test_external_price.price_mint.pubkey(), + true, + ) + .await + .unwrap(); + + test_vault + .create(&mut context, &test_external_price) + .await + .unwrap(); + + let (safety_deposit_box, store) = test_vault + .add_token_to_inactive_vault(&mut context, 1, &test_metadata) + .await + .unwrap(); + + test_vault.activate(&mut context, 1).await.unwrap(); + + test_vault + .combine(&mut context, &test_external_price) + .await + .unwrap(); + + test_edition_marker + .create_via_vault(&mut context, &test_vault, &safety_deposit_box, &store) + .await + .unwrap(); + + let edition_marker = test_edition_marker.get_data(&mut context).await; + + assert_eq!(edition_marker.ledger[1], 32); + assert_eq!(edition_marker.key, Key::EditionMarker); +} diff --git a/rust/token-metadata/program/tests/update_metadata_account.rs b/rust/token-metadata/program/tests/update_metadata_account.rs new file mode 100644 index 0000000..5ac1ea9 --- /dev/null +++ b/rust/token-metadata/program/tests/update_metadata_account.rs @@ -0,0 +1,51 @@ +mod utils; + +use solana_program_test::*; +use solana_sdk::signature::Signer; +use spl_token_metadata::state::Key; +use utils::*; + +#[tokio::test] +async fn success() { + let mut context = program_test().start_with_context().await; + let test_metadata = Metadata::new(); + + test_metadata + .create( + &mut context, + "Test".to_string(), + "TST".to_string(), + "uri".to_string(), + None, + 10, + true, + ) + .await + .unwrap(); + + test_metadata + .update( + &mut context, + "Cool".to_string(), + "TST".to_string(), + "uri".to_string(), + None, + 10, + ) + .await + .unwrap(); + + let metadata = test_metadata.get_data(&mut context).await; + + assert_eq!(metadata.data.name, "Cool"); + assert_eq!(metadata.data.symbol, "TST"); + assert_eq!(metadata.data.uri, "uri"); + assert_eq!(metadata.data.seller_fee_basis_points, 10); + assert_eq!(metadata.data.creators, None); + + assert_eq!(metadata.primary_sale_happened, false); + assert_eq!(metadata.is_mutable, true); + assert_eq!(metadata.mint, test_metadata.mint.pubkey()); + assert_eq!(metadata.update_authority, context.payer.pubkey()); + assert_eq!(metadata.key, Key::MetadataV1); +} diff --git a/rust/token-metadata/program/tests/update_primary_sale_happened_via_token.rs b/rust/token-metadata/program/tests/update_primary_sale_happened_via_token.rs new file mode 100644 index 0000000..c15a198 --- /dev/null +++ b/rust/token-metadata/program/tests/update_primary_sale_happened_via_token.rs @@ -0,0 +1,44 @@ +mod utils; + +use solana_program_test::*; +use solana_sdk::signature::Signer; +use spl_token_metadata::state::Key; +use utils::*; + +#[tokio::test] +async fn success() { + let mut context = program_test().start_with_context().await; + let test_metadata = Metadata::new(); + + test_metadata + .create( + &mut context, + "Test".to_string(), + "TST".to_string(), + "uri".to_string(), + None, + 10, + false, + ) + .await + .unwrap(); + + test_metadata + .update_primary_sale_happened_via_token(&mut context) + .await + .unwrap(); + + let metadata = test_metadata.get_data(&mut context).await; + + assert_eq!(metadata.data.name, "Test"); + assert_eq!(metadata.data.symbol, "TST"); + assert_eq!(metadata.data.uri, "uri"); + assert_eq!(metadata.data.seller_fee_basis_points, 10); + assert_eq!(metadata.data.creators, None); + + assert_eq!(metadata.primary_sale_happened, true); + assert_eq!(metadata.is_mutable, false); + assert_eq!(metadata.mint, test_metadata.mint.pubkey()); + assert_eq!(metadata.update_authority, context.payer.pubkey()); + assert_eq!(metadata.key, Key::MetadataV1); +} diff --git a/rust/token-metadata/program/tests/utils/edition_marker.rs b/rust/token-metadata/program/tests/utils/edition_marker.rs new file mode 100644 index 0000000..6d8f5e2 --- /dev/null +++ b/rust/token-metadata/program/tests/utils/edition_marker.rs @@ -0,0 +1,187 @@ +use crate::*; +use solana_program::borsh::try_from_slice_unchecked; +use solana_program_test::*; +use solana_sdk::{ + pubkey::Pubkey, signature::Signer, signer::keypair::Keypair, transaction::Transaction, + transport, +}; +use spl_token_metadata::{ + id, instruction, + state::{EDITION, EDITION_MARKER_BIT_SIZE, PREFIX}, +}; + +#[derive(Debug)] +pub struct EditionMarker { + pub new_metadata_pubkey: Pubkey, + pub new_edition_pubkey: Pubkey, + pub master_edition_pubkey: Pubkey, + pub metadata_mint_pubkey: Pubkey, + pub mint: Keypair, + pub metadata_pubkey: Pubkey, + pub pubkey: Pubkey, + pub edition: u64, + pub token: Keypair, + pub metadata_token_pubkey: Pubkey, +} + +impl EditionMarker { + pub fn new(metadata: &Metadata, master_edition: &MasterEditionV2, edition: u64) -> Self { + let mint = Keypair::new(); + let mint_pubkey = mint.pubkey(); + let metadata_mint_pubkey = metadata.mint.pubkey(); + let program_id = id(); + + let edition_number = edition.checked_div(EDITION_MARKER_BIT_SIZE).unwrap(); + let as_string = edition_number.to_string(); + let (pubkey, _) = Pubkey::find_program_address( + &[ + PREFIX.as_bytes(), + program_id.as_ref(), + metadata_mint_pubkey.as_ref(), + EDITION.as_bytes(), + as_string.as_bytes(), + ], + &program_id, + ); + + let metadata_seeds = &[PREFIX.as_bytes(), program_id.as_ref(), mint_pubkey.as_ref()]; + let (new_metadata_pubkey, _) = Pubkey::find_program_address(metadata_seeds, &id()); + + let master_edition_seeds = &[ + PREFIX.as_bytes(), + program_id.as_ref(), + mint_pubkey.as_ref(), + EDITION.as_bytes(), + ]; + let (new_edition_pubkey, _) = Pubkey::find_program_address(master_edition_seeds, &id()); + + EditionMarker { + pubkey, + edition, + mint, + metadata_mint_pubkey, + metadata_pubkey: metadata.pubkey, + master_edition_pubkey: master_edition.pubkey, + new_metadata_pubkey, + new_edition_pubkey, + metadata_token_pubkey: metadata.token.pubkey(), + token: Keypair::new(), + } + } + + pub async fn get_data( + &self, + context: &mut ProgramTestContext, + ) -> spl_token_metadata::state::EditionMarker { + let account = get_account(context, &self.pubkey).await; + try_from_slice_unchecked(&account.data).unwrap() + } + + pub async fn create_via_vault( + &self, + context: &mut ProgramTestContext, + vault: &Vault, + safety_deposit_box: &Pubkey, + store: &Pubkey, + ) -> transport::Result<()> { + let spl_token_vault_id = spl_token_vault::id(); + let vault_pubkey = vault.keypair.pubkey(); + + let vault_mint_seeds = &[ + PREFIX.as_bytes(), + spl_token_vault_id.as_ref(), + vault_pubkey.as_ref(), + ]; + let (authority, _) = Pubkey::find_program_address(vault_mint_seeds, &spl_token_vault_id); + + create_mint(context, &self.mint, &context.payer.pubkey(), None).await?; + create_token_account( + context, + &self.token, + &self.mint.pubkey(), + &context.payer.pubkey(), + ) + .await?; + mint_tokens( + context, + &self.mint.pubkey(), + &self.token.pubkey(), + 1, + &context.payer.pubkey(), + None, + ) + .await?; + + let tx = Transaction::new_signed_with_payer( + &[ + instruction::mint_edition_from_master_edition_via_vault_proxy( + id(), + self.new_metadata_pubkey, + self.new_edition_pubkey, + self.master_edition_pubkey, + self.mint.pubkey(), + self.pubkey, + context.payer.pubkey(), + context.payer.pubkey(), + context.payer.pubkey(), + *store, + *safety_deposit_box, + vault.keypair.pubkey(), + context.payer.pubkey(), + self.metadata_pubkey, + spl_token::id(), + spl_token_vault::id(), + self.edition, + ), + ], + Some(&context.payer.pubkey()), + &[&context.payer, &context.payer], + context.last_blockhash, + ); + + Ok(context.banks_client.process_transaction(tx).await?) + } + + pub async fn create(&self, context: &mut ProgramTestContext) -> transport::Result<()> { + create_mint(context, &self.mint, &context.payer.pubkey(), None).await?; + create_token_account( + context, + &self.token, + &self.mint.pubkey(), + &context.payer.pubkey(), + ) + .await?; + mint_tokens( + context, + &self.mint.pubkey(), + &self.token.pubkey(), + 1, + &context.payer.pubkey(), + None, + ) + .await?; + + let tx = Transaction::new_signed_with_payer( + &[instruction::mint_new_edition_from_master_edition_via_token( + id(), + self.new_metadata_pubkey, + self.new_edition_pubkey, + self.master_edition_pubkey, + self.mint.pubkey(), + context.payer.pubkey(), + context.payer.pubkey(), + context.payer.pubkey(), + self.metadata_token_pubkey, + context.payer.pubkey(), + self.metadata_pubkey, + self.metadata_mint_pubkey, + self.edition, + )], + Some(&context.payer.pubkey()), + &[&context.payer, &context.payer], + context.last_blockhash, + ); + + Ok(context.banks_client.process_transaction(tx).await?) + } +} diff --git a/rust/token-metadata/program/tests/utils/external_price.rs b/rust/token-metadata/program/tests/utils/external_price.rs new file mode 100644 index 0000000..4bdd8c1 --- /dev/null +++ b/rust/token-metadata/program/tests/utils/external_price.rs @@ -0,0 +1,82 @@ +use crate::*; +use solana_program::{borsh::try_from_slice_unchecked, system_instruction}; +use solana_program_test::*; +use solana_sdk::{ + pubkey::Pubkey, signature::Signer, signer::keypair::Keypair, transaction::Transaction, + transport, +}; +use spl_token_vault::instruction; + +#[derive(Debug)] +pub struct ExternalPrice { + pub keypair: Keypair, + pub price_mint: Keypair, +} + +impl ExternalPrice { + pub fn new() -> Self { + ExternalPrice { + keypair: Keypair::new(), + price_mint: Keypair::new(), + } + } + + pub async fn get_data( + &self, + context: &mut ProgramTestContext, + ) -> spl_token_vault::state::ExternalPriceAccount { + let account = get_account(context, &self.keypair.pubkey()).await; + try_from_slice_unchecked(&account.data).unwrap() + } + + pub async fn update( + &self, + context: &mut ProgramTestContext, + price_per_share: u64, + price_mint: &Pubkey, + allowed_to_combine: bool, + ) -> transport::Result<()> { + let tx = Transaction::new_signed_with_payer( + &[ + instruction::create_update_external_price_account_instruction( + spl_token_vault::id(), + self.keypair.pubkey(), + price_per_share, + *price_mint, + allowed_to_combine, + ), + ], + Some(&context.payer.pubkey()), + &[&context.payer, &self.keypair], + context.last_blockhash, + ); + + Ok(context.banks_client.process_transaction(tx).await?) + } + + pub async fn create(&self, context: &mut ProgramTestContext) -> transport::Result<()> { + create_mint( + context, + &self.price_mint, + &context.payer.pubkey(), + Some(&context.payer.pubkey()), + ) + .await?; + + let rent = context.banks_client.get_rent().await.unwrap(); + let tx = Transaction::new_signed_with_payer( + &[system_instruction::create_account( + &context.payer.pubkey(), + &self.keypair.pubkey(), + rent.minimum_balance(spl_token_vault::state::MAX_EXTERNAL_ACCOUNT_SIZE), + spl_token_vault::state::MAX_EXTERNAL_ACCOUNT_SIZE as u64, + &spl_token_vault::id(), + )], + Some(&context.payer.pubkey()), + &[&context.payer, &self.keypair], + context.last_blockhash, + ); + + Ok(context.banks_client.process_transaction(tx).await?) + } +} diff --git a/rust/token-metadata/program/tests/utils/master_edition_v2.rs b/rust/token-metadata/program/tests/utils/master_edition_v2.rs new file mode 100644 index 0000000..28cdddf --- /dev/null +++ b/rust/token-metadata/program/tests/utils/master_edition_v2.rs @@ -0,0 +1,76 @@ +use crate::*; +use solana_program::borsh::try_from_slice_unchecked; +use solana_program_test::*; +use solana_sdk::{pubkey::Pubkey, signature::Signer, transaction::Transaction, transport}; +use spl_token_metadata::{ + id, instruction, + state::{EDITION, PREFIX}, +}; + +#[derive(Debug)] +pub struct MasterEditionV2 { + pub pubkey: Pubkey, + pub metadata_pubkey: Pubkey, + pub mint_pubkey: Pubkey, +} + +impl MasterEditionV2 { + pub fn new(metadata: &Metadata) -> Self { + let program_id = id(); + let mint_pubkey = metadata.mint.pubkey(); + + let master_edition_seeds = &[ + PREFIX.as_bytes(), + program_id.as_ref(), + mint_pubkey.as_ref(), + EDITION.as_bytes(), + ]; + let (pubkey, _) = Pubkey::find_program_address(master_edition_seeds, &id()); + + MasterEditionV2 { + pubkey, + metadata_pubkey: metadata.pubkey, + mint_pubkey: mint_pubkey, + } + } + + pub async fn get_data( + &self, + context: &mut ProgramTestContext, + ) -> spl_token_metadata::state::MasterEditionV2 { + let account = get_account(context, &self.pubkey).await; + try_from_slice_unchecked(&account.data).unwrap() + } + + pub async fn get_data_from_account( + context: &mut ProgramTestContext, + pubkey: &Pubkey, + ) -> spl_token_metadata::state::MasterEditionV2 { + let account = get_account(context, pubkey).await; + try_from_slice_unchecked(&account.data).unwrap() + } + + pub async fn create( + &self, + context: &mut ProgramTestContext, + max_supply: Option, + ) -> transport::Result<()> { + let tx = Transaction::new_signed_with_payer( + &[instruction::create_master_edition( + id(), + self.pubkey, + self.mint_pubkey, + context.payer.pubkey(), + context.payer.pubkey(), + self.metadata_pubkey, + context.payer.pubkey(), + max_supply, + )], + Some(&context.payer.pubkey()), + &[&context.payer, &context.payer, &context.payer], + context.last_blockhash, + ); + + Ok(context.banks_client.process_transaction(tx).await?) + } +} diff --git a/rust/token-metadata/program/tests/utils/metadata.rs b/rust/token-metadata/program/tests/utils/metadata.rs new file mode 100644 index 0000000..586356a --- /dev/null +++ b/rust/token-metadata/program/tests/utils/metadata.rs @@ -0,0 +1,146 @@ +use crate::*; +use solana_program::borsh::try_from_slice_unchecked; +use solana_program_test::*; +use solana_sdk::{ + pubkey::Pubkey, signature::Signer, signer::keypair::Keypair, transaction::Transaction, + transport, +}; +use spl_token_metadata::{ + id, instruction, + state::{Creator, Data, PREFIX}, +}; + +#[derive(Debug)] +pub struct Metadata { + pub mint: Keypair, + pub pubkey: Pubkey, + pub token: Keypair, +} + +impl Metadata { + pub fn new() -> Self { + let mint = Keypair::new(); + let mint_pubkey = mint.pubkey(); + let program_id = id(); + + let metadata_seeds = &[PREFIX.as_bytes(), program_id.as_ref(), mint_pubkey.as_ref()]; + let (pubkey, _) = Pubkey::find_program_address(metadata_seeds, &id()); + + Metadata { + mint, + pubkey, + token: Keypair::new(), + } + } + + pub async fn get_data( + &self, + context: &mut ProgramTestContext, + ) -> spl_token_metadata::state::Metadata { + let account = get_account(context, &self.pubkey).await; + try_from_slice_unchecked(&account.data).unwrap() + } + + pub async fn create( + &self, + context: &mut ProgramTestContext, + name: String, + symbol: String, + uri: String, + creators: Option>, + seller_fee_basis_points: u16, + is_mutable: bool, + ) -> transport::Result<()> { + create_mint(context, &self.mint, &context.payer.pubkey(), None).await?; + create_token_account( + context, + &self.token, + &self.mint.pubkey(), + &context.payer.pubkey(), + ) + .await?; + mint_tokens( + context, + &self.mint.pubkey(), + &self.token.pubkey(), + 1, + &context.payer.pubkey(), + None, + ) + .await?; + + let tx = Transaction::new_signed_with_payer( + &[instruction::create_metadata_accounts( + id(), + self.pubkey.clone(), + self.mint.pubkey(), + context.payer.pubkey().clone(), + context.payer.pubkey().clone(), + context.payer.pubkey().clone(), + name, + symbol, + uri, + creators, + seller_fee_basis_points, + false, + is_mutable, + )], + Some(&context.payer.pubkey()), + &[&context.payer], + context.last_blockhash, + ); + + Ok(context.banks_client.process_transaction(tx).await?) + } + + pub async fn update_primary_sale_happened_via_token( + &self, + context: &mut ProgramTestContext, + ) -> transport::Result<()> { + let tx = Transaction::new_signed_with_payer( + &[instruction::update_primary_sale_happened_via_token( + id(), + self.pubkey, + context.payer.pubkey(), + self.token.pubkey(), + )], + Some(&context.payer.pubkey()), + &[&context.payer], + context.last_blockhash, + ); + + Ok(context.banks_client.process_transaction(tx).await?) + } + + pub async fn update( + &self, + context: &mut ProgramTestContext, + name: String, + symbol: String, + uri: String, + creators: Option>, + seller_fee_basis_points: u16, + ) -> transport::Result<()> { + let tx = Transaction::new_signed_with_payer( + &[instruction::update_metadata_accounts( + id(), + self.pubkey, + context.payer.pubkey().clone(), + None, + Some(Data { + name, + symbol, + uri, + creators, + seller_fee_basis_points, + }), + None, + )], + Some(&context.payer.pubkey()), + &[&context.payer], + context.last_blockhash, + ); + + Ok(context.banks_client.process_transaction(tx).await?) + } +} diff --git a/rust/token-metadata/program/tests/utils/mod.rs b/rust/token-metadata/program/tests/utils/mod.rs new file mode 100644 index 0000000..338c0ca --- /dev/null +++ b/rust/token-metadata/program/tests/utils/mod.rs @@ -0,0 +1,128 @@ +mod edition_marker; +mod external_price; +mod master_edition_v2; +mod metadata; +mod vault; + +pub use edition_marker::EditionMarker; +pub use external_price::ExternalPrice; +pub use master_edition_v2::MasterEditionV2; +pub use metadata::Metadata; +use solana_program_test::*; +use solana_sdk::{ + account::Account, program_pack::Pack, pubkey::Pubkey, signature::Signer, + signer::keypair::Keypair, system_instruction, transaction::Transaction, transport, +}; +use spl_token::state::Mint; +pub use vault::Vault; + +pub fn program_test<'a>() -> ProgramTest { + ProgramTest::new("spl_token_metadata", spl_token_metadata::id(), None) +} + +pub async fn get_account(context: &mut ProgramTestContext, pubkey: &Pubkey) -> Account { + context + .banks_client + .get_account(*pubkey) + .await + .expect("account not found") + .expect("account empty") +} + +pub async fn get_mint(context: &mut ProgramTestContext, pubkey: &Pubkey) -> Mint { + let account = get_account(context, pubkey).await; + Mint::unpack(&account.data).unwrap() +} + +pub async fn mint_tokens( + context: &mut ProgramTestContext, + mint: &Pubkey, + account: &Pubkey, + amount: u64, + owner: &Pubkey, + additional_signer: Option<&Keypair>, +) -> transport::Result<()> { + let mut signing_keypairs = vec![&context.payer]; + if let Some(signer) = additional_signer { + signing_keypairs.push(signer); + } + + let tx = Transaction::new_signed_with_payer( + &[ + spl_token::instruction::mint_to(&spl_token::id(), mint, account, owner, &[], amount) + .unwrap(), + ], + Some(&context.payer.pubkey()), + &signing_keypairs, + context.last_blockhash, + ); + + context.banks_client.process_transaction(tx).await +} + +pub async fn create_token_account( + context: &mut ProgramTestContext, + account: &Keypair, + mint: &Pubkey, + manager: &Pubkey, +) -> transport::Result<()> { + let rent = context.banks_client.get_rent().await.unwrap(); + + let tx = Transaction::new_signed_with_payer( + &[ + system_instruction::create_account( + &context.payer.pubkey(), + &account.pubkey(), + rent.minimum_balance(spl_token::state::Account::LEN), + spl_token::state::Account::LEN as u64, + &spl_token::id(), + ), + spl_token::instruction::initialize_account( + &spl_token::id(), + &account.pubkey(), + mint, + manager, + ) + .unwrap(), + ], + Some(&context.payer.pubkey()), + &[&context.payer, &account], + context.last_blockhash, + ); + + context.banks_client.process_transaction(tx).await +} + +pub async fn create_mint( + context: &mut ProgramTestContext, + mint: &Keypair, + manager: &Pubkey, + freeze_authority: Option<&Pubkey>, +) -> transport::Result<()> { + let rent = context.banks_client.get_rent().await.unwrap(); + + let tx = Transaction::new_signed_with_payer( + &[ + system_instruction::create_account( + &context.payer.pubkey(), + &mint.pubkey(), + rent.minimum_balance(spl_token::state::Mint::LEN), + spl_token::state::Mint::LEN as u64, + &spl_token::id(), + ), + spl_token::instruction::initialize_mint( + &spl_token::id(), + &mint.pubkey(), + &manager, + freeze_authority, + 0, + ) + .unwrap(), + ], + Some(&context.payer.pubkey()), + &[&context.payer, &mint], + context.last_blockhash, + ); + + context.banks_client.process_transaction(tx).await +} diff --git a/rust/token-metadata/program/tests/utils/vault.rs b/rust/token-metadata/program/tests/utils/vault.rs new file mode 100644 index 0000000..9c4763e --- /dev/null +++ b/rust/token-metadata/program/tests/utils/vault.rs @@ -0,0 +1,223 @@ +use super::{create_mint, create_token_account, mint_tokens, ExternalPrice, Metadata}; +use solana_program::{pubkey::Pubkey, system_instruction}; +use solana_program_test::*; +use solana_sdk::{ + signature::{Keypair, Signer}, + transaction::Transaction, + transport, +}; +use spl_token_vault::{instruction, state::PREFIX}; + +pub struct Vault { + pub keypair: Keypair, + pub mint: Keypair, + pub redeem_treasury: Keypair, + pub fraction_treasury: Keypair, +} + +impl Vault { + pub fn new() -> Self { + Vault { + keypair: Keypair::new(), + mint: Keypair::new(), + redeem_treasury: Keypair::new(), + fraction_treasury: Keypair::new(), + } + } + + pub async fn add_token_to_inactive_vault( + &self, + context: &mut ProgramTestContext, + amount: u64, + metadata: &Metadata, + ) -> transport::Result<(Pubkey, Pubkey)> { + let vault_pubkey = self.keypair.pubkey(); + let spl_token_vault_id = spl_token_vault::id(); + + let store = Keypair::new(); + let token_mint_pubkey = metadata.mint.pubkey(); + + let seeds = &[ + PREFIX.as_bytes(), + &vault_pubkey.as_ref(), + &token_mint_pubkey.as_ref(), + ]; + let (safety_deposit_box, _) = Pubkey::find_program_address(seeds, &spl_token_vault_id); + let seeds = &[ + PREFIX.as_bytes(), + &spl_token_vault_id.as_ref(), + &vault_pubkey.as_ref(), + ]; + let (authority, _) = Pubkey::find_program_address(seeds, &spl_token_vault_id); + create_token_account(context, &store, &token_mint_pubkey, &authority).await?; + + let tx = Transaction::new_signed_with_payer( + &[instruction::create_add_token_to_inactive_vault_instruction( + spl_token_vault::id(), + safety_deposit_box, + metadata.token.pubkey(), + store.pubkey(), + self.keypair.pubkey(), + context.payer.pubkey(), + context.payer.pubkey(), + context.payer.pubkey(), + amount, + )], + Some(&context.payer.pubkey()), + &[&context.payer, &context.payer, &context.payer], + context.last_blockhash, + ); + context.banks_client.process_transaction(tx).await?; + + Ok((safety_deposit_box, store.pubkey())) + } + + pub async fn activate( + &self, + context: &mut ProgramTestContext, + number_of_shares: u64, + ) -> transport::Result<()> { + let spl_token_vault_id = spl_token_vault::id(); + let vault_pubkey = self.keypair.pubkey(); + + let seeds = &[ + PREFIX.as_bytes(), + &spl_token_vault_id.as_ref(), + &vault_pubkey.as_ref(), + ]; + let (authority, _) = Pubkey::find_program_address(seeds, &spl_token_vault_id); + + let tx = Transaction::new_signed_with_payer( + &[instruction::create_activate_vault_instruction( + spl_token_vault::id(), + self.keypair.pubkey(), + self.mint.pubkey(), + self.fraction_treasury.pubkey(), + authority, + context.payer.pubkey(), + number_of_shares, + )], + Some(&context.payer.pubkey()), + &[&context.payer], + context.last_blockhash, + ); + + Ok(context.banks_client.process_transaction(tx).await?) + } + + pub async fn combine( + &self, + context: &mut ProgramTestContext, + external_price: &ExternalPrice, + ) -> transport::Result<()> { + let outstanding_token_account = Keypair::new(); + let paying_token_account = Keypair::new(); + + let spl_token_vault_id = spl_token_vault::id(); + let vault_pubkey = self.keypair.pubkey(); + + create_token_account( + context, + &outstanding_token_account, + &self.mint.pubkey(), + &context.payer.pubkey(), + ) + .await?; + create_token_account( + context, + &paying_token_account, + &external_price.price_mint.pubkey(), + &context.payer.pubkey(), + ) + .await?; + + let seeds = &[ + PREFIX.as_bytes(), + &spl_token_vault_id.as_ref(), + &vault_pubkey.as_ref(), + ]; + let (authority, _) = Pubkey::find_program_address(seeds, &spl_token_vault_id); + + let tx = Transaction::new_signed_with_payer( + &[instruction::create_combine_vault_instruction( + spl_token_vault::id(), + self.keypair.pubkey(), + outstanding_token_account.pubkey(), + paying_token_account.pubkey(), + self.mint.pubkey(), + self.fraction_treasury.pubkey(), + self.redeem_treasury.pubkey(), + context.payer.pubkey(), + context.payer.pubkey(), + context.payer.pubkey(), + authority, + external_price.keypair.pubkey(), + )], + Some(&context.payer.pubkey()), + &[&context.payer, &context.payer, &context.payer], + context.last_blockhash, + ); + + Ok(context.banks_client.process_transaction(tx).await?) + } + + pub async fn create( + &self, + context: &mut ProgramTestContext, + external_price: &ExternalPrice, + ) -> transport::Result<()> { + let spl_token_vault_id = spl_token_vault::id(); + let vault_pubkey = self.keypair.pubkey(); + + let seeds = &[ + PREFIX.as_bytes(), + &spl_token_vault_id.as_ref(), + &vault_pubkey.as_ref(), + ]; + let (authority, _) = Pubkey::find_program_address(seeds, &spl_token_vault_id); + + create_mint(context, &self.mint, &authority, Some(&authority)).await?; + create_token_account( + context, + &self.redeem_treasury, + &external_price.price_mint.pubkey(), + &authority, + ) + .await?; + create_token_account( + context, + &self.fraction_treasury, + &self.mint.pubkey(), + &authority, + ) + .await?; + + let rent = context.banks_client.get_rent().await.unwrap(); + let tx = Transaction::new_signed_with_payer( + &[ + system_instruction::create_account( + &context.payer.pubkey(), + &self.keypair.pubkey(), + rent.minimum_balance(spl_token_vault::state::MAX_VAULT_SIZE), + spl_token_vault::state::MAX_VAULT_SIZE as u64, + &spl_token_vault::id(), + ), + instruction::create_init_vault_instruction( + spl_token_vault::id(), + self.mint.pubkey(), + self.redeem_treasury.pubkey(), + self.fraction_treasury.pubkey(), + self.keypair.pubkey(), + context.payer.pubkey(), + external_price.keypair.pubkey(), + false, + ), + ], + Some(&context.payer.pubkey()), + &[&context.payer, &context.payer, &self.keypair], + context.last_blockhash, + ); + + Ok(context.banks_client.process_transaction(tx).await?) + } +} diff --git a/rust/token-vault/program/Cargo.toml b/rust/token-vault/program/Cargo.toml index b26658d..40ea6a2 100644 --- a/rust/token-vault/program/Cargo.toml +++ b/rust/token-vault/program/Cargo.toml @@ -18,7 +18,7 @@ num-traits = "0.2" solana-program = "1.6.10" spl-token = { version="3.1.1", features = [ "no-entrypoint" ] } thiserror = "1.0" -borsh = "0.8.2" +borsh = "0.9.1" [lib] crate-type = ["cdylib", "lib"]