Skip to content

Commit

Permalink
feat: Add endpoint /accounts/{accountId}/proxy-info (#1387)
Browse files Browse the repository at this point in the history
* add AccountsProxyInfo controller to chains

* export ProxyInfo

* response type AccountsProxyInfo

* Logic for the controller and service

* exports

* add test

* docs

* update copyright

* docs nit

* one more copyroight

* Update docs/src/openapi-v1.yaml

Co-authored-by: Dominique <dominique@imodworks.io>

* Update docs

---------

Co-authored-by: Dominique <dominique@imodworks.io>
  • Loading branch information
TarikGul and Imod7 committed Feb 1, 2024
1 parent cc80227 commit 9addf07
Show file tree
Hide file tree
Showing 16 changed files with 286 additions and 1 deletion.
2 changes: 1 addition & 1 deletion docs/dist/app.bundle.js

Large diffs are not rendered by default.

64 changes: 64 additions & 0 deletions docs/src/openapi-v1.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,45 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/Error'
/accounts/{accountId}/proxy-info:
get:
tags:
- accounts
summary: Get proxy account information.
description: Returns information about a proxy account. This will include
delegated accounts and deposits held.
operationId: getProxyInfo
parameters:
- name: accountId
in: path
description: SS58 address of the account.
required: true
schema:
type: string
format: SS58
- name: at
in: query
description: Block at which to query proxy info for the
specified account.
required: false
schema:
type: string
description: Block height (as a non-negative integer) or hash
(as a hex string).
format: unsignedInteger or $hex
responses:
"200":
description: successfull operation
content:
application/json:
schema:
$ref: '#/components/schemas/AccountProxyInfo'
"400":
description: Invalid Address
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/accounts/{accountId}/staking-info:
get:
tags:
Expand Down Expand Up @@ -2444,6 +2483,31 @@ components:
description: An array of queried assets.
items:
$ref: '#/components/schemas/AssetsBalance'
AccountProxyInfo:
type: object
properties:
at:
$ref: '#/components/schemas/BlockIdentifiers'
delegatedAccounts:
type: array
items:
type: object
properties:
delegate:
type: string
description: Delegate address for the given proxy.
format: ss58
delay:
type: string
description: The announcement period required of the initial proxy. Will generally be zero.
format: unsignedInteger
proxyType:
type: string
description: The permissions allowed for this proxy account.
depositHeld:
type: string
format: unsignedInteger
description: The held deposit.
AccountStakingInfo:
type: object
properties:
Expand Down
1 change: 1 addition & 0 deletions src/chains-config/assetHubPolkadotControllers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export const assetHubPolkadotControllers: ControllerConfig = {
controllers: [
'AccountsAssets',
'AccountsBalanceInfo',
'AccountsProxyInfo',
'AccountsValidate',
'Blocks',
'BlocksExtrinsics',
Expand Down
1 change: 1 addition & 0 deletions src/chains-config/assetHubWestendControllers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export const assetHubWestendControllers: ControllerConfig = {
controllers: [
'AccountsAssets',
'AccountsBalanceInfo',
'AccountsProxyInfo',
'AccountsPoolAssets',
'AccountsValidate',
'Blocks',
Expand Down
1 change: 1 addition & 0 deletions src/chains-config/defaultControllers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ export const defaultControllers: ControllerConfig = {
controllers: [
'AccountsAssets',
'AccountsBalanceInfo',
'AccountsProxyInfo',
'AccountsStakingInfo',
'AccountsStakingPayouts',
'AccountsValidate',
Expand Down
1 change: 1 addition & 0 deletions src/chains-config/kusamaControllers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export const kusamaControllers: ControllerConfig = {
controllers: [
'AccountsBalanceInfo',
'AccountsConvert',
'AccountsProxyInfo',
'AccountsStakingInfo',
'AccountsStakingPayouts',
'AccountsValidate',
Expand Down
1 change: 1 addition & 0 deletions src/chains-config/polkadotControllers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export const polkadotControllers: ControllerConfig = {
controllers: [
'AccountsBalanceInfo',
'AccountsConvert',
'AccountsProxyInfo',
'AccountsStakingInfo',
'AccountsStakingPayouts',
'AccountsValidate',
Expand Down
1 change: 1 addition & 0 deletions src/chains-config/westendControllers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export const westendControllers: ControllerConfig = {
controllers: [
'AccountsBalanceInfo',
'AccountsConvert',
'AccountsProxyInfo',
'AccountsStakingInfo',
'AccountsStakingPayouts',
'AccountsValidate',
Expand Down
51 changes: 51 additions & 0 deletions src/controllers/accounts/AccountsProxyInfoController.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// Copyright 2017-2024 Parity Technologies (UK) Ltd.
// This file is part of Substrate API Sidecar.
//
// Substrate API Sidecar is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.

import { ApiPromise } from '@polkadot/api';
import { RequestHandler } from 'express';
import { IAddressParam } from 'src/types/requests';

import { validateAddress } from '../../middleware';
import { AccountsProxyInfoService } from '../../services';
import AbstractController from '../AbstractController';

export default class AccountsProxyInfoController extends AbstractController<AccountsProxyInfoService> {
constructor(api: ApiPromise) {
super(api, '/accounts/:address/proxy-info', new AccountsProxyInfoService(api));
this.initRoutes();
}

protected initRoutes(): void {
this.router.use(this.path, validateAddress);

this.safeMountAsyncGetHandlers([['', this.getAccountProxyInfo]]);
}

/**
* Get the latest account balance summary of `address`.
*
* @param req Express Request
* @param res Express Response
*/
private getAccountProxyInfo: RequestHandler<IAddressParam> = async (
{ params: { address }, query: { at } },
res,
): Promise<void> => {
const hash = await this.getHashFromAt(at);

AccountsProxyInfoController.sanitizedSend(res, await this.service.fetchAccountProxyInfo(hash, address));
};
}
1 change: 1 addition & 0 deletions src/controllers/accounts/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export { default as AccountsAssets } from './AccountsAssetsController';
export { default as AccountsBalanceInfo } from './AccountsBalanceInfoController';
export { default as AccountsConvert } from './AccountsConvertController';
export { default as AccountsPoolAssets } from './AccountsPoolAssetsController';
export { default as AccountsProxyInfo } from './AccountsProxyInfoController';
export { default as AccountsStakingInfo } from './AccountsStakingInfoController';
export { default as AccountsStakingPayouts } from './AccountsStakingPayoutsController';
export { default as AccountsValidate } from './AccountsValidateController';
Expand Down
2 changes: 2 additions & 0 deletions src/controllers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {
AccountsBalanceInfo,
AccountsConvert,
AccountsPoolAssets,
AccountsProxyInfo,
AccountsStakingInfo,
AccountsStakingPayouts,
AccountsValidate,
Expand Down Expand Up @@ -57,6 +58,7 @@ export const controllers = {
AccountsBalanceInfo,
AccountsConvert,
AccountsPoolAssets,
AccountsProxyInfo,
AccountsStakingInfo,
AccountsValidate,
AccountsVestingInfo,
Expand Down
90 changes: 90 additions & 0 deletions src/services/accounts/AccountsProxyInfoService.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
// Copyright 2017-2024 Parity Technologies (UK) Ltd.
// This file is part of Substrate API Sidecar.
//
// Substrate API Sidecar is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.

import { ApiPromise } from '@polkadot/api';
import { ApiDecoration } from '@polkadot/api/types';
import { Hash } from '@polkadot/types/interfaces';

import { sanitizeNumbers } from '../../sanitize/sanitizeNumbers';
import { polkadotMetadataRpcV1000001 } from '../../test-helpers/metadata/polkadotV1000001Metadata';
import { polkadotRegistryV1000001 } from '../../test-helpers/registries';
import { createApiWithAugmentations, TypeFactory } from '../../test-helpers/typeFactory';
import { blockHash789629, defaultMockApi } from '../test-helpers/mock';
import { AccountsProxyInfoService } from './AccountsProxyInfoService';

const factoryApi = createApiWithAugmentations(polkadotMetadataRpcV1000001);
const factory = new TypeFactory(factoryApi);
const proxies = () =>
Promise.resolve().then(() => {
const vec = factory.vecOf([
polkadotRegistryV1000001.createType('PalletProxyProxyDefinition', {
delegate: '12TzkPCrVfrZxupsdkt3vxZQS7Ajw3DVcpFpBH2PBDU4Uyja',
proxyType: 'Staking',
delay: '0',
}),
polkadotRegistryV1000001.createType('PalletProxyProxyDefinition', {
delegate: '14hS1sUjM1GRdYG3GthbncPecsAwcRUKKXd4YWXYFrXC8Qqr',
proxyType: 'Any',
delay: '0',
}),
]);

return [vec, polkadotRegistryV1000001.createType('u128', '1000000000')];
});

const historicApi = {
query: {
proxy: {
proxies,
},
},
} as unknown as ApiDecoration<'promise'>;

const mockApi = {
...defaultMockApi,
at: (_hash: Hash) => historicApi,
} as unknown as ApiPromise;

const accountsProxyInfoService = new AccountsProxyInfoService(mockApi);

describe('AccountsProxyInfoService', () => {
it('Should correctly query proxies', async () => {
const res = await accountsProxyInfoService.fetchAccountProxyInfo(
blockHash789629,
'12oMWhAvv3rRUU1etckbDipaF9orZpkgPeoPPCLY43gJZ3BJ',
);

expect(sanitizeNumbers(res)).toStrictEqual({
at: {
hash: '0x7b713de604a99857f6c25eacc115a4f28d2611a23d9ddff99ab0e4f1c17a8578',
height: '789629',
},
delegatedAccounts: [
{
delay: '0',
delegate: '12TzkPCrVfrZxupsdkt3vxZQS7Ajw3DVcpFpBH2PBDU4Uyja',
proxyType: 'Staking',
},
{
delay: '0',
delegate: '14hS1sUjM1GRdYG3GthbncPecsAwcRUKKXd4YWXYFrXC8Qqr',
proxyType: 'Any',
},
],
depositHeld: '1000000000',
});
});
});
43 changes: 43 additions & 0 deletions src/services/accounts/AccountsProxyInfoService.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// Copyright 2017-2024 Parity Technologies (UK) Ltd.
// This file is part of Substrate API Sidecar.
//
// Substrate API Sidecar is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.

import type { BlockHash } from '@polkadot/types/interfaces';

import type { AccountsProxyInfo } from '../../types/responses';
import { AbstractService } from '../AbstractService';

export class AccountsProxyInfoService extends AbstractService {
async fetchAccountProxyInfo(hash: BlockHash, address: string): Promise<AccountsProxyInfo> {
const { api } = this;
const historicApi = await api.at(hash);

const [{ number }, proxyInfo] = await Promise.all([
api.rpc.chain.getHeader(hash),
historicApi.query.proxy.proxies(address),
]);

const at = {
hash,
height: number.unwrap().toString(10),
};

return {
at,
delegatedAccounts: proxyInfo[0],
depositHeld: proxyInfo[1],
};
}
}
1 change: 1 addition & 0 deletions src/services/accounts/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export * from './AccountsAssetsService';
export * from './AccountsBalanceInfoService';
export * from './AccountsConvertService';
export * from './AccountsPoolAssetsService';
export * from './AccountsProxyInfoService';
export * from './AccountsStakingInfoService';
export * from './AccountsStakingPayoutsService';
export * from './AccountsValidateService';
Expand Down
26 changes: 26 additions & 0 deletions src/types/responses/AccountProxyInfo.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// Copyright 2017-2024 Parity Technologies (UK) Ltd.
// This file is part of Substrate API Sidecar.
//
// Substrate API Sidecar is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.

import type { u128, Vec } from '@polkadot/types';
import type { PalletProxyProxyDefinition } from '@polkadot/types/lookup';

import type { IAt } from './';

export interface AccountsProxyInfo {
at: IAt;
delegatedAccounts: Vec<PalletProxyProxyDefinition>;
depositHeld: u128;
}
1 change: 1 addition & 0 deletions src/types/responses/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export * from './AccountAssets';
export * from './AccountBalanceInfo';
export * from './AccountConvert';
export * from './AccountPoolAssets';
export * from './AccountProxyInfo';
export * from './AccountStakingInfo';
export * from './AccountStakingPayouts';
export * from './AccountVestingInfo';
Expand Down

0 comments on commit 9addf07

Please sign in to comment.