Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion packages/common-stellar/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
"main": "dist/index.js",
"license": "GPL-3.0",
"dependencies": {
"@stellar/stellar-sdk": "^14.1.0",
"@stellar/stellar-sdk": "^14.3.3",
"@subql/common": "^5.7.0",
"@subql/types-stellar": "workspace:*",
"js-yaml": "^4.1.1",
Expand Down
51 changes: 5 additions & 46 deletions packages/common-stellar/src/project/models.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
// Copyright 2020-2025 SubQuery Pte Ltd authors & contributors
// SPDX-License-Identifier: GPL-3.0

import type {Horizon} from '@stellar/stellar-sdk';
import type {xdr} from '@stellar/stellar-sdk';
import {BaseDataSource, forbidNonWhitelisted, ProcessorImpl} from '@subql/common';
import {Processor, FileReference} from '@subql/types-core';
import {
StellarHandlerKind,
StellarDatasourceKind,
SorobanEventFilter,
StellarEventFilter,
SubqlCustomHandler,
SubqlMapping,
SubqlHandler,
Expand All @@ -17,13 +17,10 @@ import {
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';
Expand All @@ -46,23 +43,13 @@ export class TransactionFilter implements StellarTransactionFilter {

export class OperationFilter implements StellarOperationFilter {
@IsOptional()
type!: Horizon.HorizonApi.OperationResponseType;
type!: xdr.OperationType['name'];

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

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

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

export class BlockHandler implements SubqlBlockHandler {
@IsObject()
@IsOptional()
Expand All @@ -86,18 +73,6 @@ export class TransactionHandler implements SubqlTransactionHandler {
handler!: string;
}

export class SorobanTransactionHandler implements SubqlSorobanTransactionHandler {
@forbidNonWhitelisted({account: ''})
@IsObject()
@IsOptional()
@Type(() => TransactionFilter)
filter?: TransactionFilter;
@IsEnum(StellarHandlerKind, {groups: [StellarHandlerKind.SorobanTransaction]})
kind!: StellarHandlerKind.SorobanTransaction;
@IsString()
handler!: string;
}

export class OperationHandler implements SubqlOperationHandler {
@forbidNonWhitelisted({type: '', sourceAccount: ''})
@IsObject()
Expand All @@ -110,19 +85,7 @@ export class OperationHandler implements SubqlOperationHandler {
handler!: string;
}

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

export class EventFilter implements SorobanEventFilter {
export class EventFilter implements StellarEventFilter {
@IsOptional()
@IsString()
contractId?: string;
Expand All @@ -136,7 +99,7 @@ export class EventHandler implements SubqlEventHandler {
@IsOptional()
@ValidateNested()
@Type(() => EventFilter)
filter?: SorobanEventFilter;
filter?: StellarEventFilter;
@IsEnum(StellarHandlerKind, {groups: [StellarHandlerKind.Event]})
kind!: StellarHandlerKind.Event;
@IsString()
Expand All @@ -162,12 +125,8 @@ export class StellarMapping implements SubqlMapping {
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:
Expand Down
18 changes: 9 additions & 9 deletions packages/common-stellar/src/project/project.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,21 +64,21 @@ describe('project.yaml', () => {
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'));
// 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');
});
// 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 filter = deployment.dataSources[0].mapping.handlers[2].filter;
const deploymentString = manifestVersioned.toDeployment();
expect(filter).not.toBeNull();
expect(deploymentString).toContain('COUNTER');
Expand Down
2 changes: 0 additions & 2 deletions packages/common-stellar/src/project/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ export {
StellarBlockFilter,
StellarTransactionFilter,
StellarOperationFilter,
StellarEffectFilter,
SubqlDatasourceProcessor,
SubqlHandlerFilter,
StellarDatasourceKind,
Expand All @@ -27,5 +26,4 @@ export type IStellarProjectManifest = IProjectManifest<SubqlDatasource>;

export interface StellarProjectNetworkConfig extends ProjectNetworkConfig {
chainId: string;
sorobanEndpoint: string;
}
14 changes: 0 additions & 14 deletions packages/common-stellar/src/project/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@ import {
SubqlMapping,
} from '@subql/types-stellar';

type DefaultFilter = Record<string, unknown>;

export function isBlockHandlerProcessor<F extends Record<string, unknown>, B>(
hp: SecondLayerHandlerProcessorArray<StellarHandlerKind, F, unknown>
): hp is SecondLayerHandlerProcessor<StellarHandlerKind.Block, F, B> {
Expand All @@ -27,24 +25,12 @@ export function isTransactionHandlerProcessor<F extends Record<string, unknown>,
return hp.baseHandlerKind === StellarHandlerKind.Transaction;
}

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

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

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

export function isEventHandlerProcessor<F extends Record<string, unknown>, E>(
hp: SecondLayerHandlerProcessorArray<StellarHandlerKind, F, unknown>
): hp is SecondLayerHandlerProcessor<StellarHandlerKind.Event, F, E> {
Expand Down
5 changes: 0 additions & 5 deletions packages/common-stellar/test/project_1.0.0.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,6 @@ dataSources:
filter:
sourceAccount: 'GAKNXHJ5PCZYFIBNBWB4RCQHH6GDEO7Z334N74BOQUQCHKOURQEPMXCH'
type: 'account_merge'
- handler: handleEffect
kind: stellar/EffectHandler
filter:
type: 'account_credited'
account: 'GAKNXHJ5PCZYFIBNBWB4RCQHH6GDEO7Z334N74BOQUQCHKOURQEPMXCH'
- handler: handleEvent
kind: soroban/EventHandler
filter:
Expand Down
2 changes: 1 addition & 1 deletion packages/node/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
"@nestjs/event-emitter": "^3.0.1",
"@nestjs/platform-express": "^11.0.11",
"@nestjs/schedule": "^5.0.1",
"@stellar/stellar-sdk": "^14.1.0",
"@stellar/stellar-sdk": "^14.3.3",
"@subql/common": "^5.7.0",
"@subql/common-stellar": "workspace:*",
"@subql/node-core": "^18.2.0",
Expand Down
29 changes: 14 additions & 15 deletions packages/node/src/blockchain.service.spec.ts
Original file line number Diff line number Diff line change
@@ -1,39 +1,38 @@
// Copyright 2020-2025 SubQuery Pte Ltd authors & contributors
// SPDX-License-Identifier: GPL-3.0

import { BlockchainService } from './blockchain.service';
import { StellarApi, StellarApiService } from './stellar';
import { SorobanServer } from './stellar/soroban.server';
import {BlockchainService} from './blockchain.service';
import {StellarApi, StellarApiService} from './stellar';

const HTTP_ENDPOINT = 'https://horizon-futurenet.stellar.org';
const SOROBAN_ENDPOINT = 'https://rpc-futurenet.stellar.org';
const SOROBAN_ENDPOINT = 'https://stellar.api.onfinality.io/public';

// https://stellar.expert/explorer/public/ledger/60124580
const blockHeight = 60124580;

describe('BlockchainService', () => {
let blockchainService: BlockchainService;

beforeEach(() => {
const apiService = {
api: new StellarApi(HTTP_ENDPOINT, new SorobanServer(SOROBAN_ENDPOINT)),
api: new StellarApi(SOROBAN_ENDPOINT),
} as StellarApiService;

blockchainService = new BlockchainService(apiService);
});

it('correctly calculates block timestamp', async () => {
//https://stellar.expert/explorer/testnet/ledger/1453893
const timestamp = await blockchainService.getBlockTimestamp(1453893);

expect(timestamp.toISOString()).toBe('2024-05-05T04:17:35.000Z');
const timestamp = await blockchainService.getBlockTimestamp(blockHeight);
expect(timestamp.toISOString()).toBe('2025-12-03T00:51:22.000Z');
});

it('correctly gets the header for a height', async () => {
const header = await blockchainService.getHeaderForHeight(1453893);
const header = await blockchainService.getHeaderForHeight(blockHeight);

expect(header).toEqual({
blockHeight: 1453893,
blockHash: '1453893',
parentHash: '1453892',
timestamp: new Date('2024-05-05T04:17:35.000Z'),
blockHeight: blockHeight,
blockHash: '38258f21481cb72305fbfee9cdd8fb4a6dc12889cea26ef7594fda5a529577a4',
parentHash: 'f616488a2247b0831f53cab1b7bd7a3471df44fef3362aa1a670ed4ae6eb2eb1',
timestamp: new Date('2025-12-03T00:51:22.000Z'),
});
});
});
Loading