Repository: tangle-network/gadget (language: rust)

Issue:
[TASK] Circular Dependency between `tangle` and `gadget` Repositories
#### Overview:
We have encountered a circular dependency issue between two of our Git repositories: `tangle` and `gadget`. The `gadget` repository contains code that functions effectively both independently and in a mocked environment, abstracting all I/O operations into simple traits/interfaces. On the other hand, the `tangle` repository requires the utilization of gadgets from the `gadget` repository. However, complications arise when certain traits in `tangle` include numerous generics. To streamline development, we opted to create a super trait with fewer generics and intended to implement or utilize this across the codebase. Unfortunately, due to the utilization of different generic parameters in `tangle` compared to the defaults in `gadget`, the new super trait did not auto-implement for the types in `tangle`, resulting in a circular dependency between the two repositories.

#### Details:
In `tangle`, there exists a trait named `JobsApi` with an extensive list of parameters required for configuration. This trait's current definition is as follows:

```rust
pub trait JobsApi<AccountId, MaxParticipants, MaxSubmissionLen, MaxKeyLen, MaxDataLen, MaxSignatureLen, MaxProofLen>
where
    AccountId: Codec + MaybeDisplay + Serialize,
    MaxParticipants: Codec + Serialize + Get<u32> + Clone,
    MaxSubmissionLen: Codec + Serialize + Get<u32>,
    MaxKeyLen: Codec + Serialize + Get<u32>,
    MaxDataLen: Codec + Serialize + Get<u32>,
    MaxSignatureLen: Codec + Serialize + Get<u32>,
    MaxProofLen: Codec + Serialize + Get<u32>,
{
    // ...
}
```
The excessive parameters led our developers to create another trait named `JobsApiForGadget`, which takes default parameters:
```rust
pub trait JobsApiForGadget<B: Block>:
    JobsApi<
        B,
        AccountId,
        MaxParticipants,
        MaxSubmissionLen,
        MaxKeyLen,
        MaxDataLen,
        MaxSignatureLen,
        MaxProofLen,
    >
{
}

// Implement JobsApiForGadget for any T that implements JobsApi
impl<
        B: Block,
        T: JobsApi<
            B,
            AccountId,
            MaxParticipants,
            MaxSubmissionLen,
            MaxKeyLen,
            MaxDataLen,
            MaxSignatureLen,
            MaxProofLen,
        >,
    > JobsApiForGadget<B> for T
{
}
```
While this approach works as long as `tangle` utilizes the same generic parameters as those in `gadget`, this is seldom the case in reality, as `tangle` typically employs different parameters. Importing parameters from `tangle` would exacerbate the circular dependency issue.

#### Proposed Solution:
To resolve the circular dependency between `tangle` and `gadget`, we need to reconsider our approach to trait definition and parameterization. We should aim to decouple the traits from specific parameter types and instead focus on creating more flexible and reusable abstractions that do not rely on specific parameter configurations. This could involve refactoring the traits in both repositories to be more generic or implementing alternative design patterns such as dependency inversion.



Discussion / hints:

Fix patch:
diff --git a/Cargo.lock b/Cargo.lock
index e87892886..8e549ca3c 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -95,9 +95,9 @@ dependencies = [
 
 [[package]]
 name = "ahash"
-version = "0.8.9"
+version = "0.8.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d713b3834d76b85304d4d525563c1276e2e30dc97cc67bfb4585a4a29fc2c89f"
+checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011"
 dependencies = [
  "cfg-if",
  "getrandom 0.2.12",
@@ -563,7 +563,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "f28243a43d821d11341ab73c80bed182dc015c514b951616cf79bd4af39af0c3"
 dependencies = [
  "concurrent-queue",
- "event-listener 5.1.0",
+ "event-listener 5.2.0",
  "event-listener-strategy 0.5.0",
  "futures-core",
  "pin-project-lite 0.2.13",
@@ -719,7 +719,7 @@ checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.51",
+ "syn 2.0.52",
 ]
 
 [[package]]
@@ -736,7 +736,7 @@ checksum = "c980ee35e870bd1a4d2c8294d4c04d0499e67bca1e4b5cefcc693c2fa00caea9"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.51",
+ "syn 2.0.52",
 ]
 
 [[package]]
@@ -802,11 +802,11 @@ checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0"
 
 [[package]]
 name = "atomic-write-file"
-version = "0.1.2"
+version = "0.1.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "edcdbedc2236483ab103a53415653d6b4442ea6141baf1ffa85df29635e88436"
+checksum = "a8204db279bf648d64fe845bd8840f78b39c8132ed4d6a4194c3b10d4b4cfb0b"
 dependencies = [
- "nix 0.27.1",
+ "nix 0.28.0",
  "rand 0.8.5",
 ]
 
@@ -829,7 +829,7 @@ checksum = "3c87f3f15e7794432337fc718554eaa4dc8f04c9677a950ffe366f20a162ae42"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.51",
+ "syn 2.0.52",
 ]
 
 [[package]]
@@ -978,7 +978,7 @@ dependencies = [
  "regex",
  "rustc-hash",
  "shlex",
- "syn 2.0.51",
+ "syn 2.0.52",
 ]
 
 [[package]]
@@ -1266,7 +1266,7 @@ checksum = "965ab7eb5f8f97d2a083c799f3a1b994fc397b2fe2da5d1da1626ce15a39f2b1"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.51",
+ "syn 2.0.52",
 ]
 
 [[package]]
@@ -1303,10 +1303,11 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5"
 
 [[package]]
 name = "cc"
-version = "1.0.88"
+version = "1.0.89"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "02f341c093d19155a6e41631ce5971aac4e9a868262212153124c15fa22d1cdc"
+checksum = "a0ba8f7aaa012f30d5b2861462f6708eccd49c3c39863fe083a308035f63d723"
 dependencies = [
+ "jobserver",
  "libc",
 ]
 
@@ -1398,7 +1399,7 @@ dependencies = [
  "num-traits",
  "serde",
  "wasm-bindgen",
- "windows-targets 0.52.3",
+ "windows-targets 0.52.4",
 ]
 
 [[package]]
@@ -1433,7 +1434,7 @@ checksum = "67523a3b4be3ce1989d607a828d036249522dd9c1c8de7f4dd2dae43a37369d1"
 dependencies = [
  "glob",
  "libc",
- "libloading 0.8.1",
+ "libloading 0.8.2",
 ]
 
 [[package]]
@@ -1559,9 +1560,9 @@ checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8"
 
 [[package]]
 name = "const-random"
-version = "0.1.17"
+version = "0.1.18"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5aaf16c9c2c612020bcfd042e170f6e32de9b9d75adb5277cdbbd2e2c8c8299a"
+checksum = "87e00182fe74b066627d63b85fd550ac2998d4b0bd86bfed477a0ae4c7c71359"
 dependencies = [
  "const-random-macro",
 ]
@@ -2092,7 +2093,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.51",
+ "syn 2.0.52",
 ]
 
 [[package]]
@@ -2172,7 +2173,7 @@ dependencies = [
  "proc-macro2",
  "quote",
  "strsim 0.10.0",
- "syn 2.0.51",
+ "syn 2.0.52",
 ]
 
 [[package]]
@@ -2194,7 +2195,7 @@ checksum = "a668eda54683121533a393014d8692171709ff57a7d61f187b6e782719f8933f"
 dependencies = [
  "darling_core 0.20.8",
  "quote",
- "syn 2.0.51",
+ "syn 2.0.52",
 ]
 
 [[package]]
@@ -2336,23 +2337,16 @@ dependencies = [
  "hex",
  "itertools 0.12.1",
  "log",
- "pallet-dkg",
- "pallet-jobs",
- "pallet-jobs-rpc-runtime-api",
  "parity-scale-codec 3.6.9",
  "parking_lot 0.12.1",
  "protocol-macros",
  "rand 0.8.5",
  "rand_chacha 0.3.1",
  "round-based 0.2.1",
- "sc-client-api",
  "serde",
  "sha2 0.10.8",
- "sp-api",
- "sp-application-crypto",
  "sp-core",
  "sp-io",
- "sp-runtime",
  "tangle-primitives",
  "test-utils",
  "tokio",
@@ -2443,7 +2437,7 @@ checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.51",
+ "syn 2.0.52",
 ]
 
 [[package]]
