Gens parachain (#9447)
* new eq balance * fix eq&gens balances * cleanup old types and methods; gens balances on account page * fix BigInt * add types-codec package to package.json --------- Co-authored-by: Alex D <pr0fedt@gmail.com>
This commit is contained in:
parent
19883c81a6
commit
7e343933b1
@ -38,6 +38,7 @@
|
||||
"@polkadot/api-derive": "^10.7.1",
|
||||
"@polkadot/networks": "^12.2.1",
|
||||
"@polkadot/types": "^10.7.1",
|
||||
"@polkadot/types-codec": "^10.7.1",
|
||||
"@polkadot/util": "^12.2.1",
|
||||
"@polkadot/wasm-util": "^7.2.1",
|
||||
"@polkadot/x-fetch": "^12.2.1",
|
||||
|
||||
@ -10,8 +10,8 @@ import mangata from './spec/mangata.js';
|
||||
import subspace from './spec/subspace.js';
|
||||
|
||||
const mapping: [OverrideBundleDefinition, string[]][] = [
|
||||
[equilibrium, ['Equilibrium']],
|
||||
[genshiro, ['Genshiro', 'Genshiro Rococo Testnet']],
|
||||
[equilibrium, ['Equilibrium', 'Equilibrium-parachain']],
|
||||
[genshiro, ['Genshiro', 'Gens-parachain']],
|
||||
[interbtc, ['interbtc-parachain', 'interbtc-standalone', 'interlay-parachain', 'kintsugi-parachain', 'testnet-kintsugi', 'testnet-interlay']],
|
||||
[subspace, ['subspace']],
|
||||
[mangata, ['mangata', 'mangata-parachain']]
|
||||
|
||||
@ -1,164 +1,108 @@
|
||||
// Copyright 2017-2023 @polkadot/apps-config authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import type { Observable } from 'rxjs';
|
||||
import type { ApiInterfaceRx, AugmentedQuery, RxResult } from '@polkadot/api/types';
|
||||
import type { AccountData, AccountId, AccountIndex, Address, Balance } from '@polkadot/types/interfaces';
|
||||
import type { Codec, OverrideBundleDefinition } from '@polkadot/types/types';
|
||||
import type { ApiInterfaceRx } from '@polkadot/api/types';
|
||||
import type { Enum } from '@polkadot/types';
|
||||
import type { AccountId, AccountIndex, Address, Balance } from '@polkadot/types/interfaces';
|
||||
import type { OverrideBundleDefinition } from '@polkadot/types/types';
|
||||
import type { Struct, u64, u128, Vec } from '@polkadot/types-codec';
|
||||
import type { ITuple } from '@polkadot/types-codec/types';
|
||||
|
||||
import eqDefs from '@equilab/definitions';
|
||||
import { map } from 'rxjs';
|
||||
import { map, of } from 'rxjs';
|
||||
|
||||
import { Enum } from '@polkadot/types';
|
||||
import { BN } from '@polkadot/util';
|
||||
import { memo } from '@polkadot/api-derive/util';
|
||||
import { U8aFixed } from '@polkadot/types-codec';
|
||||
|
||||
interface SignedBalance extends Enum {
|
||||
export interface SignedBalance extends Enum {
|
||||
readonly isPositive: boolean;
|
||||
readonly asPositive: Balance;
|
||||
readonly isNegative: boolean;
|
||||
readonly asNegative: Balance;
|
||||
}
|
||||
|
||||
interface Currency extends Enum {
|
||||
readonly isUnknown: boolean;
|
||||
readonly isUsd: boolean;
|
||||
readonly isEq: boolean;
|
||||
readonly isEth: boolean;
|
||||
readonly isBtc: boolean;
|
||||
readonly isEos: boolean;
|
||||
readonly isDot: boolean;
|
||||
}
|
||||
|
||||
type CommonBalanceMap = ApiInterfaceRx['query']['balances']['account'];
|
||||
|
||||
type EqBalanceDoubleMap<T> = AugmentedQuery<
|
||||
'rxjs',
|
||||
(key1: AccountIndex | AccountId | Address | string, key2: T | string) => Observable<SignedBalance>,
|
||||
[AccountId, Currency]
|
||||
>
|
||||
|
||||
const { equilibrium, equilibriumNext } = eqDefs;
|
||||
|
||||
export const u64FromCurrency = (currency: string): number => {
|
||||
export const u64FromCurrency = (currency: string): bigint => {
|
||||
const buf = Buffer.from(currency.toLowerCase());
|
||||
const size = buf.length;
|
||||
|
||||
return buf.reduce(
|
||||
(val, digit, i) => val + Math.pow(256, size - 1 - i) * digit,
|
||||
0
|
||||
);
|
||||
return buf.reduce((val, digit, i) => {
|
||||
const exp = BigInt(size - 1 - i);
|
||||
|
||||
return BigInt(val) + BigInt(256) ** exp * BigInt(digit);
|
||||
}, BigInt(0));
|
||||
};
|
||||
|
||||
const transformBalanceStorage = <T>(
|
||||
query: EqBalanceDoubleMap<T>,
|
||||
currency: string,
|
||||
transform: <SB extends Enum>(data: SB) => AccountData,
|
||||
currencyToAsset: (arg: string, api?: ApiInterfaceRx) => T,
|
||||
api?: ApiInterfaceRx
|
||||
): CommonBalanceMap => {
|
||||
const arg = currencyToAsset(currency, api);
|
||||
const TOKENS = ['eq'];
|
||||
|
||||
// HACK as we cannot properly transform queryMulti result, define AccountData getters on standard Enum
|
||||
if (!(Enum as { hacked?: boolean }).hacked) {
|
||||
(Enum as { hacked?: boolean }).hacked = true;
|
||||
interface EqPrimitivesBalanceAccountData extends Enum {
|
||||
readonly isV0: boolean;
|
||||
readonly asV0: {
|
||||
readonly lock: u128;
|
||||
readonly balance: Vec<ITuple<[u64, EqPrimitivesSignedBalance]>>;
|
||||
} & Struct;
|
||||
readonly type: 'V0';
|
||||
}
|
||||
|
||||
for (const prop of ['free', 'reserved', 'miscFrozen', 'feeFrozen'] as Array<keyof AccountData>) {
|
||||
Object.defineProperty(Enum.prototype, prop, {
|
||||
get () {
|
||||
const accData: AccountData = transform(this as Enum);
|
||||
interface EqPrimitivesSignedBalance extends Enum {
|
||||
readonly isPositive: boolean;
|
||||
readonly asPositive: u128;
|
||||
readonly isNegative: boolean;
|
||||
readonly asNegative: u128;
|
||||
readonly type: 'Positive' | 'Negative';
|
||||
}
|
||||
|
||||
return accData[prop];
|
||||
},
|
||||
set () {
|
||||
// Do nothing
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
export const createDerives = (tokens: string[]) => tokens.reduce((prev, token, i) => {
|
||||
const isNative = !i;
|
||||
|
||||
// Transform result if we call the func normally
|
||||
const boundFunction = (account: AccountIndex | AccountId | Address | string) =>
|
||||
query(account, arg).pipe(map(transform));
|
||||
return {
|
||||
...prev,
|
||||
|
||||
// Bind currency as second key for doubleMap for queryMulti
|
||||
const boundCreator = (account: AccountIndex | AccountId | Address | string) =>
|
||||
query.creator([account, arg]);
|
||||
[token]: { customAccount: (instanceId: string, api: ApiInterfaceRx) => {
|
||||
const { registry } = api;
|
||||
const asset = u64FromCurrency(token);
|
||||
|
||||
Object.assign(boundCreator, { ...query.creator });
|
||||
return memo(instanceId, (address: AccountIndex | AccountId | Address | string) => api.query.system.account(address).pipe(map((v) => {
|
||||
const data = (v as unknown as { data: EqPrimitivesBalanceAccountData }).data;
|
||||
|
||||
return Object.assign(boundFunction, { ...query, creator: boundCreator } as unknown as CommonBalanceMap);
|
||||
};
|
||||
const miscFrozen = isNative ? data.asV0.lock : registry.createType('u128', 0);
|
||||
const feeFrozen = miscFrozen;
|
||||
const reserved = registry.createType('u128', 0);
|
||||
|
||||
const signedBalancePredicate = (raw: Codec): raw is SignedBalance =>
|
||||
['asNegative', 'asPositive', 'isNegative', 'isPositive'].some((key) =>
|
||||
Object.prototype.hasOwnProperty.call(raw, key)
|
||||
);
|
||||
const entry = data.asV0.balance.find(([assetId]) => {
|
||||
return assetId.toBigInt() === asset;
|
||||
});
|
||||
|
||||
export const createCustomAccount = <A = string>(currency: string, currencyToAsset: (curr: string, api?: ApiInterfaceRx) => A, accountDataType = 'AccountData'):
|
||||
(instanceId: string, api: ApiInterfaceRx) => RxResult<(arg: string | Uint8Array | AccountId) => Observable<AccountData>> => (_instanceId: string, api: ApiInterfaceRx) => {
|
||||
const registry = api.registry;
|
||||
const balance = entry?.[1];
|
||||
|
||||
const transform = <SB extends Enum>(balance: SB): AccountData => {
|
||||
let free = registry.createType('Balance');
|
||||
const reserved = registry.createType('Balance');
|
||||
const miscFrozen = registry.createType('Balance');
|
||||
const feeFrozen = registry.createType('Balance');
|
||||
const free = balance?.isPositive
|
||||
? balance.asPositive
|
||||
: registry.createType('u128', 0);
|
||||
|
||||
if (signedBalancePredicate(balance)) {
|
||||
if (balance.isPositive) {
|
||||
free = registry.createType('Balance', balance.asPositive);
|
||||
} else if (balance.isNegative) {
|
||||
free = registry.createType('Balance', balance.asNegative.mul(new BN(-1)));
|
||||
}
|
||||
}
|
||||
return {
|
||||
feeFrozen, free, miscFrozen, reserved
|
||||
};
|
||||
})));
|
||||
},
|
||||
customLocks: (instanceId: string, api: ApiInterfaceRx) => {
|
||||
const { registry } = api;
|
||||
|
||||
return registry.createType(accountDataType as 'AccountData', { feeFrozen, free, miscFrozen, reserved });
|
||||
return memo(instanceId, (address: AccountIndex | AccountId | Address | string) => isNative
|
||||
? api.query.system.account(address).pipe(map((v) => {
|
||||
const data = (v as unknown as { data: EqPrimitivesBalanceAccountData }).data;
|
||||
|
||||
return [{
|
||||
amount: data.asV0.lock,
|
||||
id: new U8aFixed(registry),
|
||||
reasons: ''
|
||||
}];
|
||||
}))
|
||||
: of([]));
|
||||
} }
|
||||
};
|
||||
|
||||
return transformBalanceStorage(
|
||||
api.query.eqBalances.account as unknown as EqBalanceDoubleMap<A>,
|
||||
currency,
|
||||
transform,
|
||||
currencyToAsset,
|
||||
api
|
||||
);
|
||||
};
|
||||
}, {});
|
||||
|
||||
const definitions: OverrideBundleDefinition = {
|
||||
derives: {
|
||||
...equilibrium.instances.balances.reduce(
|
||||
(all, cur) => ({
|
||||
...all,
|
||||
[cur]: {
|
||||
customAccount: createCustomAccount(cur, (currency: string, api?: ApiInterfaceRx) => {
|
||||
let assetsEnabled = true;
|
||||
|
||||
try {
|
||||
api?.registry.createType('AssetIdInnerType' as any);
|
||||
} catch (_) {
|
||||
assetsEnabled = false;
|
||||
}
|
||||
|
||||
return assetsEnabled ? { 0: u64FromCurrency(currency) } : currency;
|
||||
})
|
||||
}
|
||||
}),
|
||||
{}
|
||||
)
|
||||
},
|
||||
|
||||
instances: equilibrium.instances,
|
||||
|
||||
types: [
|
||||
{
|
||||
minmax: [0, 264],
|
||||
types: equilibrium.types
|
||||
},
|
||||
{
|
||||
minmax: [265, undefined],
|
||||
types: equilibriumNext.types
|
||||
}
|
||||
]
|
||||
derives: createDerives(TOKENS),
|
||||
instances: { balances: TOKENS }
|
||||
};
|
||||
|
||||
export default definitions;
|
||||
|
||||
@ -3,34 +3,13 @@
|
||||
|
||||
import type { OverrideBundleDefinition } from '@polkadot/types/types';
|
||||
|
||||
import eqDefs from '@equilab/definitions';
|
||||
import { createDerives } from './equilibrium.js';
|
||||
|
||||
import { createCustomAccount, u64FromCurrency } from './equilibrium.js';
|
||||
|
||||
const { genshiro } = eqDefs;
|
||||
const TOKENS = ['gens'];
|
||||
|
||||
const definitions: OverrideBundleDefinition = {
|
||||
derives: {
|
||||
...genshiro.instances.balances.reduce(
|
||||
(all, cur) => ({
|
||||
...all,
|
||||
[cur]: {
|
||||
customAccount: createCustomAccount(cur, (currency: string) => ({ 0: u64FromCurrency(currency) }), 'CompatAccountData')
|
||||
}
|
||||
}),
|
||||
{}
|
||||
)
|
||||
},
|
||||
|
||||
instances: genshiro.instances,
|
||||
|
||||
types: [
|
||||
{
|
||||
// on all versions
|
||||
minmax: [0, undefined],
|
||||
types: genshiro.types
|
||||
}
|
||||
]
|
||||
derives: createDerives(TOKENS),
|
||||
instances: { balances: TOKENS }
|
||||
};
|
||||
|
||||
export default definitions;
|
||||
|
||||
@ -143,7 +143,6 @@ const spec: Record<string, OverrideBundleDefinition> = {
|
||||
'Darwinia PC2': pangolin,
|
||||
Equilibrium: equilibrium,
|
||||
Genshiro: genshiro,
|
||||
'Genshiro Rococo Testnet': genshiro,
|
||||
Pangolin: pangolin,
|
||||
Pangoro: pangoro,
|
||||
VLN: vln,
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -195,12 +195,11 @@ export const prodParasKusama: Omit<EndpointOption, 'teleport'>[] = [
|
||||
}
|
||||
},
|
||||
{
|
||||
homepage: 'https://genshiro.equilibrium.io',
|
||||
info: 'genshiro',
|
||||
isUnreachable: true,
|
||||
homepage: 'https://genshiro..io',
|
||||
info: 'Genshiro',
|
||||
paraId: 2024,
|
||||
providers: {
|
||||
Equilibrium: 'wss://node.genshiro.io'
|
||||
Genshiro: 'wss://node.ksm.genshiro.io'
|
||||
},
|
||||
text: 'Genshiro',
|
||||
ui: {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user