From dfc1fca93883e456cf9f61bbed6d52250ee018be Mon Sep 17 00:00:00 2001 From: Sai Ranjit Tummalapalli Date: Thu, 19 Aug 2021 12:22:52 +0530 Subject: [PATCH 01/14] feat: added connection protocol for mediation Signed-off-by: Sai Ranjit Tummalapalli --- src/agent/index.ts | 15 ++++++ src/network/index.ts | 46 +++++++++++-------- src/protocols/connection/ConnectionService.ts | 33 +++++++------ .../mediator/ConnectWithMediatorService.ts | 22 ++++++++- src/transports/index.ts | 22 ++++++++- src/utils/Helpers.ts | 10 +++- src/utils/MessageType.ts | 40 ++++++++-------- 7 files changed, 131 insertions(+), 57 deletions(-) diff --git a/src/agent/index.ts b/src/agent/index.ts index ec399cf..f7dddab 100644 --- a/src/agent/index.ts +++ b/src/agent/index.ts @@ -46,6 +46,21 @@ class Agent { } } + connectWithGenericMediator = async (invitationUrl: string) => { + try { + this.wallet = await DatabaseServices.getWallet(); + const response = await ConnectWithMediatorService.connectWithGenericMediator( + JSON.parse(this.wallet.walletConfig), + JSON.parse(this.wallet.walletCredentials), + invitationUrl); + return response; + } + catch (error) { + console.log("Agent - Connect with mediator error = ", error); + throw error; + } + } + updateMediator = async (url: string, apiType: string, apiBody: string) => { try { return await ConnectWithMediatorService.updateMediator(url, apiType, apiBody); diff --git a/src/network/index.ts b/src/network/index.ts index 0bbcb2d..01b284b 100644 --- a/src/network/index.ts +++ b/src/network/index.ts @@ -2,6 +2,7 @@ Copyright AyanWorks Technology Solutions Pvt. Ltd. All Rights Reserved. SPDX-License-Identifier: Apache-2.0 */ +import InboundMessageService from '../transports'; export const NetworkServices: Function = async (url: string, apiType: string, apiBody: string) => { try { @@ -26,28 +27,33 @@ export const NetworkServices: Function = async (url: string, apiType: string, ap export const OutboundAgentMessage: Function = async (url: string, apiType: string, apiBody: string) => { try { - return new Promise(async function ( - resolve, reject - ) { - const response = await fetch(url, { - method: apiType, - body: apiBody, - headers: { - Accept: 'application/json', - 'Content-Type': 'application/ssi-agent-wire', - }, - }).then((response) => { - response.json() - }) - .then((json) => { - resolve(json); - }) - .catch((error) => { - reject('We are not able to communicate with the agent at this moment, Please try again later'); - }); + console.log("url", url) + console.log("apiBody", apiBody) + const abortController = new AbortController() + const id = setTimeout(() => abortController.abort(), 15000) + const response = await fetch(url, { + method: 'POST', + body: apiBody, + headers: { 'Content-Type': 'application/ssi-agent-wire' }, + signal: abortController.signal, + }) + clearTimeout(id) + const responseMessage = await response.text() + if (responseMessage) { + console.log(`Response received`, { responseMessage, status: response.status }) + try { + const wireMessage = JSON.parse(responseMessage) + console.log(`Response received`, wireMessage) + await InboundMessageService.addMessages(wireMessage) + // this.agent.receiveMessage(wireMessage) + } catch (error) { + console.log('Unable to parse response message', error) + } + } else { + console.log(`No response received.`) } - ) } catch (error) { + console.log('Error OutboundAgentMessage', error) throw new Error('We are not able to communicate with the agent at this moment, Please try again later'); } }; \ No newline at end of file diff --git a/src/protocols/connection/ConnectionService.ts b/src/protocols/connection/ConnectionService.ts index df990ba..bb38ff3 100644 --- a/src/protocols/connection/ConnectionService.ts +++ b/src/protocols/connection/ConnectionService.ts @@ -63,7 +63,7 @@ class ConnectionService { credentialsJson: WalletCredentials, didJson: Object, logo: string): Promise { - const connection: Connection = await this.createConnection(configJson, credentialsJson, didJson); + const connection: Connection = await this.createConnection(configJson, credentialsJson, didJson, ''); const connectionTags: Object = { connectionId: connection.verkey, @@ -102,14 +102,18 @@ class ConnectionService { invitation: Message, logo: string): Promise { try { - const connection: Connection = await this.createConnection(configJson, credentialsJson, didJson, invitation.label, + const connection: Connection = await this.createConnection( + configJson, + credentialsJson, + didJson, + invitation.serviceEndpoint, + invitation.label, invitation.hasOwnProperty('alias') ? invitation.alias.logoUrl : '', - invitation.hasOwnProperty('alias') ? invitation.alias.organizationId : ''); + invitation.hasOwnProperty('alias') ? invitation.alias.organizationId : '', + ); const connectionRequest = createConnectionRequestMessage(connection, DatabaseServices.getLabel(), logo); connection.state = ConnectionState.REQUESTED; - await sendOutboundMessage(configJson, credentialsJson, connection, connectionRequest, invitation) - const connectionTags: Object = { connectionId: connection.verkey, } @@ -122,9 +126,10 @@ class ConnectionService { JSON.stringify(connection), JSON.stringify(connectionTags) ); + await sendOutboundMessage(configJson, credentialsJson, connection, connectionRequest, invitation) return connection; } catch (error) { - console.log('Connection - Create invitation error = ', JSON.stringify(error)); + console.log('Connection - Accept invitation error = ', JSON.stringify(error)); throw error; } } @@ -277,6 +282,7 @@ class ConnectionService { async createConnection(configJson: WalletConfig, credentialsJson: WalletCredentials, didJson: Object, + endpoint: string, label?: string, logo?: string, organizationId?: string, @@ -284,13 +290,15 @@ class ConnectionService { try { const [pairwiseDid, verkey]: string[] = await ArnimaSdk.createAndStoreMyDid(JSON.stringify(configJson), JSON.stringify(credentialsJson), JSON.stringify(didJson), false); - const apiBody = { - publicVerkey: DatabaseServices.getVerKey(), - verkey: verkey - }; - await NetworkServices(getServiceEndpoint() + 'verkey', 'POST', JSON.stringify(apiBody)); + // const apiBody = { + // publicVerkey: DatabaseServices.getVerKey(), + // verkey: verkey + // }; + + // await NetworkServices(getServiceEndpoint() + 'verkey', 'POST', JSON.stringify(apiBody)); + console.log('Connection - createConnection - pairwiseDid = ', verkey); const publicKey = new PublicKey(`${pairwiseDid}#1`, PublicKeyType.ED25519_SIG_2018, pairwiseDid, verkey); - const service = new Service(`${pairwiseDid};indy`, DatabaseServices.getServiceEndpoint(), [verkey], [DatabaseServices.getRoutingKeys()], 0, 'IndyAgent'); + const service = new Service(`${pairwiseDid};indy`, 'didcomm:transport/queue', [verkey], [], 0, 'IndyAgent'); const auth = new Authentication(publicKey); const did_doc = new DidDoc(pairwiseDid, [auth], [publicKey], [service]); @@ -308,7 +316,6 @@ class ConnectionService { createdAt: new Date().toISOString(), updatedAt: new Date().toISOString(), }; - return connection; } catch (error) { diff --git a/src/protocols/mediator/ConnectWithMediatorService.ts b/src/protocols/mediator/ConnectWithMediatorService.ts index 8df37c6..ba4aafb 100644 --- a/src/protocols/mediator/ConnectWithMediatorService.ts +++ b/src/protocols/mediator/ConnectWithMediatorService.ts @@ -5,13 +5,31 @@ import { MediatorResponse } from "./MediatorInterface"; import { NetworkServices } from "../../network"; -import { RecordType } from '../../utils/Helpers' -import { WalletRecord } from '../../wallet/WalletInterface'; +import { decodeInvitationFromUrl, RecordType } from '../../utils/Helpers' +import { WalletConfig, WalletCredentials, WalletRecord } from '../../wallet/WalletInterface'; import DatabaseServices from "../../storage"; import WalletStorageService from '../../wallet/WalletStorageService'; +import ConnectionService from "../connection/ConnectionService"; class MediatorService { + + async connectWithGenericMediator( + configJson: WalletConfig, + credentialsJson: WalletCredentials, + invitationUrl: string): Promise { + try { + console.log(invitationUrl) + const invitationJson = decodeInvitationFromUrl(invitationUrl); + console.log(invitationJson) + const connectionRecord = await ConnectionService.acceptInvitation(configJson, credentialsJson, {}, invitationJson, ''); + console.log('connectionRecord', connectionRecord) + + } catch (error) { + console.log('Error ConnectWithNewMediator', error) + } + } + /** * Connect the mediator agent and store the mediator record * diff --git a/src/transports/index.ts b/src/transports/index.ts index 90f3322..12c7fc3 100644 --- a/src/transports/index.ts +++ b/src/transports/index.ts @@ -107,6 +107,24 @@ class InboundMessageHandler { } }); + addMessages = async (message: Object) => { + this.wallet = await DatabaseServices.getWallet() + + const ssiMessageTags = { + messageId: Math.floor(Math.random() * 1000000000).toString(), + autoProcessed: JSON.stringify(true), + isProcessed: JSON.stringify(false), + } + await WalletStorageService.addWalletRecord( + JSON.parse(this.wallet.walletConfig), JSON.parse(this.wallet.walletCredentials), + RecordType.SSIMessage, + ssiMessageTags.messageId, + JSON.stringify(message), + JSON.stringify(ssiMessageTags) + ); + EventRegister.emit('proceedInboundMessage', `proceedInboundMessage`); + } + proceedInboundMessage = async () => { try { const query: Object = { isProcessed: JSON.stringify(false) } @@ -118,9 +136,11 @@ class InboundMessageHandler { this.isProcess = true; if (unprocessedMessages[i].tags.autoProcessed === 'true') { const messageRecord = JSON.parse(unprocessedMessages[i].value); - const unpackMessageResponse = await unpackMessage(JSON.parse(this.wallet.walletConfig), JSON.parse(this.wallet.walletCredentials), messageRecord.msg); + console.log('messageRecord', messageRecord); + const unpackMessageResponse = await unpackMessage(JSON.parse(this.wallet.walletConfig), JSON.parse(this.wallet.walletCredentials), messageRecord); const message = JSON.parse(unpackMessageResponse.message); + console.log('Message Type = ', message['@type']); switch (message['@type']) { case MessageType.ConnectionResponse: { const isCompleted = await ConnectionService.processRequest(JSON.parse(this.wallet.walletConfig), JSON.parse(this.wallet.walletCredentials), unpackMessageResponse); diff --git a/src/utils/Helpers.ts b/src/utils/Helpers.ts index b6cb928..6bb67b9 100644 --- a/src/utils/Helpers.ts +++ b/src/utils/Helpers.ts @@ -15,6 +15,7 @@ import base64url from 'base64url'; import DatabaseServices from '../storage'; const Buffer = require('buffer').Buffer; +global.Buffer = global.Buffer || require('buffer').Buffer const { ArnimaSdk } = NativeModules; @@ -123,6 +124,7 @@ export async function sign(configJson: WalletConfig, credentialsJson: WalletCred export async function unpackMessage(configJson: WalletConfig, credentialsJson: WalletCredentials, inboundMessage: InboundMessage) { try { + console.log('inboundMessage', inboundMessage) const buf = Buffer.from(JSON.stringify(inboundMessage)); let unpackedBufferMessage; if (Platform.OS === 'ios') { @@ -132,6 +134,7 @@ export async function unpackMessage(configJson: WalletConfig, credentialsJson: W unpackedBufferMessage = await ArnimaSdk.unpackMessage(JSON.stringify(configJson), JSON.stringify(credentialsJson), Array.from(buf)) } const unpackedMessage = Buffer.from(unpackedBufferMessage); + console.log('unpackedMessage', unpackedMessage.toString('utf-8')) return JSON.parse(unpackedMessage.toString('utf-8')); } catch (error) { console.log("unpackMessage = ", error); @@ -142,6 +145,7 @@ export async function unpackMessage(configJson: WalletConfig, credentialsJson: W export async function packMessage(configJson: WalletConfig, credentialsJson: WalletCredentials, outboundMessage: OutboundMessage) { try { const { routingKeys, recipientKeys, senderVk, payload } = outboundMessage; + console.log("outboundMessage", outboundMessage) const buf = Buffer.from(JSON.stringify(payload)); let packedBufferMessage; if (Platform.OS === 'ios') { @@ -205,8 +209,12 @@ export function encodeBase64(data: string) { } export function createOutboundMessage(connection: Connection, payload: Object, invitation?: Message) { + payload['~transport'] = { + return_route: 'all' + } + if (invitation) { - const { recipientKeys, routingKeys, serviceEndpoint } = invitation + const { recipientKeys, routingKeys, serviceEndpoint } = invitation; return { connection, endpoint: serviceEndpoint, diff --git a/src/utils/MessageType.ts b/src/utils/MessageType.ts index 4a58385..2dcdce6 100644 --- a/src/utils/MessageType.ts +++ b/src/utils/MessageType.ts @@ -4,31 +4,31 @@ */ export enum MessageType { - ConnectionInvitation = 'did:sov:BzCbsNYhMrjHiqZDTUASHg;spec/connections/1.0/invitation', - ConnectionRequest = 'did:sov:BzCbsNYhMrjHiqZDTUASHg;spec/connections/1.0/request', - ConnectionResponse = 'did:sov:BzCbsNYhMrjHiqZDTUASHg;spec/connections/1.0/response', + ConnectionInvitation = 'https://didcomm.org/connections/1.0/invitation', + ConnectionRequest = 'https://didcomm.org/connections/1.0/request', + ConnectionResponse = 'https://didcomm.org/connections/1.0/response', - TrustPingMessage = 'did:sov:BzCbsNYhMrjHiqZDTUASHg;spec/trust_ping/1.0/ping', - TrustPingResponseMessage = 'did:sov:BzCbsNYhMrjHiqZDTUASHg;spec/trust_ping/1.0/ping_response', + TrustPingMessage = 'https://didcomm.org/trust_ping/1.0/ping', + TrustPingResponseMessage = 'https://didcomm.org/trust_ping/1.0/ping_response', - ProposeCredential = 'did:sov:BzCbsNYhMrjHiqZDTUASHg;spec/issue-credential/1.0/propose-credential', - OfferCredential = 'did:sov:BzCbsNYhMrjHiqZDTUASHg;spec/issue-credential/1.0/offer-credential', - RequestCredential = 'did:sov:BzCbsNYhMrjHiqZDTUASHg;spec/issue-credential/1.0/request-credential', - IssueCredential = 'did:sov:BzCbsNYhMrjHiqZDTUASHg;spec/issue-credential/1.0/issue-credential', - CredentialAck = 'did:sov:BzCbsNYhMrjHiqZDTUASHg;spec/issue-credential/1.0/ack', - credentialPreview = 'did:sov:BzCbsNYhMrjHiqZDTUASHg;spec/issue-credential/1.0/credential-preview', + ProposeCredential = 'https://didcomm.org/issue-credential/1.0/propose-credential', + OfferCredential = 'https://didcomm.org/issue-credential/1.0/offer-credential', + RequestCredential = 'https://didcomm.org/issue-credential/1.0/request-credential', + IssueCredential = 'https://didcomm.org/issue-credential/1.0/issue-credential', + CredentialAck = 'https://didcomm.org/issue-credential/1.0/ack', + credentialPreview = 'https://didcomm.org/issue-credential/1.0/credential-preview', - ProposePresentation = 'did:sov:BzCbsNYhMrjHiqZDTUASHg;spec/present-proof/1.0/propose-presentation', - RequestPresentation = 'did:sov:BzCbsNYhMrjHiqZDTUASHg;spec/present-proof/1.0/request-presentation', - Presentation = 'did:sov:BzCbsNYhMrjHiqZDTUASHg;spec/present-proof/1.0/presentation', - PresentationAck = 'did:sov:BzCbsNYhMrjHiqZDTUASHg;spec/present-proof/1.0/ack', - presentationPreview = "did:sov:BzCbsNYhMrjHiqZDTUASHg;spec/present-proof/1.0/presentation-preview", + ProposePresentation = 'https://didcomm.org/present-proof/1.0/propose-presentation', + RequestPresentation = 'https://didcomm.org/present-proof/1.0/request-presentation', + Presentation = 'https://didcomm.org/present-proof/1.0/presentation', + PresentationAck = 'https://didcomm.org/present-proof/1.0/ack', + presentationPreview = "https://didcomm.org/present-proof/1.0/presentation-preview", - BasicMessage = 'did:sov:BzCbsNYhMrjHiqZDTUASHg;spec/basicmessage/1.0/message', + BasicMessage = 'https://didcomm.org/basicmessage/1.0/message', - ForwardMessage = 'did:sov:BzCbsNYhMrjHiqZDTUASHg;spec/routing/1.0/forward', + ForwardMessage = 'https://didcomm.org/routing/1.0/forward', - Ack = 'did:sov:BzCbsNYhMrjHiqZDTUASHg;spec/notification/1.0/ack', + Ack = 'https://didcomm.org/notification/1.0/ack', - problemReport = "did:sov:BzCbsNYhMrjHiqZDTUASHg;spec/notification/1.0/problem-report" + problemReport = "https://didcomm.org/notification/1.0/problem-report" } From f3236cede339c577fb90bf0ec130e32448364a75 Mon Sep 17 00:00:00 2001 From: Sai Ranjit Tummalapalli Date: Fri, 20 Aug 2021 10:56:28 +0530 Subject: [PATCH 02/14] feat: added mediation request and batch messages Signed-off-by: Sai Ranjit Tummalapalli --- src/agent/index.ts | 30 +++++++++- src/protocols/connection/ConnectionService.ts | 27 +++++++-- .../mediator/ConnectWithMediatorService.ts | 60 +++++++++++++++++-- src/protocols/mediator/MediationMessages.ts | 26 ++++++++ src/transports/index.ts | 22 ++++++- src/utils/Helpers.ts | 15 +++++ src/utils/MessageType.ts | 46 +++++++------- 7 files changed, 192 insertions(+), 34 deletions(-) create mode 100644 src/protocols/mediator/MediationMessages.ts diff --git a/src/agent/index.ts b/src/agent/index.ts index f7dddab..c37651b 100644 --- a/src/agent/index.ts +++ b/src/agent/index.ts @@ -19,6 +19,7 @@ import PoolService from '../pool'; import PresentationService from '../protocols/presentation/PresentationService'; import WalletService from '../wallet/WalletService'; import WalletStorageService from '../wallet/WalletStorageService'; +import { Connection } from 'react-native-arnima-sdk/src/protocols/connection/ConnectionInterface'; const { ArnimaSdk } = NativeModules; @@ -61,6 +62,24 @@ class Agent { } } + mediationRequest = async (connection: Connection) => { + try { + const response = await ConnectWithMediatorService.mediationRequest(connection); + } catch (error) { + console.log("Agent - mediationRequest error = ", error); + throw error; + } + } + + pickupMessages = async (mediatorConnection: Connection) => { + try { + const response = await ConnectWithMediatorService.pickupMessages(mediatorConnection); + } catch (error) { + console.log("Agent - pickupMessages error = ", error); + throw error; + } + } + updateMediator = async (url: string, apiType: string, apiBody: string) => { try { return await ConnectWithMediatorService.updateMediator(url, apiType, apiBody); @@ -126,10 +145,17 @@ class Agent { } } - acceptInvitation = async (didJson: Object, message: any, logo: string,) => { + acceptInvitation = async (didJson: Object, message: any, logo: string, isMediator: boolean = false) => { try { const invitation = decodeInvitationFromUrl(message); - return await ConnectionService.acceptInvitation(JSON.parse(this.wallet.walletConfig), JSON.parse(this.wallet.walletCredentials), didJson, invitation, logo); + return await ConnectionService.acceptInvitation( + JSON.parse(this.wallet.walletConfig), + JSON.parse(this.wallet.walletCredentials), + didJson, + invitation, + logo, + isMediator + ); } catch (error) { console.log("Agent - Accept invitation error = ", error); diff --git a/src/protocols/connection/ConnectionService.ts b/src/protocols/connection/ConnectionService.ts index bb38ff3..abb62cc 100644 --- a/src/protocols/connection/ConnectionService.ts +++ b/src/protocols/connection/ConnectionService.ts @@ -100,13 +100,15 @@ class ConnectionService { credentialsJson: WalletCredentials, didJson: Object, invitation: Message, - logo: string): Promise { + logo: string, + isMediator: boolean + ): Promise { try { const connection: Connection = await this.createConnection( configJson, credentialsJson, didJson, - invitation.serviceEndpoint, + isMediator, invitation.label, invitation.hasOwnProperty('alias') ? invitation.alias.logoUrl : '', invitation.hasOwnProperty('alias') ? invitation.alias.organizationId : '', @@ -279,10 +281,11 @@ class ConnectionService { * @return {*} {Promise} * @memberof ConnectionService */ - async createConnection(configJson: WalletConfig, + async createConnection( + configJson: WalletConfig, credentialsJson: WalletCredentials, didJson: Object, - endpoint: string, + isMediator: boolean, label?: string, logo?: string, organizationId?: string, @@ -296,9 +299,23 @@ class ConnectionService { // }; // await NetworkServices(getServiceEndpoint() + 'verkey', 'POST', JSON.stringify(apiBody)); + let endpoint = ''; + let routingKeys: string[] = []; + console.log('isMediator', isMediator) + if (isMediator) { + endpoint = 'didcomm:transport/queue'; + } else { + const routingKey: string = DatabaseServices.getRoutingKeys() + console.log('routingKey', routingKey) + endpoint = getServiceEndpoint(); + routingKeys.push(routingKey); + } + console.log(routingKeys) + + console.log('Connection - createConnection - pairwiseDid = ', verkey); const publicKey = new PublicKey(`${pairwiseDid}#1`, PublicKeyType.ED25519_SIG_2018, pairwiseDid, verkey); - const service = new Service(`${pairwiseDid};indy`, 'didcomm:transport/queue', [verkey], [], 0, 'IndyAgent'); + const service = new Service(`${pairwiseDid};indy`, endpoint, [verkey], routingKeys, 0, 'IndyAgent'); const auth = new Authentication(publicKey); const did_doc = new DidDoc(pairwiseDid, [auth], [publicKey], [service]); diff --git a/src/protocols/mediator/ConnectWithMediatorService.ts b/src/protocols/mediator/ConnectWithMediatorService.ts index ba4aafb..268d773 100644 --- a/src/protocols/mediator/ConnectWithMediatorService.ts +++ b/src/protocols/mediator/ConnectWithMediatorService.ts @@ -5,15 +5,15 @@ import { MediatorResponse } from "./MediatorInterface"; import { NetworkServices } from "../../network"; -import { decodeInvitationFromUrl, RecordType } from '../../utils/Helpers' +import { decodeInvitationFromUrl, RecordType, sendOutboundMessage } from '../../utils/Helpers' import { WalletConfig, WalletCredentials, WalletRecord } from '../../wallet/WalletInterface'; import DatabaseServices from "../../storage"; import WalletStorageService from '../../wallet/WalletStorageService'; import ConnectionService from "../connection/ConnectionService"; +import { createBatchPickupMessage, createMediationRequestMessage } from "react-native-arnima-sdk/src/protocols/mediator/MediationMessages"; +import { Connection } from "react-native-arnima-sdk/src/protocols/connection/ConnectionInterface"; class MediatorService { - - async connectWithGenericMediator( configJson: WalletConfig, credentialsJson: WalletCredentials, @@ -22,7 +22,7 @@ class MediatorService { console.log(invitationUrl) const invitationJson = decodeInvitationFromUrl(invitationUrl); console.log(invitationJson) - const connectionRecord = await ConnectionService.acceptInvitation(configJson, credentialsJson, {}, invitationJson, ''); + const connectionRecord = await ConnectionService.acceptInvitation(configJson, credentialsJson, {}, invitationJson, '', true); console.log('connectionRecord', connectionRecord) } catch (error) { @@ -30,6 +30,58 @@ class MediatorService { } } + async mediationRequest(connection: Connection) { + const myWallet: any = DatabaseServices.getWallet(); + const message = await createMediationRequestMessage(); + + const connectionTags: Object = { + connectionId: connection.verkey, + } + await WalletStorageService.addWalletRecord( + myWallet.walletConfig, + myWallet.walletConfig, + RecordType.MediatorAgent, + connection.verkey, + JSON.stringify(connection), + JSON.stringify(connectionTags) + ); + await sendOutboundMessage( + JSON.parse(myWallet.walletConfig), + JSON.parse(myWallet.walletConfig), + connection, + message + ); + return true + } + + async saveRoutingKeys(message) { + const myWallet: any = DatabaseServices.getWallet(); + + DatabaseServices.storeWallet({ + walletConfig: myWallet.walletConfig, + walletCredentials: myWallet.credentialsJson, + label: myWallet.label, + serviceEndpoint: message.endpoint, + routingKey: message.routing_keys[0], + publicDid: myWallet.publicDid, + verKey: myWallet.verKey, + masterSecretId: myWallet.masterSecretId, + }); + return true + } + + async pickupMessages(mediatorConnection: Connection) { + const myWallet: any = DatabaseServices.getWallet(); + const batchPickupMessage = await createBatchPickupMessage(); + await sendOutboundMessage( + JSON.parse(myWallet.walletConfig), + JSON.parse(myWallet.walletConfig), + mediatorConnection, + batchPickupMessage, + ); + return true + } + /** * Connect the mediator agent and store the mediator record * diff --git a/src/protocols/mediator/MediationMessages.ts b/src/protocols/mediator/MediationMessages.ts new file mode 100644 index 0000000..587a783 --- /dev/null +++ b/src/protocols/mediator/MediationMessages.ts @@ -0,0 +1,26 @@ +/* + Copyright AyanWorks Technology Solutions Pvt. Ltd. All Rights Reserved. + SPDX-License-Identifier: Apache-2.0 +*/ + +import { MessageType } from "../../utils/MessageType"; +import uuid from 'uuid/v4'; + +export async function createMediationRequestMessage() { + return { + '@type': MessageType.MediationRequest, + '@id': uuid(), + sent_time: new Date().toISOString(), + '~l10n': { + locale: 'en', + } + }; +} + +export async function createBatchPickupMessage(batchSize: number = 10) { + return { + '@type': MessageType.BatchPickup, + '@id': uuid(), + batch_size: batchSize, + }; +} \ No newline at end of file diff --git a/src/transports/index.ts b/src/transports/index.ts index 12c7fc3..9409860 100644 --- a/src/transports/index.ts +++ b/src/transports/index.ts @@ -8,7 +8,7 @@ import { EventInterface } from "../agent/EventInterface"; import { EventRegister } from 'react-native-event-listeners'; import { MessageType } from "../utils/MessageType"; import { Record } from "../wallet/WalletInterface"; -import { RecordType, getServiceEndpoint, unpackMessage } from "../utils/Helpers"; +import { RecordType, getServiceEndpoint, unpackMessage, replaceDidSovPrefixOnMessage } from "../utils/Helpers"; import BasicMessageService from "../protocols/basicMessage/BasicMessageService"; import ConnectionService from "../protocols/connection/ConnectionService"; import CredentialService from "../protocols/credential/CredentialService"; @@ -17,6 +17,7 @@ import io from "socket.io-client"; import PresentationService from "../protocols/presentation/PresentationService"; import TrustPingService from "../protocols/trustPing/TrustPingService"; import WalletStorageService from "../wallet/WalletStorageService"; +import ConnectWithMediatorService from "react-native-arnima-sdk/src/protocols/mediator/ConnectWithMediatorService"; class InboundMessageHandler { @@ -140,6 +141,7 @@ class InboundMessageHandler { const unpackMessageResponse = await unpackMessage(JSON.parse(this.wallet.walletConfig), JSON.parse(this.wallet.walletCredentials), messageRecord); const message = JSON.parse(unpackMessageResponse.message); + replaceDidSovPrefixOnMessage(message); console.log('Message Type = ', message['@type']); switch (message['@type']) { case MessageType.ConnectionResponse: { @@ -274,13 +276,27 @@ class InboundMessageHandler { const event: EventInterface = { - message: `You have received a message from ${connection.theirLabel}`, - connectionId: connection.verkey, + message: `You have received a message from ${connection.theirLabel}`, + connectionId: connection.verkey, messageData: JSON.stringify({}) } EventRegister.emit('SDKEvent', event); break; } + + case MessageType.MediationGrant: { + const isCompleted = await ConnectWithMediatorService.saveRoutingKeys(message); + if (isCompleted) { await WalletStorageService.deleteWalletRecord(JSON.parse(this.wallet.walletConfig), JSON.parse(this.wallet.walletCredentials), RecordType.SSIMessage, unprocessedMessages[i].id) } + break; + } + + case MessageType.Batch: { + console.log(message); + // if (isCompleted) { + await WalletStorageService.deleteWalletRecord(JSON.parse(this.wallet.walletConfig), JSON.parse(this.wallet.walletCredentials), RecordType.SSIMessage, unprocessedMessages[i].id) + // } + break; + } default: { break; } diff --git a/src/utils/Helpers.ts b/src/utils/Helpers.ts index 6bb67b9..d975e92 100644 --- a/src/utils/Helpers.ts +++ b/src/utils/Helpers.ts @@ -246,3 +246,18 @@ export async function sendOutboundMessage(configJson: WalletConfig, credentialsJ const outboundPackMessage = await packMessage(configJson, credentialsJson, outboundMessage); await OutboundAgentMessage(outboundMessage.endpoint, 'POST', JSON.stringify(outboundPackMessage)); } + +export function replaceDidSovPrefixOnMessage(message) { + message['@type'] = replaceDidSovPrefix(message['@type']) +} + +export function replaceDidSovPrefix(messageType: string) { + const didSovPrefix = 'did:sov:BzCbsNYhMrjHiqZDTUASHg;spec' + const didCommPrefix = 'https://didcomm.org' + + if (messageType.startsWith(didCommPrefix)) { + return messageType.replace(didCommPrefix, didSovPrefix) + } + + return messageType +} \ No newline at end of file diff --git a/src/utils/MessageType.ts b/src/utils/MessageType.ts index 2dcdce6..5814979 100644 --- a/src/utils/MessageType.ts +++ b/src/utils/MessageType.ts @@ -4,31 +4,37 @@ */ export enum MessageType { - ConnectionInvitation = 'https://didcomm.org/connections/1.0/invitation', - ConnectionRequest = 'https://didcomm.org/connections/1.0/request', - ConnectionResponse = 'https://didcomm.org/connections/1.0/response', + ConnectionInvitation = 'did:sov:BzCbsNYhMrjHiqZDTUASHg;spec/connections/1.0/invitation', + ConnectionRequest = 'did:sov:BzCbsNYhMrjHiqZDTUASHg;spec/connections/1.0/request', + ConnectionResponse = 'did:sov:BzCbsNYhMrjHiqZDTUASHg;spec/connections/1.0/response', - TrustPingMessage = 'https://didcomm.org/trust_ping/1.0/ping', - TrustPingResponseMessage = 'https://didcomm.org/trust_ping/1.0/ping_response', + TrustPingMessage = 'did:sov:BzCbsNYhMrjHiqZDTUASHg;spec/trust_ping/1.0/ping', + TrustPingResponseMessage = 'did:sov:BzCbsNYhMrjHiqZDTUASHg;spec/trust_ping/1.0/ping_response', - ProposeCredential = 'https://didcomm.org/issue-credential/1.0/propose-credential', - OfferCredential = 'https://didcomm.org/issue-credential/1.0/offer-credential', - RequestCredential = 'https://didcomm.org/issue-credential/1.0/request-credential', - IssueCredential = 'https://didcomm.org/issue-credential/1.0/issue-credential', - CredentialAck = 'https://didcomm.org/issue-credential/1.0/ack', - credentialPreview = 'https://didcomm.org/issue-credential/1.0/credential-preview', + ProposeCredential = 'did:sov:BzCbsNYhMrjHiqZDTUASHg;spec/issue-credential/1.0/propose-credential', + OfferCredential = 'did:sov:BzCbsNYhMrjHiqZDTUASHg;spec/issue-credential/1.0/offer-credential', + RequestCredential = 'did:sov:BzCbsNYhMrjHiqZDTUASHg;spec/issue-credential/1.0/request-credential', + IssueCredential = 'did:sov:BzCbsNYhMrjHiqZDTUASHg;spec/issue-credential/1.0/issue-credential', + CredentialAck = 'did:sov:BzCbsNYhMrjHiqZDTUASHg;spec/issue-credential/1.0/ack', + credentialPreview = 'did:sov:BzCbsNYhMrjHiqZDTUASHg;spec/issue-credential/1.0/credential-preview', - ProposePresentation = 'https://didcomm.org/present-proof/1.0/propose-presentation', - RequestPresentation = 'https://didcomm.org/present-proof/1.0/request-presentation', - Presentation = 'https://didcomm.org/present-proof/1.0/presentation', - PresentationAck = 'https://didcomm.org/present-proof/1.0/ack', - presentationPreview = "https://didcomm.org/present-proof/1.0/presentation-preview", + ProposePresentation = 'did:sov:BzCbsNYhMrjHiqZDTUASHg;spec/present-proof/1.0/propose-presentation', + RequestPresentation = 'did:sov:BzCbsNYhMrjHiqZDTUASHg;spec/present-proof/1.0/request-presentation', + Presentation = 'did:sov:BzCbsNYhMrjHiqZDTUASHg;spec/present-proof/1.0/presentation', + PresentationAck = 'did:sov:BzCbsNYhMrjHiqZDTUASHg;spec/present-proof/1.0/ack', + presentationPreview = "did:sov:BzCbsNYhMrjHiqZDTUASHg;spec/present-proof/1.0/presentation-preview", - BasicMessage = 'https://didcomm.org/basicmessage/1.0/message', + BasicMessage = 'did:sov:BzCbsNYhMrjHiqZDTUASHg;spec/basicmessage/1.0/message', - ForwardMessage = 'https://didcomm.org/routing/1.0/forward', + ForwardMessage = 'did:sov:BzCbsNYhMrjHiqZDTUASHg;spec/routing/1.0/forward', - Ack = 'https://didcomm.org/notification/1.0/ack', + Ack = 'did:sov:BzCbsNYhMrjHiqZDTUASHg;spec/notification/1.0/ack', - problemReport = "https://didcomm.org/notification/1.0/problem-report" + problemReport = "did:sov:BzCbsNYhMrjHiqZDTUASHg;spec/notification/1.0/problem-report", + + MediationRequest = "did:sov:BzCbsNYhMrjHiqZDTUASHg;spec/coordinate-mediation/1.0/mediate-request", + MediationGrant = "did:sov:BzCbsNYhMrjHiqZDTUASHg;spec/coordinate-mediation/1.0/mediate-grant", + + BatchPickup = "did:sov:BzCbsNYhMrjHiqZDTUASHg;spec/messagepickup/1.0/batch-pickup", + Batch = "did:sov:BzCbsNYhMrjHiqZDTUASHg;spec/messagepickup/1.0/batch" } From 855396dc8082f3b0afa7917797c6e837b890b536 Mon Sep 17 00:00:00 2001 From: Sai Ranjit Tummalapalli Date: Fri, 20 Aug 2021 14:19:14 +0530 Subject: [PATCH 03/14] feat: added keylist update messages for mediation Signed-off-by: Sai Ranjit Tummalapalli --- src/agent/index.ts | 11 ++++ src/protocols/connection/ConnectionService.ts | 31 ++++------- .../mediator/ConnectWithMediatorService.ts | 52 ++++++++++++++++++- src/protocols/mediator/MediationMessages.ts | 11 ++++ src/transports/index.ts | 11 ++-- src/utils/Helpers.ts | 7 +-- src/utils/MessageType.ts | 2 + src/wallet/WalletService.ts | 48 ++++++++--------- 8 files changed, 120 insertions(+), 53 deletions(-) diff --git a/src/agent/index.ts b/src/agent/index.ts index c37651b..d889668 100644 --- a/src/agent/index.ts +++ b/src/agent/index.ts @@ -147,6 +147,7 @@ class Agent { acceptInvitation = async (didJson: Object, message: any, logo: string, isMediator: boolean = false) => { try { + this.wallet = await DatabaseServices.getWallet(); const invitation = decodeInvitationFromUrl(message); return await ConnectionService.acceptInvitation( JSON.parse(this.wallet.walletConfig), @@ -173,6 +174,16 @@ class Agent { } } + getMediatorRecord = async (query: Object) => { + try { + return await WalletStorageService.getWalletRecordsFromQuery(JSON.parse(this.wallet.walletConfig), JSON.parse(this.wallet.walletCredentials), RecordType.MediatorAgent, JSON.stringify(query)); + } + catch (error) { + console.log("Agent - Get all connections error = ", error); + throw error; + } + } + getPresentationRecord = async (query: Object) => { try { return await WalletStorageService.getWalletRecordsFromQuery(JSON.parse(this.wallet.walletConfig), JSON.parse(this.wallet.walletCredentials), RecordType.Presentation, JSON.stringify(query)); diff --git a/src/protocols/connection/ConnectionService.ts b/src/protocols/connection/ConnectionService.ts index abb62cc..f20a74f 100644 --- a/src/protocols/connection/ConnectionService.ts +++ b/src/protocols/connection/ConnectionService.ts @@ -22,6 +22,7 @@ import { TrustPing } from "../trustPing/TrustPingInterface"; import { TrustPingState } from '../trustPing/TrustPingState'; import WalletStorageService from '../../wallet/WalletStorageService'; import { createTrustPingMessage } from '../trustPing/TrustPingMessages'; +import ConnectWithMediatorService from 'react-native-arnima-sdk/src/protocols/mediator/ConnectWithMediatorService'; const { ArnimaSdk } = NativeModules; class ConnectionService { @@ -104,11 +105,13 @@ class ConnectionService { isMediator: boolean ): Promise { try { + const routing = await ConnectWithMediatorService.getRouting(); const connection: Connection = await this.createConnection( configJson, credentialsJson, didJson, isMediator, + routing, invitation.label, invitation.hasOwnProperty('alias') ? invitation.alias.logoUrl : '', invitation.hasOwnProperty('alias') ? invitation.alias.organizationId : '', @@ -286,34 +289,20 @@ class ConnectionService { credentialsJson: WalletCredentials, didJson: Object, isMediator: boolean, + routing: { + endpoint: string; + routingKeys: string[]; + pairwiseDid: string; + verkey: string; + }, label?: string, logo?: string, organizationId?: string, ): Promise { try { - const [pairwiseDid, verkey]: string[] = await ArnimaSdk.createAndStoreMyDid(JSON.stringify(configJson), JSON.stringify(credentialsJson), JSON.stringify(didJson), false); + const { endpoint, pairwiseDid, routingKeys, verkey } = routing; - // const apiBody = { - // publicVerkey: DatabaseServices.getVerKey(), - // verkey: verkey - // }; - // await NetworkServices(getServiceEndpoint() + 'verkey', 'POST', JSON.stringify(apiBody)); - let endpoint = ''; - let routingKeys: string[] = []; - console.log('isMediator', isMediator) - if (isMediator) { - endpoint = 'didcomm:transport/queue'; - } else { - const routingKey: string = DatabaseServices.getRoutingKeys() - console.log('routingKey', routingKey) - endpoint = getServiceEndpoint(); - routingKeys.push(routingKey); - } - console.log(routingKeys) - - - console.log('Connection - createConnection - pairwiseDid = ', verkey); const publicKey = new PublicKey(`${pairwiseDid}#1`, PublicKeyType.ED25519_SIG_2018, pairwiseDid, verkey); const service = new Service(`${pairwiseDid};indy`, endpoint, [verkey], routingKeys, 0, 'IndyAgent'); const auth = new Authentication(publicKey); diff --git a/src/protocols/mediator/ConnectWithMediatorService.ts b/src/protocols/mediator/ConnectWithMediatorService.ts index 268d773..db6597e 100644 --- a/src/protocols/mediator/ConnectWithMediatorService.ts +++ b/src/protocols/mediator/ConnectWithMediatorService.ts @@ -10,8 +10,11 @@ import { WalletConfig, WalletCredentials, WalletRecord } from '../../wallet/Wall import DatabaseServices from "../../storage"; import WalletStorageService from '../../wallet/WalletStorageService'; import ConnectionService from "../connection/ConnectionService"; -import { createBatchPickupMessage, createMediationRequestMessage } from "react-native-arnima-sdk/src/protocols/mediator/MediationMessages"; +import { createBatchPickupMessage, createKeylistUpdateMessage, createMediationRequestMessage } from "react-native-arnima-sdk/src/protocols/mediator/MediationMessages"; import { Connection } from "react-native-arnima-sdk/src/protocols/connection/ConnectionInterface"; +import { NativeModules } from "react-native"; + +const { ArnimaSdk } = NativeModules; class MediatorService { async connectWithGenericMediator( @@ -75,13 +78,58 @@ class MediatorService { const batchPickupMessage = await createBatchPickupMessage(); await sendOutboundMessage( JSON.parse(myWallet.walletConfig), - JSON.parse(myWallet.walletConfig), + JSON.parse(myWallet.walletCredentials), mediatorConnection, batchPickupMessage, ); return true } + async getRouting() { + try { + const myWallet: any = DatabaseServices.getWallet(); + const endpoint = myWallet.serviceEndpoint !== "" ? myWallet.serviceEndpoint : 'didcomm:transport/queue' + const routingKeys: string[] = myWallet.routingKey !== '' ? [myWallet.routingKey] : [] + const [pairwiseDid, verkey]: string[] = await ArnimaSdk.createAndStoreMyDid( + myWallet.walletConfig, + myWallet.walletCredentials, + JSON.stringify({}), + false + ); + await this.keylistUpdate(verkey); + + console.log(5) + return { endpoint, routingKeys, pairwiseDid, verkey }; + } catch (error) { + console.log('MediatorService - getRouting error = ', error); + throw error; + } + } + + async keylistUpdate(verkey: string) { + try { + const myWallet: any = DatabaseServices.getWallet(); + const keylistUpdateMessage = await createKeylistUpdateMessage(verkey); + const [mediatorConnection] = await WalletStorageService.getWalletRecordsFromQuery( + JSON.parse(myWallet.walletConfig), + JSON.parse(myWallet.walletCredentials), + RecordType.MediatorAgent, + JSON.stringify({}) + ); + if (mediatorConnection) { + await sendOutboundMessage( + JSON.parse(myWallet.walletConfig), + JSON.parse(myWallet.walletCredentials), + JSON.parse(mediatorConnection.value), + keylistUpdateMessage, + ) + } + } catch (error) { + console.log('MediatorService - keylistUpdate error = ', error); + throw error; + } + } + /** * Connect the mediator agent and store the mediator record * diff --git a/src/protocols/mediator/MediationMessages.ts b/src/protocols/mediator/MediationMessages.ts index 587a783..2aa27cb 100644 --- a/src/protocols/mediator/MediationMessages.ts +++ b/src/protocols/mediator/MediationMessages.ts @@ -23,4 +23,15 @@ export async function createBatchPickupMessage(batchSize: number = 10) { '@id': uuid(), batch_size: batchSize, }; +} + +export async function createKeylistUpdateMessage(verkey: string) { + return { + '@type': MessageType.KeyListUpdate, + '@id': uuid(), + updates: [{ + "recipient_key": verkey, + action: "add" + }] + }; } \ No newline at end of file diff --git a/src/transports/index.ts b/src/transports/index.ts index 9409860..e709ca2 100644 --- a/src/transports/index.ts +++ b/src/transports/index.ts @@ -291,10 +291,15 @@ class InboundMessageHandler { } case MessageType.Batch: { - console.log(message); - // if (isCompleted) { + await message['messages~attach'].map(async (message) => { + await this.addMessages(message.message); + }) await WalletStorageService.deleteWalletRecord(JSON.parse(this.wallet.walletConfig), JSON.parse(this.wallet.walletCredentials), RecordType.SSIMessage, unprocessedMessages[i].id) - // } + break; + } + case MessageType.KeyListUpdateResponse: { + await WalletStorageService.deleteWalletRecord(JSON.parse(this.wallet.walletConfig), JSON.parse(this.wallet.walletCredentials), RecordType.SSIMessage, unprocessedMessages[i].id) + break; } default: { diff --git a/src/utils/Helpers.ts b/src/utils/Helpers.ts index d975e92..731a865 100644 --- a/src/utils/Helpers.ts +++ b/src/utils/Helpers.ts @@ -209,10 +209,11 @@ export function encodeBase64(data: string) { } export function createOutboundMessage(connection: Connection, payload: Object, invitation?: Message) { - payload['~transport'] = { - return_route: 'all' + if (connection.didDoc.service[0].serviceEndpoint == 'didcomm:transport/queue') { + payload['~transport'] = { + return_route: 'all' + } } - if (invitation) { const { recipientKeys, routingKeys, serviceEndpoint } = invitation; return { diff --git a/src/utils/MessageType.ts b/src/utils/MessageType.ts index 5814979..17d261f 100644 --- a/src/utils/MessageType.ts +++ b/src/utils/MessageType.ts @@ -34,6 +34,8 @@ export enum MessageType { MediationRequest = "did:sov:BzCbsNYhMrjHiqZDTUASHg;spec/coordinate-mediation/1.0/mediate-request", MediationGrant = "did:sov:BzCbsNYhMrjHiqZDTUASHg;spec/coordinate-mediation/1.0/mediate-grant", + KeyListUpdate = "did:sov:BzCbsNYhMrjHiqZDTUASHg;spec/coordinatemediation/1.0/keylist-update", + KeyListUpdateResponse = "did:sov:BzCbsNYhMrjHiqZDTUASHg;spec/coordinatemediation/1.0/keylist-update-response", BatchPickup = "did:sov:BzCbsNYhMrjHiqZDTUASHg;spec/messagepickup/1.0/batch-pickup", Batch = "did:sov:BzCbsNYhMrjHiqZDTUASHg;spec/messagepickup/1.0/batch" diff --git a/src/wallet/WalletService.ts b/src/wallet/WalletService.ts index a61fbc8..2ed36ae 100644 --- a/src/wallet/WalletService.ts +++ b/src/wallet/WalletService.ts @@ -52,32 +52,32 @@ class WalletService { verKey: verkey, masterSecretId: masterSecretId, }); + // TODO : Can remove if not required + // const walletRecord: WalletRecord = { + // walletConfig: config, + // walletCredentials: credentials, + // label: label, + // serviceEndpoint: "", + // routingKey: "", + // publicDid: did, + // verKey: verkey, + // masterSecretId: masterSecretId, + // } - const walletRecord: WalletRecord = { - walletConfig: config, - walletCredentials: credentials, - label: label, - serviceEndpoint: "", - routingKey: "", - publicDid: did, - verKey: verkey, - masterSecretId: masterSecretId, - } + // const walletRecordTags: Object = { + // walletName: label, + // publicDid: did, + // verKey: verkey, + // } - const walletRecordTags: Object = { - walletName: label, - publicDid: did, - verKey: verkey, - } - - await WalletStorageService.addWalletRecord( - config, - credentials, - RecordType.MediatorAgent, - '1', - JSON.stringify(walletRecord), - JSON.stringify(walletRecordTags) - ); + // await WalletStorageService.addWalletRecord( + // config, + // credentials, + // RecordType.MediatorAgent, + // '1', + // JSON.stringify(walletRecord), + // JSON.stringify(walletRecordTags) + // ); } return response; } From 95bc3a9d7f88d34e0aa4799ebd7190932941cf08 Mon Sep 17 00:00:00 2001 From: Sai Ranjit Tummalapalli Date: Fri, 20 Aug 2021 15:58:54 +0530 Subject: [PATCH 04/14] refactor: removed unused methods in the agent service --- src/agent/index.ts | 25 +++------------ src/protocols/connection/ConnectionService.ts | 5 ++- ...hMediatorService.ts => MediatorService.ts} | 31 ++++--------------- src/transports/index.ts | 6 ++-- 4 files changed, 16 insertions(+), 51 deletions(-) rename src/protocols/mediator/{ConnectWithMediatorService.ts => MediatorService.ts} (84%) diff --git a/src/agent/index.ts b/src/agent/index.ts index d889668..e6495fc 100644 --- a/src/agent/index.ts +++ b/src/agent/index.ts @@ -11,7 +11,7 @@ import { NativeModules } from 'react-native'; import { WalletConfig, WalletCredentials } from '../wallet/WalletInterface'; import BasicMessageService from '../protocols/basicMessage/BasicMessageService'; import ConnectionService from '../protocols/connection/ConnectionService'; -import ConnectWithMediatorService from '../protocols/mediator/ConnectWithMediatorService'; +import MediatorService from '../protocols/mediator/MediatorService'; import CredentialService from '../protocols/credential/CredentialService'; import DatabaseServices from '../storage'; import InboundMessageService from '../transports'; @@ -37,23 +37,8 @@ class Agent { connectWithMediator = async (url: string, apiType: string, apiBody: string) => { try { - const response = await ConnectWithMediatorService.ConnectWithMediator(url, apiType, apiBody); this.wallet = await DatabaseServices.getWallet(); - return response; - } - catch (error) { - console.log("Agent - Connect with mediator error = ", error); - throw error; - } - } - - connectWithGenericMediator = async (invitationUrl: string) => { - try { - this.wallet = await DatabaseServices.getWallet(); - const response = await ConnectWithMediatorService.connectWithGenericMediator( - JSON.parse(this.wallet.walletConfig), - JSON.parse(this.wallet.walletCredentials), - invitationUrl); + const response = await MediatorService.ConnectWithMediator(url, apiType, apiBody); return response; } catch (error) { @@ -64,7 +49,7 @@ class Agent { mediationRequest = async (connection: Connection) => { try { - const response = await ConnectWithMediatorService.mediationRequest(connection); + await MediatorService.mediationRequest(connection); } catch (error) { console.log("Agent - mediationRequest error = ", error); throw error; @@ -73,7 +58,7 @@ class Agent { pickupMessages = async (mediatorConnection: Connection) => { try { - const response = await ConnectWithMediatorService.pickupMessages(mediatorConnection); + await MediatorService.pickupMessages(mediatorConnection); } catch (error) { console.log("Agent - pickupMessages error = ", error); throw error; @@ -82,7 +67,7 @@ class Agent { updateMediator = async (url: string, apiType: string, apiBody: string) => { try { - return await ConnectWithMediatorService.updateMediator(url, apiType, apiBody); + return await MediatorService.updateMediator(url, apiType, apiBody); } catch (error) { console.log("Agent - Update mediator error = ", error); diff --git a/src/protocols/connection/ConnectionService.ts b/src/protocols/connection/ConnectionService.ts index f20a74f..1039d06 100644 --- a/src/protocols/connection/ConnectionService.ts +++ b/src/protocols/connection/ConnectionService.ts @@ -22,7 +22,7 @@ import { TrustPing } from "../trustPing/TrustPingInterface"; import { TrustPingState } from '../trustPing/TrustPingState'; import WalletStorageService from '../../wallet/WalletStorageService'; import { createTrustPingMessage } from '../trustPing/TrustPingMessages'; -import ConnectWithMediatorService from 'react-native-arnima-sdk/src/protocols/mediator/ConnectWithMediatorService'; +import MediatorService from '../mediator/MediatorService'; const { ArnimaSdk } = NativeModules; class ConnectionService { @@ -105,7 +105,7 @@ class ConnectionService { isMediator: boolean ): Promise { try { - const routing = await ConnectWithMediatorService.getRouting(); + const routing = await MediatorService.getRouting(); const connection: Connection = await this.createConnection( configJson, credentialsJson, @@ -302,7 +302,6 @@ class ConnectionService { try { const { endpoint, pairwiseDid, routingKeys, verkey } = routing; - const publicKey = new PublicKey(`${pairwiseDid}#1`, PublicKeyType.ED25519_SIG_2018, pairwiseDid, verkey); const service = new Service(`${pairwiseDid};indy`, endpoint, [verkey], routingKeys, 0, 'IndyAgent'); const auth = new Authentication(publicKey); diff --git a/src/protocols/mediator/ConnectWithMediatorService.ts b/src/protocols/mediator/MediatorService.ts similarity index 84% rename from src/protocols/mediator/ConnectWithMediatorService.ts rename to src/protocols/mediator/MediatorService.ts index db6597e..21ac351 100644 --- a/src/protocols/mediator/ConnectWithMediatorService.ts +++ b/src/protocols/mediator/MediatorService.ts @@ -2,14 +2,12 @@ Copyright AyanWorks Technology Solutions Pvt. Ltd. All Rights Reserved. SPDX-License-Identifier: Apache-2.0 */ - -import { MediatorResponse } from "./MediatorInterface"; -import { NetworkServices } from "../../network"; -import { decodeInvitationFromUrl, RecordType, sendOutboundMessage } from '../../utils/Helpers' -import { WalletConfig, WalletCredentials, WalletRecord } from '../../wallet/WalletInterface'; -import DatabaseServices from "../../storage"; -import WalletStorageService from '../../wallet/WalletStorageService'; -import ConnectionService from "../connection/ConnectionService"; +import { MediatorResponse } from "react-native-arnima-sdk/src/protocols/mediator/MediatorInterface"; +import { NetworkServices } from "react-native-arnima-sdk/src/network"; +import { RecordType, sendOutboundMessage } from 'react-native-arnima-sdk/src/utils/Helpers' +import { WalletRecord } from 'react-native-arnima-sdk/src/wallet/WalletInterface'; +import DatabaseServices from "react-native-arnima-sdk/src/storage"; +import WalletStorageService from 'react-native-arnima-sdk/src/wallet/WalletStorageService'; import { createBatchPickupMessage, createKeylistUpdateMessage, createMediationRequestMessage } from "react-native-arnima-sdk/src/protocols/mediator/MediationMessages"; import { Connection } from "react-native-arnima-sdk/src/protocols/connection/ConnectionInterface"; import { NativeModules } from "react-native"; @@ -17,21 +15,6 @@ import { NativeModules } from "react-native"; const { ArnimaSdk } = NativeModules; class MediatorService { - async connectWithGenericMediator( - configJson: WalletConfig, - credentialsJson: WalletCredentials, - invitationUrl: string): Promise { - try { - console.log(invitationUrl) - const invitationJson = decodeInvitationFromUrl(invitationUrl); - console.log(invitationJson) - const connectionRecord = await ConnectionService.acceptInvitation(configJson, credentialsJson, {}, invitationJson, '', true); - console.log('connectionRecord', connectionRecord) - - } catch (error) { - console.log('Error ConnectWithNewMediator', error) - } - } async mediationRequest(connection: Connection) { const myWallet: any = DatabaseServices.getWallet(); @@ -97,8 +80,6 @@ class MediatorService { false ); await this.keylistUpdate(verkey); - - console.log(5) return { endpoint, routingKeys, pairwiseDid, verkey }; } catch (error) { console.log('MediatorService - getRouting error = ', error); diff --git a/src/transports/index.ts b/src/transports/index.ts index e709ca2..a87543f 100644 --- a/src/transports/index.ts +++ b/src/transports/index.ts @@ -17,7 +17,7 @@ import io from "socket.io-client"; import PresentationService from "../protocols/presentation/PresentationService"; import TrustPingService from "../protocols/trustPing/TrustPingService"; import WalletStorageService from "../wallet/WalletStorageService"; -import ConnectWithMediatorService from "react-native-arnima-sdk/src/protocols/mediator/ConnectWithMediatorService"; +import MediatorService from "../protocols/mediator/MediatorService"; class InboundMessageHandler { @@ -137,12 +137,12 @@ class InboundMessageHandler { this.isProcess = true; if (unprocessedMessages[i].tags.autoProcessed === 'true') { const messageRecord = JSON.parse(unprocessedMessages[i].value); - console.log('messageRecord', messageRecord); const unpackMessageResponse = await unpackMessage(JSON.parse(this.wallet.walletConfig), JSON.parse(this.wallet.walletCredentials), messageRecord); const message = JSON.parse(unpackMessageResponse.message); replaceDidSovPrefixOnMessage(message); console.log('Message Type = ', message['@type']); + console.log('unpackMessageResponse', JSON.stringify(message, null, 2)); switch (message['@type']) { case MessageType.ConnectionResponse: { const isCompleted = await ConnectionService.processRequest(JSON.parse(this.wallet.walletConfig), JSON.parse(this.wallet.walletCredentials), unpackMessageResponse); @@ -285,7 +285,7 @@ class InboundMessageHandler { } case MessageType.MediationGrant: { - const isCompleted = await ConnectWithMediatorService.saveRoutingKeys(message); + const isCompleted = await MediatorService.saveRoutingKeys(message); if (isCompleted) { await WalletStorageService.deleteWalletRecord(JSON.parse(this.wallet.walletConfig), JSON.parse(this.wallet.walletCredentials), RecordType.SSIMessage, unprocessedMessages[i].id) } break; } From f3e1a230b4a5484116f9439caea2c2edaec3e1c8 Mon Sep 17 00:00:00 2001 From: Sai Ranjit Tummalapalli Date: Wed, 8 Sep 2021 12:52:15 +0530 Subject: [PATCH 05/14] feat: out of band proof conditions added Signed-off-by: Sai Ranjit Tummalapalli --- .../main/java/com/arnimasdk/ArnimaSdk.java | 23 +++++++ src/agent/index.ts | 14 +++++ .../presentation/PresentationService.ts | 46 ++++++++------ src/utils/Helpers.ts | 60 ++++++++++++------- 4 files changed, 101 insertions(+), 42 deletions(-) diff --git a/android/src/main/java/com/arnimasdk/ArnimaSdk.java b/android/src/main/java/com/arnimasdk/ArnimaSdk.java index cbdb7a2..91fd2c2 100644 --- a/android/src/main/java/com/arnimasdk/ArnimaSdk.java +++ b/android/src/main/java/com/arnimasdk/ArnimaSdk.java @@ -42,6 +42,7 @@ import java.io.FileWriter; import java.io.InputStream; import java.io.OutputStream; +import java.net.HttpURLConnection; import java.net.URL; import java.net.URLConnection; import java.util.Map; @@ -799,6 +800,28 @@ private byte[] readableArrayToBuffer(ReadableArray arr) { return buffer; } + @ReactMethod + public void getRequestRedirectionUrl(String url, Promise promise) { + try { + URL urlObj = new URL(url); + + HttpURLConnection connection = (HttpURLConnection) urlObj.openConnection(); + connection.setRequestMethod("GET"); + connection.setInstanceFollowRedirects(false); + + int responseCode = connection.getResponseCode(); + + if (responseCode == 302) { + String location = connection.getHeaderField("location"); + promise.resolve(location); + } + promise.reject("Unable to fetch URL", "Unable to fetch URL"); + } catch (Exception e) { + e.printStackTrace(); + promise.reject(e.toString(), ""); + } + } + class IndySdkRejectResponse { private final String code; private final String message; diff --git a/src/agent/index.ts b/src/agent/index.ts index ec399cf..0cbfdd2 100644 --- a/src/agent/index.ts +++ b/src/agent/index.ts @@ -25,6 +25,10 @@ const { ArnimaSdk } = NativeModules; class Agent { wallet: any = DatabaseServices.getWallet(); + getRequestRedirectionUrl = async (url: string) => { + return await ArnimaSdk.getRequestRedirectionUrl(url) + } + createWallet = async (config: WalletConfig, credentials: WalletCredentials, label: string) => { try { return await WalletService.createWallet(config, credentials, label); @@ -304,6 +308,16 @@ class Agent { } } + sendOutOfBandProof = async (inboundMessage: InboundMessage, revealAttributes: boolean, presentationObj: object) => { + try { + const response: Boolean = await PresentationService.createPresentation(JSON.parse(this.wallet.walletConfig), JSON.parse(this.wallet.walletCredentials), inboundMessage, revealAttributes, presentationObj); + return response; + } catch (error) { + console.log('Agent - Send proof error = ', error); + throw error; + } + } + sendProof = async (messageId: string, inboundMessage: InboundMessage, revealAttributes: boolean, presentationObj: object) => { try { const response: Boolean = await PresentationService.createPresentation(JSON.parse(this.wallet.walletConfig), JSON.parse(this.wallet.walletCredentials), inboundMessage, revealAttributes, presentationObj); diff --git a/src/protocols/presentation/PresentationService.ts b/src/protocols/presentation/PresentationService.ts index cb5fdab..dfda3c9 100644 --- a/src/protocols/presentation/PresentationService.ts +++ b/src/protocols/presentation/PresentationService.ts @@ -232,7 +232,10 @@ class PresentationService { const query = { connectionId: recipient_verkey } - const connection: Connection = await WalletStorageService.getWalletRecordFromQuery(configJson, credentialsJson, RecordType.Connection, JSON.stringify(query)); + let connection: Connection; + if (recipient_verkey !== null) { + connection = await WalletStorageService.getWalletRecordFromQuery(configJson, credentialsJson, RecordType.Connection, JSON.stringify(query)); + } const message: Message = inboundMessage.message; const presentationRequest = message['request_presentations~attach']; const proofRequest = await decodeBase64(presentationRequest[0].data.base64); @@ -267,7 +270,6 @@ class PresentationService { this.generateCredDefJson(credentialObjects, poolName, poolConfig, sdkDB.publicDid)] ); - const presentation = await ArnimaSdk.proverCreateProof( JSON.stringify(configJson), JSON.stringify(credentialsJson), @@ -278,14 +280,18 @@ class PresentationService { JSON.stringify(credDefs), JSON.stringify(revocStates), ); - const presentProofRecord: Presentation = await { - connectionId: connection.verkey, - theirLabel: connection.theirLabel, - threadId: message.hasOwnProperty('~thread') ? Object.keys(message['~thread']).length > 0 === false ? message['@id'] : message['~thread'].thid : message['@id'], - presentationRequest: proofRequest, - presentation: JSON.parse(presentation), - state: PresentationState.STATE_PRESENTATION_SENT, - updatedAt: new Date().toISOString(), + //TODO: handle for out of band message + let presentProofRecord: Presentation; + if (recipient_verkey !== null) { + presentProofRecord = { + connectionId: connection.verkey, + theirLabel: connection.theirLabel, + threadId: message.hasOwnProperty('~thread') ? Object.keys(message['~thread']).length > 0 === false ? message['@id'] : message['~thread'].thid : message['@id'], + presentationRequest: proofRequest, + presentation: JSON.parse(presentation), + state: PresentationState.STATE_PRESENTATION_SENT, + updatedAt: new Date().toISOString(), + } } const creatPresentationMessageObject = await creatPresentationMessage( presentation, @@ -293,16 +299,18 @@ class PresentationService { message.hasOwnProperty('~thread') ? Object.keys(message['~thread']).length > 0 === false ? message['@id'] : message['~thread'].thid : message['@id'], ); - await sendOutboundMessage(configJson, credentialsJson, connection, creatPresentationMessageObject) + await sendOutboundMessage(configJson, credentialsJson, connection, creatPresentationMessageObject, undefined, message['~service']) - await WalletStorageService.updateWalletRecord( - configJson, - credentialsJson, - RecordType.Presentation, - message.hasOwnProperty('~thread') ? Object.keys(message['~thread']).length > 0 === false ? message['@id'] : message['~thread'].thid : message['@id'], - JSON.stringify(presentProofRecord), - '{}' - ); + if (recipient_verkey !== null) { + await WalletStorageService.updateWalletRecord( + configJson, + credentialsJson, + RecordType.Presentation, + message.hasOwnProperty('~thread') ? Object.keys(message['~thread']).length > 0 === false ? message['@id'] : message['~thread'].thid : message['@id'], + JSON.stringify(presentProofRecord), + '{}' + ); + } return true; } catch (error) { diff --git a/src/utils/Helpers.ts b/src/utils/Helpers.ts index be685a2..a6ba5f7 100644 --- a/src/utils/Helpers.ts +++ b/src/utils/Helpers.ts @@ -204,37 +204,51 @@ export function encodeBase64(data: string) { return Buffer.from(JSON.stringify(data)).toString('base64'); } -export function createOutboundMessage(connection: Connection, payload: Object, invitation?: Message) { - if (invitation) { - const { recipientKeys, routingKeys, serviceEndpoint } = invitation +export async function createOutboundMessage(connection: Connection, payload: Object, invitation?: Message, oobService?: object) { + if (connection) { + if (invitation) { + const { recipientKeys, routingKeys, serviceEndpoint } = invitation + return { + connection, + endpoint: serviceEndpoint, + payload, + recipientKeys: recipientKeys, + routingKeys: routingKeys || [], + senderVk: connection.verkey, + }; + } + + const { theirDidDoc } = connection; + + if (!theirDidDoc) { + throw new Error(`DidDoc for connection with verkey ${connection.verkey} not found!`); + } + const { service } = theirDidDoc return { connection, - endpoint: serviceEndpoint, + endpoint: service[0].serviceEndpoint, payload, - recipientKeys: recipientKeys, - routingKeys: routingKeys || [], + recipientKeys: service[0].recipientKeys, + routingKeys: service[0].routingKeys, senderVk: connection.verkey, }; + } else { + const wallet = await DatabaseServices.getWallet(); + const [pairwiseDid, verkey]: string[] = await ArnimaSdk.createAndStoreMyDid( + wallet.walletConfig, wallet.walletCredentials, JSON.stringify({}), false); + const { recipientKeys, routingKeys, serviceEndpoint } = oobService; + return { + payload, + recipientKeys, + routingKeys, + endpoint: serviceEndpoint, + senderVk: verkey, + } } - - const { theirDidDoc } = connection; - - if (!theirDidDoc) { - throw new Error(`DidDoc for connection with verkey ${connection.verkey} not found!`); - } - const { service } = theirDidDoc - return { - connection, - endpoint: service[0].serviceEndpoint, - payload, - recipientKeys: service[0].recipientKeys, - routingKeys: service[0].routingKeys, - senderVk: connection.verkey, - }; } -export async function sendOutboundMessage(configJson: WalletConfig, credentialsJson: WalletCredentials, connection: Connection, message: Object, invitation?: Message) { - const outboundMessage = await createOutboundMessage(connection, message, invitation); +export async function sendOutboundMessage(configJson: WalletConfig, credentialsJson: WalletCredentials, connection: Connection, message: Object, invitation?: Message, oobService?: object) { + const outboundMessage = await createOutboundMessage(connection, message, invitation, oobService); const outboundPackMessage = await packMessage(configJson, credentialsJson, outboundMessage); await OutboundAgentMessage(outboundMessage.endpoint, 'POST', JSON.stringify(outboundPackMessage)); } From b344aaa2f248682fbd1a4678edf4661b9712b5e5 Mon Sep 17 00:00:00 2001 From: Sai Ranjit Tummalapalli Date: Wed, 8 Sep 2021 18:16:44 +0530 Subject: [PATCH 06/14] refactor: added async task for getRequestRedirectionUrl method Signed-off-by: Sai Ranjit Tummalapalli --- .../main/java/com/arnimasdk/ArnimaSdk.java | 43 +++++++++++++------ 1 file changed, 30 insertions(+), 13 deletions(-) diff --git a/android/src/main/java/com/arnimasdk/ArnimaSdk.java b/android/src/main/java/com/arnimasdk/ArnimaSdk.java index 91fd2c2..a2a0a0d 100644 --- a/android/src/main/java/com/arnimasdk/ArnimaSdk.java +++ b/android/src/main/java/com/arnimasdk/ArnimaSdk.java @@ -800,25 +800,42 @@ private byte[] readableArrayToBuffer(ReadableArray arr) { return buffer; } + @ReactMethod public void getRequestRedirectionUrl(String url, Promise promise) { - try { - URL urlObj = new URL(url); + new GetRequestRedirectionUrl().execute(url, promise); + } - HttpURLConnection connection = (HttpURLConnection) urlObj.openConnection(); - connection.setRequestMethod("GET"); - connection.setInstanceFollowRedirects(false); + private class GetRequestRedirectionUrl extends AsyncTask { + Promise promise = null; - int responseCode = connection.getResponseCode(); + @Override + protected Object doInBackground(Object[] objects) { + try { + promise = (Promise) objects[1]; + URL urlObj = new URL(objects[0].toString()); + + HttpURLConnection connection = (HttpURLConnection) urlObj.openConnection(); + connection.setRequestMethod("GET"); + connection.setInstanceFollowRedirects(false); + + int responseCode = connection.getResponseCode(); - if (responseCode == 302) { - String location = connection.getHeaderField("location"); - promise.resolve(location); + if (responseCode == 302) { + String location = connection.getHeaderField("location"); + promise.resolve(location); + } + promise.reject("Unable to fetch URL", "Unable to fetch URL"); + } catch (Exception e) { + IndySdkRejectResponse rejectResponse = new IndySdkRejectResponse(e); + promise.reject(rejectResponse.getCode(), rejectResponse.toJson(), e); } - promise.reject("Unable to fetch URL", "Unable to fetch URL"); - } catch (Exception e) { - e.printStackTrace(); - promise.reject(e.toString(), ""); + return promise; + } + + @Override + protected void onPreExecute() { + super.onPreExecute(); } } From eea53c582a52811d55e5d4332c3328e4c80ef24d Mon Sep 17 00:00:00 2001 From: Sai Ranjit Tummalapalli Date: Thu, 9 Sep 2021 17:02:40 +0530 Subject: [PATCH 07/14] refactor: send implicit messages methods added Signed-off-by: Sai Ranjit Tummalapalli --- src/agent/index.ts | 9 ++++++++ src/network/index.ts | 11 +++++++--- src/protocols/mediator/MediatorService.ts | 22 +++++++++++++++++++- src/protocols/trustPing/TrustPingMessages.ts | 2 +- src/transports/index.ts | 6 +++--- src/utils/Helpers.ts | 15 ++++++++++--- src/utils/MessageType.ts | 4 ++-- 7 files changed, 56 insertions(+), 13 deletions(-) diff --git a/src/agent/index.ts b/src/agent/index.ts index e6495fc..cc87c94 100644 --- a/src/agent/index.ts +++ b/src/agent/index.ts @@ -65,6 +65,15 @@ class Agent { } } + sendImplicitMessages = async (mediatorConnection: Connection) => { + try { + await MediatorService.sendImplicitMessages(mediatorConnection); + } catch (error) { + console.log("Agent - pickupMessages error = ", error); + throw error; + } + } + updateMediator = async (url: string, apiType: string, apiBody: string) => { try { return await MediatorService.updateMediator(url, apiType, apiBody); diff --git a/src/network/index.ts b/src/network/index.ts index 01b284b..d6f9256 100644 --- a/src/network/index.ts +++ b/src/network/index.ts @@ -44,8 +44,9 @@ export const OutboundAgentMessage: Function = async (url: string, apiType: strin try { const wireMessage = JSON.parse(responseMessage) console.log(`Response received`, wireMessage) - await InboundMessageService.addMessages(wireMessage) - // this.agent.receiveMessage(wireMessage) + if (wireMessage.hasOwnProperty('tag')) { + await InboundMessageService.addMessages(wireMessage) + } } catch (error) { console.log('Unable to parse response message', error) } @@ -54,6 +55,10 @@ export const OutboundAgentMessage: Function = async (url: string, apiType: strin } } catch (error) { console.log('Error OutboundAgentMessage', error) - throw new Error('We are not able to communicate with the agent at this moment, Please try again later'); + if (error.name == 'AbortError') { + console.log('Signal aborted') + } else { + throw new Error('We are not able to communicate with the agent at this moment, Please try again later'); + } } }; \ No newline at end of file diff --git a/src/protocols/mediator/MediatorService.ts b/src/protocols/mediator/MediatorService.ts index 21ac351..64efc77 100644 --- a/src/protocols/mediator/MediatorService.ts +++ b/src/protocols/mediator/MediatorService.ts @@ -11,11 +11,30 @@ import WalletStorageService from 'react-native-arnima-sdk/src/wallet/WalletStora import { createBatchPickupMessage, createKeylistUpdateMessage, createMediationRequestMessage } from "react-native-arnima-sdk/src/protocols/mediator/MediationMessages"; import { Connection } from "react-native-arnima-sdk/src/protocols/connection/ConnectionInterface"; import { NativeModules } from "react-native"; +import { createTrustPingMessage } from "react-native-arnima-sdk/src/protocols/trustPing/TrustPingMessages"; const { ArnimaSdk } = NativeModules; class MediatorService { + async sendImplicitMessages(mediatorConnection: Connection) { + try { + const myWallet: any = DatabaseServices.getWallet(); + + const trustPingMessage = await createTrustPingMessage(false); + + await sendOutboundMessage( + JSON.parse(myWallet.walletConfig), + JSON.parse(myWallet.walletConfig), + mediatorConnection, + trustPingMessage + ); + } catch (err) { + console.log('sendImplicitMessage Error: ', err); + throw err; + } + } + async mediationRequest(connection: Connection) { const myWallet: any = DatabaseServices.getWallet(); const message = await createMediationRequestMessage(); @@ -71,7 +90,8 @@ class MediatorService { async getRouting() { try { const myWallet: any = DatabaseServices.getWallet(); - const endpoint = myWallet.serviceEndpoint !== "" ? myWallet.serviceEndpoint : 'didcomm:transport/queue' + const endpoint = myWallet.serviceEndpoint !== "" ? myWallet.serviceEndpoint : '' + const routingKeys: string[] = myWallet.routingKey !== '' ? [myWallet.routingKey] : [] const [pairwiseDid, verkey]: string[] = await ArnimaSdk.createAndStoreMyDid( myWallet.walletConfig, diff --git a/src/protocols/trustPing/TrustPingMessages.ts b/src/protocols/trustPing/TrustPingMessages.ts index 838ac79..75141b2 100644 --- a/src/protocols/trustPing/TrustPingMessages.ts +++ b/src/protocols/trustPing/TrustPingMessages.ts @@ -11,7 +11,7 @@ export function createTrustPingMessage(responseRequested: boolean = true, commen '@id': uuidv4(), '@type': MessageType.TrustPingMessage, ...(comment && { comment }), - responseRequested, + response_requested: responseRequested, }; } diff --git a/src/transports/index.ts b/src/transports/index.ts index a87543f..fac4d17 100644 --- a/src/transports/index.ts +++ b/src/transports/index.ts @@ -95,16 +95,16 @@ class InboundMessageHandler { } } - inboundMessageListener = EventRegister.addEventListener('proceedInboundMessage', () => { + inboundMessageListener = EventRegister.addEventListener('proceedInboundMessage', async () => { if (this.isProcess === false) { - this.proceedInboundMessage(); + await this.proceedInboundMessage(); } }); inboundMessageStatusListener = EventRegister.addEventListener('inboundMessageStatusListener', async () => { const unprocessedMessages: Array = await WalletStorageService.getWalletRecordsFromQuery(JSON.parse(this.wallet.walletConfig), JSON.parse(this.wallet.walletCredentials), RecordType.SSIMessage, '{}'); if (this.isProcess === false && unprocessedMessages.length > 0) { - this.proceedInboundMessage(); + await this.proceedInboundMessage(); } }); diff --git a/src/utils/Helpers.ts b/src/utils/Helpers.ts index 731a865..70ff684 100644 --- a/src/utils/Helpers.ts +++ b/src/utils/Helpers.ts @@ -145,7 +145,7 @@ export async function unpackMessage(configJson: WalletConfig, credentialsJson: W export async function packMessage(configJson: WalletConfig, credentialsJson: WalletCredentials, outboundMessage: OutboundMessage) { try { const { routingKeys, recipientKeys, senderVk, payload } = outboundMessage; - console.log("outboundMessage", outboundMessage) + console.log("outboundMessage", JSON.stringify(outboundMessage, null, 2)) const buf = Buffer.from(JSON.stringify(payload)); let packedBufferMessage; if (Platform.OS === 'ios') { @@ -209,11 +209,13 @@ export function encodeBase64(data: string) { } export function createOutboundMessage(connection: Connection, payload: Object, invitation?: Message) { - if (connection.didDoc.service[0].serviceEndpoint == 'didcomm:transport/queue') { + const shouldUseReturnRoute = Boolean(connection.didDoc.service.find((s) => s.serviceEndpoint === '')) + if (shouldUseReturnRoute) { payload['~transport'] = { return_route: 'all' } } + if (invitation) { const { recipientKeys, routingKeys, serviceEndpoint } = invitation; return { @@ -232,6 +234,7 @@ export function createOutboundMessage(connection: Connection, payload: Object, i throw new Error(`DidDoc for connection with verkey ${connection.verkey} not found!`); } const { service } = theirDidDoc + return { connection, endpoint: service[0].serviceEndpoint, @@ -242,7 +245,13 @@ export function createOutboundMessage(connection: Connection, payload: Object, i }; } -export async function sendOutboundMessage(configJson: WalletConfig, credentialsJson: WalletCredentials, connection: Connection, message: Object, invitation?: Message) { +export async function sendOutboundMessage( + configJson: WalletConfig, + credentialsJson: WalletCredentials, + connection: Connection, + message: Object, + invitation?: Message +) { const outboundMessage = await createOutboundMessage(connection, message, invitation); const outboundPackMessage = await packMessage(configJson, credentialsJson, outboundMessage); await OutboundAgentMessage(outboundMessage.endpoint, 'POST', JSON.stringify(outboundPackMessage)); diff --git a/src/utils/MessageType.ts b/src/utils/MessageType.ts index 17d261f..1aac742 100644 --- a/src/utils/MessageType.ts +++ b/src/utils/MessageType.ts @@ -34,8 +34,8 @@ export enum MessageType { MediationRequest = "did:sov:BzCbsNYhMrjHiqZDTUASHg;spec/coordinate-mediation/1.0/mediate-request", MediationGrant = "did:sov:BzCbsNYhMrjHiqZDTUASHg;spec/coordinate-mediation/1.0/mediate-grant", - KeyListUpdate = "did:sov:BzCbsNYhMrjHiqZDTUASHg;spec/coordinatemediation/1.0/keylist-update", - KeyListUpdateResponse = "did:sov:BzCbsNYhMrjHiqZDTUASHg;spec/coordinatemediation/1.0/keylist-update-response", + KeyListUpdate = "did:sov:BzCbsNYhMrjHiqZDTUASHg;spec/coordinate-mediation/1.0/keylist-update", + KeyListUpdateResponse = "did:sov:BzCbsNYhMrjHiqZDTUASHg;spec/coordinate-mediation/1.0/keylist-update-response", BatchPickup = "did:sov:BzCbsNYhMrjHiqZDTUASHg;spec/messagepickup/1.0/batch-pickup", Batch = "did:sov:BzCbsNYhMrjHiqZDTUASHg;spec/messagepickup/1.0/batch" From a54e2de9c38845424f3ed650b653f18d6c81a6b7 Mon Sep 17 00:00:00 2001 From: Sai Ranjit Tummalapalli Date: Mon, 13 Sep 2021 12:48:49 +0530 Subject: [PATCH 08/14] refactor: changed event listener Signed-off-by: Sai Ranjit Tummalapalli --- src/transports/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/transports/index.ts b/src/transports/index.ts index 0575953..764494c 100644 --- a/src/transports/index.ts +++ b/src/transports/index.ts @@ -118,7 +118,7 @@ class InboundMessageHandler { JSON.stringify(message), JSON.stringify(ssiMessageTags) ); - EventRegister.emit('proceedInboundMessage', `proceedInboundMessage`); + EventRegister.emit('inboundMessageStatusListener', `inboundMessageStatusListener`); } proceedInboundMessage = async () => { From a2055f2180e5fd9c1dcfc87be7978e4f2fd08f1e Mon Sep 17 00:00:00 2001 From: Sai Ranjit Tummalapalli Date: Mon, 13 Sep 2021 19:31:34 +0530 Subject: [PATCH 09/14] refactor: support ?d_m invitations Signed-off-by: Sai Ranjit Tummalapalli --- src/network/index.ts | 6 ++---- src/transports/index.ts | 1 - src/utils/Helpers.ts | 9 +++++++-- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/network/index.ts b/src/network/index.ts index d6f9256..e3fface 100644 --- a/src/network/index.ts +++ b/src/network/index.ts @@ -28,9 +28,8 @@ export const NetworkServices: Function = async (url: string, apiType: string, ap export const OutboundAgentMessage: Function = async (url: string, apiType: string, apiBody: string) => { try { console.log("url", url) - console.log("apiBody", apiBody) const abortController = new AbortController() - const id = setTimeout(() => abortController.abort(), 15000) + const id = setTimeout(() => abortController.abort(), 4000) const response = await fetch(url, { method: 'POST', body: apiBody, @@ -40,10 +39,9 @@ export const OutboundAgentMessage: Function = async (url: string, apiType: strin clearTimeout(id) const responseMessage = await response.text() if (responseMessage) { - console.log(`Response received`, { responseMessage, status: response.status }) + console.log(`Response received`) try { const wireMessage = JSON.parse(responseMessage) - console.log(`Response received`, wireMessage) if (wireMessage.hasOwnProperty('tag')) { await InboundMessageService.addMessages(wireMessage) } diff --git a/src/transports/index.ts b/src/transports/index.ts index 764494c..c4ca65b 100644 --- a/src/transports/index.ts +++ b/src/transports/index.ts @@ -144,7 +144,6 @@ class InboundMessageHandler { } const connection = await WalletStorageService.getWalletRecordFromQuery(JSON.parse(this.wallet.walletConfig), JSON.parse(this.wallet.walletCredentials), RecordType.Connection, JSON.stringify(query)); - console.log('connection', typeof connection) if (connection.length === 0 || connection.verkey === '') { console.log('Connection not found') await WalletStorageService.deleteWalletRecord(JSON.parse(this.wallet.walletConfig), JSON.parse(this.wallet.walletCredentials), RecordType.SSIMessage, unprocessedMessages[i].id); diff --git a/src/utils/Helpers.ts b/src/utils/Helpers.ts index 31b316a..51b741a 100644 --- a/src/utils/Helpers.ts +++ b/src/utils/Helpers.ts @@ -189,8 +189,13 @@ export function getServiceEndpoint() { } export function decodeInvitationFromUrl(invitationUrl: string) { - const [, encodedInvitation] = invitationUrl.split('c_i='); - return JSON.parse(Buffer.from(encodedInvitation, 'base64').toString()); + if (invitationUrl.includes("?c_i=")) { + const [, encodedInvitation] = invitationUrl.split('c_i='); + return JSON.parse(Buffer.from(encodedInvitation, 'base64').toString()); + } else if (invitationUrl.includes("?d_m=")) { + const [encodedInvitation] = invitationUrl.split('=')[1].split('%'); + return JSON.parse(Buffer.from(encodedInvitation, 'base64').toString()); + } } export function encodeInvitationToUrl(invitation: InvitationDetails): string { From 93224e9066d21667f2baba3a2391664fe4af35d1 Mon Sep 17 00:00:00 2001 From: Sai Ranjit Tummalapalli Date: Thu, 27 Jan 2022 12:30:23 +0530 Subject: [PATCH 10/14] chore: adding versions to all the peer dependencies Signed-off-by: Sai Ranjit Tummalapalli --- package.json | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/package.json b/package.json index 902c658..c18a338 100644 --- a/package.json +++ b/package.json @@ -1,4 +1,3 @@ - { "name": "react-native-arnima-sdk", "version": "1.0.0", @@ -10,6 +9,7 @@ "devDependencies": { "@babel/core": "^7.7.7", "@babel/runtime": "^7.7.7", + "@types/node": "^12.12.21", "@react-native-community/eslint-config": "^0.0.6", "babel-jest": "^24.9.0", "eslint": "^6.8.0", @@ -27,15 +27,13 @@ ], "license": "", "peerDependencies": { - "react": "*", - "react-native": "*", - "realm": "*", - "socket.io-client": "*", - "uuid": "*", - "base64url": "*", - "@types/node": "*", - "react-native-event-listeners": "*", - "events": "*" + "react": "17.0.2", + "react-native": "0.65.0", + "realm": "^10.1.3", + "socket.io-client": "^2.3.0", + "uuid": "^8.3.2", + "base64url": "^3.0.1", + "react-native-event-listeners": "^1.0.7" }, "bundleDependencies": false, "dependencies": {}, From b218e6f1c4f72dab43f084511ae0b07b30b67770 Mon Sep 17 00:00:00 2001 From: Sai Ranjit Tummalapalli Date: Thu, 27 Jan 2022 13:11:29 +0530 Subject: [PATCH 11/14] chore: adding versions to all the dependencies Signed-off-by: Sai Ranjit Tummalapalli --- package.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index c18a338..07497c9 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,9 @@ "Mobile Agent" ], "license": "", - "peerDependencies": { + "peerDependencies": {}, + "bundleDependencies": false, + "dependencies": { "react": "17.0.2", "react-native": "0.65.0", "realm": "^10.1.3", @@ -35,7 +37,5 @@ "base64url": "^3.0.1", "react-native-event-listeners": "^1.0.7" }, - "bundleDependencies": false, - "dependencies": {}, "deprecated": false } From 33ca97c66ace92ee93061aa83da8a3f7038f51c1 Mon Sep 17 00:00:00 2001 From: Sai Ranjit Tummalapalli Date: Thu, 27 Jan 2022 13:39:30 +0530 Subject: [PATCH 12/14] chore: updating realm version Signed-off-by: Sai Ranjit Tummalapalli --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 07497c9..1fb3c20 100644 --- a/package.json +++ b/package.json @@ -31,7 +31,7 @@ "dependencies": { "react": "17.0.2", "react-native": "0.65.0", - "realm": "^10.1.3", + "realm": "^10.12.0", "socket.io-client": "^2.3.0", "uuid": "^8.3.2", "base64url": "^3.0.1", From ceaccfcf4c313b6af318808eaa2f44d42f26fb02 Mon Sep 17 00:00:00 2001 From: Sai Ranjit Tummalapalli Date: Thu, 27 Jan 2022 13:52:46 +0530 Subject: [PATCH 13/14] reverting the package.json file Signed-off-by: Sai Ranjit Tummalapalli --- package.json | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/package.json b/package.json index 1fb3c20..5ceedd6 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,6 @@ "devDependencies": { "@babel/core": "^7.7.7", "@babel/runtime": "^7.7.7", - "@types/node": "^12.12.21", "@react-native-community/eslint-config": "^0.0.6", "babel-jest": "^24.9.0", "eslint": "^6.8.0", @@ -26,16 +25,18 @@ "Mobile Agent" ], "license": "", - "peerDependencies": {}, - "bundleDependencies": false, - "dependencies": { - "react": "17.0.2", - "react-native": "0.65.0", - "realm": "^10.12.0", - "socket.io-client": "^2.3.0", - "uuid": "^8.3.2", - "base64url": "^3.0.1", - "react-native-event-listeners": "^1.0.7" + "peerDependencies": { + "react": "*", + "react-native": "*", + "realm": "*", + "socket.io-client": "*", + "uuid": "*", + "base64url": "*", + "@types/node": "*", + "react-native-event-listeners": "*", + "events": "*" }, + "bundleDependencies": false, + "dependencies": {}, "deprecated": false } From 9c8ddd1a6261db5289a08d02025b09bb4979cf74 Mon Sep 17 00:00:00 2001 From: Sai Ranjit Tummalapalli Date: Wed, 2 Feb 2022 12:28:13 +0530 Subject: [PATCH 14/14] feat: initial websocket support for mediator Signed-off-by: Sai Ranjit Tummalapalli --- src/agent/index.ts | 16 +++- src/protocols/connection/ConnectionService.ts | 40 ++++++--- src/protocols/mediator/MediatorService.ts | 86 ++++++++++++++++++- src/utils/DidDoc.ts | 4 +- src/utils/Helpers.ts | 61 +++++++++++-- src/utils/Types.ts | 14 ++- 6 files changed, 191 insertions(+), 30 deletions(-) diff --git a/src/agent/index.ts b/src/agent/index.ts index 9f5d234..0e9ef7c 100644 --- a/src/agent/index.ts +++ b/src/agent/index.ts @@ -51,6 +51,19 @@ class Agent { } } + connectMediatorWithInvite = async (invitationUrl: string) => { + const connection = await this.acceptInvitation({},invitationUrl,''); + + setTimeout(() => { + ConnectionService.connectionStatus( + JSON.parse(this.wallet.walletConfig), + JSON.parse(this.wallet.walletCredentials), + connection.verkey, + ) + }, 5000); + connection.state == 'COMPLETE' + } + mediationRequest = async (connection: Connection) => { try { await MediatorService.mediationRequest(connection); @@ -143,7 +156,7 @@ class Agent { } } - acceptInvitation = async (didJson: Object, message: any, logo: string, isMediator: boolean = false) => { + acceptInvitation = async (didJson: Object, message: any, logo: string) => { try { this.wallet = await DatabaseServices.getWallet(); const invitation = decodeInvitationFromUrl(message); @@ -153,7 +166,6 @@ class Agent { didJson, invitation, logo, - isMediator ); } catch (error) { diff --git a/src/protocols/connection/ConnectionService.ts b/src/protocols/connection/ConnectionService.ts index 943a02c..eef5d10 100644 --- a/src/protocols/connection/ConnectionService.ts +++ b/src/protocols/connection/ConnectionService.ts @@ -17,7 +17,6 @@ import { Connection } from './ConnectionInterface'; import { ConnectionState } from './ConnectionState'; import DatabaseServices from '../../storage'; import { NativeModules } from "react-native"; -import { NetworkServices } from "../../network"; import { TrustPing } from "../trustPing/TrustPingInterface"; import { TrustPingState } from '../trustPing/TrustPingState'; import WalletStorageService from '../../wallet/WalletStorageService'; @@ -66,7 +65,9 @@ class ConnectionService { credentialsJson: WalletCredentials, didJson: Object, logo: string): Promise { - const connection: Connection = await this.createConnection(configJson, credentialsJson, didJson, ''); + + const routing = await MediatorService.getRouting(); + const connection: Connection = await this.createConnection(routing, ''); const connectionTags: Object = { connectionId: connection.verkey, @@ -99,20 +100,16 @@ class ConnectionService { * @return {*} {Promise} * @memberof ConnectionService */ - async acceptInvitation(configJson: WalletConfig, + async acceptInvitation( + configJson: WalletConfig, credentialsJson: WalletCredentials, didJson: Object, invitation: Message, logo: string, - isMediator: boolean ): Promise { try { const routing = await MediatorService.getRouting(); const connection: Connection = await this.createConnection( - configJson, - credentialsJson, - didJson, - isMediator, routing, invitation.label, invitation.hasOwnProperty('alias') ? invitation.alias.logoUrl : '', @@ -293,10 +290,6 @@ class ConnectionService { * @memberof ConnectionService */ async createConnection( - configJson: WalletConfig, - credentialsJson: WalletCredentials, - didJson: Object, - isMediator: boolean, routing: { endpoint: string; routingKeys: string[]; @@ -336,6 +329,29 @@ class ConnectionService { throw error; } } + + + async connectionStatus( + configJson: WalletConfig, + credentialsJson: WalletCredentials, + verkey:string, + ) { + try { + const query = { + connectionId: verkey + } + const connection: Connection = await WalletStorageService.getWalletRecordFromQuery(configJson, credentialsJson, RecordType.Connection, JSON.stringify(query)); + if (!connection) { + throw new Error(`Connection for verkey ${verkey} not found!`); + } + return connection; + } + catch (error) { + console.log('Connection - Connection status error = ', JSON.stringify(error)); + throw error; + } + } + } export default new ConnectionService(); \ No newline at end of file diff --git a/src/protocols/mediator/MediatorService.ts b/src/protocols/mediator/MediatorService.ts index 64efc77..050e671 100644 --- a/src/protocols/mediator/MediatorService.ts +++ b/src/protocols/mediator/MediatorService.ts @@ -12,11 +12,95 @@ import { createBatchPickupMessage, createKeylistUpdateMessage, createMediationRe import { Connection } from "react-native-arnima-sdk/src/protocols/connection/ConnectionInterface"; import { NativeModules } from "react-native"; import { createTrustPingMessage } from "react-native-arnima-sdk/src/protocols/trustPing/TrustPingMessages"; - +import InboundService from '../../transports' const { ArnimaSdk } = NativeModules; class MediatorService { + private transportSessions: Map = new Map() + private webSocket: typeof WebSocket + + constructor() { + this.webSocket = WebSocket; + } + + async sendWebSocketMessage(endpoint: string, outboundPackMessage: string) { + try { + + const socket = await this.resolveSocket(endpoint) + + socket.send(Buffer.from(JSON.stringify(outboundPackMessage))) + + } catch (error) { + console.log('MediatorService - sendWebSocketMessage error = ', error); + throw error; + } + } + + private async resolveSocket(endpoint: string) { + // If we already have a socket connection use it + let socket = this.transportSessions.get(endpoint) + + if (!socket) { + if (!endpoint) { + throw new Error(`Missing endpoint. I don't know how and where to send the message.`) + } + socket = await this.createSocketConnection(endpoint) + this.transportSessions.set(endpoint, socket) + this.listenOnWebSocketMessages(socket) + } + + if (socket.readyState !== this.webSocket.OPEN) { + throw new Error('Socket is not open.') + } + + return socket + } + + private handleMessageEvent = async (event: any) => { + console.log('WebSocket message event received.', { url: event.target.url, data: event.data }) + const wireMessage = JSON.parse(Buffer.from(event.data).toString('utf-8')) + if (wireMessage) { + console.log(`Response received`, wireMessage) + try { + if (wireMessage.hasOwnProperty('tag')) { + await InboundService.addMessages(wireMessage) + } + } catch (error) { + console.log('Unable to parse response message', error) + } + } + } + + private listenOnWebSocketMessages(socket: WebSocket) { + socket.addEventListener('message', this.handleMessageEvent) + } + + private createSocketConnection(endpoint: string): Promise { + return new Promise((resolve, reject) => { + console.log(`Connecting to WebSocket ${endpoint}`) + const socket = new this.webSocket(endpoint) + + socket.onopen = () => { + console.log(`Successfully connected to WebSocket ${endpoint}`) + resolve(socket) + } + + socket.onerror = (error) => { + console.log(`Error while connecting to WebSocket ${endpoint}`, { + error, + }) + reject(error) + } + + socket.onclose = async (event) => { + console.log(`WebSocket closing of endpoint ${endpoint}`, { event }) + socket.removeEventListener('message', this.handleMessageEvent) + this.transportSessions.delete(endpoint) + } + }) + } + async sendImplicitMessages(mediatorConnection: Connection) { try { const myWallet: any = DatabaseServices.getWallet(); diff --git a/src/utils/DidDoc.ts b/src/utils/DidDoc.ts index 0ae23bf..b849f21 100644 --- a/src/utils/DidDoc.ts +++ b/src/utils/DidDoc.ts @@ -150,8 +150,8 @@ export class Service { constructor( id: string, serviceEndpoint: string, - recipientKeys: Verkey[] = [], - routingKeys: Verkey[] = [], + recipientKeys: string[] = [], + routingKeys: string[] = [], priority: number = 0, type: string ) { diff --git a/src/utils/Helpers.ts b/src/utils/Helpers.ts index 2304b51..b149dab 100644 --- a/src/utils/Helpers.ts +++ b/src/utils/Helpers.ts @@ -3,9 +3,9 @@ SPDX-License-Identifier: Apache-2.0 */ -import {Connection} from '../protocols/connection/ConnectionInterface'; +import {Connection, ConnectionProps} from '../protocols/connection/ConnectionInterface'; import {createForwardMessage} from '../protocols/connection/ConnectionMessages'; -import {InboundMessage, OutboundMessage} from './Types'; +import {InboundMessage, OOBService, OutboundMessage} from './Types'; import {InvitationDetails} from '../protocols/connection/InvitationInterface'; import {Message} from './Types'; import {NativeModules, Platform} from 'react-native'; @@ -13,6 +13,9 @@ import {OutboundAgentMessage} from '../network'; import {WalletConfig, WalletCredentials} from '../wallet/WalletInterface'; import base64url from 'base64url'; import DatabaseServices from '../storage'; +import MediatorService from '../protocols/mediator/MediatorService'; +import { ConnectionState } from '../protocols/connection/ConnectionState'; +import { Service } from './DidDoc'; const Buffer = require('buffer').Buffer; global.Buffer = global.Buffer || require('buffer').Buffer; @@ -32,7 +35,7 @@ export enum RecordType { function timestamp(): Uint8Array { let time = Date.now(); - const bytes = []; + const bytes: number[] = []; for (let i = 0; i < 8; i++) { const byte = time & 0xff; bytes.push(byte); @@ -181,7 +184,6 @@ export async function packMessage( ) { try { const {routingKeys, recipientKeys, senderVk, payload} = outboundMessage; - console.log('outboundMessage', JSON.stringify(outboundMessage, null, 2)); const buf = Buffer.from(JSON.stringify(payload)); let packedBufferMessage; if (Platform.OS === 'ios') { @@ -286,11 +288,37 @@ export function encodeBase64(data: string) { return Buffer.from(JSON.stringify(data)).toString('base64'); } +function getServiceEndpointFromConnection(connection:ConnectionProps) { + const {theirDidDoc,state} = connection; + if (!theirDidDoc) { + throw new Error( + `DidDoc for connection with verkey ${connection.verkey} not found!`, + ); + } + const service = theirDidDoc?.service + + //Set the service endpoint to the one from the connection + let serviceEndpoint:string = service[0].serviceEndpoint + + //By default we should use the service endpoint from the connection with http protocol + //If the the service has websocket endpoint then use websocket service endpoint protocol + service.forEach(s => { + if(s.serviceEndpoint.includes('ws' || 'wss') && state === ConnectionState.COMPLETE){ + serviceEndpoint = s.serviceEndpoint + return; + } else if(s.serviceEndpoint.includes('http')){ + serviceEndpoint = s.serviceEndpoint + } + }); + + return serviceEndpoint +} + export async function createOutboundMessage( connection: Connection, payload: Object, invitation?: Message, - oobService?: object, + oobService?: OOBService, ) { if (connection) { const shouldUseReturnRoute = Boolean( @@ -321,17 +349,24 @@ export async function createOutboundMessage( ); } const {service} = theirDidDoc; + const serviceEndpoint = await getServiceEndpointFromConnection(connection) + return { connection, - endpoint: service[0].serviceEndpoint, + endpoint: serviceEndpoint, payload, recipientKeys: service[0].recipientKeys, routingKeys: service[0].routingKeys, senderVk: connection.verkey, }; } else { + + if(!oobService) { + throw new Error('No oobService provided') + } + const wallet = await DatabaseServices.getWallet(); - const [pairwiseDid, verkey]: string[] = await ArnimaSdk.createAndStoreMyDid( + const [, verkey]: string[] = await ArnimaSdk.createAndStoreMyDid( wallet.walletConfig, wallet.walletCredentials, JSON.stringify({}), @@ -354,19 +389,27 @@ export async function sendOutboundMessage( connection: Connection, message: Object, invitation?: Message, - oobService?: object, + oobService?: OOBService, ) { - const outboundMessage = await createOutboundMessage( + const outboundMessage: OutboundMessage = await createOutboundMessage( connection, message, invitation, oobService, ); + const outboundPackMessage = await packMessage( configJson, credentialsJson, outboundMessage, ); + + if(outboundMessage.endpoint.includes('ws')){ + console.log("Websocket endpoint", outboundMessage.endpoint); + await MediatorService.sendWebSocketMessage(outboundMessage.endpoint, outboundPackMessage); + return; + } + await OutboundAgentMessage( outboundMessage.endpoint, 'POST', diff --git a/src/utils/Types.ts b/src/utils/Types.ts index 82724de..d5ae576 100644 --- a/src/utils/Types.ts +++ b/src/utils/Types.ts @@ -24,12 +24,12 @@ export interface InboundMessage { } export interface OutboundMessage { - connection: Connection; - endpoint?: string; + connection?: Connection; + endpoint: string; payload: Object; recipientKeys: Verkey[]; - routingKeys: Verkey[]; - senderVk: Verkey | null; + routingKeys?: Verkey[]; + senderVk: Verkey; } export interface OutboundPackage { @@ -42,3 +42,9 @@ export interface InboundConnection { verkey: Verkey; connection: Connection; } + +export interface OOBService { + recipientKeys: string[]; + routingKeys?: string[]; + serviceEndpoint: string; +}