@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/widget.cjs CHANGED
@@ -585,7 +585,7 @@ var init_constants = __esm({
585
585
  "src/constants.ts"() {
586
586
  "use strict";
587
587
  SDK_NAME = "@trustware/sdk";
588
- SDK_VERSION = "1.1.9-staging.5";
588
+ SDK_VERSION = "1.1.9-staging.7";
589
589
  API_ROOT = "https://bv-staging-api.trustware.io";
590
590
  GTM_ID = "GTM-TZDGNCXB";
591
591
  API_PREFIX = "/api";
@@ -796,7 +796,9 @@ var init_chains = __esm({
796
796
  btc: "bitcoin",
797
797
  bitcoin: "bitcoin",
798
798
  sei: "cosmos",
799
- "pacific-1": "cosmos"
799
+ "pacific-1": "cosmos",
800
+ nibiru: "cosmos",
801
+ "cataclysm-1": "cosmos"
800
802
  };
801
803
  }
802
804
  });
@@ -1992,16 +1994,23 @@ function validateEvmAddress(address) {
1992
1994
  }
1993
1995
  return { isValid: true };
1994
1996
  }
1995
- function validateSeiAddress(address) {
1997
+ function resolveCosmosBech32Prefix(chain) {
1998
+ const chainDef = typeof chain === "object" && chain ? chain : void 0;
1999
+ const identifier = chainDef?.networkIdentifier ?? chainDef?.chainId ?? chainDef?.id ?? (typeof chain === "string" ? chain : void 0);
2000
+ const normalized = String(identifier ?? "").trim().toLowerCase();
2001
+ return COSMOS_BECH32_PREFIX_BY_CHAIN_ID[normalized] ?? "sei";
2002
+ }
2003
+ function validateCosmosAddress(address, chain) {
1996
2004
  const trimmed = address.trim();
1997
- if ((0, import_viem.isAddress)(trimmed)) {
2005
+ const prefix = resolveCosmosBech32Prefix(chain);
2006
+ if (prefix === "sei" && (0, import_viem.isAddress)(trimmed)) {
1998
2007
  return { isValid: true };
1999
2008
  }
2000
- const result = validateBech32LikeAddress(trimmed, "sei");
2009
+ const result = validateBech32LikeAddress(trimmed, prefix);
2001
2010
  if (result.isValid) return result;
2002
2011
  return {
2003
2012
  isValid: false,
2004
- error: "SEI addresses must be 0x-prefixed EVM or sei1 bech32 strings."
2013
+ error: prefix === "sei" ? "SEI addresses must be 0x-prefixed EVM or sei1 bech32 strings." : `Address must be a valid ${prefix}1 bech32 string.`
2005
2014
  };
2006
2015
  }
2007
2016
  function validateSolanaAddress(address) {
@@ -2051,15 +2060,12 @@ function validateAddressForChain(address, chain) {
2051
2060
  case "bitcoin":
2052
2061
  return validateBtcAddress(trimmed);
2053
2062
  case "cosmos":
2054
- if (chainDef?.networkIdentifier?.toLowerCase() === "sei") {
2055
- return validateSeiAddress(trimmed);
2056
- }
2057
- return validateBech32LikeAddress(trimmed, "sei");
2063
+ return validateCosmosAddress(trimmed, chainDef ?? chain);
2058
2064
  default:
2059
2065
  return { isValid: false, error: "Unsupported or unknown chain type." };
2060
2066
  }
2061
2067
  }
2062
- function validateAddressForRouteChain(address, chainType) {
2068
+ function validateAddressForRouteChain(address, chainType, chainRef) {
2063
2069
  switch (normalizeChainType(chainType)) {
2064
2070
  case "evm":
2065
2071
  return validateEvmAddress(address);
@@ -2068,7 +2074,7 @@ function validateAddressForRouteChain(address, chainType) {
2068
2074
  case "bitcoin":
2069
2075
  return validateBtcAddress(address);
2070
2076
  case "cosmos":
2071
- return validateSeiAddress(address);
2077
+ return validateCosmosAddress(address, chainRef ?? chainType);
2072
2078
  default:
2073
2079
  return { isValid: false, error: "Unsupported chain type." };
2074
2080
  }
@@ -2090,14 +2096,18 @@ function validateRouteAddresses(params) {
2090
2096
  const normalizedDirection = params.direction?.trim().toLowerCase();
2091
2097
  const isDepositFlow = normalizedDirection === "deposit" || (toType === "evm" || toType === "cosmos") && (fromType === "bitcoin" || fromType === "solana");
2092
2098
  if (isDepositFlow) {
2093
- const fromResult2 = validateAddressForRouteChain(fromAddress, fromType);
2099
+ const fromResult2 = validateAddressForRouteChain(
2100
+ fromAddress,
2101
+ fromType,
2102
+ params.fromChain
2103
+ );
2094
2104
  if (!fromResult2.isValid) {
2095
2105
  return {
2096
2106
  isValid: false,
2097
2107
  error: `From address: ${fromResult2.error ?? "Invalid address."}`
2098
2108
  };
2099
2109
  }
2100
- const toResult2 = toType === "cosmos" ? validateSeiAddress(toAddress) : validateEvmAddress(toAddress);
2110
+ const toResult2 = toType === "cosmos" ? validateCosmosAddress(toAddress, params.toChain) : validateEvmAddress(toAddress);
2101
2111
  if (!toResult2.isValid) {
2102
2112
  return {
2103
2113
  isValid: false,
@@ -2122,14 +2132,22 @@ function validateRouteAddresses(params) {
2122
2132
  }
2123
2133
  return { isValid: true };
2124
2134
  }
2125
- const fromResult = validateAddressForRouteChain(fromAddress, fromType);
2135
+ const fromResult = validateAddressForRouteChain(
2136
+ fromAddress,
2137
+ fromType,
2138
+ params.fromChain
2139
+ );
2126
2140
  if (!fromResult.isValid) {
2127
2141
  return {
2128
2142
  isValid: false,
2129
2143
  error: `From address: ${fromResult.error ?? "Invalid address."}`
2130
2144
  };
2131
2145
  }
2132
- const toResult = validateAddressForRouteChain(toAddress, toType);
2146
+ const toResult = validateAddressForRouteChain(
2147
+ toAddress,
2148
+ toType,
2149
+ params.toChain
2150
+ );
2133
2151
  if (!toResult.isValid) {
2134
2152
  return {
2135
2153
  isValid: false,
@@ -2138,7 +2156,7 @@ function validateRouteAddresses(params) {
2138
2156
  }
2139
2157
  return { isValid: true };
2140
2158
  }
2141
- var import_viem, BECH32_CHARSET;
2159
+ var import_viem, BECH32_CHARSET, COSMOS_BECH32_PREFIX_BY_CHAIN_ID;
2142
2160
  var init_address = __esm({
2143
2161
  "src/validation/address.ts"() {
2144
2162
  "use strict";
@@ -2146,6 +2164,12 @@ var init_address = __esm({
2146
2164
  init_index_node4();
2147
2165
  init_chains();
2148
2166
  BECH32_CHARSET = /^[023456789acdefghjklmnpqrstuvwxyz]+$/i;
2167
+ COSMOS_BECH32_PREFIX_BY_CHAIN_ID = {
2168
+ "pacific-1": "sei",
2169
+ sei: "sei",
2170
+ "cataclysm-1": "nibi",
2171
+ nibiru: "nibi"
2172
+ };
2149
2173
  }
2150
2174
  });
2151
2175
 
@@ -2537,7 +2561,7 @@ async function buildDepositAddress(body, signal) {
2537
2561
  route
2538
2562
  };
2539
2563
  }
2540
- async function submitReceipt(intentId, txHash, sponsorshipRequestId) {
2564
+ async function submitReceipt(intentId, txHash, sponsorshipRequestId, eoaAddress) {
2541
2565
  const r = await rateLimitedFetch(
2542
2566
  `${apiBase()}/v1/route-intent/${intentId}/receipt`,
2543
2567
  {
@@ -2545,7 +2569,8 @@ async function submitReceipt(intentId, txHash, sponsorshipRequestId) {
2545
2569
  headers: jsonHeaders({ "Idempotency-Key": txHash }),
2546
2570
  body: JSON.stringify({
2547
2571
  txHash,
2548
- ...sponsorshipRequestId ? { sponsorshipRequestId } : {}
2572
+ ...sponsorshipRequestId ? { sponsorshipRequestId } : {},
2573
+ ...eoaAddress ? { eoaAddress } : {}
2549
2574
  })
2550
2575
  }
2551
2576
  );
@@ -2855,6 +2880,7 @@ function useTrustwareConfig() {
2855
2880
  } catch {
2856
2881
  return {
2857
2882
  apiKey: "",
2883
+ mode: "deposit",
2858
2884
  routes: {
2859
2885
  toChain: "",
2860
2886
  toToken: "",
@@ -3120,7 +3146,9 @@ var init_chainHelpers = __esm({
3120
3146
  btc: "bitcoin",
3121
3147
  bitcoin: "bitcoin",
3122
3148
  sei: "cosmos",
3123
- "pacific-1": "cosmos"
3149
+ "pacific-1": "cosmos",
3150
+ nibiru: "cosmos",
3151
+ "cataclysm-1": "cosmos"
3124
3152
  };
3125
3153
  SEI_EVM_CHAIN_ID = "1329";
3126
3154
  SEI_COSMOS_CHAIN_ID = "pacific-1";
@@ -3335,7 +3363,8 @@ function filterSupportedChains(chains) {
3335
3363
  }
3336
3364
  if (chainType === "cosmos") {
3337
3365
  const seiKey = canonicalSeiChainKey(chain.chainId ?? chain.id);
3338
- if (seiKey !== "sei" && seiKey !== "pacific-1") {
3366
+ const isNibiru = normalizeChainKey2(chain.chainId ?? chain.id) === NIBIRU_COSMOS_CHAIN_ID;
3367
+ if (seiKey !== "sei" && !isNibiru) {
3339
3368
  return false;
3340
3369
  }
3341
3370
  }
@@ -3435,7 +3464,7 @@ function useChains() {
3435
3464
  error
3436
3465
  };
3437
3466
  }
3438
- var import_react4, POPULAR_CHAINS_BY_TVL, POPULAR_LIMIT;
3467
+ var import_react4, POPULAR_CHAINS_BY_TVL, POPULAR_LIMIT, NIBIRU_COSMOS_CHAIN_ID;
3439
3468
  var init_useChains = __esm({
3440
3469
  "src/core/useChains.ts"() {
3441
3470
  "use strict";
@@ -3446,6 +3475,7 @@ var init_useChains = __esm({
3446
3475
  init_popularChains();
3447
3476
  POPULAR_CHAINS_BY_TVL = popularChains_default.byTvl;
3448
3477
  POPULAR_LIMIT = popularChains_default.popularLimit;
3478
+ NIBIRU_COSMOS_CHAIN_ID = "cataclysm-1";
3449
3479
  }
3450
3480
  });
3451
3481
 
@@ -6240,21 +6270,28 @@ function formatDeepLink(id, currentUrl) {
6240
6270
  const enc = encodeURIComponent(currentUrl);
6241
6271
  switch (id) {
6242
6272
  // EVM
6273
+ // MetaMask's dapp browser also exposes its Wallet Standard Solana
6274
+ // provider in the same session, so "metamask-solana" reuses this link.
6243
6275
  case "metamask":
6276
+ case "metamask-solana":
6244
6277
  return `metamask://dapp/${currentUrl}`;
6245
6278
  case "coinbase":
6246
6279
  return `coinbase://wallet/dapp?url=${enc}`;
6247
6280
  case "rainbow":
6248
- return `rainbow://connect?uri=${enc}`;
6281
+ return `https://rainbow.me/dapp?url=${enc}`;
6249
6282
  case "trust":
6250
6283
  return `https://link.trustwallet.com/open_url?coin_id=60&url=${enc}`;
6251
6284
  case "okx":
6252
6285
  return `okx://wallet/dapp/url?dappUrl=${enc}`;
6253
6286
  // Solana
6287
+ // Phantom is one app with one in-app browser — browsing there injects
6288
+ // both window.ethereum and window.phantom.solana, so "phantom-evm"
6289
+ // reuses the same browse link as "phantom-solana".
6254
6290
  case "phantom-solana":
6255
- return `phantom://browse/${enc}`;
6291
+ case "phantom-evm":
6292
+ return `https://phantom.app/ul/browse/${enc}?ref=${enc}`;
6256
6293
  case "solflare":
6257
- return `solflare://ul/v1/browse/${enc}`;
6294
+ return `https://solflare.com/ul/v1/browse/${enc}?ref=${enc}`;
6258
6295
  case "backpack":
6259
6296
  return `https://backpack.app/ul/v1/browse/${enc}?ref=${enc}`;
6260
6297
  // No confirmed deep link scheme
@@ -6364,8 +6401,10 @@ var init_metadata = __esm({
6364
6401
  homepage: "https://phantom.app/",
6365
6402
  ios: "https://apps.apple.com/app/phantom-crypto-wallet/id1598432977",
6366
6403
  android: "https://play.google.com/store/apps/details?id=app.phantom",
6367
- detectFlags: ["isPhantom"]
6368
- // No EVM dapp browser deep link — falls back to app store
6404
+ detectFlags: ["isPhantom"],
6405
+ // Same app/in-app browser as "phantom-solana" — browsing there injects
6406
+ // window.ethereum too.
6407
+ deepLink: (url) => formatDeepLink("phantom-evm", url) ?? ""
6369
6408
  },
6370
6409
  {
6371
6410
  id: "phantom-solana",
@@ -6413,8 +6452,10 @@ var init_metadata = __esm({
6413
6452
  emoji: "\u{1F98A}",
6414
6453
  homepage: "https://metamask.io/",
6415
6454
  ios: "https://apps.apple.com/app/metamask/id1438144202",
6416
- android: "https://play.google.com/store/apps/details?id=io.metamask"
6417
- // No Solana-specific deep link for MetaMask
6455
+ android: "https://play.google.com/store/apps/details?id=io.metamask",
6456
+ // Same app/in-app browser as "metamask" — its Wallet Standard Solana
6457
+ // provider is exposed in that same browse session.
6458
+ deepLink: (url) => formatDeepLink("metamask-solana", url) ?? ""
6418
6459
  },
6419
6460
  // ── Extension/desktop only — hidden on mobile ─────────────────────────────
6420
6461
  {
@@ -6925,7 +6966,7 @@ var init_walletconnect = __esm({
6925
6966
  solanaMainnet = {
6926
6967
  id: 900,
6927
6968
  chainNamespace: "solana",
6928
- caipNetworkId: "solana:5eykt4UsFv8P8NJdTREpY1vzqAQ3H1FQ",
6969
+ caipNetworkId: "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp",
6929
6970
  name: "Solana Mainnet",
6930
6971
  nativeCurrency: {
6931
6972
  name: "Solana",
@@ -7803,8 +7844,62 @@ function getChainMeta(chainId) {
7803
7844
  rpcUrls: chain.rpcUrls.default.http
7804
7845
  };
7805
7846
  }
7806
- async function buildWalletConnectAPI(walletCfg) {
7847
+ function extractSolanaAddress(connector) {
7848
+ const caipAccount = connector.provider.session?.namespaces?.solana?.accounts?.[0];
7849
+ if (!caipAccount) return null;
7850
+ return caipAccount.split(":")[2] ?? null;
7851
+ }
7852
+ function buildWalletConnectSolanaProvider(connector) {
7853
+ return {
7854
+ get publicKey() {
7855
+ const address = extractSolanaAddress(connector);
7856
+ return address ? { toString: () => address } : void 0;
7857
+ },
7858
+ async connect() {
7859
+ const address = extractSolanaAddress(connector);
7860
+ if (!address) {
7861
+ throw new Error(
7862
+ "This wallet did not approve a Solana account over WalletConnect."
7863
+ );
7864
+ }
7865
+ return { publicKey: { toString: () => address } };
7866
+ },
7867
+ async disconnect() {
7868
+ },
7869
+ async signTransaction(transaction) {
7870
+ const tx = transaction;
7871
+ const rawBytes = "version" in tx ? tx.serialize() : tx.serialize({
7872
+ requireAllSignatures: false,
7873
+ verifySignatures: false
7874
+ });
7875
+ const result = await connector.provider.request(
7876
+ {
7877
+ method: "solana_signTransaction",
7878
+ params: { transaction: encodeBase64(rawBytes) }
7879
+ },
7880
+ solanaMainnet.caipNetworkId
7881
+ );
7882
+ if (!result.transaction) {
7883
+ throw new Error(
7884
+ "WalletConnect wallet did not return a signed Solana transaction."
7885
+ );
7886
+ }
7887
+ const signedBytes = decodeBase64(result.transaction);
7888
+ return { serialize: () => signedBytes };
7889
+ },
7890
+ on() {
7891
+ },
7892
+ off() {
7893
+ },
7894
+ removeListener() {
7895
+ }
7896
+ };
7897
+ }
7898
+ async function buildWalletConnectAPI(walletCfg, ecosystem = "evm") {
7807
7899
  const connector = await getUniversalConnector(walletCfg);
7900
+ if (ecosystem === "solana") {
7901
+ return toSolanaWalletInterface(buildWalletConnectSolanaProvider(connector));
7902
+ }
7808
7903
  const provider = connector.provider;
7809
7904
  const api = {
7810
7905
  ecosystem: "evm",
@@ -7874,7 +7969,7 @@ function bindWalletConnectEvents(provider, callbacks) {
7874
7969
  function useWalletConnectConnect(walletCfg) {
7875
7970
  const cfgRef = { current: walletCfg };
7876
7971
  return (0, import_react10.useCallback)(
7877
- () => walletManager.connectWalletConnect(cfgRef.current),
7972
+ (ecosystem) => walletManager.connectWalletConnect(cfgRef.current, ecosystem),
7878
7973
  []
7879
7974
  );
7880
7975
  }
@@ -7894,6 +7989,7 @@ function useWalletInfo(wagmi) {
7894
7989
  connectedVia: snapshot.connectedVia,
7895
7990
  walletType: snapshot.walletType,
7896
7991
  status: snapshot.status,
7992
+ detected: snapshot.detected,
7897
7993
  disconnect
7898
7994
  };
7899
7995
  }
@@ -8045,44 +8141,39 @@ var init_manager = __esm({
8045
8141
  this.emit();
8046
8142
  }
8047
8143
  }
8048
- async connectWalletConnect(walletCfg) {
8049
- if (this._status === "connected" && this._connectedVia === "walletconnect" && this._wallet) {
8144
+ async connectWalletConnect(walletCfg, ecosystem = "evm") {
8145
+ if (this._status === "connected" && this._connectedVia === "walletconnect" && this._wallet && this._wallet.ecosystem === ecosystem) {
8050
8146
  this.emit();
8051
8147
  return { error: null, api: this._wallet };
8052
8148
  }
8149
+ if (this._connectedVia === "walletconnect" && this._wallet) {
8150
+ await this._wallet.disconnect?.().catch(() => {
8151
+ });
8152
+ resetUniversalConnector();
8153
+ }
8053
8154
  this._status = "connecting";
8054
8155
  this.clearConnectedState();
8055
8156
  this.emit();
8056
8157
  try {
8057
8158
  const connector = await getUniversalConnector(walletCfg);
8058
8159
  await connector.connect();
8059
- const api = await buildWalletConnectAPI(walletCfg);
8160
+ const api = await buildWalletConnectAPI(walletCfg, ecosystem);
8161
+ try {
8162
+ await api.getAddress();
8163
+ } catch {
8164
+ await api.disconnect?.().catch(() => {
8165
+ });
8166
+ resetUniversalConnector();
8167
+ throw new Error(
8168
+ `This wallet did not approve a${ecosystem === "evm" ? "n" : ""} ${ecosystem === "evm" ? "EVM" : "Solana"} account over WalletConnect.`
8169
+ );
8170
+ }
8060
8171
  this._wallet = api;
8061
8172
  this._connectedVia = "walletconnect";
8062
8173
  this._connectedWalletId = "walletconnect";
8063
- const provider = connector.provider;
8064
- this._providerCleanup = bindWalletConnectEvents(provider, {
8065
- onAccountsChanged: (accounts) => {
8066
- if (accounts.length === 0) {
8067
- this.fullReset();
8068
- this.triggerExternalDisconnect();
8069
- this.emit();
8070
- return;
8071
- }
8072
- void this.syncIdentityFromWallet("walletconnect");
8073
- this.emit();
8074
- },
8075
- onChainChanged: () => {
8076
- void this.syncIdentityFromWallet("walletconnect");
8077
- this.emit();
8078
- },
8079
- onDisconnect: () => {
8080
- this.fullReset();
8081
- resetUniversalConnector();
8082
- this.triggerExternalDisconnect();
8083
- this.emit();
8084
- }
8085
- });
8174
+ this._providerCleanup = this.bindWalletConnectProviderEvents(
8175
+ connector.provider
8176
+ );
8086
8177
  await this.syncIdentityFromWallet("walletconnect");
8087
8178
  this._status = "connected";
8088
8179
  this._error = null;
@@ -8097,6 +8188,100 @@ var init_manager = __esm({
8097
8188
  return { error: message, api: null };
8098
8189
  }
8099
8190
  }
8191
+ bindWalletConnectProviderEvents(provider) {
8192
+ return bindWalletConnectEvents(provider, {
8193
+ onAccountsChanged: (accounts) => {
8194
+ if (accounts.length === 0) {
8195
+ this.fullReset();
8196
+ this.triggerExternalDisconnect();
8197
+ this.emit();
8198
+ return;
8199
+ }
8200
+ void this.syncIdentityFromWallet("walletconnect");
8201
+ this.emit();
8202
+ },
8203
+ onChainChanged: () => {
8204
+ void this.syncIdentityFromWallet("walletconnect");
8205
+ this.emit();
8206
+ },
8207
+ onDisconnect: () => {
8208
+ this.fullReset();
8209
+ resetUniversalConnector();
8210
+ this.triggerExternalDisconnect();
8211
+ this.emit();
8212
+ }
8213
+ });
8214
+ }
8215
+ // WalletConnect's own SignClient auto-restores the last persisted session
8216
+ // from storage on every init — including after a fresh page load — but
8217
+ // that restoration happens silently inside the library. Nothing calls back
8218
+ // into our code for it. On mobile, backgrounding the tab to approve in a
8219
+ // wallet app can cause the OS to reload the page before the original
8220
+ // connect() promise ever resolves, so the connect flow that triggered the
8221
+ // approval never gets to record it as "connected" here — even though
8222
+ // WalletConnect itself already has a live, approved session sitting in
8223
+ // storage. Call this on mount to pick that back up.
8224
+ async restoreWalletConnectSession(walletCfg) {
8225
+ if (this._status === "connected" && this._connectedVia === "walletconnect") {
8226
+ return this._wallet?.ecosystem === "solana" ? "solana" : "evm";
8227
+ }
8228
+ if (typeof window === "undefined") return null;
8229
+ try {
8230
+ if (!Object.keys(window.localStorage).some((key) => key.startsWith("wc@2"))) {
8231
+ return null;
8232
+ }
8233
+ } catch {
8234
+ }
8235
+ let connector;
8236
+ try {
8237
+ connector = await getUniversalConnector(walletCfg);
8238
+ } catch (e2) {
8239
+ console.warn(
8240
+ "[Trustware SDK] Failed to restore WalletConnect session:",
8241
+ e2
8242
+ );
8243
+ return null;
8244
+ }
8245
+ const session = connector.provider.session;
8246
+ if (!session) return null;
8247
+ const ecosystem = session.namespaces?.solana?.accounts?.length ? "solana" : session.namespaces?.eip155?.accounts?.length ? "evm" : null;
8248
+ if (!ecosystem) return null;
8249
+ try {
8250
+ const api = await buildWalletConnectAPI(walletCfg, ecosystem);
8251
+ this._wallet = api;
8252
+ this._connectedVia = "walletconnect";
8253
+ this._connectedWalletId = "walletconnect";
8254
+ this._providerCleanup = this.bindWalletConnectProviderEvents(
8255
+ connector.provider
8256
+ );
8257
+ await this.syncIdentityFromWallet("walletconnect");
8258
+ this._status = "connected";
8259
+ this._error = null;
8260
+ this.emit();
8261
+ return ecosystem;
8262
+ } catch {
8263
+ return null;
8264
+ }
8265
+ }
8266
+ // Forcibly abandon an in-progress connect() call the caller has decided is
8267
+ // stuck (e.g. the UI's own connect timeout elapsed with no response).
8268
+ // There's no clean way to cancel a pending WalletConnect pairing proposal
8269
+ // from this side, so this tears down the whole connector — the next
8270
+ // connect attempt starts against a brand new SignClient/pairing instead of
8271
+ // racing the abandoned one, which would otherwise risk reproducing the
8272
+ // "No matching key. proposal" class of error a real retry needs to avoid.
8273
+ cancelWalletConnectAttempt() {
8274
+ if (this._connectedVia === "walletconnect" && this._status === "connected") {
8275
+ return;
8276
+ }
8277
+ resetUniversalConnector();
8278
+ if (this._status === "connecting") {
8279
+ this.clearConnectedState();
8280
+ this._status = "idle";
8281
+ this._error = null;
8282
+ this.emit();
8283
+ }
8284
+ }
8100
8285
  async disconnect(wagmi) {
8101
8286
  if (wagmi && this._connectedVia === "extension") {
8102
8287
  await wagmi.disconnect().catch(() => {
@@ -8628,46 +8813,80 @@ function normalizeSlippage(v) {
8628
8813
  if (n > 5) return 5;
8629
8814
  return n;
8630
8815
  }
8816
+ function warnDeprecatedSwapModeFlag() {
8817
+ if (hasWarnedDeprecatedSwapModeFlag) return;
8818
+ hasWarnedDeprecatedSwapModeFlag = true;
8819
+ console.warn(
8820
+ '[Trustware SDK] `features.swapMode` is deprecated \u2014 use `mode: "swap"` on the top-level config instead.'
8821
+ );
8822
+ }
8823
+ function resolveMode(input) {
8824
+ if (input.mode === "swap") return "swap";
8825
+ if (input.mode === "deposit") return "deposit";
8826
+ if (input.features?.swapMode) {
8827
+ warnDeprecatedSwapModeFlag();
8828
+ return "swap";
8829
+ }
8830
+ return "deposit";
8831
+ }
8631
8832
  function resolveConfig(input) {
8632
8833
  if (!input?.apiKey) {
8633
- throw new Error("TrustwareConfig: 'apiKey' is required.");
8834
+ throw new TrustwareError({
8835
+ code: "INVALID_CONFIG" /* INVALID_CONFIG */,
8836
+ message: "TrustwareConfig: 'apiKey' is required.",
8837
+ userMessage: "Missing required API key configuration."
8838
+ });
8634
8839
  }
8635
- if (!input.routes?.toChain || !input.routes?.toToken) {
8636
- throw new Error(
8637
- "TrustwareConfig: 'routes.toChain' and 'routes.toToken' are required."
8638
- );
8840
+ const mode = resolveMode(input);
8841
+ if (mode === "deposit" && (!input.routes?.toChain || !input.routes?.toToken)) {
8842
+ throw new TrustwareError({
8843
+ code: "INVALID_CONFIG" /* INVALID_CONFIG */,
8844
+ message: "TrustwareConfig: 'routes.toChain' and 'routes.toToken' are required in deposit mode.",
8845
+ userMessage: "Missing required destination chain/token configuration."
8846
+ });
8639
8847
  }
8640
- const toChain = input.routes.toChain;
8641
- if (input.routes.toAddress) {
8848
+ const toChain = input.routes?.toChain;
8849
+ if (input.routes?.toAddress && toChain) {
8642
8850
  const result = validateAddressForChain(input.routes.toAddress, toChain);
8643
8851
  if (!result.isValid) {
8644
8852
  console.error(`[Trustware SDK] Invalid toAddress: ${result.error}`);
8645
- throw new Error(`Invalid toAddress: ${result.error}`);
8853
+ throw new TrustwareError({
8854
+ code: "INVALID_CONFIG" /* INVALID_CONFIG */,
8855
+ message: `Invalid toAddress: ${result.error}`,
8856
+ userMessage: "The configured destination address is invalid."
8857
+ });
8646
8858
  }
8647
8859
  }
8648
- if (input.routes.fromAddress) {
8649
- const result = validateAddressForChain(
8650
- input.routes.fromAddress,
8651
- input.routes.fromChain ?? toChain
8652
- );
8653
- if (!result.isValid) {
8654
- console.error(`[Trustware SDK] Invalid fromAddress: ${result.error}`);
8655
- throw new Error(`Invalid fromAddress: ${result.error}`);
8860
+ if (input.routes?.fromAddress) {
8861
+ const fromChain = input.routes.fromChain ?? toChain;
8862
+ if (fromChain) {
8863
+ const result = validateAddressForChain(
8864
+ input.routes.fromAddress,
8865
+ fromChain
8866
+ );
8867
+ if (!result.isValid) {
8868
+ console.error(`[Trustware SDK] Invalid fromAddress: ${result.error}`);
8869
+ throw new TrustwareError({
8870
+ code: "INVALID_CONFIG" /* INVALID_CONFIG */,
8871
+ message: `Invalid fromAddress: ${result.error}`,
8872
+ userMessage: "The configured source address is invalid."
8873
+ });
8874
+ }
8656
8875
  }
8657
8876
  }
8658
8877
  const autoDetectProvider = typeof input.autoDetectProvider === "boolean" ? input.autoDetectProvider : DEFAULT_AUTO_DETECT_PROVIDER;
8659
8878
  const routes = {
8660
- toChain: input.routes.toChain,
8661
- toToken: input.routes.toToken,
8662
- fromToken: input.routes.fromToken,
8663
- fromAddress: input.routes.fromAddress,
8664
- fromChain: input.routes.fromChain,
8665
- toAddress: input.routes.toAddress,
8879
+ toChain: input.routes?.toChain ?? "",
8880
+ toToken: input.routes?.toToken ?? "",
8881
+ fromToken: input.routes?.fromToken,
8882
+ fromAddress: input.routes?.fromAddress,
8883
+ fromChain: input.routes?.fromChain,
8884
+ toAddress: input.routes?.toAddress,
8666
8885
  defaultSlippage: normalizeSlippage(
8667
- input.routes.defaultSlippage ?? DEFAULT_SLIPPAGE
8886
+ input.routes?.defaultSlippage ?? DEFAULT_SLIPPAGE
8668
8887
  ),
8669
8888
  options: {
8670
- ...input.routes.options
8889
+ ...input.routes?.options
8671
8890
  }
8672
8891
  };
8673
8892
  const theme = input.theme ?? "system";
@@ -8686,13 +8905,16 @@ function resolveConfig(input) {
8686
8905
  tokensPagination: input.features?.tokensPagination ?? DEFAULT_FEATURE_FLAGS.tokensPagination,
8687
8906
  balanceStreaming: input.features?.balanceStreaming ?? DEFAULT_FEATURE_FLAGS.balanceStreaming,
8688
8907
  shouldAllowGA4: input.features?.shouldAllowGA4 ?? DEFAULT_FEATURE_FLAGS.shouldAllowGA4,
8689
- swapMode: input.features?.swapMode ?? DEFAULT_FEATURE_FLAGS.swapMode,
8908
+ // Always mirrors the canonical `mode`, however the caller set it (new `mode` field
8909
+ // or the deprecated `features.swapMode` flag).
8910
+ swapMode: mode === "swap",
8690
8911
  swapDefaultDestToken: input.features?.swapDefaultDestToken ?? DEFAULT_FEATURE_FLAGS.swapDefaultDestToken,
8691
8912
  swapLockDestToken: input.features?.swapLockDestToken ?? DEFAULT_FEATURE_FLAGS.swapLockDestToken,
8692
8913
  swapAllowedDestTokens: input.features?.swapAllowedDestTokens ?? DEFAULT_FEATURE_FLAGS.swapAllowedDestTokens
8693
8914
  };
8694
8915
  return {
8695
8916
  apiKey: input.apiKey,
8917
+ mode,
8696
8918
  routes,
8697
8919
  autoDetectProvider,
8698
8920
  theme,
@@ -8705,12 +8927,15 @@ function resolveConfig(input) {
8705
8927
  onEvent: input.onEvent
8706
8928
  };
8707
8929
  }
8930
+ var hasWarnedDeprecatedSwapModeFlag;
8708
8931
  var init_merge = __esm({
8709
8932
  "src/config/merge.ts"() {
8710
8933
  "use strict";
8711
8934
  init_defaults();
8712
8935
  init_config();
8713
8936
  init_index();
8937
+ init_TrustwareError();
8938
+ hasWarnedDeprecatedSwapModeFlag = false;
8714
8939
  }
8715
8940
  });
8716
8941
 
@@ -9296,12 +9521,71 @@ var init_useWalletSessionState = __esm({
9296
9521
  // src/widget/state/deposit/useWalletConnect.ts
9297
9522
  function useWalletConnect({
9298
9523
  setWalletType,
9299
- setCurrentStep
9524
+ setCurrentStep,
9525
+ selectedNamespace,
9526
+ setSelectedNamespace
9300
9527
  }) {
9301
9528
  const walletConnectCfg = TrustwareConfigStore.peek()?.walletConnect;
9302
9529
  const connectWC = useWalletConnectConnect(walletConnectCfg);
9530
+ const ecosystem = selectedNamespace.trim().toLowerCase() === "solana" ? "solana" : "evm";
9531
+ const [wcStatus, setWcStatus] = (0, import_react16.useState)("idle");
9532
+ const [wcErrorMessage, setWcErrorMessage] = (0, import_react16.useState)(null);
9533
+ const wcTimeoutRef = (0, import_react16.useRef)(null);
9534
+ const clearWcTimeout = (0, import_react16.useCallback)(() => {
9535
+ if (wcTimeoutRef.current !== null) {
9536
+ clearTimeout(wcTimeoutRef.current);
9537
+ wcTimeoutRef.current = null;
9538
+ }
9539
+ }, []);
9540
+ const beginWcAttempt = (0, import_react16.useCallback)(() => {
9541
+ setWcStatus("connecting");
9542
+ setWcErrorMessage(null);
9543
+ clearWcTimeout();
9544
+ wcTimeoutRef.current = setTimeout(() => {
9545
+ wcTimeoutRef.current = null;
9546
+ setWcStatus((prev) => prev === "connecting" ? "timedOut" : prev);
9547
+ }, WC_CONNECT_TIMEOUT_MS);
9548
+ }, [clearWcTimeout]);
9549
+ const resolveWcAttempt = (0, import_react16.useCallback)(() => {
9550
+ clearWcTimeout();
9551
+ setWcStatus("idle");
9552
+ setWcErrorMessage(null);
9553
+ }, [clearWcTimeout]);
9554
+ const failWcAttempt = (0, import_react16.useCallback)(
9555
+ (message) => {
9556
+ clearWcTimeout();
9557
+ setWcStatus("failed");
9558
+ setWcErrorMessage(message);
9559
+ },
9560
+ [clearWcTimeout]
9561
+ );
9562
+ const dismissWcStatus = (0, import_react16.useCallback)(() => {
9563
+ clearWcTimeout();
9564
+ setWcStatus("idle");
9565
+ setWcErrorMessage(null);
9566
+ }, [clearWcTimeout]);
9567
+ (0, import_react16.useEffect)(() => clearWcTimeout, [clearWcTimeout]);
9568
+ (0, import_react16.useEffect)(() => {
9569
+ let cancelled = false;
9570
+ beginWcAttempt();
9571
+ void (async () => {
9572
+ const restoredEcosystem = await walletManager.restoreWalletConnectSession(walletConnectCfg);
9573
+ if (cancelled) return;
9574
+ resolveWcAttempt();
9575
+ if (!restoredEcosystem) return;
9576
+ setWalletType("walletconnect");
9577
+ if (restoredEcosystem === "solana") {
9578
+ setSelectedNamespace("Solana");
9579
+ }
9580
+ const address = walletManager.identity?.addresses[0]?.address ?? null;
9581
+ if (address) setCurrentStep("crypto-pay");
9582
+ })();
9583
+ return () => {
9584
+ cancelled = true;
9585
+ };
9586
+ }, []);
9303
9587
  const WalletConnect = (0, import_react16.useCallback)(async () => {
9304
- if (walletManager.status === "connected" && walletManager.connectedVia === "walletconnect") {
9588
+ if (walletManager.status === "connected" && walletManager.connectedVia === "walletconnect" && walletManager.wallet?.ecosystem === ecosystem) {
9305
9589
  const address = walletManager.identity?.addresses[0]?.address ?? null;
9306
9590
  if (address) {
9307
9591
  setWalletType("walletconnect");
@@ -9310,35 +9594,60 @@ function useWalletConnect({
9310
9594
  }
9311
9595
  }
9312
9596
  setWalletType("walletconnect");
9313
- const { error } = await connectWC();
9597
+ beginWcAttempt();
9598
+ const { error } = await connectWC(ecosystem);
9314
9599
  if (!error) {
9315
9600
  const address = walletManager.identity?.addresses[0]?.address ?? null;
9316
9601
  if (address) {
9602
+ resolveWcAttempt();
9317
9603
  setCurrentStep("crypto-pay");
9604
+ } else {
9605
+ const message = `WalletConnect session established but no address resolved for ecosystem "${ecosystem}".`;
9606
+ console.error(`[Trustware SDK] ${message}`);
9607
+ failWcAttempt(message);
9318
9608
  }
9319
9609
  } else {
9610
+ console.error("[Trustware SDK] WalletConnect connection failed:", error);
9611
+ failWcAttempt(error);
9320
9612
  setWalletType("other");
9321
9613
  }
9322
- }, [connectWC, setCurrentStep, setWalletType]);
9614
+ }, [
9615
+ beginWcAttempt,
9616
+ connectWC,
9617
+ ecosystem,
9618
+ failWcAttempt,
9619
+ resolveWcAttempt,
9620
+ setCurrentStep,
9621
+ setWalletType
9622
+ ]);
9623
+ const retryWalletConnect = (0, import_react16.useCallback)(() => {
9624
+ walletManager.cancelWalletConnectAttempt();
9625
+ void WalletConnect();
9626
+ }, [WalletConnect]);
9323
9627
  const disconnectWalletConnect = (0, import_react16.useCallback)(async () => {
9324
9628
  await walletManager.disconnect();
9325
9629
  setWalletType("other");
9326
9630
  setCurrentStep("home");
9327
9631
  }, [setCurrentStep, setWalletType]);
9328
- const walletConnectAddress = walletManager.status === "connected" && walletManager.connectedVia === "walletconnect" ? walletManager.wallet?.ecosystem === "evm" ? walletManager.identity?.addresses[0]?.address ?? null : null : null;
9632
+ const walletConnectAddress = walletManager.status === "connected" && walletManager.connectedVia === "walletconnect" ? walletManager.identity?.addresses[0]?.address ?? null : null;
9329
9633
  return {
9330
9634
  walletConnectAddress,
9331
9635
  WalletConnect,
9332
- disconnectWalletConnect
9636
+ disconnectWalletConnect,
9637
+ wcStatus,
9638
+ wcErrorMessage,
9639
+ retryWalletConnect,
9640
+ dismissWcStatus
9333
9641
  };
9334
9642
  }
9335
- var import_react16;
9643
+ var import_react16, WC_CONNECT_TIMEOUT_MS;
9336
9644
  var init_useWalletConnect = __esm({
9337
9645
  "src/widget/state/deposit/useWalletConnect.ts"() {
9338
9646
  "use strict";
9339
9647
  import_react16 = require("react");
9340
9648
  init_config2();
9341
9649
  init_wallets();
9650
+ WC_CONNECT_TIMEOUT_MS = 3e4;
9342
9651
  }
9343
9652
  });
9344
9653
 
@@ -9372,14 +9681,24 @@ function DepositProvider({
9372
9681
  const [walletType, setWalletType] = (0, import_react17.useState)(
9373
9682
  "other"
9374
9683
  );
9375
- const { walletConnectAddress, WalletConnect, disconnectWalletConnect } = useWalletConnect({
9684
+ const [selectedNamespace, setSelectedNamespace] = (0, import_react17.useState)("evm");
9685
+ const {
9686
+ walletConnectAddress,
9687
+ WalletConnect,
9688
+ disconnectWalletConnect,
9689
+ wcStatus,
9690
+ wcErrorMessage,
9691
+ retryWalletConnect,
9692
+ dismissWcStatus
9693
+ } = useWalletConnect({
9376
9694
  setWalletType,
9377
- setCurrentStep
9695
+ setCurrentStep,
9696
+ selectedNamespace,
9697
+ setSelectedNamespace
9378
9698
  });
9379
9699
  const [selectedToken, setSelectedToken] = (0, import_react17.useState)(null);
9380
9700
  const [selectedChain, setSelectedChain] = (0, import_react17.useState)(null);
9381
9701
  const [amount, setAmount] = (0, import_react17.useState)("");
9382
- const [selectedNamespace, setSelectedNamespace] = (0, import_react17.useState)("evm");
9383
9702
  const walletAddress = (0, import_react17.useMemo)(
9384
9703
  () => walletType === "walletconnect" ? walletConnectAddress : otherWalletAddress,
9385
9704
  [walletType, walletConnectAddress, otherWalletAddress]
@@ -9451,7 +9770,11 @@ function DepositProvider({
9451
9770
  setWalletType,
9452
9771
  walletType,
9453
9772
  selectedNamespace,
9454
- setSelectedNamespace
9773
+ setSelectedNamespace,
9774
+ wcStatus,
9775
+ wcErrorMessage,
9776
+ retryWalletConnect,
9777
+ dismissWcStatus
9455
9778
  }),
9456
9779
  [
9457
9780
  WalletConnect,
@@ -9467,7 +9790,11 @@ function DepositProvider({
9467
9790
  yourWalletTokens,
9468
9791
  yourWalletTokensLoading,
9469
9792
  selectedNamespace,
9470
- setSelectedNamespace
9793
+ setSelectedNamespace,
9794
+ wcStatus,
9795
+ wcErrorMessage,
9796
+ retryWalletConnect,
9797
+ dismissWcStatus
9471
9798
  ]
9472
9799
  );
9473
9800
  const formValue = (0, import_react17.useMemo)(
@@ -16089,6 +16416,18 @@ var init_WalletNamespaceTabs = __esm({
16089
16416
  });
16090
16417
 
16091
16418
  // src/widget/features/wallet/components/CryptoWalletDropdownContent.tsx
16419
+ function ecosystemToNamespace(ecosystem) {
16420
+ switch (ecosystem.trim().toLowerCase()) {
16421
+ case "evm":
16422
+ return "evm";
16423
+ case "solana":
16424
+ return "Solana";
16425
+ case "bitcoin":
16426
+ return "bitcoin";
16427
+ default:
16428
+ return null;
16429
+ }
16430
+ }
16092
16431
  function DesktopWalletDropdownContent({
16093
16432
  browserWallets,
16094
16433
  handleWalletConnect,
@@ -16154,11 +16493,13 @@ function DesktopWalletDropdownContent({
16154
16493
  );
16155
16494
  }
16156
16495
  function MobileWalletDropdownContent({
16157
- handleWalletConnect
16496
+ browserWallets,
16497
+ handleWalletConnect,
16498
+ handleWalletSelect: connectDetectedWallet2
16158
16499
  }) {
16159
16500
  const { setCurrentStep } = useDepositNavigation();
16160
- const { selectedNamespace } = useDepositWallet();
16161
- const { walletMetaId, isConnected, status } = useWalletInfo();
16501
+ const { selectedNamespace, setSelectedNamespace } = useDepositWallet();
16502
+ const { walletMetaId, isConnected, status, detected } = useWalletInfo();
16162
16503
  const [hoveredId, setHoveredId] = (0, import_react34.useState)(null);
16163
16504
  const storeFallbackTimeoutRef = (0, import_react34.useRef)(
16164
16505
  null
@@ -16170,22 +16511,52 @@ function MobileWalletDropdownContent({
16170
16511
  }
16171
16512
  };
16172
16513
  }, []);
16514
+ (0, import_react34.useEffect)(() => {
16515
+ if (browserWallets.length > 0) return;
16516
+ const otherEcosystemWallet = detected.find((d) => {
16517
+ if (d.meta.id === "walletconnect") return false;
16518
+ const ecosystem = d.meta.ecosystem.trim().toLowerCase();
16519
+ return ecosystem !== "multi" && ecosystem !== selectedNamespace.trim().toLowerCase();
16520
+ });
16521
+ if (!otherEcosystemWallet) return;
16522
+ const nextNamespace = ecosystemToNamespace(
16523
+ otherEcosystemWallet.meta.ecosystem
16524
+ );
16525
+ if (nextNamespace) setSelectedNamespace(nextNamespace);
16526
+ }, [browserWallets, detected, selectedNamespace, setSelectedNamespace]);
16173
16527
  const connectedWalletId = isConnected ? walletMetaId : null;
16174
16528
  const currentUrl = window.location.href;
16175
- const mobileWallets = (0, import_react34.useMemo)(
16176
- () => WALLETS.filter((w) => {
16177
- if (w.id === "walletconnect") return true;
16529
+ const mobileWallets = (0, import_react34.useMemo)(() => {
16530
+ const entries = WALLETS.filter((w) => {
16531
+ if (w.id === "walletconnect") {
16532
+ return selectedNamespace.trim().toLowerCase() === "evm";
16533
+ }
16534
+ const isDetected = browserWallets.some((d) => d.meta.id === w.id);
16178
16535
  const hasMobileLink = Boolean(w.deepLink);
16179
- if (!hasMobileLink) return false;
16536
+ if (!hasMobileLink && !isDetected) return false;
16180
16537
  return w.ecosystem.trim().toLowerCase() === "multi" || w.ecosystem.trim().toLowerCase() === selectedNamespace.trim().toLowerCase();
16181
- }),
16182
- [selectedNamespace]
16183
- );
16184
- const handleWalletSelect = (wallet) => {
16538
+ }).map((meta) => ({
16539
+ meta,
16540
+ detectedWallet: browserWallets.find((d) => d.meta.id === meta.id) ?? null
16541
+ }));
16542
+ const listedIds = new Set(entries.map((e2) => e2.meta.id));
16543
+ for (const detected2 of browserWallets) {
16544
+ if (!listedIds.has(detected2.meta.id)) {
16545
+ entries.push({ meta: detected2.meta, detectedWallet: detected2 });
16546
+ }
16547
+ }
16548
+ return entries;
16549
+ }, [browserWallets, selectedNamespace]);
16550
+ const handleWalletSelect = (entry) => {
16551
+ const { meta: wallet, detectedWallet } = entry;
16185
16552
  if (wallet.id === "walletconnect") {
16186
16553
  handleWalletConnect();
16187
16554
  return;
16188
16555
  }
16556
+ if (detectedWallet) {
16557
+ void connectDetectedWallet2(detectedWallet);
16558
+ return;
16559
+ }
16189
16560
  if (wallet.deepLink) {
16190
16561
  const deepLinkUrl = wallet.deepLink(currentUrl);
16191
16562
  if (deepLinkUrl) {
@@ -16255,15 +16626,16 @@ function MobileWalletDropdownContent({
16255
16626
  scrollbarWidth: "thin",
16256
16627
  scrollbarColor: `${colors.muted} transparent`
16257
16628
  },
16258
- children: mobileWallets.map((wallet) => {
16629
+ children: mobileWallets.map((entry) => {
16630
+ const wallet = entry.meta;
16259
16631
  const isConnectedWallet = wallet.id === connectedWalletId;
16260
- const isDisabled = isConnected && !isConnectedWallet;
16632
+ const isDisabled = isConnected && !isConnectedWallet && !entry.detectedWallet;
16261
16633
  const isHovered = hoveredId === wallet.id;
16262
16634
  return /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(
16263
16635
  "button",
16264
16636
  {
16265
16637
  type: "button",
16266
- onClick: () => !isDisabled && handleWalletSelect(wallet),
16638
+ onClick: () => !isDisabled && handleWalletSelect(entry),
16267
16639
  onMouseEnter: () => !isDisabled && setHoveredId(wallet.id),
16268
16640
  onMouseLeave: () => setHoveredId(null),
16269
16641
  style: {
@@ -16339,7 +16711,7 @@ function MobileWalletDropdownContent({
16339
16711
  }
16340
16712
  }
16341
16713
  ),
16342
- /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("span", { style: { fontSize: fontSize.xs, color: "#22c55e" }, children: "Connected" })
16714
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("span", { style: { fontSize: fontSize.xs, color: "#22c55e" }, children: "Continue" })
16343
16715
  ]
16344
16716
  }
16345
16717
  )
@@ -16404,7 +16776,9 @@ function CryptoWalletDropdownContent({
16404
16776
  isMobile && /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
16405
16777
  MobileWalletDropdownContent,
16406
16778
  {
16407
- handleWalletConnect
16779
+ browserWallets,
16780
+ handleWalletConnect,
16781
+ handleWalletSelect
16408
16782
  }
16409
16783
  )
16410
16784
  ] });
@@ -16946,9 +17320,11 @@ function useHomeWalletActions({
16946
17320
  const { selectedNamespace } = useDepositWallet();
16947
17321
  const browserWallets = (0, import_react35.useMemo)(() => {
16948
17322
  if (!detectedWallets?.length) return [];
16949
- return detectedWallets.filter(
16950
- (wallet) => wallet?.meta?.id !== "walletconnect" && wallet?.meta?.ecosystem.trim().toLowerCase() === selectedNamespace.trim().toLowerCase()
16951
- );
17323
+ return detectedWallets.filter((wallet) => {
17324
+ if (wallet?.meta?.id === "walletconnect") return false;
17325
+ const ecosystem = wallet?.meta?.ecosystem.trim().toLowerCase();
17326
+ return ecosystem === "multi" || ecosystem === selectedNamespace.trim().toLowerCase();
17327
+ });
16952
17328
  }, [detectedWallets, selectedNamespace]);
16953
17329
  return {
16954
17330
  browserWallets,
@@ -16984,10 +17360,113 @@ var init_wallet = __esm({
16984
17360
  });
16985
17361
 
16986
17362
  // src/widget/pages/Home.tsx
17363
+ function WalletConnectStatusBanner({
17364
+ status,
17365
+ errorMessage,
17366
+ onRetry,
17367
+ onDismiss
17368
+ }) {
17369
+ const isDone = status !== "connecting";
17370
+ const isFailed = status === "failed";
17371
+ const { text, icon } = wcBannerCopy[status];
17372
+ return /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(
17373
+ "div",
17374
+ {
17375
+ style: {
17376
+ display: "flex",
17377
+ alignItems: "center",
17378
+ gap: spacing[2],
17379
+ width: "100%",
17380
+ padding: `${spacing[2.5]} ${spacing[3]}`,
17381
+ marginBottom: spacing[4],
17382
+ borderRadius: borderRadius.lg,
17383
+ backgroundColor: isFailed ? "rgba(239,68,68,0.1)" : isDone ? "rgba(234,179,8,0.1)" : colors.muted,
17384
+ border: isFailed ? "1px solid rgba(239,68,68,0.4)" : isDone ? "1px solid rgba(234,179,8,0.4)" : `1px solid ${colors.border}`
17385
+ },
17386
+ children: [
17387
+ icon === "spinner" ? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
17388
+ "div",
17389
+ {
17390
+ style: {
17391
+ width: "0.875rem",
17392
+ height: "0.875rem",
17393
+ border: `2px solid ${colors.mutedForeground}`,
17394
+ borderTopColor: "transparent",
17395
+ borderRadius: "9999px",
17396
+ animation: "tw-spin 1s linear infinite",
17397
+ flexShrink: 0
17398
+ }
17399
+ }
17400
+ ) : /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { style: { fontSize: fontSize.sm, flexShrink: 0 }, "aria-hidden": true, children: icon }),
17401
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(
17402
+ "p",
17403
+ {
17404
+ style: {
17405
+ flex: 1,
17406
+ fontSize: fontSize.xs,
17407
+ color: isDone ? colors.foreground : colors.mutedForeground,
17408
+ margin: 0
17409
+ },
17410
+ children: [
17411
+ text,
17412
+ isFailed && errorMessage ? ` ${errorMessage}` : ""
17413
+ ]
17414
+ }
17415
+ ),
17416
+ isDone && /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(import_jsx_runtime44.Fragment, { children: [
17417
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
17418
+ "button",
17419
+ {
17420
+ type: "button",
17421
+ onClick: onRetry,
17422
+ style: {
17423
+ fontSize: fontSize.xs,
17424
+ fontWeight: fontWeight.semibold,
17425
+ color: colors.primary,
17426
+ backgroundColor: "transparent",
17427
+ border: 0,
17428
+ cursor: "pointer",
17429
+ flexShrink: 0
17430
+ },
17431
+ children: "Retry"
17432
+ }
17433
+ ),
17434
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
17435
+ "button",
17436
+ {
17437
+ type: "button",
17438
+ onClick: onDismiss,
17439
+ "aria-label": "Dismiss",
17440
+ style: {
17441
+ fontSize: fontSize.xs,
17442
+ color: colors.mutedForeground,
17443
+ backgroundColor: "transparent",
17444
+ border: 0,
17445
+ cursor: "pointer",
17446
+ flexShrink: 0,
17447
+ padding: 0,
17448
+ lineHeight: 1
17449
+ },
17450
+ children: "\xD7"
17451
+ }
17452
+ )
17453
+ ] })
17454
+ ]
17455
+ }
17456
+ );
17457
+ }
16987
17458
  function Home({ style: _style }) {
16988
17459
  const { amount, setAmount, amountInputMode, setAmountInputMode } = useDepositForm();
16989
17460
  const { setCurrentStep, setCurrentStepInternal } = useDepositNavigation();
16990
- const { connectWallet, WalletConnect, setWalletType } = useDepositWallet();
17461
+ const {
17462
+ connectWallet,
17463
+ WalletConnect,
17464
+ setWalletType,
17465
+ wcStatus,
17466
+ wcErrorMessage,
17467
+ retryWalletConnect,
17468
+ dismissWcStatus
17469
+ } = useDepositWallet();
16991
17470
  const { resolvedTheme } = useDepositUi();
16992
17471
  const { fixedFromAmountString, isFixedAmount, minAmountUsd, maxAmountUsd } = useAmountConstraints();
16993
17472
  const { detected: detectedWallets } = useWalletDetection();
@@ -17069,6 +17548,15 @@ function Home({ style: _style }) {
17069
17548
  position: "relative"
17070
17549
  },
17071
17550
  children: [
17551
+ wcStatus !== "idle" && /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
17552
+ WalletConnectStatusBanner,
17553
+ {
17554
+ status: wcStatus,
17555
+ errorMessage: wcErrorMessage,
17556
+ onRetry: retryWalletConnect,
17557
+ onDismiss: dismissWcStatus
17558
+ }
17559
+ ),
17072
17560
  /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
17073
17561
  "p",
17074
17562
  {
@@ -17144,7 +17632,7 @@ function Home({ style: _style }) {
17144
17632
  }
17145
17633
  );
17146
17634
  }
17147
- var import_jsx_runtime44;
17635
+ var import_jsx_runtime44, wcBannerCopy;
17148
17636
  var init_Home = __esm({
17149
17637
  "src/widget/pages/Home.tsx"() {
17150
17638
  "use strict";
@@ -17155,6 +17643,20 @@ var init_Home = __esm({
17155
17643
  init_wallets();
17156
17644
  init_wallet();
17157
17645
  import_jsx_runtime44 = require("react/jsx-runtime");
17646
+ wcBannerCopy = {
17647
+ connecting: {
17648
+ text: "Waiting for wallet approval via WalletConnect\u2026",
17649
+ icon: "spinner"
17650
+ },
17651
+ timedOut: {
17652
+ text: "Still waiting on WalletConnect \u2014 this is taking longer than expected.",
17653
+ icon: "\u26A0\uFE0F"
17654
+ },
17655
+ failed: {
17656
+ text: "WalletConnect connection failed.",
17657
+ icon: "\u2715"
17658
+ }
17659
+ };
17158
17660
  }
17159
17661
  });
17160
17662
 
@@ -30964,7 +31466,7 @@ async function sendRouteAsUserOperation(params) {
30964
31466
  );
30965
31467
  }
30966
31468
  console.debug("[send] UserOp included", { userOpHash, txHash });
30967
- await submitReceipt(intentId, txHash, getSponsorshipRequestId());
31469
+ await submitReceipt(intentId, txHash, getSponsorshipRequestId(), eoaAddress);
30968
31470
  return { userOpHash, txHash, intentId };
30969
31471
  }
30970
31472
  var NATIVE_ADDRS;
@@ -33861,6 +34363,7 @@ function SwapWalletSelectorMobile({
33861
34363
  const { meta } = entry;
33862
34364
  const isWalletConnected = managerConnected && walletMetaId === meta.id;
33863
34365
  const isConnecting = connectingId === meta.id && walletStatus === "connecting";
34366
+ const isRowDisabled = managerConnected && !isWalletConnected && !entry.detectedWallet;
33864
34367
  return /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)(
33865
34368
  "div",
33866
34369
  {
@@ -33878,7 +34381,8 @@ function SwapWalletSelectorMobile({
33878
34381
  isWalletConnected && {
33879
34382
  boxShadow: `0 0 0 2px ${colors.primary}`,
33880
34383
  border: `1px solid ${colors.primary}`
33881
- }
34384
+ },
34385
+ isRowDisabled && { opacity: 0.4 }
33882
34386
  ),
33883
34387
  children: [
33884
34388
  /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(
@@ -33969,7 +34473,7 @@ function SwapWalletSelectorMobile({
33969
34473
  "button",
33970
34474
  {
33971
34475
  onClick: () => void handleClick(entry),
33972
- disabled: walletStatus === "connecting",
34476
+ disabled: walletStatus === "connecting" || isRowDisabled,
33973
34477
  style: mergeStyles(
33974
34478
  {
33975
34479
  padding: `${spacing[1.5]} ${spacing[3]}`,
@@ -33982,7 +34486,7 @@ function SwapWalletSelectorMobile({
33982
34486
  cursor: "pointer",
33983
34487
  flexShrink: 0
33984
34488
  },
33985
- walletStatus === "connecting" && {
34489
+ (walletStatus === "connecting" || isRowDisabled) && {
33986
34490
  opacity: 0.5,
33987
34491
  cursor: "not-allowed"
33988
34492
  }
@@ -34010,6 +34514,7 @@ function SwapWalletSelectorMobile({
34010
34514
  ),
34011
34515
  (() => {
34012
34516
  const wcConnected = managerConnected && connectedVia === "walletconnect";
34517
+ const wcRowDisabled = managerConnected && !wcConnected;
34013
34518
  return /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)(
34014
34519
  "div",
34015
34520
  {
@@ -34028,9 +34533,10 @@ function SwapWalletSelectorMobile({
34028
34533
  wcConnected && {
34029
34534
  boxShadow: `0 0 0 2px ${colors.primary}`,
34030
34535
  border: `1px solid ${colors.primary}`
34031
- }
34536
+ },
34537
+ wcRowDisabled && { opacity: 0.4, cursor: "not-allowed" }
34032
34538
  ),
34033
- onClick: !wcConnected ? () => void handleWalletConnect() : void 0,
34539
+ onClick: !wcConnected && !wcRowDisabled ? () => void handleWalletConnect() : void 0,
34034
34540
  children: [
34035
34541
  /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(
34036
34542
  "div",
@@ -34126,18 +34632,24 @@ function SwapWalletSelectorMobile({
34126
34632
  e2.stopPropagation();
34127
34633
  void handleWalletConnect();
34128
34634
  },
34129
- disabled: wcConnecting,
34130
- style: {
34131
- padding: `${spacing[1.5]} ${spacing[3]}`,
34132
- borderRadius: "9999px",
34133
- backgroundColor: "rgba(59,130,246,0.1)",
34134
- color: colors.primary,
34135
- fontSize: fontSize.xs,
34136
- fontWeight: fontWeight.medium,
34137
- border: 0,
34138
- cursor: "pointer",
34139
- flexShrink: 0
34140
- },
34635
+ disabled: wcConnecting || wcRowDisabled,
34636
+ style: mergeStyles(
34637
+ {
34638
+ padding: `${spacing[1.5]} ${spacing[3]}`,
34639
+ borderRadius: "9999px",
34640
+ backgroundColor: "rgba(59,130,246,0.1)",
34641
+ color: colors.primary,
34642
+ fontSize: fontSize.xs,
34643
+ fontWeight: fontWeight.medium,
34644
+ border: 0,
34645
+ cursor: "pointer",
34646
+ flexShrink: 0
34647
+ },
34648
+ (wcConnecting || wcRowDisabled) && {
34649
+ opacity: 0.5,
34650
+ cursor: "not-allowed"
34651
+ }
34652
+ ),
34141
34653
  children: "Connect"
34142
34654
  }
34143
34655
  )
@@ -35045,7 +35557,7 @@ function SwapMode({
35045
35557
  }).catch(() => {
35046
35558
  });
35047
35559
  }, [defaultDestRef, allChains]);
35048
- const { walletAddress, walletStatus, connectWallet, disconnectWallet } = useWalletSessionState();
35560
+ const { walletAddress, walletStatus, connectWallet } = useWalletSessionState();
35049
35561
  const setFromTokenStable = (0, import_react50.useCallback)(
35050
35562
  (t) => setFromToken(t),
35051
35563
  []
@@ -37123,7 +37635,7 @@ function SwapMode({
37123
37635
  walletAddress ? /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)(
37124
37636
  "button",
37125
37637
  {
37126
- onClick: () => void disconnectWallet(),
37638
+ onClick: handleConnectAndReview,
37127
37639
  style: {
37128
37640
  fontSize: fontSize.xs,
37129
37641
  color: colors.mutedForeground,
@@ -37134,8 +37646,7 @@ function SwapMode({
37134
37646
  children: [
37135
37647
  walletAddress.slice(0, 6),
37136
37648
  "...",
37137
- walletAddress.slice(-4),
37138
- " \xD7"
37649
+ walletAddress.slice(-4)
37139
37650
  ]
37140
37651
  }
37141
37652
  ) : /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(
@@ -39235,7 +39746,7 @@ var init_TrustwareWidgetV2 = __esm({
39235
39746
  if (!isOpen) {
39236
39747
  return null;
39237
39748
  }
39238
- if (config.features.swapMode) {
39749
+ if (config.mode === "swap") {
39239
39750
  return /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(SwapMode, { theme, style });
39240
39751
  }
39241
39752
  return /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(DepositProvider, { initialStep: effectiveInitialStep, children: /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(