diff --git a/Cargo.Bazel.lock b/Cargo.Bazel.lock index 3f5916a8..51cb1945 100644 --- a/Cargo.Bazel.lock +++ b/Cargo.Bazel.lock @@ -2483,7 +2483,7 @@ dependencies = [ [[package]] name = "many-client" version = "0.1.0" -source = "git+https://github.com/liftedinit/many-rs.git?rev=71eba1a1cfee506505acec865f5984afab0d3e74#71eba1a1cfee506505acec865f5984afab0d3e74" +source = "git+https://github.com/liftedinit/many-rs.git?rev=ce03b88dea51232ca578d19d52cfc263cfc4080b#ce03b88dea51232ca578d19d52cfc263cfc4080b" dependencies = [ "anyhow", "async-trait", @@ -2526,7 +2526,7 @@ dependencies = [ [[package]] name = "many-client-macros" version = "0.1.0" -source = "git+https://github.com/liftedinit/many-rs.git?rev=71eba1a1cfee506505acec865f5984afab0d3e74#71eba1a1cfee506505acec865f5984afab0d3e74" +source = "git+https://github.com/liftedinit/many-rs.git?rev=ce03b88dea51232ca578d19d52cfc263cfc4080b#ce03b88dea51232ca578d19d52cfc263cfc4080b" dependencies = [ "proc-macro2", "quote", @@ -2536,7 +2536,7 @@ dependencies = [ [[package]] name = "many-error" version = "0.1.0" -source = "git+https://github.com/liftedinit/many-rs.git?rev=71eba1a1cfee506505acec865f5984afab0d3e74#71eba1a1cfee506505acec865f5984afab0d3e74" +source = "git+https://github.com/liftedinit/many-rs.git?rev=ce03b88dea51232ca578d19d52cfc263cfc4080b#ce03b88dea51232ca578d19d52cfc263cfc4080b" dependencies = [ "minicbor", "num-derive", @@ -2547,7 +2547,7 @@ dependencies = [ [[package]] name = "many-identity" version = "0.1.0" -source = "git+https://github.com/liftedinit/many-rs.git?rev=71eba1a1cfee506505acec865f5984afab0d3e74#71eba1a1cfee506505acec865f5984afab0d3e74" +source = "git+https://github.com/liftedinit/many-rs.git?rev=ce03b88dea51232ca578d19d52cfc263cfc4080b#ce03b88dea51232ca578d19d52cfc263cfc4080b" dependencies = [ "base32", "coset", @@ -2567,7 +2567,7 @@ dependencies = [ [[package]] name = "many-identity-dsa" version = "0.1.0" -source = "git+https://github.com/liftedinit/many-rs.git?rev=71eba1a1cfee506505acec865f5984afab0d3e74#71eba1a1cfee506505acec865f5984afab0d3e74" +source = "git+https://github.com/liftedinit/many-rs.git?rev=ce03b88dea51232ca578d19d52cfc263cfc4080b#ce03b88dea51232ca578d19d52cfc263cfc4080b" dependencies = [ "asn1 0.8.7", "base32", @@ -2595,7 +2595,7 @@ dependencies = [ [[package]] name = "many-identity-hsm" version = "0.1.0" -source = "git+https://github.com/liftedinit/many-rs.git?rev=71eba1a1cfee506505acec865f5984afab0d3e74#71eba1a1cfee506505acec865f5984afab0d3e74" +source = "git+https://github.com/liftedinit/many-rs.git?rev=ce03b88dea51232ca578d19d52cfc263cfc4080b#ce03b88dea51232ca578d19d52cfc263cfc4080b" dependencies = [ "asn1 0.10.0", "coset", @@ -2615,7 +2615,7 @@ dependencies = [ [[package]] name = "many-identity-webauthn" version = "0.1.0" -source = "git+https://github.com/liftedinit/many-rs.git?rev=71eba1a1cfee506505acec865f5984afab0d3e74#71eba1a1cfee506505acec865f5984afab0d3e74" +source = "git+https://github.com/liftedinit/many-rs.git?rev=ce03b88dea51232ca578d19d52cfc263cfc4080b#ce03b88dea51232ca578d19d52cfc263cfc4080b" dependencies = [ "authenticator-ctap2-2021", "base64 0.13.1", @@ -2765,7 +2765,7 @@ dependencies = [ [[package]] name = "many-macros" version = "0.1.0" -source = "git+https://github.com/liftedinit/many-rs.git?rev=71eba1a1cfee506505acec865f5984afab0d3e74#71eba1a1cfee506505acec865f5984afab0d3e74" +source = "git+https://github.com/liftedinit/many-rs.git?rev=ce03b88dea51232ca578d19d52cfc263cfc4080b#ce03b88dea51232ca578d19d52cfc263cfc4080b" dependencies = [ "inflections", "proc-macro2", @@ -2778,7 +2778,7 @@ dependencies = [ [[package]] name = "many-migration" version = "0.1.0" -source = "git+https://github.com/liftedinit/many-rs.git?rev=71eba1a1cfee506505acec865f5984afab0d3e74#71eba1a1cfee506505acec865f5984afab0d3e74" +source = "git+https://github.com/liftedinit/many-rs.git?rev=ce03b88dea51232ca578d19d52cfc263cfc4080b#ce03b88dea51232ca578d19d52cfc263cfc4080b" dependencies = [ "many-error", "minicbor", @@ -2791,7 +2791,7 @@ dependencies = [ [[package]] name = "many-modules" version = "0.1.0" -source = "git+https://github.com/liftedinit/many-rs.git?rev=71eba1a1cfee506505acec865f5984afab0d3e74#71eba1a1cfee506505acec865f5984afab0d3e74" +source = "git+https://github.com/liftedinit/many-rs.git?rev=ce03b88dea51232ca578d19d52cfc263cfc4080b#ce03b88dea51232ca578d19d52cfc263cfc4080b" dependencies = [ "async-trait", "coset", @@ -2812,7 +2812,7 @@ dependencies = [ [[package]] name = "many-protocol" version = "0.1.0" -source = "git+https://github.com/liftedinit/many-rs.git?rev=71eba1a1cfee506505acec865f5984afab0d3e74#71eba1a1cfee506505acec865f5984afab0d3e74" +source = "git+https://github.com/liftedinit/many-rs.git?rev=ce03b88dea51232ca578d19d52cfc263cfc4080b#ce03b88dea51232ca578d19d52cfc263cfc4080b" dependencies = [ "base64 0.13.1", "coset", @@ -2836,7 +2836,7 @@ dependencies = [ [[package]] name = "many-server" version = "0.1.0" -source = "git+https://github.com/liftedinit/many-rs.git?rev=71eba1a1cfee506505acec865f5984afab0d3e74#71eba1a1cfee506505acec865f5984afab0d3e74" +source = "git+https://github.com/liftedinit/many-rs.git?rev=ce03b88dea51232ca578d19d52cfc263cfc4080b#ce03b88dea51232ca578d19d52cfc263cfc4080b" dependencies = [ "anyhow", "asn1 0.11.0", @@ -2885,7 +2885,7 @@ dependencies = [ [[package]] name = "many-types" version = "0.1.0" -source = "git+https://github.com/liftedinit/many-rs.git?rev=71eba1a1cfee506505acec865f5984afab0d3e74#71eba1a1cfee506505acec865f5984afab0d3e74" +source = "git+https://github.com/liftedinit/many-rs.git?rev=ce03b88dea51232ca578d19d52cfc263cfc4080b#ce03b88dea51232ca578d19d52cfc263cfc4080b" dependencies = [ "base64 0.20.0", "coset", diff --git a/Cargo.lock b/Cargo.lock index 2e8df19c..6a0ac3f5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -671,9 +671,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.1.2" +version = "4.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e638668a62aced2c9fb72b5135a33b4a500485ccf2a0e402e09aa04ab2fc115" +checksum = "d8d93d855ce6a0aa87b8473ef9169482f40abaa2e9e0993024c35c902cbd5920" dependencies = [ "bitflags", "clap_derive 4.1.0", @@ -975,7 +975,7 @@ dependencies = [ "anyhow", "async-trait", "atty", - "clap 4.1.2", + "clap 4.1.3", "console", "cucumber-codegen", "cucumber-expressions", @@ -2483,7 +2483,7 @@ dependencies = [ [[package]] name = "many-client" version = "0.1.0" -source = "git+https://github.com/liftedinit/many-rs.git?rev=71eba1a1cfee506505acec865f5984afab0d3e74#71eba1a1cfee506505acec865f5984afab0d3e74" +source = "git+https://github.com/liftedinit/many-rs.git?rev=ce03b88dea51232ca578d19d52cfc263cfc4080b#ce03b88dea51232ca578d19d52cfc263cfc4080b" dependencies = [ "anyhow", "async-trait", @@ -2526,7 +2526,7 @@ dependencies = [ [[package]] name = "many-client-macros" version = "0.1.0" -source = "git+https://github.com/liftedinit/many-rs.git?rev=71eba1a1cfee506505acec865f5984afab0d3e74#71eba1a1cfee506505acec865f5984afab0d3e74" +source = "git+https://github.com/liftedinit/many-rs.git?rev=ce03b88dea51232ca578d19d52cfc263cfc4080b#ce03b88dea51232ca578d19d52cfc263cfc4080b" dependencies = [ "proc-macro2", "quote", @@ -2536,7 +2536,7 @@ dependencies = [ [[package]] name = "many-error" version = "0.1.0" -source = "git+https://github.com/liftedinit/many-rs.git?rev=71eba1a1cfee506505acec865f5984afab0d3e74#71eba1a1cfee506505acec865f5984afab0d3e74" +source = "git+https://github.com/liftedinit/many-rs.git?rev=ce03b88dea51232ca578d19d52cfc263cfc4080b#ce03b88dea51232ca578d19d52cfc263cfc4080b" dependencies = [ "minicbor", "num-derive", @@ -2547,7 +2547,7 @@ dependencies = [ [[package]] name = "many-identity" version = "0.1.0" -source = "git+https://github.com/liftedinit/many-rs.git?rev=71eba1a1cfee506505acec865f5984afab0d3e74#71eba1a1cfee506505acec865f5984afab0d3e74" +source = "git+https://github.com/liftedinit/many-rs.git?rev=ce03b88dea51232ca578d19d52cfc263cfc4080b#ce03b88dea51232ca578d19d52cfc263cfc4080b" dependencies = [ "base32", "coset", @@ -2567,7 +2567,7 @@ dependencies = [ [[package]] name = "many-identity-dsa" version = "0.1.0" -source = "git+https://github.com/liftedinit/many-rs.git?rev=71eba1a1cfee506505acec865f5984afab0d3e74#71eba1a1cfee506505acec865f5984afab0d3e74" +source = "git+https://github.com/liftedinit/many-rs.git?rev=ce03b88dea51232ca578d19d52cfc263cfc4080b#ce03b88dea51232ca578d19d52cfc263cfc4080b" dependencies = [ "asn1 0.8.7", "base32", @@ -2595,7 +2595,7 @@ dependencies = [ [[package]] name = "many-identity-hsm" version = "0.1.0" -source = "git+https://github.com/liftedinit/many-rs.git?rev=71eba1a1cfee506505acec865f5984afab0d3e74#71eba1a1cfee506505acec865f5984afab0d3e74" +source = "git+https://github.com/liftedinit/many-rs.git?rev=ce03b88dea51232ca578d19d52cfc263cfc4080b#ce03b88dea51232ca578d19d52cfc263cfc4080b" dependencies = [ "asn1 0.10.0", "coset", @@ -2615,7 +2615,7 @@ dependencies = [ [[package]] name = "many-identity-webauthn" version = "0.1.0" -source = "git+https://github.com/liftedinit/many-rs.git?rev=71eba1a1cfee506505acec865f5984afab0d3e74#71eba1a1cfee506505acec865f5984afab0d3e74" +source = "git+https://github.com/liftedinit/many-rs.git?rev=ce03b88dea51232ca578d19d52cfc263cfc4080b#ce03b88dea51232ca578d19d52cfc263cfc4080b" dependencies = [ "authenticator-ctap2-2021", "base64 0.13.1", @@ -2765,7 +2765,7 @@ dependencies = [ [[package]] name = "many-macros" version = "0.1.0" -source = "git+https://github.com/liftedinit/many-rs.git?rev=71eba1a1cfee506505acec865f5984afab0d3e74#71eba1a1cfee506505acec865f5984afab0d3e74" +source = "git+https://github.com/liftedinit/many-rs.git?rev=ce03b88dea51232ca578d19d52cfc263cfc4080b#ce03b88dea51232ca578d19d52cfc263cfc4080b" dependencies = [ "inflections", "proc-macro2", @@ -2778,7 +2778,7 @@ dependencies = [ [[package]] name = "many-migration" version = "0.1.0" -source = "git+https://github.com/liftedinit/many-rs.git?rev=71eba1a1cfee506505acec865f5984afab0d3e74#71eba1a1cfee506505acec865f5984afab0d3e74" +source = "git+https://github.com/liftedinit/many-rs.git?rev=ce03b88dea51232ca578d19d52cfc263cfc4080b#ce03b88dea51232ca578d19d52cfc263cfc4080b" dependencies = [ "many-error", "minicbor", @@ -2791,7 +2791,7 @@ dependencies = [ [[package]] name = "many-modules" version = "0.1.0" -source = "git+https://github.com/liftedinit/many-rs.git?rev=71eba1a1cfee506505acec865f5984afab0d3e74#71eba1a1cfee506505acec865f5984afab0d3e74" +source = "git+https://github.com/liftedinit/many-rs.git?rev=ce03b88dea51232ca578d19d52cfc263cfc4080b#ce03b88dea51232ca578d19d52cfc263cfc4080b" dependencies = [ "async-trait", "coset", @@ -2812,7 +2812,7 @@ dependencies = [ [[package]] name = "many-protocol" version = "0.1.0" -source = "git+https://github.com/liftedinit/many-rs.git?rev=71eba1a1cfee506505acec865f5984afab0d3e74#71eba1a1cfee506505acec865f5984afab0d3e74" +source = "git+https://github.com/liftedinit/many-rs.git?rev=ce03b88dea51232ca578d19d52cfc263cfc4080b#ce03b88dea51232ca578d19d52cfc263cfc4080b" dependencies = [ "base64 0.13.1", "coset", @@ -2836,7 +2836,7 @@ dependencies = [ [[package]] name = "many-server" version = "0.1.0" -source = "git+https://github.com/liftedinit/many-rs.git?rev=71eba1a1cfee506505acec865f5984afab0d3e74#71eba1a1cfee506505acec865f5984afab0d3e74" +source = "git+https://github.com/liftedinit/many-rs.git?rev=ce03b88dea51232ca578d19d52cfc263cfc4080b#ce03b88dea51232ca578d19d52cfc263cfc4080b" dependencies = [ "anyhow", "asn1 0.11.0", @@ -2885,7 +2885,7 @@ dependencies = [ [[package]] name = "many-types" version = "0.1.0" -source = "git+https://github.com/liftedinit/many-rs.git?rev=71eba1a1cfee506505acec865f5984afab0d3e74#71eba1a1cfee506505acec865f5984afab0d3e74" +source = "git+https://github.com/liftedinit/many-rs.git?rev=ce03b88dea51232ca578d19d52cfc263cfc4080b#ce03b88dea51232ca578d19d52cfc263cfc4080b" dependencies = [ "base64 0.20.0", "coset", @@ -3024,6 +3024,15 @@ dependencies = [ "minimal-lexical", ] +[[package]] +name = "nom8" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae01545c9c7fc4486ab7debaf2aad7003ac19431791868fb2e8066df97fad2f8" +dependencies = [ + "memchr", +] + [[package]] name = "nom_locate" version = "4.1.0" @@ -3360,9 +3369,9 @@ checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" [[package]] name = "pest" -version = "2.5.3" +version = "2.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4257b4a04d91f7e9e6290be5d3da4804dd5784fafde3a497d73eb2b4a158c30a" +checksum = "4ab62d2fa33726dbe6321cc97ef96d8cde531e3eeaf858a058de53a8a6d40d8f" dependencies = [ "thiserror", "ucd-trie", @@ -3370,9 +3379,9 @@ dependencies = [ [[package]] name = "pest_derive" -version = "2.5.3" +version = "2.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "241cda393b0cdd65e62e07e12454f1f25d57017dcc514b1514cd3c4645e3a0a6" +checksum = "8bf026e2d0581559db66d837fe5242320f525d85c76283c61f4d51a1238d65ea" dependencies = [ "pest", "pest_generator", @@ -3380,9 +3389,9 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.5.3" +version = "2.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46b53634d8c8196302953c74d5352f33d0c512a9499bd2ce468fc9f4128fa27c" +checksum = "2b27bd18aa01d91c8ed2b61ea23406a676b42d82609c6e2581fba42f0c15f17f" dependencies = [ "pest", "pest_meta", @@ -3393,9 +3402,9 @@ dependencies = [ [[package]] name = "pest_meta" -version = "2.5.3" +version = "2.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ef4f1332a8d4678b41966bb4cc1d0676880e84183a1ecc3f4b69f03e99c7a51" +checksum = "9f02b677c1859756359fc9983c2e56a0237f18624a3789528804406b7e915e5d" dependencies = [ "once_cell", "pest", @@ -3503,13 +3512,12 @@ checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" [[package]] name = "proc-macro-crate" -version = "1.2.1" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eda0fc3b0fb7c975631757e14d9049da17374063edb6ebbcbc54d880d4fe94e9" +checksum = "66618389e4ec1c7afe67d51a9bf34ff9236480f8d51e7489b7d5ab0303c13f34" dependencies = [ "once_cell", - "thiserror", - "toml", + "toml_edit", ] [[package]] @@ -4767,6 +4775,23 @@ dependencies = [ "serde", ] +[[package]] +name = "toml_datetime" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4553f467ac8e3d374bc9a177a26801e5d0f9b211aa1673fb137a403afd1c9cf5" + +[[package]] +name = "toml_edit" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "729bfd096e40da9c001f778f5cdecbd2957929a24e10e5883d9392220a751581" +dependencies = [ + "indexmap", + "nom8", + "toml_datetime", +] + [[package]] name = "tower-service" version = "0.3.2" diff --git a/cargo-bazel-lock.json b/cargo-bazel-lock.json index 4d481356..be2fa769 100644 --- a/cargo-bazel-lock.json +++ b/cargo-bazel-lock.json @@ -1,5 +1,5 @@ { - "checksum": "94976a1429d803bde7f5c6d6b65b75b1bcf9cf029dab54a600e175114c901cbe", + "checksum": "65db024bdba42cc6a109fc102408caf0f6ea6f2e25f8ca45c0ebb06b3e4821b6", "crates": { "aes 0.7.5": { "name": "aes", @@ -13453,7 +13453,7 @@ "Git": { "remote": "https://github.com/liftedinit/many-rs.git", "commitish": { - "Rev": "71eba1a1cfee506505acec865f5984afab0d3e74" + "Rev": "ce03b88dea51232ca578d19d52cfc263cfc4080b" }, "strip_prefix": "src/many-client" } @@ -13646,7 +13646,7 @@ "Git": { "remote": "https://github.com/liftedinit/many-rs.git", "commitish": { - "Rev": "71eba1a1cfee506505acec865f5984afab0d3e74" + "Rev": "ce03b88dea51232ca578d19d52cfc263cfc4080b" }, "strip_prefix": "src/many-client-macros" } @@ -13699,7 +13699,7 @@ "Git": { "remote": "https://github.com/liftedinit/many-rs.git", "commitish": { - "Rev": "71eba1a1cfee506505acec865f5984afab0d3e74" + "Rev": "ce03b88dea51232ca578d19d52cfc263cfc4080b" }, "strip_prefix": "src/many-error" } @@ -13765,7 +13765,7 @@ "Git": { "remote": "https://github.com/liftedinit/many-rs.git", "commitish": { - "Rev": "71eba1a1cfee506505acec865f5984afab0d3e74" + "Rev": "ce03b88dea51232ca578d19d52cfc263cfc4080b" }, "strip_prefix": "src/many-identity" } @@ -13866,7 +13866,7 @@ "Git": { "remote": "https://github.com/liftedinit/many-rs.git", "commitish": { - "Rev": "71eba1a1cfee506505acec865f5984afab0d3e74" + "Rev": "ce03b88dea51232ca578d19d52cfc263cfc4080b" }, "strip_prefix": "src/many-identity-dsa" } @@ -14000,7 +14000,7 @@ "Git": { "remote": "https://github.com/liftedinit/many-rs.git", "commitish": { - "Rev": "71eba1a1cfee506505acec865f5984afab0d3e74" + "Rev": "ce03b88dea51232ca578d19d52cfc263cfc4080b" }, "strip_prefix": "src/many-identity-hsm" } @@ -14093,7 +14093,7 @@ "Git": { "remote": "https://github.com/liftedinit/many-rs.git", "commitish": { - "Rev": "71eba1a1cfee506505acec865f5984afab0d3e74" + "Rev": "ce03b88dea51232ca578d19d52cfc263cfc4080b" }, "strip_prefix": "src/many-identity-webauthn" } @@ -14827,7 +14827,7 @@ "Git": { "remote": "https://github.com/liftedinit/many-rs.git", "commitish": { - "Rev": "71eba1a1cfee506505acec865f5984afab0d3e74" + "Rev": "ce03b88dea51232ca578d19d52cfc263cfc4080b" }, "strip_prefix": "src/many-macros" } @@ -14892,7 +14892,7 @@ "Git": { "remote": "https://github.com/liftedinit/many-rs.git", "commitish": { - "Rev": "71eba1a1cfee506505acec865f5984afab0d3e74" + "Rev": "ce03b88dea51232ca578d19d52cfc263cfc4080b" }, "strip_prefix": "src/many-migration" } @@ -14957,7 +14957,7 @@ "Git": { "remote": "https://github.com/liftedinit/many-rs.git", "commitish": { - "Rev": "71eba1a1cfee506505acec865f5984afab0d3e74" + "Rev": "ce03b88dea51232ca578d19d52cfc263cfc4080b" }, "strip_prefix": "src/many-modules" } @@ -15062,7 +15062,7 @@ "Git": { "remote": "https://github.com/liftedinit/many-rs.git", "commitish": { - "Rev": "71eba1a1cfee506505acec865f5984afab0d3e74" + "Rev": "ce03b88dea51232ca578d19d52cfc263cfc4080b" }, "strip_prefix": "src/many-protocol" } @@ -15176,7 +15176,7 @@ "Git": { "remote": "https://github.com/liftedinit/many-rs.git", "commitish": { - "Rev": "71eba1a1cfee506505acec865f5984afab0d3e74" + "Rev": "ce03b88dea51232ca578d19d52cfc263cfc4080b" }, "strip_prefix": "src/many-server" } @@ -15393,7 +15393,7 @@ "Git": { "remote": "https://github.com/liftedinit/many-rs.git", "commitish": { - "Rev": "71eba1a1cfee506505acec865f5984afab0d3e74" + "Rev": "ce03b88dea51232ca578d19d52cfc263cfc4080b" }, "strip_prefix": "src/many-types" } diff --git a/docker/e2e/Cargo.nix b/docker/e2e/Cargo.nix index 9f4c7483..14c6a626 100644 --- a/docker/e2e/Cargo.nix +++ b/docker/e2e/Cargo.nix @@ -33,7 +33,7 @@ args@{ ignoreLockHash, }: let - nixifiedLockHash = "617ffe1c0d8f860023e2e187f2a0b0b6748cd0d7c30275a915423c54f67a3c24"; + nixifiedLockHash = "55687ddcaa22f264139196a9ddbdb384942d458a5ea980abd8be31922d517230"; workspaceSrc = if args.workspaceSrc == null then ./. else args.workspaceSrc; currentLockHash = builtins.hashFile "sha256" (workspaceSrc + /Cargo.lock); lockHashIgnored = if ignoreLockHash @@ -989,11 +989,11 @@ in }; }); - "registry+https://github.com/rust-lang/crates.io-index".clap."4.1.2" = overridableMkRustCrate (profileName: rec { + "registry+https://github.com/rust-lang/crates.io-index".clap."4.1.3" = overridableMkRustCrate (profileName: rec { name = "clap"; - version = "4.1.2"; + version = "4.1.3"; registry = "registry+https://github.com/rust-lang/crates.io-index"; - src = fetchCratesIo { inherit name version; sha256 = "0e638668a62aced2c9fb72b5135a33b4a500485ccf2a0e402e09aa04ab2fc115"; }; + src = fetchCratesIo { inherit name version; sha256 = "d8d93d855ce6a0aa87b8473ef9169482f40abaa2e9e0993024c35c902cbd5920"; }; features = builtins.concatLists [ [ "color" ] [ "default" ] @@ -1415,7 +1415,7 @@ in anyhow = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".anyhow."1.0.68" { inherit profileName; }).out; async_trait = (buildRustPackages."registry+https://github.com/rust-lang/crates.io-index".async-trait."0.1.63" { profileName = "__noProfile"; }).out; atty = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".atty."0.2.14" { inherit profileName; }).out; - clap = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".clap."4.1.2" { inherit profileName; }).out; + clap = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".clap."4.1.3" { inherit profileName; }).out; console = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".console."0.15.5" { inherit profileName; }).out; cucumber_codegen = (buildRustPackages."registry+https://github.com/rust-lang/crates.io-index".cucumber-codegen."0.17.0" { profileName = "__noProfile"; }).out; cucumber_expressions = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".cucumber-expressions."0.2.1" { inherit profileName; }).out; @@ -3119,8 +3119,8 @@ in registry = "registry+https://github.com/rust-lang/crates.io-index"; src = fetchCratesIo { inherit name version; sha256 = "96b0db21af676c1ce64250b5f40f3ce2cf27e4e47cb91ed91eb6fe9350b430c1"; }; dependencies = { - pest = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".pest."2.5.3" { inherit profileName; }).out; - pest_derive = (buildRustPackages."registry+https://github.com/rust-lang/crates.io-index".pest_derive."2.5.3" { profileName = "__noProfile"; }).out; + pest = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".pest."2.5.4" { inherit profileName; }).out; + pest_derive = (buildRustPackages."registry+https://github.com/rust-lang/crates.io-index".pest_derive."2.5.4" { profileName = "__noProfile"; }).out; serde = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".serde."1.0.152" { inherit profileName; }).out; }; }); @@ -3450,7 +3450,7 @@ in url = https://github.com/liftedinit/many-rs.git; name = "many-client"; version = "0.1.0"; - rev = "71eba1a1cfee506505acec865f5984afab0d3e74";}; + rev = "ce03b88dea51232ca578d19d52cfc263cfc4080b";}; features = builtins.concatLists [ [ "default" ] ]; @@ -3502,7 +3502,7 @@ in url = https://github.com/liftedinit/many-rs.git; name = "many-client-macros"; version = "0.1.0"; - rev = "71eba1a1cfee506505acec865f5984afab0d3e74";}; + rev = "ce03b88dea51232ca578d19d52cfc263cfc4080b";}; dependencies = { proc_macro2 = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".proc-macro2."1.0.50" { inherit profileName; }).out; quote = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".quote."1.0.23" { inherit profileName; }).out; @@ -3518,7 +3518,7 @@ in url = https://github.com/liftedinit/many-rs.git; name = "many-error"; version = "0.1.0"; - rev = "71eba1a1cfee506505acec865f5984afab0d3e74";}; + rev = "ce03b88dea51232ca578d19d52cfc263cfc4080b";}; features = builtins.concatLists [ [ "default" ] [ "minicbor" ] @@ -3539,7 +3539,7 @@ in url = https://github.com/liftedinit/many-rs.git; name = "many-identity"; version = "0.1.0"; - rev = "71eba1a1cfee506505acec865f5984afab0d3e74";}; + rev = "ce03b88dea51232ca578d19d52cfc263cfc4080b";}; features = builtins.concatLists [ [ "coset" ] [ "default" ] @@ -3573,7 +3573,7 @@ in url = https://github.com/liftedinit/many-rs.git; name = "many-identity-dsa"; version = "0.1.0"; - rev = "71eba1a1cfee506505acec865f5984afab0d3e74";}; + rev = "ce03b88dea51232ca578d19d52cfc263cfc4080b";}; features = builtins.concatLists [ [ "coset" ] [ "default" ] @@ -3615,7 +3615,7 @@ in url = https://github.com/liftedinit/many-rs.git; name = "many-identity-hsm"; version = "0.1.0"; - rev = "71eba1a1cfee506505acec865f5984afab0d3e74";}; + rev = "ce03b88dea51232ca578d19d52cfc263cfc4080b";}; dependencies = { asn1 = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".asn1."0.10.0" { inherit profileName; }).out; coset = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".coset."0.3.3" { inherit profileName; }).out; @@ -3641,7 +3641,7 @@ in url = https://github.com/liftedinit/many-rs.git; name = "many-identity-webauthn"; version = "0.1.0"; - rev = "71eba1a1cfee506505acec865f5984afab0d3e74";}; + rev = "ce03b88dea51232ca578d19d52cfc263cfc4080b";}; features = builtins.concatLists [ [ "default" ] [ "identity" ] @@ -3834,7 +3834,7 @@ in url = https://github.com/liftedinit/many-rs.git; name = "many-macros"; version = "0.1.0"; - rev = "71eba1a1cfee506505acec865f5984afab0d3e74";}; + rev = "ce03b88dea51232ca578d19d52cfc263cfc4080b";}; dependencies = { inflections = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".inflections."1.1.1" { inherit profileName; }).out; proc_macro2 = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".proc-macro2."1.0.50" { inherit profileName; }).out; @@ -3853,7 +3853,7 @@ in url = https://github.com/liftedinit/many-rs.git; name = "many-migration"; version = "0.1.0"; - rev = "71eba1a1cfee506505acec865f5984afab0d3e74";}; + rev = "ce03b88dea51232ca578d19d52cfc263cfc4080b";}; dependencies = { many_error = (rustPackages."git+https://github.com/liftedinit/many-rs.git".many-error."0.1.0" { inherit profileName; }).out; minicbor = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".minicbor."0.18.0" { inherit profileName; }).out; @@ -3872,7 +3872,7 @@ in url = https://github.com/liftedinit/many-rs.git; name = "many-modules"; version = "0.1.0"; - rev = "71eba1a1cfee506505acec865f5984afab0d3e74";}; + rev = "ce03b88dea51232ca578d19d52cfc263cfc4080b";}; features = builtins.concatLists [ [ "cucumber" ] ]; @@ -3902,7 +3902,7 @@ in url = https://github.com/liftedinit/many-rs.git; name = "many-protocol"; version = "0.1.0"; - rev = "71eba1a1cfee506505acec865f5984afab0d3e74";}; + rev = "ce03b88dea51232ca578d19d52cfc263cfc4080b";}; dependencies = { base64 = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".base64."0.13.1" { inherit profileName; }).out; coset = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".coset."0.3.3" { inherit profileName; }).out; @@ -3932,7 +3932,7 @@ in url = https://github.com/liftedinit/many-rs.git; name = "many-server"; version = "0.1.0"; - rev = "71eba1a1cfee506505acec865f5984afab0d3e74";}; + rev = "ce03b88dea51232ca578d19d52cfc263cfc4080b";}; features = builtins.concatLists [ [ "default" ] ]; @@ -3990,7 +3990,7 @@ in url = https://github.com/liftedinit/many-rs.git; name = "many-types"; version = "0.1.0"; - rev = "71eba1a1cfee506505acec865f5984afab0d3e74";}; + rev = "ce03b88dea51232ca578d19d52cfc263cfc4080b";}; features = builtins.concatLists [ [ "cucumber" ] ]; @@ -4210,6 +4210,21 @@ in }; }); + "registry+https://github.com/rust-lang/crates.io-index".nom8."0.2.0" = overridableMkRustCrate (profileName: rec { + name = "nom8"; + version = "0.2.0"; + registry = "registry+https://github.com/rust-lang/crates.io-index"; + src = fetchCratesIo { inherit name version; sha256 = "ae01545c9c7fc4486ab7debaf2aad7003ac19431791868fb2e8066df97fad2f8"; }; + features = builtins.concatLists [ + [ "alloc" ] + [ "default" ] + [ "std" ] + ]; + dependencies = { + memchr = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".memchr."2.5.0" { inherit profileName; }).out; + }; + }); + "registry+https://github.com/rust-lang/crates.io-index".nom_locate."4.1.0" = overridableMkRustCrate (profileName: rec { name = "nom_locate"; version = "4.1.0"; @@ -4350,7 +4365,7 @@ in [ "std" ] ]; dependencies = { - proc_macro_crate = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".proc-macro-crate."1.2.1" { inherit profileName; }).out; + proc_macro_crate = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".proc-macro-crate."1.3.0" { inherit profileName; }).out; proc_macro2 = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".proc-macro2."1.0.50" { inherit profileName; }).out; quote = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".quote."1.0.23" { inherit profileName; }).out; syn = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".syn."1.0.107" { inherit profileName; }).out; @@ -4673,11 +4688,11 @@ in ]; }); - "registry+https://github.com/rust-lang/crates.io-index".pest."2.5.3" = overridableMkRustCrate (profileName: rec { + "registry+https://github.com/rust-lang/crates.io-index".pest."2.5.4" = overridableMkRustCrate (profileName: rec { name = "pest"; - version = "2.5.3"; + version = "2.5.4"; registry = "registry+https://github.com/rust-lang/crates.io-index"; - src = fetchCratesIo { inherit name version; sha256 = "4257b4a04d91f7e9e6290be5d3da4804dd5784fafde3a497d73eb2b4a158c30a"; }; + src = fetchCratesIo { inherit name version; sha256 = "4ab62d2fa33726dbe6321cc97ef96d8cde531e3eeaf858a058de53a8a6d40d8f"; }; features = builtins.concatLists [ [ "default" ] [ "std" ] @@ -4689,46 +4704,46 @@ in }; }); - "registry+https://github.com/rust-lang/crates.io-index".pest_derive."2.5.3" = overridableMkRustCrate (profileName: rec { + "registry+https://github.com/rust-lang/crates.io-index".pest_derive."2.5.4" = overridableMkRustCrate (profileName: rec { name = "pest_derive"; - version = "2.5.3"; + version = "2.5.4"; registry = "registry+https://github.com/rust-lang/crates.io-index"; - src = fetchCratesIo { inherit name version; sha256 = "241cda393b0cdd65e62e07e12454f1f25d57017dcc514b1514cd3c4645e3a0a6"; }; + src = fetchCratesIo { inherit name version; sha256 = "8bf026e2d0581559db66d837fe5242320f525d85c76283c61f4d51a1238d65ea"; }; features = builtins.concatLists [ [ "default" ] [ "std" ] ]; dependencies = { - pest = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".pest."2.5.3" { inherit profileName; }).out; - pest_generator = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".pest_generator."2.5.3" { inherit profileName; }).out; + pest = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".pest."2.5.4" { inherit profileName; }).out; + pest_generator = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".pest_generator."2.5.4" { inherit profileName; }).out; }; }); - "registry+https://github.com/rust-lang/crates.io-index".pest_generator."2.5.3" = overridableMkRustCrate (profileName: rec { + "registry+https://github.com/rust-lang/crates.io-index".pest_generator."2.5.4" = overridableMkRustCrate (profileName: rec { name = "pest_generator"; - version = "2.5.3"; + version = "2.5.4"; registry = "registry+https://github.com/rust-lang/crates.io-index"; - src = fetchCratesIo { inherit name version; sha256 = "46b53634d8c8196302953c74d5352f33d0c512a9499bd2ce468fc9f4128fa27c"; }; + src = fetchCratesIo { inherit name version; sha256 = "2b27bd18aa01d91c8ed2b61ea23406a676b42d82609c6e2581fba42f0c15f17f"; }; features = builtins.concatLists [ [ "std" ] ]; dependencies = { - pest = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".pest."2.5.3" { inherit profileName; }).out; - pest_meta = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".pest_meta."2.5.3" { inherit profileName; }).out; + pest = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".pest."2.5.4" { inherit profileName; }).out; + pest_meta = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".pest_meta."2.5.4" { inherit profileName; }).out; proc_macro2 = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".proc-macro2."1.0.50" { inherit profileName; }).out; quote = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".quote."1.0.23" { inherit profileName; }).out; syn = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".syn."1.0.107" { inherit profileName; }).out; }; }); - "registry+https://github.com/rust-lang/crates.io-index".pest_meta."2.5.3" = overridableMkRustCrate (profileName: rec { + "registry+https://github.com/rust-lang/crates.io-index".pest_meta."2.5.4" = overridableMkRustCrate (profileName: rec { name = "pest_meta"; - version = "2.5.3"; + version = "2.5.4"; registry = "registry+https://github.com/rust-lang/crates.io-index"; - src = fetchCratesIo { inherit name version; sha256 = "0ef4f1332a8d4678b41966bb4cc1d0676880e84183a1ecc3f4b69f03e99c7a51"; }; + src = fetchCratesIo { inherit name version; sha256 = "9f02b677c1859756359fc9983c2e56a0237f18624a3789528804406b7e915e5d"; }; dependencies = { once_cell = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".once_cell."1.17.0" { inherit profileName; }).out; - pest = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".pest."2.5.3" { inherit profileName; }).out; + pest = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".pest."2.5.4" { inherit profileName; }).out; }; buildDependencies = { sha2 = (buildRustPackages."registry+https://github.com/rust-lang/crates.io-index".sha2."0.10.6" { profileName = "__noProfile"; }).out; @@ -4879,15 +4894,14 @@ in ]; }); - "registry+https://github.com/rust-lang/crates.io-index".proc-macro-crate."1.2.1" = overridableMkRustCrate (profileName: rec { + "registry+https://github.com/rust-lang/crates.io-index".proc-macro-crate."1.3.0" = overridableMkRustCrate (profileName: rec { name = "proc-macro-crate"; - version = "1.2.1"; + version = "1.3.0"; registry = "registry+https://github.com/rust-lang/crates.io-index"; - src = fetchCratesIo { inherit name version; sha256 = "eda0fc3b0fb7c975631757e14d9049da17374063edb6ebbcbc54d880d4fe94e9"; }; + src = fetchCratesIo { inherit name version; sha256 = "66618389e4ec1c7afe67d51a9bf34ff9236480f8d51e7489b7d5ab0303c13f34"; }; dependencies = { once_cell = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".once_cell."1.17.0" { inherit profileName; }).out; - thiserror = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".thiserror."1.0.38" { inherit profileName; }).out; - toml = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".toml."0.5.11" { inherit profileName; }).out; + toml_edit = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".toml_edit."0.18.0" { inherit profileName; }).out; }; }); @@ -6612,6 +6626,28 @@ in }; }); + "registry+https://github.com/rust-lang/crates.io-index".toml_datetime."0.5.1" = overridableMkRustCrate (profileName: rec { + name = "toml_datetime"; + version = "0.5.1"; + registry = "registry+https://github.com/rust-lang/crates.io-index"; + src = fetchCratesIo { inherit name version; sha256 = "4553f467ac8e3d374bc9a177a26801e5d0f9b211aa1673fb137a403afd1c9cf5"; }; + }); + + "registry+https://github.com/rust-lang/crates.io-index".toml_edit."0.18.0" = overridableMkRustCrate (profileName: rec { + name = "toml_edit"; + version = "0.18.0"; + registry = "registry+https://github.com/rust-lang/crates.io-index"; + src = fetchCratesIo { inherit name version; sha256 = "729bfd096e40da9c001f778f5cdecbd2957929a24e10e5883d9392220a751581"; }; + features = builtins.concatLists [ + [ "default" ] + ]; + dependencies = { + indexmap = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".indexmap."1.9.2" { inherit profileName; }).out; + nom8 = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".nom8."0.2.0" { inherit profileName; }).out; + toml_datetime = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".toml_datetime."0.5.1" { inherit profileName; }).out; + }; + }); + "registry+https://github.com/rust-lang/crates.io-index".tower-service."0.3.2" = overridableMkRustCrate (profileName: rec { name = "tower-service"; version = "0.3.2"; diff --git a/src/http_proxy/Cargo.toml b/src/http_proxy/Cargo.toml index 1fac629f..f68ed01d 100644 --- a/src/http_proxy/Cargo.toml +++ b/src/http_proxy/Cargo.toml @@ -19,11 +19,11 @@ doc = false clap = { version = "3.0.0", features = ["derive"] } hex = "0.4.3" minicbor = { version = "0.18.0", features = ["derive", "std"] } -many-client = { git = "https://github.com/liftedinit/many-rs.git", rev = "71eba1a1cfee506505acec865f5984afab0d3e74" } -many-identity = { git = "https://github.com/liftedinit/many-rs.git", rev = "71eba1a1cfee506505acec865f5984afab0d3e74" } -many-identity-dsa = { git = "https://github.com/liftedinit/many-rs.git", rev = "71eba1a1cfee506505acec865f5984afab0d3e74" } +many-client = { git = "https://github.com/liftedinit/many-rs.git", rev = "ce03b88dea51232ca578d19d52cfc263cfc4080b" } +many-identity = { git = "https://github.com/liftedinit/many-rs.git", rev = "ce03b88dea51232ca578d19d52cfc263cfc4080b" } +many-identity-dsa = { git = "https://github.com/liftedinit/many-rs.git", rev = "ce03b88dea51232ca578d19d52cfc263cfc4080b" } many-kvstore = { path = "../many-kvstore" } -many-modules = { git = "https://github.com/liftedinit/many-rs.git", rev = "71eba1a1cfee506505acec865f5984afab0d3e74" } +many-modules = { git = "https://github.com/liftedinit/many-rs.git", rev = "ce03b88dea51232ca578d19d52cfc263cfc4080b" } new_mime_guess = "4.0.0" syslog-tracing = "0.1" tiny_http = "0.11.0" diff --git a/src/kvstore/Cargo.toml b/src/kvstore/Cargo.toml index ff30ccd6..a74e79cd 100644 --- a/src/kvstore/Cargo.toml +++ b/src/kvstore/Cargo.toml @@ -20,13 +20,13 @@ clap = { version = "3.0.0", features = ["derive"] } hex = "0.4.3" indicatif = "0.16.2" minicbor = { version = "0.18.0", features = ["derive", "std"] } -many-client = { git = "https://github.com/liftedinit/many-rs.git", rev = "71eba1a1cfee506505acec865f5984afab0d3e74" } -many-error = { git = "https://github.com/liftedinit/many-rs.git", rev = "71eba1a1cfee506505acec865f5984afab0d3e74" } -many-identity = { git = "https://github.com/liftedinit/many-rs.git", rev = "71eba1a1cfee506505acec865f5984afab0d3e74" } -many-identity-dsa = { git = "https://github.com/liftedinit/many-rs.git", rev = "71eba1a1cfee506505acec865f5984afab0d3e74", features = ["ed25519", "ecdsa"] } -many-modules = { git = "https://github.com/liftedinit/many-rs.git", rev = "71eba1a1cfee506505acec865f5984afab0d3e74" } -many-protocol = { git = "https://github.com/liftedinit/many-rs.git", rev = "71eba1a1cfee506505acec865f5984afab0d3e74" } -many-types = { git = "https://github.com/liftedinit/many-rs.git", rev = "71eba1a1cfee506505acec865f5984afab0d3e74" } +many-client = { git = "https://github.com/liftedinit/many-rs.git", rev = "ce03b88dea51232ca578d19d52cfc263cfc4080b" } +many-error = { git = "https://github.com/liftedinit/many-rs.git", rev = "ce03b88dea51232ca578d19d52cfc263cfc4080b" } +many-identity = { git = "https://github.com/liftedinit/many-rs.git", rev = "ce03b88dea51232ca578d19d52cfc263cfc4080b" } +many-identity-dsa = { git = "https://github.com/liftedinit/many-rs.git", rev = "ce03b88dea51232ca578d19d52cfc263cfc4080b", features = ["ed25519", "ecdsa"] } +many-modules = { git = "https://github.com/liftedinit/many-rs.git", rev = "ce03b88dea51232ca578d19d52cfc263cfc4080b" } +many-protocol = { git = "https://github.com/liftedinit/many-rs.git", rev = "ce03b88dea51232ca578d19d52cfc263cfc4080b" } +many-types = { git = "https://github.com/liftedinit/many-rs.git", rev = "ce03b88dea51232ca578d19d52cfc263cfc4080b" } syslog-tracing = "0.1" tracing = "0.1.29" tracing-subscriber = "0.3" diff --git a/src/ledger-db/Cargo.toml b/src/ledger-db/Cargo.toml index 86a4744f..728f1eda 100644 --- a/src/ledger-db/Cargo.toml +++ b/src/ledger-db/Cargo.toml @@ -19,6 +19,6 @@ doc = false clap = { version = "3.0.0", features = ["derive"] } hex = "0.4.3" merk = { git = "https://github.com/liftedinit/merk.git", rev = "3d509c8efd3a68d85a5769f7fff300e10290d137" } -many-modules = { git = "https://github.com/liftedinit/many-rs.git", rev = "71eba1a1cfee506505acec865f5984afab0d3e74" } -many-types = { git = "https://github.com/liftedinit/many-rs.git", rev = "71eba1a1cfee506505acec865f5984afab0d3e74" } +many-modules = { git = "https://github.com/liftedinit/many-rs.git", rev = "ce03b88dea51232ca578d19d52cfc263cfc4080b" } +many-types = { git = "https://github.com/liftedinit/many-rs.git", rev = "ce03b88dea51232ca578d19d52cfc263cfc4080b" } minicbor = "0.18.0" diff --git a/src/ledger/Cargo.toml b/src/ledger/Cargo.toml index 8247a849..167fcafc 100644 --- a/src/ledger/Cargo.toml +++ b/src/ledger/Cargo.toml @@ -26,14 +26,14 @@ lazy_static = "1.4.0" mime_guess = "2.0.4" minicbor = { version = "0.18.0", features = ["derive", "std"] } num-bigint = "0.4.3" -many-client = { git = "https://github.com/liftedinit/many-rs.git", rev = "71eba1a1cfee506505acec865f5984afab0d3e74" } -many-error = { git = "https://github.com/liftedinit/many-rs.git", rev = "71eba1a1cfee506505acec865f5984afab0d3e74" } -many-identity = { git = "https://github.com/liftedinit/many-rs.git", rev = "71eba1a1cfee506505acec865f5984afab0d3e74", features = ["serde"] } -many-identity-dsa = { git = "https://github.com/liftedinit/many-rs.git", rev = "71eba1a1cfee506505acec865f5984afab0d3e74", features = ["ed25519", "ecdsa"] } -many-identity-hsm = { git = "https://github.com/liftedinit/many-rs.git", rev = "71eba1a1cfee506505acec865f5984afab0d3e74" } -many-modules = { git = "https://github.com/liftedinit/many-rs.git", rev = "71eba1a1cfee506505acec865f5984afab0d3e74" } -many-protocol = { git = "https://github.com/liftedinit/many-rs.git", rev = "71eba1a1cfee506505acec865f5984afab0d3e74" } -many-types = { git = "https://github.com/liftedinit/many-rs.git", rev = "71eba1a1cfee506505acec865f5984afab0d3e74" } +many-client = { git = "https://github.com/liftedinit/many-rs.git", rev = "ce03b88dea51232ca578d19d52cfc263cfc4080b" } +many-error = { git = "https://github.com/liftedinit/many-rs.git", rev = "ce03b88dea51232ca578d19d52cfc263cfc4080b" } +many-identity = { git = "https://github.com/liftedinit/many-rs.git", rev = "ce03b88dea51232ca578d19d52cfc263cfc4080b", features = ["serde"] } +many-identity-dsa = { git = "https://github.com/liftedinit/many-rs.git", rev = "ce03b88dea51232ca578d19d52cfc263cfc4080b", features = ["ed25519", "ecdsa"] } +many-identity-hsm = { git = "https://github.com/liftedinit/many-rs.git", rev = "ce03b88dea51232ca578d19d52cfc263cfc4080b" } +many-modules = { git = "https://github.com/liftedinit/many-rs.git", rev = "ce03b88dea51232ca578d19d52cfc263cfc4080b" } +many-protocol = { git = "https://github.com/liftedinit/many-rs.git", rev = "ce03b88dea51232ca578d19d52cfc263cfc4080b" } +many-types = { git = "https://github.com/liftedinit/many-rs.git", rev = "ce03b88dea51232ca578d19d52cfc263cfc4080b" } regex = "1.5.4" ring = "0.16.20" rpassword = "6.0" diff --git a/src/ledger/src/tokens.rs b/src/ledger/src/tokens.rs index 4e1c3f75..1b5b6685 100644 --- a/src/ledger/src/tokens.rs +++ b/src/ledger/src/tokens.rs @@ -5,13 +5,15 @@ use many_identity::{Address, Identity}; use many_modules::ledger::extended_info::visual_logo::VisualTokenLogo; use many_modules::ledger::extended_info::TokenExtendedInfo; use many_modules::ledger::{ - TokenAddExtendedInfoArgs, TokenAddExtendedInfoReturns, TokenCreateArgs, TokenCreateReturns, - TokenInfoArgs, TokenInfoReturns, TokenRemoveExtendedInfoArgs, TokenRemoveExtendedInfoReturns, - TokenUpdateArgs, TokenUpdateReturns, + TokenAddExtendedInfoArgs, TokenAddExtendedInfoReturns, TokenBurnArgs, TokenBurnReturns, + TokenCreateArgs, TokenCreateReturns, TokenInfoArgs, TokenInfoReturns, TokenMintArgs, + TokenMintReturns, TokenRemoveExtendedInfoArgs, TokenRemoveExtendedInfoReturns, TokenUpdateArgs, + TokenUpdateReturns, }; use many_types::cbor::CborNull; use many_types::ledger::{LedgerTokensAddressMap, TokenAmount, TokenInfoSummary, TokenMaybeOwner}; use many_types::{AttributeRelatedIndex, Memo}; +use std::collections::BTreeMap; use std::path::PathBuf; #[derive(Parser)] @@ -37,6 +39,37 @@ enum SubcommandOpt { /// Get token info Info(InfoOpt), + + /// Mint new tokens + Mint(MintOpt), + + /// Burn tokens + Burn(BurnOpt), +} + +#[derive(Args)] +struct MintOpt { + symbol: String, + + #[clap(parse(try_from_str = serde_json::from_str))] + distribution: LedgerTokensAddressMap, + + #[clap(long, parse(try_from_str = Memo::try_from))] + memo: Option, +} + +#[derive(Args)] +struct BurnOpt { + symbol: String, + + #[clap(parse(try_from_str = serde_json::from_str))] + distribution: LedgerTokensAddressMap, + + #[clap(long, parse(try_from_str = Memo::try_from))] + memo: Option, + + #[clap(long, action)] + error_on_under_burn: bool, } #[derive(Args)] @@ -285,6 +318,65 @@ fn info_token(client: ManyClient, opts: InfoOpt) -> Result<(), Ma Ok(()) } +fn mint_token(client: ManyClient, opts: MintOpt) -> Result<(), ManyError> { + let symbol = Address::try_from(opts.symbol.as_str()).or_else(|_| { + // Get symbol address from name + let info: many_modules::ledger::InfoReturns = + minicbor::decode(&client.call_("ledger.info", ())?).unwrap(); + let local_names: BTreeMap = info + .local_names + .iter() + .map(|(x, y)| (y.clone(), *x)) + .collect(); + local_names + .get(&opts.symbol) + .cloned() + .ok_or_else(|| ManyError::unknown("Symbol address not found.")) + })?; + let args = TokenMintArgs { + symbol, + distribution: opts.distribution, + memo: opts.memo, + }; + let response = client.call("tokens.mint", args)?; + let payload = crate::wait_response(client, response)?; + let result: TokenMintReturns = + minicbor::decode(&payload).map_err(|e| ManyError::deserialization_error(e.to_string()))?; + + println!("{result:#?}"); + Ok(()) +} + +fn burn_token(client: ManyClient, opts: BurnOpt) -> Result<(), ManyError> { + let symbol = Address::try_from(opts.symbol.as_str()).or_else(|_| { + // Get symbol address from name + let info: many_modules::ledger::InfoReturns = + minicbor::decode(&client.call_("ledger.info", ())?).unwrap(); + let local_names: BTreeMap = info + .local_names + .iter() + .map(|(x, y)| (y.clone(), *x)) + .collect(); + local_names + .get(&opts.symbol) + .cloned() + .ok_or_else(|| ManyError::unknown("Symbol address not found.")) + })?; + let args = TokenBurnArgs { + symbol, + distribution: opts.distribution, + memo: opts.memo, + error_on_under_burn: Some(opts.error_on_under_burn), + }; + let response = client.call("tokens.burn", args)?; + let payload = crate::wait_response(client, response)?; + let result: TokenBurnReturns = + minicbor::decode(&payload).map_err(|e| ManyError::deserialization_error(e.to_string()))?; + + println!("{result:#?}"); + Ok(()) +} + pub fn tokens(client: ManyClient, opts: CommandOpt) -> Result<(), ManyError> { match opts.subcommand { SubcommandOpt::Create(opts) => create_token(client, opts), @@ -292,5 +384,7 @@ pub fn tokens(client: ManyClient, opts: CommandOpt) -> Result<(), SubcommandOpt::AddExtInfo(opts) => add_ext_info(client, opts), SubcommandOpt::RemoveExtInfo(opts) => remove_ext_info(client, opts), SubcommandOpt::Info(opts) => info_token(client, opts), + SubcommandOpt::Mint(opts) => mint_token(client, opts), + SubcommandOpt::Burn(opts) => burn_token(client, opts), } } diff --git a/src/many-abci/Cargo.toml b/src/many-abci/Cargo.toml index 90a02675..1df3347d 100644 --- a/src/many-abci/Cargo.toml +++ b/src/many-abci/Cargo.toml @@ -26,15 +26,15 @@ itertools = "0.10.5" json5 = "0.4.1" lazy_static = "1.4.0" minicbor = { version = "0.18.0", features = ["derive", "std"] } -many-client = { git = "https://github.com/liftedinit/many-rs.git", rev = "71eba1a1cfee506505acec865f5984afab0d3e74" } -many-error = { git = "https://github.com/liftedinit/many-rs.git", rev = "71eba1a1cfee506505acec865f5984afab0d3e74" } -many-identity = { git = "https://github.com/liftedinit/many-rs.git", rev = "71eba1a1cfee506505acec865f5984afab0d3e74" } -many-identity-dsa = { git = "https://github.com/liftedinit/many-rs.git", rev = "71eba1a1cfee506505acec865f5984afab0d3e74" } -many-identity-webauthn = { git = "https://github.com/liftedinit/many-rs.git", rev = "71eba1a1cfee506505acec865f5984afab0d3e74" } -many-modules = { git = "https://github.com/liftedinit/many-rs.git", rev = "71eba1a1cfee506505acec865f5984afab0d3e74" } -many-protocol = { git = "https://github.com/liftedinit/many-rs.git", rev = "71eba1a1cfee506505acec865f5984afab0d3e74" } -many-server = { git = "https://github.com/liftedinit/many-rs.git", rev = "71eba1a1cfee506505acec865f5984afab0d3e74" } -many-types = { git = "https://github.com/liftedinit/many-rs.git", rev = "71eba1a1cfee506505acec865f5984afab0d3e74" } +many-client = { git = "https://github.com/liftedinit/many-rs.git", rev = "ce03b88dea51232ca578d19d52cfc263cfc4080b" } +many-error = { git = "https://github.com/liftedinit/many-rs.git", rev = "ce03b88dea51232ca578d19d52cfc263cfc4080b" } +many-identity = { git = "https://github.com/liftedinit/many-rs.git", rev = "ce03b88dea51232ca578d19d52cfc263cfc4080b" } +many-identity-dsa = { git = "https://github.com/liftedinit/many-rs.git", rev = "ce03b88dea51232ca578d19d52cfc263cfc4080b" } +many-identity-webauthn = { git = "https://github.com/liftedinit/many-rs.git", rev = "ce03b88dea51232ca578d19d52cfc263cfc4080b" } +many-modules = { git = "https://github.com/liftedinit/many-rs.git", rev = "ce03b88dea51232ca578d19d52cfc263cfc4080b" } +many-protocol = { git = "https://github.com/liftedinit/many-rs.git", rev = "ce03b88dea51232ca578d19d52cfc263cfc4080b" } +many-server = { git = "https://github.com/liftedinit/many-rs.git", rev = "ce03b88dea51232ca578d19d52cfc263cfc4080b" } +many-types = { git = "https://github.com/liftedinit/many-rs.git", rev = "ce03b88dea51232ca578d19d52cfc263cfc4080b" } num-integer = "0.1.45" reqwest = "0.11.11" sha2 = "0.10.1" diff --git a/src/many-kvstore/Cargo.toml b/src/many-kvstore/Cargo.toml index 0d3cafe1..4b7cc7e0 100644 --- a/src/many-kvstore/Cargo.toml +++ b/src/many-kvstore/Cargo.toml @@ -27,13 +27,13 @@ json5 = "0.4.1" lazy_static = "1.4.0" num-bigint = "0.4.3" minicbor = { version = "0.18.0", features = ["derive", "std"] } -many-error = { git = "https://github.com/liftedinit/many-rs.git", rev = "71eba1a1cfee506505acec865f5984afab0d3e74" } -many-identity = { git = "https://github.com/liftedinit/many-rs.git", rev = "71eba1a1cfee506505acec865f5984afab0d3e74", features = ["default", "serde"] } -many-identity-dsa = { git = "https://github.com/liftedinit/many-rs.git", rev = "71eba1a1cfee506505acec865f5984afab0d3e74", features = ["ed25519", "ecdsa"] } -many-modules = { git = "https://github.com/liftedinit/many-rs.git", rev = "71eba1a1cfee506505acec865f5984afab0d3e74" } -many-protocol = { git = "https://github.com/liftedinit/many-rs.git", rev = "71eba1a1cfee506505acec865f5984afab0d3e74" } -many-server = { git = "https://github.com/liftedinit/many-rs.git", rev = "71eba1a1cfee506505acec865f5984afab0d3e74" } -many-types = { git = "https://github.com/liftedinit/many-rs.git", rev = "71eba1a1cfee506505acec865f5984afab0d3e74" } +many-error = { git = "https://github.com/liftedinit/many-rs.git", rev = "ce03b88dea51232ca578d19d52cfc263cfc4080b" } +many-identity = { git = "https://github.com/liftedinit/many-rs.git", rev = "ce03b88dea51232ca578d19d52cfc263cfc4080b", features = ["default", "serde"] } +many-identity-dsa = { git = "https://github.com/liftedinit/many-rs.git", rev = "ce03b88dea51232ca578d19d52cfc263cfc4080b", features = ["ed25519", "ecdsa"] } +many-modules = { git = "https://github.com/liftedinit/many-rs.git", rev = "ce03b88dea51232ca578d19d52cfc263cfc4080b" } +many-protocol = { git = "https://github.com/liftedinit/many-rs.git", rev = "ce03b88dea51232ca578d19d52cfc263cfc4080b" } +many-server = { git = "https://github.com/liftedinit/many-rs.git", rev = "ce03b88dea51232ca578d19d52cfc263cfc4080b" } +many-types = { git = "https://github.com/liftedinit/many-rs.git", rev = "ce03b88dea51232ca578d19d52cfc263cfc4080b" } serde = "1.0.130" serde_json = "1.0.72" sha3 = "0.10.4" @@ -47,8 +47,8 @@ tracing-subscriber = "0.3" [dev-dependencies] once_cell = "1.14.0" -many-identity = { git = "https://github.com/liftedinit/many-rs.git", rev = "71eba1a1cfee506505acec865f5984afab0d3e74", features = ["default", "serde", "testing"] } -many-identity-dsa = { git = "https://github.com/liftedinit/many-rs.git", rev = "71eba1a1cfee506505acec865f5984afab0d3e74", features = [ "ed25519", "testing" ] } +many-identity = { git = "https://github.com/liftedinit/many-rs.git", rev = "ce03b88dea51232ca578d19d52cfc263cfc4080b", features = ["default", "serde", "testing"] } +many-identity-dsa = { git = "https://github.com/liftedinit/many-rs.git", rev = "ce03b88dea51232ca578d19d52cfc263cfc4080b", features = [ "ed25519", "testing" ] } tempfile = "3.3.0" [build-dependencies] diff --git a/src/many-kvstore/src/module/event.rs b/src/many-kvstore/src/module/event.rs index 021e735c..e71e2269 100644 --- a/src/many-kvstore/src/module/event.rs +++ b/src/many-kvstore/src/module/event.rs @@ -61,7 +61,7 @@ fn filter_account<'a>( Box::new(it.filter(move |t| match t { // Propagate the errors. Err(_) => true, - Ok(t) => account.iter().any(|id| t.is_about(id)), + Ok(t) => account.iter().any(|id| t.is_about(*id)), })) } else { it diff --git a/src/many-kvstore/tests/events.rs b/src/many-kvstore/tests/events.rs index a405b0cc..2d963f10 100644 --- a/src/many-kvstore/tests/events.rs +++ b/src/many-kvstore/tests/events.rs @@ -100,23 +100,7 @@ fn list_filter_kind() { assert_eq!(list_return.nb_events, 1); assert_eq!(list_return.events.len(), 1); assert_eq!(list_return.events[0].kind(), events::EventKind::KvStorePut); - assert!(list_return.events[0].is_about(&id)); -} - -#[test] -fn list_filter_symbol() { - let setup = setup(); - let result = setup.module_impl.list(events::ListArgs { - count: None, - order: None, - filter: Some(events::EventFilter { - symbol: Some(vec![*MFX_SYMBOL].into()), - ..events::EventFilter::default() - }), - }); - assert!(result.is_ok()); - let list_return = result.unwrap(); - assert_eq!(list_return.nb_events, 0); + assert!(list_return.events[0].is_about(id)); } #[test] @@ -146,7 +130,7 @@ fn list_filter_date() { assert_eq!(list_return.nb_events, 1); assert_eq!(list_return.events.len(), 1); assert_eq!(list_return.events[0].kind(), events::EventKind::KvStorePut); - assert!(list_return.events[0].is_about(&id)); + assert!(list_return.events[0].is_about(id)); // TODO: Remove this when we support factional seconds // See https://github.com/liftedinit/many-rs/issues/110 diff --git a/src/many-ledger/BUILD.bazel b/src/many-ledger/BUILD.bazel index af7dcae4..3b28b751 100644 --- a/src/many-ledger/BUILD.bazel +++ b/src/many-ledger/BUILD.bazel @@ -99,6 +99,7 @@ rust_test_suite( srcs = glob( include = [ "tests/ledger_tokens/*.rs", + "tests/ledger_mintburn/*.rs", ], ), crate_features = ["balance_testing"], diff --git a/src/many-ledger/Cargo.toml b/src/many-ledger/Cargo.toml index a601158c..3a112373 100644 --- a/src/many-ledger/Cargo.toml +++ b/src/many-ledger/Cargo.toml @@ -32,15 +32,15 @@ linkme = { version = "0.3.5", features = ["used_linker"] } num-bigint = "0.4.3" num-traits = "0.2.14" minicbor = { version = "0.18.0", features = ["derive", "std"] } -many-error = { git = "https://github.com/liftedinit/many-rs.git", rev = "71eba1a1cfee506505acec865f5984afab0d3e74" } -many-identity = { git = "https://github.com/liftedinit/many-rs.git", rev = "71eba1a1cfee506505acec865f5984afab0d3e74", features = ["default", "serde"] } -many-identity-dsa = { git = "https://github.com/liftedinit/many-rs.git", rev = "71eba1a1cfee506505acec865f5984afab0d3e74", features = ["ed25519", "ecdsa"] } -many-identity-webauthn = { git = "https://github.com/liftedinit/many-rs.git", rev = "71eba1a1cfee506505acec865f5984afab0d3e74" } -many-migration = { git = "https://github.com/liftedinit/many-rs.git", rev = "71eba1a1cfee506505acec865f5984afab0d3e74" } -many-modules = { git = "https://github.com/liftedinit/many-rs.git", rev = "71eba1a1cfee506505acec865f5984afab0d3e74" } -many-protocol = { git = "https://github.com/liftedinit/many-rs.git", rev = "71eba1a1cfee506505acec865f5984afab0d3e74" } -many-server = { git = "https://github.com/liftedinit/many-rs.git", rev = "71eba1a1cfee506505acec865f5984afab0d3e74" } -many-types = { git = "https://github.com/liftedinit/many-rs.git", rev = "71eba1a1cfee506505acec865f5984afab0d3e74" } +many-error = { git = "https://github.com/liftedinit/many-rs.git", rev = "ce03b88dea51232ca578d19d52cfc263cfc4080b" } +many-identity = { git = "https://github.com/liftedinit/many-rs.git", rev = "ce03b88dea51232ca578d19d52cfc263cfc4080b", features = ["default", "serde"] } +many-identity-dsa = { git = "https://github.com/liftedinit/many-rs.git", rev = "ce03b88dea51232ca578d19d52cfc263cfc4080b", features = ["ed25519", "ecdsa"] } +many-identity-webauthn = { git = "https://github.com/liftedinit/many-rs.git", rev = "ce03b88dea51232ca578d19d52cfc263cfc4080b" } +many-migration = { git = "https://github.com/liftedinit/many-rs.git", rev = "ce03b88dea51232ca578d19d52cfc263cfc4080b" } +many-modules = { git = "https://github.com/liftedinit/many-rs.git", rev = "ce03b88dea51232ca578d19d52cfc263cfc4080b" } +many-protocol = { git = "https://github.com/liftedinit/many-rs.git", rev = "ce03b88dea51232ca578d19d52cfc263cfc4080b" } +many-server = { git = "https://github.com/liftedinit/many-rs.git", rev = "ce03b88dea51232ca578d19d52cfc263cfc4080b" } +many-types = { git = "https://github.com/liftedinit/many-rs.git", rev = "ce03b88dea51232ca578d19d52cfc263cfc4080b" } rand = "0.8" serde = "1.0.130" serde_json = "1.0.72" @@ -58,11 +58,11 @@ typetag = "0.2.3" [dev-dependencies] cucumber = { version = "0.17.0", features = ["libtest"] } once_cell = "1.12" -many-client = { git = "https://github.com/liftedinit/many-rs.git", rev = "71eba1a1cfee506505acec865f5984afab0d3e74" } -many-identity = { git = "https://github.com/liftedinit/many-rs.git", rev = "71eba1a1cfee506505acec865f5984afab0d3e74", features = ["default", "serde", "testing"] } -many-identity-dsa = { git = "https://github.com/liftedinit/many-rs.git", rev = "71eba1a1cfee506505acec865f5984afab0d3e74", features = [ "ed25519", "testing" ] } -many-types = { git = "https://github.com/liftedinit/many-rs.git", rev = "71eba1a1cfee506505acec865f5984afab0d3e74", features = ["cucumber"] } -many-modules = { git = "https://github.com/liftedinit/many-rs.git", rev = "71eba1a1cfee506505acec865f5984afab0d3e74", features = ["cucumber"] } +many-client = { git = "https://github.com/liftedinit/many-rs.git", rev = "ce03b88dea51232ca578d19d52cfc263cfc4080b" } +many-identity = { git = "https://github.com/liftedinit/many-rs.git", rev = "ce03b88dea51232ca578d19d52cfc263cfc4080b", features = ["default", "serde", "testing"] } +many-identity-dsa = { git = "https://github.com/liftedinit/many-rs.git", rev = "ce03b88dea51232ca578d19d52cfc263cfc4080b", features = [ "ed25519", "testing" ] } +many-types = { git = "https://github.com/liftedinit/many-rs.git", rev = "ce03b88dea51232ca578d19d52cfc263cfc4080b", features = ["cucumber"] } +many-modules = { git = "https://github.com/liftedinit/many-rs.git", rev = "ce03b88dea51232ca578d19d52cfc263cfc4080b", features = ["cucumber"] } many-ledger = { path = ".", features = ["balance_testing", "migration_testing", "disable_token_sender_check"]} proptest = "1" tempfile = "3.3.0" diff --git a/src/many-ledger/src/error.rs b/src/many-ledger/src/error.rs index 81f20f99..fad6c079 100644 --- a/src/many-ledger/src/error.rs +++ b/src/many-ledger/src/error.rs @@ -28,6 +28,16 @@ define_attribute_many_error!( } ); +define_attribute_many_error!( + attribute 12 => { + 1: pub fn symbol_not_found(symbol) => "Unable to mint/burn a unknown symbol: {symbol}.", + 2: pub fn over_maximum_supply(symbol, amount, max) => "Unable to mint over the maximum symbol supply : {amount} > {max} {symbol}.", + 3: pub fn missing_funds(symbol, amount, balance) => "Unable to burn, missing funds: {amount} > {balance} {symbol}.", + 4: pub fn unable_to_distribute_zero(symbol) => "The mint/burn distribution contains zero for {symbol}.", + 5: pub fn partial_burn_disabled() => "Partial burns are disabled.", + } +); + define_application_many_error!( { 1: pub fn storage_apply_failed(desc) => "Unable to apply change to persistent storage: {desc}.", diff --git a/src/many-ledger/src/main.rs b/src/many-ledger/src/main.rs index ce2e7d10..d74cefdb 100644 --- a/src/many-ledger/src/main.rs +++ b/src/many-ledger/src/main.rs @@ -304,6 +304,7 @@ fn main() { } s.add_module(events::EventsModule::new(module_impl.clone())); s.add_module(ledger::LedgerTokensModule::new(module_impl.clone())); + s.add_module(ledger::LedgerMintBurnModule::new(module_impl.clone())); let idstore_module = idstore::IdStoreModule::new(module_impl.clone()); #[cfg(feature = "webauthn_testing")] diff --git a/src/many-ledger/src/migration/tokens.rs b/src/many-ledger/src/migration/tokens.rs index 8ac11558..1fc56065 100644 --- a/src/many-ledger/src/migration/tokens.rs +++ b/src/many-ledger/src/migration/tokens.rs @@ -112,7 +112,7 @@ fn migrate_token( ), ), ( - key_for_symbol(&symbol), + key_for_symbol(&symbol).into_bytes(), Op::Put(minicbor::to_vec(info).map_err(ManyError::serialization_error)?), ), ( diff --git a/src/many-ledger/src/module.rs b/src/many-ledger/src/module.rs index b0600afb..6c4cbcc8 100644 --- a/src/many-ledger/src/module.rs +++ b/src/many-ledger/src/module.rs @@ -16,6 +16,7 @@ mod idstore; pub mod idstore_webauthn; mod ledger; mod ledger_commands; +mod ledger_mintburn; mod ledger_tokens; mod multisig; diff --git a/src/many-ledger/src/module/abci.rs b/src/many-ledger/src/module/abci.rs index e7f0065a..e4e8c024 100644 --- a/src/many-ledger/src/module/abci.rs +++ b/src/many-ledger/src/module/abci.rs @@ -59,6 +59,8 @@ impl ManyAbciModuleBackend for LedgerModuleImpl { ("tokens.info".to_string(), EndpointInfo { is_command : false }), ("tokens.addExtendedInfo".to_string(), EndpointInfo { is_command : true }), ("tokens.removeExtendedInfo".to_string(), EndpointInfo { is_command : true }), + ("tokens.mint".to_string(), EndpointInfo { is_command : true }), + ("tokens.burn".to_string(), EndpointInfo { is_command : true }), ]), }) } diff --git a/src/many-ledger/src/module/event.rs b/src/many-ledger/src/module/event.rs index 5f1f7355..f91954e4 100644 --- a/src/many-ledger/src/module/event.rs +++ b/src/many-ledger/src/module/event.rs @@ -6,9 +6,8 @@ use many_modules::events; use many_modules::events::{ EventFilterAttributeSpecific, EventFilterAttributeSpecificIndex, EventInfo, EventLog, }; -use many_types::ledger::Symbol; use many_types::{CborRange, Timestamp, VecOrSingle}; -use std::collections::{BTreeMap, BTreeSet}; +use std::collections::BTreeMap; const MAXIMUM_EVENT_COUNT: usize = 100; @@ -23,7 +22,7 @@ fn filter_account<'a>( Box::new(it.filter(move |t| match t { // Propagate the errors. Err(_) => true, - Ok(t) => account.iter().any(|id| t.is_about(id)), + Ok(t) => account.iter().any(|id| t.is_about(*id)), })) } else { it @@ -45,22 +44,6 @@ fn filter_event_kind<'a>( } } -fn filter_symbol<'a>( - it: Box + 'a>, - symbol: Option>, -) -> Box + 'a> { - if let Some(s) = symbol { - let s: BTreeSet = s.into(); - Box::new(it.filter(move |t| match t { - // Propagate the errors. - Err(_) => true, - Ok(t) => t.symbol().map_or(false, |x| s.contains(x)), - })) - } else { - it - } -} - fn filter_date<'a>( it: Box + 'a>, range: CborRange, @@ -151,7 +134,6 @@ impl events::EventsModuleBackend for LedgerModuleImpl { let iter = filter_account(iter, filter.account); let iter = filter_event_kind(iter, filter.kind); - let iter = filter_symbol(iter, filter.symbol); let iter = filter_date(iter, filter.date_range.unwrap_or_default()); let iter = filter_attribute_specific(iter, &filter.events_filter_attribute_specific); diff --git a/src/many-ledger/src/module/ledger_mintburn.rs b/src/many-ledger/src/module/ledger_mintburn.rs new file mode 100644 index 00000000..271691e9 --- /dev/null +++ b/src/many-ledger/src/module/ledger_mintburn.rs @@ -0,0 +1,103 @@ +use crate::error; +use crate::migration::tokens::TOKEN_MIGRATION; +use crate::module::LedgerModuleImpl; +use crate::storage::ledger_tokens::verify_tokens_sender; +use many_error::ManyError; +use many_identity::Address; +use many_modules::events::EventInfo; +use many_modules::ledger; +use many_modules::ledger::{TokenBurnArgs, TokenBurnReturns, TokenMintArgs, TokenMintReturns}; +use many_types::ledger::Symbol; +use std::collections::BTreeSet; + +/// Check if a symbol exists in the storage +fn check_symbol_exists(symbol: &Symbol, symbols: BTreeSet) -> Result<(), ManyError> { + if !symbols.contains(symbol) { + return Err(error::symbol_not_found(symbol.to_string())); + } + Ok(()) +} + +impl ledger::LedgerMintBurnModuleBackend for LedgerModuleImpl { + fn mint( + &mut self, + sender: &Address, + args: TokenMintArgs, + ) -> Result { + if !self.storage.migrations().is_active(&TOKEN_MIGRATION) { + return Err(ManyError::invalid_method_name("tokens.mint")); + } + + let TokenMintArgs { + symbol, + distribution, + memo, + } = args; + // Only the token identity is able to mint tokens + verify_tokens_sender( + sender, + self.storage + .get_identity(crate::storage::ledger_tokens::TOKEN_IDENTITY_ROOT) + .or_else(|_| self.storage.get_identity(crate::storage::IDENTITY_ROOT))?, + )?; + + check_symbol_exists(&symbol, self.storage.get_symbols()?)?; + + // Mint into storage + self.storage.mint_token(symbol, &distribution)?; + + // Log event + self.storage.log_event(EventInfo::TokenMint { + symbol, + distribution, + memo, + })?; + + Ok(TokenMintReturns {}) + } + + fn burn( + &mut self, + sender: &Address, + args: TokenBurnArgs, + ) -> Result { + if !self.storage.migrations().is_active(&TOKEN_MIGRATION) { + return Err(ManyError::invalid_method_name("tokens.burn")); + } + + let TokenBurnArgs { + symbol, + distribution, + memo, + error_on_under_burn, + } = args; + // Only the token identity is able to burn tokens + verify_tokens_sender( + sender, + self.storage + .get_identity(crate::storage::ledger_tokens::TOKEN_IDENTITY_ROOT) + .or_else(|_| self.storage.get_identity(crate::storage::IDENTITY_ROOT))?, + )?; + + check_symbol_exists(&symbol, self.storage.get_symbols()?)?; + + // Disable partial burn, for now + if let Some(error) = error_on_under_burn { + if !error { + return Err(error::partial_burn_disabled()); + } + } + + // Burn from storage + self.storage.burn_token(symbol, &distribution)?; + + // Log event + self.storage.log_event(EventInfo::TokenBurn { + symbol, + distribution: distribution.clone(), + memo, + })?; + + Ok(TokenBurnReturns { distribution }) + } +} diff --git a/src/many-ledger/src/module/ledger_tokens.rs b/src/many-ledger/src/module/ledger_tokens.rs index 35d951cf..24b0a637 100644 --- a/src/many-ledger/src/module/ledger_tokens.rs +++ b/src/many-ledger/src/module/ledger_tokens.rs @@ -1,11 +1,9 @@ -use crate::error; use crate::migration::tokens::TOKEN_MIGRATION; -use crate::module::account::verify_account_role; use crate::module::LedgerModuleImpl; -use crate::storage::LedgerStorage; +use crate::storage::account::verify_acl; use many_error::ManyError; use many_identity::Address; -use many_modules::account; +use many_modules::account::features::tokens::TokenAccountLedger; use many_modules::account::features::TryCreateFeature; use many_modules::account::Role; use many_modules::ledger::{ @@ -16,35 +14,6 @@ use many_modules::ledger::{ }; use many_types::Either; -fn verify_tokens_acl( - storage: &LedgerStorage, - sender: &Address, - addr: &Address, - roles: impl IntoIterator, -) -> Result<(), ManyError> { - if addr != sender { - if let Some(account) = storage.get_account(addr)? { - verify_account_role( - &account, - sender, - account::features::tokens::TokenAccountLedger::ID, - roles, - )?; - } else { - return Err(error::unauthorized()); - } - } - Ok(()) -} - -#[cfg(not(feature = "disable_token_sender_check"))] -fn verify_tokens_sender(sender: &Address, token_identity: Address) -> Result<(), ManyError> { - if *sender != token_identity { - return Err(error::invalid_sender()); - } - Ok(()) -} - impl LedgerTokensModuleBackend for LedgerModuleImpl { fn create( &mut self, @@ -56,7 +25,7 @@ impl LedgerTokensModuleBackend for LedgerModuleImpl { } #[cfg(not(feature = "disable_token_sender_check"))] - verify_tokens_sender( + crate::storage::ledger_tokens::verify_tokens_sender( sender, self.storage .get_identity(crate::storage::ledger_tokens::TOKEN_IDENTITY_ROOT) @@ -64,7 +33,13 @@ impl LedgerTokensModuleBackend for LedgerModuleImpl { )?; if let Some(Either::Left(addr)) = &args.owner { - verify_tokens_acl(&self.storage, sender, addr, [Role::CanTokensCreate])?; + verify_acl( + &self.storage, + sender, + addr, + [Role::CanTokensCreate], + TokenAccountLedger::ID, + )?; } let ticker = &args.summary.ticker; @@ -109,7 +84,13 @@ impl LedgerTokensModuleBackend for LedgerModuleImpl { let current_owner = self.storage.get_owner(&args.symbol)?; match current_owner { Some(addr) => { - verify_tokens_acl(&self.storage, sender, &addr, [Role::CanTokensUpdate])?; + verify_acl( + &self.storage, + sender, + &addr, + [Role::CanTokensUpdate], + TokenAccountLedger::ID, + )?; } None => { return Err(ManyError::unknown( @@ -141,11 +122,12 @@ impl LedgerTokensModuleBackend for LedgerModuleImpl { let current_owner = self.storage.get_owner(&args.symbol)?; match current_owner { Some(addr) => { - verify_tokens_acl( + verify_acl( &self.storage, sender, &addr, [Role::CanTokensAddExtendedInfo], + TokenAccountLedger::ID, )?; } None => { @@ -170,11 +152,12 @@ impl LedgerTokensModuleBackend for LedgerModuleImpl { let current_owner = self.storage.get_owner(&args.symbol)?; match current_owner { Some(addr) => { - verify_tokens_acl( + verify_acl( &self.storage, sender, &addr, [Role::CanTokensRemoveExtendedInfo], + TokenAccountLedger::ID, )?; } None => { diff --git a/src/many-ledger/src/storage.rs b/src/many-ledger/src/storage.rs index 7d8b0abe..63b924ed 100644 --- a/src/many-ledger/src/storage.rs +++ b/src/many-ledger/src/storage.rs @@ -20,6 +20,7 @@ mod idstore; pub mod iterator; mod ledger; mod ledger_commands; +pub mod ledger_mintburn; pub mod ledger_tokens; mod migrations; pub mod multisig; diff --git a/src/many-ledger/src/storage/account.rs b/src/many-ledger/src/storage/account.rs index fa0c4fbe..a9a51e95 100644 --- a/src/many-ledger/src/storage/account.rs +++ b/src/many-ledger/src/storage/account.rs @@ -1,6 +1,6 @@ use crate::error; use crate::migration::tokens::TOKEN_MIGRATION; -use crate::module::account::validate_account; +use crate::module::account::{validate_account, verify_account_role}; use crate::storage::multisig::{ MULTISIG_DEFAULT_EXECUTE_AUTOMATICALLY, MULTISIG_DEFAULT_TIMEOUT_IN_SECS, MULTISIG_MAXIMUM_TIMEOUT_IN_SECS, @@ -8,7 +8,7 @@ use crate::storage::multisig::{ use crate::storage::{LedgerStorage, IDENTITY_ROOT}; use many_error::ManyError; use many_identity::Address; -use many_modules::account::features::{FeatureInfo, FeatureSet}; +use many_modules::account::features::{FeatureId, FeatureInfo, FeatureSet}; use many_modules::account::Role; use many_modules::{account, events}; use many_types::Either; @@ -32,6 +32,23 @@ pub(super) fn key_for_account(id: &Address) -> Vec { format!("/accounts/{id}").into_bytes() } +pub fn verify_acl( + storage: &LedgerStorage, + sender: &Address, + addr: &Address, + roles: impl IntoIterator, + feature_id: FeatureId, +) -> Result<(), ManyError> { + if addr != sender { + if let Some(account) = storage.get_account(addr)? { + verify_account_role(&account, sender, feature_id, roles)?; + } else { + return Err(error::unauthorized()); + } + } + Ok(()) +} + impl LedgerStorage { /// Create the given accounts in the storage from the Account metadata pub fn with_account( diff --git a/src/many-ledger/src/storage/ledger_mintburn.rs b/src/many-ledger/src/storage/ledger_mintburn.rs new file mode 100644 index 00000000..27ef6028 --- /dev/null +++ b/src/many-ledger/src/storage/ledger_mintburn.rs @@ -0,0 +1,131 @@ +use crate::error; +use crate::storage::ledger_tokens::key_for_symbol; +use crate::storage::{key_for_account_balance, LedgerStorage}; +use many_error::ManyError; +use many_modules::ledger::TokenInfoArgs; +use many_types::ledger::{LedgerTokensAddressMap, Symbol, TokenAmount, TokenInfoSupply}; +use merk::{BatchEntry, Op}; +use std::collections::BTreeSet; + +impl LedgerStorage { + pub(crate) fn get_token_supply(&self, symbol: &Symbol) -> Result { + Ok(self + .info_token(TokenInfoArgs { + symbol: *symbol, + extended_info: None, + })? + .info + .supply) + } + + pub fn mint_token( + &mut self, + symbol: Symbol, + distribution: &LedgerTokensAddressMap, + ) -> Result<(), ManyError> { + let mut batch: Vec = Vec::new(); + let mut circulating = TokenAmount::zero(); + let current_supply = self.get_token_supply(&symbol)?; + + for (address, amount) in distribution.iter() { + if amount.is_zero() { + return Err(error::unable_to_distribute_zero(address)); + } + + circulating += amount; + + // Make sure we don't bust the maximum, if any + match ¤t_supply.maximum { + Some(x) if &(¤t_supply.circulating + &circulating) > x => { + return Err(error::over_maximum_supply(symbol, circulating, x)) + } + _ => {} + } + + // Store the new balance to the DB + let new_balance = self + .get_multiple_balances(address, &BTreeSet::from([symbol]))? + .get(&symbol) + .map_or(amount.clone(), |b| b + amount); + let key = key_for_account_balance(address, &symbol); + batch.push((key, Op::Put(new_balance.to_vec()))); + } + + // Update circulating supply + let mut info = self + .info_token(TokenInfoArgs { + symbol, + extended_info: None, + })? + .info; + info.supply.circulating += &circulating; + info.supply.total += circulating; + + batch.push(( + key_for_symbol(&symbol).into(), + Op::Put(minicbor::to_vec(&info).map_err(ManyError::serialization_error)?), + )); + + self.persistent_store + .apply(batch.as_slice()) + .map_err(error::storage_apply_failed)?; + + self.maybe_commit()?; + + Ok(()) + } + + pub fn burn_token( + &mut self, + symbol: Symbol, + distribution: &LedgerTokensAddressMap, + ) -> Result<(), ManyError> { + let mut batch: Vec = Vec::new(); + let mut circulating = TokenAmount::zero(); + + for (address, amount) in distribution.iter() { + if amount.is_zero() { + return Err(error::unable_to_distribute_zero(address)); + } + + // Check if we have enough funds + let balance_amount = match self + .get_multiple_balances(address, &BTreeSet::from_iter([symbol]))? + .get(&symbol) + { + Some(x) if x < amount => Err(error::missing_funds(symbol, amount, x)), + Some(x) => Ok(x.clone()), + None => Err(error::missing_funds(symbol, amount, TokenAmount::zero())), + }?; + + // Store new balance in DB + let new_balance = &balance_amount - amount; + let key = key_for_account_balance(address, &symbol); + batch.push((key, Op::Put(new_balance.to_vec()))); + circulating += amount; + } + + // Update circulating supply + let mut info = self + .info_token(TokenInfoArgs { + symbol, + extended_info: None, + })? + .info; + info.supply.circulating -= &circulating; + info.supply.total -= circulating; + + batch.push(( + key_for_symbol(&symbol).into(), + Op::Put(minicbor::to_vec(&info).map_err(ManyError::serialization_error)?), + )); + + self.persistent_store + .apply(batch.as_slice()) + .map_err(error::storage_apply_failed)?; + + self.maybe_commit()?; + + Ok(()) + } +} diff --git a/src/many-ledger/src/storage/ledger_tokens.rs b/src/many-ledger/src/storage/ledger_tokens.rs index 5dae7c00..6b0e6ef1 100644 --- a/src/many-ledger/src/storage/ledger_tokens.rs +++ b/src/many-ledger/src/storage/ledger_tokens.rs @@ -21,8 +21,8 @@ pub const SYMBOLS_ROOT_DASH: &str = const_format::concatcp!(SYMBOLS_ROOT, "/"); pub const TOKEN_IDENTITY_ROOT: &str = "/config/token_identity"; pub const TOKEN_SUBRESOURCE_COUNTER_ROOT: &str = "/config/token_subresource_id"; -pub fn key_for_symbol(symbol: &Symbol) -> Vec { - format!("/config/symbols/{symbol}").into_bytes() +pub fn key_for_symbol(symbol: &Symbol) -> String { + format!("/config/symbols/{symbol}") } pub fn key_for_ext_info(symbol: &Symbol) -> Vec { @@ -36,6 +36,13 @@ pub struct SymbolMeta { pub maximum: Option, } +pub fn verify_tokens_sender(sender: &Address, token_identity: Address) -> Result<(), ManyError> { + if *sender != token_identity { + return Err(error::invalid_sender()); + } + Ok(()) +} + impl LedgerStorage { #[inline] fn _total_supply( @@ -117,7 +124,7 @@ impl LedgerStorage { ), )); batch.push(( - key_for_symbol(&k), + key_for_symbol(&k).into(), Op::Put(minicbor::to_vec(info).map_err(ManyError::serialization_error)?), )); } @@ -148,7 +155,7 @@ impl LedgerStorage { pub(crate) fn get_owner(&self, symbol: &Symbol) -> Result, ManyError> { let token_info_enc = self .persistent_store - .get(&key_for_symbol(symbol)) + .get(key_for_symbol(symbol).as_bytes()) .map_err(error::storage_get_failed)? .ok_or_else(|| error::token_info_not_found(symbol))?; @@ -257,7 +264,7 @@ impl LedgerStorage { owner: maybe_owner, }; batch.push(( - key_for_symbol(&symbol), + key_for_symbol(&symbol).into(), Op::Put(minicbor::to_vec(&info).map_err(ManyError::serialization_error)?), )); @@ -298,7 +305,7 @@ impl LedgerStorage { // Try fetching the token info from the persistent storage let token_info_enc = self .persistent_store - .get(&key_for_symbol(&symbol)) + .get(key_for_symbol(&symbol).as_bytes()) .map_err(ManyError::unknown)? .ok_or_else(|| error::token_info_not_found(symbol))?; @@ -344,7 +351,7 @@ impl LedgerStorage { // Try fetching the token info from the persistent storage if let Some(enc) = self .persistent_store - .get(&key_for_symbol(&symbol)) + .get(key_for_symbol(&symbol).as_bytes()) .map_err(ManyError::unknown)? { let mut info: TokenInfo = minicbor::decode(&enc).unwrap(); @@ -369,7 +376,7 @@ impl LedgerStorage { self.persistent_store .apply(&[( - key_for_symbol(&symbol), + key_for_symbol(&symbol).into(), Op::Put(minicbor::to_vec(&info).map_err(ManyError::serialization_error)?), )]) .map_err(error::storage_apply_failed)?; diff --git a/src/many-ledger/test-macros/src/lib.rs b/src/many-ledger/test-macros/src/lib.rs index 72b088cd..2ebb7eb6 100644 --- a/src/many-ledger/test-macros/src/lib.rs +++ b/src/many-ledger/test-macros/src/lib.rs @@ -19,9 +19,17 @@ fn impl_many_world_macro(ast: &syn::DeriveInput) -> TokenStream { self.setup.id } - fn module_impl(&mut self) -> &mut LedgerModuleImpl { + fn module_impl(&self) -> &LedgerModuleImpl { + &self.setup.module_impl + } + + fn module_impl_mut(&mut self) -> &mut LedgerModuleImpl { &mut self.setup.module_impl } + + fn error(&self) -> &Option { + &self.error + } } }; gen.into() @@ -48,6 +56,10 @@ fn impl_token_world_macro(ast: &syn::DeriveInput) -> TokenStream { fn info_mut(&mut self) -> &mut TokenInfo { &mut self.info } + + fn ext_info_mut(&mut self) -> &mut TokenExtendedInfo { + &mut self.ext_info + } } }; gen.into() diff --git a/src/many-ledger/test-utils/Cargo.toml b/src/many-ledger/test-utils/Cargo.toml index b78b6f9e..f0413c16 100644 --- a/src/many-ledger/test-utils/Cargo.toml +++ b/src/many-ledger/test-utils/Cargo.toml @@ -13,14 +13,14 @@ publish = false coset = "0.3" cucumber = { version = "0.17.0", features = ["libtest"] } itertools = "0.10.3" -many-error = { git = "https://github.com/liftedinit/many-rs.git", rev = "71eba1a1cfee506505acec865f5984afab0d3e74" } -many-identity = { git = "https://github.com/liftedinit/many-rs.git", rev = "71eba1a1cfee506505acec865f5984afab0d3e74", features = ["default", "serde", "testing"] } -many-identity-dsa = { git = "https://github.com/liftedinit/many-rs.git", rev = "71eba1a1cfee506505acec865f5984afab0d3e74", features = ["ed25519", "ecdsa", "testing"] } +many-error = { git = "https://github.com/liftedinit/many-rs.git", rev = "ce03b88dea51232ca578d19d52cfc263cfc4080b" } +many-identity = { git = "https://github.com/liftedinit/many-rs.git", rev = "ce03b88dea51232ca578d19d52cfc263cfc4080b", features = ["default", "serde", "testing"] } +many-identity-dsa = { git = "https://github.com/liftedinit/many-rs.git", rev = "ce03b88dea51232ca578d19d52cfc263cfc4080b", features = ["ed25519", "ecdsa", "testing"] } many-ledger = { path = "..", features = ["balance_testing"] } -many-migration = { git = "https://github.com/liftedinit/many-rs.git", rev = "71eba1a1cfee506505acec865f5984afab0d3e74" } -many-modules = { git = "https://github.com/liftedinit/many-rs.git", rev = "71eba1a1cfee506505acec865f5984afab0d3e74", features = ["cucumber"] } -many-protocol = { git = "https://github.com/liftedinit/many-rs.git", rev = "71eba1a1cfee506505acec865f5984afab0d3e74" } -many-types = { git = "https://github.com/liftedinit/many-rs.git", rev = "71eba1a1cfee506505acec865f5984afab0d3e74", features = ["cucumber"] } +many-migration = { git = "https://github.com/liftedinit/many-rs.git", rev = "ce03b88dea51232ca578d19d52cfc263cfc4080b" } +many-modules = { git = "https://github.com/liftedinit/many-rs.git", rev = "ce03b88dea51232ca578d19d52cfc263cfc4080b", features = ["cucumber"] } +many-protocol = { git = "https://github.com/liftedinit/many-rs.git", rev = "ce03b88dea51232ca578d19d52cfc263cfc4080b" } +many-types = { git = "https://github.com/liftedinit/many-rs.git", rev = "ce03b88dea51232ca578d19d52cfc263cfc4080b", features = ["cucumber"] } merk = { git = "https://github.com/liftedinit/merk.git", rev = "3d509c8efd3a68d85a5769f7fff300e10290d137" } minicbor = { version = "0.18.0", features = ["derive", "std"] } once_cell = "1.12" diff --git a/src/many-ledger/test-utils/src/cucumber.rs b/src/many-ledger/test-utils/src/cucumber.rs index 4dca4c9b..15e88073 100644 --- a/src/many-ledger/test-utils/src/cucumber.rs +++ b/src/many-ledger/test-utils/src/cucumber.rs @@ -1,5 +1,5 @@ use cucumber::Parameter; -use many_error::ManyError; +use many_error::{ManyError, ManyErrorCode}; use many_identity::testing::identity; use many_identity::{Address, Identity}; use many_identity_dsa::ecdsa::generate_random_ecdsa_identity; @@ -10,15 +10,19 @@ use many_modules::account::features::{FeatureInfo, FeatureSet}; use many_modules::account::{ AccountModuleBackend, AddRolesArgs, CreateArgs, RemoveRolesArgs, Role, }; -use many_modules::ledger::LedgerTokensModuleBackend; +use many_modules::ledger::extended_info::TokenExtendedInfo; +use many_modules::ledger::{LedgerTokensModuleBackend, TokenInfoArgs}; use many_types::cbor::CborNull; -use many_types::ledger::{TokenInfo, TokenMaybeOwner}; +use many_types::ledger::{TokenAmount, TokenInfo, TokenMaybeOwner}; use std::collections::{BTreeMap, BTreeSet}; +use std::fmt::Debug; use std::str::FromStr; pub trait LedgerWorld { fn setup_id(&self) -> Address; - fn module_impl(&mut self) -> &mut LedgerModuleImpl; + fn module_impl(&self) -> &LedgerModuleImpl; + fn module_impl_mut(&mut self) -> &mut LedgerModuleImpl; + fn error(&self) -> &Option; } pub trait AccountWorld { @@ -29,12 +33,13 @@ pub trait AccountWorld { pub trait TokenWorld { fn info(&self) -> &TokenInfo; fn info_mut(&mut self) -> &mut TokenInfo; + fn ext_info_mut(&mut self) -> &mut TokenExtendedInfo; } #[derive(Debug, Default, Eq, Parameter, PartialEq)] #[param( name = "id", - regex = "(myself)|id ([0-9])|(random)|(anonymous)|(the account)|(no one)" + regex = r"(myself)|id (\d+)|(random)|(anonymous)|(the account)|(token identity)|(no one)" )] pub enum SomeId { Id(u32), @@ -43,6 +48,7 @@ pub enum SomeId { Anonymous, Random, Account, + TokenIdentity, NoOne, } @@ -55,6 +61,7 @@ impl FromStr for SomeId { "anonymous" => Self::Anonymous, "random" => Self::Random, "the account" => Self::Account, + "token identity" => Self::TokenIdentity, "no one" => Self::NoOne, id => Self::Id(id.parse().expect("Unable to parse identity id")), }) @@ -69,6 +76,10 @@ impl SomeId { SomeId::Anonymous => Address::anonymous(), SomeId::Random => generate_random_ecdsa_identity().address(), SomeId::Account => w.account(), + // `id1` Address + SomeId::TokenIdentity => { + Address::from_str("maffbahksdwaqeenayy2gxke32hgb7aq4ao4wt745lsfs6wijp").unwrap() + } _ => unimplemented!(), } } @@ -81,16 +92,22 @@ impl SomeId { } } +// TODO: Split or refactor SomeError. It doesn't scale well #[derive(Debug, Default, Eq, Parameter, PartialEq)] #[param( name = "error", - regex = "(unauthorized)|missing permission ([a-z ]+)|(immutable)" + regex = "(unauthorized)|(missing permission)|(immutable)|(invalid sender)|(unable to distribute zero)|(partial burn disabled)|(missing funds)|(over maximum)" )] pub enum SomeError { #[default] Unauthorized, - MissingPermission(SomePermission), + MissingPermission, Immutable, + InvalidSender, + UnableToDistributeZero, + PartialBurnDisabled, + MissingFunds, + OverMaximum, } impl FromStr for SomeError { @@ -99,11 +116,14 @@ impl FromStr for SomeError { fn from_str(s: &str) -> Result { Ok(match s { "unauthorized" => Self::Unauthorized, + "missing permission" => Self::MissingPermission, "immutable" => Self::Immutable, - permission => Self::MissingPermission( - SomePermission::from_str(permission) - .expect("Unable to convert string to permission"), - ), + "invalid sender" => Self::InvalidSender, + "unable to distribute zero" => Self::UnableToDistributeZero, + "partial burn disabled" => Self::PartialBurnDisabled, + "missing funds" => Self::MissingFunds, + "over maximum" => Self::OverMaximum, + _ => unimplemented!(), }) } } @@ -119,6 +139,7 @@ pub enum SomePermission { AddExtInfo, RemoveExtInfo, Mint, + Burn, } impl FromStr for SomePermission { @@ -128,6 +149,7 @@ impl FromStr for SomePermission { Ok(match s { "token creation" => Self::Create, "token mint" => Self::Mint, + "token burn" => Self::Burn, "token update" => Self::Update, "token add extended info" => Self::AddExtInfo, "token remove extended info" => Self::RemoveExtInfo, @@ -137,13 +159,18 @@ impl FromStr for SomePermission { } impl SomeError { - pub fn as_many(&self) -> ManyError { + pub fn as_many_code(&self) -> ManyErrorCode { match self { - SomeError::Unauthorized => error::unauthorized(), - SomeError::MissingPermission(permission) => { - account::errors::user_needs_role(permission.as_role()) - } - SomeError::Immutable => ManyError::unknown("Unable to update, this token is immutable"), // TODO: Custom error + SomeError::Unauthorized => error::unauthorized().code(), + SomeError::MissingPermission => account::errors::user_needs_role("").code(), + SomeError::Immutable => { + ManyError::unknown("Unable to update, this token is immutable").code() + } // TODO: Custom error + SomeError::InvalidSender => error::invalid_sender().code(), + SomeError::UnableToDistributeZero => error::unable_to_distribute_zero("").code(), + SomeError::PartialBurnDisabled => error::partial_burn_disabled().code(), + SomeError::MissingFunds => error::missing_funds(Address::anonymous(), "", "").code(), + SomeError::OverMaximum => error::over_maximum_supply("", "", "").code(), } } } @@ -153,6 +180,7 @@ impl SomePermission { match self { SomePermission::Create => Role::CanTokensCreate, SomePermission::Mint => Role::CanTokensMint, + SomePermission::Burn => Role::CanTokensBurn, SomePermission::Update => Role::CanTokensUpdate, SomePermission::AddExtInfo => Role::CanTokensAddExtendedInfo, SomePermission::RemoveExtInfo => Role::CanTokensRemoveExtendedInfo, @@ -163,7 +191,7 @@ impl SomePermission { pub fn given_token_account(w: &mut T) { let sender = w.setup_id(); let account = AccountModuleBackend::create( - w.module_impl(), + w.module_impl_mut(), &sender, CreateArgs { description: Some("Token Account".into()), @@ -182,7 +210,7 @@ pub fn given_account_id_owner(w: &mut T, id: Some let sender = w.setup_id(); let account = w.account(); AccountModuleBackend::add_roles( - w.module_impl(), + w.module_impl_mut(), &sender, AddRolesArgs { account, @@ -194,7 +222,7 @@ pub fn given_account_id_owner(w: &mut T, id: Some if id != w.setup_id() { let account = w.account(); AccountModuleBackend::remove_roles( - w.module_impl(), + w.module_impl_mut(), &sender, RemoveRolesArgs { account, @@ -214,7 +242,7 @@ pub fn given_account_part_of_can_create( let sender = w.setup_id(); let account = w.account(); AccountModuleBackend::add_roles( - w.module_impl(), + w.module_impl_mut(), &sender, AddRolesArgs { account, @@ -224,17 +252,67 @@ pub fn given_account_part_of_can_create( .expect("Unable to add role to account"); } -pub fn create_default_token(w: &mut T, id: SomeId) { +fn _create_default_token( + w: &mut T, + id: SomeId, + max_supply: Option, +) { let (id, owner) = if let Some(id) = id.as_maybe_address(w) { (id, TokenMaybeOwner::Left(id)) } else { (w.setup_id(), TokenMaybeOwner::Right(CborNull)) }; let result = LedgerTokensModuleBackend::create( - w.module_impl(), + w.module_impl_mut(), &id, - crate::default_token_create_args(Some(owner)), + crate::default_token_create_args(Some(owner), max_supply), ) .expect("Unable to create default token"); *w.info_mut() = result.info; } + +pub fn create_default_token_unlimited( + w: &mut T, + id: SomeId, +) { + _create_default_token(w, id, None); +} + +pub fn create_default_token(w: &mut T, id: SomeId) { + _create_default_token(w, id, Some(TokenAmount::from(100000000u64))); +} + +pub fn verify_error_role>(w: &mut T, role: U) +where + U::Error: Debug, +{ + let err_addr = Role::try_from(w.error().as_ref().unwrap().argument("role").unwrap()).unwrap(); + assert_eq!(err_addr, role.try_into().unwrap()) +} + +pub fn verify_error_addr>(w: &mut T, addr: U) +where + U::Error: Debug, +{ + let err_addr = + Address::try_from(w.error().as_ref().unwrap().argument("symbol").unwrap()).unwrap(); + assert_eq!(err_addr, addr.try_into().unwrap()) +} + +pub fn verify_error_code(w: &mut T, code: ManyErrorCode) { + assert_eq!(w.error().as_ref().expect("Expecting an error").code(), code); +} + +pub fn refresh_token_info(w: &mut T) { + let result = LedgerTokensModuleBackend::info( + w.module_impl(), + &w.setup_id(), + TokenInfoArgs { + symbol: w.info().symbol, + ..Default::default() + }, + ) + .expect("Unable to query token info"); + *w.info_mut() = result.info; + *w.ext_info_mut() = result.extended_info; +} diff --git a/src/many-ledger/test-utils/src/lib.rs b/src/many-ledger/test-utils/src/lib.rs index b7feb933..2c374458 100644 --- a/src/many-ledger/test-utils/src/lib.rs +++ b/src/many-ledger/test-utils/src/lib.rs @@ -36,7 +36,10 @@ use std::{ str::FromStr, }; -pub fn default_token_create_args(owner: Option) -> TokenCreateArgs { +pub fn default_token_create_args( + owner: Option, + maximum_supply: Option, +) -> TokenCreateArgs { let mut logos = VisualTokenLogo::new(); logos.unicode_front('∑'); TokenCreateArgs { @@ -51,7 +54,7 @@ pub fn default_token_create_args(owner: Option) -> TokenCreateA (identity(2), TokenAmount::from(456u64)), (identity(3), TokenAmount::from(789u64)), ])), - maximum_supply: Some(TokenAmount::from(100000000u64)), + maximum_supply, extended_info: Some( TokenExtendedInfo::new() .with_memo("Foofoo".try_into().unwrap()) diff --git a/src/many-ledger/tests/events.rs b/src/many-ledger/tests/events.rs index 2c65c313..ac36fe23 100644 --- a/src/many-ledger/tests/events.rs +++ b/src/many-ledger/tests/events.rs @@ -224,45 +224,8 @@ fn list_filter_kind() { assert_eq!(list_return.nb_events, 1); assert_eq!(list_return.events.len(), 1); assert_eq!(list_return.events[0].kind(), events::EventKind::Send); - assert_eq!(list_return.events[0].symbol(), Some(&*MFX_SYMBOL)); - assert!(list_return.events[0].is_about(&id)); -} - -#[test] -fn list_filter_symbol() { - let Setup { - mut module_impl, - id, - .. - } = setup(); - send(&mut module_impl, id, identity(1)); - let result = module_impl.list(events::ListArgs { - count: None, - order: None, - filter: Some(events::EventFilter { - symbol: Some(vec![*MFX_SYMBOL].into()), - ..events::EventFilter::default() - }), - }); - assert!(result.is_ok()); - let list_return = result.unwrap(); - assert_eq!(list_return.nb_events, 1); - assert_eq!(list_return.events.len(), 1); - assert_eq!(list_return.events[0].kind(), events::EventKind::Send); - assert_eq!(list_return.events[0].symbol(), Some(&*MFX_SYMBOL)); - assert!(list_return.events[0].is_about(&id)); - - let result = module_impl.list(events::ListArgs { - count: None, - order: None, - filter: Some(events::EventFilter { - symbol: Some(vec![identity(100)].into()), - ..events::EventFilter::default() - }), - }); - assert!(result.is_ok()); - let list_return = result.unwrap(); - assert_eq!(list_return.events.len(), 0); + assert!(list_return.events[0].is_about(*MFX_SYMBOL)); + assert!(list_return.events[0].is_about(id)); } #[test] @@ -294,8 +257,8 @@ fn list_filter_date() { assert_eq!(list_return.nb_events, 1); assert_eq!(list_return.events.len(), 1); assert_eq!(list_return.events[0].kind(), events::EventKind::Send); - assert_eq!(list_return.events[0].symbol(), Some(&*MFX_SYMBOL)); - assert!(list_return.events[0].is_about(&id)); + assert!(list_return.events[0].is_about(*MFX_SYMBOL)); + assert!(list_return.events[0].is_about(id)); // TODO: Remove this when we support factional seconds // See https://github.com/liftedinit/many-rs/issues/110 diff --git a/src/many-ledger/tests/features/ledger_mintburn/burn.feature b/src/many-ledger/tests/features/ledger_mintburn/burn.feature new file mode 100644 index 00000000..1b14b36f --- /dev/null +++ b/src/many-ledger/tests/features/ledger_mintburn/burn.feature @@ -0,0 +1,87 @@ +Feature: Burn token + +@tokens +Scenario: Burn tokens + Given a default token owned by myself + And a distribution of 12 tokens to id 2 + And a distribution of 23 tokens to id 3 + And a memo "Barfoo" + When I burn the tokens as token identity + Then id 1 has 123 tokens + And id 2 has 444 tokens + And id 3 has 766 tokens + And the circulating supply is 1333 tokens + And the total supply is 1333 tokens + And the memo is "Barfoo" + +@tokens +Scenario: Burn tokens as myself/random/anonymous + Given a default token owned by myself + And a distribution of 12 tokens to id 2 + And a distribution of 23 tokens to id 3 + Then burning as myself fails with invalid sender + Then burning as random fails with invalid sender + Then burning as anonymous fails with invalid sender + Then id 1 has 123 tokens + And id 2 has 456 tokens + And id 3 has 789 tokens + And the circulating supply is 1368 tokens + And the total supply is 1368 tokens + +@tokens +Scenario: Unable to burn zero + Given a default token owned by myself + And a distribution of 0 tokens to id 2 + Then burning as token identity fails with unable to distribute zero + And the error address is id 2 + Then id 1 has 123 tokens + And id 2 has 456 tokens + And id 3 has 789 tokens + And the circulating supply is 1368 tokens + And the total supply is 1368 tokens + +@tokens +Scenario: Partial burn is disabled + Given a default token owned by myself + And a distribution of 1234 tokens to id 2 + And partial burn is enabled + Then burning as token identity fails with partial burn disabled + Then id 1 has 123 tokens + And id 2 has 456 tokens + And id 3 has 789 tokens + And the circulating supply is 1368 tokens + And the total supply is 1368 tokens + +@tokens +Scenario: Burn more funds than held + Given a default token owned by myself + And a distribution of 1234 tokens to id 2 + Then burning as token identity fails with missing funds + Then id 1 has 123 tokens + And id 2 has 456 tokens + And id 3 has 789 tokens + And the circulating supply is 1368 tokens + And the total supply is 1368 tokens + +@tokens +Scenario: Burn all circulating supply + Given a default token owned by myself + And a distribution of 123 tokens to id 1 + And a distribution of 456 tokens to id 2 + And a distribution of 789 tokens to id 3 + When I burn the tokens as token identity + Then id 1 has 0 tokens + And id 2 has 0 tokens + And id 3 has 0 tokens + And the circulating supply is 0 tokens + And the total supply is 0 tokens + +@tokens +Scenario: Burn more than circulating supply + Given a default token owned by myself + And a distribution of 124 tokens to id 1 + And a distribution of 456 tokens to id 2 + And a distribution of 789 tokens to id 3 + Then burning as token identity fails with missing funds + And the circulating supply is 1368 tokens + And the total supply is 1368 tokens diff --git a/src/many-ledger/tests/features/ledger_mintburn/mint.feature b/src/many-ledger/tests/features/ledger_mintburn/mint.feature new file mode 100644 index 00000000..0e5cdd4c --- /dev/null +++ b/src/many-ledger/tests/features/ledger_mintburn/mint.feature @@ -0,0 +1,79 @@ +Feature: Mint token + +@tokens +Scenario: Mint new tokens as token identity + Given a default token owned by myself + And a distribution of 1000 tokens to id 10 + And a distribution of 250 tokens to id 11 + And a memo "Foobar" + When I mint the tokens as token identity + Then id 1 has 123 tokens + And id 2 has 456 tokens + And id 3 has 789 tokens + And id 10 has 1000 tokens + And id 11 has 250 tokens + And myself has 0 tokens + And the circulating supply is 2618 tokens + And the total supply is 2618 tokens + And the memo is "Foobar" + +@tokens +Scenario: Mint new tokens as myself/random/anonymous + Given a default token owned by myself + And a distribution of 1000 tokens to id 10 + And a distribution of 250 tokens to id 11 + Then minting as myself fails with invalid sender + Then minting as random fails with invalid sender + Then minting as anonymous fails with invalid sender + Then id 1 has 123 tokens + And id 2 has 456 tokens + And id 3 has 789 tokens + And the circulating supply is 1368 tokens + And the total supply is 1368 tokens + +@tokens +Scenario: Unable to mint zero + Given a default token owned by myself + And a distribution of 0 tokens to id 10 + Then minting as token identity fails with unable to distribute zero + And the error address is id 10 + Then id 1 has 123 tokens + And id 2 has 456 tokens + And id 3 has 789 tokens + And the circulating supply is 1368 tokens + And the total supply is 1368 tokens + +@tokens +Scenario: Mint more than maximum supply + Given a default token owned by myself + And a distribution of 99998633 tokens to id 10 + Then minting as token identity fails with over maximum + Then id 1 has 123 tokens + And id 2 has 456 tokens + And id 3 has 789 tokens + And the circulating supply is 1368 tokens + And the total supply is 1368 tokens + +@tokens +Scenario: Mint the maximum supply + Given a default token owned by myself + And a distribution of 99998632 tokens to id 10 + When I mint the tokens as token identity + Then id 1 has 123 tokens + And id 2 has 456 tokens + And id 3 has 789 tokens + And id 10 has 99998632 tokens + And the circulating supply is 100000000 tokens + And the total supply is 100000000 tokens + +@tokens +Scenario: Unlimited maximum supply + Given a default token of unlimited supply owned by myself + And a distribution of 100000000 tokens to id 10 + When I mint the tokens as token identity + Then id 1 has 123 tokens + And id 2 has 456 tokens + And id 3 has 789 tokens + And id 10 has 100000000 tokens + And the circulating supply is 100001368 tokens + And the total supply is 100001368 tokens diff --git a/src/many-ledger/tests/features/ledger_tokens/add_token_ext_info.feature b/src/many-ledger/tests/features/ledger_tokens/add_token_ext_info.feature index 5705c5bc..61156448 100644 --- a/src/many-ledger/tests/features/ledger_tokens/add_token_ext_info.feature +++ b/src/many-ledger/tests/features/ledger_tokens/add_token_ext_info.feature @@ -55,7 +55,8 @@ Scenario: Adding ext. info to a token, sender is myself, token owner is account Given a token account And id 5 as the account owner And a default token owned by the account - Then adding extended info to the token as myself fails with missing permission token add extended info + Then adding extended info to the token as myself fails with missing permission + And the error role is canTokensAddExtendedInfo @tokens Scenario: Adding ext. info to a token, sender is myself, token owner is account I'm the owner of @@ -80,4 +81,5 @@ Scenario: Adding ext. info to a token, sender is some id, token owner is account Given a token account And id 6 has token mint permission And a default token owned by the account - Then adding extended info to the token as id 6 fails with missing permission token add extended info + Then adding extended info to the token as id 6 fails with missing permission + And the error role is canTokensAddExtendedInfo diff --git a/src/many-ledger/tests/features/ledger_tokens/create_token.feature b/src/many-ledger/tests/features/ledger_tokens/create_token.feature index 7cc62bab..159fddc6 100644 --- a/src/many-ledger/tests/features/ledger_tokens/create_token.feature +++ b/src/many-ledger/tests/features/ledger_tokens/create_token.feature @@ -40,7 +40,8 @@ Scenario: Creating a new token, sender is myself, token owner is account I'm not Given a token account And id 5 as the account owner And setting the account as the owner - Then creating the token as myself fails with missing permission token creation + Then creating the token as myself fails with missing permission + And the error role is canTokensCreate @tokens Scenario: Creating a new token, sender is myself, token owner is account I'm the owner of @@ -63,7 +64,8 @@ Scenario: Creating a new token, sender is some id, token owner is account where Given a token account And id 6 has token mint permission And setting the account as the owner - Then creating the token as id 6 fails with missing permission token creation + Then creating the token as id 6 fails with missing permission + And the error role is canTokensCreate @tokens Scenario: Creating a new token without owner (owner is sender) diff --git a/src/many-ledger/tests/features/ledger_tokens/remove_token_ext_info.feature b/src/many-ledger/tests/features/ledger_tokens/remove_token_ext_info.feature index 56a73d48..07015c7e 100644 --- a/src/many-ledger/tests/features/ledger_tokens/remove_token_ext_info.feature +++ b/src/many-ledger/tests/features/ledger_tokens/remove_token_ext_info.feature @@ -59,7 +59,8 @@ Scenario: Remove ext. info to a token, sender is myself, token owner is account And id 5 as the account owner And a default token owned by the account And the token has a memo - Then removing extended info memo as myself fails with missing permission token remove extended info + Then removing extended info memo as myself fails with missing permission + And the error role is canTokensRemoveExtendedInfo @tokens Scenario: Remove ext. info to a token, sender is myself, token owner is account I'm the owner of @@ -85,4 +86,5 @@ Scenario: Remove ext. info to a token, sender is some id, token owner is account And id 6 has token mint permission And a default token owned by the account And the token has a logo - Then removing extended info logo as id 6 fails with missing permission token remove extended info + Then removing extended info logo as id 6 fails with missing permission + And the error role is canTokensRemoveExtendedInfo diff --git a/src/many-ledger/tests/features/ledger_tokens/update_token.feature b/src/many-ledger/tests/features/ledger_tokens/update_token.feature index deba7416..a9d51813 100644 --- a/src/many-ledger/tests/features/ledger_tokens/update_token.feature +++ b/src/many-ledger/tests/features/ledger_tokens/update_token.feature @@ -62,7 +62,8 @@ Scenario: Updating a token, sender is myself, token owner is account I'm not par Given a token account And id 5 as the account owner And a default token owned by the account - Then updating the token as myself fails with missing permission token update + Then updating the token as myself fails with missing permission + And the error role is canTokensUpdate @tokens Scenario: Updating a token, sender is myself, token owner is account I'm the owner of @@ -85,7 +86,8 @@ Scenario: Updating a token, sender is some id, token owner is account where some Given a token account And id 6 has token mint permission And a default token owned by the account - Then updating the token as id 6 fails with missing permission token update + Then updating the token as id 6 fails with missing permission + And the error role is canTokensUpdate @tokens Scenario: Removing a token's owner diff --git a/src/many-ledger/tests/ledger_mintburn/burn.rs b/src/many-ledger/tests/ledger_mintburn/burn.rs new file mode 100644 index 00000000..32eb49d4 --- /dev/null +++ b/src/many-ledger/tests/ledger_mintburn/burn.rs @@ -0,0 +1,148 @@ +use cucumber::{given, then, when, World}; +use many_error::ManyError; +use many_identity::Address; +use many_ledger::migration::tokens::TOKEN_MIGRATION; +use many_ledger::module::LedgerModuleImpl; +use many_ledger_test_macros::*; +use many_ledger_test_utils::cucumber::{ + refresh_token_info, verify_error_addr, verify_error_code, AccountWorld, LedgerWorld, SomeError, + SomeId, TokenWorld, +}; +use many_ledger_test_utils::Setup; +use many_modules::events::{EventFilter, EventKind, EventsModuleBackend, ListArgs}; +use many_modules::ledger::extended_info::TokenExtendedInfo; +use many_modules::ledger::{ + BalanceArgs, LedgerMintBurnModuleBackend, LedgerModuleBackend, TokenBurnArgs, +}; +use many_types::ledger::{TokenAmount, TokenInfo}; +use many_types::Memo; +use std::path::Path; + +#[derive(World, Debug, Default, LedgerWorld, TokenWorld, AccountWorld)] +#[world(init = Self::new)] +struct BurnWorld { + setup: Setup, + args: TokenBurnArgs, + info: TokenInfo, + ext_info: TokenExtendedInfo, + account: Address, + error: Option, +} + +impl BurnWorld { + fn new() -> Self { + Self { + setup: Setup::new_with_migrations(false, [(0, &TOKEN_MIGRATION)], true), + ..Default::default() + } + } +} + +fn fail_burn_token(w: &mut BurnWorld, sender: &Address) { + w.error = Some( + LedgerMintBurnModuleBackend::burn(&mut w.setup.module_impl, sender, w.args.clone()) + .expect_err("Token burning was supposed to fail, it succeeded instead."), + ); +} + +#[given(expr = "a default token owned by {id}")] +fn create_default_token(w: &mut BurnWorld, id: SomeId) { + many_ledger_test_utils::cucumber::create_default_token(w, id); + w.args.symbol = w.info.symbol; +} + +#[given(expr = "a distribution of {int} tokens to {id}")] +fn distribution_of(w: &mut BurnWorld, amount: u64, id: SomeId) { + w.args.distribution.insert(id.as_address(w), amount.into()); +} + +#[given(expr = "a memo {string}")] +fn a_memo(w: &mut BurnWorld, memo: String) { + w.args.memo = Some(Memo::try_from(memo).expect("Unable to create memo")); +} + +#[given(expr = "partial burn is enabled")] +fn partial_burn(w: &mut BurnWorld) { + w.args.error_on_under_burn = Some(false); +} + +#[when(expr = "I burn the tokens as {id}")] +fn mint_tokens(w: &mut BurnWorld, id: SomeId) { + let sender = id.as_address(w); + LedgerMintBurnModuleBackend::burn(&mut w.setup.module_impl, &sender, w.args.clone()) + .expect("Unable to mint tokens"); + refresh_token_info(w); +} + +#[then(expr = "{id} has {int} tokens")] +fn id_has_tokens(w: &mut BurnWorld, id: SomeId, amount: u64) { + let addr = id.as_address(w); + let res = LedgerModuleBackend::balance( + &w.setup.module_impl, + &Address::anonymous(), + BalanceArgs { + account: Some(addr), + symbols: Some(vec![w.info.symbol].into()), + }, + ) + .unwrap_or_else(|_| panic!("Unable to fetch balance for {addr}")); + let amount: TokenAmount = amount.into(); + let zero = TokenAmount::zero(); + let balance = res.balances.get(&w.info.symbol).unwrap_or(&zero); + assert_eq!(*balance, amount); +} + +#[then(expr = "the circulating supply is {int} tokens")] +fn circulating_supply(w: &mut BurnWorld, amount: u64) { + let amount: TokenAmount = amount.into(); + assert_eq!(w.info.supply.circulating, amount); +} + +#[then(expr = "the total supply is {int} tokens")] +fn total_supply(w: &mut BurnWorld, amount: u64) { + let amount: TokenAmount = amount.into(); + assert_eq!(w.info.supply.total, amount); +} + +#[then(expr = "the memo is {string}")] +fn memo_is(w: &mut BurnWorld, memo: String) { + let res = EventsModuleBackend::list( + &w.setup.module_impl, + ListArgs { + filter: Some(EventFilter { + kind: Some(vec![EventKind::TokenBurn].into()), + ..Default::default() + }), + ..Default::default() + }, + ) + .expect("Unable to list TokenMint event"); + let memo = Memo::try_from(memo).unwrap(); + assert!(res.nb_events >= 1); + let event = res.events.into_iter().next().expect("Expected an event"); + assert!(event.content.memo().is_some()); + assert_eq!(event.content.memo().unwrap(), &memo); +} + +#[then(expr = "burning as {id} fails with {error}")] +fn minting_fails(w: &mut BurnWorld, id: SomeId, error: SomeError) { + let id = id.as_address(w); + fail_burn_token(w, &id); + verify_error_code(w, error.as_many_code()) +} + +#[then(expr = "the error address is {id}")] +fn error_address_is(w: &mut BurnWorld, id: SomeId) { + verify_error_addr(w, id.as_address(w)); +} + +#[tokio::main] +async fn main() { + // Support both Cargo and Bazel paths + let features = ["tests/features", "src/many-ledger/tests/features"] + .into_iter() + .find(|&p| Path::new(p).exists()) + .expect("Cucumber test features not found"); + + BurnWorld::run(Path::new(features).join("ledger_mintburn/burn.feature")).await; +} diff --git a/src/many-ledger/tests/ledger_mintburn/mint.rs b/src/many-ledger/tests/ledger_mintburn/mint.rs new file mode 100644 index 00000000..03aefa66 --- /dev/null +++ b/src/many-ledger/tests/ledger_mintburn/mint.rs @@ -0,0 +1,149 @@ +use cucumber::{given, then, when, World}; +use many_error::ManyError; +use many_identity::Address; +use many_ledger::migration::tokens::TOKEN_MIGRATION; +use many_ledger::module::LedgerModuleImpl; +use many_ledger_test_macros::*; +use many_ledger_test_utils::cucumber::{ + refresh_token_info, verify_error_addr, verify_error_code, AccountWorld, LedgerWorld, SomeError, + SomeId, TokenWorld, +}; +use many_ledger_test_utils::Setup; +use many_modules::events::{EventFilter, EventKind, EventsModuleBackend, ListArgs}; +use many_modules::ledger::extended_info::TokenExtendedInfo; +use many_modules::ledger::{ + BalanceArgs, LedgerMintBurnModuleBackend, LedgerModuleBackend, TokenMintArgs, +}; +use many_types::ledger::{TokenAmount, TokenInfo}; +use many_types::Memo; +use std::path::Path; + +#[derive(World, Debug, Default, LedgerWorld, TokenWorld, AccountWorld)] +#[world(init = Self::new)] +struct MintWorld { + setup: Setup, + args: TokenMintArgs, + info: TokenInfo, + ext_info: TokenExtendedInfo, + account: Address, + error: Option, +} + +impl MintWorld { + fn new() -> Self { + Self { + setup: Setup::new_with_migrations(false, [(0, &TOKEN_MIGRATION)], true), + ..Default::default() + } + } +} + +fn fail_mint_token(w: &mut MintWorld, sender: &Address) { + w.error = Some( + LedgerMintBurnModuleBackend::mint(&mut w.setup.module_impl, sender, w.args.clone()) + .expect_err("Token minting was supposed to fail, it succeeded instead."), + ); +} + +#[given(expr = "a default token owned by {id}")] +fn create_default_token(w: &mut MintWorld, id: SomeId) { + many_ledger_test_utils::cucumber::create_default_token(w, id); + w.args.symbol = w.info.symbol; +} + +#[given(expr = "a default token of unlimited supply owned by {id}")] +fn create_default_token_unlimited(w: &mut MintWorld, id: SomeId) { + many_ledger_test_utils::cucumber::create_default_token_unlimited(w, id); + w.args.symbol = w.info.symbol; +} + +#[given(expr = "a distribution of {int} tokens to {id}")] +fn distribution_of(w: &mut MintWorld, amount: u64, id: SomeId) { + w.args.distribution.insert(id.as_address(w), amount.into()); +} + +#[given(expr = "a memo {string}")] +fn a_memo(w: &mut MintWorld, memo: String) { + w.args.memo = Some(Memo::try_from(memo).expect("Unable to create memo")); +} + +#[when(expr = "I mint the tokens as {id}")] +fn mint_tokens(w: &mut MintWorld, id: SomeId) { + let sender = id.as_address(w); + LedgerMintBurnModuleBackend::mint(&mut w.setup.module_impl, &sender, w.args.clone()) + .expect("Unable to mint tokens"); + refresh_token_info(w); +} + +#[then(expr = "{id} has {int} tokens")] +fn id_has_tokens(w: &mut MintWorld, id: SomeId, amount: u64) { + let addr = id.as_address(w); + let res = LedgerModuleBackend::balance( + &w.setup.module_impl, + &Address::anonymous(), + BalanceArgs { + account: Some(addr), + symbols: Some(vec![w.info.symbol].into()), + }, + ) + .unwrap_or_else(|_| panic!("Unable to fetch balance for {addr}")); + let amount: TokenAmount = amount.into(); + let zero = TokenAmount::zero(); + let balance = res.balances.get(&w.info.symbol).unwrap_or(&zero); + assert_eq!(*balance, amount); +} + +#[then(expr = "the circulating supply is {int} tokens")] +fn circulating_supply(w: &mut MintWorld, amount: u64) { + let amount: TokenAmount = amount.into(); + assert_eq!(w.info.supply.circulating, amount); +} + +#[then(expr = "the total supply is {int} tokens")] +fn total_supply(w: &mut MintWorld, amount: u64) { + let amount: TokenAmount = amount.into(); + assert_eq!(w.info.supply.total, amount); +} + +#[then(expr = "the memo is {string}")] +fn memo_is(w: &mut MintWorld, memo: String) { + let res = EventsModuleBackend::list( + &w.setup.module_impl, + ListArgs { + filter: Some(EventFilter { + kind: Some(vec![EventKind::TokenMint].into()), + ..Default::default() + }), + ..Default::default() + }, + ) + .expect("Unable to list TokenMint event"); + let memo = Memo::try_from(memo).unwrap(); + assert!(res.nb_events >= 1); + let event = res.events.into_iter().next().expect("Expected an event"); + assert!(event.content.memo().is_some()); + assert_eq!(event.content.memo().unwrap(), &memo); +} + +#[then(expr = "minting as {id} fails with {error}")] +fn minting_fails(w: &mut MintWorld, id: SomeId, error: SomeError) { + let id = id.as_address(w); + fail_mint_token(w, &id); + verify_error_code(w, error.as_many_code()) +} + +#[then(expr = "the error address is {id}")] +fn error_address_is(w: &mut MintWorld, id: SomeId) { + verify_error_addr(w, id.as_address(w)); +} + +#[tokio::main] +async fn main() { + // Support both Cargo and Bazel paths + let features = ["tests/features", "src/many-ledger/tests/features"] + .into_iter() + .find(|&p| Path::new(p).exists()) + .expect("Cucumber test features not found"); + + MintWorld::run(Path::new(features).join("ledger_mintburn/mint.feature")).await; +} diff --git a/src/many-ledger/tests/ledger_tokens/add_token_ext_info.rs b/src/many-ledger/tests/ledger_tokens/add_token_ext_info.rs index 3e90f4f4..e6f8a111 100644 --- a/src/many-ledger/tests/ledger_tokens/add_token_ext_info.rs +++ b/src/many-ledger/tests/ledger_tokens/add_token_ext_info.rs @@ -1,6 +1,7 @@ use many_ledger_test_macros::*; use many_ledger_test_utils::cucumber::{ - AccountWorld, LedgerWorld, SomeError, SomeId, SomePermission, TokenWorld, + refresh_token_info, verify_error_code, verify_error_role, AccountWorld, LedgerWorld, SomeError, + SomeId, SomePermission, TokenWorld, }; use many_ledger_test_utils::Setup; use std::path::Path; @@ -13,7 +14,7 @@ use many_ledger::module::LedgerModuleImpl; use many_modules::events::{EventFilter, EventKind, EventsModuleBackend, ListArgs}; use many_modules::ledger::extended_info::visual_logo::VisualTokenLogo; use many_modules::ledger::extended_info::TokenExtendedInfo; -use many_modules::ledger::{LedgerTokensModuleBackend, TokenAddExtendedInfoArgs, TokenInfoArgs}; +use many_modules::ledger::{LedgerTokensModuleBackend, TokenAddExtendedInfoArgs}; use many_types::ledger::TokenInfo; use many_types::Memo; @@ -37,20 +38,6 @@ impl AddExtInfoWorld { } } -fn refresh_token_info(w: &mut AddExtInfoWorld) { - let result = LedgerTokensModuleBackend::info( - &w.setup.module_impl, - &w.setup.id, - TokenInfoArgs { - symbol: w.info.symbol, - ..Default::default() - }, - ) - .expect("Unable to query token info"); - w.info = result.info; - w.ext_info = result.extended_info; -} - fn fail_add_ext_info_token(w: &mut AddExtInfoWorld, sender: &Address) { w.error = Some( LedgerTokensModuleBackend::add_extended_info( @@ -154,10 +141,12 @@ fn then_has_image_logo(w: &mut AddExtInfoWorld, content_type: String, data: Stri fn then_add_ext_info_token_fail_acl(w: &mut AddExtInfoWorld, id: SomeId, error: SomeError) { let id = id.as_address(w); fail_add_ext_info_token(w, &id); - assert_eq!( - w.error.as_ref().expect("Expecting an error"), - &error.as_many() - ); + verify_error_code(w, error.as_many_code()) +} + +#[then(expr = "the error role is {word}")] +fn then_error_role(w: &mut AddExtInfoWorld, role: String) { + verify_error_role(w, role.as_str()); } #[then(expr = "the event memo is {string}")] diff --git a/src/many-ledger/tests/ledger_tokens/create_token.rs b/src/many-ledger/tests/ledger_tokens/create_token.rs index 7048eaf4..59587bf5 100644 --- a/src/many-ledger/tests/ledger_tokens/create_token.rs +++ b/src/many-ledger/tests/ledger_tokens/create_token.rs @@ -1,6 +1,7 @@ use many_ledger_test_macros::*; use many_ledger_test_utils::cucumber::{ - AccountWorld, LedgerWorld, SomeError, SomeId, SomePermission, TokenWorld, + verify_error_code, verify_error_role, AccountWorld, LedgerWorld, SomeError, SomeId, + SomePermission, TokenWorld, }; use many_ledger_test_utils::Setup; @@ -11,6 +12,7 @@ use many_identity::Address; use many_ledger::migration::tokens::TOKEN_MIGRATION; use many_ledger::module::LedgerModuleImpl; use many_modules::events::{EventFilter, EventKind, EventsModuleBackend, ListArgs}; +use many_modules::ledger::extended_info::TokenExtendedInfo; use many_modules::ledger::{LedgerTokensModuleBackend, TokenCreateArgs}; use many_types::cbor::CborNull; use many_types::ledger::{LedgerTokensAddressMap, TokenAmount, TokenInfo, TokenMaybeOwner}; @@ -23,6 +25,7 @@ struct CreateWorld { setup: Setup, args: TokenCreateArgs, info: TokenInfo, + ext_info: TokenExtendedInfo, account: Address, error: Option, } @@ -122,10 +125,12 @@ fn when_create_token(w: &mut CreateWorld, id: SomeId) { fn then_create_token_fail_acl(w: &mut CreateWorld, id: SomeId, error: SomeError) { let id = id.as_address(w); fail_create_token(w, &id); - assert_eq!( - w.error.as_ref().expect("Expecting an error"), - &error.as_many() - ); + verify_error_code(w, error.as_many_code()) +} + +#[then(expr = "the error role is {word}")] +fn then_error_role(w: &mut CreateWorld, role: String) { + verify_error_role(w, role.as_str()); } #[then(expr = "the token symbol is a subresource")] diff --git a/src/many-ledger/tests/ledger_tokens/remove_token_ext_info.rs b/src/many-ledger/tests/ledger_tokens/remove_token_ext_info.rs index cefca803..79e1fca4 100644 --- a/src/many-ledger/tests/ledger_tokens/remove_token_ext_info.rs +++ b/src/many-ledger/tests/ledger_tokens/remove_token_ext_info.rs @@ -1,6 +1,7 @@ use many_ledger_test_macros::*; use many_ledger_test_utils::cucumber::{ - AccountWorld, LedgerWorld, SomeError, SomeId, SomePermission, TokenWorld, + refresh_token_info, verify_error_code, verify_error_role, AccountWorld, LedgerWorld, SomeError, + SomeId, SomePermission, TokenWorld, }; use many_ledger_test_utils::Setup; use std::path::Path; @@ -13,7 +14,7 @@ use many_ledger::migration::tokens::TOKEN_MIGRATION; use many_ledger::module::LedgerModuleImpl; use many_modules::events::{EventFilter, EventKind, EventsModuleBackend, ListArgs}; use many_modules::ledger::extended_info::{ExtendedInfoKey, TokenExtendedInfo}; -use many_modules::ledger::{LedgerTokensModuleBackend, TokenInfoArgs, TokenRemoveExtendedInfoArgs}; +use many_modules::ledger::{LedgerTokensModuleBackend, TokenRemoveExtendedInfoArgs}; use many_types::ledger::TokenInfo; use many_types::{AttributeRelatedIndex, Memo}; @@ -96,20 +97,6 @@ fn given_account_part_of_can_create( many_ledger_test_utils::cucumber::given_account_part_of_can_create(w, id, permission); } -fn refresh_token_info(w: &mut RemoveExtInfoWorld) { - let result = LedgerTokensModuleBackend::info( - &w.setup.module_impl, - &w.setup.id, - TokenInfoArgs { - symbol: w.info.symbol, - ..Default::default() - }, - ) - .expect("Unable to query token info"); - w.info = result.info; - w.ext_info = result.extended_info; -} - #[given(expr = "a default token owned by {id}")] fn create_default_token(w: &mut RemoveExtInfoWorld, id: SomeId) { many_ledger_test_utils::cucumber::create_default_token(w, id); @@ -168,10 +155,12 @@ fn then_rm_ext_info_token_fail_acl( ))]; let id = id.as_address(w); fail_remove_ext_info_token(w, &id); - assert_eq!( - w.error.as_ref().expect("Expecting an error"), - &error.as_many() - ); + verify_error_code(w, error.as_many_code()) +} + +#[then(expr = "the error role is {word}")] +fn then_error_role(w: &mut RemoveExtInfoWorld, role: String) { + verify_error_role(w, role.as_str()); } #[then(expr = "the event memo is {string}")] diff --git a/src/many-ledger/tests/ledger_tokens/update_token.rs b/src/many-ledger/tests/ledger_tokens/update_token.rs index 2688b22b..cdbd01f6 100644 --- a/src/many-ledger/tests/ledger_tokens/update_token.rs +++ b/src/many-ledger/tests/ledger_tokens/update_token.rs @@ -1,6 +1,7 @@ use many_ledger_test_macros::*; use many_ledger_test_utils::cucumber::{ - AccountWorld, LedgerWorld, SomeError, SomeId, SomePermission, TokenWorld, + verify_error_code, verify_error_role, AccountWorld, LedgerWorld, SomeError, SomeId, + SomePermission, TokenWorld, }; use many_ledger_test_utils::Setup; @@ -10,6 +11,7 @@ use many_identity::Address; use many_ledger::migration::tokens::TOKEN_MIGRATION; use many_ledger::module::LedgerModuleImpl; use many_modules::events::{EventFilter, EventKind, EventsModuleBackend, ListArgs}; +use many_modules::ledger::extended_info::TokenExtendedInfo; use many_modules::ledger::{LedgerTokensModuleBackend, TokenInfoArgs, TokenUpdateArgs}; use many_types::cbor::CborNull; use many_types::ledger::{TokenInfo, TokenMaybeOwner}; @@ -22,6 +24,7 @@ struct UpdateWorld { setup: Setup, args: TokenUpdateArgs, info: TokenInfo, + ext_info: TokenExtendedInfo, account: Address, error: Option, } @@ -163,10 +166,12 @@ fn then_rm_owner(w: &mut UpdateWorld) { fn then_update_token_fail_acl(w: &mut UpdateWorld, id: SomeId, error: SomeError) { let id = id.as_address(w); fail_update_token(w, &id); - assert_eq!( - w.error.as_ref().expect("Expecting an error"), - &error.as_many() - ); + verify_error_code(w, error.as_many_code()) +} + +#[then(expr = "the error role is {word}")] +fn then_error_role(w: &mut UpdateWorld, role: String) { + verify_error_role(w, role.as_str()); } #[tokio::main] diff --git a/tests/e2e/ledger/mintburn.bats b/tests/e2e/ledger/mintburn.bats new file mode 100644 index 00000000..0f122786 --- /dev/null +++ b/tests/e2e/ledger/mintburn.bats @@ -0,0 +1,152 @@ +# e2e tests for the mint/burn feature set +# The Token Migration needs to be active for this feature set to be enabled. + +GIT_ROOT="$BATS_TEST_DIRNAME/../../../" +MFX_ADDRESS=mqbfbahksdwaqeenayy2gxke32hgb7aq4ao4wt745lsfs6wiaaaaqnz + +load '../../test_helper/load' +load '../../test_helper/ledger' + +function setup() { + mkdir "$BATS_TEST_ROOTDIR" + + skip_if_missing_background_utilities + + ( + cd "$GIT_ROOT" + cargo build --features migration_testing --features balance_testing + ) + + echo ' + { "migrations": [ + { + "name": "Account Count Data Attribute", + "block_height": 0, + "disabled": true + }, + { + "name": "Block 9400", + "block_height": 0, + "disabled": true + }, + { + "name": "Dummy Hotfix", + "block_height": 0, + "disabled": true + }, + { + "name": "Memo Migration", + "block_height": 0, + "disabled": true + }, + { + "name": "Token Migration", + "block_height": 0 + } + ] }' > "$BATS_TEST_ROOTDIR/migrations.json" + + + # Dummy image + echo -n -e '\x68\x65\x6c\x6c\x6f' > "$BATS_TEST_ROOTDIR/image.png" + + # Activating the Token Migration from block 0 will modify the ledger staging hash + # The symbol metadata will be stored in the DB + cp "$GIT_ROOT/staging/ledger_state.json5" "$BATS_TEST_ROOTDIR/ledger_state.json5" + + # Make `identity 1` the token identity + sed -i 's/token_identity: ".*"/token_identity: "'"$(identity 1)"'"/' "$BATS_TEST_ROOTDIR/ledger_state.json5" + + # Use token identity subresource 0 as the first token symbol + sed -i 's/token_next_subresource: 2/token_next_subresource: 0/' "$BATS_TEST_ROOTDIR/ledger_state.json5" + + # Skip hash check + sed -i 's/hash/\/\/hash/' "$BATS_TEST_ROOTDIR/ledger_state.json5" + + start_ledger --state="$BATS_TEST_ROOTDIR/ledger_state.json5" \ + --pem "$(pem 0)" \ + --balance-only-for-testing="$(identity 1):1000:$MFX_ADDRESS" \ + --migrations-config "$BATS_TEST_ROOTDIR/migrations.json" +} + +function teardown() { + stop_background_run +} + +@test "$SUITE: can mint token" { + call_ledger --pem=1 --port=8000 token mint MFX ''\''{"'$(identity 2)'": 123, "'$(identity 3)'": 456}'\''' + check_consistency --pem=2 --balance=123 8000 + check_consistency --pem=3 --balance=456 8000 + + call_ledger --port=8000 token info ${MFX_ADDRESS} + assert_output --regexp "total:.*(.*2000000579,.*)" + assert_output --regexp "circulating:.*(.*2000000579,.*)" +} + +@test "$SUITE: can burn token" { + call_ledger --pem=1 --port=8000 send $(identity 2) 123 MFX + call_ledger --pem=1 --port=8000 send $(identity 3) 456 MFX + call_ledger --pem=1 --port=8000 token burn MFX ''\''{"'$(identity 2)'": 123, "'$(identity 3)'": 456}'\''' --error-on-under-burn + check_consistency --pem=2 --balance=0 8000 + check_consistency --pem=3 --balance=0 8000 + + call_ledger --port=8000 token info ${MFX_ADDRESS} + assert_output --regexp "total:.*(.*1999999421,.*)" + assert_output --regexp "circulating:.*(.*1999999421,.*)" +} + +@test "$SUITE: only token identity can mint" { + call_ledger --pem=2 --port=8000 token mint MFX ''\''{"'$(identity 2)'": 123, "'$(identity 3)'": 456}'\''' + assert_output --partial "Unauthorised Token endpoints sender." + + call_ledger --pem=8 --port=8000 token mint MFX ''\''{"'$(identity 2)'": 123, "'$(identity 3)'": 456}'\''' + assert_output --partial "Unauthorised Token endpoints sender." + + call_ledger --port=8000 token mint MFX ''\''{"'$(identity 2)'": 123, "'$(identity 3)'": 456}'\''' + assert_output --partial "Unauthorised Token endpoints sender." +} + +@test "$SUITE: only token identity can burn" { + call_ledger --pem=1 --port=8000 send $(identity 2) 123 MFX + call_ledger --pem=1 --port=8000 send $(identity 3) 456 MFX + call_ledger --pem=2 --port=8000 token burn MFX ''\''{"'$(identity 2)'": 123, "'$(identity 3)'": 456}'\''' --error-on-under-burn + assert_output --partial "Unauthorised Token endpoints sender." + + call_ledger --pem=8 --port=8000 token burn MFX ''\''{"'$(identity 2)'": 123, "'$(identity 3)'": 456}'\''' --error-on-under-burn + assert_output --partial "Unauthorised Token endpoints sender." + + call_ledger --port=8000 token burn MFX ''\''{"'$(identity 2)'": 123, "'$(identity 3)'": 456}'\''' --error-on-under-burn + assert_output --partial "Unauthorised Token endpoints sender." +} + +@test "$SUITE: partial burns are disabled" { + call_ledger --pem=1 --port=8000 send $(identity 2) 123 MFX + call_ledger --pem=1 --port=8000 send $(identity 3) 456 MFX + call_ledger --pem=1 --port=8000 token burn MFX ''\''{"'$(identity 2)'": 123, "'$(identity 3)'": 456}'\''' + assert_output --partial "Partial burns are disabled." +} + +@test "$SUITE: can't mint over maximum" { + create_token --pem=1 --port=8000 --maximum-supply 100 + call_ledger --port=8000 token info ${SYMBOL} + assert_output --regexp "maximum:.*(.*100,.*)" + + call_ledger --pem=1 --port=8000 token mint ${SYMBOL} ''\''{"'$(identity 2)'": 123, "'$(identity 3)'": 456}'\''' + assert_output --partial "Unable to mint over the maximum symbol supply" +} + +@test "$SUITE: can't under burn" { + call_ledger --pem=1 --port=8000 send $(identity 2) 123 MFX + call_ledger --pem=1 --port=8000 send $(identity 3) 456 MFX + call_ledger --pem=1 --port=8000 token burn MFX ''\''{"'$(identity 2)'": 124, "'$(identity 3)'": 457}'\''' --error-on-under-burn + assert_output --partial "Unable to burn, missing funds" +} + +@test "$SUITE: can't mint zero" { + call_ledger --pem=1 --port=8000 token mint MFX ''\''{"'$(identity 2)'": 0, "'$(identity 3)'": 0}'\''' + assert_output --partial "The mint/burn distribution contains zero" +} + +@test "$SUITE: can't burn zero" { + call_ledger --pem=1 --port=8000 token burn MFX ''\''{"'$(identity 2)'": 0, "'$(identity 3)'": 0}'\''' --error-on-under-burn + assert_output --partial "The mint/burn distribution contains zero" +} diff --git a/tests/resiliency/ledger/token_migration.bats b/tests/resiliency/ledger/token_migration.bats index 8a75a138..f7efe8c6 100644 --- a/tests/resiliency/ledger/token_migration.bats +++ b/tests/resiliency/ledger/token_migration.bats @@ -119,6 +119,12 @@ function teardown() { call_ledger --pem=1 --port=8000 token remove-ext-info maa 0 assert_output --partial "Invalid method name" + call_ledger --pem=1 --port=8000 token mint MFX ''\''{"'$(identity 2)'": 123, "'$(identity 3)'": 456}'\''' + assert_output --partial "Invalid method name" + + call_ledger --pem=1 --port=8000 token burn MFX ''\''{"'$(identity 2)'": 123, "'$(identity 3)'": 456}'\''' --error-on-under-burn + assert_output --partial "Invalid method name" + wait_for_block 30 # Make sure MFX token info are present @@ -126,6 +132,9 @@ function teardown() { assert_output --partial "name: \"Manifest Network Token\"" assert_output --partial "ticker: \"MFX\"" assert_output --partial "decimals: 9" + assert_output --regexp "total:.*(.*100000000000000000,.*)" + assert_output --regexp "circulating:.*(.*100000000000000000,.*)" + assert_output --regexp "maximum:.*None,.*" # Test token update # Change the token owner to `identity 2` @@ -155,6 +164,20 @@ function teardown() { call_ledger --port=${port} token info "${SYMBOL}" refute_output --partial "Some memo" done + + call_ledger --pem=1 --port=8000 token mint ${SYMBOL} ''\''{"'$(identity 2)'": 123, "'$(identity 3)'": 456}'\''' + for port in 8000 8001 8002 8003; do + call_ledger --port=${port} token info "${SYMBOL}" + assert_output --regexp "total:.*(.*579,.*)" + assert_output --regexp "circulating:.*(.*579,.*)" + done + + call_ledger --pem=1 --port=8000 token burn ${SYMBOL} ''\''{"'$(identity 2)'": 122, "'$(identity 3)'": 455}'\''' --error-on-under-burn + for port in 8000 8001 8002 8003; do + call_ledger --port=${port} token info "${SYMBOL}" + assert_output --regexp "total:.*(.*2,.*)" + assert_output --regexp "circulating:.*(.*2,.*)" + done } @test "$SUITE: Token creation sender is limited to token identity" {