diff --git a/src/components/jsonld/JsonLdCredentialViewer.tsx b/src/components/jsonld/JsonLdCredentialViewer.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..a12dba3324252acf8e3d460aae1c50f72d61c518
--- /dev/null
+++ b/src/components/jsonld/JsonLdCredentialViewer.tsx
@@ -0,0 +1,25 @@
+import React from 'react';
+import JsonLdRawViewer from "./JsonLdRawViewer";
+import VereignLegalParticipant from "./VereignLegalParticipant";
+import VereignPrivatePerson from "./VereignPrivatePerson";
+
+type JsonLdCredentialViewerProps = {
+  jsonld: any;
+};
+
+const JsonLdCredentialViewer: React.FC<JsonLdCredentialViewerProps> = ({
+  jsonld
+}) => {
+  const subject = jsonld?.credentialSubject || {};
+  const subjectType = subject.type;
+  switch (subjectType) {
+    case "vereign:PrivatePerson":
+      return <VereignPrivatePerson jsonld={jsonld} />;
+    case "vereign:LegalParticipant":
+      return <VereignLegalParticipant jsonld={jsonld} />;
+    default:
+      return <JsonLdRawViewer jsonld={jsonld} />;
+  }
+};
+
+export default JsonLdCredentialViewer;
diff --git a/src/components/jsonld/JsonLdRawViewer.tsx b/src/components/jsonld/JsonLdRawViewer.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..2504b61bfcb88028a7d4953ad7da0a23d52cbd4d
--- /dev/null
+++ b/src/components/jsonld/JsonLdRawViewer.tsx
@@ -0,0 +1,40 @@
+import React from 'react';
+import {View, Text, StyleSheet} from 'react-native';
+import {ColorPallet, TextTheme} from 'src/theme/theme';
+
+type LegalParticipantProps = {
+  jsonld: any;
+};
+
+const JsonLdRawViewer: React.FC<LegalParticipantProps> = ({
+  jsonld,
+}) => {
+  return (
+    <View>
+      <Text style={styles.header}>Raw JSON-LD:</Text>
+      <View style={styles.json}>
+        <Text style={styles.jsonValue}>
+          {JSON.stringify(jsonld, null, 2)}
+        </Text>
+      </View>
+    </View>
+  );
+};
+
+export default JsonLdRawViewer;
+
+const styles = StyleSheet.create({
+  header: {
+    ...TextTheme.normal,
+    color: ColorPallet.baseColors.black,
+    fontWeight: 'bold',
+    marginBottom: 8,
+  },
+  json: {
+    paddingVertical: 16,
+  },
+  jsonValue: {
+    ...TextTheme.normal,
+    color: ColorPallet.baseColors.black,
+  },
+});
diff --git a/src/components/jsonld/VereignLegalParticipant.tsx b/src/components/jsonld/VereignLegalParticipant.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..76a6922fa78b5a9d3064835ce84e2f36648c60e6
--- /dev/null
+++ b/src/components/jsonld/VereignLegalParticipant.tsx
@@ -0,0 +1,84 @@
+import React from 'react';
+import {View, Text, StyleSheet} from 'react-native';
+import {ColorPallet, TextTheme} from 'src/theme/theme';
+
+type LegalParticipantProps = {
+  jsonld: any;
+};
+
+const VereignLegalParticipant: React.FC<LegalParticipantProps> = ({
+  jsonld,
+}) => {
+  const subject = jsonld?.credentialSubject || {};
+
+  const companyName = subject["vereign:companyName"];
+  const taxID = subject["vereign:taxID"];
+  const gleiCode = subject["vereign:gleiCode"];
+
+  const address = subject["vereign:address"] || {};
+  const street = address["vereign:street"];
+  const building = address["vereign:building"];
+  const city = address["vereign:city"];
+  const country = address["vereign:country"];
+
+  return (
+    <View>
+      <Text style={styles.header}>JSON-LD</Text>
+      <View style={styles.prop}>
+        <Text style={styles.propLabel}>CompanyName</Text>
+        <Text style={styles.propValue}>{companyName}</Text>
+      </View>
+      <View style={styles.prop}>
+        <Text style={styles.propLabel}>TaxID</Text>
+        <Text style={styles.propValue}>{taxID}</Text>
+      </View>
+      <View style={styles.prop}>
+        <Text style={styles.propLabel}>GleiCode</Text>
+        <Text style={styles.propValue}>{gleiCode}</Text>
+      </View>
+      <View style={styles.prop}>
+        <Text style={styles.propLabel}>Street</Text>
+        <Text style={styles.propValue}>{street}</Text>
+      </View>
+      <View style={styles.prop}>
+        <Text style={styles.propLabel}>Building</Text>
+        <Text style={styles.propValue}>{building}</Text>
+      </View>
+      <View style={styles.prop}>
+        <Text style={styles.propLabel}>City</Text>
+        <Text style={styles.propValue}>{city}</Text>
+      </View>
+      <View style={styles.prop}>
+        <Text style={styles.propLabel}>Country</Text>
+        <Text style={styles.propValue}>{country}</Text>
+      </View>
+    </View>
+  );
+};
+
+export default VereignLegalParticipant;
+
+const styles = StyleSheet.create({
+  header: {
+    ...TextTheme.normal,
+    color: ColorPallet.baseColors.black,
+    fontWeight: 'bold',
+    marginBottom: 8,
+  },
+  prop: {
+    flexDirection: 'row',
+    paddingVertical: 4,
+  },
+  propLabel: {
+    width: '40%',
+    ...TextTheme.normal,
+    color: ColorPallet.baseColors.black,
+    fontWeight: 'bold',
+  },
+  propValue: {
+    width: '60%',
+    ...TextTheme.normal,
+    color: ColorPallet.baseColors.black,
+    textAlign: 'right',
+  },
+});
diff --git a/src/components/jsonld/VereignPrivatePerson.tsx b/src/components/jsonld/VereignPrivatePerson.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..6c9f2ed93820d5c0c41327046e4adcc4d001560a
--- /dev/null
+++ b/src/components/jsonld/VereignPrivatePerson.tsx
@@ -0,0 +1,79 @@
+import React from 'react';
+import {View, Text, StyleSheet} from 'react-native';
+import {ColorPallet, TextTheme} from 'src/theme/theme';
+
+type PrivatePersonProps = {
+  jsonld: any;
+};
+
+const VereignPrivatePerson: React.FC<PrivatePersonProps> = ({
+  jsonld,
+}) => {
+  const subject = jsonld.credentialSubject || {};
+
+  const name = subject["vereign:name"];
+  const dateOfBirth = subject["vereign:dateOfBirth"];
+
+  const address = subject["vereign:address"] || {};
+  const street = address["vereign:street"];
+  const building = address["vereign:building"];
+  const city = address["vereign:city"];
+  const country = address["vereign:country"];
+
+  return (
+    <View>
+      <Text style={styles.header}>JSON-LD</Text>
+      <View style={styles.prop}>
+        <Text style={styles.propLabel}>Name</Text>
+        <Text style={styles.propValue}>{name}</Text>
+      </View>
+      <View style={styles.prop}>
+        <Text style={styles.propLabel}>DateOfBirth</Text>
+        <Text style={styles.propValue}>{dateOfBirth}</Text>
+      </View>
+      <View style={styles.prop}>
+        <Text style={styles.propLabel}>Street</Text>
+        <Text style={styles.propValue}>{street}</Text>
+      </View>
+      <View style={styles.prop}>
+        <Text style={styles.propLabel}>Building</Text>
+        <Text style={styles.propValue}>{building}</Text>
+      </View>
+      <View style={styles.prop}>
+        <Text style={styles.propLabel}>City</Text>
+        <Text style={styles.propValue}>{city}</Text>
+      </View>
+      <View style={styles.prop}>
+        <Text style={styles.propLabel}>Country</Text>
+        <Text style={styles.propValue}>{country}</Text>
+      </View>
+    </View>
+  );
+};
+
+export default VereignPrivatePerson;
+
+const styles = StyleSheet.create({
+  header: {
+    ...TextTheme.normal,
+    color: ColorPallet.baseColors.black,
+    fontWeight: 'bold',
+    marginBottom: 8,
+  },
+  prop: {
+    flexDirection: 'row',
+    paddingVertical: 4,
+  },
+  propLabel: {
+    width: '40%',
+    ...TextTheme.normal,
+    color: ColorPallet.baseColors.black,
+    fontWeight: 'bold',
+  },
+  propValue: {
+    width: '60%',
+    ...TextTheme.normal,
+    color: ColorPallet.baseColors.black,
+    textAlign: 'right',
+  },
+});
diff --git a/src/components/notifications/NotificationListItem.tsx b/src/components/notifications/NotificationListItem.tsx
index 72e9f53d372054e0dc69f4d2d72465b9e8a9e096..5c4b1f20cad284b6d29d7ed1a225f34995aaa307 100644
--- a/src/components/notifications/NotificationListItem.tsx
+++ b/src/components/notifications/NotificationListItem.tsx
@@ -23,7 +23,7 @@ const NotificationListItem: React.FC<NotificationListItemProps> = ({
 
   useEffect(() => {
     (async () => {
-      console.log(notification);
+      console.log(JSON.stringify(notification, null, 2));
       if (notification.proofRequest) {
         setTitle(t<string>('ProofRequest.ProofRequest'));
         setBody(notification.connection?.theirLabel ?? 'Connectionless proof request');
diff --git a/src/credo/JsonLdCredentialFormatService.ts b/src/credo/JsonLdCredentialFormatService.ts
new file mode 100644
index 0000000000000000000000000000000000000000..c50c2cea59f559d9ba002788b9106659defee624
--- /dev/null
+++ b/src/credo/JsonLdCredentialFormatService.ts
@@ -0,0 +1,587 @@
+/**
+ * This is a copy of https://code.vereign.com/gaiax/ocm/ocm-engine/-/blob/main/libs/askar/src/credo/JsonLdCredentialFormatService.ts?ref_type=heads
+ * TODO do we need to move this code bellow and code by the link at OCM-Engine to separate project? (this files are the same)
+ */
+
+import {
+  JsonLdCredentialFormat,
+  JsonCredential,
+  JsonLdFormatDataCredentialDetail,
+  JsonLdFormatDataVerifiableCredential,
+  AgentContext,
+  CredentialFormatService,
+  Attachment,
+  AttachmentData,
+  AriesFrameworkError,
+  JsonEncoder,
+  JsonTransformer,
+  findVerificationMethodByKeyType,
+  DidResolverService,
+  ClaimFormat,
+  W3cCredential,
+  W3cCredentialService,
+  W3cJsonLdVerifiableCredential,
+  CredentialFormatSpec,
+  JsonLdCredentialDetail,
+} from "@aries-framework/core";
+import type {
+  CredentialFormatAcceptOfferOptions,
+  CredentialFormatAcceptProposalOptions,
+  CredentialFormatAcceptRequestOptions,
+  CredentialFormatAutoRespondOfferOptions,
+  CredentialFormatAutoRespondProposalOptions,
+  CredentialFormatAutoRespondRequestOptions,
+  CredentialFormatCreateOfferOptions,
+  CredentialFormatCreateOfferReturn,
+  CredentialFormatCreateProposalOptions,
+  CredentialFormatCreateProposalReturn,
+  CredentialFormatCreateRequestOptions,
+  CredentialFormatCreateReturn,
+  CredentialFormatProcessCredentialOptions,
+  CredentialFormatProcessOptions,
+  CredentialFormatAutoRespondCredentialOptions,
+} from "@aries-framework/core";
+import { areObjectsEqual } from "@aries-framework/core/build/utils";
+import { W3cJsonLdCredentialService } from "@aries-framework/core/build/modules/vc/data-integrity/W3cJsonLdCredentialService";
+
+const JSONLD_VC_DETAIL = "aries/ld-proof-vc-detail@v1.0";
+const JSONLD_VC = "aries/ld-proof-vc@v1.0";
+
+export class JsonLdCredentialFormatService
+  implements CredentialFormatService<JsonLdCredentialFormat>
+{
+  public readonly formatKey = "jsonld" as const;
+  public readonly credentialRecordType = "w3c" as const;
+
+  /**
+   * Create a {@link AttachmentFormats} object dependent on the message type.
+   *
+   * @param options The object containing all the options for the proposed credential
+   * @returns object containing associated attachment, formats and filtersAttach elements
+   *
+   */
+  public async createProposal(
+    agentContext: AgentContext,
+    {
+      credentialFormats,
+    }: CredentialFormatCreateProposalOptions<JsonLdCredentialFormat>,
+  ): Promise<CredentialFormatCreateProposalReturn> {
+    const format = new CredentialFormatSpec({
+      format: JSONLD_VC_DETAIL,
+    });
+
+    const jsonLdFormat = credentialFormats.jsonld;
+    if (!jsonLdFormat) {
+      throw new AriesFrameworkError("Missing jsonld payload in createProposal");
+    }
+
+    // this does the validation
+    JsonTransformer.fromJSON(jsonLdFormat.credential, JsonLdCredentialDetail);
+
+    // jsonLdFormat is now of type JsonLdFormatDataCredentialDetail
+    const attachment = this.getFormatData(jsonLdFormat, format.attachmentId);
+    return { format, attachment };
+  }
+
+  /**
+   * Method called on reception of a propose credential message
+   * @param options the options needed to accept the proposal
+   */
+  public async processProposal(
+    agentContext: AgentContext,
+    { attachment }: CredentialFormatProcessOptions,
+  ): Promise<void> {
+    const credProposalJson =
+      attachment.getDataAsJson<JsonLdFormatDataCredentialDetail>();
+
+    if (!credProposalJson) {
+      throw new AriesFrameworkError(
+        "Missing jsonld credential proposal data payload",
+      );
+    }
+
+    // validation is done in here
+    JsonTransformer.fromJSON(credProposalJson, JsonLdCredentialDetail);
+  }
+
+  public async acceptProposal(
+    agentContext: AgentContext,
+    {
+      attachmentId,
+      proposalAttachment,
+    }: CredentialFormatAcceptProposalOptions<JsonLdCredentialFormat>,
+  ): Promise<CredentialFormatCreateOfferReturn> {
+    // if the offer has an attachment Id use that, otherwise the generated id of the formats object
+    const format = new CredentialFormatSpec({
+      attachmentId,
+      format: JSONLD_VC_DETAIL,
+    });
+
+    const credentialProposal =
+      proposalAttachment.getDataAsJson<JsonLdFormatDataCredentialDetail>();
+    JsonTransformer.fromJSON(credentialProposal, JsonLdCredentialDetail);
+
+    const offerData = credentialProposal;
+
+    const attachment = this.getFormatData(offerData, format.attachmentId);
+
+    return { format, attachment };
+  }
+
+  /**
+   * Create a {@link AttachmentFormats} object dependent on the message type.
+   *
+   * @param options The object containing all the options for the credential offer
+   * @returns object containing associated attachment, formats and offersAttach elements
+   *
+   */
+  public async createOffer(
+    agentContext: AgentContext,
+    {
+      credentialFormats,
+      attachmentId,
+    }: CredentialFormatCreateOfferOptions<JsonLdCredentialFormat>,
+  ): Promise<CredentialFormatCreateOfferReturn> {
+    // if the offer has an attachment Id use that, otherwise the generated id of the formats object
+    const format = new CredentialFormatSpec({
+      attachmentId,
+      format: JSONLD_VC_DETAIL,
+    });
+
+    const jsonLdFormat = credentialFormats?.jsonld;
+    if (!jsonLdFormat) {
+      throw new AriesFrameworkError("Missing jsonld payload in createOffer");
+    }
+
+    // validate
+    JsonTransformer.fromJSON(jsonLdFormat.credential, JsonLdCredentialDetail);
+
+    const attachment = this.getFormatData(jsonLdFormat, format.attachmentId);
+
+    return { format, attachment };
+  }
+
+  public async processOffer(
+    agentContext: AgentContext,
+    { attachment }: CredentialFormatProcessOptions,
+  ) {
+    const credentialOfferJson =
+      attachment.getDataAsJson<JsonLdFormatDataCredentialDetail>();
+
+    if (!credentialOfferJson) {
+      throw new AriesFrameworkError(
+        "Missing jsonld credential offer data payload",
+      );
+    }
+
+    JsonTransformer.fromJSON(credentialOfferJson, JsonLdCredentialDetail);
+  }
+
+  public async acceptOffer(
+    agentContext: AgentContext,
+    {
+      attachmentId,
+      offerAttachment,
+    }: CredentialFormatAcceptOfferOptions<JsonLdCredentialFormat>,
+  ): Promise<CredentialFormatCreateReturn> {
+    const credentialOffer =
+      offerAttachment.getDataAsJson<JsonLdFormatDataCredentialDetail>();
+
+    // validate
+    JsonTransformer.fromJSON(credentialOffer, JsonLdCredentialDetail);
+
+    const format = new CredentialFormatSpec({
+      attachmentId,
+      format: JSONLD_VC_DETAIL,
+    });
+
+    const attachment = this.getFormatData(credentialOffer, format.attachmentId);
+    return { format, attachment };
+  }
+
+  /**
+   * Create a credential attachment format for a credential request.
+   *
+   * @param options The object containing all the options for the credential request is derived
+   * @returns object containing associated attachment, formats and requestAttach elements
+   *
+   */
+  public async createRequest(
+    agentContext: AgentContext,
+    {
+      credentialFormats,
+    }: CredentialFormatCreateRequestOptions<JsonLdCredentialFormat>,
+  ): Promise<CredentialFormatCreateReturn> {
+    const jsonLdFormat = credentialFormats?.jsonld;
+
+    const format = new CredentialFormatSpec({
+      format: JSONLD_VC_DETAIL,
+    });
+
+    if (!jsonLdFormat) {
+      throw new AriesFrameworkError("Missing jsonld payload in createRequest");
+    }
+
+    // this does the validation
+    JsonTransformer.fromJSON(jsonLdFormat.credential, JsonLdCredentialDetail);
+
+    const attachment = this.getFormatData(jsonLdFormat, format.attachmentId);
+
+    return { format, attachment };
+  }
+
+  public async processRequest(
+    agentContext: AgentContext,
+    { attachment }: CredentialFormatProcessOptions,
+  ): Promise<void> {
+    const requestJson =
+      attachment.getDataAsJson<JsonLdFormatDataCredentialDetail>();
+
+    if (!requestJson) {
+      throw new AriesFrameworkError(
+        "Missing jsonld credential request data payload",
+      );
+    }
+
+    // validate
+    JsonTransformer.fromJSON(requestJson, JsonLdCredentialDetail);
+  }
+
+  public async acceptRequest(
+    agentContext: AgentContext,
+    {
+      credentialFormats,
+      attachmentId,
+      requestAttachment,
+    }: CredentialFormatAcceptRequestOptions<JsonLdCredentialFormat>,
+  ): Promise<CredentialFormatCreateReturn> {
+    const w3cJsonLdCredentialService = agentContext.dependencyManager.resolve(
+      W3cJsonLdCredentialService,
+    );
+
+    // sign credential here. credential to be signed is received as the request attachment
+    // (attachment in the request message from holder to issuer)
+    const credentialRequest =
+      requestAttachment.getDataAsJson<JsonLdFormatDataCredentialDetail>();
+
+    const verificationMethod =
+      credentialFormats?.jsonld?.verificationMethod ??
+      (await this.deriveVerificationMethod(
+        agentContext,
+        credentialRequest.credential,
+        credentialRequest,
+      ));
+
+    if (!verificationMethod) {
+      throw new AriesFrameworkError(
+        "Missing verification method in credential data",
+      );
+    }
+    const format = new CredentialFormatSpec({
+      attachmentId,
+      format: JSONLD_VC,
+    });
+
+    const options = credentialRequest.options;
+
+    // Get a list of fields found in the options that are not supported at the moment
+    const unsupportedFields = [
+      "challenge",
+      "domain",
+      "credentialStatus",
+      "created",
+    ] as const;
+    const foundFields = unsupportedFields.filter(
+      (field) => options[field] !== undefined,
+    );
+
+    if (foundFields.length > 0) {
+      throw new AriesFrameworkError(
+        `Some fields are not currently supported in credential options: ${foundFields.join(
+          ", ",
+        )}`,
+      );
+    }
+
+    const credential = JsonTransformer.fromJSON(
+      credentialRequest.credential,
+      W3cCredential,
+    );
+
+    const verifiableCredential =
+      await w3cJsonLdCredentialService.signCredential(agentContext, {
+        format: ClaimFormat.LdpVc,
+        credential,
+        proofType: credentialRequest.options.proofType,
+        verificationMethod: verificationMethod,
+      });
+
+    const attachment = this.getFormatData(
+      JsonTransformer.toJSON(verifiableCredential),
+      format.attachmentId,
+    );
+    return { format, attachment };
+  }
+
+  /**
+   * Derive a verification method using the issuer from the given verifiable credential
+   * @param credentialAsJson the verifiable credential we want to sign
+   * @return the verification method derived from this credential and its associated issuer did, keys etc.
+   */
+  private async deriveVerificationMethod(
+    agentContext: AgentContext,
+    credentialAsJson: JsonCredential,
+    credentialRequest: JsonLdFormatDataCredentialDetail,
+  ): Promise<string> {
+    const didResolver =
+      agentContext.dependencyManager.resolve(DidResolverService);
+    const w3cJsonLdCredentialService = agentContext.dependencyManager.resolve(
+      W3cJsonLdCredentialService,
+    );
+
+    const credential = JsonTransformer.fromJSON(
+      credentialAsJson,
+      W3cCredential,
+    );
+
+    // extract issuer from vc (can be string or Issuer)
+    let issuerDid = credential.issuer;
+
+    if (typeof issuerDid !== "string") {
+      issuerDid = issuerDid.id;
+    }
+    // this will throw an error if the issuer did is invalid
+    const issuerDidDocument = await didResolver.resolveDidDocument(
+      agentContext,
+      issuerDid,
+    );
+
+    // find first key which matches proof type
+    const proofType = credentialRequest.options.proofType;
+
+    // actually gets the key type(s)
+    const keyType =
+      w3cJsonLdCredentialService.getVerificationMethodTypesByProofType(
+        proofType,
+      );
+
+    if (!keyType || keyType.length === 0) {
+      throw new AriesFrameworkError(
+        `No Key Type found for proofType ${proofType}`,
+      );
+    }
+
+    const verificationMethod = await findVerificationMethodByKeyType(
+      keyType[0],
+      issuerDidDocument,
+    );
+    if (!verificationMethod) {
+      throw new AriesFrameworkError(
+        `Missing verification method for key type ${keyType}`,
+      );
+    }
+
+    return verificationMethod.id;
+  }
+  /**
+   * Processes an incoming credential - retrieve metadata, retrieve payload and store it in the Indy wallet
+   * @param options the issue credential message wrapped inside this object
+   * @param credentialRecord the credential exchange record for this credential
+   */
+  public async processCredential(
+    agentContext: AgentContext,
+    {
+      credentialRecord,
+      attachment,
+      requestAttachment,
+    }: CredentialFormatProcessCredentialOptions,
+  ): Promise<void> {
+    const w3cCredentialService =
+      agentContext.dependencyManager.resolve(W3cCredentialService);
+
+    const credentialAsJson = attachment.getDataAsJson();
+    const credential = JsonTransformer.fromJSON(
+      credentialAsJson,
+      W3cJsonLdVerifiableCredential,
+    );
+    const requestAsJson =
+      requestAttachment.getDataAsJson<JsonLdFormatDataCredentialDetail>();
+
+    // Verify the credential request matches the credential
+    this.verifyReceivedCredentialMatchesRequest(credential, requestAsJson);
+
+    // verify signatures of the credential
+    const result = await w3cCredentialService.verifyCredential(agentContext, {
+      credential,
+    });
+    if (result && !result.isValid) {
+      throw new AriesFrameworkError(
+        `Failed to validate credential, error = ${result.error}`,
+      );
+    }
+
+    const verifiableCredential = await w3cCredentialService.storeCredential(
+      agentContext,
+      {
+        credential,
+      },
+    );
+
+    credentialRecord.credentials.push({
+      credentialRecordType: this.credentialRecordType,
+      credentialRecordId: verifiableCredential.id,
+    });
+  }
+
+  private verifyReceivedCredentialMatchesRequest(
+    credential: W3cJsonLdVerifiableCredential,
+    request: JsonLdFormatDataCredentialDetail,
+  ): void {
+    const jsonCredential = JsonTransformer.toJSON(credential);
+    delete jsonCredential["proof"];
+
+    const credentialProof = Array.isArray(credential.proof)
+      ? credential.proof[credential.proof.length - 1]
+      : credential.proof;
+
+    if (
+      request.options.created &&
+      credentialProof.created !== request.options.created
+    ) {
+      throw new AriesFrameworkError(
+        "Received credential proof created does not match created from credential request",
+      );
+    }
+
+    if (credentialProof.domain !== request.options.domain) {
+      throw new AriesFrameworkError(
+        "Received credential proof domain does not match domain from credential request",
+      );
+    }
+
+    if (credentialProof.challenge !== request.options.challenge) {
+      throw new AriesFrameworkError(
+        "Received credential proof challenge does not match challenge from credential request",
+      );
+    }
+
+    if (credentialProof.type !== request.options.proofType) {
+      throw new AriesFrameworkError(
+        "Received credential proof type does not match proof type from credential request",
+      );
+    }
+
+    if (credentialProof.proofPurpose !== request.options.proofPurpose) {
+      throw new AriesFrameworkError(
+        "Received credential proof purpose does not match proof purpose from credential request",
+      );
+    }
+
+    // Check whether the received credential (minus the proof) matches the credential request
+    const requestJsonCredential = JsonTransformer.toJSON(request.credential);
+    delete requestJsonCredential["proof"];
+    if (!areObjectsEqual(jsonCredential, requestJsonCredential)) {
+      throw new AriesFrameworkError(
+        "Received credential does not match credential request",
+      );
+    }
+
+    // TODO: add check for the credentialStatus once this is supported in Credo
+  }
+
+  public supportsFormat(format: string): boolean {
+    const supportedFormats = [JSONLD_VC_DETAIL, JSONLD_VC];
+
+    return supportedFormats.includes(format);
+  }
+
+  public async deleteCredentialById(): Promise<void> {
+    throw new Error("Not implemented.");
+  }
+
+  public areCredentialsEqual = (
+    message1: Attachment,
+    message2: Attachment,
+  ): boolean => {
+    const obj1 = message1.getDataAsJson();
+    const obj2 = message2.getDataAsJson();
+
+    return areObjectsEqual(obj1, obj2);
+  };
+
+  public async shouldAutoRespondToProposal(
+    agentContext: AgentContext,
+    {
+      offerAttachment,
+      proposalAttachment,
+    }: CredentialFormatAutoRespondProposalOptions,
+  ) {
+    return this.areCredentialsEqual(proposalAttachment, offerAttachment);
+  }
+
+  public async shouldAutoRespondToOffer(
+    agentContext: AgentContext,
+    {
+      offerAttachment,
+      proposalAttachment,
+    }: CredentialFormatAutoRespondOfferOptions,
+  ) {
+    return this.areCredentialsEqual(proposalAttachment, offerAttachment);
+  }
+
+  public async shouldAutoRespondToRequest(
+    agentContext: AgentContext,
+    {
+      offerAttachment,
+      requestAttachment,
+    }: CredentialFormatAutoRespondRequestOptions,
+  ) {
+    return this.areCredentialsEqual(offerAttachment, requestAttachment);
+  }
+
+  public async shouldAutoRespondToCredential(
+    agentContext: AgentContext,
+    {
+      requestAttachment,
+      credentialAttachment,
+    }: CredentialFormatAutoRespondCredentialOptions,
+  ) {
+    const credentialJson =
+      credentialAttachment.getDataAsJson<JsonLdFormatDataVerifiableCredential>();
+    const w3cCredential = JsonTransformer.fromJSON(
+      credentialJson,
+      W3cJsonLdVerifiableCredential,
+    );
+    const request =
+      requestAttachment.getDataAsJson<JsonLdFormatDataCredentialDetail>();
+
+    try {
+      // This check is also done in the processCredential method, but we do it here as well
+      // to be certain we don't skip the check
+      this.verifyReceivedCredentialMatchesRequest(w3cCredential, request);
+
+      return true;
+    } catch (error) {
+      return false;
+    }
+  }
+
+  /**
+   * Returns an object of type {@link Attachment} for use in credential exchange messages.
+   * It looks up the correct format identifier and encodes the data as a base64 attachment.
+   *
+   * @param data The data to include in the attach object
+   * @param id the attach id from the formats component of the message
+   */
+  private getFormatData(data: unknown, id: string): Attachment {
+    const attachment = new Attachment({
+      id,
+      mimeType: "application/json",
+      data: new AttachmentData({
+        base64: JsonEncoder.toBase64(data),
+      }),
+    });
+
+    return attachment;
+  }
+}
diff --git a/src/screens/CredentialDetails/CredentialDetailsStore.ts b/src/screens/CredentialDetails/CredentialDetailsStore.ts
index 400048b04f7b31aa3cd2017c3cc0d79cf866a3af..3c1741029cc632c022a7d97ed43f0270ad652cd0 100644
--- a/src/screens/CredentialDetails/CredentialDetailsStore.ts
+++ b/src/screens/CredentialDetails/CredentialDetailsStore.ts
@@ -1,6 +1,6 @@
 import {makeAutoObservable} from "mobx";
 import rootStore from "src/store/rootStore";
-import {CredentialState, ProofState} from "@aries-framework/core";
+import {CredentialState, GetCredentialFormatDataReturn, ProofState} from "@aries-framework/core";
 import {RecordHistory} from "src/type/record";
 import {
   CredentialExchangeRecord
@@ -13,6 +13,7 @@ class CredentialDetailsStore {
   public loading = true;
   public credentialId: string;
   private _credential: CredentialExchangeRecord | null = null;
+  public credentialFormatData: GetCredentialFormatDataReturn | null = null;
   public get credential(): CredentialExchangeRecord {
     return this._credential as CredentialExchangeRecord;
   }
@@ -28,6 +29,7 @@ class CredentialDetailsStore {
     this.credentialId = credentialId;
     this.history = [];
     this._credential = await rootStore.agentStore.agent.credentials.getById(credentialId);
+    this.credentialFormatData = await rootStore.agentStore.agent.credentials.getFormatData(credentialId);
     await this._loadHistory();
     this.loading = false;
   };
diff --git a/src/screens/CredentialDetails/index.tsx b/src/screens/CredentialDetails/index.tsx
index 0004a1f77e8b38a8a5ecc002c76408ee3f223f13..59a44b38843e191dd2711421083c1b2c53a04c32 100644
--- a/src/screens/CredentialDetails/index.tsx
+++ b/src/screens/CredentialDetails/index.tsx
@@ -13,6 +13,7 @@ import InfoSvg from 'src/assets/svg/info.svg';
 import ActivitiesSvg from 'src/assets/svg/activities.svg';
 import CredentialDetailsStore from "./CredentialDetailsStore";
 import Loader from "src/components/Loader";
+import JsonLdCredentialViewer from "src/components/jsonld/JsonLdCredentialViewer";
 
 type CredentialDetailsProps = StackScreenProps<
   CredentialStackParams,
@@ -52,6 +53,9 @@ const CredentialDetails: React.FC<CredentialDetailsProps> = observer(({
     );
   }
 
+
+  const jsonldCredential = store.credentialFormatData?.credential?.jsonld as any || null;
+
   return (
     <ScrollView contentContainerStyle={styles.scrollView}>
       <StatusBar barStyle="light-content" />
@@ -82,9 +86,13 @@ const CredentialDetails: React.FC<CredentialDetailsProps> = observer(({
               </View>
             );
           })}
+          {!!jsonldCredential && (
+            <JsonLdCredentialViewer jsonld={jsonldCredential} />
+          )}
         </View>
       </View>
 
+
       <View style={styles.card}>
         <View style={styles.header}>
           <ActivitiesSvg style={styles.headerIcon} />
@@ -181,4 +189,8 @@ const styles = StyleSheet.create({
   primaryColor: {
     color: ColorPallet.brand.primary,
   },
+  jsonld: {
+    ...TextTheme.normal,
+    color: ColorPallet.baseColors.black
+  },
 });
diff --git a/src/screens/CredentialOffer/index.tsx b/src/screens/CredentialOffer/index.tsx
index 2588e8330b51bcad390f86d503c99aeed4cf9ce2..2e9c77494c0d822a2ab1a093d0f95f6ec7dd8ac5 100644
--- a/src/screens/CredentialOffer/index.tsx
+++ b/src/screens/CredentialOffer/index.tsx
@@ -17,6 +17,7 @@ import Button, {ButtonType} from "src/components/Button";
 import Record from "src/components/Record";
 import Title from "src/components/Title";
 import {CredentialState} from "@aries-framework/core";
+import JsonLdCredentialViewer from "src/components/jsonld/JsonLdCredentialViewer";
 
 type CredentialOfferProps = StackScreenProps<
   NotificationStackParams,
@@ -66,8 +67,10 @@ const CredentialOffer: React.FC<CredentialOfferProps> = observer(({
     }
   }, [credential.state, connection]);
 
-
   const redirectToHome = () => navigation.getParent()?.navigate(Screens.Credentials);
+  const jsonLdData = store.credentialRecord?.offer?.jsonld as any || null;
+  const jsonldCredential = jsonLdData?.credential;
+
   return (
     <>
       <StatusBar barStyle="light-content" />
@@ -89,6 +92,11 @@ const CredentialOffer: React.FC<CredentialOfferProps> = observer(({
                 <CredentialCard credential={credential} />
               )}
             </View>
+            {!!jsonldCredential && (
+              <View style={styles.jsonldWrapper}>
+                <JsonLdCredentialViewer jsonld={jsonldCredential} />
+              </View>
+            )}
           </>
         )}
         footer={() => (
@@ -183,4 +191,7 @@ const styles = StyleSheet.create({
     paddingTop: 10,
     backgroundColor: ColorPallet.grayscale.white,
   },
+  jsonldWrapper: {
+    paddingHorizontal: 16,
+  }
 });
diff --git a/src/store/AgentStore.ts b/src/store/AgentStore.ts
index 41f4a2a1d364f37b7c1518911efeb007a1fcece7..2e38386e67dc9c01d7d705b9ce0f3e7b26e3b763 100644
--- a/src/store/AgentStore.ts
+++ b/src/store/AgentStore.ts
@@ -22,6 +22,8 @@ import {
   ProofsModule,
   V2CredentialProtocol,
   V2ProofProtocol,
+  W3cCredentialService,
+  W3cCredentialsModule,
   WsOutboundTransport,
 } from "@aries-framework/core";
 import { agentDependencies } from "@aries-framework/react-native";
@@ -79,6 +81,7 @@ import TrustedEmailSender from "../db-models/TrustedEmailSender";
 import axios from "axios";
 import { NativeModules } from "react-native";
 import { addHours } from "date-fns";
+import { JsonLdCredentialFormatService } from "../credo/JsonLdCredentialFormatService";
 
 const { VereignImapModule } = NativeModules;
 
@@ -162,6 +165,7 @@ class AgentStore {
             credentialFormats: [
               legacyIndyCredentialFormatService,
               new AnonCredsCredentialFormatService(),
+              new JsonLdCredentialFormatService()
             ],
           }),
         ],
@@ -211,6 +215,7 @@ class AgentStore {
         // mediatorPickupStrategy: MediatorPickupStrategy.Implicit,
         mediatorInvitationUrl: Config.MEDIATOR_URL,
       }),
+      w3c: new W3cCredentialsModule()
     };
 
     const newAgent = new Agent({
@@ -219,6 +224,12 @@ class AgentStore {
       modules,
     });
 
+    const w3cCredentialService = newAgent.context.dependencyManager.resolve(W3cCredentialService);
+    // TODO Hack dor demo purpose
+    // @ts-ignore
+    w3cCredentialService.verifyCredential = () => ({ isValid: true })
+
+
     newAgent.registerOutboundTransport(new WsOutboundTransport());
     newAgent.registerOutboundTransport(new HttpOutboundTransport());
 
diff --git a/src/utils/helpers.ts b/src/utils/helpers.ts
index b5ebca362f5f5044a78d50f59e5eaca5aa2af32f..085cfd8139199a6c1bffb661fbd7185cda65187b 100644
--- a/src/utils/helpers.ts
+++ b/src/utils/helpers.ts
@@ -78,6 +78,9 @@ export function parsedCredentialDefinition(
 }
 
 export function hashCode(s: string): number {
+  if (!s) {
+    return 0;
+  }
   return s
     .split('')
     .reduce((hash, char) => char.charCodeAt(0) + ((hash << 5) - hash), 0);