Repository: desmos-labs/desmos
Pull request #971 (2022-07-21 10:33:43)

fix!: profile query returns nil if profile does not exist
## Description

Currently, querying a non-existing profile returns `nil` instead of error with `profile not found for address/dtag`.
This PR fixes the response of `Profile` behavior mentioned above. 

<!-- Add a description of the changes that this PR introduces and the files that
are the most critical to review. -->

---

### Author Checklist

*All items are required. Please add a note to the item if the item is not applicable and
please add links to any relevant follow up issues.*

I have...

- [x] included the correct [type prefix](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json) in the PR title
- [ ] added `!` to the type prefix if API or client breaking change
- [x] targeted the correct branch (see [PR Targeting](https://github.com/desmos-labs/desmos/blob/master/CONTRIBUTING.md#pr-targeting))
- [ ] provided a link to the relevant issue or specification
- [ ] followed the guidelines for [building modules](https://docs.cosmos.network/v0.44/building-modules/intro.html)
- [ ] included the necessary unit and integration [tests](https://github.com/desmos-labs/desmos/blob/master/CONTRIBUTING.md#testing)
- [ ] added a changelog entry to `CHANGELOG.md`
- [ ] included comments for [documenting Go code](https://blog.golang.org/godoc)
- [ ] updated the relevant documentation or specification
- [ ] reviewed "Files changed" and left comments if necessary
- [ ] confirmed all CI checks have passed

### Reviewers Checklist

*All items are required. Please add a note if the item is not applicable and please add
your handle next to the items reviewed if you only reviewed selected items.*

I have...

- [ ] confirmed the correct [type prefix](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json) in the PR title
- [ ] confirmed `!` in the type prefix if API or client breaking change
- [ ] confirmed all author checklist items have been addressed
- [ ] reviewed state machine logic
- [ ] reviewed API design and naming
- [ ] reviewed documentation is accurate
- [ ] reviewed tests and test coverage
- [ ] manually tested (if applicable)

codecov[bot]: # [Codecov](https://codecov.io/gh/desmos-labs/desmos/pull/971?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=desmos-labs) Report
> Merging [#971](https://codecov.io/gh/desmos-labs/desmos/pull/971?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=desmos-labs) (2997fc6) into [master](https://codecov.io/gh/desmos-labs/desmos/commit/c7ff50d8605e871904dd7c07f334f6dd35941fcd?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=desmos-labs) (c7ff50d) will **increase** coverage by `0.01%`.
> The diff coverage is `100.00%`.

```diff
@@            Coverage Diff             @@
##           master     #971      +/-   ##
==========================================
+ Coverage   80.54%   80.56%   +0.01%     
==========================================
  Files         172      172              
  Lines       15095    15095              
==========================================
+ Hits        12158    12161       +3     
+ Misses       2415     2413       -2     
+ Partials      522      521       -1     
```


| [Impacted Files](https://codecov.io/gh/desmos-labs/desmos/pull/971?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=desmos-labs) | Coverage Δ | |
|---|---|---|
| [x/profiles/keeper/grpc\_query.go](https://codecov.io/gh/desmos-labs/desmos/pull/971/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=desmos-labs#diff-eC9wcm9maWxlcy9rZWVwZXIvZ3JwY19xdWVyeS5nbw==) | `79.51% <100.00%> (ø)` | |
| [x/profiles/client/cli/cli\_profile.go](https://codecov.io/gh/desmos-labs/desmos/pull/971/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=desmos-labs#diff-eC9wcm9maWxlcy9jbGllbnQvY2xpL2NsaV9wcm9maWxlLmdv) | `86.20% <0.00%> (+3.44%)` | :arrow_up: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/desmos-labs/desmos/pull/971?src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=desmos-labs).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=desmos-labs)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/desmos-labs/desmos/pull/971?src=pr&el=footer&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=desmos-labs). Last update [c7ff50d...2997fc6](https://codecov.io/gh/desmos-labs/desmos/pull/971?src=pr&el=lastupdated&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=desmos-labs). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=desmos-labs).


Patch:
diff --git a/.changeset/entries/03035f411831a66120ac594cc09a140201357bb0f763287b8f49acda6efbed13.yaml b/.changeset/entries/03035f411831a66120ac594cc09a140201357bb0f763287b8f49acda6efbed13.yaml
new file mode 100644
index 00000000..7e8de59d
--- /dev/null
+++ b/.changeset/entries/03035f411831a66120ac594cc09a140201357bb0f763287b8f49acda6efbed13.yaml
@@ -0,0 +1,6 @@
+type: feat
+module: x/profiles
+pull_request: 968
+description: Added the support for EVM-specific chain link signatures
+backward_compatible: false
+date: 2022-07-18T11:42:01.267511323Z
diff --git a/.changeset/entries/e8fdc65b9f41e85409395d7e7b317f59f6d7be1ff3f8a92ebb30dafeb3254d4e.yaml b/.changeset/entries/e8fdc65b9f41e85409395d7e7b317f59f6d7be1ff3f8a92ebb30dafeb3254d4e.yaml
new file mode 100644
index 00000000..3c7352cf
--- /dev/null
+++ b/.changeset/entries/e8fdc65b9f41e85409395d7e7b317f59f6d7be1ff3f8a92ebb30dafeb3254d4e.yaml
@@ -0,0 +1,6 @@
+type: fix
+module: x/profiles
+pull_request: 971
+description: `QueryProfile` now returns an error instead of `nil` when a profile is not found
+backward_compatible: false
+date: 2022-07-22T06:27:36.4265228Z
diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml
index 672ec97d..1a51d43b 100644
--- a/.github/workflows/docs.yml
+++ b/.github/workflows/docs.yml
@@ -38,7 +38,7 @@ jobs:
 
       - name: Deploy 🚀
         if: github.ref == 'refs/heads/master'
-        uses: JamesIves/github-pages-deploy-action@v4.3.4
+        uses: JamesIves/github-pages-deploy-action@v4.4.0
         with:
           token: ${{ secrets.GITHUB_TOKEN }}
           branch: swagger-pages
diff --git a/Makefile b/Makefile
index f9d89c57..77eaa97b 100644
--- a/Makefile
+++ b/Makefile
@@ -302,6 +302,20 @@ format:
 	find . -name '*.go' -type f -not -path "./vendor*" -not -path "*.git*" -not -name '*.pb.go' -not -path "./venv" | xargs goimports -w -local github.com/desmos-labs/desmos
 .PHONY: format
 
+###############################################################################
+###                                  Types                                  ###
+###############################################################################
+
+EVMOS_URL 		 = https://raw.githubusercontent.com/evmos/ethermint/v0.17.1/crypto/
+CRYPTO_TYPES 	 = types/crypto
+
+update-deps-types:
+	@mkdir -p $(CRYPTO_TYPES)/ethsecp256k1
+	@curl -sSL $(EVMOS_URL)/ethsecp256k1/keys.pb.go > $(CRYPTO_TYPES)/ethsecp256k1/keys.pb.go
+	@curl -sSL $(EVMOS_URL)/ethsecp256k1/ethsecp256k1.go > $(CRYPTO_TYPES)/ethsecp256k1/ethsecp256k1.go
+
+.PHONY: update-deps-types
+
 ###############################################################################
 ###                                Protobuf                                 ###
 ###############################################################################
@@ -349,7 +363,8 @@ GOGO_PROTO_URL   = https://raw.githubusercontent.com/regen-network/protobuf/cosm
 COSMOS_URL 		 = https://raw.githubusercontent.com/cosmos/cosmos-sdk/v0.45.4/proto/cosmos
 COSMOS_PROTO_URL = https://raw.githubusercontent.com/regen-network/cosmos-proto/master
 CONFIO_URL 		 = https://raw.githubusercontent.com/confio/ics23/v0.6.3
-IBC_URL 		 = https://raw.githubusercontent.com/cosmos/ibc-go/v3.0.0/proto/ibc
+IBC_URL 		 = https://raw.githubusercontent.com/cosmos/ibc-go/v3.1.0/proto/ibc
+EVMOS_URL 		 = https://raw.githubusercontent.com/evmos/ethermint/v0.17.1/proto/ethermint/
 
 TM_CRYPTO_TYPES     = third_party/proto/tendermint/crypto
 TM_ABCI_TYPES       = third_party/proto/tendermint/abci
@@ -362,7 +377,7 @@ GOGO_PROTO_TYPES    = third_party/proto/gogoproto
 COSMOS_TYPES 		= third_party/proto/cosmos
 COSMOS_PROTO_TYPES  = third_party/proto/cosmos_proto
 CONFIO_TYPES        = third_party/proto/confio
-IBC_TYPES		 	= third_party/proto/ibc
+EVMOS_TYPES 		= third_party/proto/evmos
 
 proto-update-deps:
 	@mkdir -p $(COSMOS_TYPES)/base/query/v1beta1
@@ -380,6 +395,9 @@ proto-update-deps:
 	@mkdir -p $(IBC_TYPES)/core/client/v1
 	@curl -sSL $(IBC_URL)/core/client/v1/client.proto > $(IBC_TYPES)/core/client/v1/client.proto
 
+	@mkdir -p $(EVMOS_TYPES)/crypto/v1/ethsecp256k1
+	@curl -sSL $(EVMOS_URL)crypto/v1/ethsecp256k1/keys.proto > $(EVMOS_TYPES)/crypto/v1/ethsecp256k1/keys.proto
+
 	@mkdir -p $(COSMOS_TYPES)/tx/signing/v1beta1
 	@curl -sSL $(COSMOS_URL)/tx/signing/v1beta1/signing.proto > $(COSMOS_TYPES)/tx/signing/v1beta1/signing.proto
 
diff --git a/app/desmos/cmd/chainlink/builder/multi/builder.go b/app/desmos/cmd/chainlink/builder/multi/builder.go
index 0e1dda93..405c0885 100644
--- a/app/desmos/cmd/chainlink/builder/multi/builder.go
+++ b/app/desmos/cmd/chainlink/builder/multi/builder.go
@@ -86,7 +86,7 @@ func (b *AccountChainLinkJSONBuilder) BuildChainLinkJSON(chain types.Chain) (uti
 		return utils.ChainLinkJSON{}, err
 	}
 
-	sigData, err := profilestypes.SignatureDataFromCosmosSignatureData(sigs[0].Data)
+	sigData, err := profilestypes.CosmosSignatureDataToSignature(sigs[0].Data)
 	if err != nil {
 		return utils.ChainLinkJSON{}, err
 	}
diff --git a/app/desmos/cmd/chainlink/builder/single/builder.go b/app/desmos/cmd/chainlink/builder/single/builder.go
index 72175dbd..0bc1f94f 100644
--- a/app/desmos/cmd/chainlink/builder/single/builder.go
+++ b/app/desmos/cmd/chainlink/builder/single/builder.go
@@ -6,7 +6,6 @@ import (
 	"github.com/cosmos/cosmos-sdk/crypto/hd"
 	"github.com/cosmos/cosmos-sdk/crypto/keyring"
 	sdk "github.com/cosmos/cosmos-sdk/types"
-	"github.com/cosmos/cosmos-sdk/types/tx/signing"
 
 	"github.com/desmos-labs/desmos/v4/app/desmos/cmd/chainlink/getter"
 	"github.com/desmos-labs/desmos/v4/app/desmos/cmd/chainlink/types"
@@ -54,14 +53,14 @@ func (b *AccountChainLinkJSONBuilder) BuildChainLinkJSON(chain types.Chain) (uti
 	if err != nil {
 		return utils.ChainLinkJSON{}, err
 	}
-	sigData := &profilestypes.SingleSignatureData{
-		Mode:      signing.SignMode_SIGN_MODE_DIRECT,
-		Signature: sig,
-	}
 
 	return utils.NewChainLinkJSON(
 		profilestypes.NewBech32Address(addr, chain.Prefix),
-		profilestypes.NewProof(pubkey, sigData, hex.EncodeToString(value)),
+		profilestypes.NewProof(
+			pubkey,
+			profilestypes.NewSingleSignature(profilestypes.SIGNATURE_VALUE_TYPE_RAW, sig),
+			hex.EncodeToString(value),
+		),
 		profilestypes.NewChainConfig(chain.Name),
 	), nil
 }
diff --git a/docs/architecture/adr-015-improve-chain-link-signature-support.md b/docs/architecture/adr-015-improve-chain-link-signature-support.md
index e21f8a89..94fb7a02 100644
--- a/docs/architecture/adr-015-improve-chain-link-signature-support.md
+++ b/docs/architecture/adr-015-improve-chain-link-signature-support.md
@@ -27,91 +27,98 @@ Considering each ecosystem usually has a third party wallet as a reference (let'
 
 In order to support most signature specifications as possible, we will define a `Signature` interface that will be implemented into two major instances: 
 
-- `CosmosSignature`, representing a signature that is generated by a Cosmos-compatible wallet (eg. Keplr)
-- `EVMSignature`, representing a signature that is generated by an EVM-compatible wallet (eg. MetaMask)
+- `SingleSignature`, representing a signature that is generated by a single signer;
+- `CosmosMultiSignature`, representing a signature that is generated by a Cosmos multi-signature wallet.
 
 ### `Signature`
 
-The `Signature` interface will represent a generic signature, and thus will have only a method that should be used to verify it: 
+The `Signature` interface will represent a generic signature, and thus will have only a method that should be used to validate it and another one used to verify it: 
 
 ```go
 // Signature represents a generic signature data
 type Signature interface {
-	// Verify allows to verify this signature using the given public key against the given plain text
-	Verify(pubKey *any.Any, plainText string) error
+    // Validate checks the validity of the Signature
+    Validate(cdc codec.BinaryCodec, amino *codec.LegacyAmino, plainText []byte, owner string) error
+
+    // Verify allows to verify this signature using the given public key against the given plain text.
+    // If the signature is valid, it returns the public key instance used to verify it
+    Verify(cdc codec.BinaryCodec, pubKey *codectypes.Any, plainText []byte) (cryptotypes.PubKey, error)
 }
 
 ```
 
-### `CosmosSignature`
+### `SingleSignature`
 
-The `CosmosSignature` implementation of the `Signature` interface will be as follows: 
+The `SingleSignature` implementation of the `Signature` interface will be as follows: 
 
 ```protobuf
 syntax = "proto3";
 
-// CosmosSignature represents a signature generated using a Cosmos-compatible wallet 
-message CosmosSignature {
-  // Encoding of the signed value 
-  ValueEncoding value_encoding = 1;
-  
-  // Data of the signature
-  google.protobuf.Any signature_data = 2;
-  
-  // ValueEncoding contains the different kinds of value encoding that the signature can have
-  enum ValueEncoding {
-    // Unknown should never be used
-    Unknown = 0;
-    
-    // TXLegacyAmino should be used when the signed value is an Amino transaction, containing the address inside its memo 
-    TXLegacyAmino = 1;
-    
-    // TXDirect should be used when the signed value is a Protobuf transaction containing the address inside its memo
-    TXDirect = 2;
-    
-    // Textual should be used when the signed value is the address itself
-    Textual = 3;
-  }
-}
+// SingleSignature is the signature data for a single signer
+message SingleSignature {
+  option (gogoproto.goproto_getters) = false;
+  option (gogoproto.equal) = true;
+  option (cosmos_proto.implements_interface) = "CosmosSignature";
+
+  // ValueEncoding represents how the value has been encoded before being signed
+  SignatureValueEncoding value_encoding = 1
+  [ (gogoproto.moretags) = "yaml:\"value_encoding\"" ];
 
-// CosmosSingleSignatureData contains the signature data of a single Cosmos-compatible signature
-message CosmosSingleSignatureData {
-  // Raw signature bytes
-  bytes signature = 1;
+  // Signature is the raw signature bytes
+  bytes signature = 2 [ (gogoproto.moretags) = "yaml:\"signature\"" ];
 }
 
-// CosmosMultiSignatureData contains the signature data of a Cosmos-compatible multisig
-message CosmosMultiSignatureData {
-  // Bitarray specifies which keys within the multisig are signing
-  cosmos.crypto.multisig.v1beta1.CompactBitArray bit_array = 1;
+// SignatureValueEncoding tells how the value has been encoded before being
+// signed
+enum SignatureValueEncoding {
+  option (gogoproto.goproto_enum_prefix) = false;
+
+  // SIGNATURE_VALUE_ENCODING_UNSPECIFIED specifies an unknown signing mode and
+  // will be rejected
+  SIGNATURE_VALUE_ENCODING_UNSPECIFIED = 0;
 
-  // Signatures of the multi-signature
-  repeated google.protobuf.Any signatures = 2;
+  // SIGNATURE_VALUE_ENCODING_RAW should be used when the value has been signed
+  // as a raw byte array
+  SIGNATURE_VALUE_ENCODING_RAW = 1;
+
+  // SIGNATURE_VALUE_ENCODING_COSMOS_DIRECT should be used when the signed value
+  // has been encoded as a Protobuf transaction containing the owner address
+  // inside its memo field
+  SIGNATURE_VALUE_ENCODING_COSMOS_DIRECT = 2;
+
+  // SIGNATURE_VALUE_ENCODING_COSMOS_AMINO should be used when the value has
+  // been encoded as an Amino transaction containing the owner address inside
+  // its memo field
+  SIGNATURE_VALUE_ENCODING_COSMOS_AMINO = 3;
+
+  // SIGNATURE_VALUE_ENCODING_EVM_PERSONAL_SIGN should be used when the value
+  // has been encoded following the EVM personal_sign specification
+  SIGNATURE_VALUE_ENCODING_EVM_PERSONAL_SIGN = 4;
 }
 ```
 
-### `EVMSignature`
+### `CosmosMultiSignature`
 
-The `EVMSignature` implementation of the `Signature` interface will be as follows:
+The `CosmosMultiSignature` implementation of the `Signature` interface will be as follows:
 
 ```protobuf
 syntax = "proto3";
 
-// EVMSignature contains the data of a signature generated using an EVM-compatible wallet
-message EVMSignature {
-  // Method used when generating the signature
-  Method signing_method = 1;
-  
-  // Raw signature bytes
-  bytes signature = 2;
-  
-  enum Method {
-    // Unknown should never be used
-    Unknown = 0;
-    
-    // PersonalSign should be used when the value has been signed using the personal_sign signature method
-    PersonalSign = 1;
-  }
+// CosmosMultiSignature is the signature data for a multisig public key
+message CosmosMultiSignature {
+  option (gogoproto.goproto_getters) = false;
+  option (gogoproto.equal) = true;
+  option (cosmos_proto.implements_interface) = "CosmosSignature";
+
+  // Bitarray specifies which keys within the multisig are signing
+  cosmos.crypto.multisig.v1beta1.CompactBitArray bit_array = 1
+  [ (gogoproto.moretags) = "yaml:\"bit_array\"" ];
+
+  // Signatures is the signatures of the multi-signature
+  repeated google.protobuf.Any signatures = 2 [
+    (cosmos_proto.accepts_interface) = "CosmosSignature",
+    (gogoproto.moretags) = "yaml:\"signatures\""
+  ];
 }
 ```
 
@@ -120,10 +127,10 @@ message EVMSignature {
 ### Backwards Compatibility
 
 The proposed solution is partially backward compatible, but a store migration is still required. Particularly, for each link:
-- all `SingleSignatureData` instances should be converted to `CosmosSignature` containing a `CosmosSingleSignatureData`; 
-- all `MultiSignatureData` instances should be converted to `CosmosSignature` containing a `CosmosMultiSignatureData`;
+- all `SingleSignatureData` instances should be converted to `SingleSignature`; 
+- all `MultiSignatureData` instances should be converted to `CosmosMultiSignature`;
 
-Also, the `Proof#Verify` method must be updated in order to not check for different signature types, but to simply rely on the `Signature#Verify` method instead.
+Also, the `Proof#Verify` method must be updated in order to not check for different signature types, but to simply rely on the `Signature#Validate` and `Signature#Verify` methods instead.
 
 ### Positive
 
diff --git a/go.mod b/go.mod
index 4afc7092..0d745f89 100644
--- a/go.mod
+++ b/go.mod
@@ -13,7 +13,7 @@ require (
 	github.com/ghodss/yaml v1.0.0
 	github.com/gogo/protobuf v1.3.3
 	github.com/golang/protobuf v1.5.2
-	github.com/golangci/golangci-lint v1.47.1
+	github.com/golangci/golangci-lint v1.47.2
 	github.com/gorilla/mux v1.8.0
 	github.com/grpc-ecosystem/grpc-gateway v1.16.0
 	github.com/manifoldco/promptui v0.9.0
@@ -242,7 +242,7 @@ require (
 	golang.org/x/exp/typeparams v0.0.0-20220613132600-b0d781184e0d // indirect
 	golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect
 	golang.org/x/net v0.0.0-20220520000938-2e3eb7b945c2 // indirect
-	golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect
+	golang.org/x/sync v0.0.0-20220513210516-0976fa681c29 // indirect
 	golang.org/x/sys v0.0.0-20220702020025-31831981b65f // indirect
 	golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect
 	golang.org/x/text v0.3.7 // indirect
diff --git a/go.sum b/go.sum
index 6c97c6ae..daddf442 100644
--- a/go.sum
+++ b/go.sum
@@ -608,8 +608,8 @@ github.com/golangci/go-misc v0.0.0-20220329215616-d24fe342adfe h1:6RGUuS7EGotKx6
 github.com/golangci/go-misc v0.0.0-20220329215616-d24fe342adfe/go.mod h1:gjqyPShc/m8pEMpk0a3SeagVb0kaqvhscv+i9jI5ZhQ=
 github.com/golangci/gofmt v0.0.0-20190930125516-244bba706f1a h1:iR3fYXUjHCR97qWS8ch1y9zPNsgXThGwjKPrYfqMPks=
 github.com/golangci/gofmt v0.0.0-20190930125516-244bba706f1a/go.mod h1:9qCChq59u/eW8im404Q2WWTrnBUQKjpNYKMbU4M7EFU=
-github.com/golangci/golangci-lint v1.47.1 h1:hbubHskV2Ppwz4ZZE2lc0/Pw9ZhqLuzm2dT7ZVpLA6Y=
-github.com/golangci/golangci-lint v1.47.1/go.mod h1:lpS2pjBZtRyXewUcOY7yUL3K4KfpoWz072yRN8AuhHg=
+github.com/golangci/golangci-lint v1.47.2 h1:qvMDVv49Hrx3PSEXZ0bD/yhwSbhsOihQjFYCKieegIw=
+github.com/golangci/golangci-lint v1.47.2/go.mod h1:lpS2pjBZtRyXewUcOY7yUL3K4KfpoWz072yRN8AuhHg=
 github.com/golangci/lint-1 v0.0.0-20181222135242-d2cdd8c08219/go.mod h1:/X8TswGSh1pIozq4ZwCfxS0WA5JGXguxk94ar/4c87Y=
 github.com/golangci/lint-1 v0.0.0-20191013205115-297bf364a8e0 h1:MfyDlzVjl1hoaPzPD4Gpb/QgoRfSBR0jdhwGyAWwMSA=
 github.com/golangci/lint-1 v0.0.0-20191013205115-297bf364a8e0/go.mod h1:66R6K6P6VWk9I95jvqGxkqJxVWGFy9XlDwLwVz1RCFg=
@@ -1784,7 +1784,6 @@ golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJ
 golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ=
 golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20220513210516-0976fa681c29 h1:w8s32wxx3sY+OjLlv9qltkLU5yvJzxjjgiHWLjdIcw4=
 golang.org/x/sync v0.0.0-20220513210516-0976fa681c29/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
diff --git a/proto/desmos/profiles/v3/models_chain_links.proto b/proto/desmos/profiles/v3/models_chain_links.proto
index 12190a2a..c0635e48 100644
--- a/proto/desmos/profiles/v3/models_chain_links.proto
+++ b/proto/desmos/profiles/v3/models_chain_links.proto
@@ -66,14 +66,18 @@ message Proof {
   google.protobuf.Any pub_key = 1 [ (gogoproto.moretags) = "yaml:\"pub_key\"" ];
 
   // Signature represents the hex-encoded signature of the PlainText value
-  google.protobuf.Any signature = 2
-      [ (gogoproto.moretags) = "yaml:\"signature\"" ];
+  google.protobuf.Any signature = 2 [
+    (cosmos_proto.accepts_interface) = "Signature",
+    (gogoproto.moretags) = "yaml:\"signature\""
+  ];
 
   // PlainText represents the hex-encoded value signed in order to produce the
   // Signature
   string plain_text = 3 [ (gogoproto.moretags) = "yaml:\"plain_text\"" ];
 }
 
+// --------------------------------------------------------------------------------------------------------------------
+
 // Bech32Address represents a Bech32-encoded address
 message Bech32Address {
   option (gogoproto.goproto_getters) = false;
@@ -115,28 +119,62 @@ message HexAddress {
   string prefix = 2 [ (gogoproto.moretags) = "yaml:\"prefix\"" ];
 }
 
-// SingleSignatureData is the signature data for a single signer
-message SingleSignatureData {
+// --------------------------------------------------------------------------------------------------------------------
+
+// SingleSignature is the signature data for a single signer
+message SingleSignature {
   option (gogoproto.goproto_getters) = false;
   option (gogoproto.equal) = true;
-  option (cosmos_proto.implements_interface) = "SignatureData";
+  option (cosmos_proto.implements_interface) = "Signature";
 
-  // Mode is the signing mode of the single signer
-  cosmos.tx.signing.v1beta1.SignMode mode = 1;
+  // Type represents the type of the signature value
+  SignatureValueType value_type = 1
+      [ (gogoproto.moretags) = "yaml:\"value_type\"" ];
 
   // Signature is the raw signature bytes
-  bytes signature = 2;
+  bytes signature = 2 [ (gogoproto.moretags) = "yaml:\"signature\"" ];
 }
 
-// MultiSignatureData is the signature data for a multisig public key
-message MultiSignatureData {
+// SignatureValueType specifies all the possible signature types
+enum SignatureValueType {
+  option (gogoproto.goproto_enum_prefix) = false;
+
+  // SIGNATURE_VALUE_TYPE_UNSPECIFIED specifies an unknown signing mode
+  // and will be rejected
+  SIGNATURE_VALUE_TYPE_UNSPECIFIED = 0;
+
+  // SIGNATURE_VALUE_TYPE_RAW should be used when the value has been
+  // signed as a raw byte array
+  SIGNATURE_VALUE_TYPE_RAW = 1;
+
+  // SIGNATURE_VALUE_TYPE_COSMOS_DIRECT should be used when the signed
+  // value has been encoded as a Protobuf transaction containing the owner
+  // address inside its memo field
+  SIGNATURE_VALUE_TYPE_COSMOS_DIRECT = 2;
+
+  // SIGNATURE_VALUE_TYPE_COSMOS_AMINO should be used when the value has
+  // been encoded as an Amino transaction containing the owner address inside
+  // its memo field
+  SIGNATURE_VALUE_TYPE_COSMOS_AMINO = 3;
+
+  // SIGNATURE_VALUE_TYPE_EVM_PERSONAL_SIGN should be used when the value
+  // has been encoded following the EVM personal_sign specification
+  SIGNATURE_VALUE_TYPE_EVM_PERSONAL_SIGN = 4;
+}
+
+// CosmosMultiSignature is the signature data for a multisig public key
+message CosmosMultiSignature {
   option (gogoproto.goproto_getters) = false;
   option (gogoproto.equal) = true;
-  option (cosmos_proto.implements_interface) = "SignatureData";
+  option (cosmos_proto.implements_interface) = "Signature";
 
   // Bitarray specifies which keys within the multisig are signing
-  cosmos.crypto.multisig.v1beta1.CompactBitArray bit_array = 1;
+  cosmos.crypto.multisig.v1beta1.CompactBitArray bit_array = 1
+      [ (gogoproto.moretags) = "yaml:\"bit_array\"" ];
 
   // Signatures is the signatures of the multi-signature
-  repeated google.protobuf.Any signatures = 2;
+  repeated google.protobuf.Any signatures = 2 [
+    (cosmos_proto.accepts_interface) = "Signature",
+    (gogoproto.moretags) = "yaml:\"signatures\""
+  ];
 }
\ No newline at end of file
diff --git a/third_party/proto/evmos/crypto/v1/ethsecp256k1/keys.proto b/third_party/proto/evmos/crypto/v1/ethsecp256k1/keys.proto
new file mode 100644
index 00000000..4bde4739
--- /dev/null
+++ b/third_party/proto/evmos/crypto/v1/ethsecp256k1/keys.proto
@@ -0,0 +1,19 @@
+syntax = "proto3";
+package ethermint.crypto.v1.ethsecp256k1;
+
+import "gogoproto/gogo.proto";
+
+option go_package = "github.com/evmos/ethermint/crypto/ethsecp256k1";
+
+// PubKey defines a type alias for an ecdsa.PublicKey that implements
+// Tendermint's PubKey interface. It represents the 33-byte compressed public
+// key format.
+message PubKey {
+  option (gogoproto.goproto_stringer) = false;
+
+  bytes key = 1;
+}
+
+// PrivKey defines a type alias for an ecdsa.PrivateKey that implements
+// Tendermint's PrivateKey interface.
+message PrivKey { bytes key = 1; }
diff --git a/types/crypto/ethsecp256k1/ethsecp256k1.go b/types/crypto/ethsecp256k1/ethsecp256k1.go
new file mode 100644
index 00000000..38f16c33
--- /dev/null
+++ b/types/crypto/ethsecp256k1/ethsecp256k1.go
@@ -0,0 +1,217 @@
+package ethsecp256k1
+
+import (
+	"bytes"
+	"crypto/ecdsa"
+	"crypto/subtle"
+	"fmt"
+
+	"github.com/cosmos/cosmos-sdk/codec"
+	cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
+	sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
+	"github.com/ethereum/go-ethereum/crypto"
+
+	tmcrypto "github.com/tendermint/tendermint/crypto"
+)
+
+const (
+	// PrivKeySize defines the size of the PrivKey bytes
+	PrivKeySize = 32
+	// PubKeySize defines the size of the PubKey bytes
+	PubKeySize = 33
+	// KeyType is the string constant for the Secp256k1 algorithm
+	KeyType = "eth_secp256k1"
+)
+
+// Amino encoding names
+const (
+	// PrivKeyName defines the amino encoding name for the EthSecp256k1 private key
+	PrivKeyName = "ethermint/PrivKeyEthSecp256k1"
+	// PubKeyName defines the amino encoding name for the EthSecp256k1 public key
+	PubKeyName = "ethermint/PubKeyEthSecp256k1"
+)
+
+// ----------------------------------------------------------------------------
+// secp256k1 Private Key
+
+var (
+	_ cryptotypes.PrivKey  = &PrivKey{}
+	_ codec.AminoMarshaler = &PrivKey{}
+)
+
+// GenerateKey generates a new random private key. It returns an error upon
+// failure.
+func GenerateKey() (*PrivKey, error) {
+	priv, err := crypto.GenerateKey()
+	if err != nil {
+		return nil, err
+	}
+
+	return &PrivKey{
+		Key: crypto.FromECDSA(priv),
+	}, nil
+}
+
+// Bytes returns the byte representation of the ECDSA Private Key.
+func (privKey PrivKey) Bytes() []byte {
+	bz := make([]byte, len(privKey.Key))
+	copy(bz, privKey.Key)
+
+	return bz
+}
+
+// PubKey returns the ECDSA private key's public key. If the privkey is not valid
+// it returns a nil value.
+func (privKey PrivKey) PubKey() cryptotypes.PubKey {
+	ecdsaPrivKey, err := privKey.ToECDSA()
+	if err != nil {
+		return nil
+	}
+
+	return &PubKey{
+		Key: crypto.CompressPubkey(&ecdsaPrivKey.PublicKey),
+	}
+}
+
+// Equals returns true if two ECDSA private keys are equal and false otherwise.
+func (privKey PrivKey) Equals(other cryptotypes.LedgerPrivKey) bool {
+	return privKey.Type() == other.Type() && subtle.ConstantTimeCompare(privKey.Bytes(), other.Bytes()) == 1
+}
+
+// Type returns eth_secp256k1
+func (privKey PrivKey) Type() string {
+	return KeyType
+}
+
+// MarshalAmino overrides Amino binary marshaling.
+func (privKey PrivKey) MarshalAmino() ([]byte, error) {
+	return privKey.Key, nil
+}
+
+// UnmarshalAmino overrides Amino binary marshaling.
+func (privKey *PrivKey) UnmarshalAmino(bz []byte) error {
+	if len(bz) != PrivKeySize {
+		return fmt.Errorf("invalid privkey size, expected %d got %d", PrivKeySize, len(bz))
+	}
+	privKey.Key = bz
+
+	return nil
+}
+
+// MarshalAminoJSON overrides Amino JSON marshaling.
+func (privKey PrivKey) MarshalAminoJSON() ([]byte, error) {
+	// When we marshal to Amino JSON, we don't marshal the "key" field itself,
+	// just its contents (i.e. the key bytes).
+	return privKey.MarshalAmino()
+}
+
+// UnmarshalAminoJSON overrides Amino JSON marshaling.
+func (privKey *PrivKey) UnmarshalAminoJSON(bz []byte) error {
+	return privKey.UnmarshalAmino(bz)
+}
+
+// Sign creates a recoverable ECDSA signature on the secp256k1 curve over the
+// provided hash of the message. The produced signature is 65 bytes
+// where the last byte contains the recovery ID.
+func (privKey PrivKey) Sign(digestBz []byte) ([]byte, error) {
+	// TODO: remove
+	if len(digestBz) != crypto.DigestLength {
+		digestBz = crypto.Keccak256Hash(digestBz).Bytes()
+	}
+
+	key, err := privKey.ToECDSA()
+	if err != nil {
+		return nil, err
+	}
+
+	return crypto.Sign(digestBz, key)
+}
+
+// ToECDSA returns the ECDSA private key as a reference to ecdsa.PrivateKey type.
+func (privKey PrivKey) ToECDSA() (*ecdsa.PrivateKey, error) {
+	return crypto.ToECDSA(privKey.Bytes())
+}
+
+// ----------------------------------------------------------------------------
+// secp256k1 Public Key
+
+var (
+	_ cryptotypes.PubKey   = &PubKey{}
+	_ codec.AminoMarshaler = &PubKey{}
+)
+
+// Address returns the address of the ECDSA public key.
+// The function will return an empty address if the public key is invalid.
+func (pubKey PubKey) Address() tmcrypto.Address {
+	pubk, err := crypto.DecompressPubkey(pubKey.Key)
+	if err != nil {
+		return nil
+	}
+
+	return tmcrypto.Address(crypto.PubkeyToAddress(*pubk).Bytes())
+}
+
+// Bytes returns the raw bytes of the ECDSA public key.
+func (pubKey PubKey) Bytes() []byte {
+	bz := make([]byte, len(pubKey.Key))
+	copy(bz, pubKey.Key)
+
+	return bz
+}
+
+// String implements the fmt.Stringer interface.
+func (pubKey PubKey) String() string {
+	return fmt.Sprintf("EthPubKeySecp256k1{%X}", pubKey.Key)
+}
+
+// Type returns eth_secp256k1
+func (pubKey PubKey) Type() string {
+	return KeyType
+}
+
+// Equals returns true if the pubkey type is the same and their bytes are deeply equal.
+func (pubKey PubKey) Equals(other cryptotypes.PubKey) bool {
+	return pubKey.Type() == other.Type() && bytes.Equal(pubKey.Bytes(), other.Bytes())
+}
+
+// MarshalAmino overrides Amino binary marshaling.
+func (pubKey PubKey) MarshalAmino() ([]byte, error) {
+	return pubKey.Key, nil
+}
+
+// UnmarshalAmino overrides Amino binary marshaling.
+func (pubKey *PubKey) UnmarshalAmino(bz []byte) error {
+	if len(bz) != PubKeySize {
+		return sdkerrors.Wrapf(sdkerrors.ErrInvalidPubKey, "invalid pubkey size, expected %d, got %d", PubKeySize, len(bz))
+	}
+	pubKey.Key = bz
+
+	return nil
+}
+
+// MarshalAminoJSON overrides Amino JSON marshaling.
+func (pubKey PubKey) MarshalAminoJSON() ([]byte, error) {
+	// When we marshal to Amino JSON, we don't marshal the "key" field itself,
+	// just its contents (i.e. the key bytes).
+	return pubKey.MarshalAmino()
+}
+
+// UnmarshalAminoJSON overrides Amino JSON marshaling.
+func (pubKey *PubKey) UnmarshalAminoJSON(bz []byte) error {
+	return pubKey.UnmarshalAmino(bz)
+}
+
+// VerifySignature verifies that the ECDSA public key created a given signature over
+// the provided message. It will calculate the Keccak256 hash of the message
+// prior to verification.
+//
+// CONTRACT: The signature should be in [R || S] format.
+func (pubKey PubKey) VerifySignature(msg, sig []byte) bool {
+	if len(sig) == crypto.SignatureLength {
+		// remove recovery ID (V) if contained in the signature
+		sig = sig[:len(sig)-1]
+	}
+
+	// the signature needs to be in [R || S] format when provided to VerifySignature
+	return crypto.VerifySignature(pubKey.Key, crypto.Keccak256Hash(msg).Bytes(), sig)
+}
diff --git a/types/crypto/ethsecp256k1/keys.pb.go b/types/crypto/ethsecp256k1/keys.pb.go
new file mode 100644
index 00000000..7b3fb6e3
--- /dev/null
+++ b/types/crypto/ethsecp256k1/keys.pb.go
@@ -0,0 +1,498 @@
+// Code generated by protoc-gen-gogo. DO NOT EDIT.
+// source: ethermint/crypto/v1/ethsecp256k1/keys.proto
+
+package ethsecp256k1
+
+import (
+	fmt "fmt"
+	_ "github.com/gogo/protobuf/gogoproto"
+	proto "github.com/gogo/protobuf/proto"
+	io "io"
+	math "math"
+	math_bits "math/bits"
+)
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
+
+// PubKey defines a type alias for an ecdsa.PublicKey that implements
+// Tendermint's PubKey interface. It represents the 33-byte compressed public
+// key format.
+type PubKey struct {
+	Key []byte `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"`
+}
+
+func (m *PubKey) Reset()      { *m = PubKey{} }
+func (*PubKey) ProtoMessage() {}
+func (*PubKey) Descriptor() ([]byte, []int) {
+	return fileDescriptor_0c10cadcf35beb64, []int{0}
+}
+func (m *PubKey) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *PubKey) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	if deterministic {
+		return xxx_messageInfo_PubKey.Marshal(b, m, deterministic)
+	} else {
+		b = b[:cap(b)]
+		n, err := m.MarshalToSizedBuffer(b)
+		if err != nil {
+			return nil, err
+		}
+		return b[:n], nil
+	}
+}
+func (m *PubKey) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_PubKey.Merge(m, src)
+}
+func (m *PubKey) XXX_Size() int {
+	return m.Size()
+}
+func (m *PubKey) XXX_DiscardUnknown() {
+	xxx_messageInfo_PubKey.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_PubKey proto.InternalMessageInfo
+
+func (m *PubKey) GetKey() []byte {
+	if m != nil {
+		return m.Key
+	}
+	return nil
+}
+
+// PrivKey defines a type alias for an ecdsa.PrivateKey that implements
+// Tendermint's PrivateKey interface.
+type PrivKey struct {
+	Key []byte `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"`
+}
+
+func (m *PrivKey) Reset()         { *m = PrivKey{} }
+func (m *PrivKey) String() string { return proto.CompactTextString(m) }
+func (*PrivKey) ProtoMessage()    {}
+func (*PrivKey) Descriptor() ([]byte, []int) {
+	return fileDescriptor_0c10cadcf35beb64, []int{1}
+}
+func (m *PrivKey) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *PrivKey) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	if deterministic {
+		return xxx_messageInfo_PrivKey.Marshal(b, m, deterministic)
+	} else {
+		b = b[:cap(b)]
+		n, err := m.MarshalToSizedBuffer(b)
+		if err != nil {
+			return nil, err
+		}
+		return b[:n], nil
+	}
+}
+func (m *PrivKey) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_PrivKey.Merge(m, src)
+}
+func (m *PrivKey) XXX_Size() int {
+	return m.Size()
+}
+func (m *PrivKey) XXX_DiscardUnknown() {
+	xxx_messageInfo_PrivKey.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_PrivKey proto.InternalMessageInfo
+
+func (m *PrivKey) GetKey() []byte {
+	if m != nil {
+		return m.Key
+	}
+	return nil
+}
+
+func init() {
+	proto.RegisterType((*PubKey)(nil), "ethermint.crypto.v1.ethsecp256k1.PubKey")
+	proto.RegisterType((*PrivKey)(nil), "ethermint.crypto.v1.ethsecp256k1.PrivKey")
+}
+
+func init() {
+	proto.RegisterFile("ethermint/crypto/v1/ethsecp256k1/keys.proto", fileDescriptor_0c10cadcf35beb64)
+}
+
+var fileDescriptor_0c10cadcf35beb64 = []byte{
+	// 194 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xd2, 0x4e, 0x2d, 0xc9, 0x48,
+	0x2d, 0xca, 0xcd, 0xcc, 0x2b, 0xd1, 0x4f, 0x2e, 0xaa, 0x2c, 0x28, 0xc9, 0xd7, 0x2f, 0x33, 0xd4,
+	0x4f, 0x2d, 0xc9, 0x28, 0x4e, 0x4d, 0x2e, 0x30, 0x32, 0x35, 0xcb, 0x36, 0xd4, 0xcf, 0x4e, 0xad,
+	0x2c, 0xd6, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x52, 0x80, 0x2b, 0xd6, 0x83, 0x28, 0xd6, 0x2b,
+	0x33, 0xd4, 0x43, 0x56, 0x2c, 0x25, 0x92, 0x9e, 0x9f, 0x9e, 0x0f, 0x56, 0xac, 0x0f, 0x62, 0x41,
+	0xf4, 0x29, 0x29, 0x70, 0xb1, 0x05, 0x94, 0x26, 0x79, 0xa7, 0x56, 0x0a, 0x09, 0x70, 0x31, 0x67,
+	0xa7, 0x56, 0x4a, 0x30, 0x2a, 0x30, 0x6a, 0xf0, 0x04, 0x81, 0x98, 0x56, 0x2c, 0x33, 0x16, 0xc8,
+	0x33, 0x28, 0x49, 0x73, 0xb1, 0x07, 0x14, 0x65, 0x96, 0x61, 0x55, 0xe2, 0xe4, 0x71, 0xe2, 0x91,
+	0x1c, 0xe3, 0x85, 0x47, 0x72, 0x8c, 0x0f, 0x1e, 0xc9, 0x31, 0x4e, 0x78, 0x2c, 0xc7, 0x70, 0xe1,
+	0xb1, 0x1c, 0xc3, 0x8d, 0xc7, 0x72, 0x0c, 0x51, 0x7a, 0xe9, 0x99, 0x25, 0x19, 0xa5, 0x49, 0x7a,
+	0xc9, 0xf9, 0xb9, 0xfa, 0xa9, 0x65, 0xb9, 0xf9, 0xc5, 0xfa, 0x18, 0xde, 0x41, 0x76, 0x5e, 0x12,
+	0x1b, 0xd8, 0x3d, 0xc6, 0x80, 0x00, 0x00, 0x00, 0xff, 0xff, 0x9f, 0x29, 0x7b, 0x24, 0xf6, 0x00,
+	0x00, 0x00,
+}
+
+func (m *PubKey) Marshal() (dAtA []byte, err error) {
+	size := m.Size()
+	dAtA = make([]byte, size)
+	n, err := m.MarshalToSizedBuffer(dAtA[:size])
+	if err != nil {
+		return nil, err
+	}
+	return dAtA[:n], nil
+}
+
+func (m *PubKey) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *PubKey) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	_ = i
+	var l int
+	_ = l
+	if len(m.Key) > 0 {
+		i -= len(m.Key)
+		copy(dAtA[i:], m.Key)
+		i = encodeVarintKeys(dAtA, i, uint64(len(m.Key)))
+		i--
+		dAtA[i] = 0xa
+	}
+	return len(dAtA) - i, nil
+}
+
+func (m *PrivKey) Marshal() (dAtA []byte, err error) {
+	size := m.Size()
+	dAtA = make([]byte, size)
+	n, err := m.MarshalToSizedBuffer(dAtA[:size])
+	if err != nil {
+		return nil, err
+	}
+	return dAtA[:n], nil
+}
+
+func (m *PrivKey) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *PrivKey) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	_ = i
+	var l int
+	_ = l
+	if len(m.Key) > 0 {
+		i -= len(m.Key)
+		copy(dAtA[i:], m.Key)
+		i = encodeVarintKeys(dAtA, i, uint64(len(m.Key)))
+		i--
+		dAtA[i] = 0xa
+	}
+	return len(dAtA) - i, nil
+}
+
+func encodeVarintKeys(dAtA []byte, offset int, v uint64) int {
+	offset -= sovKeys(v)
+	base := offset
+	for v >= 1<<7 {
+		dAtA[offset] = uint8(v&0x7f | 0x80)
+		v >>= 7
+		offset++
+	}
+	dAtA[offset] = uint8(v)
+	return base
+}
+func (m *PubKey) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	l = len(m.Key)
+	if l > 0 {
+		n += 1 + l + sovKeys(uint64(l))
+	}
+	return n
+}
+
+func (m *PrivKey) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	l = len(m.Key)
+	if l > 0 {
+		n += 1 + l + sovKeys(uint64(l))
+	}
+	return n
+}
+
+func sovKeys(x uint64) (n int) {
+	return (math_bits.Len64(x|1) + 6) / 7
+}
+func sozKeys(x uint64) (n int) {
+	return sovKeys(uint64((x << 1) ^ uint64((int64(x) >> 63))))
+}
+func (m *PubKey) Unmarshal(dAtA []byte) error {
+	l := len(dAtA)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowKeys
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= uint64(b&0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: PubKey: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: PubKey: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Key", wireType)
+			}
+			var byteLen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowKeys
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				byteLen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if byteLen < 0 {
+				return ErrInvalidLengthKeys
+			}
+			postIndex := iNdEx + byteLen
+			if postIndex < 0 {
+				return ErrInvalidLengthKeys
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.Key = append(m.Key[:0], dAtA[iNdEx:postIndex]...)
+			if m.Key == nil {
+				m.Key = []byte{}
+			}
+			iNdEx = postIndex
+		default:
+			iNdEx = preIndex
+			skippy, err := skipKeys(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if (skippy < 0) || (iNdEx+skippy) < 0 {
+				return ErrInvalidLengthKeys
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func (m *PrivKey) Unmarshal(dAtA []byte) error {
+	l := len(dAtA)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowKeys
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= uint64(b&0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: PrivKey: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: PrivKey: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Key", wireType)
+			}
+			var byteLen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowKeys
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				byteLen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if byteLen < 0 {
+				return ErrInvalidLengthKeys
+			}
+			postIndex := iNdEx + byteLen
+			if postIndex < 0 {
+				return ErrInvalidLengthKeys
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.Key = append(m.Key[:0], dAtA[iNdEx:postIndex]...)
+			if m.Key == nil {
+				m.Key = []byte{}
+			}
+			iNdEx = postIndex
+		default:
+			iNdEx = preIndex
+			skippy, err := skipKeys(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if (skippy < 0) || (iNdEx+skippy) < 0 {
+				return ErrInvalidLengthKeys
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func skipKeys(dAtA []byte) (n int, err error) {
+	l := len(dAtA)
+	iNdEx := 0
+	depth := 0
+	for iNdEx < l {
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return 0, ErrIntOverflowKeys
+			}
+			if iNdEx >= l {
+				return 0, io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= (uint64(b) & 0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		wireType := int(wire & 0x7)
+		switch wireType {
+		case 0:
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return 0, ErrIntOverflowKeys
+				}
+				if iNdEx >= l {
+					return 0, io.ErrUnexpectedEOF
+				}
+				iNdEx++
+				if dAtA[iNdEx-1] < 0x80 {
+					break
+				}
+			}
+		case 1:
+			iNdEx += 8
+		case 2:
+			var length int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return 0, ErrIntOverflowKeys
+				}
+				if iNdEx >= l {
+					return 0, io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				length |= (int(b) & 0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if length < 0 {
+				return 0, ErrInvalidLengthKeys
+			}
+			iNdEx += length
+		case 3:
+			depth++
+		case 4:
+			if depth == 0 {
+				return 0, ErrUnexpectedEndOfGroupKeys
+			}
+			depth--
+		case 5:
+			iNdEx += 4
+		default:
+			return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
+		}
+		if iNdEx < 0 {
+			return 0, ErrInvalidLengthKeys
+		}
+		if depth == 0 {
+			return iNdEx, nil
+		}
+	}
+	return 0, io.ErrUnexpectedEOF
+}
+
+var (
+	ErrInvalidLengthKeys        = fmt.Errorf("proto: negative length found during unmarshaling")
+	ErrIntOverflowKeys          = fmt.Errorf("proto: integer overflow")
+	ErrUnexpectedEndOfGroupKeys = fmt.Errorf("proto: unexpected end of group")
+)
diff --git a/x/profiles/keeper/grpc_query.go b/x/profiles/keeper/grpc_query.go
index c8f33183..681bbda6 100644
--- a/x/profiles/keeper/grpc_query.go
+++ b/x/profiles/keeper/grpc_query.go
@@ -47,7 +47,7 @@ func (k Keeper) Profile(ctx context.Context, request *types.QueryProfileRequest)
 	}
 
 	if !found {
-		return &types.QueryProfileResponse{Profile: nil}, nil
+		return nil, status.Errorf(codes.NotFound, "profile for dtag/address %s not found", dTagOrAddress)
 	}
 
 	accountAny, err := codectypes.NewAnyWithValue(account)
diff --git a/x/profiles/legacy/v6/store.go b/x/profiles/legacy/v6/store.go
index 64feb710..434a8027 100644
--- a/x/profiles/legacy/v6/store.go
+++ b/x/profiles/legacy/v6/store.go
@@ -15,6 +15,8 @@ import (
 	authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper"
 	authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
 
+	"github.com/cosmos/cosmos-sdk/types/tx/signing"
+
 	"github.com/desmos-labs/desmos/v4/x/profiles/types"
 )
 
@@ -227,7 +229,7 @@ func convertChainLinkProof(v5Proof v5types.Proof, cdc codec.BinaryCodec) types.P
 		panic(err)
 	}
 
-	var v6Signature types.SignatureData
+	var v6Signature types.Signature
 	v6SignatureAny := convertChainLinkSignatureData(v5Proof.Signature, cdc)
 	err = cdc.UnpackAny(v6SignatureAny, &v6Signature)
 	if err != nil {
@@ -235,7 +237,6 @@ func convertChainLinkProof(v5Proof v5types.Proof, cdc codec.BinaryCodec) types.P
 	}
 
 	return types.NewProof(pubKey, v6Signature, v5Proof.PlainText)
-
 }
 
 func convertChainLinkSignatureData(data *codectypes.Any, cdc codec.BinaryCodec) *codectypes.Any {
@@ -248,24 +249,48 @@ func convertChainLinkSignatureData(data *codectypes.Any, cdc codec.BinaryCodec)
 	var signatureAny *codectypes.Any
 	switch signature := v5Signature.(type) {
 	case *v5types.SingleSignatureData:
-		v6Signature := &types.SingleSignatureData{Signature: signature.Signature, Mode: signature.Mode}
+		var signingMode types.SignatureValueType
+		switch signature.Mode {
+		case signing.SignMode_SIGN_MODE_DIRECT:
+			signingMode = types.SIGNATURE_VALUE_TYPE_COSMOS_DIRECT
+		case signing.SignMode_SIGN_MODE_LEGACY_AMINO_JSON:
+			signingMode = types.SIGNATURE_VALUE_TYPE_COSMOS_AMINO
+		case signing.SignMode_SIGN_MODE_TEXTUAL:
+			signingMode = types.SIGNATURE_VALUE_TYPE_RAW
+		default:
+			panic(fmt.Sprintf("unsupported signing mode: %s", signature.Mode))
+		}
+
+		v6Signature := types.NewSingleSignature(signingMode, signature.Signature)
 		signatureAny, err = codectypes.NewAnyWithValue(v6Signature)
 		if err != nil {
 			panic(err)
 		}
 
 	case *v5types.MultiSignatureData:
-		sigsAnys := make([]*codectypes.Any, len(signature.Signatures))
-		for i, signature := range signature.Signatures {
-			sigsAnys[i] = convertChainLinkSignatureData(signature, cdc)
+		signatures := make([]types.Signature, len(signature.Signatures))
+		for i, sig := range signature.Signatures {
+			// Recursively convert the signature any
+			sigAny := convertChainLinkSignatureData(sig, cdc)
+
+			// Unpack the signature
+			var cosmosSig types.Signature
+			err = cdc.UnpackAny(sigAny, &cosmosSig)
+			if err != nil {
+				panic(err)
+			}
+
+			signatures[i] = cosmosSig
 		}
 
-		v6Signature := &types.MultiSignatureData{BitArray: signature.BitArray, Signatures: sigsAnys}
+		// Build the signature
+		v6Signature := types.NewCosmosMultiSignature(signature.BitArray, signatures)
+
+		// Convert it as an Any
 		signatureAny, err = codectypes.NewAnyWithValue(v6Signature)
 		if err != nil {
 			panic(err)
 		}
-
 	}
 
 	return signatureAny
diff --git a/x/profiles/spec/02-concepts.md b/x/profiles/spec/02-concepts.md
index cb15a3aa..634b6fb4 100644
--- a/x/profiles/spec/02-concepts.md
+++ b/x/profiles/spec/02-concepts.md
@@ -41,50 +41,61 @@ A DTag transfer request is the method that a user A has in order to ask another
 ## Chain Link
 A chain link represents a link to an external chain account that has been created by the user to connect their Desmos profile to such account. These links can be created either offline or using the IBC protocol and the provided packet data types.
 
-### Creating a chain link
-#### 1. Create the ownership proofs
-When creating a chain link, you need to provide two different proofs to make sure the link is valid:
+### Signature
+To be properly verified, a chain link must contain a signature that proves the user owns both the Desmos address and the external account that they are trying to link together. To do this, we require the user to cryptographically sign their Desmos address using the private key associated to the external account, and then publish the signature and the public key that should be used to verify it inside the chain link's proof. 
+
+Currently, we support two types of signatures: 
+
+- `CosmosMultiSignature` should be used when 
 
-1. The proof that you own the external chain account;
-2. The proof that you own the Desmos profile to which you want to link.
+#### SingleSignature
+This signature type should be used when the external wallet is made of a single key. It must specify the type of value that has been signed, as well as the signature bytes. 
 
-In order to create a proof, the following steps are needed:
+Single signature value types can be different to support multiple use cases: 
+- `SIGNATURE_VALUE_TYPE_RAW` should be used when you have direct access to the external account, and you can sign the Desmos address directly without the need of any wrapping structure;
+- `SIGNATURE_VALUE_TYPE_COSMOS_DIRECT` should be used when you need to wrap the Desmos address into the memo field of a Protobuf-encoded transaction. This might be useful when wanting to support the creation of chain links through external wallets (i.e. Keplr) that only support the signing of transactions;
+- `SIGNATURE_VALUE_TYPE_COSMOS_AMINO` should be used when you need to wrap the Desmos address into the memo field of an Amino-encoded transaction. This might be useful when wanting to support the creation of chain links through an external wallet (i.e. Ledger) that only allows signing Amino-encoded transactions;
+- `SIGNATURE_VALUE_TYPE_EVM_PERSONAL_SIGN` should be used when you need to wrap the Desmos address within an [EVM `personal_sign` signature](https://github.com/ethereum/go-ethereum/pull/2940). This might be useful when wanting to support the creation of chain links though an external wallet (i.e. MetaMask) that allows this method.
+
+#### CosmosMultiSignature
+This signature type should be used when the external account is a multi-sig account (this might be the case of validators wanting to connect their Desmos profile to an external Cosmos-based account).
+
+The `bit_array` field should be populated with the same value that is returned after the multi-sig creation process, while the `signatures` field should contain the list of `SingleSignature` that make up the multi-sig.
+
+### Creating a chain link
+#### 1. Create the ownership proofs
+In order to create a valid chain link ownership proof, the following steps are needed:
 
-1. Get the address of the profile that should be connected to the external address;
-2. Sign the hex-encoded external address using your private key (`sign(utf8.decode(address))`);
-3. Assemble the signature, hex-encoded Desmos address and public key into a `Proof` object.
+1. get the address of the Desmos profile that should be connected to the external address;
+2. sign the Desmos address using your external account private key;
+3. assemble the signature, Desmos address and public key into a `Proof` object.
 
-Here is an example of how to create a proof (in JavaScript):
+Here is an example of how to create a proof (in JavaScript) using a raw signature of the Desmos address. Please note that different value types might be used as described [above](#singlesignature):
 
 ```js
 const desmosAddress = "cosmos15uc89vnzufu5kuhhsxdkltt38zfx8vcyggzwfm";
 const hexEncodedDesmosAddress = hex.encode(utf8.decode(desmosAddress));
-const signature = hex.encode(externalWallet.sign(utf8.decode(desmosAddress)));
+const signature = base64.encode(externalWallet.sign(utf8.decode(desmosAddress)));
 
 const proof = {
     "pub_key": {
         "@type": "/cosmos.crypto.secp256k1.PubKey",
         "key": base64.encode(externalWallet.pubKeyBytes)
     },
-    "signature": signature,
+   "signature": {
+      "@type": "/desmos.profiles.v3.SingleSignature",
+      "value_type": 1,
+      "signature": signature,
+   },
     "plain_text": hexEncodedDesmosAddress
 }
 ```
 
-Following an example of a proof JSON encoded:
-
-```json
-{
-    "pub_key": {
-        "@type": "/cosmos.crypto.secp256k1.PubKey",
-        "key": "A58DXR/lXKVkIjLofXgST/OHi+pkOQbVIiOjnTy7Zoqo"
-    },
-    "signature": "ecc6175e730917fb289d3a9f4e49a5630a44b42d972f481342f540e09def2ec5169780d85c4e060d52cc3ffb3d677745a4d56cd385760735bc6db0f1816713be",
-    "plain_text": "636f736d6f73313575633839766e7a756675356b7568687378646b6c747433387a66783876637967677a77666d"
-}
-```
-
-Note that the `pub_key` field must be encoded using Protobuf and must be compatible with the public key types that are currently supported by Cosmos. You can see a list of such key types [here](https://github.com/cosmos/cosmos-sdk/tree/master/proto/cosmos/crypto).
+Note that the `pub_key` field must be encoded using Protobuf and must be compatible with the public key types that are currently supported. These are the following:
+- [Ed25519](https://github.com/cosmos/cosmos-sdk/blob/main/proto/cosmos/crypto/ed25519/keys.proto)
+- [Secp256k1](https://github.com/cosmos/cosmos-sdk/blob/main/proto/cosmos/crypto/secp256k1/keys.proto)
+- [Secp256r1](https://github.com/cosmos/cosmos-sdk/blob/main/proto/cosmos/crypto/secp256r1/keys.proto)
+- [EthSecp256k1](https://github.com/evmos/ethermint/blob/main/proto/ethermint/crypto/v1/ethsecp256k1/keys.proto)
 
 #### 2. Create the link
 Once you have created the two ownership proofs, you are now ready to create the link. This can be done in two ways:
@@ -100,7 +111,7 @@ To implement the IBC capability of connecting an external account to a Desmos pr
 `LinkChainAccountPacketData` defines the object that should be sent inside a `MsgSendPacket` when wanting to link an external chain to a Desmos profile using IBC.
 
 ```js reference
-https://github.com/desmos-labs/desmos/blob/v3.0.0/x/profiles/types/models_packets.pb.go#L28-L43
+https://github.com/desmos-labs/desmos/blob/master/x/profiles/types/models_packets.pb.go#L28-L43
 ```
 
 Note that the `SourceAddress` field must be one of the currently supported types:
diff --git a/x/profiles/types/codec.go b/x/profiles/types/codec.go
index 55bb2ff1..f16b9798 100644
--- a/x/profiles/types/codec.go
+++ b/x/profiles/types/codec.go
@@ -9,9 +9,15 @@ import (
 	authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
 	"github.com/cosmos/cosmos-sdk/x/auth/vesting/exported"
 	authzcodec "github.com/cosmos/cosmos-sdk/x/authz/codec"
+
+	"github.com/desmos-labs/desmos/v4/types/crypto/ethsecp256k1"
 )
 
 func RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) {
+	// Register custom key types
+	cdc.RegisterConcrete(&ethsecp256k1.PubKey{}, ethsecp256k1.PubKeyName, nil)
+	cdc.RegisterConcrete(&ethsecp256k1.PrivKey{}, ethsecp256k1.PrivKeyName, nil)
+
 	cdc.RegisterConcrete(MsgSaveProfile{}, "desmos/MsgSaveProfile", nil)
 	cdc.RegisterConcrete(MsgDeleteProfile{}, "desmos/MsgDeleteProfile", nil)
 	cdc.RegisterConcrete(MsgRequestDTagTransfer{}, "desmos/MsgRequestDTagTransfer", nil)
@@ -29,9 +35,9 @@ func RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) {
 	cdc.RegisterConcrete(&Base58Address{}, "desmos/Base58Address", nil)
 	cdc.RegisterConcrete(&HexAddress{}, "desmos/HexAddress", nil)
 
-	cdc.RegisterInterface((*SignatureData)(nil), nil)
-	cdc.RegisterConcrete(&SingleSignatureData{}, "desmos/SingleSignatureData", nil)
-	cdc.RegisterConcrete(&MultiSignatureData{}, "desmos/MultiSignatureData", nil)
+	cdc.RegisterInterface((*Signature)(nil), nil)
+	cdc.RegisterConcrete(&SingleSignature{}, "desmos/SingleSignature", nil)
+	cdc.RegisterConcrete(&CosmosMultiSignature{}, "desmos/CosmosMultiSignature", nil)
 
 	cdc.RegisterConcrete(&Profile{}, "desmos/Profile", nil)
 }
@@ -49,9 +55,9 @@ func RegisterInterfaces(registry types.InterfaceRegistry) {
 	)
 	registry.RegisterInterface(
 		"desmos.profiles.v3.Signature",
-		(*SignatureData)(nil),
-		&SingleSignatureData{},
-		&MultiSignatureData{},
+		(*Signature)(nil),
+		&SingleSignature{},
+		&CosmosMultiSignature{},
 	)
 
 	registry.RegisterImplementations((*sdk.Msg)(nil),
diff --git a/x/profiles/types/models_chain_links.go b/x/profiles/types/models_chain_links.go
index 9886d553..4d757f50 100644
--- a/x/profiles/types/models_chain_links.go
+++ b/x/profiles/types/models_chain_links.go
@@ -48,7 +48,7 @@ func (c ChainConfig) Validate() error {
 
 // NewProof is a constructor function for Proof
 // nolint:interfacer
-func NewProof(pubKey cryptotypes.PubKey, signature SignatureData, plainText string) Proof {
+func NewProof(pubKey cryptotypes.PubKey, signature Signature, plainText string) Proof {
 	pubKeyAny, err := codectypes.NewAnyWithValue(pubKey)
 	if err != nil {
 		panic("failed to pack public key to any type")
@@ -56,7 +56,7 @@ func NewProof(pubKey cryptotypes.PubKey, signature SignatureData, plainText stri
 
 	signatureAny, err := codectypes.NewAnyWithValue(signature)
 	if err != nil {
-		panic("failed to pack signature data to any type")
+		panic("failed to pack signature to any type")
 	}
 
 	return Proof{
@@ -66,6 +66,20 @@ func NewProof(pubKey cryptotypes.PubKey, signature SignatureData, plainText stri
 	}
 }
 
+// GetSignature returns the Signature associated to this proof
+func (p Proof) GetSignature() (Signature, error) {
+	sigValue := p.Signature.GetCachedValue()
+	if sigValue == nil {
+		return nil, fmt.Errorf("nil signature")
+	}
+
+	signature, ok := sigValue.(Signature)
+	if !ok {
+		return nil, fmt.Errorf("invalid signature type: %T", sigValue)
+	}
+	return signature, nil
+}
+
 // Validate checks the validity of the Proof
 func (p Proof) Validate() error {
 	if p.PubKey == nil {
@@ -90,65 +104,33 @@ func (p Proof) Validate() error {
 
 // Verify verifies the signature using the given plain text and public key.
 // It returns and error if something is invalid.
-func (p Proof) Verify(cdc codec.BinaryCodec, legacyAmino *codec.LegacyAmino, owner string, address AddressData) error {
+func (p Proof) Verify(cdc codec.BinaryCodec, amino *codec.LegacyAmino, owner string, address AddressData) error {
+	// Decode the value
 	value, err := hex.DecodeString(p.PlainText)
 	if err != nil {
 		return fmt.Errorf("error while decoding proof text: %s", err)
 	}
 
-	// Make sure the signed value is valid, if it's a transaction
-	isValidTextSig := IsValidTextSig(value, owner)
-	isValidDirectTxSig := IsValidDirectTxSig(value, owner, cdc)
-	isValidAminoTxSig := IsValidAminoTxSig(value, owner, legacyAmino)
-
-	if !isValidTextSig && !isValidDirectTxSig && !isValidAminoTxSig {
-		return fmt.Errorf("proof signed value must either be the user address or a transaction containing it as the memo")
-	}
-
-	var sigData SignatureData
-	err = cdc.UnpackAny(p.Signature, &sigData)
+	// Get the signature
+	signature, err := p.GetSignature()
 	if err != nil {
-		return fmt.Errorf("failed to unpack the signature")
+		return err
 	}
 
-	// Convert the signature data to the Cosmos type
-	cosmosSigData, err := SignatureDataToCosmosSignatureData(cdc, sigData)
+	// Validate the signature
+	err = signature.Validate(cdc, amino, value, owner)
 	if err != nil {
-		return err
+		return fmt.Errorf("invalid signature: %s", err)
 	}
 
 	// Verify the signature
-	var pubkey cryptotypes.PubKey
-	switch sigData := cosmosSigData.(type) {
-	case *signing.SingleSignatureData:
-		err = cdc.UnpackAny(p.PubKey, &pubkey)
-		if err != nil {
-			return fmt.Errorf("failed to unpack the public key")
-		}
-		if !pubkey.VerifySignature(value, sigData.Signature) {
-			return fmt.Errorf("failed to verify the signature")
-		}
-
-	case *signing.MultiSignatureData:
-		var multiPubkey multisig.PubKey
-		err = cdc.UnpackAny(p.PubKey, &multiPubkey)
-		if err != nil {
-			return fmt.Errorf("failed to unpack the public key")
-		}
-		err = multiPubkey.VerifyMultisignature(
-			func(mode signing.SignMode) ([]byte, error) {
-				return value, nil
-			},
-			sigData,
-		)
-		if err != nil {
-			return err
-		}
-		pubkey = multiPubkey
+	pubKey, err := signature.Verify(cdc, p.PubKey, value)
+	if err != nil {
+		return fmt.Errorf("error while verifying the signature: %s", err)
 	}
 
 	// Verify the public key
-	valid, err := address.VerifyPubKey(pubkey)
+	valid, err := address.VerifyPubKey(pubKey)
 	if err != nil {
 		return err
 	}
@@ -159,84 +141,282 @@ func (p Proof) Verify(cdc codec.BinaryCodec, legacyAmino *codec.LegacyAmino, own
 	return nil
 }
 
-// IsValidTextSig tells whether the given value has been generated using SIGN_MODE_TEXTUAL
-// and signing the given expected value
-func IsValidTextSig(value []byte, expectedValue string) bool {
-	return string(value) == expectedValue
+// UnpackInterfaces implements codectypes.UnpackInterfacesMessage
+func (p *Proof) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error {
+	var pubKey cryptotypes.PubKey
+	err := unpacker.UnpackAny(p.PubKey, &pubKey)
+	if err != nil {
+		return err
+	}
+
+	var signatureData Signature
+	return unpacker.UnpackAny(p.Signature, &signatureData)
+}
+
+// --------------------------------------------------------------------------------------------------------------------
+
+// Signature represents a generic signature data
+type Signature interface {
+	proto.Message
+
+	// GetValueType returns the type of the signature
+	GetValueType() (SignatureValueType, error)
+
+	// Validate checks the validity of the Signature
+	Validate(cdc codec.BinaryCodec, amino *codec.LegacyAmino, plainText []byte, owner string) error
+
+	// Verify allows to verify this signature using the given public key against the given plain text.
+	// If the signature is valid, it returns the public key instance used to verify it
+	Verify(cdc codec.BinaryCodec, pubKey *codectypes.Any, plainText []byte) (cryptotypes.PubKey, error)
+}
+
+// --------------------------------------------------------------------------------------------------------------------
+
+// ValidateRawValue tells whether the given value has been properly encoded as a raw value
+func ValidateRawValue(value []byte, expectedValue string) error {
+	if string(value) != expectedValue {
+		return fmt.Errorf("invalid signed value: expected %s, got %s", expectedValue, value)
+	}
+
+	return nil
 }
 
-// IsValidDirectTxSig tells whether the given value has been generated using SIGN_MODE_DIRECT and signing
-// a transaction that contains a memo field equals to the given expected value
-func IsValidDirectTxSig(value []byte, expectedMemo string, cdc codec.BinaryCodec) bool {
+// ValidateDirectTxValue tells whether the given value has been properly encoded as a Protobuf transaction containing
+// the expected value as the memo field value
+func ValidateDirectTxValue(value []byte, expectedMemo string, cdc codec.BinaryCodec) error {
 	// Unmarshal the SignDoc
 	var signDoc tx.SignDoc
 	err := cdc.Unmarshal(value, &signDoc)
 	if err != nil {
-		return false
+		return err
 	}
 
 	// Check to make sure the value was a SignDoc. If that's not the case, the two arrays will not match
 	if !bytes.Equal(value, cdc.MustMarshal(&signDoc)) {
-		return false
+		return fmt.Errorf("invalid signed doc")
 	}
 
 	// Get the TxBody
 	var txBody tx.TxBody
 	err = cdc.Unmarshal(signDoc.BodyBytes, &txBody)
 	if err != nil {
-		return false
+		return err
 	}
 
-	// Check memo
-	return txBody.Memo == expectedMemo
+	// Check the memo field
+	if txBody.Memo != expectedMemo {
+		return fmt.Errorf("invalid signed memo: expected %s, got %s", expectedMemo, txBody.Memo)
+	}
+
+	return nil
 }
 
-// IsValidAminoTxSig tells whether the given value has been generated using SIGN_MODE_AMINO_JSON and signing
-// a transaction that contains a memo field equals to the given expected value
-func IsValidAminoTxSig(value []byte, expectedMemo string, cdc *codec.LegacyAmino) bool {
+// ValidateAminoTxValue tells whether the given value has been properly encoded as an Amino transaction containing
+// the expected value as the memo field value
+func ValidateAminoTxValue(value []byte, expectedMemo string, cdc *codec.LegacyAmino) error {
 	// Unmarshal the StdSignDoc
 	var signDoc legacytx.StdSignDoc
 	err := cdc.UnmarshalJSON(value, &signDoc)
 	if err != nil {
-		return false
+		return err
 	}
 
 	// Check the memo field
-	return signDoc.Memo == expectedMemo
+	if signDoc.Memo != expectedMemo {
+		return fmt.Errorf("invalid signed memo: expected %s, got %s", expectedMemo, signDoc.Memo)
+	}
+
+	return nil
 }
 
-// UnpackInterfaces implements codectypes.UnpackInterfacesMessage
-func (p *Proof) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error {
-	var pubKey cryptotypes.PubKey
-	err := unpacker.UnpackAny(p.PubKey, &pubKey)
+// ValidatePersonalSignValue tells whether the given value has been properly encoded using the EVM persona_sign specification
+func ValidatePersonalSignValue(value []byte, expectedValue string) error {
+	expectedSignedValue := fmt.Sprintf("\x19Ethereum Signed Message:\n%d%s", len(expectedValue), expectedValue)
+	if string(value) != expectedSignedValue {
+		return fmt.Errorf("invalid signed value: expected %s but got %s", expectedSignedValue, value)
+	}
+
+	return nil
+}
+
+// --------------------------------------------------------------------------------------------------------------------
+
+var _ Signature = &SingleSignature{}
+
+// NewSingleSignature returns a new CosmosSignature instance
+func NewSingleSignature(valueType SignatureValueType, signature []byte) *SingleSignature {
+	return &SingleSignature{
+		ValueType: valueType,
+		Signature: signature,
+	}
+}
+
+// GetValueType implements CosmosSignature
+func (s *SingleSignature) GetValueType() (SignatureValueType, error) {
+	return s.ValueType, nil
+}
+
+// Validate implements Signature
+func (s *SingleSignature) Validate(cdc codec.BinaryCodec, amino *codec.LegacyAmino, plainText []byte, owner string) error {
+	// Validate the signature itself
+	switch s.ValueType {
+	case SIGNATURE_VALUE_TYPE_COSMOS_DIRECT:
+		return ValidateDirectTxValue(plainText, owner, cdc)
+	case SIGNATURE_VALUE_TYPE_COSMOS_AMINO:
+		return ValidateAminoTxValue(plainText, owner, amino)
+	case SIGNATURE_VALUE_TYPE_RAW:
+		return ValidateRawValue(plainText, owner)
+	case SIGNATURE_VALUE_TYPE_EVM_PERSONAL_SIGN:
+		return ValidatePersonalSignValue(plainText, owner)
+	default:
+		return fmt.Errorf("invalid signature type: %s", s.ValueType)
+	}
+}
+
+// Verify implements Signature
+func (s *SingleSignature) Verify(cdc codec.BinaryCodec, pubKey *codectypes.Any, plainText []byte) (cryptotypes.PubKey, error) {
+	// Get the pub key
+	var pubkey cryptotypes.PubKey
+	err := cdc.UnpackAny(pubKey, &pubkey)
 	if err != nil {
-		return err
+		return nil, fmt.Errorf("failed to unpack the public key")
 	}
 
-	var signatureData SignatureData
-	return unpacker.UnpackAny(p.Signature, &signatureData)
+	// Verify the signature
+	if !pubkey.VerifySignature(plainText, s.Signature) {
+		return nil, fmt.Errorf("failed to verify the signature")
+	}
+
+	return pubkey, nil
 }
 
 // --------------------------------------------------------------------------------------------------------------------
 
-// SignatureData represents a generic single- or multi- signature data
-type SignatureData interface {
-	proto.Message
+var _ Signature = &CosmosMultiSignature{}
+
+// NewCosmosMultiSignature returns a new CosmosMultiSignature instance
+func NewCosmosMultiSignature(bitArray *cryptotypes.CompactBitArray, signatures []Signature) *CosmosMultiSignature {
+	sigsAnys := make([]*codectypes.Any, len(signatures))
+	for i, sig := range signatures {
+		sigAny, err := codectypes.NewAnyWithValue(sig)
+		if err != nil {
+			panic("failed to pack signature to any type")
+		}
+		sigsAnys[i] = sigAny
+	}
+
+	return &CosmosMultiSignature{
+		BitArray:   bitArray,
+		Signatures: sigsAnys,
+	}
+}
+
+// GetValueType implements CosmosSignature
+func (s *CosmosMultiSignature) GetValueType() (SignatureValueType, error) {
+	signMode := SIGNATURE_VALUE_TYPE_UNSPECIFIED
+	for i, signature := range s.Signatures {
+		// Unwrap the signature
+		cosmosSig, ok := signature.GetCachedValue().(Signature)
+		if !ok {
+			return SIGNATURE_VALUE_TYPE_UNSPECIFIED, fmt.Errorf("invalid signature type at index %d: %T", i, cosmosSig)
+		}
+
+		// Get the signature sign mode
+		signatureSignMode, err := cosmosSig.GetValueType()
+		if err != nil {
+			return SIGNATURE_VALUE_TYPE_UNSPECIFIED, err
+		}
+
+		if signatureSignMode == SIGNATURE_VALUE_TYPE_UNSPECIFIED {
+			return SIGNATURE_VALUE_TYPE_UNSPECIFIED, fmt.Errorf("invalid signature signing mode: %s", signatureSignMode)
+		}
+
+		if signMode != SIGNATURE_VALUE_TYPE_UNSPECIFIED && signMode != signatureSignMode {
+			return SIGNATURE_VALUE_TYPE_UNSPECIFIED, fmt.Errorf("signature at index %d has different signing mode than others", i)
+		}
+		signMode = signatureSignMode
+	}
+	return signMode, nil
+}
+
+// Validate implements Signature
+func (s *CosmosMultiSignature) Validate(cdc codec.BinaryCodec, amino *codec.LegacyAmino, plainText []byte, owner string) error {
+	signMode, err := s.GetValueType()
+	if err != nil {
+		return err
+	}
+
+	// Validate the signature itself
+	switch signMode {
+	case SIGNATURE_VALUE_TYPE_RAW:
+		return ValidateRawValue(plainText, owner)
+	case SIGNATURE_VALUE_TYPE_COSMOS_DIRECT:
+		return ValidateDirectTxValue(plainText, owner, cdc)
+	case SIGNATURE_VALUE_TYPE_COSMOS_AMINO:
+		return ValidateAminoTxValue(plainText, owner, amino)
+	default:
+		return fmt.Errorf("invalid signing mode: %s", signMode)
+	}
+}
+
+// Verify implements Signature
+func (s *CosmosMultiSignature) Verify(cdc codec.BinaryCodec, pubKey *codectypes.Any, plainText []byte) (cryptotypes.PubKey, error) {
+	// Convert the signature data to the Cosmos type
+	cosmosSigData, err := SignatureToCosmosSignatureData(cdc, s)
+	if err != nil {
+		return nil, err
+	}
+
+	// Make sure the sig data is of the correct type
+	sigData, ok := cosmosSigData.(*signing.MultiSignatureData)
+	if !ok {
+		return nil, fmt.Errorf("invalid signature data type: %T", sigData)
+	}
+
+	// Get the pub key
+	var multiPubkey multisig.PubKey
+	err = cdc.UnpackAny(pubKey, &multiPubkey)
+	if err != nil {
+		return nil, fmt.Errorf("failed to unpack the public key")
+	}
+
+	// Verify the signature
+	err = multiPubkey.VerifyMultisignature(func(mode signing.SignMode) ([]byte, error) {
+		return plainText, nil
+	}, sigData)
+	if err != nil {
+		return nil, err
+	}
 
-	isSignatureData()
+	return multiPubkey, nil
 }
 
-// SignatureDataToCosmosSignatureData allows to convert the given SignatureData to a Cosmos SignatureData instance
+// UnpackInterfaces implements codectypes.UnpackInterfacesMessage
+func (s *CosmosMultiSignature) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error {
+	for _, signature := range s.Signatures {
+		var signatureData Signature
+		err := unpacker.UnpackAny(signature, &signatureData)
+		if err != nil {
+			return err
+		}
+	}
+
+	return nil
+}
+
+// --------------------------------------------------------------------------------------------------------------------
+
+// SignatureToCosmosSignatureData allows to convert the given Signature to a Cosmos SignatureData instance
 // unpacking the proto.Any instance using the given unpacker.
-func SignatureDataToCosmosSignatureData(unpacker codectypes.AnyUnpacker, s SignatureData) (signing.SignatureData, error) {
+func SignatureToCosmosSignatureData(unpacker codectypes.AnyUnpacker, s Signature) (signing.SignatureData, error) {
 	switch data := s.(type) {
-	case *SingleSignatureData:
+	case *SingleSignature:
 		return &signing.SingleSignatureData{
 			Signature: data.Signature,
-			SignMode:  data.Mode,
+			SignMode:  signing.SignMode_SIGN_MODE_UNSPECIFIED, // This can be unknown since we don't use it anyway
 		}, nil
 
-	case *MultiSignatureData:
+	case *CosmosMultiSignature:
 		sigs, err := unpackSignatures(unpacker, data.Signatures)
 		if err != nil {
 			return nil, err
@@ -246,24 +426,37 @@ func SignatureDataToCosmosSignatureData(unpacker codectypes.AnyUnpacker, s Signa
 			BitArray:   data.BitArray,
 			Signatures: sigs,
 		}, nil
-	}
 
-	return nil, fmt.Errorf("signature type not supported: %T", s)
+	default:
+		return nil, fmt.Errorf("signature type not supported: %T", s)
+	}
 }
 
-// SignatureDataFromCosmosSignatureData allows to create a SignatureData instance from the given Cosmos SignatureData
-func SignatureDataFromCosmosSignatureData(data signing.SignatureData) (SignatureData, error) {
+// CosmosSignatureDataToSignature allows to create a Signature instance from the given Cosmos signature data
+func CosmosSignatureDataToSignature(data signing.SignatureData) (Signature, error) {
 	switch data := data.(type) {
 	case *signing.SingleSignatureData:
-		return &SingleSignatureData{
-			Mode:      data.SignMode,
+		var signatureType SignatureValueType
+		switch data.SignMode {
+		case signing.SignMode_SIGN_MODE_DIRECT:
+			signatureType = SIGNATURE_VALUE_TYPE_COSMOS_DIRECT
+		case signing.SignMode_SIGN_MODE_LEGACY_AMINO_JSON:
+			signatureType = SIGNATURE_VALUE_TYPE_COSMOS_AMINO
+		case signing.SignMode_SIGN_MODE_TEXTUAL:
+			signatureType = SIGNATURE_VALUE_TYPE_RAW
+		default:
+			return nil, fmt.Errorf("unsupported signing mode: %s", data.SignMode)
+		}
+
+		return &SingleSignature{
+			ValueType: signatureType,
 			Signature: data.Signature,
 		}, nil
 
 	case *signing.MultiSignatureData:
 		sigAnys := make([]*codectypes.Any, len(data.Signatures))
 		for i, data := range data.Signatures {
-			sigData, err := SignatureDataFromCosmosSignatureData(data)
+			sigData, err := CosmosSignatureDataToSignature(data)
 			if err != nil {
 				return nil, err
 			}
@@ -273,7 +466,7 @@ func SignatureDataFromCosmosSignatureData(data signing.SignatureData) (Signature
 			}
 			sigAnys[i] = sigAny
 		}
-		return &MultiSignatureData{
+		return &CosmosMultiSignature{
 			BitArray:   data.BitArray,
 			Signatures: sigAnys,
 		}, nil
@@ -286,12 +479,12 @@ func SignatureDataFromCosmosSignatureData(data signing.SignatureData) (Signature
 func unpackSignatures(unpacker codectypes.AnyUnpacker, sigs []*codectypes.Any) ([]signing.SignatureData, error) {
 	var signatures = make([]signing.SignatureData, len(sigs))
 	for i, sig := range sigs {
-		var signatureData SignatureData
-		if err := unpacker.UnpackAny(sig, &signatureData); err != nil {
+		var signature Signature
+		if err := unpacker.UnpackAny(sig, &signature); err != nil {
 			return nil, err
 		}
 
-		cosmosSigData, err := SignatureDataToCosmosSignatureData(unpacker, signatureData)
+		cosmosSigData, err := SignatureToCosmosSignatureData(unpacker, signature)
 		if err != nil {
 			return nil, err
 		}
@@ -303,33 +496,6 @@ func unpackSignatures(unpacker codectypes.AnyUnpacker, sigs []*codectypes.Any) (
 
 // --------------------------------------------------------------------------------------------------------------------
 
-var _ SignatureData = &SingleSignatureData{}
-
-// isSignatureData implements SignatureData
-func (s *SingleSignatureData) isSignatureData() {}
-
-// --------------------------------------------------------------------------------------------------------------------
-
-var _ SignatureData = &MultiSignatureData{}
-
-// isSignatureData implements SignatureData
-func (s *MultiSignatureData) isSignatureData() {}
-
-// UnpackInterfaces implements codectypes.UnpackInterfacesMessage
-func (s *MultiSignatureData) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error {
-	for _, signature := range s.Signatures {
-		var signatureData SignatureData
-		err := unpacker.UnpackAny(signature, &signatureData)
-		if err != nil {
-			return err
-		}
-	}
-
-	return nil
-}
-
-// --------------------------------------------------------------------------------------------------------------------
-
 // AddressData is an interface representing a generic external chain address
 type AddressData interface {
 	proto.Message
diff --git a/x/profiles/types/models_chain_links.pb.go b/x/profiles/types/models_chain_links.pb.go
index 0ff5906b..66b0f5f5 100644
--- a/x/profiles/types/models_chain_links.pb.go
+++ b/x/profiles/types/models_chain_links.pb.go
@@ -8,7 +8,7 @@ import (
 	fmt "fmt"
 	types "github.com/cosmos/cosmos-sdk/codec/types"
 	types1 "github.com/cosmos/cosmos-sdk/crypto/types"
-	signing "github.com/cosmos/cosmos-sdk/types/tx/signing"
+	_ "github.com/cosmos/cosmos-sdk/types/tx/signing"
 	_ "github.com/gogo/protobuf/gogoproto"
 	proto "github.com/gogo/protobuf/proto"
 	github_com_gogo_protobuf_types "github.com/gogo/protobuf/types"
@@ -32,6 +32,53 @@ var _ = time.Kitchen
 // proto package needs to be updated.
 const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
 
+// SignatureValueType specifies all the possible signature types
+type SignatureValueType int32
+
+const (
+	// SIGNATURE_VALUE_TYPE_UNSPECIFIED specifies an unknown signing mode
+	// and will be rejected
+	SIGNATURE_VALUE_TYPE_UNSPECIFIED SignatureValueType = 0
+	// SIGNATURE_VALUE_TYPE_RAW should be used when the value has been
+	// signed as a raw byte array
+	SIGNATURE_VALUE_TYPE_RAW SignatureValueType = 1
+	// SIGNATURE_VALUE_TYPE_COSMOS_DIRECT should be used when the signed
+	// value has been encoded as a Protobuf transaction containing the owner
+	// address inside its memo field
+	SIGNATURE_VALUE_TYPE_COSMOS_DIRECT SignatureValueType = 2
+	// SIGNATURE_VALUE_TYPE_COSMOS_AMINO should be used when the value has
+	// been encoded as an Amino transaction containing the owner address inside
+	// its memo field
+	SIGNATURE_VALUE_TYPE_COSMOS_AMINO SignatureValueType = 3
+	// SIGNATURE_VALUE_TYPE_EVM_PERSONAL_SIGN should be used when the value
+	// has been encoded following the EVM personal_sign specification
+	SIGNATURE_VALUE_TYPE_EVM_PERSONAL_SIGN SignatureValueType = 4
+)
+
+var SignatureValueType_name = map[int32]string{
+	0: "SIGNATURE_VALUE_TYPE_UNSPECIFIED",
+	1: "SIGNATURE_VALUE_TYPE_RAW",
+	2: "SIGNATURE_VALUE_TYPE_COSMOS_DIRECT",
+	3: "SIGNATURE_VALUE_TYPE_COSMOS_AMINO",
+	4: "SIGNATURE_VALUE_TYPE_EVM_PERSONAL_SIGN",
+}
+
+var SignatureValueType_value = map[string]int32{
+	"SIGNATURE_VALUE_TYPE_UNSPECIFIED":       0,
+	"SIGNATURE_VALUE_TYPE_RAW":               1,
+	"SIGNATURE_VALUE_TYPE_COSMOS_DIRECT":     2,
+	"SIGNATURE_VALUE_TYPE_COSMOS_AMINO":      3,
+	"SIGNATURE_VALUE_TYPE_EVM_PERSONAL_SIGN": 4,
+}
+
+func (x SignatureValueType) String() string {
+	return proto.EnumName(SignatureValueType_name, int32(x))
+}
+
+func (SignatureValueType) EnumDescriptor() ([]byte, []int) {
+	return fileDescriptor_29bee920e792da29, []int{0}
+}
+
 // ChainLink contains the data representing either an inter- or cross- chain
 // link
 type ChainLink struct {
@@ -288,26 +335,26 @@ func (m *HexAddress) XXX_DiscardUnknown() {
 
 var xxx_messageInfo_HexAddress proto.InternalMessageInfo
 
-// SingleSignatureData is the signature data for a single signer
-type SingleSignatureData struct {
-	// Mode is the signing mode of the single signer
-	Mode signing.SignMode `protobuf:"varint,1,opt,name=mode,proto3,enum=cosmos.tx.signing.v1beta1.SignMode" json:"mode,omitempty"`
+// SingleSignature is the signature data for a single signer
+type SingleSignature struct {
+	// Type represents the type of the signature value
+	ValueType SignatureValueType `protobuf:"varint,1,opt,name=value_type,json=valueType,proto3,enum=desmos.profiles.v3.SignatureValueType" json:"value_type,omitempty" yaml:"value_type"`
 	// Signature is the raw signature bytes
-	Signature []byte `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"`
+	Signature []byte `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty" yaml:"signature"`
 }
 
-func (m *SingleSignatureData) Reset()         { *m = SingleSignatureData{} }
-func (m *SingleSignatureData) String() string { return proto.CompactTextString(m) }
-func (*SingleSignatureData) ProtoMessage()    {}
-func (*SingleSignatureData) Descriptor() ([]byte, []int) {
+func (m *SingleSignature) Reset()         { *m = SingleSignature{} }
+func (m *SingleSignature) String() string { return proto.CompactTextString(m) }
+func (*SingleSignature) ProtoMessage()    {}
+func (*SingleSignature) Descriptor() ([]byte, []int) {
 	return fileDescriptor_29bee920e792da29, []int{6}
 }
-func (m *SingleSignatureData) XXX_Unmarshal(b []byte) error {
+func (m *SingleSignature) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
 }
-func (m *SingleSignatureData) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+func (m *SingleSignature) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
 	if deterministic {
-		return xxx_messageInfo_SingleSignatureData.Marshal(b, m, deterministic)
+		return xxx_messageInfo_SingleSignature.Marshal(b, m, deterministic)
 	} else {
 		b = b[:cap(b)]
 		n, err := m.MarshalToSizedBuffer(b)
@@ -317,38 +364,38 @@ func (m *SingleSignatureData) XXX_Marshal(b []byte, deterministic bool) ([]byte,
 		return b[:n], nil
 	}
 }
-func (m *SingleSignatureData) XXX_Merge(src proto.Message) {
-	xxx_messageInfo_SingleSignatureData.Merge(m, src)
+func (m *SingleSignature) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_SingleSignature.Merge(m, src)
 }
-func (m *SingleSignatureData) XXX_Size() int {
+func (m *SingleSignature) XXX_Size() int {
 	return m.Size()
 }
-func (m *SingleSignatureData) XXX_DiscardUnknown() {
-	xxx_messageInfo_SingleSignatureData.DiscardUnknown(m)
+func (m *SingleSignature) XXX_DiscardUnknown() {
+	xxx_messageInfo_SingleSignature.DiscardUnknown(m)
 }
 
-var xxx_messageInfo_SingleSignatureData proto.InternalMessageInfo
+var xxx_messageInfo_SingleSignature proto.InternalMessageInfo
 
-// MultiSignatureData is the signature data for a multisig public key
-type MultiSignatureData struct {
+// CosmosMultiSignature is the signature data for a multisig public key
+type CosmosMultiSignature struct {
 	// Bitarray specifies which keys within the multisig are signing
-	BitArray *types1.CompactBitArray `protobuf:"bytes,1,opt,name=bit_array,json=bitArray,proto3" json:"bit_array,omitempty"`
+	BitArray *types1.CompactBitArray `protobuf:"bytes,1,opt,name=bit_array,json=bitArray,proto3" json:"bit_array,omitempty" yaml:"bit_array"`
 	// Signatures is the signatures of the multi-signature
-	Signatures []*types.Any `protobuf:"bytes,2,rep,name=signatures,proto3" json:"signatures,omitempty"`
+	Signatures []*types.Any `protobuf:"bytes,2,rep,name=signatures,proto3" json:"signatures,omitempty" yaml:"signatures"`
 }
 
-func (m *MultiSignatureData) Reset()         { *m = MultiSignatureData{} }
-func (m *MultiSignatureData) String() string { return proto.CompactTextString(m) }
-func (*MultiSignatureData) ProtoMessage()    {}
-func (*MultiSignatureData) Descriptor() ([]byte, []int) {
+func (m *CosmosMultiSignature) Reset()         { *m = CosmosMultiSignature{} }
+func (m *CosmosMultiSignature) String() string { return proto.CompactTextString(m) }
+func (*CosmosMultiSignature) ProtoMessage()    {}
+func (*CosmosMultiSignature) Descriptor() ([]byte, []int) {
 	return fileDescriptor_29bee920e792da29, []int{7}
 }
-func (m *MultiSignatureData) XXX_Unmarshal(b []byte) error {
+func (m *CosmosMultiSignature) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
 }
-func (m *MultiSignatureData) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+func (m *CosmosMultiSignature) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
 	if deterministic {
-		return xxx_messageInfo_MultiSignatureData.Marshal(b, m, deterministic)
+		return xxx_messageInfo_CosmosMultiSignature.Marshal(b, m, deterministic)
 	} else {
 		b = b[:cap(b)]
 		n, err := m.MarshalToSizedBuffer(b)
@@ -358,27 +405,28 @@ func (m *MultiSignatureData) XXX_Marshal(b []byte, deterministic bool) ([]byte,
 		return b[:n], nil
 	}
 }
-func (m *MultiSignatureData) XXX_Merge(src proto.Message) {
-	xxx_messageInfo_MultiSignatureData.Merge(m, src)
+func (m *CosmosMultiSignature) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_CosmosMultiSignature.Merge(m, src)
 }
-func (m *MultiSignatureData) XXX_Size() int {
+func (m *CosmosMultiSignature) XXX_Size() int {
 	return m.Size()
 }
-func (m *MultiSignatureData) XXX_DiscardUnknown() {
-	xxx_messageInfo_MultiSignatureData.DiscardUnknown(m)
+func (m *CosmosMultiSignature) XXX_DiscardUnknown() {
+	xxx_messageInfo_CosmosMultiSignature.DiscardUnknown(m)
 }
 
-var xxx_messageInfo_MultiSignatureData proto.InternalMessageInfo
+var xxx_messageInfo_CosmosMultiSignature proto.InternalMessageInfo
 
 func init() {
+	proto.RegisterEnum("desmos.profiles.v3.SignatureValueType", SignatureValueType_name, SignatureValueType_value)
 	proto.RegisterType((*ChainLink)(nil), "desmos.profiles.v3.ChainLink")
 	proto.RegisterType((*ChainConfig)(nil), "desmos.profiles.v3.ChainConfig")
 	proto.RegisterType((*Proof)(nil), "desmos.profiles.v3.Proof")
 	proto.RegisterType((*Bech32Address)(nil), "desmos.profiles.v3.Bech32Address")
 	proto.RegisterType((*Base58Address)(nil), "desmos.profiles.v3.Base58Address")
 	proto.RegisterType((*HexAddress)(nil), "desmos.profiles.v3.HexAddress")
-	proto.RegisterType((*SingleSignatureData)(nil), "desmos.profiles.v3.SingleSignatureData")
-	proto.RegisterType((*MultiSignatureData)(nil), "desmos.profiles.v3.MultiSignatureData")
+	proto.RegisterType((*SingleSignature)(nil), "desmos.profiles.v3.SingleSignature")
+	proto.RegisterType((*CosmosMultiSignature)(nil), "desmos.profiles.v3.CosmosMultiSignature")
 }
 
 func init() {
@@ -386,57 +434,66 @@ func init() {
 }
 
 var fileDescriptor_29bee920e792da29 = []byte{
-	// 793 bytes of a gzipped FileDescriptorProto
-	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xc4, 0x55, 0x4d, 0x4f, 0xeb, 0x46,
-	0x14, 0x8d, 0x0b, 0x81, 0x66, 0x92, 0x50, 0x18, 0x52, 0x29, 0x40, 0x15, 0x53, 0x23, 0xb5, 0x54,
-	0x15, 0xb6, 0x20, 0x54, 0xad, 0xb2, 0x6a, 0x4c, 0x2b, 0x21, 0x01, 0x52, 0x6b, 0x58, 0x75, 0x13,
-	0x8d, 0x9d, 0x89, 0x19, 0x61, 0x7b, 0x2c, 0x7b, 0x1c, 0x25, 0x52, 0xa5, 0x2e, 0xdb, 0x25, 0xcb,
-	0x2e, 0xba, 0xe0, 0x3f, 0xb4, 0x3f, 0x02, 0x75, 0x85, 0xba, 0x62, 0x95, 0x56, 0xb0, 0xe9, 0x3a,
-	0xbf, 0xe0, 0x69, 0x3e, 0x9c, 0x84, 0xf0, 0x40, 0x7a, 0xab, 0xb7, 0xf3, 0xdc, 0x7b, 0xce, 0x99,
-	0x73, 0xe7, 0x5e, 0x5d, 0x83, 0x2f, 0xbb, 0x38, 0x0d, 0x69, 0x6a, 0xc5, 0x09, 0xed, 0x91, 0x00,
-	0xa7, 0x56, 0xbf, 0x69, 0x85, 0xb4, 0x8b, 0x83, 0xb4, 0xe3, 0x5d, 0x22, 0x12, 0x75, 0x02, 0x12,
-	0x5d, 0xa5, 0x66, 0x9c, 0x50, 0x46, 0x21, 0x94, 0x60, 0x33, 0x07, 0x9b, 0xfd, 0xe6, 0x66, 0xcd,
-	0xa7, 0x3e, 0x15, 0x69, 0x8b, 0x7f, 0x49, 0xe4, 0xe6, 0x86, 0x4f, 0xa9, 0x1f, 0x60, 0x4b, 0x9c,
-	0xdc, 0xac, 0x67, 0xa1, 0x68, 0xa8, 0x52, 0xfa, 0x7c, 0x8a, 0x91, 0x10, 0xa7, 0x0c, 0x85, 0x71,
-	0xce, 0xf5, 0x28, 0xbf, 0xa5, 0x23, 0x45, 0xe5, 0x41, 0xa5, 0x3e, 0x97, 0x27, 0x8b, 0x0d, 0xac,
-	0x94, 0xf8, 0x11, 0x89, 0x7c, 0xab, 0xbf, 0xef, 0x62, 0x86, 0xf6, 0xf3, 0xb3, 0x02, 0xee, 0x29,
-	0xa0, 0x97, 0x0c, 0x63, 0x46, 0xad, 0x30, 0x0b, 0x18, 0x49, 0xc9, 0x14, 0x9d, 0x07, 0x24, 0xdc,
-	0xf8, 0x63, 0x01, 0x94, 0x8e, 0x78, 0xb9, 0xa7, 0x24, 0xba, 0x82, 0x3b, 0x60, 0x31, 0x4b, 0x71,
-	0x52, 0xd7, 0xb6, 0xb5, 0xdd, 0x92, 0xfd, 0xd1, 0x78, 0xa4, 0x97, 0x87, 0x28, 0x0c, 0x5a, 0x06,
-	0x8f, 0x1a, 0x8e, 0x48, 0xc2, 0x1f, 0xc1, 0x32, 0xea, 0x76, 0x13, 0x9c, 0xa6, 0xf5, 0x0f, 0xb6,
-	0xb5, 0xdd, 0xf2, 0x41, 0xcd, 0x94, 0x85, 0x99, 0x79, 0x61, 0x66, 0x3b, 0x1a, 0xda, 0x9f, 0x8e,
-	0x47, 0xfa, 0x8a, 0x64, 0x2b, 0xb8, 0xf1, 0xf7, 0x5f, 0x7b, 0xe5, 0xb6, 0xfc, 0xfe, 0x0e, 0x31,
-	0xe4, 0xe4, 0x3a, 0xf0, 0x7b, 0x50, 0x8c, 0x13, 0x4a, 0x7b, 0xf5, 0x05, 0x21, 0xb8, 0x61, 0x3e,
-	0x7f, 0x6e, 0xf3, 0x07, 0x0e, 0xb0, 0x6b, 0xb7, 0x23, 0xbd, 0x30, 0x1e, 0xe9, 0x15, 0xa9, 0x2c,
-	0x58, 0x86, 0x23, 0xd9, 0xb0, 0x03, 0x2a, 0xb2, 0x75, 0x1e, 0x8d, 0x7a, 0xc4, 0xaf, 0x2f, 0x0a,
-	0x35, 0xfd, 0x6d, 0x6a, 0xa2, 0xe6, 0x23, 0x01, 0xb3, 0xb7, 0x94, 0xe6, 0xba, 0xd4, 0x9c, 0x95,
-	0x30, 0x9c, 0xb2, 0x37, 0x45, 0x42, 0x04, 0xaa, 0x5e, 0x82, 0x11, 0x23, 0x34, 0xea, 0xf0, 0xe6,
-	0xd5, 0x8b, 0xe2, 0x86, 0xcd, 0x67, 0x0f, 0x70, 0x91, 0x77, 0xd6, 0xde, 0x56, 0xe2, 0x35, 0x25,
-	0x3e, 0x4b, 0x37, 0xae, 0xff, 0xd5, 0x35, 0xa7, 0x92, 0xc7, 0x38, 0xa9, 0x55, 0xf9, 0xed, 0x46,
-	0x2f, 0xfc, 0x7e, 0xa3, 0x6b, 0xff, 0xdf, 0xe8, 0x9a, 0xf1, 0x2d, 0x28, 0xcf, 0x38, 0xe5, 0xfd,
-	0x89, 0x50, 0x88, 0x9f, 0xf7, 0x87, 0x47, 0x0d, 0x47, 0x24, 0xe7, 0x14, 0xee, 0x35, 0x50, 0x14,
-	0x4f, 0x07, 0xdb, 0x60, 0x39, 0xce, 0xdc, 0xce, 0x15, 0x1e, 0x0a, 0xfe, 0x4b, 0x7d, 0x83, 0xd3,
-	0xbe, 0x29, 0xb8, 0xe1, 0x2c, 0xc5, 0x99, 0x7b, 0x82, 0x87, 0xf0, 0x18, 0x94, 0xf8, 0xb4, 0x21,
-	0x96, 0x25, 0xf8, 0xd5, 0xe6, 0xd7, 0xc6, 0x23, 0x7d, 0x55, 0x8a, 0x4c, 0x08, 0x86, 0x33, 0x25,
-	0xc3, 0x43, 0x00, 0xe2, 0x80, 0xbf, 0x33, 0xc3, 0x03, 0x26, 0xda, 0x5e, 0xb2, 0x3f, 0x1e, 0x8f,
-	0xf4, 0x35, 0x75, 0xf3, 0x24, 0x67, 0x38, 0x25, 0x71, 0xb8, 0xc0, 0x03, 0x36, 0x57, 0xda, 0x2f,
-	0xa0, 0x6a, 0x63, 0xef, 0xb2, 0x79, 0xa0, 0x66, 0x0a, 0x7e, 0x06, 0x8a, 0x7d, 0x14, 0x64, 0xf9,
-	0xfb, 0xac, 0x4e, 0xe7, 0x44, 0x84, 0x0d, 0x47, 0xa6, 0xe1, 0x17, 0x60, 0x29, 0x4e, 0x70, 0x8f,
-	0x0c, 0x44, 0x0d, 0x25, 0x7b, 0x6d, 0x3c, 0xd2, 0xab, 0xf9, 0x40, 0xf1, 0x38, 0xaf, 0x58, 0x7c,
-	0xb4, 0xb6, 0x66, 0x6f, 0xfc, 0xe7, 0xe9, 0xfc, 0x1a, 0x17, 0xa0, 0x6a, 0xa3, 0x14, 0x7f, 0xf5,
-	0xcd, 0x3b, 0x1a, 0x78, 0x5d, 0xf5, 0x67, 0x00, 0x8e, 0xf1, 0xe0, 0x7d, 0xd5, 0xf4, 0xab, 0x06,
-	0xd6, 0xcf, 0x49, 0xe4, 0x07, 0xf8, 0x3c, 0x6f, 0x16, 0x8f, 0xc3, 0xaf, 0xc1, 0x22, 0xdf, 0x8e,
-	0xc2, 0xc6, 0xca, 0xc1, 0x8e, 0xa9, 0xb6, 0x13, 0x1b, 0x98, 0xf9, 0xfe, 0x51, 0x1b, 0xc6, 0xe4,
-	0xbc, 0x33, 0xda, 0xc5, 0x8e, 0x20, 0xc0, 0x4f, 0xe6, 0x67, 0xa6, 0x32, 0x33, 0x07, 0xad, 0x0d,
-	0xee, 0x45, 0xf9, 0xa8, 0x3e, 0xb9, 0xd1, 0xf8, 0x53, 0x03, 0xf0, 0x8c, 0x6f, 0xab, 0xa7, 0x46,
-	0x4e, 0x41, 0xc9, 0x25, 0xac, 0x83, 0x92, 0x04, 0xe5, 0x83, 0x6c, 0xe5, 0x6e, 0xe4, 0xd2, 0x33,
-	0x27, 0x3b, 0x2e, 0xb7, 0x74, 0x44, 0xc3, 0x18, 0x79, 0xcc, 0x26, 0xac, 0xcd, 0x69, 0xce, 0x87,
-	0xae, 0xfa, 0xe2, 0x73, 0x38, 0x31, 0xc3, 0xf7, 0xd9, 0xc2, 0x4b, 0x23, 0xed, 0xcc, 0xe0, 0x5e,
-	0x71, 0x6d, 0x9f, 0xdc, 0x3e, 0x34, 0xb4, 0xbb, 0x87, 0x86, 0xf6, 0xdf, 0x43, 0x43, 0xbb, 0x7e,
-	0x6c, 0x14, 0xee, 0x1e, 0x1b, 0x85, 0xfb, 0xc7, 0x46, 0xe1, 0xa7, 0x7d, 0x9f, 0xb0, 0xcb, 0xcc,
-	0x35, 0x3d, 0x1a, 0x5a, 0x72, 0x23, 0xed, 0x05, 0xc8, 0x4d, 0xd5, 0xb7, 0xd5, 0x3f, 0xb4, 0x06,
-	0xd3, 0x9f, 0x11, 0x1b, 0xc6, 0x38, 0x75, 0x97, 0x84, 0x83, 0xe6, 0x9b, 0x00, 0x00, 0x00, 0xff,
-	0xff, 0x32, 0xbc, 0x6e, 0x9d, 0xac, 0x06, 0x00, 0x00,
+	// 939 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xc4, 0x55, 0x4d, 0x6f, 0xe3, 0x44,
+	0x18, 0x8e, 0xb7, 0xed, 0x2e, 0x99, 0xa4, 0xbb, 0xd9, 0x21, 0x2b, 0x65, 0xbb, 0x28, 0xee, 0x0e,
+	0x50, 0x96, 0x45, 0xb5, 0xd5, 0x76, 0x91, 0x50, 0x4f, 0xc4, 0xa9, 0x81, 0x68, 0xfb, 0x85, 0x93,
+	0x96, 0x0f, 0x21, 0x59, 0x63, 0x77, 0xe2, 0x5a, 0xf5, 0x97, 0xec, 0x49, 0x94, 0x48, 0x48, 0x5c,
+	0xf7, 0xb8, 0x47, 0x0e, 0x1c, 0x2a, 0xf1, 0x17, 0x38, 0xf1, 0x0b, 0x56, 0x9c, 0x56, 0x9c, 0xe0,
+	0x12, 0x50, 0x2b, 0x24, 0x24, 0x6e, 0xf9, 0x05, 0x68, 0x66, 0xec, 0x38, 0xa4, 0xe9, 0x22, 0x4e,
+	0xdc, 0x3c, 0xef, 0xfb, 0xbc, 0xcf, 0xbc, 0x1f, 0xcf, 0xbc, 0x06, 0xef, 0x9d, 0x90, 0xc4, 0x0f,
+	0x13, 0x35, 0x8a, 0xc3, 0xae, 0xeb, 0x91, 0x44, 0xed, 0x6f, 0xa9, 0x7e, 0x78, 0x42, 0xbc, 0xc4,
+	0xb4, 0x4f, 0xb1, 0x1b, 0x98, 0x9e, 0x1b, 0x9c, 0x25, 0x4a, 0x14, 0x87, 0x34, 0x84, 0x50, 0x80,
+	0x95, 0x0c, 0xac, 0xf4, 0xb7, 0x56, 0xaa, 0x4e, 0xe8, 0x84, 0xdc, 0xad, 0xb2, 0x2f, 0x81, 0x5c,
+	0xb9, 0xef, 0x84, 0xa1, 0xe3, 0x11, 0x95, 0x9f, 0xac, 0x5e, 0x57, 0xc5, 0xc1, 0x30, 0x75, 0xc9,
+	0xb3, 0x2e, 0xea, 0xfa, 0x24, 0xa1, 0xd8, 0x8f, 0xb2, 0x58, 0x3b, 0x64, 0xb7, 0x98, 0x82, 0x54,
+	0x1c, 0x52, 0xd7, 0x3b, 0xe2, 0xa4, 0xd2, 0x81, 0x9a, 0xb8, 0x4e, 0xe0, 0x06, 0x8e, 0xda, 0xdf,
+	0xb0, 0x08, 0xc5, 0x1b, 0xd9, 0x39, 0x05, 0xae, 0xa7, 0x40, 0x3b, 0x1e, 0x46, 0x34, 0x54, 0xfd,
+	0x9e, 0x47, 0xdd, 0xc4, 0xcd, 0xd1, 0x99, 0x41, 0xc0, 0xd1, 0x77, 0x0b, 0xa0, 0xd8, 0x64, 0xe5,
+	0xee, 0xba, 0xc1, 0x19, 0x7c, 0x13, 0x2c, 0xf6, 0x12, 0x12, 0xd7, 0xa4, 0x55, 0xe9, 0x51, 0x51,
+	0xbb, 0x33, 0x1e, 0xc9, 0xa5, 0x21, 0xf6, 0xbd, 0x6d, 0xc4, 0xac, 0xc8, 0xe0, 0x4e, 0xf8, 0x29,
+	0xb8, 0x85, 0x4f, 0x4e, 0x62, 0x92, 0x24, 0xb5, 0x1b, 0xab, 0xd2, 0xa3, 0xd2, 0x66, 0x55, 0x11,
+	0x85, 0x29, 0x59, 0x61, 0x4a, 0x23, 0x18, 0x6a, 0x0f, 0xc7, 0x23, 0xf9, 0xb6, 0x88, 0x4e, 0xe1,
+	0xe8, 0xa7, 0x1f, 0xd6, 0x4b, 0x0d, 0xf1, 0xbd, 0x83, 0x29, 0x36, 0x32, 0x1e, 0xa8, 0x83, 0xa5,
+	0x28, 0x0e, 0xc3, 0x6e, 0x6d, 0x81, 0x13, 0xde, 0x57, 0xae, 0xb6, 0x5b, 0x39, 0x64, 0x00, 0xad,
+	0xfa, 0x62, 0x24, 0x17, 0xc6, 0x23, 0xb9, 0x2c, 0x98, 0x79, 0x14, 0x32, 0x44, 0x34, 0x34, 0x41,
+	0x59, 0x8c, 0xce, 0x0e, 0x83, 0xae, 0xeb, 0xd4, 0x16, 0x39, 0x9b, 0x3c, 0x8f, 0x8d, 0xd7, 0xdc,
+	0xe4, 0x30, 0xed, 0x41, 0xca, 0xf9, 0xba, 0xe0, 0x9c, 0xa6, 0x40, 0x46, 0xc9, 0xce, 0x91, 0x10,
+	0x83, 0x65, 0x3b, 0x26, 0x98, 0xba, 0x61, 0x60, 0xb2, 0xe1, 0xd5, 0x96, 0xf8, 0x0d, 0x2b, 0x57,
+	0x1a, 0xd0, 0xc9, 0x26, 0xab, 0xad, 0xa6, 0xe4, 0xd5, 0x94, 0x7c, 0x3a, 0x1c, 0x3d, 0xff, 0x4d,
+	0x96, 0x8c, 0x72, 0x66, 0x63, 0x41, 0xdb, 0xe5, 0x67, 0xe7, 0x72, 0xe1, 0xdb, 0x73, 0x59, 0xfa,
+	0xf3, 0x5c, 0x96, 0xd0, 0x87, 0xa0, 0x34, 0x95, 0x29, 0x9b, 0x4f, 0x80, 0x7d, 0x72, 0x75, 0x3e,
+	0xcc, 0x8a, 0x0c, 0xee, 0x9c, 0x61, 0xf8, 0x43, 0x02, 0x4b, 0xbc, 0x75, 0xb0, 0x01, 0x6e, 0x45,
+	0x3d, 0xcb, 0x3c, 0x23, 0x43, 0x1e, 0x7f, 0xdd, 0xdc, 0x60, 0x3e, 0xb7, 0x14, 0x8e, 0x8c, 0x9b,
+	0x51, 0xcf, 0x7a, 0x4a, 0x86, 0xf0, 0x08, 0x14, 0x99, 0xda, 0x30, 0xed, 0xc5, 0xe4, 0x5f, 0x87,
+	0x5f, 0x11, 0x24, 0x93, 0x00, 0x36, 0xfe, 0x62, 0x3b, 0x3b, 0x19, 0x39, 0x13, 0x7c, 0x02, 0x40,
+	0xe4, 0xb1, 0xa6, 0x53, 0x32, 0xa0, 0x5c, 0x03, 0x45, 0xed, 0xde, 0x78, 0x24, 0xdf, 0x4d, 0xd3,
+	0x98, 0xf8, 0x90, 0x51, 0xe4, 0x87, 0x0e, 0x19, 0xd0, 0x99, 0x3a, 0xbf, 0x01, 0xcb, 0x1a, 0xb1,
+	0x4f, 0xb7, 0x36, 0x53, 0x81, 0xc1, 0x35, 0xb0, 0xd4, 0xc7, 0x5e, 0x2f, 0x6b, 0x56, 0x25, 0x17,
+	0x0d, 0x37, 0x23, 0x43, 0xb8, 0xe1, 0xbb, 0xe0, 0x66, 0x14, 0x93, 0xae, 0x3b, 0xe0, 0x05, 0x15,
+	0xb5, 0xbb, 0xe3, 0x91, 0xbc, 0x9c, 0xa9, 0x8b, 0xd9, 0x59, 0xf9, 0xfc, 0x63, 0xfb, 0xc1, 0xf4,
+	0x8d, 0x3f, 0xff, 0x53, 0xcc, 0xa8, 0x03, 0x96, 0x35, 0x9c, 0x90, 0xf7, 0x3f, 0xf8, 0x8f, 0x09,
+	0xbc, 0x9a, 0xf5, 0x6b, 0x00, 0x3e, 0x21, 0x83, 0xff, 0xab, 0xa6, 0x1f, 0x25, 0x70, 0xa7, 0xed,
+	0x06, 0x8e, 0x47, 0x26, 0x73, 0x83, 0x5f, 0x01, 0xc0, 0x2f, 0x31, 0xe9, 0x30, 0x12, 0x89, 0xdc,
+	0xde, 0x5c, 0x9b, 0xf7, 0xc4, 0x26, 0x21, 0xc7, 0x0c, 0xde, 0x19, 0x46, 0x64, 0x7a, 0xa8, 0x39,
+	0x07, 0x32, 0x8a, 0xfd, 0x0c, 0x01, 0x37, 0x67, 0x15, 0x56, 0xd6, 0xaa, 0xf3, 0xb4, 0x34, 0x25,
+	0x9f, 0xed, 0x7b, 0xac, 0x84, 0x34, 0xfd, 0x5c, 0x60, 0xe8, 0x2f, 0x09, 0x54, 0x9b, 0x7c, 0x19,
+	0xee, 0xb1, 0x9d, 0x97, 0x57, 0x60, 0x81, 0xa2, 0xe5, 0x52, 0x13, 0xc7, 0x31, 0xce, 0x9e, 0x82,
+	0xaa, 0xa4, 0xdb, 0x56, 0xac, 0x4d, 0x65, 0xb2, 0x25, 0xd3, 0xb5, 0xa9, 0x34, 0x43, 0x3f, 0xc2,
+	0x36, 0xd5, 0x5c, 0xda, 0x60, 0x61, 0xd3, 0x49, 0x4d, 0xb8, 0x90, 0xf1, 0x9a, 0x95, 0xfa, 0xe1,
+	0xe7, 0x00, 0x4c, 0x12, 0x64, 0x7b, 0x72, 0xe1, 0xda, 0xa7, 0x82, 0xf2, 0x9e, 0xe4, 0x11, 0x33,
+	0x6f, 0x65, 0x8a, 0xeb, 0x9a, 0x6a, 0x1f, 0xff, 0x2a, 0x01, 0x78, 0xb5, 0xe3, 0xf0, 0x2d, 0xb0,
+	0xda, 0x6e, 0x7d, 0xbc, 0xdf, 0xe8, 0x1c, 0x19, 0xba, 0x79, 0xdc, 0xd8, 0x3d, 0xd2, 0xcd, 0xce,
+	0x17, 0x87, 0xba, 0x79, 0xb4, 0xdf, 0x3e, 0xd4, 0x9b, 0xad, 0x8f, 0x5a, 0xfa, 0x4e, 0xa5, 0x00,
+	0xdf, 0x00, 0xb5, 0xb9, 0x28, 0xa3, 0xf1, 0x59, 0x45, 0x82, 0x6b, 0x00, 0xcd, 0xf5, 0x36, 0x0f,
+	0xda, 0x7b, 0x07, 0x6d, 0x73, 0xa7, 0x65, 0xe8, 0xcd, 0x4e, 0xe5, 0x06, 0x7c, 0x1b, 0x3c, 0x7c,
+	0x15, 0xae, 0xb1, 0xd7, 0xda, 0x3f, 0xa8, 0x2c, 0xc0, 0xc7, 0x60, 0x6d, 0x2e, 0x4c, 0x3f, 0xde,
+	0x33, 0x0f, 0x75, 0xa3, 0x7d, 0xb0, 0xdf, 0xd8, 0x35, 0x19, 0xa2, 0xb2, 0xb8, 0xb2, 0xf8, 0xec,
+	0xfb, 0x7a, 0x41, 0x7b, 0xfa, 0xe2, 0xa2, 0x2e, 0xbd, 0xbc, 0xa8, 0x4b, 0xbf, 0x5f, 0xd4, 0xa5,
+	0xe7, 0x97, 0xf5, 0xc2, 0xcb, 0xcb, 0x7a, 0xe1, 0x97, 0xcb, 0x7a, 0xe1, 0xcb, 0x0d, 0xc7, 0xa5,
+	0xa7, 0x3d, 0x4b, 0xb1, 0x43, 0x5f, 0x15, 0x12, 0x5c, 0xf7, 0xb0, 0x95, 0xa4, 0xdf, 0x6a, 0xff,
+	0x89, 0x3a, 0xc8, 0x7f, 0xf0, 0x4c, 0x6c, 0x89, 0x75, 0x93, 0x77, 0x7f, 0xeb, 0xef, 0x00, 0x00,
+	0x00, 0xff, 0xff, 0xc6, 0x1b, 0x1e, 0xb8, 0x00, 0x08, 0x00, 0x00,
 }
 
 func (this *ChainLink) Equal(that interface{}) bool {
@@ -607,14 +664,14 @@ func (this *HexAddress) Equal(that interface{}) bool {
 	}
 	return true
 }
-func (this *SingleSignatureData) Equal(that interface{}) bool {
+func (this *SingleSignature) Equal(that interface{}) bool {
 	if that == nil {
 		return this == nil
 	}
 
-	that1, ok := that.(*SingleSignatureData)
+	that1, ok := that.(*SingleSignature)
 	if !ok {
-		that2, ok := that.(SingleSignatureData)
+		that2, ok := that.(SingleSignature)
 		if ok {
 			that1 = &that2
 		} else {
@@ -626,7 +683,7 @@ func (this *SingleSignatureData) Equal(that interface{}) bool {
 	} else if this == nil {
 		return false
 	}
-	if this.Mode != that1.Mode {
+	if this.ValueType != that1.ValueType {
 		return false
 	}
 	if !bytes.Equal(this.Signature, that1.Signature) {
@@ -634,14 +691,14 @@ func (this *SingleSignatureData) Equal(that interface{}) bool {
 	}
 	return true
 }
-func (this *MultiSignatureData) Equal(that interface{}) bool {
+func (this *CosmosMultiSignature) Equal(that interface{}) bool {
 	if that == nil {
 		return this == nil
 	}
 
-	that1, ok := that.(*MultiSignatureData)
+	that1, ok := that.(*CosmosMultiSignature)
 	if !ok {
-		that2, ok := that.(MultiSignatureData)
+		that2, ok := that.(CosmosMultiSignature)
 		if ok {
 			that1 = &that2
 		} else {
@@ -924,7 +981,7 @@ func (m *HexAddress) MarshalToSizedBuffer(dAtA []byte) (int, error) {
 	return len(dAtA) - i, nil
 }
 
-func (m *SingleSignatureData) Marshal() (dAtA []byte, err error) {
+func (m *SingleSignature) Marshal() (dAtA []byte, err error) {
 	size := m.Size()
 	dAtA = make([]byte, size)
 	n, err := m.MarshalToSizedBuffer(dAtA[:size])
@@ -934,12 +991,12 @@ func (m *SingleSignatureData) Marshal() (dAtA []byte, err error) {
 	return dAtA[:n], nil
 }
 
-func (m *SingleSignatureData) MarshalTo(dAtA []byte) (int, error) {
+func (m *SingleSignature) MarshalTo(dAtA []byte) (int, error) {
 	size := m.Size()
 	return m.MarshalToSizedBuffer(dAtA[:size])
 }
 
-func (m *SingleSignatureData) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+func (m *SingleSignature) MarshalToSizedBuffer(dAtA []byte) (int, error) {
 	i := len(dAtA)
 	_ = i
 	var l int
@@ -951,15 +1008,15 @@ func (m *SingleSignatureData) MarshalToSizedBuffer(dAtA []byte) (int, error) {
 		i--
 		dAtA[i] = 0x12
 	}
-	if m.Mode != 0 {
-		i = encodeVarintModelsChainLinks(dAtA, i, uint64(m.Mode))
+	if m.ValueType != 0 {
+		i = encodeVarintModelsChainLinks(dAtA, i, uint64(m.ValueType))
 		i--
 		dAtA[i] = 0x8
 	}
 	return len(dAtA) - i, nil
 }
 
-func (m *MultiSignatureData) Marshal() (dAtA []byte, err error) {
+func (m *CosmosMultiSignature) Marshal() (dAtA []byte, err error) {
 	size := m.Size()
 	dAtA = make([]byte, size)
 	n, err := m.MarshalToSizedBuffer(dAtA[:size])
@@ -969,12 +1026,12 @@ func (m *MultiSignatureData) Marshal() (dAtA []byte, err error) {
 	return dAtA[:n], nil
 }
 
-func (m *MultiSignatureData) MarshalTo(dAtA []byte) (int, error) {
+func (m *CosmosMultiSignature) MarshalTo(dAtA []byte) (int, error) {
 	size := m.Size()
 	return m.MarshalToSizedBuffer(dAtA[:size])
 }
 
-func (m *MultiSignatureData) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+func (m *CosmosMultiSignature) MarshalToSizedBuffer(dAtA []byte) (int, error) {
 	i := len(dAtA)
 	_ = i
 	var l int
@@ -1123,14 +1180,14 @@ func (m *HexAddress) Size() (n int) {
 	return n
 }
 
-func (m *SingleSignatureData) Size() (n int) {
+func (m *SingleSignature) Size() (n int) {
 	if m == nil {
 		return 0
 	}
 	var l int
 	_ = l
-	if m.Mode != 0 {
-		n += 1 + sovModelsChainLinks(uint64(m.Mode))
+	if m.ValueType != 0 {
+		n += 1 + sovModelsChainLinks(uint64(m.ValueType))
 	}
 	l = len(m.Signature)
 	if l > 0 {
@@ -1139,7 +1196,7 @@ func (m *SingleSignatureData) Size() (n int) {
 	return n
 }
 
-func (m *MultiSignatureData) Size() (n int) {
+func (m *CosmosMultiSignature) Size() (n int) {
 	if m == nil {
 		return 0
 	}
@@ -1927,7 +1984,7 @@ func (m *HexAddress) Unmarshal(dAtA []byte) error {
 	}
 	return nil
 }
-func (m *SingleSignatureData) Unmarshal(dAtA []byte) error {
+func (m *SingleSignature) Unmarshal(dAtA []byte) error {
 	l := len(dAtA)
 	iNdEx := 0
 	for iNdEx < l {
@@ -1950,17 +2007,17 @@ func (m *SingleSignatureData) Unmarshal(dAtA []byte) error {
 		fieldNum := int32(wire >> 3)
 		wireType := int(wire & 0x7)
 		if wireType == 4 {
-			return fmt.Errorf("proto: SingleSignatureData: wiretype end group for non-group")
+			return fmt.Errorf("proto: SingleSignature: wiretype end group for non-group")
 		}
 		if fieldNum <= 0 {
-			return fmt.Errorf("proto: SingleSignatureData: illegal tag %d (wire type %d)", fieldNum, wire)
+			return fmt.Errorf("proto: SingleSignature: illegal tag %d (wire type %d)", fieldNum, wire)
 		}
 		switch fieldNum {
 		case 1:
 			if wireType != 0 {
-				return fmt.Errorf("proto: wrong wireType = %d for field Mode", wireType)
+				return fmt.Errorf("proto: wrong wireType = %d for field ValueType", wireType)
 			}
-			m.Mode = 0
+			m.ValueType = 0
 			for shift := uint(0); ; shift += 7 {
 				if shift >= 64 {
 					return ErrIntOverflowModelsChainLinks
@@ -1970,7 +2027,7 @@ func (m *SingleSignatureData) Unmarshal(dAtA []byte) error {
 				}
 				b := dAtA[iNdEx]
 				iNdEx++
-				m.Mode |= signing.SignMode(b&0x7F) << shift
+				m.ValueType |= SignatureValueType(b&0x7F) << shift
 				if b < 0x80 {
 					break
 				}
@@ -2030,7 +2087,7 @@ func (m *SingleSignatureData) Unmarshal(dAtA []byte) error {
 	}
 	return nil
 }
-func (m *MultiSignatureData) Unmarshal(dAtA []byte) error {
+func (m *CosmosMultiSignature) Unmarshal(dAtA []byte) error {
 	l := len(dAtA)
 	iNdEx := 0
 	for iNdEx < l {
@@ -2053,10 +2110,10 @@ func (m *MultiSignatureData) Unmarshal(dAtA []byte) error {
 		fieldNum := int32(wire >> 3)
 		wireType := int(wire & 0x7)
 		if wireType == 4 {
-			return fmt.Errorf("proto: MultiSignatureData: wiretype end group for non-group")
+			return fmt.Errorf("proto: CosmosMultiSignature: wiretype end group for non-group")
 		}
 		if fieldNum <= 0 {
-			return fmt.Errorf("proto: MultiSignatureData: illegal tag %d (wire type %d)", fieldNum, wire)
+			return fmt.Errorf("proto: CosmosMultiSignature: illegal tag %d (wire type %d)", fieldNum, wire)
 		}
 		switch fieldNum {
 		case 1:


Test patch:
diff --git a/app/desmos/cmd/chainlink/create_json_suite_test.go b/app/desmos/cmd/chainlink/create_json_suite_test.go
index 2ee7fc2d..2be65d21 100644
--- a/app/desmos/cmd/chainlink/create_json_suite_test.go
+++ b/app/desmos/cmd/chainlink/create_json_suite_test.go
@@ -1,3 +1,6 @@
+//go:build norace
+// +build norace
+
 package chainlink_test
 
 import (
diff --git a/app/desmos/cmd/chainlink/create_json_test.go b/app/desmos/cmd/chainlink/create_json_test.go
index 5581d81e..a4ef81ce 100644
--- a/app/desmos/cmd/chainlink/create_json_test.go
+++ b/app/desmos/cmd/chainlink/create_json_test.go
@@ -1,3 +1,6 @@
+//go:build norace
+// +build norace
+
 package chainlink_test
 
 import (
@@ -64,8 +67,9 @@ func (suite *CreateJSONChainLinkTestSuite) TestSingleSignatureAccount() {
 		profilestypes.NewBech32Address("cosmos13j7p6faa9jr8ty6lvqv0prldprr6m5xenmafnt", "cosmos"),
 		profilestypes.NewProof(
 			key.GetPubKey(),
-			profilestesting.SingleSignatureProtoFromHex(hex.EncodeToString(sig)),
-			hex.EncodeToString([]byte(suite.Owner))),
+			profilestesting.SingleSignatureFromHex(hex.EncodeToString(sig)),
+			hex.EncodeToString([]byte(suite.Owner)),
+		),
 		profilestypes.NewChainConfig("cosmos"),
 	)
 
@@ -177,9 +181,9 @@ func (suite *CreateJSONChainLinkTestSuite) TestMultiSignatureAccount() {
 		profilestypes.NewBech32Address("cosmos1exdjkfxud8yzqtvua3hdd93xu0gmek5l47r8ra", "cosmos"),
 		profilestypes.NewProof(
 			suite.GetPubKeyFromTxFile(txFile),
-			profilestesting.MultiSignatureProtoFromAnyHex(
+			profilestesting.MultiCosmosSignatureFromHex(
 				suite.Codec,
-				"0a262f6465736d6f732e70726f66696c65732e76332e4d756c74695369676e61747572654461746112e9010a0508031201c0126f0a272f6465736d6f732e70726f66696c65732e76332e53696e676c655369676e6174757265446174611244087f124027fc4567818a29803ec13f429404c7131c818acc1954f512f3d71a3379e7ec741d25de8b142f61151652b06ef78aaeffd58707023e6e8dfbe98c990185016476126f0a272f6465736d6f732e70726f66696c65732e76332e53696e676c655369676e6174757265446174611244087f12409394c86630e7afb961899add8fc1a211d14b8cc38702c53caa701851557f35832c11e11510da4d676578a19b342865317547549b2b4bd78cdf809dafa55041f7",
+				"0a282f6465736d6f732e70726f66696c65732e76332e436f736d6f734d756c74695369676e617475726512e1010a0508031201c0126b0a232f6465736d6f732e70726f66696c65732e76332e53696e676c655369676e617475726512440803124027fc4567818a29803ec13f429404c7131c818acc1954f512f3d71a3379e7ec741d25de8b142f61151652b06ef78aaeffd58707023e6e8dfbe98c990185016476126b0a232f6465736d6f732e70726f66696c65732e76332e53696e676c655369676e61747572651244080312409394c86630e7afb961899add8fc1a211d14b8cc38702c53caa701851557f35832c11e11510da4d676578a19b342865317547549b2b4bd78cdf809dafa55041f7",
 			),
 			"7b226163636f756e745f6e756d626572223a2230222c22636861696e5f6964223a22636f736d6f73222c22666565223a7b22616d6f756e74223a5b5d2c22676173223a22323030303030227d2c226d656d6f223a226465736d6f73316e3833343574767a6b67336a756d6b6d3835397232717a3076367873633368656e7a6464636a222c226d736773223a5b7b2274797065223a22636f736d6f732d73646b2f4d7367566f7465222c2276616c7565223a7b226f7074696f6e223a312c2270726f706f73616c5f6964223a2231222c22766f746572223a22636f736d6f73316578646a6b6678756438797a7174767561336864643933787530676d656b356c343772387261227d7d5d2c2273657175656e6365223a2230227d",
 		),
diff --git a/app/desmos/cmd/sign/sign_test.go b/app/desmos/cmd/sign/sign_test.go
index de06b041..05a4a7c0 100644
--- a/app/desmos/cmd/sign/sign_test.go
+++ b/app/desmos/cmd/sign/sign_test.go
@@ -1,3 +1,6 @@
+//go:build norace
+// +build norace
+
 package sign_test
 
 import (
diff --git a/testutil/profilestesting/chain_links.go b/testutil/profilestesting/chain_links.go
index 36dac065..591fea83 100644
--- a/testutil/profilestesting/chain_links.go
+++ b/testutil/profilestesting/chain_links.go
@@ -8,7 +8,6 @@ import (
 	"github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1"
 	cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
 	sdk "github.com/cosmos/cosmos-sdk/types"
-	"github.com/cosmos/cosmos-sdk/types/tx/signing"
 
 	"github.com/desmos-labs/desmos/v4/x/profiles/types"
 )
@@ -53,11 +52,8 @@ func (a ChainLinkAccount) Bech32Address() *types.Bech32Address {
 	return types.NewBech32Address(addr, a.bech32Prefix)
 }
 
-func (a ChainLinkAccount) Bech32SignatureData(signedValue string) types.SignatureData {
-	return &types.SingleSignatureData{
-		Mode:      signing.SignMode_SIGN_MODE_TEXTUAL,
-		Signature: a.Sign(signedValue),
-	}
+func (a ChainLinkAccount) Bech32SignatureData(signedValue string) types.Signature {
+	return types.NewSingleSignature(types.SIGNATURE_VALUE_TYPE_RAW, a.Sign(signedValue))
 }
 
 func (a ChainLinkAccount) Bech32Proof(user string) types.Proof {
diff --git a/testutil/profilestesting/profiles.go b/testutil/profilestesting/profiles.go
index d4ac2906..c29a76f9 100644
--- a/testutil/profilestesting/profiles.go
+++ b/testutil/profilestesting/profiles.go
@@ -11,7 +11,6 @@ import (
 	cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
 	sdk "github.com/cosmos/cosmos-sdk/types"
 	"github.com/cosmos/cosmos-sdk/types/bech32/legacybech32"
-	"github.com/cosmos/cosmos-sdk/types/tx/signing"
 	authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
 
 	"github.com/gogo/protobuf/proto"
@@ -75,20 +74,17 @@ func ProfileFromAddr(address string) *types.Profile {
 	return profile
 }
 
-// SingleSignatureProtoFromHex convert the hex-encoded string of the single signature to SignatureData
-func SingleSignatureProtoFromHex(s string) types.SignatureData {
-	sig, err := hex.DecodeString(s)
+// SingleSignatureFromHex convert the hex-encoded string of the single signature to CosmosSignatureData
+func SingleSignatureFromHex(hexEncodedSignature string) types.Signature {
+	sig, err := hex.DecodeString(hexEncodedSignature)
 	if err != nil {
 		panic(err)
 	}
-	return &types.SingleSignatureData{
-		Mode:      signing.SignMode_SIGN_MODE_DIRECT,
-		Signature: sig,
-	}
+	return types.NewSingleSignature(types.SIGNATURE_VALUE_TYPE_RAW, sig)
 }
 
-// MultiSignatureProtoFromAnyHex convert the hex-encoded string of the MultiSignature Any value to SignatureData
-func MultiSignatureProtoFromAnyHex(unpacker codectypes.AnyUnpacker, hexEncodedSignatureData string) types.SignatureData {
+// MultiCosmosSignatureFromHex convert the hex-encoded string of the MultiSignature Any value to CosmosSignatureData
+func MultiCosmosSignatureFromHex(unpacker codectypes.AnyUnpacker, hexEncodedSignatureData string) types.Signature {
 	sig, err := hex.DecodeString(hexEncodedSignatureData)
 	if err != nil {
 		panic(err)
@@ -100,9 +96,9 @@ func MultiSignatureProtoFromAnyHex(unpacker codectypes.AnyUnpacker, hexEncodedSi
 		panic(err)
 	}
 
-	var sigData types.SignatureData
-	if err = unpacker.UnpackAny(&multisigAny, &sigData); err != nil {
+	var signature types.Signature
+	if err = unpacker.UnpackAny(&multisigAny, &signature); err != nil {
 		panic(err)
 	}
-	return sigData
+	return signature
 }
diff --git a/x/profiles/client/cli/cli_profile_test.go b/x/profiles/client/cli/cli_profile_test.go
index 09e9e8b7..3e78493b 100644
--- a/x/profiles/client/cli/cli_profile_test.go
+++ b/x/profiles/client/cli/cli_profile_test.go
@@ -51,10 +51,7 @@ func (s *IntegrationTestSuite) TestCmdQueryProfile() {
 				s.network.Validators[1].Address.String(),
 				fmt.Sprintf("--%s=json", tmcli.OutputFlag),
 			},
-			shouldErr: false,
-			expectedOutput: types.QueryProfileResponse{
-				Profile: nil,
-			},
+			shouldErr: true,
 		},
 		{
 			name: "existing profile is returned properly",
diff --git a/x/profiles/client/cli/cli_test.go b/x/profiles/client/cli/cli_test.go
index 6898760b..f3bddd9d 100644
--- a/x/profiles/client/cli/cli_test.go
+++ b/x/profiles/client/cli/cli_test.go
@@ -208,7 +208,7 @@ func (s *IntegrationTestSuite) writeChainLinkJSONFile(filePath string) {
 
 	jsonData := utils.NewChainLinkJSON(
 		types.NewBech32Address(addStr, "cosmos"),
-		types.NewProof(srcKey.PubKey(), profilestesting.SingleSignatureProtoFromHex(hex.EncodeToString(sigBz)), hex.EncodeToString([]byte(plainText))),
+		types.NewProof(srcKey.PubKey(), profilestesting.SingleSignatureFromHex(hex.EncodeToString(sigBz)), hex.EncodeToString([]byte(plainText))),
 		types.NewChainConfig("cosmos"),
 	)
 
diff --git a/x/profiles/client/utils/utils_test.go b/x/profiles/client/utils/utils_test.go
index 1a1150eb..968d260c 100644
--- a/x/profiles/client/utils/utils_test.go
+++ b/x/profiles/client/utils/utils_test.go
@@ -34,7 +34,7 @@ func TestParseLinkAccountJSON(t *testing.T) {
 
 	jsonData := utils.NewChainLinkJSON(
 		types.NewBech32Address(addStr, "cosmos"),
-		types.NewProof(pubKey, profilestesting.SingleSignatureProtoFromHex(hex.EncodeToString(sigBz)), plainText),
+		types.NewProof(pubKey, profilestesting.SingleSignatureFromHex(hex.EncodeToString(sigBz)), plainText),
 		types.NewChainConfig("cosmos"),
 	)
 
diff --git a/x/profiles/keeper/alias_functions_test.go b/x/profiles/keeper/alias_functions_test.go
index 7dc2b071..22cf3ce0 100644
--- a/x/profiles/keeper/alias_functions_test.go
+++ b/x/profiles/keeper/alias_functions_test.go
@@ -385,7 +385,7 @@ func (suite *KeeperTestSuite) TestKeeper_GetChainLinks() {
 						types.NewChainLink(
 							"cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47",
 							types.NewBech32Address("cosmos10clxpupsmddtj7wu7g0wdysajqwp890mva046f", "cosmos"),
-							types.NewProof(pub1, profilestesting.SingleSignatureProtoFromHex("1234"), "plain_text"),
+							types.NewProof(pub1, profilestesting.SingleSignatureFromHex("1234"), "plain_text"),
 							types.NewChainConfig("cosmos"),
 							time.Date(2020, 1, 2, 00, 00, 00, 000, time.UTC),
 						),
@@ -398,7 +398,7 @@ func (suite *KeeperTestSuite) TestKeeper_GetChainLinks() {
 						types.NewChainLink(
 							"cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47",
 							types.NewBech32Address("cosmos1ftkjv8njvkekk00ehwdfl5sst8zgdpenjfm4hs", "cosmos"),
-							types.NewProof(pub2, profilestesting.SingleSignatureProtoFromHex("1234"), "plain_text"),
+							types.NewProof(pub2, profilestesting.SingleSignatureFromHex("1234"), "plain_text"),
 							types.NewChainConfig("cosmos"),
 							time.Date(2020, 1, 2, 00, 00, 00, 000, time.UTC),
 						),
@@ -409,14 +409,14 @@ func (suite *KeeperTestSuite) TestKeeper_GetChainLinks() {
 				types.NewChainLink(
 					"cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47",
 					types.NewBech32Address("cosmos10clxpupsmddtj7wu7g0wdysajqwp890mva046f", "cosmos"),
-					types.NewProof(pub1, profilestesting.SingleSignatureProtoFromHex("1234"), "plain_text"),
+					types.NewProof(pub1, profilestesting.SingleSignatureFromHex("1234"), "plain_text"),
 					types.NewChainConfig("cosmos"),
 					time.Date(2020, 1, 2, 00, 00, 00, 000, time.UTC),
 				),
 				types.NewChainLink(
 					"cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47",
 					types.NewBech32Address("cosmos1ftkjv8njvkekk00ehwdfl5sst8zgdpenjfm4hs", "cosmos"),
-					types.NewProof(pub2, profilestesting.SingleSignatureProtoFromHex("1234"), "plain_text"),
+					types.NewProof(pub2, profilestesting.SingleSignatureFromHex("1234"), "plain_text"),
 					types.NewChainConfig("cosmos"),
 					time.Date(2020, 1, 2, 00, 00, 00, 000, time.UTC),
 				),
diff --git a/x/profiles/keeper/genesis_test.go b/x/profiles/keeper/genesis_test.go
index a9cb4d91..b5940300 100644
--- a/x/profiles/keeper/genesis_test.go
+++ b/x/profiles/keeper/genesis_test.go
@@ -216,14 +216,14 @@ func (suite *KeeperTestSuite) Test_InitGenesis() {
 					types.NewChainLink(
 						"cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47",
 						types.NewBech32Address(ext.GetAddress().String(), "cosmos"),
-						types.NewProof(ext.GetPubKey(), profilestesting.SingleSignatureProtoFromHex(hex.EncodeToString(ext.Sign(ext.GetAddress()))), hex.EncodeToString([]byte(ext.GetAddress().String()))),
+						types.NewProof(ext.GetPubKey(), profilestesting.SingleSignatureFromHex(hex.EncodeToString(ext.Sign(ext.GetAddress()))), hex.EncodeToString([]byte(ext.GetAddress().String()))),
 						types.NewChainConfig("cosmos"),
 						time.Date(2020, 1, 2, 00, 00, 00, 000, time.UTC),
 					),
 					types.NewChainLink(
 						"cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47",
 						types.NewBech32Address(ext.GetAddress().String(), "cosmos"),
-						types.NewProof(ext.GetPubKey(), profilestesting.SingleSignatureProtoFromHex(hex.EncodeToString(ext.Sign(ext.GetAddress()))), hex.EncodeToString([]byte(ext.GetAddress().String()))),
+						types.NewProof(ext.GetPubKey(), profilestesting.SingleSignatureFromHex(hex.EncodeToString(ext.Sign(ext.GetAddress()))), hex.EncodeToString([]byte(ext.GetAddress().String()))),
 						types.NewChainConfig("cosmos"),
 						time.Date(2020, 1, 2, 00, 00, 00, 000, time.UTC),
 					),
@@ -278,7 +278,7 @@ func (suite *KeeperTestSuite) Test_InitGenesis() {
 						types.NewBech32Address(ext.GetAddress().String(), "cosmos"),
 						types.NewProof(
 							ext.GetPubKey(),
-							profilestesting.SingleSignatureProtoFromHex(
+							profilestesting.SingleSignatureFromHex(
 								hex.EncodeToString(ext.Sign([]byte("cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47"))),
 							),
 							hex.EncodeToString([]byte("cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47")),
@@ -339,7 +339,7 @@ func (suite *KeeperTestSuite) Test_InitGenesis() {
 						types.NewBech32Address(ext.GetAddress().String(), "cosmos"),
 						types.NewProof(
 							ext.GetPubKey(),
-							profilestesting.SingleSignatureProtoFromHex(
+							profilestesting.SingleSignatureFromHex(
 								hex.EncodeToString(ext.Sign([]byte("cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47"))),
 							),
 							hex.EncodeToString([]byte("cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47")),
diff --git a/x/profiles/keeper/grpc_query_test.go b/x/profiles/keeper/grpc_query_test.go
index c282c8a9..bfe41b05 100644
--- a/x/profiles/keeper/grpc_query_test.go
+++ b/x/profiles/keeper/grpc_query_test.go
@@ -30,10 +30,9 @@ func (suite *KeeperTestSuite) TestQueryServer_Profile() {
 			shouldErr: true,
 		},
 		{
-			name:        "profile not found",
-			req:         types.NewQueryProfileRequest("cosmos19mj6dkd85m84gxvf8d929w572z5h9q0u8d8wpa"),
-			shouldErr:   false,
-			expResponse: &types.QueryProfileResponse{Profile: nil},
+			name:      "profile not found returns error",
+			req:       types.NewQueryProfileRequest("cosmos19mj6dkd85m84gxvf8d929w572z5h9q0u8d8wpa"),
+			shouldErr: true,
 		},
 		{
 			name: "found profile using DTag",
@@ -240,7 +239,7 @@ func (suite *KeeperTestSuite) TestQueryServer_ChainLinks() {
 					types.NewBech32Address("cosmos1cjf97gpzwmaf30pzvaargfgr884mpp5ak8f7ns", "cosmos"),
 					types.NewProof(
 						profilestesting.PubKeyFromBech32("cosmospub1addwnpepqvryxhhqhw52c4ny5twtfzf3fsrjqhx0x5cuya0fylw0wu0eqptykeqhr4d"),
-						profilestesting.SingleSignatureProtoFromHex("909e38994b1583d3f14384c2e9a03c90064e8fd8e19b780bb0ba303dfe671a27287da04d0ce096ce9a140bd070ee36818f5519eb2070a16971efd8143855524b"),
+						profilestesting.SingleSignatureFromHex("909e38994b1583d3f14384c2e9a03c90064e8fd8e19b780bb0ba303dfe671a27287da04d0ce096ce9a140bd070ee36818f5519eb2070a16971efd8143855524b"),
 						"74657874",
 					),
 					types.NewChainConfig("cosmos"),
@@ -256,7 +255,7 @@ func (suite *KeeperTestSuite) TestQueryServer_ChainLinks() {
 					types.NewBech32Address("cosmos19s242dxhxgzlsdmfjjg38jgfwhxca7569g84sw", "cosmos"),
 					types.NewProof(
 						profilestesting.PubKeyFromBech32("cosmospub1addwnpepqvryxhhqhw52c4ny5twtfzf3fsrjqhx0x5cuya0fylw0wu0eqptykeqhr4d"),
-						profilestesting.SingleSignatureProtoFromHex("909e38994b1583d3f14384c2e9a03c90064e8fd8e19b780bb0ba303dfe671a27287da04d0ce096ce9a140bd070ee36818f5519eb2070a16971efd8143855524b"),
+						profilestesting.SingleSignatureFromHex("909e38994b1583d3f14384c2e9a03c90064e8fd8e19b780bb0ba303dfe671a27287da04d0ce096ce9a140bd070ee36818f5519eb2070a16971efd8143855524b"),
 						"74657874",
 					),
 					types.NewChainConfig("cosmos"),
@@ -278,7 +277,7 @@ func (suite *KeeperTestSuite) TestQueryServer_ChainLinks() {
 					types.NewBech32Address("cosmos19s242dxhxgzlsdmfjjg38jgfwhxca7569g84sw", "cosmos"),
 					types.NewProof(
 						profilestesting.PubKeyFromBech32("cosmospub1addwnpepqvryxhhqhw52c4ny5twtfzf3fsrjqhx0x5cuya0fylw0wu0eqptykeqhr4d"),
-						profilestesting.SingleSignatureProtoFromHex("909e38994b1583d3f14384c2e9a03c90064e8fd8e19b780bb0ba303dfe671a27287da04d0ce096ce9a140bd070ee36818f5519eb2070a16971efd8143855524b"),
+						profilestesting.SingleSignatureFromHex("909e38994b1583d3f14384c2e9a03c90064e8fd8e19b780bb0ba303dfe671a27287da04d0ce096ce9a140bd070ee36818f5519eb2070a16971efd8143855524b"),
 						"74657874",
 					),
 					types.NewChainConfig("cosmos"),
@@ -289,7 +288,7 @@ func (suite *KeeperTestSuite) TestQueryServer_ChainLinks() {
 					types.NewBech32Address("cosmos1cjf97gpzwmaf30pzvaargfgr884mpp5ak8f7ns", "cosmos"),
 					types.NewProof(
 						profilestesting.PubKeyFromBech32("cosmospub1addwnpepqvryxhhqhw52c4ny5twtfzf3fsrjqhx0x5cuya0fylw0wu0eqptykeqhr4d"),
-						profilestesting.SingleSignatureProtoFromHex("909e38994b1583d3f14384c2e9a03c90064e8fd8e19b780bb0ba303dfe671a27287da04d0ce096ce9a140bd070ee36818f5519eb2070a16971efd8143855524b"),
+						profilestesting.SingleSignatureFromHex("909e38994b1583d3f14384c2e9a03c90064e8fd8e19b780bb0ba303dfe671a27287da04d0ce096ce9a140bd070ee36818f5519eb2070a16971efd8143855524b"),
 						"74657874",
 					),
 					types.NewChainConfig("cosmos"),
@@ -306,7 +305,7 @@ func (suite *KeeperTestSuite) TestQueryServer_ChainLinks() {
 					types.NewBech32Address("cosmos1cjf97gpzwmaf30pzvaargfgr884mpp5ak8f7ns", "cosmos"),
 					types.NewProof(
 						profilestesting.PubKeyFromBech32("cosmospub1addwnpepqvryxhhqhw52c4ny5twtfzf3fsrjqhx0x5cuya0fylw0wu0eqptykeqhr4d"),
-						profilestesting.SingleSignatureProtoFromHex("909e38994b1583d3f14384c2e9a03c90064e8fd8e19b780bb0ba303dfe671a27287da04d0ce096ce9a140bd070ee36818f5519eb2070a16971efd8143855524b"),
+						profilestesting.SingleSignatureFromHex("909e38994b1583d3f14384c2e9a03c90064e8fd8e19b780bb0ba303dfe671a27287da04d0ce096ce9a140bd070ee36818f5519eb2070a16971efd8143855524b"),
 						"74657874",
 					),
 					types.NewChainConfig("cosmos"),
@@ -322,7 +321,7 @@ func (suite *KeeperTestSuite) TestQueryServer_ChainLinks() {
 					types.NewBech32Address("cosmos19s242dxhxgzlsdmfjjg38jgfwhxca7569g84sw", "cosmos"),
 					types.NewProof(
 						profilestesting.PubKeyFromBech32("cosmospub1addwnpepqvryxhhqhw52c4ny5twtfzf3fsrjqhx0x5cuya0fylw0wu0eqptykeqhr4d"),
-						profilestesting.SingleSignatureProtoFromHex("909e38994b1583d3f14384c2e9a03c90064e8fd8e19b780bb0ba303dfe671a27287da04d0ce096ce9a140bd070ee36818f5519eb2070a16971efd8143855524b"),
+						profilestesting.SingleSignatureFromHex("909e38994b1583d3f14384c2e9a03c90064e8fd8e19b780bb0ba303dfe671a27287da04d0ce096ce9a140bd070ee36818f5519eb2070a16971efd8143855524b"),
 						"74657874",
 					),
 					types.NewChainConfig("cosmos"),
@@ -338,7 +337,7 @@ func (suite *KeeperTestSuite) TestQueryServer_ChainLinks() {
 					types.NewBech32Address("cosmos19s242dxhxgzlsdmfjjg38jgfwhxca7569g84sw", "cosmos"),
 					types.NewProof(
 						profilestesting.PubKeyFromBech32("cosmospub1addwnpepqvryxhhqhw52c4ny5twtfzf3fsrjqhx0x5cuya0fylw0wu0eqptykeqhr4d"),
-						profilestesting.SingleSignatureProtoFromHex("909e38994b1583d3f14384c2e9a03c90064e8fd8e19b780bb0ba303dfe671a27287da04d0ce096ce9a140bd070ee36818f5519eb2070a16971efd8143855524b"),
+						profilestesting.SingleSignatureFromHex("909e38994b1583d3f14384c2e9a03c90064e8fd8e19b780bb0ba303dfe671a27287da04d0ce096ce9a140bd070ee36818f5519eb2070a16971efd8143855524b"),
 						"74657874",
 					),
 					types.NewChainConfig("likecoin"),
@@ -362,7 +361,7 @@ func (suite *KeeperTestSuite) TestQueryServer_ChainLinks() {
 					types.NewBech32Address("cosmos19s242dxhxgzlsdmfjjg38jgfwhxca7569g84sw", "cosmos"),
 					types.NewProof(
 						profilestesting.PubKeyFromBech32("cosmospub1addwnpepqvryxhhqhw52c4ny5twtfzf3fsrjqhx0x5cuya0fylw0wu0eqptykeqhr4d"),
-						profilestesting.SingleSignatureProtoFromHex("909e38994b1583d3f14384c2e9a03c90064e8fd8e19b780bb0ba303dfe671a27287da04d0ce096ce9a140bd070ee36818f5519eb2070a16971efd8143855524b"),
+						profilestesting.SingleSignatureFromHex("909e38994b1583d3f14384c2e9a03c90064e8fd8e19b780bb0ba303dfe671a27287da04d0ce096ce9a140bd070ee36818f5519eb2070a16971efd8143855524b"),
 						"74657874",
 					),
 					types.NewChainConfig("cosmos"),
@@ -373,7 +372,7 @@ func (suite *KeeperTestSuite) TestQueryServer_ChainLinks() {
 					types.NewBech32Address("cosmos1cjf97gpzwmaf30pzvaargfgr884mpp5ak8f7ns", "cosmos"),
 					types.NewProof(
 						profilestesting.PubKeyFromBech32("cosmospub1addwnpepqvryxhhqhw52c4ny5twtfzf3fsrjqhx0x5cuya0fylw0wu0eqptykeqhr4d"),
-						profilestesting.SingleSignatureProtoFromHex("909e38994b1583d3f14384c2e9a03c90064e8fd8e19b780bb0ba303dfe671a27287da04d0ce096ce9a140bd070ee36818f5519eb2070a16971efd8143855524b"),
+						profilestesting.SingleSignatureFromHex("909e38994b1583d3f14384c2e9a03c90064e8fd8e19b780bb0ba303dfe671a27287da04d0ce096ce9a140bd070ee36818f5519eb2070a16971efd8143855524b"),
 						"74657874",
 					),
 					types.NewChainConfig("cosmos"),
@@ -390,7 +389,7 @@ func (suite *KeeperTestSuite) TestQueryServer_ChainLinks() {
 					types.NewBech32Address("cosmos1cjf97gpzwmaf30pzvaargfgr884mpp5ak8f7ns", "cosmos"),
 					types.NewProof(
 						profilestesting.PubKeyFromBech32("cosmospub1addwnpepqvryxhhqhw52c4ny5twtfzf3fsrjqhx0x5cuya0fylw0wu0eqptykeqhr4d"),
-						profilestesting.SingleSignatureProtoFromHex("909e38994b1583d3f14384c2e9a03c90064e8fd8e19b780bb0ba303dfe671a27287da04d0ce096ce9a140bd070ee36818f5519eb2070a16971efd8143855524b"),
+						profilestesting.SingleSignatureFromHex("909e38994b1583d3f14384c2e9a03c90064e8fd8e19b780bb0ba303dfe671a27287da04d0ce096ce9a140bd070ee36818f5519eb2070a16971efd8143855524b"),
 						"74657874",
 					),
 					types.NewChainConfig("cosmos"),
@@ -406,7 +405,7 @@ func (suite *KeeperTestSuite) TestQueryServer_ChainLinks() {
 					types.NewBech32Address("cosmos19s242dxhxgzlsdmfjjg38jgfwhxca7569g84sw", "cosmos"),
 					types.NewProof(
 						profilestesting.PubKeyFromBech32("cosmospub1addwnpepqvryxhhqhw52c4ny5twtfzf3fsrjqhx0x5cuya0fylw0wu0eqptykeqhr4d"),
-						profilestesting.SingleSignatureProtoFromHex("909e38994b1583d3f14384c2e9a03c90064e8fd8e19b780bb0ba303dfe671a27287da04d0ce096ce9a140bd070ee36818f5519eb2070a16971efd8143855524b"),
+						profilestesting.SingleSignatureFromHex("909e38994b1583d3f14384c2e9a03c90064e8fd8e19b780bb0ba303dfe671a27287da04d0ce096ce9a140bd070ee36818f5519eb2070a16971efd8143855524b"),
 						"74657874",
 					),
 					types.NewChainConfig("cosmos"),
@@ -430,7 +429,7 @@ func (suite *KeeperTestSuite) TestQueryServer_ChainLinks() {
 					types.NewBech32Address("cosmos19s242dxhxgzlsdmfjjg38jgfwhxca7569g84sw", "cosmos"),
 					types.NewProof(
 						profilestesting.PubKeyFromBech32("cosmospub1addwnpepqvryxhhqhw52c4ny5twtfzf3fsrjqhx0x5cuya0fylw0wu0eqptykeqhr4d"),
-						profilestesting.SingleSignatureProtoFromHex("909e38994b1583d3f14384c2e9a03c90064e8fd8e19b780bb0ba303dfe671a27287da04d0ce096ce9a140bd070ee36818f5519eb2070a16971efd8143855524b"),
+						profilestesting.SingleSignatureFromHex("909e38994b1583d3f14384c2e9a03c90064e8fd8e19b780bb0ba303dfe671a27287da04d0ce096ce9a140bd070ee36818f5519eb2070a16971efd8143855524b"),
 						"74657874",
 					),
 					types.NewChainConfig("cosmos"),
@@ -448,7 +447,7 @@ func (suite *KeeperTestSuite) TestQueryServer_ChainLinks() {
 					types.NewBech32Address("cosmos1cjf97gpzwmaf30pzvaargfgr884mpp5ak8f7ns", "cosmos"),
 					types.NewProof(
 						profilestesting.PubKeyFromBech32("cosmospub1addwnpepqvryxhhqhw52c4ny5twtfzf3fsrjqhx0x5cuya0fylw0wu0eqptykeqhr4d"),
-						profilestesting.SingleSignatureProtoFromHex("909e38994b1583d3f14384c2e9a03c90064e8fd8e19b780bb0ba303dfe671a27287da04d0ce096ce9a140bd070ee36818f5519eb2070a16971efd8143855524b"),
+						profilestesting.SingleSignatureFromHex("909e38994b1583d3f14384c2e9a03c90064e8fd8e19b780bb0ba303dfe671a27287da04d0ce096ce9a140bd070ee36818f5519eb2070a16971efd8143855524b"),
 						"74657874",
 					),
 					types.NewChainConfig("cosmos"),
@@ -464,7 +463,7 @@ func (suite *KeeperTestSuite) TestQueryServer_ChainLinks() {
 					types.NewBech32Address("cosmos19s242dxhxgzlsdmfjjg38jgfwhxca7569g84sw", "cosmos"),
 					types.NewProof(
 						profilestesting.PubKeyFromBech32("cosmospub1addwnpepqvryxhhqhw52c4ny5twtfzf3fsrjqhx0x5cuya0fylw0wu0eqptykeqhr4d"),
-						profilestesting.SingleSignatureProtoFromHex("909e38994b1583d3f14384c2e9a03c90064e8fd8e19b780bb0ba303dfe671a27287da04d0ce096ce9a140bd070ee36818f5519eb2070a16971efd8143855524b"),
+						profilestesting.SingleSignatureFromHex("909e38994b1583d3f14384c2e9a03c90064e8fd8e19b780bb0ba303dfe671a27287da04d0ce096ce9a140bd070ee36818f5519eb2070a16971efd8143855524b"),
 						"74657874",
 					),
 					types.NewChainConfig("cosmos"),
@@ -487,7 +486,7 @@ func (suite *KeeperTestSuite) TestQueryServer_ChainLinks() {
 					types.NewBech32Address("cosmos19s242dxhxgzlsdmfjjg38jgfwhxca7569g84sw", "cosmos"),
 					types.NewProof(
 						profilestesting.PubKeyFromBech32("cosmospub1addwnpepqvryxhhqhw52c4ny5twtfzf3fsrjqhx0x5cuya0fylw0wu0eqptykeqhr4d"),
-						profilestesting.SingleSignatureProtoFromHex("909e38994b1583d3f14384c2e9a03c90064e8fd8e19b780bb0ba303dfe671a27287da04d0ce096ce9a140bd070ee36818f5519eb2070a16971efd8143855524b"),
+						profilestesting.SingleSignatureFromHex("909e38994b1583d3f14384c2e9a03c90064e8fd8e19b780bb0ba303dfe671a27287da04d0ce096ce9a140bd070ee36818f5519eb2070a16971efd8143855524b"),
 						"74657874",
 					),
 					types.NewChainConfig("cosmos"),
diff --git a/x/profiles/keeper/invariants_test.go b/x/profiles/keeper/invariants_test.go
index b7bfe389..392a509d 100644
--- a/x/profiles/keeper/invariants_test.go
+++ b/x/profiles/keeper/invariants_test.go
@@ -83,7 +83,7 @@ func (suite *KeeperTestSuite) TestInvariants() {
 				link := types.NewChainLink(
 					"user",
 					types.NewBech32Address("value", "prefix"),
-					types.NewProof(key, profilestesting.SingleSignatureProtoFromHex("1234"), "value"),
+					types.NewProof(key, profilestesting.SingleSignatureFromHex("1234"), "value"),
 					types.NewChainConfig("chain_name"),
 					time.Now(),
 				)
diff --git a/x/profiles/keeper/keeper_chain_links_test.go b/x/profiles/keeper/keeper_chain_links_test.go
index 49aeb8f6..13188d3e 100644
--- a/x/profiles/keeper/keeper_chain_links_test.go
+++ b/x/profiles/keeper/keeper_chain_links_test.go
@@ -31,7 +31,7 @@ func (suite *KeeperTestSuite) TestKeeper_SaveChainLink() {
 				Address: profilestesting.NewAny(ext.privKey),
 				Proof: types.NewProof(
 					ext.GetPubKey(),
-					profilestesting.SingleSignatureProtoFromHex(hex.EncodeToString(ext.Sign([]byte("")))),
+					profilestesting.SingleSignatureFromHex(hex.EncodeToString(ext.Sign([]byte("")))),
 					hex.EncodeToString([]byte("")),
 				),
 				ChainConfig:  types.NewChainConfig("cosmos"),
@@ -46,7 +46,7 @@ func (suite *KeeperTestSuite) TestKeeper_SaveChainLink() {
 				types.NewBech32Address("", "cosmos"),
 				types.NewProof(
 					ext.GetPubKey(),
-					profilestesting.SingleSignatureProtoFromHex(hex.EncodeToString(ext.Sign([]byte("cosmos19xz3mrvzvp9ymgmudhpukucg6668l5haakh04x")))),
+					profilestesting.SingleSignatureFromHex(hex.EncodeToString(ext.Sign([]byte("cosmos19xz3mrvzvp9ymgmudhpukucg6668l5haakh04x")))),
 					hex.EncodeToString([]byte("cosmos19xz3mrvzvp9ymgmudhpukucg6668l5haakh04x")),
 				),
 				types.NewChainConfig("cosmos"),
@@ -61,7 +61,7 @@ func (suite *KeeperTestSuite) TestKeeper_SaveChainLink() {
 				types.NewBech32Address(ext.GetAddress().String(), "cosmos"),
 				types.NewProof(
 					ext.GetPubKey(),
-					profilestesting.SingleSignatureProtoFromHex(hex.EncodeToString(ext.Sign([]byte("cosmos19xz3mrvzvp9ymgmudhpukucg6668l5haakh04x")))),
+					profilestesting.SingleSignatureFromHex(hex.EncodeToString(ext.Sign([]byte("cosmos19xz3mrvzvp9ymgmudhpukucg6668l5haakh04x")))),
 					"wrong",
 				),
 				types.NewChainConfig("cosmos"),
@@ -81,7 +81,7 @@ func (suite *KeeperTestSuite) TestKeeper_SaveChainLink() {
 					types.NewBech32Address(ext.GetAddress().String(), "cosmos"),
 					types.NewProof(
 						ext.GetPubKey(),
-						profilestesting.SingleSignatureProtoFromHex(hex.EncodeToString(ext.Sign([]byte("cosmos19xz3mrvzvp9ymgmudhpukucg6668l5haakh04x")))),
+						profilestesting.SingleSignatureFromHex(hex.EncodeToString(ext.Sign([]byte("cosmos19xz3mrvzvp9ymgmudhpukucg6668l5haakh04x")))),
 						hex.EncodeToString([]byte("cosmos19xz3mrvzvp9ymgmudhpukucg6668l5haakh04x")),
 					),
 					types.NewChainConfig("cosmos"),
@@ -94,7 +94,7 @@ func (suite *KeeperTestSuite) TestKeeper_SaveChainLink() {
 				types.NewBech32Address(ext.GetAddress().String(), "cosmos"),
 				types.NewProof(
 					ext.GetPubKey(),
-					profilestesting.SingleSignatureProtoFromHex(hex.EncodeToString(ext.Sign([]byte("cosmos19xz3mrvzvp9ymgmudhpukucg6668l5haakh04x")))),
+					profilestesting.SingleSignatureFromHex(hex.EncodeToString(ext.Sign([]byte("cosmos19xz3mrvzvp9ymgmudhpukucg6668l5haakh04x")))),
 					hex.EncodeToString([]byte("cosmos19xz3mrvzvp9ymgmudhpukucg6668l5haakh04x")),
 				),
 				types.NewChainConfig("cosmos"),
@@ -109,7 +109,7 @@ func (suite *KeeperTestSuite) TestKeeper_SaveChainLink() {
 					types.NewBech32Address(ext.GetAddress().String(), "cosmos"),
 					types.NewProof(
 						ext.GetPubKey(),
-						profilestesting.SingleSignatureProtoFromHex(hex.EncodeToString(ext.Sign([]byte("cosmos19xz3mrvzvp9ymgmudhpukucg6668l5haakh04x")))),
+						profilestesting.SingleSignatureFromHex(hex.EncodeToString(ext.Sign([]byte("cosmos19xz3mrvzvp9ymgmudhpukucg6668l5haakh04x")))),
 						hex.EncodeToString([]byte("cosmos19xz3mrvzvp9ymgmudhpukucg6668l5haakh04x")),
 					),
 					types.NewChainConfig("cosmos"),
@@ -124,7 +124,7 @@ func (suite *KeeperTestSuite) TestKeeper_SaveChainLink() {
 				types.NewBech32Address(ext.GetAddress().String(), "cosmos"),
 				types.NewProof(
 					ext.GetPubKey(),
-					profilestesting.SingleSignatureProtoFromHex(hex.EncodeToString(ext.Sign([]byte("cosmos19xz3mrvzvp9ymgmudhpukucg6668l5haakh04x")))),
+					profilestesting.SingleSignatureFromHex(hex.EncodeToString(ext.Sign([]byte("cosmos19xz3mrvzvp9ymgmudhpukucg6668l5haakh04x")))),
 					hex.EncodeToString([]byte("cosmos19xz3mrvzvp9ymgmudhpukucg6668l5haakh04x")),
 				),
 				types.NewChainConfig("cosmos"),
@@ -139,7 +139,7 @@ func (suite *KeeperTestSuite) TestKeeper_SaveChainLink() {
 				types.NewBech32Address(ext.GetAddress().String(), "cosmos"),
 				types.NewProof(
 					ext.GetPubKey(),
-					profilestesting.SingleSignatureProtoFromHex(hex.EncodeToString(ext.Sign([]byte("cosmos19xz3mrvzvp9ymgmudhpukucg6668l5haakh04x")))),
+					profilestesting.SingleSignatureFromHex(hex.EncodeToString(ext.Sign([]byte("cosmos19xz3mrvzvp9ymgmudhpukucg6668l5haakh04x")))),
 					hex.EncodeToString([]byte("cosmos19xz3mrvzvp9ymgmudhpukucg6668l5haakh04x")),
 				),
 				types.NewChainConfig("cosmos"),
@@ -159,7 +159,7 @@ func (suite *KeeperTestSuite) TestKeeper_SaveChainLink() {
 				types.NewBech32Address(ext.GetAddress().String(), "cosmos"),
 				types.NewProof(
 					ext.GetPubKey(),
-					profilestesting.SingleSignatureProtoFromHex(hex.EncodeToString(ext.Sign([]byte("cosmos19xz3mrvzvp9ymgmudhpukucg6668l5haakh04x")))),
+					profilestesting.SingleSignatureFromHex(hex.EncodeToString(ext.Sign([]byte("cosmos19xz3mrvzvp9ymgmudhpukucg6668l5haakh04x")))),
 					hex.EncodeToString([]byte("cosmos19xz3mrvzvp9ymgmudhpukucg6668l5haakh04x")),
 				),
 				types.NewChainConfig("cosmos"),
@@ -174,7 +174,7 @@ func (suite *KeeperTestSuite) TestKeeper_SaveChainLink() {
 					types.NewBech32Address(ext.GetAddress().String(), "cosmos"),
 					types.NewProof(
 						ext.GetPubKey(),
-						profilestesting.SingleSignatureProtoFromHex(hex.EncodeToString(ext.Sign([]byte("cosmos19xz3mrvzvp9ymgmudhpukucg6668l5haakh04x")))),
+						profilestesting.SingleSignatureFromHex(hex.EncodeToString(ext.Sign([]byte("cosmos19xz3mrvzvp9ymgmudhpukucg6668l5haakh04x")))),
 						hex.EncodeToString([]byte("cosmos19xz3mrvzvp9ymgmudhpukucg6668l5haakh04x")),
 					),
 					types.NewChainConfig("cosmos"),
@@ -212,7 +212,7 @@ func (suite *KeeperTestSuite) TestKeeper_SaveChainLink() {
 				types.NewBech32Address(ext.GetAddress().String(), "cosmos"),
 				types.NewProof(
 					ext.GetPubKey(),
-					profilestesting.SingleSignatureProtoFromHex(hex.EncodeToString(ext.Sign([]byte("cosmos19xz3mrvzvp9ymgmudhpukucg6668l5haakh04x")))),
+					profilestesting.SingleSignatureFromHex(hex.EncodeToString(ext.Sign([]byte("cosmos19xz3mrvzvp9ymgmudhpukucg6668l5haakh04x")))),
 					hex.EncodeToString([]byte("cosmos19xz3mrvzvp9ymgmudhpukucg6668l5haakh04x")),
 				),
 				types.NewChainConfig("cosmos"),
@@ -227,7 +227,7 @@ func (suite *KeeperTestSuite) TestKeeper_SaveChainLink() {
 					types.NewBech32Address(ext.GetAddress().String(), "cosmos"),
 					types.NewProof(
 						ext.GetPubKey(),
-						profilestesting.SingleSignatureProtoFromHex(hex.EncodeToString(ext.Sign([]byte("cosmos19xz3mrvzvp9ymgmudhpukucg6668l5haakh04x")))),
+						profilestesting.SingleSignatureFromHex(hex.EncodeToString(ext.Sign([]byte("cosmos19xz3mrvzvp9ymgmudhpukucg6668l5haakh04x")))),
 						hex.EncodeToString([]byte("cosmos19xz3mrvzvp9ymgmudhpukucg6668l5haakh04x")),
 					),
 					types.NewChainConfig("cosmos"),
@@ -294,7 +294,7 @@ func (suite *KeeperTestSuite) TestKeeper_GetChainLink() {
 				link := types.NewChainLink(
 					"cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47",
 					types.NewBech32Address("cosmos1cjf97gpzwmaf30pzvaargfgr884mpp5ak8f7ns", "cosmos"),
-					types.NewProof(secp256k1.GenPrivKey().PubKey(), profilestesting.SingleSignatureProtoFromHex("1234"), "706c61696e5f74657874"),
+					types.NewProof(secp256k1.GenPrivKey().PubKey(), profilestesting.SingleSignatureFromHex("1234"), "706c61696e5f74657874"),
 					types.NewChainConfig("cosmos"),
 					time.Date(2020, 1, 2, 00, 00, 00, 000, time.UTC),
 				)
@@ -576,7 +576,7 @@ func (suite *KeeperTestSuite) TestKeeper_DeleteAllUserChainLinks() {
 				link := types.NewChainLink(
 					user,
 					types.NewBech32Address("cosmos10nsdxxdvy9qka3zv0lzw8z9cnu6kanld8jh773", "cosmos"),
-					types.NewProof(key, profilestesting.SingleSignatureProtoFromHex("1234"), "706c61696e74657874"),
+					types.NewProof(key, profilestesting.SingleSignatureFromHex("1234"), "706c61696e74657874"),
 					types.NewChainConfig("cosmos"),
 					time.Date(2021, 1, 1, 00, 00, 00, 000, time.UTC),
 				)
@@ -588,7 +588,7 @@ func (suite *KeeperTestSuite) TestKeeper_DeleteAllUserChainLinks() {
 				link = types.NewChainLink(
 					user,
 					types.NewBech32Address("cosmos1xcy3els9ua75kdm783c3qu0rfa2eplesldfevn", "cosmos"),
-					types.NewProof(key, profilestesting.SingleSignatureProtoFromHex("1234"), "706c61696e74657874"),
+					types.NewProof(key, profilestesting.SingleSignatureFromHex("1234"), "706c61696e74657874"),
 					types.NewChainConfig("cosmos"),
 					time.Date(2021, 1, 1, 00, 00, 00, 000, time.UTC),
 				)
diff --git a/x/profiles/keeper/msg_server_chain_link_test.go b/x/profiles/keeper/msg_server_chain_link_test.go
index 460de7dc..58cf61de 100644
--- a/x/profiles/keeper/msg_server_chain_link_test.go
+++ b/x/profiles/keeper/msg_server_chain_link_test.go
@@ -51,7 +51,7 @@ func (suite *KeeperTestSuite) TestMsgServer_LinkChainAccount() {
 			name: "invalid chain link returns error",
 			msg: types.NewMsgLinkChainAccount(
 				types.NewBech32Address(srcAddr, "cosmos"),
-				types.NewProof(srcPubKey, profilestesting.SingleSignatureProtoFromHex(srcSigHex), hex.EncodeToString([]byte(srcAddr))),
+				types.NewProof(srcPubKey, profilestesting.SingleSignatureFromHex(srcSigHex), hex.EncodeToString([]byte(srcAddr))),
 				types.NewChainConfig("cosmos"),
 				destAddr,
 			),
@@ -62,7 +62,7 @@ func (suite *KeeperTestSuite) TestMsgServer_LinkChainAccount() {
 			name: "invalid chain address packed value returns error",
 			msg: &types.MsgLinkChainAccount{
 				ChainAddress: profilestesting.NewAny(srcPriv),
-				Proof:        types.NewProof(srcPubKey, profilestesting.SingleSignatureProtoFromHex(srcSigHex), hex.EncodeToString([]byte(srcAddr))),
+				Proof:        types.NewProof(srcPubKey, profilestesting.SingleSignatureFromHex(srcSigHex), hex.EncodeToString([]byte(srcAddr))),
 				ChainConfig:  types.NewChainConfig("cosmos"),
 				Signer:       destAddr,
 			},
@@ -101,7 +101,7 @@ func (suite *KeeperTestSuite) TestMsgServer_LinkChainAccount() {
 			},
 			msg: types.NewMsgLinkChainAccount(
 				types.NewBech32Address(srcAddr, "cosmos"),
-				types.NewProof(srcPubKey, profilestesting.SingleSignatureProtoFromHex(srcSigHex), hex.EncodeToString([]byte(destAddr))),
+				types.NewProof(srcPubKey, profilestesting.SingleSignatureFromHex(srcSigHex), hex.EncodeToString([]byte(destAddr))),
 				types.NewChainConfig("cosmos"),
 				destAddr,
 			),
@@ -186,7 +186,7 @@ func (suite *KeeperTestSuite) TestMsgServer_UnlinkChainAccount() {
 					types.NewBech32Address("cosmos1cjf97gpzwmaf30pzvaargfgr884mpp5ak8f7ns", "cosmos"),
 					types.NewProof(
 						profilestesting.PubKeyFromBech32("cosmospub1addwnpepqvryxhhqhw52c4ny5twtfzf3fsrjqhx0x5cuya0fylw0wu0eqptykeqhr4d"),
-						profilestesting.SingleSignatureProtoFromHex("909e38994b1583d3f14384c2e9a03c90064e8fd8e19b780bb0ba303dfe671a27287da04d0ce096ce9a140bd070ee36818f5519eb2070a16971efd8143855524b"),
+						profilestesting.SingleSignatureFromHex("909e38994b1583d3f14384c2e9a03c90064e8fd8e19b780bb0ba303dfe671a27287da04d0ce096ce9a140bd070ee36818f5519eb2070a16971efd8143855524b"),
 						"74657874",
 					),
 					types.NewChainConfig("cosmos"),
@@ -282,7 +282,7 @@ func (suite *KeeperTestSuite) TestMsgServer_SetDefaultExternalAddress() {
 					types.NewBech32Address("cosmos1cjf97gpzwmaf30pzvaargfgr884mpp5ak8f7ns", "cosmos"),
 					types.NewProof(
 						profilestesting.PubKeyFromBech32("cosmospub1addwnpepqvryxhhqhw52c4ny5twtfzf3fsrjqhx0x5cuya0fylw0wu0eqptykeqhr4d"),
-						profilestesting.SingleSignatureProtoFromHex("909e38994b1583d3f14384c2e9a03c90064e8fd8e19b780bb0ba303dfe671a27287da04d0ce096ce9a140bd070ee36818f5519eb2070a16971efd8143855524b"),
+						profilestesting.SingleSignatureFromHex("909e38994b1583d3f14384c2e9a03c90064e8fd8e19b780bb0ba303dfe671a27287da04d0ce096ce9a140bd070ee36818f5519eb2070a16971efd8143855524b"),
 						"74657874",
 					),
 					types.NewChainConfig("cosmos"),
diff --git a/x/profiles/keeper/relay_chain_links_test.go b/x/profiles/keeper/relay_chain_links_test.go
index 4d327312..d2071e95 100644
--- a/x/profiles/keeper/relay_chain_links_test.go
+++ b/x/profiles/keeper/relay_chain_links_test.go
@@ -33,14 +33,14 @@ func (suite *KeeperTestSuite) TestOnRecvPacket() {
 					SourceAddress: nil,
 					SourceProof: types.NewProof(
 						suite.chainA.Account.GetPubKey(),
-						profilestesting.SingleSignatureProtoFromHex(srcSigHex),
+						profilestesting.SingleSignatureFromHex(srcSigHex),
 						hex.EncodeToString([]byte(destAddr)),
 					),
 					SourceChainConfig:  types.NewChainConfig("cosmos"),
 					DestinationAddress: destAddr,
 					DestinationProof: types.NewProof(
 						suite.chainB.Account.GetPubKey(),
-						profilestesting.SingleSignatureProtoFromHex(destSigHex),
+						profilestesting.SingleSignatureFromHex(destSigHex),
 						hex.EncodeToString([]byte(srcAddr)),
 					),
 				}
@@ -56,14 +56,14 @@ func (suite *KeeperTestSuite) TestOnRecvPacket() {
 					SourceAddress: invalidAny,
 					SourceProof: types.NewProof(
 						suite.chainA.Account.GetPubKey(),
-						profilestesting.SingleSignatureProtoFromHex(srcSigHex),
+						profilestesting.SingleSignatureFromHex(srcSigHex),
 						hex.EncodeToString([]byte(destAddr)),
 					),
 					SourceChainConfig:  types.NewChainConfig("cosmos"),
 					DestinationAddress: destAddr,
 					DestinationProof: types.NewProof(
 						suite.chainB.Account.GetPubKey(),
-						profilestesting.SingleSignatureProtoFromHex(destSigHex),
+						profilestesting.SingleSignatureFromHex(destSigHex),
 						hex.EncodeToString([]byte(srcAddr)),
 					),
 				}
@@ -77,14 +77,14 @@ func (suite *KeeperTestSuite) TestOnRecvPacket() {
 					types.NewBech32Address(srcAddr, "cosmos"),
 					types.NewProof(
 						suite.chainA.Account.GetPubKey(),
-						profilestesting.SingleSignatureProtoFromHex(srcSigHex),
+						profilestesting.SingleSignatureFromHex(srcSigHex),
 						hex.EncodeToString([]byte(destAddr)),
 					),
 					types.NewChainConfig("cosmos"),
 					"cosmos1asdjlansdjhasd",
 					types.NewProof(
 						suite.chainB.Account.GetPubKey(),
-						profilestesting.SingleSignatureProtoFromHex(destSigHex),
+						profilestesting.SingleSignatureFromHex(destSigHex),
 						hex.EncodeToString([]byte(srcAddr)),
 					),
 				)
@@ -98,14 +98,14 @@ func (suite *KeeperTestSuite) TestOnRecvPacket() {
 					types.NewBech32Address(srcAddr, "cosmos"),
 					types.NewProof(
 						suite.chainA.Account.GetPubKey(),
-						profilestesting.SingleSignatureProtoFromHex(srcSigHex),
+						profilestesting.SingleSignatureFromHex(srcSigHex),
 						hex.EncodeToString([]byte(destAddr)),
 					),
 					types.NewChainConfig("cosmos"),
 					destAddr,
 					types.NewProof(
 						suite.chainB.Account.GetPubKey(),
-						profilestesting.SingleSignatureProtoFromHex(destSigHex),
+						profilestesting.SingleSignatureFromHex(destSigHex),
 						hex.EncodeToString([]byte(srcAddr)),
 					),
 				)
@@ -119,14 +119,14 @@ func (suite *KeeperTestSuite) TestOnRecvPacket() {
 					types.NewBech32Address(srcAddr, "cosmos"),
 					types.NewProof(
 						suite.chainA.Account.GetPubKey(),
-						profilestesting.SingleSignatureProtoFromHex(srcSigHex),
+						profilestesting.SingleSignatureFromHex(srcSigHex),
 						hex.EncodeToString([]byte(destAddr)),
 					),
 					types.NewChainConfig("cosmos"),
 					destAddr,
 					types.NewProof(
 						suite.chainB.Account.GetPubKey(),
-						profilestesting.SingleSignatureProtoFromHex(destSigHex),
+						profilestesting.SingleSignatureFromHex(destSigHex),
 						hex.EncodeToString([]byte(srcAddr)),
 					),
 				)
@@ -160,7 +160,7 @@ func (suite *KeeperTestSuite) TestOnRecvPacket() {
 					types.NewBech32Address(srcAddr, "cosmos"),
 					types.NewProof(
 						suite.chainA.Account.GetPubKey(),
-						profilestesting.SingleSignatureProtoFromHex(srcSigHex),
+						profilestesting.SingleSignatureFromHex(srcSigHex),
 						"696e76616c6964",
 					),
 					types.NewChainConfig(
@@ -169,7 +169,7 @@ func (suite *KeeperTestSuite) TestOnRecvPacket() {
 					destAddr,
 					types.NewProof(
 						suite.chainB.Account.GetPubKey(),
-						profilestesting.SingleSignatureProtoFromHex(destSigHex),
+						profilestesting.SingleSignatureFromHex(destSigHex),
 						hex.EncodeToString([]byte(srcAddr)),
 					),
 				)
@@ -203,7 +203,7 @@ func (suite *KeeperTestSuite) TestOnRecvPacket() {
 					types.NewBech32Address(srcAddr, "cosmos"),
 					types.NewProof(
 						suite.chainA.Account.GetPubKey(),
-						profilestesting.SingleSignatureProtoFromHex(srcSigHex),
+						profilestesting.SingleSignatureFromHex(srcSigHex),
 						hex.EncodeToString([]byte(destAddr)),
 					),
 					types.NewChainConfig(
@@ -212,7 +212,7 @@ func (suite *KeeperTestSuite) TestOnRecvPacket() {
 					destAddr,
 					types.NewProof(
 						suite.chainB.Account.GetPubKey(),
-						profilestesting.SingleSignatureProtoFromHex(destSigHex),
+						profilestesting.SingleSignatureFromHex(destSigHex),
 						"696e76616c6964",
 					),
 				)
@@ -246,7 +246,7 @@ func (suite *KeeperTestSuite) TestOnRecvPacket() {
 					types.NewBech32Address(srcAddr, "cosmos"),
 					types.NewProof(
 						suite.chainA.Account.GetPubKey(),
-						profilestesting.SingleSignatureProtoFromHex(srcSigHex),
+						profilestesting.SingleSignatureFromHex(srcSigHex),
 						hex.EncodeToString([]byte(destAddr)),
 					),
 					types.NewChainConfig(
@@ -255,7 +255,7 @@ func (suite *KeeperTestSuite) TestOnRecvPacket() {
 					destAddr,
 					types.NewProof(
 						suite.chainB.Account.GetPubKey(),
-						profilestesting.SingleSignatureProtoFromHex(destSigHex),
+						profilestesting.SingleSignatureFromHex(destSigHex),
 						hex.EncodeToString([]byte(srcAddr)),
 					),
 				)
@@ -286,7 +286,7 @@ func (suite *KeeperTestSuite) TestOnRecvPacket() {
 				link := types.NewChainLink(
 					addr.String(),
 					types.NewBech32Address(srcAddr, "cosmos"),
-					types.NewProof(suite.chainA.Account.GetPubKey(), profilestesting.SingleSignatureProtoFromHex("1234"), hex.EncodeToString([]byte(srcAddr))),
+					types.NewProof(suite.chainA.Account.GetPubKey(), profilestesting.SingleSignatureFromHex("1234"), hex.EncodeToString([]byte(srcAddr))),
 					types.NewChainConfig("cosmos"),
 					time.Date(2021, 1, 1, 00, 00, 00, 000, time.UTC),
 				)
@@ -301,7 +301,7 @@ func (suite *KeeperTestSuite) TestOnRecvPacket() {
 					types.NewBech32Address(srcAddr, "cosmos"),
 					types.NewProof(
 						suite.chainA.Account.GetPubKey(),
-						profilestesting.SingleSignatureProtoFromHex(srcSigHex),
+						profilestesting.SingleSignatureFromHex(srcSigHex),
 						hex.EncodeToString([]byte(destAddr)),
 					),
 					types.NewChainConfig(
@@ -310,7 +310,7 @@ func (suite *KeeperTestSuite) TestOnRecvPacket() {
 					destAddr,
 					types.NewProof(
 						suite.chainB.Account.GetPubKey(),
-						profilestesting.SingleSignatureProtoFromHex(destSigHex),
+						profilestesting.SingleSignatureFromHex(destSigHex),
 						hex.EncodeToString([]byte(srcAddr)),
 					),
 				)
diff --git a/x/profiles/legacy/v6/store_test.go b/x/profiles/legacy/v6/store_test.go
index ff0bf3d0..59d26c9b 100644
--- a/x/profiles/legacy/v6/store_test.go
+++ b/x/profiles/legacy/v6/store_test.go
@@ -179,7 +179,7 @@ func TestMigrateStore(t *testing.T) {
 			},
 		},
 		{
-			name: "chain links are migrated properly",
+			name: "chain links are migrated properly - single signature",
 			store: func(ctx sdk.Context) {
 				kvStore := ctx.KVStore(keys[types.StoreKey])
 
@@ -192,7 +192,7 @@ func TestMigrateStore(t *testing.T) {
 					v5types.NewProof(
 						pubKey,
 						&v5types.SingleSignatureData{
-							Mode:      signing.SignMode_SIGN_MODE_DIRECT,
+							Mode:      signing.SignMode_SIGN_MODE_TEXTUAL,
 							Signature: sig,
 						},
 						"plain_text",
@@ -222,7 +222,93 @@ func TestMigrateStore(t *testing.T) {
 				require.Equal(t, types.NewChainLink(
 					"cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47",
 					types.NewBech32Address("cosmos1ftkjv8njvkekk00ehwdfl5sst8zgdpenjfm4hs", "cosmos"),
-					types.NewProof(pubKey, profilestesting.SingleSignatureProtoFromHex("1234"), "plain_text"),
+					types.NewProof(pubKey, profilestesting.SingleSignatureFromHex("1234"), "plain_text"),
+					types.NewChainConfig("cosmos"),
+					time.Date(2020, 1, 2, 00, 00, 00, 000, time.UTC),
+				), stored)
+			},
+		},
+		{
+			name: "chain links are migrated properly - multi signature",
+			store: func(ctx sdk.Context) {
+				kvStore := ctx.KVStore(keys[types.StoreKey])
+
+				var signatureJSON = `{
+				  "@type": "/desmos.profiles.v2.MultiSignatureData",
+				  "bit_array": {
+					"extra_bits_stored": 3,
+					"elems": "wA=="
+				  },
+				  "signatures": [
+					{
+					  "@type": "/desmos.profiles.v2.SingleSignatureData",
+					  "mode": "SIGN_MODE_LEGACY_AMINO_JSON",
+					  "signature": "J/xFZ4GKKYA+wT9ClATHExyBiswZVPUS89caM3nn7HQdJd6LFC9hFRZSsG73iq7/1YcHAj5ujfvpjJkBhQFkdg=="
+					},
+					{
+					  "@type": "/desmos.profiles.v2.SingleSignatureData",
+					  "mode": "SIGN_MODE_LEGACY_AMINO_JSON",
+					  "signature": "k5TIZjDnr7lhiZrdj8GiEdFLjMOHAsU8qnAYUVV/NYMsEeEVENpNZ2V4oZs0KGUxdUdUmytL14zfgJ2vpVBB9w=="
+					}
+				  ]
+				}`
+				var signatureData v5types.SignatureData
+				err := cdc.UnmarshalInterfaceJSON([]byte(signatureJSON), &signatureData)
+				require.NoError(t, err)
+
+				chainLink := v5types.NewChainLink(
+					"cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47",
+					v5types.NewBech32Address("cosmos1ftkjv8njvkekk00ehwdfl5sst8zgdpenjfm4hs", "cosmos"),
+					v5types.NewProof(pubKey, signatureData, "plain_text"),
+					v5types.NewChainConfig("cosmos"),
+					time.Date(2020, 1, 2, 00, 00, 00, 000, time.UTC),
+				)
+				kvStore.Set(
+					types.ChainLinksStoreKey(
+						"cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47",
+						"cosmos",
+						"cosmos1ftkjv8njvkekk00ehwdfl5sst8zgdpenjfm4hs",
+					),
+					cdc.MustMarshal(&chainLink),
+				)
+			},
+			shouldErr: false,
+			check: func(ctx sdk.Context) {
+				kvStore := ctx.KVStore(keys[types.StoreKey])
+
+				var signatureJSON = `{
+				  "@type": "/desmos.profiles.v3.CosmosMultiSignature",
+				  "bit_array": {
+					"extra_bits_stored": 3,
+					"elems": "wA=="
+				  },
+				  "signatures": [
+					{
+					  "@type": "/desmos.profiles.v3.SingleSignature",
+					  "value_type": "SIGNATURE_VALUE_TYPE_COSMOS_AMINO",
+					  "signature": "J/xFZ4GKKYA+wT9ClATHExyBiswZVPUS89caM3nn7HQdJd6LFC9hFRZSsG73iq7/1YcHAj5ujfvpjJkBhQFkdg=="
+					},
+					{
+					  "@type": "/desmos.profiles.v3.SingleSignature",
+					  "value_type": "SIGNATURE_VALUE_TYPE_COSMOS_AMINO",
+					  "signature": "k5TIZjDnr7lhiZrdj8GiEdFLjMOHAsU8qnAYUVV/NYMsEeEVENpNZ2V4oZs0KGUxdUdUmytL14zfgJ2vpVBB9w=="
+					}
+				  ]
+				}`
+				var signature types.Signature
+				err := cdc.UnmarshalInterfaceJSON([]byte(signatureJSON), &signature)
+				require.NoError(t, err)
+
+				var stored types.ChainLink
+				cdc.MustUnmarshal(kvStore.Get(types.ChainLinksStoreKey(
+					"cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47",
+					"cosmos",
+					"cosmos1ftkjv8njvkekk00ehwdfl5sst8zgdpenjfm4hs",
+				)), &stored)
+				require.Equal(t, types.NewChainLink(
+					"cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47",
+					types.NewBech32Address("cosmos1ftkjv8njvkekk00ehwdfl5sst8zgdpenjfm4hs", "cosmos"),
+					types.NewProof(pubKey, signature, "plain_text"),
 					types.NewChainConfig("cosmos"),
 					time.Date(2020, 1, 2, 00, 00, 00, 000, time.UTC),
 				), stored)
diff --git a/x/profiles/types/genesis_test.go b/x/profiles/types/genesis_test.go
index 80617cbe..5a957499 100644
--- a/x/profiles/types/genesis_test.go
+++ b/x/profiles/types/genesis_test.go
@@ -71,7 +71,7 @@ func TestValidateGenesis(t *testing.T) {
 						types.NewBech32Address("cosmos1xmquc944hzu6n6qtljcexkuhhz76mucxtgm5x0", "cosmos"),
 						types.NewProof(
 							profilestesting.PubKeyFromBech32("cosmospub1addwnpepq0j8zw4t6tg3v8gh7d2d799gjhue7ewwmpg2hwr77f9kuuyzgqtrw5r6wec"),
-							&types.SingleSignatureData{},
+							&types.SingleSignature{},
 							"addr",
 						),
 						types.NewChainConfig(""),
@@ -155,7 +155,7 @@ func TestValidateGenesis(t *testing.T) {
 						types.NewBech32Address("cosmos1xmquc944hzu6n6qtljcexkuhhz76mucxtgm5x0", "cosmos"),
 						types.NewProof(
 							profilestesting.PubKeyFromBech32("cosmospub1addwnpepq0j8zw4t6tg3v8gh7d2d799gjhue7ewwmpg2hwr77f9kuuyzgqtrw5r6wec"),
-							profilestesting.SingleSignatureProtoFromHex("4e188d9c17150037d5199bbdb91ae1eb2a78a15aca04cb35530cccb81494b36e"),
+							profilestesting.SingleSignatureFromHex("4e188d9c17150037d5199bbdb91ae1eb2a78a15aca04cb35530cccb81494b36e"),
 							"636f736d6f7331786d717563393434687a75366e3671746c6a6365786b7568687a37366d75637874676d357830",
 						),
 						types.NewChainConfig("cosmos"),
@@ -166,7 +166,7 @@ func TestValidateGenesis(t *testing.T) {
 						types.NewBech32Address("cosmos1xmquc944hzu6n6qtljcexkuhhz76mucxtgm5x0", "cosmos"),
 						types.NewProof(
 							profilestesting.PubKeyFromBech32("cosmospub1addwnpepq0j8zw4t6tg3v8gh7d2d799gjhue7ewwmpg2hwr77f9kuuyzgqtrw5r6wec"),
-							profilestesting.SingleSignatureProtoFromHex("4e188d9c17150037d5199bbdb91ae1eb2a78a15aca04cb35530cccb81494b36e"),
+							profilestesting.SingleSignatureFromHex("4e188d9c17150037d5199bbdb91ae1eb2a78a15aca04cb35530cccb81494b36e"),
 							"636f736d6f7331786d717563393434687a75366e3671746c6a6365786b7568687a37366d75637874676d357830",
 						),
 						types.NewChainConfig("cosmos"),
diff --git a/x/profiles/types/models_chain_links_test.go b/x/profiles/types/models_chain_links_test.go
index 20018848..aef2a58f 100644
--- a/x/profiles/types/models_chain_links_test.go
+++ b/x/profiles/types/models_chain_links_test.go
@@ -93,6 +93,50 @@ func TestChainConfig_Validate(t *testing.T) {
 
 // --------------------------------------------------------------------------------------------------------------------
 
+func TestProof_GetSignature(t *testing.T) {
+	pubKeyAny, err := codectypes.NewAnyWithValue(secp256k1.GenPrivKey().PubKey())
+	require.NoError(t, err)
+
+	testCases := []struct {
+		name         string
+		proof        types.Proof
+		shouldErr    bool
+		expSignature types.Signature
+	}{
+		{
+			name: "invalid signature returns error",
+			proof: types.Proof{
+				PubKey:    pubKeyAny,
+				Signature: pubKeyAny,
+				PlainText: "74657874",
+			},
+			shouldErr: true,
+		},
+		{
+			name: "valid signature is returned properly",
+			proof: types.NewProof(
+				secp256k1.GenPrivKey().PubKey(),
+				profilestesting.SingleSignatureFromHex("74657874"),
+				"74657874",
+			),
+			expSignature: profilestesting.SingleSignatureFromHex("74657874"),
+		},
+	}
+
+	for _, tc := range testCases {
+		tc := tc
+		t.Run(tc.name, func(t *testing.T) {
+			signature, err := tc.proof.GetSignature()
+			if tc.shouldErr {
+				require.Error(t, err)
+			} else {
+				require.NoError(t, err)
+				require.Equal(t, tc.expSignature, signature)
+			}
+		})
+	}
+}
+
 func TestProof_Validate(t *testing.T) {
 	pubKeyAny, err := codectypes.NewAnyWithValue(secp256k1.GenPrivKey().PubKey())
 	require.NoError(t, err)
@@ -114,19 +158,19 @@ func TestProof_Validate(t *testing.T) {
 		},
 		{
 			name:      "empty plain text returns error",
-			proof:     types.NewProof(secp256k1.GenPrivKey().PubKey(), profilestesting.SingleSignatureProtoFromHex("74657874"), ""),
+			proof:     types.NewProof(secp256k1.GenPrivKey().PubKey(), profilestesting.SingleSignatureFromHex("74657874"), ""),
 			shouldErr: true,
 		},
 		{
 			name:      "invalid plain text format returns error",
-			proof:     types.NewProof(secp256k1.GenPrivKey().PubKey(), profilestesting.SingleSignatureProtoFromHex("74657874"), "="),
+			proof:     types.NewProof(secp256k1.GenPrivKey().PubKey(), profilestesting.SingleSignatureFromHex("74657874"), "="),
 			shouldErr: true,
 		},
 		{
 			name: "valid proof returns no error",
 			proof: types.NewProof(
 				secp256k1.GenPrivKey().PubKey(),
-				profilestesting.SingleSignatureProtoFromHex("74657874"),
+				profilestesting.SingleSignatureFromHex("74657874"),
 				"74657874",
 			),
 			shouldErr: false,
@@ -160,9 +204,9 @@ func generateMultiSigKeys(n int) ([]cryptotypes.PrivKey, cryptotypes.PubKey) {
 	return privKeys, kmultisig.NewLegacyAminoPubKey(n, pubKeys)
 }
 
-// generateMultiSigSignatureData uses the given private keys to sign the given message using the multi sig algorithm,
+// generateCosmosMultiSigSignature uses the given private keys to sign the given message using the multi sig algorithm,
 // and returns the obtained MultiSignatureData instance.
-func generateMultiSigSignatureData(t *testing.T, privKeys []cryptotypes.PrivKey, msg []byte) types.SignatureData {
+func generateCosmosMultiSigSignature(t *testing.T, privKeys []cryptotypes.PrivKey, msg []byte) *types.CosmosMultiSignature {
 	cosmosMultisig := multisig.NewMultisig(len(privKeys))
 	pubKeys := make([]cryptotypes.PubKey, len(privKeys))
 	for i, privKey := range privKeys {
@@ -175,78 +219,37 @@ func generateMultiSigSignatureData(t *testing.T, privKeys []cryptotypes.PrivKey,
 		require.NoError(t, err)
 
 		// Build the signature data for the single signature and add it to the multi signature data
-		sigData := &signing.SingleSignatureData{Signature: sig}
+		sigData := &signing.SingleSignatureData{SignMode: signing.SignMode_SIGN_MODE_TEXTUAL, Signature: sig}
 		err = multisig.AddSignatureFromPubKey(cosmosMultisig, sigData, privKeys[i].PubKey(), pubKeys)
 		require.NoError(t, err)
 	}
 
 	// Generate the signature data object
-	sigData, err := types.SignatureDataFromCosmosSignatureData(cosmosMultisig)
+	signature, err := types.CosmosSignatureDataToSignature(cosmosMultisig)
 	require.NoError(t, err)
-
-	return sigData
+	return signature.(*types.CosmosMultiSignature)
 }
 
 func TestProof_Verify(t *testing.T) {
-	// Bech32
-	bech32PrivKey := secp256k1.GenPrivKey()
-	bech32PubKey := bech32PrivKey.PubKey()
-	bech32Addr, err := sdk.Bech32ifyAddressBytes("cosmos", bech32PubKey.Address())
-	require.NoError(t, err)
-
-	bech32Owner := "cosmos10m20h8fy0qp2a8f46zzjpvg8pfl8flajgxsvmk"
-	bech32Sig, err := bech32PrivKey.Sign([]byte(bech32Owner))
-	require.NoError(t, err)
-	bech32SigData := &types.SingleSignatureData{
-		Mode:      signing.SignMode_SIGN_MODE_TEXTUAL,
-		Signature: bech32Sig,
-	}
-	anySigData, err := codectypes.NewAnyWithValue(bech32SigData)
-	require.NoError(t, err)
-
-	// Base58
-	base58PrivKeyBz, err := hex.DecodeString("bb98111da675930d32f79451fa8d05f188289699558c17148a5d9c82cdb31d1fe04fb0a0d9e689b436b59eff9676d7f2d788244cc4ccfc5768fe117efbd0f9d3")
-	require.NoError(t, err)
-	base58PrivKey := ed25519.PrivKey{Key: base58PrivKeyBz}
-	base58PubKey := base58PrivKey.PubKey()
-	base58Addr := base58.Encode(base58PubKey.Bytes())
-
-	base58Owner := "cosmos1u55ywhk6thmhnxs7yn8vh8v7eznckcqjevnadx"
-	base58Sig, err := base58PrivKey.Sign([]byte(base58Owner))
+	privKeyBz, err := hex.DecodeString("bb98111da675930d32f79451fa8d05f188289699558c17148a5d9c82cdb31d1fe04fb0a0d9e689b436b59eff9676d7f2d788244cc4ccfc5768fe117efbd0f9d3")
 	require.NoError(t, err)
-	base58SigData := &types.SingleSignatureData{
-		Mode:      signing.SignMode_SIGN_MODE_TEXTUAL,
-		Signature: base58Sig,
-	}
+	privKey := ed25519.PrivKey{Key: privKeyBz}
 
-	// Hex
-	hexPrivKeyBz, err := hex.DecodeString("2842d8f3701d16711b9ee320f32efe38e6b0891e243eaf6515250e7b006de53e")
+	pubKey := privKey.PubKey()
+	pubKeyAny, err := codectypes.NewAnyWithValue(pubKey)
 	require.NoError(t, err)
-	hexPrivKey := secp256k1.PrivKey{Key: hexPrivKeyBz}
-	hexPubKey := hexPrivKey.PubKey()
-	hexAddr := "0x941991947B6eC9F5537bcaC30C1295E8154Df4cC"
 
-	hexOwner := "cosmos1l0g43u695yvmwem09ncwgsxup6m8aklcyr38ph"
-	hexSig, err := hexPrivKey.Sign([]byte(hexOwner))
+	anotherPubKey := secp256k1.GenPrivKey().PubKey()
+	anotherPubKeyAny, err := codectypes.NewAnyWithValue(anotherPubKey)
 	require.NoError(t, err)
-	hexSigData := &types.SingleSignatureData{
-		Mode:      signing.SignMode_SIGN_MODE_DIRECT,
-		Signature: hexSig,
-	}
 
-	// Multisig
-	privKeys, multiSigPubKey := generateMultiSigKeys(3)
-	multisigAddr, err := sdk.Bech32ifyAddressBytes("cosmos", multiSigPubKey.Address())
+	sigBz, err := privKey.Sign([]byte("cosmos1u55ywhk6thmhnxs7yn8vh8v7eznckcqjevnadx"))
 	require.NoError(t, err)
-
-	multiSigOwner := "cosmos1vfvst0mr79nzzxsk65uuhfklmwrnsfadhtn977"
-	multiSigData := generateMultiSigSignatureData(t, privKeys, []byte(multiSigOwner))
-	validMultisigDataAny, err := codectypes.NewAnyWithValue(multiSigData)
+	signature := types.NewSingleSignature(types.SIGNATURE_VALUE_TYPE_RAW, sigBz)
+	sigAny, err := codectypes.NewAnyWithValue(signature)
 	require.NoError(t, err)
 
-	validaPubKeyAny, err := codectypes.NewAnyWithValue(bech32PubKey)
-	require.NoError(t, err)
-	invalidAny, err := codectypes.NewAnyWithValue(bech32PrivKey)
+	invalidAny, err := codectypes.NewAnyWithValue(&types.SingleSignature{})
 	require.NoError(t, err)
 
 	testCases := []struct {
@@ -257,111 +260,184 @@ func TestProof_Verify(t *testing.T) {
 		shouldErr   bool
 	}{
 		{
-			name:        "invalid public key value returns error",
-			proof:       types.Proof{PubKey: invalidAny, Signature: anySigData, PlainText: hex.EncodeToString([]byte(bech32Owner))},
-			owner:       bech32Owner,
-			addressData: types.NewBech32Address(bech32Addr, "cosmos"),
+			name:        "invalid value returns error",
+			proof:       types.Proof{PubKey: pubKeyAny, Signature: sigAny, PlainText: "value"},
+			owner:       "cosmos1u55ywhk6thmhnxs7yn8vh8v7eznckcqjevnadx",
+			addressData: types.NewBase58Address(base58.Encode(pubKey.Bytes())),
 			shouldErr:   true,
 		},
 		{
-			name:        "invalid signature value returns error",
-			proof:       types.Proof{PubKey: validaPubKeyAny, Signature: invalidAny, PlainText: hex.EncodeToString([]byte(bech32Owner))},
-			owner:       bech32Owner,
-			addressData: types.NewBech32Address(bech32Addr, "cosmos"),
+			name:        "incorrect signature type returns error",
+			proof:       types.Proof{PubKey: pubKeyAny, Signature: invalidAny, PlainText: "76616C7565"},
+			owner:       "cosmos1u55ywhk6thmhnxs7yn8vh8v7eznckcqjevnadx",
+			addressData: types.NewBase58Address(base58.Encode(pubKey.Bytes())),
 			shouldErr:   true,
 		},
 		{
-			name:        "wrong plain text returns error",
-			proof:       types.NewProof(bech32PubKey, bech32SigData, "wrong"),
-			owner:       bech32Owner,
-			addressData: types.NewBech32Address(bech32Addr, "cosmos"),
+			name:        "invalid signature returns error",
+			proof:       types.Proof{PubKey: invalidAny, Signature: sigAny, PlainText: "76616C7565"},
+			owner:       "cosmos1u55ywhk6thmhnxs7yn8vh8v7eznckcqjevnadx",
+			addressData: types.NewBase58Address(base58.Encode(pubKey.Bytes())),
 			shouldErr:   true,
 		},
 		{
-			name:        "wrong signature returns error",
-			proof:       types.NewProof(bech32PubKey, profilestesting.SingleSignatureProtoFromHex("74657874"), hex.EncodeToString([]byte(bech32Owner))),
-			owner:       bech32Owner,
-			addressData: types.NewBech32Address(bech32Addr, "cosmos"),
+			name: "wrong signature returns error",
+			proof: types.Proof{
+				PubKey:    anotherPubKeyAny,
+				Signature: sigAny,
+				PlainText: "636F736D6F73317535357977686B3674686D686E787337796E387668387637657A6E636B63716A65766E616478",
+			},
+			owner:       "cosmos1u55ywhk6thmhnxs7yn8vh8v7eznckcqjevnadx",
+			addressData: types.NewBase58Address(base58.Encode(pubKey.Bytes())),
 			shouldErr:   true,
 		},
 		{
-			name:        "wrong Bech32 address returns error",
-			proof:       types.NewProof(bech32PubKey, bech32SigData, hex.EncodeToString([]byte(bech32Owner))),
-			owner:       bech32Owner,
-			addressData: types.NewBech32Address("cosmos1xcy3els9ua75kdm783c3qu0rfa2eplesldfevn", "cosmos"),
+			name: "wrong signature returns error",
+			proof: types.Proof{
+				PubKey:    pubKeyAny,
+				Signature: sigAny,
+				PlainText: "636F736D6F73317535357977686B3674686D686E787337796E387668387637657A6E636B63716A65766E616478",
+			},
+			owner:       "cosmos1u55ywhk6thmhnxs7yn8vh8v7eznckcqjevnadx",
+			addressData: types.NewBase58Address(base58.Encode(anotherPubKey.Bytes())),
 			shouldErr:   true,
 		},
 		{
-			name:        "wrong Base58 address returns error",
-			proof:       types.NewProof(base58PubKey, base58SigData, hex.EncodeToString([]byte(base58Owner))),
-			owner:       base58Owner,
-			addressData: types.NewBase58Address("HWQ14mk82aRMAad2TdxFHbeqLeUGo5SiBxTXyZyTesJT"),
-			shouldErr:   true,
+			name: "valid data returns no error",
+			proof: types.Proof{
+				PubKey:    pubKeyAny,
+				Signature: sigAny,
+				PlainText: "636F736D6F73317535357977686B3674686D686E787337796E387668387637657A6E636B63716A65766E616478",
+			},
+			owner:       "cosmos1u55ywhk6thmhnxs7yn8vh8v7eznckcqjevnadx",
+			addressData: types.NewBase58Address(base58.Encode(pubKey.Bytes())),
+			shouldErr:   false,
 		},
+	}
+
+	for _, tc := range testCases {
+		tc := tc
+		t.Run(tc.name, func(t *testing.T) {
+			cdc, legacyAmino := app.MakeCodecs()
+			err := tc.proof.Verify(cdc, legacyAmino, tc.owner, tc.addressData)
+			if tc.shouldErr {
+				require.Error(t, err)
+			} else {
+				require.NoError(t, err)
+			}
+		})
+	}
+}
+
+// --------------------------------------------------------------------------------------------------------------------
+
+func TestValidateDirectTxValue(t *testing.T) {
+	cdc, _ := app.MakeCodecs()
+	testCases := []struct {
+		name         string
+		value        []byte
+		expectedMemo string
+		shouldErr    bool
+	}{
 		{
-			name:        "wrong Hex address returns error",
-			proof:       types.NewProof(hexPubKey, hexSigData, hex.EncodeToString([]byte(hexOwner))),
-			owner:       hexOwner,
-			addressData: types.NewHexAddress("0xcdAFfbFd8c131464fEE561e3d9b585141e403719", "0x"),
-			shouldErr:   true,
+			name:         "invalid message returns error",
+			value:        cdc.MustMarshal(&types.Bech32Address{Prefix: "cosmos"}),
+			expectedMemo: "memo",
+			shouldErr:    true,
 		},
 		{
-			name:        "invalid multi sig pubkey returns error",
-			proof:       types.Proof{PubKey: invalidAny, Signature: validMultisigDataAny, PlainText: hex.EncodeToString([]byte(multiSigOwner))},
-			owner:       multiSigOwner,
-			addressData: types.NewBech32Address("cosmos1xcy3els9ua75kdm783c3qu0rfa2eplesldfevn", "cosmos"),
-			shouldErr:   true,
+			name:         "wrong memo returns error",
+			value:        cdc.MustMarshal(&tx.SignDoc{BodyBytes: cdc.MustMarshal(&tx.TxBody{Memo: "memo"})}),
+			expectedMemo: "other memo",
+			shouldErr:    true,
 		},
 		{
-			name:        "wrong multi sig address returns error",
-			proof:       types.NewProof(multiSigPubKey, multiSigData, hex.EncodeToString([]byte(multiSigOwner))),
-			owner:       multiSigOwner,
-			addressData: types.NewBech32Address("cosmos1xcy3els9ua75kdm783c3qu0rfa2eplesldfevn", "cosmos"),
-			shouldErr:   true,
+			name:         "valid data returns no error",
+			value:        cdc.MustMarshal(&tx.SignDoc{BodyBytes: cdc.MustMarshal(&tx.TxBody{Memo: "memo"})}),
+			expectedMemo: "memo",
+			shouldErr:    false,
 		},
+	}
+
+	for _, tc := range testCases {
+		tc := tc
+		t.Run(tc.name, func(t *testing.T) {
+			err := types.ValidateDirectTxValue(tc.value, tc.expectedMemo, cdc)
+			if tc.shouldErr {
+				require.Error(t, err)
+			} else {
+				require.NoError(t, err)
+			}
+		})
+	}
+}
+
+func TestValidateAminoTxValue(t *testing.T) {
+	_, legacyAmino := app.MakeCodecs()
+	testCases := []struct {
+		name         string
+		value        []byte
+		expectedMemo string
+		shouldErr    bool
+	}{
 		{
-			name:        "wrong multi sig pubkey returns error",
-			proof:       types.NewProof(bech32PubKey, multiSigData, hex.EncodeToString([]byte(multiSigOwner))),
-			owner:       multiSigOwner,
-			addressData: types.NewBech32Address("cosmos1xcy3els9ua75kdm783c3qu0rfa2eplesldfevn", "cosmos"),
-			shouldErr:   true,
+			name:         "invalid message returns error",
+			value:        legacyAmino.MustMarshalJSON(&types.Bech32Address{}),
+			expectedMemo: "memo",
+			shouldErr:    true,
 		},
 		{
-			name:        "correct proof with Base58 address returns no error",
-			proof:       types.NewProof(base58PubKey, base58SigData, hex.EncodeToString([]byte(base58Owner))),
-			owner:       base58Owner,
-			addressData: types.NewBase58Address(base58Addr),
-			shouldErr:   false,
+			name:         "wrong memo returns error",
+			value:        legacyAmino.MustMarshalJSON(&legacytx.StdSignDoc{}),
+			expectedMemo: "memo",
+			shouldErr:    true,
 		},
 		{
-			name:        "correct proof with Bech32 address returns no error",
-			proof:       types.NewProof(bech32PubKey, bech32SigData, hex.EncodeToString([]byte(bech32Owner))),
-			owner:       bech32Owner,
-			addressData: types.NewBech32Address(bech32Addr, "cosmos"),
-			shouldErr:   false,
+			name:         "valid data returns no error",
+			value:        legacyAmino.MustMarshalJSON(&legacytx.StdSignDoc{Memo: "memo"}),
+			expectedMemo: "memo",
+			shouldErr:    false,
 		},
+	}
+
+	for _, tc := range testCases {
+		tc := tc
+		t.Run(tc.name, func(t *testing.T) {
+			err := types.ValidateAminoTxValue(tc.value, tc.expectedMemo, legacyAmino)
+			if tc.shouldErr {
+				require.Error(t, err)
+			} else {
+				require.NoError(t, err)
+			}
+		})
+	}
+}
+
+func TestValidateRawValue(t *testing.T) {
+	testCases := []struct {
+		name          string
+		value         []byte
+		expectedValue string
+		shouldErr     bool
+	}{
 		{
-			name:        "correct proof with Hex address returns no error",
-			proof:       types.NewProof(hexPubKey, hexSigData, hex.EncodeToString([]byte(hexOwner))),
-			owner:       hexOwner,
-			addressData: types.NewHexAddress(hexAddr, "0x"),
-			shouldErr:   false,
+			name:          "wrong value returns error",
+			value:         []byte(""),
+			expectedValue: "value",
+			shouldErr:     true,
 		},
 		{
-			name:        "correct proof with multisig address returns no error",
-			proof:       types.NewProof(multiSigPubKey, multiSigData, hex.EncodeToString([]byte(multiSigOwner))),
-			owner:       multiSigOwner,
-			addressData: types.NewBech32Address(multisigAddr, "cosmos"),
-			shouldErr:   false,
+			name:          "correct value returns no error",
+			value:         []byte("value"),
+			expectedValue: "value",
+			shouldErr:     false,
 		},
 	}
 
 	for _, tc := range testCases {
 		tc := tc
 		t.Run(tc.name, func(t *testing.T) {
-			cdc, legacyAmino := app.MakeCodecs()
-			err := tc.proof.Verify(cdc, legacyAmino, tc.owner, tc.addressData)
-
+			err := types.ValidateRawValue(tc.value, tc.expectedValue)
 			if tc.shouldErr {
 				require.Error(t, err)
 			} else {
@@ -371,106 +447,363 @@ func TestProof_Verify(t *testing.T) {
 	}
 }
 
-func TestIsValidTextSig(t *testing.T) {
+func TestValidatePersonalSignValue(t *testing.T) {
 	testCases := []struct {
 		name          string
 		value         []byte
 		expectedValue string
-		expValid      bool
+		shouldErr     bool
 	}{
 		{
-			name:          "wrong value returns false",
+			name:          "wrong value returns error",
 			value:         []byte(""),
 			expectedValue: "value",
-			expValid:      false,
+			shouldErr:     true,
 		},
 		{
-			name:          "correct value returns true",
-			value:         []byte("value"),
-			expectedValue: "value",
-			expValid:      true,
+			name:          "correct value returns no error",
+			value:         []byte("\x19Ethereum Signed Message:\n45desmos16c60y8t8vra27zjg2arlcd58dck9cwn7p6fwtd"),
+			expectedValue: "desmos16c60y8t8vra27zjg2arlcd58dck9cwn7p6fwtd",
+			shouldErr:     false,
+		},
+	}
+
+	for _, tc := range testCases {
+		tc := tc
+		t.Run(tc.name, func(t *testing.T) {
+			err := types.ValidatePersonalSignValue(tc.value, tc.expectedValue)
+			if tc.shouldErr {
+				require.Error(t, err)
+			} else {
+				require.NoError(t, err)
+			}
+		})
+	}
+}
+
+// --------------------------------------------------------------------------------------------------------------------
+
+func TestSingleSignature_Validate(t *testing.T) {
+	cdc, amino := app.MakeCodecs()
+	testCases := []struct {
+		name      string
+		signature *types.SingleSignature
+		plainText []byte
+		owner     string
+		shouldErr bool
+	}{
+		{
+			name:      "invalid direct value returns error",
+			signature: types.NewSingleSignature(types.SIGNATURE_VALUE_TYPE_COSMOS_DIRECT, nil),
+			plainText: cdc.MustMarshal(&types.Bech32Address{Prefix: "cosmos"}),
+			owner:     "cosmos1s3p4hlhfnlsynauak7ggqv2y4hafwc0y6u0hae",
+			shouldErr: true,
+		},
+		{
+			name:      "valid direct value returns no error",
+			signature: types.NewSingleSignature(types.SIGNATURE_VALUE_TYPE_COSMOS_DIRECT, nil),
+			plainText: cdc.MustMarshal(&tx.SignDoc{BodyBytes: cdc.MustMarshal(&tx.TxBody{Memo: "cosmos1s3p4hlhfnlsynauak7ggqv2y4hafwc0y6u0hae"})}),
+			owner:     "cosmos1s3p4hlhfnlsynauak7ggqv2y4hafwc0y6u0hae",
+			shouldErr: false,
+		},
+		{
+			name:      "invalid amino value returns error",
+			signature: types.NewSingleSignature(types.SIGNATURE_VALUE_TYPE_COSMOS_AMINO, nil),
+			plainText: amino.MustMarshalJSON(&legacytx.StdSignDoc{Memo: ""}),
+			owner:     "cosmos1s3p4hlhfnlsynauak7ggqv2y4hafwc0y6u0hae",
+			shouldErr: true,
+		},
+		{
+			name:      "valid amino value returns error",
+			signature: types.NewSingleSignature(types.SIGNATURE_VALUE_TYPE_COSMOS_AMINO, nil),
+			plainText: amino.MustMarshalJSON(&legacytx.StdSignDoc{Memo: "cosmos1s3p4hlhfnlsynauak7ggqv2y4hafwc0y6u0hae"}),
+			owner:     "cosmos1s3p4hlhfnlsynauak7ggqv2y4hafwc0y6u0hae",
+			shouldErr: false,
+		},
+		{
+			name:      "invalid raw value returns error",
+			signature: types.NewSingleSignature(types.SIGNATURE_VALUE_TYPE_RAW, nil),
+			plainText: []byte(""),
+			owner:     "cosmos1s3p4hlhfnlsynauak7ggqv2y4hafwc0y6u0hae",
+			shouldErr: true,
+		},
+		{
+			name:      "valid raw value returns no error",
+			signature: types.NewSingleSignature(types.SIGNATURE_VALUE_TYPE_RAW, nil),
+			plainText: []byte("cosmos1s3p4hlhfnlsynauak7ggqv2y4hafwc0y6u0hae"),
+			owner:     "cosmos1s3p4hlhfnlsynauak7ggqv2y4hafwc0y6u0hae",
+			shouldErr: false,
+		},
+		{
+			name:      "invalid personal sign value returns error",
+			signature: types.NewSingleSignature(types.SIGNATURE_VALUE_TYPE_EVM_PERSONAL_SIGN, nil),
+			plainText: []byte("\x19Ethereum Signed Message:\n5value"),
+			owner:     "cosmos1s3p4hlhfnlsynauak7ggqv2y4hafwc0y6u0hae",
+			shouldErr: true,
+		},
+		{
+			name:      "valid personal sign value returns no error",
+			signature: types.NewSingleSignature(types.SIGNATURE_VALUE_TYPE_EVM_PERSONAL_SIGN, nil),
+			plainText: []byte("\x19Ethereum Signed Message:\n45cosmos1s3p4hlhfnlsynauak7ggqv2y4hafwc0y6u0hae"),
+			owner:     "cosmos1s3p4hlhfnlsynauak7ggqv2y4hafwc0y6u0hae",
+			shouldErr: false,
 		},
 	}
 
 	for _, tc := range testCases {
 		tc := tc
 		t.Run(tc.name, func(t *testing.T) {
-			isValid := types.IsValidTextSig(tc.value, tc.expectedValue)
-			require.Equal(t, tc.expValid, isValid)
+			err := tc.signature.Validate(cdc, amino, tc.plainText, tc.owner)
+			if tc.shouldErr {
+				require.Error(t, err)
+			} else {
+				require.NoError(t, err)
+			}
 		})
 	}
 }
 
-func TestIsValidDirectTxSig(t *testing.T) {
+func TestSingleSignature_Verify(t *testing.T) {
 	cdc, _ := app.MakeCodecs()
+
+	privKey := secp256k1.GenPrivKey()
+	pubKey := privKey.PubKey()
+	pubKeyAny, err := codectypes.NewAnyWithValue(pubKey)
+	require.NoError(t, err)
+
+	sigBz, err := privKey.Sign([]byte("cosmos10m20h8fy0qp2a8f46zzjpvg8pfl8flajgxsvmk"))
+	require.NoError(t, err)
+
+	invalidAny, err := codectypes.NewAnyWithValue(privKey)
+	require.NoError(t, err)
+
 	testCases := []struct {
-		name         string
-		value        []byte
-		expectedMemo string
-		expIsValid   bool
+		name      string
+		store     func(ctx sdk.Context)
+		signature *types.SingleSignature
+		pubKey    *codectypes.Any
+		plainText []byte
+		shouldErr bool
+		expPubKey cryptotypes.PubKey
 	}{
 		{
-			name:         "invalid message returns false",
-			value:        cdc.MustMarshal(&types.Bech32Address{Prefix: "cosmos"}),
-			expectedMemo: "memo",
-			expIsValid:   false,
+			name:      "invalid pub key returns error",
+			signature: types.NewSingleSignature(types.SIGNATURE_VALUE_TYPE_RAW, sigBz),
+			pubKey:    invalidAny,
+			plainText: []byte("cosmos10m20h8fy0qp2a8f46zzjpvg8pfl8flajgxsvmk"),
+			shouldErr: true,
 		},
 		{
-			name:         "wrong memo returns false",
-			value:        cdc.MustMarshal(&tx.SignDoc{BodyBytes: cdc.MustMarshal(&tx.TxBody{Memo: "memo"})}),
-			expectedMemo: "other memo",
-			expIsValid:   false,
+			name:      "invalid signature returns error",
+			signature: types.NewSingleSignature(types.SIGNATURE_VALUE_TYPE_RAW, sigBz),
+			pubKey:    pubKeyAny,
+			plainText: []byte("value"),
+			shouldErr: true,
 		},
 		{
-			name:         "valid data returns true",
-			value:        cdc.MustMarshal(&tx.SignDoc{BodyBytes: cdc.MustMarshal(&tx.TxBody{Memo: "memo"})}),
-			expectedMemo: "memo",
-			expIsValid:   true,
+			name:      "valid data returns no error",
+			signature: types.NewSingleSignature(types.SIGNATURE_VALUE_TYPE_RAW, sigBz),
+			pubKey:    pubKeyAny,
+			plainText: []byte("cosmos10m20h8fy0qp2a8f46zzjpvg8pfl8flajgxsvmk"),
+			shouldErr: false,
+			expPubKey: pubKey,
 		},
 	}
 
 	for _, tc := range testCases {
 		tc := tc
 		t.Run(tc.name, func(t *testing.T) {
-			isValid := types.IsValidDirectTxSig(tc.value, tc.expectedMemo, cdc)
-			require.Equal(t, tc.expIsValid, isValid)
+			pubKey, err := tc.signature.Verify(cdc, tc.pubKey, tc.plainText)
+			if tc.shouldErr {
+				require.Error(t, err)
+			} else {
+				require.NoError(t, err)
+				require.True(t, tc.expPubKey.Equals(pubKey))
+			}
 		})
 	}
 }
 
-func TestIsValidAminoTxSig(t *testing.T) {
-	_, legacyAmino := app.MakeCodecs()
+// --------------------------------------------------------------------------------------------------------------------
+
+func TestCosmosMultiSignature_GetValueType(t *testing.T) {
 	testCases := []struct {
 		name         string
-		value        []byte
-		expectedMemo string
-		expIsValid   bool
+		store        func(ctx sdk.Context)
+		signature    *types.CosmosMultiSignature
+		shouldErr    bool
+		expValueType types.SignatureValueType
 	}{
 		{
-			name:         "invalid message returns false",
-			value:        legacyAmino.MustMarshalJSON(&types.Bech32Address{}),
-			expectedMemo: "memo",
-			expIsValid:   false,
+			name: "different sign modes return error",
+			signature: types.NewCosmosMultiSignature(nil, []types.Signature{
+				types.NewSingleSignature(types.SIGNATURE_VALUE_TYPE_COSMOS_DIRECT, nil),
+				types.NewCosmosMultiSignature(nil, []types.Signature{
+					types.NewSingleSignature(types.SIGNATURE_VALUE_TYPE_RAW, nil),
+					types.NewSingleSignature(types.SIGNATURE_VALUE_TYPE_COSMOS_DIRECT, nil),
+				}),
+			}),
+			shouldErr: true,
 		},
 		{
-			name:         "wrong memo returns false",
-			value:        legacyAmino.MustMarshalJSON(&legacytx.StdSignDoc{}),
-			expectedMemo: "memo",
-			expIsValid:   false,
+			name: "correct sign modes return proper value",
+			signature: types.NewCosmosMultiSignature(nil, []types.Signature{
+				types.NewSingleSignature(types.SIGNATURE_VALUE_TYPE_RAW, nil),
+				types.NewCosmosMultiSignature(nil, []types.Signature{
+					types.NewSingleSignature(types.SIGNATURE_VALUE_TYPE_RAW, nil),
+					types.NewSingleSignature(types.SIGNATURE_VALUE_TYPE_RAW, nil),
+				}),
+			}),
+			shouldErr:    false,
+			expValueType: types.SIGNATURE_VALUE_TYPE_RAW,
+		},
+	}
+
+	for _, tc := range testCases {
+		tc := tc
+		t.Run(tc.name, func(t *testing.T) {
+			signMode, err := tc.signature.GetValueType()
+			if tc.shouldErr {
+				require.Error(t, err)
+			} else {
+				require.NoError(t, err)
+				require.Equal(t, tc.expValueType, signMode)
+			}
+		})
+	}
+}
+
+func TestCosmosMultiSignature_Validate(t *testing.T) {
+	cdc, amino := app.MakeCodecs()
+	testCases := []struct {
+		name      string
+		signature *types.CosmosMultiSignature
+		plainText []byte
+		owner     string
+		shouldErr bool
+	}{
+		{
+			name: "invalid direct value returns error",
+			signature: types.NewCosmosMultiSignature(nil, []types.Signature{
+				types.NewSingleSignature(types.SIGNATURE_VALUE_TYPE_COSMOS_DIRECT, nil),
+			}),
+			plainText: cdc.MustMarshal(&types.Bech32Address{Prefix: "cosmos"}),
+			owner:     "cosmos1s3p4hlhfnlsynauak7ggqv2y4hafwc0y6u0hae",
+			shouldErr: true,
 		},
 		{
-			name:         "valid data returns true",
-			value:        legacyAmino.MustMarshalJSON(&legacytx.StdSignDoc{Memo: "memo"}),
-			expectedMemo: "memo",
-			expIsValid:   true,
+			name: "valid direct value returns no error",
+			signature: types.NewCosmosMultiSignature(nil, []types.Signature{
+				types.NewSingleSignature(types.SIGNATURE_VALUE_TYPE_COSMOS_DIRECT, nil),
+			}),
+			plainText: cdc.MustMarshal(&tx.SignDoc{BodyBytes: cdc.MustMarshal(&tx.TxBody{Memo: "cosmos1s3p4hlhfnlsynauak7ggqv2y4hafwc0y6u0hae"})}),
+			owner:     "cosmos1s3p4hlhfnlsynauak7ggqv2y4hafwc0y6u0hae",
+			shouldErr: false,
+		},
+		{
+			name: "invalid amino value returns error",
+			signature: types.NewCosmosMultiSignature(nil, []types.Signature{
+				types.NewSingleSignature(types.SIGNATURE_VALUE_TYPE_COSMOS_AMINO, nil),
+			}),
+			plainText: amino.MustMarshalJSON(&legacytx.StdSignDoc{Memo: ""}),
+			owner:     "cosmos1s3p4hlhfnlsynauak7ggqv2y4hafwc0y6u0hae",
+			shouldErr: true,
+		},
+		{
+			name: "valid amino value returns error",
+			signature: types.NewCosmosMultiSignature(nil, []types.Signature{
+				types.NewSingleSignature(types.SIGNATURE_VALUE_TYPE_COSMOS_AMINO, nil),
+			}),
+			plainText: amino.MustMarshalJSON(&legacytx.StdSignDoc{Memo: "cosmos1s3p4hlhfnlsynauak7ggqv2y4hafwc0y6u0hae"}),
+			owner:     "cosmos1s3p4hlhfnlsynauak7ggqv2y4hafwc0y6u0hae",
+			shouldErr: false,
+		},
+		{
+			name: "invalid raw value returns error",
+			signature: types.NewCosmosMultiSignature(nil, []types.Signature{
+				types.NewSingleSignature(types.SIGNATURE_VALUE_TYPE_RAW, nil),
+			}),
+			plainText: []byte(""),
+			owner:     "cosmos1s3p4hlhfnlsynauak7ggqv2y4hafwc0y6u0hae",
+			shouldErr: true,
+		},
+		{
+			name: "valid raw value returns no error",
+			signature: types.NewCosmosMultiSignature(nil, []types.Signature{
+				types.NewSingleSignature(types.SIGNATURE_VALUE_TYPE_RAW, nil),
+			}),
+			plainText: []byte("cosmos1s3p4hlhfnlsynauak7ggqv2y4hafwc0y6u0hae"),
+			owner:     "cosmos1s3p4hlhfnlsynauak7ggqv2y4hafwc0y6u0hae",
+			shouldErr: false,
 		},
 	}
 
 	for _, tc := range testCases {
 		tc := tc
 		t.Run(tc.name, func(t *testing.T) {
-			isValid := types.IsValidAminoTxSig(tc.value, tc.expectedMemo, legacyAmino)
-			require.Equal(t, tc.expIsValid, isValid)
+			err := tc.signature.Validate(cdc, amino, tc.plainText, tc.owner)
+			if tc.shouldErr {
+				require.Error(t, err)
+			} else {
+				require.NoError(t, err)
+			}
+		})
+	}
+}
+
+func TestCosmosMultiSignature_Verify(t *testing.T) {
+	cdc, _ := app.MakeCodecs()
+
+	privKeys, pubKey := generateMultiSigKeys(3)
+	pubKeyAny, err := codectypes.NewAnyWithValue(pubKey)
+	require.NoError(t, err)
+
+	invalidAny, err := codectypes.NewAnyWithValue(&types.CosmosMultiSignature{})
+	require.NoError(t, err)
+
+	testCases := []struct {
+		name      string
+		store     func(ctx sdk.Context)
+		signature *types.CosmosMultiSignature
+		pubKey    *codectypes.Any
+		plainText []byte
+		shouldErr bool
+		expPubKey cryptotypes.PubKey
+	}{
+		{
+			name:      "invalid pub key returns error",
+			signature: generateCosmosMultiSigSignature(t, privKeys, []byte("cosmos1vfvst0mr79nzzxsk65uuhfklmwrnsfadhtn977")),
+			pubKey:    invalidAny,
+			plainText: []byte("cosmos1vfvst0mr79nzzxsk65uuhfklmwrnsfadhtn977"),
+			shouldErr: true,
+		},
+		{
+			name:      "invalid signature returns error",
+			signature: generateCosmosMultiSigSignature(t, privKeys, []byte("cosmos1vfvst0mr79nzzxsk65uuhfklmwrnsfadhtn977")),
+			pubKey:    pubKeyAny,
+			plainText: []byte("value"),
+			shouldErr: true,
+		},
+		{
+			name:      "valid data returns no error",
+			signature: generateCosmosMultiSigSignature(t, privKeys, []byte("cosmos1vfvst0mr79nzzxsk65uuhfklmwrnsfadhtn977")),
+			pubKey:    pubKeyAny,
+			plainText: []byte("cosmos1vfvst0mr79nzzxsk65uuhfklmwrnsfadhtn977"),
+			shouldErr: false,
+			expPubKey: pubKey,
+		},
+	}
+
+	for _, tc := range testCases {
+		tc := tc
+		t.Run(tc.name, func(t *testing.T) {
+			pubKey, err := tc.signature.Verify(cdc, tc.pubKey, tc.plainText)
+			if tc.shouldErr {
+				require.Error(t, err)
+			} else {
+				require.NoError(t, err)
+				require.True(t, tc.expPubKey.Equals(pubKey))
+			}
 		})
 	}
 }
@@ -685,7 +1018,7 @@ func TestChainLink_Validate(t *testing.T) {
 			name: "empty address returns error",
 			chainLink: types.ChainLink{
 				User:         "cosmos10clxpupsmddtj7wu7g0wdysajqwp890mva046f",
-				Proof:        types.NewProof(secp256k1.GenPrivKey().PubKey(), profilestesting.SingleSignatureProtoFromHex("74657874"), "74657874"),
+				Proof:        types.NewProof(secp256k1.GenPrivKey().PubKey(), profilestesting.SingleSignatureFromHex("74657874"), "74657874"),
 				ChainConfig:  types.NewChainConfig("cosmos"),
 				CreationTime: time.Now(),
 			},
@@ -696,7 +1029,7 @@ func TestChainLink_Validate(t *testing.T) {
 			chainLink: types.NewChainLink(
 				"",
 				types.NewBech32Address("cosmos1cjf97gpzwmaf30pzvaargfgr884mpp5ak8f7ns", "cosmos"),
-				types.NewProof(secp256k1.GenPrivKey().PubKey(), profilestesting.SingleSignatureProtoFromHex("74657874"), "74657874"),
+				types.NewProof(secp256k1.GenPrivKey().PubKey(), profilestesting.SingleSignatureFromHex("74657874"), "74657874"),
 				types.NewChainConfig("cosmos"),
 				time.Now(),
 			),
@@ -707,7 +1040,7 @@ func TestChainLink_Validate(t *testing.T) {
 			chainLink: types.NewChainLink(
 				"cosmos10clxpupsmddtj7wu7g0wdysajqwp890mva046f",
 				types.NewBech32Address("cosmos1cjf97gpzwmaf30pzvaargfgr884mpp5ak8f7ns", "cosmos"),
-				types.NewProof(secp256k1.GenPrivKey().PubKey(), &types.SingleSignatureData{}, "="),
+				types.NewProof(secp256k1.GenPrivKey().PubKey(), &types.SingleSignature{}, "="),
 				types.NewChainConfig("cosmos"),
 				time.Now(),
 			),
@@ -718,7 +1051,7 @@ func TestChainLink_Validate(t *testing.T) {
 			chainLink: types.NewChainLink(
 				"cosmos10clxpupsmddtj7wu7g0wdysajqwp890mva046f",
 				types.NewBech32Address("cosmos1cjf97gpzwmaf30pzvaargfgr884mpp5ak8f7ns", "cosmos"),
-				types.NewProof(secp256k1.GenPrivKey().PubKey(), profilestesting.SingleSignatureProtoFromHex("74657874"), "74657874"),
+				types.NewProof(secp256k1.GenPrivKey().PubKey(), profilestesting.SingleSignatureFromHex("74657874"), "74657874"),
 				types.NewChainConfig(""),
 				time.Now(),
 			),
@@ -729,7 +1062,7 @@ func TestChainLink_Validate(t *testing.T) {
 			chainLink: types.NewChainLink(
 				"cosmos10clxpupsmddtj7wu7g0wdysajqwp890mva046f",
 				types.NewBech32Address("cosmos1cjf97gpzwmaf30pzvaargfgr884mpp5ak8f7ns", "cosmos"),
-				types.NewProof(secp256k1.GenPrivKey().PubKey(), profilestesting.SingleSignatureProtoFromHex("74657874"), "74657874"),
+				types.NewProof(secp256k1.GenPrivKey().PubKey(), profilestesting.SingleSignatureFromHex("74657874"), "74657874"),
 				types.NewChainConfig("cosmos"),
 				time.Time{},
 			),
@@ -740,7 +1073,7 @@ func TestChainLink_Validate(t *testing.T) {
 			chainLink: types.NewChainLink(
 				"cosmos10clxpupsmddtj7wu7g0wdysajqwp890mva046f",
 				types.NewBech32Address("cosmos1cjf97gpzwmaf30pzvaargfgr884mpp5ak8f7ns", "cosmos"),
-				types.NewProof(secp256k1.GenPrivKey().PubKey(), profilestesting.SingleSignatureProtoFromHex("74657874"), "74657874"),
+				types.NewProof(secp256k1.GenPrivKey().PubKey(), profilestesting.SingleSignatureFromHex("74657874"), "74657874"),
 				types.NewChainConfig("cosmos"),
 				time.Now(),
 			),
@@ -772,7 +1105,7 @@ func TestChainLinkMarshaling(t *testing.T) {
 	chainLink := types.NewChainLink(
 		"cosmos10clxpupsmddtj7wu7g0wdysajqwp890mva046f",
 		types.NewBech32Address(addr, "cosmos"),
-		types.NewProof(pubKey, profilestesting.SingleSignatureProtoFromHex("74657874"), "plain-text"),
+		types.NewProof(pubKey, profilestesting.SingleSignatureFromHex("74657874"), "plain-text"),
 		types.NewChainConfig("cosmos"),
 		time.Date(2020, 1, 1, 00, 00, 00, 000, time.UTC),
 	)
diff --git a/x/profiles/types/models_packets_test.go b/x/profiles/types/models_packets_test.go
index 81ddeb24..55a50dce 100644
--- a/x/profiles/types/models_packets_test.go
+++ b/x/profiles/types/models_packets_test.go
@@ -21,14 +21,14 @@ func TestLinkChainAccountPacketData_Validate(t *testing.T) {
 			packet: types.LinkChainAccountPacketData{
 				SourceProof: types.NewProof(
 					secp256k1.GenPrivKey().PubKey(),
-					profilestesting.SingleSignatureProtoFromHex("032086ede8d4bce29fe364a94744ca71dbeaf370221ba20f9716a165c54b079561"),
+					profilestesting.SingleSignatureFromHex("032086ede8d4bce29fe364a94744ca71dbeaf370221ba20f9716a165c54b079561"),
 					"706c61696e5f74657874",
 				),
 				SourceChainConfig:  types.NewChainConfig("cosmos"),
 				DestinationAddress: "cosmos1yt7rqhj0hjw92ed0948r2pqwtp9smukurqcs70",
 				DestinationProof: types.NewProof(
 					secp256k1.GenPrivKey().PubKey(),
-					profilestesting.SingleSignatureProtoFromHex("032086ede8d4bce29fe364a94744ca71dbeaf370221ba20f9716a165c54b079561"),
+					profilestesting.SingleSignatureFromHex("032086ede8d4bce29fe364a94744ca71dbeaf370221ba20f9716a165c54b079561"),
 					"706c61696e5f74657874",
 				),
 			},
@@ -38,12 +38,12 @@ func TestLinkChainAccountPacketData_Validate(t *testing.T) {
 			name: "invalid source proof returns error",
 			packet: types.NewLinkChainAccountPacketData(
 				types.NewBech32Address("cosmos1yt7rqhj0hjw92ed0948r2pqwtp9smukurqcs70", "cosmos"),
-				types.NewProof(secp256k1.GenPrivKey().PubKey(), &types.SingleSignatureData{}, "wrong"),
+				types.NewProof(secp256k1.GenPrivKey().PubKey(), &types.SingleSignature{}, "wrong"),
 				types.NewChainConfig("cosmos"),
 				"cosmos1yt7rqhj0hjw92ed0948r2pqwtp9smukurqcs70",
 				types.NewProof(
 					secp256k1.GenPrivKey().PubKey(),
-					profilestesting.SingleSignatureProtoFromHex("032086ede8d4bce29fe364a94744ca71dbeaf370221ba20f9716a165c54b079561"),
+					profilestesting.SingleSignatureFromHex("032086ede8d4bce29fe364a94744ca71dbeaf370221ba20f9716a165c54b079561"),
 					"706c61696e5f74657874",
 				),
 			),
@@ -55,14 +55,14 @@ func TestLinkChainAccountPacketData_Validate(t *testing.T) {
 				types.NewBech32Address("cosmos1yt7rqhj0hjw92ed0948r2pqwtp9smukurqcs70", "cosmos"),
 				types.NewProof(
 					secp256k1.GenPrivKey().PubKey(),
-					profilestesting.SingleSignatureProtoFromHex("032086ede8d4bce29fe364a94744ca71dbeaf370221ba20f9716a165c54b079561"),
+					profilestesting.SingleSignatureFromHex("032086ede8d4bce29fe364a94744ca71dbeaf370221ba20f9716a165c54b079561"),
 					"706c61696e5f74657874",
 				),
 				types.NewChainConfig(""),
 				"cosmos1yt7rqhj0hjw92ed0948r2pqwtp9smukurqcs70",
 				types.NewProof(
 					secp256k1.GenPrivKey().PubKey(),
-					profilestesting.SingleSignatureProtoFromHex("032086ede8d4bce29fe364a94744ca71dbeaf370221ba20f9716a165c54b079561"),
+					profilestesting.SingleSignatureFromHex("032086ede8d4bce29fe364a94744ca71dbeaf370221ba20f9716a165c54b079561"),
 					"706c61696e5f74657874",
 				),
 			),
@@ -74,14 +74,14 @@ func TestLinkChainAccountPacketData_Validate(t *testing.T) {
 				types.NewBech32Address("cosmos1yt7rqhj0hjw92ed0948r2pqwtp9smukurqcs70", "cosmos"),
 				types.NewProof(
 					secp256k1.GenPrivKey().PubKey(),
-					profilestesting.SingleSignatureProtoFromHex("032086ede8d4bce29fe364a94744ca71dbeaf370221ba20f9716a165c54b079561"),
+					profilestesting.SingleSignatureFromHex("032086ede8d4bce29fe364a94744ca71dbeaf370221ba20f9716a165c54b079561"),
 					"706c61696e5f74657874",
 				),
 				types.NewChainConfig("cosmos"),
 				"",
 				types.NewProof(
 					secp256k1.GenPrivKey().PubKey(),
-					profilestesting.SingleSignatureProtoFromHex("032086ede8d4bce29fe364a94744ca71dbeaf370221ba20f9716a165c54b079561"),
+					profilestesting.SingleSignatureFromHex("032086ede8d4bce29fe364a94744ca71dbeaf370221ba20f9716a165c54b079561"),
 					"706c61696e5f74657874",
 				),
 			),
@@ -93,12 +93,12 @@ func TestLinkChainAccountPacketData_Validate(t *testing.T) {
 				types.NewBech32Address("cosmos1yt7rqhj0hjw92ed0948r2pqwtp9smukurqcs70", "cosmos"),
 				types.NewProof(
 					secp256k1.GenPrivKey().PubKey(),
-					profilestesting.SingleSignatureProtoFromHex("032086ede8d4bce29fe364a94744ca71dbeaf370221ba20f9716a165c54b079561"),
+					profilestesting.SingleSignatureFromHex("032086ede8d4bce29fe364a94744ca71dbeaf370221ba20f9716a165c54b079561"),
 					"706c61696e5f74657874",
 				),
 				types.NewChainConfig("cosmos"),
 				"cosmos1yt7rqhj0hjw92ed0948r2pqwtp9smukurqcs70",
-				types.NewProof(secp256k1.GenPrivKey().PubKey(), &types.SingleSignatureData{}, "wrong"),
+				types.NewProof(secp256k1.GenPrivKey().PubKey(), &types.SingleSignature{}, "wrong"),
 			),
 			shouldErr: true,
 		},
@@ -108,14 +108,14 @@ func TestLinkChainAccountPacketData_Validate(t *testing.T) {
 				types.NewBech32Address("cosmos1yt7rqhj0hjw92ed0948r2pqwtp9smukurqcs70", "cosmos"),
 				types.NewProof(
 					secp256k1.GenPrivKey().PubKey(),
-					profilestesting.SingleSignatureProtoFromHex("032086ede8d4bce29fe364a94744ca71dbeaf370221ba20f9716a165c54b079561"),
+					profilestesting.SingleSignatureFromHex("032086ede8d4bce29fe364a94744ca71dbeaf370221ba20f9716a165c54b079561"),
 					"706c61696e5f74657874",
 				),
 				types.NewChainConfig("cosmos"),
 				"cosmos1yt7rqhj0hjw92ed0948r2pqwtp9smukurqcs70",
 				types.NewProof(
 					secp256k1.GenPrivKey().PubKey(),
-					profilestesting.SingleSignatureProtoFromHex("032086ede8d4bce29fe364a94744ca71dbeaf370221ba20f9716a165c54b079561"),
+					profilestesting.SingleSignatureFromHex("032086ede8d4bce29fe364a94744ca71dbeaf370221ba20f9716a165c54b079561"),
 					"706c61696e5f74657874",
 				),
 			),
@@ -140,10 +140,10 @@ func TestLinkChainAccountPacketData_Validate(t *testing.T) {
 func TestLinkChainAccountPacketData_GetBytes(t *testing.T) {
 	packetData := types.NewLinkChainAccountPacketData(
 		types.NewBech32Address("cosmos1yt7rqhj0hjw92ed0948r2pqwtp9smukurqcs70", "cosmos"),
-		types.NewProof(secp256k1.GenPrivKey().PubKey(), profilestesting.SingleSignatureProtoFromHex("032086ede8d4bce29fe364a94744ca71dbeaf370221ba20f9716a165c54b079561"), "plain_text"),
+		types.NewProof(secp256k1.GenPrivKey().PubKey(), profilestesting.SingleSignatureFromHex("032086ede8d4bce29fe364a94744ca71dbeaf370221ba20f9716a165c54b079561"), "plain_text"),
 		types.NewChainConfig("cosmos"),
 		"cosmos1yt7rqhj0hjw92ed0948r2pqwtp9smukurqcs70",
-		types.NewProof(secp256k1.GenPrivKey().PubKey(), profilestesting.SingleSignatureProtoFromHex("032086ede8d4bce29fe364a94744ca71dbeaf370221ba20f9716a165c54b079561"), "plain_text"),
+		types.NewProof(secp256k1.GenPrivKey().PubKey(), profilestesting.SingleSignatureFromHex("032086ede8d4bce29fe364a94744ca71dbeaf370221ba20f9716a165c54b079561"), "plain_text"),
 	)
 	_, err := packetData.GetBytes()
 	require.NoError(t, err)
diff --git a/x/profiles/types/msgs_chain_links_test.go b/x/profiles/types/msgs_chain_links_test.go
index fcd51f91..29de588f 100644
--- a/x/profiles/types/msgs_chain_links_test.go
+++ b/x/profiles/types/msgs_chain_links_test.go
@@ -17,7 +17,7 @@ var msgChainLinkAccount = types.NewMsgLinkChainAccount(
 	types.NewBech32Address("cosmos1xmquc944hzu6n6qtljcexkuhhz76mucxtgm5x0", "cosmos"),
 	types.NewProof(
 		profilestesting.PubKeyFromBech32("cosmospub1addwnpepq0j8zw4t6tg3v8gh7d2d799gjhue7ewwmpg2hwr77f9kuuyzgqtrw5r6wec"),
-		profilestesting.SingleSignatureProtoFromHex("ad112abb30e5240c7b9d21b4cc5421d76cfadfcd5977cca262523b5f5bc759457d4aa6d5c1eb6223db104b47aa1f222468be8eb5bb2762b971622ac5b96351b5"),
+		profilestesting.SingleSignatureFromHex("ad112abb30e5240c7b9d21b4cc5421d76cfadfcd5977cca262523b5f5bc759457d4aa6d5c1eb6223db104b47aa1f222468be8eb5bb2762b971622ac5b96351b5"),
 		"74657874",
 	),
 	types.NewChainConfig("cosmos"),
@@ -51,7 +51,7 @@ func TestMsgLinkChainAccount_ValidateBasic(t *testing.T) {
 			name: "invalid proof returns error",
 			msg: types.NewMsgLinkChainAccount(
 				types.NewBech32Address("cosmos1xmquc944hzu6n6qtljcexkuhhz76mucxtgm5x0", "cosmos"),
-				types.NewProof(secp256k1.GenPrivKey().PubKey(), &types.SingleSignatureData{}, "wrong"),
+				types.NewProof(secp256k1.GenPrivKey().PubKey(), &types.SingleSignature{}, "wrong"),
 				msgChainLinkAccount.ChainConfig,
 				msgChainLinkAccount.Signer,
 			),
@@ -99,7 +99,7 @@ func TestMsgLinkChainAccount_ValidateBasic(t *testing.T) {
 }
 
 func TestMsgLinkChainAccount_GetSignBytes(t *testing.T) {
-	expected := `{"type":"desmos/MsgLinkChainAccount","value":{"chain_address":{"type":"desmos/Bech32Address","value":{"prefix":"cosmos","value":"cosmos1xmquc944hzu6n6qtljcexkuhhz76mucxtgm5x0"}},"chain_config":{"name":"cosmos"},"proof":{"plain_text":"74657874","pub_key":{"type":"tendermint/PubKeySecp256k1","value":"A+RxOqvS0RYdF/NU3xSolfmfZc7YUKu4fvJLbnCCQBY3"},"signature":{"type":"desmos/SingleSignatureData","value":{"mode":1,"signature":"rREquzDlJAx7nSG0zFQh12z6381Zd8yiYlI7X1vHWUV9SqbVwetiI9sQS0eqHyIkaL6OtbsnYrlxYirFuWNRtQ=="}}},"signer":"cosmos1u9hgsqfpe3snftr7p7fsyja3wtlmj2sgf2w9yl"}}`
+	expected := `{"type":"desmos/MsgLinkChainAccount","value":{"chain_address":{"type":"desmos/Bech32Address","value":{"prefix":"cosmos","value":"cosmos1xmquc944hzu6n6qtljcexkuhhz76mucxtgm5x0"}},"chain_config":{"name":"cosmos"},"proof":{"plain_text":"74657874","pub_key":{"type":"tendermint/PubKeySecp256k1","value":"A+RxOqvS0RYdF/NU3xSolfmfZc7YUKu4fvJLbnCCQBY3"},"signature":{"type":"desmos/SingleSignature","value":{"signature":"rREquzDlJAx7nSG0zFQh12z6381Zd8yiYlI7X1vHWUV9SqbVwetiI9sQS0eqHyIkaL6OtbsnYrlxYirFuWNRtQ==","value_type":1}}},"signer":"cosmos1u9hgsqfpe3snftr7p7fsyja3wtlmj2sgf2w9yl"}}`
 	require.Equal(t, expected, string(msgChainLinkAccount.GetSignBytes()))
 }
 
diff --git a/x/profiles/wasm/msg_parser_test.go b/x/profiles/wasm/msg_parser_test.go
index 53c7a7c4..3f7dfe3e 100644
--- a/x/profiles/wasm/msg_parser_test.go
+++ b/x/profiles/wasm/msg_parser_test.go
@@ -134,7 +134,7 @@ func TestMsgsParser_ParseCustomMsgs(t *testing.T) {
 				types.NewBech32Address("cosmos1xmquc944hzu6n6qtljcexkuhhz76mucxtgm5x0", "cosmos"),
 				types.NewProof(
 					profilestesting.PubKeyFromBech32("cosmospub1addwnpepq0j8zw4t6tg3v8gh7d2d799gjhue7ewwmpg2hwr77f9kuuyzgqtrw5r6wec"),
-					profilestesting.SingleSignatureProtoFromHex("ad112abb30e5240c7b9d21b4cc5421d76cfadfcd5977cca262523b5f5bc759457d4aa6d5c1eb6223db104b47aa1f222468be8eb5bb2762b971622ac5b96351b5"),
+					profilestesting.SingleSignatureFromHex("ad112abb30e5240c7b9d21b4cc5421d76cfadfcd5977cca262523b5f5bc759457d4aa6d5c1eb6223db104b47aa1f222468be8eb5bb2762b971622ac5b96351b5"),
 					"74657874",
 				),
 				types.NewChainConfig("cosmos"),
@@ -145,7 +145,7 @@ func TestMsgsParser_ParseCustomMsgs(t *testing.T) {
 				types.NewBech32Address("cosmos1xmquc944hzu6n6qtljcexkuhhz76mucxtgm5x0", "cosmos"),
 				types.NewProof(
 					profilestesting.PubKeyFromBech32("cosmospub1addwnpepq0j8zw4t6tg3v8gh7d2d799gjhue7ewwmpg2hwr77f9kuuyzgqtrw5r6wec"),
-					profilestesting.SingleSignatureProtoFromHex("ad112abb30e5240c7b9d21b4cc5421d76cfadfcd5977cca262523b5f5bc759457d4aa6d5c1eb6223db104b47aa1f222468be8eb5bb2762b971622ac5b96351b5"),
+					profilestesting.SingleSignatureFromHex("ad112abb30e5240c7b9d21b4cc5421d76cfadfcd5977cca262523b5f5bc759457d4aa6d5c1eb6223db104b47aa1f222468be8eb5bb2762b971622ac5b96351b5"),
 					"74657874",
 				),
 				types.NewChainConfig("cosmos"),
diff --git a/x/profiles/wasm/querier_test.go b/x/profiles/wasm/querier_test.go
index dbd5f800..6c561ffa 100644
--- a/x/profiles/wasm/querier_test.go
+++ b/x/profiles/wasm/querier_test.go
@@ -92,7 +92,7 @@ func (suite *TestSuite) TestProfilesWasmQuerier_QueryCustom() {
 					types.NewBech32Address("cosmos1cjf97gpzwmaf30pzvaargfgr884mpp5ak8f7ns", "cosmos"),
 					types.NewProof(
 						profilestesting.PubKeyFromBech32("cosmospub1addwnpepqvryxhhqhw52c4ny5twtfzf3fsrjqhx0x5cuya0fylw0wu0eqptykeqhr4d"),
-						profilestesting.SingleSignatureProtoFromHex("909e38994b1583d3f14384c2e9a03c90064e8fd8e19b780bb0ba303dfe671a27287da04d0ce096ce9a140bd070ee36818f5519eb2070a16971efd8143855524b"),
+						profilestesting.SingleSignatureFromHex("909e38994b1583d3f14384c2e9a03c90064e8fd8e19b780bb0ba303dfe671a27287da04d0ce096ce9a140bd070ee36818f5519eb2070a16971efd8143855524b"),
 						"74657874",
 					),
 					types.NewChainConfig("cosmos"),
@@ -112,7 +112,7 @@ func (suite *TestSuite) TestProfilesWasmQuerier_QueryCustom() {
 							types.NewBech32Address("cosmos1cjf97gpzwmaf30pzvaargfgr884mpp5ak8f7ns", "cosmos"),
 							types.NewProof(
 								profilestesting.PubKeyFromBech32("cosmospub1addwnpepqvryxhhqhw52c4ny5twtfzf3fsrjqhx0x5cuya0fylw0wu0eqptykeqhr4d"),
-								profilestesting.SingleSignatureProtoFromHex("909e38994b1583d3f14384c2e9a03c90064e8fd8e19b780bb0ba303dfe671a27287da04d0ce096ce9a140bd070ee36818f5519eb2070a16971efd8143855524b"),
+								profilestesting.SingleSignatureFromHex("909e38994b1583d3f14384c2e9a03c90064e8fd8e19b780bb0ba303dfe671a27287da04d0ce096ce9a140bd070ee36818f5519eb2070a16971efd8143855524b"),
 								"74657874",
 							),
 							types.NewChainConfig("cosmos"),