Skip to content

Commit

Permalink
feat: 🎸 get all eligible dividend distributions for did
Browse files Browse the repository at this point in the history
  • Loading branch information
sansan committed Nov 21, 2024
1 parent b1aec9c commit 4a662ec
Show file tree
Hide file tree
Showing 7 changed files with 83 additions and 1 deletion.
1 change: 1 addition & 0 deletions src/corporate-actions/corporate-actions.controller.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ describe('CorporateActionsController', () => {
linkDocuments: jest.fn(),
reclaimRemainingFunds: jest.fn(),
modifyCheckpoint: jest.fn(),
findUnclaimedDistributionsByAsset: jest.fn(),
};

beforeEach(async () => {
Expand Down
21 changes: 21 additions & 0 deletions src/identities/identities.controller.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ import { PendingAuthorizationsModel } from '~/authorizations/models/pending-auth
import { ClaimsService } from '~/claims/claims.service';
import { PaginatedResultsModel } from '~/common/models/paginated-results.model';
import { ResultsModel } from '~/common/models/results.model';
import { createDividendDistributionDetailsModel } from '~/corporate-actions/corporate-actions.util';
import { MockDistributionWithDetails } from '~/corporate-actions/mocks/distribution-with-details.mock';
import { RegisterIdentityDto } from '~/identities/dto/register-identity.dto';
import { IdentitiesController } from '~/identities/identities.controller';
import { IdentitiesService } from '~/identities/identities.service';
Expand Down Expand Up @@ -754,4 +756,23 @@ describe('IdentitiesController', () => {
});
});
});

describe('getUnclaimedDividendDistributions', () => {
it('should return unclaimed Dividend Distributions associated with Identity', async () => {
const mockDistributions = [new MockDistributionWithDetails()];

mockIdentitiesService.getPendingDistributions.mockResolvedValue(mockDistributions);

const result = await controller.getPendingDistributions({ did });

expect(result).toEqual(
new ResultsModel({
results: mockDistributions.map(distributionWithDetails =>
// eslint-disable-next-line @typescript-eslint/no-explicit-any
createDividendDistributionDetailsModel(distributionWithDetails as any)
),
})
);
});
});
});
33 changes: 33 additions & 0 deletions src/identities/identities.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ import { DidDto, IncludeExpiredFilterDto } from '~/common/dto/params.dto';
import { PaginatedResultsModel } from '~/common/models/paginated-results.model';
import { ResultsModel } from '~/common/models/results.model';
import { handleServiceResult, TransactionResponseModel } from '~/common/utils';
import { createDividendDistributionDetailsModel } from '~/corporate-actions/corporate-actions.util';
import { DividendDistributionDetailsModel } from '~/corporate-actions/models/dividend-distribution-details.model';
import { DeveloperTestingService } from '~/developer-testing/developer-testing.service';
import { CreateMockIdentityDto } from '~/developer-testing/dto/create-mock-identity.dto';
import { AddSecondaryAccountParamsDto } from '~/identities/dto/add-secondary-account-params.dto';
Expand Down Expand Up @@ -754,4 +756,35 @@ export class IdentitiesController {
next,
});
}

@ApiTags('dividend-distributions')
@ApiOperation({
summary: 'Fetch eligible Dividend Distributions',
description:
'This endpoint will provide the list of Dividend Distributions that are eligible to be claimed by the current Identity',
})
@ApiParam({
name: 'did',
description: 'The DID of the Identity for which fetch pending Dividend Distributions for',
type: 'string',
required: true,
example: '0x0600000000000000000000000000000000000000000000000000000000000000',
})
@ApiArrayResponse(DividendDistributionDetailsModel, {
description:
'List of Dividend Distributions that are eligible to be claimed by the specified Identity',
paginated: false,
})
@Get(':did/pending-distributions')
public async getPendingDistributions(
@Param() { did }: DidDto
): Promise<ResultsModel<DividendDistributionDetailsModel>> {
const results = await this.identitiesService.getPendingDistributions(did);

return new ResultsModel({
results: results.map(distributionWithDetails =>
createDividendDistributionDetailsModel(distributionWithDetails)
),
});
}
}
20 changes: 19 additions & 1 deletion src/identities/identities.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { BigNumber } from '@polymeshassociation/polymesh-sdk';
import { TxTags } from '@polymeshassociation/polymesh-sdk/types';

import { AccountsService } from '~/accounts/accounts.service';
import { MockDistributionWithDetails } from '~/corporate-actions/mocks/distribution-with-details.mock';
import { RegisterIdentityDto } from '~/identities/dto/register-identity.dto';
import { IdentitiesService } from '~/identities/identities.service';
import { mockPolymeshLoggerProvider } from '~/logger/mock-polymesh-logger';
Expand All @@ -27,7 +28,7 @@ import {
} from '~/test-utils/service-mocks';
import * as transactionsUtilModule from '~/transactions/transactions.util';

const { signer } = testValues;
const { signer, did } = testValues;

jest.mock('@polymeshassociation/polymesh-sdk/utils', () => ({
...jest.requireActual('@polymeshassociation/polymesh-sdk/utils'),
Expand Down Expand Up @@ -290,4 +291,21 @@ describe('IdentitiesService', () => {
expect(result).toEqual(mockAssets);
});
});

describe('getPendingDistributions', () => {
it('should return the Dividend Distributions associated with an Asset that have not been claimed', async () => {
const mockDistributions = [new MockDistributionWithDetails()];

const mockIdentity = new MockIdentity();

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

const result = await service.getPendingDistributions(did);

expect(result).toEqual(mockDistributions);
});
});
});
7 changes: 7 additions & 0 deletions src/identities/identities.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { Injectable } from '@nestjs/common';
import { BigNumber } from '@polymeshassociation/polymesh-sdk';
import {
AuthorizationRequest,
DistributionWithDetails,
FungibleAsset,
Identity,
NftCollection,
Expand Down Expand Up @@ -152,4 +153,10 @@ export class IdentitiesService {

return identity.isAssetPreApproved(asset);
}

public async getPendingDistributions(did: string): Promise<DistributionWithDetails[]> {
const identity = await this.findOne(did);

return identity.getPendingDistributions();
}
}
1 change: 1 addition & 0 deletions src/test-utils/mocks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,7 @@ export class MockIdentity {
public getHeldAssets = jest.fn();
public preApprovedAssets = jest.fn();
public isAssetPreApproved = jest.fn();
public getPendingDistributions = jest.fn();
}

export class MockPortfolio {
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 @@ -152,6 +152,7 @@ export class MockIdentitiesService {
attestPrimaryKeyRotation = jest.fn();
isAssetPreApproved = jest.fn();
getPreApprovedAssets = jest.fn();
getPendingDistributions = jest.fn();
}

export class MockSettlementsService {
Expand Down

0 comments on commit 4a662ec

Please sign in to comment.