@dynamic-labs/aleo 4.79.2 → 4.80.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.
Files changed (29) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/package.cjs +1 -1
  3. package/package.js +1 -1
  4. package/package.json +10 -6
  5. package/src/connectors/DynamicWaasAleoConnector/DynamicWaasAleoConnector.cjs +798 -0
  6. package/src/connectors/DynamicWaasAleoConnector/DynamicWaasAleoConnector.d.ts +409 -0
  7. package/src/connectors/DynamicWaasAleoConnector/DynamicWaasAleoConnector.js +794 -0
  8. package/src/connectors/DynamicWaasAleoConnector/index.cjs +13 -0
  9. package/src/connectors/DynamicWaasAleoConnector/index.d.ts +3 -0
  10. package/src/connectors/DynamicWaasAleoConnector/index.js +9 -0
  11. package/src/connectors/WaasAleoWalletConnector/WaasAleoWalletConnector.cjs +216 -0
  12. package/src/connectors/WaasAleoWalletConnector/WaasAleoWalletConnector.d.ts +116 -0
  13. package/src/connectors/WaasAleoWalletConnector/WaasAleoWalletConnector.js +211 -0
  14. package/src/connectors/WaasAleoWalletConnector/index.d.ts +1 -0
  15. package/src/index.cjs +15 -0
  16. package/src/index.d.ts +5 -0
  17. package/src/index.js +7 -0
  18. package/src/utils/AleoUiTransaction/AleoUiTransaction.cjs +354 -0
  19. package/src/utils/AleoUiTransaction/AleoUiTransaction.d.ts +130 -0
  20. package/src/utils/AleoUiTransaction/AleoUiTransaction.js +350 -0
  21. package/src/utils/AleoUiTransaction/index.d.ts +2 -0
  22. package/src/utils/aleoSendableTokens/aleoSendableTokens.cjs +185 -0
  23. package/src/utils/aleoSendableTokens/aleoSendableTokens.d.ts +78 -0
  24. package/src/utils/aleoSendableTokens/aleoSendableTokens.js +175 -0
  25. package/src/utils/aleoSendableTokens/index.d.ts +2 -0
  26. package/src/utils/aleoShieldableTokens/aleoShieldableTokens.cjs +119 -0
  27. package/src/utils/aleoShieldableTokens/aleoShieldableTokens.d.ts +45 -0
  28. package/src/utils/aleoShieldableTokens/aleoShieldableTokens.js +114 -0
  29. package/src/utils/aleoShieldableTokens/index.d.ts +2 -0
