From 1d4f2ac197d20fb3d2212a20e26bcccf74a101bb Mon Sep 17 00:00:00 2001
From: Aleksei Lunin <alexey.lunin@vereign.com>
Date: Mon, 30 Oct 2023 10:20:48 +0300
Subject: [PATCH] add Auth page

---
 apps/dashboard/src/api/agent-client.ts        |  77 ++++++---
 apps/dashboard/src/api/gateway-client.ts      | 148 +++++++++++++-----
 apps/dashboard/src/api/index.ts               |  38 ++++-
 apps/dashboard/src/components/App/index.tsx   |  22 ++-
 .../src/components/BasicMessageItem/index.tsx |   7 +-
 .../BasicMessageItem/styles.module.scss       |   2 +-
 .../BasicMessageList/BasicMessageListStore.ts |  21 +++
 .../BasicMessageList/CreateMessage/index.tsx  |  42 +++++
 .../src/components/BasicMessageList/index.tsx |  25 ++-
 .../src/components/ProofItem/index.tsx        |  12 +-
 .../components/ProofList/ProofListStore.ts    |   2 +-
 .../src/components/Sidebar/index.tsx          |   3 +
 apps/dashboard/src/main.tsx                   |   9 +-
 .../index.tsx                                 |  81 ++++++++++
 .../styles.module.scss                        |   4 +
 .../modals/IssueCredentialDialog/index.tsx    |  10 +-
 .../RequestProofDialogStore.ts}               |  12 +-
 .../index.tsx                                 |  33 ++--
 .../styles.module.scss                        |   0
 .../ViewConnectionlessProofRequest/index.tsx  |  68 ++++++++
 .../styles.module.scss                        |  46 ++++++
 apps/dashboard/src/routes/config.ts           |   6 +
 .../src/routes/pages/AuthPage/Login.tsx       |  50 ++++++
 .../src/routes/pages/AuthPage/LoginStore.ts   |  61 ++++++++
 .../src/routes/pages/AuthPage/Register.tsx    |  50 ++++++
 .../routes/pages/AuthPage/RegisterStore.ts    |  63 ++++++++
 .../src/routes/pages/AuthPage/index.tsx       |  34 ++++
 .../pages/ConnectionCreatePage/index.tsx      |  16 +-
 .../routes/pages/ConnectionViewPage/index.tsx |   6 +-
 .../src/routes/pages/ProofListPage/index.tsx  |  30 ++++
 apps/dashboard/src/store/modalStore.tsx       |  47 +++---
 31 files changed, 876 insertions(+), 149 deletions(-)
 create mode 100644 apps/dashboard/src/components/BasicMessageList/CreateMessage/index.tsx
 create mode 100644 apps/dashboard/src/modals/AcceptConnectionlessProofRequestDialog/index.tsx
 create mode 100644 apps/dashboard/src/modals/AcceptConnectionlessProofRequestDialog/styles.module.scss
 rename apps/dashboard/src/modals/{IssueProofRequestDialog/IssueProofRequestDialog.ts => RequestProofDialog/RequestProofDialogStore.ts} (93%)
 rename apps/dashboard/src/modals/{IssueProofRequestDialog => RequestProofDialog}/index.tsx (72%)
 rename apps/dashboard/src/modals/{IssueProofRequestDialog => RequestProofDialog}/styles.module.scss (100%)
 create mode 100644 apps/dashboard/src/modals/ViewConnectionlessProofRequest/index.tsx
 create mode 100644 apps/dashboard/src/modals/ViewConnectionlessProofRequest/styles.module.scss
 create mode 100644 apps/dashboard/src/routes/pages/AuthPage/Login.tsx
 create mode 100644 apps/dashboard/src/routes/pages/AuthPage/LoginStore.ts
 create mode 100644 apps/dashboard/src/routes/pages/AuthPage/Register.tsx
 create mode 100644 apps/dashboard/src/routes/pages/AuthPage/RegisterStore.ts
 create mode 100644 apps/dashboard/src/routes/pages/AuthPage/index.tsx

diff --git a/apps/dashboard/src/api/agent-client.ts b/apps/dashboard/src/api/agent-client.ts
index 91caad7e..e6fcf21b 100644
--- a/apps/dashboard/src/api/agent-client.ts
+++ b/apps/dashboard/src/api/agent-client.ts
@@ -404,7 +404,7 @@ export class RestControllerClient {
         return Promise.resolve<CreddefRecordDto>(null as any);
     }
 
-    issueCredential(body: IssueCredentialRequestDto): Promise<CredentialRecordDto> {
+    issueCredential(body: IssueCredentialRequestDto): Promise<CredentialIssueResponseDto> {
         let url_ = this.baseUrl + "/api/v1/credentials/issue";
         url_ = url_.replace(/[?&]$/, "");
 
@@ -424,13 +424,13 @@ export class RestControllerClient {
         });
     }
 
-    protected processIssueCredential(response: Response): Promise<CredentialRecordDto> {
+    protected processIssueCredential(response: Response): Promise<CredentialIssueResponseDto> {
         const status = response.status;
         let _headers: any = {}; if (response.headers && response.headers.forEach) { response.headers.forEach((v: any, k: any) => _headers[k] = v); };
         if (status === 201) {
             return response.text().then((_responseText) => {
             let result201: any = null;
-            result201 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver) as CredentialRecordDto;
+            result201 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver) as CredentialIssueResponseDto;
             return result201;
             });
         } else if (status !== 200 && status !== 204) {
@@ -438,7 +438,7 @@ export class RestControllerClient {
             return throwException("An unexpected server error occurred.", status, _responseText, _headers);
             });
         }
-        return Promise.resolve<CredentialRecordDto>(null as any);
+        return Promise.resolve<CredentialIssueResponseDto>(null as any);
     }
 
     credentials(): Promise<CredentialRecordDto[]> {
@@ -511,7 +511,7 @@ export class RestControllerClient {
         return Promise.resolve<CredentialRecordDto[]>(null as any);
     }
 
-    getCredentialById(id: string): Promise<any> {
+    getCredentialById(id: string): Promise<CredentialRecordDto> {
         let url_ = this.baseUrl + "/api/v1/credentials/{id}";
         if (id === undefined || id === null)
             throw new Error("The parameter 'id' must be defined.");
@@ -530,13 +530,13 @@ export class RestControllerClient {
         });
     }
 
-    protected processGetCredentialById(response: Response): Promise<any> {
+    protected processGetCredentialById(response: Response): Promise<CredentialRecordDto> {
         const status = response.status;
         let _headers: any = {}; if (response.headers && response.headers.forEach) { response.headers.forEach((v: any, k: any) => _headers[k] = v); };
         if (status === 200) {
             return response.text().then((_responseText) => {
             let result200: any = null;
-            result200 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver) as any;
+            result200 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver) as CredentialRecordDto;
             return result200;
             });
         } else if (status !== 200 && status !== 204) {
@@ -544,7 +544,7 @@ export class RestControllerClient {
             return throwException("An unexpected server error occurred.", status, _responseText, _headers);
             });
         }
-        return Promise.resolve<any>(null as any);
+        return Promise.resolve<CredentialRecordDto>(null as any);
     }
 
     deleteCredentialById(id: string): Promise<void> {
@@ -931,7 +931,7 @@ export class RestControllerClient {
         return Promise.resolve<void>(null as any);
     }
 
-    issueProof(body: IssueProofRequestDto): Promise<any> {
+    issueProof(body: IssueProofRequestDto): Promise<ProofIssueResponseDto> {
         let url_ = this.baseUrl + "/api/v1/credentials/proof/issue";
         url_ = url_.replace(/[?&]$/, "");
 
@@ -951,13 +951,13 @@ export class RestControllerClient {
         });
     }
 
-    protected processIssueProof(response: Response): Promise<any> {
+    protected processIssueProof(response: Response): Promise<ProofIssueResponseDto> {
         const status = response.status;
         let _headers: any = {}; if (response.headers && response.headers.forEach) { response.headers.forEach((v: any, k: any) => _headers[k] = v); };
         if (status === 201) {
             return response.text().then((_responseText) => {
             let result201: any = null;
-            result201 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver) as any;
+            result201 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver) as ProofIssueResponseDto;
             return result201;
             });
         } else if (status !== 200 && status !== 204) {
@@ -965,10 +965,10 @@ export class RestControllerClient {
             return throwException("An unexpected server error occurred.", status, _responseText, _headers);
             });
         }
-        return Promise.resolve<any>(null as any);
+        return Promise.resolve<ProofIssueResponseDto>(null as any);
     }
 
-    acceptProof(body: ProofReqDto): Promise<any> {
+    acceptProof(body: ProofReqDto): Promise<ProofRecordDto> {
         let url_ = this.baseUrl + "/api/v1/credentials/proof/accept";
         url_ = url_.replace(/[?&]$/, "");
 
@@ -988,13 +988,13 @@ export class RestControllerClient {
         });
     }
 
-    protected processAcceptProof(response: Response): Promise<any> {
+    protected processAcceptProof(response: Response): Promise<ProofRecordDto> {
         const status = response.status;
         let _headers: any = {}; if (response.headers && response.headers.forEach) { response.headers.forEach((v: any, k: any) => _headers[k] = v); };
         if (status === 201) {
             return response.text().then((_responseText) => {
             let result201: any = null;
-            result201 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver) as any;
+            result201 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver) as ProofRecordDto;
             return result201;
             });
         } else if (status !== 200 && status !== 204) {
@@ -1002,7 +1002,7 @@ export class RestControllerClient {
             return throwException("An unexpected server error occurred.", status, _responseText, _headers);
             });
         }
