diff --git a/Cargo.lock b/Cargo.lock index 017d734..cae4675 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -67,9 +67,9 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "1.1.2" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" dependencies = [ "memchr", ] @@ -85,7 +85,7 @@ name = "alloy" version = "0.1.0" source = "git+https://github.com/alloy-rs/alloy?rev=7e39c85f9f51e6449a8b661f54df0ac213f18639#7e39c85f9f51e6449a8b661f54df0ac213f18639" dependencies = [ - "alloy-core", + "alloy-core 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", "alloy-network", "alloy-pubsub", "alloy-rpc-types", @@ -116,6 +116,14 @@ dependencies = [ "alloy-sol-types 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "alloy-core" +version = "0.6.4" +source = "git+https://github.com/alloy-rs/core?rev=525a233#525a2339dfc963518a1350cf52e8928c50a49d66" +dependencies = [ + "alloy-primitives", +] + [[package]] name = "alloy-dyn-abi" version = "0.6.4" @@ -127,6 +135,7 @@ dependencies = [ "alloy-sol-type-parser", "alloy-sol-types 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", "const-hex", + "derive_more", "itoa", "serde", "serde_json", @@ -270,7 +279,7 @@ checksum = "1a047897373be4bbb0224c1afdabca92648dc57a9c9ef6e7b0be3aff7a859c83" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.57", ] [[package]] @@ -339,7 +348,9 @@ name = "alloy-signer" version = "0.1.0" source = "git+https://github.com/alloy-rs/alloy?rev=7e39c85f9f51e6449a8b661f54df0ac213f18639#7e39c85f9f51e6449a8b661f54df0ac213f18639" dependencies = [ + "alloy-dyn-abi", "alloy-primitives", + "alloy-sol-types 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", "async-trait", "auto_impl", "elliptic-curve", @@ -347,6 +358,21 @@ dependencies = [ "thiserror", ] +[[package]] +name = "alloy-signer-wallet" +version = "0.1.0" +source = "git+https://github.com/alloy-rs/alloy?rev=7e39c85f9f51e6449a8b661f54df0ac213f18639#7e39c85f9f51e6449a8b661f54df0ac213f18639" +dependencies = [ + "alloy-consensus", + "alloy-network", + "alloy-primitives", + "alloy-signer", + "async-trait", + "k256", + "rand", + "thiserror", +] + [[package]] name = "alloy-sol-macro" version = "0.6.4" @@ -360,7 +386,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.57", "syn-solidity 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", "tiny-keccak", ] @@ -377,7 +403,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.57", "syn-solidity 0.6.4 (git+https://github.com/alloy-rs/core?rev=525a233)", "tiny-keccak", ] @@ -392,7 +418,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.57", "syn-solidity 0.6.4 (git+https://github.com/alloy-rs/core?rev=525a233)", ] @@ -525,9 +551,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.80" +version = "1.0.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ad32ce52e4161730f7098c077cd2ed6229b5804ccf99e5366be1ab72a98b4e1" +checksum = "0952808a6c2afd1aa8947271f3a60f1a6763c7b912d210184c5149b5cf147247" [[package]] name = "ark-ff" @@ -706,9 +732,9 @@ dependencies = [ [[package]] name = "async-io" -version = "2.3.1" +version = "2.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f97ab0c5b00a7cdbe5a371b9a782ee7be1316095885c8a4ea1daf490eb0ef65" +checksum = "dcccb0f599cfa2f8ace422d3555572f47424da5648a4382a9dd0310ff8210884" dependencies = [ "async-lock", "cfg-if", @@ -753,18 +779,18 @@ checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.57", ] [[package]] name = "async-trait" -version = "0.1.77" +version = "0.1.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c980ee35e870bd1a4d2c8294d4c04d0499e67bca1e4b5cefcc693c2fa00caea9" +checksum = "a507401cad91ec6a857ed5513a2073c82a9b9048762b885bb98655b306964681" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.57", ] [[package]] @@ -819,20 +845,20 @@ checksum = "3c87f3f15e7794432337fc718554eaa4dc8f04c9677a950ffe366f20a162ae42" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.57", ] [[package]] name = "autocfg" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80" [[package]] name = "backtrace" -version = "0.3.69" +version = "0.3.71" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" +checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" dependencies = [ "addr2line", "cc", @@ -902,9 +928,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.4.2" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf" +checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" dependencies = [ "serde", ] @@ -953,18 +979,18 @@ dependencies = [ [[package]] name = "bs58" -version = "0.5.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5353f36341f7451062466f0b755b96ac3a9547e4d7f6b70d603fc721a7d7896" +checksum = "bf88ba1141d185c399bee5288d850d63b8369520c1eafc32a0430b5b6c287bf4" dependencies = [ "tinyvec", ] [[package]] name = "bumpalo" -version = "3.15.3" +version = "3.15.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ea184aa71bb362a1157c896979544cc23974e08fd265f29ea96b59f0b4a555b" +checksum = "7ff69b9dd49fd426c69a0db9fc04dd934cdb6645ff000864d98f7e2af8830eaa" [[package]] name = "byte-slice-cast" @@ -980,9 +1006,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.5.0" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" +checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" dependencies = [ "serde", ] @@ -1003,9 +1029,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.89" +version = "1.0.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0ba8f7aaa012f30d5b2861462f6708eccd49c3c39863fe083a308035f63d723" +checksum = "8cd6604a82acf3039f1144f54b8eb34e91ffba622051189e71b781822d5ee1f5" [[package]] name = "cfg-if" @@ -1050,9 +1076,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.2" +version = "4.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b230ab84b0ffdf890d5a10abdbc8b83ae1c4918275daea1ab8801f71536b2651" +checksum = "90bc066a67923782aa8515dbaea16946c5bcc5addbd668bb80af688e53e548a0" dependencies = [ "clap_builder", "clap_derive", @@ -1072,14 +1098,14 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.0" +version = "4.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "307bc0538d5f0f83b8248db3087aa92fe504e4691294d0c96c0eabc33f47ba47" +checksum = "528131438037fd55894f62d6e9f068b8f45ac57ffa77517819645d10aed04f64" dependencies = [ - "heck 0.4.1", + "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.57", ] [[package]] @@ -1115,9 +1141,9 @@ dependencies = [ [[package]] name = "const-hex" -version = "1.11.1" +version = "1.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efbd12d49ab0eaf8193ba9175e45f56bbc2e4b27d57b8cfe62aa47942a46b9a9" +checksum = "5ba00838774b4ab0233e355d26710fbfc8327a05c017f6dc4873f876d1f79f78" dependencies = [ "cfg-if", "cpufeatures", @@ -1265,7 +1291,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.57", ] [[package]] @@ -1309,9 +1335,9 @@ dependencies = [ [[package]] name = "der" -version = "0.7.8" +version = "0.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fffa369a668c8af7dbf8b5e56c9f744fbd399949ed171606040001947de40b1c" +checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0" dependencies = [ "const-oid", "pem-rfc7468", @@ -1394,7 +1420,7 @@ checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.57", ] [[package]] @@ -1491,7 +1517,7 @@ dependencies = [ "heck 0.4.1", "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.57", ] [[package]] @@ -1580,9 +1606,9 @@ dependencies = [ [[package]] name = "fastrand" -version = "2.0.1" +version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" +checksum = "658bd65b1cf4c852a3cc96f18a8ce7b5640f6b703f905c7d74532294c2a63984" [[package]] name = "fastrlp" @@ -1607,9 +1633,9 @@ dependencies = [ [[package]] name = "fiat-crypto" -version = "0.2.6" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1676f435fc1dadde4d03e43f5d62b259e1ce5f40bd4ffb21db2b42ebe59c1382" +checksum = "c007b1ae3abe1cb6f85a16305acd418b7ca6343b953633fee2b76d8f108b830f" [[package]] name = "finl_unicode" @@ -1748,9 +1774,9 @@ checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" [[package]] name = "futures-lite" -version = "2.2.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "445ba825b27408685aaecefd65178908c36c6e96aaf6d8599419d46e624192ba" +checksum = "52527eb5074e35e9339c6b4e8d12600c7128b68fb25dcb9fa9dec18f7c25f3a5" dependencies = [ "futures-core", "pin-project-lite", @@ -1764,7 +1790,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.57", ] [[package]] @@ -1854,9 +1880,9 @@ dependencies = [ [[package]] name = "ghash" -version = "0.5.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d930750de5717d2dd0b8c0d42c076c0e884c81a73e6cab859bbd2339c71e3e40" +checksum = "f0d8a4362ccb29cb0b265253fb0a2728f592895ee6854fd9bc13f2ffda266ff1" dependencies = [ "opaque-debug", "polyval", @@ -1887,9 +1913,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.3.24" +version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb2c4422095b67ee78da96fbb51a4cc413b3b25883c7717ff7ca1ab31022c9c9" +checksum = "4fbd2820c5e49886948654ab546d0688ff24530286bdcf8fca3cefb16d4618eb" dependencies = [ "bytes", "fnv", @@ -2292,9 +2318,9 @@ checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683" [[package]] name = "indexmap" -version = "2.2.5" +version = "2.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b0b929d511467233429c45a44ac1dcaa21ba0f5ba11e4879e6ed28ddb4f9df4" +checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" dependencies = [ "equivalent", "hashbrown", @@ -2356,9 +2382,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.10" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] name = "js-sys" @@ -2712,7 +2738,7 @@ dependencies = [ "heck 0.4.1", "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.57", ] [[package]] @@ -2866,9 +2892,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.7.1" +version = "2.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" +checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" [[package]] name = "mime" @@ -2896,19 +2922,26 @@ name = "mintpool" version = "0.1.0" dependencies = [ "alloy", + "alloy-core 0.6.4 (git+https://github.com/alloy-rs/core?rev=525a233)", "alloy-primitives", "alloy-provider", "alloy-rpc-client", + "alloy-signer", + "alloy-signer-wallet", + "alloy-sol-macro 0.6.4 (git+https://github.com/alloy-rs/core?rev=525a233)", "alloy-sol-types 0.6.4 (git+https://github.com/alloy-rs/core?rev=525a233)", "async-trait", "clap", "colored", + "const-hex", "envconfig", "eyre", + "futures", "futures-util", "libp2p", "once_cell", "rand", + "runit", "serde", "serde_json", "sqlx", @@ -3203,9 +3236,9 @@ checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" [[package]] name = "opaque-debug" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" +checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" [[package]] name = "openssl" @@ -3213,7 +3246,7 @@ version = "0.10.64" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95a0481286a310808298130d22dd1fef0fa571e05a8f44ec801801e84b216b1f" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.5.0", "cfg-if", "foreign-types", "libc", @@ -3230,7 +3263,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.57", ] [[package]] @@ -3241,9 +3274,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-sys" -version = "0.9.101" +version = "0.9.102" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dda2b0f344e78efc2facf7d195d098df0dd72151b26ab98da807afc26c198dff" +checksum = "c597637d56fbc83893a35eb0dd04b2b8e7a50c91e64e9493e398b5df4fb45fa2" dependencies = [ "cc", "libc", @@ -3345,9 +3378,9 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "pest" -version = "2.7.8" +version = "2.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56f8023d0fb78c8e03784ea1c7f3fa36e68a723138990b8d5a47d916b651e7a8" +checksum = "311fb059dee1a7b802f036316d790138c613a4e8b180c822e3925a662e9f0c95" dependencies = [ "memchr", "thiserror", @@ -3381,14 +3414,14 @@ checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.57", ] [[package]] name = "pin-project-lite" -version = "0.2.13" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" [[package]] name = "pin-utils" @@ -3425,18 +3458,19 @@ checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" [[package]] name = "platforms" -version = "3.3.0" +version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "626dec3cac7cc0e1577a2ec3fc496277ec2baa084bebad95bb6fdbfae235f84c" +checksum = "db23d408679286588f4d4644f965003d056e3dd5abcaaa938116871d7ce2fee7" [[package]] name = "polling" -version = "3.5.0" +version = "3.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24f040dee2588b4963afb4e420540439d126f73fdacf4a9c486a96d840bac3c9" +checksum = "e0c976a60b2d7e99d6f229e414670a9b85d13ac305cc6d1e9c134de58c5aaaf6" dependencies = [ "cfg-if", "concurrent-queue", + "hermit-abi", "pin-project-lite", "rustix", "tracing", @@ -3456,9 +3490,9 @@ dependencies = [ [[package]] name = "polyval" -version = "0.6.1" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d52cff9d1d4dee5fe6d03729099f4a310a41179e0a10dbf542039873f2e826fb" +checksum = "9d1fe60d06143b2430aa532c94cfe9e29783047f06c0d7fd359a9a51b729fa25" dependencies = [ "cfg-if", "cpufeatures", @@ -3491,10 +3525,11 @@ dependencies = [ [[package]] name = "proc-macro-crate" -version = "2.0.0" +version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e8366a6159044a37876a2b9817124296703c586a5c92e2c53751fa06d8d43e8" +checksum = "b00f26d3400549137f92511a46ac1cd8ce37cb5598a96d382381458b992a5d24" dependencies = [ + "toml_datetime", "toml_edit", ] @@ -3524,18 +3559,18 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.78" +version = "1.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae" +checksum = "e835ff2298f5721608eb1a980ecaee1aef2c132bf95ecc026a11b7bf3c01c02e" dependencies = [ "unicode-ident", ] [[package]] name = "prometheus-client" -version = "0.22.1" +version = "0.22.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f87c10af16e0af74010d2a123d202e8363c04db5acfa91d8747f64a8524da3a" +checksum = "c1ca959da22a332509f2a73ae9e5f23f9dcfc31fd3a54d71f159495bd5909baa" dependencies = [ "dtoa", "itoa", @@ -3551,7 +3586,7 @@ checksum = "440f724eba9f6996b75d63681b0a92b06947f1457076d503a4d2e2c8f56442b8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.57", ] [[package]] @@ -3562,13 +3597,13 @@ checksum = "31b476131c3c86cb68032fdc5cb6d5a1045e3e42d96b69fa599fd77701e1f5bf" dependencies = [ "bit-set", "bit-vec", - "bitflags 2.4.2", + "bitflags 2.5.0", "lazy_static", "num-traits", "rand", "rand_chacha", "rand_xorshift", - "regex-syntax 0.8.2", + "regex-syntax 0.8.3", "rusty-fork", "tempfile", "unarray", @@ -3727,14 +3762,14 @@ dependencies = [ [[package]] name = "regex" -version = "1.10.3" +version = "1.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b62dbe01f0b06f9d8dc7d49e05a0785f153b00b2c227856282f671e0318c9b15" +checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c" dependencies = [ "aho-corasick", "memchr", "regex-automata 0.4.6", - "regex-syntax 0.8.2", + "regex-syntax 0.8.3", ] [[package]] @@ -3754,7 +3789,7 @@ checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" dependencies = [ "aho-corasick", "memchr", - "regex-syntax 0.8.2", + "regex-syntax 0.8.3", ] [[package]] @@ -3765,9 +3800,9 @@ checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" [[package]] name = "regex-syntax" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" +checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" [[package]] name = "reqwest" @@ -3933,6 +3968,12 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f86854cf50259291520509879a5c294c3c9a4c334e9ff65071c51e42ef1e2343" +[[package]] +name = "runit" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41487335fdc938f8168a97527ff3c7f2d77fa9c6583004ae1ad7b1125219bc3a" + [[package]] name = "rustc-demangle" version = "0.1.23" @@ -3980,11 +4021,11 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.31" +version = "0.38.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ea3e1a662af26cd7a3ba09c0297a31af215563ecf42817c98df621387f4e949" +checksum = "65e04861e65f21776e67888bfbea442b3642beaa0138fdb1dd7a84a52dffdb89" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.5.0", "errno", "libc", "linux-raw-sys", @@ -4092,9 +4133,9 @@ dependencies = [ [[package]] name = "security-framework" -version = "2.9.2" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05b64fb303737d99b81884b2c63433e9ae28abebe5eb5045dcdd175dc2ecf4de" +checksum = "770452e37cad93e0a50d5abc3990d2bc351c36d0328f86cefec2f2fb206eaef6" dependencies = [ "bitflags 1.3.2", "core-foundation", @@ -4105,9 +4146,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.9.1" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e932934257d3b408ed8f30db49d85ea163bfe74961f017f405b025af298f0c7a" +checksum = "41f3cc463c0ef97e11c3461a9d3787412d30e8e7eb907c79180c4a57bf7c04ef" dependencies = [ "core-foundation-sys", "libc", @@ -4160,14 +4201,14 @@ checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.57", ] [[package]] name = "serde_json" -version = "1.0.114" +version = "1.0.115" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5f09b1bd632ef549eaa9f60a1f8de742bdbc698e6cee2095fc84dde5f549ae0" +checksum = "12dc5c46daa8e9fdf4f5e71b6cf9a53f2487da0e86e55808e2d35539666497dd" dependencies = [ "itoa", "ryu", @@ -4257,9 +4298,9 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.13.1" +version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" [[package]] name = "snow" @@ -4423,7 +4464,7 @@ checksum = "1ed31390216d20e538e447a7a9b959e06ed9fc51c37b514b46eb758016ecd418" dependencies = [ "atoi", "base64 0.21.7", - "bitflags 2.4.2", + "bitflags 2.5.0", "byteorder", "bytes", "crc", @@ -4465,7 +4506,7 @@ checksum = "7c824eb80b894f926f89a0b9da0c7f435d27cdd35b8c655b114e58223918577e" dependencies = [ "atoi", "base64 0.21.7", - "bitflags 2.4.2", + "bitflags 2.5.0", "byteorder", "crc", "dotenvy", @@ -4560,9 +4601,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.52" +version = "2.0.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b699d15b36d1f02c3e7c69f8ffef53de37aefae075d8488d4ba1a7788d574a07" +checksum = "11a6ae1e52eb25aab8f3fb9fca13be982a373b8f1157ca14b897a825ba4a2d35" dependencies = [ "proc-macro2", "quote", @@ -4578,7 +4619,7 @@ dependencies = [ "paste", "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.57", ] [[package]] @@ -4589,7 +4630,7 @@ dependencies = [ "paste", "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.57", ] [[package]] @@ -4651,22 +4692,22 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.57" +version = "1.0.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e45bcbe8ed29775f228095caf2cd67af7a4ccf756ebff23a306bf3e8b47b24b" +checksum = "03468839009160513471e86a034bb2c5c0e4baae3b43f79ffc55c4a5427b3297" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.57" +version = "1.0.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a953cb265bef375dae3de6663da4d3804eee9682ea80d8e2542529b73c531c81" +checksum = "c61f3ba182994efc43764a46c018c347bc492c79f024e705f46567b418f6d4f7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.57", ] [[package]] @@ -4745,9 +4786,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.36.0" +version = "1.37.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61285f6515fa018fb2d1e46eb21223fff441ee8db5d0f1435e8ab4f5cdb80931" +checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" dependencies = [ "backtrace", "bytes", @@ -4770,7 +4811,7 @@ checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.57", ] [[package]] @@ -4795,9 +4836,9 @@ dependencies = [ [[package]] name = "tokio-stream" -version = "0.1.14" +version = "0.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "397c988d37662c7dda6d2208364a706264bf3d6138b11d436cbac0ad38832842" +checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af" dependencies = [ "futures-core", "pin-project-lite", @@ -4836,15 +4877,15 @@ dependencies = [ [[package]] name = "toml_datetime" -version = "0.6.5" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1" +checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b" [[package]] name = "toml_edit" -version = "0.20.7" +version = "0.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70f427fce4d84c72b5b732388bf4a9f4531b53f74e2887e3ecb2481f68f66d81" +checksum = "396e4d48bbb2b7554c944bde63101b5ae446cff6ec4a24227428f15eb72ef338" dependencies = [ "indexmap", "toml_datetime", @@ -4899,7 +4940,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.57", ] [[package]] @@ -5174,7 +5215,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.57", "wasm-bindgen-shared", ] @@ -5208,7 +5249,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.57", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -5511,9 +5552,9 @@ dependencies = [ [[package]] name = "xml-rs" -version = "0.8.19" +version = "0.8.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fcb9cbac069e033553e8bb871be2fbdffcab578eb25bd0f7c508cedc6dcd75a" +checksum = "791978798f0597cfc70478424c2b4fdc2b7a8024aaff78497ef00f24ef674193" [[package]] name = "xmltree" @@ -5581,7 +5622,7 @@ checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.57", ] [[package]] @@ -5601,5 +5642,5 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.57", ] diff --git a/Cargo.toml b/Cargo.toml index 2792363..bfbb7db 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,6 +6,7 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +const-hex = "1.11.3" tracing = "0.1.40" tracing-subscriber = { version = "0.3.18", features = ["env-filter"] } libp2p = { version = "0.53.2", features = [ @@ -34,6 +35,7 @@ sqlx = { version = "0.7.4", features = [ ] } once_cell = "1.19.0" rand = "0.8.5" +runit = "0.1.0" futures-util = "0.3" alloy = { git = "https://github.com/alloy-rs/alloy", rev = "7e39c85f9f51e6449a8b661f54df0ac213f18639", features = [ @@ -43,6 +45,7 @@ alloy = { git = "https://github.com/alloy-rs/alloy", rev = "7e39c85f9f51e6449a8b "pubsub", ] } + alloy-rpc-client = { git = "https://github.com/alloy-rs/alloy", rev = "7e39c85f9f51e6449a8b661f54df0ac213f18639", features = [ "pubsub", "ws", @@ -50,9 +53,16 @@ alloy-rpc-client = { git = "https://github.com/alloy-rs/alloy", rev = "7e39c85f9 alloy-provider = { git = "https://github.com/alloy-rs/alloy", rev = "7e39c85f9f51e6449a8b661f54df0ac213f18639", features = [ "pubsub", ] } +alloy-signer = { git = "https://github.com/alloy-rs/alloy", rev = "7e39c85f9f51e6449a8b661f54df0ac213f18639", features = [ + "eip712", +]} +alloy-signer-wallet = {git = "https://github.com/alloy-rs/alloy", rev = "7e39c85f9f51e6449a8b661f54df0ac213f18639" } -alloy-sol-types = { git = "https://github.com/alloy-rs/core", rev = "525a233" } +alloy-core = { git = "https://github.com/alloy-rs/core", rev = "525a233" } +alloy-sol-types = { git = "https://github.com/alloy-rs/core", rev = "525a233" , features = ["eip712-serde"]} alloy-primitives = { git = "https://github.com/alloy-rs/core", rev = "525a233", features = ["serde"] } +alloy-sol-macro = { git = "https://github.com/alloy-rs/core", rev = "525a233" } +futures = "0.3.30" [patch.crates-io] diff --git a/src/lib.rs b/src/lib.rs index 8a1d769..b2b6f73 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -3,6 +3,7 @@ pub mod config; pub mod controller; pub mod p2p; pub mod premints; +pub mod rules; pub mod run; pub mod stdin; pub mod storage; diff --git a/src/premints/metadata.rs b/src/premints/metadata.rs new file mode 100644 index 0000000..184f8a1 --- /dev/null +++ b/src/premints/metadata.rs @@ -0,0 +1,23 @@ +use serde::{Deserialize, Serialize}; +use serde_json::{Map, Value}; + +#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] +pub struct ERC721Metadata { + pub name: String, + pub description: String, + pub image: String, +} + +#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] +pub struct ERC1155Metadata { + pub name: String, + pub description: String, + pub image: String, + pub decimals: u64, + pub properties: Map, +} + +enum TokenMetadata { + ERC721(ERC721Metadata), + ERC1155(ERC1155Metadata), +} diff --git a/src/premints/mod.rs b/src/premints/mod.rs index dd00f29..c81cfb0 100644 --- a/src/premints/mod.rs +++ b/src/premints/mod.rs @@ -1 +1,2 @@ -pub mod zora_v2; +pub mod metadata; +pub mod zora_premint_v2; diff --git a/src/premints/zora_premint_v2/mod.rs b/src/premints/zora_premint_v2/mod.rs new file mode 100644 index 0000000..5726682 --- /dev/null +++ b/src/premints/zora_premint_v2/mod.rs @@ -0,0 +1,2 @@ +pub mod rules; +pub mod types; diff --git a/src/premints/zora_premint_v2/rules.rs b/src/premints/zora_premint_v2/rules.rs new file mode 100644 index 0000000..cd6d07c --- /dev/null +++ b/src/premints/zora_premint_v2/rules.rs @@ -0,0 +1,83 @@ +use std::str::FromStr; + +use alloy_primitives::Signature; +use alloy_sol_types::SolStruct; + +use crate::premints::zora_premint_v2::types::ZoraPremintV2; +use crate::rules::RuleContext; +use crate::types::Premint; + +// create premint v2 rule implementations here + +// TODO: is there any rust sugar to make this more concise? +// as it stands, it's not defined as an async function, so can't use async stuff +pub async fn is_authorized_to_create_premint(premint: &T) -> eyre::Result { + // * if contract exists, check if the signer is the contract admin + // * if contract does not exist, check if the signer is the proposed contract admin + // * this logic exists as a function on the premint executor contract + Ok(true) +} + +// * signatureIsValid ( this can be performed entirely offline ) +// * check if the signature is valid +// * check if the signature is equal to the proposed contract admin + +pub async fn is_valid_signature( + premint: ZoraPremintV2, + context: RuleContext, +) -> eyre::Result { + // * if contract exists, check if the signer is the contract admin + // * if contract does not exist, check if the signer is the proposed contract admin + + let signature = Signature::from_str(premint.signature.as_str())?; + + let domain = premint.eip712_domain(); + let hash = premint.premint.eip712_signing_hash(&domain); + let signer = signature.recover_address_from_prehash(&hash)?; + + Ok(signer == premint.collection.contractAdmin) +} + +#[cfg(test)] +mod test { + use std::str::FromStr; + + use super::*; + + const PREMINT_JSON: &str = r#" +{ + "collection": { + "contractAdmin": "0xa771209423284bace9a24a06d166a11196724b53", + "contractURI": "ipfs://bafkreic4fnavhtymee7makmk7wp257nloh5y5ysc2fcwa5rpg6v6f3jhly", + "contractName": "Karate sketch" + }, + "premint": { + "tokenConfig": { + "tokenURI": "ipfs://bafkreier5h4a6btu24fsitbjdvpyak7moi6wkp33wlqmx2kfwgpq2lvx4y", + "maxSupply": 18446744073709551615, + "maxTokensPerAddress": 0, + "pricePerToken": 0, + "mintStart": 1702541688, + "mintDuration": 2592000, + "royaltyBPS": 500, + "fixedPriceMinter": "0x04e2516a2c207e84a1839755675dfd8ef6302f0a", + "payoutRecipient": "0xa771209423284bace9a24a06d166a11196724b53", + "createReferral": "0x0000000000000000000000000000000000000000" + }, + "uid": 2, + "version": 1, + "deleted": false + }, + "collectionAddress": "0x42e108d1ed954b0adbd53ea118ba7614622d10d0", + "chainId": 7777777, + "signature": "0x894405d100900e6823385ca881c91d5ca7137a326f0c7d27edfd2907d9669cea55626bbd807a36cea815eceeac6634f45cfec54d7157c35f496b999e7b9451de1c" +}"#; + + #[tokio::test] + async fn test_is_valid_signature() { + let premint: ZoraPremintV2 = serde_json::from_str(PREMINT_JSON).unwrap(); + assert!(is_valid_signature(premint, RuleContext {}) + .await + .expect("failed to check signature")); + } +} diff --git a/src/premints/zora_premint_v2/types.rs b/src/premints/zora_premint_v2/types.rs new file mode 100644 index 0000000..8acd2a0 --- /dev/null +++ b/src/premints/zora_premint_v2/types.rs @@ -0,0 +1,177 @@ +use std::borrow::Cow; + +use alloy::rpc::types::eth::{Filter, Log, Transaction}; +use alloy::sol_types::private::U256; +use alloy_primitives::{address, Address}; +use alloy_signer::Signer; +use alloy_signer_wallet::LocalWallet; +use alloy_sol_macro::sol; +use alloy_sol_types::{eip712_domain, Eip712Domain, SolEvent}; +use async_trait::async_trait; +use serde::{Deserialize, Serialize}; + +use crate::types::{InclusionClaim, Premint, PremintMetadata, PremintName}; + +sol! { + event PremintedV2( + address indexed contractAddress, + uint256 indexed tokenId, + bool indexed createdNewContract, + uint32 uid, + address minter, + uint256 quantityMinted + ); + + #[derive(Debug, Serialize, Deserialize, PartialEq, Default)] + struct ContractCreationConfig { + // Creator/admin of the created contract. Must match the account that signed the message + address contractAdmin; + // Metadata URI for the created contract + string contractURI; + // Name of the created contract + string contractName; + } + + #[derive(Debug, Serialize, Deserialize, PartialEq, Default)] + struct TokenCreationConfig { + // Metadata URI for the created token + string tokenURI; + // Max supply of the created token + uint256 maxSupply; + // Max tokens that can be minted for an address, 0 if unlimited + uint64 maxTokensPerAddress; + // Price per token in eth wei. 0 for a free mint. + uint96 pricePerToken; + // The start time of the mint, 0 for immediate. Prevents signatures from being used until the start time. + uint64 mintStart; + // The duration of the mint, starting from the first mint of this token. 0 for infinite + uint64 mintDuration; + // RoyaltyBPS for created tokens. The royalty amount in basis points for secondary sales. + uint32 royaltyBPS; + // This is the address that will be set on the `royaltyRecipient` for the created token on the 1155 contract, + // which is the address that receives creator rewards and secondary royalties for the token, + // and on the `fundsRecipient` on the ZoraCreatorFixedPriceSaleStrategy contract for the token, + // which is the address that receives paid mint funds for the token. + address payoutRecipient; + // Fixed price minter address + address fixedPriceMinter; + // create referral + address createReferral; + } + + #[derive(Debug, Serialize, Deserialize, PartialEq, Default)] + struct CreatorAttribution { + // The config for the token to be created + TokenCreationConfig tokenConfig; + // Unique id of the token, used to ensure that multiple signatures can't be used to create the same intended token. + // only one signature per token id, scoped to the contract hash can be executed. + uint32 uid; + // Version of this premint, scoped to the uid and contract. Not used for logic in the contract, but used externally to track the newest version + uint32 version; + // If executing this signature results in preventing any signature with this uid from being minted. + bool deleted; + } +} + +// renaming solidity type not implemented yet in alloy-sol-types, +// so we alias the generated type. +pub type ZoraPremintConfigV2 = CreatorAttribution; + +// modelled after the PremintRequest API type +#[derive(Debug, Serialize, Deserialize, Clone, Default, PartialEq)] +#[serde(rename_all = "camelCase")] +pub struct ZoraPremintV2 { + pub collection: ContractCreationConfig, + pub premint: ZoraPremintConfigV2, + pub collection_address: Address, + pub chain_id: U256, + pub signature: String, +} + +pub static PREMINT_FACTORY_ADDR: Address = address!("7777773606e7e46C8Ba8B98C08f5cD218e31d340"); + +impl ZoraPremintV2 { + pub fn eip712_domain(&self) -> Eip712Domain { + Eip712Domain { + name: Some(Cow::from("Preminter")), + version: Some(Cow::from("2")), + chain_id: Some(self.chain_id), + verifying_contract: Some(self.collection_address), + salt: None, + } + } +} + +#[async_trait] +impl Premint for ZoraPremintV2 { + fn metadata(&self) -> PremintMetadata { + PremintMetadata { + id: self.premint.uid.to_string(), + kind: Self::kind_id(), + signer: self.collection.contractAdmin, + chain_id: self.chain_id, + collection_address: Address::default(), // TODO: source this + token_id: U256::from(self.premint.uid), + uri: self.premint.tokenConfig.tokenURI.clone(), + } + } + + fn guid(&self) -> String { + format!( + "{:?}:{:?}:{:?}:{:?}", + self.chain_id, self.collection_address, self.premint.uid, self.premint.version + ) + } + + fn check_filter(chain_id: u64) -> Option { + let supported_chains = [7777777, 8423]; // TODO: add the rest here and enable testnet mode + if !supported_chains.contains(&chain_id) { + return None; + } + Some( + Filter::new() + .address(PREMINT_FACTORY_ADDR) + .event(PremintedV2::SIGNATURE), + ) + } + + fn map_claim(chain_id: u64, log: Log) -> eyre::Result { + let event = PremintedV2::decode_raw_log(&log.topics, &log.data, true)?; + + Ok(InclusionClaim { + premint_id: event.uid.to_string(), + chain_id, + tx_hash: log.transaction_hash.unwrap_or_default(), + log_index: log.log_index.unwrap_or(U256::from(0)).to(), + kind: "zora_premint_v2".to_string(), + }) + } + + async fn verify_claim(chain_id: u64, tx: Transaction, log: Log, claim: InclusionClaim) -> bool { + let event = PremintedV2::decode_raw_log(&log.topics, &log.data, true); + match event { + Ok(event) => { + let conditions = vec![ + log.address == PREMINT_FACTORY_ADDR, + log.transaction_hash.unwrap_or_default() == tx.hash, + claim.tx_hash == tx.hash, + claim.log_index == log.log_index.unwrap_or_default().to::(), + claim.premint_id == event.uid.to_string(), + claim.kind == *"zora_premint_v2", + claim.chain_id == chain_id, + ]; + + // confirm all conditions are true + conditions.into_iter().all(|x| x) + } + Err(e) => { + tracing::debug!("Failed to parse log: {}", e); + false + } + } + } + + fn kind_id() -> PremintName { + PremintName("zora_premint_v2".to_string()) + } +} diff --git a/src/premints/zora_v2.rs b/src/premints/zora_v2.rs deleted file mode 100644 index 64707a7..0000000 --- a/src/premints/zora_v2.rs +++ /dev/null @@ -1,134 +0,0 @@ -use alloy::{ - rpc::types::eth::{Filter, Log, Transaction}, - sol_types::sol, -}; - -use alloy_primitives::{address, Address, B256, U256}; -use alloy_sol_types::SolEvent; -use async_trait::async_trait; -use serde::{Deserialize, Serialize}; -use std::fmt::Debug; -// use alloy_sol_types::SolEvent; -use crate::types::{InclusionClaim, Premint, PremintMetadata, PremintName}; - -#[derive(Debug, Serialize, Deserialize, Clone, Default, PartialEq)] -#[serde(rename_all = "camelCase")] -pub struct PremintV2Message { - collection: PremintV2Collection, - premint: PremintV2, - chain_id: u64, - signature: String, -} - -sol!( - event PremintedV2( - address indexed contractAddress, - uint256 indexed tokenId, - bool indexed createdNewContract, - uint32 uid, - address minter, - uint256 quantityMinted - ); -); - -pub static PREMINT_FACTORY_ADDR: Address = address!("7777773606e7e46C8Ba8B98C08f5cD218e31d340"); - -#[async_trait] -impl Premint for PremintV2Message { - fn metadata(&self) -> PremintMetadata { - PremintMetadata { - id: self.premint.uid.to_string(), - kind: Self::kind_id(), - signer: self.collection.contract_admin, - chain_id: self.chain_id as i64, - collection_address: Address::default(), // TODO: source this - token_id: U256::from(self.premint.uid), - uri: self.premint.token_creation_config.token_uri.clone(), - } - } - - fn check_filter(chain_id: u64) -> Option { - let supported_chains = [7777777, 8423]; // TODO: add the rest here and enable testnet mode - if !supported_chains.contains(&chain_id) { - return None; - } - Some( - Filter::new() - .address(PREMINT_FACTORY_ADDR) - .event(PremintedV2::SIGNATURE), - ) - } - - fn map_claim(chain_id: u64, log: Log) -> eyre::Result { - let event = PremintedV2::decode_raw_log(&log.topics, &log.data, true)?; - - Ok(InclusionClaim { - premint_id: event.uid.to_string(), - chain_id, - tx_hash: log.transaction_hash.unwrap_or_default(), - log_index: log.log_index.unwrap_or(U256::from(0)).to(), - kind: "zora_premint_v2".to_string(), - }) - } - - async fn verify_claim(chain_id: u64, tx: Transaction, log: Log, claim: InclusionClaim) -> bool { - let event = PremintedV2::decode_raw_log(&log.topics, &log.data, true); - match event { - Ok(event) => { - let conditions = vec![ - log.address == PREMINT_FACTORY_ADDR, - log.transaction_hash.unwrap_or_default() == tx.hash, - claim.tx_hash == tx.hash, - claim.log_index == log.log_index.unwrap_or_default().to::(), - claim.premint_id == event.uid.to_string(), - claim.kind == *"zora_premint_v2", - claim.chain_id == chain_id, - ]; - - // confirm all conditions are true - conditions.into_iter().all(|x| x) - } - Err(e) => { - tracing::debug!("Failed to parse log: {}", e); - false - } - } - } - - fn kind_id() -> PremintName { - PremintName("zora_premint_v2".to_string()) - } -} - -#[derive(Debug, Serialize, Deserialize, Clone, Default, PartialEq)] -#[serde(rename_all = "camelCase")] -pub struct PremintV2Collection { - contract_admin: Address, - contract_uri: String, - contract_name: String, -} - -#[derive(Debug, Serialize, Deserialize, Clone, Default, PartialEq)] -#[serde(rename_all = "camelCase")] -pub struct PremintV2 { - token_creation_config: TokenCreationConfigV2, - uid: u64, - version: u64, - deleted: bool, -} - -#[derive(Debug, Serialize, Deserialize, Clone, Default, PartialEq)] -#[serde(rename_all = "camelCase")] -pub struct TokenCreationConfigV2 { - token_uri: String, - token_max_supply: U256, - mint_start: u64, - mint_duration: u64, - max_tokens_per_address: U256, - price_per_token: U256, - #[serde(rename = "royaltyBPS")] - royalty_bps: U256, - payout_recipient: Address, - fixed_price_minter: Address, - creator_referral: Address, -} diff --git a/src/rules.rs b/src/rules.rs new file mode 100644 index 0000000..9f5f475 --- /dev/null +++ b/src/rules.rs @@ -0,0 +1,140 @@ +use async_trait::async_trait; +use futures::future::join_all; + +use crate::types::{Premint, PremintTypes}; + +#[derive(Clone)] +pub struct RuleContext {} + +#[async_trait] +trait Rule: Send + Sync { + async fn check(&self, item: PremintTypes, context: RuleContext) -> eyre::Result; +} + +struct FnRule(pub T); + +#[async_trait] +impl Rule for FnRule +where + T: Fn(PremintTypes, RuleContext) -> Fut + Send + Sync + 'static, + Fut: std::future::Future> + Send, +{ + async fn check(&self, item: PremintTypes, context: RuleContext) -> eyre::Result { + self.0(item, context).await + } +} + +macro_rules! rule { + ($fn:tt) => { + FnRule($fn) + }; +} + +macro_rules! typed_rule { + ($t:path, $fn:tt) => { + crate::rules::FnRule( + |item: crate::types::PremintTypes, + context: crate::rules::RuleContext| + -> std::pin::Pin< + std::boxed::Box> + Send + Sync>, + > { + std::boxed::Box::pin(async { + match item { + $t(premint) => $fn(premint, context).await, + _ => Ok(true), + } + }) + }, + ) + }; +} + +struct RulesEngine { + rules: Vec>, +} + +impl RulesEngine { + pub fn new() -> Self { + RulesEngine { rules: vec![] } + } + pub fn add_rule(&mut self, rule: impl Rule + 'static) { + self.rules.push(Box::new(rule)); + } + + pub async fn evaluate(&self, item: PremintTypes, context: RuleContext) -> bool { + let results: Vec<_> = self + .rules + .iter() + .map(|rule| rule.check(item.clone(), context.clone())) + .collect(); + let all_checks = join_all(results).await; + + // TODO: handle errors + all_checks + .iter() + .all(|check| check.is_ok() && check.as_ref().unwrap().clone()) + } +} + +#[cfg(test)] +mod test { + use super::*; + use crate::types::SimplePremint; + use alloy_primitives::U256; + + async fn simple_rule(item: PremintTypes, context: RuleContext) -> eyre::Result { + Ok(true) + } + + async fn conditional_rule(item: PremintTypes, context: RuleContext) -> eyre::Result { + match item { + PremintTypes::Simple(s) => Ok(s.metadata().chain_id == U256::default()), + _ => Ok(true), + } + } + + async fn simple_typed_rule(item: SimplePremint, context: RuleContext) -> eyre::Result { + Ok(true) + } + + #[tokio::test] + async fn test_simple_rule() { + let context = RuleContext {}; + let rule = rule!(simple_rule); + let result = rule + .check(PremintTypes::Simple(Default::default()), context) + .await + .unwrap(); + assert!(result); + } + + #[tokio::test] + async fn test_simple_rules_engine() { + let mut re = RulesEngine::new(); + let context = RuleContext {}; + re.add_rule(rule!(simple_rule)); + re.add_rule(rule!(conditional_rule)); + + let result = re + .evaluate(PremintTypes::Simple(Default::default()), context) + .await; + + assert!(result); + } + + #[tokio::test] + async fn test_typed_rules_engine() { + let mut re = RulesEngine::new(); + let context = RuleContext {}; + + let rule = typed_rule!(PremintTypes::Simple, simple_typed_rule); + + re.add_rule(rule); + + let result = re + .evaluate(PremintTypes::Simple(Default::default()), context) + .await; + + assert!(result); + } +} diff --git a/src/stdin.rs b/src/stdin.rs index 36525f5..c441510 100644 --- a/src/stdin.rs +++ b/src/stdin.rs @@ -1,5 +1,5 @@ use crate::controller::{ControllerCommands, ControllerInterface, DBQuery}; -use crate::types::{Premint, PremintTypes}; +use crate::types::PremintTypes; use colored::Colorize; use tokio::io::AsyncBufReadExt; use tokio::{io, select}; diff --git a/src/storage.rs b/src/storage.rs index 9944c6c..2902ff2 100644 --- a/src/storage.rs +++ b/src/storage.rs @@ -53,15 +53,17 @@ impl PremintStorage { let signer = format!("{:?}", metadata.signer); let collection_address = format!("{:?}", metadata.collection_address); let token_id = metadata.token_id.to_string(); + let chain_id = metadata.chain_id.to::(); + let id = premint.guid(); sqlx::query!( r#" INSERT INTO premints (id, kind, signer, chain_id, collection_address, token_id, json) VALUES (?, ?, ?, ?, ?, ?, ?) "#, - metadata.id, + id, metadata.kind.0, signer, - metadata.chain_id, + chain_id, collection_address, token_id, json @@ -128,10 +130,10 @@ mod test { }; let store = PremintStorage::new(&config).await; - let premint = PremintTypes::V2(Default::default()); + let premint = PremintTypes::ZoraV2(Default::default()); store.store(premint.clone()).await.unwrap(); - let retrieved = store.get_for_id(premint.metadata().id).await.unwrap(); + let retrieved = store.get_for_id(premint.guid()).await.unwrap(); assert_eq!(premint, retrieved); } @@ -153,7 +155,7 @@ mod test { let store = PremintStorage::new(&config).await; - let premint_v2 = PremintTypes::V2(Default::default()); + let premint_v2 = PremintTypes::ZoraV2(Default::default()); store.store(premint_v2.clone()).await.unwrap(); let premint_simple = PremintTypes::Simple(Default::default()); store.store(premint_simple.clone()).await.unwrap(); diff --git a/src/types.rs b/src/types.rs index f55039c..c23bb18 100644 --- a/src/types.rs +++ b/src/types.rs @@ -1,3 +1,4 @@ +use crate::premints::zora_premint_v2::types::ZoraPremintV2; use alloy::rpc::types::eth::{Filter, Log, Transaction}; use alloy_primitives::{Address, B256, U256}; use async_trait::async_trait; @@ -6,7 +7,7 @@ use serde::de::DeserializeOwned; use serde::{Deserialize, Serialize}; use std::fmt::Debug; -use crate::premints::zora_v2::PremintV2Message; +// use crate::rules::RulesEngine; #[derive(Debug)] pub struct PremintName(pub String); @@ -28,7 +29,7 @@ pub struct PremintMetadata { pub id: String, pub kind: PremintName, pub signer: Address, - pub chain_id: i64, + pub chain_id: U256, pub collection_address: Address, pub token_id: U256, pub uri: String, @@ -38,6 +39,12 @@ pub struct PremintMetadata { pub trait Premint: Serialize + DeserializeOwned + Debug + Clone { fn metadata(&self) -> PremintMetadata; + fn guid(&self) -> String; + + // async fn validate(&self, engine: RulesEngine) -> bool { + // engine.validate(self).await + // } + fn check_filter(chain_id: u64) -> Option; fn map_claim(chain_id: u64, log: Log) -> eyre::Result; async fn verify_claim(chain_id: u64, tx: Transaction, log: Log, claim: InclusionClaim) -> bool; @@ -48,7 +55,7 @@ pub trait Premint: Serialize + DeserializeOwned + Debug + Clone { #[serde(rename_all = "camelCase")] pub enum PremintTypes { Simple(SimplePremint), - V2(PremintV2Message), + ZoraV2(ZoraPremintV2), } impl PremintTypes { @@ -67,14 +74,21 @@ impl PremintTypes { pub fn metadata(&self) -> PremintMetadata { match self { PremintTypes::Simple(p) => p.metadata(), - PremintTypes::V2(p) => p.metadata(), + PremintTypes::ZoraV2(p) => p.metadata(), + } + } + + pub fn guid(&self) -> String { + match self { + PremintTypes::Simple(p) => p.guid(), + PremintTypes::ZoraV2(p) => p.guid(), } } } #[derive(Debug, Serialize, Deserialize, Clone, Default, PartialEq)] pub struct SimplePremint { - chain_id: u64, + chain_id: U256, sender: Address, token_id: u64, media: String, @@ -87,13 +101,18 @@ impl Premint for SimplePremint { id: format!("{:?}:{:?}:{:?}", self.chain_id, self.sender, self.token_id), kind: Self::kind_id(), signer: self.sender, - chain_id: self.chain_id as i64, + chain_id: self.chain_id, collection_address: Address::default(), token_id: U256::from(self.token_id), uri: self.media.clone(), } } + fn guid(&self) -> String { + // TODO: make something slightly more unique + format!("{:?}:{:?}:{:?}", self.chain_id, self.sender, self.token_id) + } + fn check_filter(chain_id: u64) -> Option { todo!() } @@ -123,14 +142,14 @@ pub struct InclusionClaim { #[cfg(test)] mod test { use super::*; - use crate::premints::zora_v2::PREMINT_FACTORY_ADDR; + use crate::premints::zora_premint_v2::types::{ZoraPremintConfigV2, PREMINT_FACTORY_ADDR}; use alloy_primitives::Bytes; use std::str::FromStr; #[test] fn test_premint_serde() { let premint = PremintTypes::Simple(SimplePremint { - chain_id: 1, + chain_id: U256::from(1), sender: "0x66f9664f97F2b50F62D13eA064982f936dE76657" .parse() .unwrap(), @@ -143,7 +162,7 @@ mod test { let premint = PremintTypes::from_json(json).unwrap(); println!("{:?}", premint); - let premint = PremintTypes::V2(PremintV2Message::default()); + let premint = PremintTypes::ZoraV2(ZoraPremintV2::default()); let json = premint.to_json().unwrap(); println!("{}", json); let premint: PremintTypes = PremintTypes::from_json(json).unwrap(); @@ -175,7 +194,7 @@ mod test { removed: false, }; - let claim = PremintV2Message::map_claim(7777777, log.clone()).unwrap(); + let claim = ZoraPremintV2::map_claim(7777777, log.clone()).unwrap(); let expected = InclusionClaim { premint_id: "1".to_string(), chain_id: 7777777, @@ -228,7 +247,7 @@ mod test { ..Default::default() }; - let claim = PremintV2Message::map_claim(7777777, log.clone()).unwrap(); - assert!(PremintV2Message::verify_claim(7777777, tx.clone(), log.clone(), claim).await); + let claim = ZoraPremintV2::map_claim(7777777, log.clone()).unwrap(); + assert!(ZoraPremintV2::verify_claim(7777777, tx.clone(), log.clone(), claim).await); } } diff --git a/tests/p2p_test.rs b/tests/p2p_test.rs index c7188af..1c4533e 100644 --- a/tests/p2p_test.rs +++ b/tests/p2p_test.rs @@ -53,7 +53,7 @@ async fn test_list_all_premints() { first .send_command(Broadcast { - message: PremintTypes::V2(Default::default()), + message: PremintTypes::ZoraV2(Default::default()), }) .await .unwrap();