diff --git a/programs/bubblegum/Cargo.lock b/programs/bubblegum/Cargo.lock index acb1e44a..307c80e7 100644 --- a/programs/bubblegum/Cargo.lock +++ b/programs/bubblegum/Cargo.lock @@ -776,11 +776,11 @@ dependencies = [ "solana-program-test", "solana-sdk", "spl-account-compression", - "spl-associated-token-account 1.1.3", + "spl-associated-token-account 2.0.0", "spl-concurrent-merkle-tree", "spl-merkle-tree-reference", "spl-noop 0.1.3", - "spl-token 3.5.0", + "spl-token 4.0.0", ] [[package]] @@ -2264,7 +2264,7 @@ checksum = "66b1ec5ee0570f688cc84ff4624c5c50732f1a2bfc789f6b34af5b563428d971" dependencies = [ "borsh 0.10.3", "bytemuck", - "mpl-token-metadata-context-derive 0.2.1", + "mpl-token-metadata-context-derive", "num-derive", "num-traits", "rmp-serde", @@ -2277,21 +2277,14 @@ dependencies = [ [[package]] name = "mpl-token-metadata" -version = "2.0.0-beta.1" +version = "3.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3545bd5fe73416f6514cd93899612e0e138619e72df8bc7d19906a12688c69e" +checksum = "ba8ee05284d79b367ae8966d558e1a305a781fc80c9df51f37775169117ba64f" dependencies = [ - "arrayref", "borsh 0.10.3", - "mpl-token-auth-rules", - "mpl-token-metadata-context-derive 0.3.0", - "mpl-utils", "num-derive", "num-traits", - "shank", "solana-program", - "spl-associated-token-account 2.0.0", - "spl-token 4.0.0", "thiserror", ] @@ -2305,27 +2298,6 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "mpl-token-metadata-context-derive" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5a739019e11d93661a64ef5fe108ab17c79b35961e944442ff6efdd460ad01a" -dependencies = [ - "quote 1.0.32", - "syn 1.0.109", -] - -[[package]] -name = "mpl-utils" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f2e4f92aec317d5853c0cc4c03c55f5178511c45bb3dbb441aea63117bf3dc9" -dependencies = [ - "arrayref", - "solana-program", - "spl-token-2022 0.6.1", -] - [[package]] name = "nix" version = "0.26.2" @@ -2856,9 +2828,9 @@ dependencies = [ [[package]] name = "quinn-proto" -version = "0.9.4" +version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f31999cfc7927c4e212e60fd50934ab40e8e8bfd2d493d6095d2d306bc0764d9" +checksum = "94b0b33c13a79f669c85defaf4c275dc86a0c0372807d0ca3d78e0bb87274863" dependencies = [ "bytes", "rand 0.8.5", @@ -3567,9 +3539,9 @@ dependencies = [ [[package]] name = "solana-account-decoder" -version = "1.16.6" +version = "1.16.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abdbb3f97298a86fd5a885eac55786a5853885817e5e9f3c427ee3651a81636d" +checksum = "850d5d9dc8fa6ea42f4e61c78e296bbbce5a3531ff4cb3c58ef36ee31781049c" dependencies = [ "Inflector", "base64 0.21.2", @@ -3591,9 +3563,9 @@ dependencies = [ [[package]] name = "solana-address-lookup-table-program" -version = "1.16.6" +version = "1.16.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "282e7e0a459a3461f8dd83eb0609006ec8decf53e6a0cdbc2f2502fe4dc29e97" +checksum = "8a7f867cde478a078d4c4ceb113f4f9ac7e29c2efea98f80a2b30cdcd7be83c5" dependencies = [ "bincode", "bytemuck", @@ -3612,9 +3584,9 @@ dependencies = [ [[package]] name = "solana-banks-client" -version = "1.16.6" +version = "1.16.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2585412945e6b3c484da062001e04b7cf4f94ca2a8f7df4606ecef880a48c590" +checksum = "a46f22d9f8a0b253165260f44c360dd6a2a49b2731f18cbfda818e3ae0ad9112" dependencies = [ "borsh 0.10.3", "futures", @@ -3629,9 +3601,9 @@ dependencies = [ [[package]] name = "solana-banks-interface" -version = "1.16.6" +version = "1.16.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b5bc0424e5946e0f585ce630aaa2eee0c819b789c33c204f61dc402667c1ddc" +checksum = "068d206e9fb611684b61c95b7692d099a89b28e6e376fa0f17620198539de371" dependencies = [ "serde", "solana-sdk", @@ -3640,9 +3612,9 @@ dependencies = [ [[package]] name = "solana-banks-server" -version = "1.16.6" +version = "1.16.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30cf3a1506447db34000595fe9cbd8988f8b4e6dbd576cd51ad90c1bbdbd31f0" +checksum = "4e04de401b9177ef6016f24693b871e9f7c47b49a98e3ee1b794f2ae2cfa2438" dependencies = [ "bincode", "crossbeam-channel", @@ -3659,9 +3631,9 @@ dependencies = [ [[package]] name = "solana-bpf-loader-program" -version = "1.16.6" +version = "1.16.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c27b4d7a33eb06a41b90eaa521303bcf79acbaf92c3a7fdacabed0f4f83f0f3" +checksum = "1eaf42dbfe8a42b80e24f2c087a3935d6e7bb49886313b006d88fb04fdc2a02f" dependencies = [ "bincode", "byteorder", @@ -3678,9 +3650,9 @@ dependencies = [ [[package]] name = "solana-bucket-map" -version = "1.16.6" +version = "1.16.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "594ceb537638fa51eafd330d582660e4a16c1cf2015baf1b1dd8d82b9fc1a91d" +checksum = "e050e58ea0c422f9db10d987b2a10992f103209454f70d54f6208b14ec5546a0" dependencies = [ "bv", "log", @@ -3695,9 +3667,9 @@ dependencies = [ [[package]] name = "solana-clap-utils" -version = "1.16.6" +version = "1.16.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33aa7ffd67c78e34c982c5cd0be7a8f9c4caec21ef1c38adc732c61cd38cef36" +checksum = "c3c99636da9a4acad58d0e8142e36395ece48fc41c396e297e702b6a789b190f" dependencies = [ "chrono", "clap 2.34.0", @@ -3713,9 +3685,9 @@ dependencies = [ [[package]] name = "solana-client" -version = "1.16.6" +version = "1.16.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e5bbde351def5eb2df5fbb4903d5f8e891eaa643c63f654b4a9eb6fa08e88d7" +checksum = "acc7a437165d8fcfac3c63963e394f0ea497b5d2a75159bb3a1ed75dbeb36a7e" dependencies = [ "async-trait", "bincode", @@ -3746,9 +3718,9 @@ dependencies = [ [[package]] name = "solana-compute-budget-program" -version = "1.16.6" +version = "1.16.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27fd9723920466cd05cee0a8cb81cf56b49e67093e41f98bc1fcb7f11b9bd45f" +checksum = "98c90fdaafdc41a4ba0a760af5491bd79f02d1d1eae6926b7796561681c843e4" dependencies = [ "solana-program-runtime", "solana-sdk", @@ -3756,9 +3728,9 @@ dependencies = [ [[package]] name = "solana-config-program" -version = "1.16.6" +version = "1.16.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82d4fb0fa3a1714da0b03befc861aa851bb2d7b446c4eb0a3a55db2f3d47fa3b" +checksum = "d6f9f2201c7e526581511fa6525e281518be5cabaee82bd5b29fe4b78744148d" dependencies = [ "bincode", "chrono", @@ -3770,9 +3742,9 @@ dependencies = [ [[package]] name = "solana-connection-cache" -version = "1.16.6" +version = "1.16.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "313fd8693ddfff8848b00993b4e7d785c9e5dd11e4ef65c20445b86ffc789d90" +checksum = "3ee52de352e10e53b252df0815d685a9c6f3e8d3baa0f65e214dfcd247db0e21" dependencies = [ "async-trait", "bincode", @@ -3791,9 +3763,9 @@ dependencies = [ [[package]] name = "solana-frozen-abi" -version = "1.16.6" +version = "1.16.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c33ec119dc1bb0395b50d389d31ee6015cc81570d31f19cb3dca0ffff5f8f117" +checksum = "361cc834e5fbbe1a73f1d904fcb8ab052a665e5be6061bd1ba7ab478d7d17c9c" dependencies = [ "ahash 0.8.3", "blake3", @@ -3824,9 +3796,9 @@ dependencies = [ [[package]] name = "solana-frozen-abi-macro" -version = "1.16.6" +version = "1.16.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1feba80a564f52092da4c8a93bebc66f39665ebefd02d93bd54ef10453f179d" +checksum = "575d875dc050689f9f88c542e292e295e2f081d4e96e0df297981e45cbad8824" dependencies = [ "proc-macro2 1.0.66", "quote 1.0.32", @@ -3836,9 +3808,9 @@ dependencies = [ [[package]] name = "solana-loader-v4-program" -version = "1.16.6" +version = "1.16.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9aecbef2cb0a25e022a267dfd1400c0ce96dc14ad45e7421d3c3920f1defd3b" +checksum = "a4f1e56ce753307a1b169ad2ef3b9af024c93d4db6f6cd6659794c57635f32ff" dependencies = [ "log", "rand 0.7.3", @@ -3850,9 +3822,9 @@ dependencies = [ [[package]] name = "solana-logger" -version = "1.16.6" +version = "1.16.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "853aab82ead804a201f0edb036e5ff73b9bc8e97d9c1b9b91aeee2f6435073a2" +checksum = "c00faf7aa6a3f47c542bd45d2d7f13af9a382d993e647976a676fe1b0eec4eb2" dependencies = [ "env_logger", "lazy_static", @@ -3861,9 +3833,9 @@ dependencies = [ [[package]] name = "solana-measure" -version = "1.16.6" +version = "1.16.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9baba2de183b0f53e7ef67514a621598a4f83e438223b7d6a98118a0c8785e52" +checksum = "0e19c6e1b35df3c212619a7995ae3576fa92ab15ecfc065899f21385cbe45c95" dependencies = [ "log", "solana-sdk", @@ -3871,9 +3843,9 @@ dependencies = [ [[package]] name = "solana-metrics" -version = "1.16.6" +version = "1.16.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "354797e12eb6e93514074210e905ddd77faecf3ea3fdf414aac18a8290c3e5bb" +checksum = "10e62760a5f87d836169eb3bb446bae174181db07d2c8016be36de49c04fd432" dependencies = [ "crossbeam-channel", "gethostname", @@ -3885,9 +3857,9 @@ dependencies = [ [[package]] name = "solana-net-utils" -version = "1.16.6" +version = "1.16.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6666d2ab4fa92f26cfda1407f5a893237eebb3e71b475816d348b36991ad0f42" +checksum = "308c4c36c634d418589cf1df121d143819feff81932de81640de3d64878934eb" dependencies = [ "bincode", "clap 3.2.25", @@ -3907,9 +3879,9 @@ dependencies = [ [[package]] name = "solana-perf" -version = "1.16.6" +version = "1.16.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fbdd389a7bbf6850ef8e0c391aeb5fdcd3e1017578087dc01b1f7b8b9a68a32" +checksum = "a4d44a4998ba6d9b37e89399d9ce2812e84489dd4665df619fb23366e1c2ec1b" dependencies = [ "ahash 0.8.3", "bincode", @@ -3934,9 +3906,9 @@ dependencies = [ [[package]] name = "solana-program" -version = "1.16.6" +version = "1.16.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3afaa80737c3f26927df136e46b568525709371a5e161e1f490f1dd5defe9698" +checksum = "9863ff5c6e828015bec331c26fb53e48352a264a9be682e7e078d2c3b3e93b46" dependencies = [ "ark-bn254", "ark-ec", @@ -3948,6 +3920,7 @@ dependencies = [ "bitflags 1.3.2", "blake3", "borsh 0.10.3", + "borsh 0.9.3", "bs58 0.4.0", "bv", "bytemuck", @@ -3988,9 +3961,9 @@ dependencies = [ [[package]] name = "solana-program-runtime" -version = "1.16.6" +version = "1.16.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1856d8d16b0cabb912c3a71f6579efcc2a918d9325b27d62a45a38a8958fe3a" +checksum = "05813d4d2e141ab4449cf684cc5b05512dfaabb7251561c5bb1ccf1e4221b210" dependencies = [ "base64 0.21.2", "bincode", @@ -4016,9 +3989,9 @@ dependencies = [ [[package]] name = "solana-program-test" -version = "1.16.6" +version = "1.16.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "916ac43ca718d688ee045ddc72be4765030496c1e18bd43962674f7cf87df017" +checksum = "ff9f8e67fdf7306ae8ff3bb546534ecf064e6ed38e0489fee3579fa1016bd645" dependencies = [ "assert_matches", "async-trait", @@ -4043,9 +4016,9 @@ dependencies = [ [[package]] name = "solana-pubsub-client" -version = "1.16.6" +version = "1.16.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2eca89d4d7faa19562747e7a7cad85abf089ba3c6e00c16196c3627e17b7f5e6" +checksum = "7cd0753cdde1710f50d58bd40a45e58f5368a25dabff6b18ba635c3d6959a558" dependencies = [ "crossbeam-channel", "futures-util", @@ -4068,9 +4041,9 @@ dependencies = [ [[package]] name = "solana-quic-client" -version = "1.16.6" +version = "1.16.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a348eaf9aa4a5cb0139c6af7a09e49a326c25e95a14b3fb9a7d755d47cf7fc0a" +checksum = "212d96abde446eaa903d16961cfd3a6e98dc0d680b9edd61c39938c61548d53e" dependencies = [ "async-mutex", "async-trait", @@ -4096,9 +4069,9 @@ dependencies = [ [[package]] name = "solana-rayon-threadlimit" -version = "1.16.6" +version = "1.16.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8b098bb5f50ee2d6eefa38c908a390cc6c52e08421c745186264fd67cb7bb1b" +checksum = "82ab62fc62458271d746678a3f5625e1654e3cb42a8f318ef4f1ea25991bb085" dependencies = [ "lazy_static", "num_cpus", @@ -4106,9 +4079,9 @@ dependencies = [ [[package]] name = "solana-remote-wallet" -version = "1.16.6" +version = "1.16.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65dc97db0e3fad44e840711fb6a0f2b81d8f4a09611528b3cb177cebedad22bf" +checksum = "863f10b8c2a893d1ec85b3ae8020c714512a67302b80c24dde0016eea4034a7c" dependencies = [ "console", "dialoguer", @@ -4125,9 +4098,9 @@ dependencies = [ [[package]] name = "solana-rpc-client" -version = "1.16.6" +version = "1.16.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8644c6d89367636e7361dd04703ab16bb7ec1f1470d632f957cc30b83beeb7f8" +checksum = "df04998cef2d0fe1291599b69acafc7f8cd87305d7f1525c8ae10aef1cc5411c" dependencies = [ "async-trait", "base64 0.21.2", @@ -4151,9 +4124,9 @@ dependencies = [ [[package]] name = "solana-rpc-client-api" -version = "1.16.6" +version = "1.16.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d44573a6fc4d2467e1434b065641d5b8019b35f671538a9425982cf7fddc421" +checksum = "5e2912ddbff841fbce1e30b0b9a420993c63b6cc7866e5f0af3740fcd6d85bb8" dependencies = [ "base64 0.21.2", "bs58 0.4.0", @@ -4173,9 +4146,9 @@ dependencies = [ [[package]] name = "solana-rpc-client-nonce-utils" -version = "1.16.6" +version = "1.16.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f9252b4f5b0ad3c0cb79d30afb59019ca26ed8ce1f954c59df198a1e9431156" +checksum = "d31100f6cc340dd322f57d00a334fa0a96f628ba86b04fcda1f84307deb14c31" dependencies = [ "clap 2.34.0", "solana-clap-utils", @@ -4186,9 +4159,9 @@ dependencies = [ [[package]] name = "solana-runtime" -version = "1.16.6" +version = "1.16.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3516984ac4be503ef9e0936f8f1a8db7d3057311d718635f94d6160786a22b7a" +checksum = "ebf6db318fd94457b1e69a481dcf43c6fd4f44e264b35f2489f0a1c6f7736e50" dependencies = [ "arrayref", "bincode", @@ -4255,9 +4228,9 @@ dependencies = [ [[package]] name = "solana-sdk" -version = "1.16.6" +version = "1.16.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f53c6ffc2ce2fd2594f6dc1eb1e459843b5f9b008aae10e1cb3d6fef58e63706" +checksum = "621e6973766420162541b26e7974783d32d5471571610da30c5bb0b6263046c9" dependencies = [ "assert_matches", "base64 0.21.2", @@ -4308,9 +4281,9 @@ dependencies = [ [[package]] name = "solana-sdk-macro" -version = "1.16.6" +version = "1.16.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11e11e29d859ffa265e1abb6f7aa12afe6c34b64c75b56a80b777f8f957074ac" +checksum = "bd177a74fb3a0a362f1292c027d668eff609ac189f08b78158324587a0a4f8d1" dependencies = [ "bs58 0.4.0", "proc-macro2 1.0.66", @@ -4321,9 +4294,9 @@ dependencies = [ [[package]] name = "solana-send-transaction-service" -version = "1.16.6" +version = "1.16.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a618753611abb4313434128285e64cff02c44812d686c9ea1e01dccbac84f57" +checksum = "9f275f96dd61f421bda5c9cde7698d85348824f7fa2a8c4544ad24692ac50cd8" dependencies = [ "crossbeam-channel", "log", @@ -4337,9 +4310,9 @@ dependencies = [ [[package]] name = "solana-stake-program" -version = "1.16.6" +version = "1.16.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5208f3164658efddab7ea7b3e2cd3503903f7b47f58ecd5c43b7400acf9df48e" +checksum = "5421decf09671329c4786ed209acfe986bb51272f91e13e4744b13a69c800680" dependencies = [ "bincode", "log", @@ -4352,9 +4325,9 @@ dependencies = [ [[package]] name = "solana-streamer" -version = "1.16.6" +version = "1.16.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3098885b67cadc7b83aab0acd3a476fb24c3c637747ba5eed32dd511b86d9150" +checksum = "3942a60afb0282b07ef0f3c32078145ab7545cbed2cac98f1ec4b9f63016df62" dependencies = [ "async-channel", "bytes", @@ -4385,9 +4358,9 @@ dependencies = [ [[package]] name = "solana-system-program" -version = "1.16.6" +version = "1.16.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44b21678072c2fb35cbd0dc9294d1c5b7fc3043ef9326896dc78ad8b1119c97f" +checksum = "6101d189dc10a96388c695ca1d9f23f74f0fd96330f6adefafd7d6999a20ff6e" dependencies = [ "bincode", "log", @@ -4399,9 +4372,9 @@ dependencies = [ [[package]] name = "solana-thin-client" -version = "1.16.6" +version = "1.16.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d98c7fa5b031439428a35158d69c131e75805d20f61aea1196706822bc14ac90" +checksum = "d712aaf7701a4504521fc09f1743c647edf596e3852a64f6d66b2e5a822388f8" dependencies = [ "bincode", "log", @@ -4414,9 +4387,9 @@ dependencies = [ [[package]] name = "solana-tpu-client" -version = "1.16.6" +version = "1.16.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb2c2ff3d859aea2a175a77b612127b13a969430900b64e865ee39b03c0b4170" +checksum = "48cb32f7443f80cb45e244d514a706b030b5a71ef86b0436c1d39cbfff5491b4" dependencies = [ "async-trait", "bincode", @@ -4439,9 +4412,9 @@ dependencies = [ [[package]] name = "solana-transaction-status" -version = "1.16.6" +version = "1.16.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6590fe4ed93087f6fbd069659d89bacc5edee9493b95e23e016d30aad3dcd059" +checksum = "8aed485ddb4268b4e4ec64012016cd54ba3a4142377a99706fc3ab7768eb2bea" dependencies = [ "Inflector", "base64 0.21.2", @@ -4465,9 +4438,9 @@ dependencies = [ [[package]] name = "solana-udp-client" -version = "1.16.6" +version = "1.16.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa1e4d8b26360621b08d899b306db9c855fed7c3b7e325bd585e62ba068b2ba2" +checksum = "0c92798affef44c1ae2a694006209608044e99106b7945966d53586f5a95d9e2" dependencies = [ "async-trait", "solana-connection-cache", @@ -4480,9 +4453,9 @@ dependencies = [ [[package]] name = "solana-version" -version = "1.16.6" +version = "1.16.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c563989feb6af907aada46d81680dd5982511f6fc793cdf09a674d69725b5bb0" +checksum = "a80a20dfea2afed91761ab3fecc8f96b973a742dc7728f3e343711efe6e8e05f" dependencies = [ "log", "rustc_version", @@ -4496,9 +4469,9 @@ dependencies = [ [[package]] name = "solana-vote-program" -version = "1.16.6" +version = "1.16.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4509784e34e7f85458108370b7f80c2a67f8e8415468201791e8ab8676a6f03c" +checksum = "ab8b719e077cc9e42b8965dd06ff6b5f09fa2a436f2297efdcf471c05d187a6c" dependencies = [ "bincode", "log", @@ -4518,9 +4491,9 @@ dependencies = [ [[package]] name = "solana-zk-token-proof-program" -version = "1.16.6" +version = "1.16.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61698c8504ec0ef2c6fc9b300fc3485fa3fb37b1817a550b58c23c0a2a5be2c0" +checksum = "5404829f9236ac760a943a4e2f16be6f180ce4a07e1bbb9d538dcfa62b98888c" dependencies = [ "bytemuck", "getrandom 0.1.16", @@ -4533,9 +4506,9 @@ dependencies = [ [[package]] name = "solana-zk-token-sdk" -version = "1.16.6" +version = "1.16.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dec0724d3b8c469aafe87c97703ed1f9ddde5ce5df1419fd3d7018d3a41486e" +checksum = "61aabdec9fe1b311dce5d21fa5bd58fbaa985e8003e0d0aedf3795113aacc1ea" dependencies = [ "aes-gcm-siv", "base64 0.21.2", @@ -4562,9 +4535,9 @@ dependencies = [ [[package]] name = "solana_rbpf" -version = "0.6.0" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3082ec3a1d4ef7879eb5b84916d5acde057abd59733eec3647e0ab8885283ef" +checksum = "17d4ba1e58947346e360fabde0697029d36ba83c42f669199b16a8931313cf29" dependencies = [ "byteorder", "combine", diff --git a/programs/bubblegum/program/Cargo.toml b/programs/bubblegum/program/Cargo.toml index 7af93919..ffd0df2d 100644 --- a/programs/bubblegum/program/Cargo.toml +++ b/programs/bubblegum/program/Cargo.toml @@ -23,9 +23,9 @@ default = [] anchor-lang = { version = "0.28.0", features = ["init-if-needed"] } anchor-spl = "0.28.0" bytemuck = "1.13.0" -mpl-token-metadata = { version = "2.0.0-beta.1", features = ["no-entrypoint"] } +mpl-token-metadata = "3.2.3" num-traits = "0.2.15" -solana-program = "~1.16.5" +solana-program = "~1.16.8" spl-account-compression = { version="0.2.0", features = ["cpi"] } spl-associated-token-account = { version = ">= 1.1.3, < 3.0", features = ["no-entrypoint"] } spl-token = { version = ">= 3.5.0, < 5.0", features = ["no-entrypoint"] } diff --git a/programs/bubblegum/program/src/asserts.rs b/programs/bubblegum/program/src/asserts.rs index aef05bca..cdb2b79b 100644 --- a/programs/bubblegum/program/src/asserts.rs +++ b/programs/bubblegum/program/src/asserts.rs @@ -1,22 +1,21 @@ use crate::{error::BubblegumError, state::metaplex_adapter::MetadataArgs, utils::cmp_pubkeys}; use anchor_lang::prelude::*; use mpl_token_metadata::{ - instruction::MetadataDelegateRole, - pda::{find_collection_authority_account, find_metadata_delegate_record_account}, - state::{CollectionAuthorityRecord, Metadata, MetadataDelegateRecord, TokenMetadataAccount}, + accounts::{CollectionAuthorityRecord, Metadata, MetadataDelegateRecord}, + types::{Collection, MetadataDelegateRole, TokenStandard}, }; /// Assert that the provided MetadataArgs are compatible with MPL `Data` pub fn assert_metadata_is_mpl_compatible(metadata: &MetadataArgs) -> Result<()> { - if metadata.name.len() > mpl_token_metadata::state::MAX_NAME_LENGTH { + if metadata.name.len() > mpl_token_metadata::MAX_NAME_LENGTH { return Err(BubblegumError::MetadataNameTooLong.into()); } - if metadata.symbol.len() > mpl_token_metadata::state::MAX_SYMBOL_LENGTH { + if metadata.symbol.len() > mpl_token_metadata::MAX_SYMBOL_LENGTH { return Err(BubblegumError::MetadataSymbolTooLong.into()); } - if metadata.uri.len() > mpl_token_metadata::state::MAX_URI_LENGTH { + if metadata.uri.len() > mpl_token_metadata::MAX_URI_LENGTH { return Err(BubblegumError::MetadataUriTooLong.into()); } @@ -24,7 +23,7 @@ pub fn assert_metadata_is_mpl_compatible(metadata: &MetadataArgs) -> Result<()> return Err(BubblegumError::MetadataBasisPointsTooHigh.into()); } if !metadata.creators.is_empty() { - if metadata.creators.len() > mpl_token_metadata::state::MAX_CREATOR_LIMIT { + if metadata.creators.len() > mpl_token_metadata::MAX_CREATOR_LIMIT { return Err(BubblegumError::CreatorsTooLong.into()); } @@ -106,8 +105,8 @@ pub fn assert_has_collection_authority( } if let Some(record_info) = delegate_record { - let (ca_pda, ca_bump) = find_collection_authority_account(mint, collection_authority); - let (md_pda, md_bump) = find_metadata_delegate_record_account( + let (ca_pda, ca_bump) = CollectionAuthorityRecord::find_pda(mint, collection_authority); + let (md_pda, md_bump) = MetadataDelegateRecord::find_pda( mint, MetadataDelegateRole::Collection, &collection_data.update_authority, @@ -150,3 +149,41 @@ pub fn assert_has_collection_authority( } Ok(()) } + +pub fn assert_collection_membership( + membership: &Option, + collection_metadata: &Metadata, + collection_mint: &Pubkey, + collection_edition: &AccountInfo, +) -> Result<()> { + match membership { + Some(collection) => { + if collection.key != *collection_mint || collection_metadata.mint != *collection_mint { + return Err(BubblegumError::CollectionNotFound.into()); + } + } + None => { + return Err(BubblegumError::CollectionNotFound.into()); + } + } + + let (expected, _) = mpl_token_metadata::accounts::MasterEdition::find_pda(collection_mint); + + if collection_edition.key != &expected { + return Err(BubblegumError::CollectionMasterEditionAccountInvalid.into()); + } + + let edition = mpl_token_metadata::accounts::MasterEdition::try_from(collection_edition) + .map_err(|_err| BubblegumError::CollectionMustBeAUniqueMasterEdition)?; + + match collection_metadata.token_standard { + Some(TokenStandard::NonFungible) | Some(TokenStandard::ProgrammableNonFungible) => (), + _ => return Err(BubblegumError::CollectionMustBeAUniqueMasterEdition.into()), + } + + if edition.max_supply != Some(0) { + return Err(BubblegumError::CollectionMustBeAUniqueMasterEdition.into()); + } + + Ok(()) +} diff --git a/programs/bubblegum/program/src/error.rs b/programs/bubblegum/program/src/error.rs index 416e1e21..39bac159 100644 --- a/programs/bubblegum/program/src/error.rs +++ b/programs/bubblegum/program/src/error.rs @@ -1,5 +1,5 @@ use anchor_lang::prelude::*; -use mpl_token_metadata::error::MetadataError; +use mpl_token_metadata::errors::MplTokenMetadataError; use num_traits::FromPrimitive; #[error_code] @@ -82,12 +82,12 @@ pub fn metadata_error_into_bubblegum(error: ProgramError) -> BubblegumError { FromPrimitive::from_u32(e).expect("Unknown error code from token-metadata"); match metadata_error { - MetadataError::CollectionNotFound => BubblegumError::CollectionNotFound, - MetadataError::CollectionMustBeAUniqueMasterEdition => { + MplTokenMetadataError::CollectionNotFound => BubblegumError::CollectionNotFound, + MplTokenMetadataError::CollectionMustBeAUniqueMasterEdition => { BubblegumError::CollectionMustBeAUniqueMasterEdition } - MetadataError::CollectionMasterEditionAccountInvalid => { + MplTokenMetadataError::CollectionMasterEditionAccountInvalid => { BubblegumError::CollectionMasterEditionAccountInvalid } diff --git a/programs/bubblegum/program/src/processor/decompress.rs b/programs/bubblegum/program/src/processor/decompress.rs index 01310386..eb3501e7 100644 --- a/programs/bubblegum/program/src/processor/decompress.rs +++ b/programs/bubblegum/program/src/processor/decompress.rs @@ -1,5 +1,9 @@ use anchor_lang::prelude::*; use anchor_spl::{associated_token::AssociatedToken, token::Token}; +use mpl_token_metadata::{ + instructions::{CreateMasterEditionV3CpiBuilder, CreateMetadataAccountV3CpiBuilder}, + types::DataV2, +}; use solana_program::{ program::{invoke, invoke_signed}, program_pack::Pack, @@ -71,12 +75,14 @@ pub struct DecompressV1<'info> { } pub(crate) fn decompress_v1(ctx: Context, metadata: MetadataArgs) -> Result<()> { - // Allocate and create mint - let incoming_data_hash = hash_metadata(&metadata)?; + // Validate the incoming metadata + match ctx.accounts.voucher.leaf_schema { LeafSchema::V1 { owner, data_hash, .. } => { + let incoming_data_hash = hash_metadata(&metadata)?; + if !cmp_bytes(&data_hash, &incoming_data_hash, 32) { return Err(BubblegumError::HashingMismatch.into()); } @@ -180,82 +186,53 @@ pub(crate) fn decompress_v1(ctx: Context, metadata: MetadataArgs) ]], )?; - let metadata_infos = vec![ - ctx.accounts.metadata.to_account_info(), - ctx.accounts.mint.to_account_info(), - ctx.accounts.mint_authority.to_account_info(), - ctx.accounts.leaf_owner.to_account_info(), - ctx.accounts.token_metadata_program.to_account_info(), - ctx.accounts.token_program.to_account_info(), - ctx.accounts.system_program.to_account_info(), - ctx.accounts.sysvar_rent.to_account_info(), - ]; - - let master_edition_infos = vec![ - ctx.accounts.master_edition.to_account_info(), - ctx.accounts.mint.to_account_info(), - ctx.accounts.mint_authority.to_account_info(), - ctx.accounts.leaf_owner.to_account_info(), - ctx.accounts.metadata.to_account_info(), - ctx.accounts.token_metadata_program.to_account_info(), - ctx.accounts.token_program.to_account_info(), - ctx.accounts.system_program.to_account_info(), - ctx.accounts.sysvar_rent.to_account_info(), - ]; - - msg!("Creating metadata!"); - invoke_signed( - &mpl_token_metadata::instruction::create_metadata_accounts_v3( - ctx.accounts.token_metadata_program.key(), - ctx.accounts.metadata.key(), - ctx.accounts.mint.key(), - ctx.accounts.mint_authority.key(), - ctx.accounts.leaf_owner.key(), - ctx.accounts.mint_authority.key(), - metadata.name.clone(), - metadata.symbol.clone(), - metadata.uri.clone(), - if !metadata.creators.is_empty() { - Some(metadata.creators.iter().map(|c| c.adapt()).collect()) - } else { + msg!("Creating metadata"); + CreateMetadataAccountV3CpiBuilder::new(&ctx.accounts.token_metadata_program) + .metadata(&ctx.accounts.metadata) + .mint(&ctx.accounts.mint) + .mint_authority(&ctx.accounts.mint_authority) + .payer(&ctx.accounts.leaf_owner) + .update_authority(&ctx.accounts.mint_authority, true) + .system_program(&ctx.accounts.system_program) + .data(DataV2 { + name: metadata.name.clone(), + symbol: metadata.symbol.clone(), + uri: metadata.uri.clone(), + creators: if metadata.creators.is_empty() { None + } else { + Some(metadata.creators.iter().map(|c| c.adapt()).collect()) }, - metadata.seller_fee_basis_points, - true, - metadata.is_mutable, - metadata.collection.map(|c| c.adapt()), - metadata.uses.map(|u| u.adapt()), - None, - ), - metadata_infos.as_slice(), - &[&[ + collection: metadata.collection.map(|c| c.adapt()), + seller_fee_basis_points: metadata.seller_fee_basis_points, + uses: metadata.uses.map(|u| u.adapt()), + }) + .is_mutable(metadata.is_mutable) + .invoke_signed(&[&[ ctx.accounts.mint.key().as_ref(), &[ctx.bumps["mint_authority"]], - ]], - )?; + ]])?; - msg!("Creating master edition!"); - invoke_signed( - &mpl_token_metadata::instruction::create_master_edition_v3( - ctx.accounts.token_metadata_program.key(), - ctx.accounts.master_edition.key(), - ctx.accounts.mint.key(), - ctx.accounts.mint_authority.key(), - ctx.accounts.mint_authority.key(), - ctx.accounts.metadata.key(), - ctx.accounts.leaf_owner.key(), - Some(0), - ), - master_edition_infos.as_slice(), - &[&[ + msg!("Creating master edition"); + CreateMasterEditionV3CpiBuilder::new(&ctx.accounts.token_metadata_program) + .edition(&ctx.accounts.master_edition) + .mint(&ctx.accounts.mint) + .mint_authority(&ctx.accounts.mint_authority) + .update_authority(&ctx.accounts.mint_authority) + .metadata(&ctx.accounts.metadata) + .payer(&ctx.accounts.leaf_owner) + .system_program(&ctx.accounts.system_program) + .token_program(&ctx.accounts.token_program) + .max_supply(0) + .invoke_signed(&[&[ ctx.accounts.mint.key().as_ref(), &[ctx.bumps["mint_authority"]], - ]], - )?; + ]])?; ctx.accounts .mint_authority .to_account_info() .assign(&System::id()); + Ok(()) } diff --git a/programs/bubblegum/program/src/processor/mod.rs b/programs/bubblegum/program/src/processor/mod.rs index 76cc8bf0..99b6ec68 100644 --- a/programs/bubblegum/program/src/processor/mod.rs +++ b/programs/bubblegum/program/src/processor/mod.rs @@ -1,13 +1,14 @@ use anchor_lang::prelude::*; use mpl_token_metadata::{ - assertions::collection::assert_collection_verify_is_valid, state::CollectionDetails, + instructions::BubblegumSetCollectionSizeCpiBuilder, + types::{CollectionDetails, SetCollectionSizeArgs}, }; -use solana_program::{account_info::AccountInfo, program::invoke_signed, pubkey::Pubkey}; +use solana_program::{account_info::AccountInfo, pubkey::Pubkey}; use spl_account_compression::wrap_application_data_v1; use crate::{ - asserts::assert_has_collection_authority, - error::{metadata_error_into_bubblegum, BubblegumError}, + asserts::{assert_collection_membership, assert_has_collection_authority}, + error::BubblegumError, state::{ leaf_schema::LeafSchema, metaplex_adapter::{self, Creator, MetadataArgs}, @@ -190,14 +191,12 @@ fn process_collection_verification_mpl_only<'info>( // If the NFT has collection data, we set it to the correct value after doing some validation. if let Some(collection) = &mut message.collection { - // Collection verify assert from token-metadata program. - assert_collection_verify_is_valid( + assert_collection_membership( &Some(collection.adapt()), collection_metadata, - collection_mint, + collection_mint.key, edition_account, - ) - .map_err(metadata_error_into_bubblegum)?; + )?; assert_has_collection_authority( collection_metadata, @@ -228,31 +227,16 @@ fn process_collection_verification_mpl_only<'info>( } }; - // CPI into to token-metadata program to change the collection size. - let mut bubblegum_set_collection_size_infos = vec![ - collection_metadata.to_account_info(), - collection_authority.clone(), - collection_mint.clone(), - bubblegum_signer.clone(), - ]; + // CPI into Token Metadata program to change the collection size. - if let Some(record) = collection_authority_record { - bubblegum_set_collection_size_infos.push(record.clone()); - } - - invoke_signed( - &mpl_token_metadata::instruction::bubblegum_set_collection_size( - token_metadata_program.key(), - collection_metadata.to_account_info().key(), - collection_authority.key(), - collection_mint.key(), - bubblegum_signer.key(), - collection_authority_record.map(|r| r.key()), - new_size, - ), - bubblegum_set_collection_size_infos.as_slice(), - &[&[COLLECTION_CPI_PREFIX.as_bytes(), &[bubblegum_bump]]], - )?; + BubblegumSetCollectionSizeCpiBuilder::new(token_metadata_program) + .collection_metadata(&collection_metadata.to_account_info()) + .collection_authority(collection_authority) + .collection_mint(collection_mint) + .bubblegum_signer(bubblegum_signer) + .collection_authority_record(collection_authority_record) + .set_collection_size_args(SetCollectionSizeArgs { size: new_size }) + .invoke_signed(&[&[COLLECTION_CPI_PREFIX.as_bytes(), &[bubblegum_bump]]])?; } else { return Err(BubblegumError::CollectionMustBeSized.into()); } diff --git a/programs/bubblegum/program/src/state/metaplex_adapter.rs b/programs/bubblegum/program/src/state/metaplex_adapter.rs index e7823f1a..5c0b1d78 100644 --- a/programs/bubblegum/program/src/state/metaplex_adapter.rs +++ b/programs/bubblegum/program/src/state/metaplex_adapter.rs @@ -17,8 +17,8 @@ pub struct Creator { } impl Creator { - pub fn adapt(&self) -> mpl_token_metadata::state::Creator { - mpl_token_metadata::state::Creator { + pub fn adapt(&self) -> mpl_token_metadata::types::Creator { + mpl_token_metadata::types::Creator { address: self.address, verified: self.verified, share: self.share, @@ -50,12 +50,12 @@ pub struct Uses { } impl Uses { - pub fn adapt(&self) -> mpl_token_metadata::state::Uses { - mpl_token_metadata::state::Uses { + pub fn adapt(&self) -> mpl_token_metadata::types::Uses { + mpl_token_metadata::types::Uses { use_method: match self.use_method { - UseMethod::Burn => mpl_token_metadata::state::UseMethod::Burn, - UseMethod::Multiple => mpl_token_metadata::state::UseMethod::Multiple, - UseMethod::Single => mpl_token_metadata::state::UseMethod::Single, + UseMethod::Burn => mpl_token_metadata::types::UseMethod::Burn, + UseMethod::Multiple => mpl_token_metadata::types::UseMethod::Multiple, + UseMethod::Single => mpl_token_metadata::types::UseMethod::Single, }, remaining: self.remaining, total: self.total, @@ -71,8 +71,8 @@ pub struct Collection { } impl Collection { - pub fn adapt(&self) -> mpl_token_metadata::state::Collection { - mpl_token_metadata::state::Collection { + pub fn adapt(&self) -> mpl_token_metadata::types::Collection { + mpl_token_metadata::types::Collection { verified: self.verified, key: self.key, } diff --git a/programs/bubblegum/program/src/state/metaplex_anchor.rs b/programs/bubblegum/program/src/state/metaplex_anchor.rs index fcb4f8a6..b1f705b1 100644 --- a/programs/bubblegum/program/src/state/metaplex_anchor.rs +++ b/programs/bubblegum/program/src/state/metaplex_anchor.rs @@ -1,23 +1,14 @@ use anchor_lang::{prelude::*, solana_program::pubkey::Pubkey}; -use mpl_token_metadata::{ - state::{MAX_MASTER_EDITION_LEN, MAX_METADATA_LEN}, - utils::try_from_slice_checked, -}; - use std::ops::Deref; #[derive(Clone, AnchorDeserialize, AnchorSerialize)] -pub struct MasterEdition(mpl_token_metadata::state::MasterEditionV2); +pub struct MasterEdition(mpl_token_metadata::accounts::MasterEdition); impl anchor_lang::AccountDeserialize for MasterEdition { fn try_deserialize_unchecked(buf: &mut &[u8]) -> Result { - try_from_slice_checked::( - buf, - mpl_token_metadata::state::Key::MasterEditionV2, - MAX_MASTER_EDITION_LEN, - ) - .map(MasterEdition) - .map_err(Into::into) + mpl_token_metadata::accounts::MasterEdition::safe_deserialize(buf) + .map(MasterEdition) + .map_err(Into::into) } } @@ -25,12 +16,12 @@ impl anchor_lang::AccountSerialize for MasterEdition {} impl anchor_lang::Owner for MasterEdition { fn owner() -> Pubkey { - mpl_token_metadata::id() + mpl_token_metadata::ID } } impl Deref for MasterEdition { - type Target = mpl_token_metadata::state::MasterEditionV2; + type Target = mpl_token_metadata::accounts::MasterEdition; fn deref(&self) -> &Self::Target { &self.0 @@ -38,17 +29,13 @@ impl Deref for MasterEdition { } #[derive(Clone, AnchorDeserialize, AnchorSerialize)] -pub struct TokenMetadata(mpl_token_metadata::state::Metadata); +pub struct TokenMetadata(mpl_token_metadata::accounts::Metadata); impl anchor_lang::AccountDeserialize for TokenMetadata { fn try_deserialize_unchecked(buf: &mut &[u8]) -> Result { - try_from_slice_checked::( - buf, - mpl_token_metadata::state::Key::MetadataV1, - MAX_METADATA_LEN, - ) - .map(TokenMetadata) - .map_err(Into::into) + mpl_token_metadata::accounts::Metadata::safe_deserialize(buf) + .map(TokenMetadata) + .map_err(Into::into) } } @@ -56,12 +43,12 @@ impl anchor_lang::AccountSerialize for TokenMetadata {} impl anchor_lang::Owner for TokenMetadata { fn owner() -> Pubkey { - mpl_token_metadata::id() + mpl_token_metadata::ID } } impl Deref for TokenMetadata { - type Target = mpl_token_metadata::state::Metadata; + type Target = mpl_token_metadata::accounts::Metadata; fn deref(&self) -> &Self::Target { &self.0 @@ -73,6 +60,6 @@ pub struct MplTokenMetadata; impl anchor_lang::Id for MplTokenMetadata { fn id() -> Pubkey { - mpl_token_metadata::id() + mpl_token_metadata::ID } } diff --git a/programs/bubblegum/program/tests/collection.rs b/programs/bubblegum/program/tests/collection.rs index 0d9112bd..e4ac096e 100644 --- a/programs/bubblegum/program/tests/collection.rs +++ b/programs/bubblegum/program/tests/collection.rs @@ -102,7 +102,7 @@ async fn verify_collection_with_new_delegate() { let mut collection_asset = context.default_collection.dirty_clone(); let mut program_context = context.owned_test_context(); - let args = mpl_token_metadata::instruction::DelegateArgs::CollectionV1 { + let args = mpl_token_metadata::types::DelegateArgs::CollectionV1 { authorization_data: None, }; diff --git a/programs/bubblegum/program/tests/decompression.rs b/programs/bubblegum/program/tests/decompression.rs index 9088beab..a785c4b8 100644 --- a/programs/bubblegum/program/tests/decompression.rs +++ b/programs/bubblegum/program/tests/decompression.rs @@ -3,12 +3,9 @@ pub mod utils; use bubblegum::error::BubblegumError; use mpl_token_metadata::{ - pda::{find_master_edition_account, find_metadata_account}, - state::{ - MasterEditionV2, TokenMetadataAccount, TokenStandard, MAX_NAME_LENGTH, MAX_SYMBOL_LENGTH, - MAX_URI_LENGTH, - }, - utils::puffed_out_string, + accounts::{MasterEdition, Metadata}, + types::TokenStandard, + MAX_NAME_LENGTH, MAX_SYMBOL_LENGTH, MAX_URI_LENGTH, }; use solana_program::{account_info::AccountInfo, program_option::COption, program_pack::Pack}; use solana_program_test::{tokio, BanksClientError}; @@ -19,7 +16,7 @@ use spl_associated_token_account::get_associated_token_address; use spl_token::state::Mint; use utils::context::BubblegumTestContext; -use crate::utils::{tree::decompress_mint_auth_pda, Error::BanksClient}; +use crate::utils::{puffed_out_string, tree::decompress_mint_auth_pda, Error::BanksClient}; // Test for multiple combinations? const MAX_DEPTH: usize = 14; @@ -66,11 +63,11 @@ async fn test_decompress_passes() { let mint = Mint::unpack(mint_account.data.as_slice()).unwrap(); let expected_mint = Mint { - mint_authority: COption::Some(find_master_edition_account(&mint_key).0), + mint_authority: COption::Some(MasterEdition::find_pda(&mint_key).0), supply: 1, decimals: 0, is_initialized: true, - freeze_authority: COption::Some(find_master_edition_account(&mint_key).0), + freeze_authority: COption::Some(MasterEdition::find_pda(&mint_key).0), }; assert_eq!(mint, expected_mint); @@ -92,11 +89,11 @@ async fn test_decompress_passes() { assert_eq!(t, expected_t); - let metadata_key = find_metadata_account(&mint_key).0; + let metadata_key = Metadata::find_pda(&mint_key).0; let mut meta_account = tree.read_account(metadata_key).await.unwrap(); - let meta: mpl_token_metadata::state::Metadata = - mpl_token_metadata::state::Metadata::from_account_info(&AccountInfo::from(( + let meta: mpl_token_metadata::accounts::Metadata = + mpl_token_metadata::accounts::Metadata::try_from(&AccountInfo::from(( &metadata_key, &mut meta_account, ))) @@ -106,7 +103,7 @@ async fn test_decompress_passes() { // Can't compare directly as they are different types for some reason. for c1 in leaf.metadata.creators.iter() { - expected_creators.push(mpl_token_metadata::state::Creator { + expected_creators.push(mpl_token_metadata::types::Creator { address: c1.address, verified: c1.verified, share: c1.share, @@ -115,17 +112,15 @@ async fn test_decompress_passes() { assert!(expected_creators[0].verified); - let expected_meta = mpl_token_metadata::state::Metadata { - key: mpl_token_metadata::state::Key::MetadataV1, + let expected_meta = mpl_token_metadata::accounts::Metadata { + key: mpl_token_metadata::types::Key::MetadataV1, update_authority: decompress_mint_auth_pda(mint_key), mint: mint_key, - data: mpl_token_metadata::state::Data { - name: puffed_out_string(&leaf.metadata.name, MAX_NAME_LENGTH), - symbol: puffed_out_string(&leaf.metadata.symbol, MAX_SYMBOL_LENGTH), - uri: puffed_out_string(&leaf.metadata.uri, MAX_URI_LENGTH), - seller_fee_basis_points: leaf.metadata.seller_fee_basis_points, - creators: Some(expected_creators), - }, + name: puffed_out_string(&leaf.metadata.name, MAX_NAME_LENGTH), + symbol: puffed_out_string(&leaf.metadata.symbol, MAX_SYMBOL_LENGTH), + uri: puffed_out_string(&leaf.metadata.uri, MAX_URI_LENGTH), + seller_fee_basis_points: leaf.metadata.seller_fee_basis_points, + creators: Some(expected_creators), primary_sale_happened: false, is_mutable: false, collection: leaf.metadata.collection.as_mut().map(|c| c.adapt()), @@ -140,14 +135,13 @@ async fn test_decompress_passes() { assert_eq!(meta, expected_meta); // Test master edition account. - let me_key = find_master_edition_account(&mint_key).0; + let me_key = MasterEdition::find_pda(&mint_key).0; let mut me_account = tree.read_account(me_key).await.unwrap(); - let me: MasterEditionV2 = - MasterEditionV2::from_account_info(&AccountInfo::from((&me_key, &mut me_account))) - .unwrap(); + let me: MasterEdition = + MasterEdition::try_from(&AccountInfo::from((&me_key, &mut me_account))).unwrap(); - let expected_me = MasterEditionV2 { - key: mpl_token_metadata::state::Key::MasterEditionV2, + let expected_me = MasterEdition { + key: mpl_token_metadata::types::Key::MasterEditionV2, supply: 0, max_supply: Some(0), }; diff --git a/programs/bubblegum/program/tests/utils/context.rs b/programs/bubblegum/program/tests/utils/context.rs index 2b25836d..fd48c5d2 100644 --- a/programs/bubblegum/program/tests/utils/context.rs +++ b/programs/bubblegum/program/tests/utils/context.rs @@ -6,8 +6,9 @@ use super::{ }; use bubblegum::state::metaplex_adapter::{Collection, Creator, MetadataArgs, TokenProgramVersion}; use mpl_token_metadata::{ - pda::find_collection_authority_account, - state::{CollectionDetails, TokenStandard}, + accounts::CollectionAuthorityRecord, + instructions::ApproveCollectionAuthorityBuilder, + types::{CollectionDetails, TokenStandard}, }; use solana_program::pubkey::Pubkey; use solana_program_test::{BanksClient, ProgramTestContext, ProgramTestError}; @@ -219,17 +220,16 @@ impl BubblegumTestContext { let collection_asset = &self.default_collection; let (record, _) = - find_collection_authority_account(&collection_asset.mint.pubkey(), &delegate); - - let ix = mpl_token_metadata::instruction::approve_collection_authority( - mpl_token_metadata::ID, - record, - delegate, - authority.pubkey(), - payer.pubkey(), - collection_asset.metadata, - collection_asset.mint.pubkey(), - ); + CollectionAuthorityRecord::find_pda(&collection_asset.mint.pubkey(), &delegate); + + let ix = ApproveCollectionAuthorityBuilder::default() + .collection_authority_record(record) + .new_collection_authority(delegate) + .update_authority(authority.pubkey()) + .payer(payer.pubkey()) + .metadata(collection_asset.metadata) + .mint(collection_asset.mint.pubkey()) + .instruction(); let tx = Transaction::new_signed_with_payer( &[ix], diff --git a/programs/bubblegum/program/tests/utils/digital_asset.rs b/programs/bubblegum/program/tests/utils/digital_asset.rs index 14e250e9..435ec4b2 100644 --- a/programs/bubblegum/program/tests/utils/digital_asset.rs +++ b/programs/bubblegum/program/tests/utils/digital_asset.rs @@ -1,30 +1,22 @@ #![allow(clippy::too_many_arguments)] use mpl_token_metadata::{ - id, - instruction::{ - self, - builders::{ - BurnBuilder, CreateBuilder, DelegateBuilder, LockBuilder, MintBuilder, RevokeBuilder, - TransferBuilder, UnlockBuilder, UnverifyBuilder, UpdateBuilder, VerifyBuilder, - }, - BurnArgs, CreateArgs, DelegateArgs, InstructionBuilder, LockArgs, MetadataDelegateRole, - MintArgs, RevokeArgs, TransferArgs, UnlockArgs, UpdateArgs, VerificationArgs, + accounts::{EditionMarker, MasterEdition, Metadata, MetadataDelegateRecord, TokenRecord}, + instructions::{ + BurnBuilder, CreateBuilder, DelegateBuilder, LockBuilder, MintBuilder, + MintNewEditionFromMasterEditionViaToken, + MintNewEditionFromMasterEditionViaTokenInstructionArgs, RevokeBuilder, TransferBuilder, + UnlockBuilder, UnverifyBuilder, UpdateBuilder, VerifyBuilder, }, - pda::{ - find_master_edition_account, find_metadata_account, find_metadata_delegate_record_account, - find_token_record_account, + types::{ + AuthorizationData, BurnArgs, Collection, CollectionDetails, CreateArgs, Creator, + DelegateArgs, LockArgs, MetadataDelegateRole, MintArgs, + MintNewEditionFromMasterEditionViaTokenArgs, PrintSupply, ProgrammableConfig, RevokeArgs, + TokenDelegateRole, TokenStandard, TransferArgs, UnlockArgs, UpdateArgs, VerificationArgs, }, - processor::AuthorizationData, - state::{ - AssetData, Collection, CollectionDetails, Creator, Metadata, PrintSupply, - ProgrammableConfig, TokenDelegateRole, TokenMetadataAccount, TokenRecord, TokenStandard, - EDITION, EDITION_MARKER_BIT_SIZE, PREFIX, - }, -}; -use solana_program::{ - borsh::try_from_slice_unchecked, program_option::COption, program_pack::Pack, pubkey::Pubkey, + EDITION_MARKER_BIT_SIZE, }; +use solana_program::{program_option::COption, program_pack::Pack, pubkey::Pubkey, system_program}; use solana_program_test::{BanksClientError, ProgramTestContext}; use solana_sdk::{ account::AccountSharedData, @@ -67,7 +59,7 @@ impl DirtyClone for DigitalAsset { token: self.token, edition: self.edition, token_record: self.token_record, - token_standard: self.token_standard, + token_standard: self.token_standard.clone(), edition_num: self.edition_num, } } @@ -83,10 +75,8 @@ impl DigitalAsset { 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 (metadata, _) = Pubkey::find_program_address(metadata_seeds, &program_id); + let (metadata, _) = Metadata::find_pda(&mint_pubkey); Self { metadata, @@ -100,7 +90,7 @@ impl DigitalAsset { } pub fn set_edition(&mut self) { - let edition = find_master_edition_account(&self.mint.pubkey()).0; + let edition = MasterEdition::find_pda(&self.mint.pubkey()).0; self.edition = Some(edition); } @@ -120,44 +110,37 @@ impl DigitalAsset { .authority(authority.pubkey()) .metadata(self.metadata) .mint(self.mint.pubkey()) - .token(self.token.unwrap()); + .token(self.token.unwrap()) + .burn_args(args); if let Some(parent_asset) = parent_asset { - builder.master_edition_mint(parent_asset.mint.pubkey()); - builder.master_edition_token(parent_asset.token.unwrap()); - builder.master_edition(parent_asset.edition.unwrap()); + builder.master_edition_mint(Some(parent_asset.mint.pubkey())); + builder.master_edition_token(Some(parent_asset.token.unwrap())); + builder.master_edition(Some(parent_asset.edition.unwrap())); let edition_num = self.edition_num.unwrap(); let marker_num = edition_num.checked_div(EDITION_MARKER_BIT_SIZE).unwrap(); - let (edition_marker, _) = Pubkey::find_program_address( - &[ - PREFIX.as_bytes(), - mpl_token_metadata::ID.as_ref(), - parent_asset.mint.pubkey().as_ref(), - EDITION.as_bytes(), - marker_num.to_string().as_bytes(), - ], - &mpl_token_metadata::ID, - ); - builder.edition_marker(edition_marker); + let edition_marker = + EditionMarker::find_pda(&parent_asset.mint.pubkey(), &marker_num.to_string()).0; + builder.edition_marker(Some(edition_marker)); } if let Some(edition) = self.edition { println!("edition: {:?}", edition); - builder.edition(edition); + builder.edition(Some(edition)); } if token_standard == TokenStandard::ProgrammableNonFungible { - builder.token_record(self.token_record.unwrap()); + builder.token_record(Some(self.token_record.unwrap())); } if let Some(collection_metadata) = collection_metadata { - builder.collection_metadata(collection_metadata); + builder.collection_metadata(Some(collection_metadata)); } - let burn_ix = builder.build(args).unwrap().instruction(); + let burn_ix = builder.instruction(); let transaction = Transaction::new_signed_with_payer( &[burn_ix], @@ -190,24 +173,24 @@ impl DigitalAsset { VerificationArgs::CreatorV1 => (), VerificationArgs::CollectionV1 => { if let Some(delegate_record) = delegate_record { - builder.delegate_record(delegate_record); + builder.delegate_record(Some(delegate_record)); } if let Some(collection_mint) = collection_mint { - builder.collection_mint(collection_mint); + builder.collection_mint(Some(collection_mint)); } if let Some(collection_metadata) = collection_metadata { - builder.collection_metadata(collection_metadata); + builder.collection_metadata(Some(collection_metadata)); } if let Some(collection_master_edition) = collection_master_edition { - builder.collection_master_edition(collection_master_edition); + builder.collection_master_edition(Some(collection_master_edition)); } } } - let verify_ix = builder.build(args).unwrap().instruction(); + let verify_ix = builder.verification_args(args).instruction(); let transaction = Transaction::new_signed_with_payer( &[verify_ix], @@ -239,20 +222,20 @@ impl DigitalAsset { VerificationArgs::CreatorV1 => (), VerificationArgs::CollectionV1 => { if let Some(delegate_record) = delegate_record { - builder.delegate_record(delegate_record); + builder.delegate_record(Some(delegate_record)); } if let Some(collection_mint) = collection_mint { - builder.collection_mint(collection_mint); + builder.collection_mint(Some(collection_mint)); } if let Some(collection_metadata) = collection_metadata { - builder.collection_metadata(collection_metadata); + builder.collection_metadata(Some(collection_metadata)); } } } - let unverify_ix = builder.build(args).unwrap().instruction(); + let unverify_ix = builder.verification_args(args).instruction(); let transaction = Transaction::new_signed_with_payer( &[unverify_ix], @@ -306,51 +289,44 @@ impl DigitalAsset { authorization_rules: Option, print_supply: PrintSupply, ) -> Result<(), BanksClientError> { - let mut asset = AssetData::new(token_standard, name, symbol, uri); - asset.seller_fee_basis_points = seller_fee_basis_points; - asset.creators = creators; - asset.collection = collection; - asset.collection_details = collection_details; - asset.rule_set = authorization_rules; - let payer_pubkey = context.payer.pubkey(); let mint_pubkey = self.mint.pubkey(); - let program_id = id(); - let mut builder = CreateBuilder::new(); + let mut builder = CreateBuilder::default(); builder .metadata(self.metadata) - .mint(self.mint.pubkey()) + .mint(self.mint.pubkey(), true) .authority(payer_pubkey) .payer(payer_pubkey) - .update_authority(payer_pubkey) - .initialize_mint(true) - .update_authority_as_signer(true); + .update_authority(payer_pubkey, true); - let edition = match token_standard { + let edition = match &token_standard { TokenStandard::NonFungible | TokenStandard::ProgrammableNonFungible => { - // master edition PDA address - let edition_seeds = &[ - PREFIX.as_bytes(), - program_id.as_ref(), - mint_pubkey.as_ref(), - EDITION.as_bytes(), - ]; - let (edition, _) = Pubkey::find_program_address(edition_seeds, &id()); + let (edition, _) = MasterEdition::find_pda(&mint_pubkey); // sets the master edition to the builder - builder.master_edition(edition); + builder.master_edition(Some(edition)); Some(edition) } _ => None, }; // builds the instruction let create_ix = builder - .build(CreateArgs::V1 { - asset_data: asset, + .create_args(CreateArgs::V1 { + name, + symbol, + uri, + seller_fee_basis_points, + creators, + collection, + uses: None, decimals: Some(0), print_supply: Some(print_supply), + collection_details, + is_mutable: true, + primary_sale_happened: false, + rule_set: authorization_rules, + token_standard: token_standard.clone(), }) - .unwrap() .instruction(); let compute_ix = ComputeBudgetInstruction::set_compute_unit_limit(800_000); @@ -385,7 +361,7 @@ impl DigitalAsset { &spl_associated_token_account::id(), ); - let (token_record, _) = find_token_record_account(&self.mint.pubkey(), &token); + let (token_record, _) = TokenRecord::find_pda(&self.mint.pubkey(), &token); let token_record_opt = if self.is_pnft(context).await { Some(token_record) @@ -393,30 +369,20 @@ impl DigitalAsset { None }; - let mut builder = MintBuilder::new(); - builder + let mint_ix = MintBuilder::new() .token(token) - .token_record(token_record) - .token_owner(payer_pubkey) + .token_record(Some(token_record)) + .token_owner(Some(payer_pubkey)) .metadata(self.metadata) .mint(self.mint.pubkey()) .payer(payer_pubkey) - .authority(payer_pubkey); - - if let Some(edition) = self.edition { - builder.master_edition(edition); - } - - if let Some(authorization_rules) = authorization_rules { - builder.authorization_rules(authorization_rules); - } - - let mint_ix = builder - .build(MintArgs::V1 { + .authority(payer_pubkey) + .master_edition(self.edition) + .authorization_rules(authorization_rules) + .mint_args(MintArgs::V1 { amount, authorization_data, }) - .unwrap() .instruction(); let compute_ix = ComputeBudgetInstruction::set_compute_unit_limit(800_000); @@ -584,7 +550,9 @@ impl DigitalAsset { .metadata(self.metadata) .payer(payer.pubkey()) .authority(payer.pubkey()) - .spl_token_program(spl_token::ID); + .master_edition(self.edition) + .token(self.token) + .spl_token_program(Some(spl_token::ID)); let mut delegate_or_token_record = None; @@ -596,108 +564,100 @@ impl DigitalAsset { | DelegateArgs::StakingV1 { .. } | DelegateArgs::LockedTransferV1 { .. } => { let (token_record, _) = - find_token_record_account(&self.mint.pubkey(), &self.token.unwrap()); - builder.token_record(token_record); + TokenRecord::find_pda(&self.mint.pubkey(), &self.token.unwrap()); + builder.token_record(Some(token_record)); delegate_or_token_record = Some(token_record); } DelegateArgs::StandardV1 { .. } => { /* nothing to add */ } // Metadata delegates. DelegateArgs::CollectionV1 { .. } => { - let (delegate_record, _) = find_metadata_delegate_record_account( + let (delegate_record, _) = MetadataDelegateRecord::find_pda( &self.mint.pubkey(), MetadataDelegateRole::Collection, &payer.pubkey(), &delegate, ); - builder.delegate_record(delegate_record); + builder.delegate_record(Some(delegate_record)); delegate_or_token_record = Some(delegate_record); } DelegateArgs::DataV1 { .. } => { - let (delegate_record, _) = find_metadata_delegate_record_account( + let (delegate_record, _) = MetadataDelegateRecord::find_pda( &self.mint.pubkey(), MetadataDelegateRole::Data, &payer.pubkey(), &delegate, ); - builder.delegate_record(delegate_record); + builder.delegate_record(Some(delegate_record)); delegate_or_token_record = Some(delegate_record); } DelegateArgs::ProgrammableConfigV1 { .. } => { - let (delegate_record, _) = find_metadata_delegate_record_account( + let (delegate_record, _) = MetadataDelegateRecord::find_pda( &self.mint.pubkey(), MetadataDelegateRole::ProgrammableConfig, &payer.pubkey(), &delegate, ); - builder.delegate_record(delegate_record); + builder.delegate_record(Some(delegate_record)); delegate_or_token_record = Some(delegate_record); } DelegateArgs::AuthorityItemV1 { .. } => { - let (delegate_record, _) = find_metadata_delegate_record_account( + let (delegate_record, _) = MetadataDelegateRecord::find_pda( &self.mint.pubkey(), MetadataDelegateRole::AuthorityItem, &payer.pubkey(), &delegate, ); - builder.delegate_record(delegate_record); + builder.delegate_record(Some(delegate_record)); delegate_or_token_record = Some(delegate_record); } DelegateArgs::DataItemV1 { .. } => { - let (delegate_record, _) = find_metadata_delegate_record_account( + let (delegate_record, _) = MetadataDelegateRecord::find_pda( &self.mint.pubkey(), MetadataDelegateRole::DataItem, &payer.pubkey(), &delegate, ); - builder.delegate_record(delegate_record); + builder.delegate_record(Some(delegate_record)); delegate_or_token_record = Some(delegate_record); } DelegateArgs::CollectionItemV1 { .. } => { - let (delegate_record, _) = find_metadata_delegate_record_account( + let (delegate_record, _) = MetadataDelegateRecord::find_pda( &self.mint.pubkey(), MetadataDelegateRole::CollectionItem, &payer.pubkey(), &delegate, ); - builder.delegate_record(delegate_record); + builder.delegate_record(Some(delegate_record)); delegate_or_token_record = Some(delegate_record); } DelegateArgs::ProgrammableConfigItemV1 { .. } => { - let (delegate_record, _) = find_metadata_delegate_record_account( + let (delegate_record, _) = MetadataDelegateRecord::find_pda( &self.mint.pubkey(), MetadataDelegateRole::ProgrammableConfigItem, &payer.pubkey(), &delegate, ); - builder.delegate_record(delegate_record); + builder.delegate_record(Some(delegate_record)); delegate_or_token_record = Some(delegate_record); } } - if let Some(edition) = self.edition { - builder.master_edition(edition); - } - - if let Some(token) = self.token { - builder.token(token); - } - // determines if we need to set the rule set let metadata_account = get_account(context, &self.metadata).await; - let metadata: Metadata = try_from_slice_unchecked(&metadata_account.data).unwrap(); + let metadata: Metadata = Metadata::safe_deserialize(&metadata_account.data).unwrap(); if let Some(ProgrammableConfig::V1 { rule_set: Some(rule_set), }) = metadata.programmable_config { - builder.authorization_rules(rule_set); - builder.authorization_rules_program(mpl_token_auth_rules::ID); + builder.authorization_rules(Some(rule_set)); + builder.authorization_rules_program(Some(mpl_token_auth_rules::ID)); } let compute_ix = ComputeBudgetInstruction::set_compute_unit_limit(400_000); - let delegate_ix = builder.build(args.clone()).unwrap().instruction(); + let delegate_ix = builder.delegate_args(args.clone()).instruction(); let tx = Transaction::new_signed_with_payer( &[compute_ix, delegate_ix], @@ -717,8 +677,8 @@ impl DigitalAsset { ) -> Result { let print_mint = Keypair::new(); let print_token = Keypair::new(); - let (print_metadata, _) = find_metadata_account(&print_mint.pubkey()); - let (print_edition, _) = find_master_edition_account(&print_mint.pubkey()); + let (print_metadata, _) = Metadata::find_pda(&print_mint.pubkey()); + let (print_edition, _) = MasterEdition::find_pda(&print_mint.pubkey()); create_mint( context, @@ -745,22 +705,35 @@ impl DigitalAsset { ) .await?; + let ix = MintNewEditionFromMasterEditionViaToken { + new_metadata: print_metadata, + new_edition: print_edition, + master_edition: self.edition.unwrap(), + new_mint: print_mint.pubkey(), + new_mint_authority: context.payer.pubkey(), + payer: context.payer.pubkey(), + token_account_owner: context.payer.pubkey(), + token_account: self.token.unwrap(), + new_metadata_update_authority: context.payer.pubkey(), + metadata: self.metadata, + edition_mark_pda: EditionMarker::find_pda( + &self.mint.pubkey(), + &edition_num.to_string(), + ) + .0, + system_program: system_program::ID, + token_program: spl_token::ID, + rent: None, + } + .instruction(MintNewEditionFromMasterEditionViaTokenInstructionArgs { + mint_new_edition_from_master_edition_via_token_args: + MintNewEditionFromMasterEditionViaTokenArgs { + edition: edition_num, + }, + }); + let tx = Transaction::new_signed_with_payer( - &[instruction::mint_new_edition_from_master_edition_via_token( - id(), - print_metadata, - print_edition, - self.edition.unwrap(), - print_mint.pubkey(), - context.payer.pubkey(), - context.payer.pubkey(), - context.payer.pubkey(), - self.token.unwrap(), - context.payer.pubkey(), - self.metadata, - self.mint.pubkey(), - edition_num, - )], + &[ix], Some(&context.payer.pubkey()), &[&context.payer, &context.payer], context.last_blockhash, @@ -780,7 +753,7 @@ impl DigitalAsset { token: Some(print_token.pubkey()), metadata: print_metadata, edition: Some(print_edition), - token_standard: self.token_standard, + token_standard: self.token_standard.clone(), token_record: None, edition_num: Some(edition_num), }) @@ -801,7 +774,9 @@ impl DigitalAsset { .metadata(self.metadata) .payer(approver.pubkey()) .authority(approver.pubkey()) - .spl_token_program(spl_token::ID); + .master_edition(self.edition) + .token(self.token) + .spl_token_program(Some(spl_token::ID)); match args { // Token delegates. @@ -812,87 +787,79 @@ impl DigitalAsset { | RevokeArgs::LockedTransferV1 | RevokeArgs::MigrationV1 => { let (token_record, _) = - find_token_record_account(&self.mint.pubkey(), &self.token.unwrap()); - builder.token_record(token_record); + TokenRecord::find_pda(&self.mint.pubkey(), &self.token.unwrap()); + builder.token_record(Some(token_record)); } RevokeArgs::StandardV1 { .. } => { /* nothing to add */ } // Metadata delegates. RevokeArgs::CollectionV1 => { - let (delegate_record, _) = find_metadata_delegate_record_account( + let (delegate_record, _) = MetadataDelegateRecord::find_pda( &self.mint.pubkey(), MetadataDelegateRole::Collection, &payer.pubkey(), &delegate, ); - builder.delegate_record(delegate_record); + builder.delegate_record(Some(delegate_record)); } RevokeArgs::DataV1 => { - let (delegate_record, _) = find_metadata_delegate_record_account( + let (delegate_record, _) = MetadataDelegateRecord::find_pda( &self.mint.pubkey(), MetadataDelegateRole::Data, &payer.pubkey(), &delegate, ); - builder.delegate_record(delegate_record); + builder.delegate_record(Some(delegate_record)); } RevokeArgs::ProgrammableConfigV1 => { - let (delegate_record, _) = find_metadata_delegate_record_account( + let (delegate_record, _) = MetadataDelegateRecord::find_pda( &self.mint.pubkey(), MetadataDelegateRole::ProgrammableConfig, &payer.pubkey(), &delegate, ); - builder.delegate_record(delegate_record); + builder.delegate_record(Some(delegate_record)); } RevokeArgs::AuthorityItemV1 => { - let (delegate_record, _) = find_metadata_delegate_record_account( + let (delegate_record, _) = MetadataDelegateRecord::find_pda( &self.mint.pubkey(), MetadataDelegateRole::AuthorityItem, &payer.pubkey(), &delegate, ); - builder.delegate_record(delegate_record); + builder.delegate_record(Some(delegate_record)); } RevokeArgs::DataItemV1 => { - let (delegate_record, _) = find_metadata_delegate_record_account( + let (delegate_record, _) = MetadataDelegateRecord::find_pda( &self.mint.pubkey(), MetadataDelegateRole::DataItem, &payer.pubkey(), &delegate, ); - builder.delegate_record(delegate_record); + builder.delegate_record(Some(delegate_record)); } RevokeArgs::CollectionItemV1 => { - let (delegate_record, _) = find_metadata_delegate_record_account( + let (delegate_record, _) = MetadataDelegateRecord::find_pda( &self.mint.pubkey(), MetadataDelegateRole::CollectionItem, &payer.pubkey(), &delegate, ); - builder.delegate_record(delegate_record); + builder.delegate_record(Some(delegate_record)); } RevokeArgs::ProgrammableConfigItemV1 => { - let (delegate_record, _) = find_metadata_delegate_record_account( + let (delegate_record, _) = MetadataDelegateRecord::find_pda( &self.mint.pubkey(), MetadataDelegateRole::ProgrammableConfigItem, &payer.pubkey(), &delegate, ); - builder.delegate_record(delegate_record); + builder.delegate_record(Some(delegate_record)); } } - if let Some(edition) = self.edition { - builder.master_edition(edition); - } - - if let Some(token) = self.token { - builder.token(token); - } - - let revoke_ix = builder.build(args.clone()).unwrap().instruction(); + let revoke_ix = builder.revoke_args(args.clone()).instruction(); let tx = Transaction::new_signed_with_payer( &[revoke_ix], @@ -941,35 +908,29 @@ impl DigitalAsset { .token_owner(*source_owner) .token(self.token.unwrap()) .destination_owner(destination_owner) - .destination(destination_token) + .destination_token(destination_token) .metadata(self.metadata) + .edition(self.edition) .payer(payer.pubkey()) - .mint(self.mint.pubkey()); - - if let Some(record) = self.token_record { - builder.owner_token_record(record); - } + .mint(self.mint.pubkey()) + .token_record(self.token_record); // This can be optional for non pNFTs but always include it for now. let (destination_token_record, _bump) = - find_token_record_account(&self.mint.pubkey(), &destination_token); + TokenRecord::find_pda(&self.mint.pubkey(), &destination_token); let destination_token_record_opt = if self.is_pnft(context).await { - builder.destination_token_record(destination_token_record); + builder.destination_token_record(Some(destination_token_record)); Some(destination_token_record) } else { None }; - if let Some(edition) = self.edition { - builder.edition(edition); - } - if let Some(authorization_rules) = authorization_rules { - builder.authorization_rules(authorization_rules); - builder.authorization_rules_program(mpl_token_auth_rules::ID); + builder.authorization_rules(Some(authorization_rules)); + builder.authorization_rules_program(Some(mpl_token_auth_rules::ID)); } - let transfer_ix = builder.build(args).unwrap().instruction(); + let transfer_ix = builder.transfer_args(args).instruction(); instructions.push(transfer_ix); @@ -1000,25 +961,18 @@ impl DigitalAsset { .mint(self.mint.pubkey()) .metadata(self.metadata) .payer(payer.pubkey()) - .spl_token_program(spl_token::ID); - - if let Some(token_record) = token_record { - builder.token_record(token_record); - } - - if let Some(edition) = self.edition { - builder.edition(edition); - } + .token_record(token_record) + .edition(self.edition) + .spl_token_program(Some(spl_token::ID)); if let Some(token) = self.token { builder.token(token); } let utility_ix = builder - .build(LockArgs::V1 { + .lock_args(LockArgs::V1 { authorization_data: None, }) - .unwrap() .instruction(); let tx = Transaction::new_signed_with_payer( @@ -1044,25 +998,18 @@ impl DigitalAsset { .mint(self.mint.pubkey()) .metadata(self.metadata) .payer(payer.pubkey()) - .spl_token_program(spl_token::ID); - - if let Some(token_record) = token_record { - builder.token_record(token_record); - } - - if let Some(edition) = self.edition { - builder.edition(edition); - } + .token_record(token_record) + .edition(self.edition) + .spl_token_program(Some(spl_token::ID)); if let Some(token) = self.token { builder.token(token); } let unlock_ix = builder - .build(UnlockArgs::V1 { + .unlock_args(UnlockArgs::V1 { authorization_data: None, }) - .unwrap() .instruction(); let tx = Transaction::new_signed_with_payer( @@ -1085,14 +1032,11 @@ impl DigitalAsset { builder .authority(authority.pubkey()) .metadata(self.metadata) + .edition(self.edition) .payer(authority.pubkey()) .mint(self.mint.pubkey()); - if let Some(master_edition) = self.edition { - builder.edition(master_edition); - } - - let update_ix = builder.build(update_args).unwrap().instruction(); + let update_ix = builder.update_args(update_args).instruction(); let tx = Transaction::new_signed_with_payer( &[update_ix], @@ -1115,28 +1059,12 @@ impl DigitalAsset { Metadata::safe_deserialize(&metadata_account.data).unwrap() } - pub async fn get_asset_data(&self, context: &mut ProgramTestContext) -> AssetData { - let metadata = self.get_metadata(context).await; - - metadata.into_asset_data() - } - - pub async fn compare_asset_data( - &self, - context: &mut ProgramTestContext, - asset_data: &AssetData, - ) { - let on_chain_asset_data = self.get_asset_data(context).await; - - assert_eq!(on_chain_asset_data, *asset_data); - } - pub async fn get_token_delegate_role( &self, context: &mut ProgramTestContext, token: &Pubkey, ) -> Option { - let (delegate_record_pubkey, _) = find_token_record_account(&self.mint.pubkey(), token); + let (delegate_record_pubkey, _) = TokenRecord::find_pda(&self.mint.pubkey(), token); let delegate_record_account = context .banks_client .get_account(delegate_record_pubkey) @@ -1187,7 +1115,7 @@ impl DigitalAsset { creators: &Option>, ) { let metadata = self.get_metadata(context).await; - let on_chain_creators = metadata.data.creators; + let on_chain_creators = metadata.creators; assert_eq!(on_chain_creators, *creators); } @@ -1215,7 +1143,7 @@ impl DigitalAsset { &self, context: &mut ProgramTestContext, ) -> Result<(), BanksClientError> { - match self.token_standard.unwrap() { + match self.token_standard.clone().unwrap() { TokenStandard::NonFungible => { self.non_fungigble_accounts_closed(context).await?; } @@ -1273,7 +1201,7 @@ impl DigitalAsset { context: &mut ProgramTestContext, token: &Pubkey, ) -> Result<(), BanksClientError> { - let (token_record_pubkey, _) = find_token_record_account(&self.mint.pubkey(), token); + let (token_record_pubkey, _) = TokenRecord::find_pda(&self.mint.pubkey(), token); let token_record_account = context .banks_client diff --git a/programs/bubblegum/program/tests/utils/mod.rs b/programs/bubblegum/program/tests/utils/mod.rs index 2b1f5fcd..9c1d01ea 100644 --- a/programs/bubblegum/program/tests/utils/mod.rs +++ b/programs/bubblegum/program/tests/utils/mod.rs @@ -41,7 +41,7 @@ pub fn program_test() -> ProgramTest { spl_account_compression::id(), None, ); - test.add_program("mpl_token_metadata", mpl_token_metadata::id(), None); + test.add_program("mpl_token_metadata", mpl_token_metadata::ID, None); test.set_compute_max_units(1_400_000); test } @@ -138,3 +138,10 @@ impl Airdrop for Keypair { context.banks_client.process_transaction(tx).await } } + +/// Pads the string to the desired size with `0u8`s. +/// NOTE: it is assumed that the string's size is never larger than the given size. +pub fn puffed_out_string(s: &str, size: usize) -> String { + let padding = vec![0u8; size - s.len()]; + s.to_string() + &String::from_utf8(padding).unwrap() +} diff --git a/programs/bubblegum/program/tests/utils/tree.rs b/programs/bubblegum/program/tests/utils/tree.rs index 9d6451c1..43df82a8 100644 --- a/programs/bubblegum/program/tests/utils/tree.rs +++ b/programs/bubblegum/program/tests/utils/tree.rs @@ -3,7 +3,7 @@ use super::{ tx_builder::{ BurnBuilder, CancelRedeemBuilder, CollectionVerificationInner, CreateBuilder, CreatorVerificationInner, DelegateBuilder, DelegateInner, MintToCollectionV1Builder, - MintV1Builder, RedeemBuilder, SetDecompressableStateBuilder, SetTreeDelegateBuilder, + MintV1Builder, RedeemBuilder, SetDecompressibleStateBuilder, SetTreeDelegateBuilder, TransferBuilder, TransferInner, TxBuilder, UnverifyCreatorBuilder, VerifyCollectionBuilder, VerifyCreatorBuilder, }, @@ -16,6 +16,7 @@ use bubblegum::{ utils::get_asset_id, }; use bytemuck::try_from_bytes; +use mpl_token_metadata::accounts::{MasterEdition, Metadata}; use solana_program::{ instruction::{AccountMeta, Instruction}, pubkey, @@ -352,7 +353,7 @@ impl Tree Tree Tree Tree Tree SetDecompressableStateBuilder { + ) -> SetDecompressibleStateBuilder { let accounts = bubblegum::accounts::SetDecompressibleState { tree_authority: self.authority(), tree_creator: self.creator_pubkey(), }; - let data = bubblegum::instruction::SetDecompressableState { + let data = bubblegum::instruction::SetDecompressibleState { decompressable_state, }; diff --git a/programs/bubblegum/program/tests/utils/tx_builder.rs b/programs/bubblegum/program/tests/utils/tx_builder.rs index 92469666..34eefb24 100644 --- a/programs/bubblegum/program/tests/utils/tx_builder.rs +++ b/programs/bubblegum/program/tests/utils/tx_builder.rs @@ -386,18 +386,18 @@ impl<'a, const MAX_DEPTH: usize, const MAX_BUFFER_SIZE: usize> OnSuccessfulTxExe } } -pub type SetDecompressableStateBuilder<'a, const MAX_DEPTH: usize, const MAX_BUFFER_SIZE: usize> = +pub type SetDecompressibleStateBuilder<'a, const MAX_DEPTH: usize, const MAX_BUFFER_SIZE: usize> = TxBuilder< 'a, bubblegum::accounts::SetDecompressibleState, - bubblegum::instruction::SetDecompressableState, + bubblegum::instruction::SetDecompressibleState, (), MAX_DEPTH, MAX_BUFFER_SIZE, >; impl<'a, const MAX_DEPTH: usize, const MAX_BUFFER_SIZE: usize> OnSuccessfulTxExec - for SetDecompressableStateBuilder<'a, MAX_DEPTH, MAX_BUFFER_SIZE> + for SetDecompressibleStateBuilder<'a, MAX_DEPTH, MAX_BUFFER_SIZE> { fn on_successful_execute(&mut self) -> Result<()> { Ok(())