@lydianpay/lydianconnect 1.3.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 +5 -1
- package/dist/index.cjs +77 -16
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +24 -2
- package/dist/index.d.ts +24 -2
- package/dist/index.js +77 -16
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -46,6 +46,13 @@ interface Connection {
|
|
|
46
46
|
readonly account: string;
|
|
47
47
|
/** CAIP-2 chain id, e.g. "eip155:1". */
|
|
48
48
|
readonly chainId: string;
|
|
49
|
+
/**
|
|
50
|
+
* The CAIP-2 chains the wallet's session granted, across all namespaces.
|
|
51
|
+
* WalletConnect only — SDK and injected connections leave it undefined, since
|
|
52
|
+
* switching (`wallet_switchEthereumChain`) has no approval concept and any
|
|
53
|
+
* chain in the provider's family is reachable anyway.
|
|
54
|
+
*/
|
|
55
|
+
readonly approvedChains?: readonly string[];
|
|
49
56
|
request<T = unknown>(args: {
|
|
50
57
|
method: string;
|
|
51
58
|
params?: unknown;
|
|
@@ -67,13 +74,28 @@ interface LydianConnectConfig extends AppConfig {
|
|
|
67
74
|
/** WalletConnect Cloud project id — powers the fallback. */
|
|
68
75
|
walletConnectProjectId: string;
|
|
69
76
|
}
|
|
70
|
-
|
|
77
|
+
/**
|
|
78
|
+
* Input to {@link LydianConnect.connect} — one of two operations:
|
|
79
|
+
*
|
|
80
|
+
* - `chainId` **pins**: requests target that chain and EVM wallets switch onto it.
|
|
81
|
+
* - `chains` **discovers**: propose several chains, the wallet approves a subset
|
|
82
|
+
* (see {@link Connection.approvedChains}), nothing is pinned. Connect again
|
|
83
|
+
* with `chainId` once the user picks one — a WalletConnect session that
|
|
84
|
+
* approved it is reused without a second prompt.
|
|
85
|
+
*/
|
|
86
|
+
type ConnectInput = {
|
|
71
87
|
walletId: string;
|
|
72
88
|
/** Chain to connect on — a number (EVM, e.g. 137) or a CAIP-2 id ('eip155:137'). */
|
|
73
89
|
chainId: number | string;
|
|
74
90
|
/** Cancel a pending connection. */
|
|
75
91
|
signal?: AbortSignal;
|
|
76
|
-
}
|
|
92
|
+
} | {
|
|
93
|
+
walletId: string;
|
|
94
|
+
/** Chains to discover across — same formats as `chainId`; must be non-empty. */
|
|
95
|
+
chains: readonly (number | string)[];
|
|
96
|
+
/** Cancel a pending connection. */
|
|
97
|
+
signal?: AbortSignal;
|
|
98
|
+
};
|
|
77
99
|
type LydianConnectEvent =
|
|
78
100
|
/**
|
|
79
101
|
* WalletConnect only — the wc: URI.
|
package/dist/index.d.ts
CHANGED
|
@@ -46,6 +46,13 @@ interface Connection {
|
|
|
46
46
|
readonly account: string;
|
|
47
47
|
/** CAIP-2 chain id, e.g. "eip155:1". */
|
|
48
48
|
readonly chainId: string;
|
|
49
|
+
/**
|
|
50
|
+
* The CAIP-2 chains the wallet's session granted, across all namespaces.
|
|
51
|
+
* WalletConnect only — SDK and injected connections leave it undefined, since
|
|
52
|
+
* switching (`wallet_switchEthereumChain`) has no approval concept and any
|
|
53
|
+
* chain in the provider's family is reachable anyway.
|
|
54
|
+
*/
|
|
55
|
+
readonly approvedChains?: readonly string[];
|
|
49
56
|
request<T = unknown>(args: {
|
|
50
57
|
method: string;
|
|
51
58
|
params?: unknown;
|
|
@@ -67,13 +74,28 @@ interface LydianConnectConfig extends AppConfig {
|
|
|
67
74
|
/** WalletConnect Cloud project id — powers the fallback. */
|
|
68
75
|
walletConnectProjectId: string;
|
|
69
76
|
}
|
|
70
|
-
|
|
77
|
+
/**
|
|
78
|
+
* Input to {@link LydianConnect.connect} — one of two operations:
|
|
79
|
+
*
|
|
80
|
+
* - `chainId` **pins**: requests target that chain and EVM wallets switch onto it.
|
|
81
|
+
* - `chains` **discovers**: propose several chains, the wallet approves a subset
|
|
82
|
+
* (see {@link Connection.approvedChains}), nothing is pinned. Connect again
|
|
83
|
+
* with `chainId` once the user picks one — a WalletConnect session that
|
|
84
|
+
* approved it is reused without a second prompt.
|
|
85
|
+
*/
|
|
86
|
+
type ConnectInput = {
|
|
71
87
|
walletId: string;
|
|
72
88
|
/** Chain to connect on — a number (EVM, e.g. 137) or a CAIP-2 id ('eip155:137'). */
|
|
73
89
|
chainId: number | string;
|
|
74
90
|
/** Cancel a pending connection. */
|
|
75
91
|
signal?: AbortSignal;
|
|
76
|
-
}
|
|
92
|
+
} | {
|
|
93
|
+
walletId: string;
|
|
94
|
+
/** Chains to discover across — same formats as `chainId`; must be non-empty. */
|
|
95
|
+
chains: readonly (number | string)[];
|
|
96
|
+
/** Cancel a pending connection. */
|
|
97
|
+
signal?: AbortSignal;
|
|
98
|
+
};
|
|
77
99
|
type LydianConnectEvent =
|
|
78
100
|
/**
|
|
79
101
|
* WalletConnect only — the wc: URI.
|
package/dist/index.js
CHANGED
|
@@ -150,6 +150,20 @@ function buildNamespace(chainId) {
|
|
|
150
150
|
}
|
|
151
151
|
};
|
|
152
152
|
}
|
|
153
|
+
function buildNamespaces(chains) {
|
|
154
|
+
const byName = /* @__PURE__ */ new Map();
|
|
155
|
+
chains.forEach((chain) => {
|
|
156
|
+
const single = buildNamespace(chain);
|
|
157
|
+
const caip = single.value.chains?.[0];
|
|
158
|
+
const merged = byName.get(single.name);
|
|
159
|
+
if (!merged) {
|
|
160
|
+
byName.set(single.name, single);
|
|
161
|
+
} else if (caip && !merged.value.chains?.includes(caip)) {
|
|
162
|
+
merged.value.chains = [...merged.value.chains ?? [], caip];
|
|
163
|
+
}
|
|
164
|
+
});
|
|
165
|
+
return [...byName.values()];
|
|
166
|
+
}
|
|
153
167
|
|
|
154
168
|
// node_modules/@lydianpay/lydianconnect-catalog/dist/index.js
|
|
155
169
|
var ICON_BASE = "https://wallet-assets.lydian.com/wallets";
|
|
@@ -247,7 +261,7 @@ var WALLET_CATALOG = WALLETS.map((w) => ({
|
|
|
247
261
|
|
|
248
262
|
// src/core/connector.ts
|
|
249
263
|
function requestedChain(req) {
|
|
250
|
-
return req.
|
|
264
|
+
return req.pinned;
|
|
251
265
|
}
|
|
252
266
|
var BaseConnector = class {
|
|
253
267
|
constructor() {
|
|
@@ -298,6 +312,10 @@ var BaseConnector = class {
|
|
|
298
312
|
function deriveUrl() {
|
|
299
313
|
return typeof window !== "undefined" ? window.location.origin : "";
|
|
300
314
|
}
|
|
315
|
+
function deriveRedirectUrl() {
|
|
316
|
+
if (typeof window === "undefined") return "";
|
|
317
|
+
return window.location.origin + window.location.pathname;
|
|
318
|
+
}
|
|
301
319
|
|
|
302
320
|
// src/connectors/eip155/chain.ts
|
|
303
321
|
var CHAIN_SETTLE = { timeoutMs: 4e3, intervalMs: 100 };
|
|
@@ -603,9 +621,8 @@ function rpcFor2(provider) {
|
|
|
603
621
|
return ({ method, params }) => rpc(provider, method, params);
|
|
604
622
|
}
|
|
605
623
|
function evmChainIds(req) {
|
|
606
|
-
const
|
|
607
|
-
|
|
608
|
-
return Number.isFinite(n) && n > 0 ? [n] : void 0;
|
|
624
|
+
const ids = (req.namespace.value.chains ?? []).map((chain) => Number(chain.split(":")[1])).filter((n) => Number.isFinite(n) && n > 0);
|
|
625
|
+
return ids.length > 0 ? ids : void 0;
|
|
609
626
|
}
|
|
610
627
|
|
|
611
628
|
// src/connectors/injected/connector.ts
|
|
@@ -1258,13 +1275,16 @@ var WalletConnectConnector = class extends BaseConnector {
|
|
|
1258
1275
|
}
|
|
1259
1276
|
async getClient() {
|
|
1260
1277
|
if (this.client) return this.client;
|
|
1278
|
+
const redirectUrl = deriveRedirectUrl();
|
|
1261
1279
|
const client = await SignClient.init({
|
|
1262
1280
|
projectId: this.options.projectId,
|
|
1263
1281
|
metadata: {
|
|
1264
1282
|
name: this.app.appName,
|
|
1265
1283
|
description: this.app.description ?? this.app.appName,
|
|
1266
1284
|
url: deriveUrl(),
|
|
1267
|
-
icons: this.app.icon ? [this.app.icon] : []
|
|
1285
|
+
icons: this.app.icon ? [this.app.icon] : [],
|
|
1286
|
+
// Wallets may use this to return the user after deep-link approvals.
|
|
1287
|
+
...redirectUrl ? { redirect: { universal: redirectUrl } } : {}
|
|
1268
1288
|
},
|
|
1269
1289
|
relayUrl: this.options.relayUrl
|
|
1270
1290
|
});
|
|
@@ -1296,8 +1316,11 @@ var WalletConnectConnector = class extends BaseConnector {
|
|
|
1296
1316
|
const client = await this.getClient();
|
|
1297
1317
|
const reused = await this.tryReuse(client, req);
|
|
1298
1318
|
if (reused) return reused;
|
|
1319
|
+
const proposed = [req.namespace, ...req.extraNamespaces ?? []];
|
|
1299
1320
|
const { uri, approval } = await client.connect({
|
|
1300
|
-
|
|
1321
|
+
optionalNamespaces: Object.fromEntries(
|
|
1322
|
+
proposed.map((ns) => [ns.name, ns.value])
|
|
1323
|
+
)
|
|
1301
1324
|
});
|
|
1302
1325
|
if (!uri) throw new Error("WalletConnect did not return a pairing URI");
|
|
1303
1326
|
const link = isMobile() ? this.links[req.walletId] : void 0;
|
|
@@ -1329,7 +1352,8 @@ var WalletConnectConnector = class extends BaseConnector {
|
|
|
1329
1352
|
client,
|
|
1330
1353
|
req.walletId,
|
|
1331
1354
|
session,
|
|
1332
|
-
req.namespace
|
|
1355
|
+
req.namespace,
|
|
1356
|
+
req.pinned
|
|
1333
1357
|
);
|
|
1334
1358
|
this.topics.set(req.walletId, session.topic);
|
|
1335
1359
|
this.persist();
|
|
@@ -1396,21 +1420,32 @@ var WalletConnectConnector = class extends BaseConnector {
|
|
|
1396
1420
|
return null;
|
|
1397
1421
|
}
|
|
1398
1422
|
const ns = session.namespaces[req.namespace.name];
|
|
1399
|
-
|
|
1400
|
-
if (
|
|
1401
|
-
return this.toConnection(
|
|
1423
|
+
if (!ns) return null;
|
|
1424
|
+
if (req.pinned && !grantedChains(ns).includes(req.pinned)) return null;
|
|
1425
|
+
return this.toConnection(
|
|
1426
|
+
client,
|
|
1427
|
+
req.walletId,
|
|
1428
|
+
session,
|
|
1429
|
+
req.namespace,
|
|
1430
|
+
req.pinned
|
|
1431
|
+
);
|
|
1402
1432
|
}
|
|
1403
|
-
toConnection(client, walletId, session, namespace) {
|
|
1433
|
+
toConnection(client, walletId, session, namespace, wanted) {
|
|
1404
1434
|
const ns = session.namespaces[namespace.name];
|
|
1405
1435
|
const account = (ns?.accounts ?? []).map((a) => a.split(":")[2]).find((a) => !!a) ?? "";
|
|
1406
|
-
const approved =
|
|
1407
|
-
const wanted = namespace.value.chains?.[0];
|
|
1436
|
+
const approved = grantedChains(ns);
|
|
1408
1437
|
const chainId = wanted && approved.includes(wanted) ? wanted : approved[0] ?? `${namespace.name}:1`;
|
|
1438
|
+
const approvedChains = [
|
|
1439
|
+
...new Set(
|
|
1440
|
+
Object.values(session.namespaces).flatMap((n) => grantedChains(n))
|
|
1441
|
+
)
|
|
1442
|
+
];
|
|
1409
1443
|
const topic = session.topic;
|
|
1410
1444
|
return {
|
|
1411
1445
|
walletId,
|
|
1412
1446
|
account,
|
|
1413
1447
|
chainId,
|
|
1448
|
+
approvedChains,
|
|
1414
1449
|
request: (args) => client.request({
|
|
1415
1450
|
topic,
|
|
1416
1451
|
chainId,
|
|
@@ -1471,6 +1506,11 @@ var WalletConnectConnector = class extends BaseConnector {
|
|
|
1471
1506
|
}
|
|
1472
1507
|
}
|
|
1473
1508
|
};
|
|
1509
|
+
function grantedChains(ns) {
|
|
1510
|
+
if (!ns) return [];
|
|
1511
|
+
if (ns.chains?.length) return ns.chains;
|
|
1512
|
+
return (ns.accounts ?? []).map((a) => a.split(":").slice(0, 2).join(":"));
|
|
1513
|
+
}
|
|
1474
1514
|
function firstNamespace(session) {
|
|
1475
1515
|
const name = Object.keys(session.namespaces)[0];
|
|
1476
1516
|
if (!name) return null;
|
|
@@ -1515,14 +1555,35 @@ var LydianConnect = class {
|
|
|
1515
1555
|
return this.manager.init();
|
|
1516
1556
|
}
|
|
1517
1557
|
async connect(input) {
|
|
1518
|
-
|
|
1558
|
+
const chains = "chains" in input ? input.chains : void 0;
|
|
1559
|
+
const chainId = "chainId" in input ? input.chainId : void 0;
|
|
1560
|
+
if (chains !== void 0 && chainId !== void 0) {
|
|
1561
|
+
throw new Error(
|
|
1562
|
+
"connect() takes either chainId (pinned) or chains (discovery), not both"
|
|
1563
|
+
);
|
|
1564
|
+
}
|
|
1565
|
+
if (chains !== void 0) {
|
|
1566
|
+
const [primary, ...extra] = buildNamespaces(chains);
|
|
1567
|
+
if (!primary) {
|
|
1568
|
+
throw new Error("connect() discovery requires a non-empty chains list");
|
|
1569
|
+
}
|
|
1570
|
+
return this.manager.connect({
|
|
1571
|
+
walletId: input.walletId,
|
|
1572
|
+
namespace: primary,
|
|
1573
|
+
extraNamespaces: extra.length > 0 ? extra : void 0,
|
|
1574
|
+
signal: input.signal
|
|
1575
|
+
});
|
|
1576
|
+
}
|
|
1577
|
+
if (chainId === void 0 || chainId === null) {
|
|
1519
1578
|
throw new Error(
|
|
1520
|
-
'connect() requires a chainId (a number like 137 or an "eip155:<id>" string)'
|
|
1579
|
+
'connect() requires a chainId (a number like 137 or an "eip155:<id>" string) or a chains list'
|
|
1521
1580
|
);
|
|
1522
1581
|
}
|
|
1582
|
+
const namespace = buildNamespace(chainId);
|
|
1523
1583
|
return this.manager.connect({
|
|
1524
1584
|
walletId: input.walletId,
|
|
1525
|
-
namespace
|
|
1585
|
+
namespace,
|
|
1586
|
+
pinned: namespace.value.chains?.[0],
|
|
1526
1587
|
signal: input.signal
|
|
1527
1588
|
});
|
|
1528
1589
|
}
|