ghost-portal/packages/apps-config/src/api/specVersioned/equilibrium.ts
2021-01-25 12:39:07 +01:00

189 lines
6.4 KiB
TypeScript

// Copyright 2017-2021 @polkadot/apps-config authors & contributors
// SPDX-License-Identifier: Apache-2.0
import type { ApiInterfaceRx } from '@polkadot/api/types';
import type { Enum, Struct } from '@polkadot/types';
import type { Option } from '@polkadot/types/codec';
import type { AccountId, AccountIndex, AccountInfo, Address, Balance, BlockNumber, Index } from '@polkadot/types/interfaces';
import type { Observable } from '@polkadot/x-rxjs';
import { memo } from '@polkadot/api-derive/util/memo';
import { combineLatest, of } from '@polkadot/x-rxjs';
import { map, switchMap } from '@polkadot/x-rxjs/operators';
interface VestingInfo extends Struct {
readonly locked: Balance;
readonly perBlock: Balance;
readonly startingBlock: BlockNumber;
}
interface SignedBalance extends Enum {
readonly isPositive: boolean;
readonly asPositive: Balance;
readonly isNegative: boolean;
readonly asNegative: Balance;
}
export interface EQDeriveBalancesAll {
additional: []; // fix until vesting instances are supported in api-derive
freeBalance: Balance;
reservedBalance: Balance;
vestingLocked: Balance;
lockedBalance: Balance;
accountId: AccountId;
accountNonce: Index;
lockedBreakdown: unknown[];
}
type Result = [Balance, Balance, Balance, Index];
type RawResult = [
SignedBalance,
Option<Balance>,
Option<VestingInfo>,
AccountInfo
];
type EQDeriveBalancesAccountQuery = (
address: AccountIndex | AccountId | Address | string
) => Observable<{ accountNonce: Index; }>;
type EQDeriveBalancesAllQuery = (
address: AccountIndex | AccountId | Address | string
) => Observable<EQDeriveBalancesAll>;
export default {
derives: {
// TODO derive.democracy.locks
// TODO derice.staking.account
balances: {
account: (
// Compatibility with calc tx fee
instanceId: string,
api: ApiInterfaceRx
): EQDeriveBalancesAccountQuery =>
memo(
instanceId,
(address: AccountId | AccountIndex | Address | string) =>
api.derive.accounts.accountId(address).pipe(
switchMap(
(accountId): Observable<[AccountId, [Index]]> =>
accountId
? combineLatest([
of(accountId),
api
.queryMulti([
[api.query.system.account, accountId]
])
.pipe(
map((raw): [Index] => {
if (raw.length < 1) {
throw new Error('Data expected');
}
const data = raw as [AccountInfo];
return [data[0].nonce];
})
)
])
: of([
api.registry.createType('AccountId'),
[api.registry.createType('Index')]
])
),
map(([, [accountNonce]]) => ({ accountNonce }))
)
),
all: (
// Compatibility for account balance in explorer
instanceId: string,
api: ApiInterfaceRx
): EQDeriveBalancesAllQuery =>
memo(
instanceId,
(address: AccountIndex | AccountId | Address | string) =>
api.derive.accounts.accountId(address).pipe(
switchMap(
(accountId): Observable<[AccountId, Result]> =>
accountId
? combineLatest([
of(accountId),
api
.queryMulti([
[api.query.balances.account, [accountId, 'EQ']],
[api.query.eqVesting.vested, accountId],
[api.query.eqVesting.vesting, accountId],
[api.query.system.account, accountId]
])
.pipe(
map(
(raw): Result => {
if (raw.length < 4) {
throw new Error('4 members expected');
}
const res = raw as RawResult;
const freeBalance = res[0].asPositive;
let reservedBalance = api.registry.createType(
'Balance'
);
let vestingLocked = api.registry.createType(
'Balance'
);
if (res[1].isSome && res[2].isSome) {
const vested = res[1].unwrap();
const info = res[2].unwrap();
vestingLocked = info.locked;
reservedBalance = api.registry.createType(
'Balance',
vestingLocked.sub(vested)
);
}
return [
freeBalance,
reservedBalance,
vestingLocked,
res[3].nonce
];
}
)
)
])
: of([
api.registry.createType('AccountId'),
[
api.registry.createType('Balance'),
api.registry.createType('Balance'),
api.registry.createType('Balance'),
api.registry.createType('Index')
]
])
),
map(
([
accountId,
[freeBalance, reservedBalance, vestingLocked, accountNonce]
]): EQDeriveBalancesAll => ({
accountId,
accountNonce,
additional: [],
freeBalance,
lockedBalance: vestingLocked,
lockedBreakdown: [],
reservedBalance,
vestingLocked
})
)
)
)
}
}
};