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.cjs CHANGED
@@ -80,8 +80,12 @@ function createRegistry(emitter) {
80
80
  };
81
81
  if (incoming.chain === "evm") {
82
82
  account.evmProvider = incoming.provider;
83
- } else {
83
+ } else if (incoming.chain === "solana") {
84
84
  account.solanaProvider = incoming.provider;
85
+ } else if (incoming.chain === "tron") {
86
+ account.tronProvider = incoming.provider;
87
+ } else if (incoming.chain === "bitcoin") {
88
+ account.bitcoinProvider = incoming.provider;
85
89
  }
86
90
  return account;
87
91
  }
@@ -92,12 +96,10 @@ function createRegistry(emitter) {
92
96
  incoming.chain
93
97
  ].sort();
94
98
  }
95
- if (incoming.chain === "evm") {
96
- existing.evmProvider = incoming.provider;
97
- }
98
- if (incoming.chain === "solana") {
99
- existing.solanaProvider = incoming.provider;
100
- }
99
+ if (incoming.chain === "evm") existing.evmProvider = incoming.provider;
100
+ if (incoming.chain === "solana") existing.solanaProvider = incoming.provider;
101
+ if (incoming.chain === "tron") existing.tronProvider = incoming.provider;
102
+ if (incoming.chain === "bitcoin") existing.bitcoinProvider = incoming.provider;
101
103
  if (!existing.icon && incoming.icon) existing.icon = incoming.icon;
102
104
  }
103
105
  function registerOrMerge(incoming) {
@@ -144,9 +146,9 @@ function createRegistry(emitter) {
144
146
  all: () => [...wallets],
145
147
  evm: () => wallets.filter((w) => w.chainSupport.includes("evm")),
146
148
  solana: () => wallets.filter((w) => w.chainSupport.includes("solana")),
147
- multiChain: () => wallets.filter(
148
- (w) => w.chainSupport.includes("evm") && w.chainSupport.includes("solana")
149
- ),
149
+ tron: () => wallets.filter((w) => w.chainSupport.includes("tron")),
150
+ bitcoin: () => wallets.filter((w) => w.chainSupport.includes("bitcoin")),
151
+ multiChain: () => wallets.filter((w) => w.chainSupport.length >= 2),
150
152
  byId: (id) => wallets.find((w) => w.id === id)
151
153
  }
152
154
  };
@@ -729,11 +731,37 @@ var BUILT_IN_CHAINS = [
729
731
  name: "Solana Devnet",
730
732
  nativeCurrency: SOL,
731
733
  blockExplorerUrl: "https://solscan.io/?cluster=devnet"
734
+ },
735
+ // ── Tron ─────────────────────────────────────────────────────────────────────
736
+ {
737
+ id: "tron:mainnet",
738
+ type: "tron",
739
+ name: "Tron",
740
+ nativeCurrency: { name: "Tronix", symbol: "TRX", decimals: 6 },
741
+ blockExplorerUrl: "https://tronscan.org"
742
+ },
743
+ {
744
+ id: "tron:shasta",
745
+ type: "tron",
746
+ name: "Tron Shasta Testnet",
747
+ nativeCurrency: { name: "Tronix", symbol: "TRX", decimals: 6 },
748
+ blockExplorerUrl: "https://shasta.tronscan.org",
749
+ isCustom: true
750
+ },
751
+ // ── Bitcoin ───────────────────────────────────────────────────────────────────
752
+ {
753
+ id: "bip122:mainnet",
754
+ type: "bitcoin",
755
+ name: "Bitcoin",
756
+ nativeCurrency: { name: "Bitcoin", symbol: "BTC", decimals: 8 },
757
+ blockExplorerUrl: "https://blockstream.info"
732
758
  }
733
759
  ];
734
760
  function getChainType(caip2Id) {
735
761
  if (caip2Id.startsWith("eip155:")) return "evm";
736
762
  if (caip2Id.startsWith("solana:")) return "solana";
763
+ if (caip2Id.startsWith("tron:")) return "tron";
764
+ if (caip2Id.startsWith("bip122:")) return "bitcoin";
737
765
  throw new Error(`Cannot determine chain type from: ${caip2Id}`);
738
766
  }
