@midnight-ntwrk/wallet-sdk-unshielded-wallet 2.1.0 → 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 +7 -8
- package/dist/KeyStore.d.ts +3 -3
- package/dist/UnshieldedWallet.d.ts +13 -5
- package/dist/UnshieldedWallet.js +16 -8
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/v1/CoinsAndBalances.d.ts +3 -3
- package/dist/v1/CoreWallet.d.ts +5 -5
- package/dist/v1/Keys.d.ts +1 -1
- package/dist/v1/RunningV1Variant.d.ts +3 -1
- package/dist/v1/RunningV1Variant.js +5 -0
- package/dist/v1/Serialization.d.ts +2 -2
- package/dist/v1/Sync.d.ts +19 -6
- package/dist/v1/Sync.js +58 -6
- package/dist/v1/SyncSchema.d.ts +48 -48
- package/dist/v1/Transacting.d.ts +40 -16
- package/dist/v1/Transacting.js +73 -15
- package/dist/v1/TransactionHistory.d.ts +52 -10
- package/dist/v1/TransactionHistory.js +47 -24
- package/dist/v1/TransactionOps.d.ts +6 -10
- package/dist/v1/TransactionOps.js +5 -1
- package/dist/v1/UnshieldedState.d.ts +1 -1
- package/dist/v1/V1Builder.d.ts +18 -22
- package/dist/v1/WalletError.d.ts +19 -11
- package/dist/v1/WalletError.js +2 -0
- package/dist/v1/index.d.ts +1 -2
- package/dist/v1/index.js +1 -2
- package/package.json +9 -9
- package/dist/storage/InMemoryTransactionHistoryStorage.d.ts +0 -43
- package/dist/storage/InMemoryTransactionHistoryStorage.js +0 -65
- package/dist/storage/NoOpTransactionHistoryStorage.d.ts +0 -9
- package/dist/storage/NoOpTransactionHistoryStorage.js +0 -20
- package/dist/storage/TransactionHistoryStorage.d.ts +0 -34
- package/dist/storage/TransactionHistoryStorage.js +0 -33
- package/dist/storage/index.d.ts +0 -3
- package/dist/storage/index.js +0 -15
- package/dist/v1/Simulator.d.ts +0 -22
- package/dist/v1/Simulator.js +0 -103
package/README.md
CHANGED
|
@@ -24,18 +24,17 @@ Unlike shielded transactions, unshielded operations do not use zero-knowledge pr
|
|
|
24
24
|
### Starting the Wallet
|
|
25
25
|
|
|
26
26
|
```typescript
|
|
27
|
-
import {
|
|
28
|
-
|
|
29
|
-
createKeystore,
|
|
30
|
-
PublicKey,
|
|
31
|
-
InMemoryTransactionHistoryStorage,
|
|
32
|
-
} from '@midnight-ntwrk/wallet-sdk-unshielded-wallet';
|
|
27
|
+
import { UnshieldedWallet, createKeystore, PublicKey } from '@midnight-ntwrk/wallet-sdk-unshielded-wallet';
|
|
28
|
+
import { InMemoryTransactionHistoryStorage, NetworkId } from '@midnight-ntwrk/wallet-sdk-abstractions';
|
|
33
29
|
import { randomBytes } from 'node:crypto';
|
|
34
30
|
|
|
35
31
|
// Configuration for the wallet
|
|
36
32
|
const configuration = {
|
|
37
|
-
networkId:
|
|
38
|
-
|
|
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
|
+
},
|
|
39
38
|
txHistoryStorage: new InMemoryTransactionHistoryStorage(),
|
|
40
39
|
};
|
|
41
40
|
|
package/dist/KeyStore.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { MidnightBech32m } from '@midnight-ntwrk/wallet-sdk-address-format';
|
|
2
|
-
import { Signature, SignatureVerifyingKey, UserAddress } from '@midnight-ntwrk/ledger-v8';
|
|
3
|
-
import { NetworkId } from '@midnight-ntwrk/wallet-sdk-abstractions';
|
|
1
|
+
import { type MidnightBech32m } from '@midnight-ntwrk/wallet-sdk-address-format';
|
|
2
|
+
import { type Signature, type SignatureVerifyingKey, type UserAddress } from '@midnight-ntwrk/ledger-v8';
|
|
3
|
+
import { type NetworkId } from '@midnight-ntwrk/wallet-sdk-abstractions';
|
|
4
4
|
export type PublicKey = {
|
|
5
5
|
publicKey: SignatureVerifyingKey;
|
|
6
6
|
addressHex: UserAddress;
|
|
@@ -12,27 +12,28 @@ import { type UtxoWithMeta } from './v1/UnshieldedState.js';
|
|
|
12
12
|
import { type Variant, type VariantBuilder, type WalletLike } from '@midnight-ntwrk/wallet-sdk-runtime/abstractions';
|
|
13
13
|
import { type PublicKey } from './KeyStore.js';
|
|
14
14
|
import { type SyncProgress } from './v1/SyncProgress.js';
|
|
15
|
-
import { type UnshieldedUpdate } from './v1/SyncSchema.js';
|
|
16
15
|
import { type UnshieldedAddress } from '@midnight-ntwrk/wallet-sdk-address-format';
|
|
17
16
|
export type UnshieldedWalletCapabilities<TSerialized = string> = {
|
|
18
17
|
serialization: SerializationCapability<CoreWallet, TSerialized>;
|
|
19
18
|
coinsAndBalances: CoinsAndBalancesCapability<CoreWallet>;
|
|
20
19
|
keys: KeysCapability<CoreWallet>;
|
|
21
|
-
|
|
20
|
+
};
|
|
21
|
+
export type UnshieldedWalletServices = {
|
|
22
|
+
transactionHistory: TransactionHistoryService;
|
|
22
23
|
};
|
|
23
24
|
export declare class UnshieldedWalletState<TSerialized = string> {
|
|
24
|
-
static readonly mapState: <TSerialized_1 = string>(
|
|
25
|
+
static readonly mapState: <TSerialized_1 = string>(variant: UnshieldedWalletCapabilities<TSerialized_1> & UnshieldedWalletServices) => (state: ProtocolState.ProtocolState<CoreWallet>) => UnshieldedWalletState<TSerialized_1>;
|
|
25
26
|
readonly protocolVersion: ProtocolVersion.ProtocolVersion;
|
|
26
27
|
readonly state: CoreWallet;
|
|
27
28
|
readonly capabilities: UnshieldedWalletCapabilities<TSerialized>;
|
|
29
|
+
readonly services: UnshieldedWalletServices;
|
|
28
30
|
get balances(): Record<ledger.RawTokenType, bigint>;
|
|
29
31
|
get totalCoins(): readonly UtxoWithMeta[];
|
|
30
32
|
get availableCoins(): readonly UtxoWithMeta[];
|
|
31
33
|
get pendingCoins(): readonly UtxoWithMeta[];
|
|
32
34
|
get address(): UnshieldedAddress;
|
|
33
35
|
get progress(): SyncProgress;
|
|
34
|
-
|
|
35
|
-
constructor(state: ProtocolState.ProtocolState<CoreWallet>, capabilities: UnshieldedWalletCapabilities<TSerialized>);
|
|
36
|
+
constructor(state: ProtocolState.ProtocolState<CoreWallet>, capabilities: UnshieldedWalletCapabilities<TSerialized>, services: UnshieldedWalletServices);
|
|
36
37
|
serialize(): TSerialized;
|
|
37
38
|
}
|
|
38
39
|
export type UnshieldedWallet = CustomizedUnshieldedWallet<WalletSyncUpdate, string>;
|
|
@@ -45,6 +46,13 @@ export type UnshieldedWalletAPI<TSerialized = string> = {
|
|
|
45
46
|
balanceUnboundTransaction(tx: UnboundTransaction): Promise<UnboundTransactionBalanceResult>;
|
|
46
47
|
balanceUnprovenTransaction(tx: ledger.UnprovenTransaction): Promise<UnprovenTransactionBalanceResult>;
|
|
47
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>;
|
|
48
56
|
initSwap(desiredInputs: Record<ledger.RawTokenType, bigint>, desiredOutputs: readonly TokenTransfer[], ttl: Date): Promise<ledger.UnprovenTransaction>;
|
|
49
57
|
signUnprovenTransaction(transaction: ledger.UnprovenTransaction, signSegment: (data: Uint8Array) => ledger.Signature): Promise<ledger.UnprovenTransaction>;
|
|
50
58
|
signUnboundTransaction(transaction: UnboundTransaction, signSegment: (data: Uint8Array) => ledger.Signature): Promise<UnboundTransaction>;
|
package/dist/UnshieldedWallet.js
CHANGED
|
@@ -16,12 +16,15 @@ import { Effect, Either } from 'effect';
|
|
|
16
16
|
import * as rx from 'rxjs';
|
|
17
17
|
import { WalletBuilder } from '@midnight-ntwrk/wallet-sdk-runtime';
|
|
18
18
|
export class UnshieldedWalletState {
|
|
19
|
-
static mapState = (
|
|
20
|
-
|
|
19
|
+
static mapState = (variant) => (state) => {
|
|
20
|
+
const { serialization, coinsAndBalances, keys } = variant;
|
|
21
|
+
const { transactionHistory } = variant;
|
|
22
|
+
return new UnshieldedWalletState(state, { serialization, coinsAndBalances, keys }, { transactionHistory });
|
|
21
23
|
};
|
|
22
24
|
protocolVersion;
|
|
23
25
|
state;
|
|
24
26
|
capabilities;
|
|
27
|
+
services;
|
|
25
28
|
get balances() {
|
|
26
29
|
return this.capabilities.coinsAndBalances.getAvailableBalances(this.state);
|
|
27
30
|
}
|
|
@@ -40,13 +43,11 @@ export class UnshieldedWalletState {
|
|
|
40
43
|
get progress() {
|
|
41
44
|
return this.state.progress;
|
|
42
45
|
}
|
|
43
|
-
|
|
44
|
-
return this.capabilities.transactionHistory;
|
|
45
|
-
}
|
|
46
|
-
constructor(state, capabilities) {
|
|
46
|
+
constructor(state, capabilities, services) {
|
|
47
47
|
this.protocolVersion = state.version;
|
|
48
48
|
this.state = state.state;
|
|
49
49
|
this.capabilities = capabilities;
|
|
50
|
+
this.services = services;
|
|
50
51
|
}
|
|
51
52
|
serialize() {
|
|
52
53
|
return this.capabilities.serialization.serialize(this.state);
|
|
@@ -105,6 +106,13 @@ export function CustomUnshieldedWallet(configuration, builder) {
|
|
|
105
106
|
})
|
|
106
107
|
.pipe(Effect.runPromise);
|
|
107
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
|
+
}
|
|
108
116
|
initSwap(desiredInputs, desiredOutputs, ttl) {
|
|
109
117
|
return this.runtime
|
|
110
118
|
.dispatch({ [V1Tag]: (v1) => v1.initSwap(desiredInputs, desiredOutputs, ttl) })
|
|
@@ -135,8 +143,8 @@ export function CustomUnshieldedWallet(configuration, builder) {
|
|
|
135
143
|
return rx.firstValueFrom(this.state.pipe(rx.filter((state) => state.state.progress.isCompleteWithin(allowedGap))));
|
|
136
144
|
}
|
|
137
145
|
/**
|
|
138
|
-
* Serializes the most recent state
|
|
139
|
-
*
|
|
146
|
+
* Serializes the most recent state It's preferable to use [[UnshieldedWalletState.serialize]] instead, to know
|
|
147
|
+
* exactly, which state is serialized
|
|
140
148
|
*/
|
|
141
149
|
serializeState() {
|
|
142
150
|
return rx.firstValueFrom(this.state).then((state) => state.serialize());
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -11,5 +11,5 @@
|
|
|
11
11
|
// See the License for the specific language governing permissions and
|
|
12
12
|
// limitations under the License.
|
|
13
13
|
export * from './UnshieldedWallet.js';
|
|
14
|
-
export
|
|
14
|
+
export { UnshieldedSectionSchema } from './v1/TransactionHistory.js';
|
|
15
15
|
export * from './KeyStore.js';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { CoreWallet } from './CoreWallet.js';
|
|
2
|
-
import * as ledger from '@midnight-ntwrk/ledger-v8';
|
|
3
|
-
import { UtxoWithMeta } from './UnshieldedState.js';
|
|
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
4
|
export type Balances = Record<ledger.RawTokenType, bigint>;
|
|
5
5
|
export type CoinsAndBalancesCapability<TState> = {
|
|
6
6
|
getAvailableBalances(state: TState): Balances;
|
package/dist/v1/CoreWallet.d.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { ProtocolVersion } from '@midnight-ntwrk/wallet-sdk-abstractions';
|
|
2
|
-
import { SyncProgress, SyncProgressData } from './SyncProgress.js';
|
|
3
|
-
import { PublicKey } from '../KeyStore.js';
|
|
4
|
-
import { UnshieldedState, UnshieldedUpdate } from './UnshieldedState.js';
|
|
5
|
-
import * as ledger from '@midnight-ntwrk/ledger-v8';
|
|
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
6
|
import { Either } from 'effect';
|
|
7
|
-
import { WalletError } from './WalletError.js';
|
|
7
|
+
import { type WalletError } from './WalletError.js';
|
|
8
8
|
export type CoreWallet = Readonly<{
|
|
9
9
|
state: UnshieldedState;
|
|
10
10
|
publicKey: PublicKey;
|
package/dist/v1/Keys.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { UnshieldedAddress } from '@midnight-ntwrk/wallet-sdk-address-format';
|
|
2
2
|
import type { CoreWallet } from './CoreWallet.js';
|
|
3
|
-
import { SignatureVerifyingKey } from '@midnight-ntwrk/ledger-v8';
|
|
3
|
+
import { type SignatureVerifyingKey } from '@midnight-ntwrk/ledger-v8';
|
|
4
4
|
export type KeysCapability<TState> = {
|
|
5
5
|
getPublicKey(state: TState): SignatureVerifyingKey;
|
|
6
6
|
getAddress(state: TState): UnshieldedAddress;
|
|
@@ -4,6 +4,7 @@ import { type SerializationCapability } from './Serialization.js';
|
|
|
4
4
|
import { type SyncCapability, type SyncService } from './Sync.js';
|
|
5
5
|
import { type WalletSyncUpdate } from './SyncSchema.js';
|
|
6
6
|
import { type TransactingCapability, type TokenTransfer, type FinalizedTransactionBalanceResult, type UnboundTransactionBalanceResult, type UnprovenTransactionBalanceResult } from './Transacting.js';
|
|
7
|
+
import { type UtxoWithMeta } from './UnshieldedState.js';
|
|
7
8
|
import { type UnboundTransaction } from './TransactionOps.js';
|
|
8
9
|
import { type WalletError } from './WalletError.js';
|
|
9
10
|
import { type CoinsAndBalancesCapability } from './CoinsAndBalances.js';
|
|
@@ -21,7 +22,7 @@ export declare namespace RunningV1Variant {
|
|
|
21
22
|
coinsAndBalancesCapability: CoinsAndBalancesCapability<CoreWallet>;
|
|
22
23
|
keysCapability: KeysCapability<CoreWallet>;
|
|
23
24
|
coinSelection: CoinSelection<ledger.Utxo>;
|
|
24
|
-
transactionHistoryService: TransactionHistoryService
|
|
25
|
+
transactionHistoryService: TransactionHistoryService;
|
|
25
26
|
};
|
|
26
27
|
type AnyContext = Context<any, any>;
|
|
27
28
|
}
|
|
@@ -38,6 +39,7 @@ export declare class RunningV1Variant<TSerialized, TSyncUpdate> implements Varia
|
|
|
38
39
|
balanceUnboundTransaction(tx: UnboundTransaction): Effect.Effect<UnboundTransactionBalanceResult, WalletError>;
|
|
39
40
|
balanceUnprovenTransaction(tx: ledger.UnprovenTransaction): Effect.Effect<UnprovenTransactionBalanceResult, WalletError>;
|
|
40
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>;
|
|
41
43
|
initSwap(desiredInputs: Record<string, bigint>, desiredOutputs: ReadonlyArray<TokenTransfer>, ttl: Date): Effect.Effect<ledger.UnprovenTransaction, WalletError>;
|
|
42
44
|
signUnprovenTransaction(transaction: ledger.UnprovenTransaction, signSegment: (data: Uint8Array) => ledger.Signature): Effect.Effect<ledger.UnprovenTransaction, WalletError>;
|
|
43
45
|
signUnboundTransaction(transaction: UnboundTransaction, signSegment: (data: Uint8Array) => ledger.Signature): Effect.Effect<UnboundTransaction, WalletError>;
|
|
@@ -87,6 +87,11 @@ export class RunningV1Variant {
|
|
|
87
87
|
return pipe(this.#v1Context.transactingCapability.makeTransfer(state, outputs, ttl), EitherOps.toEffect, Effect.map(({ transaction, newState }) => [transaction, newState]));
|
|
88
88
|
});
|
|
89
89
|
}
|
|
90
|
+
rotateUtxos(guaranteedUtxos, fallibleUtxos, nightVerifyingKey, ttl) {
|
|
91
|
+
return SubscriptionRef.modifyEffect(this.#context.stateRef, (state) => {
|
|
92
|
+
return pipe(this.#v1Context.transactingCapability.rotateUtxos(state, guaranteedUtxos, fallibleUtxos, nightVerifyingKey, ttl), EitherOps.toEffect, Effect.map(({ transaction, newState }) => [transaction, newState]));
|
|
93
|
+
});
|
|
94
|
+
}
|
|
90
95
|
initSwap(desiredInputs, desiredOutputs, ttl) {
|
|
91
96
|
return SubscriptionRef.modifyEffect(this.#context.stateRef, (state) => {
|
|
92
97
|
return pipe(this.#v1Context.transactingCapability.initSwap(state, desiredInputs, desiredOutputs, ttl), Effect.map(({ transaction, newState }) => [transaction, newState]));
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Either } from 'effect';
|
|
2
|
-
import { WalletError } from './WalletError.js';
|
|
2
|
+
import { type WalletError } from './WalletError.js';
|
|
3
3
|
import { CoreWallet } from './CoreWallet.js';
|
|
4
|
-
import { NetworkId } from '@midnight-ntwrk/wallet-sdk-abstractions';
|
|
4
|
+
import { type NetworkId } from '@midnight-ntwrk/wallet-sdk-abstractions';
|
|
5
5
|
export type SerializationCapability<TWallet, TSerialized> = {
|
|
6
6
|
serialize(wallet: TWallet): TSerialized;
|
|
7
7
|
deserialize(data: TSerialized): Either.Either<TWallet, WalletError>;
|
package/dist/v1/Sync.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { Scope, Stream, Either } from 'effect';
|
|
1
|
+
import { type Scope, Stream, Either } from 'effect';
|
|
2
2
|
import { CoreWallet } from './CoreWallet.js';
|
|
3
|
-
import { Simulator, SimulatorState } from '
|
|
4
|
-
import { WalletError } from './WalletError.js';
|
|
5
|
-
import { TransactionHistoryService } from './TransactionHistory.js';
|
|
6
|
-
import { WalletSyncUpdate } from './SyncSchema.js';
|
|
3
|
+
import { type Simulator, type SimulatorState } from '@midnight-ntwrk/wallet-sdk-capabilities/simulation';
|
|
4
|
+
import { type WalletError } from './WalletError.js';
|
|
5
|
+
import { type TransactionHistoryService } from './TransactionHistory.js';
|
|
6
|
+
import { type WalletSyncUpdate } from './SyncSchema.js';
|
|
7
7
|
export interface SyncService<TState, TUpdate> {
|
|
8
8
|
updates: (state: TState) => Stream.Stream<TUpdate, WalletError, Scope.Scope>;
|
|
9
9
|
}
|
|
@@ -19,7 +19,7 @@ export type DefaultSyncConfiguration = {
|
|
|
19
19
|
indexerClientConnection: IndexerClientConnection;
|
|
20
20
|
};
|
|
21
21
|
export type DefaultSyncContext = {
|
|
22
|
-
transactionHistoryService: TransactionHistoryService
|
|
22
|
+
transactionHistoryService: TransactionHistoryService;
|
|
23
23
|
};
|
|
24
24
|
export declare const makeDefaultSyncService: (config: DefaultSyncConfiguration) => SyncService<CoreWallet, WalletSyncUpdate>;
|
|
25
25
|
export declare const makeDefaultSyncCapability: (_config: DefaultSyncConfiguration, getContext: () => DefaultSyncContext) => SyncCapability<CoreWallet, WalletSyncUpdate>;
|
|
@@ -30,4 +30,17 @@ export type SimulatorSyncUpdate = {
|
|
|
30
30
|
update: SimulatorState;
|
|
31
31
|
};
|
|
32
32
|
export declare const makeSimulatorSyncService: (config: SimulatorSyncConfiguration) => SyncService<CoreWallet, SimulatorSyncUpdate>;
|
|
33
|
+
/**
|
|
34
|
+
* Creates a sync capability that extracts UTXOs from the simulator's ledger state and applies them to the wallet.
|
|
35
|
+
*
|
|
36
|
+
* This capability:
|
|
37
|
+
*
|
|
38
|
+
* 1. Extracts all UTXOs for the wallet's address from the simulator ledger
|
|
39
|
+
* 2. Compares with the wallet's current UTXOs to determine created/spent
|
|
40
|
+
* 3. Applies the update to the wallet state
|
|
41
|
+
*
|
|
42
|
+
* Note: The `registeredForDustGeneration` flag is set based on whether the address appears in the ledger's dust
|
|
43
|
+
* delegation table. This is a heuristic that may not perfectly match the indexer's behavior but provides reasonable
|
|
44
|
+
* accuracy.
|
|
45
|
+
*/
|
|
33
46
|
export declare const makeSimulatorSyncCapability: () => SyncCapability<CoreWallet, SimulatorSyncUpdate>;
|
package/dist/v1/Sync.js
CHANGED
|
@@ -10,14 +10,17 @@
|
|
|
10
10
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
11
11
|
// See the License for the specific language governing permissions and
|
|
12
12
|
// limitations under the License.
|
|
13
|
-
import { Stream, Schema, pipe, Either } from 'effect';
|
|
13
|
+
import { Effect, Stream, Schema, pipe, Either, HashMap } from 'effect';
|
|
14
14
|
import { CoreWallet } from './CoreWallet.js';
|
|
15
|
+
import { UtxoWithMeta } from './UnshieldedState.js';
|
|
16
|
+
import { getCurrentBlockNumber, } from '@midnight-ntwrk/wallet-sdk-capabilities/simulation';
|
|
15
17
|
import { UnshieldedTransactions } from '@midnight-ntwrk/wallet-sdk-indexer-client';
|
|
16
18
|
import { WsSubscriptionClient, ConnectionHelper } from '@midnight-ntwrk/wallet-sdk-indexer-client/effect';
|
|
17
19
|
import { SyncWalletError } from './WalletError.js';
|
|
18
20
|
import { WsURL } from '@midnight-ntwrk/wallet-sdk-utilities/networking';
|
|
19
21
|
import { EitherOps } from '@midnight-ntwrk/wallet-sdk-utilities';
|
|
20
22
|
import { WalletSyncUpdateSchema } from './SyncSchema.js';
|
|
23
|
+
import * as ledger from '@midnight-ntwrk/ledger-v8';
|
|
21
24
|
export const makeDefaultSyncService = (config) => {
|
|
22
25
|
return {
|
|
23
26
|
updates: (state) => {
|
|
@@ -63,7 +66,7 @@ export const makeDefaultSyncCapability = (_config, getContext) => {
|
|
|
63
66
|
appliedId: BigInt(update.transaction.id),
|
|
64
67
|
});
|
|
65
68
|
const { transactionHistoryService } = getContext();
|
|
66
|
-
|
|
69
|
+
Effect.runFork(transactionHistoryService.put(update));
|
|
67
70
|
return stateAfterUpdatingProgress;
|
|
68
71
|
}));
|
|
69
72
|
}
|
|
@@ -72,14 +75,63 @@ export const makeDefaultSyncCapability = (_config, getContext) => {
|
|
|
72
75
|
};
|
|
73
76
|
export const makeSimulatorSyncService = (config) => {
|
|
74
77
|
return {
|
|
75
|
-
updates: (_state) =>
|
|
78
|
+
updates: (_state) => {
|
|
79
|
+
// Get the initial state immediately to ensure we process existing blocks.
|
|
80
|
+
// Then subscribe to state$ for subsequent changes.
|
|
81
|
+
return pipe(Stream.fromEffect(config.simulator.getLatestState()), Stream.concat(config.simulator.state$), Stream.map((state) => ({ update: state })));
|
|
82
|
+
},
|
|
76
83
|
};
|
|
77
84
|
};
|
|
85
|
+
/**
|
|
86
|
+
* Creates a sync capability that extracts UTXOs from the simulator's ledger state and applies them to the wallet.
|
|
87
|
+
*
|
|
88
|
+
* This capability:
|
|
89
|
+
*
|
|
90
|
+
* 1. Extracts all UTXOs for the wallet's address from the simulator ledger
|
|
91
|
+
* 2. Compares with the wallet's current UTXOs to determine created/spent
|
|
92
|
+
* 3. Applies the update to the wallet state
|
|
93
|
+
*
|
|
94
|
+
* Note: The `registeredForDustGeneration` flag is set based on whether the address appears in the ledger's dust
|
|
95
|
+
* delegation table. This is a heuristic that may not perfectly match the indexer's behavior but provides reasonable
|
|
96
|
+
* accuracy.
|
|
97
|
+
*/
|
|
78
98
|
export const makeSimulatorSyncCapability = () => {
|
|
99
|
+
const utxoKey = (utxo) => `${utxo.intentHash}#${utxo.outputNo}`;
|
|
79
100
|
return {
|
|
80
|
-
applyUpdate: (state,
|
|
81
|
-
|
|
82
|
-
|
|
101
|
+
applyUpdate: (state, update) => {
|
|
102
|
+
const { ledger: ledgerState, currentTime } = update.update;
|
|
103
|
+
const walletAddress = state.publicKey.addressHex;
|
|
104
|
+
const nativeTokenType = ledger.nativeToken().raw;
|
|
105
|
+
// Heuristic: check if address appears in the ledger's dust delegation table
|
|
106
|
+
const isAddressRegisteredForDust = ledgerState.dust.toString().includes(walletAddress);
|
|
107
|
+
// Build a Map of simulator UTXOs keyed by intent hash + output number
|
|
108
|
+
const simulatorUtxoMap = new Map(Array.from(ledgerState.utxo.filter(walletAddress)).map((utxo) => [
|
|
109
|
+
utxoKey(utxo),
|
|
110
|
+
new UtxoWithMeta({
|
|
111
|
+
utxo,
|
|
112
|
+
meta: {
|
|
113
|
+
ctime: currentTime,
|
|
114
|
+
registeredForDustGeneration: utxo.type === nativeTokenType && isAddressRegisteredForDust,
|
|
115
|
+
},
|
|
116
|
+
}),
|
|
117
|
+
]));
|
|
118
|
+
// Created: in simulator but not in wallet (neither available nor pending)
|
|
119
|
+
const createdUtxos = Array.from(simulatorUtxoMap)
|
|
120
|
+
.filter(([hash]) => !HashMap.has(state.state.availableUtxos, hash) && !HashMap.has(state.state.pendingUtxos, hash))
|
|
121
|
+
.map(([, utxo]) => utxo);
|
|
122
|
+
// Spent: in wallet (pending or available) but no longer in simulator
|
|
123
|
+
const spentUtxos = [
|
|
124
|
+
...Array.from(HashMap.entries(state.state.pendingUtxos)),
|
|
125
|
+
...Array.from(HashMap.entries(state.state.availableUtxos)),
|
|
126
|
+
]
|
|
127
|
+
.filter(([hash]) => !simulatorUtxoMap.has(hash))
|
|
128
|
+
.map(([, utxo]) => utxo);
|
|
129
|
+
const blockNumber = getCurrentBlockNumber(update.update);
|
|
130
|
+
const updateProgress = (wallet) => CoreWallet.updateProgress(wallet, { appliedId: blockNumber, isConnected: true });
|
|
131
|
+
if (createdUtxos.length === 0 && spentUtxos.length === 0) {
|
|
132
|
+
return Either.right(updateProgress(state));
|
|
133
|
+
}
|
|
134
|
+
return pipe(CoreWallet.applyUpdate(state, { createdUtxos, spentUtxos, status: 'SUCCESS' }), Either.map(updateProgress));
|
|
83
135
|
},
|
|
84
136
|
};
|
|
85
137
|
};
|
package/dist/v1/SyncSchema.d.ts
CHANGED
|
@@ -160,32 +160,19 @@ export declare const UnshieldedUpdateSchema: Schema.transform<Schema.Struct<{
|
|
|
160
160
|
};
|
|
161
161
|
}[];
|
|
162
162
|
readonly status: "SUCCESS" | "FAILURE" | "PARTIAL_SUCCESS";
|
|
163
|
-
readonly createdUtxos: readonly {
|
|
164
|
-
readonly utxo: {
|
|
165
|
-
readonly type: string;
|
|
166
|
-
readonly value: bigint;
|
|
167
|
-
readonly owner: string;
|
|
168
|
-
readonly intentHash: string;
|
|
169
|
-
readonly outputNo: number;
|
|
170
|
-
};
|
|
171
|
-
readonly meta: {
|
|
172
|
-
readonly ctime: Date;
|
|
173
|
-
readonly registeredForDustGeneration: boolean;
|
|
174
|
-
};
|
|
175
|
-
}[];
|
|
176
163
|
readonly transaction: {
|
|
177
164
|
readonly type: "RegularTransaction" | "SystemTransaction";
|
|
178
165
|
readonly protocolVersion: number;
|
|
179
166
|
readonly id: number;
|
|
180
167
|
readonly hash: string;
|
|
181
168
|
readonly identifiers?: readonly string[] | undefined;
|
|
169
|
+
readonly block: {
|
|
170
|
+
readonly timestamp: Date;
|
|
171
|
+
};
|
|
182
172
|
readonly fees?: {
|
|
183
173
|
readonly paidFees: bigint;
|
|
184
174
|
readonly estimatedFees: bigint;
|
|
185
175
|
} | undefined;
|
|
186
|
-
readonly block: {
|
|
187
|
-
readonly timestamp: Date;
|
|
188
|
-
};
|
|
189
176
|
readonly transactionResult?: {
|
|
190
177
|
readonly status: "SUCCESS" | "FAILURE" | "PARTIAL_SUCCESS";
|
|
191
178
|
readonly segments: readonly {
|
|
@@ -194,9 +181,7 @@ export declare const UnshieldedUpdateSchema: Schema.transform<Schema.Struct<{
|
|
|
194
181
|
}[] | null;
|
|
195
182
|
} | undefined;
|
|
196
183
|
};
|
|
197
|
-
|
|
198
|
-
readonly type: "UnshieldedTransaction";
|
|
199
|
-
readonly spentUtxos: readonly {
|
|
184
|
+
readonly createdUtxos: readonly {
|
|
200
185
|
readonly utxo: {
|
|
201
186
|
readonly type: string;
|
|
202
187
|
readonly value: bigint;
|
|
@@ -209,8 +194,9 @@ export declare const UnshieldedUpdateSchema: Schema.transform<Schema.Struct<{
|
|
|
209
194
|
readonly registeredForDustGeneration: boolean;
|
|
210
195
|
};
|
|
211
196
|
}[];
|
|
212
|
-
|
|
213
|
-
readonly
|
|
197
|
+
}, {
|
|
198
|
+
readonly type: "UnshieldedTransaction";
|
|
199
|
+
readonly spentUtxos: readonly {
|
|
214
200
|
readonly utxo: {
|
|
215
201
|
readonly type: string;
|
|
216
202
|
readonly value: bigint;
|
|
@@ -223,19 +209,20 @@ export declare const UnshieldedUpdateSchema: Schema.transform<Schema.Struct<{
|
|
|
223
209
|
readonly registeredForDustGeneration: boolean;
|
|
224
210
|
};
|
|
225
211
|
}[];
|
|
212
|
+
readonly status: "SUCCESS" | "FAILURE" | "PARTIAL_SUCCESS";
|
|
226
213
|
readonly transaction: {
|
|
227
214
|
readonly type: "RegularTransaction" | "SystemTransaction";
|
|
228
215
|
readonly protocolVersion: number;
|
|
229
216
|
readonly id: number;
|
|
230
217
|
readonly hash: string;
|
|
231
218
|
readonly identifiers?: readonly string[] | undefined;
|
|
219
|
+
readonly block: {
|
|
220
|
+
readonly timestamp: Date;
|
|
221
|
+
};
|
|
232
222
|
readonly fees?: {
|
|
233
223
|
readonly paidFees: bigint;
|
|
234
224
|
readonly estimatedFees: bigint;
|
|
235
225
|
} | undefined;
|
|
236
|
-
readonly block: {
|
|
237
|
-
readonly timestamp: Date;
|
|
238
|
-
};
|
|
239
226
|
readonly transactionResult?: {
|
|
240
227
|
readonly status: "SUCCESS" | "FAILURE" | "PARTIAL_SUCCESS";
|
|
241
228
|
readonly segments: readonly {
|
|
@@ -244,6 +231,19 @@ export declare const UnshieldedUpdateSchema: Schema.transform<Schema.Struct<{
|
|
|
244
231
|
}[] | null;
|
|
245
232
|
} | undefined;
|
|
246
233
|
};
|
|
234
|
+
readonly createdUtxos: readonly {
|
|
235
|
+
readonly utxo: {
|
|
236
|
+
readonly type: string;
|
|
237
|
+
readonly value: bigint;
|
|
238
|
+
readonly owner: string;
|
|
239
|
+
readonly intentHash: string;
|
|
240
|
+
readonly outputNo: number;
|
|
241
|
+
};
|
|
242
|
+
readonly meta: {
|
|
243
|
+
readonly ctime: Date;
|
|
244
|
+
readonly registeredForDustGeneration: boolean;
|
|
245
|
+
};
|
|
246
|
+
}[];
|
|
247
247
|
}, never>>;
|
|
248
248
|
export type UnshieldedUpdate = Schema.Schema.Type<typeof UnshieldedUpdateSchema>;
|
|
249
249
|
export declare const ProgressSchema: Schema.Struct<{
|
|
@@ -355,32 +355,19 @@ export declare const WalletSyncUpdateSchema: Schema.Union<[Schema.transform<Sche
|
|
|
355
355
|
};
|
|
356
356
|
}[];
|
|
357
357
|
readonly status: "SUCCESS" | "FAILURE" | "PARTIAL_SUCCESS";
|
|
358
|
-
readonly createdUtxos: readonly {
|
|
359
|
-
readonly utxo: {
|
|
360
|
-
readonly type: string;
|
|
361
|
-
readonly value: bigint;
|
|
362
|
-
readonly owner: string;
|
|
363
|
-
readonly intentHash: string;
|
|
364
|
-
readonly outputNo: number;
|
|
365
|
-
};
|
|
366
|
-
readonly meta: {
|
|
367
|
-
readonly ctime: Date;
|
|
368
|
-
readonly registeredForDustGeneration: boolean;
|
|
369
|
-
};
|
|
370
|
-
}[];
|
|
371
358
|
readonly transaction: {
|
|
372
359
|
readonly type: "RegularTransaction" | "SystemTransaction";
|
|
373
360
|
readonly protocolVersion: number;
|
|
374
361
|
readonly id: number;
|
|
375
362
|
readonly hash: string;
|
|
376
363
|
readonly identifiers?: readonly string[] | undefined;
|
|
364
|
+
readonly block: {
|
|
365
|
+
readonly timestamp: Date;
|
|
366
|
+
};
|
|
377
367
|
readonly fees?: {
|
|
378
368
|
readonly paidFees: bigint;
|
|
379
369
|
readonly estimatedFees: bigint;
|
|
380
370
|
} | undefined;
|
|
381
|
-
readonly block: {
|
|
382
|
-
readonly timestamp: Date;
|
|
383
|
-
};
|
|
384
371
|
readonly transactionResult?: {
|
|
385
372
|
readonly status: "SUCCESS" | "FAILURE" | "PARTIAL_SUCCESS";
|
|
386
373
|
readonly segments: readonly {
|
|
@@ -389,9 +376,7 @@ export declare const WalletSyncUpdateSchema: Schema.Union<[Schema.transform<Sche
|
|
|
389
376
|
}[] | null;
|
|
390
377
|
} | undefined;
|
|
391
378
|
};
|
|
392
|
-
|
|
393
|
-
readonly type: "UnshieldedTransaction";
|
|
394
|
-
readonly spentUtxos: readonly {
|
|
379
|
+
readonly createdUtxos: readonly {
|
|
395
380
|
readonly utxo: {
|
|
396
381
|
readonly type: string;
|
|
397
382
|
readonly value: bigint;
|
|
@@ -404,8 +389,9 @@ export declare const WalletSyncUpdateSchema: Schema.Union<[Schema.transform<Sche
|
|
|
404
389
|
readonly registeredForDustGeneration: boolean;
|
|
405
390
|
};
|
|
406
391
|
}[];
|
|
407
|
-
|
|
408
|
-
readonly
|
|
392
|
+
}, {
|
|
393
|
+
readonly type: "UnshieldedTransaction";
|
|
394
|
+
readonly spentUtxos: readonly {
|
|
409
395
|
readonly utxo: {
|
|
410
396
|
readonly type: string;
|
|
411
397
|
readonly value: bigint;
|
|
@@ -418,19 +404,20 @@ export declare const WalletSyncUpdateSchema: Schema.Union<[Schema.transform<Sche
|
|
|
418
404
|
readonly registeredForDustGeneration: boolean;
|
|
419
405
|
};
|
|
420
406
|
}[];
|
|
407
|
+
readonly status: "SUCCESS" | "FAILURE" | "PARTIAL_SUCCESS";
|
|
421
408
|
readonly transaction: {
|
|
422
409
|
readonly type: "RegularTransaction" | "SystemTransaction";
|
|
423
410
|
readonly protocolVersion: number;
|
|
424
411
|
readonly id: number;
|
|
425
412
|
readonly hash: string;
|
|
426
413
|
readonly identifiers?: readonly string[] | undefined;
|
|
414
|
+
readonly block: {
|
|
415
|
+
readonly timestamp: Date;
|
|
416
|
+
};
|
|
427
417
|
readonly fees?: {
|
|
428
418
|
readonly paidFees: bigint;
|
|
429
419
|
readonly estimatedFees: bigint;
|
|
430
420
|
} | undefined;
|
|
431
|
-
readonly block: {
|
|
432
|
-
readonly timestamp: Date;
|
|
433
|
-
};
|
|
434
421
|
readonly transactionResult?: {
|
|
435
422
|
readonly status: "SUCCESS" | "FAILURE" | "PARTIAL_SUCCESS";
|
|
436
423
|
readonly segments: readonly {
|
|
@@ -439,6 +426,19 @@ export declare const WalletSyncUpdateSchema: Schema.Union<[Schema.transform<Sche
|
|
|
439
426
|
}[] | null;
|
|
440
427
|
} | undefined;
|
|
441
428
|
};
|
|
429
|
+
readonly createdUtxos: readonly {
|
|
430
|
+
readonly utxo: {
|
|
431
|
+
readonly type: string;
|
|
432
|
+
readonly value: bigint;
|
|
433
|
+
readonly owner: string;
|
|
434
|
+
readonly intentHash: string;
|
|
435
|
+
readonly outputNo: number;
|
|
436
|
+
};
|
|
437
|
+
readonly meta: {
|
|
438
|
+
readonly ctime: Date;
|
|
439
|
+
readonly registeredForDustGeneration: boolean;
|
|
440
|
+
};
|
|
441
|
+
}[];
|
|
442
442
|
}, never>>, Schema.Struct<{
|
|
443
443
|
type: Schema.Literal<["UnshieldedTransactionsProgress"]>;
|
|
444
444
|
highestTransactionId: typeof Schema.Number;
|