Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Milestone 3 support #12

Merged
merged 28 commits into from
Sep 6, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
91817b8
stellar indexer
guplersaxanoid Jul 28, 2023
442d6a5
bug fixes
guplersaxanoid Aug 1, 2023
7513c93
add tests
guplersaxanoid Aug 1, 2023
06551bc
wrap blocks, txs, operations and effects
guplersaxanoid Aug 1, 2023
7d6e781
add generic types for operation and effect
guplersaxanoid Aug 4, 2023
01cba37
rebase
guplersaxanoid Aug 4, 2023
e752a96
change soroban names to stellar
guplersaxanoid Aug 8, 2023
4f66398
rebase
guplersaxanoid Aug 8, 2023
7a85134
delete utils/stellar.ts
guplersaxanoid Aug 8, 2023
a3c1c71
add soroban event handlers and fitlers
guplersaxanoid Aug 16, 2023
cbfbbaf
add tests for event filter and sorban server
guplersaxanoid Aug 16, 2023
1f2b72d
match events to tx with application order
guplersaxanoid Aug 16, 2023
af0abff
code cleanup
guplersaxanoid Aug 17, 2023
8c45efa
rebase with milestone-2
guplersaxanoid Aug 23, 2023
7f48f08
add tests for all types of handler
guplersaxanoid Aug 23, 2023
ffab3ea
make soroban endpoint mandatory only if event handler is present
guplersaxanoid Aug 23, 2023
d1240eb
update dictionary query to handle block and event filters
guplersaxanoid Aug 23, 2023
908b718
add soroban sdk version to meta service
guplersaxanoid Aug 23, 2023
1910fd6
fetch in parallel
guplersaxanoid Aug 23, 2023
53c959f
fetch events only once for a sequence
guplersaxanoid Aug 23, 2023
051338b
code cleanup
guplersaxanoid Aug 28, 2023
4249a25
add soroban transaction handler
guplersaxanoid Aug 28, 2023
807ed39
code cleanup
guplersaxanoid Sep 4, 2023
3e7c91c
check templates for event handlers
guplersaxanoid Sep 4, 2023
6789ef9
fix test
guplersaxanoid Sep 4, 2023
a88e8d9
fetch operations and effects once per block
guplersaxanoid Sep 6, 2023
82ce246
fetch events once per blocks
guplersaxanoid Sep 6, 2023
08975f7
handle pagination for tx, operations and effects
guplersaxanoid Sep 6, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion packages/common-stellar/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@
"@subql/types-stellar": "workspace:*",
"js-yaml": "^4.1.0",
"pino": "^6.13.3",
"reflect-metadata": "^0.1.13"
"reflect-metadata": "^0.1.13",
"stellar-sdk": "^10.4.1"
},
"peerDependencies": {
"class-transformer": "*",
Expand Down
115 changes: 112 additions & 3 deletions packages/common-stellar/src/project/models.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import {
StellarHandlerKind,
StellarDatasourceKind,
StellarEventFilter,
SorobanEventFilter,
SubqlCustomHandler,
SubqlMapping,
SubqlHandler,
Expand All @@ -14,13 +14,112 @@
SubqlCustomDatasource,
FileReference,
CustomDataSourceAsset,
StellarBlockFilter,
StellarTransactionFilter,
StellarOperationFilter,
StellarEffectFilter,
SubqlBlockHandler,
SubqlTransactionHandler,
SubqlOperationHandler,
SubqlEffectHandler,
SubqlEventHandler,
SubqlSorobanTransactionHandler,
} from '@subql/types-stellar';
import {plainToClass, Transform, Type} from 'class-transformer';
import {IsArray, IsEnum, IsInt, IsOptional, IsString, IsObject, ValidateNested} from 'class-validator';
import {Horizon} from 'stellar-sdk';
import {SubqlStellarProcessorOptions} from './types';

export class EventFilter implements StellarEventFilter {
export class BlockFilter implements StellarBlockFilter {
@IsOptional()
@IsInt()
modulo?: number;
@IsOptional()
@IsString()
timestamp?: string;
}
stwiname marked this conversation as resolved.
Show resolved Hide resolved

export class TransactionFilter implements StellarTransactionFilter {
@IsOptional()
@IsString()
account?: string;
}

export class OperationFilter implements StellarOperationFilter {
@IsOptional()
type: Horizon.OperationResponseType;

@IsOptional()
@IsString()
source_account?: string;
}

export class EffectFilter implements StellarEffectFilter {
@IsOptional()
@IsString()
type?: string;

@IsOptional()
@IsString()
account?: string;
}

export class BlockHandler implements SubqlBlockHandler {
@IsObject()
@IsOptional()
@Type(() => BlockFilter)
filter?: BlockFilter;
@IsEnum(StellarHandlerKind, {groups: [StellarHandlerKind.Block]})
kind: StellarHandlerKind.Block;
@IsString()
handler: string;
}

export class TransactionHandler implements SubqlTransactionHandler {
@IsObject()
@IsOptional()
@Type(() => TransactionFilter)
filter?: TransactionFilter;
@IsEnum(StellarHandlerKind, {groups: [StellarHandlerKind.Transaction]})
kind: StellarHandlerKind.Transaction;
@IsString()
handler: string;
}

export class SorobanTransactionHandler implements SubqlSorobanTransactionHandler {
@IsObject()
@IsOptional()
@Type(() => TransactionFilter)
filter?: TransactionFilter;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are there not more fields to filter by? Contract address?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that information (contract / to address) is available at operation level and it's only applicable for few kinds of operations, and it's under different field name for each type.

@IsEnum(StellarHandlerKind, {groups: [StellarHandlerKind.SorobanTransaction]})
kind: StellarHandlerKind.SorobanTransaction;
@IsString()
handler: string;
}

export class OperationHandler implements SubqlOperationHandler {
@IsObject()
@IsOptional()
@Type(() => OperationFilter)
filter?: OperationFilter;
@IsEnum(StellarHandlerKind, {groups: [StellarHandlerKind.Operation]})
kind: StellarHandlerKind.Operation;
@IsString()
handler: string;
}

export class EffectHandler implements SubqlEffectHandler {
@IsObject()
@IsOptional()
@Type(() => EffectFilter)
filter?: EffectFilter;
@IsEnum(StellarHandlerKind, {groups: [StellarHandlerKind.Effects]})
kind: StellarHandlerKind.Effects;
@IsString()
handler: string;
}

export class EventFilter implements SorobanEventFilter {
@IsOptional()
@IsString()
contractId?: string;
Expand All @@ -34,7 +133,7 @@
@IsOptional()
@ValidateNested()
@Type(() => EventFilter)
filter?: StellarEventFilter;
filter?: SorobanEventFilter;
@IsEnum(StellarHandlerKind, {groups: [StellarHandlerKind.Event]})
kind: StellarHandlerKind.Event;
@IsString()
Expand All @@ -56,10 +155,20 @@
const handlers: SubqlHandler[] = params.value;
return handlers.map((handler) => {
switch (handler.kind) {
case StellarHandlerKind.Block:
return plainToClass(BlockHandler, handler);
case StellarHandlerKind.Transaction:
return plainToClass(TransactionHandler, handler);
case StellarHandlerKind.SorobanTransaction:
return plainToClass(SorobanTransactionHandler, handler);
case StellarHandlerKind.Operation:
return plainToClass(OperationHandler, handler);
case StellarHandlerKind.Effects:
return plainToClass(EffectHandler, handler);
case StellarHandlerKind.Event:
return plainToClass(EventHandler, handler);
default:
throw new Error(`handler ${(handler as any).kind} not supported`);

Check warning on line 171 in packages/common-stellar/src/project/models.ts

View workflow job for this annotation

GitHub Actions / code-style

Unexpected any. Specify a different type
}
});
})
Expand Down
32 changes: 31 additions & 1 deletion packages/common-stellar/src/project/project.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,43 @@ describe('project.yaml', () => {
expect(() => loadStellarProjectManifest(path.join(projectsDir, 'project_1.0.0.yaml'))).not.toThrow();
});

it('get v1.0.0 deployment mapping filter', () => {
it('get v1.0.0 deployment mapping filter - transaction', () => {
const manifestVersioned = loadStellarProjectManifest(path.join(projectsDir, 'project_1.0.0.yaml'));

const deployment = manifestVersioned.asV1_0_0.deployment;
const filter = deployment.dataSources[0].mapping.handlers[0].filter;
const deploymentString = manifestVersioned.toDeployment();
expect(filter).not.toBeNull();
expect(deploymentString).toContain('account');
});

it('get v1.0.0 deployment mapping filter - operation', () => {
const manifestVersioned = loadStellarProjectManifest(path.join(projectsDir, 'project_1.0.0.yaml'));

const deployment = manifestVersioned.asV1_0_0.deployment;
const filter = deployment.dataSources[0].mapping.handlers[1].filter;
const deploymentString = manifestVersioned.toDeployment();
expect(filter).not.toBeNull();
expect(deploymentString).toContain('account_merge');
});

it('get v1.0.0 deployment mapping filter - effect', () => {
const manifestVersioned = loadStellarProjectManifest(path.join(projectsDir, 'project_1.0.0.yaml'));

const deployment = manifestVersioned.asV1_0_0.deployment;
const filter = deployment.dataSources[0].mapping.handlers[2].filter;
const deploymentString = manifestVersioned.toDeployment();
expect(filter).not.toBeNull();
expect(deploymentString).toContain('account_credited');
});

it('get v1.0.0 deployment mapping filter - events', () => {
const manifestVersioned = loadStellarProjectManifest(path.join(projectsDir, 'project_1.0.0.yaml'));

const deployment = manifestVersioned.asV1_0_0.deployment;
const filter = deployment.dataSources[0].mapping.handlers[3].filter;
const deploymentString = manifestVersioned.toDeployment();
expect(filter).not.toBeNull();
expect(deploymentString).toContain('COUNTER');
});

Expand Down
6 changes: 5 additions & 1 deletion packages/common-stellar/src/project/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,10 @@ export {
StellarHandlerKind,
SubqlDatasource as SubqlStellarDataSource,
SubqlCustomDatasource as SubqlStellarCustomDataSource,
StellarEventFilter,
StellarBlockFilter,
StellarTransactionFilter,
StellarOperationFilter,
StellarEffectFilter,
SubqlDatasourceProcessor,
SubqlHandlerFilter,
StellarDatasourceKind,
Expand All @@ -25,4 +28,5 @@ export type IStellarProjectManifest = IProjectManifest<SubqlDatasource>;
export interface StellarProjectNetworkConfig extends ProjectNetworkConfig {
genesisHash?: string;
chainId?: string;
soroban: string;
}
30 changes: 30 additions & 0 deletions packages/common-stellar/src/project/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,36 @@ import {
SubqlRuntimeDatasource,
} from '@subql/types-stellar';

export function isBlockHandlerProcessor<B>(
hp: SecondLayerHandlerProcessor<StellarHandlerKind, unknown, unknown>
): hp is SecondLayerHandlerProcessor<StellarHandlerKind.Block, unknown, B> {
return hp.baseHandlerKind === StellarHandlerKind.Block;
}

export function isTransactionHandlerProcessor<T>(
hp: SecondLayerHandlerProcessor<StellarHandlerKind, unknown, unknown>
): hp is SecondLayerHandlerProcessor<StellarHandlerKind.Transaction, unknown, T> {
return hp.baseHandlerKind === StellarHandlerKind.Transaction;
}

export function isSorobanTransactionHandlerProcessor<T>(
hp: SecondLayerHandlerProcessor<StellarHandlerKind, unknown, unknown>
): hp is SecondLayerHandlerProcessor<StellarHandlerKind.SorobanTransaction, unknown, T> {
return hp.baseHandlerKind === StellarHandlerKind.SorobanTransaction;
}

export function isOperationHandlerProcessor<O>(
hp: SecondLayerHandlerProcessor<StellarHandlerKind, unknown, unknown>
): hp is SecondLayerHandlerProcessor<StellarHandlerKind.Operation, unknown, O> {
return hp.baseHandlerKind === StellarHandlerKind.Operation;
}

export function isEffectHandlerProcessor<E>(
hp: SecondLayerHandlerProcessor<StellarHandlerKind, unknown, unknown>
): hp is SecondLayerHandlerProcessor<StellarHandlerKind.Effects, unknown, E> {
return hp.baseHandlerKind === StellarHandlerKind.Effects;
}

export function isEventHandlerProcessor<E>(
hp: SecondLayerHandlerProcessor<StellarHandlerKind, unknown, unknown>
): hp is SecondLayerHandlerProcessor<StellarHandlerKind.Event, unknown, E> {
Expand Down
3 changes: 3 additions & 0 deletions packages/common-stellar/src/project/versioned/v1_0_0/model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@

export class StellarCustomDataSourceImpl<
K extends string = string,
M extends BaseMapping<any, any> = BaseMapping<Record<string, unknown>, any>

Check warning on line 57 in packages/common-stellar/src/project/versioned/v1_0_0/model.ts

View workflow job for this annotation

GitHub Actions / code-style

Unexpected any. Specify a different type

Check warning on line 57 in packages/common-stellar/src/project/versioned/v1_0_0/model.ts

View workflow job for this annotation

GitHub Actions / code-style

Unexpected any. Specify a different type

Check warning on line 57 in packages/common-stellar/src/project/versioned/v1_0_0/model.ts

View workflow job for this annotation

GitHub Actions / code-style

Unexpected any. Specify a different type
>
extends CustomDataSourceBase<K, M>
implements SubqlCustomDatasource<K, M>
Expand Down Expand Up @@ -105,6 +105,9 @@
endpoint?: string | string[];
@IsString()
@IsOptional()
soroban?: string;
@IsString()
@IsOptional()
dictionary?: string;
}

Expand Down
16 changes: 15 additions & 1 deletion packages/common-stellar/test/project_1.0.0.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,22 @@ dataSources:
mapping:
file: './dist/index.js'
handlers:
- handler: handleTransaction
kind: stellar/TransactionHandler
filter:
account: 'GAKNXHJ5PCZYFIBNBWB4RCQHH6GDEO7Z334N74BOQUQCHKOURQEPMXCH'
- handler: handleOperation
kind: stellar/OperationHandler
guplersaxanoid marked this conversation as resolved.
Show resolved Hide resolved
filter:
source_account: 'GAKNXHJ5PCZYFIBNBWB4RCQHH6GDEO7Z334N74BOQUQCHKOURQEPMXCH'
type: 'account_merge'
- handler: handleEffect
kind: stellar/EffectHandler
filter:
type: 'account_credited'
account: 'GAKNXHJ5PCZYFIBNBWB4RCQHH6GDEO7Z334N74BOQUQCHKOURQEPMXCH'
- handler: handleEvent
kind: stellar/EventHandler
kind: soroban/EventHandler
filter:
contractId: '34799b3411940249e73d21def8eb2c2b56b285ab8d1ca76d6780ec10a0e8f02e'
topics:
Expand Down
1 change: 1 addition & 0 deletions packages/node/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
"rimraf": "^3.0.2",
"rxjs": "^7.5.2",
"soroban-client": "^0.9.1",
"stellar-sdk": "^10.4.1",
"yargs": "^16.2.0"
},
"peerDependencies": {
Expand Down
31 changes: 30 additions & 1 deletion packages/node/src/configure/SubqueryProject.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
SubqlStellarDataSource,
ProjectManifestV1_0_0Impl,
isCustomDs,
StellarHandlerKind,
isRuntimeDs,
} from '@subql/common-stellar';
import { getProjectRoot, updateDataSourcesV1_0_0 } from '@subql/node-core';
import { buildSchemaFromString } from '@subql/utils';
Expand Down Expand Up @@ -71,7 +73,7 @@
}
}

function processChainId(network: any): NetworkConfig {

Check warning on line 76 in packages/node/src/configure/SubqueryProject.ts

View workflow job for this annotation

GitHub Actions / code-style

Unexpected any. Specify a different type
if (network.chainId && network.genesisHash) {
throw new Error('Please only provide one of chainId and genesisHash');
} else if (network.genesisHash && !network.chainId) {
Expand Down Expand Up @@ -103,7 +105,7 @@

if (!network.endpoint) {
throw new Error(
`Network endpoint must be provided for network. chainId="${network.chainId}"`,
`Stellar network endpoint must be provided for network. chainId="${network.chainId}"`,
);
}

Expand All @@ -126,6 +128,18 @@

const templates = await loadProjectTemplates(projectManifest, root, reader);

if (
dsHasSorobanEventHandler([
...dataSources,
...(templates as SubqlProjectDs[]),
]) &&
!network.soroban
) {
throw new Error(
`Soroban network endpoint must be provided for network. chainId="${network.chainId}"`,
);
}

return {
id: reader.root ? reader.root : path, //TODO, need to method to get project_id
root,
Expand All @@ -136,7 +150,7 @@
};
}

const { version: packageVersion } = require('../../package.json');

Check warning on line 153 in packages/node/src/configure/SubqueryProject.ts

View workflow job for this annotation

GitHub Actions / code-style

Require statement not part of import statement

async function loadProjectFromManifest1_0_0(
projectManifest: ProjectManifestV1_0_0Impl,
Expand Down Expand Up @@ -182,6 +196,21 @@
}));
}

export function dsHasSorobanEventHandler(
dataSources: SubqlProjectDs[],
): boolean {
return (
dataSources.findIndex(function (ds) {
return (
isRuntimeDs(ds) &&
ds.mapping.handlers.findIndex(function (handler) {
return handler.kind === StellarHandlerKind.Event;
}) !== -1
);
}) !== -1
);
}

/*
// eslint-disable-next-line @typescript-eslint/require-await
export async function generateTimestampReferenceForBlockFilters(
Expand Down
Loading
Loading