@midnight-ntwrk/wallet-sdk-dust-wallet 1.0.0-beta.8 → 1.0.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 +97 -2
- package/dist/CoinsAndBalances.d.ts +26 -2
- package/dist/CoinsAndBalances.js +67 -11
- package/dist/DustCoreWallet.d.ts +1 -1
- package/dist/DustCoreWallet.js +14 -1
- package/dist/DustWallet.d.ts +12 -10
- package/dist/DustWallet.js +28 -10
- package/dist/Keys.d.ts +1 -1
- package/dist/RunningV1Variant.d.ts +7 -7
- package/dist/RunningV1Variant.js +26 -24
- package/dist/Serialization.js +13 -1
- package/dist/Simulator.d.ts +2 -1
- package/dist/Simulator.js +18 -3
- package/dist/Submission.d.ts +1 -1
- package/dist/Submission.js +12 -0
- package/dist/Sync.d.ts +11 -4
- package/dist/Sync.js +55 -17
- package/dist/Transacting.d.ts +11 -19
- package/dist/Transacting.js +71 -57
- package/dist/Utils.js +12 -0
- package/dist/V1Builder.d.ts +3 -3
- package/dist/V1Builder.js +12 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +13 -0
- package/dist/types/Dust.d.ts +4 -2
- package/dist/types/index.js +12 -0
- package/dist/types/ledger.d.ts +2 -2
- package/package.json +18 -16
package/dist/Submission.js
CHANGED
|
@@ -1,3 +1,15 @@
|
|
|
1
|
+
// This file is part of MIDNIGHT-WALLET-SDK.
|
|
2
|
+
// Copyright (C) 2025 Midnight Foundation
|
|
3
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
// You may not use this file except in compliance with the License.
|
|
6
|
+
// You may obtain a copy of the License at
|
|
7
|
+
// http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
// Unless required by applicable law or agreed to in writing, software
|
|
9
|
+
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
10
|
+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
11
|
+
// See the License for the specific language governing permissions and
|
|
12
|
+
// limitations under the License.
|
|
1
13
|
import { Deferred, Effect, Encoding, Exit, pipe, Scope } from 'effect';
|
|
2
14
|
import { NodeClient, PolkadotNodeClient, SubmissionEvent as SubmissionEventImported, } from '@midnight-ntwrk/wallet-sdk-node-client/effect';
|
|
3
15
|
import { WalletError } from '@midnight-ntwrk/wallet-sdk-shielded/v1';
|
package/dist/Sync.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Effect, Layer, Schema, Scope, Stream } from 'effect';
|
|
2
|
-
import { DustSecretKey, Event as LedgerEvent, LedgerParameters } from '@midnight-ntwrk/ledger-
|
|
2
|
+
import { DustSecretKey, Event as LedgerEvent, LedgerParameters } from '@midnight-ntwrk/ledger-v7';
|
|
3
3
|
import { SubscriptionClient, QueryClient } from '@midnight-ntwrk/wallet-sdk-indexer-client/effect';
|
|
4
4
|
import { WalletError } from '@midnight-ntwrk/wallet-sdk-shielded/v1';
|
|
5
5
|
import { Simulator, SimulatorState } from './Simulator.js';
|
|
@@ -7,7 +7,13 @@ import { DustCoreWallet } from './DustCoreWallet.js';
|
|
|
7
7
|
import { NetworkId } from './types/ledger.js';
|
|
8
8
|
export interface SyncService<TState, TStartAux, TUpdate> {
|
|
9
9
|
updates: (state: TState, auxData: TStartAux) => Stream.Stream<TUpdate, WalletError.WalletError, Scope.Scope>;
|
|
10
|
-
|
|
10
|
+
blockData: () => Effect.Effect<BlockData, WalletError.WalletError>;
|
|
11
|
+
}
|
|
12
|
+
export interface BlockData {
|
|
13
|
+
hash: string;
|
|
14
|
+
height: number;
|
|
15
|
+
ledgerParameters: LedgerParameters;
|
|
16
|
+
timestamp: Date;
|
|
11
17
|
}
|
|
12
18
|
export interface SyncCapability<TState, TUpdate> {
|
|
13
19
|
applyUpdate: (state: TState, update: TUpdate) => TState;
|
|
@@ -39,11 +45,12 @@ export declare const SyncEventsUpdateSchema: Schema.Struct<{
|
|
|
39
45
|
}>;
|
|
40
46
|
export type WalletSyncSubscription = Schema.Schema.Type<typeof SyncEventsUpdateSchema>;
|
|
41
47
|
export type WalletSyncUpdate = {
|
|
42
|
-
|
|
48
|
+
updates: WalletSyncSubscription[];
|
|
43
49
|
secretKeys: SecretKeysResource;
|
|
50
|
+
timestamp: Date;
|
|
44
51
|
};
|
|
45
52
|
export declare const WalletSyncUpdate: {
|
|
46
|
-
create: (
|
|
53
|
+
create: (updates: WalletSyncSubscription[], secretKey: DustSecretKey, timestamp: Date) => WalletSyncUpdate;
|
|
47
54
|
};
|
|
48
55
|
export declare const makeDefaultSyncService: (config: DefaultSyncConfiguration) => SyncService<DustCoreWallet, DustSecretKey, WalletSyncUpdate>;
|
|
49
56
|
export type IndexerSyncService = {
|
package/dist/Sync.js
CHANGED
|
@@ -1,10 +1,23 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
// This file is part of MIDNIGHT-WALLET-SDK.
|
|
2
|
+
// Copyright (C) 2025 Midnight Foundation
|
|
3
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
// You may not use this file except in compliance with the License.
|
|
6
|
+
// You may obtain a copy of the License at
|
|
7
|
+
// http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
// Unless required by applicable law or agreed to in writing, software
|
|
9
|
+
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
10
|
+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
11
|
+
// See the License for the specific language governing permissions and
|
|
12
|
+
// limitations under the License.
|
|
13
|
+
import { Effect, Either, Layer, ParseResult, pipe, Schema, Stream, Duration, Chunk, Schedule } from 'effect';
|
|
14
|
+
import { Event as LedgerEvent, LedgerParameters } from '@midnight-ntwrk/ledger-v7';
|
|
3
15
|
import { BlockHash, DustLedgerEvents } from '@midnight-ntwrk/wallet-sdk-indexer-client';
|
|
4
16
|
import { WsSubscriptionClient, HttpQueryClient, ConnectionHelper, } from '@midnight-ntwrk/wallet-sdk-indexer-client/effect';
|
|
5
17
|
import { DateOps, EitherOps, LedgerOps } from '@midnight-ntwrk/wallet-sdk-utilities';
|
|
6
18
|
import { WsURL } from '@midnight-ntwrk/wallet-sdk-utilities/networking';
|
|
7
19
|
import { WalletError } from '@midnight-ntwrk/wallet-sdk-shielded/v1';
|
|
20
|
+
import { Simulator } from './Simulator.js';
|
|
8
21
|
import { Uint8ArraySchema } from './Serialization.js';
|
|
9
22
|
export const SecretKeysResource = {
|
|
10
23
|
create: (secretKey) => {
|
|
@@ -45,10 +58,11 @@ export const SyncEventsUpdateSchema = Schema.Struct({
|
|
|
45
58
|
maxId: Schema.Number,
|
|
46
59
|
});
|
|
47
60
|
export const WalletSyncUpdate = {
|
|
48
|
-
create: (
|
|
61
|
+
create: (updates, secretKey, timestamp) => {
|
|
49
62
|
return {
|
|
50
|
-
|
|
63
|
+
updates,
|
|
51
64
|
secretKeys: SecretKeysResource.create(secretKey),
|
|
65
|
+
timestamp,
|
|
52
66
|
};
|
|
53
67
|
},
|
|
54
68
|
};
|
|
@@ -56,18 +70,26 @@ export const makeDefaultSyncService = (config) => {
|
|
|
56
70
|
const indexerSyncService = makeIndexerSyncService(config);
|
|
57
71
|
return {
|
|
58
72
|
updates: (state, secretKey) => {
|
|
59
|
-
|
|
73
|
+
const batchSize = 10;
|
|
74
|
+
const batchTimeout = Duration.millis(1);
|
|
75
|
+
return pipe(indexerSyncService.subscribeWallet(state), Stream.groupedWithin(batchSize, batchTimeout), Stream.map(Chunk.toArray), Stream.map((data) => WalletSyncUpdate.create(data, secretKey, new Date())), Stream.schedule(Schedule.spaced(Duration.millis(4))), Stream.provideSomeLayer(indexerSyncService.connectionLayer()));
|
|
60
76
|
},
|
|
61
|
-
|
|
77
|
+
blockData: () => {
|
|
62
78
|
return Effect.gen(function* () {
|
|
63
79
|
const query = yield* BlockHash;
|
|
64
80
|
const result = yield* query({ offset: null });
|
|
65
|
-
return result.block
|
|
66
|
-
}).pipe(Effect.provide(indexerSyncService.queryClient()), Effect.scoped, Effect.catchAll((err) => Effect.fail(WalletError.WalletError.other(`Encountered unexpected error: ${err.message}`))), Effect.flatMap((
|
|
67
|
-
if (
|
|
68
|
-
return Effect.fail(WalletError.WalletError.other('Unable to fetch
|
|
81
|
+
return result.block;
|
|
82
|
+
}).pipe(Effect.provide(indexerSyncService.queryClient()), Effect.scoped, Effect.catchAll((err) => Effect.fail(WalletError.WalletError.other(`Encountered unexpected error: ${err.message}`))), Effect.flatMap((blockData) => {
|
|
83
|
+
if (!blockData) {
|
|
84
|
+
return Effect.fail(WalletError.WalletError.other('Unable to fetch block data'));
|
|
69
85
|
}
|
|
70
|
-
|
|
86
|
+
// TODO: convert to schema
|
|
87
|
+
return LedgerOps.ledgerTry(() => ({
|
|
88
|
+
hash: blockData.hash,
|
|
89
|
+
height: blockData.height,
|
|
90
|
+
ledgerParameters: LedgerParameters.deserialize(Buffer.from(blockData.ledgerParameters, 'hex')),
|
|
91
|
+
timestamp: new Date(blockData.timestamp),
|
|
92
|
+
}));
|
|
71
93
|
}));
|
|
72
94
|
},
|
|
73
95
|
};
|
|
@@ -95,17 +117,22 @@ export const makeIndexerSyncService = (config) => {
|
|
|
95
117
|
export const makeDefaultSyncCapability = () => {
|
|
96
118
|
return {
|
|
97
119
|
applyUpdate(state, wrappedUpdate) {
|
|
98
|
-
const {
|
|
99
|
-
|
|
100
|
-
|
|
120
|
+
const { updates, secretKeys } = wrappedUpdate;
|
|
121
|
+
// Nothing to update yet
|
|
122
|
+
if (updates.length === 0) {
|
|
123
|
+
return state;
|
|
124
|
+
}
|
|
125
|
+
const lastUpdate = updates.at(-1);
|
|
126
|
+
const nextIndex = BigInt(lastUpdate.id);
|
|
127
|
+
const highestRelevantWalletIndex = BigInt(lastUpdate.maxId);
|
|
101
128
|
// in case the nextIndex is less than or equal to the current appliedIndex
|
|
102
129
|
// just update highestRelevantWalletIndex
|
|
103
130
|
if (nextIndex <= state.progress.appliedIndex) {
|
|
104
131
|
return state.updateProgress({ highestRelevantWalletIndex, isConnected: true });
|
|
105
132
|
}
|
|
106
|
-
const events =
|
|
133
|
+
const events = updates.map((u) => u.raw).filter((event) => event !== null);
|
|
107
134
|
return secretKeys((keys) => state
|
|
108
|
-
.applyEvents(keys, events,
|
|
135
|
+
.applyEvents(keys, events, wrappedUpdate.timestamp)
|
|
109
136
|
.updateProgress({ appliedIndex: nextIndex, highestRelevantWalletIndex, isConnected: true }));
|
|
110
137
|
},
|
|
111
138
|
};
|
|
@@ -113,7 +140,18 @@ export const makeDefaultSyncCapability = () => {
|
|
|
113
140
|
export const makeSimulatorSyncService = (config) => {
|
|
114
141
|
return {
|
|
115
142
|
updates: (_state, secretKey) => config.simulator.state$.pipe(Stream.map((state) => ({ update: state, secretKey }))),
|
|
116
|
-
|
|
143
|
+
blockData: () => {
|
|
144
|
+
return Effect.gen(function* () {
|
|
145
|
+
const state = yield* config.simulator.getLatestState();
|
|
146
|
+
const timestamp = DateOps.secondsToDate(state.lastTxNumber);
|
|
147
|
+
return {
|
|
148
|
+
hash: yield* Simulator.blockHash(timestamp),
|
|
149
|
+
height: Number(state.lastTxNumber),
|
|
150
|
+
ledgerParameters: state.ledger.parameters,
|
|
151
|
+
timestamp,
|
|
152
|
+
};
|
|
153
|
+
});
|
|
154
|
+
},
|
|
117
155
|
};
|
|
118
156
|
};
|
|
119
157
|
export const makeSimulatorSyncCapability = () => ({
|
package/dist/Transacting.d.ts
CHANGED
|
@@ -1,22 +1,18 @@
|
|
|
1
1
|
import { Either } from 'effect';
|
|
2
|
-
import { DustSecretKey, Signature, SignatureVerifyingKey,
|
|
3
|
-
import {
|
|
2
|
+
import { DustSecretKey, Signature, SignatureVerifyingKey, FinalizedTransaction, ProofErasedTransaction, UnprovenTransaction, LedgerParameters } from '@midnight-ntwrk/ledger-v7';
|
|
3
|
+
import { WalletError } from '@midnight-ntwrk/wallet-sdk-shielded/v1';
|
|
4
4
|
import { DustCoreWallet } from './DustCoreWallet.js';
|
|
5
5
|
import { AnyTransaction, DustToken, NetworkId, TotalCostParameters } from './types/index.js';
|
|
6
|
-
import { CoinsAndBalancesCapability, CoinSelection,
|
|
6
|
+
import { CoinsAndBalancesCapability, CoinSelection, UtxoWithFullDustDetails } from './CoinsAndBalances.js';
|
|
7
7
|
import { KeysCapability } from './Keys.js';
|
|
8
8
|
export interface TransactingCapability<TSecrets, TState, TTransaction> {
|
|
9
9
|
readonly networkId: NetworkId;
|
|
10
10
|
readonly costParams: TotalCostParameters;
|
|
11
|
-
createDustGenerationTransaction(currentTime: Date, ttl: Date, nightUtxos: ReadonlyArray<
|
|
12
|
-
addDustGenerationSignature(transaction: UnprovenTransaction, signature: Signature): Either.Either<
|
|
11
|
+
createDustGenerationTransaction(currentTime: Date, ttl: Date, nightUtxos: ReadonlyArray<UtxoWithFullDustDetails>, nightVerifyingKey: SignatureVerifyingKey, dustReceiverAddress: string | undefined): Either.Either<UnprovenTransaction, WalletError.WalletError>;
|
|
12
|
+
addDustGenerationSignature(transaction: UnprovenTransaction, signature: Signature): Either.Either<UnprovenTransaction, WalletError.WalletError>;
|
|
13
13
|
calculateFee(transaction: AnyTransaction, ledgerParams: LedgerParameters): bigint;
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
newState: TState;
|
|
17
|
-
}, WalletError.WalletError>;
|
|
18
|
-
revert(state: TState, tx: TTransaction): Either.Either<TState, WalletError.WalletError>;
|
|
19
|
-
revertRecipe(state: TState, recipe: ProvingRecipe.ProvingRecipe<TTransaction>): Either.Either<TState, WalletError.WalletError>;
|
|
14
|
+
balanceTransactions(secretKey: TSecrets, state: TState, transactions: ReadonlyArray<AnyTransaction>, ttl: Date, currentTime: Date, ledgerParams: LedgerParameters): Either.Either<[UnprovenTransaction, TState], WalletError.WalletError>;
|
|
15
|
+
revertTransaction(state: TState, transaction: UnprovenTransaction | TTransaction): Either.Either<TState, WalletError.WalletError>;
|
|
20
16
|
}
|
|
21
17
|
export type DefaultTransactingConfiguration = {
|
|
22
18
|
networkId: NetworkId;
|
|
@@ -37,14 +33,10 @@ export declare class TransactingCapabilityImplementation<TTransaction extends An
|
|
|
37
33
|
readonly getCoins: () => CoinsAndBalancesCapability<DustCoreWallet>;
|
|
38
34
|
readonly getKeys: () => KeysCapability<DustCoreWallet>;
|
|
39
35
|
constructor(networkId: NetworkId, costParams: TotalCostParameters, getCoinSelection: () => CoinSelection<DustToken>, getCoins: () => CoinsAndBalancesCapability<DustCoreWallet>, getKeys: () => KeysCapability<DustCoreWallet>);
|
|
40
|
-
createDustGenerationTransaction(currentTime: Date, ttl: Date, nightUtxos: ReadonlyArray<
|
|
41
|
-
addDustGenerationSignature(transaction: UnprovenTransaction, signatureData: Signature): Either.Either<
|
|
36
|
+
createDustGenerationTransaction(currentTime: Date, ttl: Date, nightUtxos: ReadonlyArray<UtxoWithFullDustDetails>, nightVerifyingKey: SignatureVerifyingKey, dustReceiverAddress: string | undefined): Either.Either<UnprovenTransaction, WalletError.WalletError>;
|
|
37
|
+
addDustGenerationSignature(transaction: UnprovenTransaction, signatureData: Signature): Either.Either<UnprovenTransaction, WalletError.WalletError>;
|
|
42
38
|
calculateFee(transaction: AnyTransaction, ledgerParams: LedgerParameters): bigint;
|
|
43
39
|
static feeImbalance(transaction: AnyTransaction, totalFee: bigint): bigint;
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
newState: DustCoreWallet;
|
|
47
|
-
}, WalletError.WalletError>;
|
|
48
|
-
revert(state: DustCoreWallet, tx: TTransaction): Either.Either<DustCoreWallet, WalletError.WalletError>;
|
|
49
|
-
revertRecipe(state: DustCoreWallet, recipe: ProvingRecipe.ProvingRecipe<TTransaction>): Either.Either<DustCoreWallet, WalletError.WalletError>;
|
|
40
|
+
balanceTransactions(secretKey: DustSecretKey, state: DustCoreWallet, transactions: ReadonlyArray<FinalizedTransaction | UnprovenTransaction>, ttl: Date, currentTime: Date, ledgerParams: LedgerParameters): Either.Either<[UnprovenTransaction, DustCoreWallet], WalletError.WalletError>;
|
|
41
|
+
revertTransaction(state: DustCoreWallet, transaction: UnprovenTransaction | TTransaction): Either.Either<DustCoreWallet, WalletError.WalletError>;
|
|
50
42
|
}
|
package/dist/Transacting.js
CHANGED
|
@@ -1,7 +1,19 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
// This file is part of MIDNIGHT-WALLET-SDK.
|
|
2
|
+
// Copyright (C) 2025 Midnight Foundation
|
|
3
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
// You may not use this file except in compliance with the License.
|
|
6
|
+
// You may obtain a copy of the License at
|
|
7
|
+
// http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
// Unless required by applicable law or agreed to in writing, software
|
|
9
|
+
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
10
|
+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
11
|
+
// See the License for the specific language governing permissions and
|
|
12
|
+
// limitations under the License.
|
|
13
|
+
import { Either, pipe, BigInt as BigIntOps, Iterable as IterableOps, Option } from 'effect';
|
|
14
|
+
import { DustActions, DustRegistration, Intent, SignatureEnabled, Transaction, UnshieldedOffer, addressFromKey, nativeToken, } from '@midnight-ntwrk/ledger-v7';
|
|
3
15
|
import { MidnightBech32m, DustAddress } from '@midnight-ntwrk/wallet-sdk-address-format';
|
|
4
|
-
import {
|
|
16
|
+
import { WalletError } from '@midnight-ntwrk/wallet-sdk-shielded/v1';
|
|
5
17
|
import { LedgerOps } from '@midnight-ntwrk/wallet-sdk-utilities';
|
|
6
18
|
import { BindingMarker, ProofMarker, SignatureMarker } from './Utils.js';
|
|
7
19
|
export const makeDefaultTransactingCapability = (config, getContext) => {
|
|
@@ -24,24 +36,48 @@ export class TransactingCapabilityImplementation {
|
|
|
24
36
|
this.getKeys = getKeys;
|
|
25
37
|
}
|
|
26
38
|
createDustGenerationTransaction(currentTime, ttl, nightUtxos, nightVerifyingKey, dustReceiverAddress) {
|
|
39
|
+
const makeOffer = (utxos) => {
|
|
40
|
+
if (utxos.length === 0) {
|
|
41
|
+
return Option.none();
|
|
42
|
+
}
|
|
43
|
+
const totalValue = pipe(utxos, IterableOps.map((coin) => coin.utxo.value), BigIntOps.sumAll);
|
|
44
|
+
const inputs = utxos.map(({ utxo }) => ({
|
|
45
|
+
...utxo,
|
|
46
|
+
owner: nightVerifyingKey,
|
|
47
|
+
}));
|
|
48
|
+
const output = {
|
|
49
|
+
owner: addressFromKey(nightVerifyingKey),
|
|
50
|
+
type: nativeToken().raw,
|
|
51
|
+
value: totalValue,
|
|
52
|
+
};
|
|
53
|
+
return Option.some(UnshieldedOffer.new(inputs, [output], []));
|
|
54
|
+
};
|
|
27
55
|
return Either.gen(this, function* () {
|
|
28
56
|
const receiver = dustReceiverAddress ? yield* this.#parseAddress(dustReceiverAddress) : undefined;
|
|
29
57
|
return yield* LedgerOps.ledgerTry(() => {
|
|
30
58
|
const network = this.networkId;
|
|
31
|
-
const
|
|
32
|
-
const totalDustValue =
|
|
33
|
-
const
|
|
34
|
-
|
|
35
|
-
owner: nightVerifyingKey,
|
|
36
|
-
}));
|
|
37
|
-
const outputs = inputs.map((input) => ({
|
|
38
|
-
owner: addressFromKey(nightVerifyingKey),
|
|
39
|
-
type: input.type,
|
|
40
|
-
value: input.value,
|
|
41
|
-
}));
|
|
42
|
-
intent.guaranteedUnshieldedOffer = UnshieldedOffer.new(inputs, outputs, []);
|
|
59
|
+
const splitResult = this.getCoins().splitNightUtxos(nightUtxos);
|
|
60
|
+
const totalDustValue = pipe(splitResult.guaranteed, IterableOps.map((coin) => coin.dust.generatedNow), BigIntOps.sumAll);
|
|
61
|
+
const maybeGuaranteedOffer = makeOffer(splitResult.guaranteed);
|
|
62
|
+
const maybeFallibleOffer = makeOffer(splitResult.fallible);
|
|
43
63
|
const dustRegistration = new DustRegistration(SignatureMarker.signature, nightVerifyingKey, receiver, dustReceiverAddress !== undefined ? totalDustValue : 0n);
|
|
44
|
-
|
|
64
|
+
const dustActions = new DustActions(SignatureMarker.signature, ProofMarker.preProof, currentTime, [], [dustRegistration]);
|
|
65
|
+
const intent = pipe(Intent.new(ttl), (intent) => Option.match(maybeGuaranteedOffer, {
|
|
66
|
+
onNone: () => intent,
|
|
67
|
+
onSome: (guaranteedOffer) => {
|
|
68
|
+
intent.guaranteedUnshieldedOffer = guaranteedOffer;
|
|
69
|
+
return intent;
|
|
70
|
+
},
|
|
71
|
+
}), (intent) => Option.match(maybeFallibleOffer, {
|
|
72
|
+
onNone: () => intent,
|
|
73
|
+
onSome: (fallibleOffer) => {
|
|
74
|
+
intent.fallibleUnshieldedOffer = fallibleOffer;
|
|
75
|
+
return intent;
|
|
76
|
+
},
|
|
77
|
+
}), (intent) => {
|
|
78
|
+
intent.dustActions = dustActions;
|
|
79
|
+
return intent;
|
|
80
|
+
});
|
|
45
81
|
return Transaction.fromParts(network, undefined, undefined, intent);
|
|
46
82
|
});
|
|
47
83
|
});
|
|
@@ -52,7 +88,7 @@ export class TransactingCapabilityImplementation {
|
|
|
52
88
|
if (!intent) {
|
|
53
89
|
return yield* Either.left(new WalletError.TransactingError({ message: 'No intent found in the transaction intents with segment = 1' }));
|
|
54
90
|
}
|
|
55
|
-
const { dustActions, guaranteedUnshieldedOffer } = intent;
|
|
91
|
+
const { dustActions, guaranteedUnshieldedOffer, fallibleUnshieldedOffer } = intent;
|
|
56
92
|
if (!dustActions) {
|
|
57
93
|
return yield* Either.left(new WalletError.TransactingError({ message: 'No dustActions found in intent' }));
|
|
58
94
|
}
|
|
@@ -76,13 +112,18 @@ export class TransactingCapabilityImplementation {
|
|
|
76
112
|
signatures.push(guaranteedUnshieldedOffer.signatures.at(i) ?? signatureData);
|
|
77
113
|
}
|
|
78
114
|
newIntent.guaranteedUnshieldedOffer = guaranteedUnshieldedOffer.addSignatures(signatures);
|
|
115
|
+
if (fallibleUnshieldedOffer) {
|
|
116
|
+
const inputsLen = fallibleUnshieldedOffer.inputs.length;
|
|
117
|
+
const signatures = [];
|
|
118
|
+
for (let i = 0; i < inputsLen; ++i) {
|
|
119
|
+
signatures.push(fallibleUnshieldedOffer.signatures.at(i) ?? signatureData);
|
|
120
|
+
}
|
|
121
|
+
newIntent.fallibleUnshieldedOffer = fallibleUnshieldedOffer.addSignatures(signatures);
|
|
122
|
+
}
|
|
79
123
|
// make a copy of transaction to avoid mutation
|
|
80
124
|
const newTransaction = Transaction.deserialize(signature.instance, ProofMarker.preProof, BindingMarker.preBinding, transaction.serialize());
|
|
81
125
|
newTransaction.intents = newTransaction.intents.set(1, newIntent);
|
|
82
|
-
return
|
|
83
|
-
type: ProvingRecipe.TRANSACTION_TO_PROVE,
|
|
84
|
-
transaction: newTransaction,
|
|
85
|
-
};
|
|
126
|
+
return newTransaction;
|
|
86
127
|
});
|
|
87
128
|
});
|
|
88
129
|
}
|
|
@@ -96,9 +137,10 @@ export class TransactingCapabilityImplementation {
|
|
|
96
137
|
.find(([tt, _]) => tt.tag === 'dust');
|
|
97
138
|
return dustImbalance ? -dustImbalance[1] : totalFee;
|
|
98
139
|
}
|
|
99
|
-
|
|
140
|
+
balanceTransactions(secretKey, state, transactions, ttl, currentTime, ledgerParams) {
|
|
100
141
|
const network = this.networkId;
|
|
101
|
-
const feeLeft =
|
|
142
|
+
const feeLeft = transactions.reduce((total, transaction) => total +
|
|
143
|
+
TransactingCapabilityImplementation.feeImbalance(transaction, this.calculateFee(transaction, ledgerParams)), 0n);
|
|
102
144
|
const dustTokens = this.getCoins().getAvailableCoinsWithGeneratedDust(state, currentTime);
|
|
103
145
|
const selectedTokens = this.getCoinSelection()(dustTokens, feeLeft);
|
|
104
146
|
if (!selectedTokens.length) {
|
|
@@ -107,8 +149,7 @@ export class TransactingCapabilityImplementation {
|
|
|
107
149
|
const totalFeeInSelected = selectedTokens.reduce((total, { value }) => total + value, 0n);
|
|
108
150
|
const feeDiff = totalFeeInSelected - feeLeft;
|
|
109
151
|
if (feeDiff < 0n) {
|
|
110
|
-
|
|
111
|
-
return Either.left(new WalletError.TransactingError({ message: 'Error in tokens selection algorithm' }));
|
|
152
|
+
return Either.left(new WalletError.TransactingError({ message: 'Not enough Dust generated to pay the fee' }));
|
|
112
153
|
}
|
|
113
154
|
// reduce the largest token's value by `feeDiff`
|
|
114
155
|
const tokensWithFeeToTake = selectedTokens.toSorted((a, b) => Number(b.value - a.value));
|
|
@@ -122,49 +163,22 @@ export class TransactingCapabilityImplementation {
|
|
|
122
163
|
return LedgerOps.ledgerTry(() => {
|
|
123
164
|
const intent = Intent.new(ttl);
|
|
124
165
|
const [spends, updatedState] = state.spendCoins(secretKey, tokensWithFeeToTake, currentTime);
|
|
125
|
-
intent.dustActions = new DustActions(SignatureMarker.signature, ProofMarker.preProof, currentTime, spends, []);
|
|
166
|
+
intent.dustActions = new DustActions(SignatureMarker.signature, ProofMarker.preProof, currentTime, [...spends], []);
|
|
126
167
|
const feeTransaction = Transaction.fromPartsRandomized(network, undefined, undefined, intent);
|
|
127
|
-
return
|
|
128
|
-
newState: updatedState,
|
|
129
|
-
recipe: {
|
|
130
|
-
type: ProvingRecipe.TRANSACTION_TO_PROVE,
|
|
131
|
-
transaction: transaction.merge(feeTransaction),
|
|
132
|
-
},
|
|
133
|
-
};
|
|
168
|
+
return [feeTransaction, updatedState];
|
|
134
169
|
});
|
|
135
170
|
}
|
|
136
|
-
|
|
171
|
+
revertTransaction(state, transaction) {
|
|
137
172
|
return Either.try({
|
|
138
|
-
try: () => state.revertTransaction(
|
|
173
|
+
try: () => state.revertTransaction(transaction),
|
|
139
174
|
catch: (err) => {
|
|
140
175
|
return new WalletError.OtherWalletError({
|
|
141
|
-
message: `Error while reverting transaction ${
|
|
176
|
+
message: `Error while reverting transaction ${transaction.identifiers().at(0)}`,
|
|
142
177
|
cause: err,
|
|
143
178
|
});
|
|
144
179
|
},
|
|
145
180
|
});
|
|
146
181
|
}
|
|
147
|
-
revertRecipe(state, recipe) {
|
|
148
|
-
const doRevert = (tx) => {
|
|
149
|
-
return Either.try({
|
|
150
|
-
try: () => state.revertTransaction(tx),
|
|
151
|
-
catch: (err) => {
|
|
152
|
-
return new WalletError.OtherWalletError({
|
|
153
|
-
message: `Error while reverting transaction ${tx.identifiers().at(0)}`,
|
|
154
|
-
cause: err,
|
|
155
|
-
});
|
|
156
|
-
},
|
|
157
|
-
});
|
|
158
|
-
};
|
|
159
|
-
switch (recipe.type) {
|
|
160
|
-
case ProvingRecipe.TRANSACTION_TO_PROVE:
|
|
161
|
-
return doRevert(recipe.transaction);
|
|
162
|
-
case ProvingRecipe.BALANCE_TRANSACTION_TO_PROVE:
|
|
163
|
-
return doRevert(recipe.transactionToProve);
|
|
164
|
-
case ProvingRecipe.NOTHING_TO_PROVE:
|
|
165
|
-
return Either.right(state);
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
182
|
#parseAddress(addr) {
|
|
169
183
|
return Either.try({
|
|
170
184
|
try: () => {
|
package/dist/Utils.js
CHANGED
|
@@ -1,3 +1,15 @@
|
|
|
1
|
+
// This file is part of MIDNIGHT-WALLET-SDK.
|
|
2
|
+
// Copyright (C) 2025 Midnight Foundation
|
|
3
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
// You may not use this file except in compliance with the License.
|
|
6
|
+
// You may obtain a copy of the License at
|
|
7
|
+
// http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
// Unless required by applicable law or agreed to in writing, software
|
|
9
|
+
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
10
|
+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
11
|
+
// See the License for the specific language governing permissions and
|
|
12
|
+
// limitations under the License.
|
|
1
13
|
export const SignatureMarker = {
|
|
2
14
|
signature: 'signature',
|
|
3
15
|
signatureErased: 'signature-erased',
|
package/dist/V1Builder.d.ts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { Types, Either } from 'effect';
|
|
2
|
-
import { DustSecretKey, FinalizedTransaction } from '@midnight-ntwrk/ledger-
|
|
2
|
+
import { DustSecretKey, FinalizedTransaction } from '@midnight-ntwrk/ledger-v7';
|
|
3
3
|
import { VariantBuilder, Variant } from '@midnight-ntwrk/wallet-sdk-runtime/abstractions';
|
|
4
4
|
import { Proving, WalletError } from '@midnight-ntwrk/wallet-sdk-shielded/v1';
|
|
5
5
|
import { SyncService, SyncCapability, DefaultSyncConfiguration, WalletSyncUpdate } from './Sync.js';
|
|
6
6
|
import { RunningV1Variant, V1Tag } from './RunningV1Variant.js';
|
|
7
7
|
import { DustCoreWallet } from './DustCoreWallet.js';
|
|
8
8
|
import { KeysCapability } from './Keys.js';
|
|
9
|
-
import { CoinsAndBalancesCapability, CoinSelection } from './CoinsAndBalances.js';
|
|
9
|
+
import { CoinsAndBalancesCapability, CoinSelection, DefaultCoinsAndBalancesContext } from './CoinsAndBalances.js';
|
|
10
10
|
import { DefaultTransactingConfiguration, DefaultTransactingContext, TransactingCapability } from './Transacting.js';
|
|
11
11
|
import { NetworkId } from './types/ledger.js';
|
|
12
12
|
import { DefaultSubmissionConfiguration, SubmissionService } from './Submission.js';
|
|
@@ -46,7 +46,7 @@ export declare class V1Builder<TConfig extends BaseV1Configuration = BaseV1Confi
|
|
|
46
46
|
withCoinSelectionDefaults(): V1Builder<TConfig, TContext, TSerialized, TSyncUpdate, TTransaction, TStartAux>;
|
|
47
47
|
withProving<TProvingConfig, TProvingContext extends Partial<RunningV1Variant.AnyContext>>(provingService: (config: TProvingConfig, getContext: () => TProvingContext) => Proving.ProvingService<TTransaction>): V1Builder<TConfig & TProvingConfig, TContext & TProvingContext, TSerialized, TSyncUpdate, TTransaction, TStartAux>;
|
|
48
48
|
withProvingDefaults(this: V1Builder<TConfig, TContext, TSerialized, TSyncUpdate, FinalizedTransaction, TStartAux>): V1Builder<TConfig & Proving.DefaultProvingConfiguration, TContext, TSerialized, TSyncUpdate, FinalizedTransaction, TStartAux>;
|
|
49
|
-
withCoinsAndBalancesDefaults(): V1Builder<TConfig, TContext, TSerialized, TSyncUpdate, TTransaction, TStartAux>;
|
|
49
|
+
withCoinsAndBalancesDefaults(): V1Builder<TConfig, TContext & DefaultCoinsAndBalancesContext, TSerialized, TSyncUpdate, TTransaction, TStartAux>;
|
|
50
50
|
withCoinsAndBalances<TBalancesConfig, TBalancesContext extends Partial<RunningV1Variant.AnyContext>>(coinsAndBalancesCapability: (configuration: TBalancesConfig, getContext: () => TBalancesContext) => CoinsAndBalancesCapability<DustCoreWallet>): V1Builder<TConfig & TBalancesConfig, TContext & TBalancesContext, TSerialized, TSyncUpdate, TTransaction, TStartAux>;
|
|
51
51
|
withKeysDefaults(): V1Builder<TConfig, TContext, TSerialized, TSyncUpdate, TTransaction, TStartAux>;
|
|
52
52
|
withKeys<TKeysConfig, TKeysContext extends Partial<RunningV1Variant.AnyContext>>(keysCapability: (configuration: TKeysConfig, getContext: () => TKeysContext) => KeysCapability<DustCoreWallet>): V1Builder<TConfig & TKeysConfig, TContext & TKeysContext, TSerialized, TSyncUpdate, TTransaction, TStartAux>;
|
package/dist/V1Builder.js
CHANGED
|
@@ -1,3 +1,15 @@
|
|
|
1
|
+
// This file is part of MIDNIGHT-WALLET-SDK.
|
|
2
|
+
// Copyright (C) 2025 Midnight Foundation
|
|
3
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
// You may not use this file except in compliance with the License.
|
|
6
|
+
// You may obtain a copy of the License at
|
|
7
|
+
// http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
// Unless required by applicable law or agreed to in writing, software
|
|
9
|
+
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
10
|
+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
11
|
+
// See the License for the specific language governing permissions and
|
|
12
|
+
// limitations under the License.
|
|
1
13
|
import { Effect, Scope } from 'effect';
|
|
2
14
|
import { Proving } from '@midnight-ntwrk/wallet-sdk-shielded/v1';
|
|
3
15
|
import { makeDefaultSyncCapability, makeDefaultSyncService, } from './Sync.js';
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -1,3 +1,15 @@
|
|
|
1
|
+
// This file is part of MIDNIGHT-WALLET-SDK.
|
|
2
|
+
// Copyright (C) 2025 Midnight Foundation
|
|
3
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
// You may not use this file except in compliance with the License.
|
|
6
|
+
// You may obtain a copy of the License at
|
|
7
|
+
// http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
// Unless required by applicable law or agreed to in writing, software
|
|
9
|
+
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
10
|
+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
11
|
+
// See the License for the specific language governing permissions and
|
|
12
|
+
// limitations under the License.
|
|
1
13
|
export * from './DustCoreWallet.js';
|
|
2
14
|
export * from './DustWallet.js';
|
|
3
15
|
export * as Keys from './Keys.js';
|
|
@@ -7,3 +19,4 @@ export * as Transacting from './Transacting.js';
|
|
|
7
19
|
export * from './RunningV1Variant.js';
|
|
8
20
|
export * from './V1Builder.js';
|
|
9
21
|
export * from './types/index.js';
|
|
22
|
+
export * as CoinsAndBalances from './CoinsAndBalances.js';
|
package/dist/types/Dust.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { DustInitialNonce, DustNullifier, DustNonce, DustPublicKey, Utxo } from '@midnight-ntwrk/ledger-
|
|
1
|
+
import { DustInitialNonce, DustNullifier, DustNonce, DustPublicKey, Utxo } from '@midnight-ntwrk/ledger-v7';
|
|
2
2
|
export type DustToken = {
|
|
3
3
|
initialValue: bigint;
|
|
4
4
|
owner: DustPublicKey;
|
|
@@ -11,8 +11,10 @@ export type DustToken = {
|
|
|
11
11
|
export type DustTokenWithNullifier = DustToken & {
|
|
12
12
|
nullifier: DustNullifier;
|
|
13
13
|
};
|
|
14
|
-
export type DustTokenFullInfo = {
|
|
14
|
+
export type DustTokenFullInfo = DustGenerationDetails & {
|
|
15
15
|
token: DustToken;
|
|
16
|
+
};
|
|
17
|
+
export type DustGenerationDetails = {
|
|
16
18
|
dtime: Date | undefined;
|
|
17
19
|
maxCap: bigint;
|
|
18
20
|
maxCapReachedAt: Date;
|
package/dist/types/index.js
CHANGED
|
@@ -1,3 +1,15 @@
|
|
|
1
|
+
// This file is part of MIDNIGHT-WALLET-SDK.
|
|
2
|
+
// Copyright (C) 2025 Midnight Foundation
|
|
3
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
// You may not use this file except in compliance with the License.
|
|
6
|
+
// You may obtain a copy of the License at
|
|
7
|
+
// http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
// Unless required by applicable law or agreed to in writing, software
|
|
9
|
+
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
10
|
+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
11
|
+
// See the License for the specific language governing permissions and
|
|
12
|
+
// limitations under the License.
|
|
1
13
|
export * from './Dust.js';
|
|
2
14
|
export * from './ledger.js';
|
|
3
15
|
export * from './transaction.js';
|
package/dist/types/ledger.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import * as ledger from '@midnight-ntwrk/ledger-
|
|
2
|
-
export type AnyTransaction = ledger.UnprovenTransaction | ledger.FinalizedTransaction | ledger.ProofErasedTransaction
|
|
1
|
+
import * as ledger from '@midnight-ntwrk/ledger-v7';
|
|
2
|
+
export type AnyTransaction = ledger.UnprovenTransaction | ledger.FinalizedTransaction | ledger.ProofErasedTransaction | ledger.Transaction<ledger.SignatureEnabled, ledger.Proof, ledger.PreBinding>;
|
|
3
3
|
export type UnprovenDustSpend = ledger.DustSpend<ledger.PreProof>;
|
|
4
4
|
export type NetworkId = string;
|
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@midnight-ntwrk/wallet-sdk-dust-wallet",
|
|
3
|
-
"version": "1.0.0
|
|
3
|
+
"version": "1.0.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
7
|
-
"author": "
|
|
7
|
+
"author": "Midnight Foundation",
|
|
8
8
|
"license": "Apache-2.0",
|
|
9
9
|
"publishConfig": {
|
|
10
10
|
"registry": "https://npm.pkg.github.com/"
|
|
@@ -23,24 +23,25 @@
|
|
|
23
23
|
}
|
|
24
24
|
},
|
|
25
25
|
"dependencies": {
|
|
26
|
-
"@midnight-ntwrk/ledger-
|
|
27
|
-
"@midnight-ntwrk/wallet-sdk-abstractions": "1.0.0
|
|
28
|
-
"@midnight-ntwrk/wallet-sdk-address-format": "3.0.0
|
|
29
|
-
"@midnight-ntwrk/wallet-sdk-capabilities": "3.0.0
|
|
30
|
-
"@midnight-ntwrk/wallet-sdk-hd": "3.0.0
|
|
31
|
-
"@midnight-ntwrk/wallet-sdk-indexer-client": "1.0.0
|
|
32
|
-
"@midnight-ntwrk/wallet-sdk-node-client": "1.0.0
|
|
33
|
-
"@midnight-ntwrk/wallet-sdk-prover-client": "1.0.0
|
|
34
|
-
"@midnight-ntwrk/wallet-sdk-shielded": "1.0.0
|
|
35
|
-
"@midnight-ntwrk/wallet-sdk-utilities": "1.0.0
|
|
36
|
-
"effect": "^3.
|
|
26
|
+
"@midnight-ntwrk/ledger-v7": "7.0.0",
|
|
27
|
+
"@midnight-ntwrk/wallet-sdk-abstractions": "1.0.0",
|
|
28
|
+
"@midnight-ntwrk/wallet-sdk-address-format": "3.0.0",
|
|
29
|
+
"@midnight-ntwrk/wallet-sdk-capabilities": "3.0.0",
|
|
30
|
+
"@midnight-ntwrk/wallet-sdk-hd": "3.0.0",
|
|
31
|
+
"@midnight-ntwrk/wallet-sdk-indexer-client": "1.0.0",
|
|
32
|
+
"@midnight-ntwrk/wallet-sdk-node-client": "1.0.0",
|
|
33
|
+
"@midnight-ntwrk/wallet-sdk-prover-client": "1.0.0",
|
|
34
|
+
"@midnight-ntwrk/wallet-sdk-shielded": "1.0.0",
|
|
35
|
+
"@midnight-ntwrk/wallet-sdk-utilities": "1.0.0",
|
|
36
|
+
"effect": "^3.19.14",
|
|
37
37
|
"rxjs": "^7.5"
|
|
38
38
|
},
|
|
39
39
|
"scripts": {
|
|
40
40
|
"typecheck": "tsc -b ./tsconfig.json --noEmit",
|
|
41
41
|
"test": "vitest run",
|
|
42
42
|
"lint": "eslint --max-warnings 0",
|
|
43
|
-
"format": "prettier --write \"**/*.{ts,js,json,yaml,yml}\"",
|
|
43
|
+
"format": "prettier --write \"**/*.{ts,js,json,yaml,yml,md}\"",
|
|
44
|
+
"format:check": "prettier --check \"**/*.{ts,js,json,yaml,yml,md}\"",
|
|
44
45
|
"dist": "tsc -b ./tsconfig.build.json",
|
|
45
46
|
"dist:publish": "tsc -b ./tsconfig.publish.json",
|
|
46
47
|
"clean": "rimraf --glob dist 'tsconfig.*.tsbuildinfo' && date +%s > .clean-timestamp",
|
|
@@ -49,10 +50,11 @@
|
|
|
49
50
|
"devDependencies": {
|
|
50
51
|
"@types/node": "22.17.0",
|
|
51
52
|
"eslint": "^9.37.0",
|
|
53
|
+
"prettier": "^3.7.0",
|
|
52
54
|
"publint": "~0.3.14",
|
|
53
55
|
"rimraf": "^6.0.1",
|
|
54
|
-
"testcontainers": "^11.0
|
|
56
|
+
"testcontainers": "^11.10.0",
|
|
55
57
|
"typescript": "^5.9.3",
|
|
56
|
-
"vitest": "^
|
|
58
|
+
"vitest": "^4.0.16"
|
|
57
59
|
}
|
|
58
60
|
}
|