@trustware/sdk-staging 1.1.9-staging.5 → 1.1.9-staging.7

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/dist/wallet.d.cts CHANGED
@@ -1,6 +1,6 @@
1
- import { u as SolanaProviderLike, Q as WalletMeta, h as DetectedWallet, M as WalletId, v as SolanaWalletInterface } from './manager-B5aklGtm.cjs';
2
- export { A as WagmiBridge, C as WagmiConnector, a1 as WalletSnapshot, a2 as useWalletConnectConnect, Z as useWalletExternalDisconnect, _ as useWalletInfo, $ as useWireDetectionIntoManager, a0 as walletManager } from './manager-B5aklGtm.cjs';
3
- export { d as autoDetectWallet, e as buildDetectedWalletFromProvider, c as connectDetectedWallet, f as createWalletConnectEntry, t as toWalletInterfaceFromDetected, u as useEIP1193, g as useIsMobile, a as useWagmi, b as useWalletDetection } from './detect-DVpECOTa.cjs';
1
+ import { v as SolanaProviderLike, U as WalletMeta, h as DetectedWallet, N as WalletId, w as SolanaWalletInterface } from './manager-DWFNyouP.cjs';
2
+ export { C as WagmiBridge, G as WagmiConnector, a2 as WalletSnapshot, a3 as useWalletConnectConnect, _ as useWalletExternalDisconnect, $ as useWalletInfo, a0 as useWireDetectionIntoManager, a1 as walletManager } from './manager-DWFNyouP.cjs';
3
+ export { d as autoDetectWallet, e as buildDetectedWalletFromProvider, c as connectDetectedWallet, f as createWalletConnectEntry, t as toWalletInterfaceFromDetected, u as useEIP1193, g as useIsMobile, a as useWagmi, b as useWalletDetection } from './detect-DWL4uExV.cjs';
4
4
  import './blockchain-BxAFzp0s.cjs';
5
5
 
