Skip to content

Commit

Permalink
feat: send and handle ack message
Browse files Browse the repository at this point in the history
Signed-off-by: Berend Sliedrecht <[email protected]>
  • Loading branch information
berendsliedrecht committed Oct 1, 2024
1 parent a50320e commit 71a1c77
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 35 deletions.
2 changes: 1 addition & 1 deletion example/src/credo/agent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ export const setupAgent = async () => {
id: 'react-native-ble-didcomm-agent',
key: 'react-native-ble-didcomm-key',
},
logger: new ConsoleLogger(LogLevel.trace),
logger: new ConsoleLogger(LogLevel.off),
},
modules: {
askar: new AskarModule({ ariesAskar }),
Expand Down
21 changes: 13 additions & 8 deletions example/src/credo/bleRequestProof.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
} from '@animo-id/react-native-ble-didcomm'
import type { AnonCredsProofFormat } from '@credo-ts/anoncreds'
import {
JsonTransformer,
MessageReceiver,
ProofEventTypes,
type ProofExchangeRecord,
Expand Down Expand Up @@ -57,7 +58,7 @@ export const bleRequestProof = async ({
)

const messageListener = startMessageReceiver(agent, peripheral)
await returnWhenProofReceived(proofRecordId, agent)
await returnWhenProofReceived(proofRecordId, agent, peripheral)
messageListener.remove()

return proofRecordId
Expand Down Expand Up @@ -140,17 +141,21 @@ const startMessageReceiver = (agent: AppAgent, peripheral: Peripheral) => {
})
}

