@midnight-ntwrk/wallet-sdk-node-client 1.0.0 → 1.0.1

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.
@@ -1,21 +1,21 @@
1
1
  import { Context, Effect, Stream } from 'effect';
2
2
  import * as SubmissionEvent from './SubmissionEvent.js';
3
3
  import * as NodeClientError from './NodeClientError.js';
4
- export type SerializedMnTransaction = Uint8Array;
4
+ import { type SerializedTransaction } from '@midnight-ntwrk/wallet-sdk-abstractions';
5
5
  export type Genesis = {
6
- readonly transactions: readonly SerializedMnTransaction[];
6
+ readonly transactions: readonly SerializedTransaction.SerializedTransaction[];
7
7
  };
8
8
  export interface Service {
9
- sendMidnightTransaction(serializedTransaction: SerializedMnTransaction): Stream.Stream<SubmissionEvent.SubmissionEvent, NodeClientError.NodeClientError>;
9
+ sendMidnightTransaction(serializedTransaction: SerializedTransaction.SerializedTransaction): Stream.Stream<SubmissionEvent.SubmissionEvent, NodeClientError.NodeClientError>;
10
10
  getGenesis(): Effect.Effect<Genesis, NodeClientError.NodeClientError>;
11
11
  }
12
12
  declare const NodeClient_base: Context.TagClass<NodeClient, "@midnight-ntwrk/wallet-node-client#NodeClient", Service>;
13
13
  export declare class NodeClient extends NodeClient_base {
14
14
  }
15
15
  export declare const getGenesisTransactions: () => Effect.Effect<Genesis, NodeClientError.NodeClientError, NodeClient>;
16
- export declare const sendMidnightTransaction: (serializedTransaction: SerializedMnTransaction) => Stream.Stream<SubmissionEvent.SubmissionEvent, NodeClientError.NodeClientError, NodeClient>;
17
- export declare function sendMidnightTransactionAndWait(serializedTransaction: SerializedMnTransaction, waitFor: SubmissionEvent.Cases.Submitted['_tag']): Effect.Effect<SubmissionEvent.Cases.Submitted, NodeClientError.NodeClientError, NodeClient>;
18
- export declare function sendMidnightTransactionAndWait(serializedTransaction: SerializedMnTransaction, waitFor: SubmissionEvent.Cases.InBlock['_tag']): Effect.Effect<SubmissionEvent.Cases.InBlock, NodeClientError.NodeClientError, NodeClient>;
19
- export declare function sendMidnightTransactionAndWait(serializedTransaction: SerializedMnTransaction, waitFor: SubmissionEvent.Cases.Finalized['_tag']): Effect.Effect<SubmissionEvent.Cases.Finalized, NodeClientError.NodeClientError, NodeClient>;
20
- export declare function sendMidnightTransactionAndWait(serializedTransaction: SerializedMnTransaction, waitFor: SubmissionEvent.SubmissionEvent['_tag']): Effect.Effect<SubmissionEvent.SubmissionEvent, NodeClientError.NodeClientError, NodeClient>;
16
+ export declare const sendMidnightTransaction: (serializedTransaction: SerializedTransaction.SerializedTransaction) => Stream.Stream<SubmissionEvent.SubmissionEvent, NodeClientError.NodeClientError, NodeClient>;
17
+ export declare function sendMidnightTransactionAndWait(serializedTransaction: SerializedTransaction.SerializedTransaction, waitFor: SubmissionEvent.Cases.Submitted['_tag']): Effect.Effect<SubmissionEvent.Cases.Submitted, NodeClientError.NodeClientError, NodeClient>;
18
+ export declare function sendMidnightTransactionAndWait(serializedTransaction: SerializedTransaction.SerializedTransaction, waitFor: SubmissionEvent.Cases.InBlock['_tag']): Effect.Effect<SubmissionEvent.Cases.InBlock, NodeClientError.NodeClientError, NodeClient>;
19
+ export declare function sendMidnightTransactionAndWait(serializedTransaction: SerializedTransaction.SerializedTransaction, waitFor: SubmissionEvent.Cases.Finalized['_tag']): Effect.Effect<SubmissionEvent.Cases.Finalized, NodeClientError.NodeClientError, NodeClient>;
20
+ export declare function sendMidnightTransactionAndWait(serializedTransaction: SerializedTransaction.SerializedTransaction, waitFor: SubmissionEvent.SubmissionEvent['_tag']): Effect.Effect<SubmissionEvent.SubmissionEvent, NodeClientError.NodeClientError, NodeClient>;
21
21
  export {};
