Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: break out indy wallet, better indy handling #396

Merged
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,6 @@ Some features are not yet supported, but are on our roadmap. Check [the roadmap]
- ✅ Indy Credentials (with `did:sov` support)
- ✅ HTTP Transport
- ✅ Connection-less Issuance and Verification
- ✅ Mediator Coordination Protocol ([RFC 0211](https://github.com/hyperledger/aries-rfcs/blob/master/features/0211-route-coordination/README.md))
- ✅ Smart Auto Acceptance of Connections, Credentials and Proofs
- 🚧 Revocation of Indy Credentials
- 🚧 Electron
Expand Down
5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
"@types/eslint": "^7.2.13",
"@types/express": "^4.17.13",
"@types/jest": "^26.0.23",
"@types/node": "^15.14.1",
"@types/node": "^15.14.4",
"@types/uuid": "^8.3.1",
"@types/ws": "^7.4.6",
"@typescript-eslint/eslint-plugin": "^4.26.1",
Expand All @@ -54,6 +54,9 @@
"typescript": "^4.3.0",
"ws": "^7.4.6"
},
"resolutions": {
"@types/node": "^15.14.4"
},
"engines": {
"node": ">= 12"
}
Expand Down
3 changes: 0 additions & 3 deletions packages/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,5 @@
"rimraf": "~3.0.2",
"tslog": "^3.2.0",
"typescript": "~4.3.0"
},
"resolutions": {
"@types/node": "^15.14.1"
}
}
12 changes: 6 additions & 6 deletions packages/core/src/agent/Agent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,9 +79,9 @@ export class Agent {
logger: initialConfig.logger != undefined,
})

