@midnight-ntwrk/wallet-sdk-dust-wallet 4.0.0 → 4.2.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 -0
- package/dist/DustWallet.d.ts +34 -0
- package/dist/DustWallet.js +45 -0
- package/dist/v1/CoinsAndBalances.d.ts +3 -2
- package/dist/v1/CoinsAndBalances.js +4 -1
- package/dist/v1/RunningV1Variant.d.ts +6 -3
- package/dist/v1/RunningV1Variant.js +36 -7
- package/dist/v1/Sync.d.ts +4 -0
- package/dist/v1/Sync.js +38 -27
- package/dist/v1/Transacting.d.ts +40 -3
- package/dist/v1/Transacting.js +71 -7
- package/dist/v1/V1Builder.d.ts +2 -3
- package/dist/v1/index.d.ts +1 -0
- package/dist/v1/index.js +1 -0
- package/package.json +13 -11
package/README.md
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
> [!IMPORTANT]
|
|
2
|
+
> **This package has moved.** The `@midnight-ntwrk` scope is published only
|
|
3
|
+
> during the migration window and will stop receiving updates. Please migrate to
|
|
4
|
+
> [`@midnightntwrk/wallet-sdk-dust-wallet`](https://www.npmjs.com/package/@midnightntwrk/wallet-sdk-dust-wallet).
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
1
8
|
# @midnight-ntwrk/wallet-sdk-dust-wallet
|
|
2
9
|
|
|
3
10
|
Manages dust (transaction fees) on the Midnight network.
|
package/dist/DustWallet.d.ts
CHANGED
|
@@ -2,11 +2,13 @@ import { type DustParameters, type DustPublicKey, DustSecretKey, type FinalizedT
|
|
|
2
2
|
import { type ProtocolState, ProtocolVersion, type SyncProgress } from '@midnight-ntwrk/wallet-sdk-abstractions';
|
|
3
3
|
import { type DustAddress } from '@midnight-ntwrk/wallet-sdk-address-format';
|
|
4
4
|
import { type Variant, type VariantBuilder, type WalletLike } from '@midnight-ntwrk/wallet-sdk-runtime/abstractions';
|
|
5
|
+
import { type Clock } from '@midnight-ntwrk/wallet-sdk-utilities';
|
|
5
6
|
import * as rx from 'rxjs';
|
|
6
7
|
import { type Balance, type CoinsAndBalancesCapability, type UtxoWithFullDustDetails } from './v1/CoinsAndBalances.js';
|
|
7
8
|
import { CoreWallet } from './v1/CoreWallet.js';
|
|
8
9
|
import { type KeysCapability } from './v1/Keys.js';
|
|
9
10
|
import { type SerializationCapability } from './v1/Serialization.js';
|
|
11
|
+
import { type NightUtxoSplitForDustRegistration } from './v1/Transacting.js';
|
|
10
12
|
import { type DustFullInfo, type UtxoWithMeta } from './v1/types/Dust.js';
|
|
11
13
|
import { type AnyTransaction } from './v1/types/ledger.js';
|
|
12
14
|
import { type BaseV1Configuration, type DefaultV1Configuration, type V1Variant } from './v1/V1Builder.js';
|
|
@@ -41,12 +43,44 @@ export type DustWalletAPI<TStartAux = DustSecretKey, TSerialized = string> = {
|
|
|
41
43
|
readonly state: rx.Observable<DustWalletState<TSerialized>>;
|
|
42
44
|
start(secretKey: TStartAux): Promise<void>;
|
|
43
45
|
createDustGenerationTransaction(currentTime: Date | undefined, ttl: Date, nightUtxos: Array<UtxoWithMeta>, nightVerifyingKey: SignatureVerifyingKey, dustReceiverAddress: DustAddress | undefined): Promise<UnprovenTransaction>;
|
|
46
|
+
splitNightUtxosForDustRegistration(currentTime: Date, nightUtxos: ReadonlyArray<UtxoWithMeta>, isRegistration: boolean): Promise<NightUtxoSplitForDustRegistration>;
|
|
47
|
+
attachDustRegistration(transaction: UnprovenTransaction, currentTime: Date, nightVerifyingKey: SignatureVerifyingKey, dustReceiverAddress: DustAddress | undefined, feePayment: bigint): Promise<UnprovenTransaction>;
|
|
44
48
|
addDustGenerationSignature(transaction: UnprovenTransaction, signature: Signature): Promise<UnprovenTransaction>;
|
|
49
|
+
/**
|
|
50
|
+
* Attaches a signature to the DustRegistration in segment 1's `dustActions` only. Unlike
|
|
51
|
+
* {@link addDustGenerationSignature}, this does NOT touch the unshielded offers — those should be signed separately
|
|
52
|
+
* via the unshielded-wallet signing path. Use this when the caller orchestrates signing across both packages (e.g.
|
|
53
|
+
* the facade's `signRecipe`).
|
|
54
|
+
*/
|
|
55
|
+
addDustRegistrationSignature(transaction: UnprovenTransaction, signature: Signature): Promise<UnprovenTransaction>;
|
|
45
56
|
calculateFee(transactions: ReadonlyArray<AnyTransaction>): Promise<bigint>;
|
|
46
57
|
estimateFee(secretKey: DustSecretKey, transactions: ReadonlyArray<AnyTransaction>, ttl?: Date, currentTime?: Date): Promise<bigint>;
|
|
47
58
|
balanceTransactions(secretKey: DustSecretKey, transactions: ReadonlyArray<AnyTransaction>, ttl: Date, currentTime?: Date): Promise<UnprovenTransaction>;
|
|
48
59
|
serializeState(): Promise<TSerialized>;
|
|
49
60
|
waitForSyncedState(allowedGap?: bigint): Promise<DustWalletState<TSerialized>>;
|
|
61
|
+
/**
|
|
62
|
+
* Resolves when the dust projected to be generated by the single highest-generation unregistered Night UTxO reaches
|
|
63
|
+
* `requiredAmount`. The projection is re-evaluated every second so the wait advances even when the dust state stream
|
|
64
|
+
* is quiet. Tracks the same quantity used as `allow_fee_payment` for the registration (the maximum across the UTxOs,
|
|
65
|
+
* not their sum, since `splitNightUtxos` puts only one UTxO in the guaranteed slot), so pairing with
|
|
66
|
+
* `WalletFacade.estimateRegistration` to pick `requiredAmount` guarantees the subsequent
|
|
67
|
+
* `registerNightUtxosForDustGeneration` will pass its fee-coverage guard.
|
|
68
|
+
*
|
|
69
|
+
* @param nightUtxos - UTxOs to project generation for; same set passed to `registerNightUtxosForDustGeneration`.
|
|
70
|
+
* Already-registered UTxOs are ignored. Must be non-empty.
|
|
71
|
+
* @param requiredAmount - Threshold to wait for, as a Dust amount. Resolves immediately if `<= 0n`.
|
|
72
|
+
* @param clock - Source of current time, read on every tick. Required, and a {@link Clock.Clock} rather than a
|
|
73
|
+
* snapshot `Date` like the other methods' `currentTime`: the projection only advances because the time is re-read
|
|
74
|
+
* each tick, and callers must inject their own clock so simulator-driven tests respect simulator time.
|
|
75
|
+
* @param opts.timeoutMs - Deadline, in ms from subscription, for `requiredAmount` to be reached; rejects if it is
|
|
76
|
+
* not. Default `300_000`.
|
|
77
|
+
* @returns A promise that resolves once the projected dust reaches `requiredAmount`.
|
|
78
|
+
* @throws Error if `nightUtxos` is empty.
|
|
79
|
+
* @throws TimeoutError if `requiredAmount` is not reached within `opts.timeoutMs`.
|
|
80
|
+
*/
|
|
81
|
+
waitForGeneratedDust(nightUtxos: ReadonlyArray<UtxoWithMeta>, requiredAmount: bigint, clock: Clock.Clock, opts?: {
|
|
82
|
+
timeoutMs?: number;
|
|
83
|
+
}): Promise<void>;
|
|
50
84
|
revertTransaction(transaction: AnyTransaction): Promise<void>;
|
|
51
85
|
getAddress(): Promise<DustAddress>;
|
|
52
86
|
stop(): Promise<void>;
|
package/dist/DustWallet.js
CHANGED
|
@@ -98,6 +98,20 @@ export function CustomDustWallet(configuration, builder) {
|
|
|
98
98
|
})
|
|
99
99
|
.pipe(Effect.runPromise);
|
|
100
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
|
+
}
|
|
101
115
|
addDustGenerationSignature(transaction, signature) {
|
|
102
116
|
return this.runtime
|
|
103
117
|
.dispatch({
|
|
@@ -105,6 +119,13 @@ export function CustomDustWallet(configuration, builder) {
|
|
|
105
119
|
})
|
|
106
120
|
.pipe(Effect.runPromise);
|
|
107
121
|
}
|
|
122
|
+
addDustRegistrationSignature(transaction, signature) {
|
|
123
|
+
return this.runtime
|
|
124
|
+
.dispatch({
|
|
125
|
+
[V1Tag]: (v1) => v1.addDustRegistrationSignature(transaction, signature),
|
|
126
|
+
})
|
|
127
|
+
.pipe(Effect.runPromise);
|
|
128
|
+
}
|
|
108
129
|
calculateFee(transactions) {
|
|
109
130
|
return this.runtime
|
|
110
131
|
.dispatch({
|
|
@@ -137,6 +158,30 @@ export function CustomDustWallet(configuration, builder) {
|
|
|
137
158
|
waitForSyncedState(allowedGap = 0n) {
|
|
138
159
|
return rx.firstValueFrom(this.state.pipe(rx.filter((state) => state.state.progress.isCompleteWithin(allowedGap))));
|
|
139
160
|
}
|
|
161
|
+
async waitForGeneratedDust(nightUtxos, requiredAmount, clock, opts) {
|
|
162
|
+
if (nightUtxos.length === 0) {
|
|
163
|
+
throw Error('At least one Night UTXO is required.');
|
|
164
|
+
}
|
|
165
|
+
if (requiredAmount <= 0n) {
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
const timeoutMs = opts?.timeoutMs ?? 300_000;
|
|
169
|
+
// Combine the dust state stream with a 1 s tick — the dust state only emits when sync
|
|
170
|
+
// updates apply, but the generation projection depends on a current-time reading, which
|
|
171
|
+
// advances continuously. Without a periodic tick the filter would never re-run between
|
|
172
|
+
// state emissions on a quiet wallet, and the wait would hang.
|
|
173
|
+
await rx.firstValueFrom(rx.combineLatest([this.state, rx.timer(0, 1000)]).pipe(rx.filter(([dustState]) => {
|
|
174
|
+
// The registration's allow_fee_payment is capped at the single highest-generation
|
|
175
|
+
// unregistered Night UTxO (splitNightUtxos puts only 1 UTxO in the guaranteed slot),
|
|
176
|
+
// so the wait must track that same quantity — summing across UTxOs would resolve
|
|
177
|
+
// optimistically and the registration would still fail the fee check.
|
|
178
|
+
const maxGeneratedNow = dustState
|
|
179
|
+
.estimateDustGeneration(nightUtxos, clock.now())
|
|
180
|
+
.filter((u) => !u.utxo.registeredForDustGeneration)
|
|
181
|
+
.reduce((max, u) => (u.dust.generatedNow > max ? u.dust.generatedNow : max), 0n);
|
|
182
|
+
return maxGeneratedNow >= requiredAmount;
|
|
183
|
+
}), rx.timeout({ first: timeoutMs })));
|
|
184
|
+
}
|
|
140
185
|
serializeState() {
|
|
141
186
|
return rx.firstValueFrom(this.state).then((state) => state.serialize());
|
|
142
187
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type CoinRecipe } from '@midnight-ntwrk/wallet-sdk-capabilities';
|
|
1
2
|
import { type CoreWallet } from './CoreWallet.js';
|
|
2
3
|
import { type KeysCapability } from './Keys.js';
|
|
3
4
|
import { type DustGenerationDetails, type DustGenerationInfo, type Dust, type DustFullInfo, type UtxoWithMeta } from './types/Dust.js';
|
|
@@ -14,8 +15,8 @@ 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
22
|
getAvailableCoins(state: TState, time?: Date): readonly DustFullInfo[];
|
|
@@ -13,7 +13,10 @@
|
|
|
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) => {
|
|
@@ -3,12 +3,12 @@ import { type TransactionHistoryService } from './TransactionHistory.js';
|
|
|
3
3
|
import { type DustSecretKey, type Signature, type SignatureVerifyingKey, type FinalizedTransaction, type UnprovenTransaction } from '@midnight-ntwrk/ledger-v8';
|
|
4
4
|
import { type WalletError } from './WalletError.js';
|
|
5
5
|
import { type WalletRuntimeError, type Variant, StateChange } from '@midnight-ntwrk/wallet-sdk-runtime/abstractions';
|
|
6
|
-
import { type
|
|
6
|
+
import { type UtxoWithMeta } from './types/Dust.js';
|
|
7
7
|
import { type KeysCapability } from './Keys.js';
|
|
8
8
|
import { type ChangesResult, type SyncCapability, type SyncService } from './Sync.js';
|
|
9
9
|
import { type SimulatorState } from '@midnight-ntwrk/wallet-sdk-capabilities/simulation';
|
|
10
10
|
import { type CoinsAndBalancesCapability, type CoinSelection } from './CoinsAndBalances.js';
|
|
11
|
-
import { type TransactingCapability } from './Transacting.js';
|
|
11
|
+
import { type NightUtxoSplitForDustRegistration, type TransactingCapability } from './Transacting.js';
|
|
12
12
|
import { type CoreWallet } from './CoreWallet.js';
|
|
13
13
|
import { type SerializationCapability } from './Serialization.js';
|
|
14
14
|
import { type AnyTransaction } from './types/ledger.js';
|
|
@@ -21,7 +21,7 @@ export declare namespace RunningV1Variant {
|
|
|
21
21
|
transactingCapability: TransactingCapability<DustSecretKey, CoreWallet, TTransaction>;
|
|
22
22
|
coinsAndBalancesCapability: CoinsAndBalancesCapability<CoreWallet>;
|
|
23
23
|
keysCapability: KeysCapability<CoreWallet>;
|
|
24
|
-
coinSelection: CoinSelection
|
|
24
|
+
coinSelection: CoinSelection;
|
|
25
25
|
transactionHistoryService: TransactionHistoryService;
|
|
26
26
|
};
|
|
27
27
|
type AnyContext = Context<any, any, any, any>;
|
|
@@ -36,7 +36,10 @@ export declare class RunningV1Variant<TSerialized, TSyncUpdate, TTransaction, TS
|
|
|
36
36
|
startSyncInBackground(startAux: TStartAux): Effect.Effect<void>;
|
|
37
37
|
startSync(startAux: TStartAux): Stream.Stream<void, WalletError, Scope.Scope>;
|
|
38
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>;
|
|
39
41
|
addDustGenerationSignature(transaction: UnprovenTransaction, signature: Signature): Effect.Effect<UnprovenTransaction, WalletError>;
|
|
42
|
+
addDustRegistrationSignature(transaction: UnprovenTransaction, signature: Signature): Effect.Effect<UnprovenTransaction, WalletError>;
|
|
40
43
|
calculateFee(transactions: ReadonlyArray<AnyTransaction>): Effect.Effect<bigint, WalletError>;
|
|
41
44
|
estimateFee(secretKey: DustSecretKey, transactions: ReadonlyArray<AnyTransaction>, ttl: Date, currentTime?: Date): Effect.Effect<bigint, WalletError>;
|
|
42
45
|
balanceTransactions(secretKey: DustSecretKey, transactions: ReadonlyArray<AnyTransaction>, ttl: Date, currentTime?: Date): Effect.Effect<UnprovenTransaction, WalletError>;
|
|
@@ -71,7 +71,14 @@ export class RunningV1Variant {
|
|
|
71
71
|
message: 'Error while applying sync update',
|
|
72
72
|
cause: err,
|
|
73
73
|
}),
|
|
74
|
-
})).pipe(Effect.flatMap(({ changes, protocolVersion }) =>
|
|
74
|
+
})).pipe(Effect.flatMap(({ changes, protocolVersion }) =>
|
|
75
|
+
// Skip the tx-history fork entirely when there are no changes.
|
|
76
|
+
// Forking unconditionally allocates a fiber per apply call (one
|
|
77
|
+
// for every batch the sync emits, even the all-progress ones),
|
|
78
|
+
// which adds up fast during catch-up.
|
|
79
|
+
changes.length === 0
|
|
80
|
+
? Effect.void
|
|
81
|
+
: 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) => {
|
|
75
82
|
const maxDelay = Duration.minutes(2);
|
|
76
83
|
const jitter = Duration.millis(Math.floor(Math.random() * 1000));
|
|
77
84
|
const delayWithJitter = Duration.toMillis(delay) + Duration.toMillis(jitter);
|
|
@@ -82,19 +89,41 @@ export class RunningV1Variant {
|
|
|
82
89
|
if (nightUtxos.some((utxo) => utxo.type !== nativeToken().raw)) {
|
|
83
90
|
return Effect.fail(new OtherWalletError({ message: 'Token of a non-Night type received' }));
|
|
84
91
|
}
|
|
85
|
-
return Effect.
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
92
|
+
return Effect.gen(this, function* () {
|
|
93
|
+
const currentState = yield* SubscriptionRef.get(this.#context.stateRef);
|
|
94
|
+
const blockData = yield* this.#v1Context.syncService.blockData();
|
|
95
|
+
const resolvedTime = currentTime ?? blockData.timestamp;
|
|
96
|
+
const utxosWithDustValue = this.#v1Context.coinsAndBalancesCapability.estimateDustGeneration(currentState, nightUtxos, resolvedTime);
|
|
97
|
+
return yield* this.#v1Context.transactingCapability
|
|
98
|
+
.createDustGenerationTransaction(resolvedTime, ttl, utxosWithDustValue, nightVerifyingKey, dustReceiverAddress)
|
|
90
99
|
.pipe(EitherOps.toEffect);
|
|
91
|
-
})
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
splitNightUtxosForDustRegistration(currentTime, nightUtxos, isRegistration) {
|
|
103
|
+
if (nightUtxos.some((utxo) => utxo.type !== nativeToken().raw)) {
|
|
104
|
+
return Effect.fail(new OtherWalletError({ message: 'Token of a non-Night type received' }));
|
|
105
|
+
}
|
|
106
|
+
return Effect.gen(this, function* () {
|
|
107
|
+
const currentState = yield* SubscriptionRef.get(this.#context.stateRef);
|
|
108
|
+
const utxosWithDustValue = this.#v1Context.coinsAndBalancesCapability.estimateDustGeneration(currentState, nightUtxos, currentTime);
|
|
109
|
+
return this.#v1Context.transactingCapability.splitNightUtxosForDustRegistration(utxosWithDustValue, isRegistration);
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
attachDustRegistration(transaction, currentTime, nightVerifyingKey, dustReceiverAddress, feePayment) {
|
|
113
|
+
return this.#v1Context.transactingCapability
|
|
114
|
+
.attachDustRegistration(transaction, currentTime, nightVerifyingKey, dustReceiverAddress, feePayment)
|
|
115
|
+
.pipe(EitherOps.toEffect);
|
|
92
116
|
}
|
|
93
117
|
addDustGenerationSignature(transaction, signature) {
|
|
94
118
|
return this.#v1Context.transactingCapability
|
|
95
119
|
.addDustGenerationSignature(transaction, signature)
|
|
96
120
|
.pipe(EitherOps.toEffect);
|
|
97
121
|
}
|
|
122
|
+
addDustRegistrationSignature(transaction, signature) {
|
|
123
|
+
return this.#v1Context.transactingCapability
|
|
124
|
+
.addDustRegistrationSignature(transaction, signature)
|
|
125
|
+
.pipe(EitherOps.toEffect);
|
|
126
|
+
}
|
|
98
127
|
calculateFee(transactions) {
|
|
99
128
|
return pipe(this.#v1Context.syncService.blockData(), Effect.map((blockData) => pipe(transactions, Arr.map((transaction) => this.#v1Context.transactingCapability.calculateFee(transaction, blockData.ledgerParameters)), ArrayOps.sumBigInt)));
|
|
100
129
|
}
|
package/dist/v1/Sync.d.ts
CHANGED
|
@@ -26,6 +26,10 @@ export type IndexerClientConnection = {
|
|
|
26
26
|
indexerHttpUrl: string;
|
|
27
27
|
indexerWsUrl?: string;
|
|
28
28
|
keepAlive?: number;
|
|
29
|
+
/** Cap on the in-flight event queue between the WebSocket push and the apply loop. Default: 10000. */
|
|
30
|
+
bufferSize?: number;
|
|
31
|
+
/** In-flight count at which the disposed WS subscription is reopened. Default: 100. */
|
|
32
|
+
resumeThreshold?: number;
|
|
29
33
|
};
|
|
30
34
|
export type BatchUpdatesConfig = {
|
|
31
35
|
/**
|
package/dist/v1/Sync.js
CHANGED
|
@@ -33,19 +33,13 @@ const LedgerEventSchema = Schema.declare((input) => input instanceof LedgerEvent
|
|
|
33
33
|
identifier: 'ledger.Event',
|
|
34
34
|
});
|
|
35
35
|
const LedgerEventFromUInt8Array = Schema.asSchema(Schema.transformOrFail(Uint8ArraySchema, LedgerEventSchema, {
|
|
36
|
-
encode: (e) => {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
return new ParseResult.Unexpected(err, 'Could not serialize Ledger Event');
|
|
41
|
-
},
|
|
42
|
-
});
|
|
43
|
-
},
|
|
36
|
+
encode: (e) => Effect.try({
|
|
37
|
+
try: () => e.serialize(),
|
|
38
|
+
catch: (err) => new ParseResult.Unexpected(err, 'Could not serialize Ledger Event'),
|
|
39
|
+
}),
|
|
44
40
|
decode: (bytes) => Effect.try({
|
|
45
41
|
try: () => LedgerEvent.deserialize(bytes),
|
|
46
|
-
catch: (err) =>
|
|
47
|
-
return new ParseResult.Unexpected(err, 'Could not deserialize Ledger Event');
|
|
48
|
-
},
|
|
42
|
+
catch: (err) => new ParseResult.Unexpected(err, 'Could not deserialize Ledger Event'),
|
|
49
43
|
}),
|
|
50
44
|
}));
|
|
51
45
|
const HexedEvent = pipe(Schema.Uint8ArrayFromHex, Schema.compose(LedgerEventFromUInt8Array));
|
|
@@ -110,8 +104,32 @@ export const makeIndexerSyncService = (config) => {
|
|
|
110
104
|
},
|
|
111
105
|
subscribeWallet(state) {
|
|
112
106
|
const { appliedIndex } = state.progress;
|
|
113
|
-
|
|
114
|
-
|
|
107
|
+
const bufferSize = config.indexerClientConnection.bufferSize ?? 10000;
|
|
108
|
+
const resumeThreshold = config.indexerClientConnection.resumeThreshold ?? 100;
|
|
109
|
+
// The boundary is load-bearing, not waste: this subscription emits only events (no tip/progress
|
|
110
|
+
// sentinel), and `isConnected`/the tip (`maxId`) are set only when an event is received. So the
|
|
111
|
+
// cursor must stay `<= appliedIndex` — never `appliedIndex + 1`. Requesting one event later would
|
|
112
|
+
// deliver nothing to a wallet already at the tip, so `applyUpdate` would never run and sync would
|
|
113
|
+
// hang.
|
|
114
|
+
//
|
|
115
|
+
// A fresh wallet has `appliedIndex === 0n` (the "nothing applied yet" sentinel), so `resumeFrom`
|
|
116
|
+
// is `-1n` and the `variables` mapping below opens the subscription with no `id` — the indexer
|
|
117
|
+
// streams from the very start. A restored wallet has `appliedIndex >= 1`, so `resumeFrom` is
|
|
118
|
+
// `appliedIndex - 1` and the inclusive cursor re-delivers the boundary event.
|
|
119
|
+
const resumeFrom = appliedIndex - 1n;
|
|
120
|
+
return pipe(
|
|
121
|
+
// Backpressure caps the in-flight queue between the WS push and the
|
|
122
|
+
// apply loop. Without it the JS heap grows linearly with catch-up
|
|
123
|
+
// depth, since `Stream.asyncPush({ bufferSize: 'unbounded' })`
|
|
124
|
+
// buffers every event the indexer pushes regardless of apply rate.
|
|
125
|
+
DustLedgerEvents.runWithBackpressure({
|
|
126
|
+
bufferSize,
|
|
127
|
+
resumeThreshold,
|
|
128
|
+
from: resumeFrom,
|
|
129
|
+
// `resumeFrom < 0n` means a fresh wallet: send no `id` so the indexer streams from the very
|
|
130
|
+
// start, rather than relying on `id: 0` sorting below the first real event id.
|
|
131
|
+
variables: (cursor) => ({ id: cursor < 0n ? null : Number(cursor) }),
|
|
132
|
+
key: (r) => BigInt(r.dustLedgerEvents.id),
|
|
115
133
|
}), Stream.mapEffect((subscription) => pipe(Schema.decodeUnknownEither(SyncEventsUpdateSchema)(subscription.dustLedgerEvents), Either.mapLeft((err) => new SyncWalletError(err)), EitherOps.toEffect)), Stream.mapError((error) => new SyncWalletError(error)));
|
|
116
134
|
},
|
|
117
135
|
};
|
|
@@ -124,21 +142,14 @@ export const makeDefaultSyncCapability = () => {
|
|
|
124
142
|
if (updates.length === 0) {
|
|
125
143
|
return [state, { changes: [], protocolVersion: Number(state.protocolVersion) }];
|
|
126
144
|
}
|
|
127
|
-
const
|
|
128
|
-
const
|
|
129
|
-
const highestRelevantWalletIndex = BigInt(
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
return [
|
|
134
|
-
CoreWallet.updateProgress(state, { highestRelevantWalletIndex, isConnected: true }),
|
|
135
|
-
{ changes: [], protocolVersion: Number(state.protocolVersion) },
|
|
136
|
-
];
|
|
137
|
-
}
|
|
138
|
-
const events = updates.map((u) => u.raw).filter((event) => event !== null);
|
|
139
|
-
const [newState, changes] = CoreWallet.applyEventsWithChanges(state, secretKey, events, wrappedUpdate.timestamp);
|
|
145
|
+
const appliedIndex = state.progress.appliedIndex;
|
|
146
|
+
const freshUpdates = updates.filter((u) => BigInt(u.id) > appliedIndex);
|
|
147
|
+
const highestRelevantWalletIndex = BigInt(updates.at(-1).maxId);
|
|
148
|
+
const [newState, changes] = freshUpdates.length === 0
|
|
149
|
+
? [state, []]
|
|
150
|
+
: CoreWallet.applyEventsWithChanges(state, secretKey, freshUpdates.map((u) => u.raw), wrappedUpdate.timestamp);
|
|
140
151
|
const updatedState = CoreWallet.updateProgress(newState, {
|
|
141
|
-
appliedIndex:
|
|
152
|
+
appliedIndex: freshUpdates.length === 0 ? appliedIndex : BigInt(freshUpdates.at(-1).id),
|
|
142
153
|
highestRelevantWalletIndex,
|
|
143
154
|
isConnected: true,
|
|
144
155
|
});
|
package/dist/v1/Transacting.d.ts
CHANGED
|
@@ -6,11 +6,45 @@ import { CoreWallet } from './CoreWallet.js';
|
|
|
6
6
|
import { type AnyTransaction, type Dust, type NetworkId, type TotalCostParameters } from './types/index.js';
|
|
7
7
|
import { type CoinsAndBalancesCapability, type CoinSelection, type CoinWithValue, type UtxoWithFullDustDetails } from './CoinsAndBalances.js';
|
|
8
8
|
import { type KeysCapability } from './Keys.js';
|
|
9
|
+
/**
|
|
10
|
+
* Result of splitting Night UTxOs into the guaranteed/fallible sections of a Dust registration or deregistration
|
|
11
|
+
* intent, together with the fee-payment allowance the registration may claim from dust generated by the guaranteed
|
|
12
|
+
* UTxO.
|
|
13
|
+
*
|
|
14
|
+
* For deregistration, `feePayment` is always `0n`.
|
|
15
|
+
*/
|
|
16
|
+
export type NightUtxoSplitForDustRegistration = {
|
|
17
|
+
readonly guaranteedUtxos: ReadonlyArray<UtxoWithFullDustDetails>;
|
|
18
|
+
readonly fallibleUtxos: ReadonlyArray<UtxoWithFullDustDetails>;
|
|
19
|
+
readonly feePayment: bigint;
|
|
20
|
+
};
|
|
9
21
|
export interface TransactingCapability<TSecrets, TState, _TTransaction> {
|
|
10
22
|
readonly networkId: NetworkId;
|
|
11
23
|
readonly costParams: TotalCostParameters;
|
|
12
24
|
createDustGenerationTransaction(currentTime: Date, ttl: Date, nightUtxos: ReadonlyArray<UtxoWithFullDustDetails>, nightVerifyingKey: SignatureVerifyingKey, dustReceiverAddress: DustAddress | undefined): Either.Either<UnprovenTransaction, WalletError>;
|
|
25
|
+
/**
|
|
26
|
+
* Decides which Night UTxOs belong in the guaranteed vs fallible section of a dust registration/deregistration
|
|
27
|
+
* transaction, and computes the fee-payment allowance the registration may claim from dust generated by the
|
|
28
|
+
* guaranteed UTxO.
|
|
29
|
+
*
|
|
30
|
+
* For deregistration (`isRegistration === false`) the fee-payment allowance is always `0n`.
|
|
31
|
+
*/
|
|
32
|
+
splitNightUtxosForDustRegistration(utxosWithDustValue: ReadonlyArray<UtxoWithFullDustDetails>, isRegistration: boolean): NightUtxoSplitForDustRegistration;
|
|
33
|
+
/**
|
|
34
|
+
* Attaches a Dust registration / deregistration action onto the intent (at segment 1) of an unproven transaction
|
|
35
|
+
* whose offers have already been built (typically by the unshielded wallet's `rotateUtxos`). The Night UTxOs are
|
|
36
|
+
* assumed to already appear in the intent's guaranteed/fallible offers and to already be booked in the unshielded
|
|
37
|
+
* wallet state.
|
|
38
|
+
*/
|
|
39
|
+
attachDustRegistration(transaction: UnprovenTransaction, currentTime: Date, nightVerifyingKey: SignatureVerifyingKey, dustReceiverAddress: DustAddress | undefined, feePayment: bigint): Either.Either<UnprovenTransaction, WalletError>;
|
|
13
40
|
addDustGenerationSignature(transaction: UnprovenTransaction, signature: Signature): Either.Either<UnprovenTransaction, WalletError>;
|
|
41
|
+
/**
|
|
42
|
+
* Attaches a signature to the DustRegistration in segment 1's `dustActions` only. Unlike
|
|
43
|
+
* {@link addDustGenerationSignature}, this does NOT touch the unshielded offers — those are expected to be signed via
|
|
44
|
+
* the unshielded-wallet signing path. Use this when the caller orchestrates signing across both packages (e.g. the
|
|
45
|
+
* facade's `signRecipe`).
|
|
46
|
+
*/
|
|
47
|
+
addDustRegistrationSignature(transaction: UnprovenTransaction, signature: Signature): Either.Either<UnprovenTransaction, WalletError>;
|
|
14
48
|
calculateFee(transaction: AnyTransaction, ledgerParams: LedgerParameters): bigint;
|
|
15
49
|
estimateFee(secretKey: TSecrets, state: TState, transactions: ReadonlyArray<AnyTransaction>, ttl: Date, currentTime: Date, ledgerParams: LedgerParameters): Either.Either<bigint, WalletError>;
|
|
16
50
|
balanceTransactions(secretKey: TSecrets, state: TState, transactions: ReadonlyArray<AnyTransaction>, ttl: Date, currentTime: Date, ledgerParams: LedgerParameters): Either.Either<[UnprovenTransaction, TState], WalletError>;
|
|
@@ -21,7 +55,7 @@ export type DefaultTransactingConfiguration = {
|
|
|
21
55
|
costParameters: TotalCostParameters;
|
|
22
56
|
};
|
|
23
57
|
export type DefaultTransactingContext = {
|
|
24
|
-
coinSelection: CoinSelection
|
|
58
|
+
coinSelection: CoinSelection;
|
|
25
59
|
coinsAndBalancesCapability: CoinsAndBalancesCapability<CoreWallet>;
|
|
26
60
|
keysCapability: KeysCapability<CoreWallet>;
|
|
27
61
|
};
|
|
@@ -41,11 +75,14 @@ export declare const findAvailableSegmentId: (transaction: AnyTransaction) => Op
|
|
|
41
75
|
export declare class TransactingCapabilityImplementation<TTransaction extends AnyTransaction> implements TransactingCapability<DustSecretKey, CoreWallet, TTransaction> {
|
|
42
76
|
readonly networkId: string;
|
|
43
77
|
readonly costParams: TotalCostParameters;
|
|
44
|
-
readonly getCoinSelection: () => CoinSelection
|
|
78
|
+
readonly getCoinSelection: () => CoinSelection;
|
|
45
79
|
readonly getCoins: () => CoinsAndBalancesCapability<CoreWallet>;
|
|
46
80
|
readonly getKeys: () => KeysCapability<CoreWallet>;
|
|
47
|
-
constructor(networkId: NetworkId, costParams: TotalCostParameters, getCoinSelection: () => CoinSelection
|
|
81
|
+
constructor(networkId: NetworkId, costParams: TotalCostParameters, getCoinSelection: () => CoinSelection, getCoins: () => CoinsAndBalancesCapability<CoreWallet>, getKeys: () => KeysCapability<CoreWallet>);
|
|
48
82
|
createDustGenerationTransaction(currentTime: Date, ttl: Date, nightUtxos: ReadonlyArray<UtxoWithFullDustDetails>, nightVerifyingKey: SignatureVerifyingKey, dustReceiverAddress: DustAddress | undefined): Either.Either<UnprovenTransaction, WalletError>;
|
|
83
|
+
splitNightUtxosForDustRegistration(utxosWithDustValue: ReadonlyArray<UtxoWithFullDustDetails>, isRegistration: boolean): NightUtxoSplitForDustRegistration;
|
|
84
|
+
attachDustRegistration(transaction: UnprovenTransaction, currentTime: Date, nightVerifyingKey: SignatureVerifyingKey, dustReceiverAddress: DustAddress | undefined, feePayment: bigint): Either.Either<UnprovenTransaction, WalletError>;
|
|
85
|
+
addDustRegistrationSignature(transaction: UnprovenTransaction, signatureData: Signature): Either.Either<UnprovenTransaction, WalletError>;
|
|
49
86
|
addDustGenerationSignature(transaction: UnprovenTransaction, signatureData: Signature): Either.Either<UnprovenTransaction, WalletError>;
|
|
50
87
|
calculateFee(transaction: AnyTransaction, ledgerParams: LedgerParameters): bigint;
|
|
51
88
|
dryRunFee(recipeInputs: ReadonlyArray<CoinWithValue<Dust>>, transactions: ReadonlyArray<FinalizedTransaction | UnprovenTransaction>, secretKey: DustSecretKey, state: CoreWallet, ttl: Date, currentTime: Date, ledgerParams: LedgerParameters): bigint;
|
package/dist/v1/Transacting.js
CHANGED
|
@@ -108,6 +108,72 @@ export class TransactingCapabilityImplementation {
|
|
|
108
108
|
});
|
|
109
109
|
});
|
|
110
110
|
}
|
|
111
|
+
splitNightUtxosForDustRegistration(utxosWithDustValue, isRegistration) {
|
|
112
|
+
const splitResult = this.getCoins().splitNightUtxos(utxosWithDustValue);
|
|
113
|
+
// Deregistration must not claim dust as fee payment (matches the historical
|
|
114
|
+
// `dustReceiverAddress === undefined` branch of createDustGenerationTransaction).
|
|
115
|
+
const feePayment = isRegistration
|
|
116
|
+
? pipe(splitResult.guaranteed, IterableOps.filter((coin) => !coin.utxo.registeredForDustGeneration), IterableOps.map((coin) => coin.dust.generatedNow), BigIntOps.sumAll)
|
|
117
|
+
: 0n;
|
|
118
|
+
return {
|
|
119
|
+
guaranteedUtxos: splitResult.guaranteed,
|
|
120
|
+
fallibleUtxos: splitResult.fallible,
|
|
121
|
+
feePayment,
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
attachDustRegistration(transaction, currentTime, nightVerifyingKey, dustReceiverAddress, feePayment) {
|
|
125
|
+
return Either.gen(this, function* () {
|
|
126
|
+
const intent = transaction.intents?.get(1);
|
|
127
|
+
if (!intent) {
|
|
128
|
+
return yield* Either.left(new TransactingError({
|
|
129
|
+
message: 'No intent found at segment 1; expected an intent built by rotateUtxos',
|
|
130
|
+
}));
|
|
131
|
+
}
|
|
132
|
+
if (intent.dustActions !== undefined && intent.dustActions.registrations.length > 0) {
|
|
133
|
+
return yield* Either.left(new TransactingError({ message: 'Intent at segment 1 already has a dust registration attached' }));
|
|
134
|
+
}
|
|
135
|
+
return yield* LedgerOps.ledgerTry(() => {
|
|
136
|
+
const receiver = dustReceiverAddress ? dustReceiverAddress.data : undefined;
|
|
137
|
+
const dustRegistration = new DustRegistration(SignatureMarker.signature, nightVerifyingKey, receiver, feePayment);
|
|
138
|
+
const dustActions = new DustActions(SignatureMarker.signature, ProofMarker.preProof, currentTime, [], [dustRegistration]);
|
|
139
|
+
// Intents fetched from `transaction.intents.get(...)` behave like value copies — assigning
|
|
140
|
+
// to a field doesn't propagate back. Match the addDustGenerationSignature pattern: copy the
|
|
141
|
+
// intent via serialize/deserialize, mutate the copy, then set it back into a fresh
|
|
142
|
+
// transaction's intents map.
|
|
143
|
+
const newIntent = Intent.deserialize(SignatureMarker.signature, ProofMarker.preProof, BindingMarker.preBinding, intent.serialize());
|
|
144
|
+
newIntent.dustActions = dustActions;
|
|
145
|
+
const newTransaction = Transaction.deserialize(SignatureMarker.signature, ProofMarker.preProof, BindingMarker.preBinding, transaction.serialize());
|
|
146
|
+
newTransaction.intents = newTransaction.intents.set(1, newIntent);
|
|
147
|
+
return newTransaction;
|
|
148
|
+
});
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
addDustRegistrationSignature(transaction, signatureData) {
|
|
152
|
+
return Either.gen(this, function* () {
|
|
153
|
+
const intent = transaction.intents?.get(1);
|
|
154
|
+
if (!intent) {
|
|
155
|
+
return yield* Either.left(new TransactingError({ message: 'No intent found in the transaction intents with segment = 1' }));
|
|
156
|
+
}
|
|
157
|
+
const { dustActions } = intent;
|
|
158
|
+
if (!dustActions) {
|
|
159
|
+
return yield* Either.left(new TransactingError({ message: 'No dustActions found in intent' }));
|
|
160
|
+
}
|
|
161
|
+
const [registration, ...restRegistrations] = dustActions.registrations;
|
|
162
|
+
if (!registration) {
|
|
163
|
+
return yield* Either.left(new TransactingError({ message: 'No registrations found in dustActions' }));
|
|
164
|
+
}
|
|
165
|
+
return yield* LedgerOps.ledgerTry(() => {
|
|
166
|
+
const signature = new SignatureEnabled(signatureData);
|
|
167
|
+
const registrationWithSignature = new DustRegistration(signature.instance, registration.nightKey, registration.dustAddress, registration.allowFeePayment, signature);
|
|
168
|
+
const newDustActions = new DustActions(signature.instance, ProofMarker.preProof, dustActions.ctime, dustActions.spends, [registrationWithSignature, ...restRegistrations]);
|
|
169
|
+
const newIntent = Intent.deserialize(signature.instance, ProofMarker.preProof, BindingMarker.preBinding, intent.serialize());
|
|
170
|
+
newIntent.dustActions = newDustActions;
|
|
171
|
+
const newTransaction = Transaction.deserialize(signature.instance, ProofMarker.preProof, BindingMarker.preBinding, transaction.serialize());
|
|
172
|
+
newTransaction.intents = newTransaction.intents.set(1, newIntent);
|
|
173
|
+
return newTransaction;
|
|
174
|
+
});
|
|
175
|
+
});
|
|
176
|
+
}
|
|
111
177
|
addDustGenerationSignature(transaction, signatureData) {
|
|
112
178
|
return Either.gen(this, function* () {
|
|
113
179
|
const intent = transaction.intents?.get(1);
|
|
@@ -167,9 +233,7 @@ export class TransactingCapabilityImplementation {
|
|
|
167
233
|
const [first, ...rest] = transactions.map((tx) => tx.eraseProofs());
|
|
168
234
|
const mergedExisting = first ? rest.reduce((acc, tx) => acc.merge(tx), first) : undefined;
|
|
169
235
|
const segmentId = mergedExisting ? Option.getOrElse(findAvailableSegmentId(mergedExisting), () => 1) : 1;
|
|
170
|
-
|
|
171
|
-
const balancingTx = Transaction.fromParts(network, undefined, undefined, undefined);
|
|
172
|
-
balancingTx.intents = new Map([[segmentId, intent]]);
|
|
236
|
+
const balancingTx = Transaction.fromParts(network).addIntent({ tag: 'specific', value: segmentId }, intent);
|
|
173
237
|
const erasedBalancing = balancingTx.eraseProofs();
|
|
174
238
|
const mergedTx = mergedExisting ? mergedExisting.merge(erasedBalancing) : erasedBalancing;
|
|
175
239
|
return this.calculateFee(mergedTx, ledgerParams);
|
|
@@ -197,14 +261,15 @@ export class TransactingCapabilityImplementation {
|
|
|
197
261
|
})),
|
|
198
262
|
initialImbalances: CapImbalances.fromEntry('dust', currentFee),
|
|
199
263
|
feeTokenType: 'dust',
|
|
264
|
+
coinSelection: this.getCoinSelection(),
|
|
200
265
|
transactionCostModel: {
|
|
201
266
|
inputFeeOverhead: 0n,
|
|
202
267
|
outputFeeOverhead: 0n,
|
|
203
268
|
},
|
|
204
269
|
createOutput: (coin) => coin,
|
|
205
|
-
isCoinEqual: (a, b) => a.
|
|
270
|
+
isCoinEqual: (a, b) => a.token.nonce === b.token.nonce,
|
|
206
271
|
});
|
|
207
|
-
const recipeInputs = recipe.inputs.map((
|
|
272
|
+
const recipeInputs = recipe.inputs.map(({ token, value }) => ({ token, value }));
|
|
208
273
|
const newFee = this.dryRunFee(recipeInputs, transactions, secretKey, state, ttl, currentTime, ledgerParams);
|
|
209
274
|
const recipeAmountCoverage = recipeInputs.reduce((sum, input) => sum + input.value, 0n);
|
|
210
275
|
return { currentFee: newFee, recipeInputs, converged: newFee <= recipeAmountCoverage };
|
|
@@ -243,8 +308,7 @@ export class TransactingCapabilityImplementation {
|
|
|
243
308
|
const [first, ...rest] = transactions.map((tx) => tx.eraseProofs());
|
|
244
309
|
const mergedExisting = first ? rest.reduce((acc, tx) => acc.merge(tx), first) : undefined;
|
|
245
310
|
const segmentId = mergedExisting ? Option.getOrElse(findAvailableSegmentId(mergedExisting), () => 1) : 1;
|
|
246
|
-
const feeTransaction = Transaction.fromParts(networkId
|
|
247
|
-
feeTransaction.intents = new Map([[segmentId, intent]]);
|
|
311
|
+
const feeTransaction = Transaction.fromParts(networkId).addIntent({ tag: 'specific', value: segmentId }, intent);
|
|
248
312
|
return [feeTransaction, updatedState];
|
|
249
313
|
});
|
|
250
314
|
}));
|
package/dist/v1/V1Builder.d.ts
CHANGED
|
@@ -10,7 +10,6 @@ import { type KeysCapability } from './Keys.js';
|
|
|
10
10
|
import { type CoinsAndBalancesCapability, type CoinSelection, type DefaultCoinsAndBalancesContext } from './CoinsAndBalances.js';
|
|
11
11
|
import { type DefaultTransactingConfiguration, type DefaultTransactingContext, type TransactingCapability } from './Transacting.js';
|
|
12
12
|
import { type NetworkId } from './types/ledger.js';
|
|
13
|
-
import { type Dust } from './types/Dust.js';
|
|
14
13
|
import { type SerializationCapability } from './Serialization.js';
|
|
15
14
|
import { type TotalCostParameters } from './types/transaction.js';
|
|
16
15
|
export type BaseV1Configuration = {
|
|
@@ -43,7 +42,7 @@ export declare class V1Builder<TConfig extends BaseV1Configuration = BaseV1Confi
|
|
|
43
42
|
withSerialization<TSerializationConfig, TSerializationContext extends Partial<RunningV1Variant.AnyContext>, TSerialized>(serializationCapability: (configuration: TSerializationConfig, getContext: () => TSerializationContext) => SerializationCapability<CoreWallet, null, TSerialized>): V1Builder<TConfig & TSerializationConfig, TContext & TSerializationContext, TSerialized, TSyncUpdate, TTransaction, TStartAux>;
|
|
44
43
|
withTransactingDefaults(this: V1Builder<TConfig, TContext, TSerialized, TSyncUpdate, FinalizedTransaction, TStartAux>): V1Builder<TConfig & DefaultTransactingConfiguration, TContext & DefaultTransactingContext, TSerialized, TSyncUpdate, FinalizedTransaction, TStartAux>;
|
|
45
44
|
withTransacting<TTransactingConfig, TTransactingContext extends Partial<RunningV1Variant.AnyContext>>(transactingCapability: (config: TTransactingConfig, getContext: () => TTransactingContext) => TransactingCapability<DustSecretKey, CoreWallet, TTransaction>): V1Builder<TConfig & TTransactingConfig, TContext & TTransactingContext, TSerialized, TSyncUpdate, TTransaction, TStartAux>;
|
|
46
|
-
withCoinSelection<TCoinSelectionConfig, TCoinSelectionContext extends Partial<RunningV1Variant.AnyContext>>(coinSelection: (config: TCoinSelectionConfig, getContext: () => TCoinSelectionContext) => CoinSelection
|
|
45
|
+
withCoinSelection<TCoinSelectionConfig, TCoinSelectionContext extends Partial<RunningV1Variant.AnyContext>>(coinSelection: (config: TCoinSelectionConfig, getContext: () => TCoinSelectionContext) => CoinSelection): V1Builder<TConfig & TCoinSelectionConfig, TContext & TCoinSelectionContext, TSerialized, TSyncUpdate, TTransaction, TStartAux>;
|
|
47
46
|
withCoinSelectionDefaults(): V1Builder<TConfig, TContext, TSerialized, TSyncUpdate, TTransaction, TStartAux>;
|
|
48
47
|
withCoinsAndBalancesDefaults(): V1Builder<TConfig, TContext & DefaultCoinsAndBalancesContext, TSerialized, TSyncUpdate, TTransaction, TStartAux>;
|
|
49
48
|
withCoinsAndBalances<TBalancesConfig, TBalancesContext extends Partial<RunningV1Variant.AnyContext>>(coinsAndBalancesCapability: (configuration: TBalancesConfig, getContext: () => TBalancesContext) => CoinsAndBalancesCapability<CoreWallet>): V1Builder<TConfig & TBalancesConfig, TContext & TBalancesContext, TSerialized, TSyncUpdate, TTransaction, TStartAux>;
|
|
@@ -66,7 +65,7 @@ declare namespace V1Builder {
|
|
|
66
65
|
readonly serializationCapability: (configuration: TConfig, getContext: () => TContext) => SerializationCapability<CoreWallet, null, TSerialized>;
|
|
67
66
|
};
|
|
68
67
|
type HasCoinSelection<TConfig, TContext> = {
|
|
69
|
-
readonly coinSelection: (configuration: TConfig, getContext: () => TContext) => CoinSelection
|
|
68
|
+
readonly coinSelection: (configuration: TConfig, getContext: () => TContext) => CoinSelection;
|
|
70
69
|
};
|
|
71
70
|
type HasCoinsAndBalances<TConfig, TContext> = {
|
|
72
71
|
readonly coinsAndBalancesCapability: (configuration: TConfig, getContext: () => TContext) => CoinsAndBalancesCapability<CoreWallet>;
|
package/dist/v1/index.d.ts
CHANGED
package/dist/v1/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@midnight-ntwrk/wallet-sdk-dust-wallet",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.2.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.js",
|
|
@@ -8,14 +8,16 @@
|
|
|
8
8
|
"author": "Midnight Foundation",
|
|
9
9
|
"license": "Apache-2.0",
|
|
10
10
|
"publishConfig": {
|
|
11
|
-
"registry": "https://
|
|
11
|
+
"registry": "https://registry.npmjs.org/",
|
|
12
|
+
"access": "public"
|
|
12
13
|
},
|
|
13
14
|
"files": [
|
|
14
15
|
"dist/"
|
|
15
16
|
],
|
|
16
17
|
"repository": {
|
|
17
18
|
"type": "git",
|
|
18
|
-
"url": "git+https://github.com/midnight-
|
|
19
|
+
"url": "git+https://github.com/midnightntwrk/midnight-wallet.git",
|
|
20
|
+
"directory": "packages/dust-wallet"
|
|
19
21
|
},
|
|
20
22
|
"exports": {
|
|
21
23
|
".": {
|
|
@@ -28,13 +30,13 @@
|
|
|
28
30
|
}
|
|
29
31
|
},
|
|
30
32
|
"dependencies": {
|
|
31
|
-
"@midnight-ntwrk/ledger-v8": "^8.0
|
|
32
|
-
"@midnight-ntwrk/wallet-sdk-abstractions": "2.1.0",
|
|
33
|
-
"@midnight-ntwrk/wallet-sdk-address-format": "3.1.
|
|
34
|
-
"@midnight-ntwrk/wallet-sdk-capabilities": "3.3.
|
|
35
|
-
"@midnight-ntwrk/wallet-sdk-indexer-client": "1.2.
|
|
36
|
-
"@midnight-ntwrk/wallet-sdk-runtime": "1.0.
|
|
37
|
-
"@midnight-ntwrk/wallet-sdk-utilities": "1.
|
|
33
|
+
"@midnight-ntwrk/ledger-v8": "^8.1.0",
|
|
34
|
+
"@midnight-ntwrk/wallet-sdk-abstractions": "^2.1.0",
|
|
35
|
+
"@midnight-ntwrk/wallet-sdk-address-format": "^3.1.2",
|
|
36
|
+
"@midnight-ntwrk/wallet-sdk-capabilities": "^3.3.1",
|
|
37
|
+
"@midnight-ntwrk/wallet-sdk-indexer-client": "^1.2.3",
|
|
38
|
+
"@midnight-ntwrk/wallet-sdk-runtime": "^1.0.5",
|
|
39
|
+
"@midnight-ntwrk/wallet-sdk-utilities": "^1.2.0",
|
|
38
40
|
"effect": "^3.19.19",
|
|
39
41
|
"rxjs": "^7.8.2"
|
|
40
42
|
},
|
|
@@ -50,6 +52,6 @@
|
|
|
50
52
|
"publint": "publint --strict"
|
|
51
53
|
},
|
|
52
54
|
"devDependencies": {
|
|
53
|
-
"@midnight-ntwrk/wallet-sdk-hd": "3.0.
|
|
55
|
+
"@midnight-ntwrk/wallet-sdk-hd": "^3.0.3"
|
|
54
56
|
}
|
|
55
57
|
}
|