Skip to content

Commit

Permalink
add ability to get account given public key (#325)
Browse files Browse the repository at this point in the history
# Problem
Currently, we cannot get an msa or any other account information given a
public key. We need to add functionality to do so.

Link to GitHub Issue(s): #266 

# Solution
- Added endpoint and service to support getting an account given a
public key
- Added a service to get an msaId given a public key

## Steps to Verify:

1. Spin up swagger
2. Test that endpoint return correct account.
3. See that open api displays all of the correct info.

## Screenshots (optional):
<img width="1492" alt="Screenshot 2024-08-01 at 3 28 19 PM"
src="https://github.com/user-attachments/assets/b94b79a8-d8f6-4040-acd3-ae4f2292bb5d">

## Additional Info
While the ticket states to just return an MSA Id, I thought it would be
more complete to return the associated account, which is an object that
contains the msaId and handle.

---------

Co-authored-by: Claire Olmstead <[email protected]>
  • Loading branch information
claireolmstead and Claire Olmstead authored Aug 5, 2024
1 parent d16dbf9 commit f3dc764
Show file tree
Hide file tree
Showing 6 changed files with 522 additions and 26 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,41 @@ export class AccountsControllerV1 {
* @returns A promise that resolves to an Account object => {msaId, handle}.
* @throws An error if the account cannot be found.
*/
async getAccount(@Param('msaId') msaId: string): Promise<AccountResponse> {
async getAccountForMsa(@Param('msaId') msaId: string): Promise<AccountResponse> {
try {
this.logger.debug(`Received request to get account with msaId: ${msaId}`);
return await this.accountsService.getAccount(msaId);
const account = await this.accountsService.getAccount(msaId);
if (account) return account;
throw new HttpException('Failed to find the account', HttpStatus.NOT_FOUND);
} catch (error) {
this.logger.error(error);
if (error instanceof HttpException) throw error;
throw new HttpException('Failed to find the account', HttpStatus.BAD_REQUEST);
}
}

@Get('account/:publicKey')
@HttpCode(HttpStatus.OK)
@ApiOperation({ summary: 'Fetch an account given a public key.' })
@ApiOkResponse({ description: 'Found account', type: AccountResponse })
/**
* Gets an account.
* @param queryParams - The query parameters for creating the account.
* @returns A promise that resolves to an Account object => {msaId, handle}.
* @throws An error if the msaId or account cannot be found.
*/
async getAccountForPublicKey(@Param('publicKey') publicKey: string): Promise<AccountResponse> {
try {
this.logger.debug(`Received request to get account with publicKey: ${publicKey}`);
const response = await this.accountsService.getMsaIdForPublicKey(publicKey);
if (response?.msaId) {
const account = await this.accountsService.getAccount(response.msaId);
if (account) return account;
}
throw new HttpException('Failed to find the account', HttpStatus.NOT_FOUND);
} catch (error) {
this.logger.error(error);
if (error instanceof HttpException) throw error;
throw new HttpException('Failed to find the account', HttpStatus.BAD_REQUEST);
}
}
Expand All @@ -58,7 +87,7 @@ export class AccountsControllerV1 {
async postSignInWithFrequency(@Body() walletLoginRequest: WalletLoginRequestDto): Promise<WalletLoginResponse> {
try {
this.logger.debug(`Received Sign-In With Frequency request: ${JSON.stringify(walletLoginRequest)}`);
return await this.accountsService.signInWithFrequency(walletLoginRequest);
return this.accountsService.signInWithFrequency(walletLoginRequest);
} catch (error) {
const errorMessage = 'Failed to Sign In With Frequency';
this.logger.error(`${errorMessage}: ${error}`);
Expand Down
42 changes: 28 additions & 14 deletions services/account/apps/api/src/metadata.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@ export default async () => {
['../../../libs/common/src/types/dtos/wallet.login.request.dto']: await import(
'../../../libs/common/src/types/dtos/wallet.login.request.dto'
),
['../../../libs/common/src/types/dtos/accounts.response.dto']: await import(
'../../../libs/common/src/types/dtos/accounts.response.dto'
),
['@polkadot/types-codec/primitive/U32']: await import('@polkadot/types-codec/primitive/U32'),
['../../../libs/common/src/types/dtos/wallet.login.config.response.dto']: await import(
'../../../libs/common/src/types/dtos/wallet.login.config.response.dto'
),
['../../../libs/common/src/types/dtos/accounts.response.dto']: await import(
'../../../libs/common/src/types/dtos/accounts.response.dto'
),
['../../../libs/common/src/types/dtos/wallet.login.response.dto']: await import(
'../../../libs/common/src/types/dtos/wallet.login.response.dto'
),
Expand Down Expand Up @@ -91,6 +91,24 @@ export default async () => {
},
},
],
[
import('../../../libs/common/src/types/dtos/accounts.response.dto'),
{
HandleResponseDTO: {
base_handle: { required: true, type: () => String },
canonical_base: { required: true, type: () => String },
suffix: { required: true, type: () => Number },
},
AccountResponse: {
msaId: { required: true, type: () => String },
handle: {
required: false,
type: () => t['../../../libs/common/src/types/dtos/accounts.response.dto'].HandleResponseDTO,
},
},
MsaIdResponse: { msaId: { required: true, type: () => String } },
},
],
[
import('../../../libs/common/src/types/dtos/transaction.response.dto'),
{ TransactionResponse: { referenceId: { required: true, type: () => String } } },
Expand All @@ -105,15 +123,6 @@ export default async () => {
},
},
],
[
import('../../../libs/common/src/types/dtos/accounts.response.dto'),
{
AccountResponse: {
msaId: { required: true, type: () => String },
handle: { required: false, type: () => Object },
},
},
],
[
import('../../../libs/common/src/types/dtos/wallet.login.config.response.dto'),
{
Expand Down Expand Up @@ -148,7 +157,12 @@ export default async () => {
type: t['../../../libs/common/src/types/dtos/wallet.login.config.response.dto']
.WalletLoginConfigResponse,
},
getAccount: { type: t['../../../libs/common/src/types/dtos/accounts.response.dto'].AccountResponse },
getAccountForMsa: {
type: t['../../../libs/common/src/types/dtos/accounts.response.dto'].AccountResponse,
},
getAccountForPublicKey: {
type: t['../../../libs/common/src/types/dtos/accounts.response.dto'].AccountResponse,
},
postSignInWithFrequency: {
type: t['../../../libs/common/src/types/dtos/wallet.login.response.dto'].WalletLoginResponse,
},
Expand All @@ -175,7 +189,7 @@ export default async () => {
changeHandle: {
type: t['../../../libs/common/src/types/dtos/transaction.response.dto'].TransactionResponse,
},
getHandle: { type: Object },
getHandle: { type: t['../../../libs/common/src/types/dtos/accounts.response.dto'].HandleResponseDTO },
},
},
],
Expand Down
22 changes: 19 additions & 3 deletions services/account/apps/api/src/services/accounts.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { ConfigService } from '#lib/config/config.service';
import { EnqueueService } from '#lib/services/enqueue-request.service';
import { WalletLoginRequestDto, PublishSIWFSignupRequest } from '#lib/types/dtos/wallet.login.request.dto';
import { WalletLoginResponse } from '#lib/types/dtos/wallet.login.response.dto';
import { AccountResponse } from '#lib/types/dtos/accounts.response.dto';
import { AccountResponse, MsaIdResponse } from '#lib/types/dtos/accounts.response.dto';
import { WalletLoginConfigResponse } from '#lib/types/dtos/wallet.login.config.response.dto';

@Injectable()
Expand All @@ -21,7 +21,7 @@ export class AccountsService {
this.logger = new Logger(this.constructor.name);
}

async getAccount(msaId: string): Promise<AccountResponse> {
async getAccount(msaId: string): Promise<AccountResponse | null> {
try {
const isValidMsaId = await this.blockchainService.isValidMsaId(msaId);
if (isValidMsaId) {
Expand All @@ -33,13 +33,29 @@ export class AccountsService {
this.logger.log(`Failed to get handle for msaId: ${msaId}`);
return { msaId };
}
throw new Error(`Invalid msaId: ${msaId}`);
this.logger.log(`Invalid msaId: ${msaId}`);
return null;
} catch (e) {
this.logger.error(`Error during get account request: ${e}`);
throw new Error('Failed to get account');
}
}

async getMsaIdForPublicKey(publicKey: string): Promise<MsaIdResponse | null> {
try {
const msaId = await this.blockchainService.publicKeyToMsaId(publicKey);
if (msaId) {
this.logger.debug(`Found msaId: ${msaId} for public key: ${publicKey}`);
return { msaId };
}
this.logger.debug(`Did not find msaId for public key: ${publicKey}`);
return null;
} catch (e) {
this.logger.error(`Error during get msaId request: ${e}`);
throw new Error('Failed to get msaId');
}
}

async getSIWFConfig(): Promise<WalletLoginConfigResponse> {
let response: WalletLoginConfigResponse;
try {
Expand Down
Loading

0 comments on commit f3dc764

Please sign in to comment.