@dynamic-labs/aleo 4.80.0 → 4.82.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +38 -0
- package/package.cjs +1 -1
- package/package.js +1 -1
- package/package.json +8 -8
- package/src/connectors/DynamicWaasAleoConnector/DynamicWaasAleoConnector.cjs +159 -1
- package/src/connectors/DynamicWaasAleoConnector/DynamicWaasAleoConnector.d.ts +26 -0
- package/src/connectors/DynamicWaasAleoConnector/DynamicWaasAleoConnector.js +159 -1
- package/src/connectors/WaasAleoWalletConnector/WaasAleoWalletConnector.cjs +16 -0
- package/src/connectors/WaasAleoWalletConnector/WaasAleoWalletConnector.d.ts +8 -0
- package/src/connectors/WaasAleoWalletConnector/WaasAleoWalletConnector.js +16 -0
- package/src/index.cjs +2 -0
- package/src/index.d.ts +1 -0
- package/src/index.js +1 -0
- package/src/utils/AleoUiTransaction/AleoUiTransaction.cjs +12 -6
- package/src/utils/AleoUiTransaction/AleoUiTransaction.d.ts +12 -6
- package/src/utils/AleoUiTransaction/AleoUiTransaction.js +12 -6
- package/src/utils/getAleoExplorerTxUrl/getAleoExplorerTxUrl.cjs +41 -0
- package/src/utils/getAleoExplorerTxUrl/getAleoExplorerTxUrl.d.ts +11 -0
- package/src/utils/getAleoExplorerTxUrl/getAleoExplorerTxUrl.js +37 -0
- package/src/utils/getAleoExplorerTxUrl/index.d.ts +1 -0
- package/src/wallet/AleoWallet/AleoWallet.cjs +131 -0
- package/src/wallet/AleoWallet/AleoWallet.d.ts +101 -0
- package/src/wallet/AleoWallet/AleoWallet.js +131 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,4 +1,42 @@
|
|
|
1
1
|
|
|
2
|
+
## [4.82.0](https://github.com/dynamic-labs/dynamic-auth/compare/v4.81.0...v4.82.0) (2026-05-11)
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
### Features
|
|
6
|
+
|
|
7
|
+
* adds react-native embedded webview ([#11168](https://github.com/dynamic-labs/dynamic-auth/issues/11168)) ([31c17e3](https://github.com/dynamic-labs/dynamic-auth/commit/31c17e34e198efc806299011ab286bf48a244908))
|
|
8
|
+
* **aleo:** expose WaaS-specific methods directly on AleoWallet ([#11174](https://github.com/dynamic-labs/dynamic-auth/issues/11174)) ([ccfb8f4](https://github.com/dynamic-labs/dynamic-auth/commit/ccfb8f4de690ee4a30b6c20e037fef51a69df8e1))
|
|
9
|
+
* **aleo:** two-step Exchange Send (unshield → public→public) ([#11172](https://github.com/dynamic-labs/dynamic-auth/issues/11172)) ([02a992c](https://github.com/dynamic-labs/dynamic-auth/commit/02a992c3239519ed283a9804f092bffca9ba4d18))
|
|
10
|
+
* **demo:** registry-driven Aleo transactions form ([#11105](https://github.com/dynamic-labs/dynamic-auth/issues/11105)) ([766949e](https://github.com/dynamic-labs/dynamic-auth/commit/766949e7bb9f613e157418ed4221cac43fbf0394))
|
|
11
|
+
* **sdk-react-core:** add ActiveMidnightWalletAddresses widget ([#11083](https://github.com/dynamic-labs/dynamic-auth/issues/11083)) ([1858292](https://github.com/dynamic-labs/dynamic-auth/commit/18582926348420332f89a3d1b2c2ca2cd453f69e))
|
|
12
|
+
* **widget:** auto-merge + auto-shield sponsored Aleo tokens on wallet load ([#11157](https://github.com/dynamic-labs/dynamic-auth/issues/11157)) ([cda1de1](https://github.com/dynamic-labs/dynamic-auth/commit/cda1de1f04789eb24bba2fbe0a49b5f42f6a609d))
|
|
13
|
+
* **widget:** auto-shield indicator + post-shield balance refresh polling ([#11173](https://github.com/dynamic-labs/dynamic-auth/issues/11173)) ([f49d480](https://github.com/dynamic-labs/dynamic-auth/commit/f49d480dc5ef85efd7d201687d9b0309090a69c8))
|
|
14
|
+
* **widget:** wire Aleo curated prices into the Shielded balance tab ([#11178](https://github.com/dynamic-labs/dynamic-auth/issues/11178)) ([eab1606](https://github.com/dynamic-labs/dynamic-auth/commit/eab16062140a0474d14a2cc43fd0a1624e4da92e))
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
### Bug Fixes
|
|
18
|
+
|
|
19
|
+
* **ci:** wire dd-trace ci visibility env vars for [@demov1](https://github.com/demov1) playwright task ([#11199](https://github.com/dynamic-labs/dynamic-auth/issues/11199)) ([9af4827](https://github.com/dynamic-labs/dynamic-auth/commit/9af48271e4721dac54d495097d43522f76ec724d))
|
|
20
|
+
* **playwright:** expose raw auth token for stable JWT reads ([#11204](https://github.com/dynamic-labs/dynamic-auth/issues/11204)) ([b002dfb](https://github.com/dynamic-labs/dynamic-auth/commit/b002dfb642755830c6c9c813ebb4d749882518d6))
|
|
21
|
+
* **playwright:** replace waitForTimeout in networkControl + reinitialize spec ([#11161](https://github.com/dynamic-labs/dynamic-auth/issues/11161)) ([5e72371](https://github.com/dynamic-labs/dynamic-auth/commit/5e723713ceb8c804d253c261be86abb997daeabd))
|
|
22
|
+
* remediate high-severity dependency vulnerabilities ([#11171](https://github.com/dynamic-labs/dynamic-auth/issues/11171)) ([285e7cb](https://github.com/dynamic-labs/dynamic-auth/commit/285e7cb0d07f957a97e8d9ef4fab0b8d2d24e031))
|
|
23
|
+
|
|
24
|
+
## [4.81.0](https://github.com/dynamic-labs/dynamic-auth/compare/v4.80.0...v4.81.0) (2026-05-07)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
### Features
|
|
28
|
+
|
|
29
|
+
* **react-native:** add waitForAuthSuccess() to auth module ([#11137](https://github.com/dynamic-labs/dynamic-auth/issues/11137)) ([089a566](https://github.com/dynamic-labs/dynamic-auth/commit/089a5663283639e7e425eead291b135010c8b398))
|
|
30
|
+
* **waas:** hook Aleo into DynamicWaasMixin ([#11102](https://github.com/dynamic-labs/dynamic-auth/issues/11102)) ([ff42df9](https://github.com/dynamic-labs/dynamic-auth/commit/ff42df99d8993e22894caee3c0570cd9c332a3d1))
|
|
31
|
+
* **widget:** shielded/unshielded tabs + Shield Manually CTA on ActiveWalletBalance for Aleo ([#11103](https://github.com/dynamic-labs/dynamic-auth/issues/11103)) ([e278836](https://github.com/dynamic-labs/dynamic-auth/commit/e278836bfcb19c13828c10483ebb87d165f5d00d))
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
### Bug Fixes
|
|
35
|
+
|
|
36
|
+
* **ethereum-aa:** return hex chain ids from EIP-5792 getCapabilities ([#11146](https://github.com/dynamic-labs/dynamic-auth/issues/11146)) ([b32dc8f](https://github.com/dynamic-labs/dynamic-auth/commit/b32dc8f6fdee3722073921787c4f77908ab4f740))
|
|
37
|
+
* remediate high-severity dependency vulnerabilities ([#11151](https://github.com/dynamic-labs/dynamic-auth/issues/11151)) ([1d84ef1](https://github.com/dynamic-labs/dynamic-auth/commit/1d84ef12e10544be0b2a80dbbbd63f615b03adc3))
|
|
38
|
+
* **wagmi-connector:** emit change unconditionally on MM accountsChanged DYNT-549 ([#11131](https://github.com/dynamic-labs/dynamic-auth/issues/11131)) ([348ee6f](https://github.com/dynamic-labs/dynamic-auth/commit/348ee6ff9a22cb55ef0cb84c4b8f8d2e843bd10e)), closes [#11043](https://github.com/dynamic-labs/dynamic-auth/issues/11043)
|
|
39
|
+
|
|
2
40
|
## [4.80.0](https://github.com/dynamic-labs/dynamic-auth/compare/v4.79.2...v4.80.0) (2026-05-05)
|
|
3
41
|
|
|
4
42
|
|
package/package.cjs
CHANGED
package/package.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dynamic-labs/aleo",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.82.0",
|
|
4
4
|
"description": "A React SDK for implementing wallet web3 authentication and authorization to your website.",
|
|
5
5
|
"author": "Dynamic Labs, Inc.",
|
|
6
6
|
"license": "MIT",
|
|
@@ -19,18 +19,18 @@
|
|
|
19
19
|
"homepage": "https://www.dynamic.xyz/",
|
|
20
20
|
"dependencies": {
|
|
21
21
|
"@dynamic-labs-sdk/client": "0.26.9",
|
|
22
|
-
"@dynamic-labs/assert-package-version": "4.
|
|
22
|
+
"@dynamic-labs/assert-package-version": "4.82.0",
|
|
23
23
|
"@dynamic-labs/sdk-api-core": "0.0.964",
|
|
24
24
|
"@provablehq/aleo-wallet-adaptor-core": "0.3.0-alpha.3",
|
|
25
25
|
"@provablehq/aleo-wallet-adaptor-shield": "0.3.0-alpha.3",
|
|
26
26
|
"@provablehq/aleo-wallet-standard": "0.3.0-alpha.3",
|
|
27
27
|
"@provablehq/aleo-types": "0.3.0-alpha.3",
|
|
28
|
-
"@dynamic-labs/logger": "4.
|
|
29
|
-
"@dynamic-labs/types": "4.
|
|
30
|
-
"@dynamic-labs/utils": "4.
|
|
31
|
-
"@dynamic-labs/waas": "4.
|
|
32
|
-
"@dynamic-labs/wallet-book": "4.
|
|
33
|
-
"@dynamic-labs/wallet-connector-core": "4.
|
|
28
|
+
"@dynamic-labs/logger": "4.82.0",
|
|
29
|
+
"@dynamic-labs/types": "4.82.0",
|
|
30
|
+
"@dynamic-labs/utils": "4.82.0",
|
|
31
|
+
"@dynamic-labs/waas": "4.82.0",
|
|
32
|
+
"@dynamic-labs/wallet-book": "4.82.0",
|
|
33
|
+
"@dynamic-labs/wallet-connector-core": "4.82.0"
|
|
34
34
|
},
|
|
35
35
|
"peerDependencies": {}
|
|
36
36
|
}
|
|
@@ -99,6 +99,46 @@ const buildTransferInputs = (args) => {
|
|
|
99
99
|
inputs: [to, `${value.toString()}u128`, recordPlaintext],
|
|
100
100
|
};
|
|
101
101
|
};
|
|
102
|
+
/**
|
|
103
|
+
* Builds the `(functionName, inputs, inputTypes)` triple for a
|
|
104
|
+
* `<program>/transfer_public` public-to-public transfer. Used as step 2
|
|
105
|
+
* of the Exchange flow (after step 1 unshield-to-self). `transfer_public`
|
|
106
|
+
* is NOT in the iframe's `SEALANCE_FUNCTIONS_REQUIRING_PROOF` set, so the
|
|
107
|
+
* caller controls inputs end-to-end (no Sealance proof injection).
|
|
108
|
+
*
|
|
109
|
+
* - `credits` u64. inputs `[recipient, amount]`.
|
|
110
|
+
* - `stablecoin` u128. inputs `[recipient, amount]`.
|
|
111
|
+
* - `arc21` u128. inputs `[token_id, recipient, amount]`. The
|
|
112
|
+
* `token_registry.aleo/transfer_public` transition keys
|
|
113
|
+
* off `token_id` since there's no record to encode it in.
|
|
114
|
+
*/
|
|
115
|
+
const buildPublicTransferInputs = (args) => {
|
|
116
|
+
const { to, value, token } = args;
|
|
117
|
+
const functionName = 'transfer_public';
|
|
118
|
+
if (token.programKind === 'credits') {
|
|
119
|
+
return {
|
|
120
|
+
functionName,
|
|
121
|
+
inputTypes: ['address.public', 'u64.public'],
|
|
122
|
+
inputs: [to, `${value.toString()}u64`],
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
if (token.programKind === 'stablecoin') {
|
|
126
|
+
return {
|
|
127
|
+
functionName,
|
|
128
|
+
inputTypes: ['address.public', 'u128.public'],
|
|
129
|
+
inputs: [to, `${value.toString()}u128`],
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
// arc21 — token_registry.aleo/transfer_public(token_id, recipient, amount).
|
|
133
|
+
if (!token.tokenId) {
|
|
134
|
+
throw new utils.DynamicError(`transfer_public: ARC-21 token ${token.contractAddress} is missing tokenId in registry.`);
|
|
135
|
+
}
|
|
136
|
+
return {
|
|
137
|
+
functionName,
|
|
138
|
+
inputTypes: ['field.public', 'address.public', 'u128.public'],
|
|
139
|
+
inputs: [token.tokenId, to, `${value.toString()}u128`],
|
|
140
|
+
};
|
|
141
|
+
};
|
|
102
142
|
/**
|
|
103
143
|
* Builds the `(functionName, inputs, inputTypes)` triple for a
|
|
104
144
|
* `<program>/transfer_public_to_private` shield call to self. Mirrors
|
|
@@ -156,6 +196,16 @@ const joinShapeForProgram = (programId) => {
|
|
|
156
196
|
}
|
|
157
197
|
return shape;
|
|
158
198
|
};
|
|
199
|
+
// Two-step Exchange flow timing. Step 1 (`transfer_private_to_public` to
|
|
200
|
+
// self) needs to surface in the user's public balance before step 2
|
|
201
|
+
// (`transfer_public` to the exchange) can spend it. Aleo block time is
|
|
202
|
+
// ~10s plus a finalize phase; we wait `STEP1_INITIAL_DELAY_MS` and then
|
|
203
|
+
// retry step 2 up to `STEP2_MAX_RETRIES` times with a fixed backoff.
|
|
204
|
+
// The most likely retryable failure is "insufficient public balance"
|
|
205
|
+
// if step 1 hasn't finalized yet.
|
|
206
|
+
const EXCHANGE_STEP1_INITIAL_DELAY_MS = 15000;
|
|
207
|
+
const EXCHANGE_STEP2_MAX_RETRIES = 3;
|
|
208
|
+
const EXCHANGE_STEP2_RETRY_DELAY_MS = 10000;
|
|
159
209
|
const hasUsableRecordShape = (r) => {
|
|
160
210
|
const rec = r;
|
|
161
211
|
return (typeof (rec === null || rec === void 0 ? void 0 : rec.record_plaintext) === 'string' &&
|
|
@@ -177,6 +227,12 @@ class DynamicWaasAleoConnector extends waas.withDynamicWaas(WaasAleoWalletConnec
|
|
|
177
227
|
this.overrideKey = 'dynamicwaas';
|
|
178
228
|
this.isEmbeddedWallet = true;
|
|
179
229
|
this.logger = new logger.Logger('DynamicWaasAleoConnector');
|
|
230
|
+
// Programs whose Exchange flow is mid-orchestration (between step 1
|
|
231
|
+
// unshield-to-self and step 2 public-to-public). The auto-shield hook
|
|
232
|
+
// consults `canShieldToken` per balance refresh — gating shield here
|
|
233
|
+
// prevents the hook from re-shielding the just-unshielded amount before
|
|
234
|
+
// step 2 spends it. Add on Exchange entry, remove in `finally`.
|
|
235
|
+
this.tokensPendingExchange = new Set();
|
|
180
236
|
this.walletUiUtils = props.walletUiUtils;
|
|
181
237
|
}
|
|
182
238
|
setVerifiedCredentials(verifiedCredentials) {
|
|
@@ -633,6 +689,15 @@ class DynamicWaasAleoConnector extends waas.withDynamicWaas(WaasAleoWalletConnec
|
|
|
633
689
|
// which validateActiveWallet has already aligned with `from`.
|
|
634
690
|
// Setting it explicitly keeps the contract obvious to readers.
|
|
635
691
|
this.activeAccountAddress = from;
|
|
692
|
+
if (mode === 'exchange') {
|
|
693
|
+
return this.submitExchangeTransfer({
|
|
694
|
+
from,
|
|
695
|
+
recordPlaintext,
|
|
696
|
+
to,
|
|
697
|
+
token,
|
|
698
|
+
value,
|
|
699
|
+
});
|
|
700
|
+
}
|
|
636
701
|
const { functionName, inputs, inputTypes } = buildTransferInputs({
|
|
637
702
|
mode,
|
|
638
703
|
recordPlaintext,
|
|
@@ -668,7 +733,15 @@ class DynamicWaasAleoConnector extends waas.withDynamicWaas(WaasAleoWalletConnec
|
|
|
668
733
|
* `credits.aleo` entry when the literal address misses.
|
|
669
734
|
*/
|
|
670
735
|
canShieldToken(token) {
|
|
671
|
-
|
|
736
|
+
const resolved = this.resolveShieldableToken(token);
|
|
737
|
+
if (!resolved)
|
|
738
|
+
return false;
|
|
739
|
+
// While an Exchange flow for this program is mid-orchestration the
|
|
740
|
+
// user's public balance is transient — auto-shield must not consume
|
|
741
|
+
// it before step 2's public→public transfer.
|
|
742
|
+
if (this.tokensPendingExchange.has(resolved.programId))
|
|
743
|
+
return false;
|
|
744
|
+
return true;
|
|
672
745
|
}
|
|
673
746
|
/**
|
|
674
747
|
* True when the Feemaster currently sponsors a shield (
|
|
@@ -781,6 +854,91 @@ class DynamicWaasAleoConnector extends waas.withDynamicWaas(WaasAleoWalletConnec
|
|
|
781
854
|
return result.txId;
|
|
782
855
|
});
|
|
783
856
|
}
|
|
857
|
+
/**
|
|
858
|
+
* Two-step Exchange transfer.
|
|
859
|
+
*
|
|
860
|
+
* Step 1: `<program>/transfer_private_to_public(record, SELF, amount)`
|
|
861
|
+
* — unshield the record into the user's *own* public balance.
|
|
862
|
+
* Step 2: `<program>/transfer_public(EXCHANGE, amount)`
|
|
863
|
+
* — public→public from the user to the exchange recipient.
|
|
864
|
+
*
|
|
865
|
+
* `tokensPendingExchange` gates `canShieldToken` for the duration of
|
|
866
|
+
* the orchestration so the auto-shield hook does not consume the
|
|
867
|
+
* just-unshielded amount before step 2 spends it. The set is cleared
|
|
868
|
+
* in `finally` regardless of outcome.
|
|
869
|
+
*
|
|
870
|
+
* Step 2 is retried on failure because Aleo's finalize phase can lag
|
|
871
|
+
* the broadcast — until step 1 has finalized, step 2 reads stale public
|
|
872
|
+
* balance and the validator rejects it. We wait
|
|
873
|
+
* `EXCHANGE_STEP1_INITIAL_DELAY_MS` first and then retry up to
|
|
874
|
+
* `EXCHANGE_STEP2_MAX_RETRIES` times. If all retries exhaust, we throw a
|
|
875
|
+
* `DynamicError` that explicitly tells the user step 1 succeeded so they
|
|
876
|
+
* can recover the funds via a manual public→public transfer.
|
|
877
|
+
*
|
|
878
|
+
* Step 2's txId is returned as the user-facing transaction id (it's the
|
|
879
|
+
* one that lands the funds at the exchange).
|
|
880
|
+
*/
|
|
881
|
+
submitExchangeTransfer(args) {
|
|
882
|
+
return _tslib.__awaiter(this, void 0, void 0, function* () {
|
|
883
|
+
var _a, _b, _c, _d, _e, _f;
|
|
884
|
+
const { from, to, value, recordPlaintext, token } = args;
|
|
885
|
+
this.tokensPendingExchange.add(token.programId);
|
|
886
|
+
try {
|
|
887
|
+
// --- Step 1: unshield record → self's public balance ---
|
|
888
|
+
const step1Build = buildTransferInputs({
|
|
889
|
+
mode: 'exchange',
|
|
890
|
+
recordPlaintext,
|
|
891
|
+
to: from,
|
|
892
|
+
token,
|
|
893
|
+
value,
|
|
894
|
+
});
|
|
895
|
+
const step1Result = yield this.proveTransaction({
|
|
896
|
+
broadcast: true,
|
|
897
|
+
functionName: step1Build.functionName,
|
|
898
|
+
inputTypes: step1Build.inputTypes,
|
|
899
|
+
inputs: step1Build.inputs,
|
|
900
|
+
programId: token.programId,
|
|
901
|
+
});
|
|
902
|
+
if (!step1Result.txId) {
|
|
903
|
+
throw new utils.DynamicError('Aleo Exchange step 1 (unshield) did not return a transaction id.');
|
|
904
|
+
}
|
|
905
|
+
(_b = (_a = this.logger).debug) === null || _b === void 0 ? void 0 : _b.call(_a, `[exchangeTransfer:${token.programId}] step 1 (unshield) tx: ${step1Result.txId}`);
|
|
906
|
+
// Wait for step 1 to finalize and surface in public balance before
|
|
907
|
+
// attempting step 2. See `EXCHANGE_STEP1_INITIAL_DELAY_MS` notes.
|
|
908
|
+
yield new Promise((resolve) => setTimeout(resolve, EXCHANGE_STEP1_INITIAL_DELAY_MS));
|
|
909
|
+
// --- Step 2: public→public self → exchange ---
|
|
910
|
+
const step2Build = buildPublicTransferInputs({ to, token, value });
|
|
911
|
+
let lastErr;
|
|
912
|
+
for (let attempt = 0; attempt <= EXCHANGE_STEP2_MAX_RETRIES; attempt += 1) {
|
|
913
|
+
try {
|
|
914
|
+
const step2Result = yield this.proveTransaction({
|
|
915
|
+
broadcast: true,
|
|
916
|
+
functionName: step2Build.functionName,
|
|
917
|
+
inputTypes: step2Build.inputTypes,
|
|
918
|
+
inputs: step2Build.inputs,
|
|
919
|
+
programId: token.programId,
|
|
920
|
+
});
|
|
921
|
+
if (!step2Result.txId) {
|
|
922
|
+
throw new utils.DynamicError('Aleo Exchange step 2 (public transfer) did not return a transaction id.');
|
|
923
|
+
}
|
|
924
|
+
(_d = (_c = this.logger).debug) === null || _d === void 0 ? void 0 : _d.call(_c, `[exchangeTransfer:${token.programId}] step 2 (public transfer) tx: ${step2Result.txId}`);
|
|
925
|
+
return step2Result.txId;
|
|
926
|
+
}
|
|
927
|
+
catch (err) {
|
|
928
|
+
lastErr = err;
|
|
929
|
+
(_f = (_e = this.logger).debug) === null || _f === void 0 ? void 0 : _f.call(_e, `[exchangeTransfer:${token.programId}] step 2 attempt ${attempt + 1} failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
930
|
+
if (attempt < EXCHANGE_STEP2_MAX_RETRIES) {
|
|
931
|
+
yield new Promise((resolve) => setTimeout(resolve, EXCHANGE_STEP2_RETRY_DELAY_MS));
|
|
932
|
+
}
|
|
933
|
+
}
|
|
934
|
+
}
|
|
935
|
+
throw new utils.DynamicError(`Aleo Exchange step 2 (public transfer) failed after ${EXCHANGE_STEP2_MAX_RETRIES + 1} attempts. Step 1 unshield (tx ${step1Result.txId}) succeeded — your funds are now in your public balance and can be sent to the exchange via a manual public transfer. Last error: ${lastErr instanceof Error ? lastErr.message : String(lastErr)}`);
|
|
936
|
+
}
|
|
937
|
+
finally {
|
|
938
|
+
this.tokensPendingExchange.delete(token.programId);
|
|
939
|
+
}
|
|
940
|
+
});
|
|
941
|
+
}
|
|
784
942
|
endSession(reason) {
|
|
785
943
|
const _super = Object.create(null, {
|
|
786
944
|
endSession: { get: () => super.endSession }
|
|
@@ -175,6 +175,7 @@ export declare class DynamicWaasAleoConnector extends DynamicWaasAleoConnector_b
|
|
|
175
175
|
activeAccountAddress: string | undefined;
|
|
176
176
|
verifiedCredentials: JwtVerifiedCredential[] | undefined;
|
|
177
177
|
protected walletUiUtils: WalletUiUtils<InternalWalletConnector>;
|
|
178
|
+
private readonly tokensPendingExchange;
|
|
178
179
|
constructor(props: DynamicWaasAleoConnectorProps);
|
|
179
180
|
setVerifiedCredentials(verifiedCredentials: JwtVerifiedCredential[]): void;
|
|
180
181
|
getWalletClientByAddress({ accountAddress, }: {
|
|
@@ -403,6 +404,31 @@ export declare class DynamicWaasAleoConnector extends DynamicWaasAleoConnector_b
|
|
|
403
404
|
isNative?: boolean;
|
|
404
405
|
amount: bigint;
|
|
405
406
|
}): Promise<string>;
|
|
407
|
+
/**
|
|
408
|
+
* Two-step Exchange transfer.
|
|
409
|
+
*
|
|
410
|
+
* Step 1: `<program>/transfer_private_to_public(record, SELF, amount)`
|
|
411
|
+
* — unshield the record into the user's *own* public balance.
|
|
412
|
+
* Step 2: `<program>/transfer_public(EXCHANGE, amount)`
|
|
413
|
+
* — public→public from the user to the exchange recipient.
|
|
414
|
+
*
|
|
415
|
+
* `tokensPendingExchange` gates `canShieldToken` for the duration of
|
|
416
|
+
* the orchestration so the auto-shield hook does not consume the
|
|
417
|
+
* just-unshielded amount before step 2 spends it. The set is cleared
|
|
418
|
+
* in `finally` regardless of outcome.
|
|
419
|
+
*
|
|
420
|
+
* Step 2 is retried on failure because Aleo's finalize phase can lag
|
|
421
|
+
* the broadcast — until step 1 has finalized, step 2 reads stale public
|
|
422
|
+
* balance and the validator rejects it. We wait
|
|
423
|
+
* `EXCHANGE_STEP1_INITIAL_DELAY_MS` first and then retry up to
|
|
424
|
+
* `EXCHANGE_STEP2_MAX_RETRIES` times. If all retries exhaust, we throw a
|
|
425
|
+
* `DynamicError` that explicitly tells the user step 1 succeeded so they
|
|
426
|
+
* can recover the funds via a manual public→public transfer.
|
|
427
|
+
*
|
|
428
|
+
* Step 2's txId is returned as the user-facing transaction id (it's the
|
|
429
|
+
* one that lands the funds at the exchange).
|
|
430
|
+
*/
|
|
431
|
+
private submitExchangeTransfer;
|
|
406
432
|
endSession(reason?: LogoutReason): Promise<void>;
|
|
407
433
|
getProvider(): undefined;
|
|
408
434
|
}
|
|
@@ -95,6 +95,46 @@ const buildTransferInputs = (args) => {
|
|
|
95
95
|
inputs: [to, `${value.toString()}u128`, recordPlaintext],
|
|
96
96
|
};
|
|
97
97
|
};
|
|
98
|
+
/**
|
|
99
|
+
* Builds the `(functionName, inputs, inputTypes)` triple for a
|
|
100
|
+
* `<program>/transfer_public` public-to-public transfer. Used as step 2
|
|
101
|
+
* of the Exchange flow (after step 1 unshield-to-self). `transfer_public`
|
|
102
|
+
* is NOT in the iframe's `SEALANCE_FUNCTIONS_REQUIRING_PROOF` set, so the
|
|
103
|
+
* caller controls inputs end-to-end (no Sealance proof injection).
|
|
104
|
+
*
|
|
105
|
+
* - `credits` u64. inputs `[recipient, amount]`.
|
|
106
|
+
* - `stablecoin` u128. inputs `[recipient, amount]`.
|
|
107
|
+
* - `arc21` u128. inputs `[token_id, recipient, amount]`. The
|
|
108
|
+
* `token_registry.aleo/transfer_public` transition keys
|
|
109
|
+
* off `token_id` since there's no record to encode it in.
|
|
110
|
+
*/
|
|
111
|
+
const buildPublicTransferInputs = (args) => {
|
|
112
|
+
const { to, value, token } = args;
|
|
113
|
+
const functionName = 'transfer_public';
|
|
114
|
+
if (token.programKind === 'credits') {
|
|
115
|
+
return {
|
|
116
|
+
functionName,
|
|
117
|
+
inputTypes: ['address.public', 'u64.public'],
|
|
118
|
+
inputs: [to, `${value.toString()}u64`],
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
if (token.programKind === 'stablecoin') {
|
|
122
|
+
return {
|
|
123
|
+
functionName,
|
|
124
|
+
inputTypes: ['address.public', 'u128.public'],
|
|
125
|
+
inputs: [to, `${value.toString()}u128`],
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
// arc21 — token_registry.aleo/transfer_public(token_id, recipient, amount).
|
|
129
|
+
if (!token.tokenId) {
|
|
130
|
+
throw new DynamicError(`transfer_public: ARC-21 token ${token.contractAddress} is missing tokenId in registry.`);
|
|
131
|
+
}
|
|
132
|
+
return {
|
|
133
|
+
functionName,
|
|
134
|
+
inputTypes: ['field.public', 'address.public', 'u128.public'],
|
|
135
|
+
inputs: [token.tokenId, to, `${value.toString()}u128`],
|
|
136
|
+
};
|
|
137
|
+
};
|
|
98
138
|
/**
|
|
99
139
|
* Builds the `(functionName, inputs, inputTypes)` triple for a
|
|
100
140
|
* `<program>/transfer_public_to_private` shield call to self. Mirrors
|
|
@@ -152,6 +192,16 @@ const joinShapeForProgram = (programId) => {
|
|
|
152
192
|
}
|
|
153
193
|
return shape;
|
|
154
194
|
};
|
|
195
|
+
// Two-step Exchange flow timing. Step 1 (`transfer_private_to_public` to
|
|
196
|
+
// self) needs to surface in the user's public balance before step 2
|
|
197
|
+
// (`transfer_public` to the exchange) can spend it. Aleo block time is
|
|
198
|
+
// ~10s plus a finalize phase; we wait `STEP1_INITIAL_DELAY_MS` and then
|
|
199
|
+
// retry step 2 up to `STEP2_MAX_RETRIES` times with a fixed backoff.
|
|
200
|
+
// The most likely retryable failure is "insufficient public balance"
|
|
201
|
+
// if step 1 hasn't finalized yet.
|
|
202
|
+
const EXCHANGE_STEP1_INITIAL_DELAY_MS = 15000;
|
|
203
|
+
const EXCHANGE_STEP2_MAX_RETRIES = 3;
|
|
204
|
+
const EXCHANGE_STEP2_RETRY_DELAY_MS = 10000;
|
|
155
205
|
const hasUsableRecordShape = (r) => {
|
|
156
206
|
const rec = r;
|
|
157
207
|
return (typeof (rec === null || rec === void 0 ? void 0 : rec.record_plaintext) === 'string' &&
|
|
@@ -173,6 +223,12 @@ class DynamicWaasAleoConnector extends withDynamicWaas(WaasAleoWalletConnector)
|
|
|
173
223
|
this.overrideKey = 'dynamicwaas';
|
|
174
224
|
this.isEmbeddedWallet = true;
|
|
175
225
|
this.logger = new Logger('DynamicWaasAleoConnector');
|
|
226
|
+
// Programs whose Exchange flow is mid-orchestration (between step 1
|
|
227
|
+
// unshield-to-self and step 2 public-to-public). The auto-shield hook
|
|
228
|
+
// consults `canShieldToken` per balance refresh — gating shield here
|
|
229
|
+
// prevents the hook from re-shielding the just-unshielded amount before
|
|
230
|
+
// step 2 spends it. Add on Exchange entry, remove in `finally`.
|
|
231
|
+
this.tokensPendingExchange = new Set();
|
|
176
232
|
this.walletUiUtils = props.walletUiUtils;
|
|
177
233
|
}
|
|
178
234
|
setVerifiedCredentials(verifiedCredentials) {
|
|
@@ -629,6 +685,15 @@ class DynamicWaasAleoConnector extends withDynamicWaas(WaasAleoWalletConnector)
|
|
|
629
685
|
// which validateActiveWallet has already aligned with `from`.
|
|
630
686
|
// Setting it explicitly keeps the contract obvious to readers.
|
|
631
687
|
this.activeAccountAddress = from;
|
|
688
|
+
if (mode === 'exchange') {
|
|
689
|
+
return this.submitExchangeTransfer({
|
|
690
|
+
from,
|
|
691
|
+
recordPlaintext,
|
|
692
|
+
to,
|
|
693
|
+
token,
|
|
694
|
+
value,
|
|
695
|
+
});
|
|
696
|
+
}
|
|
632
697
|
const { functionName, inputs, inputTypes } = buildTransferInputs({
|
|
633
698
|
mode,
|
|
634
699
|
recordPlaintext,
|
|
@@ -664,7 +729,15 @@ class DynamicWaasAleoConnector extends withDynamicWaas(WaasAleoWalletConnector)
|
|
|
664
729
|
* `credits.aleo` entry when the literal address misses.
|
|
665
730
|
*/
|
|
666
731
|
canShieldToken(token) {
|
|
667
|
-
|
|
732
|
+
const resolved = this.resolveShieldableToken(token);
|
|
733
|
+
if (!resolved)
|
|
734
|
+
return false;
|
|
735
|
+
// While an Exchange flow for this program is mid-orchestration the
|
|
736
|
+
// user's public balance is transient — auto-shield must not consume
|
|
737
|
+
// it before step 2's public→public transfer.
|
|
738
|
+
if (this.tokensPendingExchange.has(resolved.programId))
|
|
739
|
+
return false;
|
|
740
|
+
return true;
|
|
668
741
|
}
|
|
669
742
|
/**
|
|
670
743
|
* True when the Feemaster currently sponsors a shield (
|
|
@@ -777,6 +850,91 @@ class DynamicWaasAleoConnector extends withDynamicWaas(WaasAleoWalletConnector)
|
|
|
777
850
|
return result.txId;
|
|
778
851
|
});
|
|
779
852
|
}
|
|
853
|
+
/**
|
|
854
|
+
* Two-step Exchange transfer.
|
|
855
|
+
*
|
|
856
|
+
* Step 1: `<program>/transfer_private_to_public(record, SELF, amount)`
|
|
857
|
+
* — unshield the record into the user's *own* public balance.
|
|
858
|
+
* Step 2: `<program>/transfer_public(EXCHANGE, amount)`
|
|
859
|
+
* — public→public from the user to the exchange recipient.
|
|
860
|
+
*
|
|
861
|
+
* `tokensPendingExchange` gates `canShieldToken` for the duration of
|
|
862
|
+
* the orchestration so the auto-shield hook does not consume the
|
|
863
|
+
* just-unshielded amount before step 2 spends it. The set is cleared
|
|
864
|
+
* in `finally` regardless of outcome.
|
|
865
|
+
*
|
|
866
|
+
* Step 2 is retried on failure because Aleo's finalize phase can lag
|
|
867
|
+
* the broadcast — until step 1 has finalized, step 2 reads stale public
|
|
868
|
+
* balance and the validator rejects it. We wait
|
|
869
|
+
* `EXCHANGE_STEP1_INITIAL_DELAY_MS` first and then retry up to
|
|
870
|
+
* `EXCHANGE_STEP2_MAX_RETRIES` times. If all retries exhaust, we throw a
|
|
871
|
+
* `DynamicError` that explicitly tells the user step 1 succeeded so they
|
|
872
|
+
* can recover the funds via a manual public→public transfer.
|
|
873
|
+
*
|
|
874
|
+
* Step 2's txId is returned as the user-facing transaction id (it's the
|
|
875
|
+
* one that lands the funds at the exchange).
|
|
876
|
+
*/
|
|
877
|
+
submitExchangeTransfer(args) {
|
|
878
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
879
|
+
var _a, _b, _c, _d, _e, _f;
|
|
880
|
+
const { from, to, value, recordPlaintext, token } = args;
|
|
881
|
+
this.tokensPendingExchange.add(token.programId);
|
|
882
|
+
try {
|
|
883
|
+
// --- Step 1: unshield record → self's public balance ---
|
|
884
|
+
const step1Build = buildTransferInputs({
|
|
885
|
+
mode: 'exchange',
|
|
886
|
+
recordPlaintext,
|
|
887
|
+
to: from,
|
|
888
|
+
token,
|
|
889
|
+
value,
|
|
890
|
+
});
|
|
891
|
+
const step1Result = yield this.proveTransaction({
|
|
892
|
+
broadcast: true,
|
|
893
|
+
functionName: step1Build.functionName,
|
|
894
|
+
inputTypes: step1Build.inputTypes,
|
|
895
|
+
inputs: step1Build.inputs,
|
|
896
|
+
programId: token.programId,
|
|
897
|
+
});
|
|
898
|
+
if (!step1Result.txId) {
|
|
899
|
+
throw new DynamicError('Aleo Exchange step 1 (unshield) did not return a transaction id.');
|
|
900
|
+
}
|
|
901
|
+
(_b = (_a = this.logger).debug) === null || _b === void 0 ? void 0 : _b.call(_a, `[exchangeTransfer:${token.programId}] step 1 (unshield) tx: ${step1Result.txId}`);
|
|
902
|
+
// Wait for step 1 to finalize and surface in public balance before
|
|
903
|
+
// attempting step 2. See `EXCHANGE_STEP1_INITIAL_DELAY_MS` notes.
|
|
904
|
+
yield new Promise((resolve) => setTimeout(resolve, EXCHANGE_STEP1_INITIAL_DELAY_MS));
|
|
905
|
+
// --- Step 2: public→public self → exchange ---
|
|
906
|
+
const step2Build = buildPublicTransferInputs({ to, token, value });
|
|
907
|
+
let lastErr;
|
|
908
|
+
for (let attempt = 0; attempt <= EXCHANGE_STEP2_MAX_RETRIES; attempt += 1) {
|
|
909
|
+
try {
|
|
910
|
+
const step2Result = yield this.proveTransaction({
|
|
911
|
+
broadcast: true,
|
|
912
|
+
functionName: step2Build.functionName,
|
|
913
|
+
inputTypes: step2Build.inputTypes,
|
|
914
|
+
inputs: step2Build.inputs,
|
|
915
|
+
programId: token.programId,
|
|
916
|
+
});
|
|
917
|
+
if (!step2Result.txId) {
|
|
918
|
+
throw new DynamicError('Aleo Exchange step 2 (public transfer) did not return a transaction id.');
|
|
919
|
+
}
|
|
920
|
+
(_d = (_c = this.logger).debug) === null || _d === void 0 ? void 0 : _d.call(_c, `[exchangeTransfer:${token.programId}] step 2 (public transfer) tx: ${step2Result.txId}`);
|
|
921
|
+
return step2Result.txId;
|
|
922
|
+
}
|
|
923
|
+
catch (err) {
|
|
924
|
+
lastErr = err;
|
|
925
|
+
(_f = (_e = this.logger).debug) === null || _f === void 0 ? void 0 : _f.call(_e, `[exchangeTransfer:${token.programId}] step 2 attempt ${attempt + 1} failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
926
|
+
if (attempt < EXCHANGE_STEP2_MAX_RETRIES) {
|
|
927
|
+
yield new Promise((resolve) => setTimeout(resolve, EXCHANGE_STEP2_RETRY_DELAY_MS));
|
|
928
|
+
}
|
|
929
|
+
}
|
|
930
|
+
}
|
|
931
|
+
throw new DynamicError(`Aleo Exchange step 2 (public transfer) failed after ${EXCHANGE_STEP2_MAX_RETRIES + 1} attempts. Step 1 unshield (tx ${step1Result.txId}) succeeded — your funds are now in your public balance and can be sent to the exchange via a manual public transfer. Last error: ${lastErr instanceof Error ? lastErr.message : String(lastErr)}`);
|
|
932
|
+
}
|
|
933
|
+
finally {
|
|
934
|
+
this.tokensPendingExchange.delete(token.programId);
|
|
935
|
+
}
|
|
936
|
+
});
|
|
937
|
+
}
|
|
780
938
|
endSession(reason) {
|
|
781
939
|
const _super = Object.create(null, {
|
|
782
940
|
endSession: { get: () => super.endSession }
|
|
@@ -151,6 +151,22 @@ class WaasAleoWalletConnector extends walletConnectorCore.WalletConnectorBase {
|
|
|
151
151
|
supportsNetworkSwitching() {
|
|
152
152
|
return true;
|
|
153
153
|
}
|
|
154
|
+
/**
|
|
155
|
+
* Provable's hosted Aleo block explorer for the currently-selected
|
|
156
|
+
* network. Mainnet (chainId `0`) → `explorer.provable.com`, testnet
|
|
157
|
+
* (chainId `1`) → `testnet.explorer.provable.com`. The Send-flow's
|
|
158
|
+
* `TransactionStatusLayout` calls this through `getTransactionLink`
|
|
159
|
+
* to render a "View on explorer" link next to the broadcast txId.
|
|
160
|
+
*/
|
|
161
|
+
getBlockExplorerUrlsForCurrentNetwork() {
|
|
162
|
+
return _tslib.__awaiter(this, void 0, void 0, function* () {
|
|
163
|
+
var _a;
|
|
164
|
+
const chainId = (_a = this.getSelectedNetwork()) === null || _a === void 0 ? void 0 : _a.chainId;
|
|
165
|
+
const isMainnet = String(chainId !== null && chainId !== void 0 ? chainId : '') === '0';
|
|
166
|
+
const subdomain = isMainnet ? '' : 'testnet.';
|
|
167
|
+
return [`https://${subdomain}explorer.provable.com/`];
|
|
168
|
+
});
|
|
169
|
+
}
|
|
154
170
|
/**
|
|
155
171
|
* Returns the env-configured Aleo networks. The widget's NetworkPicker
|
|
156
172
|
* uses this to render the chain-switcher dropdown and to decide whether
|
|
@@ -86,6 +86,14 @@ export declare abstract class WaasAleoWalletConnector extends WalletConnectorBas
|
|
|
86
86
|
* widget UI exposes the chain-switcher dropdown for Aleo wallets.
|
|
87
87
|
*/
|
|
88
88
|
supportsNetworkSwitching(): boolean;
|
|
89
|
+
/**
|
|
90
|
+
* Provable's hosted Aleo block explorer for the currently-selected
|
|
91
|
+
* network. Mainnet (chainId `0`) → `explorer.provable.com`, testnet
|
|
92
|
+
* (chainId `1`) → `testnet.explorer.provable.com`. The Send-flow's
|
|
93
|
+
* `TransactionStatusLayout` calls this through `getTransactionLink`
|
|
94
|
+
* to render a "View on explorer" link next to the broadcast txId.
|
|
95
|
+
*/
|
|
96
|
+
getBlockExplorerUrlsForCurrentNetwork(): Promise<string[]>;
|
|
89
97
|
/**
|
|
90
98
|
* Returns the env-configured Aleo networks. The widget's NetworkPicker
|
|
91
99
|
* uses this to render the chain-switcher dropdown and to decide whether
|
|
@@ -147,6 +147,22 @@ class WaasAleoWalletConnector extends WalletConnectorBase {
|
|
|
147
147
|
supportsNetworkSwitching() {
|
|
148
148
|
return true;
|
|
149
149
|
}
|
|
150
|
+
/**
|
|
151
|
+
* Provable's hosted Aleo block explorer for the currently-selected
|
|
152
|
+
* network. Mainnet (chainId `0`) → `explorer.provable.com`, testnet
|
|
153
|
+
* (chainId `1`) → `testnet.explorer.provable.com`. The Send-flow's
|
|
154
|
+
* `TransactionStatusLayout` calls this through `getTransactionLink`
|
|
155
|
+
* to render a "View on explorer" link next to the broadcast txId.
|
|
156
|
+
*/
|
|
157
|
+
getBlockExplorerUrlsForCurrentNetwork() {
|
|
158
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
159
|
+
var _a;
|
|
160
|
+
const chainId = (_a = this.getSelectedNetwork()) === null || _a === void 0 ? void 0 : _a.chainId;
|
|
161
|
+
const isMainnet = String(chainId !== null && chainId !== void 0 ? chainId : '') === '0';
|
|
162
|
+
const subdomain = isMainnet ? '' : 'testnet.';
|
|
163
|
+
return [`https://${subdomain}explorer.provable.com/`];
|
|
164
|
+
});
|
|
165
|
+
}
|
|
150
166
|
/**
|
|
151
167
|
* Returns the env-configured Aleo networks. The widget's NetworkPicker
|
|
152
168
|
* uses this to render the chain-switcher dropdown and to decide whether
|
package/src/index.cjs
CHANGED
|
@@ -14,6 +14,7 @@ var isAleoWallet = require('./wallet/isAleoWallet/isAleoWallet.cjs');
|
|
|
14
14
|
var AleoUiTransaction = require('./utils/AleoUiTransaction/AleoUiTransaction.cjs');
|
|
15
15
|
var aleoWalletStandard = require('@provablehq/aleo-wallet-standard');
|
|
16
16
|
var aleoSendableTokens = require('./utils/aleoSendableTokens/aleoSendableTokens.cjs');
|
|
17
|
+
var getAleoExplorerTxUrl = require('./utils/getAleoExplorerTxUrl/getAleoExplorerTxUrl.cjs');
|
|
17
18
|
var DynamicWaasAleoConnector = require('./connectors/DynamicWaasAleoConnector/DynamicWaasAleoConnector.cjs');
|
|
18
19
|
|
|
19
20
|
assertPackageVersion.assertPackageVersion('@dynamic-labs/aleo', _package.version);
|
|
@@ -50,5 +51,6 @@ exports.ALEO_TOKEN_REGISTRY_PROGRAM = aleoSendableTokens.ALEO_TOKEN_REGISTRY_PRO
|
|
|
50
51
|
exports.extractRecordAtomicAmount = aleoSendableTokens.extractRecordAtomicAmount;
|
|
51
52
|
exports.getAleoSendableTokensForNetwork = aleoSendableTokens.getAleoSendableTokensForNetwork;
|
|
52
53
|
exports.recordMatchesSendableToken = aleoSendableTokens.recordMatchesSendableToken;
|
|
54
|
+
exports.getAleoExplorerTxUrl = getAleoExplorerTxUrl.getAleoExplorerTxUrl;
|
|
53
55
|
exports.DynamicWaasAleoConnector = DynamicWaasAleoConnector.DynamicWaasAleoConnector;
|
|
54
56
|
exports.AleoWalletConnectors = AleoWalletConnectors;
|
package/src/index.d.ts
CHANGED
|
@@ -13,6 +13,7 @@ export { ALEO_CHAINS, WalletDecryptPermission, WalletFeatureName, WalletReadySta
|
|
|
13
13
|
export type { AleoChain, StandardWallet } from './types';
|
|
14
14
|
export { ALEO_CREDITS_PROGRAM, ALEO_TOKEN_REGISTRY_PROGRAM, extractRecordAtomicAmount, getAleoSendableTokensForNetwork, recordMatchesSendableToken, } from './utils/aleoSendableTokens/aleoSendableTokens';
|
|
15
15
|
export type { AleoOwnedRecord, AleoProgramKind, AleoSendableToken, } from './utils/aleoSendableTokens/aleoSendableTokens';
|
|
16
|
+
export { getAleoExplorerTxUrl } from './utils/getAleoExplorerTxUrl';
|
|
16
17
|
export declare const AleoWalletConnectors: (props: {
|
|
17
18
|
walletBook: WalletBookSchema;
|
|
18
19
|
aleoNetworks: GenericNetwork[];
|
package/src/index.js
CHANGED
|
@@ -11,6 +11,7 @@ export { isAleoWallet } from './wallet/isAleoWallet/isAleoWallet.js';
|
|
|
11
11
|
export { AleoUiTransaction } from './utils/AleoUiTransaction/AleoUiTransaction.js';
|
|
12
12
|
export { ALEO_CHAINS, WalletDecryptPermission, WalletFeatureName, WalletReadyState } from '@provablehq/aleo-wallet-standard';
|
|
13
13
|
export { ALEO_CREDITS_PROGRAM, ALEO_TOKEN_REGISTRY_PROGRAM, extractRecordAtomicAmount, getAleoSendableTokensForNetwork, recordMatchesSendableToken } from './utils/aleoSendableTokens/aleoSendableTokens.js';
|
|
14
|
+
export { getAleoExplorerTxUrl } from './utils/getAleoExplorerTxUrl/getAleoExplorerTxUrl.js';
|
|
14
15
|
export { DynamicWaasAleoConnector } from './connectors/DynamicWaasAleoConnector/DynamicWaasAleoConnector.js';
|
|
15
16
|
|
|
16
17
|
assertPackageVersion('@dynamic-labs/aleo', version);
|
|
@@ -24,13 +24,19 @@ const ALEO_ADDRESS_REGEX = /^aleo1[a-z0-9]{58}$/;
|
|
|
24
24
|
*
|
|
25
25
|
* Both supported modes spend FROM a private record (so the wallet's
|
|
26
26
|
* available balance is always the shielded record sum); they differ
|
|
27
|
-
*
|
|
27
|
+
* in the on-chain orchestration they trigger inside the connector:
|
|
28
28
|
*
|
|
29
|
-
* - **Individual** = `<program>/transfer_private` — recipient
|
|
30
|
-
* a private record. The most common Aleo flow.
|
|
31
|
-
* - **Exchange** =
|
|
32
|
-
*
|
|
33
|
-
*
|
|
29
|
+
* - **Individual** = single `<program>/transfer_private` — recipient
|
|
30
|
+
* also gets a private record. The most common Aleo flow.
|
|
31
|
+
* - **Exchange** = two-step (driven by the connector's
|
|
32
|
+
* `submitExchangeTransfer`):
|
|
33
|
+
* 1. `<program>/transfer_private_to_public(record, SELF, amount)`
|
|
34
|
+
* — unshield to the sender's own public balance.
|
|
35
|
+
* 2. `<program>/transfer_public(EXCHANGE, amount)` — public→public
|
|
36
|
+
* from sender to the exchange recipient.
|
|
37
|
+
* Useful for off-ramps and exchange deposits. Splitting the unshield
|
|
38
|
+
* from the public transfer lets the connector pause auto-shield mid-
|
|
39
|
+
* flow and retry step 2 independently if Aleo's finalize phase lags.
|
|
34
40
|
*
|
|
35
41
|
* The submit path branches on the **selected token's program kind**:
|
|
36
42
|
*
|
|
@@ -22,13 +22,19 @@ type AleoUiTransactionProps = {
|
|
|
22
22
|
*
|
|
23
23
|
* Both supported modes spend FROM a private record (so the wallet's
|
|
24
24
|
* available balance is always the shielded record sum); they differ
|
|
25
|
-
*
|
|
25
|
+
* in the on-chain orchestration they trigger inside the connector:
|
|
26
26
|
*
|
|
27
|
-
* - **Individual** = `<program>/transfer_private` — recipient
|
|
28
|
-
* a private record. The most common Aleo flow.
|
|
29
|
-
* - **Exchange** =
|
|
30
|
-
*
|
|
31
|
-
*
|
|
27
|
+
* - **Individual** = single `<program>/transfer_private` — recipient
|
|
28
|
+
* also gets a private record. The most common Aleo flow.
|
|
29
|
+
* - **Exchange** = two-step (driven by the connector's
|
|
30
|
+
* `submitExchangeTransfer`):
|
|
31
|
+
* 1. `<program>/transfer_private_to_public(record, SELF, amount)`
|
|
32
|
+
* — unshield to the sender's own public balance.
|
|
33
|
+
* 2. `<program>/transfer_public(EXCHANGE, amount)` — public→public
|
|
34
|
+
* from sender to the exchange recipient.
|
|
35
|
+
* Useful for off-ramps and exchange deposits. Splitting the unshield
|
|
36
|
+
* from the public transfer lets the connector pause auto-shield mid-
|
|
37
|
+
* flow and retry step 2 independently if Aleo's finalize phase lags.
|
|
32
38
|
*
|
|
33
39
|
* The submit path branches on the **selected token's program kind**:
|
|
34
40
|
*
|
|
@@ -20,13 +20,19 @@ const ALEO_ADDRESS_REGEX = /^aleo1[a-z0-9]{58}$/;
|
|
|
20
20
|
*
|
|
21
21
|
* Both supported modes spend FROM a private record (so the wallet's
|
|
22
22
|
* available balance is always the shielded record sum); they differ
|
|
23
|
-
*
|
|
23
|
+
* in the on-chain orchestration they trigger inside the connector:
|
|
24
24
|
*
|
|
25
|
-
* - **Individual** = `<program>/transfer_private` — recipient
|
|
26
|
-
* a private record. The most common Aleo flow.
|
|
27
|
-
* - **Exchange** =
|
|
28
|
-
*
|
|
29
|
-
*
|
|
25
|
+
* - **Individual** = single `<program>/transfer_private` — recipient
|
|
26
|
+
* also gets a private record. The most common Aleo flow.
|
|
27
|
+
* - **Exchange** = two-step (driven by the connector's
|
|
28
|
+
* `submitExchangeTransfer`):
|
|
29
|
+
* 1. `<program>/transfer_private_to_public(record, SELF, amount)`
|
|
30
|
+
* — unshield to the sender's own public balance.
|
|
31
|
+
* 2. `<program>/transfer_public(EXCHANGE, amount)` — public→public
|
|
32
|
+
* from sender to the exchange recipient.
|
|
33
|
+
* Useful for off-ramps and exchange deposits. Splitting the unshield
|
|
34
|
+
* from the public transfer lets the connector pause auto-shield mid-
|
|
35
|
+
* flow and retry step 2 independently if Aleo's finalize phase lags.
|
|
30
36
|
*
|
|
31
37
|
* The submit path branches on the **selected token's program kind**:
|
|
32
38
|
*
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Provable's hosted Aleo block explorer hosts mainnet and testnet on
|
|
8
|
+
* different subdomains. We pick by Aleo network id (`0` = mainnet,
|
|
9
|
+
* `1` = testnet — matching the registries in `aleoSendableTokens` /
|
|
10
|
+
* `aleoShieldableTokens`). Numeric and string ids are both accepted so
|
|
11
|
+
* callers can pass `connector.getSelectedNetwork()?.chainId` directly
|
|
12
|
+
* (which is typed `string | number` depending on env config). When
|
|
13
|
+
* `networkId` is missing we default to testnet — mainnet should always
|
|
14
|
+
* resolve a concrete id at runtime, but defaulting to testnet here
|
|
15
|
+
* means a stale UI never accidentally surfaces a mainnet explorer link
|
|
16
|
+
* for a testnet transaction.
|
|
17
|
+
*/
|
|
18
|
+
const ALEO_MAINNET_NETWORK_ID = 0;
|
|
19
|
+
const isMainnet = (networkId) => {
|
|
20
|
+
if (networkId === undefined || networkId === null)
|
|
21
|
+
return false;
|
|
22
|
+
if (typeof networkId === 'number')
|
|
23
|
+
return networkId === ALEO_MAINNET_NETWORK_ID;
|
|
24
|
+
return Number(networkId) === ALEO_MAINNET_NETWORK_ID;
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* Build the Provable explorer URL for an Aleo transaction id.
|
|
28
|
+
*
|
|
29
|
+
* Examples:
|
|
30
|
+
* getAleoExplorerTxUrl('at1abc...', 0) → 'https://explorer.provable.com/transaction/at1abc...'
|
|
31
|
+
* getAleoExplorerTxUrl('at1abc...', 1) → 'https://testnet.explorer.provable.com/transaction/at1abc...'
|
|
32
|
+
*
|
|
33
|
+
* @param txId Aleo transaction id (`at1...`).
|
|
34
|
+
* @param networkId `0` = mainnet, `1` = testnet. Defaults to testnet.
|
|
35
|
+
*/
|
|
36
|
+
const getAleoExplorerTxUrl = (txId, networkId) => {
|
|
37
|
+
const subdomain = isMainnet(networkId) ? '' : 'testnet.';
|
|
38
|
+
return `https://${subdomain}explorer.provable.com/transaction/${txId}`;
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
exports.getAleoExplorerTxUrl = getAleoExplorerTxUrl;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Build the Provable explorer URL for an Aleo transaction id.
|
|
3
|
+
*
|
|
4
|
+
* Examples:
|
|
5
|
+
* getAleoExplorerTxUrl('at1abc...', 0) → 'https://explorer.provable.com/transaction/at1abc...'
|
|
6
|
+
* getAleoExplorerTxUrl('at1abc...', 1) → 'https://testnet.explorer.provable.com/transaction/at1abc...'
|
|
7
|
+
*
|
|
8
|
+
* @param txId Aleo transaction id (`at1...`).
|
|
9
|
+
* @param networkId `0` = mainnet, `1` = testnet. Defaults to testnet.
|
|
10
|
+
*/
|
|
11
|
+
export declare const getAleoExplorerTxUrl: (txId: string, networkId?: number | string) => string;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
/**
|
|
3
|
+
* Provable's hosted Aleo block explorer hosts mainnet and testnet on
|
|
4
|
+
* different subdomains. We pick by Aleo network id (`0` = mainnet,
|
|
5
|
+
* `1` = testnet — matching the registries in `aleoSendableTokens` /
|
|
6
|
+
* `aleoShieldableTokens`). Numeric and string ids are both accepted so
|
|
7
|
+
* callers can pass `connector.getSelectedNetwork()?.chainId` directly
|
|
8
|
+
* (which is typed `string | number` depending on env config). When
|
|
9
|
+
* `networkId` is missing we default to testnet — mainnet should always
|
|
10
|
+
* resolve a concrete id at runtime, but defaulting to testnet here
|
|
11
|
+
* means a stale UI never accidentally surfaces a mainnet explorer link
|
|
12
|
+
* for a testnet transaction.
|
|
13
|
+
*/
|
|
14
|
+
const ALEO_MAINNET_NETWORK_ID = 0;
|
|
15
|
+
const isMainnet = (networkId) => {
|
|
16
|
+
if (networkId === undefined || networkId === null)
|
|
17
|
+
return false;
|
|
18
|
+
if (typeof networkId === 'number')
|
|
19
|
+
return networkId === ALEO_MAINNET_NETWORK_ID;
|
|
20
|
+
return Number(networkId) === ALEO_MAINNET_NETWORK_ID;
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* Build the Provable explorer URL for an Aleo transaction id.
|
|
24
|
+
*
|
|
25
|
+
* Examples:
|
|
26
|
+
* getAleoExplorerTxUrl('at1abc...', 0) → 'https://explorer.provable.com/transaction/at1abc...'
|
|
27
|
+
* getAleoExplorerTxUrl('at1abc...', 1) → 'https://testnet.explorer.provable.com/transaction/at1abc...'
|
|
28
|
+
*
|
|
29
|
+
* @param txId Aleo transaction id (`at1...`).
|
|
30
|
+
* @param networkId `0` = mainnet, `1` = testnet. Defaults to testnet.
|
|
31
|
+
*/
|
|
32
|
+
const getAleoExplorerTxUrl = (txId, networkId) => {
|
|
33
|
+
const subdomain = isMainnet(networkId) ? '' : 'testnet.';
|
|
34
|
+
return `https://${subdomain}explorer.provable.com/transaction/${txId}`;
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
export { getAleoExplorerTxUrl };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './getAleoExplorerTxUrl';
|
|
@@ -6,6 +6,7 @@ Object.defineProperty(exports, '__esModule', { value: true });
|
|
|
6
6
|
var _tslib = require('../../../_virtual/_tslib.cjs');
|
|
7
7
|
var utils = require('@dynamic-labs/utils');
|
|
8
8
|
var walletConnectorCore = require('@dynamic-labs/wallet-connector-core');
|
|
9
|
+
var getAleoExplorerTxUrl = require('../../utils/getAleoExplorerTxUrl/getAleoExplorerTxUrl.cjs');
|
|
9
10
|
|
|
10
11
|
class AleoWallet extends walletConnectorCore.Wallet {
|
|
11
12
|
sendBalance(_a) {
|
|
@@ -47,6 +48,23 @@ class AleoWallet extends walletConnectorCore.Wallet {
|
|
|
47
48
|
getPublicKey() {
|
|
48
49
|
return this.address;
|
|
49
50
|
}
|
|
51
|
+
/**
|
|
52
|
+
* Build the Provable explorer URL for an Aleo transaction id, scoped to
|
|
53
|
+
* this wallet's currently-selected network. `0` = mainnet, `1` = testnet.
|
|
54
|
+
* Available on every Aleo wallet flavour (embedded + Wallet Adapter).
|
|
55
|
+
*
|
|
56
|
+
* Use this to link freshly-broadcast txIds back to the explorer in your
|
|
57
|
+
* UI — e.g. after `wallet.proveTransaction()`, `wallet.shieldToken()`, or
|
|
58
|
+
* the Send flow returns. For Exchange-mode Send the returned txId is the
|
|
59
|
+
* second (`transfer_public`) transaction, which is the one the user
|
|
60
|
+
* cares about.
|
|
61
|
+
*/
|
|
62
|
+
getExplorerTransactionUrl(txId) {
|
|
63
|
+
return _tslib.__awaiter(this, void 0, void 0, function* () {
|
|
64
|
+
const networkId = yield this._connector.getNetwork();
|
|
65
|
+
return getAleoExplorerTxUrl.getAleoExplorerTxUrl(txId, networkId);
|
|
66
|
+
});
|
|
67
|
+
}
|
|
50
68
|
/**
|
|
51
69
|
* Returns the current network this wallet is connected to (e.g. 'aleo:mainnet').
|
|
52
70
|
*/
|
|
@@ -103,6 +121,119 @@ class AleoWallet extends walletConnectorCore.Wallet {
|
|
|
103
121
|
return this._connector.requestRecords(program, options);
|
|
104
122
|
});
|
|
105
123
|
}
|
|
124
|
+
// -------------------------------------------------------------------------
|
|
125
|
+
// Embedded-WaaS proxy methods.
|
|
126
|
+
//
|
|
127
|
+
// The methods below delegate to `DynamicWaasAleoConnector` and only work
|
|
128
|
+
// when the wallet is an embedded Dynamic WaaS Aleo wallet. They throw on
|
|
129
|
+
// Wallet Adapter wallets (which expose `requestTransaction` /
|
|
130
|
+
// `requestRecords` for the same flows but route through the adapter app
|
|
131
|
+
// rather than Sodot MPC + Feemaster + DPS).
|
|
132
|
+
//
|
|
133
|
+
// Convenience over `(wallet.connector as DynamicWaasAleoConnector).foo`:
|
|
134
|
+
// - typed entry point on `wallet.*` matching the docs convention used
|
|
135
|
+
// for Stellar (`wallet.signTransaction`), EVM (`wallet.getPublicClient`),
|
|
136
|
+
// etc.
|
|
137
|
+
// - auto-sets `connector.activeAccountAddress` from `this.address` so
|
|
138
|
+
// callers don't have to mutate connector internals before each call.
|
|
139
|
+
// -------------------------------------------------------------------------
|
|
140
|
+
/**
|
|
141
|
+
* Resolves `this._connector` to a `DynamicWaasAleoConnector` and aligns
|
|
142
|
+
* its `activeAccountAddress` with this wallet's address. Duck-types on
|
|
143
|
+
* `proveTransaction` (the WaaS-specific entry point) so we don't need a
|
|
144
|
+
* runtime import of the WaaS connector. Throws a clear `DynamicError`
|
|
145
|
+
* if the underlying connector is the Wallet Adapter one.
|
|
146
|
+
*/
|
|
147
|
+
getWaasConnectorOrThrow(methodName) {
|
|
148
|
+
const c = this._connector;
|
|
149
|
+
if (typeof c.proveTransaction !== 'function') {
|
|
150
|
+
throw new utils.DynamicError(`AleoWallet.${methodName}() is only available on embedded Aleo wallets (Dynamic WaaS). For Wallet Adapter Aleo wallets use \`requestTransaction\` / \`requestRecords\` instead.`);
|
|
151
|
+
}
|
|
152
|
+
c.activeAccountAddress = this.address;
|
|
153
|
+
return c;
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Sign + prove + broadcast an arbitrary Aleo program transition through
|
|
157
|
+
* the Dynamic WaaS pipeline (Sodot MPC → optional Sealance proof
|
|
158
|
+
* injection → Feemaster sponsorship when covered → Provable DPS).
|
|
159
|
+
*
|
|
160
|
+
* Use this for the generic "execute any transition" path. The Send flow
|
|
161
|
+
* driven by the widget builds on top of this via `createUiTransaction`.
|
|
162
|
+
*/
|
|
163
|
+
proveTransaction(args) {
|
|
164
|
+
return _tslib.__awaiter(this, void 0, void 0, function* () {
|
|
165
|
+
return this.getWaasConnectorOrThrow('proveTransaction').proveTransaction(args);
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* List this wallet's owned Aleo records across every program (credits +
|
|
170
|
+
* stablecoins + ARC-21). Backed by Provable's RecordScanner via the
|
|
171
|
+
* iframe — view key never leaves the iframe.
|
|
172
|
+
*
|
|
173
|
+
* Each entry carries `program_name` + `record_name` so callers can
|
|
174
|
+
* group/display by token.
|
|
175
|
+
*/
|
|
176
|
+
listOwnedRecords() {
|
|
177
|
+
return _tslib.__awaiter(this, void 0, void 0, function* () {
|
|
178
|
+
return this.getWaasConnectorOrThrow('listOwnedRecords').listOwnedRecords();
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Pairwise-merge owned records down to one per program by running
|
|
183
|
+
* `<program>/join` until a single record remains. Sponsored by Feemaster
|
|
184
|
+
* for `credits.aleo` today; stablecoin / ARC-21 fall through to user-paid
|
|
185
|
+
* if Feemaster doesn't yet cover the pair.
|
|
186
|
+
*
|
|
187
|
+
* Programs the connector doesn't recognise (no registered join shape)
|
|
188
|
+
* are reported as `skipped: 'unsupported'` rather than thrown — iterate
|
|
189
|
+
* `results` to surface what merged vs. what didn't.
|
|
190
|
+
*/
|
|
191
|
+
joinRecords(opts) {
|
|
192
|
+
return _tslib.__awaiter(this, void 0, void 0, function* () {
|
|
193
|
+
return this.getWaasConnectorOrThrow('joinRecords').joinRecords(opts);
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Shield (`<program>/transfer_public_to_private`) `amount` of a token
|
|
198
|
+
* from this wallet's *public* balance into a fresh private record owned
|
|
199
|
+
* by self. `tokenAddress` matches `TokenBalance.address` from the
|
|
200
|
+
* unshielded-balance feed; pass `isNative: true` for native ALEO.
|
|
201
|
+
*/
|
|
202
|
+
shieldToken(args) {
|
|
203
|
+
return _tslib.__awaiter(this, void 0, void 0, function* () {
|
|
204
|
+
return this.getWaasConnectorOrThrow('shieldToken').shieldToken(args);
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* Returns `true` when the given token is registered as shieldable on the
|
|
209
|
+
* currently-selected Aleo network. Used to gate "Shield Manually" UI on
|
|
210
|
+
* unshielded balances surfaced by the public-balance feed (which can
|
|
211
|
+
* include third-party Aleo programs we don't know how to shield).
|
|
212
|
+
*/
|
|
213
|
+
canShieldToken(token) {
|
|
214
|
+
return this.getWaasConnectorOrThrow('canShieldToken').canShieldToken(token);
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* Returns `true` when the Feemaster currently sponsors a shield
|
|
218
|
+
* (`transfer_public_to_private`) of the given token. Used to decide
|
|
219
|
+
* whether the shield CTA can dispatch silently or needs a user-paid fee
|
|
220
|
+
* confirmation modal.
|
|
221
|
+
*/
|
|
222
|
+
isShieldSponsored(token) {
|
|
223
|
+
return _tslib.__awaiter(this, void 0, void 0, function* () {
|
|
224
|
+
return this.getWaasConnectorOrThrow('isShieldSponsored').isShieldSponsored(token);
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Generic Feemaster sponsorship check for any `(programId, functionName)`
|
|
229
|
+
* pair on the currently-selected network. Never throws — returns `false`
|
|
230
|
+
* on any failure so callers default to "show modal".
|
|
231
|
+
*/
|
|
232
|
+
isFeemasterSponsored(args) {
|
|
233
|
+
return _tslib.__awaiter(this, void 0, void 0, function* () {
|
|
234
|
+
return this.getWaasConnectorOrThrow('isFeemasterSponsored').isFeemasterSponsored(args);
|
|
235
|
+
});
|
|
236
|
+
}
|
|
106
237
|
}
|
|
107
238
|
|
|
108
239
|
exports.AleoWallet = AleoWallet;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Wallet } from '@dynamic-labs/wallet-connector-core';
|
|
2
2
|
import type { AleoWalletConnector } from '../../connectors/AleoWalletConnector';
|
|
3
|
+
import type { DynamicWaasAleoConnector } from '../../connectors/DynamicWaasAleoConnector';
|
|
3
4
|
import type { AleoTransaction } from '../../types';
|
|
4
5
|
export declare class AleoWallet extends Wallet<AleoWalletConnector> {
|
|
5
6
|
sendBalance({ amount, toAddress, token, }: {
|
|
@@ -16,6 +17,18 @@ export declare class AleoWallet extends Wallet<AleoWalletConnector> {
|
|
|
16
17
|
* In Aleo, the public key and address are the same value.
|
|
17
18
|
*/
|
|
18
19
|
getPublicKey(): string;
|
|
20
|
+
/**
|
|
21
|
+
* Build the Provable explorer URL for an Aleo transaction id, scoped to
|
|
22
|
+
* this wallet's currently-selected network. `0` = mainnet, `1` = testnet.
|
|
23
|
+
* Available on every Aleo wallet flavour (embedded + Wallet Adapter).
|
|
24
|
+
*
|
|
25
|
+
* Use this to link freshly-broadcast txIds back to the explorer in your
|
|
26
|
+
* UI — e.g. after `wallet.proveTransaction()`, `wallet.shieldToken()`, or
|
|
27
|
+
* the Send flow returns. For Exchange-mode Send the returned txId is the
|
|
28
|
+
* second (`transfer_public`) transaction, which is the one the user
|
|
29
|
+
* cares about.
|
|
30
|
+
*/
|
|
31
|
+
getExplorerTransactionUrl(txId: string): Promise<string>;
|
|
19
32
|
/**
|
|
20
33
|
* Returns the current network this wallet is connected to (e.g. 'aleo:mainnet').
|
|
21
34
|
*/
|
|
@@ -54,4 +67,92 @@ export declare class AleoWallet extends Wallet<AleoWalletConnector> {
|
|
|
54
67
|
requestRecords(program: string, options?: {
|
|
55
68
|
plaintext?: boolean;
|
|
56
69
|
}): Promise<unknown[]>;
|
|
70
|
+
/**
|
|
71
|
+
* Resolves `this._connector` to a `DynamicWaasAleoConnector` and aligns
|
|
72
|
+
* its `activeAccountAddress` with this wallet's address. Duck-types on
|
|
73
|
+
* `proveTransaction` (the WaaS-specific entry point) so we don't need a
|
|
74
|
+
* runtime import of the WaaS connector. Throws a clear `DynamicError`
|
|
75
|
+
* if the underlying connector is the Wallet Adapter one.
|
|
76
|
+
*/
|
|
77
|
+
private getWaasConnectorOrThrow;
|
|
78
|
+
/**
|
|
79
|
+
* Sign + prove + broadcast an arbitrary Aleo program transition through
|
|
80
|
+
* the Dynamic WaaS pipeline (Sodot MPC → optional Sealance proof
|
|
81
|
+
* injection → Feemaster sponsorship when covered → Provable DPS).
|
|
82
|
+
*
|
|
83
|
+
* Use this for the generic "execute any transition" path. The Send flow
|
|
84
|
+
* driven by the widget builds on top of this via `createUiTransaction`.
|
|
85
|
+
*/
|
|
86
|
+
proveTransaction(args: {
|
|
87
|
+
programId: string;
|
|
88
|
+
functionName: string;
|
|
89
|
+
inputs: string[];
|
|
90
|
+
inputTypes: string[];
|
|
91
|
+
broadcast?: boolean;
|
|
92
|
+
}): Promise<{
|
|
93
|
+
txId?: string;
|
|
94
|
+
provingResponse?: unknown;
|
|
95
|
+
}>;
|
|
96
|
+
/**
|
|
97
|
+
* List this wallet's owned Aleo records across every program (credits +
|
|
98
|
+
* stablecoins + ARC-21). Backed by Provable's RecordScanner via the
|
|
99
|
+
* iframe — view key never leaves the iframe.
|
|
100
|
+
*
|
|
101
|
+
* Each entry carries `program_name` + `record_name` so callers can
|
|
102
|
+
* group/display by token.
|
|
103
|
+
*/
|
|
104
|
+
listOwnedRecords(): Promise<{
|
|
105
|
+
records: unknown[];
|
|
106
|
+
}>;
|
|
107
|
+
/**
|
|
108
|
+
* Pairwise-merge owned records down to one per program by running
|
|
109
|
+
* `<program>/join` until a single record remains. Sponsored by Feemaster
|
|
110
|
+
* for `credits.aleo` today; stablecoin / ARC-21 fall through to user-paid
|
|
111
|
+
* if Feemaster doesn't yet cover the pair.
|
|
112
|
+
*
|
|
113
|
+
* Programs the connector doesn't recognise (no registered join shape)
|
|
114
|
+
* are reported as `skipped: 'unsupported'` rather than thrown — iterate
|
|
115
|
+
* `results` to surface what merged vs. what didn't.
|
|
116
|
+
*/
|
|
117
|
+
joinRecords(opts?: Parameters<DynamicWaasAleoConnector['joinRecords']>[0]): Promise<Awaited<ReturnType<DynamicWaasAleoConnector['joinRecords']>>>;
|
|
118
|
+
/**
|
|
119
|
+
* Shield (`<program>/transfer_public_to_private`) `amount` of a token
|
|
120
|
+
* from this wallet's *public* balance into a fresh private record owned
|
|
121
|
+
* by self. `tokenAddress` matches `TokenBalance.address` from the
|
|
122
|
+
* unshielded-balance feed; pass `isNative: true` for native ALEO.
|
|
123
|
+
*/
|
|
124
|
+
shieldToken(args: {
|
|
125
|
+
tokenAddress: string;
|
|
126
|
+
isNative?: boolean;
|
|
127
|
+
amount: bigint;
|
|
128
|
+
}): Promise<string>;
|
|
129
|
+
/**
|
|
130
|
+
* Returns `true` when the given token is registered as shieldable on the
|
|
131
|
+
* currently-selected Aleo network. Used to gate "Shield Manually" UI on
|
|
132
|
+
* unshielded balances surfaced by the public-balance feed (which can
|
|
133
|
+
* include third-party Aleo programs we don't know how to shield).
|
|
134
|
+
*/
|
|
135
|
+
canShieldToken(token: {
|
|
136
|
+
address?: string;
|
|
137
|
+
isNative?: boolean;
|
|
138
|
+
}): boolean;
|
|
139
|
+
/**
|
|
140
|
+
* Returns `true` when the Feemaster currently sponsors a shield
|
|
141
|
+
* (`transfer_public_to_private`) of the given token. Used to decide
|
|
142
|
+
* whether the shield CTA can dispatch silently or needs a user-paid fee
|
|
143
|
+
* confirmation modal.
|
|
144
|
+
*/
|
|
145
|
+
isShieldSponsored(token: {
|
|
146
|
+
address?: string;
|
|
147
|
+
isNative?: boolean;
|
|
148
|
+
}): Promise<boolean>;
|
|
149
|
+
/**
|
|
150
|
+
* Generic Feemaster sponsorship check for any `(programId, functionName)`
|
|
151
|
+
* pair on the currently-selected network. Never throws — returns `false`
|
|
152
|
+
* on any failure so callers default to "show modal".
|
|
153
|
+
*/
|
|
154
|
+
isFeemasterSponsored(args: {
|
|
155
|
+
programId: string;
|
|
156
|
+
functionName: string;
|
|
157
|
+
}): Promise<boolean>;
|
|
57
158
|
}
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import { __awaiter } from '../../../_virtual/_tslib.js';
|
|
3
3
|
import { DynamicError } from '@dynamic-labs/utils';
|
|
4
4
|
import { Wallet } from '@dynamic-labs/wallet-connector-core';
|
|
5
|
+
import { getAleoExplorerTxUrl } from '../../utils/getAleoExplorerTxUrl/getAleoExplorerTxUrl.js';
|
|
5
6
|
|
|
6
7
|
class AleoWallet extends Wallet {
|
|
7
8
|
sendBalance(_a) {
|
|
@@ -43,6 +44,23 @@ class AleoWallet extends Wallet {
|
|
|
43
44
|
getPublicKey() {
|
|
44
45
|
return this.address;
|
|
45
46
|
}
|
|
47
|
+
/**
|
|
48
|
+
* Build the Provable explorer URL for an Aleo transaction id, scoped to
|
|
49
|
+
* this wallet's currently-selected network. `0` = mainnet, `1` = testnet.
|
|
50
|
+
* Available on every Aleo wallet flavour (embedded + Wallet Adapter).
|
|
51
|
+
*
|
|
52
|
+
* Use this to link freshly-broadcast txIds back to the explorer in your
|
|
53
|
+
* UI — e.g. after `wallet.proveTransaction()`, `wallet.shieldToken()`, or
|
|
54
|
+
* the Send flow returns. For Exchange-mode Send the returned txId is the
|
|
55
|
+
* second (`transfer_public`) transaction, which is the one the user
|
|
56
|
+
* cares about.
|
|
57
|
+
*/
|
|
58
|
+
getExplorerTransactionUrl(txId) {
|
|
59
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
60
|
+
const networkId = yield this._connector.getNetwork();
|
|
61
|
+
return getAleoExplorerTxUrl(txId, networkId);
|
|
62
|
+
});
|
|
63
|
+
}
|
|
46
64
|
/**
|
|
47
65
|
* Returns the current network this wallet is connected to (e.g. 'aleo:mainnet').
|
|
48
66
|
*/
|
|
@@ -99,6 +117,119 @@ class AleoWallet extends Wallet {
|
|
|
99
117
|
return this._connector.requestRecords(program, options);
|
|
100
118
|
});
|
|
101
119
|
}
|
|
120
|
+
// -------------------------------------------------------------------------
|
|
121
|
+
// Embedded-WaaS proxy methods.
|
|
122
|
+
//
|
|
123
|
+
// The methods below delegate to `DynamicWaasAleoConnector` and only work
|
|
124
|
+
// when the wallet is an embedded Dynamic WaaS Aleo wallet. They throw on
|
|
125
|
+
// Wallet Adapter wallets (which expose `requestTransaction` /
|
|
126
|
+
// `requestRecords` for the same flows but route through the adapter app
|
|
127
|
+
// rather than Sodot MPC + Feemaster + DPS).
|
|
128
|
+
//
|
|
129
|
+
// Convenience over `(wallet.connector as DynamicWaasAleoConnector).foo`:
|
|
130
|
+
// - typed entry point on `wallet.*` matching the docs convention used
|
|
131
|
+
// for Stellar (`wallet.signTransaction`), EVM (`wallet.getPublicClient`),
|
|
132
|
+
// etc.
|
|
133
|
+
// - auto-sets `connector.activeAccountAddress` from `this.address` so
|
|
134
|
+
// callers don't have to mutate connector internals before each call.
|
|
135
|
+
// -------------------------------------------------------------------------
|
|
136
|
+
/**
|
|
137
|
+
* Resolves `this._connector` to a `DynamicWaasAleoConnector` and aligns
|
|
138
|
+
* its `activeAccountAddress` with this wallet's address. Duck-types on
|
|
139
|
+
* `proveTransaction` (the WaaS-specific entry point) so we don't need a
|
|
140
|
+
* runtime import of the WaaS connector. Throws a clear `DynamicError`
|
|
141
|
+
* if the underlying connector is the Wallet Adapter one.
|
|
142
|
+
*/
|
|
143
|
+
getWaasConnectorOrThrow(methodName) {
|
|
144
|
+
const c = this._connector;
|
|
145
|
+
if (typeof c.proveTransaction !== 'function') {
|
|
146
|
+
throw new DynamicError(`AleoWallet.${methodName}() is only available on embedded Aleo wallets (Dynamic WaaS). For Wallet Adapter Aleo wallets use \`requestTransaction\` / \`requestRecords\` instead.`);
|
|
147
|
+
}
|
|
148
|
+
c.activeAccountAddress = this.address;
|
|
149
|
+
return c;
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Sign + prove + broadcast an arbitrary Aleo program transition through
|
|
153
|
+
* the Dynamic WaaS pipeline (Sodot MPC → optional Sealance proof
|
|
154
|
+
* injection → Feemaster sponsorship when covered → Provable DPS).
|
|
155
|
+
*
|
|
156
|
+
* Use this for the generic "execute any transition" path. The Send flow
|
|
157
|
+
* driven by the widget builds on top of this via `createUiTransaction`.
|
|
158
|
+
*/
|
|
159
|
+
proveTransaction(args) {
|
|
160
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
161
|
+
return this.getWaasConnectorOrThrow('proveTransaction').proveTransaction(args);
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* List this wallet's owned Aleo records across every program (credits +
|
|
166
|
+
* stablecoins + ARC-21). Backed by Provable's RecordScanner via the
|
|
167
|
+
* iframe — view key never leaves the iframe.
|
|
168
|
+
*
|
|
169
|
+
* Each entry carries `program_name` + `record_name` so callers can
|
|
170
|
+
* group/display by token.
|
|
171
|
+
*/
|
|
172
|
+
listOwnedRecords() {
|
|
173
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
174
|
+
return this.getWaasConnectorOrThrow('listOwnedRecords').listOwnedRecords();
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Pairwise-merge owned records down to one per program by running
|
|
179
|
+
* `<program>/join` until a single record remains. Sponsored by Feemaster
|
|
180
|
+
* for `credits.aleo` today; stablecoin / ARC-21 fall through to user-paid
|
|
181
|
+
* if Feemaster doesn't yet cover the pair.
|
|
182
|
+
*
|
|
183
|
+
* Programs the connector doesn't recognise (no registered join shape)
|
|
184
|
+
* are reported as `skipped: 'unsupported'` rather than thrown — iterate
|
|
185
|
+
* `results` to surface what merged vs. what didn't.
|
|
186
|
+
*/
|
|
187
|
+
joinRecords(opts) {
|
|
188
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
189
|
+
return this.getWaasConnectorOrThrow('joinRecords').joinRecords(opts);
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* Shield (`<program>/transfer_public_to_private`) `amount` of a token
|
|
194
|
+
* from this wallet's *public* balance into a fresh private record owned
|
|
195
|
+
* by self. `tokenAddress` matches `TokenBalance.address` from the
|
|
196
|
+
* unshielded-balance feed; pass `isNative: true` for native ALEO.
|
|
197
|
+
*/
|
|
198
|
+
shieldToken(args) {
|
|
199
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
200
|
+
return this.getWaasConnectorOrThrow('shieldToken').shieldToken(args);
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* Returns `true` when the given token is registered as shieldable on the
|
|
205
|
+
* currently-selected Aleo network. Used to gate "Shield Manually" UI on
|
|
206
|
+
* unshielded balances surfaced by the public-balance feed (which can
|
|
207
|
+
* include third-party Aleo programs we don't know how to shield).
|
|
208
|
+
*/
|
|
209
|
+
canShieldToken(token) {
|
|
210
|
+
return this.getWaasConnectorOrThrow('canShieldToken').canShieldToken(token);
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* Returns `true` when the Feemaster currently sponsors a shield
|
|
214
|
+
* (`transfer_public_to_private`) of the given token. Used to decide
|
|
215
|
+
* whether the shield CTA can dispatch silently or needs a user-paid fee
|
|
216
|
+
* confirmation modal.
|
|
217
|
+
*/
|
|
218
|
+
isShieldSponsored(token) {
|
|
219
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
220
|
+
return this.getWaasConnectorOrThrow('isShieldSponsored').isShieldSponsored(token);
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* Generic Feemaster sponsorship check for any `(programId, functionName)`
|
|
225
|
+
* pair on the currently-selected network. Never throws — returns `false`
|
|
226
|
+
* on any failure so callers default to "show modal".
|
|
227
|
+
*/
|
|
228
|
+
isFeemasterSponsored(args) {
|
|
229
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
230
|
+
return this.getWaasConnectorOrThrow('isFeemasterSponsored').isFeemasterSponsored(args);
|
|
231
|
+
});
|
|
232
|
+
}
|
|
102
233
|
}
|
|
103
234
|
|
|
104
235
|
export { AleoWallet };
|