Skip to content

Commit

Permalink
feat: add support for did-comm over simple HTTP-based transports (#610)
Browse files Browse the repository at this point in the history
fixes #552
fixes #469

* feat: add sending didcomm messages
* feat: add transport logic
* fix(did-comm): message handler
* docs: add more inline documentation for did-comm
* fix: use http transport by default with didcomm
* test(did-comm): integration test for sending data
* test(did-comm): check didcomm events
* style: refactoring and code reformatting

Co-authored-by: Oliver Terbu <>
Co-authored-by: Mircea Nistor <mirceanis@gmail.com>
Co-authored-by: Simonas Karuzas <simonas@not.cat>
  • Loading branch information
3 people committed Jul 8, 2021
1 parent eebe32c commit 78836a4
Show file tree
Hide file tree
Showing 12 changed files with 434 additions and 129 deletions.
4 changes: 3 additions & 1 deletion __tests__/localAgent.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ import didComm from './shared/didcomm'
import messageHandler from './shared/messageHandler'
import didDiscovery from './shared/didDiscovery'
import { FakeDidProvider, FakeDidResolver } from './utils/fake-did'
import { DIDCommHttpTransport } from '../packages/did-comm/src/transports/transports'

const databaseFile = 'local-database.sqlite'
const infuraProjectId = '5ffc47f65c4042ce847ef66a3fa70d4c'
Expand Down Expand Up @@ -152,12 +153,13 @@ const setup = async (options?: IAgentOptions): Promise<boolean> => {
new SdrMessageHandler(),
],
}),
new DIDComm(),
new DIDComm([new DIDCommHttpTransport()]),
new CredentialIssuer(),
new SelectiveDisclosure(),
new DIDDiscovery({
providers: [new AliasDiscoveryProvider(), new ProfileDiscoveryProvider()],
}),
...options?.plugins || [],
],
})
return true
Expand Down
2 changes: 1 addition & 1 deletion __tests__/localMemoryStoreAgent.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@ import { FakeDidProvider, FakeDidResolver } from './utils/fake-did'

const databaseFile = 'local-database2.sqlite'
const infuraProjectId = '5ffc47f65c4042ce847ef66a3fa70d4c'
const secretKey = '29739248cad1bd1a0fc4d9b75cd4d2990de535baf5caadfdf8d8f86664aa830c'

let agent: TAgent<
IDIDManager &
Expand Down Expand Up @@ -143,6 +142,7 @@ const setup = async (options?: IAgentOptions): Promise<boolean> => {
new DIDComm(),
new CredentialIssuer(),
new SelectiveDisclosure(),
...options?.plugins || [],
],
})
return true
Expand Down
22 changes: 17 additions & 5 deletions __tests__/restAgent.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,14 +40,15 @@ import {
import { AgentRestClient } from '../packages/remote-client/src'
import express from 'express'
import { Server } from 'http'
import { AgentRouter, RequestWithAgentRouter } from '../packages/remote-server/src'
import { AgentRouter, RequestWithAgentRouter, MessagingRouter } from '../packages/remote-server/src'
import { Resolver } from 'did-resolver'
import { getResolver as ethrDidResolver } from 'ethr-did-resolver'
import { getResolver as webDidResolver } from 'web-did-resolver'
import { IDIDDiscovery, DIDDiscovery } from '../packages/did-discovery'
import { getUniversalResolver } from '../packages/did-resolver/src/universal-resolver'
import { FakeDidProvider, FakeDidResolver } from './utils/fake-did'

// import { getUniversalResolver } from '../packages/did-resolver/src/universal-resolver'
import { DIDCommHttpTransport } from '../packages/did-comm/src/transports/transports'
import { getDidKeyResolver } from '../packages/did-provider-key/build'
import fs from 'fs'

jest.setTimeout(30000)
Expand All @@ -61,6 +62,7 @@ import documentationExamples from './shared/documentationExamples'
import keyManager from './shared/keyManager'
import didManager from './shared/didManager'
import didComm from './shared/didcomm'
import didCommRemote from './shared/didcommRemote'
import messageHandler from './shared/messageHandler'
import didDiscovery from './shared/didDiscovery'

Expand Down Expand Up @@ -146,7 +148,8 @@ const setup = async (options?: IAgentOptions): Promise<boolean> => {
resolver: new Resolver({
...ethrDidResolver({ infuraProjectId }),
...webDidResolver(),
key: getUniversalResolver(), // resolve using remote resolver,
// key: getUniversalResolver(), // resolve using remote resolver... when uniresolver becomes more stable,
...getDidKeyResolver(),
...new FakeDidResolver(() => serverAgent as TAgent<IDIDManager>).getDidFakeResolver(),
}),
}),
Expand All @@ -160,12 +163,13 @@ const setup = async (options?: IAgentOptions): Promise<boolean> => {
new SdrMessageHandler(),
],
}),
new DIDComm(),
new DIDComm([new DIDCommHttpTransport()]),
new CredentialIssuer(),
new SelectiveDisclosure(),
new DIDDiscovery({
providers: [new AliasDiscoveryProvider(), new ProfileDiscoveryProvider()],
}),
...options?.plugins || [],
],
})

