@midnight-ntwrk/wallet-sdk-dust-wallet 1.0.0-beta.10

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.
@@ -0,0 +1,195 @@
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 } from 'effect';
14
+ import { DustActions, DustRegistration, Intent, SignatureEnabled, Transaction, UnshieldedOffer, addressFromKey, } from '@midnight-ntwrk/ledger-v6';
15
+ import { MidnightBech32m, DustAddress } from '@midnight-ntwrk/wallet-sdk-address-format';
16
+ import { ProvingRecipe, WalletError } from '@midnight-ntwrk/wallet-sdk-shielded/v1';
17
+ import { LedgerOps } from '@midnight-ntwrk/wallet-sdk-utilities';
18
+ import { BindingMarker, ProofMarker, SignatureMarker } from './Utils.js';
19
+ export const makeDefaultTransactingCapability = (config, getContext) => {
20
+ return new TransactingCapabilityImplementation(config.networkId, config.costParameters, () => getContext().coinSelection, () => getContext().coinsAndBalancesCapability, () => getContext().keysCapability);
21
+ };
22
+ export const makeSimulatorTransactingCapability = (config, getContext) => {
23
+ return new TransactingCapabilityImplementation(config.networkId, config.costParameters, () => getContext().coinSelection, () => getContext().coinsAndBalancesCapability, () => getContext().keysCapability);
24
+ };
25
+ export class TransactingCapabilityImplementation {
26
+ networkId;
27
+ costParams;
28
+ getCoinSelection;
29
+ getCoins;
30
+ getKeys;
31
+ constructor(networkId, costParams, getCoinSelection, getCoins, getKeys) {
32
+ this.getCoins = getCoins;
33
+ this.networkId = networkId;
34
+ this.costParams = costParams;
35
+ this.getCoinSelection = getCoinSelection;
36
+ this.getKeys = getKeys;
37
+ }
38
+ createDustGenerationTransaction(currentTime, ttl, nightUtxos, nightVerifyingKey, dustReceiverAddress) {
39
+ return Either.gen(this, function* () {
40
+ const receiver = dustReceiverAddress ? yield* this.#parseAddress(dustReceiverAddress) : undefined;
41
+ return yield* LedgerOps.ledgerTry(() => {
42
+ const network = this.networkId;
43
+ const intent = Intent.new(ttl);
44
+ const totalDustValue = nightUtxos.reduce((total, { value }) => total + value, 0n);
45
+ const inputs = nightUtxos.map(({ token: utxo }) => ({
46
+ ...utxo,
47
+ owner: nightVerifyingKey,
48
+ }));
49
+ const outputs = inputs.map((input) => ({
50
+ owner: addressFromKey(nightVerifyingKey),
51
+ type: input.type,
52
+ value: input.value,
53
+ }));
54
+ intent.guaranteedUnshieldedOffer = UnshieldedOffer.new(inputs, outputs, []);
55
+ const dustRegistration = new DustRegistration(SignatureMarker.signature, nightVerifyingKey, receiver, dustReceiverAddress !== undefined ? totalDustValue : 0n);
56
+ intent.dustActions = new DustActions(SignatureMarker.signature, ProofMarker.preProof, currentTime, [], [dustRegistration]);
57
+ return Transaction.fromParts(network, undefined, undefined, intent);
58
+ });
59
+ });
60
+ }
61
+ addDustGenerationSignature(transaction, signatureData) {
62
+ return Either.gen(this, function* () {
63
+ const intent = transaction.intents?.get(1);
64
+ if (!intent) {
65
+ return yield* Either.left(new WalletError.TransactingError({ message: 'No intent found in the transaction intents with segment = 1' }));
66
+ }
67
+ const { dustActions, guaranteedUnshieldedOffer } = intent;
68
+ if (!dustActions) {
69
+ return yield* Either.left(new WalletError.TransactingError({ message: 'No dustActions found in intent' }));
70
+ }
71
+ if (!guaranteedUnshieldedOffer) {
72
+ return yield* Either.left(new WalletError.TransactingError({ message: 'No guaranteedUnshieldedOffer found in intent' }));
73
+ }
74
+ const [registration, ...restRegistrations] = dustActions.registrations;
75
+ if (!registration) {
76
+ return yield* Either.left(new WalletError.TransactingError({ message: 'No registrations found in dustActions' }));
77
+ }
78
+ return yield* LedgerOps.ledgerTry(() => {
79
+ const signature = new SignatureEnabled(signatureData);
80
+ const registrationWithSignature = new DustRegistration(signature.instance, registration.nightKey, registration.dustAddress, registration.allowFeePayment, signature);
81
+ const newDustActions = new DustActions(signature.instance, ProofMarker.preProof, dustActions.ctime, dustActions.spends, [registrationWithSignature, ...restRegistrations]);
82
+ // make a copy of intent to avoid mutation
83
+ const newIntent = Intent.deserialize(signature.instance, ProofMarker.preProof, BindingMarker.preBinding, intent.serialize());
84
+ newIntent.dustActions = newDustActions;
85
+ const inputsLen = guaranteedUnshieldedOffer.inputs.length;
86
+ const signatures = [];
87
+ for (let i = 0; i < inputsLen; ++i) {
88
+ signatures.push(guaranteedUnshieldedOffer.signatures.at(i) ?? signatureData);
89
+ }
90
+ newIntent.guaranteedUnshieldedOffer = guaranteedUnshieldedOffer.addSignatures(signatures);
91
+ // make a copy of transaction to avoid mutation
92
+ const newTransaction = Transaction.deserialize(signature.instance, ProofMarker.preProof, BindingMarker.preBinding, transaction.serialize());
93
+ newTransaction.intents = newTransaction.intents.set(1, newIntent);
94
+ return {
95
+ type: ProvingRecipe.TRANSACTION_TO_PROVE,
96
+ transaction: newTransaction,
97
+ };
98
+ });
99
+ });
100
+ }
101
+ calculateFee(transaction, ledgerParams) {
102
+ return (transaction.feesWithMargin(ledgerParams, this.costParams.feeBlocksMargin) + this.costParams.additionalFeeOverhead);
103
+ }
104
+ static feeImbalance(transaction, totalFee) {
105
+ const dustImbalance = transaction
106
+ .imbalances(0, totalFee)
107
+ .entries()
108
+ .find(([tt, _]) => tt.tag === 'dust');
109
+ return dustImbalance ? -dustImbalance[1] : totalFee;
110
+ }
111
+ addFeePayment(secretKey, state, transaction, currentTime, ttl, ledgerParams) {
112
+ const network = this.networkId;
113
+ const feeLeft = TransactingCapabilityImplementation.feeImbalance(transaction, this.calculateFee(transaction, ledgerParams));
114
+ const dustTokens = this.getCoins().getAvailableCoinsWithGeneratedDust(state, currentTime);
115
+ const selectedTokens = this.getCoinSelection()(dustTokens, feeLeft);
116
+ if (!selectedTokens.length) {
117
+ return Either.left(new WalletError.TransactingError({ message: 'No dust tokens found in the wallet state' }));
118
+ }
119
+ const totalFeeInSelected = selectedTokens.reduce((total, { value }) => total + value, 0n);
120
+ const feeDiff = totalFeeInSelected - feeLeft;
121
+ if (feeDiff < 0n) {
122
+ // A sanity-check, should never happen
123
+ return Either.left(new WalletError.TransactingError({ message: 'Error in tokens selection algorithm' }));
124
+ }
125
+ // reduce the largest token's value by `feeDiff`
126
+ const tokensWithFeeToTake = selectedTokens.toSorted((a, b) => Number(b.value - a.value));
127
+ if (feeDiff > 0n) {
128
+ const highestByValue = tokensWithFeeToTake[0];
129
+ tokensWithFeeToTake[0] = {
130
+ value: highestByValue.value - feeDiff,
131
+ token: highestByValue.token,
132
+ };
133
+ }
134
+ return LedgerOps.ledgerTry(() => {
135
+ const intent = Intent.new(ttl);
136
+ const [spends, updatedState] = state.spendCoins(secretKey, tokensWithFeeToTake, currentTime);
137
+ intent.dustActions = new DustActions(SignatureMarker.signature, ProofMarker.preProof, currentTime, spends, []);
138
+ const feeTransaction = Transaction.fromPartsRandomized(network, undefined, undefined, intent);
139
+ return {
140
+ newState: updatedState,
141
+ recipe: {
142
+ type: ProvingRecipe.TRANSACTION_TO_PROVE,
143
+ transaction: transaction.merge(feeTransaction),
144
+ },
145
+ };
146
+ });
147
+ }
148
+ revert(state, 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
+ revertRecipe(state, recipe) {
160
+ const doRevert = (tx) => {
161
+ return Either.try({
162
+ try: () => state.revertTransaction(tx),
163
+ catch: (err) => {
164
+ return new WalletError.OtherWalletError({
165
+ message: `Error while reverting transaction ${tx.identifiers().at(0)}`,
166
+ cause: err,
167
+ });
168
+ },
169
+ });
170
+ };
171
+ switch (recipe.type) {
172
+ case ProvingRecipe.TRANSACTION_TO_PROVE:
173
+ return doRevert(recipe.transaction);
174
+ case ProvingRecipe.BALANCE_TRANSACTION_TO_PROVE:
175
+ return doRevert(recipe.transactionToProve);
176
+ case ProvingRecipe.NOTHING_TO_PROVE:
177
+ return Either.right(state);
178
+ }
179
+ }
180
+ #parseAddress(addr) {
181
+ return Either.try({
182
+ try: () => {
183
+ const repr = MidnightBech32m.parse(addr);
184
+ return DustAddress.codec.decode(this.networkId, repr).data;
185
+ },
186
+ catch: (err) => {
187
+ return new WalletError.AddressError({
188
+ message: `Address parsing error: ${addr}`,
189
+ originalAddress: addr,
190
+ cause: err,
191
+ });
192
+ },
193
+ });
194
+ }
195
+ }
@@ -0,0 +1,14 @@
1
+ export declare const SignatureMarker: {
2
+ readonly signature: "signature";
3
+ readonly signatureErased: "signature-erased";
4
+ };
5
+ export declare const ProofMarker: {
6
+ readonly proof: "proof";
7
+ readonly preProof: "pre-proof";
8
+ readonly noProof: "no-proof";
9
+ };
10
+ export declare const BindingMarker: {
11
+ readonly binding: "binding";
12
+ readonly preBinding: "pre-binding";
13
+ readonly noBinding: "no-binding";
14
+ };
package/dist/Utils.js ADDED
@@ -0,0 +1,26 @@
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
+ export const SignatureMarker = {
14
+ signature: 'signature',
15
+ signatureErased: 'signature-erased',
16
+ };
17
+ export const ProofMarker = {
18
+ proof: 'proof',
19
+ preProof: 'pre-proof',
20
+ noProof: 'no-proof',
21
+ };
22
+ export const BindingMarker = {
23
+ binding: 'binding',
24
+ preBinding: 'pre-binding',
25
+ noBinding: 'no-binding',
26
+ };
@@ -0,0 +1,100 @@
1
+ import { Types, Either } from 'effect';
2
+ import { DustSecretKey, FinalizedTransaction } from '@midnight-ntwrk/ledger-v6';
3
+ import { VariantBuilder, Variant } from '@midnight-ntwrk/wallet-sdk-runtime/abstractions';
4
+ import { Proving, WalletError } from '@midnight-ntwrk/wallet-sdk-shielded/v1';
5
+ import { SyncService, SyncCapability, DefaultSyncConfiguration, WalletSyncUpdate } from './Sync.js';
6
+ import { RunningV1Variant, V1Tag } from './RunningV1Variant.js';
7
+ import { DustCoreWallet } from './DustCoreWallet.js';
8
+ import { KeysCapability } from './Keys.js';
9
+ import { CoinsAndBalancesCapability, CoinSelection } from './CoinsAndBalances.js';
10
+ import { DefaultTransactingConfiguration, DefaultTransactingContext, TransactingCapability } from './Transacting.js';
11
+ import { NetworkId } from './types/ledger.js';
12
+ import { DefaultSubmissionConfiguration, SubmissionService } from './Submission.js';
13
+ import { DustToken } from './types/Dust.js';
14
+ import { SerializationCapability } from './Serialization.js';
15
+ import { TotalCostParameters } from './types/transaction.js';
16
+ export type BaseV1Configuration = {
17
+ networkId: NetworkId;
18
+ costParameters: TotalCostParameters;
19
+ };
20
+ export type DefaultV1Configuration = BaseV1Configuration;
21
+ declare const V1BuilderSymbol: {
22
+ readonly typeId: unique symbol;
23
+ };
24
+ export type DefaultV1Variant = V1Variant<string, WalletSyncUpdate, FinalizedTransaction, DustSecretKey>;
25
+ export type V1Variant<TSerialized, TSyncUpdate, TTransaction, TAuxData> = Variant.Variant<typeof V1Tag, DustCoreWallet, DustCoreWallet, // null,
26
+ RunningV1Variant<TSerialized, TSyncUpdate, TTransaction, TAuxData>> & {
27
+ deserializeState: (serialized: TSerialized) => Either.Either<DustCoreWallet, WalletError.WalletError>;
28
+ coinsAndBalances: CoinsAndBalancesCapability<DustCoreWallet>;
29
+ keys: KeysCapability<DustCoreWallet>;
30
+ serialization: SerializationCapability<DustCoreWallet, null, TSerialized>;
31
+ };
32
+ export type DefaultV1Builder = V1Builder<DefaultV1Configuration, RunningV1Variant.Context<string, WalletSyncUpdate, FinalizedTransaction, DustSecretKey>, string, WalletSyncUpdate, FinalizedTransaction>;
33
+ export declare class V1Builder<TConfig extends BaseV1Configuration = BaseV1Configuration, TContext extends Partial<RunningV1Variant.AnyContext> = object, TSerialized = never, TSyncUpdate = never, TTransaction = never, TStartAux extends object = object> implements VariantBuilder.VariantBuilder<V1Variant<TSerialized, TSyncUpdate, TTransaction, TStartAux>, TConfig> {
34
+ #private;
35
+ constructor(buildState?: V1Builder.PartialBuildState<TConfig, TContext, TSerialized, TSyncUpdate, TTransaction, TStartAux>);
36
+ withDefaults(): DefaultV1Builder;
37
+ withTransactionType<Transaction>(): V1Builder<TConfig, TContext, TSerialized, TSyncUpdate, Transaction, TStartAux>;
38
+ withDefaultTransactionType(): V1Builder<TConfig, TContext, TSerialized, TSyncUpdate, FinalizedTransaction, TStartAux>;
39
+ withSyncDefaults(): V1Builder<TConfig & DefaultSyncConfiguration, TContext, TSerialized, WalletSyncUpdate, TTransaction, DustSecretKey>;
40
+ withSync<TSyncConfig, TSyncContext extends Partial<RunningV1Variant.AnyContext>, TSyncUpdate, TStartAux extends object>(syncService: (configuration: TSyncConfig, getContext: () => TSyncContext) => SyncService<DustCoreWallet, TStartAux, TSyncUpdate>, syncCapability: (configuration: TSyncConfig, getContext: () => TSyncContext) => SyncCapability<DustCoreWallet, TSyncUpdate>): V1Builder<TConfig & TSyncConfig, TContext & TSyncContext, TSerialized, TSyncUpdate, TTransaction, TStartAux>;
41
+ withSerializationDefaults(): V1Builder<TConfig, TContext, string, TSyncUpdate, TTransaction, TStartAux>;
42
+ withSerialization<TSerializationConfig, TSerializationContext extends Partial<RunningV1Variant.AnyContext>, TSerialized>(serializationCapability: (configuration: TSerializationConfig, getContext: () => TSerializationContext) => SerializationCapability<DustCoreWallet, null, TSerialized>): V1Builder<TConfig & TSerializationConfig, TContext & TSerializationContext, TSerialized, TSyncUpdate, TTransaction, TStartAux>;
43
+ withTransactingDefaults(this: V1Builder<TConfig, TContext, TSerialized, TSyncUpdate, FinalizedTransaction, TStartAux>): V1Builder<TConfig & DefaultTransactingConfiguration, TContext & DefaultTransactingContext, TSerialized, TSyncUpdate, FinalizedTransaction, TStartAux>;
44
+ withTransacting<TTransactingConfig, TTransactingContext extends Partial<RunningV1Variant.AnyContext>>(transactingCapability: (config: TTransactingConfig, getContext: () => TTransactingContext) => TransactingCapability<DustSecretKey, DustCoreWallet, TTransaction>): V1Builder<TConfig & TTransactingConfig, TContext & TTransactingContext, TSerialized, TSyncUpdate, TTransaction, TStartAux>;
45
+ withCoinSelection<TCoinSelectionConfig, TCoinSelectionContext extends Partial<RunningV1Variant.AnyContext>>(coinSelection: (config: TCoinSelectionConfig, getContext: () => TCoinSelectionContext) => CoinSelection<DustToken>): V1Builder<TConfig & TCoinSelectionConfig, TContext & TCoinSelectionContext, TSerialized, TSyncUpdate, TTransaction, TStartAux>;
46
+ withCoinSelectionDefaults(): V1Builder<TConfig, TContext, TSerialized, TSyncUpdate, TTransaction, TStartAux>;
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
+ 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>;
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
+ withKeysDefaults(): V1Builder<TConfig, TContext, TSerialized, TSyncUpdate, TTransaction, TStartAux>;
52
+ withKeys<TKeysConfig, TKeysContext extends Partial<RunningV1Variant.AnyContext>>(keysCapability: (configuration: TKeysConfig, getContext: () => TKeysContext) => KeysCapability<DustCoreWallet>): V1Builder<TConfig & TKeysConfig, TContext & TKeysContext, TSerialized, TSyncUpdate, TTransaction, TStartAux>;
53
+ withSubmission<TSubmissionConfig, TSubmissionContext extends Partial<RunningV1Variant.AnyContext>>(submissionService: (config: TSubmissionConfig, getContext: () => TSubmissionContext) => SubmissionService<TTransaction>): V1Builder<TConfig & TSubmissionConfig, TContext & TSubmissionContext, TSerialized, TSyncUpdate, TTransaction, TStartAux>;
54
+ withSubmissionDefaults(this: V1Builder<TConfig, TContext, TSerialized, TSyncUpdate, FinalizedTransaction, TStartAux>): V1Builder<TConfig & DefaultSubmissionConfiguration, TContext, TSerialized, TSyncUpdate, FinalizedTransaction, TStartAux>;
55
+ build(this: V1Builder<TConfig, RunningV1Variant.Context<TSerialized, TSyncUpdate, TTransaction, TStartAux>, TSerialized, TSyncUpdate, TTransaction, TStartAux>, configuration: TConfig): V1Variant<TSerialized, TSyncUpdate, TTransaction, TStartAux>;
56
+ }
57
+ /** @internal */
58
+ declare namespace V1Builder {
59
+ type HasSync<TConfig, TContext, TSyncUpdate, TStartAux> = {
60
+ readonly syncService: (configuration: TConfig, getContext: () => TContext) => SyncService<DustCoreWallet, TStartAux, TSyncUpdate>;
61
+ readonly syncCapability: (configuration: TConfig, getContext: () => TContext) => SyncCapability<DustCoreWallet, TSyncUpdate>;
62
+ };
63
+ type HasTransacting<TConfig, TContext, TTransaction> = {
64
+ readonly transactingCapability: (configuration: TConfig, getContext: () => TContext) => TransactingCapability<DustSecretKey, DustCoreWallet, TTransaction>;
65
+ };
66
+ type HasSerialization<TConfig, TContext, TSerialized> = {
67
+ readonly serializationCapability: (configuration: TConfig, getContext: () => TContext) => SerializationCapability<DustCoreWallet, null, TSerialized>;
68
+ };
69
+ type HasCoinSelection<TConfig, TContext> = {
70
+ readonly coinSelection: (configuration: TConfig, getContext: () => TContext) => CoinSelection<DustToken>;
71
+ };
72
+ type HasProving<TConfig, TContext, TTransaction> = {
73
+ readonly provingService: (configuration: TConfig, getContext: () => TContext) => Proving.ProvingService<TTransaction>;
74
+ };
75
+ type HasCoinsAndBalances<TConfig, TContext> = {
76
+ readonly coinsAndBalancesCapability: (configuration: TConfig, getContext: () => TContext) => CoinsAndBalancesCapability<DustCoreWallet>;
77
+ };
78
+ type HasKeys<TConfig, TContext> = {
79
+ readonly keysCapability: (configuration: TConfig, getContext: () => TContext) => KeysCapability<DustCoreWallet>;
80
+ };
81
+ type HasSubmission<TConfig, TContext, TTransaction> = {
82
+ readonly submissionService: (configuration: TConfig, getContext: () => TContext) => SubmissionService<TTransaction>;
83
+ };
84
+ /**
85
+ * The internal build state of {@link V1Builder}.
86
+ */
87
+ type FullBuildState<TConfig, TContext, TSerialized, TSyncUpdate, TTransaction, TStartAux> = Types.Simplify<HasSync<TConfig, TContext, TSyncUpdate, TStartAux> & HasSerialization<TConfig, TContext, TSerialized> & HasTransacting<TConfig, TContext, TTransaction> & HasCoinSelection<TConfig, TContext> & HasProving<TConfig, TContext, TTransaction> & HasSubmission<TConfig, TContext, TTransaction> & HasCoinsAndBalances<TConfig, TContext> & HasKeys<TConfig, TContext>>;
88
+ type PartialBuildState<TConfig = object, TContext = object, TSerialized = never, TSyncUpdate = never, TTransaction = never, TStartAux = object> = {
89
+ [K in keyof FullBuildState<never, never, never, never, never, never>]?: FullBuildState<TConfig, TContext, TSerialized, TSyncUpdate, TTransaction, TStartAux>[K] | undefined;
90
+ };
91
+ /**
92
+ * Utility interface that manages the type variance of {@link V1Builder}.
93
+ */
94
+ interface Variance<R> {
95
+ readonly [V1BuilderSymbol.typeId]: {
96
+ readonly _R: Types.Covariant<R>;
97
+ };
98
+ }
99
+ }
100
+ export {};
@@ -0,0 +1,181 @@
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, Scope } from 'effect';
14
+ import { Proving } from '@midnight-ntwrk/wallet-sdk-shielded/v1';
15
+ import { makeDefaultSyncCapability, makeDefaultSyncService, } from './Sync.js';
16
+ import { RunningV1Variant, V1Tag } from './RunningV1Variant.js';
17
+ import { makeDefaultKeysCapability } from './Keys.js';
18
+ import { chooseCoin, makeDefaultCoinsAndBalancesCapability, } from './CoinsAndBalances.js';
19
+ import { makeDefaultTransactingCapability, } from './Transacting.js';
20
+ import { makeDefaultSubmissionService } from './Submission.js';
21
+ import { makeDefaultV1SerializationCapability } from './Serialization.js';
22
+ const V1BuilderSymbol = {
23
+ typeId: Symbol('@midnight-ntwrk/dustWallet#V1Builder'),
24
+ };
25
+ export class V1Builder {
26
+ #buildState;
27
+ constructor(buildState = {}) {
28
+ this.#buildState = buildState;
29
+ }
30
+ withDefaults() {
31
+ return this.withDefaultTransactionType()
32
+ .withSyncDefaults()
33
+ .withSerializationDefaults()
34
+ .withTransactingDefaults()
35
+ .withCoinsAndBalancesDefaults()
36
+ .withKeysDefaults()
37
+ .withSubmissionDefaults()
38
+ .withProvingDefaults()
39
+ .withCoinSelectionDefaults();
40
+ }
41
+ withTransactionType() {
42
+ return new V1Builder({
43
+ ...this.#buildState,
44
+ provingService: undefined,
45
+ transactingCapability: undefined,
46
+ submissionService: undefined,
47
+ });
48
+ }
49
+ withDefaultTransactionType() {
50
+ return this.withTransactionType();
51
+ }
52
+ withSyncDefaults() {
53
+ return this.withSync(makeDefaultSyncService, makeDefaultSyncCapability);
54
+ }
55
+ withSync(syncService, syncCapability) {
56
+ return new V1Builder({
57
+ ...this.#buildState,
58
+ syncService,
59
+ syncCapability,
60
+ });
61
+ }
62
+ withSerializationDefaults() {
63
+ return this.withSerialization(makeDefaultV1SerializationCapability);
64
+ }
65
+ withSerialization(serializationCapability) {
66
+ return new V1Builder({
67
+ ...this.#buildState,
68
+ serializationCapability,
69
+ });
70
+ }
71
+ withTransactingDefaults() {
72
+ return this.withTransacting(makeDefaultTransactingCapability);
73
+ }
74
+ withTransacting(transactingCapability) {
75
+ return new V1Builder({
76
+ ...this.#buildState,
77
+ transactingCapability,
78
+ });
79
+ }
80
+ withCoinSelection(coinSelection) {
81
+ return new V1Builder({
82
+ ...this.#buildState,
83
+ coinSelection,
84
+ });
85
+ }
86
+ withCoinSelectionDefaults() {
87
+ return this.withCoinSelection(() => chooseCoin);
88
+ }
89
+ withProving(provingService) {
90
+ return new V1Builder({
91
+ ...this.#buildState,
92
+ provingService,
93
+ });
94
+ }
95
+ withProvingDefaults() {
96
+ return this.withProving(Proving.makeDefaultProvingService);
97
+ }
98
+ withCoinsAndBalancesDefaults() {
99
+ return this.withCoinsAndBalances(makeDefaultCoinsAndBalancesCapability);
100
+ }
101
+ withCoinsAndBalances(coinsAndBalancesCapability) {
102
+ return new V1Builder({
103
+ ...this.#buildState,
104
+ coinsAndBalancesCapability,
105
+ });
106
+ }
107
+ withKeysDefaults() {
108
+ return this.withKeys(makeDefaultKeysCapability);
109
+ }
110
+ withKeys(keysCapability) {
111
+ return new V1Builder({
112
+ ...this.#buildState,
113
+ keysCapability,
114
+ });
115
+ }
116
+ withSubmission(submissionService) {
117
+ return new V1Builder({
118
+ ...this.#buildState,
119
+ submissionService,
120
+ });
121
+ }
122
+ withSubmissionDefaults() {
123
+ return this.withSubmission(makeDefaultSubmissionService);
124
+ }
125
+ build(configuration) {
126
+ const v1Context = this.#buildContextFromBuildState(configuration);
127
+ return {
128
+ __polyTag__: V1Tag,
129
+ coinsAndBalances: v1Context.coinsAndBalancesCapability,
130
+ keys: v1Context.keysCapability,
131
+ serialization: v1Context.serializationCapability,
132
+ start(context) {
133
+ return Effect.gen(function* () {
134
+ yield* Effect.addFinalizer(() => v1Context.submissionService.close());
135
+ const scope = yield* Scope.Scope;
136
+ return new RunningV1Variant(scope, context, v1Context);
137
+ });
138
+ },
139
+ migrateState(prevState) {
140
+ // TODO: re-implement
141
+ return Effect.succeed(prevState);
142
+ },
143
+ deserializeState: (serialized) => {
144
+ return v1Context.serializationCapability.deserialize(null, serialized);
145
+ },
146
+ };
147
+ }
148
+ #buildContextFromBuildState(configuration) {
149
+ if (!isBuildStateFull(this.#buildState)) {
150
+ throw new Error('Not all components are configured in V1 Builder');
151
+ }
152
+ const { syncCapability, syncService, transactingCapability, serializationCapability, provingService, coinSelection, coinsAndBalancesCapability, keysCapability, submissionService, } = this.#buildState;
153
+ const getContext = () => context;
154
+ const context = {
155
+ serializationCapability: serializationCapability(configuration, getContext),
156
+ syncCapability: syncCapability(configuration, getContext),
157
+ syncService: syncService(configuration, getContext),
158
+ transactingCapability: transactingCapability(configuration, getContext),
159
+ coinsAndBalancesCapability: coinsAndBalancesCapability(configuration, getContext),
160
+ keysCapability: keysCapability(configuration, getContext),
161
+ provingService: provingService(configuration, getContext),
162
+ coinSelection: coinSelection(configuration, getContext),
163
+ submissionService: submissionService(configuration, getContext),
164
+ };
165
+ return context;
166
+ }
167
+ }
168
+ const isBuildStateFull = (buildState) => {
169
+ const allBuildStateKeys = [
170
+ 'syncService',
171
+ 'syncCapability',
172
+ 'transactingCapability',
173
+ 'coinSelection',
174
+ 'serializationCapability',
175
+ 'provingService',
176
+ 'coinsAndBalancesCapability',
177
+ 'keysCapability',
178
+ 'submissionService',
179
+ ];
180
+ return allBuildStateKeys.every((key) => typeof buildState[key] == 'function');
181
+ };
@@ -0,0 +1,9 @@
1
+ export * from './DustCoreWallet.js';
2
+ export * from './DustWallet.js';
3
+ export * as Keys from './Keys.js';
4
+ export * as Simulator from './Simulator.js';
5
+ export * as SyncService from './Sync.js';
6
+ export * as Transacting from './Transacting.js';
7
+ export * from './RunningV1Variant.js';
8
+ export * from './V1Builder.js';
9
+ export * from './types/index.js';
package/dist/index.js ADDED
@@ -0,0 +1,21 @@
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
+ export * from './DustCoreWallet.js';
14
+ export * from './DustWallet.js';
15
+ export * as Keys from './Keys.js';
16
+ export * as Simulator from './Simulator.js';
17
+ export * as SyncService from './Sync.js';
18
+ export * as Transacting from './Transacting.js';
19
+ export * from './RunningV1Variant.js';
20
+ export * from './V1Builder.js';
21
+ export * from './types/index.js';
@@ -0,0 +1,30 @@
1
+ import { DustInitialNonce, DustNullifier, DustNonce, DustPublicKey, Utxo } from '@midnight-ntwrk/ledger-v6';
2
+ export type DustToken = {
3
+ initialValue: bigint;
4
+ owner: DustPublicKey;
5
+ nonce: DustNonce;
6
+ seq: number;
7
+ ctime: Date;
8
+ backingNight: DustInitialNonce;
9
+ mtIndex: bigint;
10
+ };
11
+ export type DustTokenWithNullifier = DustToken & {
12
+ nullifier: DustNullifier;
13
+ };
14
+ export type DustTokenFullInfo = {
15
+ token: DustToken;
16
+ dtime: Date | undefined;
17
+ maxCap: bigint;
18
+ maxCapReachedAt: Date;
19
+ generatedNow: bigint;
20
+ rate: bigint;
21
+ };
22
+ export type DustGenerationInfo = {
23
+ value: bigint;
24
+ owner: DustPublicKey;
25
+ nonce: DustInitialNonce;
26
+ dtime: Date | undefined;
27
+ };
28
+ export type UtxoWithMeta = Utxo & {
29
+ ctime: Date;
30
+ };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,3 @@
1
+ export * from './Dust.js';
2
+ export * from './ledger.js';
3
+ export * from './transaction.js';
@@ -0,0 +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.
13
+ export * from './Dust.js';
14
+ export * from './ledger.js';
15
+ export * from './transaction.js';
@@ -0,0 +1,4 @@
1
+ import * as ledger from '@midnight-ntwrk/ledger-v6';
2
+ export type AnyTransaction = ledger.UnprovenTransaction | ledger.FinalizedTransaction | ledger.ProofErasedTransaction;
3
+ export type UnprovenDustSpend = ledger.DustSpend<ledger.PreProof>;
4
+ export type NetworkId = string;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,4 @@
1
+ export type TotalCostParameters = {
2
+ additionalFeeOverhead: bigint;
3
+ feeBlocksMargin: number;
4
+ };
@@ -0,0 +1 @@
1
+ export {};