const returnWhenProofReceived = (id: string, agent: AppAgent): Promise<ProofExchangeRecord> => {
const returnWhenProofReceived = (id: string, agent: AppAgent, peripheral: Peripheral): Promise<ProofExchangeRecord> => {
return new Promise((resolve, reject) => {
const listener = ({ payload }: ProofStateChangedEvent) => {
const listener = async ({ payload: { proofRecord } }: ProofStateChangedEvent) => {
const off = () => agent.events.off(ProofEventTypes.ProofStateChanged, listener)
if (payload.proofRecord.id === id) {
if (payload.proofRecord.state === ProofState.PresentationReceived) {
if (proofRecord.id === id) {
if (proofRecord.state === ProofState.PresentationReceived) {
const pp = agent.proofs.config.proofProtocols.find((x) => x.version === 'v2')
const { message } = await pp.acceptPresentation(agent.context, { proofRecord })
const serializedMessage = JsonTransformer.serialize(message)
await peripheral.sendMessage(serializedMessage)
off()
resolve(payload.proofRecord)
} else if ([ProofState.Abandoned, ProofState.Declined].includes(payload.proofRecord.state)) {
resolve(proofRecord)
} else if ([ProofState.Abandoned, ProofState.Declined].includes(proofRecord.state)) {
off()
reject(new Error(`Proof could not be shared because it has been ${payload.proofRecord.state}`))
reject(new Error(`Proof could not be shared because it has been ${proofRecord.state}`))
}
}
}
Expand Down
53 changes: 28 additions & 25 deletions example/src/credo/bleShareProof.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,15 @@ import {
} from '@animo-id/react-native-ble-didcomm'
import {
type Agent,
AutoAcceptProof,
JsonTransformer,
OutOfBandInvitation,
ProofEventTypes,
type ProofExchangeRecord,
ProofRepository,
ProofState,
type ProofStateChangedEvent,
V2PresentationAckMessage,
} from '@credo-ts/core'
import { BleInboundTransport, BleOutboundTransport } from '@credo-ts/transport-ble'
import type { AppAgent } from './agent'
Expand Down Expand Up @@ -48,6 +50,9 @@ export const bleShareProof = async ({
await connectedNotifier(agent, central, onConnected)

await shareProof(agent, central, serviceUuid)

const proofExchangeRecord = await autoRespondToBleProofRequest(agent)
await ackListener(central, proofExchangeRecord.threadId)
} catch (e) {
if (e instanceof Error) {
agent.config.logger.error(e.message, { cause: e })
Expand Down Expand Up @@ -133,8 +138,6 @@ const shareProof = async (agent: AppAgent, central: Central, serviceUuid: string

const parsedMessage = JsonTransformer.deserialize(message, OutOfBandInvitation)

const responder = autoRespondToBleProofRequest(agent)

const routing = await agent.mediationRecipient.getRouting({
useDefaultMediator: false,
})
Expand All @@ -143,10 +146,6 @@ const shareProof = async (agent: AppAgent, central: Central, serviceUuid: string
routing: { ...routing, endpoints: [`ble://${serviceUuid}`] },
})

const { id } = await responder

await waitForSharedProof(id, agent)

receivedMessageListener.remove()
resolve()
})
Expand All @@ -155,6 +154,9 @@ const shareProof = async (agent: AppAgent, central: Central, serviceUuid: string
const autoRespondToBleProofRequest = (agent: AppAgent): Promise<ProofExchangeRecord> => {
return new Promise((resolve, reject) => {
const listener = async ({ payload: { proofRecord } }: ProofStateChangedEvent) => {
console.log(`state: ${proofRecord.state}`)
const off = () => agent.events.off(ProofEventTypes.ProofStateChanged, listener)

if (proofRecord.state === ProofState.RequestReceived) {
const formatData = await agent.proofs.getFormatData(proofRecord.id)

Expand All @@ -163,35 +165,36 @@ const autoRespondToBleProofRequest = (agent: AppAgent): Promise<ProofExchangeRec
return
}

await agent.proofs.acceptRequest({ proofRecordId: proofRecord.id })

resolve(proofRecord)
} else if (proofRecord.state === ProofState.Done || proofRecord.state === ProofState.PresentationSent) {
await agent.proofs.acceptRequest({ proofRecordId: proofRecord.id, autoAcceptProof: AutoAcceptProof.Always })
} else if (proofRecord.state === ProofState.PresentationSent) {
const formatData = await agent.proofs.getFormatData(proofRecord.id)
const proofRepository = agent.dependencyManager.resolve(ProofRepository)
proofRecord.metadata.set(METADATA_KEY_FORMAT_DATA, formatData)
await proofRepository.update(agent.context, proofRecord)
agent.events.off(ProofEventTypes.ProofStateChanged, listener)
resolve(proofRecord)
off()
} else if ([ProofState.Abandoned, ProofState.Declined].includes(proofRecord.state)) {
reject(new Error(`Proof could not be shared because it has been ${proofRecord.state}`))
off()
}
}
agent.events.on<ProofStateChangedEvent>(ProofEventTypes.ProofStateChanged, listener)
})
}

const waitForSharedProof = (id: string, agent: AppAgent): Promise<ProofExchangeRecord> =>
new Promise((resolve, reject) => {
const listener = ({ payload }: ProofStateChangedEvent) => {
const off = () => agent.events.off(ProofEventTypes.ProofStateChanged, listener)
if (payload.proofRecord.id === id) {
if (payload.proofRecord.state === ProofState.PresentationReceived) {
off()
resolve(payload.proofRecord)
} else if ([ProofState.Abandoned, ProofState.Declined].includes(payload.proofRecord.state)) {
off()
reject(new Error(`Proof could not be shared because it has been ${payload.proofRecord.state}`))
}
// TODO: we could process the ack message here like is done in credo.
// would be better even to handle the message itself in credo, but it gets quite complex
const ackListener = (central: Central, expectedThreadId: string) =>
new Promise<void>((resolve, reject) => {
const listener = central.registerMessageListener(({ message }) => {
if (!message.includes('@type')) reject('received invalid message')
const ackMessage = JsonTransformer.deserialize(message, V2PresentationAckMessage)
if (ackMessage.threadId === expectedThreadId) {
listener.remove()
resolve()
} else {
reject('Received ack message with invalid thread id')
listener.remove()
}
}
agent.events.on<ProofStateChangedEvent>(ProofEventTypes.ProofStateChanged, listener)
})
})
2 changes: 1 addition & 1 deletion example/src/credo/utils/createBleProofMessage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ export const createBleProofRequestMessage = async (
const { proofRecord, message } = await agent.proofs.createRequest({
proofFormats: requestMessage,
protocolVersion: 'v2',
autoAcceptProof: AutoAcceptProof.Always,
autoAcceptProof: AutoAcceptProof.Never,
})

const routing = await agent.mediationRecipient.getRouting({ useDefaultMediator: false })
Expand Down

0 comments on commit 71a1c77

Please sign in to comment.