@midnight-ntwrk/wallet-sdk-dust-wallet 3.0.0 → 4.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/dist/DustWallet.d.ts +49 -33
- package/dist/DustWallet.js +40 -25
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/v1/CoinsAndBalances.d.ts +16 -16
- package/dist/v1/CoinsAndBalances.js +20 -38
- package/dist/v1/CoreWallet.d.ts +5 -5
- package/dist/v1/CoreWallet.js +11 -7
- package/dist/v1/Keys.d.ts +2 -2
- package/dist/v1/RunningV1Variant.d.ts +13 -8
- package/dist/v1/RunningV1Variant.js +38 -15
- package/dist/v1/Serialization.d.ts +1 -1
- package/dist/v1/Sync.d.ts +37 -10
- package/dist/v1/Sync.js +65 -18
- package/dist/v1/Transacting.d.ts +58 -10
- package/dist/v1/Transacting.js +96 -8
- package/dist/v1/TransactionHistory.d.ts +69 -0
- package/dist/v1/TransactionHistory.js +106 -0
- package/dist/v1/V1Builder.d.ts +16 -14
- package/dist/v1/V1Builder.js +15 -1
- package/dist/v1/WalletError.d.ts +14 -6
- package/dist/v1/WalletError.js +2 -0
- package/dist/v1/index.d.ts +2 -1
- package/dist/v1/index.js +2 -1
- package/dist/v1/types/Dust.d.ts +7 -21
- package/dist/v1/types/ledger.d.ts +1 -1
- package/package.json +9 -9
- package/dist/v1/Simulator.d.ts +0 -33
- package/dist/v1/Simulator.js +0 -114
package/dist/DustWallet.d.ts
CHANGED
|
@@ -1,61 +1,77 @@
|
|
|
1
|
-
import { type DustParameters, type DustPublicKey, DustSecretKey, type Signature, type SignatureVerifyingKey, type UnprovenTransaction } from '@midnight-ntwrk/ledger-v8';
|
|
2
|
-
import { type ProtocolState, ProtocolVersion, SyncProgress } from '@midnight-ntwrk/wallet-sdk-abstractions';
|
|
3
|
-
import { DustAddress } from '@midnight-ntwrk/wallet-sdk-address-format';
|
|
4
|
-
import { type Variant, type WalletLike } from '@midnight-ntwrk/wallet-sdk-runtime/abstractions';
|
|
1
|
+
import { type DustParameters, type DustPublicKey, DustSecretKey, type FinalizedTransaction, type Signature, type SignatureVerifyingKey, type UnprovenTransaction } from '@midnight-ntwrk/ledger-v8';
|
|
2
|
+
import { type ProtocolState, ProtocolVersion, type SyncProgress } from '@midnight-ntwrk/wallet-sdk-abstractions';
|
|
3
|
+
import { type DustAddress } from '@midnight-ntwrk/wallet-sdk-address-format';
|
|
4
|
+
import { type Variant, type VariantBuilder, type WalletLike } from '@midnight-ntwrk/wallet-sdk-runtime/abstractions';
|
|
5
5
|
import * as rx from 'rxjs';
|
|
6
6
|
import { type Balance, type CoinsAndBalancesCapability, type UtxoWithFullDustDetails } from './v1/CoinsAndBalances.js';
|
|
7
7
|
import { CoreWallet } from './v1/CoreWallet.js';
|
|
8
8
|
import { type KeysCapability } from './v1/Keys.js';
|
|
9
9
|
import { type SerializationCapability } from './v1/Serialization.js';
|
|
10
|
-
import { type
|
|
10
|
+
import { type NightUtxoSplitForDustRegistration } from './v1/Transacting.js';
|
|
11
|
+
import { type DustFullInfo, type UtxoWithMeta } from './v1/types/Dust.js';
|
|
11
12
|
import { type AnyTransaction } from './v1/types/ledger.js';
|
|
12
|
-
import { type DefaultV1Configuration, type
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
import { type BaseV1Configuration, type DefaultV1Configuration, type V1Variant } from './v1/V1Builder.js';
|
|
14
|
+
import { type WalletSyncUpdate } from './v1/Sync.js';
|
|
15
|
+
import { type TransactionHistoryService } from './v1/TransactionHistory.js';
|
|
16
|
+
export type DustWalletCapabilities<TSerialized = string> = {
|
|
17
|
+
serialization: SerializationCapability<CoreWallet, null, TSerialized>;
|
|
15
18
|
coinsAndBalances: CoinsAndBalancesCapability<CoreWallet>;
|
|
16
19
|
keys: KeysCapability<CoreWallet>;
|
|
17
20
|
};
|
|
18
|
-
export
|
|
19
|
-
|
|
21
|
+
export type DustWalletServices = {
|
|
22
|
+
transactionHistory: TransactionHistoryService;
|
|
23
|
+
};
|
|
24
|
+
export declare class DustWalletState<TSerialized = string> {
|
|
25
|
+
static readonly mapState: <TSerialized_1 = string>(variant: DustWalletCapabilities<TSerialized_1> & DustWalletServices) => (state: ProtocolState.ProtocolState<CoreWallet>) => DustWalletState<TSerialized_1>;
|
|
20
26
|
readonly protocolVersion: ProtocolVersion.ProtocolVersion;
|
|
21
27
|
readonly state: CoreWallet;
|
|
22
|
-
readonly capabilities: DustWalletCapabilities
|
|
23
|
-
|
|
24
|
-
get
|
|
25
|
-
get
|
|
28
|
+
readonly capabilities: DustWalletCapabilities<TSerialized>;
|
|
29
|
+
readonly services: DustWalletServices;
|
|
30
|
+
get totalCoins(): readonly DustFullInfo[];
|
|
31
|
+
get availableCoins(): readonly DustFullInfo[];
|
|
32
|
+
get pendingCoins(): readonly DustFullInfo[];
|
|
26
33
|
get publicKey(): DustPublicKey;
|
|
27
34
|
get address(): DustAddress;
|
|
28
35
|
get progress(): SyncProgress.SyncProgress;
|
|
29
|
-
|
|
30
|
-
* Transaction history for the wallet.
|
|
31
|
-
* @throws Error - Not yet implemented
|
|
32
|
-
*/
|
|
33
|
-
get transactionHistory(): never;
|
|
34
|
-
constructor(state: ProtocolState.ProtocolState<CoreWallet>, capabilities: DustWalletCapabilities);
|
|
36
|
+
constructor(state: ProtocolState.ProtocolState<CoreWallet>, capabilities: DustWalletCapabilities<TSerialized>, services: DustWalletServices);
|
|
35
37
|
balance(time: Date): Balance;
|
|
36
|
-
availableCoinsWithFullInfo(time: Date): readonly DustFullInfo[];
|
|
37
38
|
estimateDustGeneration(nightUtxos: ReadonlyArray<UtxoWithMeta>, currentTime: Date): ReadonlyArray<UtxoWithFullDustDetails>;
|
|
38
|
-
serialize():
|
|
39
|
+
serialize(): TSerialized;
|
|
39
40
|
}
|
|
40
|
-
export type DustWalletAPI = {
|
|
41
|
-
readonly state: rx.Observable<DustWalletState
|
|
42
|
-
start(secretKey:
|
|
41
|
+
export type DustWalletAPI<TStartAux = DustSecretKey, TSerialized = string> = {
|
|
42
|
+
readonly state: rx.Observable<DustWalletState<TSerialized>>;
|
|
43
|
+
start(secretKey: TStartAux): Promise<void>;
|
|
43
44
|
createDustGenerationTransaction(currentTime: Date | undefined, ttl: Date, nightUtxos: Array<UtxoWithMeta>, nightVerifyingKey: SignatureVerifyingKey, dustReceiverAddress: DustAddress | undefined): Promise<UnprovenTransaction>;
|
|
45
|
+
splitNightUtxosForDustRegistration(currentTime: Date, nightUtxos: ReadonlyArray<UtxoWithMeta>, isRegistration: boolean): Promise<NightUtxoSplitForDustRegistration>;
|
|
46
|
+
attachDustRegistration(transaction: UnprovenTransaction, currentTime: Date, nightVerifyingKey: SignatureVerifyingKey, dustReceiverAddress: DustAddress | undefined, feePayment: bigint): Promise<UnprovenTransaction>;
|
|
44
47
|
addDustGenerationSignature(transaction: UnprovenTransaction, signature: Signature): Promise<UnprovenTransaction>;
|
|
48
|
+
/**
|
|
49
|
+
* Attaches a signature to the DustRegistration in segment 1's `dustActions` only. Unlike
|
|
50
|
+
* {@link addDustGenerationSignature}, this does NOT touch the unshielded offers — those should be signed separately
|
|
51
|
+
* via the unshielded-wallet signing path. Use this when the caller orchestrates signing across both packages (e.g.
|
|
52
|
+
* the facade's `signRecipe`).
|
|
53
|
+
*/
|
|
54
|
+
addDustRegistrationSignature(transaction: UnprovenTransaction, signature: Signature): Promise<UnprovenTransaction>;
|
|
45
55
|
calculateFee(transactions: ReadonlyArray<AnyTransaction>): Promise<bigint>;
|
|
46
56
|
estimateFee(secretKey: DustSecretKey, transactions: ReadonlyArray<AnyTransaction>, ttl?: Date, currentTime?: Date): Promise<bigint>;
|
|
47
57
|
balanceTransactions(secretKey: DustSecretKey, transactions: ReadonlyArray<AnyTransaction>, ttl: Date, currentTime?: Date): Promise<UnprovenTransaction>;
|
|
48
|
-
serializeState(): Promise<
|
|
49
|
-
waitForSyncedState(allowedGap?: bigint): Promise<DustWalletState
|
|
58
|
+
serializeState(): Promise<TSerialized>;
|
|
59
|
+
waitForSyncedState(allowedGap?: bigint): Promise<DustWalletState<TSerialized>>;
|
|
50
60
|
revertTransaction(transaction: AnyTransaction): Promise<void>;
|
|
51
61
|
getAddress(): Promise<DustAddress>;
|
|
52
62
|
stop(): Promise<void>;
|
|
53
63
|
};
|
|
54
|
-
export type
|
|
55
|
-
export interface DustWalletClass extends WalletLike.BaseWalletClass<[Variant.VersionedVariant<DefaultV1Variant>]> {
|
|
56
|
-
startWithSeed(seed: Uint8Array, dustParameters: DustParameters): DustWallet;
|
|
57
|
-
startWithSecretKey(secretKey: DustSecretKey, dustParameters: DustParameters): DustWallet;
|
|
58
|
-
restore(serializedState: string): DustWallet;
|
|
59
|
-
}
|
|
64
|
+
export type CustomizedDustWallet<TStartAux = DustSecretKey, TTransaction = FinalizedTransaction, TSyncUpdate = WalletSyncUpdate, TSerialized = string> = DustWalletAPI<TStartAux, TSerialized> & WalletLike.WalletLike<[Variant.VersionedVariant<V1Variant<TSerialized, TSyncUpdate, TTransaction, TStartAux>>]>;
|
|
60
65
|
export type DefaultDustConfiguration = DefaultV1Configuration;
|
|
66
|
+
export interface CustomizedDustWalletClass<TStartAux = DustSecretKey, TTransaction = FinalizedTransaction, TSyncUpdate = WalletSyncUpdate, TSerialized = string, TConfig extends BaseV1Configuration = DefaultDustConfiguration> extends WalletLike.BaseWalletClass<[
|
|
67
|
+
Variant.VersionedVariant<V1Variant<TSerialized, TSyncUpdate, TTransaction, TStartAux>>
|
|
68
|
+
]> {
|
|
69
|
+
configuration: TConfig;
|
|
70
|
+
startWithSeed(seed: Uint8Array, dustParameters: DustParameters): CustomizedDustWallet<TStartAux, TTransaction, TSyncUpdate, TSerialized>;
|
|
71
|
+
startWithSecretKey(secretKey: DustSecretKey, dustParameters: DustParameters): CustomizedDustWallet<TStartAux, TTransaction, TSyncUpdate, TSerialized>;
|
|
72
|
+
restore(serializedState: TSerialized): CustomizedDustWallet<TStartAux, TTransaction, TSyncUpdate, TSerialized>;
|
|
73
|
+
}
|
|
74
|
+
export type DustWallet = CustomizedDustWallet<DustSecretKey, FinalizedTransaction, WalletSyncUpdate, string>;
|
|
75
|
+
export type DustWalletClass = CustomizedDustWalletClass<DustSecretKey, FinalizedTransaction, WalletSyncUpdate, string>;
|
|
61
76
|
export declare function DustWallet(configuration: DefaultDustConfiguration): DustWalletClass;
|
|
77
|
+
export declare function CustomDustWallet<TConfig extends BaseV1Configuration = DefaultDustConfiguration, TStartAux = DustSecretKey, TTransaction = FinalizedTransaction, TSyncUpdate = WalletSyncUpdate, TSerialized = string>(configuration: TConfig, builder: VariantBuilder.VariantBuilder<V1Variant<TSerialized, TSyncUpdate, TTransaction, TStartAux>, TConfig>): CustomizedDustWalletClass<TStartAux, TTransaction, TSyncUpdate, TSerialized, TConfig>;
|
package/dist/DustWallet.js
CHANGED
|
@@ -19,12 +19,15 @@ import { CoreWallet } from './v1/CoreWallet.js';
|
|
|
19
19
|
import { V1Tag } from './v1/RunningV1Variant.js';
|
|
20
20
|
import { V1Builder } from './v1/V1Builder.js';
|
|
21
21
|
export class DustWalletState {
|
|
22
|
-
static mapState = (
|
|
23
|
-
|
|
22
|
+
static mapState = (variant) => (state) => {
|
|
23
|
+
const { serialization, coinsAndBalances, keys } = variant;
|
|
24
|
+
const { transactionHistory } = variant;
|
|
25
|
+
return new DustWalletState(state, { serialization, coinsAndBalances, keys }, { transactionHistory });
|
|
24
26
|
};
|
|
25
27
|
protocolVersion;
|
|
26
28
|
state;
|
|
27
29
|
capabilities;
|
|
30
|
+
services;
|
|
28
31
|
get totalCoins() {
|
|
29
32
|
return this.capabilities.coinsAndBalances.getTotalCoins(this.state);
|
|
30
33
|
}
|
|
@@ -43,24 +46,15 @@ export class DustWalletState {
|
|
|
43
46
|
get progress() {
|
|
44
47
|
return this.state.progress;
|
|
45
48
|
}
|
|
46
|
-
|
|
47
|
-
* Transaction history for the wallet.
|
|
48
|
-
* @throws Error - Not yet implemented
|
|
49
|
-
*/
|
|
50
|
-
get transactionHistory() {
|
|
51
|
-
throw new Error('Transaction history is not yet implemented for DustWallet');
|
|
52
|
-
}
|
|
53
|
-
constructor(state, capabilities) {
|
|
49
|
+
constructor(state, capabilities, services) {
|
|
54
50
|
this.protocolVersion = state.version;
|
|
55
51
|
this.state = state.state;
|
|
56
52
|
this.capabilities = capabilities;
|
|
53
|
+
this.services = services;
|
|
57
54
|
}
|
|
58
55
|
balance(time) {
|
|
59
56
|
return this.capabilities.coinsAndBalances.getWalletBalance(this.state, time);
|
|
60
57
|
}
|
|
61
|
-
availableCoinsWithFullInfo(time) {
|
|
62
|
-
return this.capabilities.coinsAndBalances.getAvailableCoinsWithFullInfo(this.state, time);
|
|
63
|
-
}
|
|
64
58
|
estimateDustGeneration(nightUtxos, currentTime) {
|
|
65
59
|
return this.capabilities.coinsAndBalances.estimateDustGeneration(this.state, nightUtxos, currentTime);
|
|
66
60
|
}
|
|
@@ -69,26 +63,30 @@ export class DustWalletState {
|
|
|
69
63
|
}
|
|
70
64
|
}
|
|
71
65
|
export function DustWallet(configuration) {
|
|
66
|
+
return CustomDustWallet(configuration, new V1Builder().withDefaults());
|
|
67
|
+
}
|
|
68
|
+
export function CustomDustWallet(configuration, builder) {
|
|
69
|
+
const buildArgs = [configuration];
|
|
72
70
|
const BaseWallet = WalletBuilder.init()
|
|
73
|
-
.withVariant(ProtocolVersion.MinSupportedVersion,
|
|
74
|
-
.build(
|
|
75
|
-
return class
|
|
71
|
+
.withVariant(ProtocolVersion.MinSupportedVersion, builder)
|
|
72
|
+
.build(...buildArgs);
|
|
73
|
+
return class CustomDustWalletImplementation extends BaseWallet {
|
|
76
74
|
static startWithSeed(seed, dustParameters) {
|
|
77
75
|
const dustSecretKey = DustSecretKey.fromSeed(seed);
|
|
78
|
-
return
|
|
76
|
+
return CustomDustWalletImplementation.startFirst(CustomDustWalletImplementation, CoreWallet.initEmpty(dustParameters, dustSecretKey, CustomDustWalletImplementation.configuration.networkId));
|
|
79
77
|
}
|
|
80
78
|
static startWithSecretKey(secretKey, dustParameters) {
|
|
81
|
-
return
|
|
79
|
+
return CustomDustWalletImplementation.startFirst(CustomDustWalletImplementation, CoreWallet.initEmpty(dustParameters, secretKey, CustomDustWalletImplementation.configuration.networkId));
|
|
82
80
|
}
|
|
83
81
|
static restore(serializedState) {
|
|
84
|
-
const deserialized =
|
|
82
|
+
const deserialized = CustomDustWalletImplementation.allVariantsRecord()[V1Tag].variant.deserializeState(serializedState)
|
|
85
83
|
.pipe(Either.getOrThrow);
|
|
86
|
-
return
|
|
84
|
+
return CustomDustWalletImplementation.startFirst(CustomDustWalletImplementation, deserialized);
|
|
87
85
|
}
|
|
88
86
|
state;
|
|
89
87
|
constructor(runtime, scope) {
|
|
90
88
|
super(runtime, scope);
|
|
91
|
-
this.state = this.rawState.pipe(rx.map(DustWalletState.mapState(
|
|
89
|
+
this.state = this.rawState.pipe(rx.map(DustWalletState.mapState(CustomDustWalletImplementation.allVariantsRecord()[V1Tag].variant)), rx.shareReplay({ refCount: true, bufferSize: 1 }));
|
|
92
90
|
}
|
|
93
91
|
start(secretKey) {
|
|
94
92
|
return this.runtime.dispatch({ [V1Tag]: (v1) => v1.startSyncInBackground(secretKey) }).pipe(Effect.runPromise);
|
|
@@ -100,6 +98,20 @@ export function DustWallet(configuration) {
|
|
|
100
98
|
})
|
|
101
99
|
.pipe(Effect.runPromise);
|
|
102
100
|
}
|
|
101
|
+
async splitNightUtxosForDustRegistration(currentTime, nightUtxos, isRegistration) {
|
|
102
|
+
return this.runtime
|
|
103
|
+
.dispatch({
|
|
104
|
+
[V1Tag]: (v1) => v1.splitNightUtxosForDustRegistration(currentTime, nightUtxos, isRegistration),
|
|
105
|
+
})
|
|
106
|
+
.pipe(Effect.runPromise);
|
|
107
|
+
}
|
|
108
|
+
async attachDustRegistration(transaction, currentTime, nightVerifyingKey, dustReceiverAddress, feePayment) {
|
|
109
|
+
return this.runtime
|
|
110
|
+
.dispatch({
|
|
111
|
+
[V1Tag]: (v1) => v1.attachDustRegistration(transaction, currentTime, nightVerifyingKey, dustReceiverAddress, feePayment),
|
|
112
|
+
})
|
|
113
|
+
.pipe(Effect.runPromise);
|
|
114
|
+
}
|
|
103
115
|
addDustGenerationSignature(transaction, signature) {
|
|
104
116
|
return this.runtime
|
|
105
117
|
.dispatch({
|
|
@@ -107,6 +119,13 @@ export function DustWallet(configuration) {
|
|
|
107
119
|
})
|
|
108
120
|
.pipe(Effect.runPromise);
|
|
109
121
|
}
|
|
122
|
+
addDustRegistrationSignature(transaction, signature) {
|
|
123
|
+
return this.runtime
|
|
124
|
+
.dispatch({
|
|
125
|
+
[V1Tag]: (v1) => v1.addDustRegistrationSignature(transaction, signature),
|
|
126
|
+
})
|
|
127
|
+
.pipe(Effect.runPromise);
|
|
128
|
+
}
|
|
110
129
|
calculateFee(transactions) {
|
|
111
130
|
return this.runtime
|
|
112
131
|
.dispatch({
|
|
@@ -139,10 +158,6 @@ export function DustWallet(configuration) {
|
|
|
139
158
|
waitForSyncedState(allowedGap = 0n) {
|
|
140
159
|
return rx.firstValueFrom(this.state.pipe(rx.filter((state) => state.state.progress.isCompleteWithin(allowedGap))));
|
|
141
160
|
}
|
|
142
|
-
/**
|
|
143
|
-
* Serializes the most recent state
|
|
144
|
-
* It's preferable to use [[DustWalletState.serialize]] instead, to know exactly, which state is serialized
|
|
145
|
-
*/
|
|
146
161
|
serializeState() {
|
|
147
162
|
return rx.firstValueFrom(this.state).then((state) => state.serialize());
|
|
148
163
|
}
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -1,39 +1,39 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import { type CoinRecipe } from '@midnight-ntwrk/wallet-sdk-capabilities';
|
|
2
|
+
import { type CoreWallet } from './CoreWallet.js';
|
|
3
|
+
import { type KeysCapability } from './Keys.js';
|
|
4
|
+
import { type DustGenerationDetails, type DustGenerationInfo, type Dust, type DustFullInfo, type UtxoWithMeta } from './types/Dust.js';
|
|
4
5
|
export type Balance = bigint;
|
|
5
6
|
export type CoinWithValue<TToken> = {
|
|
6
7
|
token: TToken;
|
|
7
8
|
value: Balance;
|
|
8
9
|
};
|
|
9
10
|
/**
|
|
10
|
-
* Type describing a Night UTxO together with details of estimated Dust generation.
|
|
11
|
-
*
|
|
11
|
+
* Type describing a Night UTxO together with details of estimated Dust generation. It is meant to be primarily used for
|
|
12
|
+
* fee estimation of Dust registration transaction
|
|
12
13
|
*/
|
|
13
14
|
export type UtxoWithFullDustDetails = Readonly<{
|
|
14
15
|
utxo: UtxoWithMeta;
|
|
15
16
|
dust: DustGenerationDetails;
|
|
16
17
|
}>;
|
|
17
|
-
export type CoinSelection
|
|
18
|
-
export declare const chooseCoin:
|
|
18
|
+
export type CoinSelection = <TCoin extends CoinRecipe>(coins: readonly TCoin[]) => TCoin | undefined;
|
|
19
|
+
export declare const chooseCoin: CoinSelection;
|
|
19
20
|
export type CoinsAndBalancesCapability<TState> = {
|
|
20
21
|
getWalletBalance(state: TState, time: Date): Balance;
|
|
21
|
-
getAvailableCoins(state: TState): readonly
|
|
22
|
-
getPendingCoins(state: TState): readonly
|
|
23
|
-
getTotalCoins(state: TState): ReadonlyArray<
|
|
22
|
+
getAvailableCoins(state: TState, time?: Date): readonly DustFullInfo[];
|
|
23
|
+
getPendingCoins(state: TState, time?: Date): readonly DustFullInfo[];
|
|
24
|
+
getTotalCoins(state: TState, time?: Date): ReadonlyArray<DustFullInfo>;
|
|
24
25
|
getAvailableCoinsWithGeneratedDust(state: TState, currentTime: Date): ReadonlyArray<CoinWithValue<Dust>>;
|
|
25
|
-
getAvailableCoinsWithFullInfo(state: TState, blockTime: Date): readonly DustFullInfo[];
|
|
26
26
|
getGenerationInfo(state: TState, coin: Dust): DustGenerationInfo | undefined;
|
|
27
|
-
/**
|
|
28
|
-
* Splits provided Night utxos into the ones that will be used as inputs in the guaranteed and fallible sections
|
|
29
|
-
*/
|
|
27
|
+
/** Splits provided Night utxos into the ones that will be used as inputs in the guaranteed and fallible sections */
|
|
30
28
|
splitNightUtxos(nightUtxos: ReadonlyArray<UtxoWithFullDustDetails>): {
|
|
31
29
|
guaranteed: ReadonlyArray<UtxoWithFullDustDetails>;
|
|
32
30
|
fallible: ReadonlyArray<UtxoWithFullDustDetails>;
|
|
33
31
|
};
|
|
34
32
|
/**
|
|
35
|
-
* Estimate how much Dust would be available to use if the Utxos provided were used for Dust generation from their
|
|
36
|
-
* This function is particularly useful for the purpose of registering for Dust generation and selecting
|
|
33
|
+
* Estimate how much Dust would be available to use if the Utxos provided were used for Dust generation from their
|
|
34
|
+
* beginning. This function is particularly useful for the purpose of registering for Dust generation and selecting
|
|
35
|
+
* the Utxo to be used for paying fees and approving the registration itself.
|
|
36
|
+
*
|
|
37
37
|
* @param state Current state of the wallet
|
|
38
38
|
* @param nightUtxos Existing Night utxos
|
|
39
39
|
* @param currentTime Current time
|
|
@@ -13,18 +13,15 @@
|
|
|
13
13
|
import * as ledger from '@midnight-ntwrk/ledger-v8';
|
|
14
14
|
import { DateOps } from '@midnight-ntwrk/wallet-sdk-utilities';
|
|
15
15
|
import { pipe, Array as Arr, Order } from 'effect';
|
|
16
|
-
export const chooseCoin = (coins) => coins
|
|
16
|
+
export const chooseCoin = (coins) => coins
|
|
17
|
+
.filter((coin) => coin.value > 0n)
|
|
18
|
+
.toSorted((a, b) => Number(a.value - b.value))
|
|
19
|
+
.at(0);
|
|
17
20
|
const FAKE_NONCE = '0'.repeat(64);
|
|
18
21
|
export const makeDefaultCoinsAndBalancesCapability = (_config, getContext) => {
|
|
19
22
|
const getWalletBalance = (state, time) => {
|
|
20
23
|
return state.state.walletBalance(time);
|
|
21
24
|
};
|
|
22
|
-
const getAvailableCoins = (state) => {
|
|
23
|
-
const pendingSpends = new Set([...state.pendingDust.values()].map((coin) => coin.nonce));
|
|
24
|
-
return pipe(state.state.utxos, Arr.filter((coin) => !pendingSpends.has(coin.nonce)));
|
|
25
|
-
};
|
|
26
|
-
const getPendingCoins = (state) => state.pendingDust;
|
|
27
|
-
const getTotalCoins = (state) => [...getAvailableCoins(state), ...getPendingCoins(state)];
|
|
28
25
|
const getGenerationInfo = (state, coin) => {
|
|
29
26
|
const info = state.state.generationInfo(coin);
|
|
30
27
|
return info && info.dtime
|
|
@@ -34,32 +31,22 @@ export const makeDefaultCoinsAndBalancesCapability = (_config, getContext) => {
|
|
|
34
31
|
}
|
|
35
32
|
: info;
|
|
36
33
|
};
|
|
37
|
-
const
|
|
38
|
-
|
|
39
|
-
const
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
return result;
|
|
34
|
+
const resolveTime = (state, time) => time ?? state.state.syncTime;
|
|
35
|
+
const toFullInfo = (state, coins, time) => coins.flatMap((coin) => {
|
|
36
|
+
const genInfo = getGenerationInfo(state, coin);
|
|
37
|
+
return genInfo ? [{ token: coin, ...getFullDustInfo(state.state.params, genInfo, coin, time) }] : [];
|
|
38
|
+
});
|
|
39
|
+
const availableDustTokens = (state) => {
|
|
40
|
+
const pendingSpends = new Set([...state.pendingDust.values()].map((coin) => coin.nonce));
|
|
41
|
+
return pipe(state.state.utxos, Arr.filter((coin) => !pendingSpends.has(coin.nonce)));
|
|
48
42
|
};
|
|
49
|
-
const
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
if (genInfo) {
|
|
55
|
-
result.push({
|
|
56
|
-
token: coin,
|
|
57
|
-
...getFullDustInfo(state.state.params, genInfo, coin, blockTime),
|
|
58
|
-
});
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
return result;
|
|
43
|
+
const getAvailableCoins = (state, time) => toFullInfo(state, availableDustTokens(state), resolveTime(state, time));
|
|
44
|
+
const getPendingCoins = (state, time) => toFullInfo(state, state.pendingDust, resolveTime(state, time));
|
|
45
|
+
const getTotalCoins = (state, time) => {
|
|
46
|
+
const effectiveTime = resolveTime(state, time);
|
|
47
|
+
return [...getAvailableCoins(state, effectiveTime), ...getPendingCoins(state, effectiveTime)];
|
|
62
48
|
};
|
|
49
|
+
const getAvailableCoinsWithGeneratedDust = (state, currentTime) => getAvailableCoins(state, currentTime).map((info) => ({ token: info.token, value: info.generatedNow }));
|
|
63
50
|
const getFullDustInfo = (parameters, genInfo, coin, currentTime) => {
|
|
64
51
|
const generatedValue = ledger.updatedValue(coin.ctime, coin.initialValue, genInfo, currentTime, parameters);
|
|
65
52
|
return {
|
|
@@ -79,9 +66,7 @@ export const makeDefaultCoinsAndBalancesCapability = (_config, getContext) => {
|
|
|
79
66
|
return { utxo, dust: details };
|
|
80
67
|
}));
|
|
81
68
|
};
|
|
82
|
-
/**
|
|
83
|
-
* Create a fake generation info for a given Utxo. It allows to estimate the Dust generation from it
|
|
84
|
-
*/
|
|
69
|
+
/** Create a fake generation info for a given Utxo. It allows to estimate the Dust generation from it */
|
|
85
70
|
const fakeGenerationInfo = (utxo, dustPublicKey) => {
|
|
86
71
|
return {
|
|
87
72
|
value: utxo.value,
|
|
@@ -90,9 +75,7 @@ export const makeDefaultCoinsAndBalancesCapability = (_config, getContext) => {
|
|
|
90
75
|
dtime: undefined,
|
|
91
76
|
};
|
|
92
77
|
};
|
|
93
|
-
/**
|
|
94
|
-
* Create a fake dust coin for a given Utxo. It allows to estimate full details of the Dust generation from it
|
|
95
|
-
*/
|
|
78
|
+
/** Create a fake dust coin for a given Utxo. It allows to estimate full details of the Dust generation from it */
|
|
96
79
|
const fakeDustToken = (dustPublicKey, utxo) => ({
|
|
97
80
|
initialValue: 0n,
|
|
98
81
|
owner: dustPublicKey,
|
|
@@ -112,7 +95,6 @@ export const makeDefaultCoinsAndBalancesCapability = (_config, getContext) => {
|
|
|
112
95
|
getPendingCoins,
|
|
113
96
|
getTotalCoins,
|
|
114
97
|
getAvailableCoinsWithGeneratedDust,
|
|
115
|
-
getAvailableCoinsWithFullInfo,
|
|
116
98
|
getGenerationInfo,
|
|
117
99
|
estimateDustGeneration,
|
|
118
100
|
splitNightUtxos,
|
package/dist/v1/CoreWallet.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { Bindingish, DustLocalState, DustNullifier, DustParameters, DustPublicKey, DustSecretKey, Proofish, Signaturish, Transaction, Event } from '@midnight-ntwrk/ledger-v8';
|
|
1
|
+
import { type Bindingish, DustLocalState, type DustNullifier, type DustParameters, type DustPublicKey, type DustSecretKey, type DustStateChanges, type Proofish, type Signaturish, type Transaction, type Event } from '@midnight-ntwrk/ledger-v8';
|
|
2
2
|
import { ProtocolVersion, SyncProgress } from '@midnight-ntwrk/wallet-sdk-abstractions';
|
|
3
|
-
import { Dust, DustWithNullifier } from './types/Dust.js';
|
|
4
|
-
import { CoinWithValue } from './CoinsAndBalances.js';
|
|
5
|
-
import { NetworkId, UnprovenDustSpend } from './types/ledger.js';
|
|
3
|
+
import { type Dust, type DustWithNullifier } from './types/Dust.js';
|
|
4
|
+
import { type CoinWithValue } from './CoinsAndBalances.js';
|
|
5
|
+
import { type NetworkId, type UnprovenDustSpend } from './types/ledger.js';
|
|
6
6
|
export type PublicKey = {
|
|
7
7
|
publicKey: DustPublicKey;
|
|
8
8
|
};
|
|
@@ -22,7 +22,7 @@ export declare const CoreWallet: {
|
|
|
22
22
|
initEmpty(dustParameters: DustParameters, secretKey: DustSecretKey, networkId: NetworkId): CoreWallet;
|
|
23
23
|
empty(localState: DustLocalState, publicKey: PublicKey, networkId: NetworkId): CoreWallet;
|
|
24
24
|
restore(localState: DustLocalState, publicKey: PublicKey, pendingTokens: Array<DustWithNullifier>, syncProgress: Omit<SyncProgress.SyncProgressData, "isConnected">, protocolVersion: bigint, networkId: NetworkId): CoreWallet;
|
|
25
|
-
|
|
25
|
+
applyEventsWithChanges(wallet: CoreWallet, secretKey: DustSecretKey, events: Event[], currentTime: Date): [CoreWallet, DustStateChanges[]];
|
|
26
26
|
applyFailed(wallet: CoreWallet, tx: Transaction<Signaturish, Proofish, Bindingish>): CoreWallet;
|
|
27
27
|
revertTransaction<TTransaction extends Transaction<Signaturish, Proofish, Bindingish>>(wallet: CoreWallet, tx: TTransaction): CoreWallet;
|
|
28
28
|
updateProgress(wallet: CoreWallet, { appliedIndex, highestRelevantWalletIndex, highestIndex, highestRelevantIndex, isConnected, }: Partial<SyncProgress.SyncProgressData>): CoreWallet;
|
package/dist/v1/CoreWallet.js
CHANGED
|
@@ -48,15 +48,19 @@ export const CoreWallet = {
|
|
|
48
48
|
protocolVersion: ProtocolVersion.ProtocolVersion(protocolVersion),
|
|
49
49
|
};
|
|
50
50
|
},
|
|
51
|
-
|
|
51
|
+
applyEventsWithChanges(wallet, secretKey, events, currentTime) {
|
|
52
52
|
// TODO: replace currentTime with `updatedState.syncTime` introduced in ledger-6.2.0-rc.1
|
|
53
|
-
const
|
|
53
|
+
const stateWithChanges = wallet.state.replayEventsWithChanges(secretKey, events);
|
|
54
|
+
const updatedState = stateWithChanges.state.processTtls(currentTime);
|
|
54
55
|
const availableNonces = updatedState.utxos.map((utxo) => utxo.nonce);
|
|
55
|
-
return
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
56
|
+
return [
|
|
57
|
+
{
|
|
58
|
+
...wallet,
|
|
59
|
+
state: updatedState,
|
|
60
|
+
pendingDust: wallet.pendingDust.filter((t) => availableNonces.includes(t.nonce)),
|
|
61
|
+
},
|
|
62
|
+
stateWithChanges.changes,
|
|
63
|
+
];
|
|
60
64
|
},
|
|
61
65
|
applyFailed(wallet, tx) {
|
|
62
66
|
const pendingSpendsMap = CoreWallet.pendingDustToMap(wallet.pendingDust);
|
package/dist/v1/Keys.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { DustPublicKey } from '@midnight-ntwrk/ledger-v8';
|
|
1
|
+
import { type DustPublicKey } from '@midnight-ntwrk/ledger-v8';
|
|
2
2
|
import { DustAddress } from '@midnight-ntwrk/wallet-sdk-address-format';
|
|
3
|
-
import { CoreWallet } from './CoreWallet.js';
|
|
3
|
+
import { type CoreWallet } from './CoreWallet.js';
|
|
4
4
|
export type KeysCapability<TState> = {
|
|
5
5
|
getPublicKey(state: TState): DustPublicKey;
|
|
6
6
|
getAddress(state: TState): DustAddress;
|
|
@@ -1,26 +1,28 @@
|
|
|
1
1
|
import { Effect, Stream, Scope } from 'effect';
|
|
2
|
+
import { type TransactionHistoryService } from './TransactionHistory.js';
|
|
2
3
|
import { type DustSecretKey, type Signature, type SignatureVerifyingKey, type FinalizedTransaction, type UnprovenTransaction } from '@midnight-ntwrk/ledger-v8';
|
|
3
|
-
import { WalletError } from './WalletError.js';
|
|
4
|
+
import { type WalletError } from './WalletError.js';
|
|
4
5
|
import { type WalletRuntimeError, type Variant, StateChange } from '@midnight-ntwrk/wallet-sdk-runtime/abstractions';
|
|
5
|
-
import { type
|
|
6
|
+
import { type UtxoWithMeta } from './types/Dust.js';
|
|
6
7
|
import { type KeysCapability } from './Keys.js';
|
|
7
|
-
import { type SyncCapability, type SyncService } from './Sync.js';
|
|
8
|
-
import { type SimulatorState } from '
|
|
8
|
+
import { type ChangesResult, type SyncCapability, type SyncService } from './Sync.js';
|
|
9
|
+
import { type SimulatorState } from '@midnight-ntwrk/wallet-sdk-capabilities/simulation';
|
|
9
10
|
import { type CoinsAndBalancesCapability, type CoinSelection } from './CoinsAndBalances.js';
|
|
10
|
-
import { type TransactingCapability } from './Transacting.js';
|
|
11
|
+
import { type NightUtxoSplitForDustRegistration, type TransactingCapability } from './Transacting.js';
|
|
11
12
|
import { type CoreWallet } from './CoreWallet.js';
|
|
12
13
|
import { type SerializationCapability } from './Serialization.js';
|
|
13
14
|
import { type AnyTransaction } from './types/ledger.js';
|
|
14
|
-
import { DustAddress } from '@midnight-ntwrk/wallet-sdk-address-format';
|
|
15
|
+
import { type DustAddress } from '@midnight-ntwrk/wallet-sdk-address-format';
|
|
15
16
|
export declare namespace RunningV1Variant {
|
|
16
17
|
type Context<TSerialized, TSyncUpdate, TTransaction, TStartAux> = {
|
|
17
18
|
serializationCapability: SerializationCapability<CoreWallet, null, TSerialized>;
|
|
18
19
|
syncService: SyncService<CoreWallet, TStartAux, TSyncUpdate>;
|
|
19
|
-
syncCapability: SyncCapability<CoreWallet, TSyncUpdate>;
|
|
20
|
+
syncCapability: SyncCapability<CoreWallet, TSyncUpdate, ChangesResult>;
|
|
20
21
|
transactingCapability: TransactingCapability<DustSecretKey, CoreWallet, TTransaction>;
|
|
21
22
|
coinsAndBalancesCapability: CoinsAndBalancesCapability<CoreWallet>;
|
|
22
23
|
keysCapability: KeysCapability<CoreWallet>;
|
|
23
|
-
coinSelection: CoinSelection
|
|
24
|
+
coinSelection: CoinSelection;
|
|
25
|
+
transactionHistoryService: TransactionHistoryService;
|
|
24
26
|
};
|
|
25
27
|
type AnyContext = Context<any, any, any, any>;
|
|
26
28
|
}
|
|
@@ -34,7 +36,10 @@ export declare class RunningV1Variant<TSerialized, TSyncUpdate, TTransaction, TS
|
|
|
34
36
|
startSyncInBackground(startAux: TStartAux): Effect.Effect<void>;
|
|
35
37
|
startSync(startAux: TStartAux): Stream.Stream<void, WalletError, Scope.Scope>;
|
|
36
38
|
createDustGenerationTransaction(currentTime: Date | undefined, ttl: Date, nightUtxos: ReadonlyArray<UtxoWithMeta>, nightVerifyingKey: SignatureVerifyingKey, dustReceiverAddress: DustAddress | undefined): Effect.Effect<UnprovenTransaction, WalletError>;
|
|
39
|
+
splitNightUtxosForDustRegistration(currentTime: Date, nightUtxos: ReadonlyArray<UtxoWithMeta>, isRegistration: boolean): Effect.Effect<NightUtxoSplitForDustRegistration, WalletError>;
|
|
40
|
+
attachDustRegistration(transaction: UnprovenTransaction, currentTime: Date, nightVerifyingKey: SignatureVerifyingKey, dustReceiverAddress: DustAddress | undefined, feePayment: bigint): Effect.Effect<UnprovenTransaction, WalletError>;
|
|
37
41
|
addDustGenerationSignature(transaction: UnprovenTransaction, signature: Signature): Effect.Effect<UnprovenTransaction, WalletError>;
|
|
42
|
+
addDustRegistrationSignature(transaction: UnprovenTransaction, signature: Signature): Effect.Effect<UnprovenTransaction, WalletError>;
|
|
38
43
|
calculateFee(transactions: ReadonlyArray<AnyTransaction>): Effect.Effect<bigint, WalletError>;
|
|
39
44
|
estimateFee(secretKey: DustSecretKey, transactions: ReadonlyArray<AnyTransaction>, ttl: Date, currentTime?: Date): Effect.Effect<bigint, WalletError>;
|
|
40
45
|
balanceTransactions(secretKey: DustSecretKey, transactions: ReadonlyArray<AnyTransaction>, ttl: Date, currentTime?: Date): Effect.Effect<UnprovenTransaction, WalletError>;
|
|
@@ -62,15 +62,16 @@ export class RunningV1Variant {
|
|
|
62
62
|
return this.startSync(startAux).pipe(Stream.runScoped(Sink.drain), Effect.forkScoped, Effect.provideService(Scope.Scope, this.#scope));
|
|
63
63
|
}
|
|
64
64
|
startSync(startAux) {
|
|
65
|
-
return pipe(SubscriptionRef.get(this.#context.stateRef), Stream.fromEffect, Stream.flatMap((state) => this.#v1Context.syncService.updates(state, startAux)), Stream.mapEffect((update) => {
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
65
|
+
return pipe(SubscriptionRef.get(this.#context.stateRef), Stream.fromEffect, Stream.flatMap((state) => this.#v1Context.syncService.updates(state, startAux)), Stream.mapEffect((update) => SubscriptionRef.modifyEffect(this.#context.stateRef, (state) => Effect.try({
|
|
66
|
+
try: () => {
|
|
67
|
+
const [newState, changesResult] = this.#v1Context.syncCapability.applyUpdate(state, update);
|
|
68
|
+
return [changesResult, newState];
|
|
69
|
+
},
|
|
70
|
+
catch: (err) => new OtherWalletError({
|
|
71
|
+
message: 'Error while applying sync update',
|
|
72
|
+
cause: err,
|
|
73
|
+
}),
|
|
74
|
+
})).pipe(Effect.flatMap(({ changes, protocolVersion }) => pipe(Effect.forEach(changes, (change) => pipe(this.#v1Context.transactionHistoryService.getTransactionDetails(change.source), Effect.flatMap((metadata) => this.#v1Context.transactionHistoryService.put(change, metadata, protocolVersion)), Effect.catchAllCause((cause) => Console.error('Error processing tx history metadata', cause))), { discard: true, concurrency: 'unbounded' }), Effect.forkScoped)), Effect.provideService(Scope.Scope, this.#scope))), Stream.tapError((error) => Console.error(error)), Stream.retry(pipe(Schedule.exponential(Duration.seconds(1), 2), Schedule.map((delay) => {
|
|
74
75
|
const maxDelay = Duration.minutes(2);
|
|
75
76
|
const jitter = Duration.millis(Math.floor(Math.random() * 1000));
|
|
76
77
|
const delayWithJitter = Duration.toMillis(delay) + Duration.toMillis(jitter);
|
|
@@ -81,19 +82,41 @@ export class RunningV1Variant {
|
|
|
81
82
|
if (nightUtxos.some((utxo) => utxo.type !== nativeToken().raw)) {
|
|
82
83
|
return Effect.fail(new OtherWalletError({ message: 'Token of a non-Night type received' }));
|
|
83
84
|
}
|
|
84
|
-
return Effect.
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
85
|
+
return Effect.gen(this, function* () {
|
|
86
|
+
const currentState = yield* SubscriptionRef.get(this.#context.stateRef);
|
|
87
|
+
const blockData = yield* this.#v1Context.syncService.blockData();
|
|
88
|
+
const resolvedTime = currentTime ?? blockData.timestamp;
|
|
89
|
+
const utxosWithDustValue = this.#v1Context.coinsAndBalancesCapability.estimateDustGeneration(currentState, nightUtxos, resolvedTime);
|
|
90
|
+
return yield* this.#v1Context.transactingCapability
|
|
91
|
+
.createDustGenerationTransaction(resolvedTime, ttl, utxosWithDustValue, nightVerifyingKey, dustReceiverAddress)
|
|
89
92
|
.pipe(EitherOps.toEffect);
|
|
90
|
-
})
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
splitNightUtxosForDustRegistration(currentTime, nightUtxos, isRegistration) {
|
|
96
|
+
if (nightUtxos.some((utxo) => utxo.type !== nativeToken().raw)) {
|
|
97
|
+
return Effect.fail(new OtherWalletError({ message: 'Token of a non-Night type received' }));
|
|
98
|
+
}
|
|
99
|
+
return Effect.gen(this, function* () {
|
|
100
|
+
const currentState = yield* SubscriptionRef.get(this.#context.stateRef);
|
|
101
|
+
const utxosWithDustValue = this.#v1Context.coinsAndBalancesCapability.estimateDustGeneration(currentState, nightUtxos, currentTime);
|
|
102
|
+
return this.#v1Context.transactingCapability.splitNightUtxosForDustRegistration(utxosWithDustValue, isRegistration);
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
attachDustRegistration(transaction, currentTime, nightVerifyingKey, dustReceiverAddress, feePayment) {
|
|
106
|
+
return this.#v1Context.transactingCapability
|
|
107
|
+
.attachDustRegistration(transaction, currentTime, nightVerifyingKey, dustReceiverAddress, feePayment)
|
|
108
|
+
.pipe(EitherOps.toEffect);
|
|
91
109
|
}
|
|
92
110
|
addDustGenerationSignature(transaction, signature) {
|
|
93
111
|
return this.#v1Context.transactingCapability
|
|
94
112
|
.addDustGenerationSignature(transaction, signature)
|
|
95
113
|
.pipe(EitherOps.toEffect);
|
|
96
114
|
}
|
|
115
|
+
addDustRegistrationSignature(transaction, signature) {
|
|
116
|
+
return this.#v1Context.transactingCapability
|
|
117
|
+
.addDustRegistrationSignature(transaction, signature)
|
|
118
|
+
.pipe(EitherOps.toEffect);
|
|
119
|
+
}
|
|
97
120
|
calculateFee(transactions) {
|
|
98
121
|
return pipe(this.#v1Context.syncService.blockData(), Effect.map((blockData) => pipe(transactions, Arr.map((transaction) => this.#v1Context.transactingCapability.calculateFee(transaction, blockData.ledgerParameters)), ArrayOps.sumBigInt)));
|
|
99
122
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Either, Schema } from 'effect';
|
|
2
|
-
import { WalletError } from './WalletError.js';
|
|
2
|
+
import { type WalletError } from './WalletError.js';
|
|
3
3
|
import { CoreWallet } from './CoreWallet.js';
|
|
4
4
|
export type SerializationCapability<TWallet, TAux, TSerialized> = {
|
|
5
5
|
serialize(wallet: TWallet): TSerialized;
|