@subql/node-stellar 2.9.3-2 → 2.9.3-3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. package/dist/.tsbuildinfo +1 -1
  2. package/dist/configure/SubqueryProject.d.ts +1 -0
  3. package/dist/configure/SubqueryProject.js +18 -2
  4. package/dist/configure/SubqueryProject.js.map +1 -1
  5. package/dist/configure/configure.module.d.ts +4 -1
  6. package/dist/configure/configure.module.js +1 -0
  7. package/dist/configure/configure.module.js.map +1 -1
  8. package/dist/indexer/blockDispatcher/block-dispatcher.service.js +1 -1
  9. package/dist/indexer/blockDispatcher/block-dispatcher.service.js.map +1 -1
  10. package/dist/indexer/fetch.module.js.map +1 -1
  11. package/dist/indexer/fetch.service.js +97 -0
  12. package/dist/indexer/fetch.service.js.map +1 -1
  13. package/dist/indexer/fetch.service.spec.js +121 -47
  14. package/dist/indexer/fetch.service.spec.js.map +1 -1
  15. package/dist/indexer/indexer.manager.d.ts +24 -5
  16. package/dist/indexer/indexer.manager.js +62 -4
  17. package/dist/indexer/indexer.manager.js.map +1 -1
  18. package/dist/indexer/unfinalizedBlocks.service.js +1 -1
  19. package/dist/indexer/unfinalizedBlocks.service.js.map +1 -1
  20. package/dist/indexer/worker/worker.unfinalizedBlocks.service.js +1 -1
  21. package/dist/indexer/worker/worker.unfinalizedBlocks.service.js.map +1 -1
  22. package/dist/meta/meta.module.js.map +1 -1
  23. package/dist/meta/meta.service.d.ts +4 -0
  24. package/dist/meta/meta.service.js +6 -1
  25. package/dist/meta/meta.service.js.map +1 -1
  26. package/dist/stellar/api.connection.d.ts +2 -1
  27. package/dist/stellar/api.connection.js +4 -3
  28. package/dist/stellar/api.connection.js.map +1 -1
  29. package/dist/stellar/api.connection.spec.js +32 -36
  30. package/dist/stellar/api.connection.spec.js.map +1 -1
  31. package/dist/stellar/api.service.stellar.js +5 -1
  32. package/dist/stellar/api.service.stellar.js.map +1 -1
  33. package/dist/stellar/api.service.stellar.spec.d.ts +2 -2
  34. package/dist/stellar/api.service.stellar.spec.js +20 -22
  35. package/dist/stellar/api.service.stellar.spec.js.map +1 -1
  36. package/dist/stellar/api.stellar.d.ts +18 -8
  37. package/dist/stellar/api.stellar.js +160 -28
  38. package/dist/stellar/api.stellar.js.map +1 -1
  39. package/dist/stellar/api.stellar.spec.js +26 -38
  40. package/dist/stellar/api.stellar.spec.js.map +1 -1
  41. package/dist/stellar/block.stellar.d.ts +15 -5
  42. package/dist/stellar/block.stellar.js +50 -2
  43. package/dist/stellar/block.stellar.js.map +1 -1
  44. package/dist/stellar/block.stellar.spec.js +150 -46
  45. package/dist/stellar/block.stellar.spec.js.map +1 -1
  46. package/dist/stellar/safe-api.d.ts +2 -2
  47. package/dist/stellar/safe-api.js +3 -3
  48. package/dist/stellar/safe-api.js.map +1 -1
  49. package/dist/stellar/soroban.server.d.ts +8 -0
  50. package/dist/stellar/soroban.server.js +72 -0
  51. package/dist/stellar/soroban.server.js.map +1 -0
  52. package/dist/stellar/{stellar.server.spec.js → soroban.server.spec.js} +4 -4
  53. package/dist/stellar/{stellar.server.spec.js.map → soroban.server.spec.js.map} +1 -1
  54. package/dist/stellar/stellar.server.d.ts +6 -6
  55. package/dist/stellar/stellar.server.js +9 -61
  56. package/dist/stellar/stellar.server.js.map +1 -1
  57. package/dist/utils/project.d.ts +0 -2
  58. package/dist/utils/project.js +1 -12
  59. package/dist/utils/project.js.map +1 -1
  60. package/dist/yargs.d.ts +6 -1
  61. package/dist/yargs.js +5 -0
  62. package/dist/yargs.js.map +1 -1
  63. package/package.json +5 -4
  64. /package/dist/stellar/{stellar.server.spec.d.ts → soroban.server.spec.d.ts} +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"api.service.stellar.js","sourceRoot":"","sources":["../../src/stellar/api.service.stellar.ts"],"names":[],"mappings":";AAAA,8DAA8D;AAC9D,mCAAmC;;;;;;;;;;;;;;;;;;;;;;AAEnC,2CAAoD;AACpD,yDAAsD;AAEtD,gDAM0B;AAE1B,kEAA+D;AAC/D,qDAAwD;AAIxD,MAAM,MAAM,GAAG,IAAA,qBAAS,EAAC,KAAK,CAAC,CAAC;AAEhC,MAAM,sBAAsB,GAAG,CAAC,CAAC;AAG1B,IAAM,iBAAiB,GAAvB,MAAM,iBAAkB,SAAQ,sBAItC;IACC,YACsC,OAAwB,EAC5D,qBAAkE,EAC1D,YAA2B;QAEnC,KAAK,CAAC,qBAAqB,CAAC,CAAC;QAJO,YAAO,GAAP,OAAO,CAAiB;QAEpD,iBAAY,GAAZ,YAAY,CAAe;IAGrC,CAAC;IAID,KAAK,CAAC,IAAI;;QACR,IAAI;YACF,IAAI,OAA6B,CAAC;YAClC,IAAI;gBACF,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC;aAChC;YAAC,OAAO,CAAC,EAAE;gBACV,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;gBAC7B,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;aACjB;YAED,MAAM,SAAS,GAAG,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC;gBAC/C,CAAC,CAAC,OAAO,CAAC,QAAQ;gBAClB,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;YAEvB,MAAM,kBAAkB,GAAyC,EAAE,CAAC;;gBAEpE,KAAkC,eAAA,KAAA,cAAA,SAAS,CAAC,OAAO,EAAE,CAAA,IAAA;oBAAnB,cAAmB;oBAAnB,WAAmB;;wBAA1C,MAAM,CAAC,CAAC,EAAE,QAAQ,CAAC,KAAA,CAAA;wBAC5B,MAAM,UAAU,GAAG,MAAM,qCAAoB,CAAC,MAAM,CAClD,QAAQ,EACR,IAAI,CAAC,iBAAiB,EACtB,IAAI,CAAC,YAAY,CAClB,CAAC;wBAEF,MAAM,GAAG,GAAG,UAAU,CAAC,SAAS,CAAC;wBAEjC,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,wBAAY,CAAC,YAAY,EAAE;4BAChD,KAAK,EAAE,CAAC;4BACR,QAAQ,EAAE,CAAC;4BACX,QAAQ,EAAE,QAAQ;yBACnB,CAAC,CAAC;wBAEH,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE;4BACrB,IAAI,CAAC,WAAW,GAAG,UAAU,CAAC,WAAW,CAAC;yBAC3C;wBAED,IAAI,OAAO,CAAC,OAAO,KAAK,GAAG,CAAC,UAAU,EAAE,CAAC,QAAQ,EAAE,EAAE;4BACnD,MAAM,IAAI,CAAC,qBAAqB,CAC9B,SAAS,EACT,OAAO,CAAC,OAAO,EACf,GAAG,CAAC,UAAU,EAAE,CAAC,QAAQ,EAAE,CAC5B,CAAC;yBACH;wBAED,kBAAkB,CAAC,QAAQ,CAAC,GAAG,UAAU,CAAC;;;;;iBAC3C;;;;;;;;;YAED,IAAI,CAAC,qBAAqB,CAAC,qBAAqB,CAAC,kBAAkB,CAAC,CAAC;YAErE,OAAO,IAAI,CAAC;SACb;QAAC,OAAO,CAAC,EAAE;YACV,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,4BAA4B,CAAC,CAAC;YAC9C,MAAM,CAAC,CAAC;SACT;IACH,CAAC;IAEO,qBAAqB,CAC3B,QAAgB,EAChB,QAAgB,EAChB,MAAc;QAEd,OAAO,KAAK,CACV,YAAY,QAAQ;mBACP,QAAQ;iBACV,MAAM,EAAE,CACpB,CAAC;IACJ,CAAC;IAED,IAAI,GAAG;QACL,OAAO,IAAI,CAAC,SAAS,CAAC;IACxB,CAAC;IAED,OAAO,CAAC,MAAc;QACpB,MAAM,UAAU,GAAG,CAAC,CAAC;QAErB,MAAM,OAAO,GAAsC;YACjD,GAAG,EAAE,CAAC,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE;gBAC9B,MAAM,cAAc,GAAG,MAAM,CAAC,IAAiC,CAAC,CAAC;gBACjE,IAAI,OAAO,cAAc,KAAK,UAAU,EAAE;oBACxC,OAAO,KAAK,EAAE,GAAG,IAAW,EAAE,EAAE;wBAC9B,IAAI,OAAO,GAAG,CAAC,CAAC;wBAChB,IAAI,UAAU,GAAG,MAAM,CAAC;wBACxB,IAAI,aAAoB,CAAC;wBAEzB,OAAO,OAAO,GAAG,UAAU,EAAE;4BAC3B,IAAI;gCACF,OAAO,MAAM,cAAc,CAAC,KAAK,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;6BACrD;4BAAC,OAAO,KAAK,EAAE;gCACd,MAAM,CAAC,IAAI,CACT,qCAAqC,MAAM,WAAW,OAAO,MAAM,KAAK,CAAC,OAAO,EAAE,CACnF,CAAC;gCACF,aAAa,GAAG,KAAK,CAAC;gCACtB,UAAU,GAAG,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;gCAC/C,OAAO,EAAE,CAAC;6BACX;yBACF;wBAED,MAAM,CAAC,KAAK,CACV,oBAAoB,UAAU,gCAAgC,MAAM,EAAE,CACvE,CAAC;wBACF,MAAM,aAAa,CAAC;oBACtB,CAAC,CAAC;iBACH;gBACD,OAAO,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAC;YAC7C,CAAC;SACF,CAAC;QAEF,OAAO,IAAI,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,CAAC;IAC/D,CAAC;IAEO,KAAK,CAAC,iBAAiB,CAC7B,GAAe,EACf,KAAe;QAEf,OAAO,GAAG,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;IAChC,CAAC;CACF,CAAA;AAlIY,iBAAiB;IAD7B,IAAA,mBAAU,GAAE;IAOR,WAAA,IAAA,eAAM,EAAC,kBAAkB,CAAC,CAAA;qCAAkB,iCAAe;QACrC,iCAAqB;QACtB,6BAAa;GAR1B,iBAAiB,CAkI7B;AAlIY,8CAAiB","sourcesContent":["// Copyright 2020-2023 SubQuery Pte Ltd authors & contributors\n// SPDX-License-Identifier: GPL-3.0\n\nimport { Inject, Injectable } from '@nestjs/common';\nimport { EventEmitter2 } from '@nestjs/event-emitter';\nimport { ProjectNetworkV1_0_0 } from '@subql/common-stellar';\nimport {\n ApiService,\n ConnectionPoolService,\n NetworkMetadataPayload,\n getLogger,\n IndexerEvent,\n} from '@subql/node-core';\nimport { StellarBlockWrapper } from '@subql/types-stellar';\nimport { SubqueryProject } from '../configure/SubqueryProject';\nimport { StellarApiConnection } from './api.connection';\nimport { StellarApi } from './api.stellar';\nimport SafeStellarProvider from './safe-api';\n\nconst logger = getLogger('api');\n\nconst MAX_RECONNECT_ATTEMPTS = 5;\n\n@Injectable()\nexport class StellarApiService extends ApiService<\n StellarApi,\n SafeStellarProvider,\n StellarBlockWrapper\n> {\n constructor(\n @Inject('ISubqueryProject') private project: SubqueryProject,\n connectionPoolService: ConnectionPoolService<StellarApiConnection>,\n private eventEmitter: EventEmitter2,\n ) {\n super(connectionPoolService);\n }\n\n networkMeta: NetworkMetadataPayload;\n\n async init(): Promise<StellarApiService> {\n try {\n let network: ProjectNetworkV1_0_0;\n try {\n network = this.project.network;\n } catch (e) {\n logger.error(Object.keys(e));\n process.exit(1);\n }\n\n const endpoints = Array.isArray(network.endpoint)\n ? network.endpoint\n : [network.endpoint];\n\n const endpointToApiIndex: Record<string, StellarApiConnection> = {};\n\n for await (const [i, endpoint] of endpoints.entries()) {\n const connection = await StellarApiConnection.create(\n endpoint,\n this.fetchBlockBatches,\n this.eventEmitter,\n );\n\n const api = connection.unsafeApi;\n\n this.eventEmitter.emit(IndexerEvent.ApiConnected, {\n value: 1,\n apiIndex: i,\n endpoint: endpoint,\n });\n\n if (!this.networkMeta) {\n this.networkMeta = connection.networkMeta;\n }\n\n if (network.chainId !== api.getChainId().toString()) {\n throw this.metadataMismatchError(\n 'ChainId',\n network.chainId,\n api.getChainId().toString(),\n );\n }\n\n endpointToApiIndex[endpoint] = connection;\n }\n\n this.connectionPoolService.addBatchToConnections(endpointToApiIndex);\n\n return this;\n } catch (e) {\n logger.error(e, 'Failed to init api service');\n throw e;\n }\n }\n\n private metadataMismatchError(\n metadata: string,\n expected: string,\n actual: string,\n ): Error {\n return Error(\n `Value of ${metadata} does not match across all endpoints. Please check that your endpoints are for the same network.\\n\n Expected: ${expected}\n Actual: ${actual}`,\n );\n }\n\n get api(): StellarApi {\n return this.unsafeApi;\n }\n\n safeApi(height: number): SafeStellarProvider {\n const maxRetries = 5;\n\n const handler: ProxyHandler<SafeStellarProvider> = {\n get: (target, prop, receiver) => {\n const originalMethod = target[prop as keyof SafeStellarProvider];\n if (typeof originalMethod === 'function') {\n return async (...args: any[]) => {\n let retries = 0;\n let currentApi = target;\n let throwingError: Error;\n\n while (retries < maxRetries) {\n try {\n return await originalMethod.apply(currentApi, args);\n } catch (error) {\n logger.warn(\n `Request failed with api at height ${height} (retry ${retries}): ${error.message}`,\n );\n throwingError = error;\n currentApi = this.unsafeApi.getSafeApi(height);\n retries++;\n }\n }\n\n logger.error(\n `Maximum retries (${maxRetries}) exceeded for api at height ${height}`,\n );\n throw throwingError;\n };\n }\n return Reflect.get(target, prop, receiver);\n },\n };\n\n return new Proxy(this.unsafeApi.getSafeApi(height), handler);\n }\n\n private async fetchBlockBatches(\n api: StellarApi,\n batch: number[],\n ): Promise<StellarBlockWrapper[]> {\n return api.fetchBlocks(batch);\n }\n}\n"]}
