@midnight-ntwrk/wallet-sdk-dust-wallet 4.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 +10 -0
- package/dist/DustWallet.js +21 -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 +28 -6
- package/dist/v1/Transacting.d.ts +40 -3
- package/dist/v1/Transacting.js +71 -7
- package/dist/v1/V1Builder.d.ts +2 -3
- package/package.json +9 -9
package/dist/DustWallet.d.ts
CHANGED
|
@@ -7,6 +7,7 @@ import { type Balance, type CoinsAndBalancesCapability, type UtxoWithFullDustDet
|
|
|
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 NightUtxoSplitForDustRegistration } from './v1/Transacting.js';
|
|
10
11
|
import { type DustFullInfo, type UtxoWithMeta } from './v1/types/Dust.js';
|
|
11
12
|
import { type AnyTransaction } from './v1/types/ledger.js';
|
|
12
13
|
import { type BaseV1Configuration, type DefaultV1Configuration, type V1Variant } from './v1/V1Builder.js';
|
|
@@ -41,7 +42,16 @@ export type DustWalletAPI<TStartAux = DustSecretKey, TSerialized = string> = {
|
|
|
41
42
|
readonly state: rx.Observable<DustWalletState<TSerialized>>;
|
|
42
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>;
|
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({
|
|
@@ -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>;
|
|
@@ -82,19 +82,41 @@ export class RunningV1Variant {
|
|
|
82
82
|
if (nightUtxos.some((utxo) => utxo.type !== nativeToken().raw)) {
|
|
83
83
|
return Effect.fail(new OtherWalletError({ message: 'Token of a non-Night type received' }));
|
|
84
84
|
}
|
|
85
|
-
return Effect.
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
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)
|
|
90
92
|
.pipe(EitherOps.toEffect);
|
|
91
|
-
})
|
|
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);
|
|
92
109
|
}
|
|
93
110
|
addDustGenerationSignature(transaction, signature) {
|
|
94
111
|
return this.#v1Context.transactingCapability
|
|
95
112
|
.addDustGenerationSignature(transaction, signature)
|
|
96
113
|
.pipe(EitherOps.toEffect);
|
|
97
114
|
}
|
|
115
|
+
addDustRegistrationSignature(transaction, signature) {
|
|
116
|
+
return this.#v1Context.transactingCapability
|
|
117
|
+
.addDustRegistrationSignature(transaction, signature)
|
|
118
|
+
.pipe(EitherOps.toEffect);
|
|
119
|
+
}
|
|
98
120
|
calculateFee(transactions) {
|
|
99
121
|
return pipe(this.#v1Context.syncService.blockData(), Effect.map((blockData) => pipe(transactions, Arr.map((transaction) => this.#v1Context.transactingCapability.calculateFee(transaction, blockData.ledgerParameters)), ArrayOps.sumBigInt)));
|
|
100
122
|
}
|
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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@midnight-ntwrk/wallet-sdk-dust-wallet",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.1.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.js",
|
|
@@ -28,13 +28,13 @@
|
|
|
28
28
|
}
|
|
29
29
|
},
|
|
30
30
|
"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.
|
|
31
|
+
"@midnight-ntwrk/ledger-v8": "^8.1.0",
|
|
32
|
+
"@midnight-ntwrk/wallet-sdk-abstractions": "^2.1.0",
|
|
33
|
+
"@midnight-ntwrk/wallet-sdk-address-format": "^3.1.2",
|
|
34
|
+
"@midnight-ntwrk/wallet-sdk-capabilities": "^3.3.1",
|
|
35
|
+
"@midnight-ntwrk/wallet-sdk-indexer-client": "^1.2.2",
|
|
36
|
+
"@midnight-ntwrk/wallet-sdk-runtime": "^1.0.4",
|
|
37
|
+
"@midnight-ntwrk/wallet-sdk-utilities": "^1.2.0",
|
|
38
38
|
"effect": "^3.19.19",
|
|
39
39
|
"rxjs": "^7.8.2"
|
|
40
40
|
},
|
|
@@ -50,6 +50,6 @@
|
|
|
50
50
|
"publint": "publint --strict"
|
|
51
51
|
},
|
|
52
52
|
"devDependencies": {
|
|
53
|
-
"@midnight-ntwrk/wallet-sdk-hd": "3.0.2"
|
|
53
|
+
"@midnight-ntwrk/wallet-sdk-hd": "^3.0.2"
|
|
54
54
|
}
|
|
55
55
|
}
|