diff --git a/packages/apps-config/src/api/spec/index.ts b/packages/apps-config/src/api/spec/index.ts index e7d024a10b..83a721ecb8 100644 --- a/packages/apps-config/src/api/spec/index.ts +++ b/packages/apps-config/src/api/spec/index.ts @@ -198,7 +198,6 @@ const spec: Record = { nftmart, 'node-moonbeam': moonbeam, 'node-polkadex': polkadex, - 'node-template-spartan': subspace, 'nodle-chain': nodle, 'oak-testnet': oakTestnet, opal: uniqueWestend, @@ -226,6 +225,7 @@ const spec: Record = { subdao, subgame, subsocial, + subspace: subspace, 'substrate-contracts-node': substrateContractsNode, subzero: zero, ternoa, diff --git a/packages/apps-config/src/api/spec/subspace.ts b/packages/apps-config/src/api/spec/subspace.ts index d7cb89001b..3ef32401f4 100644 --- a/packages/apps-config/src/api/spec/subspace.ts +++ b/packages/apps-config/src/api/spec/subspace.ts @@ -1,111 +1,136 @@ // Copyright 2017-2021 @polkadot/apps-config authors & contributors // SPDX-License-Identifier: Apache-2.0 -import type { OverrideBundleDefinition } from '@polkadot/types/types'; - // structs need to be in order /* eslint-disable sort-keys */ +import type { Observable } from 'rxjs'; +import type { ApiInterfaceRx } from '@polkadot/api/types'; +import type { Bytes, Struct, U8aFixed, u64 } from '@polkadot/types'; +import type { OverrideBundleDefinition, Registry } from '@polkadot/types/types'; + +import { combineLatest, map } from 'rxjs'; + +import { bestNumber, bestNumberFinalized, bestNumberLag, getBlock, subscribeNewBlocks } from '@polkadot/api-derive/chain'; +import { memo } from '@polkadot/api-derive/util'; +import { Digest, Header } from '@polkadot/types/interfaces'; + +type FarmerPublicKey = U8aFixed + +interface HeaderExtended extends Header { + readonly author: FarmerPublicKey | undefined; +} + +interface Solution extends Struct { + readonly publicKey: FarmerPublicKey; + readonly nonce: u64; + readonly encoding: Bytes; + readonly signature: Bytes; + readonly tag: U8aFixed; +} + +interface SubPreDigest extends Struct { + readonly slot: u64; + readonly solution: Solution; +} + +function extractAuthor ( + digest: Digest, + api: ApiInterfaceRx +): FarmerPublicKey | undefined { + const preRuntimes = digest.logs.filter( + ({ isPreRuntime, type }) => isPreRuntime && type.toString() === 'SUB_' + ); + const { solution }: SubPreDigest = api.registry.createType( + 'SubPreDigest', + preRuntimes[0] + ); + + return solution.publicKey; +} + +function createHeaderExtended ( + registry: Registry, + header: Header, + api: ApiInterfaceRx +): HeaderExtended { + const HeaderBase = registry.createClass('Header'); + + class SubHeaderExtended extends HeaderBase implements HeaderExtended { + readonly #author?: FarmerPublicKey; + + constructor (registry: Registry, header: Header, api: ApiInterfaceRx) { + super(registry, header); + this.#author = extractAuthor(this.digest, api); + this.createdAtHash = header?.createdAtHash; + } + + public get author (): FarmerPublicKey | undefined { + return this.#author; + } + } + + return new SubHeaderExtended(registry, header, api); +} + +function subscribeNewHeads ( + instanceId: string, + api: ApiInterfaceRx +): () => Observable { + return memo( + instanceId, + (): Observable => + combineLatest([api.rpc.chain.subscribeNewHeads()]).pipe( + map(([header]): HeaderExtended => { + return createHeaderExtended(header.registry, header, api); + }) + ) + ); +} + +function getHeader ( + instanceId: string, + api: ApiInterfaceRx +): () => Observable { + return memo( + instanceId, + (): Observable => + combineLatest([api.rpc.chain.getHeader()]).pipe( + map(([header]): HeaderExtended => { + return createHeaderExtended(header.registry, header, api); + }) + ) + ); +} + const definitions: OverrideBundleDefinition = { + derives: { + chain: { + bestNumber, + bestNumberFinalized, + bestNumberLag, + getBlock, + getHeader, + subscribeNewBlocks, + subscribeNewHeads + } + }, types: [ { - // on all versions minmax: [0, undefined], types: { - PoCKind: '[u8; 16]', - RpcSolution: { - public_key: '[u8; 32]', - nonce: 'u64', - encoding: 'Vec', - signature: 'Vec', - tag: '[u8; 8]' - }, - ProposedProofOfSpaceResult: { - slot_number: 'Slot', - solution: 'Option', - secret_key: 'Vec' - }, - RpcNewSlotInfo: { - slot_number: 'Slot', - challenge: '[u8; 8]', - salt: '[u8; 8]', - next_salt: 'Option<[u8; 8]>', - solution_range: 'u64' - }, - PoCRandomness: '[u8; 32]', - FarmerSignature: 'Signature', - FarmerId: 'AccountId', - PoCBlockWeight: 'u32', - PoCNextEpochDescriptor: { - randomness: 'PoCRandomness' - }, - PoCNextConfigDescriptorV1: { - c: '(u64, u64)' - }, - PoCNextConfigDescriptor: { - _enum: { - V0: 'Null', - V1: 'PoCNextConfigDescriptorV1' - } - }, - SolutionRangeDescriptor: { - solution_range: 'u64' - }, - SaltDescriptor: { - salt: 'u64' - }, - NextSolutionRangeDescriptor: { - solution_range: 'u64' - }, - NextSaltDescriptor: { - salt: 'u64' - }, - PoCEpochConfiguration: { - c: '(u64, u64)' - }, - ConsensusLog: { - _enum: { - Phantom: 'Null', - NextEpochData: 'PoCNextEpochDescriptor', - NextConfigData: 'PoCNextConfigDescriptor', - SolutionRangeData: 'SolutionRangeDescriptor', - SaltData: 'SaltDescriptor', - NextSolutionRangeData: 'NextSolutionRangeDescriptor', - NextSaltData: 'NextSaltDescriptor' - } - }, + FarmerPublicKey: '[u8; 32]', Solution: { - public_key: 'FarmerId', + publicKey: 'FarmerPublicKey', nonce: 'u64', encoding: 'Vec', signature: 'Vec', tag: '[u8; 8]' }, - PreDigest: { - slot: 'Slot', + SubPreDigest: { + slot: 'u64', solution: 'Solution' - }, - EquivocationProof: { - offender: 'FarmerId', - slot: 'Slot', - first_header: 'Header', - second_header: 'Header' - }, - PoCEquivocationOffence: { - slot: 'Slot', - offender: 'FarmerId' - }, - PoCGenesisConfiguration: { - slot_duration: 'u64', - epoch_length: 'u64', - c: '(u64, u64)', - randomness: 'PoCRandomness' - }, - Kind: 'PoCKind', - Randomness: 'PoCRandomness', - NextEpochDescriptor: 'PoCNextEpochDescriptor', - NextConfigDescriptorV1: 'PoCNextConfigDescriptorV1', - NextConfigDescriptor: 'PoCNextConfigDescriptor' + } } } ] diff --git a/packages/apps-config/src/endpoints/testing.ts b/packages/apps-config/src/endpoints/testing.ts index 3414c55c48..96bbf56d40 100644 --- a/packages/apps-config/src/endpoints/testing.ts +++ b/packages/apps-config/src/endpoints/testing.ts @@ -409,13 +409,6 @@ export function createTesting (t: TFunction, firstOnly: boolean, withSort: boole Soramitsu: 'wss://ws.stage.sora2.soramitsu.co.jp' } }, - { - info: 'spartan-testnet', - text: t('rpc.test.subspace', 'Spartan testnet', { ns: 'apps-config' }), - providers: { - 'Subspace Network': 'wss://dev-rpc.subspace.network' - } - }, { info: 'subgame', text: t('rpc.test.subgame', 'SubGame Staging', { ns: 'apps-config' }), @@ -423,6 +416,13 @@ export function createTesting (t: TFunction, firstOnly: boolean, withSort: boole SubGame: 'wss://staging.subgame.org' } }, + { + info: 'subspace', + text: t('rpc.test.subspace', 'Subspace Testnet', { ns: 'apps-config' }), + providers: { + 'Subspace Network': 'wss://test-rpc.subspace.network' + } + }, { info: 'ternoa-testnet', text: t('rpc.test.ternoa-testnet', 'Ternoa Testnet', { ns: 'apps-config' }), diff --git a/packages/apps-config/src/ui/colors.ts b/packages/apps-config/src/ui/colors.ts index a2bd2e30d7..0f7edab459 100644 --- a/packages/apps-config/src/ui/colors.ts +++ b/packages/apps-config/src/ui/colors.ts @@ -152,7 +152,7 @@ const nodeSora = '#2D2926'; const nodeStafi = '#00F3AB'; const nodeSubDAO = 'linear-gradient(50deg, #F20092 0%, #FF4D5D 100%)'; const nodeSubsocial = '#b9018c'; -const nodeSubspace = 'linear-gradient(to left, rgba(32,90,172,1) 0%, rgba(26,72,138,1) 50%, rgba(13,36,69,1) 100%)'; +const nodeSubspace = '#562b8e'; const nodeTernoa = '#d622ff'; const nodeUniarts = chainUniarts; const nodeUnique = chainUnique; @@ -288,7 +288,6 @@ export const chainColors: Record = Object.entries({ sherpax: chainChainx, Shiden: chainShiden, Spanner: chainSpanner, - 'Spartan testnet': nodeSubspace, Standard: chainStandard, 'Standard Kusama Parachain': chainUnorthodox, Statemine: specStatemine, @@ -301,6 +300,7 @@ export const chainColors: Record = Object.entries({ 'SubGame Gamma': nodeSubGame, 'SubGame Staging': nodeSubGame, 'Subsocial PC1': chainSubsocial, + 'Subspace Testnet': nodeSubspace, Tick: chainRoccoTick, Track: chainRoccoTrack, Trick: chainRoccoTrick, @@ -379,7 +379,6 @@ export const nodeColors = Object.entries({ 'Riochain Staging': nodeRiochain, 'Shiden Collator': chainShiden, SORA: nodeSora, - 'Spartan testnet': nodeSubspace, 'Stafi node': nodeStafi, 'Statemine Collator': specStatemint, 'Statemint Collator': specStatemint, @@ -388,6 +387,7 @@ export const nodeColors = Object.entries({ 'SubGame Gamma': nodeSubGame, 'SubGame Staging': nodeSubGame, 'subsocial node': nodeSubsocial, + 'Subspace Testnet': nodeSubspace, 'subzero node': nodeZero, 'Ternoa Node': nodeTernoa, 'uni arts node': nodeUniarts, diff --git a/packages/apps-config/src/ui/logos/index.ts b/packages/apps-config/src/ui/logos/index.ts index c1ead4f5b2..694a9a4135 100644 --- a/packages/apps-config/src/ui/logos/index.ts +++ b/packages/apps-config/src/ui/logos/index.ts @@ -251,12 +251,8 @@ export const chainLogos = Object.entries({ Shiden: chainShiden, SingLavender: nodeSingLavender, Spanner: chainSpanner, - 'Spartan Testnet': nodeSubspace, - Standard: chainStandard, - 'Standard Kusama Parachain': chainUnorthodox, Statemine: nodeStatemine, 'Statemine Test': nodeStatemine, - Statemint: nodeStatemine, 'Statemint Test': nodeStatemine, 'Steam PC': nodeEave, 'SubDAO PC1': nodeSubDAO, @@ -265,6 +261,7 @@ export const chainLogos = Object.entries({ 'SubGame Staging': nodeSubGame, Subsocial: nodeSubsocial, 'Subsocial PC': nodeSubsocial, + subspace: nodeSubspace, Tick: chainRococoTick, Track: chainRococoTrack, Trick: chainRococoTrick, @@ -401,7 +398,6 @@ export const nodeLogos = Object.entries({ 'Shiden Collator': chainShiden, 'SingLavender Parachain Collator': nodeSingLavender, SORA: nodeSora, - 'Spartan Testnet': nodeSubspace, Stafi: nodeStafi, 'Stafi Node': nodeStafi, 'Statemine Collator': nodeStatemine, @@ -413,6 +409,7 @@ export const nodeLogos = Object.entries({ 'Subsocial Node': nodeSubsocial, 'Subsocial PC': nodeSubsocial, 'subsocial-node': nodeSubsocial, + subspace: nodeSubspace, 'substrate-contracts-node': nodeSubstrateContractsNode, 'substrate-node': nodeSubstrate, 'subzero node': nodeZero, @@ -609,7 +606,6 @@ export const namedLogos: Record = { snakenet: chainSnakenet, 'sora-substrate': nodeSora, spanner: chainSpanner, - 'spartan-testnet': nodeSubspace, stafi: nodeStafi, statemine: nodeStatemine, statemint: nodeStatemine, @@ -617,6 +613,7 @@ export const namedLogos: Record = { 'SubGame Gamma': nodeSubGame, 'SubGame Staging': nodeSubGame, subsocial: nodeSubsocial, + subspace: nodeSubspace, substrate: nodeSubstrate, substrateContractsNode: nodeSubstrateContractsNode, 'ternoa-testnet': nodeTernoa, diff --git a/packages/apps-config/src/ui/logos/nodes/subspace.png b/packages/apps-config/src/ui/logos/nodes/subspace.png index 3d1be15bd6..5d16fe18d8 100644 Binary files a/packages/apps-config/src/ui/logos/nodes/subspace.png and b/packages/apps-config/src/ui/logos/nodes/subspace.png differ diff --git a/packages/apps/public/locales/en/apps-config.json b/packages/apps/public/locales/en/apps-config.json index 5e8cab4350..5471917bbd 100644 --- a/packages/apps/public/locales/en/apps-config.json +++ b/packages/apps/public/locales/en/apps-config.json @@ -178,7 +178,7 @@ "rpc.test.snowbridge": "Snowbridge", "rpc.test.sora-substrate-staging": "SORA-staging", "rpc.test.subgame": "SubGame Staging", - "rpc.test.subspace": "Spartan testnet", + "rpc.test.subspace": "Subspace Testnet", "rpc.test.ternoa-testnet": "Ternoa Testnet", "rpc.test.turbulence": "Turbulence", "rpc.test.uniarts": "UniArts", @@ -203,4 +203,4 @@ "ss58.default": "Default for the connected node", "testnet.kylin-node.co.uk": "Kylin Testnet", "westend-opal.unique.network": "OPAL by UNIQUE" -} \ No newline at end of file +}