@midnightntwrk/wallet-sdk-unshielded-wallet 3.1.0

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.
package/README.md ADDED
@@ -0,0 +1,123 @@
1
+ # @midnightntwrk/wallet-sdk-unshielded-wallet
2
+
3
+ Manages unshielded tokens on the Midnight network.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @midnightntwrk/wallet-sdk-unshielded-wallet
9
+ ```
10
+
11
+ ## Overview
12
+
13
+ The Unshielded Wallet handles transparent token operations where transactions are publicly visible on the blockchain.
14
+ Unlike shielded transactions, unshielded operations do not use zero-knowledge proofs. This package provides:
15
+
16
+ - Public token balance tracking
17
+ - Transparent transfer transactions
18
+ - Transaction balancing for unshielded tokens
19
+ - Swap initialization and participation
20
+ - Transaction signing
21
+
22
+ ## Usage
23
+
24
+ ### Starting the Wallet
25
+
26
+ ```typescript
27
+ import { UnshieldedWallet, createKeystore, PublicKey } from '@midnightntwrk/wallet-sdk-unshielded-wallet';
28
+ import { InMemoryTransactionHistoryStorage, NetworkId } from '@midnightntwrk/wallet-sdk-abstractions';
29
+ import { randomBytes } from 'node:crypto';
30
+
31
+ // Configuration for the wallet
32
+ const configuration = {
33
+ networkId: NetworkId.Undeployed, // or NetworkId.Testnet, NetworkId.Mainnet
34
+ indexerClientConnection: {
35
+ indexerWsUrl: 'ws://localhost:8088/api/v4/graphql/ws',
36
+ indexerHttpUrl: 'http://localhost:8088/api/v4/graphql',
37
+ },
38
+ txHistoryStorage: new InMemoryTransactionHistoryStorage(),
39
+ };
40
+
41
+ // Create a keystore from a random unshielded seed
42
+ const seed = randomBytes(32);
43
+ const keystore = createKeystore(seed, configuration.networkId);
44
+
45
+ // Create and start the wallet
46
+ const unshieldedWallet = UnshieldedWallet(configuration).startWithPublicKey(PublicKey.fromKeyStore(keystore));
47
+
48
+ // Start syncing with the network
49
+ await unshieldedWallet.start();
50
+ ```
51
+
52
+ ### Restoring from Serialized State
53
+
54
+ ```typescript
55
+ // Restore a wallet from previously serialized state
56
+ const unshieldedWallet = UnshieldedWallet(configuration).restore(serializedState);
57
+ await unshieldedWallet.start();
58
+ ```
59
+
60
+ ### Observing State
61
+
62
+ ```typescript
63
+ unshieldedWallet.state.subscribe((state) => {
64
+ console.log('Progress:', state.progress);
65
+ console.log('Balances:', state.balances);
66
+ });
67
+
68
+ // Or wait for sync
69
+ const syncedState = await unshieldedWallet.waitForSyncedState();
70
+ ```
71
+
72
+ ### Creating Transfer Transactions
73
+
74
+ ```typescript
75
+ const tx = await unshieldedWallet.transferTransaction(
76
+ [{ type: 'TOKEN_A', receiverAddress: '...', amount: 1000n }],
77
+ ttl,
78
+ );
79
+ ```
80
+
81
+ ### Balancing Transactions
82
+
83
+ ```typescript
84
+ // Balance a finalized transaction
85
+ const balancingTx = await unshieldedWallet.balanceFinalizedTransaction(finalizedTx);
86
+
87
+ // Balance an unbound transaction (in-place)
88
+ const balancedTx = await unshieldedWallet.balanceUnboundTransaction(unboundTx);
89
+
90
+ // Balance an unproven transaction (in-place)
91
+ const balancedUnprovenTx = await unshieldedWallet.balanceUnprovenTransaction(unprovenTx);
92
+ ```
93
+
94
+ ### Signing Transactions
95
+
96
+ ```typescript
97
+ // Sign an unproven transaction
98
+ const signedTx = await unshieldedWallet.signUnprovenTransaction(tx, signSegment);
99
+
100
+ // Sign an unbound transaction
101
+ const signedUnboundTx = await unshieldedWallet.signUnboundTransaction(tx, signSegment);
102
+ ```
103
+
104
+ ### Creating Swap Offers
105
+
106
+ ```typescript
107
+ const swapTx = await unshieldedWallet.initSwap(
108
+ { TOKEN_A: 500n }, // inputs
109
+ [{ type: 'TOKEN_B', receiverAddress, amount: 100n }], // outputs
110
+ ttl,
111
+ );
112
+ ```
113
+
114
+ ## Exports
115
+
116
+ - `UnshieldedWallet` - Main wallet class
117
+ - `UnshieldedWalletState` - Wallet state type
118
+ - `KeyStore` - Key storage utilities
119
+ - Storage utilities for persistence
120
+
121
+ ## License
122
+
123
+ Apache-2.0
@@ -0,0 +1,19 @@
1
+ import { type MidnightBech32m } from '@midnightntwrk/wallet-sdk-address-format';
2
+ import { type Signature, type SignatureVerifyingKey, type UserAddress } from '@midnight-ntwrk/ledger-v8';
3
+ import { type NetworkId } from '@midnightntwrk/wallet-sdk-abstractions';
4
+ export type PublicKey = {
5
+ publicKey: SignatureVerifyingKey;
6
+ addressHex: UserAddress;
7
+ address: string;
8
+ };
9
+ export declare const PublicKey: {
10
+ fromKeyStore: (keystore: UnshieldedKeystore) => PublicKey;
11
+ };
12
+ export interface UnshieldedKeystore {
13
+ getSecretKey(): Buffer;
14
+ getBech32Address(): MidnightBech32m;
15
+ getPublicKey(): SignatureVerifyingKey;
16
+ getAddress(): UserAddress;
17
+ signData(data: Uint8Array): Signature;
18
+ }
19
+ export declare const createKeystore: (secretKey: Uint8Array<ArrayBufferLike>, networkId: NetworkId.NetworkId) => UnshieldedKeystore;
@@ -0,0 +1,37 @@
1
+ // This file is part of MIDNIGHT-WALLET-SDK.
2
+ // Copyright (C) Midnight Foundation
3
+ // SPDX-License-Identifier: Apache-2.0
4
+ // Licensed under the Apache License, Version 2.0 (the "License");
5
+ // You may not use this file except in compliance with the License.
6
+ // You may obtain a copy of the License at
7
+ // http://www.apache.org/licenses/LICENSE-2.0
8
+ // Unless required by applicable law or agreed to in writing, software
9
+ // distributed under the License is distributed on an "AS IS" BASIS,
10
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
+ // See the License for the specific language governing permissions and
12
+ // limitations under the License.
13
+ import { UnshieldedAddress } from '@midnightntwrk/wallet-sdk-address-format';
14
+ import { addressFromKey, signData, signatureVerifyingKey, } from '@midnight-ntwrk/ledger-v8';
15
+ export const PublicKey = {
16
+ fromKeyStore: (keystore) => {
17
+ return {
18
+ publicKey: keystore.getPublicKey(),
19
+ addressHex: keystore.getAddress(),
20
+ address: keystore.getBech32Address().asString(),
21
+ };
22
+ },
23
+ };
24
+ export const createKeystore = (secretKey, networkId) => {
25
+ const keystore = {
26
+ getSecretKey: () => Buffer.from(secretKey),
27
+ getBech32Address: () => {
28
+ const address = keystore.getAddress();
29
+ const addressBuffer = Buffer.from(address, 'hex');
30
+ return UnshieldedAddress.codec.encode(networkId, new UnshieldedAddress(addressBuffer));
31
+ },
32
+ getPublicKey: () => signatureVerifyingKey(keystore.getSecretKey().toString('hex')),
33
+ getAddress: () => addressFromKey(keystore.getPublicKey()),
34
+ signData: (data) => signData(keystore.getSecretKey().toString('hex'), data),
35
+ };
36
+ return keystore;
37
+ };
@@ -0,0 +1,72 @@
1
+ import { type ProtocolState, ProtocolVersion } from '@midnightntwrk/wallet-sdk-abstractions';
2
+ import { type BaseV1Configuration, type DefaultV1Configuration, type V1Variant, CoreWallet, type UnboundTransaction } from './v1/index.js';
3
+ import type * as ledger from '@midnight-ntwrk/ledger-v8';
4
+ import * as rx from 'rxjs';
5
+ import { type SerializationCapability } from './v1/Serialization.js';
6
+ import { type TransactionHistoryService } from './v1/TransactionHistory.js';
7
+ import { type CoinsAndBalancesCapability } from './v1/CoinsAndBalances.js';
8
+ import { type KeysCapability } from './v1/Keys.js';
9
+ import { type TokenTransfer, type FinalizedTransactionBalanceResult, type UnboundTransactionBalanceResult, type UnprovenTransactionBalanceResult } from './v1/Transacting.js';
10
+ import { type WalletSyncUpdate } from './v1/SyncSchema.js';
11
+ import { type UtxoWithMeta } from './v1/UnshieldedState.js';
12
+ import { type Variant, type VariantBuilder, type WalletLike } from '@midnightntwrk/wallet-sdk-runtime/abstractions';
13
+ import { type PublicKey } from './KeyStore.js';
14
+ import { type SyncProgress } from './v1/SyncProgress.js';
15
+ import { type UnshieldedAddress } from '@midnightntwrk/wallet-sdk-address-format';
16
+ export type UnshieldedWalletCapabilities<TSerialized = string> = {
17
+ serialization: SerializationCapability<CoreWallet, TSerialized>;
18
+ coinsAndBalances: CoinsAndBalancesCapability<CoreWallet>;
19
+ keys: KeysCapability<CoreWallet>;
20
+ };
21
+ export type UnshieldedWalletServices = {
22
+ transactionHistory: TransactionHistoryService;
23
+ };
24
+ export declare class UnshieldedWalletState<TSerialized = string> {
25
+ static readonly mapState: <TSerialized_1 = string>(variant: UnshieldedWalletCapabilities<TSerialized_1> & UnshieldedWalletServices) => (state: ProtocolState.ProtocolState<CoreWallet>) => UnshieldedWalletState<TSerialized_1>;
26
+ readonly protocolVersion: ProtocolVersion.ProtocolVersion;
27
+ readonly state: CoreWallet;
28
+ readonly capabilities: UnshieldedWalletCapabilities<TSerialized>;
29
+ readonly services: UnshieldedWalletServices;
30
+ get balances(): Record<ledger.RawTokenType, bigint>;
31
+ get totalCoins(): readonly UtxoWithMeta[];
32
+ get availableCoins(): readonly UtxoWithMeta[];
33
+ get pendingCoins(): readonly UtxoWithMeta[];
34
+ get address(): UnshieldedAddress;
35
+ get progress(): SyncProgress;
36
+ constructor(state: ProtocolState.ProtocolState<CoreWallet>, capabilities: UnshieldedWalletCapabilities<TSerialized>, services: UnshieldedWalletServices);
37
+ serialize(): TSerialized;
38
+ }
39
+ export type UnshieldedWallet = CustomizedUnshieldedWallet<WalletSyncUpdate, string>;
40
+ export type DefaultUnshieldedConfiguration = DefaultV1Configuration;
41
+ export type UnshieldedWalletClass = CustomizedUnshieldedWalletClass<WalletSyncUpdate, string, DefaultUnshieldedConfiguration>;
42
+ export type UnshieldedWalletAPI<TSerialized = string> = {
43
+ readonly state: rx.Observable<UnshieldedWalletState<TSerialized>>;
44
+ start(): Promise<void>;
45
+ balanceFinalizedTransaction(tx: ledger.FinalizedTransaction): Promise<FinalizedTransactionBalanceResult>;
46
+ balanceUnboundTransaction(tx: UnboundTransaction): Promise<UnboundTransactionBalanceResult>;
47
+ balanceUnprovenTransaction(tx: ledger.UnprovenTransaction): Promise<UnprovenTransactionBalanceResult>;
48
+ transferTransaction(outputs: readonly TokenTransfer[], ttl: Date): Promise<ledger.UnprovenTransaction>;
49
+ /**
50
+ * Books a caller-supplied set of Night UTxOs and returns an unproven transaction that moves them back to the same
51
+ * owner, split between the guaranteed (segment 0) and fallible (segment 1) sections of a single intent. Booking moves
52
+ * the UTxOs from available to pending so a concurrent build call cannot reuse them. The fallible section is available
53
+ * for callers that want to attach further actions (e.g. a Dust registration) at segment 1.
54
+ */
55
+ rotateUtxos(guaranteedUtxos: readonly UtxoWithMeta[], fallibleUtxos: readonly UtxoWithMeta[], nightVerifyingKey: ledger.SignatureVerifyingKey, ttl: Date): Promise<ledger.UnprovenTransaction>;
56
+ initSwap(desiredInputs: Record<ledger.RawTokenType, bigint>, desiredOutputs: readonly TokenTransfer[], ttl: Date): Promise<ledger.UnprovenTransaction>;
57
+ signUnprovenTransaction(transaction: ledger.UnprovenTransaction, signSegment: (data: Uint8Array) => ledger.Signature): Promise<ledger.UnprovenTransaction>;
58
+ signUnboundTransaction(transaction: UnboundTransaction, signSegment: (data: Uint8Array) => ledger.Signature): Promise<UnboundTransaction>;
59
+ serializeState(): Promise<TSerialized>;
60
+ waitForSyncedState(allowedGap?: bigint): Promise<UnshieldedWalletState<TSerialized>>;
61
+ revertTransaction(transaction: ledger.Transaction<ledger.Signaturish, ledger.Proofish, ledger.Bindingish>): Promise<void>;
62
+ getAddress(): Promise<UnshieldedAddress>;
63
+ stop(): Promise<void>;
64
+ };
65
+ export type CustomizedUnshieldedWallet<TSyncUpdate = WalletSyncUpdate, TSerialized = string> = UnshieldedWalletAPI<TSerialized> & WalletLike.WalletLike<[Variant.VersionedVariant<V1Variant<TSerialized, TSyncUpdate>>]>;
66
+ export interface CustomizedUnshieldedWalletClass<TSyncUpdate = WalletSyncUpdate, TSerialized = string, TConfig extends BaseV1Configuration = DefaultV1Configuration> extends WalletLike.BaseWalletClass<[Variant.VersionedVariant<V1Variant<TSerialized, TSyncUpdate>>]> {
67
+ configuration: TConfig;
68
+ startWithPublicKey(publicKey: PublicKey): CustomizedUnshieldedWallet<TSyncUpdate, TSerialized>;
69
+ restore(serializedState: TSerialized): CustomizedUnshieldedWallet<TSyncUpdate, TSerialized>;
70
+ }
71
+ export declare function UnshieldedWallet(configuration: DefaultV1Configuration): UnshieldedWalletClass;
72
+ export declare function CustomUnshieldedWallet<TConfig extends BaseV1Configuration = DefaultV1Configuration, TSyncUpdate = WalletSyncUpdate, TSerialized = string>(configuration: TConfig, builder: VariantBuilder.VariantBuilder<V1Variant<TSerialized, TSyncUpdate>, TConfig>): CustomizedUnshieldedWalletClass<TSyncUpdate, TSerialized, TConfig>;
@@ -0,0 +1,156 @@
1
+ // This file is part of MIDNIGHT-WALLET-SDK.
2
+ // Copyright (C) Midnight Foundation
3
+ // SPDX-License-Identifier: Apache-2.0
4
+ // Licensed under the Apache License, Version 2.0 (the "License");
5
+ // You may not use this file except in compliance with the License.
6
+ // You may obtain a copy of the License at
7
+ // http://www.apache.org/licenses/LICENSE-2.0
8
+ // Unless required by applicable law or agreed to in writing, software
9
+ // distributed under the License is distributed on an "AS IS" BASIS,
10
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
+ // See the License for the specific language governing permissions and
12
+ // limitations under the License.
13
+ import { ProtocolVersion } from '@midnightntwrk/wallet-sdk-abstractions';
14
+ import { V1Builder, V1Tag, CoreWallet, } from './v1/index.js';
15
+ import { Effect, Either } from 'effect';
16
+ import * as rx from 'rxjs';
17
+ import { WalletBuilder } from '@midnightntwrk/wallet-sdk-runtime';
18
+ export class UnshieldedWalletState {
19
+ static mapState = (variant) => (state) => {
20
+ const { serialization, coinsAndBalances, keys } = variant;
21
+ const { transactionHistory } = variant;
22
+ return new UnshieldedWalletState(state, { serialization, coinsAndBalances, keys }, { transactionHistory });
23
+ };
24
+ protocolVersion;
25
+ state;
26
+ capabilities;
27
+ services;
28
+ get balances() {
29
+ return this.capabilities.coinsAndBalances.getAvailableBalances(this.state);
30
+ }
31
+ get totalCoins() {
32
+ return this.capabilities.coinsAndBalances.getTotalCoins(this.state);
33
+ }
34
+ get availableCoins() {
35
+ return this.capabilities.coinsAndBalances.getAvailableCoins(this.state);
36
+ }
37
+ get pendingCoins() {
38
+ return this.capabilities.coinsAndBalances.getPendingCoins(this.state);
39
+ }
40
+ get address() {
41
+ return this.capabilities.keys.getAddress(this.state);
42
+ }
43
+ get progress() {
44
+ return this.state.progress;
45
+ }
46
+ constructor(state, capabilities, services) {
47
+ this.protocolVersion = state.version;
48
+ this.state = state.state;
49
+ this.capabilities = capabilities;
50
+ this.services = services;
51
+ }
52
+ serialize() {
53
+ return this.capabilities.serialization.serialize(this.state);
54
+ }
55
+ }
56
+ export function UnshieldedWallet(configuration) {
57
+ return CustomUnshieldedWallet(configuration, new V1Builder().withDefaults());
58
+ }
59
+ export function CustomUnshieldedWallet(configuration, builder) {
60
+ const buildArgs = [configuration];
61
+ const BaseWallet = WalletBuilder.init()
62
+ .withVariant(ProtocolVersion.MinSupportedVersion, builder)
63
+ .build(...buildArgs);
64
+ return class CustomUnshieldedWalletImplementation extends BaseWallet {
65
+ static startWithPublicKey(publicKeys) {
66
+ return CustomUnshieldedWalletImplementation.startFirst(CustomUnshieldedWalletImplementation, CoreWallet.init(publicKeys, configuration.networkId));
67
+ }
68
+ static restore(serializedState) {
69
+ const deserialized = CustomUnshieldedWalletImplementation.allVariantsRecord()[V1Tag].variant.deserializeState(serializedState)
70
+ .pipe(Either.getOrThrow);
71
+ return CustomUnshieldedWalletImplementation.startFirst(CustomUnshieldedWalletImplementation, deserialized);
72
+ }
73
+ state;
74
+ constructor(runtime, scope) {
75
+ super(runtime, scope);
76
+ this.state = this.rawState.pipe(rx.map(UnshieldedWalletState.mapState(CustomUnshieldedWalletImplementation.allVariantsRecord()[V1Tag].variant)), rx.shareReplay({ refCount: true, bufferSize: 1 }));
77
+ }
78
+ start() {
79
+ return this.runtime.dispatch({ [V1Tag]: (v1) => v1.startSyncInBackground() }).pipe(Effect.runPromise);
80
+ }
81
+ balanceFinalizedTransaction(tx) {
82
+ return this.runtime
83
+ .dispatch({
84
+ [V1Tag]: (v1) => v1.balanceFinalizedTransaction(tx),
85
+ })
86
+ .pipe(Effect.runPromise);
87
+ }
88
+ balanceUnboundTransaction(tx) {
89
+ return this.runtime
90
+ .dispatch({
91
+ [V1Tag]: (v1) => v1.balanceUnboundTransaction(tx),
92
+ })
93
+ .pipe(Effect.runPromise);
94
+ }
95
+ balanceUnprovenTransaction(tx) {
96
+ return this.runtime
97
+ .dispatch({
98
+ [V1Tag]: (v1) => v1.balanceUnprovenTransaction(tx),
99
+ })
100
+ .pipe(Effect.runPromise);
101
+ }
102
+ transferTransaction(outputs, ttl) {
103
+ return this.runtime
104
+ .dispatch({
105
+ [V1Tag]: (v1) => v1.transferTransaction(outputs, ttl),
106
+ })
107
+ .pipe(Effect.runPromise);
108
+ }
109
+ rotateUtxos(guaranteedUtxos, fallibleUtxos, nightVerifyingKey, ttl) {
110
+ return this.runtime
111
+ .dispatch({
112
+ [V1Tag]: (v1) => v1.rotateUtxos(guaranteedUtxos, fallibleUtxos, nightVerifyingKey, ttl),
113
+ })
114
+ .pipe(Effect.runPromise);
115
+ }
116
+ initSwap(desiredInputs, desiredOutputs, ttl) {
117
+ return this.runtime
118
+ .dispatch({ [V1Tag]: (v1) => v1.initSwap(desiredInputs, desiredOutputs, ttl) })
119
+ .pipe(Effect.runPromise);
120
+ }
121
+ signUnprovenTransaction(transaction, signSegment) {
122
+ return this.runtime
123
+ .dispatch({
124
+ [V1Tag]: (v1) => v1.signUnprovenTransaction(transaction, signSegment),
125
+ })
126
+ .pipe(Effect.runPromise);
127
+ }
128
+ signUnboundTransaction(transaction, signSegment) {
129
+ return this.runtime
130
+ .dispatch({
131
+ [V1Tag]: (v1) => v1.signUnboundTransaction(transaction, signSegment),
132
+ })
133
+ .pipe(Effect.runPromise);
134
+ }
135
+ revertTransaction(transaction) {
136
+ return this.runtime
137
+ .dispatch({
138
+ [V1Tag]: (v1) => v1.revertTransaction(transaction),
139
+ })
140
+ .pipe(Effect.runPromise);
141
+ }
142
+ waitForSyncedState(allowedGap = 0n) {
143
+ return rx.firstValueFrom(this.state.pipe(rx.filter((state) => state.state.progress.isCompleteWithin(allowedGap))));
144
+ }
145
+ /**
146
+ * Serializes the most recent state It's preferable to use [[UnshieldedWalletState.serialize]] instead, to know
147
+ * exactly, which state is serialized
148
+ */
149
+ serializeState() {
150
+ return rx.firstValueFrom(this.state).then((state) => state.serialize());
151
+ }
152
+ getAddress() {
153
+ return rx.firstValueFrom(this.state).then((state) => state.address);
154
+ }
155
+ };
156
+ }
@@ -0,0 +1,3 @@
1
+ export * from './UnshieldedWallet.js';
2
+ export { type UnshieldedTransactionHistoryEntry, UnshieldedSectionSchema } from './v1/TransactionHistory.js';
3
+ export * from './KeyStore.js';
package/dist/index.js ADDED
@@ -0,0 +1,15 @@
1
+ // This file is part of MIDNIGHT-WALLET-SDK.
2
+ // Copyright (C) Midnight Foundation
3
+ // SPDX-License-Identifier: Apache-2.0
4
+ // Licensed under the Apache License, Version 2.0 (the "License");
5
+ // You may not use this file except in compliance with the License.
6
+ // You may obtain a copy of the License at
7
+ // http://www.apache.org/licenses/LICENSE-2.0
8
+ // Unless required by applicable law or agreed to in writing, software
9
+ // distributed under the License is distributed on an "AS IS" BASIS,
10
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
+ // See the License for the specific language governing permissions and
12
+ // limitations under the License.
13
+ export * from './UnshieldedWallet.js';
14
+ export { UnshieldedSectionSchema } from './v1/TransactionHistory.js';
15
+ export * from './KeyStore.js';
@@ -0,0 +1,13 @@
1
+ import { type CoreWallet } from './CoreWallet.js';
2
+ import type * as ledger from '@midnight-ntwrk/ledger-v8';
3
+ import { type UtxoWithMeta } from './UnshieldedState.js';
4
+ export type Balances = Record<ledger.RawTokenType, bigint>;
5
+ export type CoinsAndBalancesCapability<TState> = {
6
+ getAvailableBalances(state: TState): Balances;
7
+ getPendingBalances(state: TState): Balances;
8
+ getTotalBalances(state: TState): Balances;
9
+ getAvailableCoins(state: TState): readonly UtxoWithMeta[];
10
+ getPendingCoins(state: TState): readonly UtxoWithMeta[];
11
+ getTotalCoins(state: TState): ReadonlyArray<UtxoWithMeta>;
12
+ };
13
+ export declare const makeDefaultCoinsAndBalancesCapability: () => CoinsAndBalancesCapability<CoreWallet>;
@@ -0,0 +1,36 @@
1
+ import { pipe } from 'effect';
2
+ import { RecordOps } from '@midnightntwrk/wallet-sdk-utilities';
3
+ import { UnshieldedState } from './UnshieldedState.js';
4
+ const calculateBalances = (utxos) => utxos.reduce((acc, { utxo }) => ({
5
+ ...acc,
6
+ [utxo.type]: acc[utxo.type] === undefined ? utxo.value : acc[utxo.type] + utxo.value,
7
+ }), {});
8
+ export const makeDefaultCoinsAndBalancesCapability = () => {
9
+ const getAvailableBalances = (state) => {
10
+ const availableCoins = getAvailableCoins(state);
11
+ return calculateBalances(availableCoins);
12
+ };
13
+ const getPendingBalances = (state) => {
14
+ const pendingCoins = getPendingCoins(state);
15
+ return calculateBalances(pendingCoins);
16
+ };
17
+ const getTotalBalances = (state) => {
18
+ const availableBalances = getAvailableBalances(state);
19
+ const pendingBalances = getPendingBalances(state);
20
+ return pipe([availableBalances, pendingBalances], RecordOps.mergeWithAccumulator(0n, (a, b) => a + b));
21
+ };
22
+ const getAvailableCoins = (state) => UnshieldedState.toArrays(state.state).availableUtxos;
23
+ const getPendingCoins = (state) => UnshieldedState.toArrays(state.state).pendingUtxos;
24
+ const getTotalCoins = (state) => [
25
+ ...getAvailableCoins(state),
26
+ ...getPendingCoins(state),
27
+ ];
28
+ return {
29
+ getAvailableBalances,
30
+ getPendingBalances,
31
+ getTotalBalances,
32
+ getAvailableCoins,
33
+ getPendingCoins,
34
+ getTotalCoins,
35
+ };
36
+ };
@@ -0,0 +1,24 @@
1
+ import { ProtocolVersion } from '@midnightntwrk/wallet-sdk-abstractions';
2
+ import { type SyncProgress, type SyncProgressData } from './SyncProgress.js';
3
+ import { type PublicKey } from '../KeyStore.js';
4
+ import { UnshieldedState, type UnshieldedUpdate } from './UnshieldedState.js';
5
+ import type * as ledger from '@midnight-ntwrk/ledger-v8';
6
+ import { Either } from 'effect';
7
+ import { type WalletError } from './WalletError.js';
8
+ export type CoreWallet = Readonly<{
9
+ state: UnshieldedState;
10
+ publicKey: PublicKey;
11
+ protocolVersion: ProtocolVersion.ProtocolVersion;
12
+ progress: SyncProgress;
13
+ networkId: string;
14
+ }>;
15
+ export declare const CoreWallet: {
16
+ init(publicKey: PublicKey, networkId: string): CoreWallet;
17
+ restore(state: UnshieldedState, publicKey: PublicKey, syncProgress: Omit<SyncProgressData, "isConnected">, protocolVersion: ProtocolVersion.ProtocolVersion, networkId: string): CoreWallet;
18
+ updateProgress(wallet: CoreWallet, { appliedId, highestTransactionId, isConnected }: Partial<SyncProgressData>): CoreWallet;
19
+ applyUpdate(coreWallet: CoreWallet, update: UnshieldedUpdate): Either.Either<CoreWallet, WalletError>;
20
+ applyFailedUpdate(coreWallet: CoreWallet, update: UnshieldedUpdate): Either.Either<CoreWallet, WalletError>;
21
+ rollbackUtxo(coreWallet: CoreWallet, utxo: ledger.Utxo): Either.Either<CoreWallet, WalletError>;
22
+ spend(coreWallet: CoreWallet, utxo: ledger.Utxo): Either.Either<CoreWallet, WalletError>;
23
+ spendUtxos(wallet: CoreWallet, utxos: ReadonlyArray<ledger.Utxo>): Either.Either<[ReadonlyArray<ledger.Utxo>, CoreWallet], WalletError>;
24
+ };
@@ -0,0 +1,60 @@
1
+ // This file is part of MIDNIGHT-WALLET-SDK.
2
+ // Copyright (C) Midnight Foundation
3
+ // SPDX-License-Identifier: Apache-2.0
4
+ // Licensed under the Apache License, Version 2.0 (the "License");
5
+ // You may not use this file except in compliance with the License.
6
+ // You may obtain a copy of the License at
7
+ // http://www.apache.org/licenses/LICENSE-2.0
8
+ // Unless required by applicable law or agreed to in writing, software
9
+ // distributed under the License is distributed on an "AS IS" BASIS,
10
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
+ // See the License for the specific language governing permissions and
12
+ // limitations under the License.
13
+ import { ProtocolVersion } from '@midnightntwrk/wallet-sdk-abstractions';
14
+ import { createSyncProgress } from './SyncProgress.js';
15
+ import { UnshieldedState } from './UnshieldedState.js';
16
+ import { Either, Array as Arr, pipe } from 'effect';
17
+ import { ApplyTransactionError, RollbackUtxoError, SpendUtxoError } from './WalletError.js';
18
+ export const CoreWallet = {
19
+ init(publicKey, networkId) {
20
+ return {
21
+ state: UnshieldedState.empty(),
22
+ publicKey,
23
+ protocolVersion: ProtocolVersion.MinSupportedVersion,
24
+ progress: createSyncProgress(),
25
+ networkId,
26
+ };
27
+ },
28
+ restore(state, publicKey, syncProgress, protocolVersion, networkId) {
29
+ return {
30
+ state,
31
+ publicKey,
32
+ protocolVersion,
33
+ progress: createSyncProgress(syncProgress),
34
+ networkId,
35
+ };
36
+ },
37
+ updateProgress(wallet, { appliedId, highestTransactionId, isConnected }) {
38
+ const progress = createSyncProgress({
39
+ appliedId: appliedId ?? wallet.progress.appliedId,
40
+ highestTransactionId: highestTransactionId ?? wallet.progress.highestTransactionId,
41
+ isConnected: isConnected ?? wallet.progress.isConnected,
42
+ });
43
+ return { ...wallet, progress };
44
+ },
45
+ applyUpdate(coreWallet, update) {
46
+ return UnshieldedState.applyUpdate(coreWallet.state, update).pipe(Either.map((state) => ({ ...coreWallet, state })), Either.mapLeft((error) => new ApplyTransactionError(error)));
47
+ },
48
+ applyFailedUpdate(coreWallet, update) {
49
+ return UnshieldedState.applyFailedUpdate(coreWallet.state, update).pipe(Either.map((state) => ({ ...coreWallet, state })), Either.mapLeft((error) => new ApplyTransactionError(error)));
50
+ },
51
+ rollbackUtxo(coreWallet, utxo) {
52
+ return UnshieldedState.rollbackSpendByUtxo(coreWallet.state, utxo).pipe(Either.map((state) => ({ ...coreWallet, state })), Either.mapLeft((error) => new RollbackUtxoError(error)));
53
+ },
54
+ spend(coreWallet, utxo) {
55
+ return UnshieldedState.spendByUtxo(coreWallet.state, utxo).pipe(Either.map((state) => ({ ...coreWallet, state })), Either.mapLeft((error) => new SpendUtxoError(error)));
56
+ },
57
+ spendUtxos(wallet, utxos) {
58
+ return pipe(utxos, Arr.reduce(Either.right([[], wallet.state]), (acc, utxoToSpend) => acc.pipe(Either.flatMap(([accUtxos, state]) => UnshieldedState.spendByUtxo(state, utxoToSpend).pipe(Either.map((nextState) => [accUtxos.concat([utxoToSpend]), nextState]), Either.mapLeft((error) => new SpendUtxoError(error)))))), Either.map(([spentUtxos, state]) => [spentUtxos, { ...wallet, state }]));
59
+ },
60
+ };
@@ -0,0 +1,8 @@
1
+ import { UnshieldedAddress } from '@midnightntwrk/wallet-sdk-address-format';
2
+ import type { CoreWallet } from './CoreWallet.js';
3
+ import { type SignatureVerifyingKey } from '@midnight-ntwrk/ledger-v8';
4
+ export type KeysCapability<TState> = {
5
+ getPublicKey(state: TState): SignatureVerifyingKey;
6
+ getAddress(state: TState): UnshieldedAddress;
7
+ };
8
+ export declare const makeDefaultKeysCapability: () => KeysCapability<CoreWallet>;
@@ -0,0 +1,23 @@
1
+ // This file is part of MIDNIGHT-WALLET-SDK.
2
+ // Copyright (C) Midnight Foundation
3
+ // SPDX-License-Identifier: Apache-2.0
4
+ // Licensed under the Apache License, Version 2.0 (the "License");
5
+ // You may not use this file except in compliance with the License.
6
+ // You may obtain a copy of the License at
7
+ // http://www.apache.org/licenses/LICENSE-2.0
8
+ // Unless required by applicable law or agreed to in writing, software
9
+ // distributed under the License is distributed on an "AS IS" BASIS,
10
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
+ // See the License for the specific language governing permissions and
12
+ // limitations under the License.
13
+ import { UnshieldedAddress } from '@midnightntwrk/wallet-sdk-address-format';
14
+ export const makeDefaultKeysCapability = () => {
15
+ return {
16
+ getPublicKey: (state) => {
17
+ return state.publicKey.publicKey;
18
+ },
19
+ getAddress: (state) => {
20
+ return new UnshieldedAddress(Buffer.from(state.publicKey.addressHex, 'hex'));
21
+ },
22
+ };
23
+ };
@@ -0,0 +1,48 @@
1
+ import { Effect, Scope, Stream } from 'effect';
2
+ import { type WalletRuntimeError, type Variant, StateChange } from '@midnightntwrk/wallet-sdk-runtime/abstractions';
3
+ import { type SerializationCapability } from './Serialization.js';
4
+ import { type SyncCapability, type SyncService } from './Sync.js';
5
+ import { type WalletSyncUpdate } from './SyncSchema.js';
6
+ import { type TransactingCapability, type TokenTransfer, type FinalizedTransactionBalanceResult, type UnboundTransactionBalanceResult, type UnprovenTransactionBalanceResult } from './Transacting.js';
7
+ import { type UtxoWithMeta } from './UnshieldedState.js';
8
+ import { type UnboundTransaction } from './TransactionOps.js';
9
+ import { type WalletError } from './WalletError.js';
10
+ import { type CoinsAndBalancesCapability } from './CoinsAndBalances.js';
11
+ import { type KeysCapability } from './Keys.js';
12
+ import { type CoinSelection } from '@midnightntwrk/wallet-sdk-capabilities';
13
+ import { type CoreWallet } from './CoreWallet.js';
14
+ import { type TransactionHistoryService } from './TransactionHistory.js';
15
+ import type * as ledger from '@midnight-ntwrk/ledger-v8';
16
+ export declare namespace RunningV1Variant {
17
+ type Context<TSerialized, TSyncUpdate> = {
18
+ serializationCapability: SerializationCapability<CoreWallet, TSerialized>;
19
+ syncService: SyncService<CoreWallet, TSyncUpdate>;
20
+ syncCapability: SyncCapability<CoreWallet, TSyncUpdate>;
21
+ transactingCapability: TransactingCapability<CoreWallet>;
22
+ coinsAndBalancesCapability: CoinsAndBalancesCapability<CoreWallet>;
23
+ keysCapability: KeysCapability<CoreWallet>;
24
+ coinSelection: CoinSelection<ledger.Utxo>;
25
+ transactionHistoryService: TransactionHistoryService;
26
+ };
27
+ type AnyContext = Context<any, any>;
28
+ }
29
+ export declare const V1Tag: unique symbol;
30
+ export type DefaultRunningV1 = RunningV1Variant<string, WalletSyncUpdate>;
31
+ export declare class RunningV1Variant<TSerialized, TSyncUpdate> implements Variant.RunningVariant<typeof V1Tag, CoreWallet> {
32
+ #private;
33
+ readonly __polyTag__: typeof V1Tag;
34
+ readonly state: Stream.Stream<StateChange.StateChange<CoreWallet>, WalletRuntimeError>;
35
+ constructor(scope: Scope.Scope, context: Variant.VariantContext<CoreWallet>, v1Context: RunningV1Variant.Context<TSerialized, TSyncUpdate>);
36
+ startSyncInBackground(): Effect.Effect<void>;
37
+ startSync(): Stream.Stream<void, WalletError, Scope.Scope>;
38
+ balanceFinalizedTransaction(tx: ledger.FinalizedTransaction): Effect.Effect<FinalizedTransactionBalanceResult, WalletError>;
39
+ balanceUnboundTransaction(tx: UnboundTransaction): Effect.Effect<UnboundTransactionBalanceResult, WalletError>;
40
+ balanceUnprovenTransaction(tx: ledger.UnprovenTransaction): Effect.Effect<UnprovenTransactionBalanceResult, WalletError>;
41
+ transferTransaction(outputs: ReadonlyArray<TokenTransfer>, ttl: Date): Effect.Effect<ledger.UnprovenTransaction, WalletError>;
42
+ rotateUtxos(guaranteedUtxos: ReadonlyArray<UtxoWithMeta>, fallibleUtxos: ReadonlyArray<UtxoWithMeta>, nightVerifyingKey: ledger.SignatureVerifyingKey, ttl: Date): Effect.Effect<ledger.UnprovenTransaction, WalletError>;
43
+ initSwap(desiredInputs: Record<string, bigint>, desiredOutputs: ReadonlyArray<TokenTransfer>, ttl: Date): Effect.Effect<ledger.UnprovenTransaction, WalletError>;
44
+ signUnprovenTransaction(transaction: ledger.UnprovenTransaction, signSegment: (data: Uint8Array) => ledger.Signature): Effect.Effect<ledger.UnprovenTransaction, WalletError>;
45
+ signUnboundTransaction(transaction: UnboundTransaction, signSegment: (data: Uint8Array) => ledger.Signature): Effect.Effect<UnboundTransaction, WalletError>;
46
+ revertTransaction(transaction: ledger.Transaction<ledger.SignatureEnabled, ledger.Proofish, ledger.Bindingish>): Effect.Effect<void, WalletError>;
47
+ serializeState(state: CoreWallet): TSerialized;
48
+ }