@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.cjs CHANGED
@@ -250,7 +250,7 @@ var init_constants = __esm({
250
250
  "src/constants.ts"() {
251
251
  "use strict";
252
252
  SDK_NAME = "@trustware/sdk";
253
- SDK_VERSION = "1.1.9-staging.5";
253
+ SDK_VERSION = "1.1.9-staging.7";
254
254
  API_ROOT = "https://bv-staging-api.trustware.io";
255
255
  API_PREFIX = "/api";
256
256
  WALLETCONNECT_PROJECT_ID = "72ea74c400f5111d43aea638d7d83a24";
@@ -1214,7 +1214,9 @@ var init_chains = __esm({
1214
1214
  btc: "bitcoin",
1215
1215
  bitcoin: "bitcoin",
1216
1216
  sei: "cosmos",
1217
- "pacific-1": "cosmos"
1217
+ "pacific-1": "cosmos",
1218
+ nibiru: "cosmos",
1219
+ "cataclysm-1": "cosmos"
1218
1220
  };
1219
1221
  }
1220
1222
  });
@@ -1257,16 +1259,23 @@ function validateEvmAddress(address) {
1257
1259
  }
1258
1260
  return { isValid: true };
1259
1261
  }
1260
- function validateSeiAddress(address) {
1262
+ function resolveCosmosBech32Prefix(chain) {
1263
+ const chainDef = typeof chain === "object" && chain ? chain : void 0;
1264
+ const identifier = chainDef?.networkIdentifier ?? chainDef?.chainId ?? chainDef?.id ?? (typeof chain === "string" ? chain : void 0);
1265
+ const normalized = String(identifier ?? "").trim().toLowerCase();
1266
+ return COSMOS_BECH32_PREFIX_BY_CHAIN_ID[normalized] ?? "sei";
1267
+ }
1268
+ function validateCosmosAddress(address, chain) {
1261
1269
  const trimmed = address.trim();
1262
- if ((0, import_viem.isAddress)(trimmed)) {
1270
+ const prefix = resolveCosmosBech32Prefix(chain);
1271
+ if (prefix === "sei" && (0, import_viem.isAddress)(trimmed)) {
1263
1272
  return { isValid: true };
1264
1273
  }
1265
- const result = validateBech32LikeAddress(trimmed, "sei");
1274
+ const result = validateBech32LikeAddress(trimmed, prefix);
1266
1275
  if (result.isValid) return result;
1267
1276
  return {
1268
1277
  isValid: false,
1269
- error: "SEI addresses must be 0x-prefixed EVM or sei1 bech32 strings."
1278
+ error: prefix === "sei" ? "SEI addresses must be 0x-prefixed EVM or sei1 bech32 strings." : `Address must be a valid ${prefix}1 bech32 string.`
1270
1279
  };
1271
1280
  }
1272
1281
  function validateSolanaAddress(address) {
@@ -1316,15 +1325,12 @@ function validateAddressForChain(address, chain) {
1316
1325
  case "bitcoin":
1317
1326
  return validateBtcAddress(trimmed);
1318
1327
  case "cosmos":
1319
- if (chainDef?.networkIdentifier?.toLowerCase() === "sei") {
1320
- return validateSeiAddress(trimmed);
1321
- }
1322
- return validateBech32LikeAddress(trimmed, "sei");
1328
+ return validateCosmosAddress(trimmed, chainDef ?? chain);
1323
1329
  default:
1324
1330
  return { isValid: false, error: "Unsupported or unknown chain type." };
1325
1331
  }
1326
1332
  }
1327
- var import_viem, BECH32_CHARSET;
1333
+ var import_viem, BECH32_CHARSET, COSMOS_BECH32_PREFIX_BY_CHAIN_ID;
1328
1334
  var init_address = __esm({
1329
1335
  "src/validation/address.ts"() {
1330
1336
  "use strict";
@@ -1332,6 +1338,37 @@ var init_address = __esm({
1332
1338
  init_index_node4();
1333
1339
  init_chains();
1334
1340
  BECH32_CHARSET = /^[023456789acdefghjklmnpqrstuvwxyz]+$/i;
1341
+ COSMOS_BECH32_PREFIX_BY_CHAIN_ID = {
1342
+ "pacific-1": "sei",
1343
+ sei: "sei",
1344
+ "cataclysm-1": "nibi",
1345
+ nibiru: "nibi"
1346
+ };
1347
+ }
1348
+ });
1349
+
1350
+ // src/errors/TrustwareError.ts
1351
+ var TrustwareError;
1352
+ var init_TrustwareError = __esm({
1353
+ "src/errors/TrustwareError.ts"() {
1354
+ "use strict";
1355
+ TrustwareError = class extends Error {
1356
+ constructor(params) {
1357
+ super(params.message);
1358
+ this.name = "TrustwareError";
1359
+ this.code = params.code;
1360
+ this.userMessage = params.userMessage;
1361
+ this.cause = params.cause;
1362
+ }
1363
+ toJSON() {
1364
+ return {
1365
+ name: this.name,
1366
+ code: this.code,
1367
+ message: this.message,
1368
+ userMessage: this.userMessage
1369
+ };
1370
+ }
1371
+ };
1335
1372
  }
1336
1373
  });
1337
1374
 
@@ -1340,21 +1377,28 @@ function formatDeepLink(id, currentUrl) {
1340
1377
  const enc = encodeURIComponent(currentUrl);
1341
1378
  switch (id) {
1342
1379
  // EVM
1380
+ // MetaMask's dapp browser also exposes its Wallet Standard Solana
1381
+ // provider in the same session, so "metamask-solana" reuses this link.
1343
1382
  case "metamask":
1383
+ case "metamask-solana":
1344
1384
  return `metamask://dapp/${currentUrl}`;
1345
1385
  case "coinbase":
1346
1386
  return `coinbase://wallet/dapp?url=${enc}`;
1347
1387
  case "rainbow":
1348
- return `rainbow://connect?uri=${enc}`;
1388
+ return `https://rainbow.me/dapp?url=${enc}`;
1349
1389
  case "trust":
1350
1390
  return `https://link.trustwallet.com/open_url?coin_id=60&url=${enc}`;
1351
1391
  case "okx":
1352
1392
  return `okx://wallet/dapp/url?dappUrl=${enc}`;
1353
1393
  // Solana
1394
+ // Phantom is one app with one in-app browser — browsing there injects
1395
+ // both window.ethereum and window.phantom.solana, so "phantom-evm"
1396
+ // reuses the same browse link as "phantom-solana".
1354
1397
  case "phantom-solana":
1355
- return `phantom://browse/${enc}`;
1398
+ case "phantom-evm":
1399
+ return `https://phantom.app/ul/browse/${enc}?ref=${enc}`;
1356
1400
  case "solflare":
1357
- return `solflare://ul/v1/browse/${enc}`;
1401
+ return `https://solflare.com/ul/v1/browse/${enc}?ref=${enc}`;
1358
1402
  case "backpack":
1359
1403
  return `https://backpack.app/ul/v1/browse/${enc}?ref=${enc}`;
1360
1404
  // No confirmed deep link scheme
@@ -1503,8 +1547,10 @@ var init_metadata = __esm({
1503
1547
  homepage: "https://phantom.app/",
1504
1548
  ios: "https://apps.apple.com/app/phantom-crypto-wallet/id1598432977",
1505
1549
  android: "https://play.google.com/store/apps/details?id=app.phantom",
1506
- detectFlags: ["isPhantom"]
1507
- // No EVM dapp browser deep link — falls back to app store
1550
+ detectFlags: ["isPhantom"],
1551
+ // Same app/in-app browser as "phantom-solana" — browsing there injects
1552
+ // window.ethereum too.
1553
+ deepLink: (url) => formatDeepLink("phantom-evm", url) ?? ""
1508
1554
  },
1509
1555
  {
1510
1556
  id: "phantom-solana",
@@ -1552,8 +1598,10 @@ var init_metadata = __esm({
1552
1598
  emoji: "\u{1F98A}",
1553
1599
  homepage: "https://metamask.io/",
1554
1600
  ios: "https://apps.apple.com/app/metamask/id1438144202",
1555
- android: "https://play.google.com/store/apps/details?id=io.metamask"
1556
- // No Solana-specific deep link for MetaMask
1601
+ android: "https://play.google.com/store/apps/details?id=io.metamask",
1602
+ // Same app/in-app browser as "metamask" — its Wallet Standard Solana
1603
+ // provider is exposed in that same browse session.
1604
+ deepLink: (url) => formatDeepLink("metamask-solana", url) ?? ""
1557
1605
  },
1558
1606
  // ── Extension/desktop only — hidden on mobile ─────────────────────────────
1559
1607
  {
@@ -2076,7 +2124,7 @@ var init_walletconnect = __esm({
2076
2124
  solanaMainnet = {
2077
2125
  id: 900,
2078
2126
  chainNamespace: "solana",
2079
- caipNetworkId: "solana:5eykt4UsFv8P8NJdTREpY1vzqAQ3H1FQ",
2127
+ caipNetworkId: "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp",
2080
2128
  name: "Solana Mainnet",
2081
2129
  nativeCurrency: {
2082
2130
  name: "Solana",
@@ -2954,8 +3002,62 @@ function getChainMeta(chainId) {
2954
3002
  rpcUrls: chain.rpcUrls.default.http
2955
3003
  };
2956
3004
  }
2957
- async function buildWalletConnectAPI(walletCfg) {
3005
+ function extractSolanaAddress(connector) {
3006
+ const caipAccount = connector.provider.session?.namespaces?.solana?.accounts?.[0];
3007
+ if (!caipAccount) return null;
3008
+ return caipAccount.split(":")[2] ?? null;
3009
+ }
3010
+ function buildWalletConnectSolanaProvider(connector) {
3011
+ return {
3012
+ get publicKey() {
3013
+ const address = extractSolanaAddress(connector);
3014
+ return address ? { toString: () => address } : void 0;
3015
+ },
3016
+ async connect() {
3017
+ const address = extractSolanaAddress(connector);
3018
+ if (!address) {
3019
+ throw new Error(
3020
+ "This wallet did not approve a Solana account over WalletConnect."
3021
+ );
3022
+ }
3023
+ return { publicKey: { toString: () => address } };
3024
+ },
3025
+ async disconnect() {
3026
+ },
3027
+ async signTransaction(transaction) {
3028
+ const tx = transaction;
3029
+ const rawBytes = "version" in tx ? tx.serialize() : tx.serialize({
3030
+ requireAllSignatures: false,
3031
+ verifySignatures: false
3032
+ });
3033
+ const result = await connector.provider.request(
3034
+ {
3035
+ method: "solana_signTransaction",
3036
+ params: { transaction: encodeBase64(rawBytes) }
3037
+ },
3038
+ solanaMainnet.caipNetworkId
3039
+ );
3040
+ if (!result.transaction) {
3041
+ throw new Error(
3042
+ "WalletConnect wallet did not return a signed Solana transaction."
3043
+ );
3044
+ }
3045
+ const signedBytes = decodeBase64(result.transaction);
3046
+ return { serialize: () => signedBytes };
3047
+ },
3048
+ on() {
3049
+ },
3050
+ off() {
3051
+ },
3052
+ removeListener() {
3053
+ }
3054
+ };
3055
+ }
3056
+ async function buildWalletConnectAPI(walletCfg, ecosystem = "evm") {
2958
3057
  const connector = await getUniversalConnector(walletCfg);
3058
+ if (ecosystem === "solana") {
3059
+ return toSolanaWalletInterface(buildWalletConnectSolanaProvider(connector));
3060
+ }
2959
3061
  const provider = connector.provider;
2960
3062
  const api = {
2961
3063
  ecosystem: "evm",
@@ -3031,7 +3133,7 @@ function useWireDetectionIntoManager() {
3031
3133
  function useWalletConnectConnect(walletCfg) {
3032
3134
  const cfgRef = { current: walletCfg };
3033
3135
  return (0, import_react2.useCallback)(
3034
- () => walletManager.connectWalletConnect(cfgRef.current),
3136
+ (ecosystem) => walletManager.connectWalletConnect(cfgRef.current, ecosystem),
3035
3137
  []
3036
3138
  );
3037
3139
  }
@@ -3051,6 +3153,7 @@ function useWalletInfo(wagmi) {
3051
3153
  connectedVia: snapshot.connectedVia,
3052
3154
  walletType: snapshot.walletType,
3053
3155
  status: snapshot.status,
3156
+ detected: snapshot.detected,
3054
3157
  disconnect
3055
3158
  };
3056
3159
  }
@@ -3203,44 +3306,39 @@ var init_manager = __esm({
3203
3306
  this.emit();
3204
3307
  }
3205
3308
  }
3206
- async connectWalletConnect(walletCfg) {
3207
- if (this._status === "connected" && this._connectedVia === "walletconnect" && this._wallet) {
3309
+ async connectWalletConnect(walletCfg, ecosystem = "evm") {
3310
+ if (this._status === "connected" && this._connectedVia === "walletconnect" && this._wallet && this._wallet.ecosystem === ecosystem) {
3208
3311
  this.emit();
3209
3312
  return { error: null, api: this._wallet };
3210
3313
  }
3314
+ if (this._connectedVia === "walletconnect" && this._wallet) {
3315
+ await this._wallet.disconnect?.().catch(() => {
3316
+ });
3317
+ resetUniversalConnector();
3318
+ }
3211
3319
  this._status = "connecting";
3212
3320
  this.clearConnectedState();
3213
3321
  this.emit();
3214
3322
  try {
3215
3323
  const connector = await getUniversalConnector(walletCfg);
3216
3324
  await connector.connect();
3217
- const api = await buildWalletConnectAPI(walletCfg);
3325
+ const api = await buildWalletConnectAPI(walletCfg, ecosystem);
3326
+ try {
3327
+ await api.getAddress();
3328
+ } catch {
3329
+ await api.disconnect?.().catch(() => {
3330
+ });
3331
+ resetUniversalConnector();
3332
+ throw new Error(
3333
+ `This wallet did not approve a${ecosystem === "evm" ? "n" : ""} ${ecosystem === "evm" ? "EVM" : "Solana"} account over WalletConnect.`
3334
+ );
3335
+ }
3218
3336
  this._wallet = api;
3219
3337
  this._connectedVia = "walletconnect";
3220
3338
  this._connectedWalletId = "walletconnect";
3221
- const provider = connector.provider;
3222
- this._providerCleanup = bindWalletConnectEvents(provider, {
3223
- onAccountsChanged: (accounts) => {
3224
- if (accounts.length === 0) {
3225
- this.fullReset();
3226
- this.triggerExternalDisconnect();
3227
- this.emit();
3228
- return;
3229
- }
3230
- void this.syncIdentityFromWallet("walletconnect");
3231
- this.emit();
3232
- },
3233
- onChainChanged: () => {
3234
- void this.syncIdentityFromWallet("walletconnect");
3235
- this.emit();
3236
- },
3237
- onDisconnect: () => {
3238
- this.fullReset();
3239
- resetUniversalConnector();
3240
- this.triggerExternalDisconnect();
3241
- this.emit();
3242
- }
3243
- });
3339
+ this._providerCleanup = this.bindWalletConnectProviderEvents(
3340
+ connector.provider
3341
+ );
3244
3342
  await this.syncIdentityFromWallet("walletconnect");
3245
3343
  this._status = "connected";
3246
3344
  this._error = null;
@@ -3255,6 +3353,100 @@ var init_manager = __esm({
3255
3353
  return { error: message, api: null };
3256
3354
  }
3257
3355
  }
3356
+ bindWalletConnectProviderEvents(provider) {
3357
+ return bindWalletConnectEvents(provider, {
3358
+ onAccountsChanged: (accounts) => {
3359
+ if (accounts.length === 0) {
3360
+ this.fullReset();
3361
+ this.triggerExternalDisconnect();
3362
+ this.emit();
3363
+ return;
3364
+ }
3365
+ void this.syncIdentityFromWallet("walletconnect");
3366
+ this.emit();
3367
+ },
3368
+ onChainChanged: () => {
3369
+ void this.syncIdentityFromWallet("walletconnect");
3370
+ this.emit();
3371
+ },
3372
+ onDisconnect: () => {
3373
+ this.fullReset();
3374
+ resetUniversalConnector();
3375
+ this.triggerExternalDisconnect();
3376
+ this.emit();
3377
+ }
3378
+ });
3379
+ }
3380
+ // WalletConnect's own SignClient auto-restores the last persisted session
3381
+ // from storage on every init — including after a fresh page load — but
3382
+ // that restoration happens silently inside the library. Nothing calls back
3383
+ // into our code for it. On mobile, backgrounding the tab to approve in a
3384
+ // wallet app can cause the OS to reload the page before the original
3385
+ // connect() promise ever resolves, so the connect flow that triggered the
3386
+ // approval never gets to record it as "connected" here — even though
3387
+ // WalletConnect itself already has a live, approved session sitting in
3388
+ // storage. Call this on mount to pick that back up.
3389
+ async restoreWalletConnectSession(walletCfg) {
3390
+ if (this._status === "connected" && this._connectedVia === "walletconnect") {
3391
+ return this._wallet?.ecosystem === "solana" ? "solana" : "evm";
3392
+ }
3393
+ if (typeof window === "undefined") return null;
3394
+ try {
3395
+ if (!Object.keys(window.localStorage).some((key) => key.startsWith("wc@2"))) {
3396
+ return null;
3397
+ }
3398
+ } catch {
3399
+ }
3400
+ let connector;
3401
+ try {
3402
+ connector = await getUniversalConnector(walletCfg);
3403
+ } catch (e2) {
3404
+ console.warn(
3405
+ "[Trustware SDK] Failed to restore WalletConnect session:",
3406
+ e2
3407
+ );
3408
+ return null;
3409
+ }
3410
+ const session = connector.provider.session;
3411
+ if (!session) return null;
3412
+ const ecosystem = session.namespaces?.solana?.accounts?.length ? "solana" : session.namespaces?.eip155?.accounts?.length ? "evm" : null;
3413
+ if (!ecosystem) return null;
3414
+ try {
3415
+ const api = await buildWalletConnectAPI(walletCfg, ecosystem);
3416
+ this._wallet = api;
3417
+ this._connectedVia = "walletconnect";
3418
+ this._connectedWalletId = "walletconnect";
3419
+ this._providerCleanup = this.bindWalletConnectProviderEvents(
3420
+ connector.provider
3421
+ );
3422
+ await this.syncIdentityFromWallet("walletconnect");
3423
+ this._status = "connected";
3424
+ this._error = null;
3425
+ this.emit();
3426
+ return ecosystem;
3427
+ } catch {
3428
+ return null;
3429
+ }
3430
+ }
3431
+ // Forcibly abandon an in-progress connect() call the caller has decided is
3432
+ // stuck (e.g. the UI's own connect timeout elapsed with no response).
3433
+ // There's no clean way to cancel a pending WalletConnect pairing proposal
3434
+ // from this side, so this tears down the whole connector — the next
3435
+ // connect attempt starts against a brand new SignClient/pairing instead of
3436
+ // racing the abandoned one, which would otherwise risk reproducing the
3437
+ // "No matching key. proposal" class of error a real retry needs to avoid.
3438
+ cancelWalletConnectAttempt() {
3439
+ if (this._connectedVia === "walletconnect" && this._status === "connected") {
3440
+ return;
3441
+ }
3442
+ resetUniversalConnector();
3443
+ if (this._status === "connecting") {
3444
+ this.clearConnectedState();
3445
+ this._status = "idle";
3446
+ this._error = null;
3447
+ this.emit();
3448
+ }
3449
+ }
3258
3450
  async disconnect(wagmi) {
3259
3451
  if (wagmi && this._connectedVia === "extension") {
3260
3452
  await wagmi.disconnect().catch(() => {
@@ -3464,46 +3656,80 @@ function normalizeSlippage(v) {
3464
3656
  if (n > 5) return 5;
3465
3657
  return n;
3466
3658
  }
3659
+ function warnDeprecatedSwapModeFlag() {
3660
+ if (hasWarnedDeprecatedSwapModeFlag) return;
3661
+ hasWarnedDeprecatedSwapModeFlag = true;
3662
+ console.warn(
3663
+ '[Trustware SDK] `features.swapMode` is deprecated \u2014 use `mode: "swap"` on the top-level config instead.'
3664
+ );
3665
+ }
3666
+ function resolveMode(input) {
3667
+ if (input.mode === "swap") return "swap";
3668
+ if (input.mode === "deposit") return "deposit";
3669
+ if (input.features?.swapMode) {
3670
+ warnDeprecatedSwapModeFlag();
3671
+ return "swap";
3672
+ }
3673
+ return "deposit";
3674
+ }
3467
3675
  function resolveConfig(input) {
3468
3676
  if (!input?.apiKey) {
3469
- throw new Error("TrustwareConfig: 'apiKey' is required.");
3677
+ throw new TrustwareError({
3678
+ code: "INVALID_CONFIG" /* INVALID_CONFIG */,
3679
+ message: "TrustwareConfig: 'apiKey' is required.",
3680
+ userMessage: "Missing required API key configuration."
3681
+ });
3470
3682
  }
3471
- if (!input.routes?.toChain || !input.routes?.toToken) {
3472
- throw new Error(
3473
- "TrustwareConfig: 'routes.toChain' and 'routes.toToken' are required."
3474
- );
3683
+ const mode = resolveMode(input);
3684
+ if (mode === "deposit" && (!input.routes?.toChain || !input.routes?.toToken)) {
3685
+ throw new TrustwareError({
3686
+ code: "INVALID_CONFIG" /* INVALID_CONFIG */,
3687
+ message: "TrustwareConfig: 'routes.toChain' and 'routes.toToken' are required in deposit mode.",
3688
+ userMessage: "Missing required destination chain/token configuration."
3689
+ });
3475
3690
  }
3476
- const toChain = input.routes.toChain;
3477
- if (input.routes.toAddress) {
3691
+ const toChain = input.routes?.toChain;
3692
+ if (input.routes?.toAddress && toChain) {
3478
3693
  const result = validateAddressForChain(input.routes.toAddress, toChain);
3479
3694
  if (!result.isValid) {
3480
3695
  console.error(`[Trustware SDK] Invalid toAddress: ${result.error}`);
3481
- throw new Error(`Invalid toAddress: ${result.error}`);
3696
+ throw new TrustwareError({
3697
+ code: "INVALID_CONFIG" /* INVALID_CONFIG */,
3698
+ message: `Invalid toAddress: ${result.error}`,
3699
+ userMessage: "The configured destination address is invalid."
3700
+ });
3482
3701
  }
3483
3702
  }
3484
- if (input.routes.fromAddress) {
3485
- const result = validateAddressForChain(
3486
- input.routes.fromAddress,
3487
- input.routes.fromChain ?? toChain
3488
- );
3489
- if (!result.isValid) {
3490
- console.error(`[Trustware SDK] Invalid fromAddress: ${result.error}`);
3491
- throw new Error(`Invalid fromAddress: ${result.error}`);
3703
+ if (input.routes?.fromAddress) {
3704
+ const fromChain = input.routes.fromChain ?? toChain;
3705
+ if (fromChain) {
3706
+ const result = validateAddressForChain(
3707
+ input.routes.fromAddress,
3708
+ fromChain
3709
+ );
3710
+ if (!result.isValid) {
3711
+ console.error(`[Trustware SDK] Invalid fromAddress: ${result.error}`);
3712
+ throw new TrustwareError({
3713
+ code: "INVALID_CONFIG" /* INVALID_CONFIG */,
3714
+ message: `Invalid fromAddress: ${result.error}`,
3715
+ userMessage: "The configured source address is invalid."
3716
+ });
3717
+ }
3492
3718
  }
3493
3719
  }
3494
3720
  const autoDetectProvider = typeof input.autoDetectProvider === "boolean" ? input.autoDetectProvider : DEFAULT_AUTO_DETECT_PROVIDER;
3495
3721
  const routes = {
3496
- toChain: input.routes.toChain,
3497
- toToken: input.routes.toToken,
3498
- fromToken: input.routes.fromToken,
3499
- fromAddress: input.routes.fromAddress,
3500
- fromChain: input.routes.fromChain,
3501
- toAddress: input.routes.toAddress,
3722
+ toChain: input.routes?.toChain ?? "",
3723
+ toToken: input.routes?.toToken ?? "",
3724
+ fromToken: input.routes?.fromToken,
3725
+ fromAddress: input.routes?.fromAddress,
3726
+ fromChain: input.routes?.fromChain,
3727
+ toAddress: input.routes?.toAddress,
3502
3728
  defaultSlippage: normalizeSlippage(
3503
- input.routes.defaultSlippage ?? DEFAULT_SLIPPAGE
3729
+ input.routes?.defaultSlippage ?? DEFAULT_SLIPPAGE
3504
3730
  ),
3505
3731
  options: {
3506
- ...input.routes.options
3732
+ ...input.routes?.options
3507
3733
  }
3508
3734
  };
3509
3735
  const theme = input.theme ?? "system";
@@ -3522,13 +3748,16 @@ function resolveConfig(input) {
3522
3748
  tokensPagination: input.features?.tokensPagination ?? DEFAULT_FEATURE_FLAGS.tokensPagination,
3523
3749
  balanceStreaming: input.features?.balanceStreaming ?? DEFAULT_FEATURE_FLAGS.balanceStreaming,
3524
3750
  shouldAllowGA4: input.features?.shouldAllowGA4 ?? DEFAULT_FEATURE_FLAGS.shouldAllowGA4,
3525
- swapMode: input.features?.swapMode ?? DEFAULT_FEATURE_FLAGS.swapMode,
3751
+ // Always mirrors the canonical `mode`, however the caller set it (new `mode` field
3752
+ // or the deprecated `features.swapMode` flag).
3753
+ swapMode: mode === "swap",
3526
3754
  swapDefaultDestToken: input.features?.swapDefaultDestToken ?? DEFAULT_FEATURE_FLAGS.swapDefaultDestToken,
3527
3755
  swapLockDestToken: input.features?.swapLockDestToken ?? DEFAULT_FEATURE_FLAGS.swapLockDestToken,
3528
3756
  swapAllowedDestTokens: input.features?.swapAllowedDestTokens ?? DEFAULT_FEATURE_FLAGS.swapAllowedDestTokens
3529
3757
  };
3530
3758
  return {
3531
3759
  apiKey: input.apiKey,
3760
+ mode,
3532
3761
  routes,
3533
3762
  autoDetectProvider,
3534
3763
  theme,
@@ -3541,12 +3770,15 @@ function resolveConfig(input) {
3541
3770
  onEvent: input.onEvent
3542
3771
  };
3543
3772
  }
3773
+ var hasWarnedDeprecatedSwapModeFlag;
3544
3774
  var init_merge = __esm({
3545
3775
  "src/config/merge.ts"() {
3546
3776
  "use strict";
3547
3777
  init_defaults();
3548
3778
  init_config();
3549
3779
  init_index();
3780
+ init_TrustwareError();
3781
+ hasWarnedDeprecatedSwapModeFlag = false;
3550
3782
  }
3551
3783
  });
3552
3784
 
@@ -4121,7 +4353,9 @@ __export(wallet_exports, {
4121
4353
  buildDetectedWalletFromProvider: () => buildDetectedWalletFromProvider,
4122
4354
  connectDetectedWallet: () => connectDetectedWallet,
4123
4355
  createWalletConnectEntry: () => createWalletConnectEntry,
4356
+ decodeBase64: () => decodeBase64,
4124
4357
  detectSolanaWallets: () => detectSolanaWallets,
4358
+ encodeBase64: () => encodeBase64,
4125
4359
  formatDeepLink: () => formatDeepLink,
4126
4360
  formatWalletConnectDeepLink: () => formatWalletConnectDeepLink,
4127
4361
  formatWalletConnectDeepLinkForWallet: () => formatWalletConnectDeepLinkForWallet,
@@ -4149,7 +4383,9 @@ init_wallets2();
4149
4383
  buildDetectedWalletFromProvider,
4150
4384
  connectDetectedWallet,
4151
4385
  createWalletConnectEntry,
4386
+ decodeBase64,
4152
4387
  detectSolanaWallets,
4388
+ encodeBase64,
4153
4389
  formatDeepLink,
4154
4390
  formatWalletConnectDeepLink,
4155
4391
  formatWalletConnectDeepLinkForWallet,