739
767
  function toCAIP10(chainId, address) {
@@ -749,6 +777,14 @@ var SOLANA_METHODS = /* @__PURE__ */ new Set([
749
777
  "wallet_signMessage"
750
778
  // wallet_signTypedData is EVM-only — never included here
751
779
  ]);
780
+ var TRON_METHODS = /* @__PURE__ */ new Set([
781
+ "wallet_sendTransaction",
782
+ "wallet_signMessage"
783
+ ]);
784
+ var BITCOIN_METHODS = /* @__PURE__ */ new Set([
785
+ "wallet_sendTransaction",
786
+ "wallet_signMessage"
787
+ ]);
752
788
  var CHAINS = {
753
789
  // Tier-1
754
790
  ETHEREUM: "eip155:1",
@@ -814,13 +850,17 @@ var CHAINS = {
814
850
  LOCALHOST: "eip155:31337",
815
851
  // Solana
816
852
  SOLANA: "solana:mainnet",
817
- SOLANA_DEVNET: "solana:devnet"
853
+ SOLANA_DEVNET: "solana:devnet",
854
+ // Tron
855
+ TRON: "tron:mainnet",
856
+ // Bitcoin
857
+ BITCOIN: "bip122:mainnet"
818
858
  };
819
859
  function validateCustomChain(chain) {
820
860
  if (!chain || typeof chain !== "object") return false;
821
861
  const c = chain;
822
862
  if (typeof c.id !== "string" || !c.id) return false;
823
- if (c.type !== "evm" && c.type !== "solana") return false;
863
+ if (c.type !== "evm" && c.type !== "solana" && c.type !== "tron" && c.type !== "bitcoin") return false;
824
864
  if (typeof c.name !== "string" || !c.name) return false;
825
865
  if (!c.nativeCurrency || typeof c.nativeCurrency !== "object") return false;
826
866
  if (c.type === "evm" && (typeof c.chainId !== "number" || !c.id.startsWith("eip155:")))
@@ -1039,7 +1079,12 @@ async function walletStandardRequest(wallet, method, payload, account) {
1039
1079
  );
1040
1080
  }
1041
1081
  }
1082
+ function isSolanaAccount(a) {
1083
+ return !a.chains?.length || a.chains.some((c) => c.startsWith("solana:"));
1084
+ }
1042
1085
  async function getSolanaAddress(wallet) {
1086
+ const pre = wallet.accounts.find(isSolanaAccount);
1087
+ if (pre) return import_base.base58.encode(pre.publicKey);
1043
1088
  const connectFeature = wallet.features["standard:connect"];
1044
1089
  if (!connectFeature) {
1045
1090
  throw new DecaneError(
@@ -1048,13 +1093,81 @@ async function getSolanaAddress(wallet) {
1048
1093
  );
1049
1094
  }
1050
1095
  const { accounts } = await connectFeature.connect();
1051
- if (!accounts?.[0]) {
1096
+ const solanaAccount = accounts.find(isSolanaAccount);
1097
+ if (!solanaAccount) {
1052
1098
  throw new DecaneError(
1053
1099
  4001 /* USER_REJECTED */,
1054
1100
  "No Solana accounts returned"
1055
1101
  );
1056
1102
  }
1057
- return import_base.base58.encode(accounts[0].publicKey);
1103
+ return import_base.base58.encode(solanaAccount.publicKey);
1104
+ }
1105
+
1106
+ // src/tron/adapter.ts
1107
+ async function getTronAddress(provider) {
1108
+ try {
1109
+ const result = await provider.request({ method: "tron_requestAccounts" });
1110
+ const accounts = result;
1111
+ if (accounts?.[0]) return accounts[0];
1112
+ } catch {
1113
+ }
1114
+ const result2 = await provider.request({ method: "tron_accounts" }).catch(() => null);
1115
+ const accounts2 = result2;
1116
+ if (accounts2?.[0]) return accounts2[0];
1117
+ throw new DecaneError(4001 /* USER_REJECTED */, "No Tron accounts returned");
1118
+ }
1119
+ async function tronRequest(provider, method, payload, account) {
1120
+ switch (method) {
1121
+ case "wallet_signMessage":
1122
+ return provider.request({
1123
+ method: "tron_signMessage",
1124
+ params: { message: payload }
1125
+ });
1126
+ case "wallet_sendTransaction":
1127
+ return provider.request({
1128
+ method: "tron_sendTransaction",
1129
+ params: { ...payload, from: account }
1130
+ });
1131
+ default:
1132
+ throw new DecaneError(
1133
+ 5030 /* METHOD_NOT_SUPPORTED */,
1134
+ `Tron adapter: unsupported method ${method}`
1135
+ );
1136
+ }
1137
+ }
1138
+
1139
+ // src/bitcoin/adapter.ts
1140
+ async function getBitcoinAddress(provider) {
1141
+ const result = await provider.requestAccounts();
1142
+ if (!result || result.length === 0) {
1143
+ throw new DecaneError(4001 /* USER_REJECTED */, "No Bitcoin accounts returned");
1144
+ }
1145
+ const first = result[0];
1146
+ return typeof first === "string" ? first : first.address;
1147
+ }
1148
+ async function bitcoinRequest(provider, method, payload, account) {
1149
+ switch (method) {
1150
+ case "wallet_signMessage":
1151
+ return provider.signMessage(payload);
1152
+ case "wallet_sendTransaction": {
1153
+ const { to, value } = payload;
1154
+ if (provider.sendBitcoin) {
1155
+ return provider.sendBitcoin(to, value);
1156
+ }
1157
+ if (provider.send) {
1158
+ return provider.send({ to, value, from: account });
1159
+ }
1160
+ throw new DecaneError(
1161
+ 5030 /* METHOD_NOT_SUPPORTED */,
1162
+ "Bitcoin wallet does not support sendBitcoin"
1163
+ );
1164
+ }
1165
+ default:
1166
+ throw new DecaneError(
1167
+ 5030 /* METHOD_NOT_SUPPORTED */,
1168
+ `Bitcoin adapter: unsupported method ${method}`
1169
+ );
1170
+ }
1058
1171
  }
1059
1172
 
1060
1173
  // src/core/router.ts
@@ -1105,20 +1218,23 @@ function createRouter(opts) {
1105
1218
  const chainType = getChainType(chainId);
1106
1219
  if (chainType === "evm" && !connectedWallet.evmProvider) continue;
1107
1220
  if (chainType === "solana" && !connectedWallet.solanaProvider) continue;
1221
+ if (chainType === "tron" && !connectedWallet.tronProvider) continue;
1222
+ if (chainType === "bitcoin" && !connectedWallet.bitcoinProvider) continue;
1108
1223
  let address;
1109
1224
  if (chainType === "evm") {
1110
1225
  address = await getEvmAddress(connectedWallet.evmProvider);
1111
1226
  if (chain.isCustom) {
1112
- await addEthereumChain(
1113
- connectedWallet.evmProvider,
1114
- chain
1115
- ).catch(() => {
1227
+ await addEthereumChain(connectedWallet.evmProvider, chain).catch(() => {
1116
1228
  });
1117
1229
  }
1118
- } else {
1230
+ } else if (chainType === "solana") {
1119
1231
  address = await getSolanaAddress(connectedWallet.solanaProvider);
1232
+ } else if (chainType === "tron") {
1233
+ address = await getTronAddress(connectedWallet.tronProvider);
1234
+ } else {
1235
+ address = await getBitcoinAddress(connectedWallet.bitcoinProvider);
1120
1236
  }
1121
- const methodSet = chainType === "evm" ? EVM_METHODS : SOLANA_METHODS;
1237
+ const methodSet = chainType === "evm" ? EVM_METHODS : chainType === "solana" ? SOLANA_METHODS : chainType === "tron" ? TRON_METHODS : BITCOIN_METHODS;
1122
1238
  const grantedMethods = (scope?.methods ?? []).filter(
1123
1239
  (m) => methodSet.has(m)
1124
1240
  );
@@ -1197,19 +1313,13 @@ function createRouter(opts) {
1197
1313
  );
1198
1314
  }
1199
1315
  if (chainType === "evm") {
1200
- return eip1193Request(
1201
- wallet.evmProvider,
1202
- method,
1203
- payload,
1204
- account
1205
- );
1316
+ return eip1193Request(wallet.evmProvider, method, payload, account);
1317
+ } else if (chainType === "solana") {
1318
+ return walletStandardRequest(wallet.solanaProvider, method, payload, account);
1319
+ } else if (chainType === "tron") {
1320
+ return tronRequest(wallet.tronProvider, method, payload, account);
1206
1321
  } else {
1207
- return walletStandardRequest(
1208
- wallet.solanaProvider,
1209
- method,
1210
- payload,
1211
- account
1212
- );
1322
+ return bitcoinRequest(wallet.bitcoinProvider, method, payload, account);
1213
1323
  }
1214
1324
  }
1215
1325
  return { request };
@@ -1264,6 +1374,12 @@ function createProvider(opts) {
1264
1374
  get multiChainWallets() {
1265
1375
  return registry.get.multiChain();
1266
1376
  },
1377
+ get tronWallets() {
1378
+ return registry.get.tron();
1379
+ },
1380
+ get bitcoinWallets() {
1381
+ return registry.get.bitcoin();
1382
+ },
1267
1383
  // ── Connection ──────────────────────────────────────────────────────────
1268
1384
  async connect(wallet, preferredChain) {
1269
1385
  if (session.get()) {
@@ -1272,13 +1388,19 @@ function createProvider(opts) {
1272
1388
  }
1273
1389
  _connectedWallet = wallet;
1274
1390
  const support = wallet.chainSupport;
1275
- if (support.includes("evm") && preferredChain !== "solana") {
1391
+ const hasEvm = support.includes("evm") && preferredChain !== "solana" && preferredChain !== "tron" && preferredChain !== "bitcoin";
1392
+ const hasSol = support.includes("solana") && preferredChain !== "evm" && preferredChain !== "tron" && preferredChain !== "bitcoin";
1393
+ const hasTron = support.includes("tron") && preferredChain !== "evm" && preferredChain !== "solana" && preferredChain !== "bitcoin";
1394
+ const hasBitcoin = support.includes("bitcoin") && preferredChain !== "evm" && preferredChain !== "solana" && preferredChain !== "tron";
1395
+ if (hasEvm) {
1276
1396
  _activeChain = config.defaultChain?.startsWith("eip155:") ? config.defaultChain : "eip155:1";
1277
- } else {
1397
+ } else if (hasSol) {
1278
1398
  _activeChain = "solana:mainnet";
1399
+ } else if (hasTron) {
1400
+ _activeChain = "tron:mainnet";
1401
+ } else if (hasBitcoin) {
1402
+ _activeChain = "bip122:mainnet";
1279
1403
  }
1280
- const hasEvm = support.includes("evm") && preferredChain !== "solana";
1281
- const hasSol = support.includes("solana") && preferredChain !== "evm";
1282
1404
  const required = {};
1283
1405
  const optional = {};
1284
1406
  if (hasEvm) {
@@ -1302,6 +1424,34 @@ function createProvider(opts) {
1302
1424
  _activeChain = solChain;
1303
1425
  }
1304
1426
  }
1427
+ if (hasTron) {
1428
+ const tronChain = "tron:mainnet";
1429
+ const scope = {
1430
+ methods: ["wallet_sendTransaction", "wallet_signMessage"],
1431
+ accounts: [],
1432
+ events: []
1433
+ };
1434
+ if (hasEvm || hasSol) {
1435
+ optional[tronChain] = scope;
1436
+ } else {
1437
+ required[tronChain] = scope;
1438
+ _activeChain = tronChain;
1439
+ }
1440
+ }
1441
+ if (hasBitcoin) {
1442
+ const btcChain = "bip122:mainnet";
1443
+ const scope = {
1444
+ methods: ["wallet_sendTransaction", "wallet_signMessage"],
1445
+ accounts: [],
1446
+ events: []
1447
+ };
1448
+ if (hasEvm || hasSol || hasTron) {
1449
+ optional[btcChain] = scope;
1450
+ } else {
1451
+ required[btcChain] = scope;
1452
+ _activeChain = btcChain;
1453
+ }
1454
+ }
1305
1455
  await router.request({
1306
1456
  method: "wallet_requestPermissions",
1307
1457
  params: [{ requiredScopes: required, optionalScopes: optional }, wallet.id]
@@ -1369,6 +1519,58 @@ function createProvider(opts) {
1369
1519
  return provider;
1370
1520
  }
1371
1521
 
1522
+ // src/evm/bitcoinSnap.ts
1523
+ var BITCOIN_SNAP_IDS = [
1524
+ "npm:@metamask/bitcoin-snap",
1525
+ "npm:@consensys/btc-snap"
1526
+ ];
1527
+ async function detectBitcoinSnap(provider) {
1528
+ try {
1529
+ const snaps = await provider.request({ method: "wallet_getSnaps" });
1530
+ if (!snaps) return null;
1531
+ for (const id of BITCOIN_SNAP_IDS) {
1532
+ const snap = snaps[id];
1533
+ if (snap && snap.blocked !== true) return id;
1534
+ }
1535
+ return null;
1536
+ } catch {
1537
+ return null;
1538
+ }
1539
+ }
1540
+ function makeBitcoinSnapProvider(snapId, evmProvider) {
1541
+ function invoke(method, params) {
1542
+ return evmProvider.request({
1543
+ method: "wallet_invokeSnap",
1544
+ params: [{ snapId, request: { method, params } }]
1545
+ });
1546
+ }
1547
+ return {
1548
+ async requestAccounts() {
1549
+ const result = await invoke("btc_getAddress").catch(() => invoke("btc_getPublicKey"));
1550
+ if (typeof result === "string") return [result];
1551
+ if (Array.isArray(result)) return result;
1552
+ return [];
1553
+ },
1554
+ async signMessage(message) {
1555
+ return invoke("btc_signMessage", [message]);
1556
+ },
1557
+ async sendBitcoin(to, value) {
1558
+ return invoke("btc_sendBitcoin", [{ to, satoshis: value }]);
1559
+ }
1560
+ };
1561
+ }
1562
+ async function tryRegisterBitcoinSnap(registry, name, icon, rdns, evmProvider) {
1563
+ const snapId = await detectBitcoinSnap(evmProvider);
1564
+ if (!snapId) return;
1565
+ registry.registerOrMerge({
1566
+ chain: "bitcoin",
1567
+ name,
1568
+ icon,
1569
+ rdns,
1570
+ provider: makeBitcoinSnapProvider(snapId, evmProvider)
1571
+ });
1572
+ }
1573
+
1372
1574
  // src/evm/discovery.ts
1373
1575
  function startEvmDiscovery(registry) {
1374
1576
  if (typeof window === "undefined") return;
@@ -1388,6 +1590,14 @@ function startEvmDiscovery(registry) {
1388
1590
  uuid: info.uuid,
1389
1591
  provider
1390
1592
  });
1593
+ tryRegisterBitcoinSnap(
1594
+ registry,
1595
+ info.name,
1596
+ info.icon,
1597
+ info.rdns,
1598
+ provider
1599
+ ).catch(() => {
1600
+ });
1391
1601
  }
1392
1602
  );
1393
1603
  window.dispatchEvent(new CustomEvent("eip6963:requestProvider"));
@@ -1428,6 +1638,53 @@ function startSolanaDiscovery(registry) {
1428
1638
  );
1429
1639
  }
1430
1640
 
1641
+ // src/tron/discovery.ts
1642
+ var TRONLINK_RDNS = "link.tron.tronlink";
1643
+ var TRONLINK_ICON = "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAzMiAzMiI+PGNpcmNsZSBjeD0iMTYiIGN5PSIxNiIgcj0iMTYiIGZpbGw9IiNGRjAwMTMiLz48cG9seWdvbiBwb2ludHM9IjEyLDkgMjMsMTYgMTIsMjMiIGZpbGw9IndoaXRlIi8+PC9zdmc+";
1644
+ function startTronDiscovery(registry) {
1645
+ let registered = false;
1646
+ function tryRegister() {
1647
+ if (registered || !window.tronLink) return;
1648
+ registered = true;
1649
+ registry.registerOrMerge({
1650
+ chain: "tron",
1651
+ name: "TronLink",
1652
+ icon: TRONLINK_ICON,
1653
+ rdns: TRONLINK_RDNS,
1654
+ provider: window.tronLink
1655
+ });
1656
+ }
1657
+ tryRegister();
1658
+ window.addEventListener("tronLink#initialized", tryRegister, { once: true });
1659
+ const start = Date.now();
1660
+ const poll = setInterval(() => {
1661
+ tryRegister();
1662
+ if (registered || Date.now() - start > 3e3) clearInterval(poll);
1663
+ }, 200);
1664
+ }
1665
+
1666
+ // src/bitcoin/discovery.ts
1667
+ var BTC_ICON = "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAzMiAzMiI+PGNpcmNsZSBjeD0iMTYiIGN5PSIxNiIgcj0iMTYiIGZpbGw9IiNGNzkzMUEiLz48dGV4dCB4PSIxNi41IiB5PSIyMiIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1zaXplPSIxNiIgZm9udC13ZWlnaHQ9IjcwMCIgZmlsbD0id2hpdGUiIGZvbnQtZmFtaWx5PSJBcmlhbCxzeXN0ZW0tdWkiPuKmojwvdGV4dD48L3N2Zz4=";
1668
+ function startBitcoinDiscovery(registry) {
1669
+ setTimeout(() => {
1670
+ const candidates = [
1671
+ { name: "Unisat", rdns: "io.unisat.wallet", provider: window.unisat },
1672
+ // OKX shares rdns with its EVM provider — merges into the EVM entry automatically
1673
+ { name: "OKX Wallet", rdns: "com.okex.okxwallet", provider: window.okxwallet?.bitcoin }
1674
+ ];
1675
+ for (const { name, rdns, provider } of candidates) {
1676
+ if (!provider) continue;
1677
+ registry.registerOrMerge({
1678
+ chain: "bitcoin",
1679
+ name,
1680
+ icon: BTC_ICON,
1681
+ rdns,
1682
+ provider
1683
+ });
1684
+ }
1685
+ }, 150);
1686
+ }
1687
+
1431
1688
  // src/factory.ts
1432
1689
  function createDecane(config = {}) {
1433
1690
  const emitter = createEmitter();
@@ -1441,6 +1698,8 @@ function createDecane(config = {}) {
1441
1698
  const router = createRouter({ registry, session, chainStore });
1442
1699
  startEvmDiscovery(registry);
1443
1700
  startSolanaDiscovery(registry);
1701
+ startTronDiscovery(registry);
1702
+ startBitcoinDiscovery(registry);
1444
1703
  return createProvider({ config, registry, session, chainStore, router, emitter });
1445
1704
  }
1446
1705
 
@@ -1608,6 +1867,67 @@ function WalletIcon({ src, name, size = 36 }) {
1608
1867
  initial
1609
1868
  );
1610
1869
  }
1870
+ function EthCircle({ size }) {
1871
+ const s = size;
1872
+ return /* @__PURE__ */ import_react.default.createElement("svg", { width: s, height: s, viewBox: "0 0 16 16", fill: "none" }, /* @__PURE__ */ import_react.default.createElement("circle", { cx: "8", cy: "8", r: "8", fill: "#627EEA" }), /* @__PURE__ */ import_react.default.createElement("polygon", { points: "8,2.5 11.5,8 8,9.8 4.5,8", fill: "white", fillOpacity: "0.9" }), /* @__PURE__ */ import_react.default.createElement("polygon", { points: "8,9.8 11.5,8 8,13.5", fill: "white", fillOpacity: "0.6" }), /* @__PURE__ */ import_react.default.createElement("polygon", { points: "8,9.8 4.5,8 8,13.5", fill: "white", fillOpacity: "0.8" }), /* @__PURE__ */ import_react.default.createElement("polygon", { points: "8,2.5 8,9.8 4.5,8", fill: "white", fillOpacity: "0.6" }));
1873
+ }
1874
+ function SolCircle({ size }) {
1875
+ const s = size;
1876
+ return /* @__PURE__ */ import_react.default.createElement("svg", { width: s, height: s, viewBox: "0 0 16 16", fill: "none" }, /* @__PURE__ */ import_react.default.createElement("circle", { cx: "8", cy: "8", r: "8", fill: "#9945FF" }), /* @__PURE__ */ import_react.default.createElement("rect", { x: "4", y: "4.5", width: "7", height: "1.5", rx: "0.75", fill: "white", fillOpacity: "0.95" }), /* @__PURE__ */ import_react.default.createElement("rect", { x: "4", y: "7.25", width: "7", height: "1.5", rx: "0.75", fill: "white", fillOpacity: "0.95" }), /* @__PURE__ */ import_react.default.createElement("rect", { x: "4", y: "10", width: "5.5", height: "1.5", rx: "0.75", fill: "white", fillOpacity: "0.95" }));
1877
+ }
1878
+ function TronCircle({ size }) {
1879
+ const s = size;
1880
+ return /* @__PURE__ */ import_react.default.createElement("svg", { width: s, height: s, viewBox: "0 0 16 16", fill: "none" }, /* @__PURE__ */ import_react.default.createElement("circle", { cx: "8", cy: "8", r: "8", fill: "#FF0013" }), /* @__PURE__ */ import_react.default.createElement("polygon", { points: "6,4.5 12,8 6,11.5", fill: "white", fillOpacity: "0.95" }));
1881
+ }
1882
+ function BitcoinCircle({ size }) {
1883
+ const s = size;
1884
+ return /* @__PURE__ */ import_react.default.createElement("svg", { width: s, height: s, viewBox: "0 0 16 16", fill: "none" }, /* @__PURE__ */ import_react.default.createElement("circle", { cx: "8", cy: "8", r: "8", fill: "#F7931A" }), /* @__PURE__ */ import_react.default.createElement(
1885
+ "text",
1886
+ {
1887
+ x: "8.3",
1888
+ y: "11.5",
1889
+ textAnchor: "middle",
1890
+ fontSize: "8",
1891
+ fontWeight: "700",
1892
+ fill: "white",
1893
+ fontFamily: "Arial, system-ui"
1894
+ },
1895
+ "\u20BF"
1896
+ ));
1897
+ }
1898
+ function ChainCircleIcon({ chain, size }) {
1899
+ switch (chain) {
1900
+ case "evm":
1901
+ return /* @__PURE__ */ import_react.default.createElement(EthCircle, { size });
1902
+ case "solana":
1903
+ return /* @__PURE__ */ import_react.default.createElement(SolCircle, { size });
1904
+ case "tron":
1905
+ return /* @__PURE__ */ import_react.default.createElement(TronCircle, { size });
1906
+ case "bitcoin":
1907
+ return /* @__PURE__ */ import_react.default.createElement(BitcoinCircle, { size });
1908
+ }
1909
+ }
1910
+ var CHAIN_ORDER = ["evm", "solana", "tron", "bitcoin"];
1911
+ function ChainIconStack({ support, size = 16 }) {
1912
+ const ordered = CHAIN_ORDER.filter((c) => support.includes(c));
1913
+ if (ordered.length === 0) return null;
1914
+ const overlap = Math.round(size * 0.35);
1915
+ return /* @__PURE__ */ import_react.default.createElement("div", { style: { display: "flex", alignItems: "center", flexShrink: 0 } }, ordered.map((chain, i) => /* @__PURE__ */ import_react.default.createElement(
1916
+ "div",
1917
+ {
1918
+ key: chain,
1919
+ style: {
1920
+ marginLeft: i === 0 ? 0 : `-${overlap}px`,
1921
+ zIndex: ordered.length - i,
1922
+ position: "relative",
1923
+ borderRadius: "50%",
1924
+ lineHeight: 0,
1925
+ boxShadow: i > 0 ? `0 0 0 1.5px var(--dc-bg, #fff)` : void 0
1926
+ }
1927
+ },
1928
+ /* @__PURE__ */ import_react.default.createElement(ChainCircleIcon, { chain, size })
1929
+ )));
1930
+ }
1611
1931
 
1612
1932
  // src/ui/WalletSelector.tsx
1613
1933
  var FONT_URL = "https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@400;500;600;700;800&display=swap";
@@ -1634,21 +1954,6 @@ function injectFont() {
1634
1954
  link.href = FONT_URL;
1635
1955
  document.head.appendChild(link);
1636
1956
  }
1637
- var badgeBase = {
1638
- display: "inline-flex",
1639
- alignItems: "center",
1640
- padding: "3px 8px",
1641
- borderRadius: 20,
1642
- fontSize: 10,
1643
- fontWeight: 700,
1644
- letterSpacing: "0.04em",
1645
- textTransform: "uppercase"
1646
- };
1647
- function ChainBadges({ chainSupport }) {
1648
- const hasEvm = chainSupport.includes("evm");
1649
- const hasSol = chainSupport.includes("solana");
1650
- return /* @__PURE__ */ import_react2.default.createElement("div", { style: { display: "flex", gap: 4 } }, hasEvm && /* @__PURE__ */ import_react2.default.createElement("span", { style: { ...badgeBase, background: "var(--dc-badge-evm)", color: "var(--dc-badge-evm-text)" } }, "EVM"), hasSol && /* @__PURE__ */ import_react2.default.createElement("span", { style: { ...badgeBase, background: "var(--dc-badge-sol)", color: "var(--dc-badge-sol-text)", border: "1px solid var(--dc-border)" } }, "SVM"));
1651
- }
1652
1957
  function WalletRow({ wallet, onClick }) {
1653
1958
  const [hovered, setHovered] = (0, import_react2.useState)(false);
1654
1959
  const [focused, setFocused] = (0, import_react2.useState)(false);
@@ -1678,7 +1983,7 @@ function WalletRow({ wallet, onClick }) {
1678
1983
  },
1679
1984
  /* @__PURE__ */ import_react2.default.createElement(WalletIcon, { src: wallet.icon || void 0, name: wallet.name, size: 38 }),
1680
1985
  /* @__PURE__ */ import_react2.default.createElement("span", { style: { flex: 1, fontSize: 14, fontWeight: 600, color: "var(--dc-text)", letterSpacing: "-0.01em" } }, wallet.name),
1681
- /* @__PURE__ */ import_react2.default.createElement(ChainBadges, { chainSupport: wallet.chainSupport }),
1986
+ /* @__PURE__ */ import_react2.default.createElement(ChainIconStack, { support: wallet.chainSupport, size: 16 }),
1682
1987
  /* @__PURE__ */ import_react2.default.createElement(
1683
1988
  "svg",
1684
1989
  {
@@ -1805,17 +2110,19 @@ function WalletSelector({
1805
2110
  const cs = w.chainSupport;
1806
2111
  if (networks === "evm") return cs.includes("evm");
1807
2112
  if (networks === "solana") return cs.includes("solana");
2113
+ if (networks === "tron") return cs.includes("tron");
2114
+ if (networks === "bitcoin") return cs.includes("bitcoin");
1808
2115
  return true;
1809
2116
  });
1810
- const baseWallets = filter === "evm" ? networkWallets.filter((w) => w.chainSupport.includes("evm")) : filter === "solana" ? networkWallets.filter((w) => w.chainSupport.includes("solana")) : networkWallets;
2117
+ 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;
1811
2118
  const filtered = q ? baseWallets.filter((w) => w.name.toLowerCase().includes(q)) : baseWallets;
1812
2119
  function handleWalletClick(wallet) {
1813
2120
  const cs = wallet.chainSupport;
1814
- const isMulti = cs.includes("evm") && cs.includes("solana");
2121
+ const isMulti = cs.length >= 2;
1815
2122
  if (isMulti && networks === "all") {
1816
2123
  setPendingWallet(wallet);
1817
2124
  } else {
1818
- const preference = networks === "evm" ? "evm" : networks === "solana" ? "solana" : void 0;
2125
+ const preference = networks === "evm" ? "evm" : networks === "solana" ? "solana" : networks === "tron" ? "tron" : networks === "bitcoin" ? "bitcoin" : void 0;
1819
2126
  onConnect(wallet, preference);
1820
2127
  onClose();
1821
2128
  }
@@ -1950,28 +2257,44 @@ function WalletSelector({
1950
2257
  },
1951
2258
  /* @__PURE__ */ import_react2.default.createElement(WalletIcon, { src: pendingWallet.icon || void 0, name: pendingWallet.name, size: 36 }),
1952
2259
  /* @__PURE__ */ import_react2.default.createElement("div", null, /* @__PURE__ */ import_react2.default.createElement("div", { style: { fontSize: 14, fontWeight: 700, color: "var(--dc-text)" } }, pendingWallet.name), /* @__PURE__ */ import_react2.default.createElement("div", { style: { fontSize: 11, color: "var(--dc-text-muted)", marginTop: 2 } }, "Multi-chain wallet detected"))
1953
- ), /* @__PURE__ */ import_react2.default.createElement("div", { style: { padding: "0 12px 20px", display: "flex", flexDirection: "column", gap: 8 } }, /* @__PURE__ */ import_react2.default.createElement(
2260
+ ), /* @__PURE__ */ import_react2.default.createElement("div", { style: { padding: "0 12px 20px", display: "flex", flexDirection: "column", gap: 8 } }, pendingWallet.chainSupport.includes("evm") && /* @__PURE__ */ import_react2.default.createElement(
1954
2261
  ChainOption,
1955
2262
  {
1956
2263
  label: "EVM networks",
1957
2264
  description: "Connect your Ethereum-compatible address only",
1958
- badges: /* @__PURE__ */ import_react2.default.createElement("span", { style: { ...badgeBase, background: "var(--dc-badge-evm)", color: "var(--dc-badge-evm-text)" } }, "EVM"),
2265
+ badges: /* @__PURE__ */ import_react2.default.createElement(ChainIconStack, { support: ["evm"], size: 18 }),
1959
2266
  onClick: () => handleChainChoice("evm")
1960
2267
  }
1961
- ), /* @__PURE__ */ import_react2.default.createElement(
2268
+ ), pendingWallet.chainSupport.includes("solana") && /* @__PURE__ */ import_react2.default.createElement(
1962
2269
  ChainOption,
1963
2270
  {
1964
2271
  label: "Solana network",
1965
2272
  description: "Connect your Solana address only",
1966
- badges: /* @__PURE__ */ import_react2.default.createElement("span", { style: { ...badgeBase, background: "var(--dc-badge-sol)", color: "var(--dc-badge-sol-text)", border: "1px solid var(--dc-border)" } }, "SVM"),
2273
+ badges: /* @__PURE__ */ import_react2.default.createElement(ChainIconStack, { support: ["solana"], size: 18 }),
1967
2274
  onClick: () => handleChainChoice("solana")
1968
2275
  }
2276
+ ), pendingWallet.chainSupport.includes("tron") && /* @__PURE__ */ import_react2.default.createElement(
2277
+ ChainOption,
2278
+ {
2279
+ label: "Tron network",
2280
+ description: "Connect your Tron address only",
2281
+ badges: /* @__PURE__ */ import_react2.default.createElement(ChainIconStack, { support: ["tron"], size: 18 }),
2282
+ onClick: () => handleChainChoice("tron")
2283
+ }
2284
+ ), pendingWallet.chainSupport.includes("bitcoin") && /* @__PURE__ */ import_react2.default.createElement(
2285
+ ChainOption,
2286
+ {
2287
+ label: "Bitcoin network",
2288
+ description: "Connect your Bitcoin address only",
2289
+ badges: /* @__PURE__ */ import_react2.default.createElement(ChainIconStack, { support: ["bitcoin"], size: 18 }),
2290
+ onClick: () => handleChainChoice("bitcoin")
2291
+ }
1969
2292
  ), /* @__PURE__ */ import_react2.default.createElement(
1970
2293
  ChainOption,
1971
2294
  {
1972
- label: "Both networks",
1973
- description: "Connect EVM and Solana addresses together",
1974
- badges: /* @__PURE__ */ import_react2.default.createElement("div", { style: { display: "flex", gap: 4 } }, /* @__PURE__ */ import_react2.default.createElement("span", { style: { ...badgeBase, background: "var(--dc-badge-evm)", color: "var(--dc-badge-evm-text)" } }, "EVM"), /* @__PURE__ */ import_react2.default.createElement("span", { style: { ...badgeBase, background: "var(--dc-badge-sol)", color: "var(--dc-badge-sol-text)", border: "1px solid var(--dc-border)" } }, "SVM")),
2295
+ label: "All networks",
2296
+ description: "Connect all supported addresses together",
2297
+ badges: /* @__PURE__ */ import_react2.default.createElement(ChainIconStack, { support: pendingWallet.chainSupport, size: 18 }),
1975
2298
  onClick: () => handleChainChoice(void 0)
1976
2299
  }
1977
2300
  )))
@@ -2046,7 +2369,7 @@ function WalletSelector({
2046
2369
  e.currentTarget.style.borderColor = "var(--dc-border)";
2047
2370
  }
2048
2371
  }
2049
- )), networks === "all" && /* @__PURE__ */ import_react2.default.createElement("div", { style: { display: "flex", gap: 4, marginBottom: 10 } }, /* @__PURE__ */ import_react2.default.createElement(FilterTab, { label: "All", active: filter === "all", onClick: () => setFilter("all") }), /* @__PURE__ */ import_react2.default.createElement(FilterTab, { label: "EVM", active: filter === "evm", onClick: () => setFilter("evm") }), /* @__PURE__ */ import_react2.default.createElement(FilterTab, { label: "Solana", active: filter === "solana", onClick: () => setFilter("solana") }))), /* @__PURE__ */ import_react2.default.createElement("div", { style: { overflowY: "auto", flex: 1, padding: "0 12px 20px" } }, filtered.length > 0 ? /* @__PURE__ */ import_react2.default.createElement("div", { style: { display: "flex", flexDirection: "column", gap: 2 } }, filtered.map((w) => /* @__PURE__ */ import_react2.default.createElement(WalletRow, { key: w.id, wallet: w, onClick: () => handleWalletClick(w) }))) : /* @__PURE__ */ import_react2.default.createElement("div", { style: { textAlign: "center", padding: "32px 16px", color: "var(--dc-text-muted)", fontSize: 13 } }, q ? `No wallets matching "${q}"` : "No wallets detected")), /* @__PURE__ */ import_react2.default.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"))
2372
+ )), networks === "all" && /* @__PURE__ */ import_react2.default.createElement("div", { style: { display: "flex", gap: 4, marginBottom: 10 } }, /* @__PURE__ */ import_react2.default.createElement(FilterTab, { label: "All", active: filter === "all", onClick: () => setFilter("all") }), /* @__PURE__ */ import_react2.default.createElement(FilterTab, { label: "EVM", active: filter === "evm", onClick: () => setFilter("evm") }), /* @__PURE__ */ import_react2.default.createElement(FilterTab, { label: "Solana", active: filter === "solana", onClick: () => setFilter("solana") }), provider.tronWallets && provider.tronWallets.length > 0 && /* @__PURE__ */ import_react2.default.createElement(FilterTab, { label: "Tron", active: filter === "tron", onClick: () => setFilter("tron") }), provider.bitcoinWallets && provider.bitcoinWallets.length > 0 && /* @__PURE__ */ import_react2.default.createElement(FilterTab, { label: "Bitcoin", active: filter === "bitcoin", onClick: () => setFilter("bitcoin") }))), /* @__PURE__ */ import_react2.default.createElement("div", { style: { overflowY: "auto", flex: 1, padding: "0 12px 20px" } }, filtered.length > 0 ? /* @__PURE__ */ import_react2.default.createElement("div", { style: { display: "flex", flexDirection: "column", gap: 2 } }, filtered.map((w) => /* @__PURE__ */ import_react2.default.createElement(WalletRow, { key: w.id, wallet: w, onClick: () => handleWalletClick(w) }))) : /* @__PURE__ */ import_react2.default.createElement("div", { style: { textAlign: "center", padding: "32px 16px", color: "var(--dc-text-muted)", fontSize: 13 } }, q ? `No wallets matching "${q}"` : "No wallets detected")), /* @__PURE__ */ import_react2.default.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"))
2050
2373
  )
2051
2374
  )
2052
2375
  );