@@ -1,5 +1,5 @@
1
1
  // This file is part of MIDNIGHT-WALLET-SDK.
2
- // Copyright (C) 2025 Midnight Foundation
2
+ // Copyright (C) Midnight Foundation
3
3
  // SPDX-License-Identifier: Apache-2.0
4
4
  // Licensed under the Apache License, Version 2.0 (the "License");
5
5
  // You may not use this file except in compliance with the License.
@@ -1,10 +1,11 @@
1
- import { SubmissionEvent } from './SubmissionEvent.js';
1
+ import { type SubmissionEvent } from './SubmissionEvent.js';
2
+ import { type SerializedTransaction } from '@midnight-ntwrk/wallet-sdk-abstractions';
2
3
  declare const SubmissionError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }) => import("effect/Cause").YieldableError & {
3
4
  readonly _tag: "SubmissionError";
4
5
  } & Readonly<A>;
5
6
  export declare class SubmissionError extends SubmissionError_base<{
6
7
  message: string;
7
- txData: Uint8Array;
8
+ txData: SerializedTransaction.SerializedTransaction;
8
9
  cause?: unknown;
9
10
  }> {
10
11
  }
@@ -21,7 +22,7 @@ declare const TransactionProgressError_base: new <A extends Record<string, any>
21
22
  } & Readonly<A>;
22
23
  export declare class TransactionProgressError extends TransactionProgressError_base<{
23
24
  message: string;
24
- txData: Uint8Array;
25
+ txData: SerializedTransaction.SerializedTransaction;
25
26
  desiredStage: SubmissionEvent['_tag'];
26
27
  }> {
27
28
  }
@@ -1,5 +1,5 @@
1
1
  // This file is part of MIDNIGHT-WALLET-SDK.
2
- // Copyright (C) 2025 Midnight Foundation
2
+ // Copyright (C) Midnight Foundation
3
3
  // SPDX-License-Identifier: Apache-2.0
4
4
  // Licensed under the Apache License, Version 2.0 (the "License");
5
5
  // You may not use this file except in compliance with the License.
@@ -1,9 +1,10 @@
1
1
  import '../gen/augment-api.js';
2
2
  import { ApiPromise } from '@polkadot/api';
3
- import { Duration, Effect, Layer, Scope, Stream } from 'effect';
3
+ import { Duration, Effect, Layer, type Scope, Stream } from 'effect';
4
4
  import * as NodeClient from './NodeClient.js';
5
5
  import * as SubmissionEvent from './SubmissionEvent.js';
6
6
  import * as NodeClientError from './NodeClientError.js';
