decane-connect-kit 0.0.1 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -32,8 +32,12 @@ function createRegistry(emitter) {
32
32
  };
33
33
  if (incoming.chain === "evm") {
34
34
  account.evmProvider = incoming.provider;
35
- } else {
35
+ } else if (incoming.chain === "solana") {
36
36
  account.solanaProvider = incoming.provider;
37
+ } else if (incoming.chain === "tron") {
38
+ account.tronProvider = incoming.provider;
39
+ } else if (incoming.chain === "bitcoin") {
40
+ account.bitcoinProvider = incoming.provider;
37
41
  }
38
42
  return account;
39
43
  }
@@ -44,12 +48,10 @@ function createRegistry(emitter) {
44
48
  incoming.chain
45
49
  ].sort();
46
50
  }
47
- if (incoming.chain === "evm") {
48
- existing.evmProvider = incoming.provider;
49
- }
50
- if (incoming.chain === "solana") {
51
- existing.solanaProvider = incoming.provider;
52
- }
51
+ if (incoming.chain === "evm") existing.evmProvider = incoming.provider;
52
+ if (incoming.chain === "solana") existing.solanaProvider = incoming.provider;
53
+ if (incoming.chain === "tron") existing.tronProvider = incoming.provider;
54
+ if (incoming.chain === "bitcoin") existing.bitcoinProvider = incoming.provider;
53
55
  if (!existing.icon && incoming.icon) existing.icon = incoming.icon;
54
56
  }
55
57
  function registerOrMerge(incoming) {
@@ -96,9 +98,9 @@ function createRegistry(emitter) {
96
98
  all: () => [...wallets],
97
99
  evm: () => wallets.filter((w) => w.chainSupport.includes("evm")),
98
100
  solana: () => wallets.filter((w) => w.chainSupport.includes("solana")),
99
- multiChain: () => wallets.filter(
100
- (w) => w.chainSupport.includes("evm") && w.chainSupport.includes("solana")
101
- ),
101
+ tron: () => wallets.filter((w) => w.chainSupport.includes("tron")),
102
+ bitcoin: () => wallets.filter((w) => w.chainSupport.includes("bitcoin")),
103
+ multiChain: () => wallets.filter((w) => w.chainSupport.length >= 2),
102
104
  byId: (id) => wallets.find((w) => w.id === id)
103
105
  }
104
106
  };
@@ -681,11 +683,37 @@ var BUILT_IN_CHAINS = [
681
683
  name: "Solana Devnet",
682
684
  nativeCurrency: SOL,
683
685
  blockExplorerUrl: "https://solscan.io/?cluster=devnet"
686
+ },
687
+ // ── Tron ─────────────────────────────────────────────────────────────────────
688
+ {
689
+ id: "tron:mainnet",
690
+ type: "tron",
691
+ name: "Tron",
692
+ nativeCurrency: { name: "Tronix", symbol: "TRX", decimals: 6 },
693
+ blockExplorerUrl: "https://tronscan.org"
694
+ },
695
+ {
696
+ id: "tron:shasta",
697
+ type: "tron",
698
+ name: "Tron Shasta Testnet",
699
+ nativeCurrency: { name: "Tronix", symbol: "TRX", decimals: 6 },
700
+ blockExplorerUrl: "https://shasta.tronscan.org",
701
+ isCustom: true
702
+ },
703
+ // ── Bitcoin ───────────────────────────────────────────────────────────────────
704
+ {
705
+ id: "bip122:mainnet",
706
+ type: "bitcoin",
707
+ name: "Bitcoin",
708
+ nativeCurrency: { name: "Bitcoin", symbol: "BTC", decimals: 8 },
709
+ blockExplorerUrl: "https://blockstream.info"
684
710
  }
685
711
  ];
686
712
  function getChainType(caip2Id) {
687
713
  if (caip2Id.startsWith("eip155:")) return "evm";
688
714
  if (caip2Id.startsWith("solana:")) return "solana";
715
+ if (caip2Id.startsWith("tron:")) return "tron";
716
+ if (caip2Id.startsWith("bip122:")) return "bitcoin";
689
717
  throw new Error(`Cannot determine chain type from: ${caip2Id}`);
690
718
  }
