Skip to content

Commit 07ea58e

Browse files
committed
test(cheqd): Add JsonLD issuance test
Signed-off-by: DaevMithran <daevmithran1999@gmail.com>
1 parent 2310b90 commit 07ea58e

File tree

1 file changed

+340
-0
lines changed

1 file changed

+340
-0
lines changed
Lines changed: 340 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,340 @@
1+
import type { CheqdDidCreateOptions } from '../src'
2+
3+
import {
4+
SECURITY_JWS_CONTEXT_URL,
5+
DidDocumentBuilder,
6+
getEd25519VerificationKey2018,
7+
KeyType,
8+
utils,
9+
Agent,
10+
TypedArrayEncoder,
11+
DifPresentationExchangeProofFormatService,
12+
JsonLdCredentialFormatService,
13+
CredentialsModule,
14+
V2CredentialProtocol,
15+
ProofsModule,
16+
V2ProofProtocol,
17+
CacheModule,
18+
InMemoryLruCache,
19+
W3cCredentialsModule,
20+
CredentialState,
21+
CredentialExchangeRecord,
22+
JsonTransformer,
23+
ProofEventTypes,
24+
CredentialEventTypes,
25+
} from '@credo-ts/core'
26+
27+
import { getInMemoryAgentOptions, makeConnection, waitForCredentialRecordSubject } from '../../core/tests/helpers'
28+
29+
import { cheqdPayerSeeds, getCheqdModules } from './setupCheqdModule'
30+
import { EventReplaySubject, setupEventReplaySubjects, setupSubjectTransports, testLogger } from '../../core/tests'
31+
32+
let did = `did:cheqd:testnet:${utils.uuid()}`
33+
34+
const signCredentialOptions = {
35+
credential: {
36+
'@context': [
37+
'https://www.w3.org/2018/credentials/v1',
38+
'https://w3id.org/citizenship/v1',
39+
'https://w3id.org/security/bbs/v1',
40+
],
41+
id: 'https://issuer.oidp.uscis.gov/credentials/83627465',
42+
type: ['VerifiableCredential', 'PermanentResidentCard'],
43+
issuer: did,
44+
issuanceDate: '2019-12-03T12:19:52Z',
45+
expirationDate: '2029-12-03T12:19:52Z',
46+
identifier: '83627465',
47+
name: 'Permanent Resident Card',
48+
credentialSubject: {
49+
id: 'did:example:b34ca6cd37bbf23',
50+
type: ['PermanentResident', 'Person'],
51+
givenName: 'JOHN',
52+
familyName: 'SMITH',
53+
gender: 'Male',
54+
image: 'data:image/png;base64,iVBORw0KGgokJggg==',
55+
residentSince: '2015-01-01',
56+
description: 'Government of Example Permanent Resident Card.',
57+
lprCategory: 'C09',
58+
lprNumber: '999-999-999',
59+
commuterClassification: 'C1',
60+
birthCountry: 'Bahamas',
61+
birthDate: '1958-07-17',
62+
},
63+
},
64+
options: {
65+
proofType: 'Ed25519Signature2018',
66+
proofPurpose: 'assertionMethod',
67+
},
68+
}
69+
70+
const jsonLdCredentialFormat = new JsonLdCredentialFormatService()
71+
const jsonLdProofFormat = new DifPresentationExchangeProofFormatService()
72+
73+
const getCheqdJsonLdModules = () =>
74+
({
75+
...getCheqdModules(cheqdPayerSeeds[0], 'https://rpc.cheqd.network'),
76+
credentials: new CredentialsModule({
77+
credentialProtocols: [
78+
new V2CredentialProtocol({
79+
credentialFormats: [jsonLdCredentialFormat],
80+
}),
81+
],
82+
}),
83+
proofs: new ProofsModule({
84+
proofProtocols: [
85+
new V2ProofProtocol({
86+
proofFormats: [jsonLdProofFormat],
87+
}),
88+
],
89+
}),
90+
cache: new CacheModule({
91+
cache: new InMemoryLruCache({ limit: 100 }),
92+
}),
93+
w3cCredentials: new W3cCredentialsModule({}),
94+
} as const)
95+
96+
// TODO: extract these very specific tests to the jsonld format
97+
describe('Cheqd V2 Credentials - JSON-LD - Ed25519', () => {
98+
let faberAgent: Agent<ReturnType<typeof getCheqdJsonLdModules>>
99+
let faberReplay: EventReplaySubject
100+
let aliceAgent: Agent<ReturnType<typeof getCheqdJsonLdModules>>
101+
let aliceReplay: EventReplaySubject
102+
let aliceConnectionId: string
103+
104+
beforeAll(async () => {
105+
faberAgent = new Agent(
106+
getInMemoryAgentOptions(
107+
'Faber Agent Indy/JsonLD',
108+
{
109+
endpoints: ['rxjs:faber'],
110+
},
111+
getCheqdJsonLdModules()
112+
)
113+
)
114+
aliceAgent = new Agent(
115+
getInMemoryAgentOptions(
116+
'Alice Agent Indy/JsonLD',
117+
{
118+
endpoints: ['rxjs:alice'],
119+
},
120+
getCheqdJsonLdModules()
121+
)
122+
)
123+
124+
setupSubjectTransports([faberAgent, aliceAgent])
125+
;[faberReplay, aliceReplay] = setupEventReplaySubjects(
126+
[faberAgent, aliceAgent],
127+
[CredentialEventTypes.CredentialStateChanged, ProofEventTypes.ProofStateChanged]
128+
)
129+
await faberAgent.initialize()
130+
await aliceAgent.initialize()
131+
;[, { id: aliceConnectionId }] = await makeConnection(faberAgent, aliceAgent)
132+
133+
await faberAgent.context.wallet.createKey({
134+
privateKey: TypedArrayEncoder.fromString('testseed000000000000000000000001'),
135+
keyType: KeyType.Ed25519,
136+
})
137+
})
138+
139+
afterAll(async () => {
140+
await faberAgent.shutdown()
141+
await faberAgent.wallet.delete()
142+
await aliceAgent.shutdown()
143+
await aliceAgent.wallet.delete()
144+
})
145+
146+
it('should create a did:cheqd did using custom did document containing Ed25519 key', async () => {
147+
const ed25519Key = await faberAgent.wallet.createKey({
148+
keyType: KeyType.Ed25519,
149+
})
150+
151+
const createResult = await faberAgent.dids.create<CheqdDidCreateOptions>({
152+
method: 'cheqd',
153+
didDocument: new DidDocumentBuilder(did)
154+
.addContext(SECURITY_JWS_CONTEXT_URL)
155+
.addVerificationMethod(
156+
getEd25519VerificationKey2018({
157+
key: ed25519Key,
158+
controller: did,
159+
id: `${did}#${ed25519Key.fingerprint}`,
160+
})
161+
)
162+
.addAssertionMethod(`${did}#${ed25519Key.fingerprint}`)
163+
.addAuthentication(`${did}#${ed25519Key.fingerprint}`)
164+
.build(),
165+
})
166+
167+
expect(createResult).toMatchObject({
168+
didState: {
169+
state: 'finished',
170+
},
171+
})
172+
173+
expect(createResult.didState.didDocument?.toJSON()).toMatchObject({
174+
'@context': ['https://w3id.org/did/v1', 'https://w3id.org/security/suites/jws-2020/v1'],
175+
verificationMethod: [
176+
{
177+
controller: did,
178+
type: 'Ed25519VerificationKey2018',
179+
publicKeyBase58: ed25519Key.publicKeyBase58,
180+
},
181+
],
182+
})
183+
})
184+
185+
test('Alice starts with V2 (ld format, Ed25519 signature) credential proposal to Faber', async () => {
186+
testLogger.test('Alice sends (v2 jsonld) credential proposal to Faber')
187+
188+
const credentialExchangeRecord = await aliceAgent.credentials.proposeCredential({
189+
connectionId: aliceConnectionId,
190+
protocolVersion: 'v2',
191+
credentialFormats: {
192+
jsonld: signCredentialOptions,
193+
},
194+
comment: 'v2 propose credential test for W3C Credentials',
195+
})
196+
197+
expect(credentialExchangeRecord.connectionId).toEqual(aliceConnectionId)
198+
expect(credentialExchangeRecord.protocolVersion).toEqual('v2')
199+
expect(credentialExchangeRecord.state).toEqual(CredentialState.ProposalSent)
200+
expect(credentialExchangeRecord.threadId).not.toBeNull()
201+
202+
testLogger.test('Faber waits for credential proposal from Alice')
203+
let faberCredentialRecord = await waitForCredentialRecordSubject(faberReplay, {
204+
threadId: credentialExchangeRecord.threadId,
205+
state: CredentialState.ProposalReceived,
206+
})
207+
208+
testLogger.test('Faber sends credential offer to Alice')
209+
await faberAgent.credentials.acceptProposal({
210+
credentialRecordId: faberCredentialRecord.id,
211+
comment: 'V2 W3C Offer',
212+
})
213+
214+
testLogger.test('Alice waits for credential offer from Faber')
215+
let aliceCredentialRecord = await waitForCredentialRecordSubject(aliceReplay, {
216+
threadId: faberCredentialRecord.threadId,
217+
state: CredentialState.OfferReceived,
218+
})
219+
220+
const offerMessage = await aliceAgent.credentials.findOfferMessage(aliceCredentialRecord.id)
221+
expect(JsonTransformer.toJSON(offerMessage)).toMatchObject({
222+
'@type': 'https://didcomm.org/issue-credential/2.0/offer-credential',
223+
'@id': expect.any(String),
224+
comment: 'V2 W3C Offer',
225+
formats: [
226+
{
227+
attach_id: expect.any(String),
228+
format: 'aries/ld-proof-vc-detail@v1.0',
229+
},
230+
],
231+
'offers~attach': [
232+
{
233+
'@id': expect.any(String),
234+
'mime-type': 'application/json',
235+
data: expect.any(Object),
236+
lastmod_time: undefined,
237+
byte_count: undefined,
238+
},
239+
],
240+
'~thread': {
241+
thid: expect.any(String),
242+
pthid: undefined,
243+
sender_order: undefined,
244+
received_orders: undefined,
245+
},
246+
'~service': undefined,
247+
'~attach': undefined,
248+
'~please_ack': undefined,
249+
'~timing': undefined,
250+
'~transport': undefined,
251+
'~l10n': undefined,
252+
credential_preview: expect.any(Object),
253+
replacement_id: undefined,
254+
})
255+
expect(aliceCredentialRecord.id).not.toBeNull()
256+
expect(aliceCredentialRecord.type).toBe(CredentialExchangeRecord.type)
257+
258+
const offerCredentialExchangeRecord = await aliceAgent.credentials.acceptOffer({
259+
credentialRecordId: aliceCredentialRecord.id,
260+
credentialFormats: {
261+
jsonld: {},
262+
},
263+
})
264+
265+
expect(offerCredentialExchangeRecord.connectionId).toEqual(aliceConnectionId)
266+
expect(offerCredentialExchangeRecord.protocolVersion).toEqual('v2')
267+
expect(offerCredentialExchangeRecord.state).toEqual(CredentialState.RequestSent)
268+
expect(offerCredentialExchangeRecord.threadId).not.toBeNull()
269+
270+
testLogger.test('Faber waits for credential request from Alice')
271+
await waitForCredentialRecordSubject(faberReplay, {
272+
threadId: aliceCredentialRecord.threadId,
273+
state: CredentialState.RequestReceived,
274+
})
275+
276+
testLogger.test('Faber sends credential to Alice')
277+
278+
await faberAgent.credentials.acceptRequest({
279+
credentialRecordId: faberCredentialRecord.id,
280+
comment: 'V2 Indy Credential',
281+
})
282+
283+
testLogger.test('Alice waits for credential from Faber')
284+
aliceCredentialRecord = await waitForCredentialRecordSubject(aliceReplay, {
285+
threadId: faberCredentialRecord.threadId,
286+
state: CredentialState.CredentialReceived,
287+
})
288+
289+
testLogger.test('Alice sends credential ack to Faber')
290+
await aliceAgent.credentials.acceptCredential({ credentialRecordId: aliceCredentialRecord.id })
291+
292+
testLogger.test('Faber waits for credential ack from Alice')
293+
faberCredentialRecord = await waitForCredentialRecordSubject(faberReplay, {
294+
threadId: faberCredentialRecord.threadId,
295+
state: CredentialState.Done,
296+
})
297+
expect(aliceCredentialRecord).toMatchObject({
298+
type: CredentialExchangeRecord.type,
299+
id: expect.any(String),
300+
createdAt: expect.any(Date),
301+
threadId: expect.any(String),
302+
connectionId: expect.any(String),
303+
state: CredentialState.CredentialReceived,
304+
})
305+
306+
const credentialMessage = await faberAgent.credentials.findCredentialMessage(faberCredentialRecord.id)
307+
expect(JsonTransformer.toJSON(credentialMessage)).toMatchObject({
308+
'@type': 'https://didcomm.org/issue-credential/2.0/issue-credential',
309+
'@id': expect.any(String),
310+
comment: 'V2 Indy Credential',
311+
formats: [
312+
{
313+
attach_id: expect.any(String),
314+
format: 'aries/ld-proof-vc@v1.0',
315+
},
316+
],
317+
'credentials~attach': [
318+
{
319+
'@id': expect.any(String),
320+
'mime-type': 'application/json',
321+
data: expect.any(Object),
322+
lastmod_time: undefined,
323+
byte_count: undefined,
324+
},
325+
],
326+
'~thread': {
327+
thid: expect.any(String),
328+
pthid: undefined,
329+
sender_order: undefined,
330+
received_orders: undefined,
331+
},
332+
'~please_ack': { on: ['RECEIPT'] },
333+
'~service': undefined,
334+
'~attach': undefined,
335+
'~timing': undefined,
336+
'~transport': undefined,
337+
'~l10n': undefined,
338+
})
339+
})
340+
})

0 commit comments

Comments
 (0)