@@ -2507,7 +2501,7 @@ dependencies = [
  "proc-macro2",
  "quote",
  "regex",
- "syn 2.0.51",
+ "syn 2.0.52",
  "termcolor",
  "toml 0.8.2",
  "walkdir",
@@ -2781,7 +2775,7 @@ dependencies = [
  "num-traits",
  "proc-macro2",
  "quote",
- "syn 2.0.51",
+ "syn 2.0.52",
 ]
 
 [[package]]
@@ -2802,7 +2796,7 @@ dependencies = [
  "darling 0.20.8",
  "proc-macro2",
  "quote",
- "syn 2.0.51",
+ "syn 2.0.52",
 ]
 
 [[package]]
@@ -3006,9 +3000,9 @@ dependencies = [
 
 [[package]]
 name = "event-listener"
-version = "5.1.0"
+version = "5.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b7ad6fd685ce13acd6d9541a30f6db6567a7a24c9ffd4ba2955d29e3f22c8b27"
+checksum = "2b5fb89194fa3cad959b833185b3063ba881dbfc7030680b314250779fb4cc91"
 dependencies = [
  "concurrent-queue",
  "parking",
@@ -3031,7 +3025,7 @@ version = "0.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "feedafcaa9b749175d5ac357452a9d41ea2911da598fde46ce1fe02c37751291"
 dependencies = [
- "event-listener 5.1.0",
+ "event-listener 5.2.0",
  "pin-project-lite 0.2.13",
 ]
 
@@ -3046,15 +3040,16 @@ dependencies = [
 
 [[package]]
 name = "expander"
-version = "2.0.0"
+version = "2.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5f86a749cf851891866c10515ef6c299b5c69661465e9c3bbe7e07a2b77fb0f7"
+checksum = "00e83c02035136f1592a47964ea60c05a50e4ed8b5892cfac197063850898d4d"
 dependencies = [
  "blake2",
  "fs-err",
+ "prettier-please",
  "proc-macro2",
  "quote",
- "syn 2.0.51",
+ "syn 2.0.52",
 ]
 
 [[package]]
@@ -3416,7 +3411,7 @@ dependencies = [
  "proc-macro-warning",
  "proc-macro2",
  "quote",
- "syn 2.0.51",
+ "syn 2.0.52",
 ]
 
 [[package]]
@@ -3428,7 +3423,7 @@ dependencies = [
  "proc-macro-crate 1.1.3",
  "proc-macro2",
  "quote",
- "syn 2.0.51",
+ "syn 2.0.52",
 ]
 
 [[package]]
@@ -3438,7 +3433,7 @@ source = "git+https://github.com/paritytech/polkadot-sdk?branch=release-polkadot
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.51",
+ "syn 2.0.52",
 ]
 
 [[package]]
@@ -3463,7 +3458,7 @@ dependencies = [
 [[package]]
 name = "frost-core"
 version = "0.6.1"
-source = "git+https://github.com/webb-tools/tangle.git?branch=main#81c5c468ec7b8a80d8b9c585412da3670b8ebcd3"
+source = "git+https://github.com/webb-tools/tangle.git?branch=main#26bbeb5203a92ac9262302ffcd051742eb11ce49"
 dependencies = [
  "byteorder",
  "debugless-unwrap",
@@ -3503,7 +3498,7 @@ dependencies = [
 [[package]]
 name = "frost-ed25519"
 version = "1.0.0-rc.0"
-source = "git+https://github.com/webb-tools/tangle.git?branch=main#81c5c468ec7b8a80d8b9c585412da3670b8ebcd3"
+source = "git+https://github.com/webb-tools/tangle.git?branch=main#26bbeb5203a92ac9262302ffcd051742eb11ce49"
 dependencies = [
  "curve25519-dalek 4.1.1",
  "frost-core 0.6.1",
@@ -3529,7 +3524,7 @@ dependencies = [
 [[package]]
 name = "frost-ed448"
 version = "1.0.0-rc.0"
-source = "git+https://github.com/webb-tools/tangle.git?branch=main#81c5c468ec7b8a80d8b9c585412da3670b8ebcd3"
+source = "git+https://github.com/webb-tools/tangle.git?branch=main#26bbeb5203a92ac9262302ffcd051742eb11ce49"
 dependencies = [
  "ed448-goldilocks-plus 0.11.2 (git+https://github.com/webb-tools/Ed448-Goldilocks)",
  "frost-core 0.6.1",
@@ -3555,7 +3550,7 @@ dependencies = [
 [[package]]
 name = "frost-p256"
 version = "1.0.0-rc.0"
-source = "git+https://github.com/webb-tools/tangle.git?branch=main#81c5c468ec7b8a80d8b9c585412da3670b8ebcd3"
+source = "git+https://github.com/webb-tools/tangle.git?branch=main#26bbeb5203a92ac9262302ffcd051742eb11ce49"
 dependencies = [
  "frost-core 0.6.1",
  "p256 0.13.2",
@@ -3581,7 +3576,7 @@ dependencies = [
 [[package]]
 name = "frost-p384"
 version = "1.0.0-rc.0"
-source = "git+https://github.com/webb-tools/tangle.git?branch=main#81c5c468ec7b8a80d8b9c585412da3670b8ebcd3"
+source = "git+https://github.com/webb-tools/tangle.git?branch=main#26bbeb5203a92ac9262302ffcd051742eb11ce49"
 dependencies = [
  "frost-core 0.6.1",
  "p384",
@@ -3618,7 +3613,7 @@ dependencies = [
 [[package]]
 name = "frost-ristretto255"
 version = "1.0.0-rc.0"
-source = "git+https://github.com/webb-tools/tangle.git?branch=main#81c5c468ec7b8a80d8b9c585412da3670b8ebcd3"
+source = "git+https://github.com/webb-tools/tangle.git?branch=main#26bbeb5203a92ac9262302ffcd051742eb11ce49"
 dependencies = [
  "curve25519-dalek 4.1.1",
  "frost-core 0.6.1",
@@ -3644,7 +3639,7 @@ dependencies = [
 [[package]]
 name = "frost-secp256k1"
 version = "1.0.0-rc.0"
-source = "git+https://github.com/webb-tools/tangle.git?branch=main#81c5c468ec7b8a80d8b9c585412da3670b8ebcd3"
+source = "git+https://github.com/webb-tools/tangle.git?branch=main#26bbeb5203a92ac9262302ffcd051742eb11ce49"
 dependencies = [
  "frost-core 0.6.1",
  "k256",
@@ -3800,7 +3795,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.51",
+ "syn 2.0.52",
 ]
 
 [[package]]
@@ -3875,7 +3870,6 @@ dependencies = [
  "lazy_static",
  "linked-hash-map",
  "log",
- "pallet-jobs-rpc-runtime-api",
  "parity-scale-codec 3.6.9",
  "parking_lot 0.12.1",
  "protocol-macros",
@@ -3897,9 +3891,8 @@ dependencies = [
  "sqlx",
  "substrate-prometheus-endpoint",
  "subxt-signer",
- "tangle-primitives",
+ "tangle-subxt",
  "tokio",
- "webb",
 ]
 
 [[package]]
@@ -3912,8 +3905,6 @@ dependencies = [
  "hex",
  "log",
  "parking_lot 0.12.1",
- "sc-client-api",
- "sp-runtime",
  "tokio",
 ]
 
@@ -3958,9 +3949,9 @@ dependencies = [
 
 [[package]]
 name = "generic-ec-core"
-version = "0.1.2"
+version = "0.1.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1193740c17f0324ea5d7db0635230f7538e5d33e0f9732af92d3f9fd4b87663e"
+checksum = "22cab102fc88bfc017c16e69d21edae6f41ab58bfe69eed09ed0a2cf10ec923f"
 dependencies = [
  "generic-array 0.14.7",
  "rand_core 0.6.4",
@@ -3971,9 +3962,9 @@ dependencies = [
 
 [[package]]
 name = "generic-ec-curves"
-version = "0.1.3"
+version = "0.1.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fd36d2998f36338ccff5c7e9155e280b8d7caeba2aa9ea72e06c4bd01760cf90"
+checksum = "9a133d38cde4fef7aea4e367ca51f291db0248495a424ec4208cdace08ba59f4"
 dependencies = [
  "crypto-bigint 0.5.5",
  "elliptic-curve 0.13.8",
@@ -4003,8 +3994,8 @@ dependencies = [
 
 [[package]]
 name = "gennaro-dkg"
-version = "0.9.0"
-source = "git+https://github.com/mikelodder7/gennaro-dkg.git#b054b46641a6410600c1b341cb6646f692b3312b"
+version = "0.9.0-rc0"
+source = "git+https://github.com/mikelodder7/gennaro-dkg.git#3130147a21e8e071d53f5842420cbe0f632bdebb"
 dependencies = [
  "anyhow",
  "data-encoding",
@@ -4041,13 +4032,22 @@ dependencies = [
  "wasi 0.11.0+wasi-snapshot-preview1",
 ]
 
+[[package]]
+name = "getrandom_or_panic"
+version = "0.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6ea1015b5a70616b688dc230cfe50c8af89d972cb132d5a622814d29773b10b9"
+dependencies = [
+ "rand_core 0.6.4",
+]
+
 [[package]]
 name = "ghash"
-version = "0.5.0"
+version = "0.5.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d930750de5717d2dd0b8c0d42c076c0e884c81a73e6cab859bbd2339c71e3e40"
+checksum = "f0d8a4362ccb29cb0b265253fb0a2728f592895ee6854fd9bc13f2ffda266ff1"
 dependencies = [
- "opaque-debug 0.3.0",
+ "opaque-debug 0.3.1",
  "polyval",
 ]
 
@@ -4094,7 +4094,7 @@ dependencies = [
  "aho-corasick",
  "bstr",
  "log",
- "regex-automata 0.4.5",
+ "regex-automata 0.4.6",
  "regex-syntax 0.8.2",
 ]
 
@@ -4170,7 +4170,7 @@ dependencies = [
  "futures-sink",
  "futures-util",
  "http",
- "indexmap 2.2.3",
+ "indexmap 2.2.5",
  "slab",
  "tokio",
  "tokio-util",
@@ -4231,7 +4231,7 @@ version = "0.13.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e"
 dependencies = [
- "ahash 0.8.9",
+ "ahash 0.8.11",
 ]
 
 [[package]]
@@ -4240,7 +4240,7 @@ version = "0.14.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604"
 dependencies = [
- "ahash 0.8.9",
+ "ahash 0.8.11",
  "allocator-api2",
  "serde",
 ]
@@ -4297,9 +4297,9 @@ dependencies = [
 
 [[package]]
 name = "hermit-abi"
-version = "0.3.8"
+version = "0.3.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "379dada1584ad501b383485dd706b8afb7a70fcbc7f4da7d780638a5a6124a60"
+checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024"
 
 [[package]]
 name = "hex"
@@ -4387,9 +4387,9 @@ dependencies = [
 
 [[package]]
 name = "http"
-version = "0.2.11"
+version = "0.2.12"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8947b1a6fad4393052c7ba1f4cd97bed3e953a95c79c92ad9b051a04611d9fbb"
+checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1"
 dependencies = [
  "bytes",
  "fnv",
@@ -4483,7 +4483,7 @@ dependencies = [
  "iana-time-zone-haiku",
  "js-sys",
  "wasm-bindgen",
- "windows-core 0.52.0",
+ "windows-core",
 ]
 
 [[package]]
@@ -4636,9 +4636,9 @@ dependencies = [
 
 [[package]]
 name = "indexmap"
-version = "2.2.3"
+version = "2.2.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "233cf39063f058ea2caae4091bf4a3ef70a653afbc026f5c4a4135d114e3c177"
+checksum = "7b0b929d511467233429c45a44ac1dcaa21ba0f5ba11e4879e6ed28ddb4f9df4"
 dependencies = [
  "equivalent",
  "hashbrown 0.14.3",
@@ -4689,7 +4689,7 @@ version = "1.0.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2"
 dependencies = [
- "hermit-abi 0.3.8",
+ "hermit-abi 0.3.9",
  "libc",
  "windows-sys 0.48.0",
 ]
@@ -4724,7 +4724,7 @@ version = "0.4.12"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "f23ff5ef2b80d608d61efee834934d862cd92461afc0560dedf493e4c033738b"
 dependencies = [
- "hermit-abi 0.3.8",
+ "hermit-abi 0.3.9",
  "libc",
  "windows-sys 0.52.0",
 ]
@@ -4762,11 +4762,20 @@ version = "1.0.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c"
 
+[[package]]
+name = "jobserver"
+version = "0.1.28"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ab46a6e9526ddef3ae7f787c06f0f2600639ba80ea3eade3d8e670a2230f51d6"
+dependencies = [
+ "libc",
+]
+
 [[package]]
 name = "js-sys"
-version = "0.3.68"
+version = "0.3.69"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "406cda4b368d531c842222cf9d2600a9a4acce8d29423695379c6868a143a9ee"
+checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d"
 dependencies = [
  "wasm-bindgen",
 ]
@@ -4998,12 +5007,12 @@ dependencies = [
 
 [[package]]
 name = "libloading"
-version = "0.8.1"
+version = "0.8.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c571b676ddfc9a8c12f1f3d3085a7b163966a8fd8098a90640953ce5f6170161"
+checksum = "2caa5afb8bf9f3a2652760ce7d4f62d21c4d5a423e68466fca30df82f2330164"
 dependencies = [
  "cfg-if",
- "windows-sys 0.48.0",
+ "windows-targets 0.52.4",
 ]
 
 [[package]]
@@ -5561,9 +5570,9 @@ dependencies = [
 
 [[package]]
 name = "log"
-version = "0.4.20"
+version = "0.4.21"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f"
+checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c"
 
 [[package]]
 name = "loupe"
@@ -5642,7 +5651,7 @@ dependencies = [
  "macro_magic_core",
  "macro_magic_macros",
  "quote",
- "syn 2.0.51",
+ "syn 2.0.52",
 ]
 
 [[package]]
@@ -5656,7 +5665,7 @@ dependencies = [
  "macro_magic_core_macros",
  "proc-macro2",
  "quote",
- "syn 2.0.51",
+ "syn 2.0.52",
 ]
 
 [[package]]
@@ -5667,7 +5676,7 @@ checksum = "d710e1214dffbab3b5dacb21475dde7d6ed84c69ff722b3a47a782668d44fbac"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.51",
+ "syn 2.0.52",
 ]
 
 [[package]]
@@ -5678,7 +5687,7 @@ checksum = "b8fb85ec1620619edf2984a7693497d4ec88a9665d8b87e942856884c92dbf2a"
 dependencies = [
  "macro_magic_core",
  "quote",
- "syn 2.0.51",
+ "syn 2.0.52",
 ]
 
 [[package]]
@@ -5861,9 +5870,9 @@ dependencies = [
 
 [[package]]
 name = "mio"
-version = "0.8.10"
+version = "0.8.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8f3d0b296e374a4e6f3c7b0a1f5a51d748a0d34c85e7dc48fc3fa9a87657fe09"
+checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c"
 dependencies = [
  "libc",
  "wasi 0.11.0+wasi-snapshot-preview1",
@@ -6116,12 +6125,13 @@ dependencies = [
 
 [[package]]
 name = "nix"
-version = "0.27.1"
+version = "0.28.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053"
+checksum = "ab2156c4fce2f8df6c499cc1c763e4394b7482525bf2a9701c9d79d215f519e4"
 dependencies = [
  "bitflags 2.4.2",
  "cfg-if",
+ "cfg_aliases",
  "libc",
 ]
 
@@ -6307,7 +6317,7 @@ version = "1.16.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43"
 dependencies = [
- "hermit-abi 0.3.8",
+ "hermit-abi 0.3.9",
  "libc",
 ]
 
@@ -6329,7 +6339,7 @@ dependencies = [
  "proc-macro-crate 2.0.2",
  "proc-macro2",
  "quote",
- "syn 2.0.51",
+ "syn 2.0.52",
 ]
 
 [[package]]
@@ -6394,9 +6404,9 @@ checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c"
 
 [[package]]
 name = "opaque-debug"
-version = "0.3.0"
+version = "0.3.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
+checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381"
 
 [[package]]
 name = "open-fastrlp"
@@ -6533,7 +6543,7 @@ dependencies = [
 [[package]]
 name = "pallet-dkg"
 version = "0.6.1"
-source = "git+https://github.com/webb-tools/tangle.git?branch=main#81c5c468ec7b8a80d8b9c585412da3670b8ebcd3"
+source = "git+https://github.com/webb-tools/tangle.git?branch=main#26bbeb5203a92ac9262302ffcd051742eb11ce49"
 dependencies = [
  "digest 0.10.7",
  "elliptic-curve 0.13.8",
@@ -6575,7 +6585,7 @@ dependencies = [
 [[package]]
 name = "pallet-jobs"
 version = "0.6.1"
-source = "git+https://github.com/webb-tools/tangle.git?branch=main#81c5c468ec7b8a80d8b9c585412da3670b8ebcd3"
+source = "git+https://github.com/webb-tools/tangle.git?branch=main#26bbeb5203a92ac9262302ffcd051742eb11ce49"
 dependencies = [
  "frame-benchmarking",
  "frame-support",
@@ -6592,7 +6602,7 @@ dependencies = [
 [[package]]
 name = "pallet-jobs-rpc-runtime-api"
 version = "0.6.1"
-source = "git+https://github.com/webb-tools/tangle.git?branch=main#81c5c468ec7b8a80d8b9c585412da3670b8ebcd3"
+source = "git+https://github.com/webb-tools/tangle.git?branch=main#26bbeb5203a92ac9262302ffcd051742eb11ce49"
 dependencies = [
  "parity-scale-codec 3.6.9",
  "sp-api",
@@ -6623,7 +6633,7 @@ dependencies = [
 [[package]]
 name = "pallet-zksaas"
 version = "0.6.1"
-source = "git+https://github.com/webb-tools/tangle.git?branch=main#81c5c468ec7b8a80d8b9c585412da3670b8ebcd3"
+source = "git+https://github.com/webb-tools/tangle.git?branch=main#26bbeb5203a92ac9262302ffcd051742eb11ce49"
 dependencies = [
  "frame-benchmarking",
  "frame-support",
@@ -6865,7 +6875,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "e1d3afd2628e69da2be385eb6f2fd57c8ac7977ceeff6dc166ff1657b0e386a9"
 dependencies = [
  "fixedbitset",
- "indexmap 2.2.3",
+ "indexmap 2.2.5",
 ]
 
 [[package]]
@@ -6903,7 +6913,7 @@ checksum = "266c042b60c9c76b8d53061e52b2e0d1116abc57cefc8c5cd671619a56ac3690"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.51",
+ "syn 2.0.52",
 ]
 
 [[package]]
@@ -7043,19 +7053,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "8159bd90725d2df49889a078b54f4f79e87f1f8a8444194cdca81d38f5393abf"
 dependencies = [
  "cpufeatures",
- "opaque-debug 0.3.0",
+ "opaque-debug 0.3.1",
  "universal-hash",
 ]
 
 [[package]]
 name = "polyval"
-version = "0.6.1"
+version = "0.6.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d52cff9d1d4dee5fe6d03729099f4a310a41179e0a10dbf542039873f2e826fb"
+checksum = "9d1fe60d06143b2430aa532c94cfe9e29783047f06c0d7fd359a9a51b729fa25"
 dependencies = [
  "cfg-if",
  "cpufeatures",
- "opaque-debug 0.3.0",
+ "opaque-debug 0.3.1",
  "universal-hash",
 ]
 
@@ -7113,11 +7123,21 @@ dependencies = [
  "termtree",
 ]
 
+[[package]]
+name = "prettier-please"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "22020dfcf177fcc7bf5deaf7440af371400c67c0de14c399938d8ed4fb4645d3"
+dependencies = [
+ "proc-macro2",
+ "syn 2.0.52",
+]
+
 [[package]]
 name = "prettyplease"
-version = "0.1.25"
+version = "0.1.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6c8646e95016a7a6c4adea95bafa8a16baab64b583356217f2c85db4a39d9a86"
+checksum = "f28f53e8b192565862cf99343194579a022eb9c7dd3a8d03134734803c7b3125"
 dependencies = [
  "proc-macro2",
  "syn 1.0.109",
@@ -7130,7 +7150,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "a41cf62165e97c7f814d2221421dbb9afcbcdb0a88068e5ea206e19951c2cbb5"
 dependencies = [
  "proc-macro2",
- "syn 2.0.51",
+ "syn 2.0.52",
 ]
 
 [[package]]
@@ -7227,7 +7247,7 @@ checksum = "3d1eaa7fa0aa1929ffdf7eeb6eac234dde6268914a14ad44d23521ab6a9b258e"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.51",
+ "syn 2.0.52",
 ]
 
 [[package]]
@@ -7273,7 +7293,7 @@ checksum = "440f724eba9f6996b75d63681b0a92b06947f1457076d503a4d2e2c8f56442b8"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.51",
+ "syn 2.0.52",
 ]
 
 [[package]]
@@ -7315,7 +7335,7 @@ dependencies = [
  "log",
  "multimap",
  "petgraph",
- "prettyplease 0.1.25",
+ "prettyplease 0.1.11",
  "prost",
  "prost-types",
  "regex",
@@ -7352,7 +7372,7 @@ version = "0.1.0"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.51",
+ "syn 2.0.52",
 ]
 
 [[package]]
@@ -7687,9 +7707,9 @@ checksum = "60a357793950651c4ed0f3f52338f53b2f809f32d83a07f72909fa13e4c6c1e3"
 
 [[package]]
 name = "rayon"
-version = "1.8.1"
+version = "1.9.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fa7237101a77a10773db45d62004a272517633fbcc3df19d96455ede1122e051"
+checksum = "e4963ed1bc86e4f3ee217022bd855b297cef07fb9eac5dfa1f788b220b49b3bd"
 dependencies = [
  "either",
  "rayon-core",
@@ -7796,7 +7816,7 @@ checksum = "5fddb4f8d99b0a2ebafc65a87a69a7b9875e4b1ae1f00db265d300ef7f28bccc"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.51",
+ "syn 2.0.52",
 ]
 
 [[package]]
@@ -7830,7 +7850,7 @@ checksum = "b62dbe01f0b06f9d8dc7d49e05a0785f153b00b2c227856282f671e0318c9b15"
 dependencies = [
  "aho-corasick",
  "memchr",
- "regex-automata 0.4.5",
+ "regex-automata 0.4.6",
  "regex-syntax 0.8.2",
 ]
 
@@ -7845,9 +7865,9 @@ dependencies = [
 
 [[package]]
 name = "regex-automata"
-version = "0.4.5"
+version = "0.4.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5bb987efffd3c6d0d8f5f89510bb458559eab11e4f869acb20bf845e016259cd"
+checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea"
 dependencies = [
  "aho-corasick",
  "memchr",
@@ -8357,7 +8377,7 @@ dependencies = [
  "proc-macro-crate 1.1.3",
  "proc-macro2",
  "quote",
- "syn 2.0.51",
+ "syn 2.0.52",
 ]
 
 [[package]]
@@ -8912,7 +8932,7 @@ dependencies = [
  "proc-macro-crate 1.1.3",
  "proc-macro2",
  "quote",
- "syn 2.0.51",
+ "syn 2.0.52",
 ]
 
 [[package]]
@@ -9100,7 +9120,7 @@ version = "0.2.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "772575a524feeb803e5b0fcbc6dd9f367e579488197c94c6e4023aad2305774d"
 dependencies = [
- "ahash 0.8.9",
+ "ahash 0.8.11",
  "cfg-if",
  "hashbrown 0.13.2",
 ]
@@ -9140,6 +9160,23 @@ dependencies = [
  "zeroize",
 ]
 
+[[package]]
+name = "schnorrkel"
+version = "0.11.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8de18f6d8ba0aad7045f5feae07ec29899c1112584a38509a84ad7b04451eaa0"
+dependencies = [
+ "arrayref",
+ "arrayvec 0.7.4",
+ "curve25519-dalek 4.1.1",
+ "getrandom_or_panic",
+ "merlin 3.0.0",
+ "rand_core 0.6.4",
+ "sha2 0.10.8",
+ "subtle",
+ "zeroize",
+]
+
 [[package]]
 name = "scopeguard"
 version = "1.2.0"
@@ -9323,7 +9360,7 @@ checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.51",
+ "syn 2.0.52",
 ]
 
 [[package]]
@@ -9382,7 +9419,7 @@ dependencies = [
  "darling 0.20.8",
  "proc-macro2",
  "quote",
- "syn 2.0.51",
+ "syn 2.0.52",
 ]
 
 [[package]]
@@ -9394,7 +9431,7 @@ dependencies = [
  "darling 0.20.8",
  "proc-macro2",
  "quote",
- "syn 2.0.51",
+ "syn 2.0.52",
 ]
 
 [[package]]
@@ -9417,7 +9454,7 @@ dependencies = [
  "cfg-if",
  "cpufeatures",
  "digest 0.9.0",
- "opaque-debug 0.3.0",
+ "opaque-debug 0.3.1",
 ]
 
 [[package]]
@@ -9453,7 +9490,7 @@ dependencies = [
  "cfg-if",
  "cpufeatures",
  "digest 0.9.0",
- "opaque-debug 0.3.0",
+ "opaque-debug 0.3.1",
 ]
 
 [[package]]
@@ -9476,7 +9513,7 @@ dependencies = [
  "block-buffer 0.9.0",
  "digest 0.9.0",
  "keccak",
- "opaque-debug 0.3.0",
+ "opaque-debug 0.3.1",
 ]
 
 [[package]]
@@ -9809,7 +9846,7 @@ dependencies = [
  "proc-macro-crate 1.1.3",
  "proc-macro2",
  "quote",
- "syn 2.0.51",
+ "syn 2.0.52",
 ]
 
 [[package]]
@@ -10014,7 +10051,7 @@ source = "git+https://github.com/paritytech/polkadot-sdk?branch=release-polkadot
 dependencies = [
  "quote",
  "sp-core-hashing 9.0.0 (git+https://github.com/paritytech/polkadot-sdk?branch=release-polkadot-v1.1.0)",
- "syn 2.0.51",
+ "syn 2.0.52",
 ]
 
 [[package]]
@@ -10033,7 +10070,7 @@ source = "git+https://github.com/paritytech/polkadot-sdk?branch=release-polkadot
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.51",
+ "syn 2.0.52",
 ]
 
 [[package]]
@@ -10207,7 +10244,7 @@ dependencies = [
  "proc-macro-crate 1.1.3",
  "proc-macro2",
  "quote",
- "syn 2.0.51",
+ "syn 2.0.52",
 ]
 
 [[package]]
@@ -10362,7 +10399,7 @@ name = "sp-trie"
 version = "22.0.0"
 source = "git+https://github.com/paritytech/polkadot-sdk?branch=release-polkadot-v1.1.0#c8d2251cafadc108ba2f1f8a3208dc547ff38901"
 dependencies = [
- "ahash 0.8.9",
+ "ahash 0.8.11",
  "hash-db",
  "hashbrown 0.13.2",
  "lazy_static",
@@ -10405,7 +10442,7 @@ dependencies = [
  "parity-scale-codec 3.6.9",
  "proc-macro2",
  "quote",
- "syn 2.0.51",
+ "syn 2.0.52",
 ]
 
 [[package]]
@@ -10501,7 +10538,7 @@ version = "0.7.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "d84b0a3c3739e220d94b3239fd69fb1f74bc36e16643423bd99de3b43c21bfbd"
 dependencies = [
- "ahash 0.8.9",
+ "ahash 0.8.11",
  "atoi",
  "byteorder",
  "bytes",
@@ -10517,7 +10554,7 @@ dependencies = [
  "futures-util",
  "hashlink",
  "hex",
- "indexmap 2.2.3",
+ "indexmap 2.2.5",
  "log",
  "memchr",
  "once_cell",
@@ -10821,7 +10858,7 @@ dependencies = [
  "proc-macro2",
  "quote",
  "rustversion",
- "syn 2.0.51",
+ "syn 2.0.52",
 ]
 
 [[package]]
@@ -10833,6 +10870,7 @@ dependencies = [
  "gadget-common",
  "parking_lot 0.12.1",
  "protocol-macros",
+ "sp-core",
  "tangle-primitives",
  "test-utils",
  "tokio",
@@ -10840,13 +10878,13 @@ dependencies = [
 
 [[package]]
 name = "substrate-bip39"
-version = "0.4.5"
+version = "0.4.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e620c7098893ba667438b47169c00aacdd9e7c10e042250ce2b60b087ec97328"
+checksum = "6a7590dc041b9bc2825e52ce5af8416c73dbe9d0654402bfd4b4941938b94d8f"
 dependencies = [
  "hmac 0.11.0",
  "pbkdf2 0.8.0",
- "schnorrkel 0.9.1",
+ "schnorrkel 0.11.4",
  "sha2 0.9.9",
  "zeroize",
 ]
@@ -10922,7 +10960,7 @@ dependencies = [
  "quote",
  "scale-info",
  "subxt-metadata",
- "syn 2.0.51",
+ "syn 2.0.52",
  "thiserror",
  "tokio",
 ]
@@ -10953,7 +10991,7 @@ dependencies = [
  "darling 0.20.8",
  "proc-macro-error",
  "subxt-codegen",
- "syn 2.0.51",
+ "syn 2.0.52",
 ]
 
 [[package]]
@@ -11003,9 +11041,9 @@ dependencies = [
 
 [[package]]
 name = "syn"
-version = "2.0.51"
+version = "2.0.52"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6ab617d94515e94ae53b8406c628598680aa0c9587474ecbe58188f7b345d66c"
+checksum = "b699d15b36d1f02c3e7c69f8ffef53de37aefae075d8488d4ba1a7788d574a07"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -11048,7 +11086,7 @@ dependencies = [
 [[package]]
 name = "tangle-crypto-primitives"
 version = "0.6.1"
-source = "git+https://github.com/webb-tools/tangle.git?branch=main#81c5c468ec7b8a80d8b9c585412da3670b8ebcd3"
+source = "git+https://github.com/webb-tools/tangle.git?branch=main#26bbeb5203a92ac9262302ffcd051742eb11ce49"
 dependencies = [
  "parity-scale-codec 3.6.9",
  "scale-info",
@@ -11058,7 +11096,7 @@ dependencies = [
 [[package]]
 name = "tangle-primitives"
 version = "0.6.1"
-source = "git+https://github.com/webb-tools/tangle.git?branch=main#81c5c468ec7b8a80d8b9c585412da3670b8ebcd3"
+source = "git+https://github.com/webb-tools/tangle.git?branch=main#26bbeb5203a92ac9262302ffcd051742eb11ce49"
 dependencies = [
  "ark-bn254",
  "ark-crypto-primitives",
@@ -11083,6 +11121,16 @@ dependencies = [
  "sp-std 8.0.0 (git+https://github.com/paritytech/polkadot-sdk?branch=release-polkadot-v1.1.0)",
 ]
 
+[[package]]
+name = "tangle-subxt"
+version = "0.6.1"
+source = "git+https://github.com/webb-tools/tangle.git?branch=main#26bbeb5203a92ac9262302ffcd051742eb11ce49"
+dependencies = [
+ "parity-scale-codec 3.6.9",
+ "scale-info",
+ "subxt",
+]
+
 [[package]]
 name = "tap"
 version = "1.0.1"
@@ -11170,6 +11218,7 @@ dependencies = [
  "sc-client-api",
  "sc-utils",
  "scale-info",
+ "serde",
  "sp-api",
  "sp-application-crypto",
  "sp-core",
@@ -11218,7 +11267,7 @@ checksum = "e4c60d69f36615a077cc7663b9cb8e42275722d23e58a7fa3d2c7f2915d09d04"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.51",
+ "syn 2.0.52",
 ]
 
 [[package]]
@@ -11229,7 +11278,7 @@ checksum = "a953cb265bef375dae3de6663da4d3804eee9682ea80d8e2542529b73c531c81"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.51",
+ "syn 2.0.52",
 ]
 
 [[package]]
@@ -11280,6 +11329,7 @@ dependencies = [
  "round-based 0.1.7",
  "serde",
  "snowbridge-milagro-bls",
+ "sp-core",
  "tangle-primitives",
  "test-utils",
  "tokio",
@@ -11405,7 +11455,7 @@ checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.51",
+ "syn 2.0.52",
 ]
 
 [[package]]
@@ -11481,7 +11531,7 @@ version = "0.20.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "396e4d48bbb2b7554c944bde63101b5ae446cff6ec4a24227428f15eb72ef338"
 dependencies = [
- "indexmap 2.2.3",
+ "indexmap 2.2.5",
  "serde",
  "serde_spanned",
  "toml_datetime",
@@ -11549,7 +11599,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.51",
+ "syn 2.0.52",
 ]
 
 [[package]]
@@ -11743,7 +11793,7 @@ checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675"
 dependencies = [
  "cfg-if",
  "digest 0.10.7",
- "rand 0.8.5",
+ "rand 0.6.5",
  "static_assertions",
 ]
 
@@ -11771,7 +11821,7 @@ checksum = "8b29f121da05aa0857e7b96cf2f8782bd4140911506518486d4a125b97d7d609"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.51",
+ "syn 2.0.52",
 ]
 
 [[package]]
@@ -11935,7 +11985,7 @@ checksum = "b3fd98999db9227cf28e59d83e1f120f42bc233d4b152e8fab9bc87d5bb1e0f8"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.51",
+ "syn 2.0.52",
 ]
 
 [[package]]
@@ -11946,9 +11996,9 @@ checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
 
 [[package]]
 name = "vsss-rs"
-version = "4.0.0-rc2"
+version = "4.0.0-rc3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d7eac81128b4ad540f259117e25900fe68ea0d4309f176d164944346cb94921e"
+checksum = "02192ed3d4d744854b210e01efe63ca6c0524ee301ce1cf3131279805e5b75e6"
 dependencies = [
  "elliptic-curve 0.13.8",
  "rand_chacha 0.3.1",
@@ -11968,9 +12018,9 @@ checksum = "f3c4517f54858c779bbcbf228f4fca63d121bf85fbecb2dc578cdf4a39395690"
 
 [[package]]
 name = "walkdir"
-version = "2.4.0"
+version = "2.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d71d857dc86794ca4c280d616f7da00d2dbfd8cd788846559a6813e6aa4b54ee"
+checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b"
 dependencies = [
  "same-file",
  "winapi-util",
@@ -11997,11 +12047,17 @@ version = "0.11.0+wasi-snapshot-preview1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
 
+[[package]]
+name = "wasite"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855b"
+
 [[package]]
 name = "wasm-bindgen"
-version = "0.2.91"
+version = "0.2.92"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c1e124130aee3fb58c5bdd6b639a0509486b0338acaaae0c84a5124b0f588b7f"
+checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8"
 dependencies = [
  "cfg-if",
  "wasm-bindgen-macro",
@@ -12009,24 +12065,24 @@ dependencies = [
 
 [[package]]
 name = "wasm-bindgen-backend"
-version = "0.2.91"
+version = "0.2.92"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c9e7e1900c352b609c8488ad12639a311045f40a35491fb69ba8c12f758af70b"
+checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da"
 dependencies = [
  "bumpalo",
  "log",
  "once_cell",
  "proc-macro2",
  "quote",
- "syn 2.0.51",
+ "syn 2.0.52",
  "wasm-bindgen-shared",
 ]
 
 [[package]]
 name = "wasm-bindgen-futures"
-version = "0.4.41"
+version = "0.4.42"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "877b9c3f61ceea0e56331985743b13f3d25c406a7098d45180fb5f09bc19ed97"
+checksum = "76bc14366121efc8dbb487ab05bcc9d346b3b5ec0eaa76e46594cabbe51762c0"
 dependencies = [
  "cfg-if",
  "js-sys",
@@ -12036,9 +12092,9 @@ dependencies = [
 
 [[package]]
 name = "wasm-bindgen-macro"
-version = "0.2.91"
+version = "0.2.92"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b30af9e2d358182b5c7449424f017eba305ed32a7010509ede96cdc4696c46ed"
+checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726"
 dependencies = [
  "quote",
  "wasm-bindgen-macro-support",
@@ -12046,28 +12102,28 @@ dependencies = [
 
 [[package]]
 name = "wasm-bindgen-macro-support"
-version = "0.2.91"
+version = "0.2.92"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "642f325be6301eb8107a83d12a8ac6c1e1c54345a7ef1a9261962dfefda09e66"
+checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.51",
+ "syn 2.0.52",
  "wasm-bindgen-backend",
  "wasm-bindgen-shared",
 ]
 
 [[package]]
 name = "wasm-bindgen-shared"
-version = "0.2.91"
+version = "0.2.92"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4f186bd2dcf04330886ce82d6f33dd75a7bfcf69ecf5763b89fcde53b6ac9838"
+checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96"
 
 [[package]]
 name = "wasm-encoder"
-version = "0.200.0"
+version = "0.201.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b9e3fb0c8fbddd78aa6095b850dfeedbc7506cf5f81e633f69cf8f2333ab84b9"
+checksum = "b9c7d2731df60006819b013f64ccc2019691deccf6e11a1804bc850cd6748f1a"
 dependencies = [
  "leb128",
 ]
@@ -12581,9 +12637,9 @@ dependencies = [
 
 [[package]]
 name = "wast"
-version = "200.0.0"
+version = "201.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d1810d14e6b03ebb8fb05eef4009ad5749c989b65197d83bce7de7172ed91366"
+checksum = "1ef6e1ef34d7da3e2b374fd2b1a9c0227aff6cad596e1b24df9b58d0f6222faa"
 dependencies = [
  "bumpalo",
  "leb128",
@@ -12594,41 +12650,23 @@ dependencies = [
 
 [[package]]
 name = "wat"
-version = "1.200.0"
+version = "1.201.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "776cbd10e217f83869beaa3f40e312bb9e91d5eee29bbf6f560db1261b6a4c3d"
+checksum = "453d5b37a45b98dee4f4cb68015fc73634d7883bbef1c65e6e9c78d454cf3f32"
 dependencies = [
  "wast",
 ]
 
 [[package]]
 name = "web-sys"
-version = "0.3.68"
+version = "0.3.69"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "96565907687f7aceb35bc5fc03770a8a0471d82e479f25832f54a0e3f4b28446"
+checksum = "77afa9a11836342370f4817622a2f0f418b134426d91a82dfb48f532d2ec13ef"
 dependencies = [
  "js-sys",
  "wasm-bindgen",
 ]
 
-[[package]]
-name = "webb"
-version = "0.8.4"
-source = "git+https://github.com/webb-tools/webb-rs.git?branch=main#05c3441fe2c957c2eaa473f3f59bd593c396b521"
-dependencies = [
- "async-trait",
- "hex",
- "parity-scale-codec 3.6.9",
- "prettyplease 0.2.16",
- "rand 0.8.5",
- "scale-info",
- "serde",
- "serde_json",
- "subxt",
- "tempfile",
- "thiserror",
-]
-
 [[package]]
 name = "webpki"
 version = "0.22.4"
@@ -12668,9 +12706,13 @@ dependencies = [
 
 [[package]]
 name = "whoami"
-version = "1.4.1"
+version = "1.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "22fc3756b8a9133049b26c7f61ab35416c130e8c09b660f5b3958b446f52cc50"
+checksum = "0fec781d48b41f8163426ed18e8fc2864c12937df9ce54c88ede7bd47270893e"
+dependencies = [
+ "redox_syscall 0.4.1",
+ "wasite",
+]
 
 [[package]]
 name = "wide"
@@ -12725,7 +12767,7 @@ version = "0.51.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "ca229916c5ee38c2f2bc1e9d8f04df975b4bd93f9955dc69fabb5d91270045c9"
 dependencies = [
- "windows-core 0.51.1",
+ "windows-core",
  "windows-targets 0.48.5",
 ]
 
@@ -12738,15 +12780,6 @@ dependencies = [
  "windows-targets 0.48.5",
 ]
 
-[[package]]
-name = "windows-core"
-version = "0.52.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9"
-dependencies = [
- "windows-targets 0.52.3",
-]
-
 [[package]]
 name = "windows-sys"
 version = "0.33.0"
@@ -12784,7 +12817,7 @@ version = "0.52.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
 dependencies = [
- "windows-targets 0.52.3",
+ "windows-targets 0.52.4",
 ]
 
 [[package]]
@@ -12819,17 +12852,17 @@ dependencies = [
 
 [[package]]
 name = "windows-targets"
-version = "0.52.3"
+version = "0.52.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d380ba1dc7187569a8a9e91ed34b8ccfc33123bbacb8c0aed2d1ad7f3ef2dc5f"
+checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b"
 dependencies = [
- "windows_aarch64_gnullvm 0.52.3",
- "windows_aarch64_msvc 0.52.3",
- "windows_i686_gnu 0.52.3",
- "windows_i686_msvc 0.52.3",
- "windows_x86_64_gnu 0.52.3",
- "windows_x86_64_gnullvm 0.52.3",
- "windows_x86_64_msvc 0.52.3",
+ "windows_aarch64_gnullvm 0.52.4",
+ "windows_aarch64_msvc 0.52.4",
+ "windows_i686_gnu 0.52.4",
+ "windows_i686_msvc 0.52.4",
+ "windows_x86_64_gnu 0.52.4",
+ "windows_x86_64_gnullvm 0.52.4",
+ "windows_x86_64_msvc 0.52.4",
 ]
 
 [[package]]
@@ -12846,9 +12879,9 @@ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
 
 [[package]]
 name = "windows_aarch64_gnullvm"
-version = "0.52.3"
+version = "0.52.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "68e5dcfb9413f53afd9c8f86e56a7b4d86d9a2fa26090ea2dc9e40fba56c6ec6"
+checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9"
 
 [[package]]
 name = "windows_aarch64_msvc"
@@ -12870,9 +12903,9 @@ checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
 
 [[package]]
 name = "windows_aarch64_msvc"
-version = "0.52.3"
+version = "0.52.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8dab469ebbc45798319e69eebf92308e541ce46760b49b18c6b3fe5e8965b30f"
+checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675"
 
 [[package]]
 name = "windows_i686_gnu"
@@ -12894,9 +12927,9 @@ checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
 
 [[package]]
 name = "windows_i686_gnu"
-version = "0.52.3"
+version = "0.52.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2a4e9b6a7cac734a8b4138a4e1044eac3404d8326b6c0f939276560687a033fb"
+checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3"
 
 [[package]]
 name = "windows_i686_msvc"
@@ -12918,9 +12951,9 @@ checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
 
 [[package]]
 name = "windows_i686_msvc"
-version = "0.52.3"
+version = "0.52.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "28b0ec9c422ca95ff34a78755cfa6ad4a51371da2a5ace67500cf7ca5f232c58"
+checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02"
 
 [[package]]
 name = "windows_x86_64_gnu"
@@ -12942,9 +12975,9 @@ checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
 
 [[package]]
 name = "windows_x86_64_gnu"
-version = "0.52.3"
+version = "0.52.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "704131571ba93e89d7cd43482277d6632589b18ecf4468f591fbae0a8b101614"
+checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03"
 
 [[package]]
 name = "windows_x86_64_gnullvm"
@@ -12960,9 +12993,9 @@ checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
 
 [[package]]
 name = "windows_x86_64_gnullvm"
-version = "0.52.3"
+version = "0.52.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "42079295511643151e98d61c38c0acc444e52dd42ab456f7ccfd5152e8ecf21c"
+checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177"
 
 [[package]]
 name = "windows_x86_64_msvc"
@@ -12984,9 +13017,9 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
 
 [[package]]
 name = "windows_x86_64_msvc"
-version = "0.52.3"
+version = "0.52.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0770833d60a970638e989b3fa9fd2bb1aaadcf88963d1659fd7d9990196ed2d6"
+checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8"
 
 [[package]]
 name = "winnow"
@@ -13116,9 +13149,6 @@ dependencies = [
  "hex",
  "itertools 0.12.1",
  "log",
- "pallet-dkg",
- "pallet-jobs",
- "pallet-jobs-rpc-runtime-api",
  "parity-scale-codec 3.6.9",
  "parking_lot 0.12.1",
  "protocol-macros",
@@ -13126,14 +13156,11 @@ dependencies = [
  "rand_chacha 0.3.1",
  "rand_core 0.6.4",
  "round-based 0.2.1",
- "sc-client-api",
  "serde",
  "sha2 0.10.8",
  "sp-api",
- "sp-application-crypto",
  "sp-core",
  "sp-io",
- "sp-runtime",
  "tangle-primitives",
  "test-utils",
  "thiserror",
@@ -13158,7 +13185,7 @@ checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.51",
+ "syn 2.0.52",
 ]
 
 [[package]]
@@ -13178,7 +13205,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.51",
+ "syn 2.0.52",
 ]
 
 [[package]]
@@ -13208,16 +13235,13 @@ dependencies = [
  "groth16",
  "log",
  "mpc-net",
- "pallet-jobs-rpc-runtime-api",
  "parking_lot 0.12.1",
  "protocol-macros",
  "rayon",
  "rcgen 0.12.1",
- "sc-client-api",
  "secret-sharing",
  "serde",
  "serde_bytes",
- "sp-api",
  "sp-core",
  "sp-runtime",
  "tangle-primitives",
diff --git a/Cargo.toml b/Cargo.toml
index 302fb5edb..fb87574ba 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -31,13 +31,8 @@ pallet-jobs = { git = "https://github.com/webb-tools/tangle.git", branch = "main
 pallet-dkg = { git = "https://github.com/webb-tools/tangle.git", branch = "main" }
 pallet-zksaas = { git = "https://github.com/webb-tools/tangle.git", branch = "main" }
 tangle-primitives = { git = "https://github.com/webb-tools/tangle.git", branch = "main" }
-# pallet-jobs-rpc-runtime-api = { path = "../tangle/pallets/jobs/rpc/runtime-api" }
-# pallet-jobs = { path = "../tangle/pallets/jobs" }
-# pallet-dkg = { path = "../tangle/pallets/dkg" }
-# pallet-zksaas = { path = "../tangle/pallets/zksaas" }
-# tangle-primitives = { path = "../tangle/primitives" }
+tangle-subxt = { git = "https://github.com/webb-tools/tangle.git", branch = "main", default-features = false }
 
-webb = { git = "https://github.com/webb-tools/webb-rs.git", default-features = false, branch = "main" }
 subxt-signer = { version = "0.31.0", default-features = false }
 
 multi-party-ecdsa = { git = "https://github.com/webb-tools/cggmp-threshold-ecdsa/" }
diff --git a/flake.lock b/flake.lock
index 30ece7b96..a42147d9a 100644
--- a/flake.lock
+++ b/flake.lock
@@ -5,11 +5,11 @@
         "systems": "systems"
       },
       "locked": {
-        "lastModified": 1705309234,
-        "narHash": "sha256-uNRRNRKmJyCRC/8y1RqBkqWBLM034y4qN7EprSdmgyA=",
+        "lastModified": 1709126324,
+        "narHash": "sha256-q6EQdSeUZOG26WelxqkmR7kArjgWCdw5sfJVHPH/7j8=",
         "owner": "numtide",
         "repo": "flake-utils",
-        "rev": "1ef2e671c3b0c19053962c07dbda38332dcebf26",
+        "rev": "d465f4819400de7c8d874d50b982301f28a84605",
         "type": "github"
       },
       "original": {
@@ -20,11 +20,11 @@
     },
     "nixpkgs": {
       "locked": {
-        "lastModified": 1706173671,
-        "narHash": "sha256-lciR7kQUK2FCAYuszyd7zyRRmTaXVeoZsCyK6QFpGdk=",
+        "lastModified": 1709386671,
+        "narHash": "sha256-VPqfBnIJ+cfa78pd4Y5Cr6sOWVW8GYHRVucxJGmRf8Q=",
         "owner": "NixOS",
         "repo": "nixpkgs",
-        "rev": "4fddc9be4eaf195d631333908f2a454b03628ee5",
+        "rev": "fa9a51752f1b5de583ad5213eb621be071806663",
         "type": "github"
       },
       "original": {
@@ -51,11 +51,11 @@
         ]
       },
       "locked": {
-        "lastModified": 1706235145,
-        "narHash": "sha256-3jh5nahTlcsX6QFcMPqxtLn9p9CgT9RSce5GLqjcpi4=",
+        "lastModified": 1709604635,
+        "narHash": "sha256-le4fwmWmjGRYWwkho0Gr7mnnZndOOe4XGbLw68OvF40=",
         "owner": "oxalica",
         "repo": "rust-overlay",
-        "rev": "3a57c4e29cb2beb777b2e6ae7309a680585b8b2f",
+        "rev": "e86c0fb5d3a22a5f30d7f64ecad88643fe26449d",
         "type": "github"
       },
       "original": {
diff --git a/gadget-common/Cargo.toml b/gadget-common/Cargo.toml
index bf76df48c..e667ffa47 100644
--- a/gadget-common/Cargo.toml
+++ b/gadget-common/Cargo.toml
@@ -5,20 +5,8 @@ edition = "2021"
 
 # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
 
-[features]
-default = [
-    "std"
-]
-std = [
-    "sp-api/std",
-    "tangle-primitives/std",
-    "pallet-jobs-rpc-runtime-api/std"
-]
-testnet = []
-testing = []
-
 [dependencies]
-gadget-core = { workspace = true, features = ["substrate"] }
+gadget-core = { workspace = true }
 protocol-macros = { workspace = true }
 tokio = { workspace = true }
 serde = { workspace = true, features = ["derive"] }
@@ -27,33 +15,57 @@ async-trait = { workspace = true }
 log = { workspace = true }
 parking_lot = { workspace = true }
 futures-util = { workspace = true }
-sc-client-api = { workspace = true }
-sc-service = { workspace = true }
-sp-core = { workspace = true }
-sp-runtime = { workspace = true }
-sp-application-crypto = { workspace = true }
 hex = { workspace = true }
 bincode2 = { workspace = true }
 serde_bytes = { workspace = true }
-linked-hash-map = { workspace = true }
-webb = { workspace = true, default-features = false, features = ["substrate-runtime"] }
-subxt-signer = { workspace = true, features = ["subxt", "sr25519"] }
 anyhow = { workspace = true }
 futures = { workspace = true }
 round-based = { workspace = true }
 round-based-21 = { workspace = true, features = ["derive"]}
-sp-api = { workspace = true }
-sp-io = { workspace = true }
 sqlx = { workspace = true, features = ["runtime-tokio-rustls", "sqlite"] }
-substrate-prometheus-endpoint = { workspace = true }
 lazy_static = { workspace = true }
 
-frame-support = { workspace = true }
-sc-network = { workspace = true }
-sc-network-common = { workspace = true }
-sc-network-sync = { workspace = true }
+# Substrate
+tangle-subxt = { workspace = true, default-features = false, optional = true }
+subxt-signer = { workspace = true, features = ["subxt", "sr25519"], optional = true }
+sp-api = { workspace = true, optional = true }
+sp-io = { workspace = true, optional = true }
+sp-core = { workspace = true, optional = true }
+sp-application-crypto = { workspace = true, optional = true }
+sp-runtime = { workspace = true, optional = true }
+sc-service = { workspace = true, optional = true }
+sc-client-api = { workspace = true, optional = true }
+sc-network = { workspace = true, optional = true }
+sc-network-common = { workspace = true, optional = true }
+sc-network-sync = { workspace = true, optional = true }
+substrate-prometheus-endpoint = { workspace = true, optional = true }
+frame-support = { workspace = true, optional = true }
+linked-hash-map = { workspace = true, optional = true }
 
-tangle-primitives = { workspace = true, features = ["std"] }
-pallet-jobs-rpc-runtime-api = { workspace = true, features = ["std"] }
-parity-scale-codec = { workspace = true }
-scale-info = { workspace = true }
+parity-scale-codec = { workspace = true, optional = true }
+scale-info = { workspace = true, optional = true }
+
+
+[features]
+default = ["substrate"]
+substrate = [
+  "gadget-core/substrate",
+  "tangle-subxt",
+  "subxt-signer",
+  "sp-api",
+  "sp-io",
+  "sp-core",
+  "sp-runtime",
+  "sp-application-crypto",
+  "sc-service",
+  "sc-client-api",
+  "sc-network",
+  "sc-network-common",
+  "sc-network-sync",
+  "frame-support",
+  "linked-hash-map",
+  "substrate-prometheus-endpoint",
+  "parity-scale-codec",
+  "scale-info",
+]
+testing = []
diff --git a/gadget-common/src/client.rs b/gadget-common/src/client.rs
index 4bedb1dc2..8aea1896f 100644
--- a/gadget-common/src/client.rs
+++ b/gadget-common/src/client.rs
@@ -1,298 +1,278 @@
 use crate::debug_logger::DebugLogger;
 use async_trait::async_trait;
 use auto_impl::auto_impl;
-use gadget_core::gadget::substrate::Client;
-use pallet_jobs_rpc_runtime_api::{BlockNumberOf, JobsApi};
-use sc_client_api::{
-    Backend, BlockImportNotification, BlockchainEvents, FinalityNotification,
-    FinalityNotifications, ImportNotifications, StorageEventStream, StorageKey,
-};
-use sp_api::{ApiRef, ProvideRuntimeApi};
-use sp_api::{BlockT as Block, Decode, Encode};
-use sp_core::Pair;
+use gadget_core::gadget::substrate::{Client, FinalityNotification};
 use sp_core::{ecdsa, ByteArray};
+use sp_core::{sr25519, Pair};
+use tangle_subxt::tangle_runtime::api::runtime_types::tangle_primitives::{jobs, roles};
 
 use std::sync::Arc;
+use subxt::config::ExtrinsicParams;
 use subxt::tx::TxPayload;
+use subxt::utils::AccountId32;
 use subxt::OnlineClient;
-use tangle_primitives::jobs::JobId;
-use tangle_primitives::jobs::{PhaseResult, RpcResponseJobsData};
-use tangle_primitives::roles::RoleType;
-use webb::substrate::subxt;
-use webb::substrate::subxt::config::ExtrinsicParams;
+use tangle_subxt::subxt;
 
-pub struct JobsClient<B: Block, BE, C> {
+pub struct JobsClient<C> {
     pub client: C,
     logger: DebugLogger,
     pallet_tx: Arc<dyn PalletSubmitter>,
-    _block: std::marker::PhantomData<(BE, B)>,
 }
 
-impl<B: Block, BE, C: Clone> Clone for JobsClient<B, BE, C> {
+impl<C: Clone> Clone for JobsClient<C> {
     fn clone(&self) -> Self {
         Self {
             client: self.client.clone(),
             logger: self.logger.clone(),
             pallet_tx: self.pallet_tx.clone(),
-            _block: self._block,
         }
     }
 }
 
-pub async fn create_client<B: Block, BE: Backend<B>, C: ClientWithApi<B, BE>>(
+pub async fn create_client<C: ClientWithApi>(
     client: C,
     logger: DebugLogger,
     pallet_tx: Arc<dyn PalletSubmitter>,
-) -> Result<JobsClient<B, BE, C>, crate::Error>
-where
-    <C as ProvideRuntimeApi<B>>::Api: JobsApiForGadget<B>,
-{
+) -> Result<JobsClient<C>, crate::Error> {
     Ok(JobsClient {
         client,
         logger,
         pallet_tx,
-        _block: std::marker::PhantomData,
     })
 }
 
-pub mod types {
-    #[cfg(not(feature = "testnet"))]
-    use frame_support::pallet_prelude::{Decode, Encode, TypeInfo};
-    use pallet_jobs_rpc_runtime_api::JobsApi;
-    #[cfg(not(feature = "testnet"))]
-    use serde::{Deserialize, Serialize};
-    use sp_runtime::traits::Block;
-    #[cfg(not(feature = "testnet"))]
-    use sp_runtime::RuntimeDebug;
-    use tangle_primitives::jobs::{JobResult, JobType, PhaseResult};
-
-    #[cfg(not(feature = "testnet"))]
-    frame_support::parameter_types! {
-        #[derive(Clone, RuntimeDebug, Eq, PartialEq, TypeInfo, Encode, Decode)]
-        #[derive(Serialize, Deserialize)]
-        pub const MaxSubmissionLen: u32 = 60_000_000;
-        #[derive(Clone, RuntimeDebug, Eq, PartialEq, TypeInfo, Encode, Decode)]
-        #[derive(Serialize, Deserialize)]
-        pub const MaxParticipants: u32 = 10;
-        #[derive(Clone, RuntimeDebug, Eq, PartialEq, TypeInfo, Encode, Decode)]
-        #[derive(Serialize, Deserialize)]
-        pub const MaxKeyLen: u32 = 256;
-        #[derive(Clone, RuntimeDebug, Eq, PartialEq, TypeInfo, Encode, Decode)]
-        #[derive(Serialize, Deserialize)]
-        pub const MaxDataLen: u32 = 256;
-        #[derive(Clone, RuntimeDebug, Eq, PartialEq, TypeInfo, Encode, Decode)]
-        #[derive(Serialize, Deserialize)]
-        pub const MaxSignatureLen: u32 = 256;
-        #[derive(Clone, RuntimeDebug, Eq, PartialEq, TypeInfo, Encode, Decode)]
-        #[derive(Serialize, Deserialize)]
-        pub const MaxProofLen: u32 = 256;
-        #[derive(Clone, RuntimeDebug, Eq, PartialEq, TypeInfo, Encode, Decode)]
-        #[derive(Serialize, Deserialize)]
-        pub const MaxActiveJobsPerValidator: u32 = 100;
-        #[derive(Clone, RuntimeDebug, Eq, PartialEq, TypeInfo, Encode, Decode)]
-        #[derive(Serialize, Deserialize)]
-        pub const MaxRolesPerValidator: u32 = 100;
-    }
-
-    #[cfg(feature = "testnet")]
-    pub use tangle_primitives::jobs::{
-        MaxActiveJobsPerValidator, MaxDataLen, MaxKeyLen, MaxParticipants, MaxProofLen,
-        MaxSignatureLen, MaxSubmissionLen,
-    };
-    pub use tangle_primitives::AccountId;
-
-    pub type GadgetJobResult =
-        JobResult<MaxParticipants, MaxKeyLen, MaxSignatureLen, MaxDataLen, MaxProofLen>;
-    pub type GadgetJobType = JobType<AccountId, MaxParticipants, MaxSubmissionLen>;
-    pub type GadgetPhaseResult<B> = PhaseResult<
-        AccountId,
-        B,
-        MaxParticipants,
-        MaxKeyLen,
-        MaxDataLen,
-        MaxSignatureLen,
-        MaxSubmissionLen,
-        MaxProofLen,
-    >;
-
-    pub trait JobsApiForGadget<B: Block>:
-        JobsApi<
-        B,
-        AccountId,
-        MaxParticipants,
-        MaxSubmissionLen,
-        MaxKeyLen,
-        MaxDataLen,
-        MaxSignatureLen,
-        MaxProofLen,
-    >
-    {
-    }
-    // Implement JobsApiForGadget for any T that implements JobsApi
-    impl<
-            B: Block,
-            T: JobsApi<
-                B,
-                AccountId,
-                MaxParticipants,
-                MaxSubmissionLen,
-                MaxKeyLen,
-                MaxDataLen,
-                MaxSignatureLen,
-                MaxProofLen,
-            >,
-        > JobsApiForGadget<B> for T
-    {
-    }
-}
-
-pub use types::*;
-
-pub trait ClientWithApi<B, BE>:
-    BlockchainEvents<B> + ProvideRuntimeApi<B> + Send + Sync + Client<B> + Clone + 'static
+pub async fn exec_client_function<C: Clone, F, T>(client: &C, function: F) -> T
 where
-    B: Block,
-    BE: Backend<B>,
-    <Self as ProvideRuntimeApi<B>>::Api: JobsApiForGadget<B>,
+    for<'a> F: FnOnce(&'a C) -> T,
+    C: Send + Sync + 'static,
+    T: Send + 'static,
+    F: Send + 'static,
 {
+    let client = client.clone();
+    tokio::task::spawn_blocking(move || function(&client))
+        .await
+        .expect("Failed to spawn blocking task")
 }
 
-impl<B, BE, T> ClientWithApi<B, BE> for T
-where
-    B: Block,
-    BE: Backend<B>,
-    T: BlockchainEvents<B> + ProvideRuntimeApi<B> + Send + Sync + Client<B> + Clone + 'static,
-    <T as ProvideRuntimeApi<B>>::Api: JobsApiForGadget<B>,
-{
+pub trait JobTypeExt {
+    /// Checks if the job type is a phase one job.
+    fn is_phase_one(&self) -> bool;
+    /// Gets the participants for the job type, if applicable.
+    fn get_participants(self) -> Option<Vec<AccountId32>>;
+    /// Gets the threshold value for the job type, if applicable.
+    fn get_threshold(self) -> Option<u8>;
+    /// Gets the role associated with the job type.
+    fn get_role_type(&self) -> roles::RoleType;
+    /// Gets the phase one ID for phase two jobs, if applicable.
+    fn get_phase_one_id(&self) -> Option<u64>;
+    /// Gets the permitted caller for the job type, if applicable.
+    fn get_permitted_caller(self) -> Option<AccountId32>;
 }
 
-impl<B: Block, BE: Backend<B>, C: ClientWithApi<B, BE>> ProvideRuntimeApi<B>
-    for JobsClient<B, BE, C>
-where
-    <C as ProvideRuntimeApi<B>>::Api: JobsApiForGadget<B>,
-{
-    type Api = C::Api;
-
-    fn runtime_api(&self) -> ApiRef<Self::Api> {
-        self.client.runtime_api()
-    }
+pub trait PhaseResultExt {
+    /// Gets the participants for the phase result, if applicable.
+    fn participants(&self) -> Option<Vec<AccountId32>>;
+    /// Gets the threshold value for the phase result, if applicable.
+    fn threshold(&self) -> Option<u8>;
 }
 
-impl<B: Block, BE: Backend<B>, C: ClientWithApi<B, BE>> BlockchainEvents<B> for JobsClient<B, BE, C>
-where
-    <C as ProvideRuntimeApi<B>>::Api: JobsApiForGadget<B>,
-{
-    fn import_notification_stream(&self) -> ImportNotifications<B> {
-        self.client.import_notification_stream()
-    }
-
-    fn every_import_notification_stream(&self) -> ImportNotifications<B> {
-        self.client.every_import_notification_stream()
-    }
+#[async_trait]
+pub trait ClientWithApi: Client {
+    /// Query jobs associated with a specific validator.
+    ///
+    /// This function takes a `validator` parameter of type `AccountId` and attempts
+    /// to retrieve a list of jobs associated with the provided validator. If successful,
+    /// it constructs a vector of `RpcResponseJobsData` containing information
+    /// about the jobs and returns it as a `Result`.
+    ///
+    /// # Arguments
+    ///
+    /// * `validator` - The account ID of the validator whose jobs are to be queried.
+    ///
+    /// # Returns
+    ///
+    /// An optional vec of `RpcResponseJobsData` of jobs assigned to validator
+    async fn query_jobs_by_validator(
+        &self,
+        at: [u8; 32],
+        validator: AccountId32,
+    ) -> Result<
+        Option<
+            Vec<
+                jobs::RpcResponseJobsData<
+                    AccountId32,
+                    u64,
+                    jobs::MaxParticipants,
+                    jobs::MaxSubmissionLen,
+                >,
+            >,
+        >,
+        crate::Error,
+    >;
+    /// Queries a job by its key and ID.
+    ///
+    /// # Arguments
+    ///
+    /// * `role_type` - The role of the job.
+    /// * `job_id` - The ID of the job.
+    ///
+    /// # Returns
+    ///
+    /// An optional `RpcResponseJobsData` containing the account ID of the job.
+    async fn query_job_by_id(
+        &self,
+        at: [u8; 32],
+        role_type: roles::RoleType,
+        job_id: u64,
+    ) -> Result<
+        Option<
+            jobs::RpcResponseJobsData<
+                AccountId32,
+                u64,
+                jobs::MaxParticipants,
+                jobs::MaxSubmissionLen,
+            >,
+        >,
+        crate::Error,
+    >;
 
-    fn finality_notification_stream(&self) -> FinalityNotifications<B> {
-        self.client.finality_notification_stream()
-    }
+    /// Queries the result of a job by its role_type and ID.
+    ///
+    /// # Arguments
+    ///
+    /// * `role_type` - The role of the job.
+    /// * `job_id` - The ID of the job.
+    ///
+    /// # Returns
+    ///
+    /// An `Option` containing the phase one result of the job, wrapped in an `PhaseResult`.
+    async fn query_job_result(
+        &self,
+        at: [u8; 32],
+        role_type: roles::RoleType,
+        job_id: u64,
+    ) -> Result<
+        Option<
+            jobs::PhaseResult<
+                AccountId32,
+                u64,
+                jobs::MaxParticipants,
+                jobs::MaxKeyLen,
+                jobs::MaxDataLen,
+                jobs::MaxSignatureLen,
+                jobs::MaxSubmissionLen,
+                jobs::MaxProofLen,
+            >,
+        >,
+        crate::Error,
+    >;
 
-    fn storage_changes_notification_stream(
+    /// Queries next job ID.
+    ///
+    ///  # Returns
+    ///  Next job ID.
+    async fn query_next_job_id(&self, at: [u8; 32]) -> Result<u64, crate::Error>;
+
+    /// Queries restaker's role key
+    ///
+    ///  # Returns
+    ///  Role key
+    async fn query_restaker_role_key(
         &self,
-        filter_keys: Option<&[StorageKey]>,
-        child_filter_keys: Option<&[(StorageKey, Option<Vec<StorageKey>>)]>,
-    ) -> sc_client_api::blockchain::Result<StorageEventStream<B::Hash>> {
-        self.client
-            .storage_changes_notification_stream(filter_keys, child_filter_keys)
-    }
+        at: [u8; 32],
+        address: AccountId32,
+    ) -> Result<Option<Vec<u8>>, crate::Error>;
 }
 
-impl<B: Block, BE: Backend<B>, C: ClientWithApi<B, BE>> JobsClient<B, BE, C>
-where
-    <C as ProvideRuntimeApi<B>>::Api: JobsApiForGadget<B>,
-{
+impl<C: ClientWithApi> JobsClient<C> {
     pub async fn query_jobs_by_validator(
         &self,
-        at: <B as Block>::Hash,
-        validator: AccountId,
+        at: [u8; 32],
+        validator: sr25519::Public,
     ) -> Result<
-        Vec<RpcResponseJobsData<AccountId, BlockNumberOf<B>, MaxParticipants, MaxSubmissionLen>>,
+        Vec<
+            jobs::RpcResponseJobsData<
+                AccountId32,
+                u64,
+                jobs::MaxParticipants,
+                jobs::MaxSubmissionLen,
+            >,
+        >,
         crate::Error,
     > {
-        exec_client_function(&self.client, move |client| {
-            client.runtime_api().query_jobs_by_validator(at, validator)
-        })
-        .await
-        .map_err(|err| crate::Error::ClientError {
-            err: format!("Failed to query jobs by validator: {err:?}"),
-        })
-        .map(|r| r.unwrap_or_default())
+        Ok(self
+            .client
+            .query_jobs_by_validator(at, AccountId32::from(validator.0))
+            .await?
+            .into_iter()
+            .flatten()
+            .collect())
     }
 
     pub async fn query_restaker_role_key(
         &self,
-        at: <B as Block>::Hash,
-        address: AccountId,
+        at: [u8; 32],
+        address: sr25519::Public,
     ) -> Result<Option<ecdsa::Public>, crate::Error> {
-        exec_client_function(&self.client, move |client| {
-            client.runtime_api().query_restaker_role_key(at, address)
-        })
-        .await
-        .map_err(|err| crate::Error::ClientError {
-            err: format!("Failed to query restaker role key: {err:?}"),
-        })
-        .map(|r| r.and_then(|v| ecdsa::Public::from_slice(v.as_slice()).ok()))
+        self.client
+            .query_restaker_role_key(at, AccountId32::from(address.0))
+            .await
+            .map(|r| r.and_then(|v| ecdsa::Public::from_slice(v.as_slice()).ok()))
     }
 
     pub async fn query_job_by_id(
         &self,
-        at: <B as Block>::Hash,
-        role_type: RoleType,
-        job_id: JobId,
+        at: [u8; 32],
+        role_type: roles::RoleType,
+        job_id: u64,
     ) -> Result<
-        Option<RpcResponseJobsData<AccountId, BlockNumberOf<B>, MaxParticipants, MaxSubmissionLen>>,
+        Option<
+            jobs::RpcResponseJobsData<
+                AccountId32,
+                u64,
+                jobs::MaxParticipants,
+                jobs::MaxSubmissionLen,
+            >,
+        >,
         crate::Error,
     > {
-        exec_client_function(&self.client, move |client| {
-            client.runtime_api().query_job_by_id(at, role_type, job_id)
-        })
-        .await
-        .map_err(|err| crate::Error::ClientError {
-            err: format!("Failed to query job by id: {err:?}"),
-        })
+        self.client.query_job_by_id(at, role_type, job_id).await
     }
 
     pub async fn query_job_result(
         &self,
-        at: <B as Block>::Hash,
-        role_type: RoleType,
-        job_id: JobId,
+        at: [u8; 32],
+        role_type: roles::RoleType,
+        job_id: u64,
     ) -> Result<
         Option<
-            PhaseResult<
-                AccountId,
-                BlockNumberOf<B>,
-                MaxParticipants,
-                MaxKeyLen,
-                MaxDataLen,
-                MaxSignatureLen,
-                MaxSubmissionLen,
-                MaxProofLen,
+            jobs::PhaseResult<
+                AccountId32,
+                u64,
+                jobs::MaxParticipants,
+                jobs::MaxKeyLen,
+                jobs::MaxDataLen,
+                jobs::MaxSignatureLen,
+                jobs::MaxSubmissionLen,
+                jobs::MaxProofLen,
             >,
         >,
         crate::Error,
     > {
-        exec_client_function(&self.client, move |client| {
-            client.runtime_api().query_job_result(at, role_type, job_id)
-        })
-        .await
-        .map_err(|err| crate::Error::ClientError {
-            err: format!("Failed to query phase 1 by id: {err:?}"),
-        })
+        self.client.query_job_result(at, role_type, job_id).await
     }
 
     pub async fn submit_job_result(
         &self,
-        role_type: RoleType,
-        job_id: JobId,
-        result: GadgetJobResult,
+        role_type: roles::RoleType,
+        job_id: u64,
+        result: jobs::JobResult<
+            jobs::MaxParticipants,
+            jobs::MaxKeyLen,
+            jobs::MaxSignatureLen,
+            jobs::MaxDataLen,
+            jobs::MaxProofLen,
+        >,
     ) -> Result<(), crate::Error> {
         self.pallet_tx
             .submit_job_result(role_type, job_id, result)
@@ -300,24 +280,108 @@ where
     }
 }
 
-#[async_trait]
-impl<B, BE, C> Client<B> for JobsClient<B, BE, C>
-where
-    B: Block,
-    BE: Backend<B>,
-    C: ClientWithApi<B, BE>,
-    <C as ProvideRuntimeApi<B>>::Api: JobsApiForGadget<B>,
+impl<MaxParticipants, MaxSubmissionLen> JobTypeExt
+    for jobs::JobType<AccountId32, MaxParticipants, MaxSubmissionLen>
 {
-    async fn get_next_finality_notification(&self) -> Option<FinalityNotification<B>> {
-        self.client.get_next_finality_notification().await
+    fn is_phase_one(&self) -> bool {
+        use jobs::JobType::*;
+        matches!(self, DKGTSSPhaseOne(_) | ZkSaaSPhaseOne(_))
     }
 
-    async fn get_latest_finality_notification(&self) -> Option<FinalityNotification<B>> {
-        self.client.get_latest_finality_notification().await
+    fn get_participants(self) -> Option<Vec<AccountId32>> {
+        use jobs::JobType::*;
+        match self {
+            DKGTSSPhaseOne(p) => Some(p.participants.0),
+            ZkSaaSPhaseOne(p) => Some(p.participants.0),
+            _ => None,
+        }
+    }
+
+    fn get_threshold(self) -> Option<u8> {
+        use jobs::JobType::*;
+        match self {
+            DKGTSSPhaseOne(p) => Some(p.threshold),
+            _ => None,
+        }
+    }
+
+    fn get_role_type(&self) -> roles::RoleType {
+        use jobs::JobType::*;
+        use roles::RoleType;
+        match self {
+            DKGTSSPhaseOne(job) => RoleType::Tss(job.role_type.clone()),
+            ZkSaaSPhaseOne(job) => RoleType::ZkSaaS(job.role_type.clone()),
+            DKGTSSPhaseTwo(job) => RoleType::Tss(job.role_type.clone()),
+            ZkSaaSPhaseTwo(job) => RoleType::ZkSaaS(job.role_type.clone()),
+            DKGTSSPhaseThree(job) => RoleType::Tss(job.role_type.clone()),
+            DKGTSSPhaseFour(job) => RoleType::Tss(job.role_type.clone()),
+        }
+    }
+
+    fn get_phase_one_id(&self) -> Option<u64> {
+        use jobs::JobType::*;
+        match self {
+            DKGTSSPhaseTwo(info) => Some(info.phase_one_id),
+            DKGTSSPhaseThree(info) => Some(info.phase_one_id),
+            DKGTSSPhaseFour(info) => Some(info.phase_one_id),
+            ZkSaaSPhaseTwo(info) => Some(info.phase_one_id),
+            _ => None,
+        }
+    }
+
+    fn get_permitted_caller(self) -> Option<AccountId32> {
+        use jobs::JobType::*;
+        match self {
+            DKGTSSPhaseOne(p) => p.permitted_caller,
+            ZkSaaSPhaseOne(p) => p.permitted_caller,
+            _ => None,
+        }
+    }
+}
+
+impl<
+        JobId,
+        MaxParticipants,
+        MaxKeyLen,
+        MaxDataLen,
+        MaxSignatureLen,
+        MaxSubmissionLen,
+        MaxProofLen,
+    > PhaseResultExt
+    for jobs::PhaseResult<
+        AccountId32,
+        JobId,
+        MaxParticipants,
+        MaxKeyLen,
+        MaxDataLen,
+        MaxSignatureLen,
+        MaxSubmissionLen,
+        MaxProofLen,
+    >
+{
+    fn participants(&self) -> Option<Vec<AccountId32>> {
+        match &self.job_type {
+            jobs::JobType::DKGTSSPhaseOne(p) => Some(p.participants.0.clone()),
+            jobs::JobType::ZkSaaSPhaseOne(p) => Some(p.participants.0.clone()),
+            _ => None,
+        }
+    }
+    fn threshold(&self) -> Option<u8> {
+        match &self.job_type {
+            jobs::JobType::DKGTSSPhaseOne(p) => Some(p.threshold),
+            _ => None,
+        }
+    }
+}
+
+#[async_trait]
+impl<C: Client> Client for JobsClient<C> {
+    async fn get_next_finality_notification(&self) -> Option<FinalityNotification> {
+        self.client.get_next_finality_notification().await
     }
 
-    async fn get_next_block_import_notification(&self) -> Option<BlockImportNotification<B>> {
-        self.client.get_next_block_import_notification().await
+    async fn get_latest_finality_notification(&self) -> Option<FinalityNotification> {
+        self.client.get_latest_finality_notification().await
     }
 }
 /// A [`Signer`] implementation that can be constructed from an [`sp_core::Pair`].
@@ -359,9 +423,16 @@ where
 pub trait PalletSubmitter: Send + Sync + 'static {
     async fn submit_job_result(
         &self,
-        role_type: RoleType,
-        job_id: JobId,
-        result: GadgetJobResult,
+        role_type: roles::RoleType,
+        job_id: u64,
+
+        result: jobs::JobResult<
+            jobs::MaxParticipants,
+            jobs::MaxKeyLen,
+            jobs::MaxSignatureLen,
+            jobs::MaxDataLen,
+            jobs::MaxProofLen,
+        >,
     ) -> Result<(), crate::Error>;
 }
 
@@ -386,17 +457,19 @@ where
 {
     async fn submit_job_result(
         &self,
-        role_type: RoleType,
-        job_id: JobId,
-        result: GadgetJobResult,
+        role_type: roles::RoleType,
+        job_id: u64,
+        result: jobs::JobResult<
+            jobs::MaxParticipants,
+            jobs::MaxKeyLen,
+            jobs::MaxSignatureLen,
+            jobs::MaxDataLen,
+            jobs::MaxProofLen,
+        >,
     ) -> Result<(), crate::Error> {
-        let tx = webb::substrate::tangle_runtime::api::tx()
+        let tx = tangle_subxt::tangle_runtime::api::tx()
             .jobs()
-            .submit_job_result(
-                Decode::decode(&mut role_type.encode().as_slice()).expect("Should decode"),
-                job_id,
-                Decode::decode(&mut result.encode().as_slice()).expect("Should decode"),
-            );
+            .submit_job_result(role_type, job_id, result);
         match self.submit(&tx).await {
             Ok(hash) => {
                 self.logger.info(format!(
@@ -461,24 +534,12 @@ where
     }
 }
 
-async fn exec_client_function<C: Clone, F, T>(client: &C, function: F) -> T
-where
-    for<'a> F: FnOnce(&'a C) -> T,
-    C: Send + Sync + 'static,
-    T: Send + 'static,
-    F: Send + 'static,
-{
-    let client = client.clone();
-    tokio::task::spawn_blocking(move || function(&client))
-        .await
-        .expect("Failed to spawn blocking task")
-}
-
 #[cfg(test)]
 mod tests {
 
-    use webb::substrate::{
+    use tangle_subxt::{
         subxt::{tx::Signer, utils::AccountId32, PolkadotConfig},
+        tangle_runtime::api,
         tangle_runtime::api::runtime_types::{
             bounded_collections::bounded_vec::BoundedVec,
             tangle_primitives::{jobs, roles},
@@ -512,9 +573,7 @@ mod tests {
                 __subxt_unused_type_params: std::marker::PhantomData,
             }),
         };
-        let tx = webb::substrate::tangle_runtime::api::tx()
-            .jobs()
-            .submit_job(dkg_phase_one);
+        let tx = api::tx().jobs().submit_job(dkg_phase_one);
         let _hash = pallet_tx.submit(&tx).await?;
         Ok(())
     }
diff --git a/gadget-common/src/config.rs b/gadget-common/src/config.rs
index 9b95a9cf1..32b02d5b4 100644
--- a/gadget-common/src/config.rs
+++ b/gadget-common/src/config.rs
@@ -1,40 +1,39 @@
-use crate::client::{create_client, JobsApiForGadget, JobsClient, PalletSubmitter};
-pub use crate::client::{AccountId, ClientWithApi};
+pub use crate::client::ClientWithApi;
+use crate::client::{create_client, JobsClient, PalletSubmitter};
 pub use crate::debug_logger::DebugLogger;
 pub use crate::gadget::network::Network;
 pub use crate::gadget::GadgetProtocol;
 pub use crate::prometheus::PrometheusConfig;
 use async_trait::async_trait;
-pub use pallet_jobs_rpc_runtime_api::JobsApi;
-pub use sc_client_api::Backend;
-pub use sp_api::ProvideRuntimeApi;
-pub use sp_runtime::traits::Block;
 use std::sync::Arc;
 
 #[async_trait]
 pub trait ProtocolConfig
 where
-    <<Self::ProtocolSpecificConfiguration as NetworkAndProtocolSetup>::Client as ProvideRuntimeApi<<Self::ProtocolSpecificConfiguration as NetworkAndProtocolSetup>::Block>>::Api: JobsApiForGadget<<Self::ProtocolSpecificConfiguration as NetworkAndProtocolSetup>::Block>,
     Self: Sized,
 {
     type Network: Network;
     type Protocol: GadgetProtocol<
-        <Self::ProtocolSpecificConfiguration as NetworkAndProtocolSetup>::Block,
-        <Self::ProtocolSpecificConfiguration as NetworkAndProtocolSetup>::Backend,
-        <Self::ProtocolSpecificConfiguration as NetworkAndProtocolSetup>::Client
+        <Self::ProtocolSpecificConfiguration as NetworkAndProtocolSetup>::Client,
     >;
     type ProtocolSpecificConfiguration: Clone
-        + NetworkAndProtocolSetup<Network = Self::Network, Protocol = Self::Protocol> + Sync;
+        + NetworkAndProtocolSetup<Network = Self::Network, Protocol = Self::Protocol>
+        + Sync;
     fn params(&self) -> &Self::ProtocolSpecificConfiguration;
 
     fn take_network(&mut self) -> Self::Network;
     fn take_protocol(&mut self) -> Self::Protocol;
-    fn take_client(&mut self) -> <Self::ProtocolSpecificConfiguration as NetworkAndProtocolSetup>::Client;
+    fn take_client(
+        &mut self,
+    ) -> <Self::ProtocolSpecificConfiguration as NetworkAndProtocolSetup>::Client;
     fn prometheus_config(&self) -> PrometheusConfig;
 
     async fn build(&self) -> Result<Self, crate::Error> {
         let jobs_client = self.params().build_jobs_client().await?;
-        let (network, protocol) = self.params().build_network_and_protocol(jobs_client).await?;
+        let (network, protocol) = self
+            .params()
+            .build_network_and_protocol(jobs_client)
+            .await?;
         let client = self.params().client();
         let params = self.params().clone();
         let pallet_tx = self.pallet_tx();
@@ -42,7 +41,13 @@ where
         let prometheus_config = self.prometheus_config();
 
         Ok(Self::new(
-            network, client, protocol, params, pallet_tx, logger, prometheus_config,
+            network,
+            client,
+            protocol,
+            params,
+            pallet_tx,
+            logger,
+            prometheus_config,
         ))
     }
 
@@ -69,27 +74,18 @@ where
 }
 
 #[async_trait]
-pub trait NetworkAndProtocolSetup
-where
-    <<Self as NetworkAndProtocolSetup>::Client as ProvideRuntimeApi<
-        <Self as NetworkAndProtocolSetup>::Block,
-    >>::Api: JobsApiForGadget<<Self as NetworkAndProtocolSetup>::Block>,
-{
+pub trait NetworkAndProtocolSetup {
     type Network;
     type Protocol;
-    type Client: ClientWithApi<Self::Block, Self::Backend>;
-    type Block: Block;
-    type Backend: Backend<Self::Block>;
+    type Client: ClientWithApi;
 
-    async fn build_jobs_client(
-        &self,
-    ) -> Result<JobsClient<Self::Block, Self::Backend, Self::Client>, crate::Error> {
+    async fn build_jobs_client(&self) -> Result<JobsClient<Self::Client>, crate::Error> {
         create_client(self.client(), self.logger(), self.pallet_tx()).await
     }
 
     async fn build_network_and_protocol(
         &self,
-        jobs_client: JobsClient<Self::Block, Self::Backend, Self::Client>,
+        jobs_client: JobsClient<Self::Client>,
     ) -> Result<(Self::Network, Self::Protocol), crate::Error>;
     fn pallet_tx(&self) -> Arc<dyn PalletSubmitter>;
     fn logger(&self) -> DebugLogger;
diff --git a/gadget-common/src/full_protocol.rs b/gadget-common/src/full_protocol.rs
index 09e14b66f..3c025e4ec 100644
--- a/gadget-common/src/full_protocol.rs
+++ b/gadget-common/src/full_protocol.rs
@@ -1,4 +1,4 @@
-use crate::client::{ClientWithApi, GadgetJobType, JobsApiForGadget, JobsClient, PalletSubmitter};
+use crate::client::{ClientWithApi, JobsClient, PalletSubmitter};
 use crate::config::{DebugLogger, GadgetProtocol, Network, NetworkAndProtocolSetup};
 use crate::gadget::message::GadgetProtocolMessage;
 use crate::gadget::work_manager::WorkManager;
@@ -12,29 +12,20 @@ use gadget_core::job::{BuiltExecutableJobWrapper, JobError};
 use gadget_core::job_manager::{ProtocolWorkManager, WorkManagerInterface};
 use parity_scale_codec::{Decode, Encode};
 use parking_lot::Mutex;
-use sc_client_api::{Backend, BlockImportNotification};
-use sp_api::ProvideRuntimeApi;
-use sp_core::ecdsa::Signature;
-use sp_core::keccak_256;
+use sp_core::ecdsa::{Public, Signature};
+use sp_core::{keccak_256, sr25519};
 use sp_io::crypto::ecdsa_verify_prehashed;
-use sp_runtime::traits::Block;
-use std::marker::PhantomData;
 use std::sync::Arc;
-use tangle_primitives::roles::RoleType;
-use tangle_primitives::AccountId;
+use tangle_subxt::subxt::utils::AccountId32;
+use tangle_subxt::tangle_runtime::api::runtime_types::tangle_primitives::{jobs, roles};
 use tokio::sync::mpsc::UnboundedReceiver;
 
 pub type SharedOptional<T> = Arc<Mutex<Option<T>>>;
 
 #[async_trait]
-pub trait FullProtocolConfig: Clone + Send + Sync + Sized + 'static
-where
-    <Self::Client as ProvideRuntimeApi<Self::Block>>::Api: JobsApiForGadget<Self::Block>,
-{
+pub trait FullProtocolConfig: Clone + Send + Sync + Sized + 'static {
     type AsyncProtocolParameters: Send + Sync + Clone;
-    type Client: ClientWithApi<Self::Block, Self::Backend>;
-    type Block: Block;
-    type Backend: Backend<Self::Block>;
+    type Client: ClientWithApi;
     type Network: Network;
     type AdditionalNodeParameters: Clone + Send + Sync + 'static;
     type KeystoreBackend: KeystoreBackend;
@@ -43,7 +34,7 @@ where
         pallet_tx: Arc<dyn PalletSubmitter>,
         network: Self::Network,
         logger: DebugLogger,
-        account_id: AccountId,
+        account_id: sr25519::Public,
         key_store: ECDSAKeyStore<Self::KeystoreBackend>,
         prometheus_config: PrometheusConfig,
     ) -> Result<Self, Error>;
@@ -69,37 +60,32 @@ where
     /// The provided work manager should only be used for querying recorded_messages
     async fn create_next_job(
         &self,
-        job: JobInitMetadata<Self::Block>,
+        job: JobInitMetadata,
         work_manager: &ProtocolWorkManager<WorkManager>,
     ) -> Result<Self::AsyncProtocolParameters, Error>;
 
-    async fn process_block_import_notification(
-        &self,
-        _notification: BlockImportNotification<Self::Block>,
-        _job_manager: &ProtocolWorkManager<WorkManager>,
-    ) -> Result<(), Error> {
-        Ok(())
-    }
-
     async fn process_error(&self, error: Error, _job_manager: &ProtocolWorkManager<WorkManager>) {
         self.logger().error(format!("Error in protocol: {error}"));
     }
 
-    fn account_id(&self) -> &AccountId;
+    fn account_id(&self) -> &sr25519::Public;
 
     fn name(&self) -> String;
 
-    fn role_filter(&self, role: RoleType) -> bool;
+    fn role_filter(&self, role: roles::RoleType) -> bool;
 
-    fn phase_filter(&self, job: GadgetJobType) -> bool;
+    fn phase_filter(
+        &self,
+        job: jobs::JobType<AccountId32, jobs::MaxParticipants, jobs::MaxSubmissionLen>,
+    ) -> bool;
 
-    fn jobs_client(&self) -> &SharedOptional<JobsClient<Self::Block, Self::Backend, Self::Client>>;
+    fn jobs_client(&self) -> &SharedOptional<JobsClient<Self::Client>>;
     fn pallet_tx(&self) -> Arc<dyn PalletSubmitter>;
 
     fn logger(&self) -> DebugLogger;
 
     fn client(&self) -> Self::Client;
-    fn get_jobs_client(&self) -> JobsClient<Self::Block, Self::Backend, Self::Client> {
+    fn get_jobs_client(&self) -> JobsClient<Self::Client> {
         self.jobs_client()
             .lock()
             .clone()
@@ -112,10 +98,7 @@ where
 }
 
 #[async_trait]
-impl<T: FullProtocolConfig> AsyncProtocol for T
-where
-    <T::Client as ProvideRuntimeApi<T::Block>>::Api: JobsApiForGadget<T::Block>,
-{
+impl<T: FullProtocolConfig> AsyncProtocol for T {
     type AdditionalParams = T::AsyncProtocolParameters;
 
     async fn generate_protocol_from(
@@ -141,19 +124,14 @@ where
 }
 
 #[async_trait]
-impl<T: FullProtocolConfig> NetworkAndProtocolSetup for T
-where
-    <T::Client as ProvideRuntimeApi<T::Block>>::Api: JobsApiForGadget<T::Block>,
-{
+impl<T: FullProtocolConfig> NetworkAndProtocolSetup for T {
     type Network = T;
     type Protocol = T;
     type Client = T::Client;
-    type Block = T::Block;
-    type Backend = T::Backend;
 
     async fn build_network_and_protocol(
         &self,
-        jobs_client: JobsClient<Self::Block, Self::Backend, Self::Client>,
+        jobs_client: JobsClient<Self::Client>,
     ) -> Result<(Self::Network, Self::Protocol), Error> {
         let jobs_client_store = T::jobs_client(self);
         jobs_client_store.lock().replace(jobs_client);
@@ -174,31 +152,20 @@ where
 }
 
 #[async_trait]
-impl<T: FullProtocolConfig> GadgetProtocol<T::Block, T::Backend, T::Client> for T
-where
-    <T::Client as ProvideRuntimeApi<T::Block>>::Api: JobsApiForGadget<T::Block>,
-{
+impl<T: FullProtocolConfig> GadgetProtocol<T::Client> for T {
     async fn create_next_job(
         &self,
-        job: JobInitMetadata<T::Block>,
+        job: JobInitMetadata,
         work_manager: &ProtocolWorkManager<WorkManager>,
     ) -> Result<<Self as AsyncProtocol>::AdditionalParams, Error> {
         T::create_next_job(self, job, work_manager).await
     }
 
-    async fn process_block_import_notification(
-        &self,
-        notification: BlockImportNotification<T::Block>,
-        job_manager: &ProtocolWorkManager<WorkManager>,
-    ) -> Result<(), Error> {
-        T::process_block_import_notification(self, notification, job_manager).await
-    }
-
     async fn process_error(&self, error: Error, job_manager: &ProtocolWorkManager<WorkManager>) {
         T::process_error(self, error, job_manager).await;
     }
 
-    fn account_id(&self) -> &AccountId {
+    fn account_id(&self) -> &sr25519::Public {
         T::account_id(self)
     }
 
@@ -206,15 +173,18 @@ where
         T::name(self)
     }
 
-    fn role_filter(&self, role: RoleType) -> bool {
+    fn role_filter(&self, role: roles::RoleType) -> bool {
         T::role_filter(self, role)
     }
 
-    fn phase_filter(&self, job: GadgetJobType) -> bool {
+    fn phase_filter(
+        &self,
+        job: jobs::JobType<AccountId32, jobs::MaxParticipants, jobs::MaxSubmissionLen>,
+    ) -> bool {
         T::phase_filter(self, job)
     }
 
-    fn client(&self) -> JobsClient<T::Block, T::Backend, T::Client> {
+    fn client(&self) -> JobsClient<T::Client> {
         T::get_jobs_client(self)
     }
 
@@ -228,10 +198,11 @@ where
 }
 
 #[async_trait]
-impl<T: FullProtocolConfig> Network for T
-where
-    <T::Client as ProvideRuntimeApi<T::Block>>::Api: JobsApiForGadget<T::Block>,
-{
+impl<T: FullProtocolConfig> Network for T {
+    fn greatest_authority_id(&self) -> Option<Public> {
+        T::internal_network(self).greatest_authority_id()
+    }
+
     async fn next_message(&self) -> Option<<WorkManager as WorkManagerInterface>::ProtocolMessage> {
         let mut message = T::internal_network(self).next_message().await?;
         if let Some(peer_public_key) = message.from_network_id {
@@ -286,26 +257,16 @@ where
 /// Used for constructing an instance of a node. If there is both a keygen and a signing protocol, then,
 /// the length of the vectors are 2. The length of the vector is equal to the numbers of protocols that
 /// the constructed node is going to concurrently execute
-pub struct NodeInput<
-    B: Block,
-    BE: Backend<B>,
-    C: ClientWithApi<B, BE>,
-    N: Network,
-    KBE: KeystoreBackend,
-    D,
-> where
-    <C as ProvideRuntimeApi<B>>::Api: JobsApiForGadget<B>,
-{
-    pub mock_clients: Vec<C>,
-    pub mock_networks: Vec<N>,
-    pub account_id: AccountId,
+pub struct NodeInput<C: ClientWithApi, N: Network, KBE: KeystoreBackend, D> {
+    pub clients: Vec<C>,
+    pub networks: Vec<N>,
+    pub account_id: sr25519::Public,
     pub logger: DebugLogger,
     pub pallet_tx: Arc<dyn PalletSubmitter>,
     pub keystore: ECDSAKeyStore<KBE>,
     pub node_index: usize,
     pub additional_params: D,
     pub prometheus_config: PrometheusConfig,
-    pub _pd: PhantomData<(B, BE)>,
 }
 
 #[derive(Encode, Decode)]
diff --git a/gadget-common/src/gadget/mod.rs b/gadget-common/src/gadget/mod.rs
index b36949214..d63b4d11a 100644
--- a/gadget-common/src/gadget/mod.rs
+++ b/gadget-common/src/gadget/mod.rs
@@ -1,37 +1,32 @@
-use crate::client::{AccountId, ClientWithApi, GadgetJobType, JobsApiForGadget, JobsClient};
+use crate::client::{ClientWithApi, JobsClient};
 use crate::debug_logger::DebugLogger;
 use crate::gadget::message::GadgetProtocolMessage;
 use crate::gadget::work_manager::WorkManager;
 use crate::protocol::{AsyncProtocol, AsyncProtocolRemote};
 use crate::Error;
 use async_trait::async_trait;
-use gadget_core::gadget::substrate::SubstrateGadgetModule;
+use gadget_core::gadget::substrate::{FinalityNotification, SubstrateGadgetModule};
 use gadget_core::job::BuiltExecutableJobWrapper;
 use gadget_core::job_manager::{PollMethod, ProtocolWorkManager, WorkManagerInterface};
 use network::Network;
 use parking_lot::RwLock;
-use sc_client_api::{Backend, BlockImportNotification, FinalityNotification};
-use sp_api::ProvideRuntimeApi;
-use sp_core::{ecdsa, keccak_256};
-use sp_runtime::traits::{Block, Header};
-use sp_runtime::SaturatedConversion;
-use std::marker::PhantomData;
+use sp_core::{ecdsa, keccak_256, sr25519};
 use std::sync::Arc;
 use std::time::Duration;
-use tangle_primitives::jobs::JobId;
-use tangle_primitives::roles::RoleType;
+use tangle_subxt::subxt::utils::AccountId32;
+use tangle_subxt::tangle_runtime::api::runtime_types::tangle_primitives::{jobs, roles};
 
 pub mod message;
 pub mod network;
 pub mod work_manager;
 
 /// Used as a module to place inside the SubstrateGadget
-pub struct Module<B, C, N, M, BE> {
+pub struct Module<C, N, M> {
     protocol: M,
     network: N,
     job_manager: ProtocolWorkManager<WorkManager>,
     clock: Arc<RwLock<Option<u64>>>,
-    _pd: PhantomData<(B, C, BE)>,
+    _client: core::marker::PhantomData<C>,
 }
 
 const DEFAULT_MAX_ACTIVE_TASKS: usize = 4;
@@ -55,16 +50,7 @@ impl Default for WorkManagerConfig {
     }
 }
 
-impl<
-        C: ClientWithApi<B, BE>,
-        B: Block,
-        N: Network,
-        M: GadgetProtocol<B, BE, C>,
-        BE: Backend<B>,
-    > Module<B, C, N, M, BE>
-where
-    <C as ProvideRuntimeApi<B>>::Api: JobsApiForGadget<B>,
-{
+impl<C: ClientWithApi, N: Network, M: GadgetProtocol<C>> Module<C, N, M> {
     pub fn new(network: N, module: M, job_manager: ProtocolWorkManager<WorkManager>) -> Self {
         let clock = job_manager.utility.clock.clone();
         Module {
@@ -72,38 +58,29 @@ where
             job_manager,
             network,
             clock,
-            _pd: Default::default(),
+            _client: Default::default(),
         }
     }
 }
 
-pub struct JobInitMetadata<B: Block> {
-    pub job_type: GadgetJobType,
-    pub role_type: RoleType,
+pub struct JobInitMetadata {
+    pub job_type: jobs::JobType<AccountId32, jobs::MaxParticipants, jobs::MaxSubmissionLen>,
+    pub role_type: roles::RoleType,
     /// This value only exists if this is a stage2 job
-    pub phase1_job: Option<GadgetJobType>,
+    pub phase1_job:
+        Option<jobs::JobType<AccountId32, jobs::MaxParticipants, jobs::MaxSubmissionLen>>,
     pub participants_role_ids: Vec<ecdsa::Public>,
     pub task_id: <WorkManager as WorkManagerInterface>::TaskID,
     pub retry_id: <WorkManager as WorkManagerInterface>::RetryID,
-    pub job_id: JobId,
+    pub job_id: u64,
     pub now: <WorkManager as WorkManagerInterface>::Clock,
-    pub at: B::Hash,
+    pub at: [u8; 32],
 }
 
 #[async_trait]
-impl<
-        C: ClientWithApi<B, BE>,
-        B: Block,
-        N: Network,
-        M: GadgetProtocol<B, BE, C>,
-        BE: Backend<B>,
-    > SubstrateGadgetModule for Module<B, C, N, M, BE>
-where
-    <C as ProvideRuntimeApi<B>>::Api: JobsApiForGadget<B>,
-{
+impl<C: ClientWithApi, N: Network, M: GadgetProtocol<C>> SubstrateGadgetModule for Module<C, N, M> {
     type Error = Error;
     type ProtocolMessage = GadgetProtocolMessage;
-    type Block = B;
     type Client = C;
 
     async fn get_next_protocol_message(&self) -> Option<Self::ProtocolMessage> {
@@ -112,10 +89,9 @@ where
 
     async fn process_finality_notification(
         &self,
-        notification: FinalityNotification<B>,
+        notification: FinalityNotification,
     ) -> Result<(), Self::Error> {
-        let now_header = *notification.header.number();
-        let now: u64 = now_header.saturated_into();
+        let now: u64 = notification.number;
         *self.clock.write() = Some(now);
         self.protocol.logger().info(format!(
             "Processing finality notification at block number {now}",
@@ -124,7 +100,7 @@ where
         let jobs = self
             .protocol
             .client()
-            .query_jobs_by_validator(notification.hash, self.protocol.account_id().clone())
+            .query_jobs_by_validator(notification.hash, *self.protocol.account_id())
             .await?;
 
         self.protocol.logger().trace(format!(
@@ -135,21 +111,43 @@ where
 
         for job in jobs {
             // Job is expired.
-            if job.expiry < now_header {
+            if job.expiry < now {
                 self.protocol.logger().trace(format!(
                     "[{}] The job requested for initialization is expired, skipping submission",
                     self.protocol.name()
                 ));
                 continue;
             }
+            let role_type = match &job.job_type {
+                jobs::JobType::DKGTSSPhaseOne(p) => roles::RoleType::Tss(p.role_type.clone()),
+                jobs::JobType::DKGTSSPhaseTwo(p) => roles::RoleType::Tss(p.role_type.clone()),
+                jobs::JobType::DKGTSSPhaseThree(p) => roles::RoleType::Tss(p.role_type.clone()),
+                jobs::JobType::DKGTSSPhaseFour(p) => roles::RoleType::Tss(p.role_type.clone()),
+                jobs::JobType::ZkSaaSPhaseOne(p) => roles::RoleType::ZkSaaS(p.role_type.clone()),
+                jobs::JobType::ZkSaaSPhaseTwo(p) => roles::RoleType::ZkSaaS(p.role_type.clone()),
+            };
             // Job is not for this role
-            if !self.protocol.role_filter(job.job_type.get_role_type()) {
-                // self.protocol.logger().trace(format!("[{}] The job {} requested for initialization is not for this role {:?}, skipping submission", self.protocol.name(), job.job_id, job.job_type.get_role_type()));
+            if !self.protocol.role_filter(role_type.clone()) {
+                self.protocol.logger().trace(
+                    format!(
+                        "[{}] The job {} requested for initialization is not for this role {:?}, skipping submission",
+                        self.protocol.name(),
+                        job.job_id,
+                        role_type
+                    )
+                );
                 continue;
             }
             // Job is not for this phase
             if !self.protocol.phase_filter(job.job_type.clone()) {
-                // self.protocol.logger().trace(format!("[{}] The job {} requested for initialization is not for this phase {:?}, skipping submission", self.protocol.name(), job.job_id, job.job_type));
+                self.protocol.logger().trace(
+                    format!(
+                        "[{}] The job {} requested for initialization is not for this phase {:?}, skipping submission",
+                        self.protocol.name(),
+                        job.job_id,
+                        job.job_type
+                    )
+                );
                 continue;
             }
 
@@ -167,33 +165,44 @@ where
                 .map(|r| r + 1)
                 .unwrap_or(0);
 
-            let phase1_job = if job.job_type.is_phase_one() {
+            let is_phase_one = matches!(
+                job.job_type,
+                jobs::JobType::DKGTSSPhaseOne(_) | jobs::JobType::ZkSaaSPhaseOne(_)
+            );
+
+            let phase1_job = if is_phase_one {
                 None
             } else {
-                let phase_one_job_id = job
-                    .job_type
-                    .get_phase_one_id()
-                    .expect("Should exist for non phase 1 jobs");
+                let phase_one_job_id = match &job.job_type {
+                    jobs::JobType::DKGTSSPhaseOne(_) => unreachable!(),
+                    jobs::JobType::ZkSaaSPhaseOne(_) => unreachable!(),
+                    jobs::JobType::DKGTSSPhaseTwo(p) => p.phase_one_id,
+                    jobs::JobType::DKGTSSPhaseThree(p) => p.phase_one_id,
+                    jobs::JobType::DKGTSSPhaseFour(p) => p.phase_one_id,
+                    jobs::JobType::ZkSaaSPhaseTwo(p) => p.phase_one_id,
+                };
                 let phase1_job = self
                         .protocol
                         .client()
-                        .query_job_result(notification.hash, job.job_type.get_role_type(), phase_one_job_id)
+                        .query_job_result(notification.hash, role_type.clone(), phase_one_job_id)
                         .await?
                         .ok_or_else(|| Error::ClientError {
                             err: format!("Corresponding phase one job {phase_one_job_id} not found for phase two job {job_id}"),
                         })?;
                 Some(phase1_job.job_type)
             };
+
             let participants = match phase1_job {
-                Some(ref j) => j
-                    .clone()
-                    .get_participants()
-                    .expect("Should exist for phase 1 jobs"),
-                None => job
-                    .job_type
-                    .clone()
-                    .get_participants()
-                    .expect("Should exist for phase 1 jobs"),
+                Some(ref j) => match j {
+                    jobs::JobType::DKGTSSPhaseOne(p) => p.participants.0.clone(),
+                    jobs::JobType::ZkSaaSPhaseOne(p) => p.participants.0.clone(),
+                    _ => unreachable!(),
+                },
+                None => match &job.job_type {
+                    jobs::JobType::DKGTSSPhaseOne(p) => p.participants.0.clone(),
+                    jobs::JobType::ZkSaaSPhaseOne(p) => p.participants.0.clone(),
+                    _ => unreachable!(),
+                },
             };
 
             let participants_role_ids = {
@@ -202,7 +211,7 @@ where
                     let maybe_role_key = self
                         .protocol
                         .client()
-                        .query_restaker_role_key(notification.hash, p.clone())
+                        .query_restaker_role_key(notification.hash, sr25519::Public(p.0))
                         .await?;
                     if let Some(role_key) = maybe_role_key {
                         out.push(role_key);
@@ -215,7 +224,7 @@ where
                 out
             };
             relevant_jobs.push(JobInitMetadata {
-                role_type: job.job_type.get_role_type(),
+                role_type,
                 job_type: job.job_type,
                 phase1_job,
                 participants_role_ids,
@@ -292,15 +301,6 @@ where
         Ok(())
     }
 
-    async fn process_block_import_notification(
-        &self,
-        notification: BlockImportNotification<B>,
-    ) -> Result<(), Self::Error> {
-        self.protocol
-            .process_block_import_notification(notification, &self.job_manager)
-            .await
-    }
-
     async fn process_protocol_message(
         &self,
         message: Self::ProtocolMessage,
@@ -319,31 +319,21 @@ where
 pub type Job = (AsyncProtocolRemote, BuiltExecutableJobWrapper);
 
 #[async_trait]
-pub trait GadgetProtocol<B: Block, BE: Backend<B>, C: ClientWithApi<B, BE>>:
-    AsyncProtocol + Send + Sync
-where
-    <C as ProvideRuntimeApi<B>>::Api: JobsApiForGadget<B>,
-{
+pub trait GadgetProtocol<C: ClientWithApi>: AsyncProtocol + Send + Sync {
     /// Given an input of a valid and relevant job, return the parameters needed to start the async protocol
     /// Note: the parameters returned must be relevant to the `AsyncProtocol` implementation of this protocol
     ///
     /// In case the participant is not selected for some reason, return an [`Error::ParticipantNotSelected`]
     async fn create_next_job(
         &self,
-        job: JobInitMetadata<B>,
+        job: JobInitMetadata,
         work_manager: &ProtocolWorkManager<WorkManager>,
     ) -> Result<<Self as AsyncProtocol>::AdditionalParams, Error>;
 
-    /// Process a block import notification
-    async fn process_block_import_notification(
-        &self,
-        notification: BlockImportNotification<B>,
-        job_manager: &ProtocolWorkManager<WorkManager>,
-    ) -> Result<(), Error>;
     /// Process an error that may arise from the work manager, async protocol, or the executor
     async fn process_error(&self, error: Error, job_manager: &ProtocolWorkManager<WorkManager>);
     /// The account ID of this node. Jobs queried will be filtered by this account ID
-    fn account_id(&self) -> &AccountId;
+    fn account_id(&self) -> &sr25519::Public;
 
     /// The Protocol Name.
     /// Used for logging and debugging purposes
@@ -356,7 +346,7 @@ where
     ///   matches!(role, RoleType::Tss(ThresholdSignatureRoleType::ZengoGG20Secp256k1))
     /// }
     /// ```
-    fn role_filter(&self, role: RoleType) -> bool;
+    fn role_filter(&self, role: roles::RoleType) -> bool;
 
     /// Filter queried jobs by Job type & Phase.
     /// ## Example
@@ -366,8 +356,11 @@ where
     ///   matches!(job, JobType::DKGTSSPhaseOne(_))
     /// }
     /// ```
-    fn phase_filter(&self, job: GadgetJobType) -> bool;
-    fn client(&self) -> JobsClient<B, BE, C>;
+    fn phase_filter(
+        &self,
+        job: jobs::JobType<AccountId32, jobs::MaxParticipants, jobs::MaxSubmissionLen>,
+    ) -> bool;
+    fn client(&self) -> JobsClient<C>;
     fn logger(&self) -> DebugLogger;
     fn get_work_manager_config(&self) -> WorkManagerConfig {
         Default::default()
diff --git a/gadget-common/src/keystore.rs b/gadget-common/src/keystore.rs
index 2c2191324..6719a6540 100644
--- a/gadget-common/src/keystore.rs
+++ b/gadget-common/src/keystore.rs
@@ -10,7 +10,6 @@ use sqlx::sqlite::SqlitePoolOptions;
 use sqlx::{Pool, Row, Sqlite};
 use std::collections::HashMap;
 use std::sync::Arc;
-use tangle_primitives::jobs::JobId;
 
 pub type ECDSAKeyStore<BE> = GenericKeyStore<BE, EcdsaPair>;
 pub type Sr25519KeyStore<BE> = GenericKeyStore<BE, Sr25519Pair>;
@@ -59,7 +58,7 @@ impl<P: Pair, BE: KeystoreBackend> GenericKeyStore<BE, P> {
 
     pub async fn get_job_result<T: DeserializeOwned>(
         &self,
-        job_id: JobId,
+        job_id: u64,
     ) -> Result<Option<T>, crate::Error> {
         let key = keccak_256(&job_id.to_be_bytes());
         self.get(&key).await
@@ -75,7 +74,7 @@ impl<P: Pair, BE: KeystoreBackend> GenericKeyStore<BE, P> {
 
     pub async fn set_job_result<T: Serialize + Send>(
         &self,
-        job_id: JobId,
+        job_id: u64,
         value: T,
     ) -> Result<(), crate::Error> {
         let key = keccak_256(&job_id.to_be_bytes());
diff --git a/gadget-common/src/lib.rs b/gadget-common/src/lib.rs
index 4104bbb24..43c7b4858 100644
--- a/gadget-common/src/lib.rs
+++ b/gadget-common/src/lib.rs
@@ -1,28 +1,24 @@
-use crate::client::{ClientWithApi, JobsApiForGadget};
-use crate::config::{NetworkAndProtocolSetup, ProtocolConfig};
+use crate::client::ClientWithApi;
+use crate::config::ProtocolConfig;
 use crate::gadget::work_manager::WorkManager;
 use crate::gadget::{GadgetProtocol, Module};
 use crate::prelude::PrometheusConfig;
 use gadget::network::Network;
 use gadget_core::gadget::manager::{AbstractGadget, GadgetError, GadgetManager};
-use gadget_core::gadget::substrate::{Client, SubstrateGadget};
+use gadget_core::gadget::substrate::{Client, FinalityNotification, SubstrateGadget};
 pub use gadget_core::job::JobError;
 pub use gadget_core::job::*;
 pub use gadget_core::job_manager::WorkManagerInterface;
 pub use gadget_core::job_manager::{PollMethod, ProtocolWorkManager, WorkManagerError};
 use parking_lot::RwLock;
-pub use sc_client_api::BlockImportNotification;
-pub use sc_client_api::{Backend, FinalityNotification};
-use sp_api::ProvideRuntimeApi;
 pub use sp_core;
 use sp_core::ecdsa;
-pub use sp_runtime::traits::{Block, Header};
-use sp_runtime::SaturatedConversion;
 use std::fmt::{Debug, Display, Formatter};
 use std::sync::Arc;
-pub use subxt_signer;
 use tokio::task::JoinError;
-pub use webb;
+
+pub use subxt_signer;
+pub use tangle_subxt;
 
 #[allow(ambiguous_glob_reexports)]
 pub mod prelude {
@@ -43,8 +39,8 @@ pub mod prelude {
     pub use protocol_macros::protocol;
     pub use std::pin::Pin;
     pub use std::sync::Arc;
-    pub use tangle_primitives::jobs::*;
-    pub use tangle_primitives::roles::{RoleType, ThresholdSignatureRoleType};
+    pub use tangle_subxt::subxt::utils::AccountId32;
+    pub use tangle_subxt::tangle_runtime::api::runtime_types::tangle_primitives::{jobs, roles};
     pub use tokio::sync::mpsc::{UnboundedReceiver, UnboundedSender};
 }
 pub mod channels;
@@ -96,12 +92,7 @@ impl From<JobError> for Error {
     }
 }
 
-pub async fn run_protocol<T: ProtocolConfig>(mut protocol_config: T) -> Result<(), Error>
-where
-    <<T::ProtocolSpecificConfiguration as NetworkAndProtocolSetup>::Client as ProvideRuntimeApi<
-        <T::ProtocolSpecificConfiguration as NetworkAndProtocolSetup>::Block,
-    >>::Api: JobsApiForGadget<<T::ProtocolSpecificConfiguration as NetworkAndProtocolSetup>::Block>,
-{
+pub async fn run_protocol<T: ProtocolConfig>(mut protocol_config: T) -> Result<(), Error> {
     let client = protocol_config.take_client();
     let network = protocol_config.take_network();
     let protocol = protocol_config.take_protocol();
@@ -146,19 +137,11 @@ where
 }
 
 /// Creates a work manager
-pub async fn create_work_manager<
-    B: Block,
-    BE: Backend<B>,
-    C: ClientWithApi<B, BE>,
-    P: GadgetProtocol<B, BE, C>,
->(
-    latest_finality_notification: &FinalityNotification<B>,
+pub async fn create_work_manager<C: ClientWithApi, P: GadgetProtocol<C>>(
+    latest_finality_notification: &FinalityNotification,
     protocol: &P,
-) -> Result<ProtocolWorkManager<WorkManager>, Error>
-where
-    <C as ProvideRuntimeApi<B>>::Api: JobsApiForGadget<B>,
-{
-    let now: u64 = (*latest_finality_notification.header.number()).saturated_into();
+) -> Result<ProtocolWorkManager<WorkManager>, Error> {
+    let now: u64 = latest_finality_notification.number;
 
     let work_manager_config = protocol.get_work_manager_config();
 
@@ -184,9 +167,9 @@ where
     ))
 }
 
-async fn get_latest_finality_notification_from_client<C: Client<B>, B: Block>(
+async fn get_latest_finality_notification_from_client<C: Client>(
     client: &C,
-) -> Result<FinalityNotification<B>, Error> {
+) -> Result<FinalityNotification, Error> {
     client
         .get_latest_finality_notification()
         .await
@@ -202,14 +185,13 @@ async fn get_latest_finality_notification_from_client<C: Client<B>, B: Block>(
 macro_rules! generate_setup_and_run_command {
     ($( $config:ident ),*) => {
         /// Sets up a future that runs all the protocols concurrently
-        pub fn setup_node<B: Block, BE: Backend<B> + 'static, C: ClientWithApi<B, BE>, N: Network, KBE: gadget_common::keystore::KeystoreBackend, D: Send + Clone + 'static>(node_input: NodeInput<B, BE, C, N, KBE, D>) -> impl SendFuture<'static, ()>
-                where
-            <C as ProvideRuntimeApi<B>>::Api: JobsApiForGadget<B>,{
+        pub fn setup_node<C: ClientWithApi + 'static, N: Network, KBE: $crate::keystore::KeystoreBackend, D: Send + Clone + 'static>(node_input: NodeInput<C, N, KBE, D>) -> impl SendFuture<'static, ()>
+        {
             async move {
                 if let Err(err) = run(
-                    node_input.mock_clients,
+                    node_input.clients,
                     node_input.pallet_tx,
-                    node_input.mock_networks,
+                    node_input.networks,
                     node_input.logger.clone(),
                     node_input.account_id,
                     node_input.keystore,
@@ -224,24 +206,22 @@ macro_rules! generate_setup_and_run_command {
             }
         }
 
-        pub async fn run<B: Block, BE: Backend<B> + 'static, C: ClientWithApi<B, BE>, N: Network, KBE: gadget_common::keystore::KeystoreBackend>(
+        pub async fn run<C: ClientWithApi + 'static, N: Network, KBE: $crate::keystore::KeystoreBackend>(
             mut client: Vec<C>,
             pallet_tx: Arc<dyn PalletSubmitter>,
             mut network: Vec<N>,
             logger: DebugLogger,
-            account_id: AccountId,
+            account_id: sp_core::sr25519::Public,
             key_store: ECDSAKeyStore<KBE>,
             prometheus_config: $crate::prometheus::PrometheusConfig,
         ) -> Result<(), Error>
-        where
-            <C as ProvideRuntimeApi<B>>::Api: JobsApiForGadget<B>,
         {
             use futures::TryStreamExt;
             let futures = futures::stream::FuturesUnordered::new();
 
             $(
                 let config = crate::$config::new(client.pop().expect("Not enough clients"), pallet_tx.clone(), network.pop().expect("Not enough networks"), logger.clone(), account_id.clone(), key_store.clone(), prometheus_config.clone()).await?;
-                futures.push(Box::pin(config.execute()) as std::pin::Pin<Box<dyn SendFuture<'static, Result<(), gadget_common::Error>>>>);
+                futures.push(Box::pin(config.execute()) as std::pin::Pin<Box<dyn SendFuture<'static, Result<(), $crate::Error>>>>);
             )*
 
             futures.try_collect::<Vec<_>>().await.map(|_| ())
@@ -254,41 +234,30 @@ macro_rules! generate_protocol {
     ($name:expr, $struct_name:ident, $async_proto_params:ty, $proto_gen_path:expr, $create_job_path:expr, $phase_filter:pat, $( $role_filter:pat ),*) => {
         #[protocol]
         pub struct $struct_name<
-            B: Block,
-            BE: Backend<B> + 'static,
-            C: ClientWithApi<B, BE>,
+            C: ClientWithApi + 'static,
             N: Network,
             KBE: KeystoreBackend,
-        > where
-            <C as ProvideRuntimeApi<B>>::Api: JobsApiForGadget<B>,
-        {
+        > {
             pallet_tx: Arc<dyn PalletSubmitter>,
             logger: DebugLogger,
             client: C,
-            // This field should NEVER be used directly. Use Self instead as the network
+            /// This field should NEVER be used directly. Use Self instead as the network
             network_inner: N,
-            account_id: AccountId,
+            account_id: sp_core::sr25519::Public,
             key_store: ECDSAKeyStore<KBE>,
-            jobs_client: Arc<Mutex<Option<JobsClient<B, BE, C>>>>,
+            jobs_client: Arc<Mutex<Option<JobsClient<C>>>>,
             prometheus_config: $crate::prometheus::PrometheusConfig,
-            _pd: std::marker::PhantomData<(B, BE)>,
         }
 
         #[async_trait]
         impl<
-                B: Block,
-                BE: Backend<B> + 'static,
-                C: ClientWithApi<B, BE>,
+                C: ClientWithApi + 'static,
                 N: Network,
                 KBE: KeystoreBackend,
-            > FullProtocolConfig for $struct_name<B, BE, C, N, KBE>
-        where
-            <C as ProvideRuntimeApi<B>>::Api: JobsApiForGadget<B>,
+            > FullProtocolConfig for $struct_name<C, N, KBE>
         {
             type AsyncProtocolParameters = $async_proto_params;
             type Client = C;
-            type Block = B;
-            type Backend = BE;
             type Network = N;
             type AdditionalNodeParameters = ();
             type KeystoreBackend = KBE;
@@ -298,7 +267,7 @@ macro_rules! generate_protocol {
                 pallet_tx: Arc<dyn PalletSubmitter>,
                 network_inner: Self::Network,
                 logger: DebugLogger,
-                account_id: AccountId,
+                account_id: sp_core::sr25519::Public,
                 key_store: ECDSAKeyStore<Self::KeystoreBackend>,
                 prometheus_config: $crate::prometheus::PrometheusConfig,
             ) -> Result<Self, Error> {
@@ -314,7 +283,6 @@ macro_rules! generate_protocol {
                     key_store,
                     prometheus_config,
                     jobs_client: Arc::new(parking_lot::Mutex::new(None)),
-                    _pd: std::marker::PhantomData,
                 })
             }
 
@@ -345,13 +313,13 @@ macro_rules! generate_protocol {
 
             async fn create_next_job(
                 &self,
-                job: JobInitMetadata<Self::Block>,
+                job: JobInitMetadata,
                 work_manager: &ProtocolWorkManager<WorkManager>,
             ) -> Result<Self::AsyncProtocolParameters, Error> {
                 $create_job_path(self, job, work_manager).await
             }
 
-            fn account_id(&self) -> &AccountId {
+            fn account_id(&self) -> &sp_core::sr25519::Public {
                 &self.account_id
             }
 
@@ -359,7 +327,7 @@ macro_rules! generate_protocol {
                 $name.to_string()
             }
 
-            fn role_filter(&self, role: RoleType) -> bool {
+            fn role_filter(&self, role: roles::RoleType) -> bool {
                 $(
                     if matches!(role, $role_filter) {
                         return true;
@@ -369,11 +337,14 @@ macro_rules! generate_protocol {
                 false
             }
 
-            fn phase_filter(&self, job: GadgetJobType) -> bool {
+            fn phase_filter(
+                &self,
+                job: jobs::JobType<AccountId32, jobs::MaxParticipants, jobs::MaxSubmissionLen>,
+            ) -> bool {
                 matches!(job, $phase_filter)
             }
 
-            fn jobs_client(&self) -> &SharedOptional<JobsClient<Self::Block, Self::Backend, Self::Client>> {
+            fn jobs_client(&self) -> &SharedOptional<JobsClient<Self::Client>> {
                 &self.jobs_client
             }
 
@@ -385,7 +356,6 @@ macro_rules! generate_protocol {
                 self.logger.clone()
             }
 
-
             fn key_store(&self) -> &ECDSAKeyStore<Self::KeystoreBackend> {
                 &self.key_store
             }
diff --git a/gadget-common/src/utils.rs b/gadget-common/src/utils.rs
index acf9feb1a..212984b7f 100644
--- a/gadget-common/src/utils.rs
+++ b/gadget-common/src/utils.rs
@@ -1,8 +1,11 @@
 use futures::Stream;
+use sp_core::ecdsa;
 use std::sync::atomic::AtomicBool;
 use std::sync::Arc;
 use tokio::sync::mpsc::UnboundedReceiver;
 
+pub const ECDSA_SIGNATURE_LENGTH: usize = 65;
+
 /// A Channel Receiver that can be cloned.
 ///
 /// On the second clone, the original channel will stop receiving new messages
@@ -52,3 +55,84 @@ impl<T> Stream for CloneableUnboundedReceiver<T> {
         rx.poll_recv(cx)
     }
 }
+
+/// Recovers the ECDSA public key from a given message and signature.
+///
+/// # Arguments
+///
+/// * `data` - The message for which the signature is being verified.
+/// * `signature` - The ECDSA signature to be verified.
+///
+/// # Returns
+///
+/// Returns a `Result` containing the recovered ECDSA public key as a `Vec<u8>` or an
+/// `EcdsaVerifyError` if verification fails.
+pub fn recover_ecdsa_pub_key(
+    data: &[u8],
+    signature: &[u8],
+) -> Result<Vec<u8>, sp_io::EcdsaVerifyError> {
+    if signature.len() == ECDSA_SIGNATURE_LENGTH {
+        let mut sig = [0u8; ECDSA_SIGNATURE_LENGTH];
+        sig[..ECDSA_SIGNATURE_LENGTH].copy_from_slice(signature);
+
+        let hash = sp_core::keccak_256(data);
+
+        let pub_key = sp_io::crypto::secp256k1_ecdsa_recover(&sig, &hash)?;
+        return Ok(pub_key.to_vec());
+    }
+    Err(sp_io::EcdsaVerifyError::BadSignature)
+}
+
+/// Verifies the signer of a given message using a set of ECDSA public keys.
+///
+/// Given a vector of ECDSA public keys (`maybe_signers`), a message (`msg`), and an ECDSA
+/// signature (`signature`), this function checks if any of the public keys in the set can be a
+/// valid signer for the provided message and signature.
+///
+/// # Arguments
+///
+/// * `maybe_signers` - A vector of ECDSA public keys that may represent the potential signers.
+/// * `msg` - The message for which the signature is being verified.
+/// * `signature` - The ECDSA signature to be verified.
+///
+/// # Returns
+///
+/// Returns a tuple containing:
+/// * An optional ECDSA public key (`Option<ecdsa::Public>`) representing the verified signer. It is
+///   `None` if no valid signer is found.
+/// * A boolean value (`bool`) indicating whether the verification was successful (`true`) or not
+///   (`false`).
+pub fn verify_signer_from_set_ecdsa(
+    maybe_signers: Vec<ecdsa::Public>,
+    msg: &[u8],
+    signature: &[u8],
+) -> (Option<ecdsa::Public>, bool) {
+    let mut signer = None;
+    let recovered_result = recover_ecdsa_pub_key(msg, signature);
+    let res = if let Ok(data) = recovered_result {
+        let recovered = &data[..32];
+        maybe_signers.iter().any(|x| {
+            if x.0[1..].to_vec() == recovered.to_vec() {
+                signer = Some(*x);
+                true
+            } else {
+                false
+            }
+        })
+    } else {
+        false
+    };
+
+    (signer, res)
+}
+
+/// Utility function to create slice of fixed size
+pub fn to_slice_33(val: &[u8]) -> Option<[u8; 33]> {
+    if val.len() == 33 {
+        let mut key = [0u8; 33];
+        key[..33].copy_from_slice(val);
+
+        return Some(key);
+    }
+    None
+}
diff --git a/gadget-core/Cargo.toml b/gadget-core/Cargo.toml
index 5e0479ba0..4093472aa 100644
--- a/gadget-core/Cargo.toml
+++ b/gadget-core/Cargo.toml
@@ -6,10 +6,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0"
 edition = "2021"
 
 [features]
-substrate = [
-    "sp-runtime",
-    "sc-client-api",
-]
+substrate = []
 
 [dependencies]
 parking_lot = { workspace = true }
@@ -20,8 +17,5 @@ async-trait = { workspace = true }
 auto_impl = { workspace = true }
 futures = { workspace = true }
 
-sp-runtime = { optional = true, workspace = true }
-sc-client-api = { optional = true, workspace = true }
-
 [dev-dependencies]
-tokio = { workspace = true, features = ["macros"]}
\ No newline at end of file
+tokio = { workspace = true, features = ["macros"] }
diff --git a/gadget-core/src/gadget/manager.rs b/gadget-core/src/gadget/manager.rs
index ae682a5de..841dd3c78 100644
--- a/gadget-core/src/gadget/manager.rs
+++ b/gadget-core/src/gadget/manager.rs
@@ -11,7 +11,6 @@ pub struct GadgetManager<'a> {
 #[derive(Copy, Clone, Debug, Eq, PartialEq)]
 pub enum GadgetError {
     FinalityNotificationStreamEnded,
-    BlockImportNotificationStreamEnded,
     ProtocolMessageStreamEnded,
 }
 
@@ -26,22 +25,16 @@ impl std::error::Error for GadgetError {}
 #[async_trait]
 pub trait AbstractGadget: Send + Sync {
     type FinalityNotification: Send;
-    type BlockImportNotification: Send;
     type ProtocolMessage: Send;
     type Error: Error + Send;
 
     async fn get_next_finality_notification(&self) -> Option<Self::FinalityNotification>;
-    async fn get_next_block_import_notification(&self) -> Option<Self::BlockImportNotification>;
     async fn get_next_protocol_message(&self) -> Option<Self::ProtocolMessage>;
 
     async fn process_finality_notification(
         &self,
         notification: Self::FinalityNotification,
     ) -> Result<(), Self::Error>;
-    async fn process_block_import_notification(
-        &self,
-        notification: Self::BlockImportNotification,
-    ) -> Result<(), Self::Error>;
     async fn process_protocol_message(
         &self,
         message: Self::ProtocolMessage,
@@ -67,20 +60,6 @@ impl<'a> GadgetManager<'a> {
                 }
             };
 
-            let block_import_notification_task = async move {
-                loop {
-                    if let Some(notification) = gadget.get_next_block_import_notification().await {
-                        if let Err(err) =
-                            gadget.process_block_import_notification(notification).await
-                        {
-                            gadget.process_error(err).await;
-                        }
-                    } else {
-                        return Err(GadgetError::BlockImportNotificationStreamEnded);
-                    }
-                }
-            };
-
             let protocol_message_task = async move {
                 loop {
                     if let Some(message) = gadget.get_next_protocol_message().await {
@@ -95,8 +74,7 @@ impl<'a> GadgetManager<'a> {
 
             tokio::select! {
                 res0 = finality_notification_task => res0,
-                res1 = block_import_notification_task => res1,
-                res2 = protocol_message_task => res2
+                res1 = protocol_message_task => res1
             }
         };
 
diff --git a/gadget-core/src/gadget/substrate/mod.rs b/gadget-core/src/gadget/substrate/mod.rs
index 3787e29ab..7aa6e187e 100644
--- a/gadget-core/src/gadget/substrate/mod.rs
+++ b/gadget-core/src/gadget/substrate/mod.rs
@@ -1,8 +1,6 @@
 use crate::gadget::manager::AbstractGadget;
 use async_trait::async_trait;
 use auto_impl::auto_impl;
-use sc_client_api::{BlockImportNotification, FinalityNotification};
-use sp_runtime::traits::Block;
 use std::error::Error;
 use std::fmt::{Debug, Display, Formatter};
 use std::sync::Arc;
@@ -12,6 +10,14 @@ pub struct SubstrateGadget<Module: SubstrateGadgetModule> {
     client: Arc<Module::Client>,
 }
 
+#[derive(Debug, Clone, Eq, PartialEq)]
+pub struct FinalityNotification {
+    /// Finalized block number.
+    pub number: u64,
+    /// Finalized block header hash.
+    pub hash: [u8; 32],
+}
+
 #[derive(Copy, Clone, Debug, Eq, PartialEq)]
 pub struct SubstrateGadgetError {}
 
@@ -20,17 +26,12 @@ pub struct SubstrateGadgetError {}
 pub trait SubstrateGadgetModule: Send + Sync {
     type Error: Error + Send;
     type ProtocolMessage: Send;
-    type Block: Block;
-    type Client: Client<Self::Block>;
+    type Client: Client;
 
     async fn get_next_protocol_message(&self) -> Option<Self::ProtocolMessage>;
     async fn process_finality_notification(
         &self,
-        notification: FinalityNotification<Self::Block>,
-    ) -> Result<(), Self::Error>;
-    async fn process_block_import_notification(
-        &self,
-        notification: BlockImportNotification<Self::Block>,
+        notification: FinalityNotification,
     ) -> Result<(), Self::Error>;
     async fn process_protocol_message(
         &self,
@@ -49,12 +50,9 @@ impl Error for SubstrateGadgetError {}
 
 #[async_trait]
 #[auto_impl(Arc)]
-pub trait Client<B: Block>: Send + Sync {
-    async fn get_next_finality_notification(&self) -> Option<FinalityNotification<B>>;
-    async fn get_latest_finality_notification(&self) -> Option<FinalityNotification<B>>;
-    async fn get_next_block_import_notification(&self) -> Option<BlockImportNotification<B>> {
-        futures::future::pending().await
-    }
+pub trait Client: Clone + Send + Sync {
+    async fn get_next_finality_notification(&self) -> Option<FinalityNotification>;
+    async fn get_latest_finality_notification(&self) -> Option<FinalityNotification>;
 }
 
 impl<Module> SubstrateGadget<Module>
@@ -78,8 +76,7 @@ impl<Module> AbstractGadget for SubstrateGadget<Module>
 where
     Module: SubstrateGadgetModule,
 {
-    type FinalityNotification = FinalityNotification<Module::Block>;
-    type BlockImportNotification = BlockImportNotification<Module::Block>;
+    type FinalityNotification = FinalityNotification;
     type ProtocolMessage = Module::ProtocolMessage;
     type Error = Module::Error;
 
@@ -87,10 +84,6 @@ where
         self.client.get_next_finality_notification().await
     }
 
-    async fn get_next_block_import_notification(&self) -> Option<Self::BlockImportNotification> {
-        self.client.get_next_block_import_notification().await
-    }
-
     async fn get_next_protocol_message(&self) -> Option<Self::ProtocolMessage> {
         self.module.get_next_protocol_message().await
     }
@@ -104,15 +97,6 @@ where
             .await
     }
 
-    async fn process_block_import_notification(
-        &self,
-        notification: Self::BlockImportNotification,
-    ) -> Result<(), Self::Error> {
-        self.module
-            .process_block_import_notification(notification)
-            .await
-    }
-
     async fn process_protocol_message(
         &self,
         message: Self::ProtocolMessage,
diff --git a/protocol-macros/src/lib.rs b/protocol-macros/src/lib.rs
index d96bdac7a..9ce9bc311 100644
--- a/protocol-macros/src/lib.rs
+++ b/protocol-macros/src/lib.rs
@@ -103,7 +103,7 @@ pub fn protocol(_args: TokenStream, input: TokenStream) -> TokenStream {
     let generated = quote! {
         #input_struct
 
-        pub struct #new_struct<C: gadget_common::config::ClientWithApi<B, BE>, B: gadget_common::config::Block, BE: gadget_common::config::Backend<B> + 'static, #generics_token_stream_unique_with_bounds>
+        pub struct #new_struct<C: gadget_common::config::ClientWithApi + 'static, #generics_token_stream_unique_with_bounds>
             #where_bounds {
             pub network: Option<<#struct_ident<#generics_token_stream> as gadget_common::config::NetworkAndProtocolSetup>::Network>,
             pub protocol: Option<<#struct_ident<#generics_token_stream> as gadget_common::config::NetworkAndProtocolSetup>::Protocol>,
@@ -112,10 +112,9 @@ pub fn protocol(_args: TokenStream, input: TokenStream) -> TokenStream {
             pub pallet_tx: Arc<dyn gadget_common::client::PalletSubmitter>,
             pub logger: gadget_common::config::DebugLogger,
             pub prometheus_config: gadget_common::prometheus::PrometheusConfig,
-            _pd: std::marker::PhantomData<(B, BE)>,
         }
 
-        impl<C: gadget_common::config::ClientWithApi<B, BE>, B: gadget_common::config::Block, BE: gadget_common::config::Backend<B> + 'static, #generics_token_stream_unique_with_bounds> gadget_common::config::ProtocolConfig for #new_struct <C, B, BE, #generics_token_stream_unique>
+        impl<C: gadget_common::config::ClientWithApi + 'static, #generics_token_stream_unique_with_bounds> gadget_common::config::ProtocolConfig for #new_struct <C, #generics_token_stream_unique>
             #where_bounds
         {
             type Network = <Self::ProtocolSpecificConfiguration as gadget_common::config::NetworkAndProtocolSetup>::Network;
@@ -131,7 +130,6 @@ pub fn protocol(_args: TokenStream, input: TokenStream) -> TokenStream {
                     pallet_tx,
                     logger,
                     prometheus_config,
-                    _pd: std::marker::PhantomData,
                 }
             }
 
@@ -156,10 +154,10 @@ pub fn protocol(_args: TokenStream, input: TokenStream) -> TokenStream {
             }
         }
 
-        impl<C: gadget_common::config::ClientWithApi<B, BE>, B: gadget_common::config::Block, BE: gadget_common::config::Backend<B> + 'static, #generics_token_stream_unique_with_bounds> #struct_ident <#generics_token_stream>
+        impl<C: gadget_common::config::ClientWithApi + 'static, #generics_token_stream_unique_with_bounds> #struct_ident <#generics_token_stream>
             #where_bounds
         {
-            pub fn setup(self) -> #new_struct <C, B, BE, #generics_token_stream_unique> {
+            pub fn setup(self) -> #new_struct <C, #generics_token_stream_unique> {
                 let pallet_tx = <Self as gadget_common::config::NetworkAndProtocolSetup>::pallet_tx(&self);
                 let logger = <Self as gadget_common::config::NetworkAndProtocolSetup>::logger(&self);
                 let prometheus_config = self.prometheus_config.clone();
@@ -172,7 +170,6 @@ pub fn protocol(_args: TokenStream, input: TokenStream) -> TokenStream {
                     pallet_tx,
                     logger,
                     prometheus_config,
-                    _pd: std::marker::PhantomData,
                 }
             }
 
diff --git a/protocols/bls/Cargo.toml b/protocols/bls/Cargo.toml
index 11deed1ce..1ee84504f 100644
--- a/protocols/bls/Cargo.toml
+++ b/protocols/bls/Cargo.toml
@@ -12,7 +12,6 @@ async-trait = { workspace = true }
 futures = { workspace = true }
 tokio = { workspace = true }
 protocol-macros = { workspace = true }
-tangle-primitives = { workspace = true }
 gennaro-dkg = { workspace = true }
 serde = { workspace = true, features = ["derive"] }
 bincode2 = { workspace = true }
@@ -23,4 +22,9 @@ log = { workspace = true }
 bls12_381_plus = { workspace = true }
 snowbridge-milagro-bls = { workspace = true }
 parking_lot = { workspace = true }
+sp-core = { workspace = true }
+
+
+[dev-dependencies]
 test-utils = { workspace = true }
+tangle-primitives = { workspace = true }
diff --git a/protocols/bls/src/lib.rs b/protocols/bls/src/lib.rs
index 02d98060c..6a51b9662 100644
--- a/protocols/bls/src/lib.rs
+++ b/protocols/bls/src/lib.rs
@@ -14,8 +14,8 @@ generate_protocol!(
     BlsKeygenAdditionalParams,
     protocol::keygen::generate_protocol_from,
     protocol::keygen::create_next_job,
-    GadgetJobType::DKGTSSPhaseOne(_),
-    RoleType::Tss(ThresholdSignatureRoleType::GennaroDKGBls381)
+    jobs::JobType::DKGTSSPhaseOne(_),
+    roles::RoleType::Tss(roles::tss::ThresholdSignatureRoleType::GennaroDKGBls381)
 );
 generate_protocol!(
     "BLS-Signing-Protocol",
@@ -23,10 +23,12 @@ generate_protocol!(
     BlsSigningAdditionalParams,
     protocol::signing::generate_protocol_from,
     protocol::signing::create_next_job,
-    GadgetJobType::DKGTSSPhaseTwo(_),
-    RoleType::Tss(ThresholdSignatureRoleType::GennaroDKGBls381)
+    jobs::JobType::DKGTSSPhaseTwo(_),
+    roles::RoleType::Tss(roles::tss::ThresholdSignatureRoleType::GennaroDKGBls381)
 );
 generate_setup_and_run_command!(BlsKeygenProtocol, BlsSigningProtocol);
+
+#[cfg(test)]
 test_utils::generate_signing_and_keygen_tss_tests!(
     2,
     3,
diff --git a/protocols/bls/src/protocol/keygen.rs b/protocols/bls/src/protocol/keygen.rs
index 35f033e76..e47e80ffc 100644
--- a/protocols/bls/src/protocol/keygen.rs
+++ b/protocols/bls/src/protocol/keygen.rs
@@ -3,6 +3,7 @@ use crate::protocol::state_machine::BlsStateMachine;
 use gadget_common::gadget::message::UserID;
 use gadget_common::prelude::*;
 use gadget_common::sp_core::{ecdsa, keccak_256, ByteArray, Pair};
+use gadget_common::tangle_subxt::tangle_runtime::api::runtime_types::bounded_collections::bounded_vec::BoundedVec;
 use itertools::Itertools;
 use round_based::Msg;
 use std::collections::{BTreeMap, HashMap};
@@ -12,25 +13,16 @@ pub struct BlsKeygenAdditionalParams {
     pub i: u16,
     pub t: u16,
     pub n: u16,
-    pub role_type: RoleType,
-    pub job_id: JobId,
+    pub role_type: roles::RoleType,
+    pub job_id: u64,
     pub user_id_to_account_id_mapping: Arc<HashMap<UserID, ecdsa::Public>>,
 }
 
-pub async fn create_next_job<
-    B: Block,
-    BE: Backend<B>,
-    C: ClientWithApi<B, BE>,
-    N: Network,
-    KBE: KeystoreBackend,
->(
-    config: &crate::BlsKeygenProtocol<B, BE, C, N, KBE>,
-    job: JobInitMetadata<B>,
+pub async fn create_next_job<C: ClientWithApi, N: Network, KBE: KeystoreBackend>(
+    config: &crate::BlsKeygenProtocol<C, N, KBE>,
+    job: JobInitMetadata,
     _work_manager: &ProtocolWorkManager<WorkManager>,
-) -> Result<BlsKeygenAdditionalParams, Error>
-where
-    <C as ProvideRuntimeApi<B>>::Api: JobsApiForGadget<B>,
-{
+) -> Result<BlsKeygenAdditionalParams, Error> {
     let job_id = job.job_id;
     let p1_job = job.job_type;
     let threshold = p1_job.clone().get_threshold().expect("Should exist") as u16;
@@ -48,7 +40,7 @@ where
     let additional_params = BlsKeygenAdditionalParams {
         i: (participants
             .iter()
-            .position(|p| p == &config.account_id)
+            .position(|p| p.0 == config.account_id.0)
             .expect("Should exist")
             + 1) as u16,
         t: threshold,
@@ -61,24 +53,15 @@ where
     Ok(additional_params)
 }
 
-pub async fn generate_protocol_from<
-    B: Block,
-    BE: Backend<B>,
-    C: ClientWithApi<B, BE>,
-    N: Network,
-    KBE: KeystoreBackend,
->(
-    config: &crate::BlsKeygenProtocol<B, BE, C, N, KBE>,
+pub async fn generate_protocol_from<C: ClientWithApi, N: Network, KBE: KeystoreBackend>(
+    config: &crate::BlsKeygenProtocol<C, N, KBE>,
     associated_block_id: <WorkManager as WorkManagerInterface>::Clock,
     associated_retry_id: <WorkManager as WorkManagerInterface>::RetryID,
     associated_session_id: <WorkManager as WorkManagerInterface>::SessionID,
     associated_task_id: <WorkManager as WorkManagerInterface>::TaskID,
     protocol_message_rx: UnboundedReceiver<GadgetProtocolMessage>,
     additional_params: BlsKeygenAdditionalParams,
-) -> Result<BuiltExecutableJobWrapper, JobError>
-where
-    <C as ProvideRuntimeApi<B>>::Api: JobsApiForGadget<B>,
-{
+) -> Result<BuiltExecutableJobWrapper, JobError> {
     let network = config.clone();
     let result = Arc::new(tokio::sync::Mutex::new(None));
     let result_clone = result.clone();
@@ -191,7 +174,16 @@ pub(crate) async fn handle_public_key_broadcast<KBE: KeystoreBackend>(
     tx: &UnboundedSender<Msg<RoundPayload>>,
     rx: &mut UnboundedReceiver<Msg<RoundPayload>>,
     user_id_to_account_id_mapping: &Arc<HashMap<UserID, ecdsa::Public>>,
-) -> Result<GadgetJobResult, JobError> {
+) -> Result<
+    jobs::JobResult<
+        jobs::MaxParticipants,
+        jobs::MaxKeyLen,
+        jobs::MaxSignatureLen,
+        jobs::MaxDataLen,
+        jobs::MaxProofLen,
+    >,
+    JobError,
+> {
     let mut received_pk_shares = BTreeMap::new();
     let mut received_signatures = BTreeMap::new();
     received_pk_shares.insert(i, public_key_share.clone());
@@ -290,26 +282,25 @@ pub(crate) async fn handle_public_key_broadcast<KBE: KeystoreBackend>(
     let participants = user_id_to_account_id_mapping
         .iter()
         .sorted_by_key(|x| x.0)
-        .map(|r| r.1.to_raw_vec().try_into().unwrap())
-        .collect::<Vec<_>>()
-        .try_into()
-        .unwrap();
+        .map(|r| BoundedVec(r.1.to_raw_vec()))
+        .collect::<Vec<_>>();
 
     let signatures = received_signatures
         .into_iter()
         .sorted_by_key(|x| x.0)
-        .map(|r| r.1.try_into().unwrap())
-        .collect::<Vec<_>>()
-        .try_into()
-        .unwrap();
+        .map(|r| BoundedVec(r.1))
+        .collect::<Vec<_>>();
 
     let key = uncompressed_public_key[1..].to_vec();
 
-    Ok(JobResult::DKGPhaseOne(DKGTSSKeySubmissionResult {
-        signature_scheme: DigitalSignatureScheme::Bls381,
-        key: key.try_into().unwrap(),
-        participants,
-        signatures,
-        threshold: t as u8,
-    }))
+    Ok(jobs::JobResult::DKGPhaseOne(
+        jobs::tss::DKGTSSKeySubmissionResult {
+            signature_scheme: jobs::tss::DigitalSignatureScheme::Bls381,
+            key: BoundedVec(key),
+            participants: BoundedVec(participants),
+            signatures: BoundedVec(signatures),
+            threshold: t as u8,
+            __subxt_unused_type_params: Default::default(),
+        },
+    ))
 }
diff --git a/protocols/bls/src/protocol/signing.rs b/protocols/bls/src/protocol/signing.rs
index d1782d93a..2aa6de68a 100644
--- a/protocols/bls/src/protocol/signing.rs
+++ b/protocols/bls/src/protocol/signing.rs
@@ -1,14 +1,16 @@
 use crate::protocol::state_machine::Group;
-use gadget_common::client::{ClientWithApi, JobsApiForGadget};
-use gadget_common::config::{Network, ProvideRuntimeApi};
+use gadget_common::client::ClientWithApi;
+use gadget_common::config::Network;
 use gadget_common::full_protocol::FullProtocolConfig;
 use gadget_common::gadget::message::{GadgetProtocolMessage, UserID};
 use gadget_common::gadget::work_manager::WorkManager;
 use gadget_common::gadget::JobInitMetadata;
 use gadget_common::keystore::KeystoreBackend;
+use gadget_common::prelude::*;
 use gadget_common::sp_core::{ecdsa, keccak_256, Pair};
+use gadget_common::tangle_subxt::tangle_runtime::api::runtime_types::bounded_collections::bounded_vec::BoundedVec;
 use gadget_common::{
-    Backend, Block, BuiltExecutableJobWrapper, Error, JobBuilder, JobError, ProtocolWorkManager,
+    BuiltExecutableJobWrapper, Error, JobBuilder, JobError, ProtocolWorkManager,
     WorkManagerInterface,
 };
 use gennaro_dkg::{Participant, SecretParticipantImpl};
@@ -16,42 +18,29 @@ use itertools::Itertools;
 use round_based::Msg;
 use std::collections::{BTreeMap, HashMap};
 use std::sync::Arc;
-use tangle_primitives::jobs::{
-    DKGTSSSignatureResult, DigitalSignatureScheme, JobId, JobResult, JobType,
-};
-use tangle_primitives::roles::RoleType;
 
 #[derive(Clone)]
 pub struct BlsSigningAdditionalParams {
     i: u16,
     t: u16,
-    role_type: RoleType,
-    job_id: JobId,
+    role_type: roles::RoleType,
+    job_id: u64,
     key_bundle: Participant<SecretParticipantImpl<Group>, Group>,
     user_id_to_account_id_mapping: Arc<HashMap<UserID, ecdsa::Public>>,
     input_data_to_sign: Vec<u8>,
 }
 
-pub async fn create_next_job<
-    B: Block,
-    BE: Backend<B> + 'static,
-    C: ClientWithApi<B, BE>,
-    N: Network,
-    KBE: KeystoreBackend,
->(
-    config: &crate::BlsSigningProtocol<B, BE, C, N, KBE>,
-    job: JobInitMetadata<B>,
+pub async fn create_next_job<C: ClientWithApi, N: Network, KBE: KeystoreBackend>(
+    config: &crate::BlsSigningProtocol<C, N, KBE>,
+    job: JobInitMetadata,
     _work_manager: &ProtocolWorkManager<WorkManager>,
-) -> Result<BlsSigningAdditionalParams, Error>
-where
-    <C as ProvideRuntimeApi<B>>::Api: JobsApiForGadget<B>,
-{
+) -> Result<BlsSigningAdditionalParams, Error> {
     let job_id = job.job_id;
     let p1_job = job.phase1_job.expect("Should exist");
     let threshold = p1_job.clone().get_threshold().expect("Should exist") as u16;
     let role_type = p1_job.get_role_type();
     let participants = p1_job.get_participants().expect("Should exist");
-    let JobType::DKGTSSPhaseTwo(p2_job) = job.job_type else {
+    let jobs::JobType::DKGTSSPhaseTwo(p2_job) = job.job_type else {
         panic!("Should be valid type")
     };
     let input_data_to_sign = p2_job.submission;
@@ -76,14 +65,14 @@ where
         let additional_params = BlsSigningAdditionalParams {
             i: participants
                 .iter()
-                .position(|p| p == &config.account_id)
+                .position(|p| p.0 == config.account_id.0)
                 .expect("Should exist") as u16,
             t: threshold,
             role_type,
             job_id,
             user_id_to_account_id_mapping,
             key_bundle,
-            input_data_to_sign: input_data_to_sign.to_vec(),
+            input_data_to_sign: input_data_to_sign.0,
         };
 
         Ok(additional_params)
@@ -94,30 +83,21 @@ where
     }
 }
 
-pub async fn generate_protocol_from<
-    B: Block,
-    BE: Backend<B> + 'static,
-    C: ClientWithApi<B, BE>,
-    N: Network,
-    KBE: KeystoreBackend,
->(
-    config: &crate::BlsSigningProtocol<B, BE, C, N, KBE>,
+pub async fn generate_protocol_from<C: ClientWithApi, N: Network, KBE: KeystoreBackend>(
+    config: &crate::BlsSigningProtocol<C, N, KBE>,
     associated_block_id: <WorkManager as WorkManagerInterface>::Clock,
     associated_retry_id: <WorkManager as WorkManagerInterface>::RetryID,
     associated_session_id: <WorkManager as WorkManagerInterface>::SessionID,
     associated_task_id: <WorkManager as WorkManagerInterface>::TaskID,
     protocol_message_rx: tokio::sync::mpsc::UnboundedReceiver<GadgetProtocolMessage>,
     additional_params: BlsSigningAdditionalParams,
-) -> Result<BuiltExecutableJobWrapper, JobError>
-where
-    <C as ProvideRuntimeApi<B>>::Api: JobsApiForGadget<B>,
-{
+) -> Result<BuiltExecutableJobWrapper, JobError> {
     let threshold = additional_params.t;
     let network = config.clone();
     let result = Arc::new(tokio::sync::Mutex::new(None));
     let result_clone = result.clone();
     let client = config.get_jobs_client();
-    let role_type = additional_params.role_type;
+    let role_type = additional_params.role_type.clone();
     let job_id = additional_params.job_id;
     let logger = config.logger.clone();
     let id = config.key_store.pair().public();
@@ -244,15 +224,12 @@ where
             let signature = as_sig.as_bytes().to_vec();
 
             logger.info("BlsSigningProtocol finished verification stage");
-            let job_result = JobResult::DKGPhaseTwo(DKGTSSSignatureResult {
-                signature_scheme: DigitalSignatureScheme::Bls381,
-                data: additional_params
-                    .input_data_to_sign
-                    .clone()
-                    .try_into()
-                    .unwrap(),
-                signature: signature.try_into().unwrap(),
-                verifying_key: signing_key.try_into().unwrap(),
+            let job_result = jobs::JobResult::DKGPhaseTwo(jobs::tss::DKGTSSSignatureResult {
+                signature_scheme: jobs::tss::DigitalSignatureScheme::Bls381,
+                data: BoundedVec(additional_params.input_data_to_sign.clone()),
+                signature: BoundedVec(signature),
+                verifying_key: BoundedVec(signing_key),
+                __subxt_unused_type_params: Default::default(),
             });
 
             *result.lock().await = Some(job_result);
diff --git a/protocols/dfns-cggmp21/Cargo.toml b/protocols/dfns-cggmp21/Cargo.toml
index f91a3c865..b9b0e03f7 100644
--- a/protocols/dfns-cggmp21/Cargo.toml
+++ b/protocols/dfns-cggmp21/Cargo.toml
@@ -18,18 +18,8 @@ itertools = { workspace = true }
 bincode2 = { workspace = true }
 digest = { workspace = true }
 
-pallet-jobs-rpc-runtime-api = { workspace = true, features = ["std"] }
-pallet-jobs = { workspace = true, features = ["std"] }
-pallet-dkg = { workspace = true, features = ["std"] }
-tangle-primitives = { workspace = true, features = ["std"] }
-
 sp-core = { workspace = true, features = ["std"] }
 sp-io = { workspace = true, features = ["std"] }
-sp-api = { workspace = true, features = ["std"] }
-sp-runtime = { workspace = true, features = ["std"] }
-sp-application-crypto = { workspace = true, features = ["std"] }
-
-sc-client-api = { workspace = true }
 
 frame-support = { workspace = true  }
 parity-scale-codec = { workspace = true }
@@ -38,6 +28,9 @@ serde = { version = "1.0.193", features = ["derive"] }
 rand = { workspace = true }
 rand_chacha = { workspace = true }
 hex = { workspace = true }
-test-utils = { workspace = true }
 parking_lot = { workspace = true }
-sha2 = { workspace = true }
\ No newline at end of file
+sha2 = { workspace = true }
+
+[dev-dependencies]
+test-utils = { workspace = true }
+tangle-primitives = { workspace = true }
diff --git a/protocols/dfns-cggmp21/src/lib.rs b/protocols/dfns-cggmp21/src/lib.rs
index 4dda5bd51..2a355ee12 100644
--- a/protocols/dfns-cggmp21/src/lib.rs
+++ b/protocols/dfns-cggmp21/src/lib.rs
@@ -7,12 +7,10 @@ use gadget_common::full_protocol::SharedOptional;
 use gadget_common::prelude::*;
 use gadget_common::{generate_protocol, generate_setup_and_run_command};
 use protocol_macros::protocol;
-use test_utils::generate_signing_and_keygen_tss_tests;
 
 pub mod constants;
 pub mod error;
 pub mod protocols;
-pub mod util;
 
 generate_protocol!(
     "DFNS-Keygen-Protocol",
@@ -20,8 +18,10 @@ generate_protocol!(
     DfnsCGGMP21KeygenExtraParams,
     protocols::keygen::generate_protocol_from,
     protocols::keygen::create_next_job,
-    GadgetJobType::DKGTSSPhaseOne(_),
-    RoleType::Tss(ThresholdSignatureRoleType::DfnsCGGMP21Secp256k1)
+    jobs::JobType::DKGTSSPhaseOne(_),
+    roles::RoleType::Tss(roles::tss::ThresholdSignatureRoleType::DfnsCGGMP21Secp256k1)
+        | roles::RoleType::Tss(roles::tss::ThresholdSignatureRoleType::DfnsCGGMP21Secp256r1)
+        | roles::RoleType::Tss(roles::tss::ThresholdSignatureRoleType::DfnsCGGMP21Stark)
 );
 generate_protocol!(
     "DFNS-Signing-Protocol",
@@ -29,8 +29,10 @@ generate_protocol!(
     DfnsCGGMP21SigningExtraParams,
     protocols::sign::generate_protocol_from,
     protocols::sign::create_next_job,
-    GadgetJobType::DKGTSSPhaseTwo(_),
-    RoleType::Tss(ThresholdSignatureRoleType::DfnsCGGMP21Secp256k1)
+    jobs::JobType::DKGTSSPhaseTwo(_),
+    roles::RoleType::Tss(roles::tss::ThresholdSignatureRoleType::DfnsCGGMP21Secp256k1)
+        | roles::RoleType::Tss(roles::tss::ThresholdSignatureRoleType::DfnsCGGMP21Secp256r1)
+        | roles::RoleType::Tss(roles::tss::ThresholdSignatureRoleType::DfnsCGGMP21Stark)
 );
 generate_protocol!(
     "DFNS-Refresh-Protocol",
@@ -38,8 +40,10 @@ generate_protocol!(
     DfnsCGGMP21KeyRefreshExtraParams,
     protocols::key_refresh::generate_protocol_from,
     protocols::key_refresh::create_next_job,
-    GadgetJobType::DKGTSSPhaseThree(_),
-    RoleType::Tss(ThresholdSignatureRoleType::DfnsCGGMP21Secp256k1)
+    jobs::JobType::DKGTSSPhaseThree(_),
+    roles::RoleType::Tss(roles::tss::ThresholdSignatureRoleType::DfnsCGGMP21Secp256k1)
+        | roles::RoleType::Tss(roles::tss::ThresholdSignatureRoleType::DfnsCGGMP21Secp256r1)
+        | roles::RoleType::Tss(roles::tss::ThresholdSignatureRoleType::DfnsCGGMP21Stark)
 );
 generate_protocol!(
     "DFNS-Rotate-Protocol",
@@ -47,8 +51,10 @@ generate_protocol!(
     DfnsCGGMP21KeyRotateExtraParams,
     protocols::key_rotate::generate_protocol_from,
     protocols::key_rotate::create_next_job,
-    GadgetJobType::DKGTSSPhaseFour(_),
-    RoleType::Tss(ThresholdSignatureRoleType::DfnsCGGMP21Secp256k1)
+    jobs::JobType::DKGTSSPhaseFour(_),
+    roles::RoleType::Tss(roles::tss::ThresholdSignatureRoleType::DfnsCGGMP21Secp256k1)
+        | roles::RoleType::Tss(roles::tss::ThresholdSignatureRoleType::DfnsCGGMP21Secp256r1)
+        | roles::RoleType::Tss(roles::tss::ThresholdSignatureRoleType::DfnsCGGMP21Stark)
 );
 
 generate_setup_and_run_command!(
@@ -58,8 +64,9 @@ generate_setup_and_run_command!(
     DfnsKeyRotateProtocol
 );
 
+#[cfg(test)]
 mod secp256k1 {
-    super::generate_signing_and_keygen_tss_tests!(
+    test_utils::generate_signing_and_keygen_tss_tests!(
         2,
         3,
         4,
@@ -67,8 +74,9 @@ mod secp256k1 {
     );
 }
 
+#[cfg(test)]
 mod secp256r1 {
-    super::generate_signing_and_keygen_tss_tests!(
+    test_utils::generate_signing_and_keygen_tss_tests!(
         2,
         3,
         4,
@@ -76,8 +84,9 @@ mod secp256r1 {
     );
 }
 
+#[cfg(test)]
 mod stark {
-    super::generate_signing_and_keygen_tss_tests!(
+    test_utils::generate_signing_and_keygen_tss_tests!(
         2,
         3,
         4,
diff --git a/protocols/dfns-cggmp21/src/protocols/key_refresh.rs b/protocols/dfns-cggmp21/src/protocols/key_refresh.rs
index 1925ee3c2..cea19c810 100644
--- a/protocols/dfns-cggmp21/src/protocols/key_refresh.rs
+++ b/protocols/dfns-cggmp21/src/protocols/key_refresh.rs
@@ -7,49 +7,33 @@ use dfns_cggmp21::supported_curves::{Secp256k1, Secp256r1, Stark};
 use dfns_cggmp21::{KeyShare, PregeneratedPrimes};
 use digest::typenum::U32;
 use digest::Digest;
-use gadget_common::client::{ClientWithApi, JobsApiForGadget};
+use gadget_common::client::ClientWithApi;
 use gadget_common::gadget::message::{GadgetProtocolMessage, UserID};
 use gadget_common::gadget::network::Network;
 use gadget_common::gadget::work_manager::WorkManager;
 use gadget_common::gadget::JobInitMetadata;
 use gadget_common::keystore::KeystoreBackend;
+use gadget_common::prelude::*;
 use gadget_common::prelude::{DebugLogger, FullProtocolConfig};
-use gadget_common::Block;
 use gadget_core::job::{BuiltExecutableJobWrapper, JobBuilder, JobError};
 use gadget_core::job_manager::{ProtocolWorkManager, WorkManagerInterface};
 use rand::SeedableRng;
 use round_based_21::{Incoming, Outgoing};
-use sc_client_api::Backend;
-use sp_api::ProvideRuntimeApi;
-use sp_application_crypto::sp_core::keccak_256;
-use sp_core::{ecdsa, Pair};
+use sp_core::{ecdsa, keccak_256, Pair};
 use std::collections::HashMap;
 use std::sync::Arc;
-use tangle_primitives::jobs::{
-    DKGTSSKeyRefreshResult, DigitalSignatureScheme, JobId, JobResult, JobType,
-};
-use tangle_primitives::roles::{RoleType, ThresholdSignatureRoleType};
 use tokio::sync::mpsc::UnboundedReceiver;
 
-pub(crate) async fn create_next_job<
-    B: Block,
-    BE: Backend<B> + 'static,
-    C: ClientWithApi<B, BE>,
-    KBE: KeystoreBackend,
-    N: Network,
->(
-    config: &crate::DfnsKeyRefreshProtocol<B, BE, C, N, KBE>,
-    job: JobInitMetadata<B>,
+pub(crate) async fn create_next_job<C: ClientWithApi, KBE: KeystoreBackend, N: Network>(
+    config: &crate::DfnsKeyRefreshProtocol<C, N, KBE>,
+    job: JobInitMetadata,
     _work_manager: &ProtocolWorkManager<WorkManager>,
-) -> Result<DfnsCGGMP21KeyRefreshExtraParams, gadget_common::Error>
-where
-    <C as ProvideRuntimeApi<B>>::Api: JobsApiForGadget<B>,
-{
+) -> Result<DfnsCGGMP21KeyRefreshExtraParams, gadget_common::Error> {
     let job_id = job.job_id;
     let role_type = job.job_type.get_role_type();
 
     // We can safely make this assumption because we are only creating jobs for phase one
-    let JobType::DKGTSSPhaseThree(p3_job) = job.job_type else {
+    let jobs::JobType::DKGTSSPhaseThree(p3_job) = job.job_type else {
         panic!("Should be valid type")
     };
 
@@ -101,32 +85,23 @@ where
 
 #[derive(Clone)]
 pub struct DfnsCGGMP21KeyRefreshExtraParams {
-    job_id: JobId,
-    phase_one_id: JobId,
-    role_type: RoleType,
+    job_id: u64,
+    phase_one_id: u64,
+    role_type: roles::RoleType,
     key: Vec<u8>,
     pregenerated_primes: dfns_cggmp21::PregeneratedPrimes,
     user_id_to_account_id_mapping: Arc<HashMap<UserID, ecdsa::Public>>,
 }
 
-pub async fn generate_protocol_from<
-    B: Block,
-    BE: Backend<B> + 'static,
-    C: ClientWithApi<B, BE>,
-    KBE: KeystoreBackend,
-    N: Network,
->(
-    config: &crate::DfnsKeyRefreshProtocol<B, BE, C, N, KBE>,
+pub async fn generate_protocol_from<C: ClientWithApi, KBE: KeystoreBackend, N: Network>(
+    config: &crate::DfnsKeyRefreshProtocol<C, N, KBE>,
     associated_block_id: <WorkManager as WorkManagerInterface>::Clock,
     associated_retry_id: <WorkManager as WorkManagerInterface>::RetryID,
     associated_session_id: <WorkManager as WorkManagerInterface>::SessionID,
     associated_task_id: <WorkManager as WorkManagerInterface>::TaskID,
     protocol_message_channel: UnboundedReceiver<GadgetProtocolMessage>,
     additional_params: DfnsCGGMP21KeyRefreshExtraParams,
-) -> Result<BuiltExecutableJobWrapper, JobError>
-where
-    <C as ProvideRuntimeApi<B>>::Api: JobsApiForGadget<B>,
-{
+) -> Result<BuiltExecutableJobWrapper, JobError> {
     let key_store = config.key_store.clone();
     let protocol_output = Arc::new(tokio::sync::Mutex::new(None));
     let protocol_output_clone = protocol_output.clone();
@@ -134,7 +109,7 @@ where
     let role_id = config.key_store.pair().public();
     let logger = config.logger.clone();
     let network = config.clone();
-    let role_type = additional_params.role_type;
+    let role_type = additional_params.role_type.clone();
 
     let (mapping, serialized_key_share, pregenerated_primes) = (
         additional_params.user_id_to_account_id_mapping,
@@ -145,7 +120,9 @@ where
     Ok(JobBuilder::new()
         .protocol(async move {
             let key = match role_type {
-                RoleType::Tss(ThresholdSignatureRoleType::DfnsCGGMP21Secp256k1) => {
+                roles::RoleType::Tss(
+                    roles::tss::ThresholdSignatureRoleType::DfnsCGGMP21Secp256k1,
+                ) => {
                     handle_key_refresh::<Secp256k1, DefaultSecurityLevel, DefaultCryptoHasher, _>(
                         &serialized_key_share,
                         &logger,
@@ -163,7 +140,9 @@ where
                     .await?
                 }
 
-                RoleType::Tss(ThresholdSignatureRoleType::DfnsCGGMP21Secp256r1) => {
+                roles::RoleType::Tss(
+                    roles::tss::ThresholdSignatureRoleType::DfnsCGGMP21Secp256r1,
+                ) => {
                     handle_key_refresh::<Secp256r1, DefaultSecurityLevel, DefaultCryptoHasher, _>(
                         &serialized_key_share,
                         &logger,
@@ -181,7 +160,7 @@ where
                     .await?
                 }
 
-                RoleType::Tss(ThresholdSignatureRoleType::DfnsCGGMP21Stark) => {
+                roles::RoleType::Tss(roles::tss::ThresholdSignatureRoleType::DfnsCGGMP21Stark) => {
                     handle_key_refresh::<Stark, DefaultSecurityLevel, DefaultCryptoHasher, _>(
                         &serialized_key_share,
                         &logger,
@@ -207,8 +186,8 @@ where
                 }
             };
 
-            let job_result = JobResult::DKGPhaseThree(DKGTSSKeyRefreshResult {
-                signature_scheme: DigitalSignatureScheme::Ecdsa,
+            let job_result = jobs::JobResult::DKGPhaseThree(jobs::tss::DKGTSSKeyRefreshResult {
+                signature_scheme: jobs::tss::DigitalSignatureScheme::Ecdsa,
             });
 
             *protocol_output.lock().await = Some((key, job_result));
@@ -251,7 +230,7 @@ async fn handle_key_refresh<
 >(
     serialized_key_share: &[u8],
     logger: &DebugLogger,
-    job_id: JobId,
+    job_id: u64,
     pregenerated_primes: PregeneratedPrimes<S>,
     protocol_message_channel: UnboundedReceiver<GadgetProtocolMessage>,
     associated_block_id: <WorkManager as WorkManagerInterface>::Clock,
diff --git a/protocols/dfns-cggmp21/src/protocols/key_rotate.rs b/protocols/dfns-cggmp21/src/protocols/key_rotate.rs
index 46c8d0488..c4b4d7a60 100644
--- a/protocols/dfns-cggmp21/src/protocols/key_rotate.rs
+++ b/protocols/dfns-cggmp21/src/protocols/key_rotate.rs
@@ -1,8 +1,8 @@
 use crate::protocols::sign::run_and_serialize_signing;
+use crate::protocols::{DefaultCryptoHasher, DefaultSecurityLevel};
 use dfns_cggmp21::signing::msg::Msg;
 use dfns_cggmp21::supported_curves::{Secp256k1, Secp256r1, Stark};
-
-use gadget_common::client::{ClientWithApi, JobsApiForGadget};
+use gadget_common::client::ClientWithApi;
 use gadget_common::gadget::message::{GadgetProtocolMessage, UserID};
 use gadget_common::gadget::network::Network;
 use gadget_common::gadget::work_manager::WorkManager;
@@ -10,42 +10,25 @@ use gadget_common::gadget::JobInitMetadata;
 use gadget_common::keystore::KeystoreBackend;
 use gadget_common::prelude::FullProtocolConfig;
 use gadget_common::prelude::*;
-use gadget_common::Block;
+use gadget_common::tangle_subxt::tangle_runtime::api::runtime_types::bounded_collections::bounded_vec::BoundedVec;
 use gadget_core::job::{BuiltExecutableJobWrapper, JobBuilder, JobError};
 use gadget_core::job_manager::{ProtocolWorkManager, WorkManagerInterface};
 use rand::SeedableRng;
-
-use crate::protocols::{DefaultCryptoHasher, DefaultSecurityLevel};
-use sc_client_api::Backend;
-use sp_api::ProvideRuntimeApi;
 use sp_core::{ecdsa, keccak_256, Pair};
 use std::collections::HashMap;
 use std::sync::Arc;
-use tangle_primitives::jobs::{
-    DKGTSSKeyRotationResult, DigitalSignatureScheme, JobId, JobResult, JobType,
-};
-use tangle_primitives::roles::RoleType;
 use tokio::sync::mpsc::UnboundedReceiver;
 
 use super::keygen::create_party;
 
-pub async fn create_next_job<
-    B: Block,
-    BE: Backend<B> + 'static,
-    C: ClientWithApi<B, BE>,
-    KBE: KeystoreBackend,
-    N: Network,
->(
-    config: &crate::DfnsKeyRotateProtocol<B, BE, C, N, KBE>,
-    job: JobInitMetadata<B>,
+pub async fn create_next_job<C: ClientWithApi, KBE: KeystoreBackend, N: Network>(
+    config: &crate::DfnsKeyRotateProtocol<C, N, KBE>,
+    job: JobInitMetadata,
     _work_manager: &ProtocolWorkManager<WorkManager>,
-) -> Result<DfnsCGGMP21KeyRotateExtraParams, gadget_common::Error>
-where
-    <C as ProvideRuntimeApi<B>>::Api: JobsApiForGadget<B>,
-{
+) -> Result<DfnsCGGMP21KeyRotateExtraParams, gadget_common::Error> {
     let job_id = job.job_id;
 
-    let JobType::DKGTSSPhaseFour(p4_job) = job.job_type else {
+    let jobs::JobType::DKGTSSPhaseFour(p4_job) = job.job_type else {
         panic!("Should be valid type")
     };
     let phase_one_id = p4_job.phase_one_id;
@@ -117,33 +100,24 @@ pub struct DfnsCGGMP21KeyRotateExtraParams {
     i: u16,
     t: u16,
     signers: Vec<u16>,
-    job_id: JobId,
-    phase_one_id: JobId,
-    new_phase_one_id: JobId,
-    role_type: RoleType,
+    job_id: u64,
+    phase_one_id: u64,
+    new_phase_one_id: u64,
+    role_type: roles::RoleType,
     key: Vec<u8>,
     new_key: Vec<u8>,
     user_id_to_account_id_mapping: Arc<HashMap<UserID, ecdsa::Public>>,
 }
 
-pub async fn generate_protocol_from<
-    B: Block,
-    BE: Backend<B> + 'static,
-    C: ClientWithApi<B, BE>,
-    KBE: KeystoreBackend,
-    N: Network,
->(
-    config: &crate::DfnsKeyRotateProtocol<B, BE, C, N, KBE>,
+pub async fn generate_protocol_from<C: ClientWithApi, KBE: KeystoreBackend, N: Network>(
+    config: &crate::DfnsKeyRotateProtocol<C, N, KBE>,
     associated_block_id: <WorkManager as WorkManagerInterface>::Clock,
     associated_retry_id: <WorkManager as WorkManagerInterface>::RetryID,
     associated_session_id: <WorkManager as WorkManagerInterface>::SessionID,
     associated_task_id: <WorkManager as WorkManagerInterface>::TaskID,
     protocol_message_channel: UnboundedReceiver<GadgetProtocolMessage>,
     additional_params: DfnsCGGMP21KeyRotateExtraParams,
-) -> Result<BuiltExecutableJobWrapper, JobError>
-where
-    <C as ProvideRuntimeApi<B>>::Api: JobsApiForGadget<B>,
-{
+) -> Result<BuiltExecutableJobWrapper, JobError> {
     let debug_logger_post = config.logger.clone();
     let logger = debug_logger_post.clone();
     let protocol_output = Arc::new(tokio::sync::Mutex::new(None));
@@ -168,7 +142,7 @@ where
         additional_params.t,
         additional_params.new_phase_one_id,
         additional_params.key,
-        additional_params.role_type,
+        additional_params.role_type.clone(),
         additional_params.new_key.clone(),
         additional_params.user_id_to_account_id_mapping.clone(),
     );
@@ -198,7 +172,9 @@ where
             let eid = dfns_cggmp21::ExecutionId::new(&eid_bytes);
             let mut tracer = dfns_cggmp21::progress::PerfProfiler::new();
             let signature = match role_type {
-                RoleType::Tss(ThresholdSignatureRoleType::DfnsCGGMP21Secp256k1) => {
+                roles::RoleType::Tss(
+                    roles::tss::ThresholdSignatureRoleType::DfnsCGGMP21Secp256k1,
+                ) => {
                     let data_to_sign = dfns_cggmp21::DataToSign::<Secp256k1>::from_scalar(
                         dfns_cggmp21::generic_ec::Scalar::<Secp256k1>::from_be_bytes_mod_order(
                             data_hash,
@@ -233,7 +209,9 @@ where
                     )
                     .await?
                 }
-                RoleType::Tss(ThresholdSignatureRoleType::DfnsCGGMP21Secp256r1) => {
+                roles::RoleType::Tss(
+                    roles::tss::ThresholdSignatureRoleType::DfnsCGGMP21Secp256r1,
+                ) => {
                     let data_to_sign = dfns_cggmp21::DataToSign::<Secp256r1>::from_scalar(
                         dfns_cggmp21::generic_ec::Scalar::<Secp256r1>::from_be_bytes_mod_order(
                             data_hash,
@@ -274,7 +252,7 @@ where
                     )
                     .await?
                 }
-                RoleType::Tss(ThresholdSignatureRoleType::DfnsCGGMP21Stark) => {
+                roles::RoleType::Tss(roles::tss::ThresholdSignatureRoleType::DfnsCGGMP21Stark) => {
                     let data_to_sign = dfns_cggmp21::DataToSign::<Stark>::from_scalar(
                         dfns_cggmp21::generic_ec::Scalar::<Stark>::from_be_bytes_mod_order(
                             data_hash,
@@ -333,14 +311,16 @@ where
                     &data_to_sign_bytes,
                     &new_public_key,
                 );
-                let job_result = JobResult::DKGPhaseFour(DKGTSSKeyRotationResult {
-                    signature_scheme: DigitalSignatureScheme::Ecdsa,
-                    signature: signature.to_vec().try_into().unwrap(),
-                    phase_one_id,
-                    new_phase_one_id,
-                    new_key: new_public_key.try_into().unwrap(),
-                    key: public_key.try_into().unwrap(),
-                });
+                let job_result =
+                    jobs::JobResult::DKGPhaseFour(jobs::tss::DKGTSSKeyRotationResult {
+                        signature_scheme: jobs::tss::DigitalSignatureScheme::Ecdsa,
+                        signature: BoundedVec(signature.to_vec()),
+                        phase_one_id,
+                        new_phase_one_id,
+                        new_key: BoundedVec(new_public_key),
+                        key: BoundedVec(public_key),
+                        __subxt_unused_type_params: Default::default(),
+                    });
 
                 client
                     .submit_job_result(
diff --git a/protocols/dfns-cggmp21/src/protocols/keygen.rs b/protocols/dfns-cggmp21/src/protocols/keygen.rs
index 87d31e425..d1aaa97c8 100644
--- a/protocols/dfns-cggmp21/src/protocols/keygen.rs
+++ b/protocols/dfns-cggmp21/src/protocols/keygen.rs
@@ -12,9 +12,7 @@ use digest::typenum::U32;
 use digest::Digest;
 use futures::channel::mpsc::{TryRecvError, UnboundedSender};
 use futures::StreamExt;
-use gadget_common::client::{
-    ClientWithApi, GadgetJobResult, JobsApiForGadget, MaxKeyLen, MaxParticipants, MaxSignatureLen,
-};
+use gadget_common::client::ClientWithApi;
 use gadget_common::debug_logger::DebugLogger;
 use gadget_common::full_protocol::FullProtocolConfig;
 use gadget_common::gadget::message::{GadgetProtocolMessage, UserID};
@@ -22,51 +20,34 @@ use gadget_common::gadget::network::Network;
 use gadget_common::gadget::work_manager::WorkManager;
 use gadget_common::gadget::JobInitMetadata;
 use gadget_common::keystore::{ECDSAKeyStore, KeystoreBackend};
-use gadget_common::Block;
+use gadget_common::{prelude::*, utils};
+use gadget_common::tangle_subxt::tangle_runtime::api::runtime_types::bounded_collections::bounded_vec::BoundedVec;
 use gadget_core::job::{BuiltExecutableJobWrapper, JobBuilder, JobError};
 use gadget_core::job_manager::{ProtocolWorkManager, WorkManagerInterface};
 use itertools::Itertools;
-use pallet_dkg::signatures_schemes::ecdsa::verify_signer_from_set_ecdsa;
-use pallet_dkg::signatures_schemes::to_slice_33;
 use rand::rngs::{OsRng, StdRng};
 use rand::{CryptoRng, RngCore, SeedableRng};
 use round_based_21::{Delivery, Incoming, MpcParty, Outgoing};
-use sc_client_api::Backend;
 use serde::Serialize;
-use sp_api::ProvideRuntimeApi;
-use sp_application_crypto::sp_core::keccak_256;
+use sp_core::keccak_256;
 use sp_core::{ecdsa, Pair};
-use sp_runtime::DeserializeOwned;
 use std::collections::{BTreeMap, HashMap};
 use std::sync::Arc;
-use tangle_primitives::jobs::{
-    DKGTSSKeySubmissionResult, DigitalSignatureScheme, JobId, JobResult, JobType,
-};
-use tangle_primitives::roles::{RoleType, ThresholdSignatureRoleType};
 use tokio::sync::mpsc::UnboundedReceiver;
 
 use crate::protocols::{DefaultCryptoHasher, DefaultSecurityLevel};
 use gadget_common::channels::PublicKeyGossipMessage;
 
-pub async fn create_next_job<
-    B: Block,
-    BE: Backend<B> + 'static,
-    KBE: KeystoreBackend,
-    C: ClientWithApi<B, BE>,
-    N: Network,
->(
-    config: &crate::DfnsKeygenProtocol<B, BE, C, N, KBE>,
-    job: JobInitMetadata<B>,
+pub async fn create_next_job<KBE: KeystoreBackend, C: ClientWithApi, N: Network>(
+    config: &crate::DfnsKeygenProtocol<C, N, KBE>,
+    job: JobInitMetadata,
     _work_manager: &ProtocolWorkManager<WorkManager>,
-) -> Result<DfnsCGGMP21KeygenExtraParams, gadget_common::Error>
-where
-    <C as ProvideRuntimeApi<B>>::Api: JobsApiForGadget<B>,
-{
+) -> Result<DfnsCGGMP21KeygenExtraParams, gadget_common::Error> {
     let job_id = job.job_id;
     let role_type = job.job_type.get_role_type();
 
     // We can safely make this assumption because we are only creating jobs for phase one
-    let JobType::DKGTSSPhaseOne(p1_job) = job.job_type else {
+    let jobs::JobType::DKGTSSPhaseOne(p1_job) = job.job_type else {
         panic!("Should be valid type")
     };
 
@@ -84,8 +65,9 @@ where
 
     let i = p1_job
         .participants
+        .0
         .iter()
-        .position(|p| p == &config.account_id)
+        .position(|p| p.0 == config.account_id.0)
         .expect("Should exist") as u16;
 
     let params = DfnsCGGMP21KeygenExtraParams {
@@ -105,8 +87,8 @@ pub struct DfnsCGGMP21KeygenExtraParams {
     i: u16,
     t: u16,
     n: u16,
-    job_id: JobId,
-    role_type: RoleType,
+    job_id: u64,
+    role_type: roles::RoleType,
     user_id_to_account_id_mapping: Arc<HashMap<UserID, ecdsa::Public>>,
 }
 
@@ -229,7 +211,7 @@ where
     N: Network,
     L: SecurityLevel,
     E: Curve,
-    M: Serialize + DeserializeOwned + Send + Sync + 'static,
+    M: Serialize + serde::de::DeserializeOwned + Send + Sync + 'static,
 {
     let (tx_to_outbound, rx_async_proto, broadcast_tx_to_outbound, broadcast_rx_from_gadget) =
         gadget_common::channels::create_job_manager_to_async_protocol_channel_split_io::<
@@ -256,24 +238,15 @@ where
     )
 }
 
-pub async fn generate_protocol_from<
-    B: Block,
-    BE: Backend<B> + 'static,
-    KBE: KeystoreBackend,
-    C: ClientWithApi<B, BE>,
-    N: Network,
->(
-    config: &crate::DfnsKeygenProtocol<B, BE, C, N, KBE>,
+pub async fn generate_protocol_from<KBE: KeystoreBackend, C: ClientWithApi, N: Network>(
+    config: &crate::DfnsKeygenProtocol<C, N, KBE>,
     associated_block_id: <WorkManager as WorkManagerInterface>::Clock,
     associated_retry_id: <WorkManager as WorkManagerInterface>::RetryID,
     associated_session_id: <WorkManager as WorkManagerInterface>::SessionID,
     associated_task_id: <WorkManager as WorkManagerInterface>::TaskID,
     protocol_message_channel: UnboundedReceiver<GadgetProtocolMessage>,
     additional_params: DfnsCGGMP21KeygenExtraParams,
-) -> Result<BuiltExecutableJobWrapper, JobError>
-where
-    <C as ProvideRuntimeApi<B>>::Api: JobsApiForGadget<B>,
-{
+) -> Result<BuiltExecutableJobWrapper, JobError> {
     let key_store = config.key_store.clone();
     let key_store2 = config.key_store.clone();
     let protocol_output = Arc::new(tokio::sync::Mutex::new(None));
@@ -287,7 +260,7 @@ where
         additional_params.i,
         additional_params.t,
         additional_params.n,
-        additional_params.role_type,
+        additional_params.role_type.clone(),
         additional_params.user_id_to_account_id_mapping,
     );
 
@@ -309,7 +282,9 @@ where
 
             let (key_share, serialized_public_key, tx2, rx2) =
                 match role_type {
-                    RoleType::Tss(ThresholdSignatureRoleType::DfnsCGGMP21Secp256k1) => {
+                    roles::RoleType::Tss(
+                        roles::tss::ThresholdSignatureRoleType::DfnsCGGMP21Secp256k1,
+                    ) => {
                         run_full_keygen_protocol::<
                             Secp256k1,
                             DefaultSecurityLevel,
@@ -339,7 +314,9 @@ where
                         )
                         .await?
                     }
-                    RoleType::Tss(ThresholdSignatureRoleType::DfnsCGGMP21Secp256r1) => {
+                    roles::RoleType::Tss(
+                        roles::tss::ThresholdSignatureRoleType::DfnsCGGMP21Secp256r1,
+                    ) => {
                         run_full_keygen_protocol::<
                             Secp256r1,
                             DefaultSecurityLevel,
@@ -369,7 +346,9 @@ where
                         )
                         .await?
                     }
-                    RoleType::Tss(ThresholdSignatureRoleType::DfnsCGGMP21Stark) => {
+                    roles::RoleType::Tss(
+                        roles::tss::ThresholdSignatureRoleType::DfnsCGGMP21Stark,
+                    ) => {
                         run_full_keygen_protocol::<
                             Stark,
                             DefaultSecurityLevel,
@@ -457,7 +436,16 @@ async fn handle_public_key_gossip<KBE: KeystoreBackend>(
     i: u16,
     broadcast_tx_to_outbound: UnboundedSender<PublicKeyGossipMessage>,
     mut broadcast_rx_from_gadget: futures::channel::mpsc::UnboundedReceiver<PublicKeyGossipMessage>,
-) -> Result<GadgetJobResult, JobError> {
+) -> Result<
+    jobs::JobResult<
+        jobs::MaxParticipants,
+        jobs::MaxKeyLen,
+        jobs::MaxSignatureLen,
+        jobs::MaxDataLen,
+        jobs::MaxProofLen,
+    >,
+    JobError,
+> {
     let key_hashed = keccak_256(serialized_public_key);
     let signature = key_store.pair().sign_prehashed(&key_hashed).0.to_vec();
     let my_id = key_store.pair().public();
@@ -523,16 +511,14 @@ async fn handle_public_key_gossip<KBE: KeystoreBackend>(
     let signatures = received_keys
         .into_iter()
         .sorted_by_key(|x| x.0)
-        .map(|r| r.1.try_into().unwrap())
+        .map(|r| BoundedVec(r.1))
         .collect::<Vec<_>>();
 
     let participants = received_participants
         .into_iter()
         .sorted_by_key(|x| x.0)
-        .map(|r| r.1 .0.to_vec().try_into().unwrap())
-        .collect::<Vec<_>>()
-        .try_into()
-        .unwrap();
+        .map(|(_, p)| BoundedVec(p.0.to_vec()))
+        .collect::<Vec<_>>();
 
     if signatures.len() < t as usize {
         return Err(JobError {
@@ -544,32 +530,38 @@ async fn handle_public_key_gossip<KBE: KeystoreBackend>(
         });
     }
 
-    let res = DKGTSSKeySubmissionResult {
-        signature_scheme: DigitalSignatureScheme::Ecdsa,
-        key: serialized_public_key.to_vec().try_into().unwrap(),
-        participants,
-        signatures: signatures.try_into().unwrap(),
+    let res = jobs::tss::DKGTSSKeySubmissionResult {
+        signature_scheme: jobs::tss::DigitalSignatureScheme::Ecdsa,
+        key: BoundedVec(serialized_public_key.to_vec()),
+        participants: BoundedVec(participants),
+        signatures: BoundedVec(signatures),
         threshold: t as _,
+        __subxt_unused_type_params: Default::default(),
     };
     verify_generated_dkg_key_ecdsa(res.clone(), logger);
-    Ok(JobResult::DKGPhaseOne(res))
+    Ok(jobs::JobResult::DKGPhaseOne(res))
 }
 
 fn verify_generated_dkg_key_ecdsa(
-    data: DKGTSSKeySubmissionResult<MaxKeyLen, MaxParticipants, MaxSignatureLen>,
+    data: jobs::tss::DKGTSSKeySubmissionResult<
+        jobs::MaxKeyLen,
+        jobs::MaxParticipants,
+        jobs::MaxSignatureLen,
+    >,
     logger: &DebugLogger,
 ) {
     // Ensure participants and signatures are not empty
-    assert!(!data.participants.is_empty(), "NoParticipantsFound",);
-    assert!(!data.signatures.is_empty(), "NoSignaturesFound");
+    assert!(!data.participants.0.is_empty(), "NoParticipantsFound",);
+    assert!(!data.signatures.0.is_empty(), "NoSignaturesFound");
 
     // Generate the required ECDSA signers
     let maybe_signers = data
         .participants
+        .0
         .iter()
         .map(|x| {
             ecdsa::Public(
-                to_slice_33(x)
+                utils::to_slice_33(&x.0)
                     .unwrap_or_else(|| panic!("Failed to convert input to ecdsa public key")),
             )
         })
@@ -579,10 +571,10 @@ fn verify_generated_dkg_key_ecdsa(
 
     let mut known_signers: Vec<ecdsa::Public> = Default::default();
 
-    for signature in data.signatures {
+    for signature in data.signatures.0 {
         // Ensure the required signer signature exists
         let (maybe_authority, success) =
-            verify_signer_from_set_ecdsa(maybe_signers.clone(), &data.key, &signature);
+            utils::verify_signer_from_set_ecdsa(maybe_signers.clone(), &data.key.0, &signature.0);
 
         if success {
             let authority = maybe_authority.expect("CannotRetreiveSigner");
@@ -671,7 +663,7 @@ async fn run_full_keygen_protocol<
     logger: &DebugLogger,
     job_id_bytes: &[u8],
     key_store: &ECDSAKeyStore<KBE>,
-    role_type: RoleType,
+    role_type: roles::RoleType,
 ) -> Result<
     (
         Vec<u8>,
diff --git a/protocols/dfns-cggmp21/src/protocols/sign.rs b/protocols/dfns-cggmp21/src/protocols/sign.rs
index 224d8b833..ca76a623b 100644
--- a/protocols/dfns-cggmp21/src/protocols/sign.rs
+++ b/protocols/dfns-cggmp21/src/protocols/sign.rs
@@ -1,61 +1,44 @@
+use crate::protocols::{DefaultCryptoHasher, DefaultSecurityLevel};
 use dfns_cggmp21::generic_ec::coords::HasAffineX;
 use dfns_cggmp21::generic_ec::{Curve, Point};
 use dfns_cggmp21::round_based::{Delivery, MpcParty};
 use dfns_cggmp21::security_level::SecurityLevel;
 use dfns_cggmp21::signing::msg::Msg;
-
+use dfns_cggmp21::signing::SigningBuilder;
 use dfns_cggmp21::supported_curves::{Secp256k1, Secp256r1, Stark};
 use dfns_cggmp21::{DataToSign, KeyShare};
-use gadget_common::client::{ClientWithApi, JobsApiForGadget};
+use digest::typenum::U32;
+use digest::Digest;
+use gadget_common::client::ClientWithApi;
 use gadget_common::config::DebugLogger;
 use gadget_common::gadget::message::{GadgetProtocolMessage, UserID};
 use gadget_common::gadget::work_manager::WorkManager;
 use gadget_common::gadget::JobInitMetadata;
 use gadget_common::keystore::KeystoreBackend;
+use gadget_common::prelude::*;
 use gadget_common::prelude::{FullProtocolConfig, Network};
-use gadget_common::Block;
+use gadget_common::tangle_subxt::tangle_runtime::api::runtime_types::bounded_collections::bounded_vec::BoundedVec;
 use gadget_core::job::{BuiltExecutableJobWrapper, JobBuilder, JobError};
 use gadget_core::job_manager::{ProtocolWorkManager, WorkManagerInterface};
 use rand::{CryptoRng, RngCore, SeedableRng};
-
-use sc_client_api::Backend;
-
-use crate::protocols::{DefaultCryptoHasher, DefaultSecurityLevel};
-use dfns_cggmp21::signing::SigningBuilder;
-use digest::typenum::U32;
-use digest::Digest;
-use sp_api::ProvideRuntimeApi;
 use sp_core::{ecdsa, keccak_256, Pair};
 use std::collections::HashMap;
 use std::sync::Arc;
-use tangle_primitives::jobs::{
-    DKGTSSSignatureResult, DigitalSignatureScheme, JobId, JobResult, JobType,
-};
-use tangle_primitives::roles::{RoleType, ThresholdSignatureRoleType};
 use tokio::sync::mpsc::UnboundedReceiver;
 
 use super::keygen::create_party;
 
-pub async fn create_next_job<
-    B: Block,
-    BE: Backend<B> + 'static,
-    KBE: KeystoreBackend,
-    C: ClientWithApi<B, BE>,
-    N: Network,
->(
-    config: &crate::DfnsSigningProtocol<B, BE, C, N, KBE>,
-    job: JobInitMetadata<B>,
+pub async fn create_next_job<KBE: KeystoreBackend, C: ClientWithApi, N: Network>(
+    config: &crate::DfnsSigningProtocol<C, N, KBE>,
+    job: JobInitMetadata,
     _work_manager: &ProtocolWorkManager<WorkManager>,
-) -> Result<DfnsCGGMP21SigningExtraParams, gadget_common::Error>
-where
-    <C as ProvideRuntimeApi<B>>::Api: JobsApiForGadget<B>,
-{
+) -> Result<DfnsCGGMP21SigningExtraParams, gadget_common::Error> {
     let job_id = job.job_id;
 
-    let JobType::DKGTSSPhaseTwo(p2_job) = job.job_type else {
+    let jobs::JobType::DKGTSSPhaseTwo(p2_job) = job.job_type else {
         panic!("Should be valid type")
     };
-    let input_data_to_sign = p2_job.submission.to_vec();
+    let input_data_to_sign = p2_job.submission.0.to_vec();
     let previous_job_id = p2_job.phase_one_id;
 
     let phase1_job = job.phase1_job.expect("Should exist for a phase 2 job");
@@ -101,8 +84,8 @@ pub struct DfnsCGGMP21SigningExtraParams {
     i: u16,
     t: u16,
     signers: Vec<u16>,
-    job_id: JobId,
-    role_type: RoleType,
+    job_id: u64,
+    role_type: roles::RoleType,
     serialized_key_share: Vec<u8>,
     input_data_to_sign: Vec<u8>,
     user_id_to_account_id_mapping: Arc<HashMap<UserID, ecdsa::Public>>,
@@ -152,24 +135,15 @@ where
     Ok(ret.to_vec())
 }
 
-pub async fn generate_protocol_from<
-    B: Block,
-    BE: Backend<B> + 'static,
-    KBE: KeystoreBackend,
-    C: ClientWithApi<B, BE>,
-    N: Network,
->(
-    config: &crate::DfnsSigningProtocol<B, BE, C, N, KBE>,
+pub async fn generate_protocol_from<KBE: KeystoreBackend, C: ClientWithApi, N: Network>(
+    config: &crate::DfnsSigningProtocol<C, N, KBE>,
     associated_block_id: <WorkManager as WorkManagerInterface>::Clock,
     associated_retry_id: <WorkManager as WorkManagerInterface>::RetryID,
     associated_session_id: <WorkManager as WorkManagerInterface>::SessionID,
     associated_task_id: <WorkManager as WorkManagerInterface>::TaskID,
     protocol_message_channel: UnboundedReceiver<GadgetProtocolMessage>,
     additional_params: DfnsCGGMP21SigningExtraParams,
-) -> Result<BuiltExecutableJobWrapper, JobError>
-where
-    <C as ProvideRuntimeApi<B>>::Api: JobsApiForGadget<B>,
-{
+) -> Result<BuiltExecutableJobWrapper, JobError> {
     let debug_logger_post = config.logger.clone();
     let logger = debug_logger_post.clone();
     let protocol_output = Arc::new(tokio::sync::Mutex::new(None));
@@ -183,7 +157,7 @@ where
         additional_params.signers,
         additional_params.t,
         additional_params.serialized_key_share,
-        additional_params.role_type,
+        additional_params.role_type.clone(),
         additional_params.input_data_to_sign.clone(),
         additional_params.user_id_to_account_id_mapping.clone(),
     );
@@ -209,7 +183,9 @@ where
             let data_hash = keccak_256(&input_data_to_sign);
 
             let signature = match role_type {
-                RoleType::Tss(ThresholdSignatureRoleType::DfnsCGGMP21Secp256k1) => {
+                roles::RoleType::Tss(
+                    roles::tss::ThresholdSignatureRoleType::DfnsCGGMP21Secp256k1,
+                ) => {
                     let data_to_sign = DataToSign::from_scalar(dfns_cggmp21::generic_ec::Scalar::<
                         Secp256k1,
                     >::from_be_bytes_mod_order(
@@ -244,7 +220,9 @@ where
                     )
                     .await?
                 }
-                RoleType::Tss(ThresholdSignatureRoleType::DfnsCGGMP21Secp256r1) => {
+                roles::RoleType::Tss(
+                    roles::tss::ThresholdSignatureRoleType::DfnsCGGMP21Secp256r1,
+                ) => {
                     let data_to_sign = DataToSign::from_scalar(dfns_cggmp21::generic_ec::Scalar::<
                         Secp256r1,
                     >::from_be_bytes_mod_order(
@@ -279,7 +257,7 @@ where
                     )
                     .await?
                 }
-                RoleType::Tss(ThresholdSignatureRoleType::DfnsCGGMP21Stark) => {
+                roles::RoleType::Tss(roles::tss::ThresholdSignatureRoleType::DfnsCGGMP21Stark) => {
                     let data_to_sign = DataToSign::from_scalar(dfns_cggmp21::generic_ec::Scalar::<
                         Stark,
                     >::from_be_bytes_mod_order(
@@ -334,11 +312,12 @@ where
                     &public_key,
                 );
 
-                let job_result = JobResult::DKGPhaseTwo(DKGTSSSignatureResult {
-                    signature_scheme: DigitalSignatureScheme::Ecdsa,
-                    data: additional_params.input_data_to_sign.try_into().unwrap(),
-                    signature: signature.to_vec().try_into().unwrap(),
-                    verifying_key: public_key.try_into().unwrap(),
+                let job_result = jobs::JobResult::DKGPhaseTwo(jobs::tss::DKGTSSSignatureResult {
+                    signature_scheme: jobs::tss::DigitalSignatureScheme::Ecdsa,
+                    data: BoundedVec(additional_params.input_data_to_sign),
+                    signature: BoundedVec(signature.to_vec()),
+                    verifying_key: BoundedVec(public_key),
+                    __subxt_unused_type_params: Default::default(),
                 });
 
                 client
@@ -359,23 +338,23 @@ where
 }
 
 pub fn get_public_key_from_serialized_key_share_bytes<S: SecurityLevel>(
-    role_type: &RoleType,
+    role_type: &roles::RoleType,
     serialized_key_share: &[u8],
 ) -> Result<Vec<u8>, JobError> {
     match role_type {
-        RoleType::Tss(ThresholdSignatureRoleType::DfnsCGGMP21Secp256k1) => {
+        roles::RoleType::Tss(roles::tss::ThresholdSignatureRoleType::DfnsCGGMP21Secp256k1) => {
             get_local_key_share_from_serialized_local_key_bytes::<Secp256k1, S>(
                 serialized_key_share,
             )
             .map(|key_share| key_share.shared_public_key().to_bytes(true).to_vec())
         }
-        RoleType::Tss(ThresholdSignatureRoleType::DfnsCGGMP21Secp256r1) => {
+        roles::RoleType::Tss(roles::tss::ThresholdSignatureRoleType::DfnsCGGMP21Secp256r1) => {
             get_local_key_share_from_serialized_local_key_bytes::<Secp256r1, S>(
                 serialized_key_share,
             )
             .map(|key_share| key_share.shared_public_key().to_bytes(true).to_vec())
         }
-        RoleType::Tss(ThresholdSignatureRoleType::DfnsCGGMP21Stark) => {
+        roles::RoleType::Tss(roles::tss::ThresholdSignatureRoleType::DfnsCGGMP21Stark) => {
             get_local_key_share_from_serialized_local_key_bytes::<Stark, S>(serialized_key_share)
                 .map(|key_share| key_share.shared_public_key().to_bytes(true).to_vec())
         }
diff --git a/protocols/dfns-cggmp21/src/util.rs b/protocols/dfns-cggmp21/src/util.rs
deleted file mode 100644
index 8b1378917..000000000
--- a/protocols/dfns-cggmp21/src/util.rs
+++ /dev/null
@@ -1,1 +0,0 @@
-
diff --git a/protocols/stub/Cargo.toml b/protocols/stub/Cargo.toml
index fa4529c6c..e2b25fd06 100644
--- a/protocols/stub/Cargo.toml
+++ b/protocols/stub/Cargo.toml
@@ -9,6 +9,10 @@ async-trait = { workspace = true }
 futures = { workspace = true }
 tokio = { workspace = true }
 protocol-macros = { workspace = true }
-tangle-primitives = { workspace = true }
 parking_lot = { workspace = true }
+sp-core = { workspace = true }
+
+
+[dev-dependencies]
 test-utils = { workspace = true }
+tangle-primitives = { workspace = true }
diff --git a/protocols/stub/src/lib.rs b/protocols/stub/src/lib.rs
index 9b1f9c583..0f21ba078 100644
--- a/protocols/stub/src/lib.rs
+++ b/protocols/stub/src/lib.rs
@@ -1,41 +1,25 @@
 use gadget_common::full_protocol::SharedOptional;
 use gadget_common::prelude::*;
+use sp_core::sr25519;
 
 #[protocol]
-pub struct StubProtocol<
-    B: Block,
-    BE: Backend<B> + 'static,
-    C: ClientWithApi<B, BE>,
-    N: Network,
-    KBE: KeystoreBackend,
-> where
-    <C as ProvideRuntimeApi<B>>::Api: JobsApiForGadget<B>,
-{
+pub struct StubProtocol<C: ClientWithApi, N: Network, KBE: KeystoreBackend> {
     pallet_tx: Arc<dyn PalletSubmitter>,
     logger: DebugLogger,
     client: C,
     network: N,
-    account_id: AccountId,
+    account_id: sr25519::Public,
     key_store: ECDSAKeyStore<KBE>,
     prometheus_config: PrometheusConfig,
-    jobs_client: Arc<Mutex<Option<JobsClient<B, BE, C>>>>,
+    jobs_client: Arc<Mutex<Option<JobsClient<C>>>>,
 }
 
 #[async_trait]
-impl<
-        B: Block,
-        BE: Backend<B> + 'static,
-        C: ClientWithApi<B, BE>,
-        N: Network,
-        KBE: KeystoreBackend,
-    > FullProtocolConfig for StubProtocol<B, BE, C, N, KBE>
-where
-    <C as ProvideRuntimeApi<B>>::Api: JobsApiForGadget<B>,
+impl<C: ClientWithApi + 'static, N: Network, KBE: KeystoreBackend> FullProtocolConfig
+    for StubProtocol<C, N, KBE>
 {
     type AsyncProtocolParameters = ();
     type Client = C;
-    type Block = B;
-    type Backend = BE;
     type Network = N;
     type AdditionalNodeParameters = ();
     type KeystoreBackend = KBE;
@@ -45,7 +29,7 @@ where
         pallet_tx: Arc<dyn PalletSubmitter>,
         network: Self::Network,
         logger: DebugLogger,
-        account_id: AccountId,
+        account_id: sr25519::Public,
         key_store: ECDSAKeyStore<Self::KeystoreBackend>,
         prometheus_config: PrometheusConfig,
     ) -> Result<Self, Error> {
@@ -79,13 +63,13 @@ where
 
     async fn create_next_job(
         &self,
-        _job: JobInitMetadata<Self::Block>,
+        _job: JobInitMetadata,
         _work_manager: &ProtocolWorkManager<WorkManager>,
     ) -> Result<Self::AsyncProtocolParameters, Error> {
         Ok(())
     }
 
-    fn account_id(&self) -> &AccountId {
+    fn account_id(&self) -> &sr25519::Public {
         &self.account_id
     }
 
@@ -93,15 +77,18 @@ where
         "STUB-PROTOCOL".to_string()
     }
 
-    fn role_filter(&self, _role: RoleType) -> bool {
+    fn role_filter(&self, _role: roles::RoleType) -> bool {
         false
     }
 
-    fn phase_filter(&self, _job: GadgetJobType) -> bool {
+    fn phase_filter(
+        &self,
+        _job: jobs::JobType<AccountId32, jobs::MaxParticipants, jobs::MaxSubmissionLen>,
+    ) -> bool {
         false
     }
 
-    fn jobs_client(&self) -> &SharedOptional<JobsClient<Self::Block, Self::Backend, Self::Client>> {
+    fn jobs_client(&self) -> &SharedOptional<JobsClient<Self::Client>> {
         &self.jobs_client
     }
 
diff --git a/protocols/zcash-frost/Cargo.toml b/protocols/zcash-frost/Cargo.toml
index b2bd6e772..07b699e83 100644
--- a/protocols/zcash-frost/Cargo.toml
+++ b/protocols/zcash-frost/Cargo.toml
@@ -32,19 +32,9 @@ frost-ristretto255 = { workspace = true }
 frost-secp256k1 = { workspace = true }
 frost-rerandomized = { workspace = true }
 
-pallet-jobs-rpc-runtime-api = { workspace = true, features = ["std"] }
-pallet-jobs = { workspace = true, features = ["std"] }
-pallet-dkg = { workspace = true, features = ["std"] }
-tangle-primitives = { workspace = true, features = ["std"] }
-
 sp-core = { workspace = true, features = ["std"] }
 sp-io = { workspace = true, features = ["std"] }
 sp-api = { workspace = true, features = ["std"] }
-sp-runtime = { workspace = true, features = ["std"] }
-sp-application-crypto = { workspace = true, features = ["std"] }
-
-sc-client-api = { workspace = true }
-
 frame-support = { workspace = true  }
 parity-scale-codec = { workspace = true }
 
@@ -52,4 +42,9 @@ serde = { version = "1.0.193", features = ["derive"] }
 rand = { workspace = true }
 hex = { workspace = true }
 parking_lot = { workspace = true }
+
+
+[dev-dependencies]
 test-utils = { workspace = true }
+tangle-primitives = { workspace = true }
+
diff --git a/protocols/zcash-frost/src/lib.rs b/protocols/zcash-frost/src/lib.rs
index b57d61a04..2e371456c 100644
--- a/protocols/zcash-frost/src/lib.rs
+++ b/protocols/zcash-frost/src/lib.rs
@@ -16,13 +16,13 @@ generate_protocol!(
     ZcashFrostKeygenExtraParams,
     crate::protocol::keygen::generate_protocol_from,
     crate::protocol::keygen::create_next_job,
-    GadgetJobType::DKGTSSPhaseOne(_),
-    RoleType::Tss(ThresholdSignatureRoleType::ZcashFrostEd25519)
-        | RoleType::Tss(ThresholdSignatureRoleType::ZcashFrostEd448)
-        | RoleType::Tss(ThresholdSignatureRoleType::ZcashFrostP256)
-        | RoleType::Tss(ThresholdSignatureRoleType::ZcashFrostP384)
-        | RoleType::Tss(ThresholdSignatureRoleType::ZcashFrostSecp256k1)
-        | RoleType::Tss(ThresholdSignatureRoleType::ZcashFrostRistretto255)
+    jobs::JobType::DKGTSSPhaseOne(_),
+    roles::RoleType::Tss(roles::tss::ThresholdSignatureRoleType::ZcashFrostEd25519)
+        | roles::RoleType::Tss(roles::tss::ThresholdSignatureRoleType::ZcashFrostEd448)
+        | roles::RoleType::Tss(roles::tss::ThresholdSignatureRoleType::ZcashFrostP256)
+        | roles::RoleType::Tss(roles::tss::ThresholdSignatureRoleType::ZcashFrostP384)
+        | roles::RoleType::Tss(roles::tss::ThresholdSignatureRoleType::ZcashFrostSecp256k1)
+        | roles::RoleType::Tss(roles::tss::ThresholdSignatureRoleType::ZcashFrostRistretto255)
 );
 generate_protocol!(
     "Zcash-FROST-Signing-Protocol",
@@ -30,17 +30,18 @@ generate_protocol!(
     ZcashFrostSigningExtraParams,
     crate::protocol::sign::generate_protocol_from,
     crate::protocol::sign::create_next_job,
-    GadgetJobType::DKGTSSPhaseTwo(_),
-    RoleType::Tss(ThresholdSignatureRoleType::ZcashFrostEd25519)
-        | RoleType::Tss(ThresholdSignatureRoleType::ZcashFrostEd448)
-        | RoleType::Tss(ThresholdSignatureRoleType::ZcashFrostP256)
-        | RoleType::Tss(ThresholdSignatureRoleType::ZcashFrostP384)
-        | RoleType::Tss(ThresholdSignatureRoleType::ZcashFrostSecp256k1)
-        | RoleType::Tss(ThresholdSignatureRoleType::ZcashFrostRistretto255)
+    jobs::JobType::DKGTSSPhaseTwo(_),
+    roles::RoleType::Tss(roles::tss::ThresholdSignatureRoleType::ZcashFrostEd25519)
+        | roles::RoleType::Tss(roles::tss::ThresholdSignatureRoleType::ZcashFrostEd448)
+        | roles::RoleType::Tss(roles::tss::ThresholdSignatureRoleType::ZcashFrostP256)
+        | roles::RoleType::Tss(roles::tss::ThresholdSignatureRoleType::ZcashFrostP384)
+        | roles::RoleType::Tss(roles::tss::ThresholdSignatureRoleType::ZcashFrostSecp256k1)
+        | roles::RoleType::Tss(roles::tss::ThresholdSignatureRoleType::ZcashFrostRistretto255)
 );
 
 generate_setup_and_run_command!(ZcashFrostKeygenProtocol, ZcashFrostSigningProtocol);
 
+#[cfg(test)]
 mod secp256k1 {
     test_utils::generate_signing_and_keygen_tss_tests!(
         2,
@@ -50,6 +51,7 @@ mod secp256k1 {
     );
 }
 
+#[cfg(test)]
 mod ristretto255 {
     test_utils::generate_signing_and_keygen_tss_tests!(
         2,
@@ -59,6 +61,7 @@ mod ristretto255 {
     );
 }
 
+#[cfg(test)]
 mod p256 {
     test_utils::generate_signing_and_keygen_tss_tests!(
         2,
@@ -68,6 +71,7 @@ mod p256 {
     );
 }
 
+#[cfg(test)]
 mod p384 {
     test_utils::generate_signing_and_keygen_tss_tests!(
         2,
@@ -77,6 +81,7 @@ mod p384 {
     );
 }
 
+#[cfg(test)]
 mod ed25519 {
     test_utils::generate_signing_and_keygen_tss_tests!(
         2,
@@ -86,6 +91,7 @@ mod ed25519 {
     );
 }
 
+#[cfg(test)]
 mod ed448 {
     test_utils::generate_signing_and_keygen_tss_tests!(
         2,
diff --git a/protocols/zcash-frost/src/protocol/keygen.rs b/protocols/zcash-frost/src/protocol/keygen.rs
index 48c4985ba..561072e24 100644
--- a/protocols/zcash-frost/src/protocol/keygen.rs
+++ b/protocols/zcash-frost/src/protocol/keygen.rs
@@ -5,31 +5,24 @@ use frost_p384::P384Sha384;
 use frost_ristretto255::Ristretto255Sha512;
 use frost_secp256k1::Secp256K1Sha256;
 use futures::StreamExt;
-use gadget_common::client::JobsApiForGadget;
-use gadget_common::client::{
-    ClientWithApi, GadgetJobResult, MaxKeyLen, MaxParticipants, MaxSignatureLen,
-};
-use gadget_common::config::{Network, ProvideRuntimeApi};
+use gadget_common::client::ClientWithApi;
+use gadget_common::config::Network;
 use gadget_common::debug_logger::DebugLogger;
 use gadget_common::gadget::message::{GadgetProtocolMessage, UserID};
 use gadget_common::gadget::work_manager::WorkManager;
 use gadget_common::gadget::JobInitMetadata;
 use gadget_common::keystore::{ECDSAKeyStore, KeystoreBackend};
-use gadget_common::{channels, Block};
+use gadget_common::prelude::*;
+use gadget_common::tangle_subxt::tangle_runtime::api::runtime_types::bounded_collections::bounded_vec::BoundedVec;
+use gadget_common::{channels, utils};
 use gadget_core::job::{BuiltExecutableJobWrapper, JobBuilder, JobError};
 use gadget_core::job_manager::{ProtocolWorkManager, WorkManagerInterface};
 use itertools::Itertools;
-use pallet_dkg::signatures_schemes::ecdsa::verify_signer_from_set_ecdsa;
-use pallet_dkg::signatures_schemes::to_slice_33;
 use rand::SeedableRng;
 use round_based_21::{Incoming, Outgoing};
-use sc_client_api::Backend;
-use sp_application_crypto::sp_core::keccak_256;
-use sp_core::{ecdsa, Pair};
+use sp_core::{ecdsa, keccak_256, Pair};
 use std::collections::{BTreeMap, HashMap};
 use std::sync::Arc;
-use tangle_primitives::jobs::{DKGTSSKeySubmissionResult, DigitalSignatureScheme, JobId, JobType};
-use tangle_primitives::roles::{RoleType, ThresholdSignatureRoleType};
 use tokio::sync::mpsc::UnboundedReceiver;
 
 use crate::rounds;
@@ -41,30 +34,21 @@ pub struct ZcashFrostKeygenExtraParams {
     pub i: u16,
     pub t: u16,
     pub n: u16,
-    pub job_id: JobId,
-    pub role_type: RoleType,
+    pub job_id: u64,
+    pub role_type: roles::RoleType,
     pub user_id_to_account_id_mapping: Arc<HashMap<UserID, ecdsa::Public>>,
 }
 
-pub async fn create_next_job<
-    B: Block,
-    BE: Backend<B>,
-    C: ClientWithApi<B, BE>,
-    N: Network,
-    KBE: KeystoreBackend,
->(
-    config: &crate::ZcashFrostKeygenProtocol<B, BE, C, N, KBE>,
-    job: JobInitMetadata<B>,
+pub async fn create_next_job<C: ClientWithApi, N: Network, KBE: KeystoreBackend>(
+    config: &crate::ZcashFrostKeygenProtocol<C, N, KBE>,
+    job: JobInitMetadata,
     _work_manager: &ProtocolWorkManager<WorkManager>,
-) -> Result<ZcashFrostKeygenExtraParams, gadget_common::Error>
-where
-    <C as ProvideRuntimeApi<B>>::Api: JobsApiForGadget<B>,
-{
+) -> Result<ZcashFrostKeygenExtraParams, gadget_common::Error> {
     let job_id = job.job_id;
     let role_type = job.job_type.get_role_type();
 
     // We can safely make this assumption because we are only creating jobs for phase one
-    let JobType::DKGTSSPhaseOne(p1_job) = job.job_type else {
+    let jobs::JobType::DKGTSSPhaseOne(p1_job) = job.job_type else {
         panic!("Should be valid type")
     };
 
@@ -116,24 +100,15 @@ macro_rules! run_threshold_keygen {
     };
 }
 
-pub async fn generate_protocol_from<
-    B: Block,
-    BE: Backend<B>,
-    C: ClientWithApi<B, BE>,
-    N: Network,
-    KBE: KeystoreBackend,
->(
-    config: &crate::ZcashFrostKeygenProtocol<B, BE, C, N, KBE>,
+pub async fn generate_protocol_from<C: ClientWithApi, N: Network, KBE: KeystoreBackend>(
+    config: &crate::ZcashFrostKeygenProtocol<C, N, KBE>,
     associated_block_id: <WorkManager as WorkManagerInterface>::Clock,
     associated_retry_id: <WorkManager as WorkManagerInterface>::RetryID,
     associated_session_id: <WorkManager as WorkManagerInterface>::SessionID,
     associated_task_id: <WorkManager as WorkManagerInterface>::TaskID,
     protocol_message_channel: UnboundedReceiver<GadgetProtocolMessage>,
     additional_params: ZcashFrostKeygenExtraParams,
-) -> Result<BuiltExecutableJobWrapper, JobError>
-where
-    <C as ProvideRuntimeApi<B>>::Api: JobsApiForGadget<B>,
-{
+) -> Result<BuiltExecutableJobWrapper, JobError> {
     let key_store = config.key_store.clone();
     let key_store2 = config.key_store.clone();
     let protocol_output = Arc::new(tokio::sync::Mutex::new(None));
@@ -148,11 +123,11 @@ where
         additional_params.t,
         additional_params.n,
         additional_params.user_id_to_account_id_mapping,
-        additional_params.role_type,
+        additional_params.role_type.clone(),
     );
 
     let role = match role_type {
-        RoleType::Tss(role) => role,
+        roles::RoleType::Tss(role) => role,
         _ => {
             return Err(JobError {
                 reason: "Invalid role type".to_string(),
@@ -192,56 +167,74 @@ where
             let delivery = (keygen_rx_async_proto, keygen_tx_to_outbound);
             let party = round_based_21::MpcParty::connected(delivery);
             let frost_key_share_package = match role {
-                ThresholdSignatureRoleType::ZcashFrostEd25519 => {
+                roles::tss::ThresholdSignatureRoleType::ZcashFrostEd25519 => {
                     run_threshold_keygen!(
                         Ed25519Sha512,
                         &mut tracer,
                         i,
                         t,
                         n,
-                        role,
+                        role.clone(),
                         &mut rng,
                         party
                     )
                 }
-                ThresholdSignatureRoleType::ZcashFrostEd448 => {
+                roles::tss::ThresholdSignatureRoleType::ZcashFrostEd448 => {
                     run_threshold_keygen!(
                         Ed448Shake256,
                         &mut tracer,
                         i,
                         t,
                         n,
-                        role,
+                        role.clone(),
                         &mut rng,
                         party
                     )
                 }
-                ThresholdSignatureRoleType::ZcashFrostP256 => {
-                    run_threshold_keygen!(P256Sha256, &mut tracer, i, t, n, role, &mut rng, party)
+                roles::tss::ThresholdSignatureRoleType::ZcashFrostP256 => {
+                    run_threshold_keygen!(
+                        P256Sha256,
+                        &mut tracer,
+                        i,
+                        t,
+                        n,
+                        role.clone(),
+                        &mut rng,
+                        party
+                    )
                 }
-                ThresholdSignatureRoleType::ZcashFrostP384 => {
-                    run_threshold_keygen!(P384Sha384, &mut tracer, i, t, n, role, &mut rng, party)
+                roles::tss::ThresholdSignatureRoleType::ZcashFrostP384 => {
+                    run_threshold_keygen!(
+                        P384Sha384,
+                        &mut tracer,
+                        i,
+                        t,
+                        n,
+                        role.clone(),
+                        &mut rng,
+                        party
+                    )
                 }
-                ThresholdSignatureRoleType::ZcashFrostRistretto255 => {
+                roles::tss::ThresholdSignatureRoleType::ZcashFrostRistretto255 => {
                     run_threshold_keygen!(
                         Ristretto255Sha512,
                         &mut tracer,
                         i,
                         t,
                         n,
-                        role,
+                        role.clone(),
                         &mut rng,
                         party
                     )
                 }
-                ThresholdSignatureRoleType::ZcashFrostSecp256k1 => {
+                roles::tss::ThresholdSignatureRoleType::ZcashFrostSecp256k1 => {
                     run_threshold_keygen!(
                         Secp256K1Sha256,
                         &mut tracer,
                         i,
                         t,
                         n,
-                        role,
+                        role.clone(),
                         &mut rng,
                         party
                     )
@@ -258,7 +251,7 @@ where
                 key_store2,
                 &logger,
                 &frost_key_share_package.verifying_key,
-                role,
+                role.clone(),
                 t,
                 i,
                 broadcast_tx_to_outbound,
@@ -302,12 +295,21 @@ async fn handle_public_key_gossip<KBE: KeystoreBackend>(
     key_store: ECDSAKeyStore<KBE>,
     logger: &DebugLogger,
     public_key_package: &[u8],
-    role: ThresholdSignatureRoleType,
+    role: roles::tss::ThresholdSignatureRoleType,
     t: u16,
     i: u16,
     broadcast_tx_to_outbound: futures::channel::mpsc::UnboundedSender<PublicKeyGossipMessage>,
     mut broadcast_rx_from_gadget: futures::channel::mpsc::UnboundedReceiver<PublicKeyGossipMessage>,
-) -> Result<GadgetJobResult, JobError> {
+) -> Result<
+    jobs::JobResult<
+        jobs::MaxParticipants,
+        jobs::MaxKeyLen,
+        jobs::MaxSignatureLen,
+        jobs::MaxDataLen,
+        jobs::MaxProofLen,
+    >,
+    JobError,
+> {
     let key_hashed = keccak_256(public_key_package);
     let signature = key_store.pair().sign_prehashed(&key_hashed).0.to_vec();
     let my_id = key_store.pair().public();
@@ -373,16 +375,16 @@ async fn handle_public_key_gossip<KBE: KeystoreBackend>(
     let signatures = received_keys
         .into_iter()
         .sorted_by_key(|x| x.0)
-        .map(|r| r.1.try_into().unwrap())
+        .map(|(_, p)| BoundedVec(p))
         .collect::<Vec<_>>();
 
-    let participants = received_participants
-        .into_iter()
-        .sorted_by_key(|x| x.0)
-        .map(|r| r.1 .0.to_vec().try_into().unwrap())
-        .collect::<Vec<_>>()
-        .try_into()
-        .unwrap();
+    let participants = BoundedVec(
+        received_participants
+            .into_iter()
+            .sorted_by_key(|x| x.0)
+            .map(|(_, p)| BoundedVec(p.0.to_vec()))
+            .collect::<Vec<_>>(),
+    );
 
     if signatures.len() < t as usize {
         return Err(JobError {
@@ -394,44 +396,58 @@ async fn handle_public_key_gossip<KBE: KeystoreBackend>(
         });
     }
 
-    let res = DKGTSSKeySubmissionResult {
+    let res = jobs::tss::DKGTSSKeySubmissionResult {
         signature_scheme: match role {
-            ThresholdSignatureRoleType::ZcashFrostEd25519 => DigitalSignatureScheme::SchnorrEd25519,
-            ThresholdSignatureRoleType::ZcashFrostEd448 => DigitalSignatureScheme::SchnorrEd448,
-            ThresholdSignatureRoleType::ZcashFrostP256 => DigitalSignatureScheme::SchnorrP256,
-            ThresholdSignatureRoleType::ZcashFrostP384 => DigitalSignatureScheme::SchnorrP384,
-            ThresholdSignatureRoleType::ZcashFrostRistretto255 => {
-                DigitalSignatureScheme::SchnorrRistretto255
+            roles::tss::ThresholdSignatureRoleType::ZcashFrostEd25519 => {
+                jobs::tss::DigitalSignatureScheme::SchnorrEd25519
+            }
+            roles::tss::ThresholdSignatureRoleType::ZcashFrostEd448 => {
+                jobs::tss::DigitalSignatureScheme::SchnorrEd448
+            }
+            roles::tss::ThresholdSignatureRoleType::ZcashFrostP256 => {
+                jobs::tss::DigitalSignatureScheme::SchnorrP256
+            }
+            roles::tss::ThresholdSignatureRoleType::ZcashFrostP384 => {
+                jobs::tss::DigitalSignatureScheme::SchnorrP384
+            }
+            roles::tss::ThresholdSignatureRoleType::ZcashFrostRistretto255 => {
+                jobs::tss::DigitalSignatureScheme::SchnorrRistretto255
             }
-            ThresholdSignatureRoleType::ZcashFrostSecp256k1 => {
-                DigitalSignatureScheme::SchnorrSecp256k1
+            roles::tss::ThresholdSignatureRoleType::ZcashFrostSecp256k1 => {
+                jobs::tss::DigitalSignatureScheme::SchnorrSecp256k1
             }
             _ => unreachable!("Invalid role"),
         },
-        key: public_key_package.to_vec().try_into().unwrap(),
+        key: BoundedVec(public_key_package.to_vec()),
         participants,
-        signatures: signatures.try_into().unwrap(),
+        signatures: BoundedVec(signatures),
         threshold: t as _,
+        __subxt_unused_type_params: Default::default(),
     };
     verify_generated_dkg_key_ecdsa(res.clone(), logger);
-    Ok(GadgetJobResult::DKGPhaseOne(res))
+    Ok(jobs::JobResult::DKGPhaseOne(res))
 }
 
 fn verify_generated_dkg_key_ecdsa(
-    data: DKGTSSKeySubmissionResult<MaxKeyLen, MaxParticipants, MaxSignatureLen>,
+    data: jobs::tss::DKGTSSKeySubmissionResult<
+        jobs::MaxKeyLen,
+        jobs::MaxParticipants,
+        jobs::MaxSignatureLen,
+    >,
     logger: &DebugLogger,
 ) {
     // Ensure participants and signatures are not empty
-    assert!(!data.participants.is_empty(), "NoParticipantsFound",);
-    assert!(!data.signatures.is_empty(), "NoSignaturesFound");
+    assert!(!data.participants.0.is_empty(), "NoParticipantsFound",);
+    assert!(!data.signatures.0.is_empty(), "NoSignaturesFound");
 
     // Generate the required ECDSA signers
     let maybe_signers = data
         .participants
+        .0
         .iter()
         .map(|x| {
             ecdsa::Public(
-                to_slice_33(x)
+                utils::to_slice_33(&x.0)
                     .unwrap_or_else(|| panic!("Failed to convert input to ecdsa public key")),
             )
         })
@@ -441,10 +457,10 @@ fn verify_generated_dkg_key_ecdsa(
 
     let mut known_signers: Vec<ecdsa::Public> = Default::default();
 
-    for signature in data.signatures {
+    for signature in data.signatures.0 {
         // Ensure the required signer signature exists
         let (maybe_authority, success) =
-            verify_signer_from_set_ecdsa(maybe_signers.clone(), &data.key, &signature);
+            utils::verify_signer_from_set_ecdsa(maybe_signers.clone(), &data.key.0, &signature.0);
 
         if success {
             let authority = maybe_authority.expect("CannotRetreiveSigner");
diff --git a/protocols/zcash-frost/src/protocol/sign.rs b/protocols/zcash-frost/src/protocol/sign.rs
index 8ffea0b8d..bd46d7562 100644
--- a/protocols/zcash-frost/src/protocol/sign.rs
+++ b/protocols/zcash-frost/src/protocol/sign.rs
@@ -1,4 +1,3 @@
-use frame_support::BoundedVec;
 use frost_core::keys::{KeyPackage, PublicKeyPackage};
 use frost_ed25519::Ed25519Sha512;
 use frost_ed448::Ed448Shake256;
@@ -6,26 +5,22 @@ use frost_p256::P256Sha256;
 use frost_p384::P384Sha384;
 use frost_ristretto255::Ristretto255Sha512;
 use frost_secp256k1::Secp256K1Sha256;
-use gadget_common::client::JobsApiForGadget;
-use gadget_common::client::{ClientWithApi, GadgetJobResult};
-use gadget_common::config::{Network, ProvideRuntimeApi};
-
+use gadget_common::channels;
+use gadget_common::client::ClientWithApi;
+use gadget_common::config::Network;
 use gadget_common::gadget::message::{GadgetProtocolMessage, UserID};
 use gadget_common::gadget::work_manager::WorkManager;
 use gadget_common::gadget::JobInitMetadata;
 use gadget_common::keystore::KeystoreBackend;
-
-use gadget_common::{channels, Block};
+use gadget_common::prelude::*;
+use gadget_common::tangle_subxt::tangle_runtime::api::runtime_types::bounded_collections::bounded_vec::BoundedVec;
 use gadget_core::job::{BuiltExecutableJobWrapper, JobBuilder, JobError};
 use gadget_core::job_manager::{ProtocolWorkManager, WorkManagerInterface};
 use rand::SeedableRng;
 use round_based_21::{Incoming, MpcParty, Outgoing};
-use sc_client_api::Backend;
 use sp_core::{ecdsa, keccak_256, Pair};
 use std::collections::HashMap;
 use std::sync::Arc;
-use tangle_primitives::jobs::{DKGTSSSignatureResult, DigitalSignatureScheme, JobId, JobType};
-use tangle_primitives::roles::{RoleType, ThresholdSignatureRoleType};
 use tokio::sync::mpsc::UnboundedReceiver;
 
 use crate::rounds;
@@ -37,33 +32,24 @@ pub struct ZcashFrostSigningExtraParams {
     pub i: u16,
     pub t: u16,
     pub signers: Vec<u16>,
-    pub job_id: JobId,
-    pub role_type: RoleType,
+    pub job_id: u64,
+    pub role_type: roles::RoleType,
     pub keyshare: FrostKeyShare,
     pub input_data_to_sign: Vec<u8>,
     pub user_id_to_account_id_mapping: Arc<HashMap<UserID, ecdsa::Public>>,
 }
 
-pub async fn create_next_job<
-    B: Block,
-    BE: Backend<B>,
-    C: ClientWithApi<B, BE>,
-    N: Network,
-    KBE: KeystoreBackend,
->(
-    config: &crate::ZcashFrostSigningProtocol<B, BE, C, N, KBE>,
-    job: JobInitMetadata<B>,
+pub async fn create_next_job<C: ClientWithApi, N: Network, KBE: KeystoreBackend>(
+    config: &crate::ZcashFrostSigningProtocol<C, N, KBE>,
+    job: JobInitMetadata,
     _work_manager: &ProtocolWorkManager<WorkManager>,
-) -> Result<ZcashFrostSigningExtraParams, gadget_common::Error>
-where
-    <C as ProvideRuntimeApi<B>>::Api: JobsApiForGadget<B>,
-{
+) -> Result<ZcashFrostSigningExtraParams, gadget_common::Error> {
     let job_id = job.job_id;
 
-    let JobType::DKGTSSPhaseTwo(p2_job) = job.job_type else {
+    let jobs::JobType::DKGTSSPhaseTwo(p2_job) = job.job_type else {
         panic!("Should be valid type")
     };
-    let input_data_to_sign = p2_job.submission.into();
+    let input_data_to_sign = p2_job.submission.0;
     let previous_job_id = p2_job.phase_one_id;
 
     let phase1_job = job.phase1_job.expect("Should exist for a phase 2 job");
@@ -134,24 +120,15 @@ macro_rules! deserialize_and_run_threshold_sign {
     }};
 }
 
-pub async fn generate_protocol_from<
-    B: Block,
-    BE: Backend<B>,
-    C: ClientWithApi<B, BE>,
-    N: Network,
-    KBE: KeystoreBackend,
->(
-    config: &crate::ZcashFrostSigningProtocol<B, BE, C, N, KBE>,
+pub async fn generate_protocol_from<C: ClientWithApi, N: Network, KBE: KeystoreBackend>(
+    config: &crate::ZcashFrostSigningProtocol<C, N, KBE>,
     associated_block_id: <WorkManager as WorkManagerInterface>::Clock,
     associated_retry_id: <WorkManager as WorkManagerInterface>::RetryID,
     associated_session_id: <WorkManager as WorkManagerInterface>::SessionID,
     associated_task_id: <WorkManager as WorkManagerInterface>::TaskID,
     protocol_message_channel: UnboundedReceiver<GadgetProtocolMessage>,
     additional_params: ZcashFrostSigningExtraParams,
-) -> Result<BuiltExecutableJobWrapper, JobError>
-where
-    <C as ProvideRuntimeApi<B>>::Api: JobsApiForGadget<B>,
-{
+) -> Result<BuiltExecutableJobWrapper, JobError> {
     let debug_logger_post = config.logger.clone();
     let logger = debug_logger_post.clone();
     let protocol_output = Arc::new(tokio::sync::Mutex::new(None));
@@ -165,13 +142,13 @@ where
         additional_params.signers,
         additional_params.t,
         additional_params.keyshare,
-        additional_params.role_type,
+        additional_params.role_type.clone(),
         additional_params.input_data_to_sign.clone(),
         additional_params.user_id_to_account_id_mapping.clone(),
     );
 
     let role = match role_type {
-        RoleType::Tss(role) => role,
+        roles::RoleType::Tss(role) => role.clone(),
         _ => {
             return Err(JobError {
                 reason: "Invalid role type".to_string(),
@@ -179,6 +156,8 @@ where
         }
     };
 
+    let role2 = role.clone();
+
     Ok(JobBuilder::new()
         .protocol(async move {
             let mut rng = rand::rngs::StdRng::from_entropy();
@@ -212,7 +191,7 @@ where
             let delivery = (signing_rx_async_proto, signing_tx_to_outbound);
             let party = MpcParty::connected(delivery);
             let signature = match role {
-                ThresholdSignatureRoleType::ZcashFrostSecp256k1 => {
+                roles::tss::ThresholdSignatureRoleType::ZcashFrostSecp256k1 => {
                     deserialize_and_run_threshold_sign!(
                         Secp256K1Sha256,
                         keyshare,
@@ -220,12 +199,12 @@ where
                         i,
                         signers,
                         &input_data_to_sign,
-                        role,
+                        role.clone(),
                         &mut rng,
                         party
                     )
                 }
-                ThresholdSignatureRoleType::ZcashFrostEd25519 => {
+                roles::tss::ThresholdSignatureRoleType::ZcashFrostEd25519 => {
                     deserialize_and_run_threshold_sign!(
                         Ed25519Sha512,
                         keyshare,
@@ -233,12 +212,12 @@ where
                         i,
                         signers,
                         &input_data_to_sign,
-                        role,
+                        role.clone(),
                         &mut rng,
                         party
                     )
                 }
-                ThresholdSignatureRoleType::ZcashFrostEd448 => {
+                roles::tss::ThresholdSignatureRoleType::ZcashFrostEd448 => {
                     deserialize_and_run_threshold_sign!(
                         Ed448Shake256,
                         keyshare,
@@ -246,12 +225,12 @@ where
                         i,
                         signers,
                         &input_data_to_sign,
-                        role,
+                        role.clone(),
                         &mut rng,
                         party
                     )
                 }
-                ThresholdSignatureRoleType::ZcashFrostP256 => {
+                roles::tss::ThresholdSignatureRoleType::ZcashFrostP256 => {
                     deserialize_and_run_threshold_sign!(
                         P256Sha256,
                         keyshare,
@@ -259,12 +238,12 @@ where
                         i,
                         signers,
                         &input_data_to_sign,
-                        role,
+                        role.clone(),
                         &mut rng,
                         party
                     )
                 }
-                ThresholdSignatureRoleType::ZcashFrostP384 => {
+                roles::tss::ThresholdSignatureRoleType::ZcashFrostP384 => {
                     deserialize_and_run_threshold_sign!(
                         P384Sha384,
                         keyshare,
@@ -272,12 +251,12 @@ where
                         i,
                         signers,
                         &input_data_to_sign,
-                        role,
+                        role.clone(),
                         &mut rng,
                         party
                     )
                 }
-                ThresholdSignatureRoleType::ZcashFrostRistretto255 => {
+                roles::tss::ThresholdSignatureRoleType::ZcashFrostRistretto255 => {
                     deserialize_and_run_threshold_sign!(
                         Ristretto255Sha512,
                         keyshare,
@@ -285,7 +264,7 @@ where
                         i,
                         signers,
                         &input_data_to_sign,
-                        role,
+                        role.clone(),
                         &mut rng,
                         party
                     )
@@ -309,53 +288,53 @@ where
             if let Some(signature) = protocol_output_clone.lock().await.take() {
                 // Compute the signature bytes by first converting the signature
                 // to a fixed byte array and then converting that to a Vec<u8>.
-                let (signature, signature_scheme) = match role {
-                    ThresholdSignatureRoleType::ZcashFrostSecp256k1 => {
+                let (signature, signature_scheme) = match role2 {
+                    roles::tss::ThresholdSignatureRoleType::ZcashFrostSecp256k1 => {
                         let mut signature_bytes = [0u8; 65];
                         signature_bytes.copy_from_slice(&signature.group_signature);
                         (
-                            signature_bytes.to_vec().try_into().unwrap(),
-                            DigitalSignatureScheme::SchnorrSecp256k1,
+                            signature_bytes.to_vec(),
+                            jobs::tss::DigitalSignatureScheme::SchnorrSecp256k1,
                         )
                     }
-                    ThresholdSignatureRoleType::ZcashFrostEd25519 => {
+                    roles::tss::ThresholdSignatureRoleType::ZcashFrostEd25519 => {
                         let mut signature_bytes = [0u8; 64];
                         signature_bytes.copy_from_slice(&signature.group_signature);
                         (
-                            signature_bytes.to_vec().try_into().unwrap(),
-                            DigitalSignatureScheme::SchnorrEd25519,
+                            signature_bytes.to_vec(),
+                            jobs::tss::DigitalSignatureScheme::SchnorrEd25519,
                         )
                     }
-                    ThresholdSignatureRoleType::ZcashFrostEd448 => {
+                    roles::tss::ThresholdSignatureRoleType::ZcashFrostEd448 => {
                         let mut signature_bytes = [0u8; 114];
                         signature_bytes.copy_from_slice(&signature.group_signature);
                         (
-                            signature_bytes.to_vec().try_into().unwrap(),
-                            DigitalSignatureScheme::SchnorrEd448,
+                            signature_bytes.to_vec(),
+                            jobs::tss::DigitalSignatureScheme::SchnorrEd448,
                         )
                     }
-                    ThresholdSignatureRoleType::ZcashFrostP256 => {
+                    roles::tss::ThresholdSignatureRoleType::ZcashFrostP256 => {
                         let mut signature_bytes = [0u8; 65];
                         signature_bytes.copy_from_slice(&signature.group_signature);
                         (
-                            signature_bytes.to_vec().try_into().unwrap(),
-                            DigitalSignatureScheme::SchnorrP256,
+                            signature_bytes.to_vec(),
+                            jobs::tss::DigitalSignatureScheme::SchnorrP256,
                         )
                     }
-                    ThresholdSignatureRoleType::ZcashFrostP384 => {
+                    roles::tss::ThresholdSignatureRoleType::ZcashFrostP384 => {
                         let mut signature_bytes = [0u8; 97];
                         signature_bytes.copy_from_slice(&signature.group_signature);
                         (
-                            signature_bytes.to_vec().try_into().unwrap(),
-                            DigitalSignatureScheme::SchnorrP384,
+                            signature_bytes.to_vec(),
+                            jobs::tss::DigitalSignatureScheme::SchnorrP384,
                         )
                     }
-                    ThresholdSignatureRoleType::ZcashFrostRistretto255 => {
+                    roles::tss::ThresholdSignatureRoleType::ZcashFrostRistretto255 => {
                         let mut signature_bytes = [0u8; 64];
                         signature_bytes.copy_from_slice(&signature.group_signature);
                         (
-                            signature_bytes.to_vec().try_into().unwrap(),
-                            DigitalSignatureScheme::SchnorrRistretto255,
+                            signature_bytes.to_vec(),
+                            jobs::tss::DigitalSignatureScheme::SchnorrRistretto255,
                         )
                     }
                     _ => {
@@ -365,11 +344,12 @@ where
                     }
                 };
 
-                let job_result = GadgetJobResult::DKGPhaseTwo(DKGTSSSignatureResult {
+                let job_result = jobs::JobResult::DKGPhaseTwo(jobs::tss::DKGTSSSignatureResult {
                     signature_scheme,
-                    data: additional_params.input_data_to_sign.try_into().unwrap(),
-                    signature,
-                    verifying_key: BoundedVec::new(),
+                    data: BoundedVec(additional_params.input_data_to_sign),
+                    signature: BoundedVec(signature),
+                    verifying_key: BoundedVec(Default::default()),
+                    __subxt_unused_type_params: Default::default(),
                 });
 
                 pallet_tx
diff --git a/protocols/zcash-frost/src/rounds/keygen.rs b/protocols/zcash-frost/src/rounds/keygen.rs
index 16e05fd02..278215d4f 100644
--- a/protocols/zcash-frost/src/rounds/keygen.rs
+++ b/protocols/zcash-frost/src/rounds/keygen.rs
@@ -9,6 +9,7 @@ use frost_core::{
     Ciphersuite, Identifier,
 };
 use futures::SinkExt;
+use gadget_common::prelude::*;
 use rand_core::{CryptoRng, RngCore};
 use round_based::{
     rounds_router::{
@@ -20,7 +21,6 @@ use round_based::{
 };
 use round_based_21 as round_based;
 use serde::{Deserialize, Serialize};
-use tangle_primitives::roles::ThresholdSignatureRoleType;
 
 use super::{Error, IoError};
 
@@ -71,7 +71,7 @@ pub async fn run_threshold_keygen<C, R, M>(
     i: u16,
     t: u16,
     n: u16,
-    role: ThresholdSignatureRoleType,
+    role: roles::tss::ThresholdSignatureRoleType,
     rng: &mut R,
     party: M,
 ) -> Result<FrostKeyShare, Error<C>>
@@ -96,7 +96,7 @@ where
     // Round 1
     tracer.round_begins();
     tracer.stage("Compute round 1 dkg secret package");
-    let (round1_secret_package, round1_package) = dkg_part1(i + 1, t, n, role, rng)?;
+    let (round1_secret_package, round1_package) = dkg_part1(i + 1, t, n, role.clone(), rng)?;
     runtime.yield_now().await;
     tracer.send_msg();
     outgoings
@@ -127,7 +127,7 @@ where
     tracer.msgs_received();
     tracer.stage("Compute round 2 dkg secret package");
     let (round2_secret_package, round2_packages_map) =
-        dkg_part2(role, round1_secret_package, &round1_packages_map)?;
+        dkg_part2(role.clone(), round1_secret_package, &round1_packages_map)?;
 
     tracer.send_msg();
     for (receiver_identifier, round2_package) in round2_packages_map {
@@ -176,7 +176,7 @@ where
         })
         .collect();
     let (key_package, pubkey_package) = dkg_part3(
-        role,
+        role.clone(),
         &round2_secret_package,
         &round1_packages_map,
         &round2_packages_map,
@@ -190,7 +190,10 @@ where
     })
 }
 
-fn validate_role<C: Ciphersuite>(role: ThresholdSignatureRoleType) -> Result<(), Error<C>> {
+fn validate_role<C: Ciphersuite>(
+    role: roles::tss::ThresholdSignatureRoleType,
+) -> Result<(), Error<C>> {
+    use roles::tss::ThresholdSignatureRoleType;
     match role {
         ThresholdSignatureRoleType::ZcashFrostEd25519
         | ThresholdSignatureRoleType::ZcashFrostEd448
@@ -208,7 +211,7 @@ pub fn dkg_part1<R, C>(
     i: u16,
     t: u16,
     n: u16,
-    role: ThresholdSignatureRoleType,
+    role: roles::tss::ThresholdSignatureRoleType,
     rng: R,
 ) -> Result<(round1::SecretPackage<C>, round1::Package<C>), Error<C>>
 where
@@ -228,7 +231,7 @@ where
 
 #[allow(clippy::type_complexity)]
 pub fn dkg_part2<C>(
-    role: ThresholdSignatureRoleType,
+    role: roles::tss::ThresholdSignatureRoleType,
     secret_package: round1::SecretPackage<C>,
     round1_packages: &BTreeMap<Identifier<C>, round1::Package<C>>,
 ) -> Result<
@@ -250,7 +253,7 @@ where
 }
 
 pub fn dkg_part3<C>(
-    role: ThresholdSignatureRoleType,
+    role: roles::tss::ThresholdSignatureRoleType,
     round2_secret_package: &round2::SecretPackage<C>,
     round1_packages: &BTreeMap<Identifier<C>, round1::Package<C>>,
     round2_packages: &BTreeMap<Identifier<C>, round2::Package<C>>,
diff --git a/protocols/zcash-frost/src/rounds/sign.rs b/protocols/zcash-frost/src/rounds/sign.rs
index 8824767f8..e720035f2 100644
--- a/protocols/zcash-frost/src/rounds/sign.rs
+++ b/protocols/zcash-frost/src/rounds/sign.rs
@@ -8,13 +8,13 @@ use rand_core::{CryptoRng, RngCore};
 use round_based::rounds_router::simple_store::RoundInput;
 use round_based_21 as round_based;
 
+use gadget_common::prelude::*;
 use round_based::rounds_router::RoundsRouter;
 use round_based::runtime::AsyncRuntime;
 use round_based::ProtocolMessage;
 use round_based::{Delivery, Mpc, MpcParty, Outgoing};
 use serde::{Deserialize, Serialize};
 use std::collections::BTreeMap;
-use tangle_primitives::roles::ThresholdSignatureRoleType;
 
 use super::{Error, IoError};
 
@@ -57,7 +57,7 @@ pub async fn run_threshold_sign<C, R, M>(
     signers: Vec<u16>,
     frost_keyshare: (KeyPackage<C>, PublicKeyPackage<C>),
     message_to_sign: &[u8],
-    role: ThresholdSignatureRoleType,
+    role: roles::tss::ThresholdSignatureRoleType,
     rng: &mut R,
     party: M,
 ) -> Result<FrostSignature, Error<C>>
@@ -81,7 +81,7 @@ where
     // Round 1
     tracer.round_begins();
     tracer.stage("Generate nonces and commitments for Round 1");
-    let (nonces, commitments) = participant_round1(role, &frost_keyshare.0, rng)?;
+    let (nonces, commitments) = participant_round1(role.clone(), &frost_keyshare.0, rng)?;
     runtime.yield_now().await;
     tracer.send_msg();
     let my_round1_msg = MsgRound1 {
@@ -179,7 +179,10 @@ where
     })
 }
 
-fn validate_role<C: Ciphersuite>(role: ThresholdSignatureRoleType) -> Result<(), Error<C>> {
+fn validate_role<C: Ciphersuite>(
+    role: roles::tss::ThresholdSignatureRoleType,
+) -> Result<(), Error<C>> {
+    use roles::tss::ThresholdSignatureRoleType;
     match role {
         ThresholdSignatureRoleType::ZcashFrostEd25519
         | ThresholdSignatureRoleType::ZcashFrostEd448
@@ -195,7 +198,7 @@ fn validate_role<C: Ciphersuite>(role: ThresholdSignatureRoleType) -> Result<(),
 
 /// Participant generates nonces and commitments for Round 1.
 fn participant_round1<R: RngCore + CryptoRng, C: Ciphersuite>(
-    role: ThresholdSignatureRoleType,
+    role: roles::tss::ThresholdSignatureRoleType,
     key_package: &KeyPackage<C>,
     rng: &mut R,
 ) -> Result<(SigningNonces<C>, SigningCommitments<C>), Error<C>> {
@@ -205,7 +208,7 @@ fn participant_round1<R: RngCore + CryptoRng, C: Ciphersuite>(
 
 /// Participant produces their signature share using the `SigningPackage` and their `SigningNonces` from Round 1.
 fn participant_round2<C: Ciphersuite>(
-    role: ThresholdSignatureRoleType,
+    role: roles::tss::ThresholdSignatureRoleType,
     signing_package: &SigningPackage<C>,
     nonces: &SigningNonces<C>,
     key_package: &KeyPackage<C>,
diff --git a/protocols/zk-saas/Cargo.toml b/protocols/zk-saas/Cargo.toml
index b267c5e62..926be568c 100644
--- a/protocols/zk-saas/Cargo.toml
+++ b/protocols/zk-saas/Cargo.toml
@@ -35,11 +35,6 @@ futures = { workspace = true }
 
 sp-runtime = { workspace = true }
 sp-core = { workspace = true }
-sp-api = { workspace = true }
-
-sc-client-api = { workspace = true }
-
-pallet-jobs-rpc-runtime-api = { workspace = true }
 tangle-primitives = { workspace = true, features = ["verifying"] }
 
 ark-serialize = { workspace = true, default-features = false }
@@ -60,4 +55,4 @@ ark-std = { workspace = true, default-features = false }
 frame-support = { workspace = true }
 test-utils = { workspace = true }
 rcgen = "0.12.0"
-gadget-common = { workspace = true, features = ["testing"] }
\ No newline at end of file
+gadget-common = { workspace = true, features = ["testing"] }
diff --git a/protocols/zk-saas/src/lib.rs b/protocols/zk-saas/src/lib.rs
index f57a09005..c06b89927 100644
--- a/protocols/zk-saas/src/lib.rs
+++ b/protocols/zk-saas/src/lib.rs
@@ -1,18 +1,16 @@
 use crate::network::ZkNetworkService;
 use crate::protocol::ZkJobAdditionalParams;
 use async_trait::async_trait;
+use gadget_common::client::{ClientWithApi, JobsClient, PalletSubmitter};
+use gadget_common::debug_logger::DebugLogger;
 use gadget_common::full_protocol::SharedOptional;
 use gadget_common::prelude::*;
 use gadget_common::{generate_protocol, Error};
 use mpc_net::prod::RustlsCertificate;
 use network::ZkProtocolNetworkConfig;
 use protocol_macros::protocol;
-use sc_client_api::Backend;
-use sp_api::ProvideRuntimeApi;
 use sp_core::Pair;
-use sp_runtime::traits::Block;
 use std::sync::Arc;
-use tangle_primitives::roles::ZeroKnowledgeRoleType;
 use tokio_rustls::rustls::{Certificate, PrivateKey, RootCertStore};
 
 pub mod network;
@@ -24,8 +22,8 @@ generate_protocol!(
     ZkJobAdditionalParams,
     protocol::generate_protocol_from,
     protocol::create_next_job,
-    GadgetJobType::ZkSaaSPhaseTwo(_),
-    RoleType::ZkSaaS(ZeroKnowledgeRoleType::ZkSaaSGroth16)
+    jobs::JobType::ZkSaaSPhaseTwo(_),
+    roles::RoleType::ZkSaaS(roles::zksaas::ZeroKnowledgeRoleType::ZkSaaSGroth16)
 );
 
 pub async fn create_zk_network<KBE: KeystoreBackend>(
diff --git a/protocols/zk-saas/src/network/mod.rs b/protocols/zk-saas/src/network/mod.rs
index 69f906d05..5cdbbb565 100644
--- a/protocols/zk-saas/src/network/mod.rs
+++ b/protocols/zk-saas/src/network/mod.rs
@@ -3,7 +3,6 @@ use bytes::Bytes;
 use futures_util::sink::SinkExt;
 use futures_util::stream::{SplitSink, SplitStream};
 use futures_util::StreamExt;
-use gadget_common::client::AccountId;
 use gadget_common::keystore::{ECDSAKeyStore, KeystoreBackend};
 use gadget_core::job_manager::WorkManagerInterface;
 use mpc_net::multi::WrappedStream;
@@ -11,7 +10,7 @@ use mpc_net::prod::{CertToDer, RustlsCertificate};
 use mpc_net::MpcNetError;
 use parking_lot::RwLock;
 use serde::{Deserialize, Serialize};
-use sp_core::ecdsa;
+use sp_core::{ecdsa, sr25519};
 use std::collections::HashMap;
 use std::io::ErrorKind;
 use std::net::SocketAddr;
@@ -40,7 +39,7 @@ pub enum ZkNetworkService {
     },
     Client {
         king_registry_addr: SocketAddr,
-        king_registry_id: Option<RegistantId>,
+        king_registry_id: Arc<parking_lot::Mutex<Option<RegistantId>>>,
         registry_id: RegistantId,
         cert_der: Vec<u8>,
         local_to_outbound_tx: UnboundedSender<RegistryPacket>,
@@ -206,7 +205,7 @@ impl ZkNetworkService {
         let mut this = ZkNetworkService::Client {
             king_registry_addr,
             local_to_outbound_tx,
-            king_registry_id: None,
+            king_registry_id: Arc::new(parking_lot::Mutex::new(None)),
             registry_id: registrant_id,
             cert_der,
             inbound_messages: Arc::new(Mutex::new(from_registry)),
@@ -258,7 +257,7 @@ impl ZkNetworkService {
                             });
                         }
 
-                        *king_registry_id = Some(king_id);
+                        *king_registry_id.lock() = Some(king_id);
                     }
                     _ => {
                         return Err(Error::RegistryCreateError {
@@ -283,7 +282,7 @@ impl ZkNetworkService {
             Self::King { registry_id, .. } => Some(*registry_id),
             Self::Client {
                 king_registry_id, ..
-            } => *king_registry_id,
+            } => *king_registry_id.lock(),
         }
     }
 
@@ -519,7 +518,14 @@ impl Network for ZkNetworkService {
                     king_registry_id,
                     ..
                 } => {
-                    if to != king_registry_id.expect("Should exist") {
+                    let king_registry_id =
+                        king_registry_id
+                            .lock()
+                            .ok_or_else(|| Error::RegistrySendError {
+                                err: "No king registry id".to_string(),
+                            })?;
+
+                    if to != king_registry_id {
                         return Err(Error::RegistrySendError {
                             err: "Cannot send message to non-king as client".to_string(),
                         });
@@ -581,6 +587,6 @@ pub struct ZkProtocolNetworkConfig<KBE: KeystoreBackend> {
     pub public_identity_der: Vec<u8>,
     pub private_identity_der: Vec<u8>,
     pub client_only_king_public_identity_der: Option<Vec<u8>>,
-    pub account_id: AccountId,
+    pub account_id: sr25519::Public,
     pub key_store: ECDSAKeyStore<KBE>,
 }
diff --git a/protocols/zk-saas/src/protocol/mod.rs b/protocols/zk-saas/src/protocol/mod.rs
index ac2a6824f..0ec332f72 100644
--- a/protocols/zk-saas/src/protocol/mod.rs
+++ b/protocols/zk-saas/src/protocol/mod.rs
@@ -9,28 +9,23 @@ use ark_poly::{EvaluationDomain, Radix2EvaluationDomain};
 use ark_relations::r1cs::SynthesisError;
 use ark_serialize::{CanonicalDeserialize, CanonicalSerialize};
 use futures_util::TryFutureExt;
-use gadget_common::client::{AccountId, ClientWithApi, JobsApiForGadget, MaxSubmissionLen};
+use gadget_common::prelude::*;
+use gadget_common::client::{ClientWithApi, JobTypeExt};
 use gadget_common::gadget::message::GadgetProtocolMessage;
 use gadget_common::gadget::work_manager::WorkManager;
 use gadget_common::gadget::JobInitMetadata;
 use gadget_common::prelude::{KeystoreBackend, Network};
+use gadget_common::tangle_subxt::tangle_runtime::api::runtime_types::bounded_collections::bounded_vec::BoundedVec;
+use gadget_common::tangle_subxt::tangle_runtime::api::runtime_types::tangle_primitives::jobs::zksaas;
 use gadget_common::Error;
 use gadget_core::job::{BuiltExecutableJobWrapper, JobBuilder, JobError};
 use gadget_core::job_manager::{ProtocolWorkManager, WorkManagerInterface};
 use groth16::proving_key::PackedProvingKeyShare;
 use mpc_net::{MpcNet, MultiplexedStreamID};
-use sc_client_api::Backend;
 use secret_sharing::pss::PackedSharingParams;
-use sp_api::ProvideRuntimeApi;
 use sp_core::ecdsa;
 use sp_core::Pair;
-use sp_runtime::traits::Block;
 use std::collections::HashMap;
-use tangle_primitives::jobs::{
-    ArkworksProofResult, HyperData, JobId, JobResult, JobType, ZkSaaSPhaseTwoRequest,
-    ZkSaaSProofResult, ZkSaaSSystem,
-};
-use tangle_primitives::roles::RoleType;
 use tangle_primitives::verifier::to_field_elements;
 use tokio::sync::mpsc::UnboundedReceiver;
 
@@ -44,33 +39,30 @@ pub trait AdditionalProtocolParams: Send + Sync + Clone + 'static {
     fn party_id(&self) -> u32;
 }
 
-pub async fn create_next_job<B, C, BE, N: Network, KBE>(
-    config: &crate::ZkProtocol<B, BE, C, N, KBE>,
-    job: JobInitMetadata<B>,
+pub async fn create_next_job<C, N: Network, KBE>(
+    config: &crate::ZkProtocol<C, N, KBE>,
+    job: JobInitMetadata,
     _work_manager: &ProtocolWorkManager<WorkManager>,
 ) -> Result<ZkJobAdditionalParams, Error>
 where
-    <C as ProvideRuntimeApi<B>>::Api: JobsApiForGadget<B>,
-    B: Block,
-    C: ClientWithApi<B, BE> + 'static,
-    BE: Backend<B> + 'static,
+    C: ClientWithApi + 'static,
     KBE: KeystoreBackend,
 {
     let (_now, job_id) = (job.now, job.job_id);
     let role_type = job.job_type.get_role_type();
-    let JobType::ZkSaaSPhaseTwo(phase_two) = job.job_type else {
+    let jobs::JobType::ZkSaaSPhaseTwo(phase_two) = job.job_type else {
         panic!("Should be valid")
     };
-    let JobType::ZkSaaSPhaseOne(phase_one) = job.phase1_job.expect("Should exist") else {
+    let jobs::JobType::ZkSaaSPhaseOne(phase_one) = job.phase1_job.expect("Should exist") else {
         panic!("Should be valid")
     };
 
-    let participants = phase_one.participants;
+    let participants = phase_one.participants.0;
     let params = ZkJobAdditionalParams {
         n_parties: participants.len(),
         party_id: participants
             .iter()
-            .position(|p| p == &config.account_id)
+            .position(|p| p.0 == config.account_id.0)
             .expect("Should exist") as _,
         job_id,
         role_type,
@@ -86,10 +78,10 @@ where
 pub struct ZkJobAdditionalParams {
     n_parties: usize,
     party_id: u32,
-    job_id: JobId,
-    role_type: RoleType,
-    system: ZkSaaSSystem<MaxSubmissionLen>,
-    request: ZkSaaSPhaseTwoRequest<MaxSubmissionLen>,
+    job_id: u64,
+    role_type: roles::RoleType,
+    system: zksaas::ZkSaaSSystem<jobs::MaxSubmissionLen>,
+    request: zksaas::ZkSaaSPhaseTwoRequest<jobs::MaxSubmissionLen>,
     participants_role_ids: Vec<ecdsa::Public>,
 }
 
@@ -102,8 +94,8 @@ impl AdditionalProtocolParams for ZkJobAdditionalParams {
     }
 }
 
-pub async fn generate_protocol_from<B, C, BE, N: Network, KBE>(
-    config: &crate::ZkProtocol<B, BE, C, N, KBE>,
+pub async fn generate_protocol_from<C, N: Network, KBE>(
+    config: &crate::ZkProtocol<C, N, KBE>,
     associated_block_id: <WorkManager as WorkManagerInterface>::Clock,
     associated_retry_id: <WorkManager as WorkManagerInterface>::RetryID,
     associated_session_id: <WorkManager as WorkManagerInterface>::SessionID,
@@ -112,10 +104,7 @@ pub async fn generate_protocol_from<B, C, BE, N: Network, KBE>(
     additional_params: ZkJobAdditionalParams,
 ) -> Result<BuiltExecutableJobWrapper, JobError>
 where
-    <C as ProvideRuntimeApi<B>>::Api: JobsApiForGadget<B>,
-    B: Block,
-    C: ClientWithApi<B, BE> + 'static,
-    BE: Backend<B> + 'static,
+    C: ClientWithApi + 'static,
     KBE: KeystoreBackend,
 {
     let pallet_tx = config.pallet_tx.clone();
@@ -128,7 +117,7 @@ where
         reason: format!("Failed to setup phase order participants: {err:?}"),
     })?;
 
-    let params = ZkAsyncProtocolParameters::<_, _, _, B, BE> {
+    let params = ZkAsyncProtocolParameters {
         associated_block_id,
         associated_retry_id,
         associated_session_id,
@@ -141,7 +130,6 @@ where
         network: config.clone(),
         client: config.client.clone(),
         extra_parameters: additional_params.clone(),
-        _pd: Default::default(),
     };
 
     Ok(JobBuilder::new()
@@ -151,64 +139,66 @@ where
                 params.extra_parameters.role_type,
                 params.extra_parameters.job_id
             );
-            let ZkSaaSSystem::Groth16(ref system) = params.extra_parameters.system;
-            let ZkSaaSPhaseTwoRequest::Groth16(ref job) = params.extra_parameters.request;
-            let HyperData::Raw(ref proving_key_bytes) = system.proving_key else {
+            let zksaas::ZkSaaSSystem::Groth16(ref system) = params.extra_parameters.system;
+            let zksaas::ZkSaaSPhaseTwoRequest::Groth16(ref job) = params.extra_parameters.request;
+            let zksaas::HyperData::Raw(ref proving_key_bytes) = system.proving_key else {
                 return Err(JobError {
                     reason: "Only raw proving key is supported".to_string(),
                 });
             };
 
-            let pk =
-                ProvingKey::<E>::deserialize_compressed(&proving_key_bytes[..]).map_err(|err| {
-                    JobError {
-                        reason: format!("Failed to deserialize proving key: {err:?}"),
-                    }
-                })?;
+            let pk = ProvingKey::<E>::deserialize_compressed(&proving_key_bytes.0[..]).map_err(
+                |err| JobError {
+                    reason: format!("Failed to deserialize proving key: {err:?}"),
+                },
+            )?;
             let l = params.n_parties / 4;
             let pp = PackedSharingParams::new(l);
             let crs_shares = PackedProvingKeyShare::<E>::pack_from_arkworks_proving_key(&pk, pp);
-            let our_qap_share = job
-                .qap_shares
-                .get(params.party_id as usize)
-                .ok_or_else(|| JobError {
-                    reason: "Failed to get our qap share".to_string(),
-                })?;
-            let HyperData::Raw(ref qap_a) = our_qap_share.a else {
+            let our_qap_share =
+                job.qap_shares
+                    .0
+                    .get(params.party_id as usize)
+                    .ok_or_else(|| JobError {
+                        reason: "Failed to get our qap share".to_string(),
+                    })?;
+            let zksaas::HyperData::Raw(ref qap_a) = our_qap_share.a else {
                 return Err(JobError {
                     reason: "Only raw qap_a is supported".to_string(),
                 });
             };
-            let HyperData::Raw(ref qap_b) = our_qap_share.b else {
+            let zksaas::HyperData::Raw(ref qap_b) = our_qap_share.b else {
                 return Err(JobError {
                     reason: "Only raw qap_b is supported".to_string(),
                 });
             };
-            let HyperData::Raw(ref qap_c) = our_qap_share.c else {
+            let zksaas::HyperData::Raw(ref qap_c) = our_qap_share.c else {
                 return Err(JobError {
                     reason: "Only raw qap_c is supported".to_string(),
                 });
             };
-            let our_a_share =
-                job.a_shares
-                    .get(params.party_id as usize)
-                    .ok_or_else(|| JobError {
-                        reason: "Failed to get our a share".to_string(),
-                    })?;
-            let HyperData::Raw(a_share_bytes) = our_a_share else {
+            let our_a_share = job
+                .a_shares
+                .0
+                .get(params.party_id as usize)
+                .ok_or_else(|| JobError {
+                    reason: "Failed to get our a share".to_string(),
+                })?;
+            let zksaas::HyperData::Raw(a_share_bytes) = our_a_share else {
                 return Err(JobError {
                     reason: "Only raw a_share is supported".to_string(),
                 });
             };
 
-            let our_ax_share =
-                job.ax_shares
-                    .get(params.party_id as usize)
-                    .ok_or_else(|| JobError {
-                        reason: "Failed to get our ax share".to_string(),
-                    })?;
+            let our_ax_share = job
+                .ax_shares
+                .0
+                .get(params.party_id as usize)
+                .ok_or_else(|| JobError {
+                    reason: "Failed to get our ax share".to_string(),
+                })?;
 
-            let HyperData::Raw(ax_share_bytes) = our_ax_share else {
+            let zksaas::HyperData::Raw(ax_share_bytes) = our_ax_share else {
                 return Err(JobError {
                     reason: "Only raw ax_share is supported".to_string(),
                 });
@@ -222,21 +212,21 @@ where
             let qap_share = groth16::qap::PackedQAPShare {
                 num_inputs: system.num_inputs as _,
                 num_constraints: system.num_constraints as _,
-                a: to_field_elements(qap_a).map_err(|err| JobError {
+                a: to_field_elements(&qap_a.0).map_err(|err| JobError {
                     reason: format!("Failed to convert a to field elements: {err:?}"),
                 })?,
-                b: to_field_elements(qap_b).map_err(|err| JobError {
+                b: to_field_elements(&qap_b.0).map_err(|err| JobError {
                     reason: format!("Failed to convert b to field elements: {err:?}"),
                 })?,
-                c: to_field_elements(qap_c).map_err(|err| JobError {
+                c: to_field_elements(&qap_c.0).map_err(|err| JobError {
                     reason: format!("Failed to convert c to field elements: {err:?}"),
                 })?,
                 domain,
             };
-            let a_share = to_field_elements(a_share_bytes).map_err(|err| JobError {
+            let a_share = to_field_elements(&a_share_bytes.0).map_err(|err| JobError {
                 reason: format!("Failed to convert a_share to field elements: {err:?}"),
             })?;
-            let ax_share = to_field_elements(ax_share_bytes).map_err(|err| JobError {
+            let ax_share = to_field_elements(&ax_share_bytes.0).map_err(|err| JobError {
                 reason: format!("Failed to convert ax_share to field elements: {err:?}"),
             })?;
             let crs_share = crs_shares
@@ -309,7 +299,7 @@ where
                 // Verify the proof
                 // convert the public inputs from string to bigints
                 let public_inputs =
-                    to_field_elements(&job.public_input).map_err(|err| JobError {
+                    to_field_elements(&job.public_input.0).map_err(|err| JobError {
                         reason: format!(
                             "Failed to convert public inputs to field elements: {err:?}"
                         ),
@@ -328,15 +318,16 @@ where
                 }
                 let mut proof_bytes = Vec::new();
                 proof.serialize_compressed(&mut proof_bytes).unwrap();
-                let result = ZkSaaSProofResult::Arkworks(ArkworksProofResult {
-                    proof: proof_bytes.try_into().unwrap(),
+                let result = zksaas::ZkSaaSProofResult::Arkworks(zksaas::ArkworksProofResult {
+                    proof: BoundedVec(proof_bytes),
+                    __subxt_unused_type_params: Default::default(),
                 });
 
                 pallet_tx
                     .submit_job_result(
                         params.extra_parameters.role_type,
                         params.extra_parameters.job_id,
-                        JobResult::ZkSaaSPhaseTwo(result),
+                        jobs::JobResult::ZkSaaSPhaseTwo(result),
                     )
                     .await
                     .map_err(|err| JobError {
@@ -406,10 +397,6 @@ async fn zk_setup_rxs(
     Ok(rxs)
 }
 
-pub trait ZkNetworkExt {
-    fn king_id(&self) -> Option<AccountId>;
-}
-
 fn zk_setup_phase_order_participants<N: Network>(
     mut participants: Vec<ecdsa::Public>,
     network: N,
diff --git a/protocols/zk-saas/src/protocol/proto_gen.rs b/protocols/zk-saas/src/protocol/proto_gen.rs
index ce501e380..85c5504db 100644
--- a/protocols/zk-saas/src/protocol/proto_gen.rs
+++ b/protocols/zk-saas/src/protocol/proto_gen.rs
@@ -1,21 +1,17 @@
 use crate::network::RegistantId;
 use async_trait::async_trait;
 use bytes::Bytes;
-use gadget_common::client::{ClientWithApi, JobsApiForGadget};
+use gadget_common::client::ClientWithApi;
 use gadget_common::gadget::message::GadgetProtocolMessage;
 use gadget_common::gadget::network::Network;
 use gadget_common::gadget::work_manager::WorkManager;
 use gadget_core::job_manager::WorkManagerInterface;
 use mpc_net::{MpcNet, MpcNetError, MultiplexedStreamID};
-use sc_client_api::Backend;
 use serde::{Deserialize, Serialize};
-use sp_api::ProvideRuntimeApi;
-use sp_runtime::traits::Block;
 use std::collections::HashMap;
-use std::marker::PhantomData;
 use tokio::sync::mpsc::UnboundedReceiver;
 
-pub struct ZkAsyncProtocolParameters<B, N, C, Bl, BE> {
+pub struct ZkAsyncProtocolParameters<P, N, C> {
     pub associated_block_id: <WorkManager as WorkManagerInterface>::Clock,
     pub associated_retry_id: <WorkManager as WorkManagerInterface>::RetryID,
     pub associated_session_id: <WorkManager as WorkManagerInterface>::SessionID,
@@ -25,11 +21,10 @@ pub struct ZkAsyncProtocolParameters<B, N, C, Bl, BE> {
     pub n_parties: usize,
     pub network: N,
     pub client: C,
-    pub extra_parameters: B,
+    pub extra_parameters: P,
     pub my_network_id: RegistantId,
     // Mapping from party_id to network_id, needed for routing messages
     pub other_network_ids: HashMap<u32, RegistantId>,
-    pub(crate) _pd: PhantomData<(Bl, BE)>,
 }
 
 #[derive(Serialize, Deserialize)]
@@ -40,11 +35,7 @@ pub(crate) struct MpcNetMessage {
 }
 
 #[async_trait]
-impl<B: Send + Sync, N: Network, C: ClientWithApi<Bl, BE>, Bl: Block, BE: Backend<Bl>> MpcNet
-    for ZkAsyncProtocolParameters<B, N, C, Bl, BE>
-where
-    <C as ProvideRuntimeApi<Bl>>::Api: JobsApiForGadget<Bl>,
-{
+impl<P: Send + Sync, N: Network, C: ClientWithApi> MpcNet for ZkAsyncProtocolParameters<P, N, C> {
     fn n_parties(&self) -> usize {
         self.n_parties
     }
diff --git a/rust-toolchain.toml b/rust-toolchain.toml
index 83b8c051f..288fa153b 100644
--- a/rust-toolchain.toml
+++ b/rust-toolchain.toml
@@ -1,9 +1,5 @@
 [toolchain]
-# We are using this old version of rustc since
-# substrate has issues with newer versions.
-# See: https://substrate.stackexchange.com/questions/7714/cannot-run-substrate-on-a-fresh-macbook-m2
-# and: https://stackoverflow.com/questions/75955457/substrate-node-template-cannot-create-a-runtime-error-othercannot-deserialize
-channel = "nightly-2023-09-28"
+channel = "stable"
 components = ["rustfmt", "clippy", "rust-src"]
 targets = ["wasm32-unknown-unknown"]
 profile = "minimal"


Test patch:
diff --git a/protocols/dfns-cggmp21/tests/dfns.rs b/protocols/dfns-cggmp21/tests/dfns.rs
index 3ede83883..45de5f1fd 100644
--- a/protocols/dfns-cggmp21/tests/dfns.rs
+++ b/protocols/dfns-cggmp21/tests/dfns.rs
@@ -8,7 +8,7 @@ mod tests {
     };
     use tangle_primitives::roles::{RoleType, ThresholdSignatureRoleType};
     use tangle_primitives::AccountId;
-    use test_utils::mock::{id_to_sr25519_public, Jobs, MockBackend, RuntimeOrigin};
+    use test_utils::mock::{id_to_sr25519_public, Jobs, RuntimeOrigin};
     use test_utils::sync::substrate_test_channel::MultiThreadedTestExternalities;
     #[tokio::test(flavor = "multi_thread")]
     async fn test_externalities_keyrefresh() {
@@ -228,15 +228,15 @@ mod tests {
 
     async fn new_test_ext<const N: usize>() -> MultiThreadedTestExternalities {
         test_utils::mock::new_test_ext::<N, 4, _, _, _>((), |node_input| async move {
-            let clients = node_input.mock_clients;
-            let networks = node_input.mock_networks;
+            let clients = node_input.clients;
+            let networks = node_input.networks;
             let account_id = node_input.account_id;
             let logger = node_input.logger.clone();
             let prometheus_config = node_input.prometheus_config.clone();
 
             let (pallet_tx, key_store) = (node_input.pallet_tx, node_input.keystore);
             logger.info("Starting gadget");
-            if let Err(err) = dfns_cggmp21_protocol::run::<_, MockBackend, _, _, _>(
+            if let Err(err) = dfns_cggmp21_protocol::run(
                 clients,
                 pallet_tx,
                 networks,
diff --git a/protocols/zk-saas/tests/zksaas.rs b/protocols/zk-saas/tests/zksaas.rs
index 150fdbb61..755f459ea 100644
--- a/protocols/zk-saas/tests/zksaas.rs
+++ b/protocols/zk-saas/tests/zksaas.rs
@@ -27,7 +27,7 @@ mod tests {
     use tangle_primitives::roles::{RoleType, ZeroKnowledgeRoleType};
     use tangle_primitives::verifier::from_field_elements;
     use tangle_primitives::AccountId;
-    use test_utils::mock::{id_to_public, id_to_sr25519_public, Jobs, MockBackend, RuntimeOrigin};
+    use test_utils::mock::{id_to_public, id_to_sr25519_public, Jobs, RuntimeOrigin};
     use test_utils::sync::substrate_test_channel::MultiThreadedTestExternalities;
     use zk_saas_protocol::network::ZkProtocolNetworkConfig;
 
@@ -164,6 +164,7 @@ mod tests {
             rcgen::generate_simple_self_signed(vec!["localhost".into(), "127.0.0.1".into()])
                 .unwrap();
         let king_cert = Arc::new(king_cert);
+
         test_utils::mock::new_test_ext::<N, 1, _, _, _>(king_cert, |mut node_info| async move {
             let king_cert = node_info.additional_params;
             let king_public_identity_der = king_cert.serialize_der().expect("Should serialize");
@@ -194,12 +195,12 @@ mod tests {
             };
 
             let logger = node_info.logger.clone();
-            let client = node_info.mock_clients.pop().expect("Should have client");
+            let client = node_info.clients.pop().expect("Should have client");
             let pallet_tx = node_info.pallet_tx;
             let key_store = node_info.keystore;
 
             let network_cfg = ZkProtocolNetworkConfig {
-                account_id: node_info.account_id.clone(),
+                account_id: node_info.account_id,
                 king_bind_addr,
                 client_only_king_addr,
                 client_only_king_public_identity_der,
@@ -217,7 +218,7 @@ mod tests {
             let prometheus_config = node_info.prometheus_config.clone();
             log::info!(target: "gadget", "Started node {}", node_info.node_index);
             // ZkSaaS only requires 1 client and 1 network, no need to use the NodeInput's vectors
-            if let Err(err) = zk_saas_protocol::run::<_, MockBackend, _, _, _>(
+            if let Err(err) = zk_saas_protocol::run(
                 vec![client],
                 pallet_tx,
                 vec![network],
diff --git a/test-gadget/src/gadget.rs b/test-gadget/src/gadget.rs
index c0076b61a..d2cb7204a 100644
--- a/test-gadget/src/gadget.rs
+++ b/test-gadget/src/gadget.rs
@@ -61,7 +61,6 @@ pub struct TestFinalityNotification {
 #[async_trait]
 impl<B: Send + Sync + Clone + 'static> AbstractGadget for TestGadget<B> {
     type FinalityNotification = TestFinalityNotification;
-    type BlockImportNotification = ();
     type ProtocolMessage = TestProtocolMessage;
     type Error = TestError;
 
@@ -69,11 +68,6 @@ impl<B: Send + Sync + Clone + 'static> AbstractGadget for TestGadget<B> {
         self.blockchain_connection.lock().await.recv().await.ok()
     }
 
-    async fn get_next_block_import_notification(&self) -> Option<Self::BlockImportNotification> {
-        // We don't care to test block import notifications in this test gadget
-        futures::future::pending().await
-    }
-
     async fn get_next_protocol_message(&self) -> Option<Self::ProtocolMessage> {
         self.network_connection.lock().await.recv().await
     }
@@ -109,13 +103,6 @@ impl<B: Send + Sync + Clone + 'static> AbstractGadget for TestGadget<B> {
         Ok(())
     }
 
-    async fn process_block_import_notification(
-        &self,
-        _notification: Self::BlockImportNotification,
-    ) -> Result<(), Self::Error> {
-        unreachable!("We don't care to test block import notifications in this test gadget")
-    }
-
     async fn process_protocol_message(
         &self,
         message: Self::ProtocolMessage,
diff --git a/test-utils/Cargo.toml b/test-utils/Cargo.toml
index ed2b35fa6..6ba3f97f6 100644
--- a/test-utils/Cargo.toml
+++ b/test-utils/Cargo.toml
@@ -34,4 +34,5 @@ sp-externalities = { workspace = true }
 tangle-primitives = { workspace = true, features = ["verifying"] }
 scale-info = { workspace = true }
 parity-scale-codec = { workspace = true }
+serde = { workspace = true }
 tracing-subscriber = { version = "0.3.17", features = ["env-filter"] }
diff --git a/test-utils/src/lib.rs b/test-utils/src/lib.rs
index f74c25335..daabc18bd 100644
--- a/test-utils/src/lib.rs
+++ b/test-utils/src/lib.rs
@@ -1,12 +1,12 @@
 use crate::mock::{Jobs, Runtime};
 use crate::sync::substrate_test_channel::MultiThreadedTestExternalities;
-use gadget_common::client::GadgetPhaseResult;
 pub use gadget_core::job_manager::SendFuture;
 pub use log;
 use pallet_jobs::{SubmittedJobs, SubmittedJobsRole};
 use std::time::Duration;
-use tangle_primitives::jobs::JobId;
+use tangle_primitives::jobs::{JobId, PhaseResult};
 use tangle_primitives::roles::RoleType;
+use tangle_primitives::AccountId;
 use tracing_subscriber::filter::EnvFilter;
 use tracing_subscriber::fmt::SubscriberBuilder;
 use tracing_subscriber::util::SubscriberInitExt;
@@ -30,8 +30,17 @@ pub fn setup_log() {
 pub async fn wait_for_job_completion(
     ext: &MultiThreadedTestExternalities,
     role_type: RoleType,
-    job_id: JobId,
-) -> GadgetPhaseResult<mock::BlockNumber> {
+    job_id: u64,
+) -> PhaseResult<
+    AccountId,
+    mock::BlockNumber,
+    mock::MaxParticipants,
+    mock::MaxKeyLen,
+    mock::MaxDataLen,
+    mock::MaxSignatureLen,
+    mock::MaxSubmissionLen,
+    mock::MaxProofLen,
+> {
     loop {
         tokio::time::sleep(Duration::from_millis(100)).await;
         if let Some(ret) = ext
@@ -108,7 +117,7 @@ macro_rules! generate_signing_and_keygen_tss_tests {
                         let identities = (0..N).map(|i| id_to_sr25519_public(i as u8)).map(AccountId::from).collect::<Vec<_>>();
 
                         let submission = JobSubmission {
-                            fallback: gadget_common::prelude::FallbackOptions::Destroy,
+                            fallback: tangle_primitives::jobs::FallbackOptions::Destroy,
                             expiry: 100,
                             ttl: 100,
                             job_type: JobType::DKGTSSPhaseOne(DKGTSSPhaseOneJobType {
@@ -144,7 +153,7 @@ macro_rules! generate_signing_and_keygen_tss_tests {
                         let job_id = Jobs::next_job_id();
                         let identities = (0..N).map(|i| id_to_sr25519_public(i as u8)).map(AccountId::from).collect::<Vec<_>>();
                         let submission = JobSubmission {
-                            fallback: gadget_common::prelude::FallbackOptions::Destroy,
+                            fallback: tangle_primitives::jobs::FallbackOptions::Destroy,
                             expiry: 100,
                             ttl: 100,
                             job_type: JobType::DKGTSSPhaseTwo(DKGTSSPhaseTwoJobType {
diff --git a/test-utils/src/mock.rs b/test-utils/src/mock.rs
index 90772da1e..e717490de 100644
--- a/test-utils/src/mock.rs
+++ b/test-utils/src/mock.rs
@@ -15,6 +15,7 @@
 // along with Tangle.  If not, see <http://www.gnu.org/licenses/>.
 
 use async_trait::async_trait;
+use frame_support::pallet_prelude::*;
 use frame_support::traits::Hooks;
 use frame_support::{
     construct_runtime, parameter_types,
@@ -22,18 +23,17 @@ use frame_support::{
     PalletId,
 };
 use frame_system::EnsureSigned;
-use gadget_common::client::{
-    AccountId, MaxActiveJobsPerValidator, MaxDataLen, MaxKeyLen, MaxParticipants, MaxProofLen,
-    MaxSignatureLen, MaxSubmissionLen,
-};
 use pallet_jobs_rpc_runtime_api::BlockNumberOf;
 use sc_client_api::{FinalityNotification, FinalizeSummary};
 use sc_utils::mpsc::{tracing_unbounded, TracingUnboundedReceiver, TracingUnboundedSender};
+use serde::{Deserialize, Serialize};
 use sp_api::{ApiRef, ProvideRuntimeApi};
 use sp_core::{sr25519, ByteArray, Pair, H256};
+use sp_runtime::RuntimeDebug;
 use sp_runtime::{traits::Block as BlockT, traits::IdentityLookup, BuildStorage, DispatchResult};
 use std::collections::HashMap;
 use std::time::Duration;
+use tangle_primitives::AccountId;
 
 pub type Balance = u128;
 pub type BlockNumber = u64;
@@ -223,6 +223,36 @@ parameter_types! {
     pub const JobsPalletId: PalletId = PalletId(*b"py/jobss");
 }
 
+const KB: u32 = 1024;
+const MB: u32 = 1024 * KB;
+
+parameter_types! {
+    #[derive(Clone, RuntimeDebug, Eq, PartialEq, TypeInfo, Encode, Decode)]
+    #[derive(Serialize, Deserialize)]
+    pub const MaxSubmissionLen: u32 = 64 * MB;
+    #[derive(Clone, RuntimeDebug, Eq, PartialEq, TypeInfo, Encode, Decode)]
+    #[derive(Serialize, Deserialize)]
+    pub const MaxParticipants: u32 = 10;
+    #[derive(Clone, RuntimeDebug, Eq, PartialEq, TypeInfo, Encode, Decode)]
+    #[derive(Serialize, Deserialize)]
+    pub const MaxKeyLen: u32 = 256;
+    #[derive(Clone, RuntimeDebug, Eq, PartialEq, TypeInfo, Encode, Decode)]
+    #[derive(Serialize, Deserialize)]
+    pub const MaxDataLen: u32 = 256;
+    #[derive(Clone, RuntimeDebug, Eq, PartialEq, TypeInfo, Encode, Decode)]
+    #[derive(Serialize, Deserialize)]
+    pub const MaxSignatureLen: u32 = 256;
+    #[derive(Clone, RuntimeDebug, Eq, PartialEq, TypeInfo, Encode, Decode)]
+    #[derive(Serialize, Deserialize)]
+    pub const MaxProofLen: u32 = 256;
+    #[derive(Clone, RuntimeDebug, Eq, PartialEq, TypeInfo, Encode, Decode)]
+    #[derive(Serialize, Deserialize)]
+    pub const MaxActiveJobsPerValidator: u32 = 100;
+    #[derive(Clone, RuntimeDebug, Eq, PartialEq, TypeInfo, Encode, Decode)]
+    #[derive(Serialize, Deserialize)]
+    pub const MaxRolesPerValidator: u32 = 100;
+}
+
 impl pallet_jobs::Config for Runtime {
     type RuntimeEvent = RuntimeEvent;
     type Currency = Balances;
@@ -485,9 +515,7 @@ pub async fn new_test_ext<
     const N: usize,
     const K: usize,
     D: Send + Clone + 'static,
-    F: Fn(
-        NodeInput<Block, MockBackend, MockClient<Runtime, Block>, MockNetwork, InMemoryBackend, D>,
-    ) -> Fut,
+    F: Fn(NodeInput<MockClient<Runtime, Block>, MockNetwork, InMemoryBackend, D>) -> Fut,
     Fut: SendFuture<'static, ()>,
 >(
     additional_params: D,
@@ -612,16 +640,15 @@ pub async fn new_test_ext<
         let prometheus_config = PrometheusConfig::Disabled;
 
         let input = NodeInput {
-            mock_clients,
-            mock_networks: networks,
-            account_id,
+            clients: mock_clients,
+            networks,
+            account_id: sr25519::Public(account_id.into()),
             logger,
             pallet_tx,
             keystore,
             node_index,
             additional_params: additional_params.clone(),
             prometheus_config,
-            _pd: Default::default(),
         };
 
         let task = f(input);
@@ -636,21 +663,28 @@ pub mod mock_wrapper_client {
     use crate::sync::substrate_test_channel::MultiThreadedTestExternalities;
     use async_trait::async_trait;
     use futures::StreamExt;
-    use gadget_common::client::{AccountId, GadgetJobResult, PalletSubmitter};
+    use gadget_common::client::{exec_client_function, PalletSubmitter};
+    use gadget_common::config::ClientWithApi;
     use gadget_common::locks::TokioMutexExt;
-    use gadget_common::Header;
-    use gadget_core::gadget::substrate::Client;
+    use gadget_common::tangle_subxt::subxt::utils::AccountId32;
+    use gadget_common::tangle_subxt::tangle_runtime::api::runtime_types::tangle_primitives::{
+        jobs, roles,
+    };
+    use gadget_core::gadget::substrate::{self, Client};
+    use pallet_jobs_rpc_runtime_api::JobsApi;
+    use parity_scale_codec::{Decode, Encode};
     use sc_client_api::{
         BlockchainEvents, FinalityNotification, FinalityNotifications, ImportNotifications,
         StorageEventStream, StorageKey,
     };
     use sc_utils::mpsc::{tracing_unbounded, TracingUnboundedSender};
-    use sp_api::{ApiRef, BlockT, ProvideRuntimeApi};
+    use sp_api::{ApiRef, ProvideRuntimeApi};
     use sp_runtime::traits::Block;
+    use sp_runtime::traits::Header;
     use std::sync::Arc;
     use std::time::Duration;
     use tangle_primitives::jobs::JobId;
-    use tangle_primitives::roles::RoleType;
+    use tangle_primitives::AccountId;
 
     #[derive(Clone)]
     pub struct MockClient<R, B: Block> {
@@ -687,8 +721,8 @@ pub mod mock_wrapper_client {
     }
 
     #[async_trait]
-    impl<R: Send + Sync, B: Block> Client<B> for MockClient<R, B> {
-        async fn get_next_finality_notification(&self) -> Option<FinalityNotification<B>> {
+    impl<R: Send + Sync + Clone, B: Block> Client for MockClient<R, B> {
+        async fn get_next_finality_notification(&self) -> Option<substrate::FinalityNotification> {
             let mut lock = self
                 .finality_notification_stream
                 .lock_timeout(Duration::from_millis(500))
@@ -699,16 +733,28 @@ pub mod mock_wrapper_client {
                 .latest_finality_notification
                 .lock_timeout(Duration::from_millis(500))
                 .await = next.clone();
-            next
+            next.map(|n| {
+                let mut hash = [0u8; 32];
+                hash.copy_from_slice(n.header.hash().as_ref());
+                let number =
+                    Decode::decode(&mut Encode::encode(&n.header.number()).as_slice()).unwrap();
+                substrate::FinalityNotification { hash, number }
+            })
         }
 
-        async fn get_latest_finality_notification(&self) -> Option<FinalityNotification<B>> {
+        async fn get_latest_finality_notification(
+            &self,
+        ) -> Option<substrate::FinalityNotification> {
             let lock = self
                 .latest_finality_notification
                 .lock_timeout(Duration::from_millis(500))
                 .await;
-            if let Some(latest) = lock.clone() {
-                Some(latest)
+            if let Some(n) = lock.clone() {
+                let mut hash = [0u8; 32];
+                hash.copy_from_slice(n.header.hash().as_ref());
+                let number =
+                    Decode::decode(&mut Encode::encode(&n.header.number()).as_slice()).unwrap();
+                Some(substrate::FinalityNotification { hash, number })
             } else {
                 drop(lock);
                 self.get_next_finality_notification().await
@@ -716,6 +762,149 @@ pub mod mock_wrapper_client {
         }
     }
 
+    #[async_trait]
+    impl<R: Send + Sync + Clone + 'static, B: Block> ClientWithApi for MockClient<R, B>
+    where
+        R: ProvideRuntimeApi<B>,
+        R::Api: pallet_jobs_rpc_runtime_api::JobsApi<
+            B,
+            ::tangle_primitives::AccountId,
+            super::MaxParticipants,
+            super::MaxSubmissionLen,
+            super::MaxKeyLen,
+            super::MaxDataLen,
+            super::MaxSignatureLen,
+            super::MaxProofLen,
+        >,
+    {
+        async fn query_jobs_by_validator(
+            &self,
+            at: [u8; 32],
+            validator: AccountId32,
+        ) -> Result<
+            Option<
+                Vec<
+                    jobs::RpcResponseJobsData<
+                        AccountId32,
+                        u64,
+                        jobs::MaxParticipants,
+                        jobs::MaxSubmissionLen,
+                    >,
+                >,
+            >,
+            gadget_common::Error,
+        > {
+            let at = Decode::decode(&mut Encode::encode(&at).as_slice()).unwrap();
+            let validator = tangle_primitives::AccountId::from(validator.0);
+            exec_client_function(&self.runtime, move |r| {
+                r.runtime_api()
+                    .query_jobs_by_validator(at, validator)
+                    .map_err(|err| gadget_common::Error::ClientError {
+                        err: format!("{err:?}"),
+                    })
+                    .map(|r| {
+                        r.map(|r| {
+                            r.into_iter()
+                                .flat_map(|r| Decode::decode(&mut Encode::encode(&r).as_slice()))
+                                .collect()
+                        })
+                    })
+            })
+            .await
+        }
+        async fn query_job_by_id(
+            &self,
+            at: [u8; 32],
+            role_type: roles::RoleType,
+            job_id: u64,
+        ) -> Result<
+            Option<
+                jobs::RpcResponseJobsData<
+                    AccountId32,
+                    u64,
+                    jobs::MaxParticipants,
+                    jobs::MaxSubmissionLen,
+                >,
+            >,
+            gadget_common::Error,
+        > {
+            let at = Decode::decode(&mut Encode::encode(&at).as_slice()).unwrap();
+            let role_type = Decode::decode(&mut Encode::encode(&role_type).as_slice()).unwrap();
+            exec_client_function(&self.runtime, move |r| {
+                r.runtime_api()
+                    .query_job_by_id(at, role_type, job_id)
+                    .map_err(|err| gadget_common::Error::ClientError {
+                        err: format!("{err:?}"),
+                    })
+                    .map(|r| r.map(|r| Decode::decode(&mut Encode::encode(&r).as_slice()).unwrap()))
+            })
+            .await
+        }
+
+        async fn query_job_result(
+            &self,
+            at: [u8; 32],
+            role_type: roles::RoleType,
+            job_id: u64,
+        ) -> Result<
+            Option<
+                jobs::PhaseResult<
+                    AccountId32,
+                    u64,
+                    jobs::MaxParticipants,
+                    jobs::MaxKeyLen,
+                    jobs::MaxDataLen,
+                    jobs::MaxSignatureLen,
+                    jobs::MaxSubmissionLen,
+                    jobs::MaxProofLen,
+                >,
+            >,
+            gadget_common::Error,
+        > {
+            let at = Decode::decode(&mut Encode::encode(&at).as_slice()).unwrap();
+            let role_type = Decode::decode(&mut Encode::encode(&role_type).as_slice()).unwrap();
+            exec_client_function(&self.runtime, move |r| {
+                r.runtime_api()
+                    .query_job_result(at, role_type, job_id)
+                    .map_err(|err| gadget_common::Error::ClientError {
+                        err: format!("{err:?}"),
+                    })
+                    .map(|r| r.map(|r| Decode::decode(&mut Encode::encode(&r).as_slice()).unwrap()))
+            })
+            .await
+        }
+
+        async fn query_next_job_id(&self, at: [u8; 32]) -> Result<u64, gadget_common::Error> {
+            let at = Decode::decode(&mut Encode::encode(&at).as_slice()).unwrap();
+            exec_client_function(&self.runtime, move |r| {
+                r.runtime_api().query_next_job_id(at).map_err(|err| {
+                    gadget_common::Error::ClientError {
+                        err: format!("{err:?}"),
+                    }
+                })
+            })
+            .await
+        }
+
+        async fn query_restaker_role_key(
+            &self,
+            at: [u8; 32],
+            address: AccountId32,
+        ) -> Result<Option<Vec<u8>>, gadget_common::Error> {
+            let at = Decode::decode(&mut Encode::encode(&at).as_slice()).unwrap();
+            let address = tangle_primitives::AccountId::from(address.0);
+            exec_client_function(&self.runtime, move |r| {
+                r.runtime_api()
+                    .query_restaker_role_key(at, address)
+                    .map_err(|err| gadget_common::Error::ClientError {
+                        err: format!("{err:?}"),
+                    })
+                    .map(|r| r.map(|r| r.to_vec()))
+            })
+            .await
+        }
+    }
+
     impl<R: ProvideRuntimeApi<B>, B: Block> ProvideRuntimeApi<B> for MockClient<R, B> {
         type Api = R::Api;
         fn runtime_api(&self) -> ApiRef<Self::Api> {
@@ -746,7 +935,7 @@ pub mod mock_wrapper_client {
             &self,
             _filter_keys: Option<&[StorageKey]>,
             _child_filter_keys: Option<&[(StorageKey, Option<Vec<StorageKey>>)]>,
-        ) -> sc_client_api::blockchain::Result<StorageEventStream<<B as BlockT>::Hash>> {
+        ) -> sc_client_api::blockchain::Result<StorageEventStream<<B as Block>::Hash>> {
             unimplemented!()
         }
     }
@@ -760,16 +949,26 @@ pub mod mock_wrapper_client {
     impl PalletSubmitter for TestExternalitiesPalletSubmitter {
         async fn submit_job_result(
             &self,
-            role_type: RoleType,
+            role_type: roles::RoleType,
             job_id: JobId,
-            result: GadgetJobResult,
+            result: jobs::JobResult<
+                jobs::MaxParticipants,
+                jobs::MaxKeyLen,
+                jobs::MaxSignatureLen,
+                jobs::MaxDataLen,
+                jobs::MaxProofLen,
+            >,
         ) -> Result<(), gadget_common::Error> {
             let id = self.id.clone();
             self.ext
                 .execute_with_async(move || {
                     let origin = RuntimeOrigin::signed(id);
-                    let res =
-                        crate::mock::Jobs::submit_job_result(origin, role_type, job_id, result);
+                    let res = crate::mock::Jobs::submit_job_result(
+                        origin,
+                        Decode::decode(&mut Encode::encode(&role_type).as_slice()).unwrap(),
+                        job_id,
+                        Decode::decode(&mut Encode::encode(&result).as_slice()).unwrap(),
+                    );
                     if let Err(err) = res {
                         let err = format!("Pallet tx error: {err:?}");
                         if err.contains("JobNotFound") {