691
719
  function toCAIP10(chainId, address) {
@@ -701,6 +729,14 @@ var SOLANA_METHODS = /* @__PURE__ */ new Set([
701
729
  "wallet_signMessage"
702
730
  // wallet_signTypedData is EVM-only — never included here
703
731
  ]);
732
+ var TRON_METHODS = /* @__PURE__ */ new Set([
733
+ "wallet_sendTransaction",
734
+ "wallet_signMessage"
735
+ ]);
736
+ var BITCOIN_METHODS = /* @__PURE__ */ new Set([
737
+ "wallet_sendTransaction",
738
+ "wallet_signMessage"
739
+ ]);
704
740
  var CHAINS = {
705
741
  // Tier-1
706
742
  ETHEREUM: "eip155:1",
@@ -766,13 +802,17 @@ var CHAINS = {
766
802
  LOCALHOST: "eip155:31337",
767
803
  // Solana
768
804
  SOLANA: "solana:mainnet",
769
- SOLANA_DEVNET: "solana:devnet"
805
+ SOLANA_DEVNET: "solana:devnet",
806
+ // Tron
807
+ TRON: "tron:mainnet",
808
+ // Bitcoin
809
+ BITCOIN: "bip122:mainnet"
770
810
  };
771
811
  function validateCustomChain(chain) {
772
812
  if (!chain || typeof chain !== "object") return false;
773
813
  const c = chain;
774
814
  if (typeof c.id !== "string" || !c.id) return false;
775
- if (c.type !== "evm" && c.type !== "solana") return false;
815
+ if (c.type !== "evm" && c.type !== "solana" && c.type !== "tron" && c.type !== "bitcoin") return false;
776
816
  if (typeof c.name !== "string" || !c.name) return false;
777
817
  if (!c.nativeCurrency || typeof c.nativeCurrency !== "object") return false;
778
818
  if (c.type === "evm" && (typeof c.chainId !== "number" || !c.id.startsWith("eip155:")))
@@ -991,7 +1031,12 @@ async function walletStandardRequest(wallet, method, payload, account) {
991
1031
  );
992
1032
  }
993
1033
  }
1034
+ function isSolanaAccount(a) {
1035
+ return !a.chains?.length || a.chains.some((c) => c.startsWith("solana:"));
1036
+ }
994
1037
  async function getSolanaAddress(wallet) {
1038
+ const pre = wallet.accounts.find(isSolanaAccount);
1039
+ if (pre) return base58.encode(pre.publicKey);
995
1040
  const connectFeature = wallet.features["standard:connect"];
996
1041
  if (!connectFeature) {
997
1042
  throw new DecaneError(
@@ -1000,13 +1045,81 @@ async function getSolanaAddress(wallet) {
1000
1045
  );
1001
1046
  }
1002
1047
  const { accounts } = await connectFeature.connect();
1003
- if (!accounts?.[0]) {
1048
+ const solanaAccount = accounts.find(isSolanaAccount);
1049
+ if (!solanaAccount) {
1004
1050
  throw new DecaneError(
1005
1051
  4001 /* USER_REJECTED */,
1006
1052
  "No Solana accounts returned"
1007
1053
  );
1008
1054
  }
1009
- return base58.encode(accounts[0].publicKey);
1055
+ return base58.encode(solanaAccount.publicKey);
1056
+ }
1057
+
1058
+ // src/tron/adapter.ts
1059
+ async function getTronAddress(provider) {
1060
+ try {
1061
+ const result = await provider.request({ method: "tron_requestAccounts" });
1062
+ const accounts = result;
1063
+ if (accounts?.[0]) return accounts[0];
1064
+ } catch {
1065
+ }
1066
+ const result2 = await provider.request({ method: "tron_accounts" }).catch(() => null);
1067
+ const accounts2 = result2;
1068
+ if (accounts2?.[0]) return accounts2[0];
1069
+ throw new DecaneError(4001 /* USER_REJECTED */, "No Tron accounts returned");
1070
+ }
1071
+ async function tronRequest(provider, method, payload, account) {
1072
+ switch (method) {
1073
+ case "wallet_signMessage":
1074
+ return provider.request({
1075
+ method: "tron_signMessage",
1076
+ params: { message: payload }
1077
+ });
1078
+ case "wallet_sendTransaction":
1079
+ return provider.request({
1080
+ method: "tron_sendTransaction",
1081
+ params: { ...payload, from: account }
1082
+ });
1083
+ default:
1084
+ throw new DecaneError(
1085
+ 5030 /* METHOD_NOT_SUPPORTED */,
1086
+ `Tron adapter: unsupported method ${method}`
1087
+ );
1088
+ }
1089
+ }
1090
+
1091
+ // src/bitcoin/adapter.ts
1092
+ async function getBitcoinAddress(provider) {
1093
+ const result = await provider.requestAccounts();
1094
+ if (!result || result.length === 0) {
1095
+ throw new DecaneError(4001 /* USER_REJECTED */, "No Bitcoin accounts returned");
1096
+ }
1097
+ const first = result[0];
1098
+ return typeof first === "string" ? first : first.address;
1099
+ }
1100
+ async function bitcoinRequest(provider, method, payload, account) {
1101
+ switch (method) {
1102
+ case "wallet_signMessage":
1103
+ return provider.signMessage(payload);
1104
+ case "wallet_sendTransaction": {
1105
+ const { to, value } = payload;
1106
+ if (provider.sendBitcoin) {
1107
+ return provider.sendBitcoin(to, value);
1108
+ }
1109
+ if (provider.send) {
1110
+ return provider.send({ to, value, from: account });
1111
+ }
1112
+ throw new DecaneError(
1113
+ 5030 /* METHOD_NOT_SUPPORTED */,
1114
+ "Bitcoin wallet does not support sendBitcoin"
1115
+ );
1116
+ }
1117
+ default:
1118
+ throw new DecaneError(
1119
+ 5030 /* METHOD_NOT_SUPPORTED */,
1120
+ `Bitcoin adapter: unsupported method ${method}`
1121
+ );
1122
+ }
1010
1123
  }
1011
1124
 
1012
1125
  // src/core/router.ts
@@ -1057,20 +1170,23 @@ function createRouter(opts) {
1057
1170
  const chainType = getChainType(chainId);
1058
1171
  if (chainType === "evm" && !connectedWallet.evmProvider) continue;
1059
1172
  if (chainType === "solana" && !connectedWallet.solanaProvider) continue;
1173
+ if (chainType === "tron" && !connectedWallet.tronProvider) continue;
1174
+ if (chainType === "bitcoin" && !connectedWallet.bitcoinProvider) continue;
1060
1175
  let address;
1061
1176
  if (chainType === "evm") {
1062
1177
  address = await getEvmAddress(connectedWallet.evmProvider);
1063
1178
  if (chain.isCustom) {
1064
- await addEthereumChain(
1065
- connectedWallet.evmProvider,
1066
- chain
1067
- ).catch(() => {
1179
+ await addEthereumChain(connectedWallet.evmProvider, chain).catch(() => {
1068
1180
  });
1069
1181
  }
1070
- } else {
1182
+ } else if (chainType === "solana") {
1071
1183
  address = await getSolanaAddress(connectedWallet.solanaProvider);
1184
+ } else if (chainType === "tron") {
1185
+ address = await getTronAddress(connectedWallet.tronProvider);
1186
+ } else {
1187
+ address = await getBitcoinAddress(connectedWallet.bitcoinProvider);
1072
1188
  }
1073
- const methodSet = chainType === "evm" ? EVM_METHODS : SOLANA_METHODS;
1189
+ const methodSet = chainType === "evm" ? EVM_METHODS : chainType === "solana" ? SOLANA_METHODS : chainType === "tron" ? TRON_METHODS : BITCOIN_METHODS;
1074
1190
  const grantedMethods = (scope?.methods ?? []).filter(
1075
1191
  (m) => methodSet.has(m)
1076
1192
  );
@@ -1149,19 +1265,13 @@ function createRouter(opts) {
1149
1265
  );
1150
1266
  }
1151
1267
  if (chainType === "evm") {
1152
- return eip1193Request(
1153
- wallet.evmProvider,
1154
- method,
1155
- payload,
1156
- account
1157
- );
1268
+ return eip1193Request(wallet.evmProvider, method, payload, account);
1269
+ } else if (chainType === "solana") {
1270
+ return walletStandardRequest(wallet.solanaProvider, method, payload, account);
1271
+ } else if (chainType === "tron") {
1272
+ return tronRequest(wallet.tronProvider, method, payload, account);
1158
1273
  } else {
1159
- return walletStandardRequest(
1160
- wallet.solanaProvider,
1161
- method,
1162
- payload,
1163
- account
1164
- );
1274
+ return bitcoinRequest(wallet.bitcoinProvider, method, payload, account);
1165
1275
  }
1166
1276
  }
1167
1277
  return { request };
@@ -1216,6 +1326,12 @@ function createProvider(opts) {
1216
1326
  get multiChainWallets() {
1217
1327
  return registry.get.multiChain();
1218
1328
  },
1329
+ get tronWallets() {
1330
+ return registry.get.tron();
1331
+ },
1332
+ get bitcoinWallets() {
1333
+ return registry.get.bitcoin();
1334
+ },
1219
1335
  // ── Connection ──────────────────────────────────────────────────────────
1220
1336
  async connect(wallet, preferredChain) {
1221
1337
  if (session.get()) {
@@ -1224,13 +1340,19 @@ function createProvider(opts) {
1224
1340
  }
1225
1341
  _connectedWallet = wallet;
1226
1342
  const support = wallet.chainSupport;
1227
- if (support.includes("evm") && preferredChain !== "solana") {
1343
+ const hasEvm = support.includes("evm") && preferredChain !== "solana" && preferredChain !== "tron" && preferredChain !== "bitcoin";
1344
+ const hasSol = support.includes("solana") && preferredChain !== "evm" && preferredChain !== "tron" && preferredChain !== "bitcoin";
1345
+ const hasTron = support.includes("tron") && preferredChain !== "evm" && preferredChain !== "solana" && preferredChain !== "bitcoin";
1346
+ const hasBitcoin = support.includes("bitcoin") && preferredChain !== "evm" && preferredChain !== "solana" && preferredChain !== "tron";
1347
+ if (hasEvm) {
1228
1348
  _activeChain = config.defaultChain?.startsWith("eip155:") ? config.defaultChain : "eip155:1";
1229
- } else {
1349
+ } else if (hasSol) {
1230
1350
  _activeChain = "solana:mainnet";
1351
+ } else if (hasTron) {
1352
+ _activeChain = "tron:mainnet";
1353
+ } else if (hasBitcoin) {
1354
+ _activeChain = "bip122:mainnet";
1231
1355
  }
1232
- const hasEvm = support.includes("evm") && preferredChain !== "solana";
1233
- const hasSol = support.includes("solana") && preferredChain !== "evm";
1234
1356
  const required = {};
1235
1357
  const optional = {};
1236
1358
  if (hasEvm) {
@@ -1254,6 +1376,34 @@ function createProvider(opts) {
1254
1376
  _activeChain = solChain;
1255
1377
  }
1256
1378
  }
1379
+ if (hasTron) {
1380
+ const tronChain = "tron:mainnet";
1381
+ const scope = {
1382
+ methods: ["wallet_sendTransaction", "wallet_signMessage"],
1383
+ accounts: [],
1384
+ events: []
1385
+ };
1386
+ if (hasEvm || hasSol) {
1387
+ optional[tronChain] = scope;
1388
+ } else {
1389
+ required[tronChain] = scope;
1390
+ _activeChain = tronChain;
1391
+ }
1392
+ }
1393
+ if (hasBitcoin) {
1394
+ const btcChain = "bip122:mainnet";
1395
+ const scope = {
1396
+ methods: ["wallet_sendTransaction", "wallet_signMessage"],
1397
+ accounts: [],
1398
+ events: []
1399
+ };
1400
+ if (hasEvm || hasSol || hasTron) {
1401
+ optional[btcChain] = scope;
1402
+ } else {
1403
+ required[btcChain] = scope;
1404
+ _activeChain = btcChain;
1405
+ }
1406
+ }
1257
1407
  await router.request({
1258
1408
  method: "wallet_requestPermissions",
1259
1409
  params: [{ requiredScopes: required, optionalScopes: optional }, wallet.id]
@@ -1321,6 +1471,58 @@ function createProvider(opts) {
1321
1471
  return provider;
1322
1472
  }
1323
1473
 
1474
+ // src/evm/bitcoinSnap.ts
1475
+ var BITCOIN_SNAP_IDS = [
1476
+ "npm:@metamask/bitcoin-snap",
1477
+ "npm:@consensys/btc-snap"
1478
+ ];
1479
+ async function detectBitcoinSnap(provider) {
1480
+ try {
1481
+ const snaps = await provider.request({ method: "wallet_getSnaps" });
1482
+ if (!snaps) return null;
1483
+ for (const id of BITCOIN_SNAP_IDS) {
1484
+ const snap = snaps[id];
1485
+ if (snap && snap.blocked !== true) return id;
1486
+ }
1487
+ return null;
1488
+ } catch {
1489
+ return null;
1490
+ }
1491
+ }
1492
+ function makeBitcoinSnapProvider(snapId, evmProvider) {
1493
+ function invoke(method, params) {
1494
+ return evmProvider.request({
1495
+ method: "wallet_invokeSnap",
1496
+ params: [{ snapId, request: { method, params } }]
1497
+ });
1498
+ }
1499
+ return {
1500
+ async requestAccounts() {
1501
+ const result = await invoke("btc_getAddress").catch(() => invoke("btc_getPublicKey"));
1502
+ if (typeof result === "string") return [result];
1503
+ if (Array.isArray(result)) return result;
1504
+ return [];
1505
+ },
1506
+ async signMessage(message) {
1507
+ return invoke("btc_signMessage", [message]);
1508
+ },
1509
+ async sendBitcoin(to, value) {
1510
+ return invoke("btc_sendBitcoin", [{ to, satoshis: value }]);
1511
+ }
1512
+ };
1513
+ }
1514
+ async function tryRegisterBitcoinSnap(registry, name, icon, rdns, evmProvider) {
1515
+ const snapId = await detectBitcoinSnap(evmProvider);
1516
+ if (!snapId) return;
1517
+ registry.registerOrMerge({
1518
+ chain: "bitcoin",
1519
+ name,
1520
+ icon,
1521
+ rdns,
1522
+ provider: makeBitcoinSnapProvider(snapId, evmProvider)
1523
+ });
1524
+ }
1525
+
1324
1526
  // src/evm/discovery.ts
1325
1527
  function startEvmDiscovery(registry) {
1326
1528
  if (typeof window === "undefined") return;
@@ -1340,6 +1542,14 @@ function startEvmDiscovery(registry) {
1340
1542
  uuid: info.uuid,
1341
1543
  provider
1342
1544
  });
1545
+ tryRegisterBitcoinSnap(
1546
+ registry,
1547
+ info.name,
1548
+ info.icon,
1549
+ info.rdns,
1550
+ provider
1551
+ ).catch(() => {
1552
+ });
1343
1553
  }
1344
1554
  );
1345
1555
  window.dispatchEvent(new CustomEvent("eip6963:requestProvider"));
@@ -1380,6 +1590,53 @@ function startSolanaDiscovery(registry) {
1380
1590
  );
1381
1591
  }
1382
1592
 
1593
+ // src/tron/discovery.ts
1594
+ var TRONLINK_RDNS = "link.tron.tronlink";
1595
+ var TRONLINK_ICON = "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAzMiAzMiI+PGNpcmNsZSBjeD0iMTYiIGN5PSIxNiIgcj0iMTYiIGZpbGw9IiNGRjAwMTMiLz48cG9seWdvbiBwb2ludHM9IjEyLDkgMjMsMTYgMTIsMjMiIGZpbGw9IndoaXRlIi8+PC9zdmc+";
1596
+ function startTronDiscovery(registry) {
1597
+ let registered = false;
1598
+ function tryRegister() {
1599
+ if (registered || !window.tronLink) return;
1600
+ registered = true;
1601
+ registry.registerOrMerge({
1602
+ chain: "tron",
1603
+ name: "TronLink",
1604
+ icon: TRONLINK_ICON,
1605
+ rdns: TRONLINK_RDNS,
1606
+ provider: window.tronLink
1607
+ });
1608
+ }
1609
+ tryRegister();
1610
+ window.addEventListener("tronLink#initialized", tryRegister, { once: true });
1611
+ const start = Date.now();
1612
+ const poll = setInterval(() => {
1613
+ tryRegister();
1614
+ if (registered || Date.now() - start > 3e3) clearInterval(poll);
1615
+ }, 200);
1616
+ }
1617
+
1618
+ // src/bitcoin/discovery.ts
1619
+ var BTC_ICON = "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAzMiAzMiI+PGNpcmNsZSBjeD0iMTYiIGN5PSIxNiIgcj0iMTYiIGZpbGw9IiNGNzkzMUEiLz48dGV4dCB4PSIxNi41IiB5PSIyMiIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1zaXplPSIxNiIgZm9udC13ZWlnaHQ9IjcwMCIgZmlsbD0id2hpdGUiIGZvbnQtZmFtaWx5PSJBcmlhbCxzeXN0ZW0tdWkiPuKmojwvdGV4dD48L3N2Zz4=";
1620
+ function startBitcoinDiscovery(registry) {
1621
+ setTimeout(() => {
1622
+ const candidates = [
1623
+ { name: "Unisat", rdns: "io.unisat.wallet", provider: window.unisat },
1624
+ // OKX shares rdns with its EVM provider — merges into the EVM entry automatically
1625
+ { name: "OKX Wallet", rdns: "com.okex.okxwallet", provider: window.okxwallet?.bitcoin }
1626
+ ];
1627
+ for (const { name, rdns, provider } of candidates) {
1628
+ if (!provider) continue;
1629
+ registry.registerOrMerge({
1630
+ chain: "bitcoin",
1631
+ name,
1632
+ icon: BTC_ICON,
1633
+ rdns,
1634
+ provider
1635
+ });
1636
+ }
1637
+ }, 150);
1638
+ }
1639
+
1383
1640
  // src/factory.ts
1384
1641
  function createDecane(config = {}) {
1385
1642
  const emitter = createEmitter();
@@ -1393,6 +1650,8 @@ function createDecane(config = {}) {
1393
1650
  const router = createRouter({ registry, session, chainStore });
1394
1651
  startEvmDiscovery(registry);
1395
1652
  startSolanaDiscovery(registry);
1653
+ startTronDiscovery(registry);
1654
+ startBitcoinDiscovery(registry);
1396
1655
  return createProvider({ config, registry, session, chainStore, router, emitter });
1397
1656
  }
1398
1657
 
@@ -1560,6 +1819,67 @@ function WalletIcon({ src, name, size = 36 }) {
1560
1819
  initial
1561
1820
  );
1562
1821
  }
1822
+ function EthCircle({ size }) {
1823
+ const s = size;
1824
+ return /* @__PURE__ */ React.createElement("svg", { width: s, height: s, viewBox: "0 0 16 16", fill: "none" }, /* @__PURE__ */ React.createElement("circle", { cx: "8", cy: "8", r: "8", fill: "#627EEA" }), /* @__PURE__ */ React.createElement("polygon", { points: "8,2.5 11.5,8 8,9.8 4.5,8", fill: "white", fillOpacity: "0.9" }), /* @__PURE__ */ React.createElement("polygon", { points: "8,9.8 11.5,8 8,13.5", fill: "white", fillOpacity: "0.6" }), /* @__PURE__ */ React.createElement("polygon", { points: "8,9.8 4.5,8 8,13.5", fill: "white", fillOpacity: "0.8" }), /* @__PURE__ */ React.createElement("polygon", { points: "8,2.5 8,9.8 4.5,8", fill: "white", fillOpacity: "0.6" }));
1825
+ }
1826
+ function SolCircle({ size }) {
1827
+ const s = size;
1828
+ return /* @__PURE__ */ React.createElement("svg", { width: s, height: s, viewBox: "0 0 16 16", fill: "none" }, /* @__PURE__ */ React.createElement("circle", { cx: "8", cy: "8", r: "8", fill: "#9945FF" }), /* @__PURE__ */ React.createElement("rect", { x: "4", y: "4.5", width: "7", height: "1.5", rx: "0.75", fill: "white", fillOpacity: "0.95" }), /* @__PURE__ */ React.createElement("rect", { x: "4", y: "7.25", width: "7", height: "1.5", rx: "0.75", fill: "white", fillOpacity: "0.95" }), /* @__PURE__ */ React.createElement("rect", { x: "4", y: "10", width: "5.5", height: "1.5", rx: "0.75", fill: "white", fillOpacity: "0.95" }));
1829
+ }
1830
+ function TronCircle({ size }) {
1831
+ const s = size;
1832
+ return /* @__PURE__ */ React.createElement("svg", { width: s, height: s, viewBox: "0 0 16 16", fill: "none" }, /* @__PURE__ */ React.createElement("circle", { cx: "8", cy: "8", r: "8", fill: "#FF0013" }), /* @__PURE__ */ React.createElement("polygon", { points: "6,4.5 12,8 6,11.5", fill: "white", fillOpacity: "0.95" }));
1833
+ }
1834
+ function BitcoinCircle({ size }) {
1835
+ const s = size;
1836
+ return /* @__PURE__ */ React.createElement("svg", { width: s, height: s, viewBox: "0 0 16 16", fill: "none" }, /* @__PURE__ */ React.createElement("circle", { cx: "8", cy: "8", r: "8", fill: "#F7931A" }), /* @__PURE__ */ React.createElement(
1837
+ "text",
1838
+ {
1839
+ x: "8.3",
1840
+ y: "11.5",
1841
+ textAnchor: "middle",
1842
+ fontSize: "8",
1843
+ fontWeight: "700",
1844
+ fill: "white",
1845
+ fontFamily: "Arial, system-ui"
1846
+ },
1847
+ "\u20BF"
1848
+ ));
1849
+ }
1850
+ function ChainCircleIcon({ chain, size }) {
1851
+ switch (chain) {
1852
+ case "evm":
1853
+ return /* @__PURE__ */ React.createElement(EthCircle, { size });
1854
+ case "solana":
1855
+ return /* @__PURE__ */ React.createElement(SolCircle, { size });
1856
+ case "tron":
1857
+ return /* @__PURE__ */ React.createElement(TronCircle, { size });
1858
+ case "bitcoin":
1859
+ return /* @__PURE__ */ React.createElement(BitcoinCircle, { size });
1860
+ }
1861
+ }
1862
+ var CHAIN_ORDER = ["evm", "solana", "tron", "bitcoin"];
1863
+ function ChainIconStack({ support, size = 16 }) {
1864
+ const ordered = CHAIN_ORDER.filter((c) => support.includes(c));
1865
+ if (ordered.length === 0) return null;
1866
+ const overlap = Math.round(size * 0.35);
1867
+ return /* @__PURE__ */ React.createElement("div", { style: { display: "flex", alignItems: "center", flexShrink: 0 } }, ordered.map((chain, i) => /* @__PURE__ */ React.createElement(
1868
+ "div",
1869
+ {
1870
+ key: chain,
1871
+ style: {
1872
+ marginLeft: i === 0 ? 0 : `-${overlap}px`,
1873
+ zIndex: ordered.length - i,
1874
+ position: "relative",
1875
+ borderRadius: "50%",
1876
+ lineHeight: 0,
1877
+ boxShadow: i > 0 ? `0 0 0 1.5px var(--dc-bg, #fff)` : void 0
1878
+ }
1879
+ },
1880
+ /* @__PURE__ */ React.createElement(ChainCircleIcon, { chain, size })
1881
+ )));
1882
+ }
1563
1883
 
1564
1884
  // src/ui/WalletSelector.tsx
1565
1885
  var FONT_URL = "https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@400;500;600;700;800&display=swap";
@@ -1586,21 +1906,6 @@ function injectFont() {
1586
1906
  link.href = FONT_URL;
1587
1907
  document.head.appendChild(link);
1588
1908
  }
1589
- var badgeBase = {
1590
- display: "inline-flex",
1591
- alignItems: "center",
1592
- padding: "3px 8px",
1593
- borderRadius: 20,
1594
- fontSize: 10,
1595
- fontWeight: 700,
1596
- letterSpacing: "0.04em",
1597
- textTransform: "uppercase"
1598
- };
1599
- function ChainBadges({ chainSupport }) {
1600
- const hasEvm = chainSupport.includes("evm");
1601
- const hasSol = chainSupport.includes("solana");
1602
- return /* @__PURE__ */ React2.createElement("div", { style: { display: "flex", gap: 4 } }, hasEvm && /* @__PURE__ */ React2.createElement("span", { style: { ...badgeBase, background: "var(--dc-badge-evm)", color: "var(--dc-badge-evm-text)" } }, "EVM"), hasSol && /* @__PURE__ */ React2.createElement("span", { style: { ...badgeBase, background: "var(--dc-badge-sol)", color: "var(--dc-badge-sol-text)", border: "1px solid var(--dc-border)" } }, "SVM"));
1603
- }
1604
1909
  function WalletRow({ wallet, onClick }) {
1605
1910
  const [hovered, setHovered] = useState(false);
1606
1911
  const [focused, setFocused] = useState(false);
@@ -1630,7 +1935,7 @@ function WalletRow({ wallet, onClick }) {
1630
1935
  },
1631
1936
  /* @__PURE__ */ React2.createElement(WalletIcon, { src: wallet.icon || void 0, name: wallet.name, size: 38 }),
1632
1937
  /* @__PURE__ */ React2.createElement("span", { style: { flex: 1, fontSize: 14, fontWeight: 600, color: "var(--dc-text)", letterSpacing: "-0.01em" } }, wallet.name),
1633
- /* @__PURE__ */ React2.createElement(ChainBadges, { chainSupport: wallet.chainSupport }),
1938
+ /* @__PURE__ */ React2.createElement(ChainIconStack, { support: wallet.chainSupport, size: 16 }),
1634
1939
  /* @__PURE__ */ React2.createElement(
1635
1940
  "svg",
1636
1941
  {
@@ -1757,17 +2062,19 @@ function WalletSelector({
1757
2062
  const cs = w.chainSupport;
1758
2063
  if (networks === "evm") return cs.includes("evm");
1759
2064
  if (networks === "solana") return cs.includes("solana");
2065
+ if (networks === "tron") return cs.includes("tron");
2066
+ if (networks === "bitcoin") return cs.includes("bitcoin");
1760
2067
  return true;
1761
2068
  });
1762
- const baseWallets = filter === "evm" ? networkWallets.filter((w) => w.chainSupport.includes("evm")) : filter === "solana" ? networkWallets.filter((w) => w.chainSupport.includes("solana")) : networkWallets;
2069
+ const baseWallets = filter === "evm" ? networkWallets.filter((w) => w.chainSupport.includes("evm")) : filter === "solana" ? networkWallets.filter((w) => w.chainSupport.includes("solana")) : filter === "tron" ? networkWallets.filter((w) => w.chainSupport.includes("tron")) : filter === "bitcoin" ? networkWallets.filter((w) => w.chainSupport.includes("bitcoin")) : networkWallets;
1763
2070
  const filtered = q ? baseWallets.filter((w) => w.name.toLowerCase().includes(q)) : baseWallets;
1764
2071
  function handleWalletClick(wallet) {
1765
2072
  const cs = wallet.chainSupport;
1766
- const isMulti = cs.includes("evm") && cs.includes("solana");
2073
+ const isMulti = cs.length >= 2;
1767
2074
  if (isMulti && networks === "all") {
1768
2075
  setPendingWallet(wallet);
1769
2076
  } else {
1770
- const preference = networks === "evm" ? "evm" : networks === "solana" ? "solana" : void 0;
2077
+ const preference = networks === "evm" ? "evm" : networks === "solana" ? "solana" : networks === "tron" ? "tron" : networks === "bitcoin" ? "bitcoin" : void 0;
1771
2078
  onConnect(wallet, preference);
1772
2079
  onClose();
1773
2080
  }
@@ -1902,28 +2209,44 @@ function WalletSelector({
1902
2209
  },
1903
2210
  /* @__PURE__ */ React2.createElement(WalletIcon, { src: pendingWallet.icon || void 0, name: pendingWallet.name, size: 36 }),
1904
2211
  /* @__PURE__ */ React2.createElement("div", null, /* @__PURE__ */ React2.createElement("div", { style: { fontSize: 14, fontWeight: 700, color: "var(--dc-text)" } }, pendingWallet.name), /* @__PURE__ */ React2.createElement("div", { style: { fontSize: 11, color: "var(--dc-text-muted)", marginTop: 2 } }, "Multi-chain wallet detected"))
1905
- ), /* @__PURE__ */ React2.createElement("div", { style: { padding: "0 12px 20px", display: "flex", flexDirection: "column", gap: 8 } }, /* @__PURE__ */ React2.createElement(
2212
+ ), /* @__PURE__ */ React2.createElement("div", { style: { padding: "0 12px 20px", display: "flex", flexDirection: "column", gap: 8 } }, pendingWallet.chainSupport.includes("evm") && /* @__PURE__ */ React2.createElement(
1906
2213
  ChainOption,
1907
2214
  {
1908
2215
  label: "EVM networks",
1909
2216
  description: "Connect your Ethereum-compatible address only",
1910
- badges: /* @__PURE__ */ React2.createElement("span", { style: { ...badgeBase, background: "var(--dc-badge-evm)", color: "var(--dc-badge-evm-text)" } }, "EVM"),
2217
+ badges: /* @__PURE__ */ React2.createElement(ChainIconStack, { support: ["evm"], size: 18 }),
1911
2218
  onClick: () => handleChainChoice("evm")
1912
2219
  }
1913
- ), /* @__PURE__ */ React2.createElement(
2220
+ ), pendingWallet.chainSupport.includes("solana") && /* @__PURE__ */ React2.createElement(
1914
2221
  ChainOption,
1915
2222
  {
1916
2223
  label: "Solana network",
1917
2224
  description: "Connect your Solana address only",
1918
- badges: /* @__PURE__ */ React2.createElement("span", { style: { ...badgeBase, background: "var(--dc-badge-sol)", color: "var(--dc-badge-sol-text)", border: "1px solid var(--dc-border)" } }, "SVM"),
2225
+ badges: /* @__PURE__ */ React2.createElement(ChainIconStack, { support: ["solana"], size: 18 }),
1919
2226
  onClick: () => handleChainChoice("solana")
1920
2227
  }
2228
+ ), pendingWallet.chainSupport.includes("tron") && /* @__PURE__ */ React2.createElement(
2229
+ ChainOption,
2230
+ {
2231
+ label: "Tron network",
2232
+ description: "Connect your Tron address only",
2233
+ badges: /* @__PURE__ */ React2.createElement(ChainIconStack, { support: ["tron"], size: 18 }),
2234
+ onClick: () => handleChainChoice("tron")
2235
+ }
2236
+ ), pendingWallet.chainSupport.includes("bitcoin") && /* @__PURE__ */ React2.createElement(
2237
+ ChainOption,
2238
+ {
2239
+ label: "Bitcoin network",
2240
+ description: "Connect your Bitcoin address only",
2241
+ badges: /* @__PURE__ */ React2.createElement(ChainIconStack, { support: ["bitcoin"], size: 18 }),
2242
+ onClick: () => handleChainChoice("bitcoin")
2243
+ }
1921
2244
  ), /* @__PURE__ */ React2.createElement(
1922
2245
  ChainOption,
1923
2246
  {
1924
- label: "Both networks",
1925
- description: "Connect EVM and Solana addresses together",
1926
- badges: /* @__PURE__ */ React2.createElement("div", { style: { display: "flex", gap: 4 } }, /* @__PURE__ */ React2.createElement("span", { style: { ...badgeBase, background: "var(--dc-badge-evm)", color: "var(--dc-badge-evm-text)" } }, "EVM"), /* @__PURE__ */ React2.createElement("span", { style: { ...badgeBase, background: "var(--dc-badge-sol)", color: "var(--dc-badge-sol-text)", border: "1px solid var(--dc-border)" } }, "SVM")),
2247
+ label: "All networks",
2248
+ description: "Connect all supported addresses together",
2249
+ badges: /* @__PURE__ */ React2.createElement(ChainIconStack, { support: pendingWallet.chainSupport, size: 18 }),
1927
2250
  onClick: () => handleChainChoice(void 0)
1928
2251
  }
1929
2252
  )))
@@ -1998,7 +2321,7 @@ function WalletSelector({
1998
2321
  e.currentTarget.style.borderColor = "var(--dc-border)";
1999
2322
  }
2000
2323
  }
2001
- )), networks === "all" && /* @__PURE__ */ React2.createElement("div", { style: { display: "flex", gap: 4, marginBottom: 10 } }, /* @__PURE__ */ React2.createElement(FilterTab, { label: "All", active: filter === "all", onClick: () => setFilter("all") }), /* @__PURE__ */ React2.createElement(FilterTab, { label: "EVM", active: filter === "evm", onClick: () => setFilter("evm") }), /* @__PURE__ */ React2.createElement(FilterTab, { label: "Solana", active: filter === "solana", onClick: () => setFilter("solana") }))), /* @__PURE__ */ React2.createElement("div", { style: { overflowY: "auto", flex: 1, padding: "0 12px 20px" } }, filtered.length > 0 ? /* @__PURE__ */ React2.createElement("div", { style: { display: "flex", flexDirection: "column", gap: 2 } }, filtered.map((w) => /* @__PURE__ */ React2.createElement(WalletRow, { key: w.id, wallet: w, onClick: () => handleWalletClick(w) }))) : /* @__PURE__ */ React2.createElement("div", { style: { textAlign: "center", padding: "32px 16px", color: "var(--dc-text-muted)", fontSize: 13 } }, q ? `No wallets matching "${q}"` : "No wallets detected")), /* @__PURE__ */ React2.createElement("div", { style: { padding: "10px 20px 14px", borderTop: "1px solid var(--dc-border)", textAlign: "center", fontSize: 11, color: "var(--dc-text-muted)" } }, "Don't see your wallet? Make sure it's installed and unlocked"))
2324
+ )), networks === "all" && /* @__PURE__ */ React2.createElement("div", { style: { display: "flex", gap: 4, marginBottom: 10 } }, /* @__PURE__ */ React2.createElement(FilterTab, { label: "All", active: filter === "all", onClick: () => setFilter("all") }), /* @__PURE__ */ React2.createElement(FilterTab, { label: "EVM", active: filter === "evm", onClick: () => setFilter("evm") }), /* @__PURE__ */ React2.createElement(FilterTab, { label: "Solana", active: filter === "solana", onClick: () => setFilter("solana") }), provider.tronWallets && provider.tronWallets.length > 0 && /* @__PURE__ */ React2.createElement(FilterTab, { label: "Tron", active: filter === "tron", onClick: () => setFilter("tron") }), provider.bitcoinWallets && provider.bitcoinWallets.length > 0 && /* @__PURE__ */ React2.createElement(FilterTab, { label: "Bitcoin", active: filter === "bitcoin", onClick: () => setFilter("bitcoin") }))), /* @__PURE__ */ React2.createElement("div", { style: { overflowY: "auto", flex: 1, padding: "0 12px 20px" } }, filtered.length > 0 ? /* @__PURE__ */ React2.createElement("div", { style: { display: "flex", flexDirection: "column", gap: 2 } }, filtered.map((w) => /* @__PURE__ */ React2.createElement(WalletRow, { key: w.id, wallet: w, onClick: () => handleWalletClick(w) }))) : /* @__PURE__ */ React2.createElement("div", { style: { textAlign: "center", padding: "32px 16px", color: "var(--dc-text-muted)", fontSize: 13 } }, q ? `No wallets matching "${q}"` : "No wallets detected")), /* @__PURE__ */ React2.createElement("div", { style: { padding: "10px 20px 14px", borderTop: "1px solid var(--dc-border)", textAlign: "center", fontSize: 11, color: "var(--dc-text-muted)" } }, "Don't see your wallet? Make sure it's installed and unlocked"))
2002
2325
  )
2003
2326
  )
2004
2327
  );