@lydianpay/lydianconnect 1.4.0 → 1.5.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/README.md CHANGED
@@ -41,7 +41,9 @@ lc.on((event) => {
41
41
  | `icon` | no | Icon shown in the connect prompt. |
42
42
  | `description` | no | Defaults to `appName`. |
43
43
 
44
- `connect({ walletId, chainId })` — `chainId` is the chain the user is paying on (a number like `137`, or a CAIP-2 id like `'eip155:137'`).
44
+ `connect({ walletId, chainId })` — `chainId` is the chain the user is paying on (a number like `137`, or a CAIP-2 id like `'eip155:137'`). The connection is pinned to it: requests target it, and EVM wallets are switched onto it.
45
+
46
+ `connect({ walletId, chains })` — multi-network discovery: propose every chain the app can serve and let the wallet approve a subset, reported on `connection.approvedChains` (WalletConnect sessions only; SDK/injected connections leave it `undefined`). Nothing is pinned and no chain switch is forced. Connect again with `chainId` once the user picks a chain — a WalletConnect session that approved it is reused without a second prompt.
45
47
 
46
48
  The WalletConnect client also advertises a return link derived from the page URL (origin + path, no query/hash); wallets may use it to bring the user back to the page after a deep-link approval.
47
49
 
package/dist/index.cjs CHANGED
@@ -156,6 +156,20 @@ function buildNamespace(chainId) {
156
156
  }
157
157
  };
158
158
  }
159
+ function buildNamespaces(chains) {
160
+ const byName = /* @__PURE__ */ new Map();
161
+ chains.forEach((chain) => {
162
+ const single = buildNamespace(chain);
163
+ const caip = single.value.chains?.[0];
164
+ const merged = byName.get(single.name);
165
+ if (!merged) {
166
+ byName.set(single.name, single);
167
+ } else if (caip && !merged.value.chains?.includes(caip)) {
168
+ merged.value.chains = [...merged.value.chains ?? [], caip];
169
+ }
170
+ });
171
+ return [...byName.values()];
172
+ }
159
173
 
160
174
  // node_modules/@lydianpay/lydianconnect-catalog/dist/index.js
161
175
  var ICON_BASE = "https://wallet-assets.lydian.com/wallets";