7
+ import { SerializedTransaction } from '@midnight-ntwrk/wallet-sdk-abstractions';
7
8
  export type Config = {
8
9
  nodeURL: URL;
9
10
  reconnectionTimeout: Duration.Duration;
@@ -22,8 +23,8 @@ export declare class PolkadotNodeClient implements NodeClient.Service {
22
23
  readonly api: ApiPromise;
23
24
  constructor(config: Config, api: ApiPromise);
24
25
  ensureConnection(): Effect.Effect<void, NodeClientError.NodeClientError>;
25
- sendMidnightTransaction(serializedTransaction: NodeClient.SerializedMnTransaction): Stream.Stream<SubmissionEvent.SubmissionEvent, NodeClientError.NodeClientError>;
26
+ sendMidnightTransaction(serializedTransaction: SerializedTransaction.SerializedTransaction): Stream.Stream<SubmissionEvent.SubmissionEvent, NodeClientError.NodeClientError>;
26
27
  getGenesis(): Effect.Effect<{
27
- readonly transactions: readonly NodeClient.SerializedMnTransaction[];
28
+ readonly transactions: readonly SerializedTransaction.SerializedTransaction[];
28
29
  }, NodeClientError.NodeClientError>;
29
30
  }
@@ -1,5 +1,5 @@
1
1
  // This file is part of MIDNIGHT-WALLET-SDK.
2
- // Copyright (C) 2025 Midnight Foundation
2
+ // Copyright (C) Midnight Foundation
3
3
  // SPDX-License-Identifier: Apache-2.0
4
4
  // Licensed under the Apache License, Version 2.0 (the "License");
5
5
  // You may not use this file except in compliance with the License.
@@ -18,6 +18,7 @@ import * as SubmissionEvent from './SubmissionEvent.js';
18
18
  import * as NodeClientError from './NodeClientError.js';
19
19
  import BN from 'bn.js';
20
20
  import { u8aToHex } from '@polkadot/util';
21
+ import { SerializedTransaction } from '@midnight-ntwrk/wallet-sdk-abstractions';
21
22
  export const DEFAULT_CONFIG = {
22
23
  reconnectionTimeout: Duration.infinity,
23
24
  reconnectionDelay: Duration.seconds(1),
@@ -29,15 +30,22 @@ export const makeConfig = (input) => ({
29
30
  export class PolkadotNodeClient {
30
31
  static make(configInput) {
31
32
  const config = makeConfig(configInput);
32
- return Effect.acquireRelease(Effect.promise(() => ApiPromise.create({
33
- // @ts-expect-error -- exactOptionalPropertyTypes cause an incompatibility here
34
- provider: new WsProvider(config.nodeURL.toString()),
35
- throwOnConnect: false,
36
- noInitWarn: true,
37
- })), (api) => Effect.promise(() => api.disconnect())).pipe(Effect.map((api) => new PolkadotNodeClient(config, api)));
33
+ return Effect.acquireRelease(Effect.promise(async () => {
34
+ const api = await ApiPromise.create({
35
+ // @ts-expect-error -- exactOptionalPropertyTypes cause an incompatibility here
36
+ provider: new WsProvider(config.nodeURL.toString()),
37
+ throwOnConnect: false,
38
+ noInitWarn: true,
39
+ });
40
+ // Disconnect immediately after loading metadata to avoid keeping the WebSocket open.
41
+ // The health-check timer (10s interval) and timeout handler (5s interval) are cleared on disconnect.
42
+ // Metadata and type registry remain cached in memory for subsequent on-demand connections.
43
+ await api.disconnect();
44
+ return api;
45
+ }), (api) => Effect.promise(() => api.disconnect())).pipe(Effect.map((api) => new PolkadotNodeClient(config, api)));
38
46
  }
39
47
  static layer(configInput) {
40
- return Layer.effect(NodeClient.NodeClient, PolkadotNodeClient.make(configInput));
48
+ return Layer.scoped(NodeClient.NodeClient, PolkadotNodeClient.make(configInput));
41
49
  }
42
50
  config;
43
51
  api;
@@ -48,7 +56,16 @@ export class PolkadotNodeClient {
48
56
  ensureConnection() {
49
57
  return pipe(Effect.promise(async () => {
50
58
  if (!this.api.isConnected) {
51
- await this.api.connect();
59
+ try {
60
+ await this.api.connect();
61
+ }
62
+ catch (error) {
63
+ // WsProvider.connect() rejects if a WebSocket already exists (connection in progress).
64
+ // This is expected when the repeat loop re-enters before the 'open' event fires.
65
+ if (!(error instanceof Error && error.message === 'WebSocket is already connected')) {
66
+ throw error;
67
+ }
68
+ }
52
69
  }
53
70
  }), Effect.andThen(Effect.sync(() => this.api.isConnected)), Effect.repeat({
54
71
  until: (value) => value,
@@ -75,20 +92,20 @@ export class PolkadotNodeClient {
75
92
  });
76
93
  return Effect.promise(callUnsubscribe);
77
94
  });
78
- return pipe(Stream.fromEffect(this.ensureConnection()), Stream.flatMap(() => outputStream));
95
+ return pipe(Stream.fromEffect(this.ensureConnection()), Stream.flatMap(() => outputStream), Stream.ensuring(Effect.promise(() => this.api.disconnect())));
79
96
  }
80
97
  getGenesis() {
81
- return Effect.promise(() => this.api.rpc.chain.getBlock(this.api.genesisHash)).pipe(Effect.map((block) => {
82
- // https://polkadot.js.org/docs/api/cookbook/blocks/#how-do-i-view-extrinsic-information
83
- return {
84
- transactions: block.block.extrinsics
85
- .filter((extrinsic) => extrinsic.method.section === 'midnight' && extrinsic.method.method === 'sendMnTransaction')
86
- .map((extrinsic) => extrinsic.method.args[0].toU8a()),
87
- };
88
- }), Effect.mapError((error) => new NodeClientError.ConnectionError({
98
+ return pipe(this.ensureConnection(), Effect.andThen(() => Effect.promise(() => this.api.rpc.chain.getBlock(this.api.genesisHash))),
99
+ // https://polkadot.js.org/docs/api/cookbook/blocks/#how-do-i-view-extrinsic-information
100
+ Effect.map(({ block }) => ({
101
+ transactions: block.extrinsics
102
+ .filter(({ method }) => method.section === 'midnight' && method.method === 'sendMnTransaction')
103
+ .map(({ method }) => method.args[0].toU8a())
104
+ .map(SerializedTransaction.of),
105
+ })), Effect.mapError((error) => new NodeClientError.ConnectionError({
89
106
  message: 'Failed to retrieve genesis transactions',
90
107
  cause: error,
91
- })));
108
+ })), Effect.ensuring(Effect.promise(() => this.api.disconnect())));
92
109
  }
93
110
  #handleSubmissionResult = (serializedTransaction, emit, unsubscribe) => {
94
111
  const WithBNBlockNumber = Schema.Struct({
@@ -1,5 +1,5 @@
1
1
  import { Data } from 'effect';
2
- import { SerializedMnTransaction } from './NodeClient.js';
2
+ import { type SerializedTransaction } from '@midnight-ntwrk/wallet-sdk-abstractions';
3
3
  export type HexString = string;
4
4
  export type SubmissionEvent = Cases.Submitted | Cases.InBlock | Cases.Finalized;
5
5
  export declare const Submitted: Data.Case.Constructor<Cases.Submitted, "_tag">, InBlock: Data.Case.Constructor<Cases.InBlock, "_tag">, Finalized: Data.Case.Constructor<Cases.Finalized, "_tag">, match: {
@@ -23,21 +23,21 @@ export declare const Submitted: Data.Case.Constructor<Cases.Submitted, "_tag">,
23
23
  export declare namespace Cases {
24
24
  type Submitted = {
25
25
  _tag: 'Submitted';
26
- tx: SerializedMnTransaction;
26
+ tx: SerializedTransaction.SerializedTransaction;
27
27
  txHash: HexString;
28
28
  };
29
29
  type InBlock = {
30
30
  _tag: 'InBlock';
31
31
  blockHash: HexString;
32
32
  blockHeight: bigint;
33
- tx: SerializedMnTransaction;
33
+ tx: SerializedTransaction.SerializedTransaction;
34
34
  txHash: HexString;
35
35
  };
36
36
  type Finalized = {
37
37
  _tag: 'Finalized';
38
38
  blockHash: HexString;
39
39
  blockHeight: bigint;
40
- tx: SerializedMnTransaction;
40
+ tx: SerializedTransaction.SerializedTransaction;
41
41
  txHash: HexString;
42
42
  };
43
43
  }
@@ -1,5 +1,5 @@
1
1
  // This file is part of MIDNIGHT-WALLET-SDK.
2
- // Copyright (C) 2025 Midnight Foundation
2
+ // Copyright (C) Midnight Foundation
3
3
  // SPDX-License-Identifier: Apache-2.0
4
4
  // Licensed under the Apache License, Version 2.0 (the "License");
5
5
  // You may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
1
1
  // This file is part of MIDNIGHT-WALLET-SDK.
2
- // Copyright (C) 2025 Midnight Foundation
2
+ // Copyright (C) Midnight Foundation
3
3
  // SPDX-License-Identifier: Apache-2.0
4
4
  // Licensed under the Apache License, Version 2.0 (the "License");
5
5
  // You may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
1
1
  // This file is part of MIDNIGHT-WALLET-SDK.
2
- // Copyright (C) 2025 Midnight Foundation
2
+ // Copyright (C) Midnight Foundation
3
3
  // SPDX-License-Identifier: Apache-2.0
4
4
  // Licensed under the Apache License, Version 2.0 (the "License");
5
5
  // You may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
1
1
  // This file is part of MIDNIGHT-WALLET-SDK.
2
- // Copyright (C) 2025 Midnight Foundation
2
+ // Copyright (C) Midnight Foundation
3
3
  // SPDX-License-Identifier: Apache-2.0
4
4
  // Licensed under the Apache License, Version 2.0 (the "License");
5
5
  // You may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
1
1
  // This file is part of MIDNIGHT-WALLET-SDK.
2
- // Copyright (C) 2025 Midnight Foundation
2
+ // Copyright (C) Midnight Foundation
3
3
  // SPDX-License-Identifier: Apache-2.0
4
4
  // Licensed under the Apache License, Version 2.0 (the "License");
5
5
  // You may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
1
1
  // This file is part of MIDNIGHT-WALLET-SDK.
2
- // Copyright (C) 2025 Midnight Foundation
2
+ // Copyright (C) Midnight Foundation
3
3
  // SPDX-License-Identifier: Apache-2.0
4
4
  // Licensed under the Apache License, Version 2.0 (the "License");
5
5
  // You may not use this file except in compliance with the License.
package/dist/index.d.ts CHANGED
@@ -1,13 +1,14 @@
1
- import { NodeClient, SubmissionEvent, Config } from './effect/index.js';
2
- import { Observable } from '@polkadot/types/types';
1
+ import { type SubmissionEvent, type Config } from './effect/index.js';
2
+ import { type Observable } from '@polkadot/types/types';
3
+ import { type SerializedTransaction } from '@midnight-ntwrk/wallet-sdk-abstractions';
3
4
  export { Config, makeConfig, DEFAULT_CONFIG } from './effect/PolkadotNodeClient.js';
4
5
  export declare class PolkadotNodeClient {
5
6
  #private;
6
7
  static init(config: Config): Promise<PolkadotNodeClient>;
7
8
  private constructor();
8
- sendMidnightTransaction(serializedTransaction: NodeClient.SerializedMnTransaction): Observable<SubmissionEvent.SubmissionEvent>;
9
- sendMidnightTransactionAndWait(serializedTransaction: NodeClient.SerializedMnTransaction, waitFor: SubmissionEvent.Cases.Submitted['_tag']): Promise<SubmissionEvent.Cases.Submitted>;
10
- sendMidnightTransactionAndWait(serializedTransaction: NodeClient.SerializedMnTransaction, waitFor: SubmissionEvent.Cases.InBlock['_tag']): Promise<SubmissionEvent.Cases.InBlock>;
11
- sendMidnightTransactionAndWait(serializedTransaction: NodeClient.SerializedMnTransaction, waitFor: SubmissionEvent.Cases.Finalized['_tag']): Promise<SubmissionEvent.Cases.Finalized>;
9
+ sendMidnightTransaction(serializedTransaction: SerializedTransaction.SerializedTransaction): Observable<SubmissionEvent.SubmissionEvent>;
10
+ sendMidnightTransactionAndWait(serializedTransaction: SerializedTransaction.SerializedTransaction, waitFor: SubmissionEvent.Cases.Submitted['_tag']): Promise<SubmissionEvent.Cases.Submitted>;
11
+ sendMidnightTransactionAndWait(serializedTransaction: SerializedTransaction.SerializedTransaction, waitFor: SubmissionEvent.Cases.InBlock['_tag']): Promise<SubmissionEvent.Cases.InBlock>;
12
+ sendMidnightTransactionAndWait(serializedTransaction: SerializedTransaction.SerializedTransaction, waitFor: SubmissionEvent.Cases.Finalized['_tag']): Promise<SubmissionEvent.Cases.Finalized>;
12
13
  close(): Promise<void>;
13
14
  }
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  // This file is part of MIDNIGHT-WALLET-SDK.
2
- // Copyright (C) 2025 Midnight Foundation
2
+ // Copyright (C) Midnight Foundation
3
3
  // SPDX-License-Identifier: Apache-2.0
4
4
  // Licensed under the Apache License, Version 2.0 (the "License");
5
5
  // You may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
1
1
  // This file is part of MIDNIGHT-WALLET-SDK.
2
- // Copyright (C) 2025 Midnight Foundation
2
+ // Copyright (C) Midnight Foundation
3
3
  // SPDX-License-Identifier: Apache-2.0
4
4
  // Licensed under the Apache License, Version 2.0 (the "License");
5
5
  // You may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
1
1
  // This file is part of MIDNIGHT-WALLET-SDK.
2
- // Copyright (C) 2025 Midnight Foundation
2
+ // Copyright (C) Midnight Foundation
3
3
  // SPDX-License-Identifier: Apache-2.0
4
4
  // Licensed under the Apache License, Version 2.0 (the "License");
5
5
  // You may not use this file except in compliance with the License.
@@ -1,11 +1,17 @@
1
- import { Error, FileSystem } from '@effect/platform';
1
+ import { type Error, FileSystem } from '@effect/platform';
2
2
  import * as ledger from '@midnight-ntwrk/ledger-v7';
3
3
  import { SerializedTransaction } from '@midnight-ntwrk/wallet-sdk-abstractions';
4
4
  import { ProverClient } from '@midnight-ntwrk/wallet-sdk-prover-client/effect';
5
- import { ClientError, ServerError } from '@midnight-ntwrk/wallet-sdk-utilities/networking';
6
- import { Effect, ParseResult, Schema, Stream } from 'effect';
7
- import { Scope } from 'effect/Scope';
8
- import { StartedNetwork } from 'testcontainers';
5
+ import { type ClientError, type ServerError } from '@midnight-ntwrk/wallet-sdk-utilities/networking';
6
+ import { Effect, DateTime, ParseResult, Schema, Stream, Option } from 'effect';
7
+ import { type Scope } from 'effect/Scope';
8
+ import { type StartedNetwork, type StartedTestContainer } from 'testcontainers';
9
+ export type Paths = {
10
+ readonly outputPath: string;
11
+ readonly fileName: string;
12
+ readonly fullPath: string;
13
+ };
14
+ export declare const defaultPaths: Paths;
9
15
  export type FinalizedTransaction = ledger.Transaction<ledger.SignatureEnabled, ledger.Proof, ledger.Binding>;
10
16
  declare const TestTransactionsSchema: Schema.Struct<{
11
17
  initial_tx: Schema.Schema<FinalizedTransaction, string, never>;
@@ -15,6 +21,13 @@ declare const TestTransactionsSchema: Schema.Struct<{
15
21
  export type TestTransactions = Schema.Schema.Type<typeof TestTransactionsSchema>;
16
22
  export declare const load: (file: string) => Effect.Effect<TestTransactions, ParseResult.ParseError | Error.PlatformError, FileSystem.FileSystem>;
17
23
  export declare const streamAllValid: (txs: TestTransactions) => Stream.Stream<FinalizedTransaction>;
18
- export declare const genUnbalancedTx: () => Effect.Effect<SerializedTransaction, ClientError | ServerError, ProverClient.ProverClient>;
19
- export declare const generateTestTransactions: (nodeUrl: string, proofServerUrl: string, network: StartedNetwork, outputPath: string, fileName: string) => Effect.Effect<void, Error | Error.PlatformError, FileSystem.FileSystem | Scope>;
24
+ export declare const getTTL: (txs: TestTransactions) => Effect.Effect<Option.Option<DateTime.Utc>, never, never>;
25
+ export declare const genUnbalancedTx: () => Effect.Effect<SerializedTransaction.SerializedTransaction, ClientError | ServerError, ProverClient.ProverClient>;
26
+ type TestTransactionsEnvironment = {
27
+ nodeContainer: StartedTestContainer;
28
+ hostProofServerContainer: StartedTestContainer;
29
+ networkProofServerContainer: StartedTestContainer;
30
+ network: StartedNetwork;
31
+ };
32
+ export declare const generateTestTransactions: (environment: TestTransactionsEnvironment, paths: Paths) => Effect.Effect<void, Error | Error.PlatformError, FileSystem.FileSystem | Scope>;
20
33
  export {};
@@ -1,5 +1,5 @@
1
1
  // This file is part of MIDNIGHT-WALLET-SDK.
2
- // Copyright (C) 2025 Midnight Foundation
2
+ // Copyright (C) Midnight Foundation
3
3
  // SPDX-License-Identifier: Apache-2.0
4
4
  // Licensed under the Apache License, Version 2.0 (the "License");
5
5
  // You may not use this file except in compliance with the License.
@@ -15,8 +15,21 @@ import * as ledger from '@midnight-ntwrk/ledger-v7';
15
15
  import { SerializedTransaction } from '@midnight-ntwrk/wallet-sdk-abstractions';
16
16
  import { HttpProverClient, ProverClient } from '@midnight-ntwrk/wallet-sdk-prover-client/effect';
17
17
  import { TestContainers } from '@midnight-ntwrk/wallet-sdk-utilities/testing';
18
- import { Effect, Encoding, ParseResult, pipe, Random, Schema, Stream } from 'effect';
18
+ import { Duration, Effect, Encoding, DateTime, ParseResult, pipe, Random, Schema, Stream, Option } from 'effect';
19
+ import { Wait } from 'testcontainers';
19
20
  import { normalizeTxs } from './normalize-txs.js';
21
+ import * as tar from 'tar-stream';
22
+ import * as path from 'node:path';
23
+ const Paths = {
24
+ make: (outputPath, fileName) => {
25
+ return {
26
+ outputPath,
27
+ fileName,
28
+ fullPath: path.resolve(outputPath, fileName),
29
+ };
30
+ },
31
+ };
32
+ export const defaultPaths = pipe(path.dirname(new URL(import.meta.url).pathname), (currentDir) => path.resolve(currentDir, '..', '..', 'temp-resources'), (outputPath) => Paths.make(outputPath, 'test-txs.json'));
20
33
  const TxSchema = Schema.declare((input) => input instanceof ledger.Transaction).annotations({
21
34
  identifier: 'ledger.Transaction',
22
35
  });
@@ -42,6 +55,12 @@ export const streamAllValid = (txs) => {
42
55
  const batches = Stream.fromIterable(txs.batches);
43
56
  return Stream.concat(initial, batches);
44
57
  };
58
+ export const getTTL = (txs) => {
59
+ return streamAllValid(txs).pipe(Stream.mapConcat((tx) => tx.intents ?? []), Stream.map(([_, intent]) => intent.ttl), Stream.mapConcat((ttl) => pipe(ttl, DateTime.make, Option.toArray)), Stream.runFold(Option.none(), (acc, ttl) => Option.match(acc, {
60
+ onNone: () => Option.some(ttl),
61
+ onSome: (accValue) => Option.some(DateTime.min(accValue, ttl)),
62
+ })));
63
+ };
45
64
  export const genUnbalancedTx = () => Effect.Do.pipe(Effect.bind('value', () => Random.nextIntBetween(1, 100_000_000).pipe(Effect.map((nr) => BigInt(nr)))), Effect.bind('shieldedTokenType', () => Effect.succeed(ledger.shieldedToken())), Effect.let('unprovenTx', ({ value, shieldedTokenType }) => {
46
65
  const recipient = ledger.ZswapSecretKeys.fromSeed(new Uint8Array(32).fill(0));
47
66
  const coin = ledger.createShieldedCoinInfo(shieldedTokenType.raw, value);
@@ -50,8 +69,8 @@ export const genUnbalancedTx = () => Effect.Do.pipe(Effect.bind('value', () => R
50
69
  return ledger.Transaction.fromParts('undeployed', unprovenOffer);
51
70
  }), Effect.flatMap(({ unprovenTx }) => Effect.gen(function* () {
52
71
  const proverClient = yield* ProverClient.ProverClient;
53
- const provedTx = yield* proverClient.proveTransaction(unprovenTx, ledger.CostModel.initialCostModel());
54
- return SerializedTransaction(provedTx.bind().serialize());
72
+ const provenTx = yield* proverClient.proveTransaction(unprovenTx, ledger.CostModel.initialCostModel());
73
+ return SerializedTransaction.from(provenTx.bind());
55
74
  })));
56
75
  const normalizeAndSaveUnbalancedTx = (txsPath, tx) => {
57
76
  /* eslint-disable @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-explicit-any */
@@ -73,16 +92,31 @@ const generateUnbalancedTransaction = (proofServerUrl) => {
73
92
  url: new URL(proofServerUrl),
74
93
  })));
75
94
  };
76
- export const generateTestTransactions = (nodeUrl, proofServerUrl, network, outputPath, fileName) => Effect.gen(function* () {
77
- const [, unbalancedTx] = yield* Effect.all([
95
+ export const generateTestTransactions = (environment, paths) => Effect.gen(function* () {
96
+ const fs = yield* FileSystem.FileSystem;
97
+ const [startedContainer, unbalancedTx] = yield* Effect.all([
78
98
  TestContainers.runTxGenerator({
79
- nodeUrl: nodeUrl,
80
- destPath: outputPath,
81
- fileName: fileName,
99
+ nodeUrl: `ws://${environment.nodeContainer.getHostname()}:9944`,
100
+ proofServerUrl: `http://${environment.networkProofServerContainer.getHostname()}:6300`,
101
+ destPath: paths.outputPath,
102
+ fileName: paths.fileName,
82
103
  txsPerBatch: 1,
83
104
  batches: 1,
84
- }, (c) => c.withNetwork(network)),
85
- generateUnbalancedTransaction(proofServerUrl),
86
- ]);
87
- yield* normalizeAndSaveUnbalancedTx(`${outputPath}/${fileName}`, unbalancedTx);
105
+ }, (c) => c.withNetwork(environment.network).withWaitStrategy(Wait.forLogMessage('generated transactions'))),
106
+ generateUnbalancedTransaction(`http://localhost:${environment.hostProofServerContainer.getMappedPort(6300)}`),
107
+ ], { concurrency: 'unbounded' });
108
+ yield* Effect.sleep(Duration.seconds(1));
109
+ const stoppedContainer = yield* Effect.promise(() => startedContainer.stop({ remove: false }));
110
+ yield* Effect.log('copying archive from container');
111
+ yield* Effect.promise(() => stoppedContainer.copyArchiveFromContainer(`/tmp/${paths.fileName}`)).pipe(Effect.flatMap((stream) => pipe(stream, (s) => s.pipe(tar.extract()), (s) => Stream.fromAsyncIterable(s, (error) => error), Stream.tapBoth({
112
+ onSuccess: (entry) => Effect.log('entry after extract', entry),
113
+ onFailure: (error) => Effect.log(error),
114
+ }), Stream.tapBoth({
115
+ onSuccess: (entry) => Effect.log('entry', entry),
116
+ onFailure: (error) => Effect.log(error),
117
+ }), Stream.mapEffect((entry) => Stream.fromAsyncIterable(entry, (error) => error).pipe(Stream.tapBoth({
118
+ onSuccess: (chunk) => Effect.log('chunk', chunk),
119
+ onFailure: (error) => Effect.log(error),
120
+ }), Stream.run(fs.sink(paths.fullPath)))), Stream.runDrain, Effect.andThen(Effect.log('done')))));
121
+ yield* normalizeAndSaveUnbalancedTx(paths.fullPath, unbalancedTx);
88
122
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@midnight-ntwrk/wallet-sdk-node-client",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
4
4
  "type": "module",
5
5
  "module": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -31,50 +31,35 @@
31
31
  }
32
32
  },
33
33
  "dependencies": {
34
- "@polkadot/api": "^16.3.1",
35
- "@polkadot/api-augment": "^16.3.1",
36
- "@polkadot/api-base": "^16.3.1",
37
- "@polkadot/rpc-augment": "^16.3.1",
38
- "@polkadot/rpc-core": "^16.3.1",
39
- "@polkadot/types": "^16.3.1",
40
- "@polkadot/types-augment": "^16.3.1",
41
- "@polkadot/types-codec": "^16.3.1",
42
- "@polkadot/types-known": "^16.3.1",
43
- "@polkadot/types-support": "^16.3.1",
34
+ "@midnight-ntwrk/wallet-sdk-abstractions": "2.0.0",
35
+ "@midnight-ntwrk/wallet-sdk-utilities": "1.0.1",
36
+ "@polkadot/api": "^16.5.4",
37
+ "@polkadot/types": "^16.5.4",
38
+ "@polkadot/util": "^14.0.1",
44
39
  "@types/bn.js": "^5.2.0",
45
- "bn.js": "^5.2.2",
46
- "effect": "^3.19.14",
47
- "rxjs": "^7.5",
48
- "testcontainers": "^11.10.0"
40
+ "bn.js": "^5.2.3",
41
+ "effect": "^3.19.19"
49
42
  },
50
43
  "devDependencies": {
51
- "@effect/cluster": "^0.46.2",
52
- "@effect/experimental": "^0.54.2",
53
- "@effect/platform": "^0.90.0",
54
- "@effect/platform-node": "^0.94.0",
55
- "@effect/rpc": "^0.68.0",
56
- "@effect/sql": "^0.44.0",
57
- "@effect/workflow": "^0.8.1",
58
- "@midnight-ntwrk/ledger-v7": "7.0.0",
59
- "@midnight-ntwrk/wallet-sdk-abstractions": "1.0.0",
60
- "@midnight-ntwrk/wallet-sdk-prover-client": "1.0.0",
61
- "@midnight-ntwrk/wallet-sdk-utilities": "1.0.0",
62
- "@polkadot/typegen": "^16.3.1",
63
- "@types/yargs": "^17.0.33",
64
- "eslint": "^9.37.0",
65
- "prettier": "^3.7.0",
66
- "publint": "~0.3.14",
67
- "rimraf": "^6.0.1",
68
- "tsx": "^4.20.4",
69
- "typescript": "^5.9.3",
70
- "vitest": "^4.0.16",
71
- "yargs": "^18.0.0"
44
+ "@effect/cluster": "^0.56.4",
45
+ "@effect/experimental": "^0.58.0",
46
+ "@effect/platform": "^0.94.5",
47
+ "@effect/platform-node": "^0.104.1",
48
+ "@effect/rpc": "^0.73.2",
49
+ "@effect/sql": "^0.49.0",
50
+ "@effect/workflow": "^0.16.0",
51
+ "@midnight-ntwrk/ledger-v7": "^7.0.2",
52
+ "@midnight-ntwrk/wallet-sdk-prover-client": "1.1.0",
53
+ "@types/tar-stream": "^3.1.4",
54
+ "tar-stream": "^3.1.7",
55
+ "tsx": "^4.21.0"
72
56
  },
73
57
  "scripts": {
74
58
  "typecheck-script": "tsc -b ./tsconfig.script.json --noEmit",
75
59
  "polkadot-typegen": "tsx ./scripts/generate-types.ts",
76
- "typecheck": "tsc -b ./tsconfig.json --noEmit",
77
- "test": "vitest run",
60
+ "gen-test-tx": "DEBUG='testcontainers:containers' tsx ./scripts/generate-test-tx.ts",
61
+ "typecheck": "tsc -b ./tsconfig.json --noEmit --force",
62
+ "test": "DEBUG='testcontainers:containers' vitest run",
78
63
  "lint": "eslint --max-warnings 0",
79
64
  "format": "prettier --write \"**/*.{ts,js,json,yaml,yml,md}\"",
80
65
  "format:check": "prettier --check \"**/*.{ts,js,json,yaml,yml,md}\"",