Skip to content

Commit

Permalink
feat: 🎸 Add API to get account to identity lookup
Browse files Browse the repository at this point in the history
  • Loading branch information
prashantasdeveloper committed Apr 5, 2024
1 parent aefd26f commit 7983657
Show file tree
Hide file tree
Showing 5 changed files with 93 additions and 4 deletions.
25 changes: 24 additions & 1 deletion src/accounts/accounts.controller.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { DeepMocked } from '@golevelup/ts-jest';
import { HttpStatus } from '@nestjs/common';
import { HttpStatus, NotFoundException } from '@nestjs/common';
import { Test, TestingModule } from '@nestjs/testing';
import { BigNumber } from '@polymeshassociation/polymesh-sdk';
import {
Expand All @@ -17,13 +17,15 @@ import { ExtrinsicModel } from '~/common/models/extrinsic.model';
import { PaginatedResultsModel } from '~/common/models/paginated-results.model';
import { PermissionsLikeDto } from '~/identities/dto/permissions-like.dto';
import { AccountModel } from '~/identities/models/account.model';
import { IdentitySignerModel } from '~/identities/models/identity-signer.model';
import { NetworkService } from '~/network/network.service';
import { SubsidyService } from '~/subsidy/subsidy.service';
import { extrinsic, testValues } from '~/test-utils/consts';
import {
createMockResponseObject,
createMockSubsidy,
MockAsset,
MockIdentity,
MockPortfolio,
} from '~/test-utils/mocks';
import {
Expand Down Expand Up @@ -57,6 +59,27 @@ describe('AccountsController', () => {
expect(controller).toBeDefined();
});

describe('getIdentity', () => {
it('should throw NotFoundException if no Identity is associated with the Account', () => {
mockAccountsService.getIdentity.mockResolvedValue(null);

return expect(() => controller.getIdentity({ account: '5xdd' })).rejects.toBeInstanceOf(
NotFoundException
);
});

describe('otherwise', () => {
it('should return the associated DID for the given account', async () => {
const identity = new MockIdentity();
mockAccountsService.getIdentity.mockResolvedValue(identity);

const result = await controller.getIdentity({ account: '5xdd' });

expect(result).toEqual(new IdentitySignerModel({ did }));
});
});
});

describe('getAccountBalance', () => {
it('should return the POLYX balance of an Account', async () => {
const mockResult = {
Expand Down
40 changes: 39 additions & 1 deletion src/accounts/accounts.controller.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,14 @@
import { Body, Controller, Get, HttpStatus, Param, Post, Query, Res } from '@nestjs/common';
import {
Body,
Controller,
Get,
HttpStatus,
NotFoundException,
Param,
Post,
Query,
Res,
} from '@nestjs/common';
import {
ApiBadRequestResponse,
ApiNoContentResponse,
Expand Down Expand Up @@ -27,6 +37,7 @@ import { PaginatedResultsModel } from '~/common/models/paginated-results.model';
import { TransactionQueueModel } from '~/common/models/transaction-queue.model';
import { handleServiceResult, TransactionResponseModel } from '~/common/utils';
import { AccountModel } from '~/identities/models/account.model';
import { IdentitySignerModel } from '~/identities/models/identity-signer.model';
import { NetworkService } from '~/network/network.service';
import { SubsidyModel } from '~/subsidy/models/subsidy.model';
import { SubsidyService } from '~/subsidy/subsidy.service';
Expand All @@ -41,6 +52,33 @@ export class AccountsController {
private readonly subsidyService: SubsidyService
) {}

@ApiOperation({
summary: 'Get the DID associated with an Account',
description: 'This endpoint provides account to identity lookup',
})
@ApiParam({
name: 'account',
description: 'The Account address whose DID is to be fetched',
type: 'string',
example: '5GwwYnwCYcJ1Rkop35y7SDHAzbxrCkNUDD4YuCUJRPPXbvyV',
})
@ApiOkResponse({
description: 'DID of the Identity associated with the given Account',
type: IdentitySignerModel,
})
@ApiNotFoundResponse({
description: 'No DID is associated with the given account',
})
@Get(':account/identity')
async getIdentity(@Param() { account }: AccountParamsDto): Promise<IdentitySignerModel> {
const identity = await this.accountsService.getIdentity(account);

if (!identity) {
throw new NotFoundException('No DID is associated with the given account');
}
return new IdentitySignerModel({ did: identity.did });
}

@ApiOperation({
summary: 'Get POLYX balance of an Account',
description: 'This endpoint provides the free, locked and total POLYX balance of an Account',
Expand Down
25 changes: 23 additions & 2 deletions src/accounts/accounts.service.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
/* eslint-disable import/first */
const mockIsPolymeshTransaction = jest.fn();

import { Test, TestingModule } from '@nestjs/testing';
import { BigNumber } from '@polymeshassociation/polymesh-sdk';
import { ExtrinsicsOrderBy } from '@polymeshassociation/polymesh-sdk/middleware/types';
Expand All @@ -14,7 +13,13 @@ import { PolymeshModule } from '~/polymesh/polymesh.module';
import { PolymeshService } from '~/polymesh/polymesh.service';
import { SigningModule } from '~/signing/signing.module';
import { extrinsic, testValues } from '~/test-utils/consts';
import { MockAccount, MockAsset, MockPolymesh, MockTransaction } from '~/test-utils/mocks';
import {
MockAccount,
MockAsset,
MockIdentity,
MockPolymesh,
MockTransaction,
} from '~/test-utils/mocks';
import { mockTransactionsProvider, MockTransactionsService } from '~/test-utils/service-mocks';
import * as transactionsUtilModule from '~/transactions/transactions.util';

Expand Down Expand Up @@ -87,6 +92,22 @@ describe('AccountsService', () => {
});
});

describe('getIdentity', () => {
it('should return the Identity associated with a given address', async () => {
const mockAccount = new MockAccount();

const findOneSpy = jest.spyOn(service, 'findOne');
// eslint-disable-next-line @typescript-eslint/no-explicit-any
findOneSpy.mockResolvedValue(mockAccount as any);

const mockResult = new MockIdentity();
mockAccount.getIdentity.mockResolvedValue(mockResult);

const result = await service.getIdentity('address');
expect(result).toEqual(mockResult);
});
});

describe('getAccountBalance', () => {
it('should return the POLYX balance of an Account', async () => {
const fakeBalance = 'balance';
Expand Down
6 changes: 6 additions & 0 deletions src/accounts/accounts.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {
Account,
AccountBalance,
ExtrinsicData,
Identity,
Permissions,
ResultSet,
} from '@polymeshassociation/polymesh-sdk/types';
Expand Down Expand Up @@ -33,6 +34,11 @@ export class AccountsService {
});
}

public async getIdentity(address: string): Promise<Identity | null> {
const account = await this.findOne(address);
return account.getIdentity();
}

public async getAccountBalance(account: string): Promise<AccountBalance> {
const {
polymeshService: { polymeshApi },
Expand Down
1 change: 1 addition & 0 deletions src/test-utils/service-mocks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ export class MockAccountsService {
modifyPermissions = jest.fn();
revokePermissions = jest.fn();
getTreasuryAccount = jest.fn();
getIdentity = jest.fn();
}

export class MockEventsService {
Expand Down

0 comments on commit 7983657

Please sign in to comment.