-        return Promise.resolve<any>(null as any);
+        return Promise.resolve<ProofRecordDto>(null as any);
     }
 
     declineProofRequest(proof_record_id: string): Promise<ProofRecordDto> {
@@ -1150,7 +1150,7 @@ export interface IssueCredentialAttributes {
 }
 
 export interface IssueCredentialRequestDto {
-    connectionId: string;
+    connectionId?: string;
     credentialDefinitionId: string;
     attributes: IssueCredentialAttributes[];
 
@@ -1169,6 +1169,14 @@ export interface CredentialRecordDto {
     [key: string]: any;
 }
 
+export interface CredentialIssueResponseDto {
+    credentialUrl: string | null;
+    shortCredentialUrl: string | null;
+    credentialRecord: CredentialRecordDto;
+
+    [key: string]: any;
+}
+
 export interface CredentialFilterDto {
     states?: States[];
     connectionId?: string;
@@ -1178,16 +1186,18 @@ export interface CredentialFilterDto {
 
 export interface MakeBasicMessageRequestDto {
     connectionId: string;
-    message: string;
+    content: string;
 
     [key: string]: any;
 }
 
 export interface MessageRecordDto {
     connectionId: string;
+    role: MessageRecordDtoRole;
+    sentTime: string;
     from?: string;
     to?: string;
-    message: string;
+    content: string;
     id: string;
     createdAt: Date;
     updatedAt?: Date;
@@ -1204,7 +1214,7 @@ export interface MessageFilterDto {
 
 export interface ProofRecordDto {
     connectionId?: string;
-    state: string;
+    state: ProofRecordDtoState;
     id: string;
     createdAt: Date;
     updatedAt?: Date;
@@ -1235,8 +1245,16 @@ export interface IssueProofRequestDto {
     [key: string]: any;
 }
 
+export interface ProofIssueResponseDto {
+    proofUrl: string | null;
+    shortProofUrl: string | null;
+    proofRecord: ProofRecordDto;
+
+    [key: string]: any;
+}
+
 export interface ProofReqDto {
-    proofRecordId: string;
+    proofId: string;
     proofUrl: string;
 
     [key: string]: any;
@@ -1270,11 +1288,28 @@ export enum States {
     Abandoned = "abandoned",
 }
 
+export enum MessageRecordDtoRole {
+    Sender = "sender",
+    Receiver = "receiver",
+}
+
 export enum MessageFilterDtoRole {
     Sender = "sender",
     Receiver = "receiver",
 }
 
+export enum ProofRecordDtoState {
+    ProposalSent = "proposal-sent",
+    ProposalReceived = "proposal-received",
+    RequestSent = "request-sent",
+    RequestReceived = "request-received",
+    PresentationSent = "presentation-sent",
+    PresentationReceived = "presentation-received",
+    Declined = "declined",
+    Abandoned = "abandoned",
+    Done = "done",
+}
+
 export enum States2 {
     ProposalSent = "proposal-sent",
     ProposalReceived = "proposal-received",
diff --git a/apps/dashboard/src/api/gateway-client.ts b/apps/dashboard/src/api/gateway-client.ts
index cbc879c4..cd58bbf3 100644
--- a/apps/dashboard/src/api/gateway-client.ts
+++ b/apps/dashboard/src/api/gateway-client.ts
@@ -41,7 +41,13 @@ export class ConnectionControllerClient {
     protected processCreateInvitation(response: Response): Promise<GatewayAcceptedResponseDto> {
         const status = response.status;
         let _headers: any = {}; if (response.headers && response.headers.forEach) { response.headers.forEach((v: any, k: any) => _headers[k] = v); };
-        if (status === 201) {
+        if (status === 200) {
+            return response.text().then((_responseText) => {
+            let result200: any = null;
+            result200 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver) as GatewayAcceptedResponseDto;
+            return result200;
+            });
+        } else if (status === 201) {
             return response.text().then((_responseText) => {
             let result201: any = null;
             result201 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver) as GatewayAcceptedResponseDto;
@@ -88,7 +94,13 @@ export class ConnectionControllerClient {
     protected processAcceptInvitation(response: Response): Promise<GatewayAcceptedResponseDto> {
         const status = response.status;
         let _headers: any = {}; if (response.headers && response.headers.forEach) { response.headers.forEach((v: any, k: any) => _headers[k] = v); };
-        if (status === 201) {
+        if (status === 200) {
+            return response.text().then((_responseText) => {
+            let result200: any = null;
+            result200 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver) as GatewayAcceptedResponseDto;
+            return result200;
+            });
+        } else if (status === 201) {
             return response.text().then((_responseText) => {
             let result201: any = null;
             result201 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver) as GatewayAcceptedResponseDto;
@@ -137,7 +149,7 @@ export class ConnectionControllerClient {
     protected processList(response: Response): Promise<GatewayAcceptedResponseDto> {
         const status = response.status;
         let _headers: any = {}; if (response.headers && response.headers.forEach) { response.headers.forEach((v: any, k: any) => _headers[k] = v); };
-        if (status === 200 || status === 201) {
+        if (status === 200) {
             return response.text().then((_responseText) => {
             let result200: any = null;
             result200 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver) as GatewayAcceptedResponseDto;
@@ -183,7 +195,7 @@ export class ConnectionControllerClient {
     protected processGetConnectionById(response: Response): Promise<GatewayAcceptedResponseDto> {
         const status = response.status;
         let _headers: any = {}; if (response.headers && response.headers.forEach) { response.headers.forEach((v: any, k: any) => _headers[k] = v); };
-        if (status === 200 || status === 201) {
+        if (status === 200) {
             return response.text().then((_responseText) => {
             let result200: any = null;
             result200 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver) as GatewayAcceptedResponseDto;
@@ -229,7 +241,7 @@ export class ConnectionControllerClient {
     protected processDeleteConnectionById(response: Response): Promise<GatewayAcceptedResponseDto> {
         const status = response.status;
         let _headers: any = {}; if (response.headers && response.headers.forEach) { response.headers.forEach((v: any, k: any) => _headers[k] = v); };
-        if (status === 200 || status === 201) {
+        if (status === 200) {
             return response.text().then((_responseText) => {
             let result200: any = null;
             result200 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver) as GatewayAcceptedResponseDto;
@@ -287,7 +299,13 @@ export class AttestationControllerClient {
     protected processCreateSchema(response: Response): Promise<GatewayAcceptedResponseDto> {
         const status = response.status;
         let _headers: any = {}; if (response.headers && response.headers.forEach) { response.headers.forEach((v: any, k: any) => _headers[k] = v); };
-        if (status === 201) {
+        if (status === 200) {
+            return response.text().then((_responseText) => {
+            let result200: any = null;
+            result200 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver) as GatewayAcceptedResponseDto;
+            return result200;
+            });
+        } else if (status === 201) {
             return response.text().then((_responseText) => {
             let result201: any = null;
             result201 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver) as GatewayAcceptedResponseDto;
@@ -336,7 +354,7 @@ export class AttestationControllerClient {
     protected processListSchema(response: Response): Promise<GatewayAcceptedResponseDto> {
         const status = response.status;
         let _headers: any = {}; if (response.headers && response.headers.forEach) { response.headers.forEach((v: any, k: any) => _headers[k] = v); };
-        if (status === 200 || status === 201) {
+        if (status === 200) {
             return response.text().then((_responseText) => {
             let result200: any = null;
             result200 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver) as GatewayAcceptedResponseDto;
@@ -383,7 +401,13 @@ export class AttestationControllerClient {
     protected processGetSchemaById(response: Response): Promise<GatewayAcceptedResponseDto> {
         const status = response.status;
         let _headers: any = {}; if (response.headers && response.headers.forEach) { response.headers.forEach((v: any, k: any) => _headers[k] = v); };
-        if (status === 201) {
+        if (status === 200) {
+            return response.text().then((_responseText) => {
+            let result200: any = null;
+            result200 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver) as GatewayAcceptedResponseDto;
+            return result200;
+            });
+        } else if (status === 201) {
             return response.text().then((_responseText) => {
             let result201: any = null;
             result201 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver) as GatewayAcceptedResponseDto;
@@ -432,7 +456,7 @@ export class AttestationControllerClient {
     protected processCredentialDefinitions(response: Response): Promise<GatewayAcceptedResponseDto> {
         const status = response.status;
         let _headers: any = {}; if (response.headers && response.headers.forEach) { response.headers.forEach((v: any, k: any) => _headers[k] = v); };
-        if (status === 200 || status === 201) {
+        if (status === 200) {
             return response.text().then((_responseText) => {
             let result200: any = null;
             result200 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver) as GatewayAcceptedResponseDto;
@@ -479,7 +503,13 @@ export class AttestationControllerClient {
     protected processGetCredentialDefinitionsById(response: Response): Promise<GatewayAcceptedResponseDto> {
         const status = response.status;
         let _headers: any = {}; if (response.headers && response.headers.forEach) { response.headers.forEach((v: any, k: any) => _headers[k] = v); };
-        if (status === 201) {
+        if (status === 200) {
+            return response.text().then((_responseText) => {
+            let result200: any = null;
+            result200 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver) as GatewayAcceptedResponseDto;
+            return result200;
+            });
+        } else if (status === 201) {
             return response.text().then((_responseText) => {
             let result201: any = null;
             result201 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver) as GatewayAcceptedResponseDto;
@@ -532,7 +562,13 @@ export class AttestationControllerClient {
     protected processCreateCredentialDefinition(response: Response): Promise<GatewayAcceptedResponseDto> {
         const status = response.status;
         let _headers: any = {}; if (response.headers && response.headers.forEach) { response.headers.forEach((v: any, k: any) => _headers[k] = v); };
-        if (status === 201) {
+        if (status === 200) {
+            return response.text().then((_responseText) => {
+            let result200: any = null;
+            result200 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver) as GatewayAcceptedResponseDto;
+            return result200;
+            });
+        } else if (status === 201) {
             return response.text().then((_responseText) => {
             let result201: any = null;
             result201 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver) as GatewayAcceptedResponseDto;
@@ -585,7 +621,13 @@ export class AttestationControllerClient {
     protected processIssueCredential(response: Response): Promise<GatewayAcceptedResponseDto> {
         const status = response.status;
         let _headers: any = {}; if (response.headers && response.headers.forEach) { response.headers.forEach((v: any, k: any) => _headers[k] = v); };
-        if (status === 201) {
+        if (status === 200) {
+            return response.text().then((_responseText) => {
+            let result200: any = null;
+            result200 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver) as GatewayAcceptedResponseDto;
+            return result200;
+            });
+        } else if (status === 201) {
             return response.text().then((_responseText) => {
             let result201: any = null;
             result201 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver) as GatewayAcceptedResponseDto;
@@ -634,7 +676,7 @@ export class AttestationControllerClient {
     protected processCredentials(response: Response): Promise<GatewayAcceptedResponseDto> {
         const status = response.status;
         let _headers: any = {}; if (response.headers && response.headers.forEach) { response.headers.forEach((v: any, k: any) => _headers[k] = v); };
-        if (status === 200 || status === 201) {
+        if (status === 200) {
             return response.text().then((_responseText) => {
             let result200: any = null;
             result200 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver) as GatewayAcceptedResponseDto;
@@ -681,7 +723,7 @@ export class AttestationControllerClient {
     protected processCredentialsQuery(response: Response): Promise<GatewayAcceptedResponseDto> {
         const status = response.status;
         let _headers: any = {}; if (response.headers && response.headers.forEach) { response.headers.forEach((v: any, k: any) => _headers[k] = v); };
-        if (status === 200 || status === 201) {
+        if (status === 200) {
             return response.text().then((_responseText) => {
             let result200: any = null;
             result200 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver) as GatewayAcceptedResponseDto;
@@ -689,7 +731,9 @@ export class AttestationControllerClient {
             });
         } else if (status === 201) {
             return response.text().then((_responseText) => {
-            return throwException("A server side error occurred.", status, _responseText, _headers);
+            let result201: any = null;
+            result201 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver) as GatewayAcceptedResponseDto;
+            return result201;
             });
         } else if (status === 500) {
             return response.text().then((_responseText) => {
@@ -731,7 +775,7 @@ export class AttestationControllerClient {
     protected processGetCredentialById(response: Response): Promise<GatewayAcceptedResponseDto> {
         const status = response.status;
         let _headers: any = {}; if (response.headers && response.headers.forEach) { response.headers.forEach((v: any, k: any) => _headers[k] = v); };
-        if (status === 200 || status === 201) {
+        if (status === 200) {
             return response.text().then((_responseText) => {
             let result200: any = null;
             result200 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver) as GatewayAcceptedResponseDto;
@@ -783,7 +827,7 @@ export class AttestationControllerClient {
     protected processDeleteCredentialById(response: Response): Promise<GatewayAcceptedResponseDto> {
         const status = response.status;
         let _headers: any = {}; if (response.headers && response.headers.forEach) { response.headers.forEach((v: any, k: any) => _headers[k] = v); };
-        if (status === 200 || status === 201) {
+        if (status === 200) {
             return response.text().then((_responseText) => {
             let result200: any = null;
             result200 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver) as GatewayAcceptedResponseDto;
@@ -832,7 +876,7 @@ export class AttestationControllerClient {
     protected processGetCredentialOffers(response: Response): Promise<GatewayAcceptedResponseDto> {
         const status = response.status;
         let _headers: any = {}; if (response.headers && response.headers.forEach) { response.headers.forEach((v: any, k: any) => _headers[k] = v); };
-        if (status === 200 || status === 201) {
+        if (status === 200) {
             return response.text().then((_responseText) => {
             let result200: any = null;
             result200 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver) as GatewayAcceptedResponseDto;
@@ -878,7 +922,7 @@ export class AttestationControllerClient {
     protected processAcceptCredential(response: Response): Promise<GatewayAcceptedResponseDto> {
         const status = response.status;
         let _headers: any = {}; if (response.headers && response.headers.forEach) { response.headers.forEach((v: any, k: any) => _headers[k] = v); };
-        if (status === 200 || status === 201) {
+        if (status === 200) {
             return response.text().then((_responseText) => {
             let result200: any = null;
             result200 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver) as GatewayAcceptedResponseDto;
@@ -886,7 +930,9 @@ export class AttestationControllerClient {
             });
         } else if (status === 201) {
             return response.text().then((_responseText) => {
-            return throwException("A server side error occurred.", status, _responseText, _headers);
+            let result201: any = null;
+            result201 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver) as GatewayAcceptedResponseDto;
+            return result201;
             });
         } else if (status === 500) {
             return response.text().then((_responseText) => {
@@ -928,7 +974,7 @@ export class AttestationControllerClient {
     protected processDeclineCredential(response: Response): Promise<GatewayAcceptedResponseDto> {
         const status = response.status;
         let _headers: any = {}; if (response.headers && response.headers.forEach) { response.headers.forEach((v: any, k: any) => _headers[k] = v); };
-        if (status === 200 || status === 201) {
+        if (status === 200) {
             return response.text().then((_responseText) => {
             let result200: any = null;
             result200 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver) as GatewayAcceptedResponseDto;
@@ -936,7 +982,9 @@ export class AttestationControllerClient {
             });
         } else if (status === 201) {
             return response.text().then((_responseText) => {
-            return throwException("A server side error occurred.", status, _responseText, _headers);
+            let result201: any = null;
+            result201 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver) as GatewayAcceptedResponseDto;
+            return result201;
             });
         } else if (status === 500) {
             return response.text().then((_responseText) => {
@@ -979,7 +1027,7 @@ export class AttestationControllerClient {
     protected processSendMessage(response: Response): Promise<GatewayAcceptedResponseDto> {
         const status = response.status;
         let _headers: any = {}; if (response.headers && response.headers.forEach) { response.headers.forEach((v: any, k: any) => _headers[k] = v); };
-        if (status === 200 || status === 201) {
+        if (status === 200) {
             return response.text().then((_responseText) => {
             let result200: any = null;
             result200 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver) as GatewayAcceptedResponseDto;
@@ -987,7 +1035,9 @@ export class AttestationControllerClient {
             });
         } else if (status === 201) {
             return response.text().then((_responseText) => {
-            return throwException("A server side error occurred.", status, _responseText, _headers);
+            let result201: any = null;
+            result201 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver) as GatewayAcceptedResponseDto;
+            return result201;
             });
         } else if (status === 400) {
             return response.text().then((_responseText) => {
@@ -1036,7 +1086,7 @@ export class AttestationControllerClient {
     protected processQueryMessages(response: Response): Promise<GatewayAcceptedResponseDto> {
         const status = response.status;
         let _headers: any = {}; if (response.headers && response.headers.forEach) { response.headers.forEach((v: any, k: any) => _headers[k] = v); };
-        if (status === 200 || status === 201) {
+        if (status === 200) {
             return response.text().then((_responseText) => {
             let result200: any = null;
             result200 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver) as GatewayAcceptedResponseDto;
@@ -1044,7 +1094,9 @@ export class AttestationControllerClient {
             });
         } else if (status === 201) {
             return response.text().then((_responseText) => {
-            return throwException("A server side error occurred.", status, _responseText, _headers);
+            let result201: any = null;
+            result201 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver) as GatewayAcceptedResponseDto;
+            return result201;
             });
         } else if (status === 400) {
             return response.text().then((_responseText) => {
@@ -1092,7 +1144,7 @@ export class AttestationControllerClient {
     protected processDeleteMessage(response: Response): Promise<GatewayAcceptedResponseDto> {
         const status = response.status;
         let _headers: any = {}; if (response.headers && response.headers.forEach) { response.headers.forEach((v: any, k: any) => _headers[k] = v); };
-        if (status === 200 || status === 201) {
+        if (status === 200) {
             return response.text().then((_responseText) => {
             let result200: any = null;
             result200 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver) as GatewayAcceptedResponseDto;
@@ -1152,7 +1204,7 @@ export class ProofControllerClient {
     protected processProofs(response: Response): Promise<GatewayAcceptedResponseDto> {
         const status = response.status;
         let _headers: any = {}; if (response.headers && response.headers.forEach) { response.headers.forEach((v: any, k: any) => _headers[k] = v); };
-        if (status === 200 || status === 201) {
+        if (status === 200) {
             return response.text().then((_responseText) => {
             let result200: any = null;
             result200 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver) as GatewayAcceptedResponseDto;
@@ -1199,7 +1251,7 @@ export class ProofControllerClient {
     protected processProofsQuery(response: Response): Promise<GatewayAcceptedResponseDto> {
         const status = response.status;
         let _headers: any = {}; if (response.headers && response.headers.forEach) { response.headers.forEach((v: any, k: any) => _headers[k] = v); };
-        if (status === 200 || status === 201) {
+        if (status === 200) {
             return response.text().then((_responseText) => {
             let result200: any = null;
             result200 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver) as GatewayAcceptedResponseDto;
@@ -1207,7 +1259,9 @@ export class ProofControllerClient {
             });
         } else if (status === 201) {
             return response.text().then((_responseText) => {
-            return throwException("A server side error occurred.", status, _responseText, _headers);
+            let result201: any = null;
+            result201 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver) as GatewayAcceptedResponseDto;
+            return result201;
             });
         } else if (status === 500) {
             return response.text().then((_responseText) => {
@@ -1249,7 +1303,7 @@ export class ProofControllerClient {
     protected processGetProofById(response: Response): Promise<GatewayAcceptedResponseDto> {
         const status = response.status;
         let _headers: any = {}; if (response.headers && response.headers.forEach) { response.headers.forEach((v: any, k: any) => _headers[k] = v); };
-        if (status === 200 || status === 201) {
+        if (status === 200) {
             return response.text().then((_responseText) => {
             let result200: any = null;
             result200 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver) as GatewayAcceptedResponseDto;
@@ -1295,7 +1349,7 @@ export class ProofControllerClient {
     protected processDeleteProofById(response: Response): Promise<GatewayAcceptedResponseDto> {
         const status = response.status;
         let _headers: any = {}; if (response.headers && response.headers.forEach) { response.headers.forEach((v: any, k: any) => _headers[k] = v); };
-        if (status === 200 || status === 201) {
+        if (status === 200) {
             return response.text().then((_responseText) => {
             let result200: any = null;
             result200 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver) as GatewayAcceptedResponseDto;
@@ -1316,7 +1370,7 @@ export class ProofControllerClient {
     }
 
     /**
-     * Request proof for credential
+     * Issue proof for credential
      * @return Request is accepted for execution, the response id will match the event id received from the web socket
      */
     issueProof(body: IssueProofRequestDto): Promise<GatewayAcceptedResponseDto> {
@@ -1342,7 +1396,13 @@ export class ProofControllerClient {
     protected processIssueProof(response: Response): Promise<GatewayAcceptedResponseDto> {
         const status = response.status;
         let _headers: any = {}; if (response.headers && response.headers.forEach) { response.headers.forEach((v: any, k: any) => _headers[k] = v); };
-        if (status === 201) {
+        if (status === 200) {
+            return response.text().then((_responseText) => {
+            let result200: any = null;
+            result200 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver) as GatewayAcceptedResponseDto;
+            return result200;
+            });
+        } else if (status === 201) {
             return response.text().then((_responseText) => {
             let result201: any = null;
             result201 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver) as GatewayAcceptedResponseDto;
@@ -1395,7 +1455,13 @@ export class ProofControllerClient {
     protected processAcceptProof(response: Response): Promise<GatewayAcceptedResponseDto> {
         const status = response.status;
         let _headers: any = {}; if (response.headers && response.headers.forEach) { response.headers.forEach((v: any, k: any) => _headers[k] = v); };
-        if (status === 201) {
+        if (status === 200) {
+            return response.text().then((_responseText) => {
+            let result200: any = null;
+            result200 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver) as GatewayAcceptedResponseDto;
+            return result200;
+            });
+        } else if (status === 201) {
             return response.text().then((_responseText) => {
             let result201: any = null;
             result201 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver) as GatewayAcceptedResponseDto;
@@ -1441,7 +1507,7 @@ export class ProofControllerClient {
     protected processDeclineProofRequest(response: Response): Promise<GatewayAcceptedResponseDto> {
         const status = response.status;
         let _headers: any = {}; if (response.headers && response.headers.forEach) { response.headers.forEach((v: any, k: any) => _headers[k] = v); };
-        if (status === 200 || status === 201) {
+        if (status === 200) {
             return response.text().then((_responseText) => {
             let result200: any = null;
             result200 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver) as GatewayAcceptedResponseDto;
@@ -1449,7 +1515,9 @@ export class ProofControllerClient {
             });
         } else if (status === 201) {
             return response.text().then((_responseText) => {
-            return throwException("A server side error occurred.", status, _responseText, _headers);
+            let result201: any = null;
+            result201 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver) as GatewayAcceptedResponseDto;
+            return result201;
             });
         } else if (status === 500) {
             return response.text().then((_responseText) => {
@@ -1514,7 +1582,7 @@ export interface IssueCredentialAttributes {
 }
 
 export interface IssueCredentialRequestDto {
-    connectionId: string;
+    connectionId?: string;
     credentialDefinitionId: string;
     attributes: IssueCredentialAttributes[];
 
@@ -1530,7 +1598,7 @@ export interface CredentialFilterDto {
 
 export interface MakeBasicMessageRequestDto {
     connectionId: string;
-    message: string;
+    content: string;
 
     [key: string]: any;
 }
@@ -1566,7 +1634,7 @@ export interface IssueProofRequestDto {
 }
 
 export interface ProofReqDto {
-    proofRecordId: string;
+    proofId: string;
     proofUrl: string;
 
     [key: string]: any;
diff --git a/apps/dashboard/src/api/index.ts b/apps/dashboard/src/api/index.ts
index 4631687a..f009e21b 100644
--- a/apps/dashboard/src/api/index.ts
+++ b/apps/dashboard/src/api/index.ts
@@ -1,7 +1,8 @@
 import {
   ConnectionRecordDto,
   CreateCredentialDefinitionRequestDto,
-  CreateInvitationResponseDto, CreateSchemaRequestDto,
+  CreateInvitationResponseDto,
+  CreateSchemaRequestDto,
   CreddefRecordDto,
   IssueCredentialRequestDto,
   IdReqDto,
@@ -14,13 +15,16 @@ import {
   ProofRecordDto,
   ProofFilterDto,
   IssueProofRequestDto,
-  ProofReqDto
+  ProofReqDto,
+  ProofIssueResponseDto,
+  CredentialIssueResponseDto
 } from "./agent-client";
 
 import {
   ConnectionControllerClient,
   AttestationControllerClient,
-  ProofControllerClient, GatewayAcceptedResponseDto,
+  ProofControllerClient,
+  GatewayAcceptedResponseDto,
 } from "./gateway-client";
 
 
@@ -47,6 +51,8 @@ interface GatewayMessageType {
 // type RestControllerClientType = InstanceType<typeof RestControllerClient>;
 // type OmittedRestControllerClientType = Omit<RestControllerClientType, 'http' | 'baseUrl'>;
 
+type BasicMessageReceivedCallback = (event: MessageRecordDto) => void;
+
 class ApiClient /* implements OmittedRestControllerClientType */ {
   private _ws!: WebSocket;
   private _wsMessages: GatewayMessageType[] = [];
@@ -55,6 +61,19 @@ class ApiClient /* implements OmittedRestControllerClientType */ {
   private _attestation!: AttestationControllerClient;
   private _proof!: ProofControllerClient;
 
+  private _messageCallbacks: { id: string, cb: BasicMessageReceivedCallback }[] = [];
+  public subscribeToBasicMessages = (cb: (event: MessageRecordDto) => void) => {
+    const id = Math.random().toString();
+    this._messageCallbacks.push({ id: id, cb });
+
+    return () => {
+      const index = this._messageCallbacks.findIndex(p => p.id === id);
+      if (index >= 0) {
+        this._messageCallbacks.splice(index, 1);
+      }
+    };
+  }
+
   /* rest api methods */
   public createInvitation = (): Promise<CreateInvitationResponseDto> =>
     this._waitForResponse(this._connection.createInvitation())
@@ -86,7 +105,7 @@ class ApiClient /* implements OmittedRestControllerClientType */ {
   public createCredentialDefinition = (body: CreateCredentialDefinitionRequestDto): Promise<CreddefRecordDto> =>
     this._waitForResponse(this._attestation.createCredentialDefinition(body));
 
-  public issueCredential = (body: IssueCredentialRequestDto): Promise<CredentialRecordDto> =>
+  public issueCredential = (body: IssueCredentialRequestDto): Promise<CredentialIssueResponseDto> =>
     this._waitForResponse(this._attestation.issueCredential(body));
 
   public credentials = (): Promise<CredentialRecordDto[]> =>
@@ -132,7 +151,7 @@ class ApiClient /* implements OmittedRestControllerClientType */ {
   public deleteProofById = (proof_record_id: string): Promise<void> =>
     this._waitForResponse(this._proof.deleteProofById(proof_record_id));
 
-  public issueProof = (body: IssueProofRequestDto): Promise<ProofRecordDto> =>
+  public issueProof = (body: IssueProofRequestDto): Promise<ProofIssueResponseDto> =>
     this._waitForResponse(this._proof.issueProof(body));
 
   public acceptProof = (body: ProofReqDto): Promise<ProofRecordDto> =>
@@ -230,6 +249,7 @@ class ApiClient /* implements OmittedRestControllerClientType */ {
     ws.addEventListener('message', (event) => {
       console.log('Message from server: ', event.data);
       const data = JSON.parse(event.data, this.jsonParseReviver);
+      this._checkIncomingBasicMessage(data);
       this._wsMessages.push(data);
     });
 
@@ -247,6 +267,14 @@ class ApiClient /* implements OmittedRestControllerClientType */ {
       console.error(`WebSocket Error: ${error}`);
     });
   }
+
+  private _checkIncomingBasicMessage = (event: GatewayMessageType) => {
+    if (event.source === "agent-basic-message-afj") {
+      const data = event.data as MessageRecordDto;
+
+      this._messageCallbacks.forEach(subscription => subscription.cb(data));
+    }
+  }
 }
 
 export default new ApiClient();
diff --git a/apps/dashboard/src/components/App/index.tsx b/apps/dashboard/src/components/App/index.tsx
index a4846785..7d41907b 100644
--- a/apps/dashboard/src/components/App/index.tsx
+++ b/apps/dashboard/src/components/App/index.tsx
@@ -1,18 +1,36 @@
 import React, { useEffect, useState } from "react";
-import {Spin} from "antd";
-import { ToastContainer } from "react-toastify";
+import {Button, Spin} from "antd";
+import {toast, ToastContainer} from "react-toastify";
 import PageRoutes from "@dashboard/routes";
 import Sidebar from "../Sidebar";
 import modalStore from "@dashboard/store/modalStore";
 import {observer} from "mobx-react";
+import api from "@dashboard/api";
+import {useNavigate} from "react-router-dom";
+import config from "@dashboard/routes/config";
 import s from "./styles.module.scss";
 
 
 const App = observer(() => {
+  const navigate = useNavigate();
   const [isAppLoading, setIsAppLoading] = useState(true);
 
   useEffect(() => {
     (async () => {
+      api.subscribeToBasicMessages((message) => {
+        toast.info((
+          <div>
+            You received a new message from {message.from || message.connectionId}.
+            <div>
+              <Button type="primary" onClick={() => {
+                navigate(config.connection_view.getLink(message.connectionId))
+              }}>
+                View message
+              </Button>
+            </div>
+          </div>
+        ));
+      });
       setIsAppLoading(false);
     })();
   }, []);
diff --git a/apps/dashboard/src/components/BasicMessageItem/index.tsx b/apps/dashboard/src/components/BasicMessageItem/index.tsx
index 1d593ed8..8e057cad 100644
--- a/apps/dashboard/src/components/BasicMessageItem/index.tsx
+++ b/apps/dashboard/src/components/BasicMessageItem/index.tsx
@@ -14,13 +14,10 @@ const BasicMessageItem = observer(({ item, onClick }: BasicMessageItemProps) =>
   return (
     <div className={classNames(s.item, { [s.clickable]: onClick })} onClick={onClick}>
       <div>
-        From: {item.from}
+        Role: {item.role}
       </div>
       <div>
-        To: {item.to}
-      </div>
-      <div>
-        Message: {item.message}
+        Message: {item.content}
       </div>
 
       <div className={s.createdAt}>
diff --git a/apps/dashboard/src/components/BasicMessageItem/styles.module.scss b/apps/dashboard/src/components/BasicMessageItem/styles.module.scss
index 221d8432..5a5a0d4c 100644
--- a/apps/dashboard/src/components/BasicMessageItem/styles.module.scss
+++ b/apps/dashboard/src/components/BasicMessageItem/styles.module.scss
@@ -1,6 +1,6 @@
 .item {
   display: flex;
-  flex-direction: row;
+  flex-direction: column;
 
   margin: 4px 0;
   border: 1px solid rgba(0, 0, 0, 0.1);
diff --git a/apps/dashboard/src/components/BasicMessageList/BasicMessageListStore.ts b/apps/dashboard/src/components/BasicMessageList/BasicMessageListStore.ts
index 52c38947..4f416bb6 100644
--- a/apps/dashboard/src/components/BasicMessageList/BasicMessageListStore.ts
+++ b/apps/dashboard/src/components/BasicMessageList/BasicMessageListStore.ts
@@ -6,6 +6,7 @@ import {MessageRecordDto} from "@dashboard/api/agent-client";
 
 class BasicMessageListStore {
   public loading = false;
+  public sendingMessage = false;
   public items: MessageRecordDto[] = [];
   constructor() {
     makeAutoObservable(this);
@@ -27,6 +28,26 @@ class BasicMessageListStore {
       runInAction(() => this.loading = false);
     }
   }
+
+  public sendMessage = async (connectionId: string, content: string) => {
+    runInAction(() => this.sendingMessage = true);
+    try {
+      const message = await api.sendMessage({
+        connectionId: connectionId,
+        content: content
+      });
+      runInAction(() => {
+        this.items.push(message);
+        this.sendingMessage = false;
+      });
+      return true;
+    } catch (e: any) {
+      toast(e.message);
+      console.error(e);
+      runInAction(() => this.sendingMessage = false);
+    }
+    return false;
+  }
 }
 
 export type { BasicMessageListStore };
diff --git a/apps/dashboard/src/components/BasicMessageList/CreateMessage/index.tsx b/apps/dashboard/src/components/BasicMessageList/CreateMessage/index.tsx
new file mode 100644
index 00000000..196ffa17
--- /dev/null
+++ b/apps/dashboard/src/components/BasicMessageList/CreateMessage/index.tsx
@@ -0,0 +1,42 @@
+import React, {useState} from "react";
+import {observer} from "mobx-react";
+import {Button, Input} from 'antd';
+
+export interface CreateMessageProps {
+  onCreateMessage: (message: string) => Promise<boolean>;
+}
+
+const CreateMessage: React.FC<CreateMessageProps> = observer(({ onCreateMessage }) => {
+  const [text, setText] = useState('');
+  const [loading, setLoading] = useState(false);
+  
+  const handleCreate = async () => {
+    setLoading(true);
+    try {
+      const result = await onCreateMessage(text);
+      if (result) {
+        setText('');
+      }
+    }
+    catch (e) {
+
+    }
+    setLoading(false);
+  }
+  return (
+    <div>
+      <div>Create a message</div>
+      <Input.TextArea
+        rows={6}
+        value={text}
+        onChange={(e) => { setText(e.target.value) }}
+        disabled={loading}
+      />
+      <Button onClick={handleCreate} disabled={loading} loading={loading}>
+        Send message
+      </Button>
+    </div>
+  );
+});
+
+export default CreateMessage;
diff --git a/apps/dashboard/src/components/BasicMessageList/index.tsx b/apps/dashboard/src/components/BasicMessageList/index.tsx
index 3c538dff..5a3e0fe0 100644
--- a/apps/dashboard/src/components/BasicMessageList/index.tsx
+++ b/apps/dashboard/src/components/BasicMessageList/index.tsx
@@ -5,16 +5,27 @@ import BasicMessageListStore from './BasicMessageListStore';
 import NoRecordsMessage from "../NoRecordsMessage";
 import BasicMessageItem from "@dashboard/components/BasicMessageItem";
 import modalStore from "@dashboard/store/modalStore";
+import api from "@dashboard/api";
+import CreateMessage from "@dashboard/components/BasicMessageList/CreateMessage";
 
-export interface ProofListProps {
+export interface BasicMessageListProps {
   connectionId: string | null;
 }
 
-const ProofList: React.FC<ProofListProps> = observer(({ connectionId }) => {
+const BasicMessageList: React.FC<BasicMessageListProps> = observer(({ connectionId }) => {
   const [store] = useState(() => new BasicMessageListStore());
 
   useEffect(() => {
-    store.loadAll(connectionId)
+    store.loadAll(connectionId);
+
+    const unsubscribe = api.subscribeToBasicMessages((message) => {
+      if (connectionId === message.connectionId) {
+        store.items.push(message);
+      }
+    });
+    return () => {
+      unsubscribe();
+    };
   }, [])
   return (
     <div>
@@ -31,8 +42,14 @@ const ProofList: React.FC<ProofListProps> = observer(({ connectionId }) => {
       {store.loading && (
         <Spin />
       )}
+
+      {connectionId && (
+        <div>
+          <CreateMessage onCreateMessage={message => store.sendMessage(connectionId, message)}/>
+        </div>
+      )}
     </div>
   );
 });
 
-export default ProofList;
+export default BasicMessageList;
diff --git a/apps/dashboard/src/components/ProofItem/index.tsx b/apps/dashboard/src/components/ProofItem/index.tsx
index 256ce3e4..f6947dcc 100644
--- a/apps/dashboard/src/components/ProofItem/index.tsx
+++ b/apps/dashboard/src/components/ProofItem/index.tsx
@@ -1,16 +1,16 @@
 import React from "react";
 import { observer } from "mobx-react";
 import {Button, Space} from "antd";
-import {CredentialRecordDtoState, ProofRecordDto} from "@dashboard/api/agent-client";
+import {ProofRecordDto} from "@dashboard/api/agent-client";
 import s from './styles.module.scss';
 
 interface ProofItemProps {
   item: ProofRecordDto;
   onOpen?: () => void;
   onRemove?: () => void;
-  onAccept: () => void;
-  onDecline: () => void;
-  statusChanging: boolean;
+  onAccept?: () => void;
+  onDecline?: () => void;
+  statusChanging?: boolean;
 }
 
 const ProofItem = observer(({
@@ -28,12 +28,12 @@ const ProofItem = observer(({
       </pre>
       <Space direction="horizontal">
         {onOpen && <Button onClick={onOpen}>Go to credential</Button>}
-        {item.state === 'request-received' && (
+        {onAccept && item.state === 'request-received' && (
           <Button disabled={statusChanging} onClick={onAccept} type="primary">
             Accept
           </Button>
         )}
-        {item.state === 'request-received' && (
+        {onDecline && item.state === 'request-received' && (
           <Button disabled={statusChanging} onClick={onDecline} danger>
             Decline
           </Button>
diff --git a/apps/dashboard/src/components/ProofList/ProofListStore.ts b/apps/dashboard/src/components/ProofList/ProofListStore.ts
index a7d9984f..101e1055 100644
--- a/apps/dashboard/src/components/ProofList/ProofListStore.ts
+++ b/apps/dashboard/src/components/ProofList/ProofListStore.ts
@@ -37,7 +37,7 @@ class ProofListStore {
     });
     try {
       const credRecord = await api.acceptProof({
-        proofRecordId: proofRecordId,
+        proofId: proofRecordId,
         proofUrl: ""
       });
       runInAction(() => {
diff --git a/apps/dashboard/src/components/Sidebar/index.tsx b/apps/dashboard/src/components/Sidebar/index.tsx
index ae148617..012e3857 100644
--- a/apps/dashboard/src/components/Sidebar/index.tsx
+++ b/apps/dashboard/src/components/Sidebar/index.tsx
@@ -22,6 +22,9 @@ const Sidebar = () => {
       <Link className={s.link} to={config.proof_list.getLink()}>
         Proof List
       </Link>
+      <Link className={s.link} to={config.auth.getLink()}>
+        Auth
+      </Link>
     </div>
   );
 };
diff --git a/apps/dashboard/src/main.tsx b/apps/dashboard/src/main.tsx
index 956965d7..f870f8ec 100644
--- a/apps/dashboard/src/main.tsx
+++ b/apps/dashboard/src/main.tsx
@@ -1,8 +1,8 @@
-import * as ReactDOM from "react-dom/client";
+import * as ReactDOM from 'react-dom/client';
 import { BrowserRouter } from "react-router-dom";
 import { ConfigProvider } from "antd";
 import getConfig from "./utils/getConfig";
-import App from "./components/App";
+import App from './components/App';
 
 import api, {setConfig} from "./api";
 import "react-toastify/dist/ReactToastify.css";
@@ -12,7 +12,7 @@ const config = getConfig();
 setConfig({
   websocketUrl: config.WS_GATEWAY,
   gatewayUrl: config.HTTP_GATEWAY,
-  getToken: async () => "",
+  getToken: async () => ''
 });
 
 api.initialize();
@@ -20,8 +20,9 @@ api.initialize();
 // @ts-ignore
 window.api = api;
 
+
 const root = ReactDOM.createRoot(
-  document.getElementById("root") as HTMLElement,
+  document.getElementById('root') as HTMLElement
 );
 root.render(
   <BrowserRouter>
diff --git a/apps/dashboard/src/modals/AcceptConnectionlessProofRequestDialog/index.tsx b/apps/dashboard/src/modals/AcceptConnectionlessProofRequestDialog/index.tsx
new file mode 100644
index 00000000..7c46c641
--- /dev/null
+++ b/apps/dashboard/src/modals/AcceptConnectionlessProofRequestDialog/index.tsx
@@ -0,0 +1,81 @@
+import React, { useEffect, useState } from "react";
+import { observer } from "mobx-react";
+import { Form, Input, Button } from 'antd';
+import api from "@dashboard/api";
+import {toast} from "react-toastify";
+import Modal, {FcProps} from "@dashboard/components/Modal";
+import {ProofRecordDto} from "@dashboard/api/agent-client";
+import s from "./styles.module.scss";
+
+export interface AcceptConnectionlessProofRequestDialogProps {
+  onProofReceived: (proofRecord: ProofRecordDto) => void;
+}
+
+const AcceptConnectionlessProofRequestDialog = observer(({
+  setTitle,
+  onClose,
+  data
+}: FcProps<AcceptConnectionlessProofRequestDialogProps>) => {
+  useEffect(() => {
+    setTitle('Accept proof request by URL');
+  }, []);
+
+  const [loading, setLoading] = useState(false);
+
+  const onFinish = async ({ proofUrl }: any) => {
+    try {
+      setLoading(true);
+      const proofRecord = await api.acceptProof({
+        proofUrl,
+        proofId: ""
+      });
+      toast(`Proof request accepted`);
+      if (proofRecord) {
+        data.onProofReceived(proofRecord);
+        onClose();
+      }
+    } catch (e: any) {
+      console.error(e);
+      toast(e.message);
+    }
+    setLoading(false);
+  };
+
+  return (
+    <Modal.Body>
+      <div className={s.body}>
+        <Form
+          layout="vertical"
+          initialValues={{
+            proofUrl: ''
+          }}
+          onFinish={onFinish}
+          autoComplete="off"
+        >
+          <Form.Item
+            label="proof url"
+            name="proofUrl"
+            rules={[{ required: true, message: 'Please enter proof url!' }]}
+          >
+            <Input.TextArea rows={12} />
+          </Form.Item>
+
+          <div className={s.footerActions}>
+            <Button type="primary" htmlType="submit" disabled={loading}>
+              Accept
+            </Button>
+            <Button
+              className={s.cancelButton}
+              onClick={onClose}
+              disabled={loading}
+            >
+              Close
+            </Button>
+          </div>
+        </Form>
+      </div>
+    </Modal.Body>
+  );
+});
+
+export default AcceptConnectionlessProofRequestDialog;
diff --git a/apps/dashboard/src/modals/AcceptConnectionlessProofRequestDialog/styles.module.scss b/apps/dashboard/src/modals/AcceptConnectionlessProofRequestDialog/styles.module.scss
new file mode 100644
index 00000000..5cc463b5
--- /dev/null
+++ b/apps/dashboard/src/modals/AcceptConnectionlessProofRequestDialog/styles.module.scss
@@ -0,0 +1,4 @@
+.footerActions {
+  display: flex;
+  justify-content: space-around;
+}
diff --git a/apps/dashboard/src/modals/IssueCredentialDialog/index.tsx b/apps/dashboard/src/modals/IssueCredentialDialog/index.tsx
index 88dc7cc4..77758ef4 100644
--- a/apps/dashboard/src/modals/IssueCredentialDialog/index.tsx
+++ b/apps/dashboard/src/modals/IssueCredentialDialog/index.tsx
@@ -2,13 +2,13 @@ import React, { useEffect, useState } from "react";
 import { observer } from "mobx-react";
 import {Form, Input, Button, Spin, Select} from 'antd';
 import Modal, {FcProps} from "@dashboard/components/Modal";
-import {CredentialRecordDto} from "@dashboard/api/agent-client";
+import {CredentialIssueResponseDto} from "@dashboard/api/agent-client";
 import IssueCredentialDialogStore from "./IssueCredentialDialogStore";
 import s from "./styles.module.scss";
 
 export interface IssueCredentialDialogProps {
   connectionId: string;
-  onCredentialIssued: (cred: CredentialRecordDto) => void;
+  onCredentialIssued: (cred: CredentialIssueResponseDto) => void;
 }
 
 const IssueCredentialDialog = observer(({
@@ -23,9 +23,9 @@ const IssueCredentialDialog = observer(({
   }, []);
 
   const onFinish = async ({ attributes }: any) => {
-    const credential = await store.issueCredential(attributes);
-    if (credential) {
-      data.onCredentialIssued(credential);
+    const response = await store.issueCredential(attributes);
+    if (response) {
+      data.onCredentialIssued(response);
       onClose();
     }
   }
diff --git a/apps/dashboard/src/modals/IssueProofRequestDialog/IssueProofRequestDialog.ts b/apps/dashboard/src/modals/RequestProofDialog/RequestProofDialogStore.ts
similarity index 93%
rename from apps/dashboard/src/modals/IssueProofRequestDialog/IssueProofRequestDialog.ts
rename to apps/dashboard/src/modals/RequestProofDialog/RequestProofDialogStore.ts
index 196e215e..e91a5aaa 100644
--- a/apps/dashboard/src/modals/IssueProofRequestDialog/IssueProofRequestDialog.ts
+++ b/apps/dashboard/src/modals/RequestProofDialog/RequestProofDialogStore.ts
@@ -10,9 +10,9 @@ interface ProofUiAttribute {
   attributeName: string | null;
 }
 
-class IssueProofRequestDialog {
+class RequestProofDialogStore {
   public initLoading = false;
-  public connectionId!: string;
+  public connectionId: string | undefined = undefined;
   public credDefList: CreddefRecordDto[] = [];
 
   public rows: ProofUiAttribute[] = [];
@@ -41,7 +41,7 @@ class IssueProofRequestDialog {
     makeAutoObservable(this);
   }
 
-  public async init(connectionId: string) {
+  public async init(connectionId: string | undefined) {
     runInAction(() => {
       this.initLoading = true;
       this.connectionId = connectionId;
@@ -123,7 +123,7 @@ class IssueProofRequestDialog {
           schemaId: p.schema!.id
         }))
       });
-      toast("Proof request sent");
+      toast("Proof request created");
       runInAction(() => {
         this.issuingLoading = false;
       });
@@ -140,6 +140,6 @@ class IssueProofRequestDialog {
 
 }
 
-export type { IssueProofRequestDialog };
+export type { RequestProofDialogStore };
 
-export default IssueProofRequestDialog;
+export default RequestProofDialogStore;
diff --git a/apps/dashboard/src/modals/IssueProofRequestDialog/index.tsx b/apps/dashboard/src/modals/RequestProofDialog/index.tsx
similarity index 72%
rename from apps/dashboard/src/modals/IssueProofRequestDialog/index.tsx
rename to apps/dashboard/src/modals/RequestProofDialog/index.tsx
index 675b2c7a..3c4d432f 100644
--- a/apps/dashboard/src/modals/IssueProofRequestDialog/index.tsx
+++ b/apps/dashboard/src/modals/RequestProofDialog/index.tsx
@@ -2,23 +2,28 @@ import React, { useEffect, useState } from "react";
 import { observer } from "mobx-react";
 import {Button, Spin, Select, Space} from 'antd';
 import Modal, {FcProps} from "@dashboard/components/Modal";
-import {ProofRecordDto} from "@dashboard/api/agent-client";
-import IssueProofRequestDialog from "./IssueProofRequestDialog";
+import {ProofIssueResponseDto} from "@dashboard/api/agent-client";
+import RequestProofDialogStore from "./RequestProofDialogStore";
 import s from "./styles.module.scss";
 
-export interface IssueProofRequestDialogProps {
-  connectionId: string;
-  onProofRequestIssued: (cred: ProofRecordDto) => void;
+export interface RequestProofDialogProps {
+  connectionId?: string;
+  onProofRequestIssued: (cred: ProofIssueResponseDto) => void;
 }
 
-const IssueCredentialDialog = observer(({
+const RequestProofDialog = observer(({
   setTitle,
   onClose,
   data
-}: FcProps<IssueProofRequestDialogProps>) => {
-  const [store] = useState(() => new IssueProofRequestDialog());
+}: FcProps<RequestProofDialogProps>) => {
+  const [store] = useState(() => new RequestProofDialogStore());
   useEffect(() => {
-    setTitle('Send proof request to ' + data.connectionId);
+    if (data.connectionId) {
+      setTitle('Request proof from ' + data.connectionId);
+    } else {
+      setTitle('Create connectionless proof request');
+    }
+
     store.init(data.connectionId);
   }, []);
 
@@ -32,10 +37,10 @@ const IssueCredentialDialog = observer(({
 
       <div>
         {store.rows.map((row, rowIndex) => (
-          <Space direction="horizontal" className={s.row}>
+          <Space direction="horizontal" className={s.row} key={rowIndex}>
             <Select
               placeholder="Select credential"
-              style={{ width: 300 }}
+              // style={{ width: 300 }}
               value={row.credentialDefinitionId}
               showSearch
               onChange={val => store.selectCredDef(rowIndex, val)}
@@ -50,7 +55,7 @@ const IssueCredentialDialog = observer(({
             {row.schema && (
               <Select
                 placeholder="Select attribute"
-                style={{ width: 300 }}
+                // style={{ width: 300 }}
                 value={row.attributeName}
                 showSearch
                 onChange={val => store.selectAttributeName(rowIndex, val)}
@@ -76,7 +81,7 @@ const IssueCredentialDialog = observer(({
               }
             }}
           >
-            Submit proof request
+            Request proof
           </Button>
         </Space>
       </div>
@@ -85,4 +90,4 @@ const IssueCredentialDialog = observer(({
   );
 });
 
-export default IssueCredentialDialog;
+export default RequestProofDialog;
diff --git a/apps/dashboard/src/modals/IssueProofRequestDialog/styles.module.scss b/apps/dashboard/src/modals/RequestProofDialog/styles.module.scss
similarity index 100%
rename from apps/dashboard/src/modals/IssueProofRequestDialog/styles.module.scss
rename to apps/dashboard/src/modals/RequestProofDialog/styles.module.scss
diff --git a/apps/dashboard/src/modals/ViewConnectionlessProofRequest/index.tsx b/apps/dashboard/src/modals/ViewConnectionlessProofRequest/index.tsx
new file mode 100644
index 00000000..ba9cfd77
--- /dev/null
+++ b/apps/dashboard/src/modals/ViewConnectionlessProofRequest/index.tsx
@@ -0,0 +1,68 @@
+import React, { useEffect } from "react";
+import { observer } from "mobx-react";
+import QRCode from "react-qr-code";
+import Modal, {FcProps} from "@dashboard/components/Modal";
+import {ProofRecordDto} from "@dashboard/api/agent-client";
+import ProofItem from "@dashboard/components/ProofItem";
+import s from "./styles.module.scss";
+
+export interface ViewConnectionlessProofRequestProps {
+  proofUrl: string;
+  proofRecord: ProofRecordDto;
+}
+
+const ViewConnectionlessProofRequest = observer(({
+  setTitle,
+  setWidth,
+  setClassName,
+  onClose,
+  data
+}: FcProps<ViewConnectionlessProofRequestProps>) => {
+  useEffect(() => {
+    setClassName(s.modal);
+    setWidth('80vw');
+    setTitle('Connectionless proof request');
+  }, []);
+
+  return (
+    <Modal.Body className={s.body}>
+      <div className={s.info}>
+        <div>
+          <div className={s.qrCodeHint}>
+            Scan this QR code with mobile wallet
+          </div>
+          <div className={s.qrWrapper}>
+            <QRCode
+              value={data.proofUrl}
+              size={500}
+            />
+          </div>
+          <div>
+            <div className={s.urlTitle}>
+              Proof request URL:
+            </div>
+            <div className={s.url}>
+              <b>
+                {data.proofUrl}
+              </b>
+            </div>
+            <div className={s.urlHint}>
+              Copy this URL and send it to the person you want to request proof from
+            </div>
+            <br />
+            {data.proofRecord.oob && (
+              <div>
+                Details:
+                <ProofItem
+                  item={data.proofRecord}
+                />
+              </div>
+            )}
+          </div>
+        </div>
+      </div>
+    </Modal.Body>
+  );
+});
+
+export default ViewConnectionlessProofRequest;
diff --git a/apps/dashboard/src/modals/ViewConnectionlessProofRequest/styles.module.scss b/apps/dashboard/src/modals/ViewConnectionlessProofRequest/styles.module.scss
new file mode 100644
index 00000000..66d3a4f7
--- /dev/null
+++ b/apps/dashboard/src/modals/ViewConnectionlessProofRequest/styles.module.scss
@@ -0,0 +1,46 @@
+.modal {
+  top: 40px;
+}
+
+.body {
+  height: calc(100vh - 140px);
+}
+
+.qrWrapper {
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  background: white;
+  padding: 16px;
+}
+
+.info {
+  display: flex;
+  flex-direction: column;
+  justify-content: space-between;
+  overflow: scroll;
+}
+
+.urlTitle {
+  margin-top: 12px;
+  font-weight: bold;
+}
+
+.url {
+  margin-top: 12px;
+  word-break: break-word;
+  border-right: 8px;
+  background-color: rgba(0,0,0, 0.04);
+  padding: 8px;
+}
+
+.urlHint {
+  margin-top: 12px;
+  font-size: 16px;
+}
+
+.qrCodeHint {
+  text-align: center;
+  margin: 24px 0 12px 0;
+  font-size: 18px;
+}
\ No newline at end of file
diff --git a/apps/dashboard/src/routes/config.ts b/apps/dashboard/src/routes/config.ts
index 5465d334..dfe057b6 100644
--- a/apps/dashboard/src/routes/config.ts
+++ b/apps/dashboard/src/routes/config.ts
@@ -5,6 +5,7 @@ import SchemaListPage from "./pages/SchemaListPage";
 import CredentialDefListPage from "./pages/CredentialDefListPage";
 import CredentialListPage from "./pages/CredentialListPage";
 import ProofListPage from "./pages/ProofListPage";
+import AuthPage from "./pages/AuthPage";
 
 const routes = {
   connection_create: {
@@ -42,6 +43,11 @@ const routes = {
     route: "/proof/list",
     getLink: () => "/proof/list",
   },
+  auth: {
+    Component: AuthPage,
+    route: "/auth",
+    getLink: () => "/auth",
+  },
 };
 
 export default routes;
diff --git a/apps/dashboard/src/routes/pages/AuthPage/Login.tsx b/apps/dashboard/src/routes/pages/AuthPage/Login.tsx
new file mode 100644
index 00000000..5cc1cc29
--- /dev/null
+++ b/apps/dashboard/src/routes/pages/AuthPage/Login.tsx
@@ -0,0 +1,50 @@
+import React, {useEffect, useState} from "react";
+import {observer} from "mobx-react";
+import QRCode from "react-qr-code";
+import LoginStore from "@dashboard/routes/pages/AuthPage/LoginStore";
+import { Spin } from "antd";
+
+const Login = observer(() => {
+  const [store] = useState(() => new LoginStore());
+  useEffect(() => {
+    store.initialize();
+  }, []);
+
+  return (
+    <div>
+      {store.loading && (
+        <div>
+          <Spin />
+          Loading...
+        </div>
+      )}
+      <p>
+        Scan this QR code in order to send proof with information about issued credentials by out system<br />
+        Doing that you will be autorized<br />
+        Credentials will contains: <br />
+        SchemaId: {store.schemaId}
+        Schema attributes: {store.schema?.attributes.join(', ')}
+        CreddefId: {store.creddef?.id}
+
+      </p>
+      <QRCode value={store.shortProofUrl || ''} size={256}  />
+
+      <br/>
+      <div>
+        Technical information:
+      </div>
+      <div>
+        proofUrl: {store.proofUrl}
+      </div>
+      <div>
+        proof record:<br />
+        <pre>
+          {JSON.stringify(store.proofRecord || {}, null, 2)}
+        </pre>
+      </div>
+    </div>
+
+  );
+});
+
+export default Login;
diff --git a/apps/dashboard/src/routes/pages/AuthPage/LoginStore.ts b/apps/dashboard/src/routes/pages/AuthPage/LoginStore.ts
new file mode 100644
index 00000000..2f978697
--- /dev/null
+++ b/apps/dashboard/src/routes/pages/AuthPage/LoginStore.ts
@@ -0,0 +1,61 @@
+import {makeAutoObservable, runInAction} from "mobx";
+import api from "@dashboard/api";
+import {
+  CreddefRecordDto,
+  ProofRecordDto,
+  SchemaRecordDto
+} from "@dashboard/api/agent-client";
+import {toast} from "react-toastify";
+import {v4} from "uuid";
+
+
+class ConnectionListStore {
+  public loading = false;
+  public id = v4();
+  public schemaId = 'did:indy:bcovrin:test:FcZ4aS728oRGVdNUKVaECP/anoncreds/v0/SCHEMA/SelfIdentity/1.0';
+  public schema: SchemaRecordDto | null = null;
+  public creddef: CreddefRecordDto | null = null;
+  public shortProofUrl: string | null = null;
+  public proofUrl: string | null = null;
+  public proofRecord: ProofRecordDto | null = null;
+
+  constructor() {
+    makeAutoObservable(this);
+  }
+
+  public async initialize() {
+    runInAction(() => this.loading = true);
+    try {
+      const schema = await api.getSchemaById({ id: this.schemaId });
+      const credDefs = await api.credentialDefinitions();
+      let requiredCredDef = credDefs.find((credDef) => credDef.schemaId === this.schemaId);
+      if (!requiredCredDef) {
+        requiredCredDef = await api.createCredentialDefinition({ schemaId: this.schemaId, tag: 'SelfIdentity' });
+      }
+
+      const { shortProofUrl, proofUrl, proofRecord } = await api.issueProof({
+        attributes: [{
+          attributeName: 'identity-name',
+          credentialDefinitionId: requiredCredDef.id,
+          schemaId: this.schemaId
+        }]
+      })
+      runInAction(() => {
+        this.schema = schema;
+        this.creddef = requiredCredDef!;
+        this.shortProofUrl = shortProofUrl;
+        this.proofUrl = proofUrl;
+        this.proofRecord = proofRecord;
+        this.loading = false;
+      });
+    } catch (e: any) {
+      console.error(e);
+      toast.error(e.message);
+      runInAction(() => this.loading = false);
+    }
+  }
+}
+
+export type { ConnectionListStore };
+
+export default ConnectionListStore;
diff --git a/apps/dashboard/src/routes/pages/AuthPage/Register.tsx b/apps/dashboard/src/routes/pages/AuthPage/Register.tsx
new file mode 100644
index 00000000..f55dbc06
--- /dev/null
+++ b/apps/dashboard/src/routes/pages/AuthPage/Register.tsx
@@ -0,0 +1,50 @@
+import React, {useEffect, useState} from "react";
+import {observer} from "mobx-react";
+import QRCode from "react-qr-code";
+import RegisterStore from "@dashboard/routes/pages/AuthPage/RegisterStore";
+import { Spin } from "antd";
+
+const Register = observer(() => {
+  const [store] = useState(() => new RegisterStore());
+  useEffect(() => {
+    store.initialize();
+  }, []);
+
+  return (
+    <div>
+      {store.loading && (
+        <div>
+          <Spin />
+          Loading...
+        </div>
+      )}
+      <p>
+        Scan this QR code in order to receive connection-less credentials<br />
+        Using this credentials you will be able to authorize in our system<br />
+        Credentials contains: <br />
+        SchemaId: {store.schemaId}
+        Schema attributes: {store.schema?.attributes.join(', ')}
+        CreddefId: {store.creddef?.id}
+
+      </p>
+      <QRCode value={store.shortCredentialUrl || ''} size={256}  />
+
+      <br/>
+      <div>
+        Technical information:
+      </div>
+      <div>
+        credentialUrl: {store.credentialUrl}
+      </div>
+      <div>
+        crendential record:<br />
+        <pre>
+          {JSON.stringify(store.credentialRecord || {}, null, 2)}
+        </pre>
+      </div>
+    </div>
+
+  );
+});
+
+export default Register;
diff --git a/apps/dashboard/src/routes/pages/AuthPage/RegisterStore.ts b/apps/dashboard/src/routes/pages/AuthPage/RegisterStore.ts
new file mode 100644
index 00000000..d88afe83
--- /dev/null
+++ b/apps/dashboard/src/routes/pages/AuthPage/RegisterStore.ts
@@ -0,0 +1,63 @@
+import {makeAutoObservable, runInAction} from "mobx";
+import api from "@dashboard/api";
+import {
+  ConnectionRecordDto,
+  CreddefRecordDto,
+  CredentialRecordDto,
+  IssueCredentialAttributes,
+  SchemaRecordDto
+} from "@dashboard/api/agent-client";
+import {toast} from "react-toastify";
+import {v4} from "uuid";
+
+
+class ConnectionListStore {
+  public loading = false;
+  public id = v4();
+  public schemaId = 'did:indy:bcovrin:test:FcZ4aS728oRGVdNUKVaECP/anoncreds/v0/SCHEMA/SelfIdentity/1.0';
+  public schema: SchemaRecordDto | null = null;
+  public creddef: CreddefRecordDto | null = null;
+  public shortCredentialUrl: string | null = null;
+  public credentialUrl: string | null = null;
+  public credentialRecord: CredentialRecordDto | null = null;
+
+  constructor() {
+    makeAutoObservable(this);
+  }
+
+  public async initialize() {
+    runInAction(() => this.loading = true);
+    try {
+      const schema = await api.getSchemaById({ id: this.schemaId });
+      const credDefs = await api.credentialDefinitions();
+      let requiredCredDef = credDefs.find((credDef) => credDef.schemaId === this.schemaId);
+      if (!requiredCredDef) {
+        requiredCredDef = await api.createCredentialDefinition({ schemaId: this.schemaId, tag: 'SelfIdentity' });
+      }
+
+      const { shortCredentialUrl, credentialUrl, credentialRecord } = await api.issueCredential({
+        credentialDefinitionId: requiredCredDef.id,
+        attributes: [{
+          name: 'identity-name',
+          value: this.id,
+        }]
+      })
+      runInAction(() => {
+        this.schema = schema;
+        this.creddef = requiredCredDef!;
+        this.shortCredentialUrl = shortCredentialUrl;
+        this.credentialUrl = credentialUrl;
+        this.credentialRecord = credentialRecord;
+        this.loading = false;
+      });
+    } catch (e: any) {
+      console.error(e);
+      toast.error(e.message);
+      runInAction(() => this.loading = false);
+    }
+  }
+}
+
+export type { ConnectionListStore };
+
+export default ConnectionListStore;
diff --git a/apps/dashboard/src/routes/pages/AuthPage/index.tsx b/apps/dashboard/src/routes/pages/AuthPage/index.tsx
new file mode 100644
index 00000000..d208f557
--- /dev/null
+++ b/apps/dashboard/src/routes/pages/AuthPage/index.tsx
@@ -0,0 +1,34 @@
+import React from "react";
+import {observer} from "mobx-react";
+import {Tabs, TabsProps} from "antd";
+import Login from "./Login";
+import Register from "./Register";
+
+const AuthPage = observer(() => {
+  const onChange = (key: string) => {
+    console.log(key);
+  };
+
+
+  const items: TabsProps['items'] = [
+    {
+      key: '1',
+      label: 'Login',
+      children: <Login />,
+    },
+    {
+      key: '2',
+      label: 'Registration',
+      children: <Register />,
+    }
+  ];
+
+  return (
+    <div>
+      <Tabs defaultActiveKey="1" items={items} onChange={onChange} />
+    </div>
+
+  );
+});
+
+export default AuthPage;
diff --git a/apps/dashboard/src/routes/pages/ConnectionCreatePage/index.tsx b/apps/dashboard/src/routes/pages/ConnectionCreatePage/index.tsx
index 10f7a1fc..eaad0ea3 100644
--- a/apps/dashboard/src/routes/pages/ConnectionCreatePage/index.tsx
+++ b/apps/dashboard/src/routes/pages/ConnectionCreatePage/index.tsx
@@ -1,6 +1,7 @@
 import React, {useEffect, useState} from "react";
 import { observer } from "mobx-react";
-import {QRCode, Spin } from 'antd';
+import { Spin } from 'antd';
+import QRCode from "react-qr-code";
 import ConnectionCreatePageStore from './ConnectionCreatePageStore';
 import s from './styles.module.scss';
 
@@ -38,14 +39,11 @@ const ConnectionCreatePage = observer(() => {
                   <div className={s.qrCodeHint}>
                     Or scan this QR code with your mobile wallet
                   </div>
-                  <div style={{ background: 'white', padding: '16px' }}>
-                    <QRCode
-                      errorLevel="H"
-                      status={store.loading ? "loading" : "active"}
-                      value={store.invitationUrl || ""}
-                      icon="https://gw.alipayobjects.com/zos/rmsportal/KDpgvguMpGfqaHPjicRK.svg"
-                    />
-                  </div>
+                  {store.invitationUrl && (
+                    <div style={{ background: 'white', padding: '16px' }}>
+                      <QRCode value={store.invitationUrl} />
+                    </div>
+                  )}
                   <br />
                   {store.oob && (
                     <div>
diff --git a/apps/dashboard/src/routes/pages/ConnectionViewPage/index.tsx b/apps/dashboard/src/routes/pages/ConnectionViewPage/index.tsx
index 0e197e7a..706712ef 100644
--- a/apps/dashboard/src/routes/pages/ConnectionViewPage/index.tsx
+++ b/apps/dashboard/src/routes/pages/ConnectionViewPage/index.tsx
@@ -8,6 +8,7 @@ import JsonDetails from "@dashboard/components/JsonDetails";
 import CredentialList from "@dashboard/components/CredentialList";
 import ProofList from "@dashboard/components/ProofList";
 import modalStore from "@dashboard/store/modalStore";
+import BasicMessageList from "@dashboard/components/BasicMessageList";
 
 
 const ConnectionViewPage = observer(() => {
@@ -36,7 +37,7 @@ const ConnectionViewPage = observer(() => {
         </Button>
         <Button
           onClick={() => {
-            modalStore.openIssueProofRequestDialog({
+            modalStore.openRequestProofDialog({
               connectionId: id,
               onProofRequestIssued: (proofRequest) => {
                 setTimeout(() => {
@@ -71,6 +72,9 @@ const ConnectionViewPage = observer(() => {
       <h3>Proofs</h3>
       <ProofList connectionId={id} />
 
+      <h3>Messages</h3>
+      <BasicMessageList connectionId={id} />
+
       <JsonDetails object={store.connection} />
     </div>
   );
diff --git a/apps/dashboard/src/routes/pages/ProofListPage/index.tsx b/apps/dashboard/src/routes/pages/ProofListPage/index.tsx
index 2e8b8cd0..4b4b2944 100644
--- a/apps/dashboard/src/routes/pages/ProofListPage/index.tsx
+++ b/apps/dashboard/src/routes/pages/ProofListPage/index.tsx
@@ -1,10 +1,40 @@
 import React from "react";
 import {observer} from "mobx-react";
 import ProofList from "@dashboard/components/ProofList";
+import {Button, Space} from "antd";
+import modalStore from "@dashboard/store/modalStore";
 
 const ProofListPage = observer(() => {
   return (
     <div>
+      <Space direction="horizontal">
+        <Button
+          onClick={() => {
+            modalStore.openRequestProofDialog({
+              connectionId: undefined,
+              onProofRequestIssued: (proofRequest) => {
+                modalStore.openViewConnectionlessProofRequest({
+                  proofUrl: proofRequest.proofUrl!,
+                  proofRecord: proofRequest.proofRecord
+                })
+              }
+            })
+          }}
+        >
+          Create connectionless proof request
+        </Button>
+        <Button
+          onClick={() => {
+            modalStore.openAcceptConnectionlessProofRequestDialog({
+              onProofReceived: (proofRecord) => {
+                window.location.reload();
+              }
+            })
+          }}
+        >
+          Accept connectionless proof request
+        </Button>
+      </Space>
       <h2>Proof List</h2>
       <div>
         <ProofList connectionId={null} />
diff --git a/apps/dashboard/src/store/modalStore.tsx b/apps/dashboard/src/store/modalStore.tsx
index c0741f41..c6538871 100644
--- a/apps/dashboard/src/store/modalStore.tsx
+++ b/apps/dashboard/src/store/modalStore.tsx
@@ -1,25 +1,25 @@
 import React from "react";
 import { action, makeAutoObservable } from "mobx";
-import Modal, { FcProps } from "@dashboard/components/Modal";
-import ConfirmDialog, {
-  ConfirmDialogProps,
-} from "@dashboard/modals/ConfirmDialog";
-import ReceiveInvitationDialog, {
-  ReceiveInvitationDialogProps,
-} from "@dashboard/modals/ReceiveInvitationDialog";
+import {v4 as uuidv4} from "uuid";
+import Modal, {FcProps} from "@dashboard/components/Modal";
+import ConfirmDialog, {ConfirmDialogProps} from "@dashboard/modals/ConfirmDialog";
+import ReceiveInvitationDialog, { ReceiveInvitationDialogProps } from "@dashboard/modals/ReceiveInvitationDialog";
 import NewCredentialDefDialog, { NewCredentialDefDialogProps } from "@dashboard/modals/NewCredentialDefDialog";
 import NewSchemaDialog, { NewSchemaDialogProps } from "@dashboard/modals/NewSchemaDialog";
 import ViewJsonDialog, { ViewJsonDialogProps } from "@dashboard/modals/ViewJsonDialog";
 import IssueCredentialDialog, { IssueCredentialDialogProps } from "@dashboard/modals/IssueCredentialDialog";
-import IssueProofRequestDialog, { IssueProofRequestDialogProps } from "@dashboard/modals/IssueProofRequestDialog";
+import RequestProofDialog, { RequestProofDialogProps } from "@dashboard/modals/RequestProofDialog";
+import ViewConnectionlessProofRequest, { ViewConnectionlessProofRequestProps } from "@dashboard/modals/ViewConnectionlessProofRequest";
+import AcceptConnectionlessProofRequestDialog, { AcceptConnectionlessProofRequestDialogProps } from "@dashboard/modals/AcceptConnectionlessProofRequestDialog";
 
 class ModalStore {
-  public modals: { id: string, modal: React.ReactNode }[] = [];
+  public modals: { id: string, modal: any }[] = [];
 
   constructor() {
     makeAutoObservable(this);
   }
 
+
   private removeModal = action((id: string) => {
     const modalIndex = this.modals.findIndex(p => p.id === id);
     if (modalIndex >= 0) {
@@ -27,8 +27,9 @@ class ModalStore {
     }
   });
 
+
   protected open<TData>(Component: React.FC<FcProps<TData>>, data: TData) {
-    const id = Math.random().toString();
+    const id = uuidv4();
     this.modals.push({
       id: id,
       modal: (
@@ -39,24 +40,20 @@ class ModalStore {
           }}
           data={data}
         />
-      ),
+      )
     });
   }
 
-  public openConfirmDialog = (data: ConfirmDialogProps) =>
-    this.open(ConfirmDialog, data);
-  public openReceiveInvitationDialog = (data: ReceiveInvitationDialogProps) =>
-    this.open(ReceiveInvitationDialog, data);
-  public openNewCredentialDefDialog = (data: NewCredentialDefDialogProps) =>
-    this.open(NewCredentialDefDialog, data);
-  public openNewSchemaDialog = (data: NewSchemaDialogProps) =>
-    this.open(NewSchemaDialog, data);
-  public openViewJsonDialog = (data: ViewJsonDialogProps) =>
-    this.open(ViewJsonDialog, data);
-  public openIssueCredentialDialog = (data: IssueCredentialDialogProps) =>
-    this.open(IssueCredentialDialog, data);
-  public openIssueProofRequestDialog = (data: IssueProofRequestDialogProps) =>
-    this.open(IssueProofRequestDialog, data);
+  public openConfirmDialog = (data: ConfirmDialogProps) => this.open(ConfirmDialog, data);
+  public openReceiveInvitationDialog = (data: ReceiveInvitationDialogProps) => this.open(ReceiveInvitationDialog, data);
+  public openNewCredentialDefDialog = (data: NewCredentialDefDialogProps) => this.open(NewCredentialDefDialog, data);
+  public openNewSchemaDialog = (data: NewSchemaDialogProps) => this.open(NewSchemaDialog, data);
+  public openViewJsonDialog = (data: ViewJsonDialogProps) => this.open(ViewJsonDialog, data);
+  public openIssueCredentialDialog = (data: IssueCredentialDialogProps) => this.open(IssueCredentialDialog, data);
+  public openRequestProofDialog = (data: RequestProofDialogProps) => this.open(RequestProofDialog, data);
+  public openViewConnectionlessProofRequest = (data: ViewConnectionlessProofRequestProps) => this.open(ViewConnectionlessProofRequest, data);
+  public openAcceptConnectionlessProofRequestDialog = (data: AcceptConnectionlessProofRequestDialogProps) => this.open(AcceptConnectionlessProofRequestDialog, data);
+
 }
 
 export type { ModalStore };
-- 
GitLab