@@ -0,0 +1,354 @@
1
+ 'use client'
2
+ 'use strict';
3
+
4
+ Object.defineProperty(exports, '__esModule', { value: true });
5
+
6
+ var _tslib = require('../../../_virtual/_tslib.cjs');
7
+ var utils = require('@dynamic-labs/utils');
8
+ var aleoSendableTokens = require('../aleoSendableTokens/aleoSendableTokens.cjs');
9
+
10
+ // `10n ** decimals` via string construction. Equivalent to `BigInt(10) **
11
+ // BigInt(decimals)` but avoids the TS2791 error in environments whose
12
+ // `target` predates es2016 (which is where rollup compiles this package).
13
+ const pow10 = (decimals) => BigInt(`1${'0'.repeat(decimals)}`);
14
+ // Aleo addresses are 63-character strings: `aleo1` prefix + 58 lowercase
15
+ // alphanumeric characters. We deliberately don't enforce the bech32m
16
+ // alphabet — Aleo's encoding admits a wider character set than standard
17
+ // bech32m (e.g. `o` appears in real testnet addresses). Format-level
18
+ // validation only — the on-chain transition rejects bad checksums with a
19
+ // clear error, so we don't pull the Provable WASM into the widget bundle
20
+ // for client-side checksum verification.
21
+ const ALEO_ADDRESS_REGEX = /^aleo1[a-z0-9]{58}$/;
22
+ /**
23
+ * Aleo `IUITransaction` for the widget's Send flow.
24
+ *
25
+ * Both supported modes spend FROM a private record (so the wallet's
26
+ * available balance is always the shielded record sum); they differ
27
+ * only in what the recipient receives:
28
+ *
29
+ * - **Individual** = `<program>/transfer_private` — recipient also gets
30
+ * a private record. The most common Aleo flow.
31
+ * - **Exchange** = `<program>/transfer_private_to_public` —
32
+ * recipient's *public* balance is incremented. Useful for off-ramps,
33
+ * exchange deposits, etc.
34
+ *
35
+ * The submit path branches on the **selected token's program kind**:
36
+ *
37
+ * - `credits` → `credits.aleo` transitions, 3 inputs `[record, recipient, amount]`.
38
+ * - `stablecoin` → `<stablecoin>.aleo` transitions, 3 inputs
39
+ * `[recipient, amount, record]`. The iframe appends a
40
+ * Sealance freeze-list exclusion proof (and its type)
41
+ * automatically — see `proveTransaction` in the iframe's
42
+ * Aleo client.
43
+ * - `arc21` → `token_registry.aleo` transitions, 3 inputs
44
+ * `[recipient, amount, record]`. The token_id is
45
+ * encoded inside the record's plaintext, so the
46
+ * transition signature does NOT include it as a
47
+ * separate argument — only the record carries it.
48
+ *
49
+ * In all kinds, the form auto-picks the smallest single record (filtered
50
+ * to the selected token) that covers the amount. If no single record
51
+ * fits, the form surfaces a merge CTA backed by `joinAllRecordsForToken`.
52
+ */
53
+ class AleoUiTransaction {
54
+ constructor({ from, networkId, listOwnedRecords, joinAllRecordsForToken, onSubmit, }) {
55
+ var _a;
56
+ this.chain = 'ALEO';
57
+ this.data = undefined;
58
+ this.fee = { gas: undefined };
59
+ this.transactionModes = [
60
+ {
61
+ icon: 'individual',
62
+ id: 'individual',
63
+ label: 'Individual',
64
+ },
65
+ {
66
+ icon: 'exchange',
67
+ id: 'exchange',
68
+ label: 'Exchange',
69
+ },
70
+ ];
71
+ // No default — the user must explicitly pick Individual or Exchange
72
+ // before submitting. Both modes spend from the same shielded balance,
73
+ // so the rest of the form stays interactive without a selection; we
74
+ // just gate the Preview/Submit button. Pre-selecting felt
75
+ // presumptuous given Individual vs. Exchange has real semantic
76
+ // differences (recipient gets a private record vs. public balance).
77
+ this.selectedTransactionMode = undefined;
78
+ this.from = from;
79
+ this.networkId = networkId;
80
+ this.listOwnedRecords = listOwnedRecords;
81
+ this.joinAllRecordsForToken = joinAllRecordsForToken;
82
+ this.onSubmitFn = onSubmit;
83
+ this.selectedToken = (_a = this.tokensForNetwork()[0]) !== null && _a !== void 0 ? _a : this.creditsFallback();
84
+ }
85
+ setTransactionMode(modeId) {
86
+ if (modeId !== 'exchange' && modeId !== 'individual')
87
+ return;
88
+ this.selectedTransactionMode = modeId;
89
+ }
90
+ setSelectedToken(contractAddress) {
91
+ const match = this.tokensForNetwork().find((t) => t.contractAddress === contractAddress);
92
+ if (match)
93
+ this.selectedToken = match;
94
+ }
95
+ setPendingAmount(amountInput) {
96
+ try {
97
+ this.pendingValue = this.parse(amountInput);
98
+ }
99
+ catch (_a) {
100
+ this.pendingValue = undefined;
101
+ }
102
+ }
103
+ /**
104
+ * Triggered by the form's "Merge records first" button. After this
105
+ * resolves the form re-evaluates `getRecordMergeAction`, so we drop the
106
+ * cached records first to force a fresh `listOwnedRecords` on the
107
+ * next call (the on-chain merge produced new records).
108
+ */
109
+ mergeRecordsForSelectedToken() {
110
+ return _tslib.__awaiter(this, void 0, void 0, function* () {
111
+ yield this.joinAllRecordsForToken(this.selectedToken);
112
+ this.cachedRecords = undefined;
113
+ });
114
+ }
115
+ getRecordMergeAction() {
116
+ // Both modes consume one private record, so the CTA fires for either
117
+ // selection when the user's largest single record (of the selected
118
+ // token) can't cover the amount. (Exchange = transfer_private_to_public
119
+ // also burns a record; the only difference is that the recipient gets
120
+ // public balance instead of a private record.)
121
+ if (this.pendingValue === undefined || this.pendingValue <= BigInt(0)) {
122
+ return undefined;
123
+ }
124
+ // We can only know "fits / doesn't fit" if we've loaded records at
125
+ // least once. The form refreshes the action on amount blur — by then
126
+ // the iframe has typically been pinged at least once (e.g. when
127
+ // `getBalance` ran), but we also have to handle the cold case where
128
+ // records haven't been fetched yet. Returning `undefined` here is
129
+ // safe: the form will re-check on blur after the user types again,
130
+ // and `listOwnedRecords` will be invoked from the submit path
131
+ // anyway. We choose to never block submit on an unknown — the worst
132
+ // case is the user clicks Preview, sees the underlying error, and
133
+ // clicks merge from there.
134
+ if (!this.cachedRecords)
135
+ return undefined;
136
+ const matching = this.cachedRecords.filter((r) => aleoSendableTokens.recordMatchesSendableToken(r, this.selectedToken));
137
+ const largest = matching.reduce((acc, r) => {
138
+ const v = aleoSendableTokens.extractRecordAtomicAmount(r, this.selectedToken);
139
+ return v > acc ? v : acc;
140
+ }, BigInt(0));
141
+ if (largest >= this.pendingValue)
142
+ return undefined;
143
+ // No single record fits. The CTA mirrors the language we use in the
144
+ // demo + the merge button we already shipped. Action delegates back
145
+ // to the connector via the closure injected at construction time.
146
+ const { symbol } = this.selectedToken;
147
+ return {
148
+ actionLabel: 'Merge records first',
149
+ message: `No single private record covers this amount. Largest is ${this.format(largest)} ${symbol}; you're sending ${this.format(this.pendingValue)} ${symbol}.`,
150
+ onAction: () => this.mergeRecordsForSelectedToken(),
151
+ };
152
+ }
153
+ /**
154
+ * Parses a human-readable amount (e.g. `"0.5"`) into atomic units using
155
+ * the *selected token's* decimals (credits = 6, stablecoin = 6, each
156
+ * ARC-21 token has its own — wETH = 18, etc.). BigInt math via integer
157
+ * multiplication keeps precision lossless up to `decimals` places.
158
+ */
159
+ parse(input) {
160
+ const { decimals } = this.selectedToken;
161
+ const trimmed = input.trim();
162
+ const re = new RegExp(`^(\\d+)(?:\\.(\\d{1,${decimals}}))?$`);
163
+ const match = re.exec(trimmed);
164
+ if (!match) {
165
+ throw new Error(`Invalid amount — expected up to ${decimals} decimal places.`);
166
+ }
167
+ const [, whole, fracRaw] = match;
168
+ const frac = (fracRaw !== null && fracRaw !== void 0 ? fracRaw : '').padEnd(decimals, '0');
169
+ return BigInt(whole) * pow10(decimals) + BigInt(frac);
170
+ }
171
+ // Formats an atomic-units bigint into a display string using the
172
+ // selected token's decimals. BigInt math throughout — Number() coercion
173
+ // on the whole atomic value would lose precision for high-decimal tokens
174
+ // (e.g. wETH at 18 decimals: 9 wETH ≈ 9·10¹⁸ atomic units, well past
175
+ // Number.MAX_SAFE_INTEGER).
176
+ format(value, { precision } = {}) {
177
+ const { decimals } = this.selectedToken;
178
+ if (decimals === 0) {
179
+ return utils.formatNumberText(value.toString(), { precision });
180
+ }
181
+ const negative = value < BigInt(0);
182
+ const abs = negative ? -value : value;
183
+ const divisor = pow10(decimals);
184
+ const wholePart = abs / divisor;
185
+ const fracPart = abs % divisor;
186
+ // Linear-time trailing-zero trim. Avoids `/0+$/` — anchored, bounded
187
+ // input, but the SAST tooling flags any `+`-quantified regex as
188
+ // ReDoS-prone, so we walk back manually.
189
+ const fracPadded = fracPart.toString().padStart(decimals, '0');
190
+ let fracEnd = fracPadded.length;
191
+ while (fracEnd > 0 && fracPadded[fracEnd - 1] === '0')
192
+ fracEnd -= 1;
193
+ const fracString = fracPadded.slice(0, fracEnd);
194
+ const sign = negative ? '-' : '';
195
+ const decimalString = fracString.length > 0
196
+ ? `${sign}${wholePart.toString()}.${fracString}`
197
+ : `${sign}${wholePart.toString()}`;
198
+ return utils.formatNumberText(decimalString, { precision });
199
+ }
200
+ validateAddressFormat(address) {
201
+ return ALEO_ADDRESS_REGEX.test(address);
202
+ }
203
+ /**
204
+ * Returns the user's *available* balance for the selected token in
205
+ * atomic units — the sum of unspent matching records. Both Send modes
206
+ * spend FROM records, so the displayed available balance is the same
207
+ * regardless of the toggle. Caches the record list so the merge CTA
208
+ * (and the auto-pick at submit time) can share it.
209
+ */
210
+ getBalance() {
211
+ return _tslib.__awaiter(this, void 0, void 0, function* () {
212
+ const records = yield this.refreshRecordsCache();
213
+ return records
214
+ .filter((r) => aleoSendableTokens.recordMatchesSendableToken(r, this.selectedToken))
215
+ .reduce((acc, r) => acc + aleoSendableTokens.extractRecordAtomicAmount(r, this.selectedToken), BigInt(0));
216
+ });
217
+ }
218
+ /**
219
+ * Feemaster sponsors `credits.aleo/transfer_public` and `transfer_private`
220
+ * per ANF's policy, so the user pays zero on credits sends. Stablecoin
221
+ * + ARC-21 sends today fall through to user-paid (Feemaster policy
222
+ * doesn't yet cover them on testnet); the iframe still completes the
223
+ * transfer, just deducts the credits-fee directly. The optimistic `0n`
224
+ * here matches what we tell the user via `isGasSponsored()` below.
225
+ */
226
+ fetchFee() {
227
+ return _tslib.__awaiter(this, void 0, void 0, function* () {
228
+ this.fee.gas = BigInt(0);
229
+ });
230
+ }
231
+ isGasSponsored() {
232
+ return this.selectedToken.programKind === 'credits';
233
+ }
234
+ /**
235
+ * Tells the SendBalanceView to populate the picker / "Available"
236
+ * display from the wallet's *shielded* balance per token — not from
237
+ * the redcoast public-balance fetch the form would otherwise use.
238
+ * Both Send modes (Individual = `transfer_private`, Exchange =
239
+ * `transfer_private_to_public`) consume a private record, so what
240
+ * the user can actually send is the records sum.
241
+ *
242
+ * Returns one entry per token in the network registry (credits +
243
+ * stablecoins always; mainnet additionally exposes the 5 ARC-21
244
+ * hyp_warp tokens). Tokens with zero matching records still appear so
245
+ * the user can see the full menu — picking a zero-balance token
246
+ * surfaces the merge / fund flow, not silently hides the option.
247
+ */
248
+ getSendableTokenBalances() {
249
+ return _tslib.__awaiter(this, void 0, void 0, function* () {
250
+ const records = yield this.refreshRecordsCache();
251
+ const tokens = this.tokensForNetwork();
252
+ return tokens.map((token) => {
253
+ var _a;
254
+ const sumAtomic = records
255
+ .filter((r) => aleoSendableTokens.recordMatchesSendableToken(r, token))
256
+ .reduce((acc, r) => acc + aleoSendableTokens.extractRecordAtomicAmount(r, token), BigInt(0));
257
+ const divisor = Number(pow10(token.decimals));
258
+ const rawBalance = Number(sumAtomic);
259
+ return {
260
+ address: token.contractAddress,
261
+ balance: rawBalance / divisor,
262
+ decimals: token.decimals,
263
+ // Every Aleo Send token uses the same record-spend mechanics and
264
+ // the same `transaction.parse` / `getBalance` / `submit` pipeline
265
+ // internally (decimals + program both come from `selectedToken`).
266
+ // The form's "non-native" branch was designed for EVM-style ERC-20
267
+ // tokens that need a separate `parseNonNativeToken` + a separate
268
+ // contract balance source — neither of which applies here. Marking
269
+ // every entry as native sends the form through `transaction.parse`
270
+ // + `transaction.getBalance`, which is exactly what we want for
271
+ // credits AND stablecoins AND ARC-21 alike. Not a hack — it's an
272
+ // accurate description of the form's contract for this chain.
273
+ isNative: true,
274
+ logoURI: (_a = token.logoURI) !== null && _a !== void 0 ? _a : '',
275
+ name: token.name,
276
+ rawBalance,
277
+ symbol: token.symbol,
278
+ };
279
+ });
280
+ });
281
+ }
282
+ submit() {
283
+ return _tslib.__awaiter(this, void 0, void 0, function* () {
284
+ if (!this.selectedTransactionMode) {
285
+ throw new Error('Pick Individual or Exchange before submitting an Aleo transfer.');
286
+ }
287
+ if (!this.to) {
288
+ throw new Error('Recipient address is required');
289
+ }
290
+ if (this.value === undefined) {
291
+ throw new Error('Amount is required');
292
+ }
293
+ // Both modes consume one private record. Pick the smallest record of
294
+ // the SELECTED token that covers `value` for minimal change-record
295
+ // fragmentation. If none fits we throw — the form should have already
296
+ // shown the merge CTA, but we keep the safety net so a stale form
297
+ // state can't slip a doomed transaction past us.
298
+ const targetValue = this.value;
299
+ const records = yield this.refreshRecordsCache();
300
+ const fitting = records
301
+ .filter((r) => aleoSendableTokens.recordMatchesSendableToken(r, this.selectedToken) &&
302
+ typeof r.record_plaintext === 'string')
303
+ .map((r) => ({
304
+ atomic: aleoSendableTokens.extractRecordAtomicAmount(r, this.selectedToken),
305
+ plaintext: r.record_plaintext,
306
+ }))
307
+ .filter((r) => r.atomic >= targetValue)
308
+ .sort((a, b) => {
309
+ if (a.atomic < b.atomic)
310
+ return -1;
311
+ if (a.atomic > b.atomic)
312
+ return 1;
313
+ return 0;
314
+ });
315
+ if (fitting.length === 0) {
316
+ throw new Error('No single private record covers this amount. Merge records first.');
317
+ }
318
+ return this.onSubmitFn({
319
+ mode: this.selectedTransactionMode,
320
+ recordPlaintext: fitting[0].plaintext,
321
+ to: this.to,
322
+ token: this.selectedToken,
323
+ value: this.value,
324
+ });
325
+ });
326
+ }
327
+ refreshRecordsCache() {
328
+ return _tslib.__awaiter(this, void 0, void 0, function* () {
329
+ const records = yield this.listOwnedRecords();
330
+ this.cachedRecords = records;
331
+ return records;
332
+ });
333
+ }
334
+ tokensForNetwork() {
335
+ return aleoSendableTokens.getAleoSendableTokensForNetwork(this.networkId);
336
+ }
337
+ // Last-resort default when the network registry is empty (shouldn't
338
+ // happen in practice — both supported networks include credits).
339
+ creditsFallback() {
340
+ return {
341
+ contractAddress: aleoSendableTokens.ALEO_CREDITS_PROGRAM,
342
+ decimals: aleoSendableTokens.ALEO_CREDITS_DECIMALS,
343
+ logoURI: '',
344
+ name: 'Aleo Credits',
345
+ programId: aleoSendableTokens.ALEO_CREDITS_PROGRAM,
346
+ programKind: 'credits',
347
+ recordName: 'credits',
348
+ recordTypeLiteral: 'credits.record',
349
+ symbol: 'ALEO',
350
+ };
351
+ }
352
+ }
353
+
354
+ exports.AleoUiTransaction = AleoUiTransaction;
@@ -0,0 +1,130 @@
1
+ import { TokenBalance } from '@dynamic-labs/sdk-api-core';
2
+ import { IUITransaction, IUITransactionFormatOptions, RecordMergeAction, TransactionModeOption } from '@dynamic-labs/types';
3
+ import { AleoOwnedRecord, AleoSendableToken } from '../aleoSendableTokens';
4
+ export type AleoTransferMode = 'exchange' | 'individual';
5
+ export type AleoSubmitParams = {
6
+ to: string;
7
+ value: bigint;
8
+ mode: AleoTransferMode;
9
+ recordPlaintext: string;
10
+ token: AleoSendableToken;
11
+ };
12
+ type AleoUiTransactionProps = {
13
+ /** The sender's `aleo1...` address. */
14
+ from: string;
15
+ networkId: number;
16
+ listOwnedRecords: () => Promise<AleoOwnedRecord[]>;
17
+ joinAllRecordsForToken: (token: AleoSendableToken) => Promise<void>;
18
+ onSubmit: (params: AleoSubmitParams) => Promise<string>;
19
+ };
20
+ /**
21
+ * Aleo `IUITransaction` for the widget's Send flow.
22
+ *
23
+ * Both supported modes spend FROM a private record (so the wallet's
24
+ * available balance is always the shielded record sum); they differ
25
+ * only in what the recipient receives:
26
+ *
27
+ * - **Individual** = `<program>/transfer_private` — recipient also gets
28
+ * a private record. The most common Aleo flow.
29
+ * - **Exchange** = `<program>/transfer_private_to_public` —
30
+ * recipient's *public* balance is incremented. Useful for off-ramps,
31
+ * exchange deposits, etc.
32
+ *
33
+ * The submit path branches on the **selected token's program kind**:
34
+ *
35
+ * - `credits` → `credits.aleo` transitions, 3 inputs `[record, recipient, amount]`.
36
+ * - `stablecoin` → `<stablecoin>.aleo` transitions, 3 inputs
37
+ * `[recipient, amount, record]`. The iframe appends a
38
+ * Sealance freeze-list exclusion proof (and its type)
39
+ * automatically — see `proveTransaction` in the iframe's
40
+ * Aleo client.
41
+ * - `arc21` → `token_registry.aleo` transitions, 3 inputs
42
+ * `[recipient, amount, record]`. The token_id is
43
+ * encoded inside the record's plaintext, so the
44
+ * transition signature does NOT include it as a
45
+ * separate argument — only the record carries it.
46
+ *
47
+ * In all kinds, the form auto-picks the smallest single record (filtered
48
+ * to the selected token) that covers the amount. If no single record
49
+ * fits, the form surfaces a merge CTA backed by `joinAllRecordsForToken`.
50
+ */
51
+ export declare class AleoUiTransaction implements IUITransaction {
52
+ chain: string;
53
+ to: string | undefined;
54
+ from: string;
55
+ value: bigint | undefined;
56
+ data: string | undefined;
57
+ receipt: string | undefined;
58
+ fee: {
59
+ gas: bigint | undefined;
60
+ };
61
+ nativePrice?: number;
62
+ readonly transactionModes: TransactionModeOption[];
63
+ selectedTransactionMode: AleoTransferMode | undefined;
64
+ private readonly networkId;
65
+ private readonly listOwnedRecords;
66
+ private readonly joinAllRecordsForToken;
67
+ private readonly onSubmitFn;
68
+ private pendingValue;
69
+ private cachedRecords;
70
+ private selectedToken;
71
+ constructor({ from, networkId, listOwnedRecords, joinAllRecordsForToken, onSubmit, }: AleoUiTransactionProps);
72
+ setTransactionMode(modeId: string): void;
73
+ setSelectedToken(contractAddress: string): void;
74
+ setPendingAmount(amountInput: string): void;
75
+ /**
76
+ * Triggered by the form's "Merge records first" button. After this
77
+ * resolves the form re-evaluates `getRecordMergeAction`, so we drop the
78
+ * cached records first to force a fresh `listOwnedRecords` on the
79
+ * next call (the on-chain merge produced new records).
80
+ */
81
+ private mergeRecordsForSelectedToken;
82
+ getRecordMergeAction(): RecordMergeAction | undefined;
83
+ /**
84
+ * Parses a human-readable amount (e.g. `"0.5"`) into atomic units using
85
+ * the *selected token's* decimals (credits = 6, stablecoin = 6, each
86
+ * ARC-21 token has its own — wETH = 18, etc.). BigInt math via integer
87
+ * multiplication keeps precision lossless up to `decimals` places.
88
+ */
89
+ parse(input: string): bigint;
90
+ format(value: bigint, { precision }?: IUITransactionFormatOptions): string;
91
+ validateAddressFormat(address: string): boolean;
92
+ /**
93
+ * Returns the user's *available* balance for the selected token in
94
+ * atomic units — the sum of unspent matching records. Both Send modes
95
+ * spend FROM records, so the displayed available balance is the same
96
+ * regardless of the toggle. Caches the record list so the merge CTA
97
+ * (and the auto-pick at submit time) can share it.
98
+ */
99
+ getBalance(): Promise<bigint>;
100
+ /**
101
+ * Feemaster sponsors `credits.aleo/transfer_public` and `transfer_private`
102
+ * per ANF's policy, so the user pays zero on credits sends. Stablecoin
103
+ * + ARC-21 sends today fall through to user-paid (Feemaster policy
104
+ * doesn't yet cover them on testnet); the iframe still completes the
105
+ * transfer, just deducts the credits-fee directly. The optimistic `0n`
106
+ * here matches what we tell the user via `isGasSponsored()` below.
107
+ */
108
+ fetchFee(): Promise<void>;
109
+ isGasSponsored(): boolean;
110
+ /**
111
+ * Tells the SendBalanceView to populate the picker / "Available"
112
+ * display from the wallet's *shielded* balance per token — not from
113
+ * the redcoast public-balance fetch the form would otherwise use.
114
+ * Both Send modes (Individual = `transfer_private`, Exchange =
115
+ * `transfer_private_to_public`) consume a private record, so what
116
+ * the user can actually send is the records sum.
117
+ *
118
+ * Returns one entry per token in the network registry (credits +
119
+ * stablecoins always; mainnet additionally exposes the 5 ARC-21
120
+ * hyp_warp tokens). Tokens with zero matching records still appear so
121
+ * the user can see the full menu — picking a zero-balance token
122
+ * surfaces the merge / fund flow, not silently hides the option.
123
+ */
124
+ getSendableTokenBalances(): Promise<TokenBalance[]>;
125
+ submit(): Promise<string>;
126
+ private refreshRecordsCache;
127
+ private tokensForNetwork;
128
+ private creditsFallback;
129
+ }
130
+ export {};