Expand All @@ -180,6 +184,13 @@ const setup = async (options?: IAgentOptions): Promise<boolean> => {
return new Promise((resolve) => {
const app = express()
app.use(basePath, requestWithAgent, agentRouter)
app.use(
'/messaging',
requestWithAgent,
MessagingRouter({
metaData: { type: 'DIDComm', value: 'integration test' },
}),
)
restServer = app.listen(port, () => {
resolve(true)
})
Expand All @@ -205,5 +216,6 @@ describe('REST integration tests', () => {
didManager(testContext)
messageHandler(testContext)
didComm(testContext)
didCommRemote(testContext)
didDiscovery(testContext)
})
126 changes: 126 additions & 0 deletions __tests__/shared/didcommRemote.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
import {
TAgent,
IDIDManager,
IKeyManager,
IIdentifier,
IResolver,
IEventListener,
IAgentOptions,
} from '../../packages/core/src'
import { IDIDComm } from '../../packages/did-comm/src'

type ConfiguredAgent = TAgent<IDIDManager & IKeyManager & IResolver & IDIDComm>

const DIDCommEventSniffer: IEventListener = {
eventTypes: ['DIDCommV2Message-sent', 'DIDCommV2Message-received'],
onEvent: jest.fn(),
}

export default (testContext: {
getAgent: () => ConfiguredAgent
setup: (options?: IAgentOptions) => Promise<boolean>
tearDown: () => Promise<boolean>
}) => {
describe('DID comm remote', () => {
let agent: ConfiguredAgent
let sender: IIdentifier
let receiver: IIdentifier

beforeAll(async () => {
await testContext.setup({ plugins: [DIDCommEventSniffer] })
agent = testContext.getAgent()

sender = await agent.didManagerImport({
did: 'did:fake:z6MkgbqNU4uF9NKSz5BqJQ4XKVHuQZYcUZP8pXGsJC8nTHwo',
keys: [
{
type: 'Ed25519',
kid: 'didcomm-senderKey-1',
publicKeyHex: '1fe9b397c196ab33549041b29cf93be29b9f2bdd27322f05844112fad97ff92a',
privateKeyHex:
'b57103882f7c66512dc96777cbafbeb2d48eca1e7a867f5a17a84e9a6740f7dc1fe9b397c196ab33549041b29cf93be29b9f2bdd27322f05844112fad97ff92a',
kms: 'local',
},
],
services: [
{
id: 'msg1',
type: 'DIDCommMessaging',
serviceEndpoint: 'http://localhost:3002/messaging',
},
],
provider: 'did:fake',
alias: 'sender',
})

receiver = await agent.didManagerImport({
did: 'did:fake:z6MkrPhffVLBZpxH7xvKNyD4sRVZeZsNTWJkLdHdgWbfgNu3',
keys: [
{
type: 'Ed25519',
kid: 'didcomm-receiverKey-1',
publicKeyHex: 'b162e405b6485eff8a57932429b192ec4de13c06813e9028a7cdadf0e2703636',
privateKeyHex:
'19ed9b6949cfd0f9a57e30f0927839a985fa699491886ebcdda6a954d869732ab162e405b6485eff8a57932429b192ec4de13c06813e9028a7cdadf0e2703636',
kms: 'local',
},
],
services: [
{
id: 'msg2',
type: 'DIDCommMessaging',
serviceEndpoint: 'http://localhost:3002/messaging',
},
],
provider: 'did:fake',
alias: 'receiver',
})
return true
})
afterAll(testContext.tearDown)

it('should send a message', async () => {
expect.assertions(3)

const message = {
type: 'test',
to: receiver.did,
from: sender.did,
id: 'test',
body: { hello: 'world' },
}
const packedMessage = await agent.packDIDCommMessage({
packing: 'authcrypt',
message,
})
const result = await agent.sendDIDCommMessage({
messageId: '123',
packedMessage,
recipientDidUrl: receiver.did,
})

expect(result).toBeTruthy()
expect(DIDCommEventSniffer.onEvent).toHaveBeenCalledWith(
{ data: '123', type: 'DIDCommV2Message-sent' },
expect.anything(),
)
// in our case, it is the same agent that is receiving the messages
expect(DIDCommEventSniffer.onEvent).toHaveBeenCalledWith(
{
data: {
message: {
body: { hello: 'world' },
from: 'did:fake:z6MkgbqNU4uF9NKSz5BqJQ4XKVHuQZYcUZP8pXGsJC8nTHwo',
id: 'test',
to: 'did:fake:z6MkrPhffVLBZpxH7xvKNyD4sRVZeZsNTWJkLdHdgWbfgNu3',
type: 'test',
},
metaData: { packing: 'authcrypt' },
},
type: 'DIDCommV2Message-received',
},
expect.anything(),
)
})
})
}
41 changes: 12 additions & 29 deletions packages/did-comm/plugin.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -103,39 +103,22 @@
"packedMessage": {
"$ref": "#/components/schemas/IPackedDIDCommMessage"
},
"returnTransport": {
"$ref": "#/components/schemas/IDIDCommTransport"
"messageId": {
"type": "string"
},
"recipientDID": {
"returnTransportId": {
"type": "string"
}
},
"required": [
"packedMessage",
"recipientDID"
]
},
"IDIDCommTransport": {
"type": "object",
"properties": {
"id": {
},
"recipientDidUrl": {
"type": "string"
}
},
"required": [
"id"
]
},
"ISendDIDCommMessageResult": {
"type": "object",
"properties": {
"sent": {
"type": "boolean"
},
"error": {
"type": "string"
}
}
"packedMessage",
"messageId",
"recipientDidUrl"
],
"description": "The input to the {@link DIDComm.sendDIDCommMessage } method. The provided `messageId` will be used in the emitted event to allow event/message correlation."
},
"ISendMessageDIDCommAlpha1Args": {
"type": "object",
Expand Down Expand Up @@ -488,12 +471,12 @@
}
},
"sendDIDCommMessage": {
"description": "TODO: add docs here",
"description": "Sends the given message to the recipient. If a return transport is provided it will be checked whether the parent thread allows reusing the route. You cannot reuse the transport if the message was forwarded from a DIDComm mediator.",
"arguments": {
"$ref": "#/components/schemas/ISendDIDCommMessageArgs"
},
"returnType": {
"$ref": "#/components/schemas/ISendDIDCommMessageResult"
"type": "string"
}
},
"sendMessageDIDCommAlpha1": {
Expand Down
Loading

0 comments on commit 78836a4

Please sign in to comment.