Skip to content

Commit 9632abc

Browse files
committed
feat(cheqd): Add CheqdTokenStatusListRegistry and tests
Signed-off-by: DaevMithran <[email protected]>
1 parent c91f53f commit 9632abc

File tree

9 files changed

+219
-80
lines changed

9 files changed

+219
-80
lines changed

packages/cheqd/src/wrappers/CheqdTokenStatusListRegistry.ts

Lines changed: 23 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,17 @@
1-
import { type AgentContext, Buffer, CredoError, Jwt, utils } from '@credo-ts/core'
21
import {
2+
type AgentContext,
3+
CredoError,
4+
Jwt,
35
PublishTokenStatusListOptions,
6+
SdJwtVcIssuerDid,
47
TokenStatusListRegistry,
5-
} from 'packages/core/src/modules/sd-jwt-vc/credential-status/token-status-list/TokenStatusListRegistry'
8+
TokenStatusListResponse,
9+
TypedArrayEncoder,
10+
utils,
11+
} from '@credo-ts/core'
612
import { parseCheqdDid } from '../anoncreds/utils/identifiers'
713
import { CheqdCreateResourceOptions, CheqdDidRegistrar, CheqdDidResolver } from '../dids'
814

9-
export interface CheqdPublishTokenStatusListOptions extends PublishTokenStatusListOptions {
10-
name: string
11-
}
12-
1315
export class CheqdTokenStatusListRegistry implements TokenStatusListRegistry {
1416
public readonly supportedMethods = ['cheqd']
1517
public readonly allowsCaching = true
@@ -19,11 +21,11 @@ export class CheqdTokenStatusListRegistry implements TokenStatusListRegistry {
1921
*/
2022
async publish(
2123
agentContext: AgentContext,
22-
statusListId: string,
24+
issuer: SdJwtVcIssuerDid,
2325
jwt: string,
24-
options: CheqdPublishTokenStatusListOptions
26+
options: PublishTokenStatusListOptions
2527
): Promise<string> {
26-
const parsedDid = parseCheqdDid(statusListId)
28+
const parsedDid = parseCheqdDid(issuer.didUrl)
2729
if (!parsedDid) {
2830
throw new Error('Invalid did:cheqd')
2931
}
@@ -48,11 +50,8 @@ export class CheqdTokenStatusListRegistry implements TokenStatusListRegistry {
4850
const { didDocument } = await didResolver.resolve(agentContext, did, parsedDid)
4951
if (!didDocument) throw new CredoError(`Unable to resolve DID Document for ${did}`)
5052

51-
const kid = parsedJwt.header.kid
52-
if (!kid) throw new CredoError(`JWT is missing 'kid' header`)
53-
54-
const method = didDocument.verificationMethod?.find((vm) => vm.id === kid)
55-
if (!method) throw new CredoError(`No verification method found for kid ${kid}`)
53+
const method = didDocument.verificationMethod?.find((vm) => vm.id === issuer.didUrl)
54+
if (!method) throw new CredoError(`No verification method found for issuer ${issuer.didUrl}`)
5655

5756
// Upload to Cheqd
5857
const cheqdDidRegistrar = agentContext.dependencyManager.resolve(CheqdDidRegistrar)
@@ -62,7 +61,7 @@ export class CheqdTokenStatusListRegistry implements TokenStatusListRegistry {
6261
id: utils.uuid(),
6362
name: options.name,
6463
resourceType: 'TokenStatusList',
65-
data: Buffer.from(jwt),
64+
data: TypedArrayEncoder.toBase64(TypedArrayEncoder.fromString(jwt)),
6665
version: options.version ?? utils.uuid(),
6766
}
6867

@@ -71,20 +70,25 @@ export class CheqdTokenStatusListRegistry implements TokenStatusListRegistry {
7170
throw new CredoError(response.resourceState.reason ?? 'Unknown error')
7271
}
7372

73+
// return statusListUri
7474
return `${did}?resourceName=${options.name}&resourceType=TokenStatusList`
7575
}
7676

7777
/**
7878
* Retrieve a token status list JWT from the registry
7979
*/
80-
async retrieve(agentContext: AgentContext, statusListId: string): Promise<string> {
80+
async retrieve(agentContext: AgentContext, statusListUri: SdJwtVcIssuerDid): Promise<TokenStatusListResponse> {
8181
const cheqdDidResolver = agentContext.dependencyManager.resolve(CheqdDidResolver)
8282

83-
const response = await cheqdDidResolver.resolveResource(agentContext, statusListId)
84-
if (response.error) {
83+
const response = await cheqdDidResolver.resolveResource(agentContext, statusListUri.didUrl)
84+
if (response.error || !response.resourceMetadata) {
8585
throw new CredoError(response.message)
8686
}
8787

88-
return response.resource
88+
return {
89+
jwt: TypedArrayEncoder.fromBase64(response.resource).toString(),
90+
name: response.resourceMetadata?.name,
91+
version: response.resourceMetadata?.version,
92+
}
8993
}
9094
}
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
import type { CheqdDidCreateOptions } from '../src'
2+
3+
import { Agent, SdJwtVcIssuer, TokenStatusListService } from '@credo-ts/core'
4+
5+
import { getAgentOptions } from '../../core/tests/helpers'
6+
import { getCheqdModules } from './setupCheqdModule'
7+
8+
// biome-ignore lint/suspicious/noExportsInTest: <explanation>
9+
export const agent = new Agent(
10+
getAgentOptions('Cheqd Status List Registry', {}, {}, getCheqdModules(undefined, 'https://rpc.cheqd.network:443'))
11+
)
12+
13+
describe('Cheqd DID Token Status List Registry', () => {
14+
let did: string
15+
16+
beforeAll(async () => {
17+
await agent.initialize()
18+
const didResult = await agent.dids.create<CheqdDidCreateOptions>({
19+
method: 'cheqd',
20+
options: {
21+
createKey: { type: { kty: 'OKP', crv: 'Ed25519' } },
22+
network: 'testnet',
23+
methodSpecificIdAlgo: 'uuid',
24+
},
25+
})
26+
27+
if (!didResult.didState.did) {
28+
throw new Error('No DID created')
29+
}
30+
did = didResult.didState.did
31+
})
32+
33+
afterAll(async () => {
34+
await agent.shutdown()
35+
})
36+
37+
it('should publish and retreive a token status list in local testnet', async () => {
38+
const tokenStatusListService = agent.dependencyManager.resolve(TokenStatusListService)
39+
const resolveResult = await agent.dids.resolve(did, {
40+
useLocalCreatedDidRecord: false,
41+
})
42+
expect(resolveResult.didDocument).toBeDefined()
43+
44+
const issuer: SdJwtVcIssuer = {
45+
method: 'did',
46+
didUrl: `${did}#key-1`,
47+
}
48+
49+
const result = await tokenStatusListService.createStatusList(agent.context, issuer, {
50+
name: 'test-token-status-list',
51+
size: 10,
52+
publish: true,
53+
})
54+
expect(result.jwt).toBeDefined()
55+
expect(result.uri).toBeDefined()
56+
expect(result.uri).toContain(did)
57+
58+
const statusListUri: SdJwtVcIssuer = {
59+
method: 'did',
60+
didUrl: result.uri as string,
61+
}
62+
63+
// fetch token status list
64+
const statusList = await tokenStatusListService.getStatusList(agent.context, statusListUri)
65+
expect(statusList).toBeDefined()
66+
67+
// verify token status at index 0
68+
const status = await tokenStatusListService.getStatus(agent.context, statusListUri, 0)
69+
expect(status).toBe(0)
70+
71+
// revoke index 0
72+
await tokenStatusListService.revokeIndex(agent.context, issuer, statusListUri, { indices: [0], publish: true })
73+
74+
// verify token status at index 0
75+
const isRevoked = await tokenStatusListService.getStatus(agent.context, statusListUri, 0)
76+
expect(isRevoked).toBe(1)
77+
})
78+
})

packages/cheqd/tests/setupCheqdModule.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
import type { CheqdModuleConfigOptions } from '../src'
22

3-
import { DidsModule } from '@credo-ts/core'
3+
import { DidsModule, SdJwtVcModule } from '@credo-ts/core'
44

55
import { CheqdDidRegistrar, CheqdDidResolver, CheqdModule } from '../src'
6+
import { CheqdTokenStatusListRegistry } from '../src/wrappers/CheqdTokenStatusListRegistry'
67

78
export const cheqdPayerSeeds = [
89
'sketch mountain erode window enact net enrich smoke claim kangaroo another visual write meat latin bacon pulp similar forum guilt father state erase bright',
@@ -36,4 +37,7 @@ export const getCheqdModules = (seed?: string, rpcUrl?: string) => ({
3637
registrars: [new CheqdDidRegistrar()],
3738
resolvers: [new CheqdDidResolver()],
3839
}),
40+
sdJwtVc: new SdJwtVcModule({
41+
registries: [new CheqdTokenStatusListRegistry()],
42+
}),
3943
})
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from './token-status-list'

0 commit comments

Comments
 (0)