@midnight-ntwrk/wallet-sdk-indexer-client 1.0.0-beta.11

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 (62) hide show
  1. package/README.md +1 -0
  2. package/dist/effect/ConnectionHelper.d.ts +4 -0
  3. package/dist/effect/ConnectionHelper.js +29 -0
  4. package/dist/effect/HttpQueryClient.d.ts +4 -0
  5. package/dist/effect/HttpQueryClient.js +38 -0
  6. package/dist/effect/Query.d.ts +46 -0
  7. package/dist/effect/Query.js +35 -0
  8. package/dist/effect/QueryClient.d.ts +15 -0
  9. package/dist/effect/QueryClient.js +3 -0
  10. package/dist/effect/Subscription.d.ts +21 -0
  11. package/dist/effect/Subscription.js +28 -0
  12. package/dist/effect/SubscriptionClient.d.ts +15 -0
  13. package/dist/effect/SubscriptionClient.js +3 -0
  14. package/dist/effect/WsSubscriptionClient.d.ts +4 -0
  15. package/dist/effect/WsSubscriptionClient.js +32 -0
  16. package/dist/effect/index.d.ts +7 -0
  17. package/dist/effect/index.js +7 -0
  18. package/dist/effect/test/httpQueryClient.spied.test.d.ts +1 -0
  19. package/dist/effect/test/httpQueryClient.spied.test.js +25 -0
  20. package/dist/effect/test/httpQueryClient.test.d.ts +1 -0
  21. package/dist/effect/test/httpQueryClient.test.js +20 -0
  22. package/dist/effect/test/wsSubscriptionClient.spied.test.d.ts +1 -0
  23. package/dist/effect/test/wsSubscriptionClient.spied.test.js +25 -0
  24. package/dist/effect/test/wsSubscriptionClient.test.d.ts +1 -0
  25. package/dist/effect/test/wsSubscriptionClient.test.js +20 -0
  26. package/dist/graphql/generated/fragment-masking.d.ts +19 -0
  27. package/dist/graphql/generated/fragment-masking.js +16 -0
  28. package/dist/graphql/generated/gql.d.ts +66 -0
  29. package/dist/graphql/generated/gql.js +14 -0
  30. package/dist/graphql/generated/graphql.d.ts +656 -0
  31. package/dist/graphql/generated/graphql.js +7 -0
  32. package/dist/graphql/generated/index.d.ts +2 -0
  33. package/dist/graphql/generated/index.js +2 -0
  34. package/dist/graphql/queries/BlockHash.d.ts +6 -0
  35. package/dist/graphql/queries/BlockHash.js +11 -0
  36. package/dist/graphql/queries/Connect.d.ts +6 -0
  37. package/dist/graphql/queries/Connect.js +7 -0
  38. package/dist/graphql/queries/Disconnect.d.ts +6 -0
  39. package/dist/graphql/queries/Disconnect.js +7 -0
  40. package/dist/graphql/queries/index.d.ts +3 -0
  41. package/dist/graphql/queries/index.js +3 -0
  42. package/dist/graphql/queries/test/BlockHash.test.d.ts +1 -0
  43. package/dist/graphql/queries/test/BlockHash.test.js +69 -0
  44. package/dist/graphql/subscriptions/DustLedgerEvents.d.ts +6 -0
  45. package/dist/graphql/subscriptions/DustLedgerEvents.js +12 -0
  46. package/dist/graphql/subscriptions/ShieldedTransactions.d.ts +8 -0
  47. package/dist/graphql/subscriptions/ShieldedTransactions.js +42 -0
  48. package/dist/graphql/subscriptions/UnshieldedTransactions.d.ts +8 -0
  49. package/dist/graphql/subscriptions/UnshieldedTransactions.js +49 -0
  50. package/dist/graphql/subscriptions/ZswapEvents.d.ts +6 -0
  51. package/dist/graphql/subscriptions/ZswapEvents.js +11 -0
  52. package/dist/graphql/subscriptions/index.d.ts +4 -0
  53. package/dist/graphql/subscriptions/index.js +4 -0
  54. package/dist/graphql/subscriptions/test/ShieldedTransactions.test.d.ts +1 -0
  55. package/dist/graphql/subscriptions/test/ShieldedTransactions.test.js +41 -0
  56. package/dist/graphql/subscriptions/test/UnshieldedTransactions.test.d.ts +1 -0
  57. package/dist/graphql/subscriptions/test/UnshieldedTransactions.test.js +38 -0
  58. package/dist/graphql/subscriptions/test/ZswapEvents.test.d.ts +1 -0
  59. package/dist/graphql/subscriptions/test/ZswapEvents.test.js +36 -0
  60. package/dist/index.d.ts +3 -0
  61. package/dist/index.js +3 -0
  62. package/package.json +61 -0
