diff --git a/.nvmrc b/.nvmrc new file mode 100644 index 0000000000..dae199aecb --- /dev/null +++ b/.nvmrc @@ -0,0 +1 @@ +v12 diff --git a/package.json b/package.json index a8ae37a1ac..33a75a8d11 100644 --- a/package.json +++ b/package.json @@ -38,7 +38,7 @@ "@types/cors": "^2.8.7", "@types/debug": "^4.1.5", "@types/express": "^4.17.7", - "@types/indy-sdk": "^1.15.0", + "@types/indy-sdk": "^1.15.1", "@types/jest": "^26.0.10", "@types/node-fetch": "^2.5.7", "@types/uuid": "^8.3.0", diff --git a/src/lib/__tests__/credentials.test.ts b/src/lib/__tests__/credentials.test.ts index 5f5b7b7d3e..c566aca20d 100644 --- a/src/lib/__tests__/credentials.test.ts +++ b/src/lib/__tests__/credentials.test.ts @@ -90,12 +90,12 @@ describe('credentials', () => { schema: ledgerSchema, tag: 'TAG', signatureType: 'CL', - config: { support_revocation: false }, + config: { supportRevocation: false }, }; const [ledgerCredDefId] = await registerDefinition(faberAgent, definitionTemplate); credDefId = ledgerCredDefId; - const publicDid = faberAgent.getPublicDid()?.did; + const publicDid = faberAgent.publicDid?.did; await ensurePublicDidIsOnLedger(faberAgent, publicDid!); const { agentAConnection, agentBConnection } = await makeConnection(faberAgent, aliceAgent); faberConnection = agentAConnection; diff --git a/src/lib/__tests__/helpers.ts b/src/lib/__tests__/helpers.ts index bccaf0ef38..09a8348a2f 100644 --- a/src/lib/__tests__/helpers.ts +++ b/src/lib/__tests__/helpers.ts @@ -154,7 +154,7 @@ export async function makeConnection(agentA: Agent, agentB: Agent) { } export async function registerSchema(agent: Agent, schemaTemplate: SchemaTemplate): Promise<[SchemaId, Schema]> { - const [schemaId] = await agent.ledger.registerCredentialSchema(schemaTemplate); + const [schemaId] = await agent.ledger.registerSchema(schemaTemplate); const ledgerSchema = await agent.ledger.getSchema(schemaId); logger.logJson(`created schema with id ${schemaId}`, ledgerSchema); return [schemaId, ledgerSchema]; diff --git a/src/lib/__tests__/ledger.test.ts b/src/lib/__tests__/ledger.test.ts index b503e99fa7..ce5fc24277 100644 --- a/src/lib/__tests__/ledger.test.ts +++ b/src/lib/__tests__/ledger.test.ts @@ -35,7 +35,7 @@ describe('ledger', () => { }); test(`initialization of agent's public DID`, async () => { - faberAgentPublicDid = faberAgent.getPublicDid(); + faberAgentPublicDid = faberAgent.publicDid; logger.logJson('faberAgentPublicDid', faberAgentPublicDid!); expect(faberAgentPublicDid).toEqual( @@ -48,7 +48,7 @@ describe('ledger', () => { test('get public DID from ledger', async () => { if (!faberAgentPublicDid) { - throw new Error('Agent does not have publid did.'); + throw new Error('Agent does not have public did.'); } const result = await faberAgent.ledger.getPublicDid(faberAgentPublicDid.did); @@ -71,7 +71,7 @@ describe('ledger', () => { test('register schema on ledger', async () => { if (!faberAgentPublicDid) { - throw new Error('Agent does not have publid did.'); + throw new Error('Agent does not have public did.'); } const schemaName = `test-schema-${Date.now()}`; @@ -81,32 +81,36 @@ describe('ledger', () => { version: '1.0', }; - [schemaId] = await faberAgent.ledger.registerCredentialSchema(schemaTemplate); + const schemaResponse = await faberAgent.ledger.registerSchema(schemaTemplate); + schemaId = schemaResponse[0]; + const schema = schemaResponse[1]; + const ledgerSchema = await faberAgent.ledger.getSchema(schemaId); expect(schemaId).toBe(`${faberAgentPublicDid.did}:2:${schemaName}:1.0`); + expect(ledgerSchema).toEqual( expect.objectContaining({ - attrNames: expect.arrayContaining(['name', 'age']), + attrNames: expect.arrayContaining(schemaTemplate.attributes), id: `${faberAgentPublicDid.did}:2:${schemaName}:1.0`, name: schemaName, - seqNo: expect.any(Number), - ver: '1.0', - version: '1.0', + seqNo: schema.seqNo, + ver: schemaTemplate.version, + version: schemaTemplate.version, }) ); }); test('register definition on ledger', async () => { if (!faberAgentPublicDid) { - throw new Error('Agent does not have publid did.'); + throw new Error('Agent does not have public did.'); } const schema = await faberAgent.ledger.getSchema(schemaId); const credentialDefinitionTemplate = { schema: schema, tag: 'TAG', signatureType: 'CL', - config: { support_revocation: true }, + config: { supportRevocation: true }, }; const [credDefId] = await faberAgent.ledger.registerCredentialDefinition(credentialDefinitionTemplate); @@ -117,9 +121,9 @@ describe('ledger', () => { expect(ledgerCredDef).toEqual( expect.objectContaining({ id: expect.stringMatching(credDefIdRegExp), - schemaId: expect.any(String), - type: 'CL', - tag: 'TAG', + schemaId: String(schema.seqNo), + type: credentialDefinitionTemplate.signatureType, + tag: credentialDefinitionTemplate.tag, ver: '1.0', value: expect.objectContaining({ primary: expect.anything(), diff --git a/src/lib/__tests__/proofs.test.ts b/src/lib/__tests__/proofs.test.ts index 3363ee81c2..f9bdc4754a 100644 --- a/src/lib/__tests__/proofs.test.ts +++ b/src/lib/__tests__/proofs.test.ts @@ -96,12 +96,12 @@ describe('Present Proof', () => { schema: ledgerSchema, tag: 'TAG', signatureType: 'CL', - config: { support_revocation: false }, + config: { supportRevocation: false }, }; const [ledgerCredDefId] = await registerDefinition(faberAgent, definitionTemplate); credDefId = ledgerCredDefId; - const publicDid = faberAgent.getPublicDid()?.did; + const publicDid = faberAgent.publicDid?.did; await ensurePublicDidIsOnLedger(faberAgent, publicDid!); const { agentAConnection, agentBConnection } = await makeConnection(faberAgent, aliceAgent); diff --git a/src/lib/agent/Agent.ts b/src/lib/agent/Agent.ts index 9d2dbd7744..7437cbdd4f 100644 --- a/src/lib/agent/Agent.ts +++ b/src/lib/agent/Agent.ts @@ -156,8 +156,8 @@ export class Agent { return this.inboundTransporter.start(this); } - public getPublicDid() { - return this.wallet.getPublicDid(); + public get publicDid() { + return this.wallet.publicDid; } public getMediatorUrl() { diff --git a/src/lib/modules/credentials/__tests__/StubWallet.ts b/src/lib/modules/credentials/__tests__/StubWallet.ts index 09c995cadd..28052c74a8 100644 --- a/src/lib/modules/credentials/__tests__/StubWallet.ts +++ b/src/lib/modules/credentials/__tests__/StubWallet.ts @@ -25,13 +25,16 @@ import type { WalletQuery, LedgerRequest, } from 'indy-sdk'; -import { Wallet, DidInfo } from '../../../wallet/Wallet'; +import { Wallet } from '../../../wallet/Wallet'; import { UnpackedMessageContext } from '../../../types'; export class StubWallet implements Wallet { public get walletHandle() { return 0; } + public get publicDid() { + return undefined; + } public init(): Promise { return Promise.resolve(); } @@ -59,9 +62,6 @@ export class StubWallet implements Wallet { public initPublicDid(didConfig: DidConfig): Promise { throw new Error('Method not implemented.'); } - public getPublicDid(): DidInfo | undefined { - throw new Error('Method not implemented.'); - } public createDid(didConfig?: DidConfig | undefined): Promise<[string, string]> { throw new Error('Method not implemented.'); } diff --git a/src/lib/modules/ledger/LedgerModule.ts b/src/lib/modules/ledger/LedgerModule.ts index 4c1afa016c..dff6743b31 100644 --- a/src/lib/modules/ledger/LedgerModule.ts +++ b/src/lib/modules/ledger/LedgerModule.ts @@ -16,18 +16,20 @@ export class LedgerModule { } public async registerPublicDid() { - // TODO: handle ping response message + throw new Error('registerPublicDid not implemented.'); } public async getPublicDid(did: Did) { return this.ledgerService.getPublicDid(did); } - public async registerCredentialSchema(schema: SchemaTemplate) { - const did = this.wallet.getPublicDid()?.did; + public async registerSchema(schema: SchemaTemplate) { + const did = this.wallet.publicDid?.did; + if (!did) { throw new Error('Agent has no public DID.'); } + return this.ledgerService.registerSchema(did, schema); } @@ -36,10 +38,12 @@ export class LedgerModule { } public async registerCredentialDefinition(credentialDefinitionTemplate: CredDefTemplate) { - const did = this.wallet.getPublicDid()?.did; + const did = this.wallet.publicDid?.did; + if (!did) { throw new Error('Agent has no public DID.'); } + return this.ledgerService.registerCredentialDefinition(did, credentialDefinitionTemplate); } diff --git a/src/lib/modules/ledger/LedgerService.ts b/src/lib/modules/ledger/LedgerService.ts index 53d2a53cbf..88d46ac40e 100644 --- a/src/lib/modules/ledger/LedgerService.ts +++ b/src/lib/modules/ledger/LedgerService.ts @@ -7,7 +7,7 @@ import { Wallet } from '../../wallet/Wallet'; export class LedgerService { private wallet: Wallet; private indy: typeof Indy; - private poolHandle?: PoolHandle; + private _poolHandle?: PoolHandle; private authorAgreement?: AuthorAgreement | null; public constructor(wallet: Wallet, indy: typeof Indy) { @@ -15,6 +15,14 @@ export class LedgerService { this.indy = indy; } + private get poolHandle() { + if (!this._poolHandle) { + throw new Error('Pool has not been initialized yet.'); + } + + return this._poolHandle; + } + public async connect(poolName: string, poolConfig: PoolConfig) { try { logger.log(`Creating pool config with name "${poolName}".`); @@ -31,13 +39,10 @@ export class LedgerService { await this.indy.setProtocolVersion(2); logger.log('Opening pool'); - this.poolHandle = await this.indy.openPoolLedger(poolName); + this._poolHandle = await this.indy.openPoolLedger(poolName); } public async getPublicDid(did: Did) { - if (!this.poolHandle) { - throw new Error('Pool has not been initialized.'); - } const request = await this.indy.buildGetNymRequest(null, did); logger.log('request', request); @@ -51,9 +56,6 @@ export class LedgerService { } public async registerSchema(did: Did, schemaTemplate: SchemaTemplate): Promise<[SchemaId, Schema]> { - if (!this.poolHandle) { - throw new Error('Pool has not been initialized.'); - } const { name, attributes, version } = schemaTemplate; const [schemaId, schema] = await this.indy.issuerCreateSchema(did, name, version, attributes); logger.log(`Register schema with ID = ${schemaId}:`, schema); @@ -67,13 +69,15 @@ export class LedgerService { const response = await this.indy.submitRequest(this.poolHandle, signedRequest); logger.log('Register schema response', response); + const seqNo = response.result.txnMetadata?.seqNo; + + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + schema.seqNo = seqNo!; + return [schemaId, schema]; } public async getCredentialSchema(schemaId: SchemaId) { - if (!this.poolHandle) { - throw new Error('Pool has not been initialized.'); - } const request = await this.indy.buildGetSchemaRequest(null, schemaId); logger.log('Get schema request', request); @@ -90,12 +94,11 @@ export class LedgerService { did: Did, credentialDefinitionTemplate: CredDefTemplate ): Promise<[CredDefId, CredDef]> { - if (!this.poolHandle) { - throw new Error('Pool has not been initialized.'); - } const { schema, tag, signatureType, config } = credentialDefinitionTemplate; - const [credDefId, credDef] = await this.wallet.createCredentialDefinition(did, schema, tag, signatureType, config); + const [credDefId, credDef] = await this.wallet.createCredentialDefinition(did, schema, tag, signatureType, { + support_revocation: config.supportRevocation, + }); logger.log(`Register credential definition with ID = ${credDefId}:`, credDef); const request = await this.indy.buildCredDefRequest(did, credDef); @@ -111,9 +114,6 @@ export class LedgerService { } public async getCredentialDefinition(credDefId: CredDefId) { - if (!this.poolHandle) { - throw new Error('Pool has not been initialized.'); - } const request = await this.indy.buildGetCredDefRequest(null, credDefId); logger.log('Get credential definition request:', request); @@ -154,10 +154,6 @@ export class LedgerService { return this.authorAgreement; } - if (!this.poolHandle) { - throw new Error('Pool has not been initialized.'); - } - const taaRequest = await this.indy.buildGetTxnAuthorAgreementRequest(null); const taaResponse = await this.indy.submitRequest(this.poolHandle, taaRequest); const acceptanceMechanismRequest = await this.indy.buildGetAcceptanceMechanismsRequest(null); @@ -195,7 +191,7 @@ export interface CredDefTemplate { schema: Schema; tag: string; signatureType: string; - config: { support_revocation: boolean }; + config: { supportRevocation: boolean }; } interface AuthorAgreement { diff --git a/src/lib/wallet/IndyWallet.ts b/src/lib/wallet/IndyWallet.ts index abf37bff09..1dd7b2809a 100644 --- a/src/lib/wallet/IndyWallet.ts +++ b/src/lib/wallet/IndyWallet.ts @@ -50,6 +50,10 @@ export class IndyWallet implements Wallet { this.indy = indy; } + public get publicDid() { + return this.publicDidInfo; + } + private get walletHandle() { if (!this._walletHandle) { throw new Error('Wallet has not been initialized yet'); @@ -107,10 +111,6 @@ export class IndyWallet implements Wallet { }; } - public getPublicDid() { - return this.publicDidInfo; - } - public async createDid(didConfig?: DidConfig): Promise<[Did, Verkey]> { return this.indy.createAndStoreMyDid(this.walletHandle, didConfig || {}); } diff --git a/src/lib/wallet/Wallet.test.ts b/src/lib/wallet/Wallet.test.ts index f0e594e894..c5bf0007db 100644 --- a/src/lib/wallet/Wallet.test.ts +++ b/src/lib/wallet/Wallet.test.ts @@ -9,7 +9,7 @@ describe('Wallet', () => { await wallet.initPublicDid({ seed: '00000000000000000000000Forward01' }); - expect(wallet.getPublicDid()).toEqual({ + expect(wallet.publicDid).toEqual({ did: 'DtWRdd6C5dN5vpcN6XRAvu', verkey: '82RBSn3heLgXzZd74UsMC8Q8YRfEEhQoAM7LUqE6bevJ', }); diff --git a/src/lib/wallet/Wallet.ts b/src/lib/wallet/Wallet.ts index 5a4437fb4c..5f20210f75 100644 --- a/src/lib/wallet/Wallet.ts +++ b/src/lib/wallet/Wallet.ts @@ -30,11 +30,12 @@ import type { import { UnpackedMessageContext } from '../types'; export interface Wallet { + publicDid: DidInfo | undefined; + init(): Promise; close(): Promise; delete(): Promise; initPublicDid(didConfig: DidConfig): Promise; - getPublicDid(): DidInfo | undefined; createDid(didConfig?: DidConfig): Promise<[Did, Verkey]>; createCredentialDefinition( issuerDid: Did, diff --git a/src/samples/mediator.ts b/src/samples/mediator.ts index d1a4d2a820..0f15914fa7 100644 --- a/src/samples/mediator.ts +++ b/src/samples/mediator.ts @@ -71,7 +71,7 @@ const messageReceiver = new HttpInboundTransporter(app); const agent = new Agent(config, messageReceiver, messageSender, indy, messageRepository); app.get('/', async (req, res) => { - const agentDid = agent.getPublicDid(); + const agentDid = agent.publicDid; res.send(agentDid); }); diff --git a/yarn.lock b/yarn.lock index 5b2eaedde5..fe1e84f80b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -601,10 +601,10 @@ dependencies: "@types/node" "*" -"@types/indy-sdk@^1.15.0": - version "1.15.0" - resolved "https://registry.yarnpkg.com/@types/indy-sdk/-/indy-sdk-1.15.0.tgz#44b49978fc8c4892f2c90ec580d3c957b9a88805" - integrity sha512-xkxmHpxiCnw28URfP6xWtB93KAarfKPRDA3U1dv9ejkw4rLAXPeWkmnDmvmtoY2/QLCyq20hqP/ZEAV188okiw== +"@types/indy-sdk@^1.15.1": + version "1.15.1" + resolved "https://registry.yarnpkg.com/@types/indy-sdk/-/indy-sdk-1.15.1.tgz#7baf9eab749ddac643126d8553ce5295ba256952" + integrity sha512-H8ZvxwpR0L+I9Was0Mcx4POmC5DCVaMMAVM7feEX1u7DFdMNoK7jWruP0sT8IT/UaeQ+ie3dArYis72i4wuVTg== dependencies: "@types/node" "*"