1
+ {"version":3,"file":"api.service.stellar.js","sourceRoot":"","sources":["../../src/stellar/api.service.stellar.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2020-2023 SubQuery Pte Ltd authors & contributors\n// SPDX-License-Identifier: GPL-3.0\n\nimport { Inject, Injectable } from '@nestjs/common';\nimport { EventEmitter2 } from '@nestjs/event-emitter';\nimport { ProjectNetworkV1_0_0 } from '@subql/common-stellar';\nimport {\n ApiService,\n ConnectionPoolService,\n NetworkMetadataPayload,\n getLogger,\n IndexerEvent,\n} from '@subql/node-core';\nimport { StellarBlockWrapper } from '@subql/types-stellar';\nimport { SubqueryProject } from '../configure/SubqueryProject';\nimport { StellarApiConnection } from './api.connection';\nimport { StellarApi } from './api.stellar';\nimport SafeStellarProvider from './safe-api';\nimport { SorobanServer } from './soroban.server';\n\nconst logger = getLogger('api');\n\nconst MAX_RECONNECT_ATTEMPTS = 5;\n\n@Injectable()\nexport class StellarApiService extends ApiService<\n StellarApi,\n SafeStellarProvider,\n StellarBlockWrapper\n> {\n constructor(\n @Inject('ISubqueryProject') private project: SubqueryProject,\n connectionPoolService: ConnectionPoolService<StellarApiConnection>,\n private eventEmitter: EventEmitter2,\n ) {\n super(connectionPoolService);\n }\n\n networkMeta: NetworkMetadataPayload;\n\n async init(): Promise<StellarApiService> {\n try {\n let network: ProjectNetworkV1_0_0;\n try {\n network = this.project.network;\n } catch (e) {\n logger.error(Object.keys(e));\n process.exit(1);\n }\n\n const sorobanClient = network.soroban\n ? new SorobanServer(network.soroban)\n : undefined;\n\n const endpoints = Array.isArray(network.endpoint)\n ? network.endpoint\n : [network.endpoint];\n\n const endpointToApiIndex: Record<string, StellarApiConnection> = {};\n\n for await (const [i, endpoint] of endpoints.entries()) {\n const connection = await StellarApiConnection.create(\n endpoint,\n this.fetchBlockBatches,\n this.eventEmitter,\n sorobanClient,\n );\n\n const api = connection.unsafeApi;\n\n this.eventEmitter.emit(IndexerEvent.ApiConnected, {\n value: 1,\n apiIndex: i,\n endpoint: endpoint,\n });\n\n if (!this.networkMeta) {\n this.networkMeta = connection.networkMeta;\n }\n\n if (network.chainId !== api.getChainId().toString()) {\n throw this.metadataMismatchError(\n 'ChainId',\n network.chainId,\n api.getChainId().toString(),\n );\n }\n\n endpointToApiIndex[endpoint] = connection;\n }\n\n this.connectionPoolService.addBatchToConnections(endpointToApiIndex);\n\n return this;\n } catch (e) {\n logger.error(e, 'Failed to init api service');\n throw e;\n }\n }\n\n private metadataMismatchError(\n metadata: string,\n expected: string,\n actual: string,\n ): Error {\n return Error(\n `Value of ${metadata} does not match across all endpoints. Please check that your endpoints are for the same network.\\n\n Expected: ${expected}\n Actual: ${actual}`,\n );\n }\n\n get api(): StellarApi {\n return this.unsafeApi;\n }\n\n safeApi(height: number): SafeStellarProvider {\n const maxRetries = 5;\n\n const handler: ProxyHandler<SafeStellarProvider> = {\n get: (target, prop, receiver) => {\n const originalMethod = target[prop as keyof SafeStellarProvider];\n if (typeof originalMethod === 'function') {\n return async (...args: any[]) => {\n let retries = 0;\n let currentApi = target;\n let throwingError: Error;\n\n while (retries < maxRetries) {\n try {\n return await originalMethod.apply(currentApi, args);\n } catch (error) {\n logger.warn(\n `Request failed with api at height ${height} (retry ${retries}): ${error.message}`,\n );\n throwingError = error;\n currentApi = this.unsafeApi.getSafeApi(height);\n retries++;\n }\n }\n\n logger.error(\n `Maximum retries (${maxRetries}) exceeded for api at height ${height}`,\n );\n throw throwingError;\n };\n }\n return Reflect.get(target, prop, receiver);\n },\n };\n\n return new Proxy(this.unsafeApi.getSafeApi(height), handler);\n }\n\n private async fetchBlockBatches(\n api: StellarApi,\n batch: number[],\n ): Promise<StellarBlockWrapper[]> {\n return api.fetchBlocks(batch);\n }\n}\n"]}
@@ -1,5 +1,5 @@
1
1
  import { INestApplication } from '@nestjs/common';