@@ -253,7 +267,7 @@ var WALLET_CATALOG = WALLETS.map((w) => ({
253
267
 
254
268
  // src/core/connector.ts
255
269
  function requestedChain(req) {
256
- return req.namespace.value.chains?.[0];
270
+ return req.pinned;
257
271
  }
258
272
  var BaseConnector = class {
259
273
  constructor() {
@@ -613,9 +627,8 @@ function rpcFor2(provider) {
613
627
  return ({ method, params }) => rpc(provider, method, params);
614
628
  }
615
629
  function evmChainIds(req) {
616
- const wanted = req.namespace.value.chains?.[0];
617
- const n = wanted ? Number(wanted.split(":")[1]) : NaN;
618
- return Number.isFinite(n) && n > 0 ? [n] : void 0;
630
+ const ids = (req.namespace.value.chains ?? []).map((chain) => Number(chain.split(":")[1])).filter((n) => Number.isFinite(n) && n > 0);
631
+ return ids.length > 0 ? ids : void 0;
619
632
  }
620
633
 
621
634
  // src/connectors/injected/connector.ts
@@ -1309,8 +1322,11 @@ var WalletConnectConnector = class extends BaseConnector {
1309
1322
  const client = await this.getClient();
1310
1323
  const reused = await this.tryReuse(client, req);
1311
1324
  if (reused) return reused;
1325
+ const proposed = [req.namespace, ...req.extraNamespaces ?? []];
1312
1326
  const { uri, approval } = await client.connect({
1313
- requiredNamespaces: { [req.namespace.name]: req.namespace.value }
1327
+ optionalNamespaces: Object.fromEntries(
1328
+ proposed.map((ns) => [ns.name, ns.value])
1329
+ )
1314
1330
  });
1315
1331
  if (!uri) throw new Error("WalletConnect did not return a pairing URI");
1316
1332
  const link = isMobile() ? this.links[req.walletId] : void 0;
@@ -1342,7 +1358,8 @@ var WalletConnectConnector = class extends BaseConnector {
1342
1358
  client,
1343
1359
  req.walletId,
1344
1360
  session,
1345
- req.namespace
1361
+ req.namespace,
1362
+ req.pinned
1346
1363
  );
1347
1364
  this.topics.set(req.walletId, session.topic);
1348
1365
  this.persist();
@@ -1409,21 +1426,32 @@ var WalletConnectConnector = class extends BaseConnector {
1409
1426
  return null;
1410
1427
  }
1411
1428
  const ns = session.namespaces[req.namespace.name];
1412
- const wanted = req.namespace.value.chains?.[0];
1413
- if (!ns || wanted && !ns.chains?.includes(wanted)) return null;
1414
- return this.toConnection(client, req.walletId, session, req.namespace);
1429
+ if (!ns) return null;
1430
+ if (req.pinned && !grantedChains(ns).includes(req.pinned)) return null;
1431
+ return this.toConnection(
1432
+ client,
1433
+ req.walletId,
1434
+ session,
1435
+ req.namespace,
1436
+ req.pinned
1437
+ );
1415
1438
  }
1416
- toConnection(client, walletId, session, namespace) {
1439
+ toConnection(client, walletId, session, namespace, wanted) {
1417
1440
  const ns = session.namespaces[namespace.name];
1418
1441
  const account = (ns?.accounts ?? []).map((a) => a.split(":")[2]).find((a) => !!a) ?? "";
1419
- const approved = ns?.chains?.length ? ns.chains : (ns?.accounts ?? []).map((a) => a.split(":").slice(0, 2).join(":"));
1420
- const wanted = namespace.value.chains?.[0];
1442
+ const approved = grantedChains(ns);
1421
1443
  const chainId = wanted && approved.includes(wanted) ? wanted : approved[0] ?? `${namespace.name}:1`;
1444
+ const approvedChains = [
1445
+ ...new Set(
1446
+ Object.values(session.namespaces).flatMap((n) => grantedChains(n))
1447
+ )
1448
+ ];
1422
1449
  const topic = session.topic;
1423
1450
  return {
1424
1451
  walletId,
1425
1452
  account,
1426
1453
  chainId,
1454
+ approvedChains,
1427
1455
  request: (args) => client.request({
1428
1456
  topic,
1429
1457
  chainId,
@@ -1484,6 +1512,11 @@ var WalletConnectConnector = class extends BaseConnector {
1484
1512
  }
1485
1513
  }
1486
1514
  };
1515
+ function grantedChains(ns) {
1516
+ if (!ns) return [];
1517
+ if (ns.chains?.length) return ns.chains;
1518
+ return (ns.accounts ?? []).map((a) => a.split(":").slice(0, 2).join(":"));
1519
+ }
1487
1520
  function firstNamespace(session) {
1488
1521
  const name = Object.keys(session.namespaces)[0];
1489
1522
  if (!name) return null;
@@ -1528,14 +1561,35 @@ var LydianConnect = class {
1528
1561
  return this.manager.init();
1529
1562
  }
1530
1563
  async connect(input) {
1531
- if (input.chainId === void 0 || input.chainId === null) {
1564
+ const chains = "chains" in input ? input.chains : void 0;
1565
+ const chainId = "chainId" in input ? input.chainId : void 0;
1566
+ if (chains !== void 0 && chainId !== void 0) {
1567
+ throw new Error(
1568
+ "connect() takes either chainId (pinned) or chains (discovery), not both"
1569
+ );
1570
+ }
1571
+ if (chains !== void 0) {
1572
+ const [primary, ...extra] = buildNamespaces(chains);
1573
+ if (!primary) {
1574
+ throw new Error("connect() discovery requires a non-empty chains list");
1575
+ }
1576
+ return this.manager.connect({
1577
+ walletId: input.walletId,
1578
+ namespace: primary,
1579
+ extraNamespaces: extra.length > 0 ? extra : void 0,
1580
+ signal: input.signal
1581
+ });
1582
+ }
1583
+ if (chainId === void 0 || chainId === null) {
1532
1584
  throw new Error(
1533
- 'connect() requires a chainId (a number like 137 or an "eip155:<id>" string)'
1585
+ 'connect() requires a chainId (a number like 137 or an "eip155:<id>" string) or a chains list'
1534
1586
  );
1535
1587
  }
1588
+ const namespace = buildNamespace(chainId);
1536
1589
  return this.manager.connect({
1537
1590
  walletId: input.walletId,
1538
- namespace: buildNamespace(input.chainId),
1591
+ namespace,
1592
+ pinned: namespace.value.chains?.[0],
1539
1593
  signal: input.signal
1540
1594
  });
1541
1595
  }