if (!this.agentConfig.walletConfig || !this.agentConfig.walletCredentials) {
if (!this.agentConfig.walletConfig) {
this.logger.warn(
'Wallet config and/or credentials have not been set on the agent config. ' +
'Wallet config has not been set on the agent config. ' +
'Make sure to initialize the wallet yourself before initializing the agent, ' +
'or provide the required wallet configuration in the agent constructor'
)
Expand Down Expand Up @@ -135,19 +135,19 @@ export class Agent {
}

public async initialize() {
const { publicDidSeed, walletConfig, walletCredentials, mediatorConnectionsInvite } = this.agentConfig
const { publicDidSeed, walletConfig, mediatorConnectionsInvite } = this.agentConfig

if (this._isInitialized) {
throw new AriesFrameworkError(
'Agent already initialized. Currently it is not supported to re-initialize an already initialized agent.'
)
}

if (!this.wallet.isInitialized && walletConfig && walletCredentials) {
await this.wallet.initialize(walletConfig, walletCredentials)
if (!this.wallet.isInitialized && walletConfig) {
await this.wallet.initialize(walletConfig)
} else if (!this.wallet.isInitialized) {
throw new WalletError(
'Wallet config and/or credentials have not been set on the agent config. ' +
'Wallet config has not been set on the agent config. ' +
'Make sure to initialize the wallet yourself before initializing the agent, ' +
'or provide the required wallet configuration in the agent constructor'
)
Expand Down
4 changes: 0 additions & 4 deletions packages/core/src/agent/AgentConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,10 +62,6 @@ export class AgentConfig {
return this.initConfig.walletConfig
}

public get walletCredentials() {
return this.initConfig.walletCredentials
}

public get autoAcceptConnections() {
return this.initConfig.autoAcceptConnections ?? false
}
Expand Down
13 changes: 6 additions & 7 deletions packages/core/src/agent/EnvelopeService.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import type { Logger } from '../logger'
import type { UnpackedMessageContext, WireMessage } from '../types'
import type { AgentMessage } from './AgentMessage'
import type { Verkey } from 'indy-sdk'

import { inject, scoped, Lifecycle } from 'tsyringe'

Expand All @@ -12,9 +11,9 @@ import { Wallet } from '../wallet/Wallet'
import { AgentConfig } from './AgentConfig'

export interface EnvelopeKeys {
recipientKeys: Verkey[]
routingKeys: Verkey[]
senderKey: Verkey | null
recipientKeys: string[]
routingKeys: string[]
senderKey: string | null
}

@scoped(Lifecycle.ContainerScoped)
Expand All @@ -28,12 +27,12 @@ class EnvelopeService {
}

public async packMessage(payload: AgentMessage, keys: EnvelopeKeys): Promise<WireMessage> {
const { routingKeys, recipientKeys, senderKey: senderVk } = keys
const { routingKeys, recipientKeys, senderKey } = keys
const message = payload.toJSON()

this.logger.debug(`Pack outbound message ${payload.type}`)

let wireMessage = await this.wallet.pack(message, recipientKeys, senderVk)
let wireMessage = await this.wallet.pack(message, recipientKeys, senderKey ?? undefined)

if (routingKeys && routingKeys.length > 0) {
for (const routingKey of routingKeys) {
Expand All @@ -44,7 +43,7 @@ class EnvelopeService {
message: wireMessage,
})
this.logger.debug('Forward message created', forwardMessage)
wireMessage = await this.wallet.pack(forwardMessage.toJSON(), [routingKey], senderVk)
wireMessage = await this.wallet.pack(forwardMessage.toJSON(), [routingKey], senderKey ?? undefined)
}
}
return wireMessage
Expand Down
10 changes: 5 additions & 5 deletions packages/core/src/agent/__tests__/Agent.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { ConnectionService } from '../../modules/connections/services/Connection
import { TrustPingService } from '../../modules/connections/services/TrustPingService'
import { CredentialRepository, CredentialService } from '../../modules/credentials'
import { CredentialsModule } from '../../modules/credentials/CredentialsModule'
import { LedgerService } from '../../modules/ledger'
import { IndyLedgerService } from '../../modules/ledger'
import { LedgerModule } from '../../modules/ledger/LedgerModule'
import { ProofRepository, ProofService } from '../../modules/proofs'
import { ProofsModule } from '../../modules/proofs/ProofsModule'
Expand Down Expand Up @@ -71,7 +71,7 @@ describe('Agent', () => {
it('wallet must be initialized if wallet config is not set before agent can be initialized', async () => {
expect.assertions(9)

const { walletConfig, walletCredentials, ...withoutWalletConfig } = config
const { walletConfig, ...withoutWalletConfig } = config
agent = new Agent(withoutWalletConfig, dependencies)

const wallet = agent.injectionContainer.resolve<Wallet>(InjectionSymbols.Wallet)
Expand All @@ -84,7 +84,7 @@ describe('Agent', () => {
expect(wallet.isInitialized).toBe(false)

// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
await wallet.initialize(walletConfig!, walletCredentials!)
await wallet.initialize(walletConfig!)
berendsliedrecht marked this conversation as resolved.
Show resolved Hide resolved
expect(agent.isInitialized).toBe(false)
expect(wallet.isInitialized).toBe(true)

Expand Down Expand Up @@ -124,7 +124,7 @@ describe('Agent', () => {
expect(container.resolve(MediationRecipientService)).toBeInstanceOf(MediationRecipientService)

expect(container.resolve(LedgerModule)).toBeInstanceOf(LedgerModule)
expect(container.resolve(LedgerService)).toBeInstanceOf(LedgerService)
expect(container.resolve(IndyLedgerService)).toBeInstanceOf(IndyLedgerService)

// Symbols, interface based
expect(container.resolve(InjectionSymbols.Wallet)).toBeInstanceOf(IndyWallet)
Expand Down Expand Up @@ -168,7 +168,7 @@ describe('Agent', () => {
expect(container.resolve(MediationRecipientService)).toBe(container.resolve(MediationRecipientService))

expect(container.resolve(LedgerModule)).toBe(container.resolve(LedgerModule))
expect(container.resolve(LedgerService)).toBe(container.resolve(LedgerService))
expect(container.resolve(IndyLedgerService)).toBe(container.resolve(IndyLedgerService))

// Symbols, interface based
expect(container.resolve(InjectionSymbols.Wallet)).toBe(container.resolve(InjectionSymbols.Wallet))
Expand Down
9 changes: 4 additions & 5 deletions packages/core/src/agent/models/InboundMessageContext.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,19 @@
import type { ConnectionRecord } from '../../modules/connections'
import type { AgentMessage } from '../AgentMessage'
import type { Verkey } from 'indy-sdk'

import { AriesFrameworkError } from '../../error'

export interface MessageContextParams {
connection?: ConnectionRecord
senderVerkey?: Verkey
recipientVerkey?: Verkey
senderVerkey?: string
recipientVerkey?: string
}

export class InboundMessageContext<T extends AgentMessage = AgentMessage> {
public message: T
public connection?: ConnectionRecord
public senderVerkey?: Verkey
public recipientVerkey?: Verkey
public senderVerkey?: string
public recipientVerkey?: string

public constructor(message: T, context: MessageContextParams = {}) {
this.message = message
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ describe('Decorators | Signature | SignatureDecoratorUtils', () => {
const config = getAgentConfig('SignatureDecoratorUtilsTest')
wallet = new IndyWallet(config)
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
await wallet.initialize(config.walletConfig!, config.walletCredentials!)
await wallet.initialize(config.walletConfig!)
})

afterAll(async () => {
Expand All @@ -52,7 +52,7 @@ describe('Decorators | Signature | SignatureDecoratorUtils', () => {

test('signData signs json object and returns SignatureDecorator', async () => {
const seed1 = '00000000000000000000000000000My1'
TimoGlastra marked this conversation as resolved.
Show resolved Hide resolved
const [, verkey] = await wallet.createDid({ seed: seed1 })
const { verkey } = await wallet.createDid({ seed: seed1 })

const result = await signData(data, wallet, verkey)

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import type { Wallet } from '../../wallet/Wallet'
import type { Verkey } from 'indy-sdk'

import { AriesFrameworkError } from '../../error'
import { BufferEncoder } from '../../utils/BufferEncoder'
Expand Down Expand Up @@ -46,7 +45,7 @@ export async function unpackAndVerifySignatureDecorator(
*
* @returns Resulting signature decorator.
*/
export async function signData(data: unknown, wallet: Wallet, signerKey: Verkey): Promise<SignatureDecorator> {
export async function signData(data: unknown, wallet: Wallet, signerKey: string): Promise<SignatureDecorator> {
const dataBuffer = Buffer.concat([timestamp(), JsonEncoder.toBuffer(data)])

const signatureBuffer = await wallet.sign(dataBuffer, signerKey)
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/error/BaseError.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ export class BaseError extends makeError.BaseError {
super(message)

Object.defineProperty(this, 'cause', {
value: cause,
writable: false,
enumerable: false,
configurable: false,
Expand Down
11 changes: 11 additions & 0 deletions packages/core/src/error/IndySdkError.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import type { IndyError } from '../utils/indyError'

import { AriesFrameworkError } from './AriesFrameworkError'

export class IndySdkError extends AriesFrameworkError {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is kind of interesting. I would assume that IndySdk is lower-level detail than framework level error. Therefore, I'm not sure about IndySdkError extending AriesFrameworkError

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The normal IndyError is lower-level detail than the framework level error. However, because the normal error is not very nice in stacktracing/information we've wrapped it with a framework specific error.

To me AriesFrameworkError is the basis for all framework created errors (which is the case if we wrap the original error). I think it can be beneficial to have a single base error that allows to catch all framework errors. Maybe AriesFrameworkError is not the best name as the base error

public constructor(indyError: IndyError, message?: string) {
const base = `${indyError.name}(${indyError.indyName}): ${indyError.message}`

super(message ? `${message}: ${base}` : base, { cause: indyError })
}
}
1 change: 1 addition & 0 deletions packages/core/src/error/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export * from './AriesFrameworkError'
export * from './RecordNotFoundError'
export * from './RecordDuplicateError'
export * from './IndySdkError'
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import type { AgentConfig } from '../../../agent/AgentConfig'
import type { StorageService } from '../../../storage/StorageService'
import type { Wallet } from '../../../wallet/Wallet'
import type { BasicMessageReceivedEvent } from '../BasicMessageEvents'

import { getAgentConfig, getMockConnection } from '../../../../tests/helpers'
Expand All @@ -22,16 +21,16 @@ describe('BasicMessageService', () => {
did: 'did:sov:C2SsBf5QUQpqSAQfhu3sd2',
})

let wallet: Wallet
let wallet: IndyWallet
let storageService: StorageService<BasicMessageRecord>
let agentConfig: AgentConfig

beforeAll(async () => {
agentConfig = getAgentConfig('BasicMessageServiceTest')
wallet = new IndyWallet(agentConfig)
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
await wallet.initialize(agentConfig.walletConfig!, agentConfig.walletCredentials!)
storageService = new IndyStorageService(wallet)
await wallet.initialize(agentConfig.walletConfig!)
storageService = new IndyStorageService(wallet, agentConfig)
})

afterAll(async () => {
Expand Down
5 changes: 2 additions & 3 deletions packages/core/src/modules/connections/ConnectionsModule.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import type { ConnectionRecord } from './repository/ConnectionRecord'
import type { Verkey } from 'indy-sdk'

import { Lifecycle, scoped } from 'tsyringe'

Expand Down Expand Up @@ -207,7 +206,7 @@ export class ConnectionsModule {
* @returns the connection record, or null if not found
* @throws {RecordDuplicateError} if multiple connections are found for the given verkey
*/
public findByVerkey(verkey: Verkey): Promise<ConnectionRecord | null> {
public findByVerkey(verkey: string): Promise<ConnectionRecord | null> {
return this.connectionService.findByVerkey(verkey)
}

Expand All @@ -218,7 +217,7 @@ export class ConnectionsModule {
* @returns the connection record, or null if not found
* @throws {RecordDuplicateError} if multiple connections are found for the given verkey
*/
public findByTheirKey(verkey: Verkey): Promise<ConnectionRecord | null> {
public findByTheirKey(verkey: string): Promise<ConnectionRecord | null> {
return this.connectionService.findByTheirKey(verkey)
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import type { Wallet } from '../../../wallet/Wallet'
import type { Did } from 'indy-sdk'

import { getAgentConfig, getMockConnection, mockFunction } from '../../../../tests/helpers'
import { AgentMessage } from '../../../agent/AgentMessage'
Expand Down Expand Up @@ -34,12 +33,12 @@ describe('ConnectionService', () => {
let connectionRepository: ConnectionRepository
let connectionService: ConnectionService
let eventEmitter: EventEmitter
let myRouting: { did: Did; verkey: string; endpoint: string; routingKeys: string[] }
let myRouting: { did: string; verkey: string; endpoint: string; routingKeys: string[] }

beforeAll(async () => {
wallet = new IndyWallet(config)
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
await wallet.initialize(config.walletConfig!, config.walletCredentials!)
await wallet.initialize(config.walletConfig!)
berendsliedrecht marked this conversation as resolved.
Show resolved Hide resolved
})

afterAll(async () => {
Expand Down Expand Up @@ -372,7 +371,7 @@ describe('ConnectionService', () => {
expect.assertions(2)

// Needed for signing connection~sig
const [did, verkey] = await wallet.createDid()
const { did, verkey } = await wallet.createDid()
const mockConnection = getMockConnection({
did,
verkey,
Expand Down Expand Up @@ -431,8 +430,8 @@ describe('ConnectionService', () => {
it('returns a connection record containing the information from the connection response', async () => {
expect.assertions(3)

const [did, verkey] = await wallet.createDid()
const [theirDid, theirVerkey] = await wallet.createDid()
const { did, verkey } = await wallet.createDid()
const { did: theirDid, verkey: theirVerkey } = await wallet.createDid()
berendsliedrecht marked this conversation as resolved.
Show resolved Hide resolved

const connectionRecord = getMockConnection({
did,
Expand Down Expand Up @@ -505,8 +504,8 @@ describe('ConnectionService', () => {
it('throws an error when the connection sig is not signed with the same key as the recipient key from the invitation', async () => {
expect.assertions(1)

const [did, verkey] = await wallet.createDid()
const [theirDid, theirVerkey] = await wallet.createDid()
const { did, verkey } = await wallet.createDid()
const { did: theirDid, verkey: theirVerkey } = await wallet.createDid()
TimoGlastra marked this conversation as resolved.
Show resolved Hide resolved
const connectionRecord = getMockConnection({
did,
verkey,
Expand Down Expand Up @@ -579,8 +578,8 @@ describe('ConnectionService', () => {
it('throws an error when the message does not contain a did doc with any recipientKeys', async () => {
expect.assertions(1)

const [did, verkey] = await wallet.createDid()
const [theirDid, theirVerkey] = await wallet.createDid()
const { did, verkey } = await wallet.createDid()
const { did: theirDid, verkey: theirVerkey } = await wallet.createDid()
const connectionRecord = getMockConnection({
did,
verkey,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import type { Verkey } from 'indy-sdk'

export interface InvitationDetails {
label: string
recipientKeys: Verkey[]
recipientKeys: string[]
serviceEndpoint: string
routingKeys: Verkey[]
routingKeys: string[]
}
Loading