@lydianpay/lydianconnect 0.0.0-managed
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 +620 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +233 -0
- package/dist/index.d.ts +233 -0
- package/dist/index.js +609 -0
- package/dist/index.js.map +1 -0
- package/package.json +47 -0
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,620 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var SignClient = require('@walletconnect/sign-client');
|
|
4
|
+
var utils = require('@walletconnect/utils');
|
|
5
|
+
|
|
6
|
+
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
7
|
+
|
|
8
|
+
var SignClient__default = /*#__PURE__*/_interopDefault(SignClient);
|
|
9
|
+
|
|
10
|
+
// src/core/manager.ts
|
|
11
|
+
var LydianConnect = class {
|
|
12
|
+
constructor(config) {
|
|
13
|
+
this.byWallet = /* @__PURE__ */ new Map();
|
|
14
|
+
this.connections = /* @__PURE__ */ new Map();
|
|
15
|
+
this.handlers = /* @__PURE__ */ new Set();
|
|
16
|
+
this.unsubs = [];
|
|
17
|
+
this.started = false;
|
|
18
|
+
this.fallback = config.fallback;
|
|
19
|
+
this.all = [...config.connectors ?? [], config.fallback];
|
|
20
|
+
for (const connector of config.connectors ?? []) {
|
|
21
|
+
for (const id of connector.walletIds) this.byWallet.set(id, connector);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
/** Wire connector event forwarding, once. Safe to call repeatedly. */
|
|
25
|
+
async init() {
|
|
26
|
+
if (this.started) return;
|
|
27
|
+
this.started = true;
|
|
28
|
+
for (const connector of this.all) {
|
|
29
|
+
this.unsubs.push(connector.on((event) => this.handle(event)));
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
/** SDK connector if one claims this walletId, else the WC fallback. The host app is oblivious. */
|
|
33
|
+
resolve(walletId) {
|
|
34
|
+
return this.byWallet.get(walletId) ?? this.fallback;
|
|
35
|
+
}
|
|
36
|
+
async connect(input) {
|
|
37
|
+
if (!this.started) await this.init();
|
|
38
|
+
const connection = await this.resolve(input.walletId).connect(input);
|
|
39
|
+
this.connections.set(input.walletId, connection);
|
|
40
|
+
this.emit({ type: "connect", walletId: input.walletId, connection });
|
|
41
|
+
return connection;
|
|
42
|
+
}
|
|
43
|
+
/** Resume any live sessions across all connectors (e.g. after a page reload). */
|
|
44
|
+
async restore() {
|
|
45
|
+
if (!this.started) await this.init();
|
|
46
|
+
const restored = [];
|
|
47
|
+
for (const connector of this.all) {
|
|
48
|
+
const conns = await connector.restore().catch(() => []);
|
|
49
|
+
for (const conn of conns) {
|
|
50
|
+
this.connections.set(conn.walletId, conn);
|
|
51
|
+
restored.push(conn);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return restored;
|
|
55
|
+
}
|
|
56
|
+
get(walletId) {
|
|
57
|
+
return this.connections.get(walletId);
|
|
58
|
+
}
|
|
59
|
+
async disconnect(walletId) {
|
|
60
|
+
if (walletId) {
|
|
61
|
+
await this.connections.get(walletId)?.disconnect().catch(() => {
|
|
62
|
+
});
|
|
63
|
+
this.connections.delete(walletId);
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
await Promise.allSettled([...this.connections.values()].map((c) => c.disconnect()));
|
|
67
|
+
this.connections.clear();
|
|
68
|
+
}
|
|
69
|
+
/** Disconnect everything and clear all connector-held state. */
|
|
70
|
+
async reset() {
|
|
71
|
+
await this.disconnect();
|
|
72
|
+
await Promise.allSettled(this.all.map((c) => c.reset()));
|
|
73
|
+
}
|
|
74
|
+
on(handler) {
|
|
75
|
+
this.handlers.add(handler);
|
|
76
|
+
return () => this.handlers.delete(handler);
|
|
77
|
+
}
|
|
78
|
+
handle(event) {
|
|
79
|
+
if (event.type === "disconnect") this.connections.delete(event.walletId);
|
|
80
|
+
this.emit(event);
|
|
81
|
+
}
|
|
82
|
+
emit(event) {
|
|
83
|
+
for (const handler of this.handlers) handler(event);
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
// src/core/connector.ts
|
|
88
|
+
var BaseConnector = class {
|
|
89
|
+
constructor() {
|
|
90
|
+
this.walletIds = [];
|
|
91
|
+
this.handlers = /* @__PURE__ */ new Set();
|
|
92
|
+
}
|
|
93
|
+
async restore() {
|
|
94
|
+
return [];
|
|
95
|
+
}
|
|
96
|
+
async reset() {
|
|
97
|
+
}
|
|
98
|
+
on(handler) {
|
|
99
|
+
this.handlers.add(handler);
|
|
100
|
+
return () => this.handlers.delete(handler);
|
|
101
|
+
}
|
|
102
|
+
emit(event) {
|
|
103
|
+
for (const handler of this.handlers) handler(event);
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
// src/connectors/walletconnect/wallet-links.generated.ts
|
|
108
|
+
var GENERATED_WALLET_LINKS = {
|
|
109
|
+
metamask: { "scheme": "metamask://wc", "universal": "https://metamask.app.link/wc", "store": { "ios": "https://apps.apple.com/us/app/metamask/id1438144202", "android": "https://play.google.com/store/apps/details?id=io.metamask" } },
|
|
110
|
+
trust: { "scheme": "trust://wc", "universal": "https://link.trustwallet.com/wc", "store": { "ios": "https://apps.apple.com/app/apple-store/id1288339409", "android": "https://play.google.com/store/apps/details?id=com.wallet.crypto.trustapp" } },
|
|
111
|
+
rainbow: { "scheme": "rainbow://wc", "universal": "https://rnbwapp.com/wc", "store": { "ios": "https://apps.apple.com/app/apple-store/id1457119021?pt=119997837&ct=wc&mt=8", "android": "https://play.google.com/store/apps/details?id=me.rainbow&referrer=utm_source%3Dwc%26utm_medium%3Dconnector%26utm_campaign%3Dwc" } },
|
|
112
|
+
coinbase: { "store": { "ios": "https://apps.apple.com/us/app/base-formerly-coinbase-wallet/id1278383455" } },
|
|
113
|
+
zerion: { "scheme": "zerion://wc", "universal": "https://wallet.zerion.io/wc/wc", "store": { "ios": "https://apps.apple.com/app/id1456732565", "android": "https://play.google.com/store/apps/details?id=io.zerion.android&hl=en&gl=US" } },
|
|
114
|
+
tokenpocket: { "scheme": "tpoutside://wc", "store": { "ios": "https://apps.apple.com/us/app/tp-wallet/id6444625622?l=en", "android": "https://play.google.com/store/apps/details?id=vip.mytokenpocket" } },
|
|
115
|
+
blockchaincom: { "scheme": "blockchain-wallet://wc", "universal": "https://login.blockchain.com/app/wc", "store": { "ios": "https://apps.apple.com/us/app/blockchain-bitcoin-wallet/id493253309", "android": "https://play.google.com/store/apps/details?id=piuk.blockchain.android" } },
|
|
116
|
+
exodus: { "scheme": "exodus://wc", "universal": "https://exodus.com/m/wc", "store": { "ios": "https://apps.apple.com/us/app/exodus-crypto-bitcoin-wallet/id1414384820", "android": "https://play.google.com/store/apps/details?id=exodusmovement.exodus&hl=en&gl=US" } },
|
|
117
|
+
phantom: { "store": { "ios": "https://apps.apple.com/us/app/phantom-crypto-wallet/id1598432977", "android": "https://play.google.com/store/apps/details?id=app.phantom&hl=en" } },
|
|
118
|
+
okx: { "scheme": "okex://main/wc", "universal": "https://www.okx.com/download?appendQuery=true&deeplink=okx://web3/wallet/walletConnect/wc", "store": { "ios": "https://apps.apple.com/us/app/okx-buy-bitcoin-eth-crypto/id1327268470", "android": "https://play.google.com/store/apps/details?id=com.okinc.okex.gp" } },
|
|
119
|
+
cryptocom: { "scheme": "dfw://wc", "universal": "https://wallet.crypto.com/deeplink/wc", "store": { "ios": "https://apps.apple.com/US/app/id1512048310?mt=8", "android": "https://play.google.com/store/apps/details?id=com.defi.wallet" } },
|
|
120
|
+
argent: { "scheme": "argent://app/wc", "universal": "https://www.argent.xyz/app/wc", "store": { "ios": "https://apps.apple.com/us/app/argent-defi-in-a-tap/id1358741926", "android": "https://play.google.com/store/apps/details?id=im.argent.contractwalletclient&hl=en&gl=US&pli=1" } },
|
|
121
|
+
safepal: { "scheme": "safepalwallet://wc", "universal": "https://link.safepal.io/wc", "store": { "ios": "https://apps.apple.com/app/safepal-wallet/id1548297139", "android": "https://play.google.com/store/apps/details?id=io.safepal.wallet" } },
|
|
122
|
+
imtoken: { "scheme": "imtokenv2://wc", "store": { "ios": "https://apps.apple.com/us/app/imtoken2/id1384798940", "android": "https://play.google.com/store/apps/details?id=im.token.app" } },
|
|
123
|
+
ronin: { "scheme": "roninwallet://wc", "universal": "https://wallet.roninchain.com/wc", "store": { "ios": "https://apps.apple.com/us/app/ronin-wallet/id1592675001", "android": "https://play.google.com/store/apps/details?id=com.skymavis.genesis" } },
|
|
124
|
+
coin98: { "scheme": "coin98://wc", "universal": "https://coin98.com/wc", "store": { "ios": "https://apps.apple.com/vn/app/coin98-wallet/id1561969966", "android": "https://play.google.com/store/apps/details?id=coin98.crypto.finance.media&hl=vi&gl=US" } },
|
|
125
|
+
bitkeep: { "scheme": "bitkeep://wc", "universal": "https://bkapp.vip/wc", "store": { "ios": "https://web3.bitget.com/en/wallet-download?type=0", "android": "https://web3.bitget.com/en/wallet-download?type=0" } },
|
|
126
|
+
"1inch": { "scheme": "oneinch://open/nobodywilleveruseit/wc", "universal": "https://wallet.1inch.io/app/nobodywilleveruseit/wc", "store": { "ios": "https://apps.apple.com/us/app/1inch-defi-wallet/id1546049391", "android": "https://play.google.com/store/apps/details?id=io.oneinch.android" } },
|
|
127
|
+
ledgerlive: { "scheme": "ledgerlive://wc", "store": { "ios": "https://itunes.apple.com/app/id1361671700", "android": "https://play.google.com/store/apps/details?id=com.ledger.live" } },
|
|
128
|
+
atomic: { "scheme": "atomicwallet://wc", "store": { "ios": "https://apps.apple.com/us/app/atomic-wallet/id1478257827", "android": "https://play.google.com/store/apps/details?id=io.atomicwallet" } },
|
|
129
|
+
alpha: { "scheme": "awallet://wc", "universal": "https://aw.app/wc", "store": { "ios": "https://apps.apple.com/us/app/alphawallet-eth-wallet/id1358230430", "android": "https://play.google.com/store/apps/details?id=io.stormbird.wallet" } },
|
|
130
|
+
math: { "scheme": "mathwallet://wc", "universal": "https://www.mathwallet.org/wc", "store": { "ios": "https://apps.apple.com/us/app/mathwallet5/id1582612388", "android": "https://play.google.com/store/apps/details?id=com.mathwallet.android" } },
|
|
131
|
+
bitpay: { "scheme": "bitpay://wc", "universal": "https://link.bitpay.com/wc", "store": { "ios": "https://bitpay.onelink.me/Cenw/ejjaw7bs", "android": "https://bitpay.onelink.me/Cenw/ejjaw7bs" } }
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
// src/connectors/walletconnect/registry.ts
|
|
135
|
+
var MANUAL_WALLET_LINKS = {
|
|
136
|
+
infinity: { scheme: "infinity://wc" }
|
|
137
|
+
};
|
|
138
|
+
var DEFAULT_WALLET_LINKS = {
|
|
139
|
+
...MANUAL_WALLET_LINKS,
|
|
140
|
+
...GENERATED_WALLET_LINKS
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
// src/connectors/walletconnect/deeplink.ts
|
|
144
|
+
function isMobile() {
|
|
145
|
+
if (typeof navigator === "undefined") return false;
|
|
146
|
+
const ua = navigator.userAgent || "";
|
|
147
|
+
const uaDataMobile = navigator.userAgentData?.mobile ?? false;
|
|
148
|
+
return /iPhone|iPad|iPod|Android/i.test(ua) || uaDataMobile;
|
|
149
|
+
}
|
|
150
|
+
function buildLink(base, uri) {
|
|
151
|
+
const sep = base.includes("?") ? "&" : "?";
|
|
152
|
+
return `${base}${sep}uri=${encodeURIComponent(uri)}`;
|
|
153
|
+
}
|
|
154
|
+
function openWallet(link, uri) {
|
|
155
|
+
if (typeof document === "undefined") return;
|
|
156
|
+
if (link.universal) {
|
|
157
|
+
openHref(buildLink(link.universal, uri), true);
|
|
158
|
+
} else if (link.scheme) {
|
|
159
|
+
openHref(buildLink(link.scheme, uri), false);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
function openHref(href, newContext) {
|
|
163
|
+
const a = document.createElement("a");
|
|
164
|
+
a.href = href;
|
|
165
|
+
if (newContext) {
|
|
166
|
+
a.target = "_blank";
|
|
167
|
+
a.rel = "noopener noreferrer";
|
|
168
|
+
}
|
|
169
|
+
a.style.display = "none";
|
|
170
|
+
document.body.appendChild(a);
|
|
171
|
+
a.click();
|
|
172
|
+
document.body.removeChild(a);
|
|
173
|
+
}
|
|
174
|
+
function detectAppOpen(timeoutMs) {
|
|
175
|
+
if (typeof document === "undefined") return Promise.resolve(false);
|
|
176
|
+
return new Promise((resolve) => {
|
|
177
|
+
let done = false;
|
|
178
|
+
const finish = (opened) => {
|
|
179
|
+
if (done) return;
|
|
180
|
+
done = true;
|
|
181
|
+
document.removeEventListener("visibilitychange", onVisibility);
|
|
182
|
+
window.removeEventListener("pagehide", onPageHide);
|
|
183
|
+
clearTimeout(timer);
|
|
184
|
+
resolve(opened);
|
|
185
|
+
};
|
|
186
|
+
const onVisibility = () => {
|
|
187
|
+
if (document.hidden) finish(true);
|
|
188
|
+
};
|
|
189
|
+
const onPageHide = () => finish(true);
|
|
190
|
+
document.addEventListener("visibilitychange", onVisibility);
|
|
191
|
+
window.addEventListener("pagehide", onPageHide);
|
|
192
|
+
const timer = setTimeout(() => finish(false), timeoutMs);
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
// src/connectors/walletconnect/connector.ts
|
|
197
|
+
var STORAGE_KEY = "lydianconnect.wc.topics";
|
|
198
|
+
var WalletConnectConnector = class extends BaseConnector {
|
|
199
|
+
constructor(config) {
|
|
200
|
+
super();
|
|
201
|
+
this.config = config;
|
|
202
|
+
this.type = "walletconnect";
|
|
203
|
+
this.walletIds = [];
|
|
204
|
+
// claims any wallet not served by an SDK connector
|
|
205
|
+
this.client = null;
|
|
206
|
+
this.topics = /* @__PURE__ */ new Map();
|
|
207
|
+
this.warm = null;
|
|
208
|
+
this.warming = null;
|
|
209
|
+
this.links = { ...DEFAULT_WALLET_LINKS, ...config.walletLinks ?? {} };
|
|
210
|
+
}
|
|
211
|
+
isAvailable() {
|
|
212
|
+
return true;
|
|
213
|
+
}
|
|
214
|
+
async getClient() {
|
|
215
|
+
if (this.client) return this.client;
|
|
216
|
+
const client = await SignClient__default.default.init({
|
|
217
|
+
projectId: this.config.projectId,
|
|
218
|
+
metadata: this.config.metadata,
|
|
219
|
+
relayUrl: this.config.relayUrl
|
|
220
|
+
});
|
|
221
|
+
client.on("session_delete", ({ topic }) => {
|
|
222
|
+
const walletId = this.walletForTopic(topic);
|
|
223
|
+
if (!walletId) return;
|
|
224
|
+
this.topics.delete(walletId);
|
|
225
|
+
this.persist();
|
|
226
|
+
this.emit({ type: "disconnect", walletId });
|
|
227
|
+
});
|
|
228
|
+
client.on("session_event", ({ topic, params }) => {
|
|
229
|
+
const walletId = this.walletForTopic(topic);
|
|
230
|
+
if (!walletId) return;
|
|
231
|
+
const { name, data } = params.event;
|
|
232
|
+
if (name === "chainChanged") {
|
|
233
|
+
const chainId = typeof data === "string" && data.includes(":") ? data : `eip155:${String(data)}`;
|
|
234
|
+
this.emit({ type: "chainChanged", walletId, chainId });
|
|
235
|
+
} else if (name === "accountsChanged" && Array.isArray(data) && data[0]) {
|
|
236
|
+
const account = String(data[0]).split(":").pop() ?? "";
|
|
237
|
+
if (account) this.emit({ type: "accountsChanged", walletId, account });
|
|
238
|
+
}
|
|
239
|
+
});
|
|
240
|
+
this.client = client;
|
|
241
|
+
this.load();
|
|
242
|
+
return client;
|
|
243
|
+
}
|
|
244
|
+
/** Pre-create a pairing so connect() can deep-link synchronously within the gesture. */
|
|
245
|
+
async warmup() {
|
|
246
|
+
if (this.warm) return;
|
|
247
|
+
if (this.warming) return this.warming;
|
|
248
|
+
this.warming = (async () => {
|
|
249
|
+
const client = await this.getClient();
|
|
250
|
+
const { topic, uri } = await client.core.pairing.create();
|
|
251
|
+
this.warm = { topic, uri };
|
|
252
|
+
this.warming = null;
|
|
253
|
+
})();
|
|
254
|
+
return this.warming;
|
|
255
|
+
}
|
|
256
|
+
async connect(req) {
|
|
257
|
+
const client = await this.getClient();
|
|
258
|
+
const reused = this.tryReuse(client, req);
|
|
259
|
+
if (reused) return reused;
|
|
260
|
+
if (!this.warm) await this.warmup();
|
|
261
|
+
const warm = this.warm;
|
|
262
|
+
this.warm = null;
|
|
263
|
+
if (!warm) throw new Error("Failed to create WalletConnect pairing");
|
|
264
|
+
this.emit({ type: "display_uri", walletId: req.walletId, uri: warm.uri });
|
|
265
|
+
if (isMobile()) {
|
|
266
|
+
const link = this.links[req.walletId];
|
|
267
|
+
if (link) {
|
|
268
|
+
openWallet(link, warm.uri);
|
|
269
|
+
void detectAppOpen(this.config.openTimeoutMs ?? 2e3).then((opened) => {
|
|
270
|
+
if (!opened) this.emit({ type: "wallet_open_failed", walletId: req.walletId, uri: warm.uri });
|
|
271
|
+
});
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
const { approval } = await client.connect({
|
|
275
|
+
pairingTopic: warm.topic,
|
|
276
|
+
optionalNamespaces: { [req.namespace.name]: req.namespace.value }
|
|
277
|
+
});
|
|
278
|
+
const session = await withSignal(approval(), req.signal, () => {
|
|
279
|
+
void client.core.pairing.disconnect({ topic: warm.topic }).catch(() => {
|
|
280
|
+
});
|
|
281
|
+
});
|
|
282
|
+
void this.warmup();
|
|
283
|
+
const connection = this.toConnection(client, req.walletId, session, req.namespace);
|
|
284
|
+
this.topics.set(req.walletId, session.topic);
|
|
285
|
+
this.persist();
|
|
286
|
+
return connection;
|
|
287
|
+
}
|
|
288
|
+
async restore() {
|
|
289
|
+
const client = await this.getClient();
|
|
290
|
+
const out = [];
|
|
291
|
+
for (const [walletId, topic] of [...this.topics]) {
|
|
292
|
+
const session = this.liveSession(client, topic);
|
|
293
|
+
if (!session) {
|
|
294
|
+
this.topics.delete(walletId);
|
|
295
|
+
continue;
|
|
296
|
+
}
|
|
297
|
+
const ns = firstNamespace(session);
|
|
298
|
+
if (ns) out.push(this.toConnection(client, walletId, session, ns));
|
|
299
|
+
}
|
|
300
|
+
this.persist();
|
|
301
|
+
return out;
|
|
302
|
+
}
|
|
303
|
+
async reset() {
|
|
304
|
+
const client = this.client;
|
|
305
|
+
if (client) {
|
|
306
|
+
await Promise.allSettled(
|
|
307
|
+
client.session.getAll().map((s) => client.disconnect({ topic: s.topic, reason: utils.getSdkError("USER_DISCONNECTED") }))
|
|
308
|
+
);
|
|
309
|
+
}
|
|
310
|
+
this.topics.clear();
|
|
311
|
+
this.persist();
|
|
312
|
+
this.warm = null;
|
|
313
|
+
}
|
|
314
|
+
// --- helpers ---
|
|
315
|
+
tryReuse(client, req) {
|
|
316
|
+
const topic = this.topics.get(req.walletId);
|
|
317
|
+
if (!topic) return null;
|
|
318
|
+
const session = this.liveSession(client, topic);
|
|
319
|
+
if (!session) {
|
|
320
|
+
this.topics.delete(req.walletId);
|
|
321
|
+
return null;
|
|
322
|
+
}
|
|
323
|
+
const ns = session.namespaces[req.namespace.name];
|
|
324
|
+
const wanted = req.namespace.value.chains?.[0];
|
|
325
|
+
if (!ns || wanted && !ns.chains?.includes(wanted)) return null;
|
|
326
|
+
return this.toConnection(client, req.walletId, session, req.namespace);
|
|
327
|
+
}
|
|
328
|
+
toConnection(client, walletId, session, namespace) {
|
|
329
|
+
const ns = session.namespaces[namespace.name];
|
|
330
|
+
const account = (ns?.accounts ?? []).map((a) => a.split(":")[2]).find((a) => !!a) ?? "";
|
|
331
|
+
const chainId = ns?.chains?.[0] ?? (ns?.accounts?.[0] ? ns.accounts[0].split(":").slice(0, 2).join(":") : `${namespace.name}:1`);
|
|
332
|
+
const topic = session.topic;
|
|
333
|
+
return {
|
|
334
|
+
walletId,
|
|
335
|
+
account,
|
|
336
|
+
chainId,
|
|
337
|
+
request: (args) => client.request({
|
|
338
|
+
topic,
|
|
339
|
+
chainId,
|
|
340
|
+
request: { method: args.method, params: args.params }
|
|
341
|
+
}),
|
|
342
|
+
disconnect: async () => {
|
|
343
|
+
await client.disconnect({ topic, reason: utils.getSdkError("USER_DISCONNECTED") }).catch(() => {
|
|
344
|
+
});
|
|
345
|
+
this.topics.delete(walletId);
|
|
346
|
+
this.persist();
|
|
347
|
+
this.emit({ type: "disconnect", walletId });
|
|
348
|
+
}
|
|
349
|
+
};
|
|
350
|
+
}
|
|
351
|
+
liveSession(client, topic) {
|
|
352
|
+
try {
|
|
353
|
+
return client.session.get(topic);
|
|
354
|
+
} catch {
|
|
355
|
+
return void 0;
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
walletForTopic(topic) {
|
|
359
|
+
for (const [walletId, t] of this.topics) if (t === topic) return walletId;
|
|
360
|
+
return null;
|
|
361
|
+
}
|
|
362
|
+
persist() {
|
|
363
|
+
try {
|
|
364
|
+
localStorage.setItem(STORAGE_KEY, JSON.stringify([...this.topics]));
|
|
365
|
+
} catch {
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
load() {
|
|
369
|
+
try {
|
|
370
|
+
const raw = localStorage.getItem(STORAGE_KEY);
|
|
371
|
+
if (raw) this.topics = new Map(JSON.parse(raw));
|
|
372
|
+
} catch {
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
};
|
|
376
|
+
function firstNamespace(session) {
|
|
377
|
+
const name = Object.keys(session.namespaces)[0];
|
|
378
|
+
if (!name) return null;
|
|
379
|
+
const v = session.namespaces[name];
|
|
380
|
+
if (!v) return null;
|
|
381
|
+
return { name, value: { chains: v.chains, methods: v.methods, events: v.events } };
|
|
382
|
+
}
|
|
383
|
+
function withSignal(promise, signal, onAbort) {
|
|
384
|
+
if (!signal) return promise;
|
|
385
|
+
if (signal.aborted) {
|
|
386
|
+
onAbort();
|
|
387
|
+
return Promise.reject(new DOMException("Aborted", "AbortError"));
|
|
388
|
+
}
|
|
389
|
+
return new Promise((resolve, reject) => {
|
|
390
|
+
const abortHandler = () => {
|
|
391
|
+
onAbort();
|
|
392
|
+
reject(new DOMException("Aborted", "AbortError"));
|
|
393
|
+
};
|
|
394
|
+
signal.addEventListener("abort", abortHandler, { once: true });
|
|
395
|
+
promise.then(
|
|
396
|
+
(v) => {
|
|
397
|
+
signal.removeEventListener("abort", abortHandler);
|
|
398
|
+
resolve(v);
|
|
399
|
+
},
|
|
400
|
+
(e) => {
|
|
401
|
+
signal.removeEventListener("abort", abortHandler);
|
|
402
|
+
reject(e);
|
|
403
|
+
}
|
|
404
|
+
);
|
|
405
|
+
});
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
// src/connectors/metamask/connector.ts
|
|
409
|
+
var WALLET_ID = "metamask";
|
|
410
|
+
var MetaMaskConnector = class extends BaseConnector {
|
|
411
|
+
constructor(config) {
|
|
412
|
+
super();
|
|
413
|
+
this.config = config;
|
|
414
|
+
this.type = "sdk";
|
|
415
|
+
this.walletIds = [WALLET_ID];
|
|
416
|
+
this.sdk = null;
|
|
417
|
+
this.provider = null;
|
|
418
|
+
this.listenersBound = false;
|
|
419
|
+
}
|
|
420
|
+
isAvailable() {
|
|
421
|
+
return true;
|
|
422
|
+
}
|
|
423
|
+
async getProvider() {
|
|
424
|
+
if (this.provider) return this.provider;
|
|
425
|
+
const { MetaMaskSDK } = await import('@metamask/sdk');
|
|
426
|
+
const sdk = new MetaMaskSDK({
|
|
427
|
+
dappMetadata: this.config.dappMetadata,
|
|
428
|
+
...this.config.sdkOptions
|
|
429
|
+
});
|
|
430
|
+
await sdk.init();
|
|
431
|
+
const provider = sdk.getProvider();
|
|
432
|
+
if (!provider) throw new Error("MetaMask provider unavailable");
|
|
433
|
+
this.sdk = sdk;
|
|
434
|
+
this.provider = provider;
|
|
435
|
+
this.bindEvents(provider);
|
|
436
|
+
return provider;
|
|
437
|
+
}
|
|
438
|
+
bindEvents(provider) {
|
|
439
|
+
if (this.listenersBound) return;
|
|
440
|
+
this.listenersBound = true;
|
|
441
|
+
provider.on("chainChanged", (hex) => {
|
|
442
|
+
this.emit({ type: "chainChanged", walletId: WALLET_ID, chainId: toCaip(String(hex)) });
|
|
443
|
+
});
|
|
444
|
+
provider.on("accountsChanged", (accounts) => {
|
|
445
|
+
const account = Array.isArray(accounts) ? accounts[0] : void 0;
|
|
446
|
+
if (account) this.emit({ type: "accountsChanged", walletId: WALLET_ID, account });
|
|
447
|
+
else this.emit({ type: "disconnect", walletId: WALLET_ID });
|
|
448
|
+
});
|
|
449
|
+
provider.on("disconnect", () => this.emit({ type: "disconnect", walletId: WALLET_ID }));
|
|
450
|
+
}
|
|
451
|
+
async connect(req) {
|
|
452
|
+
const provider = await this.getProvider();
|
|
453
|
+
const accounts = await provider.request({ method: "eth_requestAccounts" });
|
|
454
|
+
const account = accounts?.[0];
|
|
455
|
+
if (!account) throw new Error("MetaMask returned no account");
|
|
456
|
+
await this.ensureChain(provider, req);
|
|
457
|
+
const chainId = toCaip(await provider.request({ method: "eth_chainId" }));
|
|
458
|
+
return this.toConnection(provider, account, chainId);
|
|
459
|
+
}
|
|
460
|
+
async restore() {
|
|
461
|
+
const provider = await this.getProvider().catch(() => null);
|
|
462
|
+
if (!provider) return [];
|
|
463
|
+
const accounts = await provider.request({ method: "eth_accounts" }).catch(() => []);
|
|
464
|
+
const account = accounts?.[0];
|
|
465
|
+
if (!account) return [];
|
|
466
|
+
const chainId = toCaip(
|
|
467
|
+
await provider.request({ method: "eth_chainId" }).catch(() => "0x1")
|
|
468
|
+
);
|
|
469
|
+
return [this.toConnection(provider, account, chainId)];
|
|
470
|
+
}
|
|
471
|
+
async reset() {
|
|
472
|
+
await this.sdk?.terminate();
|
|
473
|
+
this.provider = null;
|
|
474
|
+
this.listenersBound = false;
|
|
475
|
+
}
|
|
476
|
+
/** Best-effort switch to the requested chain; leaves the wallet as-is if it's unknown to it. */
|
|
477
|
+
async ensureChain(provider, req) {
|
|
478
|
+
const wanted = req.namespace.value.chains?.[0];
|
|
479
|
+
const wantedNum = wanted ? Number(wanted.split(":")[1]) : NaN;
|
|
480
|
+
if (!Number.isFinite(wantedNum) || wantedNum <= 0) return;
|
|
481
|
+
const current = parseInt(
|
|
482
|
+
await provider.request({ method: "eth_chainId" }).catch(() => "0x0") ?? "0x0",
|
|
483
|
+
16
|
|
484
|
+
);
|
|
485
|
+
if (current === wantedNum) return;
|
|
486
|
+
await provider.request({
|
|
487
|
+
method: "wallet_switchEthereumChain",
|
|
488
|
+
params: [{ chainId: `0x${wantedNum.toString(16)}` }]
|
|
489
|
+
}).catch(() => {
|
|
490
|
+
});
|
|
491
|
+
}
|
|
492
|
+
toConnection(provider, account, chainId) {
|
|
493
|
+
return {
|
|
494
|
+
walletId: WALLET_ID,
|
|
495
|
+
account,
|
|
496
|
+
chainId,
|
|
497
|
+
request: async (args) => await provider.request({ method: args.method, params: args.params }),
|
|
498
|
+
disconnect: async () => {
|
|
499
|
+
await this.sdk?.terminate();
|
|
500
|
+
this.provider = null;
|
|
501
|
+
this.listenersBound = false;
|
|
502
|
+
this.emit({ type: "disconnect", walletId: WALLET_ID });
|
|
503
|
+
}
|
|
504
|
+
};
|
|
505
|
+
}
|
|
506
|
+
};
|
|
507
|
+
function toCaip(hexChainId) {
|
|
508
|
+
if (!hexChainId) return "eip155:1";
|
|
509
|
+
const num = hexChainId.startsWith("0x") ? parseInt(hexChainId, 16) : Number(hexChainId);
|
|
510
|
+
return `eip155:${Number.isFinite(num) ? num : 1}`;
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
// src/connectors/coinbase/connector.ts
|
|
514
|
+
function rpc(provider, method, params) {
|
|
515
|
+
return provider.request({ method, params });
|
|
516
|
+
}
|
|
517
|
+
var WALLET_ID2 = "coinbase";
|
|
518
|
+
var CoinbaseConnector = class extends BaseConnector {
|
|
519
|
+
constructor(config) {
|
|
520
|
+
super();
|
|
521
|
+
this.config = config;
|
|
522
|
+
this.type = "sdk";
|
|
523
|
+
this.walletIds = [WALLET_ID2];
|
|
524
|
+
this.provider = null;
|
|
525
|
+
this.listenersBound = false;
|
|
526
|
+
}
|
|
527
|
+
isAvailable() {
|
|
528
|
+
return true;
|
|
529
|
+
}
|
|
530
|
+
async getProvider() {
|
|
531
|
+
if (this.provider) return this.provider;
|
|
532
|
+
const { CoinbaseWalletSDK } = await import('@coinbase/wallet-sdk');
|
|
533
|
+
const sdk = new CoinbaseWalletSDK({
|
|
534
|
+
appName: this.config.appName,
|
|
535
|
+
appLogoUrl: this.config.appLogoUrl,
|
|
536
|
+
appChainIds: this.config.appChainIds
|
|
537
|
+
});
|
|
538
|
+
const provider = sdk.makeWeb3Provider();
|
|
539
|
+
this.provider = provider;
|
|
540
|
+
this.bindEvents(provider);
|
|
541
|
+
return provider;
|
|
542
|
+
}
|
|
543
|
+
bindEvents(provider) {
|
|
544
|
+
if (this.listenersBound) return;
|
|
545
|
+
this.listenersBound = true;
|
|
546
|
+
provider.on("chainChanged", (hex) => {
|
|
547
|
+
this.emit({ type: "chainChanged", walletId: WALLET_ID2, chainId: toCaip2(String(hex)) });
|
|
548
|
+
});
|
|
549
|
+
provider.on("accountsChanged", (accounts) => {
|
|
550
|
+
const account = Array.isArray(accounts) ? accounts[0] : void 0;
|
|
551
|
+
if (account) this.emit({ type: "accountsChanged", walletId: WALLET_ID2, account });
|
|
552
|
+
else this.emit({ type: "disconnect", walletId: WALLET_ID2 });
|
|
553
|
+
});
|
|
554
|
+
provider.on("disconnect", () => this.emit({ type: "disconnect", walletId: WALLET_ID2 }));
|
|
555
|
+
}
|
|
556
|
+
async connect(req) {
|
|
557
|
+
const provider = await this.getProvider();
|
|
558
|
+
const accounts = await rpc(provider, "eth_requestAccounts");
|
|
559
|
+
const account = accounts?.[0];
|
|
560
|
+
if (!account) throw new Error("Coinbase Wallet returned no account");
|
|
561
|
+
await this.ensureChain(provider, req);
|
|
562
|
+
const chainId = toCaip2(await rpc(provider, "eth_chainId"));
|
|
563
|
+
return this.toConnection(provider, account, chainId);
|
|
564
|
+
}
|
|
565
|
+
async restore() {
|
|
566
|
+
const provider = await this.getProvider().catch(() => null);
|
|
567
|
+
if (!provider) return [];
|
|
568
|
+
const accounts = await rpc(provider, "eth_accounts").catch(() => []);
|
|
569
|
+
const account = accounts?.[0];
|
|
570
|
+
if (!account) return [];
|
|
571
|
+
const chainId = toCaip2(await rpc(provider, "eth_chainId").catch(() => "0x1"));
|
|
572
|
+
return [this.toConnection(provider, account, chainId)];
|
|
573
|
+
}
|
|
574
|
+
async reset() {
|
|
575
|
+
await this.provider?.disconnect().catch(() => {
|
|
576
|
+
});
|
|
577
|
+
this.provider = null;
|
|
578
|
+
this.listenersBound = false;
|
|
579
|
+
}
|
|
580
|
+
async ensureChain(provider, req) {
|
|
581
|
+
const wanted = req.namespace.value.chains?.[0];
|
|
582
|
+
const wantedNum = wanted ? Number(wanted.split(":")[1]) : NaN;
|
|
583
|
+
if (!Number.isFinite(wantedNum) || wantedNum <= 0) return;
|
|
584
|
+
const current = parseInt(await rpc(provider, "eth_chainId").catch(() => "0x0"), 16);
|
|
585
|
+
if (current === wantedNum) return;
|
|
586
|
+
await rpc(provider, "wallet_switchEthereumChain", [{ chainId: `0x${wantedNum.toString(16)}` }]).catch(
|
|
587
|
+
() => {
|
|
588
|
+
}
|
|
589
|
+
);
|
|
590
|
+
}
|
|
591
|
+
toConnection(provider, account, chainId) {
|
|
592
|
+
return {
|
|
593
|
+
walletId: WALLET_ID2,
|
|
594
|
+
account,
|
|
595
|
+
chainId,
|
|
596
|
+
request: (args) => rpc(provider, args.method, args.params),
|
|
597
|
+
disconnect: async () => {
|
|
598
|
+
await provider.disconnect().catch(() => {
|
|
599
|
+
});
|
|
600
|
+
this.provider = null;
|
|
601
|
+
this.listenersBound = false;
|
|
602
|
+
this.emit({ type: "disconnect", walletId: WALLET_ID2 });
|
|
603
|
+
}
|
|
604
|
+
};
|
|
605
|
+
}
|
|
606
|
+
};
|
|
607
|
+
function toCaip2(hexChainId) {
|
|
608
|
+
if (!hexChainId) return "eip155:1";
|
|
609
|
+
const num = hexChainId.startsWith("0x") ? parseInt(hexChainId, 16) : Number(hexChainId);
|
|
610
|
+
return `eip155:${Number.isFinite(num) ? num : 1}`;
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
exports.BaseConnector = BaseConnector;
|
|
614
|
+
exports.CoinbaseConnector = CoinbaseConnector;
|
|
615
|
+
exports.DEFAULT_WALLET_LINKS = DEFAULT_WALLET_LINKS;
|
|
616
|
+
exports.LydianConnect = LydianConnect;
|
|
617
|
+
exports.MetaMaskConnector = MetaMaskConnector;
|
|
618
|
+
exports.WalletConnectConnector = WalletConnectConnector;
|
|
619
|
+
//# sourceMappingURL=index.cjs.map
|
|
620
|
+
//# sourceMappingURL=index.cjs.map
|