@@ -0,0 +1,7 @@
1
+ export const BlockHashDocument = { "kind": "Document", "definitions": [{ "kind": "OperationDefinition", "operation": "query", "name": { "kind": "Name", "value": "BlockHash" }, "variableDefinitions": [{ "kind": "VariableDefinition", "variable": { "kind": "Variable", "name": { "kind": "Name", "value": "offset" } }, "type": { "kind": "NamedType", "name": { "kind": "Name", "value": "BlockOffset" } } }], "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "block" }, "arguments": [{ "kind": "Argument", "name": { "kind": "Name", "value": "offset" }, "value": { "kind": "Variable", "name": { "kind": "Name", "value": "offset" } } }], "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "height" } }, { "kind": "Field", "name": { "kind": "Name", "value": "hash" } }, { "kind": "Field", "name": { "kind": "Name", "value": "ledgerParameters" } }] } }] } }] };
2
+ export const ConnectDocument = { "kind": "Document", "definitions": [{ "kind": "OperationDefinition", "operation": "mutation", "name": { "kind": "Name", "value": "Connect" }, "variableDefinitions": [{ "kind": "VariableDefinition", "variable": { "kind": "Variable", "name": { "kind": "Name", "value": "viewingKey" } }, "type": { "kind": "NonNullType", "type": { "kind": "NamedType", "name": { "kind": "Name", "value": "ViewingKey" } } } }], "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "connect" }, "arguments": [{ "kind": "Argument", "name": { "kind": "Name", "value": "viewingKey" }, "value": { "kind": "Variable", "name": { "kind": "Name", "value": "viewingKey" } } }] }] } }] };
3
+ export const DisconnectDocument = { "kind": "Document", "definitions": [{ "kind": "OperationDefinition", "operation": "mutation", "name": { "kind": "Name", "value": "Disconnect" }, "variableDefinitions": [{ "kind": "VariableDefinition", "variable": { "kind": "Variable", "name": { "kind": "Name", "value": "sessionId" } }, "type": { "kind": "NonNullType", "type": { "kind": "NamedType", "name": { "kind": "Name", "value": "HexEncoded" } } } }], "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "disconnect" }, "arguments": [{ "kind": "Argument", "name": { "kind": "Name", "value": "sessionId" }, "value": { "kind": "Variable", "name": { "kind": "Name", "value": "sessionId" } } }] }] } }] };
4
+ export const DustLedgerEventsDocument = { "kind": "Document", "definitions": [{ "kind": "OperationDefinition", "operation": "subscription", "name": { "kind": "Name", "value": "DustLedgerEvents" }, "variableDefinitions": [{ "kind": "VariableDefinition", "variable": { "kind": "Variable", "name": { "kind": "Name", "value": "id" } }, "type": { "kind": "NamedType", "name": { "kind": "Name", "value": "Int" } } }], "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "dustLedgerEvents" }, "arguments": [{ "kind": "Argument", "name": { "kind": "Name", "value": "id" }, "value": { "kind": "Variable", "name": { "kind": "Name", "value": "id" } } }], "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "alias": { "kind": "Name", "value": "type" }, "name": { "kind": "Name", "value": "__typename" } }, { "kind": "Field", "name": { "kind": "Name", "value": "id" } }, { "kind": "Field", "name": { "kind": "Name", "value": "raw" } }, { "kind": "Field", "name": { "kind": "Name", "value": "maxId" } }] } }] } }] };
5
+ export const ShieldedTransactionsDocument = { "kind": "Document", "definitions": [{ "kind": "OperationDefinition", "operation": "subscription", "name": { "kind": "Name", "value": "ShieldedTransactions" }, "variableDefinitions": [{ "kind": "VariableDefinition", "variable": { "kind": "Variable", "name": { "kind": "Name", "value": "sessionId" } }, "type": { "kind": "NonNullType", "type": { "kind": "NamedType", "name": { "kind": "Name", "value": "HexEncoded" } } } }, { "kind": "VariableDefinition", "variable": { "kind": "Variable", "name": { "kind": "Name", "value": "index" } }, "type": { "kind": "NamedType", "name": { "kind": "Name", "value": "Int" } } }], "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "shieldedTransactions" }, "arguments": [{ "kind": "Argument", "name": { "kind": "Name", "value": "sessionId" }, "value": { "kind": "Variable", "name": { "kind": "Name", "value": "sessionId" } } }, { "kind": "Argument", "name": { "kind": "Name", "value": "index" }, "value": { "kind": "Variable", "name": { "kind": "Name", "value": "index" } } }], "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "__typename" } }, { "kind": "InlineFragment", "typeCondition": { "kind": "NamedType", "name": { "kind": "Name", "value": "ShieldedTransactionsProgress" } }, "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "highestEndIndex" } }, { "kind": "Field", "name": { "kind": "Name", "value": "highestCheckedEndIndex" } }, { "kind": "Field", "name": { "kind": "Name", "value": "highestRelevantEndIndex" } }] } }, { "kind": "InlineFragment", "typeCondition": { "kind": "NamedType", "name": { "kind": "Name", "value": "RelevantTransaction" } }, "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "transaction" }, "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "id" } }, { "kind": "Field", "name": { "kind": "Name", "value": "raw" } }, { "kind": "Field", "name": { "kind": "Name", "value": "hash" } }, { "kind": "Field", "name": { "kind": "Name", "value": "protocolVersion" } }, { "kind": "Field", "name": { "kind": "Name", "value": "identifiers" } }, { "kind": "Field", "name": { "kind": "Name", "value": "startIndex" } }, { "kind": "Field", "name": { "kind": "Name", "value": "endIndex" } }, { "kind": "Field", "name": { "kind": "Name", "value": "fees" }, "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "paidFees" } }, { "kind": "Field", "name": { "kind": "Name", "value": "estimatedFees" } }] } }, { "kind": "Field", "name": { "kind": "Name", "value": "transactionResult" }, "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "status" } }, { "kind": "Field", "name": { "kind": "Name", "value": "segments" }, "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "id" } }, { "kind": "Field", "name": { "kind": "Name", "value": "success" } }] } }] } }] } }, { "kind": "Field", "name": { "kind": "Name", "value": "collapsedMerkleTree" }, "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "startIndex" } }, { "kind": "Field", "name": { "kind": "Name", "value": "endIndex" } }, { "kind": "Field", "name": { "kind": "Name", "value": "update" } }, { "kind": "Field", "name": { "kind": "Name", "value": "protocolVersion" } }] } }] } }] } }] } }] };
6
+ export const UnshieldedTransactionsDocument = { "kind": "Document", "definitions": [{ "kind": "OperationDefinition", "operation": "subscription", "name": { "kind": "Name", "value": "UnshieldedTransactions" }, "variableDefinitions": [{ "kind": "VariableDefinition", "variable": { "kind": "Variable", "name": { "kind": "Name", "value": "address" } }, "type": { "kind": "NonNullType", "type": { "kind": "NamedType", "name": { "kind": "Name", "value": "UnshieldedAddress" } } } }, { "kind": "VariableDefinition", "variable": { "kind": "Variable", "name": { "kind": "Name", "value": "transactionId" } }, "type": { "kind": "NamedType", "name": { "kind": "Name", "value": "Int" } } }], "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "unshieldedTransactions" }, "arguments": [{ "kind": "Argument", "name": { "kind": "Name", "value": "address" }, "value": { "kind": "Variable", "name": { "kind": "Name", "value": "address" } } }, { "kind": "Argument", "name": { "kind": "Name", "value": "transactionId" }, "value": { "kind": "Variable", "name": { "kind": "Name", "value": "transactionId" } } }], "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "InlineFragment", "typeCondition": { "kind": "NamedType", "name": { "kind": "Name", "value": "UnshieldedTransaction" } }, "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "alias": { "kind": "Name", "value": "type" }, "name": { "kind": "Name", "value": "__typename" } }, { "kind": "Field", "name": { "kind": "Name", "value": "transaction" }, "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "alias": { "kind": "Name", "value": "type" }, "name": { "kind": "Name", "value": "__typename" } }, { "kind": "Field", "name": { "kind": "Name", "value": "id" } }, { "kind": "Field", "name": { "kind": "Name", "value": "hash" } }, { "kind": "Field", "name": { "kind": "Name", "value": "protocolVersion" } }, { "kind": "InlineFragment", "typeCondition": { "kind": "NamedType", "name": { "kind": "Name", "value": "RegularTransaction" } }, "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "identifiers" } }, { "kind": "Field", "name": { "kind": "Name", "value": "transactionResult" }, "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "status" } }, { "kind": "Field", "name": { "kind": "Name", "value": "segments" }, "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "id" } }, { "kind": "Field", "name": { "kind": "Name", "value": "success" } }] } }] } }] } }] } }, { "kind": "Field", "name": { "kind": "Name", "value": "createdUtxos" }, "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "owner" } }, { "kind": "Field", "name": { "kind": "Name", "value": "tokenType" } }, { "kind": "Field", "name": { "kind": "Name", "value": "value" } }, { "kind": "Field", "name": { "kind": "Name", "value": "outputIndex" } }, { "kind": "Field", "name": { "kind": "Name", "value": "intentHash" } }, { "kind": "Field", "name": { "kind": "Name", "value": "ctime" } }, { "kind": "Field", "name": { "kind": "Name", "value": "registeredForDustGeneration" } }] } }, { "kind": "Field", "name": { "kind": "Name", "value": "spentUtxos" }, "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "owner" } }, { "kind": "Field", "name": { "kind": "Name", "value": "tokenType" } }, { "kind": "Field", "name": { "kind": "Name", "value": "value" } }, { "kind": "Field", "name": { "kind": "Name", "value": "outputIndex" } }, { "kind": "Field", "name": { "kind": "Name", "value": "intentHash" } }, { "kind": "Field", "name": { "kind": "Name", "value": "ctime" } }, { "kind": "Field", "name": { "kind": "Name", "value": "registeredForDustGeneration" } }] } }] } }, { "kind": "InlineFragment", "typeCondition": { "kind": "NamedType", "name": { "kind": "Name", "value": "UnshieldedTransactionsProgress" } }, "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "alias": { "kind": "Name", "value": "type" }, "name": { "kind": "Name", "value": "__typename" } }, { "kind": "Field", "name": { "kind": "Name", "value": "highestTransactionId" } }] } }] } }] } }] };
7
+ export const ZswapEventsDocument = { "kind": "Document", "definitions": [{ "kind": "OperationDefinition", "operation": "subscription", "name": { "kind": "Name", "value": "ZswapEvents" }, "variableDefinitions": [{ "kind": "VariableDefinition", "variable": { "kind": "Variable", "name": { "kind": "Name", "value": "id" } }, "type": { "kind": "NamedType", "name": { "kind": "Name", "value": "Int" } } }], "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "zswapLedgerEvents" }, "arguments": [{ "kind": "Argument", "name": { "kind": "Name", "value": "id" }, "value": { "kind": "Variable", "name": { "kind": "Name", "value": "id" } } }], "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "id" } }, { "kind": "Field", "name": { "kind": "Name", "value": "raw" } }, { "kind": "Field", "name": { "kind": "Name", "value": "maxId" } }] } }] } }] };
@@ -0,0 +1,2 @@
1
+ export * from './fragment-masking.js';
2
+ export * from './gql.js';
@@ -0,0 +1,2 @@
1
+ export * from './fragment-masking.js';
2
+ export * from './gql.js';
@@ -0,0 +1,6 @@
1
+ import { Query } from '../../effect/index.js';
2
+ export declare const BlockHash: Query.Query<import("../generated/graphql.js").BlockHashQuery, import("../generated/graphql.js").Exact<{
3
+ offset: import("../generated/graphql.js").InputMaybe<import("../generated/graphql.js").BlockOffset>;
4
+ }>, Query.Query.QueryFn<import("../generated/graphql.js").BlockHashQuery, import("../generated/graphql.js").Exact<{
5
+ offset: import("../generated/graphql.js").InputMaybe<import("../generated/graphql.js").BlockOffset>;
6
+ }>>>;
@@ -0,0 +1,11 @@
1
+ import { Query } from '../../effect/index.js';
2
+ import { gql } from '../generated/index.js';
3
+ export const BlockHash = Query.make('BlockHash', gql(`
4
+ query BlockHash($offset: BlockOffset) {
5
+ block(offset: $offset) {
6
+ height
7
+ hash
8
+ ledgerParameters
9
+ }
10
+ }
11
+ `));
@@ -0,0 +1,6 @@
1
+ import { Query } from '../../effect/index.js';
2
+ export declare const Connect: Query.Query<import("../generated/graphql.js").ConnectMutation, import("../generated/graphql.js").Exact<{
3
+ viewingKey: import("../generated/graphql.js").Scalars["ViewingKey"]["input"];
4
+ }>, Query.Query.QueryFn<import("../generated/graphql.js").ConnectMutation, import("../generated/graphql.js").Exact<{
5
+ viewingKey: import("../generated/graphql.js").Scalars["ViewingKey"]["input"];
6
+ }>>>;
@@ -0,0 +1,7 @@
1
+ import { Query } from '../../effect/index.js';
2
+ import { gql } from '../generated/index.js';
3
+ export const Connect = Query.make('Connect', gql(`
4
+ mutation Connect($viewingKey: ViewingKey!) {
5
+ connect(viewingKey: $viewingKey)
6
+ }
7
+ `));
@@ -0,0 +1,6 @@
1
+ import { Query } from '../../effect/index.js';
2
+ export declare const Disconnect: Query.Query<import("../generated/graphql.js").DisconnectMutation, import("../generated/graphql.js").Exact<{
3
+ sessionId: import("../generated/graphql.js").Scalars["HexEncoded"]["input"];
4
+ }>, Query.Query.QueryFn<import("../generated/graphql.js").DisconnectMutation, import("../generated/graphql.js").Exact<{
5
+ sessionId: import("../generated/graphql.js").Scalars["HexEncoded"]["input"];
6
+ }>>>;
@@ -0,0 +1,7 @@
1
+ import { Query } from '../../effect/index.js';
2
+ import { gql } from '../generated/index.js';
3
+ export const Disconnect = Query.make('Disconnect', gql(`
4
+ mutation Disconnect($sessionId: HexEncoded!) {
5
+ disconnect(sessionId: $sessionId)
6
+ }
7
+ `));
@@ -0,0 +1,3 @@
1
+ export * from './Connect.js';
2
+ export * from './Disconnect.js';
3
+ export * from './BlockHash.js';
@@ -0,0 +1,3 @@
1
+ export * from './Connect.js';
2
+ export * from './Disconnect.js';
3
+ export * from './BlockHash.js';
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,69 @@
1
+ /* eslint-disable @typescript-eslint/no-unsafe-assignment */
2
+ import { Effect, Option } from 'effect';
3
+ import { randomUUID } from 'node:crypto';
4
+ import * as path from 'node:path';
5
+ import { DockerComposeEnvironment, Wait } from 'testcontainers';
6
+ import { afterAll, beforeAll, describe, expect, it, vi } from 'vitest';
7
+ import { HttpQueryClient } from '../../../effect/index.js';
8
+ import { BlockHash } from '../BlockHash.js';
9
+ const COMPOSE_PATH = path.resolve(new URL(import.meta.url).pathname, '../../../../../');
10
+ const timeout_minutes = (mins) => 1_000 * 60 * mins;
11
+ describe('BlockHash query', () => {
12
+ describe('with available Indexer Server', () => {
13
+ const environmentId = randomUUID();
14
+ let environment = undefined;
15
+ const getIndexerPort = () => environment?.getContainer(`indexer_${environmentId}`)?.getMappedPort(8088) ?? 8088;
16
+ beforeAll(async () => {
17
+ environment = await new DockerComposeEnvironment(COMPOSE_PATH, 'docker-compose.yml')
18
+ .withEnvironment({
19
+ TESTCONTAINERS_UID: environmentId,
20
+ })
21
+ // The test below assumes indexer is able to serve blocks, so we wait for it to index at least one block
22
+ // Otherwise the test below would be flakey or not precise enough to be useful
23
+ // Inspecting logs is not the best idea, but here it's the only way
24
+ .withWaitStrategy(`indexer_${environmentId}`, Wait.forLogMessage(/block indexed/))
25
+ .up();
26
+ }, timeout_minutes(3));
27
+ afterAll(async () => {
28
+ await environment?.down();
29
+ }, timeout_minutes(1));
30
+ it('should fail with ClientError for unknown URL', async () => {
31
+ await BlockHash.run({ offset: null }).pipe(Effect.catchSome((err) => (err._tag === 'ClientError' ? Option.some(Effect.succeed(void 0)) : Option.none())), Effect.catchAll((err) => Effect.fail(`Encountered unexpected '${err._tag}' error: ${err.message}`)), Effect.flatMap((data) => (data ? Effect.fail('Unexpectedly received data') : Effect.succeed(void 0))), Effect.provide(HttpQueryClient.layer({ url: `http://127.0.0.1:${getIndexerPort()}/a__p__i/v3/graphql` })), Effect.scoped, Effect.runPromise);
32
+ }, timeout_minutes(1));
33
+ it('should invoke GraphQL query', async () => {
34
+ // Expect a result containing a block with any height and hash value.
35
+ const blockExpectation = expect.objectContaining({
36
+ block: expect.objectContaining({
37
+ height: expect.any(Number),
38
+ hash: expect.any(String),
39
+ }),
40
+ });
41
+ await Effect.gen(function* () {
42
+ const query = yield* BlockHash;
43
+ const result = yield* query({ offset: null });
44
+ expect(result).toEqual(blockExpectation);
45
+ }).pipe(Effect.provide(HttpQueryClient.layer({ url: `http://127.0.0.1:${getIndexerPort()}/api/v3/graphql` })), Effect.scoped, Effect.catchAll((err) => Effect.fail(`Encountered unexpected error: ${err.message}`)), Effect.runPromise);
46
+ }, timeout_minutes(1));
47
+ });
48
+ it('should support query function injection', async () => {
49
+ const block = { block: { height: 1_000, hash: 'SOME_HASH', ledgerParameters: '0x0' } };
50
+ const blockExpectation = expect.objectContaining({
51
+ block: expect.objectContaining({
52
+ height: block.block.height,
53
+ hash: block.block.hash,
54
+ ledgerParameters: block.block.ledgerParameters,
55
+ }),
56
+ });
57
+ const mockedQueryFn = vi.fn();
58
+ mockedQueryFn.mockReturnValue(Effect.succeed(block));
59
+ await Effect.gen(function* () {
60
+ const query = yield* BlockHash;
61
+ const result = yield* query({ offset: null });
62
+ expect(result).toEqual(blockExpectation);
63
+ }).pipe(Effect.provideService(BlockHash.tag, mockedQueryFn), Effect.provide(HttpQueryClient.layer({ url: 'http://127.0.0.1:8088/a__p__i/v3/graphql' })), Effect.scoped, Effect.catchAll((err) => Effect.fail(`Encountered unexpected error: ${err.message}`)), Effect.runPromise);
64
+ await Effect.gen(function* () {
65
+ const result = yield* BlockHash.run({ offset: null });
66
+ expect(result).toEqual(blockExpectation);
67
+ }).pipe(Effect.provideService(BlockHash.tag, mockedQueryFn), Effect.provide(HttpQueryClient.layer({ url: 'http://127.0.0.1:8088/a__p__i/v3/graphql' })), Effect.scoped, Effect.catchAll((err) => Effect.fail(`Encountered unexpected error: ${err.message}`)), Effect.runPromise);
68
+ });
69
+ });
@@ -0,0 +1,6 @@
1
+ import { Subscription } from '../../effect/index.js';
2
+ export declare const DustLedgerEvents: Subscription.Subscription<import("../generated/graphql.js").DustLedgerEventsSubscription, import("../generated/graphql.js").Exact<{
3
+ id: import("../generated/graphql.js").InputMaybe<import("../generated/graphql.js").Scalars["Int"]["input"]>;
4
+ }>, Subscription.Subscription.SubscriptionFn<import("../generated/graphql.js").DustLedgerEventsSubscription, import("../generated/graphql.js").Exact<{
5
+ id: import("../generated/graphql.js").InputMaybe<import("../generated/graphql.js").Scalars["Int"]["input"]>;
6
+ }>>>;
@@ -0,0 +1,12 @@
1
+ import { Subscription } from '../../effect/index.js';
2
+ import { gql } from '../generated/index.js';
3
+ export const DustLedgerEvents = Subscription.make('DustLedgerEvents', gql(`
4
+ subscription DustLedgerEvents($id: Int) {
5
+ dustLedgerEvents(id: $id) {
6
+ type: __typename
7
+ id
8
+ raw
9
+ maxId
10
+ }
11
+ }
12
+ `));
@@ -0,0 +1,8 @@
1
+ import { Subscription } from '../../effect/index.js';
2
+ export declare const ShieldedTransactions: Subscription.Subscription<import("../generated/graphql.js").ShieldedTransactionsSubscription, import("../generated/graphql.js").Exact<{
3
+ sessionId: import("../generated/graphql.js").Scalars["HexEncoded"]["input"];
4
+ index: import("../generated/graphql.js").InputMaybe<import("../generated/graphql.js").Scalars["Int"]["input"]>;
5
+ }>, Subscription.Subscription.SubscriptionFn<import("../generated/graphql.js").ShieldedTransactionsSubscription, import("../generated/graphql.js").Exact<{
6
+ sessionId: import("../generated/graphql.js").Scalars["HexEncoded"]["input"];
7
+ index: import("../generated/graphql.js").InputMaybe<import("../generated/graphql.js").Scalars["Int"]["input"]>;
8
+ }>>>;
@@ -0,0 +1,42 @@
1
+ import { Subscription } from '../../effect/index.js';
2
+ import { gql } from '../generated/index.js';
3
+ export const ShieldedTransactions = Subscription.make('ShieldedTransactions', gql(`
4
+ subscription ShieldedTransactions($sessionId: HexEncoded!, $index: Int) {
5
+ shieldedTransactions(sessionId: $sessionId, index: $index) {
6
+ __typename
7
+ ... on ShieldedTransactionsProgress {
8
+ highestEndIndex
9
+ highestCheckedEndIndex
10
+ highestRelevantEndIndex
11
+ }
12
+ ... on RelevantTransaction {
13
+ transaction {
14
+ id
15
+ raw
16
+ hash
17
+ protocolVersion
18
+ identifiers
19
+ startIndex
20
+ endIndex
21
+ fees {
22
+ paidFees
23
+ estimatedFees
24
+ }
25
+ transactionResult {
26
+ status
27
+ segments {
28
+ id
29
+ success
30
+ }
31
+ }
32
+ }
33
+ collapsedMerkleTree {
34
+ startIndex
35
+ endIndex
36
+ update
37
+ protocolVersion
38
+ }
39
+ }
40
+ }
41
+ }
42
+ `));
@@ -0,0 +1,8 @@
1
+ import { Subscription } from '../../effect/index.js';
2
+ export declare const UnshieldedTransactions: Subscription.Subscription<import("../generated/graphql.js").UnshieldedTransactionsSubscription, import("../generated/graphql.js").Exact<{
3
+ address: import("../generated/graphql.js").Scalars["UnshieldedAddress"]["input"];
4
+ transactionId: import("../generated/graphql.js").InputMaybe<import("../generated/graphql.js").Scalars["Int"]["input"]>;
5
+ }>, Subscription.Subscription.SubscriptionFn<import("../generated/graphql.js").UnshieldedTransactionsSubscription, import("../generated/graphql.js").Exact<{
6
+ address: import("../generated/graphql.js").Scalars["UnshieldedAddress"]["input"];
7
+ transactionId: import("../generated/graphql.js").InputMaybe<import("../generated/graphql.js").Scalars["Int"]["input"]>;
8
+ }>>>;
@@ -0,0 +1,49 @@
1
+ import { Subscription } from '../../effect/index.js';
2
+ import { gql } from '../generated/index.js';
3
+ export const UnshieldedTransactions = Subscription.make('UnshieldedTransactions', gql(`
4
+ subscription UnshieldedTransactions($address: UnshieldedAddress!, $transactionId: Int) {
5
+ unshieldedTransactions(address: $address, transactionId: $transactionId) {
6
+ ... on UnshieldedTransaction {
7
+ type: __typename
8
+ transaction {
9
+ type: __typename
10
+ id
11
+ hash
12
+ protocolVersion
13
+ ... on RegularTransaction {
14
+ identifiers
15
+ transactionResult {
16
+ status
17
+ segments {
18
+ id
19
+ success
20
+ }
21
+ }
22
+ }
23
+ }
24
+ createdUtxos {
25
+ owner
26
+ tokenType
27
+ value
28
+ outputIndex
29
+ intentHash
30
+ ctime
31
+ registeredForDustGeneration
32
+ }
33
+ spentUtxos {
34
+ owner
35
+ tokenType
36
+ value
37
+ outputIndex
38
+ intentHash
39
+ ctime
40
+ registeredForDustGeneration
41
+ }
42
+ }
43
+ ... on UnshieldedTransactionsProgress {
44
+ type: __typename
45
+ highestTransactionId
46
+ }
47
+ }
48
+ }
49
+ `));
@@ -0,0 +1,6 @@
1
+ import { Subscription } from '../../effect/index.js';
2
+ export declare const ZswapEvents: Subscription.Subscription<import("../generated/graphql.js").ZswapEventsSubscription, import("../generated/graphql.js").Exact<{
3
+ id: import("../generated/graphql.js").InputMaybe<import("../generated/graphql.js").Scalars["Int"]["input"]>;
4
+ }>, Subscription.Subscription.SubscriptionFn<import("../generated/graphql.js").ZswapEventsSubscription, import("../generated/graphql.js").Exact<{
5
+ id: import("../generated/graphql.js").InputMaybe<import("../generated/graphql.js").Scalars["Int"]["input"]>;
6
+ }>>>;
@@ -0,0 +1,11 @@
1
+ import { Subscription } from '../../effect/index.js';
2
+ import { gql } from '../generated/index.js';
3
+ export const ZswapEvents = Subscription.make('ZswapEvents', gql(`
4
+ subscription ZswapEvents($id: Int) {
5
+ zswapLedgerEvents(id: $id) {
6
+ id
7
+ raw
8
+ maxId
9
+ }
10
+ }
11
+ `));
@@ -0,0 +1,4 @@
1
+ export * from './DustLedgerEvents.js';
2
+ export * from './ShieldedTransactions.js';
3
+ export * from './UnshieldedTransactions.js';
4
+ export * from './ZswapEvents.js';
@@ -0,0 +1,4 @@
1
+ export * from './DustLedgerEvents.js';
2
+ export * from './ShieldedTransactions.js';
3
+ export * from './UnshieldedTransactions.js';
4
+ export * from './ZswapEvents.js';
@@ -0,0 +1,41 @@
1
+ import { Effect, Stream } from 'effect';
2
+ import { randomUUID } from 'node:crypto';
3
+ import * as path from 'node:path';
4
+ import { DockerComposeEnvironment, Wait } from 'testcontainers';
5
+ import { afterAll, beforeAll, describe, expect, it } from 'vitest';
6
+ import { HttpQueryClient, WsSubscriptionClient } from '../../../effect/index.js';
7
+ import { Connect, Disconnect } from '../../queries/index.js';
8
+ import { ShieldedTransactions } from '../ShieldedTransactions.js';
9
+ const COMPOSE_PATH = path.resolve(new URL(import.meta.url).pathname, '../../../../../');
10
+ const KNOWN_VIEWING_KEY = 'mn_shield-esk_undeployed1d45kgmnfva58gwn9de3hy7tsw35k7m3dwdjkxun9wskkketetdmrzhf6dlyj7u8juj68fd4psnkqhjxh32sec0q480vzswg8kd485e2kljcsmxqc0u';
11
+ const timeout_minutes = (mins) => 1_000 * 60 * mins;
12
+ describe('Wallet subscription', () => {
13
+ describe('with available Indexer Server', () => {
14
+ const environmentId = randomUUID();
15
+ let environment = undefined;
16
+ const getIndexerPort = () => environment?.getContainer(`indexer_${environmentId}`).getMappedPort(8088) ?? 8088;
17
+ beforeAll(async () => {
18
+ environment = await new DockerComposeEnvironment(COMPOSE_PATH, 'docker-compose.yml')
19
+ .withEnvironment({
20
+ TESTCONTAINERS_UID: environmentId,
21
+ })
22
+ .withWaitStrategy(`node_${environmentId}`, Wait.forListeningPorts())
23
+ .withWaitStrategy(`indexer_${environmentId}`, Wait.forListeningPorts())
24
+ .up();
25
+ }, timeout_minutes(3));
26
+ afterAll(async () => {
27
+ await environment?.down();
28
+ }, timeout_minutes(1));
29
+ it('should stream GraphQL subscription', async () => {
30
+ const makeScopedSession = Effect.acquireRelease(Connect.run({ viewingKey: KNOWN_VIEWING_KEY }), (session) => Disconnect.run({ sessionId: session.connect }).pipe(Effect.catchAll((_) => Effect.void)));
31
+ await Effect.gen(function* () {
32
+ const session = yield* makeScopedSession;
33
+ const events = yield* ShieldedTransactions.run({
34
+ sessionId: session.connect,
35
+ index: null,
36
+ }).pipe(Stream.take(2), Stream.tap((data) => Effect.log(data.shieldedTransactions.__typename)), Stream.runCollect);
37
+ expect(events).toHaveLength(2);
38
+ }).pipe(Effect.provide(HttpQueryClient.layer({ url: `http://127.0.0.1:${getIndexerPort()}/api/v3/graphql` })), Effect.provide(WsSubscriptionClient.layer({ url: `ws://127.0.0.1:${getIndexerPort()}/api/v3/graphql/ws` })), Effect.scoped, Effect.runPromise);
39
+ }, timeout_minutes(1));
40
+ });
41
+ });
@@ -0,0 +1,38 @@
1
+ import { Effect, Stream } from 'effect';
2
+ import { randomUUID } from 'node:crypto';
3
+ import * as path from 'node:path';
4
+ import { DockerComposeEnvironment, Wait } from 'testcontainers';
5
+ import { afterAll, beforeAll, describe, expect, it } from 'vitest';
6
+ import { WsSubscriptionClient } from '../../../effect/index.js';
7
+ import { UnshieldedTransactions } from '../UnshieldedTransactions.js';
8
+ const COMPOSE_PATH = path.resolve(new URL(import.meta.url).pathname, '../../../../../');
9
+ const timeout_minutes = (mins) => 1_000 * 60 * mins;
10
+ const ADDRESS = 'mn_addr_undeployed1rhqz8aq6t74ym2uq5gh53t9x02gducxnamtdvnjxfhelxwaf8ztqpmrwwj';
11
+ describe('Wallet subscription', () => {
12
+ describe('with available Indexer Server', () => {
13
+ const environmentId = randomUUID();
14
+ let environment = undefined;
15
+ const getIndexerPort = () => environment?.getContainer(`indexer_${environmentId}`).getMappedPort(8088) ?? 8088;
16
+ beforeAll(async () => {
17
+ environment = await new DockerComposeEnvironment(COMPOSE_PATH, 'docker-compose.yml')
18
+ .withEnvironment({
19
+ TESTCONTAINERS_UID: environmentId,
20
+ })
21
+ .withWaitStrategy(`node_${environmentId}`, Wait.forListeningPorts())
22
+ .withWaitStrategy(`indexer_${environmentId}`, Wait.forLogMessage(/block indexed/))
23
+ .up();
24
+ }, timeout_minutes(3));
25
+ afterAll(async () => {
26
+ await environment?.down();
27
+ }, timeout_minutes(1));
28
+ it('should stream GraphQL subscription', async () => {
29
+ await Effect.gen(function* () {
30
+ const events = yield* UnshieldedTransactions.run({
31
+ address: ADDRESS,
32
+ transactionId: 0,
33
+ }).pipe(Stream.take(2), Stream.tap((data) => Effect.log(data.unshieldedTransactions.type)), Stream.runCollect);
34
+ expect(events).toHaveLength(2);
35
+ }).pipe(Effect.provide(WsSubscriptionClient.layer({ url: `ws://127.0.0.1:${getIndexerPort()}/api/v3/graphql/ws` })), Effect.scoped, Effect.runPromise);
36
+ }, timeout_minutes(1));
37
+ });
38
+ });
@@ -0,0 +1,36 @@
1
+ import { Effect, Stream } from 'effect';
2
+ import { randomUUID } from 'node:crypto';
3
+ import * as path from 'node:path';
4
+ import { DockerComposeEnvironment, Wait } from 'testcontainers';
5
+ import { afterAll, beforeAll, describe, expect, it } from 'vitest';
6
+ import { WsSubscriptionClient } from '../../../effect/index.js';
7
+ import { ZswapEvents } from '../ZswapEvents.js';
8
+ const COMPOSE_PATH = path.resolve(new URL(import.meta.url).pathname, '../../../../../');
9
+ const timeout_minutes = (mins) => 1_000 * 60 * mins;
10
+ describe('ZSwap events subscription', () => {
11
+ describe('with available Indexer Server', () => {
12
+ const environmentId = randomUUID();
13
+ let environment = undefined;
14
+ const getIndexerPort = () => environment?.getContainer(`indexer_${environmentId}`).getMappedPort(8088) ?? 8088;
15
+ beforeAll(async () => {
16
+ environment = await new DockerComposeEnvironment(COMPOSE_PATH, 'docker-compose.yml')
17
+ .withEnvironment({
18
+ TESTCONTAINERS_UID: environmentId,
19
+ })
20
+ .withWaitStrategy(`node_${environmentId}`, Wait.forListeningPorts())
21
+ .withWaitStrategy(`indexer_${environmentId}`, Wait.forLogMessage(/block indexed/))
22
+ .up();
23
+ }, timeout_minutes(3));
24
+ afterAll(async () => {
25
+ await environment?.down();
26
+ }, timeout_minutes(1));
27
+ it('should stream GraphQL subscription', async () => {
28
+ await Effect.gen(function* () {
29
+ const events = yield* ZswapEvents.run({
30
+ id: 0,
31
+ }).pipe(Stream.take(2), Stream.tap((data) => Effect.log(`ID=${data.zswapLedgerEvents.id}, MAX_ID=${data.zswapLedgerEvents.maxId}`)), Stream.runCollect);
32
+ expect(events).toHaveLength(2);
33
+ }).pipe(Effect.provide(WsSubscriptionClient.layer({ url: `ws://127.0.0.1:${getIndexerPort()}/api/v3/graphql/ws` })), Effect.scoped, Effect.runPromise);
34
+ }, timeout_minutes(1));
35
+ });
36
+ });
@@ -0,0 +1,3 @@
1
+ export * from './graphql/queries/index.js';
2
+ export * from './graphql/subscriptions/index.js';
3
+ export * from './graphql/generated/graphql.js';
package/dist/index.js ADDED
@@ -0,0 +1,3 @@
1
+ export * from './graphql/queries/index.js';
2
+ export * from './graphql/subscriptions/index.js';
3
+ export * from './graphql/generated/graphql.js';
package/package.json ADDED
@@ -0,0 +1,61 @@
1
+ {
2
+ "name": "@midnight-ntwrk/wallet-sdk-indexer-client",
3
+ "version": "1.0.0-beta.11",
4
+ "type": "module",
5
+ "module": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "author": "IOHK",
8
+ "license": "Apache-2.0",
9
+ "publishConfig": {
10
+ "registry": "https://npm.pkg.github.com/"
11
+ },
12
+ "files": [
13
+ "dist/"
14
+ ],
15
+ "repository": {
16
+ "type": "git",
17
+ "url": "git+https://github.com/midnight-ntwrk/artifacts.git"
18
+ },
19
+ "exports": {
20
+ ".": {
21
+ "types": "./dist/index.d.ts",
22
+ "import": "./dist/index.js"
23
+ },
24
+ "./effect": {
25
+ "types": "./dist/effect/index.d.ts",
26
+ "import": "./dist/effect/index.js"
27
+ }
28
+ },
29
+ "dependencies": {
30
+ "@effect/platform": "^0.90.0",
31
+ "@graphql-typed-document-node/core": "^3.2.0",
32
+ "@midnight-ntwrk/wallet-sdk-abstractions": "1.0.0-beta.8",
33
+ "@midnight-ntwrk/wallet-sdk-utilities": "1.0.0-beta.7",
34
+ "effect": "^3.17.3",
35
+ "graphql": "^16.11.0",
36
+ "graphql-http": "^1.22.4",
37
+ "graphql-ws": "^6.0.5"
38
+ },
39
+ "devDependencies": {
40
+ "@graphql-codegen/cli": "^5.0.7",
41
+ "@graphql-codegen/client-preset": "^4.8.2",
42
+ "@graphql-codegen/typescript": "^4.1.6",
43
+ "@graphql-codegen/typescript-operations": "^4.6.1",
44
+ "eslint": "^9.37.0",
45
+ "publint": "~0.3.14",
46
+ "rimraf": "^6.0.1",
47
+ "testcontainers": "^11.4.0",
48
+ "typescript": "^5.9.3",
49
+ "vitest": "^3.2.4"
50
+ },
51
+ "scripts": {
52
+ "gql:codegen": "graphql-codegen",
53
+ "typecheck": "tsc -b ./tsconfig.json --noEmit",
54
+ "test": "vitest run",
55
+ "lint": "eslint",
56
+ "dist": "tsc -b ./tsconfig.build.json",
57
+ "dist:publish": "tsc -b ./tsconfig.publish.json",
58
+ "clean": "rimraf --glob dist 'tsconfig.*.tsbuildinfo' && date +%s > .clean-timestamp",
59
+ "publint": "publint --strict"
60
+ }
61
+ }