@midnight-ntwrk/wallet-sdk-dust-wallet 1.0.0-beta.14 → 1.0.0-beta.15

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.
@@ -1,10 +1,15 @@
1
1
  import { DustCoreWallet } from './DustCoreWallet.js';
2
- import { DustGenerationInfo, DustToken, DustTokenFullInfo } from './types/Dust.js';
2
+ import { KeysCapability } from './Keys.js';
3
+ import { DustGenerationDetails, DustGenerationInfo, DustToken, DustTokenFullInfo, UtxoWithMeta } from './types/Dust.js';
3
4
  export type Balance = bigint;
4
5
  export type CoinWithValue<TToken> = {
5
6
  token: TToken;
6
7
  value: Balance;
7
8
  };
9
+ export type UtxoWithFullDustDetails = Readonly<{
10
+ utxo: UtxoWithMeta;
11
+ dust: DustGenerationDetails;
12
+ }>;
8
13
  export type CoinSelection<TInput> = (coins: readonly CoinWithValue<TInput>[], amountNeeded: Balance) => CoinWithValue<TInput>[];
9
14
  export declare const chooseCoin: <TInput>(coins: readonly CoinWithValue<TInput>[], amountNeeded: Balance) => CoinWithValue<TInput>[];
10
15
  export type CoinsAndBalancesCapability<TState> = {
@@ -15,5 +20,24 @@ export type CoinsAndBalancesCapability<TState> = {
15
20
  getAvailableCoinsWithGeneratedDust(state: TState, currentTime: Date): ReadonlyArray<CoinWithValue<DustToken>>;
16
21
  getAvailableCoinsWithFullInfo(state: TState, blockTime: Date): readonly DustTokenFullInfo[];
17
22
  getGenerationInfo(state: TState, token: DustToken): DustGenerationInfo | undefined;
23
+ /**
24
+ * Splits provided Night utxos into the ones that will be used as inputs in the guaranteed and fallible sections
25
+ */
26
+ splitNightUtxos(nightUtxos: ReadonlyArray<UtxoWithFullDustDetails>): {
27
+ guaranteed: ReadonlyArray<UtxoWithFullDustDetails>;
28
+ fallible: ReadonlyArray<UtxoWithFullDustDetails>;
29
+ };
30
+ /**
31
+ * Estimate how much Dust would be available to use if the Utxos provided were used for Dust generation from their beginning.
32
+ * This function is particularly useful for the purpose of registering for Dust generation and selecting the Utxo to be used for paying fees and approving the registration itself.
33
+ * @param state Current state of the wallet
34
+ * @param nightUtxos Existing Night utxos
35
+ * @param currentTime Current time
36
+ * @returns Estimated Dust generation per Utxo
37
+ */
38
+ estimateDustGeneration(state: TState, nightUtxos: ReadonlyArray<UtxoWithMeta>, currentTime: Date): ReadonlyArray<UtxoWithFullDustDetails>;
18
39
  };
19
- export declare const makeDefaultCoinsAndBalancesCapability: () => CoinsAndBalancesCapability<DustCoreWallet>;
40
+ export type DefaultCoinsAndBalancesContext = {
41
+ keysCapability: KeysCapability<DustCoreWallet>;
42
+ };
43
+ export declare const makeDefaultCoinsAndBalancesCapability: (config: object, getContext: () => DefaultCoinsAndBalancesContext) => CoinsAndBalancesCapability<DustCoreWallet>;
@@ -10,9 +10,9 @@
10
10
  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
11
  // See the License for the specific language governing permissions and
12
12
  // limitations under the License.
13
- import { Array, pipe } from 'effect';
14
- import { updatedValue } from '@midnight-ntwrk/ledger-v7';
13
+ import * as ledger from '@midnight-ntwrk/ledger-v7';
15
14
  import { DateOps } from '@midnight-ntwrk/wallet-sdk-utilities';
15
+ import { pipe, Array as Arr, Order } from 'effect';
16
16
  export const chooseCoin = (coins, amountNeeded) => {
17
17
  let sum = 0n;
18
18
  const sorted = coins.toSorted((a, b) => Number(a.value - b.value));
@@ -25,13 +25,14 @@ export const chooseCoin = (coins, amountNeeded) => {
25
25
  }
26
26
  return result;
27
27
  };
28
- export const makeDefaultCoinsAndBalancesCapability = () => {
28
+ const FAKE_NONCE = '0'.repeat(64);
29
+ export const makeDefaultCoinsAndBalancesCapability = (config, getContext) => {
29
30
  const getWalletBalance = (state, time) => {
30
31
  return state.state.walletBalance(time);
31
32
  };
32
33
  const getAvailableCoins = (state) => {
33
34
  const pendingSpends = new Set([...state.pendingDustTokens.values()].map((coin) => coin.nonce));
34
- return pipe(state.state.utxos, Array.filter((coin) => !pendingSpends.has(coin.nonce)));
35
+ return pipe(state.state.utxos, Arr.filter((coin) => !pendingSpends.has(coin.nonce)));
35
36
  };
36
37
  const getPendingCoins = (state) => state.pendingDustTokens;
37
38
  const getTotalCoins = (state) => [
@@ -53,7 +54,7 @@ export const makeDefaultCoinsAndBalancesCapability = () => {
53
54
  for (const coin of available) {
54
55
  const genInfo = getGenerationInfo(state, coin);
55
56
  if (genInfo) {
56
- const generatedValue = updatedValue(coin.ctime, coin.initialValue, genInfo, currentTime, state.state.params);
57
+ const generatedValue = ledger.updatedValue(coin.ctime, coin.initialValue, genInfo, currentTime, state.state.params);
57
58
  result.push({ token: coin, value: generatedValue });
58
59
  }
59
60
  }
@@ -65,19 +66,60 @@ export const makeDefaultCoinsAndBalancesCapability = () => {
65
66
  for (const coin of available) {
66
67
  const genInfo = getGenerationInfo(state, coin);
67
68
  if (genInfo) {
68
- const generatedValue = updatedValue(coin.ctime, coin.initialValue, genInfo, blockTime, state.state.params);
69
69
  result.push({
70
70
  token: coin,
71
- dtime: genInfo.dtime,
72
- maxCap: genInfo.value * state.state.params.nightDustRatio,
73
- maxCapReachedAt: DateOps.addSeconds(coin.ctime, state.state.params.timeToCapSeconds),
74
- generatedNow: generatedValue,
75
- rate: genInfo.value * state.state.params.generationDecayRate,
71
+ ...getFullDustInfo(state.state.params, genInfo, coin, blockTime),
76
72
  });
77
73
  }
78
74
  }
79
75
  return result;
80
76
  };
77
+ const getFullDustInfo = (parameters, genInfo, coin, currentTime) => {
78
+ const generatedValue = ledger.updatedValue(coin.ctime, coin.initialValue, genInfo, currentTime, parameters);
79
+ return {
80
+ dtime: genInfo.dtime,
81
+ maxCap: genInfo.value * parameters.nightDustRatio,
82
+ maxCapReachedAt: DateOps.addSeconds(coin.ctime, parameters.timeToCapSeconds),
83
+ generatedNow: generatedValue,
84
+ rate: genInfo.value * parameters.generationDecayRate,
85
+ };
86
+ };
87
+ const estimateDustGeneration = (state, nightUtxos, currentTime) => {
88
+ const dustPublicKey = getContext().keysCapability.getDustPublicKey(state);
89
+ return pipe(nightUtxos, Arr.map((utxo) => {
90
+ const genInfo = fakeGenerationInfo(utxo, dustPublicKey);
91
+ const fakeDustCoin = fakeDustToken(dustPublicKey, utxo);
92
+ const details = getFullDustInfo(state.state.params, genInfo, fakeDustCoin, currentTime);
93
+ return { utxo, dust: details };
94
+ }));
95
+ };
96
+ /**
97
+ * Create a fake generation info for a given Utxo. It allows to estimate the Dust generation from it
98
+ */
99
+ const fakeGenerationInfo = (utxo, dustPublicKey) => {
100
+ return {
101
+ value: utxo.value,
102
+ owner: dustPublicKey,
103
+ nonce: FAKE_NONCE,
104
+ dtime: undefined,
105
+ };
106
+ };
107
+ /**
108
+ * Create a fake dust coin for a given Utxo. It allows to estimate full details of the Dust generation from it
109
+ */
110
+ const fakeDustToken = (dustPublicKey, utxo) => ({
111
+ initialValue: 0n,
112
+ owner: dustPublicKey,
113
+ nonce: 0n,
114
+ seq: 0,
115
+ ctime: utxo.ctime,
116
+ backingNight: '',
117
+ mtIndex: 0n,
118
+ });
119
+ const splitNightUtxos = (utxos) => {
120
+ const [guaranteed, fallible] = pipe(utxos, Arr.sort(pipe(Order.bigint, Order.reverse, Order.mapInput((coin) => coin.dust.generatedNow))), Arr.splitAt(1));
121
+ return { guaranteed, fallible };
122
+ };
81
123
  return {
82
124
  getWalletBalance,
83
125
  getAvailableCoins,
@@ -86,5 +128,7 @@ export const makeDefaultCoinsAndBalancesCapability = () => {
86
128
  getAvailableCoinsWithGeneratedDust,
87
129
  getAvailableCoinsWithFullInfo,
88
130
  getGenerationInfo,
131
+ estimateDustGeneration,
132
+ splitNightUtxos,
89
133
  };
90
134
  };
@@ -1,9 +1,9 @@
1
1
  import { DustParameters, DustPublicKey, DustSecretKey, FinalizedTransaction, Signature, SignatureVerifyingKey, UnprovenTransaction } from '@midnight-ntwrk/ledger-v7';
2
2
  import { ProtocolState, ProtocolVersion } from '@midnight-ntwrk/wallet-sdk-abstractions';
3
3
  import { Variant, WalletLike } from '@midnight-ntwrk/wallet-sdk-runtime/abstractions';
4
- import { ProvingRecipe, TransactionHistory } from '@midnight-ntwrk/wallet-sdk-shielded/v1';
4
+ import { TransactionHistory } from '@midnight-ntwrk/wallet-sdk-shielded/v1';
5
5
  import * as rx from 'rxjs';
6
- import { Balance, CoinsAndBalancesCapability } from './CoinsAndBalances.js';
6
+ import { Balance, CoinsAndBalancesCapability, UtxoWithFullDustDetails } from './CoinsAndBalances.js';
7
7
  import { DustCoreWallet } from './DustCoreWallet.js';
8
8
  import { KeysCapability } from './Keys.js';
9
9
  import { SerializationCapability } from './Serialization.js';
@@ -30,16 +30,17 @@ export declare class DustWalletState {
30
30
  constructor(state: ProtocolState.ProtocolState<DustCoreWallet>, capabilities: DustWalletCapabilities);
31
31
  walletBalance(time: Date): Balance;
32
32
  availableCoinsWithFullInfo(time: Date): readonly DustTokenFullInfo[];
33
+ estimateDustGeneration(nightUtxos: ReadonlyArray<UtxoWithMeta>, currentTime: Date): ReadonlyArray<UtxoWithFullDustDetails>;
33
34
  serialize(): string;
34
35
  }
35
36
  export interface DustWallet extends WalletLike.WalletLike<[Variant.VersionedVariant<DefaultV1Variant>]> {
36
37
  readonly state: rx.Observable<DustWalletState>;
37
38
  start(secretKey: DustSecretKey): Promise<void>;
38
39
  createDustGenerationTransaction(currentTime: Date | undefined, ttl: Date, nightUtxos: Array<UtxoWithMeta>, nightVerifyingKey: SignatureVerifyingKey, dustReceiverAddress: string | undefined): Promise<UnprovenTransaction>;
39
- addDustGenerationSignature(transaction: UnprovenTransaction, signature: Signature): Promise<ProvingRecipe.ProvingRecipe<FinalizedTransaction>>;
40
- calculateFee(transaction: AnyTransaction): Promise<bigint>;
41
- addFeePayment(secretKey: DustSecretKey, transaction: UnprovenTransaction, ttl: Date, currentTime?: Date): Promise<ProvingRecipe.ProvingRecipe<FinalizedTransaction>>;
42
- finalizeTransaction(recipe: ProvingRecipe.ProvingRecipe<FinalizedTransaction>): Promise<FinalizedTransaction>;
40
+ addDustGenerationSignature(transaction: UnprovenTransaction, signature: Signature): Promise<UnprovenTransaction>;
41
+ calculateFee(transactions: ReadonlyArray<AnyTransaction>): Promise<bigint>;
42
+ balanceTransactions(secretKey: DustSecretKey, transactions: ReadonlyArray<AnyTransaction>, ttl: Date, currentTime?: Date): Promise<UnprovenTransaction>;
43
+ proveTransaction(transaction: UnprovenTransaction): Promise<FinalizedTransaction>;
43
44
  readonly submitTransaction: SubmitTransactionMethod<FinalizedTransaction>;
44
45
  serializeState(): Promise<string>;
45
46
  waitForSyncedState(allowedGap?: bigint): Promise<DustWalletState>;
@@ -60,6 +60,9 @@ export class DustWalletState {
60
60
  availableCoinsWithFullInfo(time) {
61
61
  return this.capabilities.coinsAndBalances.getAvailableCoinsWithFullInfo(this.state, time);
62
62
  }
63
+ estimateDustGeneration(nightUtxos, currentTime) {
64
+ return this.capabilities.coinsAndBalances.estimateDustGeneration(this.state, nightUtxos, currentTime);
65
+ }
63
66
  serialize() {
64
67
  return this.capabilities.serialization.serialize(this.state);
65
68
  }
@@ -103,24 +106,24 @@ export function DustWallet(configuration) {
103
106
  })
104
107
  .pipe(Effect.runPromise);
105
108
  }
106
- calculateFee(transaction) {
109
+ calculateFee(transactions) {
107
110
  return this.runtime
108
111
  .dispatch({
109
- [V1Tag]: (v1) => v1.calculateFee(transaction),
112
+ [V1Tag]: (v1) => v1.calculateFee(transactions),
110
113
  })
111
114
  .pipe(Effect.runPromise);
112
115
  }
113
- addFeePayment(secretKey, transaction, ttl, currentTime) {
116
+ balanceTransactions(secretKey, transactions, ttl, currentTime) {
114
117
  return this.runtime
115
118
  .dispatch({
116
- [V1Tag]: (v1) => v1.addFeePayment(secretKey, transaction, ttl, currentTime),
119
+ [V1Tag]: (v1) => v1.balanceTransactions(secretKey, transactions, ttl, currentTime),
117
120
  })
118
121
  .pipe(Effect.runPromise);
119
122
  }
120
- finalizeTransaction(recipe) {
123
+ proveTransaction(transaction) {
121
124
  return this.runtime
122
125
  .dispatch({
123
- [V1Tag]: (v1) => v1.finalizeTransaction(recipe),
126
+ [V1Tag]: (v1) => v1.proveTransaction(transaction),
124
127
  })
125
128
  .pipe(Effect.runPromise);
126
129
  }
@@ -1,6 +1,6 @@
1
1
  import { Effect, Stream, Scope } from 'effect';
2
2
  import { DustSecretKey, Signature, SignatureVerifyingKey, FinalizedTransaction, UnprovenTransaction } from '@midnight-ntwrk/ledger-v7';
3
- import { Proving, ProvingRecipe, WalletError } from '@midnight-ntwrk/wallet-sdk-shielded/v1';
3
+ import { Proving, WalletError } from '@midnight-ntwrk/wallet-sdk-shielded/v1';
4
4
  import { WalletRuntimeError, Variant, StateChange } from '@midnight-ntwrk/wallet-sdk-runtime/abstractions';
5
5
  import { DustToken, UtxoWithMeta } from './types/Dust.js';
6
6
  import { KeysCapability } from './Keys.js';
@@ -36,9 +36,9 @@ 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.WalletError, Scope.Scope>;
38
38
  createDustGenerationTransaction(currentTime: Date | undefined, ttl: Date, nightUtxos: ReadonlyArray<UtxoWithMeta>, nightVerifyingKey: SignatureVerifyingKey, dustReceiverAddress: string | undefined): Effect.Effect<UnprovenTransaction, WalletError.WalletError>;
39
- addDustGenerationSignature(transaction: UnprovenTransaction, signature: Signature): Effect.Effect<ProvingRecipe.ProvingRecipe<FinalizedTransaction>, WalletError.WalletError>;
40
- calculateFee(transaction: AnyTransaction): Effect.Effect<bigint, WalletError.WalletError>;
41
- addFeePayment(secretKey: DustSecretKey, transaction: UnprovenTransaction, ttl: Date, currentTime?: Date): Effect.Effect<ProvingRecipe.ProvingRecipe<FinalizedTransaction>, WalletError.WalletError>;
42
- finalizeTransaction(recipe: ProvingRecipe.ProvingRecipe<TTransaction>): Effect.Effect<TTransaction, WalletError.WalletError>;
39
+ addDustGenerationSignature(transaction: UnprovenTransaction, signature: Signature): Effect.Effect<UnprovenTransaction, WalletError.WalletError>;
40
+ calculateFee(transactions: ReadonlyArray<AnyTransaction>): Effect.Effect<bigint, WalletError.WalletError>;
41
+ balanceTransactions(secretKey: DustSecretKey, transactions: ReadonlyArray<AnyTransaction>, ttl: Date, currentTime?: Date): Effect.Effect<UnprovenTransaction, WalletError.WalletError>;
42
+ proveTransaction(transaction: UnprovenTransaction): Effect.Effect<TTransaction, WalletError.WalletError>;
43
43
  submitTransaction: SubmitTransactionMethod<TTransaction>;
44
44
  }
@@ -10,11 +10,11 @@
10
10
  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
11
  // See the License for the specific language governing permissions and
12
12
  // limitations under the License.
13
- import { Effect, SubscriptionRef, Stream, pipe, Scope, Sink, Console, Duration, Schedule } from 'effect';
14
- import { nativeToken, updatedValue, } from '@midnight-ntwrk/ledger-v7';
13
+ import { Effect, SubscriptionRef, Stream, pipe, Scope, Sink, Console, Duration, Schedule, Array as Arr } from 'effect';
14
+ import { nativeToken, } from '@midnight-ntwrk/ledger-v7';
15
15
  import { ProtocolVersion } from '@midnight-ntwrk/wallet-sdk-abstractions';
16
16
  import { WalletError } from '@midnight-ntwrk/wallet-sdk-shielded/v1';
17
- import { EitherOps, LedgerOps } from '@midnight-ntwrk/wallet-sdk-utilities';
17
+ import { ArrayOps, EitherOps } from '@midnight-ntwrk/wallet-sdk-utilities';
18
18
  import { StateChange, VersionChangeType, } from '@midnight-ntwrk/wallet-sdk-runtime/abstractions';
19
19
  const progress = (state) => {
20
20
  const appliedIndex = state.progress?.appliedIndex ?? 0n;
@@ -81,21 +81,11 @@ export class RunningV1Variant {
81
81
  if (nightUtxos.some((utxo) => utxo.type !== nativeToken().raw)) {
82
82
  return Effect.fail(WalletError.WalletError.other('Token of a non-Night type received'));
83
83
  }
84
- return Effect.Do.pipe(Effect.bind('currentState', () => SubscriptionRef.get(this.#context.stateRef)), Effect.bind('blockData', () => this.#v1Context.syncService.blockData()), Effect.bind('utxosWithDustValue', ({ currentState, blockData }) => LedgerOps.ledgerTry(() => {
85
- const dustPublicKey = this.#v1Context.keysCapability.getDustPublicKey(currentState);
86
- return nightUtxos.map((utxo) => {
87
- const genInfo = {
88
- value: utxo.value,
89
- owner: dustPublicKey,
90
- nonce: LedgerOps.randomNonce(),
91
- dtime: undefined,
92
- };
93
- const dustValue = updatedValue(utxo.ctime, 0n, genInfo, currentTime ?? blockData.timestamp, currentState.state.params);
94
- return { token: utxo, value: dustValue };
95
- });
96
- })), Effect.flatMap(({ utxosWithDustValue, blockData }) => {
84
+ return Effect.Do.pipe(Effect.bind('currentState', () => SubscriptionRef.get(this.#context.stateRef)), Effect.bind('blockData', () => this.#v1Context.syncService.blockData()), Effect.let('currentTime', ({ blockData }) => currentTime ?? blockData.timestamp), Effect.let('utxosWithDustValue', ({ currentState, currentTime }) => {
85
+ return this.#v1Context.coinsAndBalancesCapability.estimateDustGeneration(currentState, nightUtxos, currentTime);
86
+ }), Effect.flatMap(({ utxosWithDustValue, currentTime }) => {
97
87
  return this.#v1Context.transactingCapability
98
- .createDustGenerationTransaction(currentTime ?? blockData.timestamp, ttl, utxosWithDustValue, nightVerifyingKey, dustReceiverAddress)
88
+ .createDustGenerationTransaction(currentTime, ttl, utxosWithDustValue, nightVerifyingKey, dustReceiverAddress)
99
89
  .pipe(EitherOps.toEffect);
100
90
  }));
101
91
  }
@@ -104,22 +94,22 @@ export class RunningV1Variant {
104
94
  .addDustGenerationSignature(transaction, signature)
105
95
  .pipe(EitherOps.toEffect);
106
96
  }
107
- calculateFee(transaction) {
108
- return pipe(this.#v1Context.syncService.blockData(), Effect.map((blockData) => this.#v1Context.transactingCapability.calculateFee(transaction, blockData.ledgerParameters)));
97
+ calculateFee(transactions) {
98
+ return pipe(this.#v1Context.syncService.blockData(), Effect.map((blockData) => pipe(transactions, Arr.map((transaction) => this.#v1Context.transactingCapability.calculateFee(transaction, blockData.ledgerParameters)), ArrayOps.sumBigInt)));
109
99
  }
110
- addFeePayment(secretKey, transaction, ttl, currentTime) {
100
+ balanceTransactions(secretKey, transactions, ttl, currentTime) {
111
101
  return SubscriptionRef.modifyEffect(this.#context.stateRef, (state) => {
112
- return pipe(this.#v1Context.syncService.blockData(), Effect.flatMap((blockData) => this.#v1Context.transactingCapability.addFeePayment(secretKey, state, transaction, ttl, currentTime ?? blockData.timestamp, blockData.ledgerParameters)), Effect.map(({ recipe, newState }) => [recipe, newState]));
102
+ return pipe(this.#v1Context.syncService.blockData(), Effect.flatMap((blockData) => this.#v1Context.transactingCapability.balanceTransactions(secretKey, state, transactions, ttl, currentTime ?? blockData.timestamp, blockData.ledgerParameters)));
113
103
  });
114
104
  }
115
- finalizeTransaction(recipe) {
105
+ proveTransaction(transaction) {
116
106
  return this.#v1Context.provingService
117
- .prove(recipe)
118
- .pipe(Effect.tapError(() => SubscriptionRef.updateEffect(this.#context.stateRef, (state) => EitherOps.toEffect(this.#v1Context.transactingCapability.revertRecipe(state, recipe)))));
107
+ .prove(transaction)
108
+ .pipe(Effect.tapError(() => SubscriptionRef.updateEffect(this.#context.stateRef, (state) => EitherOps.toEffect(this.#v1Context.transactingCapability.revertTransaction(state, transaction)))));
119
109
  }
120
110
  submitTransaction = ((transaction, waitForStatus = 'InBlock') => {
121
111
  return this.#v1Context.submissionService
122
112
  .submitTransaction(transaction, waitForStatus)
123
- .pipe(Effect.tapError(() => SubscriptionRef.updateEffect(this.#context.stateRef, (state) => EitherOps.toEffect(this.#v1Context.transactingCapability.revert(state, transaction)))));
113
+ .pipe(Effect.tapError(() => SubscriptionRef.updateEffect(this.#context.stateRef, (state) => EitherOps.toEffect(this.#v1Context.transactingCapability.revertTransaction(state, transaction)))));
124
114
  });
125
115
  }
package/dist/Sync.d.ts CHANGED
@@ -45,11 +45,12 @@ export declare const SyncEventsUpdateSchema: Schema.Struct<{
45
45
  }>;
46
46
  export type WalletSyncSubscription = Schema.Schema.Type<typeof SyncEventsUpdateSchema>;
47
47
  export type WalletSyncUpdate = {
48
- update: WalletSyncSubscription;
48
+ updates: WalletSyncSubscription[];
49
49
  secretKeys: SecretKeysResource;
50
+ timestamp: Date;
50
51
  };
51
52
  export declare const WalletSyncUpdate: {
52
- create: (update: WalletSyncSubscription, secretKey: DustSecretKey) => WalletSyncUpdate;
53
+ create: (updates: WalletSyncSubscription[], secretKey: DustSecretKey, timestamp: Date) => WalletSyncUpdate;
53
54
  };
54
55
  export declare const makeDefaultSyncService: (config: DefaultSyncConfiguration) => SyncService<DustCoreWallet, DustSecretKey, WalletSyncUpdate>;
55
56
  export type IndexerSyncService = {
package/dist/Sync.js CHANGED
@@ -10,7 +10,7 @@
10
10
  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
11
  // See the License for the specific language governing permissions and
12
12
  // limitations under the License.
13
- import { Effect, Either, Layer, ParseResult, pipe, Schema, Stream, Duration } from 'effect';
13
+ import { Effect, Either, Layer, ParseResult, pipe, Schema, Stream, Duration, Chunk, Schedule } from 'effect';
14
14
  import { Event as LedgerEvent, LedgerParameters } from '@midnight-ntwrk/ledger-v7';
15
15
  import { BlockHash, DustLedgerEvents } from '@midnight-ntwrk/wallet-sdk-indexer-client';
16
16
  import { WsSubscriptionClient, HttpQueryClient, ConnectionHelper, } from '@midnight-ntwrk/wallet-sdk-indexer-client/effect';
@@ -58,10 +58,11 @@ export const SyncEventsUpdateSchema = Schema.Struct({
58
58
  maxId: Schema.Number,
59
59
  });
60
60
  export const WalletSyncUpdate = {
61
- create: (update, secretKey) => {
61
+ create: (updates, secretKey, timestamp) => {
62
62
  return {
63
- update,
63
+ updates,
64
64
  secretKeys: SecretKeysResource.create(secretKey),
65
+ timestamp,
65
66
  };
66
67
  },
67
68
  };
@@ -69,9 +70,9 @@ export const makeDefaultSyncService = (config) => {
69
70
  const indexerSyncService = makeIndexerSyncService(config);
70
71
  return {
71
72
  updates: (state, secretKey) => {
72
- const batchSize = 50;
73
- const batchTimeout = Duration.seconds(10);
74
- return pipe(indexerSyncService.subscribeWallet(state), Stream.map((data) => WalletSyncUpdate.create(data, secretKey)), Stream.groupedWithin(batchSize, batchTimeout), Stream.flatMap((chunk) => Stream.fromIterable(chunk)), Stream.provideSomeLayer(indexerSyncService.connectionLayer()));
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()));
75
76
  },
76
77
  blockData: () => {
77
78
  return Effect.gen(function* () {
@@ -116,17 +117,22 @@ export const makeIndexerSyncService = (config) => {
116
117
  export const makeDefaultSyncCapability = () => {
117
118
  return {
118
119
  applyUpdate(state, wrappedUpdate) {
119
- const { update, secretKeys } = wrappedUpdate;
120
- const nextIndex = BigInt(update.id);
121
- const highestRelevantWalletIndex = BigInt(update.maxId);
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);
122
128
  // in case the nextIndex is less than or equal to the current appliedIndex
123
129
  // just update highestRelevantWalletIndex
124
130
  if (nextIndex <= state.progress.appliedIndex) {
125
131
  return state.updateProgress({ highestRelevantWalletIndex, isConnected: true });
126
132
  }
127
- const events = [update.raw].filter((event) => event !== null);
133
+ const events = updates.map((u) => u.raw).filter((event) => event !== null);
128
134
  return secretKeys((keys) => state
129
- .applyEvents(keys, events, new Date())
135
+ .applyEvents(keys, events, wrappedUpdate.timestamp)
130
136
  .updateProgress({ appliedIndex: nextIndex, highestRelevantWalletIndex, isConnected: true }));
131
137
  },
132
138
  };
@@ -1,22 +1,18 @@
1
1
  import { Either } from 'effect';
2
- import { DustSecretKey, Signature, SignatureVerifyingKey, Utxo, FinalizedTransaction, ProofErasedTransaction, UnprovenTransaction, LedgerParameters } from '@midnight-ntwrk/ledger-v7';
3
- import { ProvingRecipe, WalletError } from '@midnight-ntwrk/wallet-sdk-shielded/v1';
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, CoinWithValue } from './CoinsAndBalances.js';
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<CoinWithValue<Utxo>>, nightVerifyingKey: SignatureVerifyingKey, dustReceiverAddress: string | undefined): Either.Either<UnprovenTransaction, WalletError.WalletError>;
12
- addDustGenerationSignature(transaction: UnprovenTransaction, signature: Signature): Either.Either<ProvingRecipe.ProvingRecipe<FinalizedTransaction>, WalletError.WalletError>;
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
- addFeePayment(secretKey: TSecrets, state: TState, transaction: UnprovenTransaction, ttl: Date, currentTime: Date, ledgerParams: LedgerParameters): Either.Either<{
15
- recipe: ProvingRecipe.ProvingRecipe<FinalizedTransaction>;
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<CoinWithValue<Utxo>>, nightVerifyingKey: SignatureVerifyingKey, dustReceiverAddress: string | undefined): Either.Either<UnprovenTransaction, WalletError.WalletError>;
41
- addDustGenerationSignature(transaction: UnprovenTransaction, signatureData: Signature): Either.Either<ProvingRecipe.ProvingRecipe<FinalizedTransaction>, WalletError.WalletError>;
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
- addFeePayment(secretKey: DustSecretKey, state: DustCoreWallet, transaction: UnprovenTransaction, ttl: Date, currentTime: Date, ledgerParams: LedgerParameters): Either.Either<{
45
- recipe: ProvingRecipe.ProvingRecipe<FinalizedTransaction>;
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
  }
@@ -10,10 +10,10 @@
10
10
  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
11
  // See the License for the specific language governing permissions and
12
12
  // limitations under the License.
13
- import { Either } from 'effect';
14
- import { DustActions, DustRegistration, Intent, SignatureEnabled, Transaction, UnshieldedOffer, addressFromKey, } from '@midnight-ntwrk/ledger-v7';
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';
15
15
  import { MidnightBech32m, DustAddress } from '@midnight-ntwrk/wallet-sdk-address-format';
16
- import { ProvingRecipe, WalletError } from '@midnight-ntwrk/wallet-sdk-shielded/v1';
16
+ import { WalletError } from '@midnight-ntwrk/wallet-sdk-shielded/v1';
17
17
  import { LedgerOps } from '@midnight-ntwrk/wallet-sdk-utilities';
18
18
  import { BindingMarker, ProofMarker, SignatureMarker } from './Utils.js';
19
19
  export const makeDefaultTransactingCapability = (config, getContext) => {
@@ -36,24 +36,48 @@ export class TransactingCapabilityImplementation {
36
36
  this.getKeys = getKeys;
37
37
  }
38
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
+ };
39
55
  return Either.gen(this, function* () {
40
56
  const receiver = dustReceiverAddress ? yield* this.#parseAddress(dustReceiverAddress) : undefined;
41
57
  return yield* LedgerOps.ledgerTry(() => {
42
58
  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, []);
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);
55
63
  const dustRegistration = new DustRegistration(SignatureMarker.signature, nightVerifyingKey, receiver, dustReceiverAddress !== undefined ? totalDustValue : 0n);
56
- intent.dustActions = new DustActions(SignatureMarker.signature, ProofMarker.preProof, currentTime, [], [dustRegistration]);
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
+ });
57
81
  return Transaction.fromParts(network, undefined, undefined, intent);
58
82
  });
59
83
  });
@@ -64,7 +88,7 @@ export class TransactingCapabilityImplementation {
64
88
  if (!intent) {
65
89
  return yield* Either.left(new WalletError.TransactingError({ message: 'No intent found in the transaction intents with segment = 1' }));
66
90
  }
67
- const { dustActions, guaranteedUnshieldedOffer } = intent;
91
+ const { dustActions, guaranteedUnshieldedOffer, fallibleUnshieldedOffer } = intent;
68
92
  if (!dustActions) {
69
93
  return yield* Either.left(new WalletError.TransactingError({ message: 'No dustActions found in intent' }));
70
94
  }
@@ -88,13 +112,18 @@ export class TransactingCapabilityImplementation {
88
112
  signatures.push(guaranteedUnshieldedOffer.signatures.at(i) ?? signatureData);
89
113
  }
90
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
+ }
91
123
  // make a copy of transaction to avoid mutation
92
124
  const newTransaction = Transaction.deserialize(signature.instance, ProofMarker.preProof, BindingMarker.preBinding, transaction.serialize());
93
125
  newTransaction.intents = newTransaction.intents.set(1, newIntent);
94
- return {
95
- type: ProvingRecipe.TRANSACTION_TO_PROVE,
96
- transaction: newTransaction,
97
- };
126
+ return newTransaction;
98
127
  });
99
128
  });
100
129
  }
@@ -108,9 +137,10 @@ export class TransactingCapabilityImplementation {
108
137
  .find(([tt, _]) => tt.tag === 'dust');
109
138
  return dustImbalance ? -dustImbalance[1] : totalFee;
110
139
  }
111
- addFeePayment(secretKey, state, transaction, ttl, currentTime, ledgerParams) {
140
+ balanceTransactions(secretKey, state, transactions, ttl, currentTime, ledgerParams) {
112
141
  const network = this.networkId;
113
- const feeLeft = TransactingCapabilityImplementation.feeImbalance(transaction, this.calculateFee(transaction, ledgerParams));
142
+ const feeLeft = transactions.reduce((total, transaction) => total +
143
+ TransactingCapabilityImplementation.feeImbalance(transaction, this.calculateFee(transaction, ledgerParams)), 0n);
114
144
  const dustTokens = this.getCoins().getAvailableCoinsWithGeneratedDust(state, currentTime);
115
145
  const selectedTokens = this.getCoinSelection()(dustTokens, feeLeft);
116
146
  if (!selectedTokens.length) {
@@ -133,49 +163,22 @@ export class TransactingCapabilityImplementation {
133
163
  return LedgerOps.ledgerTry(() => {
134
164
  const intent = Intent.new(ttl);
135
165
  const [spends, updatedState] = state.spendCoins(secretKey, tokensWithFeeToTake, currentTime);
136
- intent.dustActions = new DustActions(SignatureMarker.signature, ProofMarker.preProof, currentTime, spends, []);
166
+ intent.dustActions = new DustActions(SignatureMarker.signature, ProofMarker.preProof, currentTime, [...spends], []);
137
167
  const feeTransaction = Transaction.fromPartsRandomized(network, undefined, undefined, intent);
138
- return {
139
- newState: updatedState,
140
- recipe: {
141
- type: ProvingRecipe.TRANSACTION_TO_PROVE,
142
- transaction: transaction.merge(feeTransaction),
143
- },
144
- };
168
+ return [feeTransaction, updatedState];
145
169
  });
146
170
  }
147
- revert(state, tx) {
171
+ revertTransaction(state, transaction) {
148
172
  return Either.try({
149
- try: () => state.revertTransaction(tx),
173
+ try: () => state.revertTransaction(transaction),
150
174
  catch: (err) => {
151
175
  return new WalletError.OtherWalletError({
152
- message: `Error while reverting transaction ${tx.identifiers().at(0)}`,
176
+ message: `Error while reverting transaction ${transaction.identifiers().at(0)}`,
153
177
  cause: err,
154
178
  });
155
179
  },
156
180
  });
157
181
  }
158
- revertRecipe(state, recipe) {
159
- const doRevert = (tx) => {
160
- return Either.try({
161
- try: () => state.revertTransaction(tx),
162
- catch: (err) => {
163
- return new WalletError.OtherWalletError({
164
- message: `Error while reverting transaction ${tx.identifiers().at(0)}`,
165
- cause: err,
166
- });
167
- },
168
- });
169
- };
170
- switch (recipe.type) {
171
- case ProvingRecipe.TRANSACTION_TO_PROVE:
172
- return doRevert(recipe.transaction);
173
- case ProvingRecipe.BALANCE_TRANSACTION_TO_PROVE:
174
- return doRevert(recipe.transactionToProve);
175
- case ProvingRecipe.NOTHING_TO_PROVE:
176
- return Either.right(state);
177
- }
178
- }
179
182
  #parseAddress(addr) {
180
183
  return Either.try({
181
184
  try: () => {
@@ -6,7 +6,7 @@ import { SyncService, SyncCapability, DefaultSyncConfiguration, WalletSyncUpdate
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/index.d.ts CHANGED
@@ -7,3 +7,4 @@ export * as Transacting from './Transacting.js';
7
7
  export * from './RunningV1Variant.js';
8
8
  export * from './V1Builder.js';
9
9
  export * from './types/index.js';
10
+ export * as CoinsAndBalances from './CoinsAndBalances.js';
package/dist/index.js CHANGED
@@ -19,3 +19,4 @@ export * as Transacting from './Transacting.js';
19
19
  export * from './RunningV1Variant.js';
20
20
  export * from './V1Builder.js';
21
21
  export * from './types/index.js';
22
+ export * as CoinsAndBalances from './CoinsAndBalances.js';
@@ -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;
@@ -1,4 +1,4 @@
1
1
  import * as ledger from '@midnight-ntwrk/ledger-v7';
2
- export type AnyTransaction = ledger.UnprovenTransaction | ledger.FinalizedTransaction | ledger.ProofErasedTransaction;
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,6 +1,6 @@
1
1
  {
2
2
  "name": "@midnight-ntwrk/wallet-sdk-dust-wallet",
3
- "version": "1.0.0-beta.14",
3
+ "version": "1.0.0-beta.15",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -31,9 +31,9 @@
31
31
  "@midnight-ntwrk/wallet-sdk-indexer-client": "1.0.0-beta.16",
32
32
  "@midnight-ntwrk/wallet-sdk-node-client": "1.0.0-beta.12",
33
33
  "@midnight-ntwrk/wallet-sdk-prover-client": "1.0.0-beta.13",
34
- "@midnight-ntwrk/wallet-sdk-shielded": "1.0.0-beta.15",
34
+ "@midnight-ntwrk/wallet-sdk-shielded": "1.0.0-beta.16",
35
35
  "@midnight-ntwrk/wallet-sdk-utilities": "1.0.0-beta.10",
36
- "effect": "^3.17.3",
36
+ "effect": "^3.19.14",
37
37
  "rxjs": "^7.5"
38
38
  },
39
39
  "scripts": {