6
6
  type SolanaEventHandlers = {
@@ -8,6 +8,8 @@ type SolanaEventHandlers = {
8
8
  onAccountChanged?: () => void;
9
9
  onDisconnect?: () => void;
10
10
  };
11
+ declare function decodeBase64(serializedTransaction: string): Uint8Array<ArrayBuffer>;
12
+ declare function encodeBase64(bytes: Uint8Array): string;
11
13
  declare function getSolanaProviders(): Partial<Record<WalletId, SolanaProviderLike>>;
12
14
  declare function detectSolanaWallets(wallets: WalletMeta[]): DetectedWallet[];
13
15
  declare function bindSolanaProviderEvents(provider: SolanaProviderLike, handlers: SolanaEventHandlers): () => void;
@@ -35,4 +37,4 @@ declare function formatWalletConnectDeepLink(wcUri: string): string;
35
37
  */
36
38
  declare function formatWalletConnectDeepLinkForWallet(walletId: string, wcUri: string): string;
37
39
 
38
- export { POPULAR_ORDER, WALLETS, bindSolanaProviderEvents, detectSolanaWallets, formatDeepLink, formatWalletConnectDeepLink, formatWalletConnectDeepLinkForWallet, getSolanaProviders, toSolanaWalletInterface };
40
+ export { POPULAR_ORDER, WALLETS, bindSolanaProviderEvents, decodeBase64, detectSolanaWallets, encodeBase64, formatDeepLink, formatWalletConnectDeepLink, formatWalletConnectDeepLinkForWallet, getSolanaProviders, toSolanaWalletInterface };
package/dist/wallet.d.ts CHANGED
@@ -1,6 +1,6 @@
1
- import { u as SolanaProviderLike, Q as WalletMeta, h as DetectedWallet, M as WalletId, v as SolanaWalletInterface } from './manager-xFiq0SHr.js';
2
- export { A as WagmiBridge, C as WagmiConnector, a1 as WalletSnapshot, a2 as useWalletConnectConnect, Z as useWalletExternalDisconnect, _ as useWalletInfo, $ as useWireDetectionIntoManager, a0 as walletManager } from './manager-xFiq0SHr.js';
3
- export { d as autoDetectWallet, e as buildDetectedWalletFromProvider, c as connectDetectedWallet, f as createWalletConnectEntry, t as toWalletInterfaceFromDetected, u as useEIP1193, g as useIsMobile, a as useWagmi, b as useWalletDetection } from './detect-d2PUaxE_.js';
1
+ import { v as SolanaProviderLike, U as WalletMeta, h as DetectedWallet, N as WalletId, w as SolanaWalletInterface } from './manager-Dn4muk74.js';
2
+ export { C as WagmiBridge, G as WagmiConnector, a2 as WalletSnapshot, a3 as useWalletConnectConnect, _ as useWalletExternalDisconnect, $ as useWalletInfo, a0 as useWireDetectionIntoManager, a1 as walletManager } from './manager-Dn4muk74.js';
3
+ export { d as autoDetectWallet, e as buildDetectedWalletFromProvider, c as connectDetectedWallet, f as createWalletConnectEntry, t as toWalletInterfaceFromDetected, u as useEIP1193, g as useIsMobile, a as useWagmi, b as useWalletDetection } from './detect-Cprq6X9o.js';
4
4
  import './blockchain-BxAFzp0s.js';
5
5
 
6
6
  type SolanaEventHandlers = {
@@ -8,6 +8,8 @@ type SolanaEventHandlers = {
8
8
  onAccountChanged?: () => void;
9
9
  onDisconnect?: () => void;
10
10
  };
11
+ declare function decodeBase64(serializedTransaction: string): Uint8Array<ArrayBuffer>;
12
+ declare function encodeBase64(bytes: Uint8Array): string;
11
13
  declare function getSolanaProviders(): Partial<Record<WalletId, SolanaProviderLike>>;
12
14
  declare function detectSolanaWallets(wallets: WalletMeta[]): DetectedWallet[];
13
15
  declare function bindSolanaProviderEvents(provider: SolanaProviderLike, handlers: SolanaEventHandlers): () => void;
@@ -35,4 +37,4 @@ declare function formatWalletConnectDeepLink(wcUri: string): string;
35
37
  */
36
38
  declare function formatWalletConnectDeepLinkForWallet(walletId: string, wcUri: string): string;
37
39
 
38
- export { POPULAR_ORDER, WALLETS, bindSolanaProviderEvents, detectSolanaWallets, formatDeepLink, formatWalletConnectDeepLink, formatWalletConnectDeepLinkForWallet, getSolanaProviders, toSolanaWalletInterface };
40
+ export { POPULAR_ORDER, WALLETS, bindSolanaProviderEvents, decodeBase64, detectSolanaWallets, encodeBase64, formatDeepLink, formatWalletConnectDeepLink, formatWalletConnectDeepLinkForWallet, getSolanaProviders, toSolanaWalletInterface };
package/dist/wallet.mjs CHANGED
@@ -224,7 +224,7 @@ var init_constants = __esm({
224
224
  "src/constants.ts"() {
225
225
  "use strict";
226
226
  SDK_NAME = "@trustware/sdk";
227
- SDK_VERSION = "1.1.9-staging.5";
227
+ SDK_VERSION = "1.1.9-staging.7";
228
228
  API_ROOT = "https://bv-staging-api.trustware.io";
229
229
  API_PREFIX = "/api";
230
230
  WALLETCONNECT_PROJECT_ID = "72ea74c400f5111d43aea638d7d83a24";
@@ -1188,7 +1188,9 @@ var init_chains = __esm({
1188
1188
  btc: "bitcoin",
1189
1189
  bitcoin: "bitcoin",
1190
1190
  sei: "cosmos",
1191
- "pacific-1": "cosmos"
1191
+ "pacific-1": "cosmos",
1192
+ nibiru: "cosmos",
1193
+ "cataclysm-1": "cosmos"
1192
1194
  };
1193
1195
  }
1194
1196
  });
@@ -1232,16 +1234,23 @@ function validateEvmAddress(address) {
1232
1234
  }
1233
1235
  return { isValid: true };
1234
1236
  }
1235
- function validateSeiAddress(address) {
1237
+ function resolveCosmosBech32Prefix(chain) {
1238
+ const chainDef = typeof chain === "object" && chain ? chain : void 0;
1239
+ const identifier = chainDef?.networkIdentifier ?? chainDef?.chainId ?? chainDef?.id ?? (typeof chain === "string" ? chain : void 0);
1240
+ const normalized = String(identifier ?? "").trim().toLowerCase();
1241
+ return COSMOS_BECH32_PREFIX_BY_CHAIN_ID[normalized] ?? "sei";
1242
+ }
1243
+ function validateCosmosAddress(address, chain) {
1236
1244
  const trimmed = address.trim();
1237
- if (isEvmAddress(trimmed)) {
1245
+ const prefix = resolveCosmosBech32Prefix(chain);
1246
+ if (prefix === "sei" && isEvmAddress(trimmed)) {
1238
1247
  return { isValid: true };
1239
1248
  }
1240
- const result = validateBech32LikeAddress(trimmed, "sei");
1249
+ const result = validateBech32LikeAddress(trimmed, prefix);
1241
1250
  if (result.isValid) return result;
1242
1251
  return {
1243
1252
  isValid: false,
1244
- error: "SEI addresses must be 0x-prefixed EVM or sei1 bech32 strings."
1253
+ error: prefix === "sei" ? "SEI addresses must be 0x-prefixed EVM or sei1 bech32 strings." : `Address must be a valid ${prefix}1 bech32 string.`
1245
1254
  };
1246
1255
  }
1247
1256
  function validateSolanaAddress(address) {
@@ -1291,21 +1300,49 @@ function validateAddressForChain(address, chain) {
1291
1300
  case "bitcoin":
1292
1301
  return validateBtcAddress(trimmed);
1293
1302
  case "cosmos":
1294
- if (chainDef?.networkIdentifier?.toLowerCase() === "sei") {
1295
- return validateSeiAddress(trimmed);
1296
- }
1297
- return validateBech32LikeAddress(trimmed, "sei");
1303
+ return validateCosmosAddress(trimmed, chainDef ?? chain);
1298
1304
  default:
1299
1305
  return { isValid: false, error: "Unsupported or unknown chain type." };
1300
1306
  }
1301
1307
  }
1302
- var BECH32_CHARSET;
1308
+ var BECH32_CHARSET, COSMOS_BECH32_PREFIX_BY_CHAIN_ID;
1303
1309
  var init_address = __esm({
1304
1310
  "src/validation/address.ts"() {
1305
1311
  "use strict";
1306
1312
  init_index_node4();
1307
1313
  init_chains();
1308
1314
  BECH32_CHARSET = /^[023456789acdefghjklmnpqrstuvwxyz]+$/i;
1315
+ COSMOS_BECH32_PREFIX_BY_CHAIN_ID = {
1316
+ "pacific-1": "sei",
1317
+ sei: "sei",
1318
+ "cataclysm-1": "nibi",
1319
+ nibiru: "nibi"
1320
+ };
1321
+ }
1322
+ });
1323
+
1324
+ // src/errors/TrustwareError.ts
1325
+ var TrustwareError;
1326
+ var init_TrustwareError = __esm({
1327
+ "src/errors/TrustwareError.ts"() {
1328
+ "use strict";
1329
+ TrustwareError = class extends Error {
1330
+ constructor(params) {
1331
+ super(params.message);
1332
+ this.name = "TrustwareError";
1333
+ this.code = params.code;
1334
+ this.userMessage = params.userMessage;
1335
+ this.cause = params.cause;
1336
+ }
1337
+ toJSON() {
1338
+ return {
1339
+ name: this.name,
1340
+ code: this.code,
1341
+ message: this.message,
1342
+ userMessage: this.userMessage
1343
+ };
1344
+ }
1345
+ };
1309
1346
  }
1310
1347
  });
1311
1348
 
@@ -1314,21 +1351,28 @@ function formatDeepLink(id, currentUrl) {
1314
1351
  const enc = encodeURIComponent(currentUrl);
1315
1352
  switch (id) {
1316
1353
  // EVM
1354
+ // MetaMask's dapp browser also exposes its Wallet Standard Solana
1355
+ // provider in the same session, so "metamask-solana" reuses this link.
1317
1356
  case "metamask":
1357
+ case "metamask-solana":
1318
1358
  return `metamask://dapp/${currentUrl}`;
1319
1359
  case "coinbase":
1320
1360
  return `coinbase://wallet/dapp?url=${enc}`;
1321
1361
  case "rainbow":
1322
- return `rainbow://connect?uri=${enc}`;
1362
+ return `https://rainbow.me/dapp?url=${enc}`;
1323
1363
  case "trust":
1324
1364
  return `https://link.trustwallet.com/open_url?coin_id=60&url=${enc}`;
1325
1365
  case "okx":
1326
1366
  return `okx://wallet/dapp/url?dappUrl=${enc}`;
1327
1367
  // Solana
1368
+ // Phantom is one app with one in-app browser — browsing there injects
1369
+ // both window.ethereum and window.phantom.solana, so "phantom-evm"
1370
+ // reuses the same browse link as "phantom-solana".
1328
1371
  case "phantom-solana":
1329
- return `phantom://browse/${enc}`;
1372
+ case "phantom-evm":
1373
+ return `https://phantom.app/ul/browse/${enc}?ref=${enc}`;
1330
1374
  case "solflare":
1331
- return `solflare://ul/v1/browse/${enc}`;
1375
+ return `https://solflare.com/ul/v1/browse/${enc}?ref=${enc}`;
1332
1376
  case "backpack":
1333
1377
  return `https://backpack.app/ul/v1/browse/${enc}?ref=${enc}`;
1334
1378
  // No confirmed deep link scheme
@@ -1477,8 +1521,10 @@ var init_metadata = __esm({
1477
1521
  homepage: "https://phantom.app/",
1478
1522
  ios: "https://apps.apple.com/app/phantom-crypto-wallet/id1598432977",
1479
1523
  android: "https://play.google.com/store/apps/details?id=app.phantom",
1480
- detectFlags: ["isPhantom"]
1481
- // No EVM dapp browser deep link — falls back to app store
1524
+ detectFlags: ["isPhantom"],
1525
+ // Same app/in-app browser as "phantom-solana" — browsing there injects
1526
+ // window.ethereum too.
1527
+ deepLink: (url) => formatDeepLink("phantom-evm", url) ?? ""
1482
1528
  },
1483
1529
  {
1484
1530
  id: "phantom-solana",
@@ -1526,8 +1572,10 @@ var init_metadata = __esm({
1526
1572
  emoji: "\u{1F98A}",
1527
1573
  homepage: "https://metamask.io/",
1528
1574
  ios: "https://apps.apple.com/app/metamask/id1438144202",
1529
- android: "https://play.google.com/store/apps/details?id=io.metamask"
1530
- // No Solana-specific deep link for MetaMask
1575
+ android: "https://play.google.com/store/apps/details?id=io.metamask",
1576
+ // Same app/in-app browser as "metamask" — its Wallet Standard Solana
1577
+ // provider is exposed in that same browse session.
1578
+ deepLink: (url) => formatDeepLink("metamask-solana", url) ?? ""
1531
1579
  },
1532
1580
  // ── Extension/desktop only — hidden on mobile ─────────────────────────────
1533
1581
  {
@@ -2050,7 +2098,7 @@ var init_walletconnect = __esm({
2050
2098
  solanaMainnet = {
2051
2099
  id: 900,
2052
2100
  chainNamespace: "solana",
2053
- caipNetworkId: "solana:5eykt4UsFv8P8NJdTREpY1vzqAQ3H1FQ",
2101
+ caipNetworkId: "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp",
2054
2102
  name: "Solana Mainnet",
2055
2103
  nativeCurrency: {
2056
2104
  name: "Solana",
@@ -2929,8 +2977,62 @@ function getChainMeta(chainId) {
2929
2977
  rpcUrls: chain.rpcUrls.default.http
2930
2978
  };
2931
2979
  }
2932
- async function buildWalletConnectAPI(walletCfg) {
2980
+ function extractSolanaAddress(connector) {
2981
+ const caipAccount = connector.provider.session?.namespaces?.solana?.accounts?.[0];
2982
+ if (!caipAccount) return null;
2983
+ return caipAccount.split(":")[2] ?? null;
2984
+ }
2985
+ function buildWalletConnectSolanaProvider(connector) {
2986
+ return {
2987
+ get publicKey() {
2988
+ const address = extractSolanaAddress(connector);
2989
+ return address ? { toString: () => address } : void 0;
2990
+ },
2991
+ async connect() {
2992
+ const address = extractSolanaAddress(connector);
2993
+ if (!address) {
2994
+ throw new Error(
2995
+ "This wallet did not approve a Solana account over WalletConnect."
2996
+ );
2997
+ }
2998
+ return { publicKey: { toString: () => address } };
2999
+ },
3000
+ async disconnect() {
3001
+ },
3002
+ async signTransaction(transaction) {
3003
+ const tx = transaction;
3004
+ const rawBytes = "version" in tx ? tx.serialize() : tx.serialize({
3005
+ requireAllSignatures: false,
3006
+ verifySignatures: false
3007
+ });
3008
+ const result = await connector.provider.request(
3009
+ {
3010
+ method: "solana_signTransaction",
3011
+ params: { transaction: encodeBase64(rawBytes) }
3012
+ },
3013
+ solanaMainnet.caipNetworkId
3014
+ );
3015
+ if (!result.transaction) {
3016
+ throw new Error(
3017
+ "WalletConnect wallet did not return a signed Solana transaction."
3018
+ );
3019
+ }
3020
+ const signedBytes = decodeBase64(result.transaction);
3021
+ return { serialize: () => signedBytes };
3022
+ },
3023
+ on() {
3024
+ },
3025
+ off() {
3026
+ },
3027
+ removeListener() {
3028
+ }
3029
+ };
3030
+ }
3031
+ async function buildWalletConnectAPI(walletCfg, ecosystem = "evm") {
2933
3032
  const connector = await getUniversalConnector(walletCfg);
3033
+ if (ecosystem === "solana") {
3034
+ return toSolanaWalletInterface(buildWalletConnectSolanaProvider(connector));
3035
+ }
2934
3036
  const provider = connector.provider;
2935
3037
  const api = {
2936
3038
  ecosystem: "evm",
@@ -3006,7 +3108,7 @@ function useWireDetectionIntoManager() {
3006
3108
  function useWalletConnectConnect(walletCfg) {
3007
3109
  const cfgRef = { current: walletCfg };
3008
3110
  return useCallback(
3009
- () => walletManager.connectWalletConnect(cfgRef.current),
3111
+ (ecosystem) => walletManager.connectWalletConnect(cfgRef.current, ecosystem),
3010
3112
  []
3011
3113
  );
3012
3114
  }
@@ -3026,6 +3128,7 @@ function useWalletInfo(wagmi) {
3026
3128
  connectedVia: snapshot.connectedVia,
3027
3129
  walletType: snapshot.walletType,
3028
3130
  status: snapshot.status,
3131
+ detected: snapshot.detected,
3029
3132
  disconnect
3030
3133
  };
3031
3134
  }
@@ -3177,44 +3280,39 @@ var init_manager = __esm({
3177
3280
  this.emit();
3178
3281
  }
3179
3282
  }
3180
- async connectWalletConnect(walletCfg) {
3181
- if (this._status === "connected" && this._connectedVia === "walletconnect" && this._wallet) {
3283
+ async connectWalletConnect(walletCfg, ecosystem = "evm") {
3284
+ if (this._status === "connected" && this._connectedVia === "walletconnect" && this._wallet && this._wallet.ecosystem === ecosystem) {
3182
3285
  this.emit();
3183
3286
  return { error: null, api: this._wallet };
3184
3287
  }
3288
+ if (this._connectedVia === "walletconnect" && this._wallet) {
3289
+ await this._wallet.disconnect?.().catch(() => {
3290
+ });
3291
+ resetUniversalConnector();
3292
+ }
3185
3293
  this._status = "connecting";
3186
3294
  this.clearConnectedState();
3187
3295
  this.emit();
3188
3296
  try {
3189
3297
  const connector = await getUniversalConnector(walletCfg);
3190
3298
  await connector.connect();
3191
- const api = await buildWalletConnectAPI(walletCfg);
3299
+ const api = await buildWalletConnectAPI(walletCfg, ecosystem);
3300
+ try {
3301
+ await api.getAddress();
3302
+ } catch {
3303
+ await api.disconnect?.().catch(() => {
3304
+ });
3305
+ resetUniversalConnector();
3306
+ throw new Error(
3307
+ `This wallet did not approve a${ecosystem === "evm" ? "n" : ""} ${ecosystem === "evm" ? "EVM" : "Solana"} account over WalletConnect.`
3308
+ );
3309
+ }
3192
3310
  this._wallet = api;
3193
3311
  this._connectedVia = "walletconnect";
3194
3312
  this._connectedWalletId = "walletconnect";
3195
- const provider = connector.provider;
3196
- this._providerCleanup = bindWalletConnectEvents(provider, {
3197
- onAccountsChanged: (accounts) => {
3198
- if (accounts.length === 0) {
3199
- this.fullReset();
3200
- this.triggerExternalDisconnect();
3201
- this.emit();
3202
- return;
3203
- }
3204
- void this.syncIdentityFromWallet("walletconnect");
3205
- this.emit();
3206
- },
3207
- onChainChanged: () => {
3208
- void this.syncIdentityFromWallet("walletconnect");
3209
- this.emit();
3210
- },
3211
- onDisconnect: () => {
3212
- this.fullReset();
3213
- resetUniversalConnector();
3214
- this.triggerExternalDisconnect();
3215
- this.emit();
3216
- }
3217
- });
3313
+ this._providerCleanup = this.bindWalletConnectProviderEvents(
3314
+ connector.provider
3315
+ );
3218
3316
  await this.syncIdentityFromWallet("walletconnect");
3219
3317
  this._status = "connected";
3220
3318
  this._error = null;
@@ -3229,6 +3327,100 @@ var init_manager = __esm({
3229
3327
  return { error: message, api: null };
3230
3328
  }
3231
3329
  }
3330
+ bindWalletConnectProviderEvents(provider) {
3331
+ return bindWalletConnectEvents(provider, {
3332
+ onAccountsChanged: (accounts) => {
3333
+ if (accounts.length === 0) {
3334
+ this.fullReset();
3335
+ this.triggerExternalDisconnect();
3336
+ this.emit();
3337
+ return;
3338
+ }
3339
+ void this.syncIdentityFromWallet("walletconnect");
3340
+ this.emit();
3341
+ },
3342
+ onChainChanged: () => {
3343
+ void this.syncIdentityFromWallet("walletconnect");
3344
+ this.emit();
3345
+ },
3346
+ onDisconnect: () => {
3347
+ this.fullReset();
3348
+ resetUniversalConnector();
3349
+ this.triggerExternalDisconnect();
3350
+ this.emit();
3351
+ }
3352
+ });
3353
+ }
3354
+ // WalletConnect's own SignClient auto-restores the last persisted session
3355
+ // from storage on every init — including after a fresh page load — but
3356
+ // that restoration happens silently inside the library. Nothing calls back
3357
+ // into our code for it. On mobile, backgrounding the tab to approve in a
3358
+ // wallet app can cause the OS to reload the page before the original
3359
+ // connect() promise ever resolves, so the connect flow that triggered the
3360
+ // approval never gets to record it as "connected" here — even though
3361
+ // WalletConnect itself already has a live, approved session sitting in
3362
+ // storage. Call this on mount to pick that back up.
3363
+ async restoreWalletConnectSession(walletCfg) {
3364
+ if (this._status === "connected" && this._connectedVia === "walletconnect") {
3365
+ return this._wallet?.ecosystem === "solana" ? "solana" : "evm";
3366
+ }
3367
+ if (typeof window === "undefined") return null;
3368
+ try {
3369
+ if (!Object.keys(window.localStorage).some((key) => key.startsWith("wc@2"))) {
3370
+ return null;
3371
+ }
3372
+ } catch {
3373
+ }
3374
+ let connector;
3375
+ try {
3376
+ connector = await getUniversalConnector(walletCfg);
3377
+ } catch (e2) {
3378
+ console.warn(
3379
+ "[Trustware SDK] Failed to restore WalletConnect session:",
3380
+ e2
3381
+ );
3382
+ return null;
3383
+ }
3384
+ const session = connector.provider.session;
3385
+ if (!session) return null;
3386
+ const ecosystem = session.namespaces?.solana?.accounts?.length ? "solana" : session.namespaces?.eip155?.accounts?.length ? "evm" : null;
3387
+ if (!ecosystem) return null;
3388
+ try {
3389
+ const api = await buildWalletConnectAPI(walletCfg, ecosystem);
3390
+ this._wallet = api;
3391
+ this._connectedVia = "walletconnect";
3392
+ this._connectedWalletId = "walletconnect";
3393
+ this._providerCleanup = this.bindWalletConnectProviderEvents(
3394
+ connector.provider
3395
+ );
3396
+ await this.syncIdentityFromWallet("walletconnect");
3397
+ this._status = "connected";
3398
+ this._error = null;
3399
+ this.emit();
3400
+ return ecosystem;
3401
+ } catch {
3402
+ return null;
3403
+ }
3404
+ }
3405
+ // Forcibly abandon an in-progress connect() call the caller has decided is
3406
+ // stuck (e.g. the UI's own connect timeout elapsed with no response).
3407
+ // There's no clean way to cancel a pending WalletConnect pairing proposal
3408
+ // from this side, so this tears down the whole connector — the next
3409
+ // connect attempt starts against a brand new SignClient/pairing instead of
3410
+ // racing the abandoned one, which would otherwise risk reproducing the
3411
+ // "No matching key. proposal" class of error a real retry needs to avoid.
3412
+ cancelWalletConnectAttempt() {
3413
+ if (this._connectedVia === "walletconnect" && this._status === "connected") {
3414
+ return;
3415
+ }
3416
+ resetUniversalConnector();
3417
+ if (this._status === "connecting") {
3418
+ this.clearConnectedState();
3419
+ this._status = "idle";
3420
+ this._error = null;
3421
+ this.emit();
3422
+ }
3423
+ }
3232
3424
  async disconnect(wagmi) {
3233
3425
  if (wagmi && this._connectedVia === "extension") {
3234
3426
  await wagmi.disconnect().catch(() => {
@@ -3438,46 +3630,80 @@ function normalizeSlippage(v) {
3438
3630
  if (n > 5) return 5;
3439
3631
  return n;
3440
3632
  }
3633
+ function warnDeprecatedSwapModeFlag() {
3634
+ if (hasWarnedDeprecatedSwapModeFlag) return;
3635
+ hasWarnedDeprecatedSwapModeFlag = true;
3636
+ console.warn(
3637
+ '[Trustware SDK] `features.swapMode` is deprecated \u2014 use `mode: "swap"` on the top-level config instead.'
3638
+ );
3639
+ }
3640
+ function resolveMode(input) {
3641
+ if (input.mode === "swap") return "swap";
3642
+ if (input.mode === "deposit") return "deposit";
3643
+ if (input.features?.swapMode) {
3644
+ warnDeprecatedSwapModeFlag();
3645
+ return "swap";
3646
+ }
3647
+ return "deposit";
3648
+ }
3441
3649
  function resolveConfig(input) {
3442
3650
  if (!input?.apiKey) {
3443
- throw new Error("TrustwareConfig: 'apiKey' is required.");
3651
+ throw new TrustwareError({
3652
+ code: "INVALID_CONFIG" /* INVALID_CONFIG */,
3653
+ message: "TrustwareConfig: 'apiKey' is required.",
3654
+ userMessage: "Missing required API key configuration."
3655
+ });
3444
3656
  }
3445
- if (!input.routes?.toChain || !input.routes?.toToken) {
3446
- throw new Error(
3447
- "TrustwareConfig: 'routes.toChain' and 'routes.toToken' are required."
3448
- );
3657
+ const mode = resolveMode(input);
3658
+ if (mode === "deposit" && (!input.routes?.toChain || !input.routes?.toToken)) {
3659
+ throw new TrustwareError({
3660
+ code: "INVALID_CONFIG" /* INVALID_CONFIG */,
3661
+ message: "TrustwareConfig: 'routes.toChain' and 'routes.toToken' are required in deposit mode.",
3662
+ userMessage: "Missing required destination chain/token configuration."
3663
+ });
3449
3664
  }
3450
- const toChain = input.routes.toChain;
3451
- if (input.routes.toAddress) {
3665
+ const toChain = input.routes?.toChain;
3666
+ if (input.routes?.toAddress && toChain) {
3452
3667
  const result = validateAddressForChain(input.routes.toAddress, toChain);
3453
3668
  if (!result.isValid) {
3454
3669
  console.error(`[Trustware SDK] Invalid toAddress: ${result.error}`);
3455
- throw new Error(`Invalid toAddress: ${result.error}`);
3670
+ throw new TrustwareError({
3671
+ code: "INVALID_CONFIG" /* INVALID_CONFIG */,
3672
+ message: `Invalid toAddress: ${result.error}`,
3673
+ userMessage: "The configured destination address is invalid."
3674
+ });
3456
3675
  }
3457
3676
  }
3458
- if (input.routes.fromAddress) {
3459
- const result = validateAddressForChain(
3460
- input.routes.fromAddress,
3461
- input.routes.fromChain ?? toChain
3462
- );
3463
- if (!result.isValid) {
3464
- console.error(`[Trustware SDK] Invalid fromAddress: ${result.error}`);
3465
- throw new Error(`Invalid fromAddress: ${result.error}`);
3677
+ if (input.routes?.fromAddress) {
3678
+ const fromChain = input.routes.fromChain ?? toChain;
3679
+ if (fromChain) {
3680
+ const result = validateAddressForChain(
3681
+ input.routes.fromAddress,
3682
+ fromChain
3683
+ );
3684
+ if (!result.isValid) {
3685
+ console.error(`[Trustware SDK] Invalid fromAddress: ${result.error}`);
3686
+ throw new TrustwareError({
3687
+ code: "INVALID_CONFIG" /* INVALID_CONFIG */,
3688
+ message: `Invalid fromAddress: ${result.error}`,
3689
+ userMessage: "The configured source address is invalid."
3690
+ });
3691
+ }
3466
3692
  }
3467
3693
  }
3468
3694
  const autoDetectProvider = typeof input.autoDetectProvider === "boolean" ? input.autoDetectProvider : DEFAULT_AUTO_DETECT_PROVIDER;
3469
3695
  const routes = {
3470
- toChain: input.routes.toChain,
3471
- toToken: input.routes.toToken,
3472
- fromToken: input.routes.fromToken,
3473
- fromAddress: input.routes.fromAddress,
3474
- fromChain: input.routes.fromChain,
3475
- toAddress: input.routes.toAddress,
3696
+ toChain: input.routes?.toChain ?? "",
3697
+ toToken: input.routes?.toToken ?? "",
3698
+ fromToken: input.routes?.fromToken,
3699
+ fromAddress: input.routes?.fromAddress,
3700
+ fromChain: input.routes?.fromChain,
3701
+ toAddress: input.routes?.toAddress,
3476
3702
  defaultSlippage: normalizeSlippage(
3477
- input.routes.defaultSlippage ?? DEFAULT_SLIPPAGE
3703
+ input.routes?.defaultSlippage ?? DEFAULT_SLIPPAGE
3478
3704
  ),
3479
3705
  options: {
3480
- ...input.routes.options
3706
+ ...input.routes?.options
3481
3707
  }
3482
3708
  };
3483
3709
  const theme = input.theme ?? "system";
@@ -3496,13 +3722,16 @@ function resolveConfig(input) {
3496
3722
  tokensPagination: input.features?.tokensPagination ?? DEFAULT_FEATURE_FLAGS.tokensPagination,
3497
3723
  balanceStreaming: input.features?.balanceStreaming ?? DEFAULT_FEATURE_FLAGS.balanceStreaming,
3498
3724
  shouldAllowGA4: input.features?.shouldAllowGA4 ?? DEFAULT_FEATURE_FLAGS.shouldAllowGA4,
3499
- swapMode: input.features?.swapMode ?? DEFAULT_FEATURE_FLAGS.swapMode,
3725
+ // Always mirrors the canonical `mode`, however the caller set it (new `mode` field
3726
+ // or the deprecated `features.swapMode` flag).
3727
+ swapMode: mode === "swap",
3500
3728
  swapDefaultDestToken: input.features?.swapDefaultDestToken ?? DEFAULT_FEATURE_FLAGS.swapDefaultDestToken,
3501
3729
  swapLockDestToken: input.features?.swapLockDestToken ?? DEFAULT_FEATURE_FLAGS.swapLockDestToken,
3502
3730
  swapAllowedDestTokens: input.features?.swapAllowedDestTokens ?? DEFAULT_FEATURE_FLAGS.swapAllowedDestTokens
3503
3731
  };
3504
3732
  return {
3505
3733
  apiKey: input.apiKey,
3734
+ mode,
3506
3735
  routes,
3507
3736
  autoDetectProvider,
3508
3737
  theme,
@@ -3515,12 +3744,15 @@ function resolveConfig(input) {
3515
3744
  onEvent: input.onEvent
3516
3745
  };
3517
3746
  }
3747
+ var hasWarnedDeprecatedSwapModeFlag;
3518
3748
  var init_merge = __esm({
3519
3749
  "src/config/merge.ts"() {
3520
3750
  "use strict";
3521
3751
  init_defaults();
3522
3752
  init_config();
3523
3753
  init_index();
3754
+ init_TrustwareError();
3755
+ hasWarnedDeprecatedSwapModeFlag = false;
3524
3756
  }
3525
3757
  });
3526
3758
 
@@ -4095,7 +4327,9 @@ export {
4095
4327
  buildDetectedWalletFromProvider,
4096
4328
  connectDetectedWallet,
4097
4329
  createWalletConnectEntry,
4330
+ decodeBase64,
4098
4331
  detectSolanaWallets,
4332
+ encodeBase64,
4099
4333
  formatDeepLink,
4100
4334
  formatWalletConnectDeepLink,
4101
4335
  formatWalletConnectDeepLinkForWallet,