2
2
  import { SubqueryProject } from '../configure/SubqueryProject';
3
3
  import { StellarApiService } from './api.service.stellar';
4
- export declare function testSubqueryProject(endpoint: string): SubqueryProject;
5
- export declare const prepareApiService: (endpoint?: string, project?: SubqueryProject) => Promise<[StellarApiService, INestApplication]>;
4
+ export declare function testSubqueryProject(endpoint: string, soroban: string): SubqueryProject;
5
+ export declare const prepareApiService: (endpoint?: string, soroban?: string, project?: SubqueryProject) => Promise<[StellarApiService, INestApplication]>;
@@ -10,11 +10,15 @@ const dist_1 = require("@subql/node-core/dist");
10
10
  const graphql_1 = require("graphql");
11
11
  const lodash_1 = require("lodash");
12
12
  const api_service_stellar_1 = require("./api.service.stellar");
13
- const HTTP_ENDPOINT = 'https://rpc-futurenet.stellar.org:443';
14
- function testSubqueryProject(endpoint) {
13
+ const api_stellar_1 = require("./api.stellar");
14
+ const block_stellar_1 = require("./block.stellar");
15
+ const HTTP_ENDPOINT = 'https://horizon-futurenet.stellar.org';
16
+ const SOROBAN_ENDPOINT = 'https://rpc-futurenet.stellar.org';
17
+ function testSubqueryProject(endpoint, soroban) {
15
18
  return {
16
19
  network: {
17
20
  endpoint,
21
+ soroban,
18
22
  chainId: 'Test SDF Future Network ; October 2022',
19
23
  },
20
24
  dataSources: [],
@@ -25,7 +29,7 @@ function testSubqueryProject(endpoint) {
25
29
  };
26
30
  }
27
31
  exports.testSubqueryProject = testSubqueryProject;
28
- const prepareApiService = async (endpoint = HTTP_ENDPOINT, project) => {
32
+ const prepareApiService = async (endpoint = HTTP_ENDPOINT, soroban = SOROBAN_ENDPOINT, project) => {
29
33
  const module = await testing_1.Test.createTestingModule({
30
34
  providers: [
31
35
  node_core_1.ConnectionPoolService,
@@ -36,7 +40,7 @@ const prepareApiService = async (endpoint = HTTP_ENDPOINT, project) => {
36
40
  },
37
41
  {
38
42
  provide: 'ISubqueryProject',
39
- useFactory: () => project !== null && project !== void 0 ? project : testSubqueryProject(endpoint),
43
+ useFactory: () => project !== null && project !== void 0 ? project : testSubqueryProject(endpoint, soroban),
40
44
  },
41
45
  api_service_stellar_1.StellarApiService,
42
46
  ],
@@ -56,32 +60,26 @@ describe('StellarApiService', () => {
56
60
  beforeEach(async () => {
57
61
  [apiService, app] = await (0, exports.prepareApiService)();
58
62
  });
59
- it('can instantiate api', async () => {
60
- console.log(apiService.api.getChainId());
61
- await (0, node_core_1.delay)(0.5);
63
+ it('should instantiate api', () => {
64
+ expect(apiService.api).toBeInstanceOf(api_stellar_1.StellarApi);
62
65
  });
63
- it('can fetch blocks', async () => {
64
- const finalizedHeight = await apiService.api.getFinalizedBlockHeight();
65
- const blocks = await apiService.api.fetchBlocks((0, lodash_1.range)(finalizedHeight - 1000, finalizedHeight));
66
+ it('should fetch blocks', async () => {
67
+ const latestHeight = await apiService.api.getFinalizedBlockHeight();
68
+ const blocks = await apiService.fetchBlocks((0, lodash_1.range)(latestHeight - 1, latestHeight));
66
69
  expect(blocks).toBeDefined();
67
- await (0, node_core_1.delay)(0.5);
70
+ expect(blocks).toEqual(expect.arrayContaining([expect.any(block_stellar_1.StellarBlockWrapped)]));
68
71
  });
69
- it('can get the finalized height', async () => {
70
- const height = await apiService.api.getFinalizedBlockHeight();
71
- console.log('Finalized height', height);
72
- expect(height).not.toBeNaN();
73
- });
74
- it('throws error when chainId does not match', async () => {
75
- const faultyProject = Object.assign(Object.assign({}, testSubqueryProject(HTTP_ENDPOINT)), { network: Object.assign(Object.assign({}, testSubqueryProject(HTTP_ENDPOINT).network), { chainId: 'Incorrect ChainId' }) });
76
- await expect((0, exports.prepareApiService)(HTTP_ENDPOINT, faultyProject)).rejects.toThrow();
72
+ it('should throw error when chainId does not match', async () => {
73
+ const faultyProject = Object.assign(Object.assign({}, testSubqueryProject(HTTP_ENDPOINT, SOROBAN_ENDPOINT)), { network: Object.assign(Object.assign({}, testSubqueryProject(HTTP_ENDPOINT, SOROBAN_ENDPOINT).network), { chainId: 'Incorrect ChainId' }) });
74
+ await expect((0, exports.prepareApiService)(HTTP_ENDPOINT, SOROBAN_ENDPOINT, faultyProject)).rejects.toThrow();
77
75
  });
78
76
  it('fails after maximum retries', async () => {
79
- const safeApi = apiService.safeApi(50000);
77
+ const api = apiService.unsafeApi;
80
78
  // Mock the fetchBlocks method to always throw an error
81
- safeApi.fetchBlocks = jest
79
+ api.fetchBlocks = jest
82
80
  .fn()
83
81
  .mockRejectedValue(new Error('Network error'));
84
- await expect(safeApi.fetchBlocks((0, lodash_1.range)(50000, 50100))).rejects.toThrow();
82
+ await expect(api.fetchBlocks((0, lodash_1.range)(50000, 50100))).rejects.toThrow();
85
83
  });
86
84
  });
87
85
  //# sourceMappingURL=api.service.stellar.spec.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"api.service.stellar.spec.js","sourceRoot":"","sources":["../../src/stellar/api.service.stellar.spec.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2020-2023 SubQuery Pte Ltd authors & contributors\n// SPDX-License-Identifier: GPL-3.0\n\nimport { INestApplication } from '@nestjs/common';\nimport { EventEmitterModule } from '@nestjs/event-emitter';\nimport { Test } from '@nestjs/testing';\nimport { ConnectionPoolService, delay, NodeConfig } from '@subql/node-core';\nimport { ConnectionPoolStateManager } from '@subql/node-core/dist';\nimport { GraphQLSchema } from 'graphql';\nimport { range } from 'lodash';\nimport { SubqueryProject } from '../configure/SubqueryProject';\nimport { StellarApiService } from './api.service.stellar';\n\nconst HTTP_ENDPOINT = 'https://rpc-futurenet.stellar.org:443';\n\nexport function testSubqueryProject(endpoint: string): SubqueryProject {\n return {\n network: {\n endpoint,\n chainId: 'Test SDF Future Network ; October 2022',\n },\n dataSources: [],\n id: 'test',\n root: './',\n schema: new GraphQLSchema({}),\n templates: [],\n };\n}\n\nexport const prepareApiService = async (\n endpoint: string = HTTP_ENDPOINT,\n project?: SubqueryProject,\n): Promise<[StellarApiService, INestApplication]> => {\n const module = await Test.createTestingModule({\n providers: [\n ConnectionPoolService,\n ConnectionPoolStateManager,\n {\n provide: NodeConfig,\n useFactory: () => ({}),\n },\n {\n provide: 'ISubqueryProject',\n useFactory: () => project ?? testSubqueryProject(endpoint),\n },\n StellarApiService,\n ],\n imports: [EventEmitterModule.forRoot()],\n }).compile();\n\n const app = module.createNestApplication();\n await app.init();\n const apiService = app.get(StellarApiService);\n await apiService.init();\n return [apiService, app];\n};\n\njest.setTimeout(90000);\ndescribe('StellarApiService', () => {\n let apiService: StellarApiService;\n let app: INestApplication;\n\n beforeEach(async () => {\n [apiService, app] = await prepareApiService();\n });\n\n it('can instantiate api', async () => {\n console.log(apiService.api.getChainId());\n await delay(0.5);\n });\n\n it('can fetch blocks', async () => {\n const finalizedHeight = await apiService.api.getFinalizedBlockHeight();\n const blocks = await apiService.api.fetchBlocks(\n range(finalizedHeight - 1000, finalizedHeight),\n );\n expect(blocks).toBeDefined();\n await delay(0.5);\n });\n\n it('can get the finalized height', async () => {\n const height = await apiService.api.getFinalizedBlockHeight();\n console.log('Finalized height', height);\n expect(height).not.toBeNaN();\n });\n\n it('throws error when chainId does not match', async () => {\n const faultyProject = {\n ...testSubqueryProject(HTTP_ENDPOINT),\n network: {\n ...testSubqueryProject(HTTP_ENDPOINT).network,\n chainId: 'Incorrect ChainId',\n },\n };\n\n await expect(\n prepareApiService(HTTP_ENDPOINT, faultyProject),\n ).rejects.toThrow();\n });\n\n it('fails after maximum retries', async () => {\n const safeApi = apiService.safeApi(50000);\n\n // Mock the fetchBlocks method to always throw an error\n (safeApi as any).fetchBlocks = jest\n .fn()\n .mockRejectedValue(new Error('Network error'));\n\n await expect(\n (safeApi as any).fetchBlocks(range(50000, 50100)),\n ).rejects.toThrow();\n });\n});\n"]}
1
+ {"version":3,"file":"api.service.stellar.spec.js","sourceRoot":"","sources":["../../src/stellar/api.service.stellar.spec.ts"],"names":[],"mappings":";AAAA,8DAA8D;AAC9D,mCAAmC;;;AAGnC,yDAA2D;AAC3D,6CAAuC;AACvC,gDAA4E;AAC5E,gDAAmE;AACnE,qCAAwC;AACxC,mCAAqC;AAErC,+DAA0D;AAC1D,+CAA2C;AAC3C,mDAAsD;AAEtD,MAAM,aAAa,GAAG,uCAAuC,CAAC;AAC9D,MAAM,gBAAgB,GAAG,mCAAmC,CAAC;AAE7D,SAAgB,mBAAmB,CACjC,QAAgB,EAChB,OAAe;IAEf,OAAO;QACL,OAAO,EAAE;YACP,QAAQ;YACR,OAAO;YACP,OAAO,EAAE,wCAAwC;SAClD;QACD,WAAW,EAAE,EAAE;QACf,EAAE,EAAE,MAAM;QACV,IAAI,EAAE,IAAI;QACV,MAAM,EAAE,IAAI,uBAAa,CAAC,EAAE,CAAC;QAC7B,SAAS,EAAE,EAAE;KACd,CAAC;AACJ,CAAC;AAhBD,kDAgBC;AAEM,MAAM,iBAAiB,GAAG,KAAK,EACpC,WAAmB,aAAa,EAChC,UAAkB,gBAAgB,EAClC,OAAyB,EACuB,EAAE;IAClD,MAAM,MAAM,GAAG,MAAM,cAAI,CAAC,mBAAmB,CAAC;QAC5C,SAAS,EAAE;YACT,iCAAqB;YACrB,iCAA0B;YAC1B;gBACE,OAAO,EAAE,sBAAU;gBACnB,UAAU,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC;aACvB;YACD;gBACE,OAAO,EAAE,kBAAkB;gBAC3B,UAAU,EAAE,GAAG,EAAE,CAAC,OAAO,aAAP,OAAO,cAAP,OAAO,GAAI,mBAAmB,CAAC,QAAQ,EAAE,OAAO,CAAC;aACpE;YACD,uCAAiB;SAClB;QACD,OAAO,EAAE,CAAC,kCAAkB,CAAC,OAAO,EAAE,CAAC;KACxC,CAAC,CAAC,OAAO,EAAE,CAAC;IAEb,MAAM,GAAG,GAAG,MAAM,CAAC,qBAAqB,EAAE,CAAC;IAC3C,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;IACjB,MAAM,UAAU,GAAG,GAAG,CAAC,GAAG,CAAC,uCAAiB,CAAC,CAAC;IAC9C,MAAM,UAAU,CAAC,IAAI,EAAE,CAAC;IACxB,OAAO,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC;AAC3B,CAAC,CAAC;AA3BW,QAAA,iBAAiB,qBA2B5B;AAEF,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;AACvB,QAAQ,CAAC,mBAAmB,EAAE,GAAG,EAAE;IACjC,IAAI,UAA6B,CAAC;IAClC,IAAI,GAAqB,CAAC;IAE1B,UAAU,CAAC,KAAK,IAAI,EAAE;QACpB,CAAC,UAAU,EAAE,GAAG,CAAC,GAAG,MAAM,IAAA,yBAAiB,GAAE,CAAC;IAChD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wBAAwB,EAAE,GAAG,EAAE;QAChC,MAAM,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,cAAc,CAAC,wBAAU,CAAC,CAAC;IACpD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qBAAqB,EAAE,KAAK,IAAI,EAAE;QACnC,MAAM,YAAY,GAAG,MAAM,UAAU,CAAC,GAAG,CAAC,uBAAuB,EAAE,CAAC;QACpE,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,WAAW,CACzC,IAAA,cAAK,EAAC,YAAY,GAAG,CAAC,EAAE,YAAY,CAAC,CACtC,CAAC;QACF,MAAM,CAAC,MAAM,CAAC,CAAC,WAAW,EAAE,CAAC;QAC7B,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CACpB,MAAM,CAAC,eAAe,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,mCAAmB,CAAC,CAAC,CAAC,CAC1D,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,gDAAgD,EAAE,KAAK,IAAI,EAAE;QAC9D,MAAM,aAAa,mCACd,mBAAmB,CAAC,aAAa,EAAE,gBAAgB,CAAC,KACvD,OAAO,kCACF,mBAAmB,CAAC,aAAa,EAAE,gBAAgB,CAAC,CAAC,OAAO,KAC/D,OAAO,EAAE,mBAAmB,MAE/B,CAAC;QAEF,MAAM,MAAM,CACV,IAAA,yBAAiB,EAAC,aAAa,EAAE,gBAAgB,EAAE,aAAa,CAAC,CAClE,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;IACtB,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6BAA6B,EAAE,KAAK,IAAI,EAAE;QAC3C,MAAM,GAAG,GAAG,UAAU,CAAC,SAAS,CAAC;QAEjC,uDAAuD;QACtD,GAAW,CAAC,WAAW,GAAG,IAAI;aAC5B,EAAE,EAAE;aACJ,iBAAiB,CAAC,IAAI,KAAK,CAAC,eAAe,CAAC,CAAC,CAAC;QAEjD,MAAM,MAAM,CACT,GAAW,CAAC,WAAW,CAAC,IAAA,cAAK,EAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAC9C,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;IACtB,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC","sourcesContent":["// Copyright 2020-2023 SubQuery Pte Ltd authors & contributors\n// SPDX-License-Identifier: GPL-3.0\n\nimport { INestApplication } from '@nestjs/common';\nimport { EventEmitterModule } from '@nestjs/event-emitter';\nimport { Test } from '@nestjs/testing';\nimport { ConnectionPoolService, delay, NodeConfig } from '@subql/node-core';\nimport { ConnectionPoolStateManager } from '@subql/node-core/dist';\nimport { GraphQLSchema } from 'graphql';\nimport { range, some } from 'lodash';\nimport { SubqueryProject } from '../configure/SubqueryProject';\nimport { StellarApiService } from './api.service.stellar';\nimport { StellarApi } from './api.stellar';\nimport { StellarBlockWrapped } from './block.stellar';\n\nconst HTTP_ENDPOINT = 'https://horizon-futurenet.stellar.org';\nconst SOROBAN_ENDPOINT = 'https://rpc-futurenet.stellar.org';\n\nexport function testSubqueryProject(\n endpoint: string,\n soroban: string,\n): SubqueryProject {\n return {\n network: {\n endpoint,\n soroban,\n chainId: 'Test SDF Future Network ; October 2022',\n },\n dataSources: [],\n id: 'test',\n root: './',\n schema: new GraphQLSchema({}),\n templates: [],\n };\n}\n\nexport const prepareApiService = async (\n endpoint: string = HTTP_ENDPOINT,\n soroban: string = SOROBAN_ENDPOINT,\n project?: SubqueryProject,\n): Promise<[StellarApiService, INestApplication]> => {\n const module = await Test.createTestingModule({\n providers: [\n ConnectionPoolService,\n ConnectionPoolStateManager,\n {\n provide: NodeConfig,\n useFactory: () => ({}),\n },\n {\n provide: 'ISubqueryProject',\n useFactory: () => project ?? testSubqueryProject(endpoint, soroban),\n },\n StellarApiService,\n ],\n imports: [EventEmitterModule.forRoot()],\n }).compile();\n\n const app = module.createNestApplication();\n await app.init();\n const apiService = app.get(StellarApiService);\n await apiService.init();\n return [apiService, app];\n};\n\njest.setTimeout(90000);\ndescribe('StellarApiService', () => {\n let apiService: StellarApiService;\n let app: INestApplication;\n\n beforeEach(async () => {\n [apiService, app] = await prepareApiService();\n });\n\n it('should instantiate api', () => {\n expect(apiService.api).toBeInstanceOf(StellarApi);\n });\n\n it('should fetch blocks', async () => {\n const latestHeight = await apiService.api.getFinalizedBlockHeight();\n const blocks = await apiService.fetchBlocks(\n range(latestHeight - 1, latestHeight),\n );\n expect(blocks).toBeDefined();\n expect(blocks).toEqual(\n expect.arrayContaining([expect.any(StellarBlockWrapped)]),\n );\n });\n\n it('should throw error when chainId does not match', async () => {\n const faultyProject = {\n ...testSubqueryProject(HTTP_ENDPOINT, SOROBAN_ENDPOINT),\n network: {\n ...testSubqueryProject(HTTP_ENDPOINT, SOROBAN_ENDPOINT).network,\n chainId: 'Incorrect ChainId',\n },\n };\n\n await expect(\n prepareApiService(HTTP_ENDPOINT, SOROBAN_ENDPOINT, faultyProject),\n ).rejects.toThrow();\n });\n\n it('fails after maximum retries', async () => {\n const api = apiService.unsafeApi;\n\n // Mock the fetchBlocks method to always throw an error\n (api as any).fetchBlocks = jest\n .fn()\n .mockRejectedValue(new Error('Network error'));\n\n await expect(\n (api as any).fetchBlocks(range(50000, 50100)),\n ).rejects.toThrow();\n });\n});\n"]}
@@ -1,25 +1,35 @@
1
1
  import { EventEmitter2 } from '@nestjs/event-emitter';
2
- import { ApiWrapper, StellarBlockWrapper } from '@subql/types-stellar';
3
- import { Server, SorobanRpc } from 'soroban-client';
4
- import { StellarBlockWrapped } from './block.stellar';
2
+ import { ApiWrapper, SorobanEvent, StellarBlockWrapper } from '@subql/types-stellar';
3
+ import { Server, ServerApi } from 'stellar-sdk';
5
4
  import SafeStellarProvider from './safe-api';
5
+ import { SorobanServer } from './soroban.server';
6
6
  export declare class StellarApi implements ApiWrapper<StellarBlockWrapper> {
7
7
  private endpoint;
8
8
  private eventEmitter;
9
- private client;
9
+ private sorobanClient?;
10
+ private stellarClient;
10
11
  private chainId;
12
+ private genesisHash;
11
13
  private name;
12
- constructor(endpoint: string, eventEmitter: EventEmitter2);
14
+ constructor(endpoint: string, eventEmitter: EventEmitter2, sorobanClient?: SorobanServer);
13
15
  init(): Promise<void>;
14
- getFinalizedBlock(): Promise<SorobanRpc.GetLatestLedgerResponse>;
16
+ getFinalizedBlock(): Promise<ServerApi.LedgerRecord>;
15
17
  getFinalizedBlockHeight(): Promise<number>;
16
18
  getBestBlockHeight(): Promise<number>;
17
19
  getRuntimeChain(): string;
18
20
  getChainId(): string;
19
21
  getGenesisHash(): string;
20
22
  getSpecName(): string;
21
- getEvents(height: number): Promise<SorobanRpc.GetEventsResponse>;
22
- fetchBlock(blockNumber: number, includeTx?: boolean): Promise<StellarBlockWrapped>;
23
+ private fetchTransactionsForLedger;
24
+ private fetchOperationsForLedger;
25
+ private fetchEffectsForLedger;
26
+ private getTransactionApplicationOrder;
27
+ private getOperationIndex;
28
+ getAndWrapEvents(height: number): Promise<SorobanEvent[]>;
29
+ private wrapEffectsForOperation;
30
+ private wrapOperationsForTx;
31
+ private wrapTransactionsForLedger;
32
+ private fetchAndWrapLedger;
23
33
  fetchBlocks(bufferBlocks: number[]): Promise<StellarBlockWrapper[]>;
24
34
  get api(): Server;
25
35
  getSafeApi(blockHeight: number): SafeStellarProvider;
@@ -7,17 +7,18 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
7
7
  Object.defineProperty(exports, "__esModule", { value: true });
8
8
  exports.StellarApi = void 0;
9
9
  const node_core_1 = require("@subql/node-core");
10
- const soroban_client_1 = require("soroban-client");
11
- const block_stellar_1 = require("./block.stellar");
10
+ const lodash_1 = require("lodash");
11
+ const block_stellar_1 = require("../stellar/block.stellar");
12
12
  const safe_api_1 = __importDefault(require("./safe-api"));
13
13
  const stellar_server_1 = require("./stellar.server");
14
14
  // eslint-disable-next-line @typescript-eslint/no-var-requires
15
15
  const { version: packageVersion } = require('../../package.json');
16
16
  const logger = (0, node_core_1.getLogger)('api.Stellar');
17
17
  class StellarApi {
18
- constructor(endpoint, eventEmitter) {
18
+ constructor(endpoint, eventEmitter, sorobanClient) {
19
19
  this.endpoint = endpoint;
20
20
  this.eventEmitter = eventEmitter;
21
+ this.sorobanClient = sorobanClient;
21
22
  const { hostname, protocol, searchParams } = new URL(endpoint);
22
23
  const protocolStr = protocol.replace(':', '');
23
24
  logger.info(`Api host: ${hostname}, method: ${protocolStr}`);
@@ -31,18 +32,20 @@ class StellarApi {
31
32
  //searchParams.forEach((value, name, searchParams) => {
32
33
  // (connection.headers as any)[name] = value;
33
34
  //});
34
- this.client = new stellar_server_1.StellarServer(endpoint, options);
35
+ this.stellarClient = new stellar_server_1.StellarServer(endpoint, options);
35
36
  }
36
37
  else {
37
38
  throw new Error(`Unsupported protocol: ${protocol}`);
38
39
  }
39
40
  }
40
41
  async init() {
41
- const network = await this.client.getNetwork();
42
- this.chainId = network.passphrase;
42
+ //need archive node for genesis hash
43
+ //const genesisLedger = (await this.stellarClient.ledgers().ledger(1).call()).records[0];
44
+ this.chainId = (await this.stellarClient.getNetwork()).network_passphrase;
45
+ //this.genesisHash = genesisLedger.hash;
43
46
  }
44
47
  async getFinalizedBlock() {
45
- return this.client.getLatestLedger();
48
+ return (await this.stellarClient.ledgers().order('desc').call()).records[0];
46
49
  }
47
50
  async getFinalizedBlockHeight() {
48
51
  return (await this.getFinalizedBlock()).sequence;
@@ -57,39 +60,168 @@ class StellarApi {
57
60
  return this.chainId;
58
61
  }
59
62
  getGenesisHash() {
60
- return this.getChainId();
63
+ return this.chainId;
61
64
  }
62
65
  getSpecName() {
63
66
  return 'Stellar';
64
67
  }
65
- async getEvents(height) {
66
- return this.client.getEvents({ startLedger: height, filters: [] });
67
- }
68
- async fetchBlock(blockNumber, includeTx) {
69
- try {
70
- const rawEvents = (await this.getEvents(blockNumber)).events;
71
- const events = rawEvents.map((event) => (Object.assign(Object.assign({}, event), { value: Object.assign(Object.assign({}, event.value), { get decoded() {
72
- return (0, soroban_client_1.scValToNative)(soroban_client_1.xdr.ScVal.fromXDR(event.value.xdr, 'base64'));
73
- } }), topic: event.topic.map((topic) => block_stellar_1.StellarBlockWrapped.decodeScVals(soroban_client_1.xdr.ScVal.fromXDR(topic, 'base64'))) })));
74
- const ret = new block_stellar_1.StellarBlockWrapped(events, {
75
- ledger: blockNumber,
76
- hash: blockNumber.toString(),
77
- });
78
- this.eventEmitter.emit('fetchBlock');
79
- return ret;
68
+ async fetchTransactionsForLedger(sequence) {
69
+ const txs = [];
70
+ let txsPage = await this.api.transactions().forLedger(sequence).call();
71
+ while (txsPage.records.length !== 0) {
72
+ txs.push(...txsPage.records);
73
+ txsPage = await txsPage.next();
74
+ }
75
+ return txs;
76
+ }
77
+ async fetchOperationsForLedger(sequence) {
78
+ const operations = [];
79
+ let operationsPage = await this.api.operations().forLedger(sequence).call();
80
+ while (operationsPage.records.length !== 0) {
81
+ operations.push(...operationsPage.records);
82
+ operationsPage = await operationsPage.next();
80
83
  }
81
- catch (e) {
82
- throw this.handleError(e, blockNumber);
84
+ return operations;
85
+ }
86
+ async fetchEffectsForLedger(sequence) {
87
+ const effects = [];
88
+ let effectsPage = await this.api.effects().forLedger(sequence).call();
89
+ while (effectsPage.records.length !== 0) {
90
+ effects.push(...effectsPage.records);
91
+ effectsPage = await effectsPage.next();
83
92
  }
93
+ return effects;
94
+ }
95
+ getTransactionApplicationOrder(eventId) {
96
+ // Right shift the ID by 12 bits to exclude the Operation Index
97
+ const shiftedId = BigInt(eventId.split('-')[0]) >> BigInt(12);
98
+ // Create a mask for 20 bits to ignore the Ledger Sequence Number
99
+ const mask = BigInt((1 << 20) - 1);
100
+ // Apply bitwise AND operation with the mask to get the Transaction Application Order
101
+ const transactionApplicationOrder = shiftedId & mask;
102
+ return Number(transactionApplicationOrder);
103
+ }
104
+ getOperationIndex(id) {
105
+ // Pick the first part of the ID before the '-' character
106
+ const idPart = id.split('-')[0];
107
+ // Create a mask for 12 bits to isolate the Operation Index
108
+ const mask = BigInt((1 << 12) - 1);
109
+ // Apply bitwise AND operation with the mask to get the Operation Index
110
+ const operationIndex = BigInt(idPart) & mask;
111
+ return Number(operationIndex);
112
+ }
113
+ async getAndWrapEvents(height) {
114
+ const { events: events } = await this.sorobanClient.getEvents({
115
+ startLedger: height,
116
+ filters: [],
117
+ });
118
+ return events.map((event) => {
119
+ const wrappedEvent = Object.assign(Object.assign({}, event), { ledger: null, transaction: null, operation: null });
120
+ return wrappedEvent;
121
+ });
122
+ }
123
+ wrapEffectsForOperation(operationIndex, effectsForSequence) {
124
+ return effectsForSequence
125
+ .filter((effect) => this.getOperationIndex(effect.id) === operationIndex)
126
+ .map((effect) => (Object.assign(Object.assign({}, effect), { ledger: null, transaction: null, operation: null })));
127
+ }
128
+ wrapOperationsForTx(transactionId, applicationOrder, sequence, operationsForSequence, effectsForSequence, eventsForSequence) {
129
+ const operations = operationsForSequence.filter((op) => op.transaction_hash === transactionId);
130
+ return operations.map((op, index) => {
131
+ const effects = this.wrapEffectsForOperation(index, effectsForSequence);
132
+ const events = eventsForSequence.filter((event) => this.getTransactionApplicationOrder(event.id) === applicationOrder);
133
+ const wrappedOp = Object.assign(Object.assign({}, op), { ledger: null, transaction: null, effects: [], events });
134
+ effects.forEach((effect) => {
135
+ effect.operation = (0, lodash_1.cloneDeep)(wrappedOp);
136
+ wrappedOp.effects.push(effect);
137
+ });
138
+ return wrappedOp;
139
+ });
140
+ }
141
+ wrapTransactionsForLedger(sequence, transactions, operationsForSequence, effectsForSequence, eventsForSequence) {
142
+ return transactions.map((tx, index) => {
143
+ const wrappedTx = Object.assign(Object.assign({}, tx), { ledger: null, operations: [], effects: [], events: [] });
144
+ const operations = this.wrapOperationsForTx(tx.id, index + 1, sequence, operationsForSequence, effectsForSequence, eventsForSequence).map((op) => {
145
+ op.transaction = (0, lodash_1.cloneDeep)(wrappedTx);
146
+ op.effects = op.effects.map((effect) => {
147
+ effect.transaction = (0, lodash_1.cloneDeep)(wrappedTx);
148
+ return effect;
149
+ });
150
+ op.events = op.events.map((event) => {
151
+ event.transaction = (0, lodash_1.cloneDeep)(wrappedTx);
152
+ return event;
153
+ });
154
+ return op;
155
+ });
156
+ wrappedTx.operations.push(...operations);
157
+ operations.forEach((op) => {
158
+ wrappedTx.effects.push(...op.effects);
159
+ wrappedTx.events.push(...op.events);
160
+ });
161
+ return wrappedTx;
162
+ });
163
+ }
164
+ async fetchAndWrapLedger(sequence) {
165
+ const [ledger, transactions, operations, effects] = await Promise.all([
166
+ this.api.ledgers().ledger(sequence).call(),
167
+ this.fetchTransactionsForLedger(sequence),
168
+ this.fetchOperationsForLedger(sequence),
169
+ this.fetchEffectsForLedger(sequence),
170
+ ]);
171
+ let eventsForSequence = [];
172
+ //check if there is InvokeHostFunctionOp operation
173
+ //If yes then, there are soroban transactions and we should we fetch soroban events
174
+ const hasInvokeHostFunctionOp = operations.some((op) => op.type.toString() === 'invoke_host_function');
175
+ if (this.sorobanClient && hasInvokeHostFunctionOp) {
176
+ try {
177
+ eventsForSequence = await this.getAndWrapEvents(sequence);
178
+ }
179
+ catch (e) {
180
+ if (e.message === 'start is before oldest ledger') {
181
+ throw new Error(`The requested events for ledger number ${sequence} is not available on the current soroban node.
182
+ This is because you're trying to access a ledger that is older than the oldest ledger stored in this node.
183
+ To resolve this issue, you can either:
184
+ 1. Increase the start ledger to a more recent one, or
185
+ 2. Connect to a different node that might have a longer history of ledgers.`);
186
+ }
187
+ throw e;
188
+ }
189
+ }
190
+ const wrappedLedger = Object.assign(Object.assign({}, ledger), { transactions: [], operations: [], effects: [], events: eventsForSequence });
191
+ const wrapperTxs = this.wrapTransactionsForLedger(sequence, transactions, operations, effects, eventsForSequence);
192
+ wrapperTxs.forEach((tx) => {
193
+ tx.ledger = (0, lodash_1.cloneDeep)(wrappedLedger);
194
+ tx.operations = tx.operations.map((op) => {
195
+ op.ledger = (0, lodash_1.cloneDeep)(wrappedLedger);
196
+ op.effects = op.effects.map((effect) => {
197
+ effect.ledger = (0, lodash_1.cloneDeep)(wrappedLedger);
198
+ return effect;
199
+ });
200
+ op.events = op.events.map((event) => {
201
+ event.ledger = (0, lodash_1.cloneDeep)(wrappedLedger);
202
+ return event;
203
+ });
204
+ return op;
205
+ });
206
+ wrappedLedger.transactions.push(tx);
207
+ wrappedLedger.operations.push(...tx.operations);
208
+ tx.operations.forEach((op) => {
209
+ wrappedLedger.effects.push(...op.effects);
210
+ });
211
+ });
212
+ const wrappedLedgerInstance = new block_stellar_1.StellarBlockWrapped(wrappedLedger, wrappedLedger.transactions, wrappedLedger.operations, wrappedLedger.effects, wrappedLedger.events);
213
+ return wrappedLedgerInstance;
84
214
  }
85
215
  async fetchBlocks(bufferBlocks) {
86
- return Promise.all(bufferBlocks.map(async (num) => this.fetchBlock(num, true)));
216
+ const ledgers = await Promise.all(bufferBlocks.map((sequence) => this.fetchAndWrapLedger(sequence)));
217
+ return ledgers;
87
218
  }
88
219
  get api() {
89
- return this.client;
220
+ return this.stellarClient;
90
221
  }
91
222
  getSafeApi(blockHeight) {
92
- return new safe_api_1.default(this.client, blockHeight);
223
+ //safe api not implemented yet
224
+ return new safe_api_1.default(null, blockHeight);
93
225
  }
94
226
  // eslint-disable-next-line @typescript-eslint/require-await
95
227
  async connect() {
@@ -1 +1 @@
1
- {"version":3,"file":"api.stellar.js","sourceRoot":"","sources":["../../src/stellar/api.stellar.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2020-2023 SubQuery Pte Ltd authors & contributors\n// SPDX-License-Identifier: GPL-3.0\n\nimport { EventEmitter2 } from '@nestjs/event-emitter';\nimport { getLogger } from '@subql/node-core';\nimport {\n ApiWrapper,\n StellarBlock,\n StellarBlockWrapper,\n} from '@subql/types-stellar';\nimport { Server, SorobanRpc, scValToNative, xdr } from 'soroban-client';\nimport { StellarBlockWrapped } from './block.stellar';\nimport SafeStellarProvider from './safe-api';\nimport { StellarServer } from './stellar.server';\n\n// eslint-disable-next-line @typescript-eslint/no-var-requires\nconst { version: packageVersion } = require('../../package.json');\n\nconst logger = getLogger('api.Stellar');\n\nexport class StellarApi implements ApiWrapper<StellarBlockWrapper> {\n private client: Server;\n\n private chainId: string;\n private name: string;\n\n constructor(private endpoint: string, private eventEmitter: EventEmitter2) {\n const { hostname, protocol, searchParams } = new URL(endpoint);\n\n const protocolStr = protocol.replace(':', '');\n\n logger.info(`Api host: ${hostname}, method: ${protocolStr}`);\n if (protocolStr === 'https' || protocolStr === 'http') {\n const options: Server.Options = {\n //headers: {\n // 'User-Agent': `Subquery-Node ${packageVersion}`,\n //},\n allowHttp: protocolStr === 'http',\n };\n //searchParams.forEach((value, name, searchParams) => {\n // (connection.headers as any)[name] = value;\n //});\n this.client = new StellarServer(endpoint, options);\n } else {\n throw new Error(`Unsupported protocol: ${protocol}`);\n }\n }\n\n async init(): Promise<void> {\n const network = await this.client.getNetwork();\n this.chainId = network.passphrase;\n }\n\n async getFinalizedBlock(): Promise<SorobanRpc.GetLatestLedgerResponse> {\n return this.client.getLatestLedger();\n }\n\n async getFinalizedBlockHeight(): Promise<number> {\n return (await this.getFinalizedBlock()).sequence;\n }\n\n async getBestBlockHeight(): Promise<number> {\n return (await this.getFinalizedBlockHeight()) + 1;\n }\n\n getRuntimeChain(): string {\n return this.name;\n }\n\n getChainId(): string {\n return this.chainId;\n }\n\n getGenesisHash(): string {\n return this.getChainId();\n }\n\n getSpecName(): string {\n return 'Stellar';\n }\n\n async getEvents(height: number): Promise<SorobanRpc.GetEventsResponse> {\n return this.client.getEvents({ startLedger: height, filters: [] });\n }\n\n async fetchBlock(\n blockNumber: number,\n includeTx?: boolean,\n ): Promise<StellarBlockWrapped> {\n try {\n const rawEvents = (await this.getEvents(blockNumber)).events;\n\n const events = rawEvents.map((event) => ({\n ...event,\n value: {\n ...event.value,\n get decoded() {\n return scValToNative(xdr.ScVal.fromXDR(event.value.xdr, 'base64'));\n },\n },\n topic: event.topic.map((topic) =>\n StellarBlockWrapped.decodeScVals(xdr.ScVal.fromXDR(topic, 'base64')),\n ),\n }));\n\n const ret = new StellarBlockWrapped(events, {\n ledger: blockNumber,\n hash: blockNumber.toString(),\n } as StellarBlock);\n\n this.eventEmitter.emit('fetchBlock');\n return ret;\n } catch (e) {\n throw this.handleError(e, blockNumber);\n }\n }\n\n async fetchBlocks(bufferBlocks: number[]): Promise<StellarBlockWrapper[]> {\n return Promise.all(\n bufferBlocks.map(async (num) => this.fetchBlock(num, true)),\n );\n }\n\n get api(): Server {\n return this.client;\n }\n\n getSafeApi(blockHeight: number): SafeStellarProvider {\n return new SafeStellarProvider(this.client, blockHeight);\n }\n\n // eslint-disable-next-line @typescript-eslint/require-await\n async connect(): Promise<void> {\n logger.error('Stellar API connect is not implemented');\n throw new Error('Not implemented');\n }\n\n // eslint-disable-next-line @typescript-eslint/require-await\n async disconnect(): Promise<void> {\n logger.error('Stellar API disconnect is not implemented');\n throw new Error('Not implemented');\n }\n\n handleError(e: Error, height: number): Error {\n if (e.message === 'start is before oldest ledger') {\n return new Error(`The requested ledger number ${height} is not available on the current blockchain node. \n This is because you're trying to access a ledger that is older than the oldest ledger stored in this node. \n To resolve this issue, you can either:\n 1. Increase the start ledger to a more recent one, or\n 2. Connect to a different node that might have a longer history of ledgers.`);\n }\n\n return e;\n }\n}\n"]}
1
+ {"version":3,"file":"api.stellar.js","sourceRoot":"","sources":["../../src/stellar/api.stellar.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2020-2023 SubQuery Pte Ltd authors & contributors\n// SPDX-License-Identifier: GPL-3.0\n\nimport { EventEmitter2 } from '@nestjs/event-emitter';\nimport { getLogger } from '@subql/node-core';\nimport {\n ApiWrapper,\n SorobanEvent,\n StellarBlock,\n StellarBlockWrapper,\n StellarEffect,\n StellarOperation,\n StellarTransaction,\n} from '@subql/types-stellar';\nimport { cloneDeep } from 'lodash';\nimport { Server, ServerApi } from 'stellar-sdk';\nimport { StellarBlockWrapped } from '../stellar/block.stellar';\nimport SafeStellarProvider from './safe-api';\nimport { SorobanServer } from './soroban.server';\nimport { StellarServer } from './stellar.server';\n\n// eslint-disable-next-line @typescript-eslint/no-var-requires\nconst { version: packageVersion } = require('../../package.json');\n\nconst logger = getLogger('api.Stellar');\n\nexport class StellarApi implements ApiWrapper<StellarBlockWrapper> {\n //private client: Server;\n private stellarClient: StellarServer;\n\n private chainId: string;\n private genesisHash: string;\n private name: string;\n\n constructor(\n private endpoint: string,\n private eventEmitter: EventEmitter2,\n private sorobanClient?: SorobanServer,\n ) {\n const { hostname, protocol, searchParams } = new URL(endpoint);\n\n const protocolStr = protocol.replace(':', '');\n\n logger.info(`Api host: ${hostname}, method: ${protocolStr}`);\n if (protocolStr === 'https' || protocolStr === 'http') {\n const options: Server.Options = {\n //headers: {\n // 'User-Agent': `Subquery-Node ${packageVersion}`,\n //},\n allowHttp: protocolStr === 'http',\n };\n //searchParams.forEach((value, name, searchParams) => {\n // (connection.headers as any)[name] = value;\n //});\n this.stellarClient = new StellarServer(endpoint, options);\n } else {\n throw new Error(`Unsupported protocol: ${protocol}`);\n }\n }\n\n async init(): Promise<void> {\n //need archive node for genesis hash\n //const genesisLedger = (await this.stellarClient.ledgers().ledger(1).call()).records[0];\n this.chainId = (await this.stellarClient.getNetwork()).network_passphrase;\n //this.genesisHash = genesisLedger.hash;\n }\n\n async getFinalizedBlock(): Promise<ServerApi.LedgerRecord> {\n return (await this.stellarClient.ledgers().order('desc').call()).records[0];\n }\n\n async getFinalizedBlockHeight(): Promise<number> {\n return (await this.getFinalizedBlock()).sequence;\n }\n\n async getBestBlockHeight(): Promise<number> {\n return (await this.getFinalizedBlockHeight()) + 1;\n }\n\n getRuntimeChain(): string {\n return this.name;\n }\n\n getChainId(): string {\n return this.chainId;\n }\n\n getGenesisHash(): string {\n return this.chainId;\n }\n\n getSpecName(): string {\n return 'Stellar';\n }\n\n private async fetchTransactionsForLedger(\n sequence: number,\n ): Promise<ServerApi.TransactionRecord[]> {\n const txs: ServerApi.TransactionRecord[] = [];\n let txsPage = await this.api.transactions().forLedger(sequence).call();\n while (txsPage.records.length !== 0) {\n txs.push(...txsPage.records);\n txsPage = await txsPage.next();\n }\n\n return txs;\n }\n\n private async fetchOperationsForLedger(\n sequence: number,\n ): Promise<ServerApi.OperationRecord[]> {\n const operations: ServerApi.OperationRecord[] = [];\n let operationsPage = await this.api.operations().forLedger(sequence).call();\n while (operationsPage.records.length !== 0) {\n operations.push(...operationsPage.records);\n operationsPage = await operationsPage.next();\n }\n\n return operations;\n }\n\n private async fetchEffectsForLedger(\n sequence: number,\n ): Promise<ServerApi.EffectRecord[]> {\n const effects: ServerApi.EffectRecord[] = [];\n let effectsPage = await this.api.effects().forLedger(sequence).call();\n while (effectsPage.records.length !== 0) {\n effects.push(...effectsPage.records);\n effectsPage = await effectsPage.next();\n }\n\n return effects;\n }\n\n private getTransactionApplicationOrder(eventId: string) {\n // Right shift the ID by 12 bits to exclude the Operation Index\n const shiftedId = BigInt(eventId.split('-')[0]) >> BigInt(12);\n\n // Create a mask for 20 bits to ignore the Ledger Sequence Number\n const mask = BigInt((1 << 20) - 1);\n\n // Apply bitwise AND operation with the mask to get the Transaction Application Order\n const transactionApplicationOrder = shiftedId & mask;\n return Number(transactionApplicationOrder);\n }\n\n private getOperationIndex(id: string) {\n // Pick the first part of the ID before the '-' character\n const idPart = id.split('-')[0];\n\n // Create a mask for 12 bits to isolate the Operation Index\n const mask = BigInt((1 << 12) - 1);\n\n // Apply bitwise AND operation with the mask to get the Operation Index\n const operationIndex = BigInt(idPart) & mask;\n\n return Number(operationIndex);\n }\n\n async getAndWrapEvents(height: number): Promise<SorobanEvent[]> {\n const { events: events } = await this.sorobanClient.getEvents({\n startLedger: height,\n filters: [],\n });\n return events.map((event) => {\n const wrappedEvent = {\n ...event,\n ledger: null,\n transaction: null,\n operation: null,\n } as SorobanEvent;\n\n return wrappedEvent;\n });\n }\n\n private wrapEffectsForOperation(\n operationIndex: number,\n effectsForSequence: ServerApi.EffectRecord[],\n ): StellarEffect[] {\n return effectsForSequence\n .filter((effect) => this.getOperationIndex(effect.id) === operationIndex)\n .map((effect) => ({\n ...effect,\n ledger: null,\n transaction: null,\n operation: null,\n }));\n }\n\n private wrapOperationsForTx(\n transactionId: string,\n applicationOrder: number,\n sequence: number,\n operationsForSequence: ServerApi.OperationRecord[],\n effectsForSequence: ServerApi.EffectRecord[],\n eventsForSequence: SorobanEvent[],\n ): StellarOperation[] {\n const operations = operationsForSequence.filter(\n (op) => op.transaction_hash === transactionId,\n );\n\n return operations.map((op, index) => {\n const effects = this.wrapEffectsForOperation(index, effectsForSequence);\n\n const events = eventsForSequence.filter(\n (event) =>\n this.getTransactionApplicationOrder(event.id) === applicationOrder,\n );\n\n const wrappedOp: StellarOperation = {\n ...op,\n ledger: null,\n transaction: null,\n effects: [],\n events,\n };\n\n effects.forEach((effect) => {\n effect.operation = cloneDeep(wrappedOp);\n wrappedOp.effects.push(effect);\n });\n\n return wrappedOp;\n });\n }\n\n private wrapTransactionsForLedger(\n sequence: number,\n transactions: ServerApi.TransactionRecord[],\n operationsForSequence: ServerApi.OperationRecord[],\n effectsForSequence: ServerApi.EffectRecord[],\n eventsForSequence: SorobanEvent[],\n ): StellarTransaction[] {\n return transactions.map((tx, index) => {\n const wrappedTx: StellarTransaction = {\n ...tx,\n ledger: null,\n operations: [] as StellarOperation[],\n effects: [] as StellarEffect[],\n events: [] as SorobanEvent[],\n };\n\n const operations = this.wrapOperationsForTx(\n tx.id,\n index + 1,\n sequence,\n operationsForSequence,\n effectsForSequence,\n eventsForSequence,\n ).map((op) => {\n op.transaction = cloneDeep(wrappedTx);\n op.effects = op.effects.map((effect) => {\n effect.transaction = cloneDeep(wrappedTx);\n return effect;\n });\n op.events = op.events.map((event) => {\n event.transaction = cloneDeep(wrappedTx);\n return event;\n });\n return op;\n });\n\n wrappedTx.operations.push(...operations);\n operations.forEach((op) => {\n wrappedTx.effects.push(...op.effects);\n wrappedTx.events.push(...op.events);\n });\n\n return wrappedTx;\n });\n }\n\n private async fetchAndWrapLedger(\n sequence: number,\n ): Promise<StellarBlockWrapper> {\n const [ledger, transactions, operations, effects] = await Promise.all([\n this.api.ledgers().ledger(sequence).call(),\n this.fetchTransactionsForLedger(sequence),\n this.fetchOperationsForLedger(sequence),\n this.fetchEffectsForLedger(sequence),\n ]);\n\n let eventsForSequence: SorobanEvent[] = [];\n\n //check if there is InvokeHostFunctionOp operation\n //If yes then, there are soroban transactions and we should we fetch soroban events\n const hasInvokeHostFunctionOp = operations.some(\n (op) => op.type.toString() === 'invoke_host_function',\n );\n\n if (this.sorobanClient && hasInvokeHostFunctionOp) {\n try {\n eventsForSequence = await this.getAndWrapEvents(sequence);\n } catch (e) {\n if (e.message === 'start is before oldest ledger') {\n throw new Error(`The requested events for ledger number ${sequence} is not available on the current soroban node. \n This is because you're trying to access a ledger that is older than the oldest ledger stored in this node. \n To resolve this issue, you can either:\n 1. Increase the start ledger to a more recent one, or\n 2. Connect to a different node that might have a longer history of ledgers.`);\n }\n\n throw e;\n }\n }\n\n const wrappedLedger: StellarBlock = {\n ...(ledger as unknown as ServerApi.LedgerRecord),\n transactions: [] as StellarTransaction[],\n operations: [] as StellarOperation[],\n effects: [] as StellarEffect[],\n events: eventsForSequence,\n };\n\n const wrapperTxs = this.wrapTransactionsForLedger(\n sequence,\n transactions,\n operations,\n effects,\n eventsForSequence,\n );\n\n wrapperTxs.forEach((tx) => {\n tx.ledger = cloneDeep(wrappedLedger);\n tx.operations = tx.operations.map((op) => {\n op.ledger = cloneDeep(wrappedLedger);\n op.effects = op.effects.map((effect) => {\n effect.ledger = cloneDeep(wrappedLedger);\n return effect;\n });\n op.events = op.events.map((event) => {\n event.ledger = cloneDeep(wrappedLedger);\n return event;\n });\n return op;\n });\n\n wrappedLedger.transactions.push(tx);\n wrappedLedger.operations.push(...tx.operations);\n\n tx.operations.forEach((op) => {\n wrappedLedger.effects.push(...op.effects);\n });\n });\n\n const wrappedLedgerInstance = new StellarBlockWrapped(\n wrappedLedger,\n wrappedLedger.transactions,\n wrappedLedger.operations,\n wrappedLedger.effects,\n wrappedLedger.events,\n );\n\n return wrappedLedgerInstance;\n }\n\n async fetchBlocks(bufferBlocks: number[]): Promise<StellarBlockWrapper[]> {\n const ledgers = await Promise.all(\n bufferBlocks.map((sequence) => this.fetchAndWrapLedger(sequence)),\n );\n return ledgers;\n }\n\n get api(): Server {\n return this.stellarClient;\n }\n\n getSafeApi(blockHeight: number): SafeStellarProvider {\n //safe api not implemented yet\n return new SafeStellarProvider(null, blockHeight);\n }\n\n // eslint-disable-next-line @typescript-eslint/require-await\n async connect(): Promise<void> {\n logger.error('Stellar API connect is not implemented');\n throw new Error('Not implemented');\n }\n\n // eslint-disable-next-line @typescript-eslint/require-await\n async disconnect(): Promise<void> {\n logger.error('Stellar API disconnect is not implemented');\n throw new Error('Not implemented');\n }\n\n handleError(e: Error, height: number): Error {\n if (e.message === 'start is before oldest ledger') {\n return new Error(`The requested ledger number ${height} is not available on the current blockchain node. \n This is because you're trying to access a ledger that is older than the oldest ledger stored in this node. \n To resolve this issue, you can either:\n 1. Increase the start ledger to a more recent one, or\n 2. Connect to a different node that might have a longer history of ledgers.`);\n }\n\n return e;\n }\n}\n"]}