Skip to content

Commit

Permalink
Merge branch 'develop'
Browse files Browse the repository at this point in the history
  • Loading branch information
wouterter committed Nov 10, 2023
2 parents 9782a3e + 5eb2345 commit 422aa06
Show file tree
Hide file tree
Showing 32 changed files with 2,505 additions and 1,500 deletions.
1,650 changes: 980 additions & 670 deletions package-lock.json

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions projects/polkascan-explorer/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion projects/polkascan-explorer/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@polkadapt/polkascan-explorer",
"version": "2.0.0",
"version": "2.0.1",
"license": "Apache-2.0",
"author": "Polkascan Foundation <info@polkascan.org>",
"description": "PolkADAPT plug-in to fetch data from the Polkascan Explorer API.",
Expand Down
2 changes: 1 addition & 1 deletion projects/polkascan-explorer/src/lib/polkascan-explorer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ export type Api = {
subscribeNewEventByAccount: (accountIdHex: string,
filters?: AccountEventsFilters) =>
Observable<types.AccountEvent>;
getExtrinsic: (blockNumber: number, eventIdx: number) =>
getExtrinsic: (blockNumberOrHash: number | string, extrinsicIdx?: number) =>
Observable<types.Extrinsic>;
getExtrinsics: (filters?: ExtrinsicsFilters, pageSize?: number) =>
Observable<types.Extrinsic[]>;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import {
createSubscriptionObservable,
generateObjectQuery,
generateSubscriptionQuery,
isBlockHash,
isHash,
isObject,
isPositiveNumber
} from './helpers';
Expand Down Expand Up @@ -56,7 +56,7 @@ export const getBlock = (adapter: Adapter) => {

const filters: string[] = [];

if (isBlockHash(hashOrNumber)) {
if (isHash(hashOrNumber)) {
filters.push(`hash: "${hashOrNumber}"`);
} else if (isPositiveNumber(hashOrNumber)) {
filters.push(`number: ${hashOrNumber}`);
Expand Down Expand Up @@ -90,15 +90,15 @@ const getBlocksFn = (adapter: Adapter, direction?: 'from' | 'until') =>
const filters: string[] = [];

if (direction === 'from') {
if (isBlockHash(hashOrNumber)) {
if (isHash(hashOrNumber)) {
filters.push(`hashFrom: "${hashOrNumber}"`);
} else if (isPositiveNumber(hashOrNumber)) {
filters.push(`numberGte: ${hashOrNumber}`);
} else {
throw new Error('[PolkascanExplorerAdapter] getBlocksFrom: Provide a block hash (string) or block number (number).');
}
} else if (direction === 'until') {
if (isBlockHash(hashOrNumber)) {
if (isHash(hashOrNumber)) {
filters.push(`hashUntil: "${hashOrNumber}"`);
} else if (isPositiveNumber(hashOrNumber)) {
filters.push(`numberLte: ${hashOrNumber}`);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import {
generateObjectQuery,
generateSubscriptionQuery,
isDate,
isDefined,
isDefined, isHash,
isNumber,
isObject,
isPositiveNumber,
Expand Down Expand Up @@ -85,25 +85,27 @@ export interface ExtrinsicsFilters {
const identifiers = ['blockNumber', 'extrinsicIdx'];

export const getExtrinsic = (adapter: Adapter) => {
const fn = (blockNumber: number, extrinsicIdx: number): Observable<types.Extrinsic> => {
const fn = (blockNumberOrHash: number | string, extrinsicIdx?: number): Observable<types.Extrinsic> => {
if (!adapter.socket) {
throw new Error('[PolkascanExplorerAdapter] Socket is not initialized!');
}

const filters: string[] = [];

if (!isDefined(blockNumber)) {
throw new Error('[PolkascanExplorerAdapter] getExtrinsic: Provide a block number (number).');
if (!isDefined(blockNumberOrHash)) {
throw new Error('[PolkascanExplorerAdapter] getExtrinsic: Provide a block number (number) or hash (string).');
}

if (!isDefined(extrinsicIdx)) {
throw new Error('[PolkascanExplorerAdapter] getExtrinsic: Provide an extrinsicIdx (number).');
}

if (isPositiveNumber(blockNumber)) {
filters.push(`blockNumber: ${blockNumber}`);
if (isPositiveNumber(blockNumberOrHash)) {
filters.push(`blockNumber: ${blockNumberOrHash}`);
} else if (isHash(blockNumberOrHash)) {
filters.push(`hash: "${blockNumberOrHash}"`);
} else {
throw new Error('[PolkascanExplorerAdapter] getExtrinsic: Provided block number must be a positive number.');
throw new Error('[PolkascanExplorerAdapter] getExtrinsic: Provided block number must be a positive number or a hash string.');
}

if (isPositiveNumber(extrinsicIdx)) {
Expand Down
2 changes: 1 addition & 1 deletion projects/polkascan-explorer/src/lib/web-socket/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import { map, Observable, ReplaySubject, share, take, tap } from 'rxjs';
import { Adapter } from '../polkascan-explorer';
import * as pst from '../polkascan-explorer.types';

export const isBlockHash = (hash: unknown): hash is string => isString(hash) && hash.startsWith('0x');
export const isHash = (hash: unknown): hash is string => isString(hash) && hash.startsWith('0x');


export const isPositiveNumber = (val: unknown): val is number => Number.isInteger(val) && (val as number) >= 0;
Expand Down
4 changes: 2 additions & 2 deletions projects/subsquid/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion projects/subsquid/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@polkadapt/subsquid",
"version": "1.0.2",
"version": "1.0.3",
"license": "Apache-2.0",
"author": "Polkascan Foundation <info@polkascan.org>",
"description": "PolkADAPT plug-in to fetch data from the Subsquid APIs.",
Expand Down
79 changes: 79 additions & 0 deletions projects/subsquid/src/lib/queries/account.functions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/*
* PolkADAPT
*
* Copyright 2020-2023 Polkascan Foundation (NL)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import { combineLatestWith, map, throwError } from 'rxjs';
import * as st from '../subsquid.types';
import { Adapter } from '../subsquid';
import { isString } from './helpers';

export type GSMainIdentityInput = {
id: string;
display: string;
}[];

export type GSMainIdentitySubInput = {
id: string;
name: string;
}[];

export const findAccountsByIdentity = (adapter: Adapter) => {
const fn = (searchTerm: string) => {
if (!isString(searchTerm)) {
return throwError(() => 'Provided identity search term must be a string.');
}

return adapter.queryGSMain<GSMainIdentityInput>(
'identities',
['id', 'display'],
{'display_containsInsensitive': searchTerm},
'display_ASC',
10
).pipe(
combineLatestWith(adapter.queryGSMain<GSMainIdentitySubInput>(
'identitySubs',
['id', 'name'],
{'name_containsInsensitive': searchTerm},
'name_ASC',
10
)),
map(([identities, identitySubs]) => {
const items: st.Account[] = [];
for (const identity of identities) {
items.push({
id: identity.id,
identity: {
display: identity.display
}
});
}
for (const sub of identitySubs) {
items.push({
id: sub.id,
identity: {
display: sub.name
}
});
}
items.sort((a, b) => a.identity.display.localeCompare(b.identity.display));
return items;
})
);
};
fn.identifiers = ['id'];
return fn;
};
55 changes: 16 additions & 39 deletions projects/subsquid/src/lib/queries/block.functions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,24 +20,15 @@ import { types } from '@polkadapt/core';
import { catchError, filter, map, merge, Observable, of, switchMap, take, tap, throwError, timer } from 'rxjs';
import * as st from '../subsquid.types';
import { Adapter, Where } from '../subsquid';
import { isBlockHash, isNumber, isObject } from './helpers';
import { isHash, isNumber, isObject } from './helpers';

export type ArchiveBlockInput = {
extrinsicsRoot: string;
hash: string;
export type GSExplorerBlockInput = {
height: number;
hash: string;
parentHash: string;
spec: {
specName: string;
specVersion: number;
};
stateRoot: string;
specVersion: number;
timestamp: string;
validator: string;
}[];

export type GSExplorerBlockInput = {
height: number;
extrinsicsCount: number;
callsCount: number;
eventsCount: number;
Expand All @@ -52,13 +43,14 @@ export const getBlocksBase = (
fromNumber?: string | number,
untilNumber?: string | number): Observable<types.Block[]> => {
const contentType = 'blocks';
const orderBy = 'id_DESC';
let orderBy: string | undefined = 'id_DESC';

let where: Where | undefined;
if (typeof hashOrNumber !== 'undefined') {
const whereKey = (typeof hashOrNumber === 'string' && hashOrNumber.startsWith('0x')) ? 'hash_eq' : 'height_eq';
where = {};
where[whereKey] = hashOrNumber;
orderBy = undefined;
}

if (typeof fromNumber !== 'undefined') {
Expand All @@ -72,40 +64,25 @@ export const getBlocksBase = (
}

return merge(
adapter.queryArchive<ArchiveBlockInput>(
adapter.queryGSExplorer<GSExplorerBlockInput>(
contentType,
['extrinsicsRoot', 'hash', 'height', 'parentHash', {spec: ['specName', 'specVersion']}, 'stateRoot', 'timestamp', 'validator'],
['height', 'hash', 'parentHash', 'specVersion', 'timestamp', 'validator', 'callsCount', 'eventsCount', 'extrinsicsCount'],
where,
orderBy,
pageSize
).pipe(
map(blocks => blocks.map<st.ArchiveBlockOutput>(block => ({
map(blocks => blocks.map<st.GSExplorerBlockOutput>(block => ({
// eslint-disable-next-line id-blacklist
number: block.height,
hash: block.hash,
parentHash: block.parentHash,
stateRoot: block.stateRoot,
extrinsicsRoot: block.extrinsicsRoot,
specVersion: block.specVersion,
datetime: block.timestamp,
authorAccountId: block.validator,
specName: block.spec.specName,
specVersion: block.spec.specVersion,
complete: 1
})))
),
adapter.queryGSExplorer<GSExplorerBlockInput>(
contentType,
['height', 'callsCount', 'eventsCount', 'extrinsicsCount'],
where,
orderBy,
pageSize
).pipe(
map(blocks => blocks.map<st.GSExplorerBlockOutput>(block => ({
// eslint-disable-next-line id-blacklist
number: block.height,
countCalls: block.callsCount,
countEvents: block.eventsCount,
countExtrinsics: block.extrinsicsCount
countExtrinsics: block.extrinsicsCount,
complete: 1
})))
)
);
Expand Down Expand Up @@ -140,7 +117,7 @@ export const getBlocksFrom = (adapter: Adapter) => {
const fn = (hashOrNumber: string | number, pageSize?: number) => {
if (isNumber(hashOrNumber)) {
return getBlocksBase(adapter, pageSize, undefined, hashOrNumber);
} else if (isBlockHash(hashOrNumber)) {
} else if (isHash(hashOrNumber)) {
// Find number for block hash;
return getBlocksBase(adapter, 1, hashOrNumber).pipe(
take(1),
Expand All @@ -166,7 +143,7 @@ export const getBlocksUntil = (adapter: Adapter) => {
const fn = (hashOrNumber: string | number, pageSize?: number) => {
if (isNumber(hashOrNumber)) {
return getBlocksBase(adapter, pageSize, undefined, undefined, hashOrNumber);
} else if (isBlockHash(hashOrNumber)) {
} else if (isHash(hashOrNumber)) {
return getBlocksBase(adapter, 1, hashOrNumber).pipe(
take(1),
map((blocks) => {
Expand Down Expand Up @@ -194,12 +171,12 @@ export const subscribeNewBlock = (adapter: Adapter) => {
const fn = () => timer(0, 6000).pipe(
switchMap(() =>
getBlocksBase(adapter, 1).pipe(
filter((blocks) => blocks && blocks[0] && (blocks[0].number as number) !== ignoreHeight),
filter((blocks) => blocks && blocks[0] && blocks[0].number !== ignoreHeight),
switchMap((blocks) => {
if (blocks.length === 1) {
const prevHeight = height;
const latestBlock = blocks[0];
const latestBlockNumber = latestBlock.number as number;
const latestBlockNumber = latestBlock.number;

if (prevHeight !== undefined && latestBlockNumber - prevHeight > 1) {
// Missed multiple blocks, retrieve and emit individually.
Expand Down
46 changes: 4 additions & 42 deletions projects/subsquid/src/lib/queries/chain.functions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,46 +16,8 @@
* limitations under the License.
*/

import { Adapter } from '../subsquid';
import { map, merge, Observable } from 'rxjs';
import { types } from '@polkadapt/core';
import { ArchiveChainInfoOutput, ExplorerChainInfoOutput } from '../subsquid.types';
import { Observable, throwError } from 'rxjs';


export type ExplorerChainInfoInput = {
name: string;
prefix: number;
tokens: {
decimals: string;
symbol: string;
}[];
};

export type ArchiveChainInfoInput = {
specName: string;
};

export const getChainProperties = (adapter: Adapter) =>
(): Observable<types.ChainProperties> =>
merge(
adapter.queryExplorer<ExplorerChainInfoInput>(
'chainInfo',
['name', 'prefix', {tokens: ['decimals', 'symbol']}]
).pipe(
map<ExplorerChainInfoInput, ExplorerChainInfoOutput>((chainInfo) => ({
chainSS58: chainInfo.prefix,
chainDecimals: chainInfo.tokens && chainInfo.tokens.map((token) => Number.parseInt(token.decimals, 10)) || [],
chainTokens: chainInfo.tokens && chainInfo.tokens.map((token) => token.symbol) || [],
name: chainInfo.name
}))),
adapter.queryArchive<ArchiveChainInfoInput>(
'metadata',
['specName'],
undefined,
'blockHeight_DESC',
1
).pipe(
map<ArchiveChainInfoInput, ArchiveChainInfoOutput>((metadata) => ({
specName: metadata.specName
})))
);
export const getChainProperties = () =>
(): Observable<any> =>
throwError(() => `Functionality for getChainProperties not implemented.`)
Loading

0 comments on commit 422aa06

Please sign in to comment.