Skip to content
Snippets Groups Projects
Commit 8e338fb7 authored by Berend Sliedrecht's avatar Berend Sliedrecht Committed by Berend Sliedrecht
Browse files

seperated the agent into its own service


Signed-off-by: default avatarBerend Sliedrecht <blu3beri@proton.me>
parent 7005c886
No related branches found
No related tags found
No related merge requests found
Showing
with 382 additions and 1221 deletions
...@@ -14,5 +14,6 @@ AGENT_AUTO_ACCEPT_CREDENTIAL=contentApproved ...@@ -14,5 +14,6 @@ AGENT_AUTO_ACCEPT_CREDENTIAL=contentApproved
AGENT_WALLET_KEY=ssi-wallet-key AGENT_WALLET_KEY=ssi-wallet-key
AGENT_WALLET_ID=ssi-wallet-id AGENT_WALLET_ID=ssi-wallet-id
AGENT_LEDGER_ID=ID_UNION,BCOVRIN_TEST # AGENT_LEDGER_ID=ID_UNION,BCOVRIN_TEST
AGENT_LEDGER_ID=BCOVRIN_TEST
AGENT_ID_UNION_KEY=example-example-example-example AGENT_ID_UNION_KEY=example-example-example-example
import { AutoAcceptCredential } from '@aries-framework/core/build/modules/credentials/CredentialAutoAcceptType'; import { AutoAcceptCredential } from '@aries-framework/core';
import * as process from 'process'; import * as process from 'process';
interface Config { interface Config {
agentHost: string; agentHost: string;
port: number; port: number;
afjExtPort: number;
jwtSecret: string; jwtSecret: string;
nats: { nats: {
url: string; url: string;
}, };
agent: { agent: {
name: string; name: string;
...@@ -23,15 +22,14 @@ interface Config { ...@@ -23,15 +22,14 @@ interface Config {
autoAcceptConnection: boolean; autoAcceptConnection: boolean;
autoAcceptCredential: AutoAcceptCredential; autoAcceptCredential: AutoAcceptCredential;
idUnionKey: string; idUnionKey: string;
basicUser: string, basicUser: string;
basicPass: string basicPass: string;
}, };
} }
const config = (): Config => ({ const config = (): Config => ({
agentHost: process.env.AGENT_HOST || '', agentHost: process.env.AGENT_HOST || '',
port: Number(process.env.PORT), port: Number(process.env.PORT),
afjExtPort: Number(process.env.AFJ_EXT_PORT),
jwtSecret: process.env.JWT_SECRET || '', jwtSecret: process.env.JWT_SECRET || '',
nats: { nats: {
...@@ -48,7 +46,8 @@ const config = (): Config => ({ ...@@ -48,7 +46,8 @@ const config = (): Config => ({
path: process.env.AGENT_URL_PATH || '', path: process.env.AGENT_URL_PATH || '',
publicDidSeed: process.env.AGENT_PUBLIC_DID_SEED || '', publicDidSeed: process.env.AGENT_PUBLIC_DID_SEED || '',
autoAcceptConnection: process.env.AGENT_AUTO_ACCEPT_CONNECTION === 'true', autoAcceptConnection: process.env.AGENT_AUTO_ACCEPT_CONNECTION === 'true',
autoAcceptCredential: process.env.AGENT_AUTO_ACCEPT_CREDENTIAL as AutoAcceptCredential, autoAcceptCredential: process.env
.AGENT_AUTO_ACCEPT_CREDENTIAL as AutoAcceptCredential,
idUnionKey: process.env.AGENT_ID_UNION_KEY || '', idUnionKey: process.env.AGENT_ID_UNION_KEY || '',
basicUser: process.env.BASIC_USER!, basicUser: process.env.BASIC_USER!,
basicPass: process.env.BASIC_PASS!, basicPass: process.env.BASIC_PASS!,
......
...@@ -3,7 +3,6 @@ import Joi from 'joi'; ...@@ -3,7 +3,6 @@ import Joi from 'joi';
const validationSchema = Joi.object({ const validationSchema = Joi.object({
NATS_URL: Joi.string().required(), NATS_URL: Joi.string().required(),
PORT: Joi.number().required(), PORT: Joi.number().required(),
AFJ_EXT_PORT: Joi.number().required(),
AGENT_NAME: Joi.string().required(), AGENT_NAME: Joi.string().required(),
AGENT_WALLET_ID: Joi.string().required(), AGENT_WALLET_ID: Joi.string().required(),
......
...@@ -20,10 +20,16 @@ ...@@ -20,10 +20,16 @@
"test:e2e": "jest -i --config ./test/jest-e2e.json" "test:e2e": "jest -i --config ./test/jest-e2e.json"
}, },
"dependencies": { "dependencies": {
"@aries-framework/core": "^0.1.0", "@aries-framework/anoncreds": "0.4.2",
"@aries-framework/node": "^0.1.0", "@aries-framework/anoncreds-rs": "0.4.2",
"@aries-framework/rest": "^0.8.0", "@aries-framework/askar": "0.4.2",
"@aries-framework/core": "0.4.2",
"@aries-framework/indy-vdr": "0.4.2",
"@aries-framework/node": "0.4.2",
"@elastic/ecs-winston-format": "^1.3.1", "@elastic/ecs-winston-format": "^1.3.1",
"@hyperledger/anoncreds-nodejs": "^0.1.0",
"@hyperledger/aries-askar-nodejs": "^0.1.0",
"@hyperledger/indy-vdr-nodejs": "^0.1.0",
"@nestjs/axios": "0.0.5", "@nestjs/axios": "0.0.5",
"@nestjs/common": "^8.0.0", "@nestjs/common": "^8.0.0",
"@nestjs/config": "^1.1.6", "@nestjs/config": "^1.1.6",
......
import { Controller, Get, HttpStatus } from '@nestjs/common';
import { AgentService } from './agent.service';
@Controller('agent')
export class AgentController {
public constructor(private agent: AgentService) {}
// eslint-disable-next-line class-methods-use-this
@Get('info')
async getWalletInfo() {
return {
statusCode: HttpStatus.OK,
message: 'Success',
data: 'SHOULD_BE_PUBLIC_DID',
};
}
}
export default AgentController;
import config from '@config/config';
import { Module } from '@nestjs/common'; import { Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';
import { ClientsModule, Transport } from '@nestjs/microservices'; import { ClientsModule, Transport } from '@nestjs/microservices';
import { HttpModule } from '@nestjs/axios'; import { NatsClientService } from '@src/client/nats.client';
import DidCommController from '@didComm/controller/controller'; import { NATSServices } from '@src/common/constants';
import AgentModule from '@agent/module'; import { AgentController } from './agent.controller';
import { NATSServices } from '@common/constants'; import { AgentService } from './agent.service';
import config from '@config/config';
@Module({ @Module({
imports: [ imports: [
HttpModule, ConfigModule,
ClientsModule.register([ ClientsModule.register([
{ {
name: NATSServices.SERVICE_NAME, name: NATSServices.SERVICE_NAME,
...@@ -18,9 +19,10 @@ import config from '@config/config'; ...@@ -18,9 +19,10 @@ import config from '@config/config';
}, },
}, },
]), ]),
AgentModule,
], ],
controllers: [DidCommController], providers: [NatsClientService, AgentService],
providers: [], controllers: [AgentController],
}) })
export default class DidCommModule {} export class AgentModule {}
export default AgentModule;
import {
Agent,
ConnectionsModule,
CredentialsModule,
DidsModule,
HttpOutboundTransport,
InitConfig,
KeyDidRegistrar,
KeyDidResolver,
KeyType,
LogLevel,
PeerDidRegistrar,
PeerDidResolver,
TypedArrayEncoder,
} from '@aries-framework/core';
import { agentDependencies, HttpInboundTransport } from '@aries-framework/node';
import { Injectable } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { NatsClientService } from '@src/client/nats.client';
import logger from '@src/globalUtils/logger';
import { AnonCredsRsModule } from '@aries-framework/anoncreds-rs';
import { anoncreds } from '@hyperledger/anoncreds-nodejs';
import { AnonCredsModule } from '@aries-framework/anoncreds';
import { ariesAskar } from '@hyperledger/aries-askar-nodejs';
import { AskarModule } from '@aries-framework/askar';
import { indyVdr } from '@hyperledger/indy-vdr-nodejs';
import {
IndyVdrAnonCredsRegistry,
IndyVdrIndyDidResolver,
IndyVdrModule,
IndyVdrPoolConfig,
IndyVdrSovDidResolver,
} from '@aries-framework/indy-vdr';
import { subscribe } from './utils/listener';
import {
LedgerIds,
ledgerNamespaces,
LEDGER_GENESIS,
} from './utils/ledgerConfig';
import { AgentLogger } from './utils/logger';
import { registerPublicDids } from './ledger/register';
@Injectable()
export class AgentService {
private agent: Agent<this['modules']>;
private configService: ConfigService;
private natsClient: NatsClientService;
public constructor(
configService: ConfigService,
natsClient: NatsClientService,
) {
this.configService = configService;
this.natsClient = natsClient;
const peerPort = this.configService.get('agent.peerPort');
this.agent = new Agent({
config: this.config,
modules: this.modules,
dependencies: agentDependencies,
});
const httpInbound = new HttpInboundTransport({
port: Number(peerPort.replace(':', '')),
});
this.agent.registerInboundTransport(httpInbound);
this.agent.registerOutboundTransport(new HttpOutboundTransport());
}
public get config(): InitConfig {
const { name, walletId, walletKey, host, peerPort, path } =
this.configService.get('agent');
const endpoints = [`${host}${peerPort}${path}`];
return {
label: name,
walletConfig: {
id: walletId,
key: walletKey,
},
endpoints,
logger: new AgentLogger(LogLevel.warn),
};
}
public get modules() {
const { autoAcceptConnection, autoAcceptCredential } =
this.configService.get('agent');
return {
connections: new ConnectionsModule({
autoAcceptConnections: autoAcceptConnection,
}),
credentials: new CredentialsModule({
autoAcceptCredentials: autoAcceptCredential,
}),
anoncredsRs: new AnonCredsRsModule({ anoncreds }),
anoncreds: new AnonCredsModule({
registries: [new IndyVdrAnonCredsRegistry()],
}),
indyVdr: new IndyVdrModule({ indyVdr, networks: this.ledgers }),
dids: new DidsModule({
resolvers: [
new IndyVdrIndyDidResolver(),
new IndyVdrSovDidResolver(),
new PeerDidResolver(),
new KeyDidResolver(),
],
registrars: [new PeerDidRegistrar(), new KeyDidRegistrar()],
}),
askar: new AskarModule({ ariesAskar }),
};
}
public get ledgers() {
const ledgerIds = this.configService.get('agent.ledgerIds');
if (!ledgerIds || ledgerIds.length < 1 || ledgerIds[0] === '') {
throw new Error(
'Agent could not start, please provide a ledger environment variable.',
);
}
return ledgerIds.map((id: LedgerIds) => {
const ledgerId: LedgerIds = id;
if (!LEDGER_GENESIS?.[ledgerId]) {
throw new Error(
`No pool transaction genesis provided for ledger ${ledgerId}`,
);
}
const ledger: IndyVdrPoolConfig = {
indyNamespace: ledgerNamespaces[ledgerId],
genesisTransactions: LEDGER_GENESIS?.[ledgerId],
isProduction: false,
};
return ledger;
});
}
private async registerPublicDid() {
const { publicDidSeed, ledgerIds } = this.configService.get('agent');
if (!publicDidSeed) {
logger.info('No public did seed provided, skipping registration');
}
if (!ledgerIds || ledgerIds.length < 1 || ledgerIds[0] === '') {
throw new Error(
'Agent could not start, please provide a ledger environment variable.',
);
}
const registeredPublicDidResponses = await registerPublicDids({
alias: this.config.label,
ledgerIds,
seed: publicDidSeed,
});
// eslint-disable-next-line no-restricted-syntax
for (const publicDidResponse of registeredPublicDidResponses) {
// eslint-disable-next-line no-await-in-loop
await this.agent.dids.import({
overwrite: true,
did: publicDidResponse.did,
privateKeys: [
{
keyType: KeyType.Ed25519,
privateKey: TypedArrayEncoder.fromString(publicDidSeed),
},
],
});
}
}
public async onModuleInit() {
await this.agent.initialize();
await this.registerPublicDid();
subscribe(this.agent, this.natsClient);
logger.info('Agent initialized');
}
public async onModuleDestory() {
await this.agent.shutdown();
}
}
export default AgentService;
import logger from '@src/globalUtils/logger';
import axios from 'axios';
import { logAxiosError } from '../utils/helperFunctions';
import { LedgerIds, ledgerNamespaces, NYM_URL } from '../utils/ledgerConfig';
type RegisterPublicDidOptions = {
alias: string;
ledgerIds: Array<LedgerIds>;
seed: string;
};
type LedgerRegistrationBody = {
role?: 'ENDORSER';
alias?: string;
seed: string;
};
type RegisterPublicDidResponse = {
seed: string;
did: string;
verkey: string;
};
export const registerPublicDids = async ({
ledgerIds,
alias,
seed,
}: RegisterPublicDidOptions): Promise<Array<RegisterPublicDidResponse>> => {
const responses: Array<RegisterPublicDidResponse> = [];
// eslint-disable-next-line no-restricted-syntax
for (const ledgerId of ledgerIds) {
try {
// TODO: why does this fail?
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
const ledgerRegisterUrl = NYM_URL[ledgerId];
const ledgerNamespace = ledgerNamespaces[ledgerId];
const body: LedgerRegistrationBody = {
role: 'ENDORSER',
alias,
seed,
};
// eslint-disable-next-line no-await-in-loop
const res = await axios.post<RegisterPublicDidResponse>(
ledgerRegisterUrl,
body,
);
if (res.data) {
logger.info('Agent DID registered.');
res.data.did = `did:indy:${ledgerNamespace}:${res.data.did}`;
responses.push(res.data);
} else {
throw new Error('No data was returned from the ledger request');
}
} catch (err) {
// if did is already registered on IdUnion it will catch 500, but it's ok
logAxiosError(err);
}
}
return responses;
};
export default registerPublicDids;
import { Inject, Module } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import logger from '@src/globalUtils/logger';
import { Agent, HttpOutboundTransport } from '@aries-framework/core';
import {
LedgerIds,
LedgerInfo,
ledgerNamespaces,
LEDGER_GENESIS,
NYM_URL,
} from '@src/agent/agentUtils/ledgerConfig';
import { agentDependencies, HttpInboundTransport } from '@aries-framework/node';
import { subscribe } from '@src/agent/agentUtils/listener';
import { NatsClientService } from '@src/client/nats.client';
import { ClientsModule, Transport } from '@nestjs/microservices';
import { NATSServices } from '@common/constants';
import config from '@config/config';
import axios from 'axios';
import LedgerRegistationBody from '@src/didComm/entities/LedgerRegistrationBody';
import { logAxiosError } from './agentUtils/helperFunctions';
export const AGENT = 'agent';
const agentFactory = {
provide: AGENT,
useFactory: async (
configService: ConfigService,
natsClient: NatsClientService,
) => {
logger.info('Agent initializing...');
const {
name,
walletId,
walletKey,
ledgerIds,
host,
peerPort,
path,
publicDidSeed,
autoAcceptConnection,
autoAcceptCredential,
basicUser,
basicPass,
} = configService.get('agent');
const endpoints = [`${host}${peerPort}${path}`];
if (!ledgerIds || ledgerIds.length < 1 || ledgerIds[0] === '') {
throw new Error(
'Agent could not start, please provide a ledger environment variable.',
);
}
const indyLedgers: LedgerInfo[] = ledgerIds.map((id: LedgerIds) => {
if (!LEDGER_GENESIS?.[id]) {
throw new Error(
`No pool transaction genesis provided for ledger ${id}`,
);
}
const ledger: LedgerInfo = {
id: `${id}_Genesis`,
indyNamespace: `${ledgerNamespaces[id]}`,
genesisTransactions: LEDGER_GENESIS?.[id],
isProduction: false,
};
return ledger;
});
const agentConfig = {
label: name,
walletConfig: {
id: walletId,
key: walletKey,
},
indyLedgers,
publicDidSeed,
endpoints,
autoAcceptConnections: autoAcceptConnection,
autoAcceptCredentials: autoAcceptCredential,
};
const agent = new Agent(agentConfig, agentDependencies);
const httpInbound = new HttpInboundTransport({
port: Number(peerPort.replace(':', '')),
});
agent.registerInboundTransport(httpInbound);
agent.registerOutboundTransport(new HttpOutboundTransport());
await agent.initialize();
subscribe(agent, natsClient);
if (agent.isInitialized) {
ledgerIds.map(async (id: LedgerIds) => {
let body: LedgerRegistationBody = {
role: 'ENDORSER',
alias: name,
did: agent.publicDid?.did,
verkey: agent.publicDid?.verkey,
};
if (id === 'ID_UNION') {
body = {
did: agent.publicDid?.did,
verkey: agent.publicDid?.verkey,
};
}
if (id === 'ID_UNION' && basicPass && basicPass) {
await axios
.post(NYM_URL[id], body, {
auth: {
username: basicUser,
password: basicPass,
},
})
.then((res: any) => {
if (res.data) {
logger.info('Agent DID registered.');
}
})
.catch((err: any) => {
// if did is already registered on IdUnion it will catch 500, but it's ok
logAxiosError(err);
});
} else {
await axios
.post(NYM_URL[id], body)
.then((res: any) => {
if (res.data) {
logger.info('Agent DID registered.');
}
})
.catch((err: any) => {
// if did is already registered on IdUnion it will catch 500, but it's ok
logAxiosError(err);
});
}
});
}
logger.info('Agent initialized');
return agent;
},
inject: [ConfigService, NatsClientService],
};
@Module({
imports: [
ClientsModule.register([
{
name: NATSServices.SERVICE_NAME,
transport: Transport.NATS,
options: {
servers: [config().nats.url],
},
},
]),
],
controllers: [],
providers: [agentFactory, NatsClientService],
exports: [AGENT],
})
export class AgentModule {
constructor(@Inject(AGENT) private agent: Agent) {}
async onModuleDestroy() {
await this.agent.shutdown();
}
}
export default AgentModule;
...@@ -11,7 +11,7 @@ export function logAxiosError(err: any) { ...@@ -11,7 +11,7 @@ export function logAxiosError(err: any) {
logger.error(err.request); logger.error(err.request);
} else { } else {
// Something happened in setting up the request that triggered an Error // Something happened in setting up the request that triggered an Error
logger.error('Request error: ', err.message); logger.error('Request error: ', err);
} }
} }
......
import config from '@config/config';
export const LEDGER_GENESIS = { export const LEDGER_GENESIS = {
ID_UNION: `{"reqSignature":{},"txn":{"data":{"data":{"alias":"MainIncubator","blskey":"14MPfxHnRvCL5dnbpD3SjxekAGnKyjkmifDFLnMJAvHcvEAarDLWX6KawhubPujSmmUMqRmQfPQzBambrdUqBGgHDryDS6Aj8BioWRwZkyTcH1zzkVQ7vZjE5S6ri5epkiS1VkVX42Z22z4cohdHVuKTgeQB5mjAwi55xNeRxpxhrNb","blskey_pop":"QoqRe3vMPr5Bt1qHDstYewWkxb5VEdugnvumLCWpkZAeUpdqjjaSTSKKJtT7U7aCe8CmShGSdCZFWs9hcpmMSGfMnmon7R99UTJj4jEr48smyxo1UpBcgooznc8N8USkZ8hSec3bRbN9y6NppuaFzfgt1WmJ3cdFi9L1Wbj1fNs5CK","client_ip":"35.207.81.15","client_port":"9702","node_ip":"35.207.81.15","node_port":"9701","services":["VALIDATOR"]},"dest":"EQ2oCtWpMdUCzKgQ2hvbyQ2i6VyJuQF9LcpHRfiah6rW"},"metadata":{"from":"2MZYuPv2Km7Q1eD4GCsSb6"},"type":"0"},"txnMetadata":{"seqNo":1,"txnId":"0a35c047f19448f12a0c2961d8e3085140b8149d87291acbdaf56ed956900d48"},"ver":"1"} ID_UNION: `{"reqSignature":{},"txn":{"data":{"data":{"alias":"MainIncubator","blskey":"14MPfxHnRvCL5dnbpD3SjxekAGnKyjkmifDFLnMJAvHcvEAarDLWX6KawhubPujSmmUMqRmQfPQzBambrdUqBGgHDryDS6Aj8BioWRwZkyTcH1zzkVQ7vZjE5S6ri5epkiS1VkVX42Z22z4cohdHVuKTgeQB5mjAwi55xNeRxpxhrNb","blskey_pop":"QoqRe3vMPr5Bt1qHDstYewWkxb5VEdugnvumLCWpkZAeUpdqjjaSTSKKJtT7U7aCe8CmShGSdCZFWs9hcpmMSGfMnmon7R99UTJj4jEr48smyxo1UpBcgooznc8N8USkZ8hSec3bRbN9y6NppuaFzfgt1WmJ3cdFi9L1Wbj1fNs5CK","client_ip":"35.207.81.15","client_port":"9702","node_ip":"35.207.81.15","node_port":"9701","services":["VALIDATOR"]},"dest":"EQ2oCtWpMdUCzKgQ2hvbyQ2i6VyJuQF9LcpHRfiah6rW"},"metadata":{"from":"2MZYuPv2Km7Q1eD4GCsSb6"},"type":"0"},"txnMetadata":{"seqNo":1,"txnId":"0a35c047f19448f12a0c2961d8e3085140b8149d87291acbdaf56ed956900d48"},"ver":"1"}
{"reqSignature":{},"txn":{"data":{"data":{"alias":"tubzecm","blskey":"3Zpdx6LMWPdybnQKPq62S3TaWUhwypr7RV2BBFkeFigjKuue7KJ7rh5w1gZY9qgugww9vZnpURLSjBuTonJpfyfN5nn2ofwFQQa3viiT77hhFf6kQqoMH53f66ZfBNWU2LzphQikXsma9zjZWALMtMsNWx7ftNZ8yzMrZpf1X6VqYX5","blskey_pop":"RbPQSMsV8iuxNXVFNEUPvb6k1wQe1rxaXroMMkpHTstiiJfCApER38jW79Ew1yrnt5ndz7wJeDRU7CkLNzJ6pEZaRYjLzhZL2shRgyaGqnMqkxvD1ewxNMSz7cSgBSChwUgLBxsms5iDyshwAM5dx8B1GayMyATcFxAdgCRiDv3EHm","client_ip":"141.23.35.186","client_port":"9702","node_ip":"141.23.35.186","node_port":"9701","services":["VALIDATOR"]},"dest":"Ddqm5GATTcEb5hrgMBbVL8w6R6mtTHjUpdpyCeWg3pVS"},"metadata":{"from":"JhyMn8Nn3xy2zsXjPaPu3B"},"type":"0"},"txnMetadata":{"seqNo":2,"txnId":"e2f9efff1bfef015098ae299a665154fa39a898a5071d0af03c7f2311fe8577f"},"ver":"1"} {"reqSignature":{},"txn":{"data":{"data":{"alias":"tubzecm","blskey":"3Zpdx6LMWPdybnQKPq62S3TaWUhwypr7RV2BBFkeFigjKuue7KJ7rh5w1gZY9qgugww9vZnpURLSjBuTonJpfyfN5nn2ofwFQQa3viiT77hhFf6kQqoMH53f66ZfBNWU2LzphQikXsma9zjZWALMtMsNWx7ftNZ8yzMrZpf1X6VqYX5","blskey_pop":"RbPQSMsV8iuxNXVFNEUPvb6k1wQe1rxaXroMMkpHTstiiJfCApER38jW79Ew1yrnt5ndz7wJeDRU7CkLNzJ6pEZaRYjLzhZL2shRgyaGqnMqkxvD1ewxNMSz7cSgBSChwUgLBxsms5iDyshwAM5dx8B1GayMyATcFxAdgCRiDv3EHm","client_ip":"141.23.35.186","client_port":"9702","node_ip":"141.23.35.186","node_port":"9701","services":["VALIDATOR"]},"dest":"Ddqm5GATTcEb5hrgMBbVL8w6R6mtTHjUpdpyCeWg3pVS"},"metadata":{"from":"JhyMn8Nn3xy2zsXjPaPu3B"},"type":"0"},"txnMetadata":{"seqNo":2,"txnId":"e2f9efff1bfef015098ae299a665154fa39a898a5071d0af03c7f2311fe8577f"},"ver":"1"}
...@@ -20,27 +18,18 @@ export const LEDGER_GENESIS = { ...@@ -20,27 +18,18 @@ export const LEDGER_GENESIS = {
{"reqSignature":{},"txn":{"data":{"data":{"alias":"Node4","blskey":"2zN3bHM1m4rLz54MJHYSwvqzPchYp8jkHswveCLAEJVcX6Mm1wHQD1SkPYMzUDTZvWvhuE6VNAkK3KxVeEmsanSmvjVkReDeBEMxeDaayjcZjFGPydyey1qxBHmTvAnBKoPydvuTAqx5f7YNNRAdeLmUi99gERUU7TD8KfAa6MpQ9bw","blskey_pop":"RPLagxaR5xdimFzwmzYnz4ZhWtYQEj8iR5ZU53T2gitPCyCHQneUn2Huc4oeLd2B2HzkGnjAff4hWTJT6C7qHYB1Mv2wU5iHHGFWkhnTX9WsEAbunJCV2qcaXScKj4tTfvdDKfLiVuU2av6hbsMztirRze7LvYBkRHV3tGwyCptsrP","client_ip":"138.197.161.221","client_port":9708,"node_ip":"138.197.161.221","node_port":9707,"services":["VALIDATOR"]},"dest":"4PS3EDQ3dW1tci1Bp6543CfuuebjFrg36kLAUcskGfaA"},"metadata":{"from":"TWwCRQRZ2ZHMJFn9TzLp7W"},"type":"0"},"txnMetadata":{"seqNo":4,"txnId":"aa5e817d7cc626170eca175822029339a444eb0ee8f0bd20d3b0b76e566fb008"},"ver":"1"}`, {"reqSignature":{},"txn":{"data":{"data":{"alias":"Node4","blskey":"2zN3bHM1m4rLz54MJHYSwvqzPchYp8jkHswveCLAEJVcX6Mm1wHQD1SkPYMzUDTZvWvhuE6VNAkK3KxVeEmsanSmvjVkReDeBEMxeDaayjcZjFGPydyey1qxBHmTvAnBKoPydvuTAqx5f7YNNRAdeLmUi99gERUU7TD8KfAa6MpQ9bw","blskey_pop":"RPLagxaR5xdimFzwmzYnz4ZhWtYQEj8iR5ZU53T2gitPCyCHQneUn2Huc4oeLd2B2HzkGnjAff4hWTJT6C7qHYB1Mv2wU5iHHGFWkhnTX9WsEAbunJCV2qcaXScKj4tTfvdDKfLiVuU2av6hbsMztirRze7LvYBkRHV3tGwyCptsrP","client_ip":"138.197.161.221","client_port":9708,"node_ip":"138.197.161.221","node_port":9707,"services":["VALIDATOR"]},"dest":"4PS3EDQ3dW1tci1Bp6543CfuuebjFrg36kLAUcskGfaA"},"metadata":{"from":"TWwCRQRZ2ZHMJFn9TzLp7W"},"type":"0"},"txnMetadata":{"seqNo":4,"txnId":"aa5e817d7cc626170eca175822029339a444eb0ee8f0bd20d3b0b76e566fb008"},"ver":"1"}`,
}; };
const { idUnionKey } = config().agent;
export const NYM_URL = { export const NYM_URL = {
ID_UNION: `https://endorser.idunion.org/api/dids?apiKey=${idUnionKey}`, ID_UNION: 'https://idu.cloudcompass.ca/register',
BCOVRIN_TEST: 'http://test.bcovrin.vonx.io/register', BCOVRIN_TEST: 'http://test.bcovrin.vonx.io/register',
GREEN_LIGHT: 'http://greenlight.bcovrin.vonx.io/register', GREEN_LIGHT: 'http://greenlight.bcovrin.vonx.io/register',
}; } as const;
export type LedgerIds = keyof typeof LEDGER_GENESIS; export type LedgerIds = keyof typeof LEDGER_GENESIS;
export const ledgerNamespaces = { export const ledgerNamespaces = {
ID_UNION: 'idunion', ID_UNION: 'idunion:test',
BCOVRIN_TEST: 'sovrin:test', BCOVRIN_TEST: 'bcovrin:test',
GREEN_LIGHT: 'sovrin', GREEN_LIGHT: 'bcovrin:greenlight',
};
export type LedgerInfo = {
id: string;
indyNamespace: string;
genesisTransactions?: string;
genesisPath?: any;
isProduction: boolean;
}; };
export default { export default {
......
...@@ -9,16 +9,13 @@ import { listenerConfig } from './listenerConfig'; ...@@ -9,16 +9,13 @@ import { listenerConfig } from './listenerConfig';
* @param agent - the agent that has been initialized on startup * @param agent - the agent that has been initialized on startup
* @param natsClient - the client that specifies how events are published * @param natsClient - the client that specifies how events are published
*/ */
export const subscribe = ( export const subscribe = (agent: Agent, natsClient: NatsClientService) => {
agent: Agent,
natsClient: NatsClientService,
) => {
for (let i = 0; i < listenerConfig.length; i += 1) { for (let i = 0; i < listenerConfig.length; i += 1) {
agent.events.on(listenerConfig[i], ({ payload }) => { agent.events.on(listenerConfig[i], ({ payload }) => {
logger.info( logger.info(
`${listenerConfig[i]} called. Payload: ${JSON.stringify(payload)}`, `${listenerConfig[i]} called. Payload: ${JSON.stringify(payload)}`,
); );
natsClient.publish(`${listenerConfig[i]}`, payload); natsClient.publish(listenerConfig[i], payload);
}); });
} }
}; };
......
/* eslint-disable class-methods-use-this */
import { BaseLogger, LogLevel } from '@aries-framework/core';
import logger from '@src/globalUtils/logger';
export class AgentLogger extends BaseLogger {
public test(message: string, data?: Record<string, any> | undefined): void {
if (!this.isEnabled(LogLevel.test)) return;
logger.verbose(message, data);
}
public trace(message: string, data?: Record<string, any> | undefined): void {
if (!this.isEnabled(LogLevel.trace)) return;
logger.info(message, data);
}
public debug(message: string, data?: Record<string, any> | undefined): void {
if (!this.isEnabled(LogLevel.debug)) return;
logger.info(message, data);
}
public info(message: string, data?: Record<string, any> | undefined): void {
if (!this.isEnabled(LogLevel.info)) return;
logger.info(message, data);
}
public warn(message: string, data?: Record<string, any> | undefined): void {
if (!this.isEnabled(LogLevel.warn)) return;
logger.warn(message, data);
}
public error(message: string, data?: Record<string, any> | undefined): void {
if (!this.isEnabled(LogLevel.error)) return;
logger.error(message, data);
}
public fatal(message: string, data?: Record<string, any> | undefined): void {
if (!this.isEnabled(LogLevel.fatal)) return;
logger.error(message, data);
}
}
export default AgentLogger;
...@@ -6,8 +6,8 @@ import config from '@config/config'; ...@@ -6,8 +6,8 @@ import config from '@config/config';
import validationSchema from '@config/validation'; import validationSchema from '@config/validation';
import HealthController from '@src/health/health.controller'; import HealthController from '@src/health/health.controller';
import ExceptionHandler from '@src/globalUtils/exception.handler'; import ExceptionHandler from '@src/globalUtils/exception.handler';
import DidCommModule from '@didComm/module';
import { AgentMid } from './middleware/agentMid.middleware'; import { AgentMid } from './middleware/agentMid.middleware';
import { AgentModule } from './agent/agent.module';
@Module({ @Module({
imports: [ imports: [
...@@ -17,7 +17,7 @@ import { AgentMid } from './middleware/agentMid.middleware'; ...@@ -17,7 +17,7 @@ import { AgentMid } from './middleware/agentMid.middleware';
load: [config], load: [config],
validationSchema, validationSchema,
}), }),
DidCommModule, AgentModule,
], ],
controllers: [HealthController], controllers: [HealthController],
providers: [ providers: [
......
This diff is collapsed.
import {
All,
Body,
Controller,
Get,
HttpStatus,
Inject,
Param,
} from '@nestjs/common';
import { ResponseType } from '@common/response';
import { AGENT } from '@agent/module';
import logger from '@src/globalUtils/logger';
import { Agent } from '@aries-framework/core';
import { GenericBody } from '@didComm/entities/GenericBody';
import { GenericParams } from '../utils/whitelist';
import { objectPathLoop } from '../didCommUtils';
import { prepareInputData, prepareOutputData } from '../utils/prepareData';
@Controller('agent')
export class DidCommController {
constructor(@Inject(AGENT) private readonly agent: Agent) {}
/**
* A backup endpoint that dynamically interfaces with the agent, in case the extension
* lags behind the AFJ or malfunctions
*
* expected body:
* {
* "subMethod": {
* "name": "asdas.asdasd",
* "subMethodData": [
* "argument1",
* "argument2"
* ]
* },
* "data": [
* "argumentN",
* "argumentN+1"
* ]
* }
* @param params -one of the allowed properties/method to be called on the agent
* @param body -arguments of the method and/or calling a method on the returned object
*/
@All('/:property/:method')
async generic(@Param() params: GenericParams, @Body() body: GenericBody) {
logger.info(
`Received request ${params.property}/${params.method}, body: ${JSON.stringify(body)}`,
);
const { property, method } = params;
const prop: any = this.agent[property];
// eslint-disable-next-line prefer-spread
let response = await prop[method].apply(prop, prepareInputData(body.data));
if (body.subMethod && body.subMethod.name) {
const path = body.subMethod.name.split('.');
let result: any;
if (Array.isArray(response)) {
const results = [];
for (let j = 0; j < response.length; j += 1) {
const prevContext = response[j];
const context = response[j][path[0]];
result = objectPathLoop(response, path, context, prevContext, body);
results.push(prepareOutputData(result));
}
return {
statusCode: HttpStatus.OK,
message: `${property}.${method}(${JSON.stringify(body.data)}) => ${
body.subMethod.name
}`,
data: results,
} as ResponseType;
}
const prevContext = response;
const context = response[path[0]];
response = objectPathLoop(response, path, context, prevContext, body);
}
return {
statusCode: HttpStatus.OK,
message: `${property}.${method}(${JSON.stringify(body.data)}) => ${
body.subMethod && body.subMethod.name && body.subMethod.name
}`,
data: prepareOutputData(response),
} as ResponseType;
}
@Get('info')
async getWalletInfo() {
const { publicDid } = this.agent.wallet;
if (!publicDid) {
throw new Error('Wallet is not initialized');
}
return {
statusCode: HttpStatus.OK,
message: 'Success',
data: publicDid,
} as ResponseType;
}
}
export default DidCommController;
import GenericBody from '@didComm/entities/GenericBody';
import { prepareInputData } from './utils/prepareData';
/**
*
* Handles the subMethods of responses
*
* @param response - generic response from the agent
* @param path - the location of the subMethod within the response object ('.' notation)
* @param context - subMethod on which the body.subMethod.subMethodData is applied on
* @param prevContext - the object which contains the subMethod
* @param body - arguments of the property method + subMethod name and arguments
* @returns - the result from the applied subMethod arguments on the subMethod
*/
export function objectPathLoop(
response: any,
path: string[],
context: any,
prevContext: any,
body: GenericBody,
) {
let responseRe = response;
let contextRe = context;
let prevContextRe = prevContext;
for (let i = 1; i < path.length; i += 1) {
prevContextRe = contextRe;
contextRe = contextRe[path[i]];
}
responseRe = contextRe;
if (typeof contextRe === 'function' && body.subMethod) {
responseRe = contextRe.apply(
prevContextRe,
prepareInputData(body.subMethod.subMethodData),
); // eslint-disable-line
}
return responseRe;
}
export default {
objectPathLoop,
};
describe('check GenericBody', () => {
it('should return module', async () => {
jest.requireActual('./GenericBody');
});
});
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment