@human.tech/waap-sdk 1.3.0 → 2.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.mjs ADDED
@@ -0,0 +1,2162 @@
1
+ // src/ui/index.ts
2
+ import {
3
+ silkWalletAppOrigin2 as silkWalletAppOrigin22,
4
+ silkWalletAppOrigin2Staging as silkWalletAppOrigin2Staging2
5
+ } from "@human.tech/waap-constants";
6
+
7
+ // src/lib/provider/EthereumProvider.ts
8
+ import { EventEmitter as EventEmitter2 } from "events";
9
+ import {
10
+ SILK_METHOD as SILK_METHOD2,
11
+ JSON_RPC_METHOD
12
+ } from "@human.tech/waap-interface-core";
13
+
14
+ // src/lib/UIMessageManager.ts
15
+ import { EventEmitter } from "events";
16
+ var UI_EVENT_NAMES = /* @__PURE__ */ ((UI_EVENT_NAMES2) => {
17
+ UI_EVENT_NAMES2["show_modal"] = "show_modal";
18
+ UI_EVENT_NAMES2["hide_modal"] = "hide_modal";
19
+ return UI_EVENT_NAMES2;
20
+ })(UI_EVENT_NAMES || {});
21
+ var UIMessageManager = class extends EventEmitter {
22
+ constructor() {
23
+ super();
24
+ }
25
+ };
26
+
27
+ // src/lib/provider/requests.ts
28
+ import { rpcMethodRequiresUI } from "@human.tech/waap-constants";
29
+ async function handleWalletRequestAndResponse(args, interactionRequired, walletMessageManager, internalProviderEventEmitter, silkOptions) {
30
+ const method = args.method;
31
+ const params = args.params;
32
+ const id = await walletMessageManager.postSilkRequest({
33
+ method,
34
+ params,
35
+ interactionRequired,
36
+ silkOptions
37
+ });
38
+ return new Promise((resolve, reject) => {
39
+ internalProviderEventEmitter.once(id, (response) => {
40
+ if (response.error) reject(response.error);
41
+ else resolve(response.data);
42
+ });
43
+ });
44
+ }
45
+
46
+ // src/lib/provider/utils.ts
47
+ function isMetaMask(provider) {
48
+ if (!(provider == null ? void 0 : provider.isMetaMask)) return false;
49
+ if (provider.isApexWallet) return false;
50
+ if (provider.isAvalanche) return false;
51
+ if (provider.isBitKeep) return false;
52
+ if (provider.isBlockWallet) return false;
53
+ if (provider.isMathWallet) return false;
54
+ if (provider.isOkxWallet || provider.isOKExWallet) return false;
55
+ if (provider.isOneInchIOSWallet || provider.isOneInchAndroidWallet) {
56
+ return false;
57
+ }
58
+ if (provider.isOpera) return false;
59
+ if (provider.isPortal) return false;
60
+ if (provider.isRabby) return false;
61
+ if (provider.isDefiant) return false;
62
+ if (provider.isTokenPocket) return false;
63
+ if (provider.isTokenary) return false;
64
+ if (provider.isZerion) return false;
65
+ return true;
66
+ }
67
+ function isSafeTransaction(params) {
68
+ var _a;
69
+ try {
70
+ if (!params || !Array.isArray(params)) return false;
71
+ const typedData = JSON.parse(
72
+ typeof params[1] === "string" ? params[1] : JSON.stringify(params[1])
73
+ );
74
+ return typedData.primaryType === "SafeTx" && ((_a = typedData.domain) == null ? void 0 : _a.verifyingContract) !== void 0 && typedData.message && "to" in typedData.message && "value" in typedData.message && "safeTxGas" in typedData.message && "baseGas" in typedData.message && "gasPrice" in typedData.message && "nonce" in typedData.message;
75
+ } catch {
76
+ return false;
77
+ }
78
+ }
79
+ var defaultConfig = {
80
+ styles: {
81
+ darkMode: false
82
+ }
83
+ };
84
+
85
+ // src/lib/WalletConnect.ts
86
+ import { EthersAdapter } from "@reown/appkit-adapter-ethers";
87
+ var SilkWalletConnect = class {
88
+ static instance = null;
89
+ static projectId = void 0;
90
+ // Ethereum, Optimism, Gnosis, Polygon, Base, Avalanche, Arbitrum, Celo, Base Sepolia, Sepolia
91
+ static chains = [
92
+ 1,
93
+ 10,
94
+ 100,
95
+ 137,
96
+ 8453,
97
+ 43114,
98
+ 42161,
99
+ 42220,
100
+ 84532,
101
+ 11155111
102
+ ];
103
+ // private static optionalChains: AppKitNetwork[]
104
+ /**
105
+ * Set the WalletConnect project ID programmatically
106
+ * Use this if environment variables aren't working in your setup
107
+ *
108
+ * @param id - The WalletConnect project ID to use
109
+ */
110
+ static setProjectId(id) {
111
+ this.projectId = id;
112
+ }
113
+ // /**
114
+ // * Set the optional chains to use for WalletConnect
115
+ // *
116
+ // * @param chains - The optional chains to use (number[])
117
+ // */
118
+ // static setOptionalChains(chains: AppKitNetwork[]) {
119
+ // SilkWalletConnect.optionalChains = chains
120
+ // }
121
+ static getProjectIdFromEnv() {
122
+ try {
123
+ if (typeof process !== "undefined" && process.env) {
124
+ return process.env.NEXT_PUBLIC_WALLET_CONNECT_PROJECT_ID || process.env.VITE_WALLET_CONNECT_PROJECT_ID || process.env.REACT_APP_WALLET_CONNECT_PROJECT_ID || process.env.WALLET_CONNECT_PROJECT_ID;
125
+ }
126
+ } catch (error) {
127
+ return void 0;
128
+ }
129
+ return void 0;
130
+ }
131
+ static async getInstance() {
132
+ if (typeof window === "undefined" || typeof document === "undefined") {
133
+ return null;
134
+ }
135
+ const { createAppKit } = await import("@reown/appkit");
136
+ const {
137
+ mainnet,
138
+ sepolia,
139
+ optimism,
140
+ arbitrum,
141
+ optimismGoerli,
142
+ polygon,
143
+ gnosis,
144
+ avalanche,
145
+ aurora,
146
+ fantom,
147
+ base,
148
+ celo
149
+ } = await import("@reown/appkit/networks");
150
+ try {
151
+ const metadata = {
152
+ name: "Human Wallet",
153
+ description: "Silk lets you create human keys for web3 wallets that are recoverable with private identity proofs and secured by zero trust protocols.",
154
+ url: window.location.origin,
155
+ // origin must match your domain & subdomain
156
+ icons: [
157
+ "https://imagedelivery.net/_aTEfDRm7z3tKgu9JhfeKA/f11f5753-616a-4aa0-2aee-9b75befea700/sm"
158
+ ]
159
+ };
160
+ const projectId = this.projectId || this.getProjectIdFromEnv();
161
+ if (!projectId) {
162
+ console.error(
163
+ 'WalletConnect project ID not found. Please set it using one of these methods:\n1. Pass walletConnectProjectId when calling initSilk\n2. Call SilkWalletConnect.setProjectId("your-project-id")\n3. Set WALLET_CONNECT_PROJECT_ID (NEXT_PUBLIC_WALLET_CONNECT_PROJECT_ID for Next projects) environment variable'
164
+ );
165
+ return null;
166
+ }
167
+ this.projectId = projectId;
168
+ if (!this.instance) {
169
+ this.instance = createAppKit({
170
+ adapters: [new EthersAdapter()],
171
+ projectId,
172
+ metadata,
173
+ networks: [
174
+ // @ts-ignore
175
+ mainnet,
176
+ sepolia,
177
+ arbitrum,
178
+ optimism,
179
+ polygon,
180
+ gnosis,
181
+ avalanche,
182
+ aurora,
183
+ fantom,
184
+ base,
185
+ celo
186
+ ],
187
+ features: {
188
+ socials: false,
189
+ email: false
190
+ }
191
+ });
192
+ }
193
+ return this.instance;
194
+ } catch (error) {
195
+ console.error("Error importing or initializing WalletConnect:", error);
196
+ return null;
197
+ }
198
+ }
199
+ static async listenToAccountChangeEvent() {
200
+ await new Promise((resolve) => {
201
+ const unsubscribe = this.instance.subscribeAccount(
202
+ (accountState) => {
203
+ if (accountState == null ? void 0 : accountState.isConnected) {
204
+ resolve();
205
+ }
206
+ }
207
+ );
208
+ });
209
+ }
210
+ /**
211
+ * Wait for WalletConnect to be properly initialized and connected
212
+ * @returns Promise<boolean> - true if connected, false if timeout reached
213
+ */
214
+ static async waitForReadyAndCheckConnection() {
215
+ if (!this.instance) {
216
+ return false;
217
+ }
218
+ let isConnected = false;
219
+ let attempts = 0;
220
+ const maxAttempts = 15;
221
+ while (!isConnected && attempts < maxAttempts) {
222
+ const delay = attempts < 5 ? 500 : 1e3;
223
+ await new Promise((resolve) => setTimeout(resolve, delay));
224
+ isConnected = this.instance.getIsConnectedState();
225
+ attempts++;
226
+ console.log(
227
+ `WalletConnect connection check attempt ${attempts}: ${isConnected}`
228
+ );
229
+ }
230
+ return isConnected;
231
+ }
232
+ /**
233
+ * Check if WalletConnect is currently connected (immediate check, no waiting)
234
+ * @returns boolean - true if connected, false otherwise
235
+ */
236
+ static isConnected() {
237
+ var _a;
238
+ return ((_a = this.instance) == null ? void 0 : _a.getIsConnectedState()) ?? false;
239
+ }
240
+ /**
241
+ * Get the wallet provider from the WalletConnect instance
242
+ * @returns The wallet provider or null if not available
243
+ */
244
+ static getWalletProvider() {
245
+ var _a;
246
+ return ((_a = this.instance) == null ? void 0 : _a.getWalletProvider()) ?? null;
247
+ }
248
+ };
249
+
250
+ // src/lib/WalletMessageManager.ts
251
+ import {
252
+ SILK_MESSAGE_TYPE,
253
+ SILK_NOTIFICATION,
254
+ generateMessageId
255
+ } from "@human.tech/waap-interface-core";
256
+ import {
257
+ silkWalletAppOrigin2,
258
+ silkWalletAppOrigin2Staging
259
+ } from "@human.tech/waap-constants";
260
+ var WalletMessageManager = class {
261
+ iframeWindow = null;
262
+ walletOrigin;
263
+ constructor(iframeWindow, useStaging) {
264
+ this.iframeWindow = iframeWindow;
265
+ this.walletOrigin = useStaging ? silkWalletAppOrigin2Staging : silkWalletAppOrigin2;
266
+ }
267
+ /**
268
+ * Post a Silk notification to the given iframeWindow
269
+ */
270
+ postSilkNotification(data) {
271
+ this.iframeWindow.postMessage(
272
+ {
273
+ target: "silk",
274
+ messageType: SILK_MESSAGE_TYPE.notification,
275
+ data
276
+ },
277
+ this.walletOrigin
278
+ );
279
+ }
280
+ postReadyNotification() {
281
+ this.postSilkNotification(SILK_NOTIFICATION.ready);
282
+ }
283
+ postConnectNotification() {
284
+ this.postSilkNotification(SILK_NOTIFICATION.connect);
285
+ }
286
+ /**
287
+ * Post a 'ready' notification to the iframe, and wait
288
+ * for the iframe to respond with a 'ready' notification.
289
+ */
290
+ pingIframe() {
291
+ return new Promise((resolve, reject) => {
292
+ setTimeout(() => reject("Wallet ping timed out."), 1e4);
293
+ const eventHandler = (event) => {
294
+ if (event.data.target === "silk" && event.data.messageType === SILK_MESSAGE_TYPE.notification && event.data.data === SILK_NOTIFICATION.ready) {
295
+ window.removeEventListener("message", eventHandler);
296
+ resolve();
297
+ }
298
+ };
299
+ window.addEventListener("message", eventHandler);
300
+ this.postReadyNotification();
301
+ });
302
+ }
303
+ /**
304
+ * Post a SilkRequest to the iframeWindow. Don't wait for a response.
305
+ */
306
+ async postSilkRequest(req) {
307
+ const { silkOptions, ...restReq } = req;
308
+ const baseRequest = {
309
+ ...restReq,
310
+ target: "silk",
311
+ messageType: SILK_MESSAGE_TYPE.request,
312
+ // Include silkOptions for transaction methods
313
+ ...silkOptions && { silkOptions }
314
+ };
315
+ const id = await generateMessageId(baseRequest);
316
+ this.iframeWindow.postMessage({ ...baseRequest, id }, this.walletOrigin);
317
+ return id;
318
+ }
319
+ /**
320
+ * Add a message listener to the window in which this is called (which should be the top frame).
321
+ * It handles all messages from the Silk iframe posted to the top frame.
322
+ * @param config - Configuration that includes callbacks for handling specific messages.
323
+ */
324
+ addListener(config) {
325
+ const {
326
+ handleResponse,
327
+ handleRequest,
328
+ onReceiveConnectNotif,
329
+ onAccountChanged,
330
+ onAsyncTxNotification
331
+ } = config;
332
+ window.addEventListener("message", (event) => {
333
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l;
334
+ try {
335
+ const origin = typeof process !== "undefined" && process.env && process.env.NODE_ENV === "test" ? "http://127.0.0.1:3000" : event.origin;
336
+ if (origin !== this.walletOrigin) {
337
+ return;
338
+ }
339
+ } catch (error) {
340
+ if (event.origin !== this.walletOrigin) {
341
+ return;
342
+ }
343
+ }
344
+ if (((_a = event.data) == null ? void 0 : _a.messageType) === SILK_MESSAGE_TYPE.request) {
345
+ handleRequest(event.data);
346
+ } else if (((_b = event.data) == null ? void 0 : _b.messageType) === SILK_MESSAGE_TYPE.response) {
347
+ handleResponse(event.data);
348
+ } else if (((_c = event.data) == null ? void 0 : _c.messageType) === SILK_MESSAGE_TYPE.notification) {
349
+ if (((_d = event.data) == null ? void 0 : _d.data) === SILK_NOTIFICATION.connect) {
350
+ onReceiveConnectNotif == null ? void 0 : onReceiveConnectNotif();
351
+ } else if (((_f = (_e = event.data) == null ? void 0 : _e.data) == null ? void 0 : _f.type) === SILK_NOTIFICATION.account_changed && onAccountChanged) {
352
+ onAccountChanged(event.data.data.account);
353
+ } else if ((((_i = (_h = (_g = event.data) == null ? void 0 : _g.data) == null ? void 0 : _h.type) == null ? void 0 : _i.startsWith("waap_sign_")) || ((_l = (_k = (_j = event.data) == null ? void 0 : _j.data) == null ? void 0 : _k.type) == null ? void 0 : _l.startsWith("waap_tx_"))) && onAsyncTxNotification) {
354
+ onAsyncTxNotification({
355
+ type: event.data.data.type,
356
+ payload: event.data.data.payload
357
+ });
358
+ }
359
+ }
360
+ });
361
+ }
362
+ };
363
+ var WalletMessageManager_default = WalletMessageManager;
364
+
365
+ // src/lib/provider/EthereumProvider.ts
366
+ var VALID_LOGIN_METHODS = [
367
+ "waap",
368
+ "human",
369
+ "injected",
370
+ "walletconnect"
371
+ ];
372
+ function normalizeLoginResponse(response) {
373
+ if (response === null || response === void 0) {
374
+ return null;
375
+ }
376
+ if (typeof response === "string") {
377
+ if (VALID_LOGIN_METHODS.includes(response)) {
378
+ return response;
379
+ }
380
+ throw new Error(
381
+ `[EthereumProvider] Unexpected login method: "${response}". Expected one of: ${VALID_LOGIN_METHODS.join(", ")}`
382
+ );
383
+ }
384
+ if (typeof response === "object" && "loginMethod" in response && typeof response.loginMethod === "string") {
385
+ const method = response.loginMethod;
386
+ console.warn(
387
+ `[EthereumProvider] Received object login response. Normalizing "${method}" to string. This is unexpected for the web SDK.`
388
+ );
389
+ if (VALID_LOGIN_METHODS.includes(method)) {
390
+ return method;
391
+ }
392
+ throw new Error(
393
+ `[EthereumProvider] Unknown loginMethod in object: "${method}". Expected one of: ${VALID_LOGIN_METHODS.join(", ")}`
394
+ );
395
+ }
396
+ throw new Error(
397
+ `[EthereumProvider] Unexpected login response: ${JSON.stringify(
398
+ response
399
+ )} (type: ${typeof response})`
400
+ );
401
+ }
402
+ var EthereumProvider = class extends EventEmitter2 {
403
+ isSilk = true;
404
+ isWaaP = true;
405
+ connected = false;
406
+ walletMessageManager;
407
+ uiMessageManager;
408
+ config;
409
+ currentAccount = null;
410
+ walletConnectProvider = null;
411
+ /**
412
+ * When true, eth_sendTransaction resolves with the pre-calculated tx hash
413
+ * after signing. Broadcasting continues in the background with events.
414
+ */
415
+ asyncTxs = false;
416
+ /**
417
+ * When true, sends `asyncSigning: true` in silkOptions instead of `async: true`.
418
+ * This mimics the v1 SDK protocol for backward compatibility testing.
419
+ * @internal
420
+ */
421
+ legacyAsyncSigning = false;
422
+ persistedMethods;
423
+ /**
424
+ * We use the internalEventEmitter to emit as events
425
+ * Silk messages posted to the window.
426
+ */
427
+ internalEventEmitter = new EventEmitter2();
428
+ /**
429
+ * @param iframeWindow - The contentWindow of the iframe of the Silk website.
430
+ * @param referralCode - Silk points referral code
431
+ * @param customConfig - Silk custom UI configuration
432
+ * @param project - Silk project configuration
433
+ * @param useStaging - Whether to use the staging environment
434
+ * @param asyncTxs - When true, eth_sendTransaction resolves with tx hash after signing
435
+ * @param legacyAsyncSigning - When true, sends asyncSigning in silkOptions (v1 compat)
436
+ */
437
+ constructor(iframeWindow, referralCode, customConfig, project, useStaging, asyncTxs = false, legacyAsyncSigning = false) {
438
+ super();
439
+ this.asyncTxs = asyncTxs;
440
+ this.legacyAsyncSigning = legacyAsyncSigning;
441
+ this.uiMessageManager = new UIMessageManager();
442
+ this.walletMessageManager = new WalletMessageManager_default(
443
+ iframeWindow,
444
+ !!useStaging
445
+ );
446
+ this.config = {
447
+ ...defaultConfig,
448
+ ...customConfig || {}
449
+ // Override with customConfig if provided
450
+ };
451
+ this.persistedMethods = {
452
+ login: this.login.bind(this),
453
+ logout: this.logout.bind(this),
454
+ getLoginMethod: this.getLoginMethod.bind(this),
455
+ walletMessageManager: this.walletMessageManager,
456
+ internalEventEmitter: this.internalEventEmitter,
457
+ uiMessageManager: this.uiMessageManager,
458
+ portal: this.portal.bind(this),
459
+ requestEmail: this.requestEmail.bind(this),
460
+ requestSBT: this.requestSBT.bind(this),
461
+ requestPermissionToken: this.requestPermissionToken.bind(this),
462
+ orcid: this.orcid.bind(this),
463
+ enable: this.enable.bind(this),
464
+ isConnected: this.isConnected.bind(this),
465
+ toggleDarkMode: this.toggleDarkMode.bind(this),
466
+ // We leave this silkRequest separate and never changing so that
467
+ // we can still call the original request method if needed no matter
468
+ // the current provider
469
+ silkRequest: this.request.bind(this),
470
+ waaPRequest: this.request.bind(this)
471
+ };
472
+ this.walletMessageManager.addListener({
473
+ onReceiveConnectNotif: () => {
474
+ console.log("onReceiveConnectNotif");
475
+ this.connected = true;
476
+ this.emit("connect");
477
+ },
478
+ handleResponse: (response) => this.internalEventEmitter.emit(response.id, response),
479
+ handleRequest: (request) => {
480
+ if (request.method === SILK_METHOD2.show_modal) {
481
+ this.uiMessageManager.emit("show_modal" /* show_modal */);
482
+ } else if (request.method === SILK_METHOD2.hide_modal) {
483
+ this.uiMessageManager.emit("hide_modal" /* hide_modal */);
484
+ }
485
+ },
486
+ onAccountChanged: (newAccount) => {
487
+ if (this.currentAccount !== newAccount) {
488
+ this.currentAccount = newAccount;
489
+ this.emit("accountsChanged", newAccount ? [newAccount] : []);
490
+ }
491
+ },
492
+ onAsyncTxNotification: (notification) => {
493
+ this.emit(notification.type, notification.payload);
494
+ }
495
+ });
496
+ if (referralCode) {
497
+ this.walletMessageManager.pingIframe().then(() => {
498
+ return handleWalletRequestAndResponse(
499
+ {
500
+ method: SILK_METHOD2.set_points_referral_code,
501
+ params: [referralCode]
502
+ },
503
+ false,
504
+ this.walletMessageManager,
505
+ this.internalEventEmitter
506
+ );
507
+ }).catch((error) => {
508
+ console.error("Error setting referral code in Silk iframe:", error);
509
+ });
510
+ }
511
+ if (project) {
512
+ console.log(" =========== project =========== ", project);
513
+ this.walletMessageManager.pingIframe().then(() => {
514
+ return handleWalletRequestAndResponse(
515
+ {
516
+ method: SILK_METHOD2.set_project,
517
+ params: [project, window.location.origin]
518
+ },
519
+ false,
520
+ this.walletMessageManager,
521
+ this.internalEventEmitter
522
+ );
523
+ });
524
+ }
525
+ if (customConfig) {
526
+ this.walletMessageManager.pingIframe().then(() => {
527
+ return handleWalletRequestAndResponse(
528
+ {
529
+ method: SILK_METHOD2.set_custom_config,
530
+ params: [customConfig]
531
+ },
532
+ false,
533
+ this.walletMessageManager,
534
+ this.internalEventEmitter
535
+ );
536
+ }).catch((error) => {
537
+ console.error("Error setting custom config in Silk iframe:", error);
538
+ });
539
+ }
540
+ }
541
+ async initializeWalletConnect() {
542
+ try {
543
+ this.walletConnectProvider = await SilkWalletConnect.getInstance();
544
+ console.log("WalletConnect provider initialized");
545
+ } catch (error) {
546
+ console.error("Failed to initialize WalletConnect provider:", error);
547
+ this.walletConnectProvider = null;
548
+ }
549
+ }
550
+ async enable() {
551
+ return this.request({ method: "eth_requestAccounts" });
552
+ }
553
+ isConnected() {
554
+ return this.connected;
555
+ }
556
+ async request(args) {
557
+ var _a, _b, _c, _d, _e, _f, _g, _h;
558
+ if (!Object.keys(JSON_RPC_METHOD).includes(
559
+ args.method
560
+ )) {
561
+ return Promise.reject({ error: `Not implemented (${args.method})` });
562
+ }
563
+ const autoConnectResult = await this.attemptAutoConnect(args.method);
564
+ if (autoConnectResult !== null) {
565
+ return autoConnectResult;
566
+ }
567
+ const isSafeTx = isSafeTransaction(args.params);
568
+ if (isSafeTx) {
569
+ if (args.method !== JSON_RPC_METHOD.eth_signTypedData_v4) {
570
+ return Promise.reject({
571
+ error: "Safe transactions must be signed using eth_signTypedData_v4"
572
+ });
573
+ }
574
+ }
575
+ await this.walletMessageManager.pingIframe();
576
+ const isTxMethod = args.method === JSON_RPC_METHOD.eth_sendTransaction || args.method === JSON_RPC_METHOD.eth_signTransaction || args.method === JSON_RPC_METHOD.eth_signTypedData_v4 || args.method === JSON_RPC_METHOD.personal_sign;
577
+ const isAsync = isTxMethod && this.asyncTxs || args.async;
578
+ const silkOptions = isAsync || args.withPT ? this.legacyAsyncSigning ? {
579
+ // v1 SDK protocol: send asyncSigning instead of async
580
+ asyncSigning: isAsync || void 0,
581
+ withPT: args.withPT
582
+ } : {
583
+ async: isAsync,
584
+ withPT: args.withPT
585
+ } : void 0;
586
+ const response = await handleWalletRequestAndResponse(
587
+ args,
588
+ rpcMethodRequiresUI(args.method),
589
+ this.walletMessageManager,
590
+ this.internalEventEmitter,
591
+ silkOptions
592
+ );
593
+ if ((args.method === JSON_RPC_METHOD.wallet_switchEthereumChain || args.method === JSON_RPC_METHOD.wallet_addEthereumChain) && response === null) {
594
+ this.emit(
595
+ "chainChanged",
596
+ (_b = (_a = args.params) == null ? void 0 : _a[0]) == null ? void 0 : _b.chainId
597
+ );
598
+ try {
599
+ const accounts = await this.request({
600
+ method: "eth_accounts"
601
+ });
602
+ if (accounts && accounts.length > 0) {
603
+ this.currentAccount = accounts[0];
604
+ this.emit("accountsChanged", accounts);
605
+ this.emit("connect", {
606
+ chainId: (_d = (_c = args.params) == null ? void 0 : _c[0]) == null ? void 0 : _d.chainId
607
+ });
608
+ console.log(
609
+ "[EthereumProvider] Re-emitted accounts and connect after chain switch:",
610
+ {
611
+ accounts,
612
+ chainId: (_f = (_e = args.params) == null ? void 0 : _e[0]) == null ? void 0 : _f.chainId
613
+ }
614
+ );
615
+ }
616
+ } catch (error) {
617
+ console.warn(
618
+ "[EthereumProvider] Failed to get accounts after chain switch:",
619
+ error
620
+ );
621
+ if (this.currentAccount) {
622
+ this.emit("accountsChanged", [this.currentAccount]);
623
+ this.emit("connect", {
624
+ chainId: (_h = (_g = args.params) == null ? void 0 : _g[0]) == null ? void 0 : _h.chainId
625
+ });
626
+ }
627
+ }
628
+ }
629
+ return response;
630
+ }
631
+ async login(customProvider) {
632
+ var _a;
633
+ if (typeof window === "undefined" || typeof document === "undefined") {
634
+ return null;
635
+ }
636
+ if (((_a = this.config.authenticationMethods) == null ? void 0 : _a.includes("wallet")) && !this.walletConnectProvider) {
637
+ await this.initializeWalletConnect();
638
+ }
639
+ const provider = customProvider || window.ethereum;
640
+ const providerWalletName = provider && isMetaMask(provider) ? "MetaMask" : "Browser Wallet";
641
+ await this.walletMessageManager.pingIframe();
642
+ const rawResponse = await handleWalletRequestAndResponse(
643
+ { method: SILK_METHOD2.login, params: [providerWalletName] },
644
+ true,
645
+ this.walletMessageManager,
646
+ this.internalEventEmitter
647
+ );
648
+ const loginMethod = normalizeLoginResponse(rawResponse);
649
+ if (loginMethod === null) {
650
+ return null;
651
+ }
652
+ switch (loginMethod) {
653
+ case "waap":
654
+ case "human":
655
+ localStorage.setItem(`${window.location.origin}-connected`, "waap");
656
+ this.setupWaaP();
657
+ break;
658
+ case "injected":
659
+ if (provider) {
660
+ localStorage.setItem(
661
+ `${window.location.origin}-connected`,
662
+ "injected"
663
+ );
664
+ this.setupInjectedWallet(provider);
665
+ }
666
+ break;
667
+ case "walletconnect": {
668
+ localStorage.setItem(
669
+ `${window.location.origin}-connected`,
670
+ "walletconnect"
671
+ );
672
+ if (!SilkWalletConnect.isConnected()) {
673
+ await this.walletConnectProvider.open({ view: "Connect" });
674
+ await SilkWalletConnect.listenToAccountChangeEvent();
675
+ }
676
+ const wcProvider = SilkWalletConnect.getWalletProvider();
677
+ this.setupWalletConnect(wcProvider);
678
+ break;
679
+ }
680
+ }
681
+ return loginMethod;
682
+ }
683
+ async logout() {
684
+ await this.walletMessageManager.pingIframe();
685
+ this.cleanupInvalidLoginState();
686
+ try {
687
+ if (this.walletConnectProvider) {
688
+ await this.walletConnectProvider.disconnect();
689
+ }
690
+ } catch (error) {
691
+ console.error("Error disconnecting from WalletConnect:", error);
692
+ }
693
+ return handleWalletRequestAndResponse(
694
+ { method: SILK_METHOD2.logout },
695
+ false,
696
+ this.walletMessageManager,
697
+ this.internalEventEmitter
698
+ );
699
+ }
700
+ cleanupInvalidLoginState() {
701
+ try {
702
+ localStorage.removeItem(`${window.location.origin}-connected`);
703
+ } catch (error) {
704
+ console.warn("Could not clean up login state:", error);
705
+ }
706
+ }
707
+ /**
708
+ * Helper method to set up window.waap for WaaP
709
+ */
710
+ setupWaaP() {
711
+ const provider = {
712
+ ...this.persistedMethods,
713
+ isWaaP: true,
714
+ on: this.on.bind(this),
715
+ removeListener: this.removeListener.bind(this),
716
+ request: this.request.bind(this)
717
+ };
718
+ window.silk = provider;
719
+ window.waap = provider;
720
+ }
721
+ /**
722
+ * Helper method to set up window.silk for injected wallets (e.g., MetaMask)
723
+ */
724
+ setupInjectedWallet(provider) {
725
+ var _a, _b;
726
+ const injectedProvider = {
727
+ ...this.persistedMethods,
728
+ ...provider,
729
+ isSilk: true,
730
+ connected: provider.connected ?? false,
731
+ on: ((_a = provider.on) == null ? void 0 : _a.bind(provider)) ?? (() => {
732
+ }),
733
+ removeListener: ((_b = provider.removeListener) == null ? void 0 : _b.bind(provider)) ?? (() => {
734
+ }),
735
+ request: provider.request.bind(provider)
736
+ };
737
+ window.silk = injectedProvider;
738
+ window.waap = injectedProvider;
739
+ }
740
+ /**
741
+ * Helper method to set up window.silk for WalletConnect
742
+ */
743
+ setupWalletConnect(provider) {
744
+ var _a, _b;
745
+ const walletConnectProvider = {
746
+ ...this.persistedMethods,
747
+ ...provider,
748
+ isSilk: true,
749
+ connected: true,
750
+ on: ((_a = provider.on) == null ? void 0 : _a.bind(provider)) ?? (() => {
751
+ }),
752
+ removeListener: ((_b = provider.removeListener) == null ? void 0 : _b.bind(provider)) ?? (() => {
753
+ }),
754
+ request: provider.request.bind(provider)
755
+ };
756
+ window.silk = walletConnectProvider;
757
+ window.waap = walletConnectProvider;
758
+ }
759
+ /**
760
+ * Helper method to set up window.silk for auto-connect with injected wallets
761
+ */
762
+ setupAutoConnectInjected(provider) {
763
+ var _a, _b, _c;
764
+ const injectedProvider = {
765
+ ...this.persistedMethods,
766
+ ...provider,
767
+ isSilk: false,
768
+ // @ts-ignore
769
+ connected: ((_a = provider.isConnected) == null ? void 0 : _a.call(provider)) ?? false,
770
+ // @ts-ignore
771
+ on: ((_b = provider.on) == null ? void 0 : _b.bind(provider)) ?? (() => {
772
+ }),
773
+ removeListener: (
774
+ // @ts-ignore
775
+ ((_c = provider.removeListener) == null ? void 0 : _c.bind(provider)) ?? (() => {
776
+ })
777
+ ),
778
+ // @ts-ignore
779
+ request: provider.request.bind(provider)
780
+ };
781
+ window.silk = injectedProvider;
782
+ window.waap = injectedProvider;
783
+ }
784
+ /**
785
+ * Helper method to set up window.silk for auto-connect with WalletConnect
786
+ */
787
+ setupAutoConnectWalletConnect(provider) {
788
+ var _a, _b;
789
+ const walletConnectProvider = {
790
+ ...this.persistedMethods,
791
+ ...provider,
792
+ isSilk: false,
793
+ connected: true,
794
+ on: ((_a = provider.on) == null ? void 0 : _a.bind(provider)) ?? (() => {
795
+ }),
796
+ removeListener: ((_b = provider.removeListener) == null ? void 0 : _b.bind(provider)) ?? (() => {
797
+ }),
798
+ request: provider.request.bind(provider)
799
+ };
800
+ window.silk = walletConnectProvider;
801
+ window.waap = walletConnectProvider;
802
+ }
803
+ /**
804
+ * Attempts to auto-connect using previously stored login method
805
+ * @param method - The RPC method being called
806
+ * @returns Promise<unknown> if auto-connect succeeds, null if it should fall through to normal flow
807
+ */
808
+ async attemptAutoConnect(method) {
809
+ if (method !== "eth_requestAccounts" && method !== "eth_accounts") {
810
+ return null;
811
+ }
812
+ this.walletMessageManager.pingIframe().then(async () => {
813
+ await handleWalletRequestAndResponse(
814
+ {
815
+ method: SILK_METHOD2.auto_conn,
816
+ params: [window.location.origin]
817
+ },
818
+ false,
819
+ this.walletMessageManager,
820
+ this.internalEventEmitter
821
+ );
822
+ });
823
+ const loginMethod = this.getLoginMethod();
824
+ if (loginMethod === "injected" && window.ethereum) {
825
+ try {
826
+ this.setupAutoConnectInjected(window.ethereum);
827
+ return window.ethereum.request({
828
+ method: "eth_requestAccounts"
829
+ });
830
+ } catch (error) {
831
+ console.warn("Injected wallet auto-connect failed:", error);
832
+ this.cleanupInvalidLoginState();
833
+ return null;
834
+ }
835
+ } else if (loginMethod === "walletconnect") {
836
+ try {
837
+ if (!this.walletConnectProvider) {
838
+ this.walletConnectProvider = await SilkWalletConnect.getInstance();
839
+ }
840
+ const isConnected = await SilkWalletConnect.waitForReadyAndCheckConnection();
841
+ if (isConnected) {
842
+ const provider = SilkWalletConnect.getWalletProvider();
843
+ this.setupAutoConnectWalletConnect(provider);
844
+ return provider.request({
845
+ method: "eth_requestAccounts"
846
+ });
847
+ } else {
848
+ console.log(
849
+ "WalletConnect not connected, cleaning up and falling through to normal flow"
850
+ );
851
+ this.cleanupInvalidLoginState();
852
+ return null;
853
+ }
854
+ } catch (error) {
855
+ console.warn("WalletConnect auto-connect failed:", error);
856
+ this.cleanupInvalidLoginState();
857
+ return null;
858
+ }
859
+ }
860
+ return null;
861
+ }
862
+ getLoginMethod() {
863
+ if (typeof window === "undefined" || typeof localStorage === "undefined") {
864
+ return null;
865
+ }
866
+ try {
867
+ const stored = localStorage.getItem(`${window.location.origin}-connected`);
868
+ if (!stored) {
869
+ return null;
870
+ }
871
+ if (!["waap", "human", "injected", "walletconnect"].includes(stored)) {
872
+ this.cleanupInvalidLoginState();
873
+ return null;
874
+ }
875
+ switch (stored) {
876
+ case "injected":
877
+ if (!window.ethereum) {
878
+ this.cleanupInvalidLoginState();
879
+ return null;
880
+ }
881
+ return "injected";
882
+ case "walletconnect":
883
+ try {
884
+ if (!SilkWalletConnect.isConnected()) {
885
+ this.cleanupInvalidLoginState();
886
+ return null;
887
+ }
888
+ return "walletconnect";
889
+ } catch (error) {
890
+ this.cleanupInvalidLoginState();
891
+ return null;
892
+ }
893
+ case "waap":
894
+ return "waap";
895
+ case "human":
896
+ return "human";
897
+ default:
898
+ this.cleanupInvalidLoginState();
899
+ return null;
900
+ }
901
+ } catch (error) {
902
+ console.warn("Error checking login method:", error);
903
+ this.cleanupInvalidLoginState();
904
+ return null;
905
+ }
906
+ }
907
+ async toggleDarkMode() {
908
+ this.config.styles.darkMode = !this.config.styles.darkMode;
909
+ this.walletMessageManager.pingIframe().then(() => {
910
+ return handleWalletRequestAndResponse(
911
+ {
912
+ method: SILK_METHOD2.set_custom_config,
913
+ params: [this.config]
914
+ },
915
+ false,
916
+ this.walletMessageManager,
917
+ this.internalEventEmitter
918
+ );
919
+ }).catch((error) => {
920
+ console.error("Error setting custom config in Silk iframe:", error);
921
+ });
922
+ }
923
+ async safe() {
924
+ this.walletMessageManager.pingIframe().then(() => {
925
+ return handleWalletRequestAndResponse(
926
+ { method: SILK_METHOD2.safe },
927
+ true,
928
+ this.walletMessageManager,
929
+ this.internalEventEmitter
930
+ );
931
+ });
932
+ }
933
+ async orcid() {
934
+ this.walletMessageManager.pingIframe().then(() => {
935
+ return handleWalletRequestAndResponse(
936
+ { method: SILK_METHOD2.orcid },
937
+ true,
938
+ this.walletMessageManager,
939
+ this.internalEventEmitter
940
+ );
941
+ });
942
+ }
943
+ /**
944
+ * INTERNAL METHOD: Gas tank administration operations
945
+ * This method is ONLY accessible from the Dev Portal domain
946
+ * It's not included in the public typing to hide it from regular dApps
947
+ */
948
+ async portal(feature, operation, payload) {
949
+ await this.walletMessageManager.pingIframe();
950
+ let methodName;
951
+ switch (operation) {
952
+ case "get":
953
+ methodName = feature === "gastank" ? SILK_METHOD2.gastank_get_settings : SILK_METHOD2.customization_get;
954
+ break;
955
+ case "update":
956
+ methodName = feature === "gastank" ? SILK_METHOD2.gastank_update_settings : SILK_METHOD2.customization_update;
957
+ break;
958
+ case "topup":
959
+ methodName = SILK_METHOD2.gastank_topup;
960
+ break;
961
+ case "init":
962
+ methodName = SILK_METHOD2.project_init;
963
+ break;
964
+ }
965
+ const interactionRequired = operation !== "get" && feature !== "customization";
966
+ return handleWalletRequestAndResponse(
967
+ {
968
+ method: methodName,
969
+ params: [payload, window.location.origin]
970
+ },
971
+ interactionRequired,
972
+ // Only open modal for update operations
973
+ this.walletMessageManager,
974
+ this.internalEventEmitter
975
+ );
976
+ }
977
+ async requestEmail() {
978
+ await this.walletMessageManager.pingIframe();
979
+ return handleWalletRequestAndResponse(
980
+ { method: SILK_METHOD2.silk_requestEmail },
981
+ true,
982
+ this.walletMessageManager,
983
+ this.internalEventEmitter
984
+ );
985
+ }
986
+ /**
987
+ * Request a Permission Token from the user.
988
+ * Allows pre-authorized transactions without individual confirmations.
989
+ * @param params - Permission token parameters (allowed addresses, chain, limits, expiry)
990
+ * @returns Promise<RequestPermissionTokenResult>
991
+ */
992
+ async requestPermissionToken(params) {
993
+ await this.walletMessageManager.pingIframe();
994
+ return handleWalletRequestAndResponse(
995
+ {
996
+ method: SILK_METHOD2.waap_requestPermissionToken,
997
+ params: [params]
998
+ },
999
+ true,
1000
+ // Requires UI for user approval
1001
+ this.walletMessageManager,
1002
+ this.internalEventEmitter
1003
+ );
1004
+ }
1005
+ /**
1006
+ * Prompt the user to mint a Zeronym SBT.
1007
+ * @returns string or null - The address of the owner of the SBT, or null
1008
+ * if the user already minted the SBT.
1009
+ */
1010
+ async requestSBT(type) {
1011
+ await this.walletMessageManager.pingIframe();
1012
+ return handleWalletRequestAndResponse(
1013
+ {
1014
+ method: SILK_METHOD2.silk_requestSbt,
1015
+ params: [type]
1016
+ },
1017
+ true,
1018
+ this.walletMessageManager,
1019
+ this.internalEventEmitter
1020
+ );
1021
+ }
1022
+ };
1023
+
1024
+ // src/ui/WaapComponent.ts
1025
+ var WAAP_COMPONENT_TAG_NAME = "waap-wallet";
1026
+ var WAAP_COMPONENT_CONTAINER_ID = "waap-component-container";
1027
+ var isBrowser = typeof window !== "undefined" && typeof document !== "undefined" && typeof HTMLElement !== "undefined";
1028
+ var WaapWalletElement;
1029
+ if (isBrowser) {
1030
+ WaapWalletElement = class extends HTMLElement {
1031
+ constructor() {
1032
+ super();
1033
+ if (!this.style.display || this.style.display === "") {
1034
+ this.style.display = "flex";
1035
+ this.style.alignItems = "center";
1036
+ this.style.justifyContent = "center";
1037
+ }
1038
+ if (!this.style.width || this.style.width === "") {
1039
+ this.style.width = "100%";
1040
+ }
1041
+ if (!this.style.height || this.style.height === "") {
1042
+ this.style.height = "100%";
1043
+ }
1044
+ this.id = WAAP_COMPONENT_CONTAINER_ID;
1045
+ }
1046
+ connectedCallback() {
1047
+ this.setAttribute("data-waap-mounted", "true");
1048
+ }
1049
+ disconnectedCallback() {
1050
+ this.removeAttribute("data-waap-mounted");
1051
+ }
1052
+ };
1053
+ if (typeof customElements !== "undefined" && !customElements.get(WAAP_COMPONENT_TAG_NAME)) {
1054
+ customElements.define(WAAP_COMPONENT_TAG_NAME, WaapWalletElement);
1055
+ }
1056
+ } else {
1057
+ WaapWalletElement = class {
1058
+ };
1059
+ }
1060
+ function hasWaapComponent() {
1061
+ if (!isBrowser) return false;
1062
+ return !!document.getElementById(WAAP_COMPONENT_CONTAINER_ID) || !!document.querySelector(WAAP_COMPONENT_TAG_NAME);
1063
+ }
1064
+ function getWaapComponentContainer() {
1065
+ if (!isBrowser) return null;
1066
+ return document.getElementById(WAAP_COMPONENT_CONTAINER_ID) || document.querySelector(WAAP_COMPONENT_TAG_NAME);
1067
+ }
1068
+
1069
+ // src/ui/index.ts
1070
+ var LEGACY_IFRAME_CONTAINER_ID = "silk-wallet-iframe-container";
1071
+ var LEGACY_IFRAME_WRAPPER_ID = "silk-wallet-iframe-wrapper";
1072
+ var LEGACY_IFRAME_ID = "silk-wallet-iframe";
1073
+ var NEW_IFRAME_CONTAINER_ID = "waap-wallet-iframe-container";
1074
+ var NEW_IFRAME_WRAPPER_ID = "waap-wallet-iframe-wrapper";
1075
+ var NEW_IFRAME_ID = "waap-wallet-iframe";
1076
+ var getIframeContainer = () => {
1077
+ return document.getElementById(NEW_IFRAME_CONTAINER_ID) || document.getElementById(LEGACY_IFRAME_CONTAINER_ID);
1078
+ };
1079
+ var getIframeWrapper = () => {
1080
+ return document.getElementById(NEW_IFRAME_WRAPPER_ID) || document.getElementById(LEGACY_IFRAME_WRAPPER_ID);
1081
+ };
1082
+ var getIframe = () => {
1083
+ return document.getElementById(NEW_IFRAME_ID) || document.getElementById(LEGACY_IFRAME_ID);
1084
+ };
1085
+ var iframeContainerId = NEW_IFRAME_CONTAINER_ID;
1086
+ var iframeWrapperId = NEW_IFRAME_WRAPPER_ID;
1087
+ var iframeId = NEW_IFRAME_ID;
1088
+ var createIframeElement = (useStaging) => {
1089
+ const iframe = window.document.createElement("iframe");
1090
+ iframe.id = iframeId;
1091
+ iframe.src = `${useStaging ? silkWalletAppOrigin2Staging2 : silkWalletAppOrigin22}/iframe`;
1092
+ console.log("iframe.src: ", iframe.src);
1093
+ iframe.style.width = "100%";
1094
+ iframe.style.height = "100%";
1095
+ iframe.style.border = "none";
1096
+ iframe.style.borderRadius = "24px";
1097
+ iframe.style.backgroundColor = "transparent";
1098
+ iframe.style.background = "transparent";
1099
+ iframe.style.padding = "0";
1100
+ iframe.style.margin = "0";
1101
+ return iframe;
1102
+ };
1103
+ var setupIframeMessageListener = (useStaging, iframe) => {
1104
+ const handleIframeMessage = (event) => {
1105
+ const expectedOrigin = useStaging ? silkWalletAppOrigin2Staging2 : silkWalletAppOrigin22;
1106
+ if (event.origin !== expectedOrigin) return;
1107
+ if (!event.data || typeof event.data !== "object") return;
1108
+ if (event.data.type !== "silk-iframe-size") return;
1109
+ const contentHeight = event.data.height;
1110
+ const contentWidth = event.data.width;
1111
+ const maxDimension = 2e3;
1112
+ const minDimension = 50;
1113
+ if (typeof contentHeight !== "number" || typeof contentWidth !== "number")
1114
+ return;
1115
+ if (contentHeight < minDimension || contentHeight > maxDimension) return;
1116
+ if (contentWidth < minDimension || contentWidth > maxDimension) return;
1117
+ if (!Number.isFinite(contentHeight) || !Number.isFinite(contentWidth))
1118
+ return;
1119
+ const iframeWrapper = getIframeWrapper();
1120
+ if (!iframeWrapper) return;
1121
+ iframeWrapper.style.height = `${Math.floor(contentHeight)}px`;
1122
+ iframeWrapper.style.width = `${Math.floor(contentWidth)}px`;
1123
+ };
1124
+ window.addEventListener("message", handleIframeMessage);
1125
+ iframe.__silkCleanup = () => {
1126
+ window.removeEventListener("message", handleIframeMessage);
1127
+ };
1128
+ };
1129
+ var createComponentModeIframe = (useStaging) => {
1130
+ const componentContainer = getWaapComponentContainer();
1131
+ if (!componentContainer) {
1132
+ throw new Error("WaaP component not found in DOM");
1133
+ }
1134
+ if (getIframe()) {
1135
+ return;
1136
+ }
1137
+ const iframeWrapper = window.document.createElement("div");
1138
+ iframeWrapper.id = iframeWrapperId;
1139
+ iframeWrapper.style.position = "relative";
1140
+ iframeWrapper.style.display = "flex";
1141
+ iframeWrapper.style.alignItems = "center";
1142
+ iframeWrapper.style.justifyContent = "center";
1143
+ iframeWrapper.style.padding = "0";
1144
+ iframeWrapper.style.margin = "0";
1145
+ iframeWrapper.style.height = "600px";
1146
+ iframeWrapper.style.width = "380px";
1147
+ const iframe = createIframeElement(useStaging);
1148
+ setupIframeMessageListener(useStaging, iframe);
1149
+ setTimeout(() => {
1150
+ const wrapper = getIframeWrapper();
1151
+ if (wrapper) {
1152
+ wrapper.style.height = "600px";
1153
+ wrapper.style.width = "380px";
1154
+ }
1155
+ }, 100);
1156
+ iframeWrapper.appendChild(iframe);
1157
+ componentContainer.appendChild(iframeWrapper);
1158
+ };
1159
+ var createModalModeIframe = (useStaging) => {
1160
+ if (getIframeContainer()) {
1161
+ return;
1162
+ }
1163
+ const container = window.document.createElement("div");
1164
+ container.id = iframeContainerId;
1165
+ container.style.position = "fixed";
1166
+ container.style.top = "0";
1167
+ container.style.left = "0";
1168
+ container.style.right = "0";
1169
+ container.style.bottom = "0";
1170
+ container.style.width = "100%";
1171
+ container.style.height = "100%";
1172
+ container.style.display = "flex";
1173
+ container.style.alignItems = "center";
1174
+ container.style.justifyContent = "center";
1175
+ container.style.backgroundColor = "rgba(0, 0, 0, 0.5)";
1176
+ container.style.zIndex = "9999999999";
1177
+ container.style.display = "none";
1178
+ const iframeWrapper = window.document.createElement("div");
1179
+ iframeWrapper.id = iframeWrapperId;
1180
+ iframeWrapper.style.position = "relative";
1181
+ iframeWrapper.style.display = "flex";
1182
+ iframeWrapper.style.alignItems = "center";
1183
+ iframeWrapper.style.justifyContent = "center";
1184
+ iframeWrapper.style.padding = "0";
1185
+ iframeWrapper.style.margin = "0";
1186
+ iframeWrapper.style.height = "600px";
1187
+ iframeWrapper.style.width = "380px";
1188
+ container.appendChild(iframeWrapper);
1189
+ const iframe = createIframeElement(useStaging);
1190
+ setupIframeMessageListener(useStaging, iframe);
1191
+ setTimeout(() => {
1192
+ const wrapper = getIframeWrapper();
1193
+ if (wrapper) {
1194
+ wrapper.style.height = "600px";
1195
+ wrapper.style.width = "380px";
1196
+ }
1197
+ }, 100);
1198
+ iframeWrapper.appendChild(iframe);
1199
+ window.document.body.appendChild(container);
1200
+ };
1201
+ var createSilkIframe = (useStaging) => {
1202
+ if (hasWaapComponent()) {
1203
+ createComponentModeIframe(useStaging);
1204
+ } else {
1205
+ createModalModeIframe(useStaging);
1206
+ }
1207
+ };
1208
+ var initWaaP = (params = {}) => {
1209
+ createSilkIframe(!!params.useStaging);
1210
+ const iframe = getIframe();
1211
+ if (!iframe) {
1212
+ throw new Error("WaaP iframe does not exist on page");
1213
+ }
1214
+ const isComponentMode = hasWaapComponent();
1215
+ if (params.walletConnectProjectId) {
1216
+ SilkWalletConnect.setProjectId(params.walletConnectProjectId);
1217
+ }
1218
+ const { referralCode, config, project, asyncTxs, asyncSigning } = params;
1219
+ if (asyncSigning && !asyncTxs) {
1220
+ console.warn(
1221
+ "[WaaP SDK] `asyncSigning` is deprecated. Use `asyncTxs` instead."
1222
+ );
1223
+ }
1224
+ const contentWindow = iframe.contentWindow;
1225
+ const isLegacyAsyncSigning = !!asyncSigning && !asyncTxs;
1226
+ const silkEthereumProvider = new EthereumProvider(
1227
+ contentWindow,
1228
+ referralCode,
1229
+ config || {},
1230
+ project || {},
1231
+ params.useStaging,
1232
+ asyncTxs || asyncSigning || false,
1233
+ isLegacyAsyncSigning
1234
+ );
1235
+ let currentMode = isComponentMode ? "component" : "modal";
1236
+ silkEthereumProvider.uiMessageManager.on("show_modal" /* show_modal */, () => {
1237
+ const nowComponentMode = hasWaapComponent();
1238
+ const newMode = nowComponentMode ? "component" : "modal";
1239
+ const iframeWrapper = getIframeWrapper();
1240
+ if (newMode !== currentMode && iframeWrapper) {
1241
+ currentMode = newMode;
1242
+ if (nowComponentMode) {
1243
+ const componentContainer = getWaapComponentContainer();
1244
+ if (componentContainer) {
1245
+ componentContainer.appendChild(iframeWrapper);
1246
+ }
1247
+ } else {
1248
+ let modalContainer = getIframeContainer();
1249
+ if (!modalContainer) {
1250
+ modalContainer = window.document.createElement("div");
1251
+ modalContainer.id = iframeContainerId;
1252
+ modalContainer.style.position = "fixed";
1253
+ modalContainer.style.top = "0";
1254
+ modalContainer.style.left = "0";
1255
+ modalContainer.style.right = "0";
1256
+ modalContainer.style.bottom = "0";
1257
+ modalContainer.style.width = "100%";
1258
+ modalContainer.style.height = "100%";
1259
+ modalContainer.style.display = "flex";
1260
+ modalContainer.style.alignItems = "center";
1261
+ modalContainer.style.justifyContent = "center";
1262
+ modalContainer.style.backgroundColor = "rgba(0, 0, 0, 0.5)";
1263
+ modalContainer.style.zIndex = "9999999999";
1264
+ window.document.body.appendChild(modalContainer);
1265
+ }
1266
+ modalContainer.appendChild(iframeWrapper);
1267
+ }
1268
+ }
1269
+ const container = getIframeContainer();
1270
+ if (nowComponentMode && iframeWrapper) {
1271
+ iframeWrapper.style.display = "flex";
1272
+ } else if (container) {
1273
+ container.style.display = "flex";
1274
+ }
1275
+ });
1276
+ silkEthereumProvider.uiMessageManager.on("hide_modal" /* hide_modal */, () => {
1277
+ const isComponentMode2 = hasWaapComponent();
1278
+ const iframeWrapper = getIframeWrapper();
1279
+ const container = getIframeContainer();
1280
+ if (isComponentMode2 && iframeWrapper) {
1281
+ iframeWrapper.style.display = "none";
1282
+ } else if (container) {
1283
+ container.style.display = "none";
1284
+ }
1285
+ });
1286
+ window.silk = silkEthereumProvider;
1287
+ window.waap = silkEthereumProvider;
1288
+ return silkEthereumProvider;
1289
+ };
1290
+
1291
+ // src/lib/provider/EthereumProviderExtension.ts
1292
+ import {
1293
+ JSON_RPC_METHOD as JSON_RPC_METHOD2,
1294
+ SILK_METHOD as SILK_METHOD3
1295
+ } from "@human.tech/waap-interface-core";
1296
+ import { EventEmitter as EventEmitter3 } from "events";
1297
+ var EthereumProviderExtension = class extends EventEmitter3 {
1298
+ isSilk = true;
1299
+ connected = false;
1300
+ config;
1301
+ constructor(customConfig) {
1302
+ super();
1303
+ this.config = {
1304
+ ...defaultConfig,
1305
+ ...customConfig || {}
1306
+ };
1307
+ }
1308
+ // Send a message to the background script via `chrome.runtime.sendMessage`
1309
+ sendToExtension(args) {
1310
+ return new Promise((resolve, reject) => {
1311
+ window.postMessage({ type: "FROM_PAGE", request: args }, "*");
1312
+ window.addEventListener("message", (event) => {
1313
+ if (event.data.type === "FROM_EXTENSION") {
1314
+ if (event.data.error) reject(event.data.error);
1315
+ else resolve(event.data.result);
1316
+ }
1317
+ });
1318
+ });
1319
+ }
1320
+ // EIP-1193 `request` method implementation
1321
+ async request(args) {
1322
+ var _a, _b;
1323
+ if (!Object.keys(JSON_RPC_METHOD2).includes(args.method)) {
1324
+ return Promise.reject({ error: `Not implemented (${args.method})` });
1325
+ }
1326
+ const response = await this.sendToExtension(args);
1327
+ if ((args.method === JSON_RPC_METHOD2.wallet_switchEthereumChain || args.method === JSON_RPC_METHOD2.wallet_addEthereumChain) && response === null) {
1328
+ this.emit(
1329
+ "chainChanged",
1330
+ (_b = (_a = args.params) == null ? void 0 : _a[0]) == null ? void 0 : _b.chainId
1331
+ );
1332
+ }
1333
+ return response;
1334
+ }
1335
+ // Enable method that dApps use to request accounts
1336
+ async enable() {
1337
+ return this.request({ method: "eth_requestAccounts" });
1338
+ }
1339
+ // Check if the provider is connected
1340
+ isConnected() {
1341
+ return this.connected;
1342
+ }
1343
+ // Example of a custom method to handle login requests
1344
+ async login() {
1345
+ return this.sendToExtension({ method: SILK_METHOD3.login });
1346
+ }
1347
+ // Example of requesting an SBT (Soulbound Token)
1348
+ async requestSBT(type) {
1349
+ return this.sendToExtension({
1350
+ method: SILK_METHOD3.silk_requestSbt,
1351
+ params: [type]
1352
+ });
1353
+ }
1354
+ // Example of toggling dark mode as part of custom config
1355
+ async toggleDarkMode() {
1356
+ this.config.styles.darkMode = !this.config.styles.darkMode;
1357
+ await this.sendToExtension({
1358
+ method: SILK_METHOD3.set_custom_config,
1359
+ params: [this.config]
1360
+ });
1361
+ }
1362
+ async safe() {
1363
+ return this.sendToExtension({ method: SILK_METHOD3.safe });
1364
+ }
1365
+ };
1366
+
1367
+ // src/lib/sui/SuiWallet.ts
1368
+ import { EventEmitter as EventEmitter4 } from "events";
1369
+ import {
1370
+ SILK_METHOD as SILK_METHOD4
1371
+ } from "@human.tech/waap-interface-core";
1372
+ var WAAP_ICON = "data:image/webp;base64,UklGRpoDAABXRUJQVlA4WAoAAAAQAAAAYwAAYwAAQUxQSDMDAAABJyAQSOFmFxERA8TatqpGoimANbEAxlBAPhSgQP9FyXv3vkcFEf134EZS5DREhGvTM8z0ki8stMRvK4cm8bk5rIu3xNbvkgPk4K6ti5IHquRQnLi6KrdBb81hdyF1jTLM1CW425943iba38/djOcG+dg85p/KXGd/g7+xAzJ2VPWTS8R+q65uA1ZcwG3iZ4urjw9Lh4xn83n3gZmQQ3VMVGEO6D403jdr81Ml1OISAAf7RGImBHISwQ5zCJonTuEyOyP7Sga4cDcjMPgXuiK9cUpaGrIDJtH4iAB25utB8O0DDztOKTr8u9hpX0jrx6k8UM5eAlqsynNxlX9tPRLQEtySKwcDOIDnMqEcek1UnylVNac4r0mlypNvhmCNODlhUXuT4fxTQyrDKY0uyV+gi0iiLLpY76A08C/IX8GQoYb8PcVxK7HkZkT5IjAF4gZicOfJW1ovJjyAlYVPlM6BkkHGI0fniAIZIXC0CbAM92BB8SBznU0ITYLr9XkfnKlDgV8170HGMWwitY51+zxcgkftLD4RLh4HSTIa3QzRWKxlaHZTz21s6GLxnBmjogkVilW4kuaMMMGUfgkZ1JhrBSEANrEDMwucAXgbTqIExY3FYRMdtkQRDFjD6BKtJ2GWTopGRY4P9DBkdE4rp9LJHuYhju45oeVZVv3zNmVdZiIOffHDppOz0Q34p0e/+nXy7JmF1846lmF2ZombLt8pgZpbPNeqpJSVJ0bGd4cH8dUNflNPfdQVXUkC95UQS0ZGfDmOJgjs3IyVOExZBEsxONd080gYK/ftQ2nbYaqGW89Hu7M6avmzXEjhO4G8O8ae8gwWtwZsyp8v8j/ys5H7bM+unOfurO4bbbL4v865Nb8s98Ld2X9yg6tLBQanMP8fhplOMMN8fiNDzTvNOMXGuYzejo12vY7s3clhXwgDPuBIcxi9QZftbKVxAjLCcVQdRxGR1QknhCs3GuieMLzfrrC9RhfJgVpcXRn71nZfEjsiYy/Ca1J7ch0clK64ReH3G/s2cekpP+BIx2YteMvSoLy6G9FCgd1nvF/VoVRtJoNJNLQ0RM3BXY9WgPbcHF78swAAVlA4IEAAAACwBQCdASpkAGQAPpFIoUylpCMiIKgAsBIJaW7hc+AAY2upvcReWAa6m9xF5YBrqb3EXlgGngAA/v81aVcAAAAA";
1373
+ var WaaPSuiWallet = class {
1374
+ name = "WaaP";
1375
+ version = "1.0.0";
1376
+ icon = WAAP_ICON;
1377
+ _accounts = [];
1378
+ _chains = ["sui:mainnet", "sui:testnet", "sui:devnet"];
1379
+ walletMessageManager;
1380
+ uiMessageManager;
1381
+ internalEventEmitter = new EventEmitter4();
1382
+ changeListeners = /* @__PURE__ */ new Set();
1383
+ /**
1384
+ * Creates a new WaaPSuiWallet instance.
1385
+ *
1386
+ * @param iframeWindow - The contentWindow of the WaaP iframe
1387
+ * @param options - Initialization options
1388
+ */
1389
+ constructor(iframeWindow, options = {}) {
1390
+ const useStaging = options.useStaging ?? false;
1391
+ this.walletMessageManager = new WalletMessageManager_default(iframeWindow, useStaging);
1392
+ this.uiMessageManager = new UIMessageManager();
1393
+ if (options.referralCode) {
1394
+ this.walletMessageManager.pingIframe().then(() => {
1395
+ this.postRequestAndWait({
1396
+ method: SILK_METHOD4.set_points_referral_code,
1397
+ params: [options.referralCode],
1398
+ interactionRequired: false
1399
+ }).catch((err) => console.error("Error setting referral code:", err));
1400
+ });
1401
+ }
1402
+ if (options.project) {
1403
+ this.walletMessageManager.pingIframe().then(() => {
1404
+ this.postRequestAndWait({
1405
+ method: SILK_METHOD4.set_project,
1406
+ params: [options.project, window.location.origin],
1407
+ interactionRequired: false
1408
+ }).catch((err) => console.error("Error setting project:", err));
1409
+ });
1410
+ }
1411
+ if (options.config) {
1412
+ this.walletMessageManager.pingIframe().then(() => {
1413
+ this.postRequestAndWait({
1414
+ method: SILK_METHOD4.set_custom_config,
1415
+ params: [options.config],
1416
+ interactionRequired: false
1417
+ }).catch((err) => console.error("Error setting custom config:", err));
1418
+ });
1419
+ }
1420
+ this.walletMessageManager.addListener({
1421
+ handleResponse: (response) => {
1422
+ this.internalEventEmitter.emit(response.id, response);
1423
+ },
1424
+ handleRequest: (request) => {
1425
+ if (request.method === SILK_METHOD4.show_modal) {
1426
+ this.uiMessageManager.emit("show_modal" /* show_modal */);
1427
+ } else if (request.method === SILK_METHOD4.hide_modal) {
1428
+ this.uiMessageManager.emit("hide_modal" /* hide_modal */);
1429
+ }
1430
+ },
1431
+ onAccountChanged: async (newAccount) => {
1432
+ try {
1433
+ const result = await this.refreshAccounts();
1434
+ this.notifyChange({ accounts: result.accounts });
1435
+ } catch (error) {
1436
+ console.error("Failed to refresh Sui accounts:", error);
1437
+ this._accounts = [];
1438
+ this.notifyChange({ accounts: [] });
1439
+ }
1440
+ }
1441
+ });
1442
+ }
1443
+ /**
1444
+ * Refresh accounts by making a silent connect request.
1445
+ * Used internally when account changes are detected.
1446
+ */
1447
+ async refreshAccounts() {
1448
+ var _a;
1449
+ try {
1450
+ await this.walletMessageManager.pingIframe();
1451
+ const response = await this.postRequestAndWait({
1452
+ method: "sui_connect",
1453
+ params: [{ silent: true }],
1454
+ interactionRequired: false
1455
+ });
1456
+ if (response.error) {
1457
+ this._accounts = [];
1458
+ return { accounts: [] };
1459
+ }
1460
+ const accounts = ((_a = response.data) == null ? void 0 : _a.accounts) || [];
1461
+ this._accounts = accounts;
1462
+ return { accounts: this._accounts };
1463
+ } catch (error) {
1464
+ this._accounts = [];
1465
+ return { accounts: [] };
1466
+ }
1467
+ }
1468
+ /**
1469
+ * Supported chains.
1470
+ */
1471
+ get chains() {
1472
+ return this._chains;
1473
+ }
1474
+ /**
1475
+ * Connected accounts.
1476
+ */
1477
+ get accounts() {
1478
+ return this._accounts;
1479
+ }
1480
+ /**
1481
+ * UI message manager for showing/hiding modal.
1482
+ */
1483
+ get ui() {
1484
+ return this.uiMessageManager;
1485
+ }
1486
+ /**
1487
+ * Connect to the wallet.
1488
+ */
1489
+ async connect(input) {
1490
+ var _a;
1491
+ await this.walletMessageManager.pingIframe();
1492
+ const response = await this.postRequestAndWait({
1493
+ method: "sui_connect",
1494
+ params: [input || {}],
1495
+ interactionRequired: !(input == null ? void 0 : input.silent)
1496
+ });
1497
+ if (response.error) {
1498
+ throw new Error(response.error.message || "Failed to connect");
1499
+ }
1500
+ const accounts = ((_a = response.data) == null ? void 0 : _a.accounts) || [];
1501
+ this._accounts = accounts;
1502
+ this.notifyChange({ accounts: this._accounts });
1503
+ return { accounts: this._accounts };
1504
+ }
1505
+ /**
1506
+ * Disconnect from the wallet.
1507
+ */
1508
+ async disconnect() {
1509
+ await this.walletMessageManager.pingIframe();
1510
+ await this.postRequestAndWait({
1511
+ method: "sui_disconnect",
1512
+ params: [],
1513
+ interactionRequired: false
1514
+ });
1515
+ this._accounts = [];
1516
+ this.notifyChange({ accounts: [] });
1517
+ }
1518
+ /**
1519
+ * Sign a personal message.
1520
+ *
1521
+ * @param input - Sign personal message input
1522
+ * @returns Signed message result with bytes and signature
1523
+ */
1524
+ async signPersonalMessage(input) {
1525
+ await this.walletMessageManager.pingIframe();
1526
+ const accountAddress = input.account.address;
1527
+ const isConnected = this._accounts.some((a) => a.address === accountAddress);
1528
+ if (!isConnected) {
1529
+ throw new Error(`Account ${accountAddress} is not connected`);
1530
+ }
1531
+ const response = await this.postRequestAndWait({
1532
+ method: "sui_signPersonalMessage",
1533
+ params: [{
1534
+ message: Array.from(input.message),
1535
+ account: accountAddress,
1536
+ chain: input.chain
1537
+ }],
1538
+ interactionRequired: true
1539
+ });
1540
+ if (response.error) {
1541
+ throw new Error(response.error.message || "Failed to sign message");
1542
+ }
1543
+ return {
1544
+ bytes: response.data.bytes,
1545
+ signature: response.data.signature
1546
+ };
1547
+ }
1548
+ /**
1549
+ * Extract the destination addresses from BCS-serialized Sui transaction bytes.
1550
+ *
1551
+ * Unlike EVM transactions where `to` is a top-level field, Sui transaction
1552
+ * destinations are embedded in BCS-encoded programmable transaction blocks.
1553
+ * We deserialize with Transaction.from() and inspect TransferObjects commands.
1554
+ *
1555
+ * Only TransferObjects destinations are extracted — MoveCall package addresses
1556
+ * are not user-facing recipients and should not be validated against a PT's
1557
+ * allowedAddresses list.
1558
+ *
1559
+ * Returns an empty array if no TransferObjects are found or deserialization fails.
1560
+ */
1561
+ async extractTransferAddresses(txBytes) {
1562
+ try {
1563
+ const { Transaction } = await import("@mysten/sui/transactions");
1564
+ const tx = Transaction.from(txBytes);
1565
+ const data = tx.getData();
1566
+ const addresses = [];
1567
+ for (const command of data.commands) {
1568
+ if (command.$kind !== "TransferObjects") continue;
1569
+ const addrArg = command.TransferObjects.address;
1570
+ if (addrArg.$kind !== "Input") continue;
1571
+ const inputIndex = addrArg.Input;
1572
+ const input = data.inputs[inputIndex];
1573
+ if (!input || input.$kind !== "Pure") continue;
1574
+ const bytes = Uint8Array.from(atob(input.Pure.bytes), (c) => c.charCodeAt(0));
1575
+ if (bytes.length !== 32) continue;
1576
+ const hex = "0x" + Array.from(bytes).map((b) => b.toString(16).padStart(2, "0")).join("");
1577
+ addresses.push(hex);
1578
+ }
1579
+ return addresses;
1580
+ } catch {
1581
+ return [];
1582
+ }
1583
+ }
1584
+ /**
1585
+ * Helper to resolve transaction bytes from various input formats.
1586
+ * If the input is a Transaction/TransactionBlock object, it builds it.
1587
+ */
1588
+ async resolveTransactionBytes(tx, chain = "sui:mainnet") {
1589
+ if (tx instanceof Uint8Array) {
1590
+ return tx;
1591
+ } else if (Array.isArray(tx)) {
1592
+ return new Uint8Array(tx);
1593
+ } else if (typeof tx === "string") {
1594
+ try {
1595
+ return Uint8Array.from(atob(tx), (c) => c.charCodeAt(0));
1596
+ } catch {
1597
+ throw new Error("Transaction string must be base64 encoded bytes. If you have a serialized transaction JSON, please build it to bytes first.");
1598
+ }
1599
+ } else if (tx && typeof tx === "object") {
1600
+ if (typeof tx.build === "function") {
1601
+ try {
1602
+ const { getFullnodeUrl, SuiClient } = await import("@mysten/sui/client");
1603
+ let network = "mainnet";
1604
+ if (chain === "sui:testnet") network = "testnet";
1605
+ else if (chain === "sui:devnet") network = "devnet";
1606
+ else if (chain === "sui:localnet") network = "localnet";
1607
+ const url = getFullnodeUrl(network);
1608
+ const client = new SuiClient({ url });
1609
+ const builtBytes = await tx.build({ client });
1610
+ return builtBytes;
1611
+ } catch (e) {
1612
+ console.warn("[SuiWallet] Failed to build transaction object:", e);
1613
+ throw new Error(`Failed to build transaction: ${e instanceof Error ? e.message : String(e)}`);
1614
+ }
1615
+ }
1616
+ if (typeof tx.serialize === "function") {
1617
+ try {
1618
+ const serialized = await tx.serialize();
1619
+ if (typeof serialized === "string") {
1620
+ return Uint8Array.from(atob(serialized), (c) => c.charCodeAt(0));
1621
+ } else if (serialized instanceof Uint8Array) {
1622
+ return serialized;
1623
+ }
1624
+ } catch (e) {
1625
+ console.warn("[SuiWallet] serialize() failed:", e);
1626
+ }
1627
+ }
1628
+ if (typeof tx.toJSON === "function") {
1629
+ try {
1630
+ const json = await tx.toJSON();
1631
+ if (typeof json === "string") {
1632
+ try {
1633
+ return Uint8Array.from(atob(json), (c) => c.charCodeAt(0));
1634
+ } catch {
1635
+ try {
1636
+ const parsed = JSON.parse(json);
1637
+ if (parsed.bytes && typeof parsed.bytes === "string") {
1638
+ return Uint8Array.from(atob(parsed.bytes), (c) => c.charCodeAt(0));
1639
+ }
1640
+ } catch {
1641
+ }
1642
+ }
1643
+ }
1644
+ } catch (e) {
1645
+ console.warn("[SuiWallet] toJSON() failed:", e);
1646
+ }
1647
+ }
1648
+ if (typeof tx.getData === "function") {
1649
+ try {
1650
+ const data = tx.getData();
1651
+ if (data instanceof Uint8Array) return data;
1652
+ } catch (e) {
1653
+ console.warn("[SuiWallet] getData() failed:", e);
1654
+ }
1655
+ }
1656
+ throw new Error(`Unsupported transaction format. Keys: ${Object.keys(tx).join(", ")}`);
1657
+ } else {
1658
+ throw new Error(`Unsupported transaction format: ${typeof tx}. Please pass Uint8Array bytes or a Transaction object.`);
1659
+ }
1660
+ }
1661
+ /**
1662
+ * Sign a transaction.
1663
+ *
1664
+ * @param input - Sign transaction input with transaction
1665
+ * @returns Signed transaction result with bytes and signature
1666
+ */
1667
+ async signTransaction(input) {
1668
+ await this.walletMessageManager.pingIframe();
1669
+ const accountAddress = input.account.address;
1670
+ const isConnected = this._accounts.some((a) => a.address === accountAddress);
1671
+ if (!isConnected) {
1672
+ throw new Error(`Account ${accountAddress} is not connected`);
1673
+ }
1674
+ const txBytes = await this.resolveTransactionBytes(input.transaction, input.chain);
1675
+ const response = await this.postRequestAndWait({
1676
+ method: "sui_signTransaction",
1677
+ params: [{
1678
+ transaction: Array.from(txBytes),
1679
+ account: accountAddress,
1680
+ chain: input.chain
1681
+ }],
1682
+ interactionRequired: true
1683
+ });
1684
+ if (response.error) {
1685
+ throw new Error(response.error.message || "Failed to sign transaction");
1686
+ }
1687
+ return {
1688
+ bytes: response.data.bytes,
1689
+ signature: response.data.signature
1690
+ };
1691
+ }
1692
+ /**
1693
+ * Sign and execute a transaction.
1694
+ *
1695
+ * @param input - Sign and execute transaction input
1696
+ */
1697
+ async signAndExecuteTransaction(input) {
1698
+ await this.walletMessageManager.pingIframe();
1699
+ const accountAddress = input.account.address;
1700
+ const isConnected = this._accounts.some((a) => a.address === accountAddress);
1701
+ if (!isConnected) {
1702
+ throw new Error(`Account ${accountAddress} is not connected`);
1703
+ }
1704
+ const txBytes = await this.resolveTransactionBytes(input.transaction, input.chain);
1705
+ const toAddresses = await this.extractTransferAddresses(txBytes);
1706
+ const response = await this.postRequestAndWait({
1707
+ method: "sui_signAndExecuteTransaction",
1708
+ params: [{
1709
+ transaction: Array.from(txBytes),
1710
+ account: accountAddress,
1711
+ chain: input.chain,
1712
+ options: input.options,
1713
+ requestType: input.requestType,
1714
+ toAddresses: toAddresses.length > 0 ? toAddresses : void 0
1715
+ }],
1716
+ interactionRequired: true
1717
+ });
1718
+ if (response.error) {
1719
+ throw new Error(response.error.message || "Failed to sign and execute transaction");
1720
+ }
1721
+ return response.data;
1722
+ }
1723
+ /**
1724
+ * Switch the active chain.
1725
+ */
1726
+ async switchChain(input) {
1727
+ await this.walletMessageManager.pingIframe();
1728
+ if (!this._chains.includes(input.chain)) {
1729
+ throw new Error(`Chain ${input.chain} is not supported`);
1730
+ }
1731
+ const response = await this.postRequestAndWait({
1732
+ method: "sui_switchChain",
1733
+ params: [input],
1734
+ interactionRequired: false
1735
+ });
1736
+ if (response.error) {
1737
+ throw new Error(response.error.message || "Failed to switch chain");
1738
+ }
1739
+ this.notifyChange({ chains: this._chains, accounts: this._accounts });
1740
+ }
1741
+ /**
1742
+ * Subscribe to wallet change events.
1743
+ *
1744
+ * @param event - Event name (currently only 'change')
1745
+ * @param listener - Event listener callback
1746
+ * @returns Unsubscribe function
1747
+ */
1748
+ on(event, listener) {
1749
+ if (event === "change") {
1750
+ this.changeListeners.add(listener);
1751
+ return () => {
1752
+ this.changeListeners.delete(listener);
1753
+ };
1754
+ }
1755
+ return () => {
1756
+ };
1757
+ }
1758
+ /**
1759
+ * Wallet Standard features property.
1760
+ * Required by @mysten/wallet-standard registerWallet.
1761
+ */
1762
+ get features() {
1763
+ return {
1764
+ "standard:connect": {
1765
+ version: "1.0.0",
1766
+ connect: this.connect.bind(this)
1767
+ },
1768
+ "standard:disconnect": {
1769
+ version: "1.0.0",
1770
+ disconnect: this.disconnect.bind(this)
1771
+ },
1772
+ "standard:events": {
1773
+ version: "1.0.0",
1774
+ on: this.on.bind(this)
1775
+ },
1776
+ "sui:signPersonalMessage": {
1777
+ version: "1.1.0",
1778
+ signPersonalMessage: this.signPersonalMessage.bind(this)
1779
+ },
1780
+ "sui:signTransaction": {
1781
+ version: "2.0.0",
1782
+ signTransaction: this.signTransaction.bind(this)
1783
+ },
1784
+ "sui:signAndExecuteTransaction": {
1785
+ version: "1.0.0",
1786
+ signAndExecuteTransaction: this.signAndExecuteTransaction.bind(this)
1787
+ },
1788
+ "sui:signTransactionBlock": {
1789
+ version: "2.0.0",
1790
+ signTransactionBlock: this.signTransactionBlock.bind(this)
1791
+ },
1792
+ "sui:signAndExecuteTransactionBlock": {
1793
+ version: "1.0.0",
1794
+ signAndExecuteTransactionBlock: this.signAndExecuteTransactionBlock.bind(this)
1795
+ },
1796
+ "sui:switchChain": {
1797
+ version: "1.0.0",
1798
+ switchChain: this.switchChain.bind(this)
1799
+ }
1800
+ };
1801
+ }
1802
+ /**
1803
+ * Legacy method for signing a transaction block.
1804
+ * Maps to signTransaction.
1805
+ */
1806
+ async signTransactionBlock(input) {
1807
+ return this.signTransaction({
1808
+ transaction: input.transactionBlock,
1809
+ account: input.account,
1810
+ chain: input.chain
1811
+ });
1812
+ }
1813
+ /**
1814
+ * Legacy method for signing and executing a transaction block.
1815
+ * Maps to signAndExecuteTransaction.
1816
+ */
1817
+ async signAndExecuteTransactionBlock(input) {
1818
+ return this.signAndExecuteTransaction({
1819
+ transaction: input.transactionBlock,
1820
+ account: input.account,
1821
+ chain: input.chain,
1822
+ options: input.options,
1823
+ requestType: input.requestType
1824
+ });
1825
+ }
1826
+ /**
1827
+ * Request a Permission Token from the user.
1828
+ * Allows pre-authorised batches of Sui transactions without individual confirmations.
1829
+ *
1830
+ * @param params - Allowed addresses, chainId (e.g. "sui:mainnet"), spend limit, expiry
1831
+ */
1832
+ async requestPermissionToken(params) {
1833
+ await this.walletMessageManager.pingIframe();
1834
+ const response = await this.postRequestAndWait({
1835
+ method: SILK_METHOD4.waap_requestPermissionToken,
1836
+ params: [params],
1837
+ interactionRequired: true
1838
+ });
1839
+ if (response.error) {
1840
+ throw new Error(response.error.message || "Failed to request permission token");
1841
+ }
1842
+ return response.data;
1843
+ }
1844
+ /**
1845
+ * Request the user's email address.
1846
+ *
1847
+ * @returns Promise resolving to the user's email address
1848
+ */
1849
+ async requestEmail() {
1850
+ await this.walletMessageManager.pingIframe();
1851
+ const response = await this.postRequestAndWait({
1852
+ method: SILK_METHOD4.silk_requestEmail,
1853
+ params: [],
1854
+ interactionRequired: true
1855
+ });
1856
+ if (response.error) {
1857
+ throw new Error(response.error.message || "Failed to request email");
1858
+ }
1859
+ return response.data;
1860
+ }
1861
+ /**
1862
+ * Post a request to the iframe and wait for response.
1863
+ */
1864
+ async postRequestAndWait(args) {
1865
+ const id = await this.walletMessageManager.postSilkRequest({
1866
+ method: args.method,
1867
+ params: args.params,
1868
+ interactionRequired: args.interactionRequired
1869
+ });
1870
+ return new Promise((resolve) => {
1871
+ this.internalEventEmitter.once(id, (response) => {
1872
+ resolve(response);
1873
+ });
1874
+ });
1875
+ }
1876
+ /**
1877
+ * Notify all change listeners.
1878
+ */
1879
+ notifyChange(properties) {
1880
+ Array.from(this.changeListeners).forEach((listener) => {
1881
+ listener(properties);
1882
+ });
1883
+ }
1884
+ };
1885
+
1886
+ // src/lib/sui/init.ts
1887
+ import {
1888
+ silkWalletAppOrigin2 as silkWalletAppOrigin23,
1889
+ silkWalletAppOrigin2Staging as silkWalletAppOrigin2Staging3
1890
+ } from "@human.tech/waap-constants";
1891
+ var IFRAME_CONTAINER_ID = "waap-wallet-iframe-container";
1892
+ var IFRAME_ID = "waap-wallet-iframe";
1893
+ var LEGACY_IFRAME_CONTAINER_ID2 = "silk-wallet-iframe-container";
1894
+ var LEGACY_IFRAME_ID2 = "silk-wallet-iframe";
1895
+ var getIframeContainer2 = () => {
1896
+ return document.getElementById(IFRAME_CONTAINER_ID) || document.getElementById(LEGACY_IFRAME_CONTAINER_ID2);
1897
+ };
1898
+ var getIframe2 = () => {
1899
+ return document.getElementById(IFRAME_ID) || document.getElementById(LEGACY_IFRAME_ID2);
1900
+ };
1901
+ var IFRAME_WRAPPER_ID = "waap-wallet-iframe-wrapper";
1902
+ var LEGACY_IFRAME_WRAPPER_ID2 = "silk-wallet-iframe-wrapper";
1903
+ var getIframeWrapper2 = () => {
1904
+ return document.getElementById(IFRAME_WRAPPER_ID) || document.getElementById(LEGACY_IFRAME_WRAPPER_ID2);
1905
+ };
1906
+ var setupIframeMessageListener2 = (useStaging) => {
1907
+ const handleIframeMessage = (event) => {
1908
+ const expectedOrigin = useStaging ? silkWalletAppOrigin2Staging3 : silkWalletAppOrigin23;
1909
+ if (event.origin !== expectedOrigin) return;
1910
+ if (!event.data || typeof event.data !== "object") return;
1911
+ if (event.data.type !== "silk-iframe-size") return;
1912
+ const contentHeight = event.data.height;
1913
+ const contentWidth = event.data.width;
1914
+ const maxDimension = 2e3;
1915
+ const minDimension = 50;
1916
+ if (typeof contentHeight !== "number" || typeof contentWidth !== "number")
1917
+ return;
1918
+ if (contentHeight < minDimension || contentHeight > maxDimension) return;
1919
+ if (contentWidth < minDimension || contentWidth > maxDimension) return;
1920
+ if (!Number.isFinite(contentHeight) || !Number.isFinite(contentWidth))
1921
+ return;
1922
+ const iframeWrapper = getIframeWrapper2();
1923
+ if (!iframeWrapper) return;
1924
+ iframeWrapper.style.height = `${Math.floor(contentHeight)}px`;
1925
+ iframeWrapper.style.width = `${Math.floor(contentWidth)}px`;
1926
+ };
1927
+ window.addEventListener("message", handleIframeMessage);
1928
+ };
1929
+ var createWaapIframe = (useStaging) => {
1930
+ if (getIframeContainer2()) {
1931
+ return;
1932
+ }
1933
+ const container = document.createElement("div");
1934
+ container.id = IFRAME_CONTAINER_ID;
1935
+ container.style.cssText = `
1936
+ position: fixed;
1937
+ top: 0;
1938
+ left: 0;
1939
+ right: 0;
1940
+ bottom: 0;
1941
+ width: 100%;
1942
+ height: 100%;
1943
+ display: none;
1944
+ align-items: center;
1945
+ justify-content: center;
1946
+ background-color: rgba(0, 0, 0, 0.5);
1947
+ z-index: 9999999999;
1948
+ `;
1949
+ const wrapper = document.createElement("div");
1950
+ wrapper.id = IFRAME_WRAPPER_ID;
1951
+ wrapper.style.cssText = `
1952
+ position: relative;
1953
+ display: flex;
1954
+ align-items: center;
1955
+ justify-content: center;
1956
+ padding: 0;
1957
+ margin: 0;
1958
+ height: 600px;
1959
+ width: 380px;
1960
+ `;
1961
+ container.appendChild(wrapper);
1962
+ const iframe = document.createElement("iframe");
1963
+ iframe.id = IFRAME_ID;
1964
+ iframe.src = `${useStaging ? silkWalletAppOrigin2Staging3 : silkWalletAppOrigin23}/iframe`;
1965
+ iframe.style.cssText = `
1966
+ width: 100%;
1967
+ height: 100%;
1968
+ border: none;
1969
+ border-radius: 24px;
1970
+ background: transparent;
1971
+ `;
1972
+ wrapper.appendChild(iframe);
1973
+ setupIframeMessageListener2(useStaging);
1974
+ document.body.appendChild(container);
1975
+ };
1976
+ function initWaaPSui(options = {}) {
1977
+ const useStaging = options.useStaging ?? false;
1978
+ createWaapIframe(useStaging);
1979
+ const container = getIframeContainer2();
1980
+ const iframe = getIframe2();
1981
+ if (!container || !iframe) {
1982
+ throw new Error("Failed to create WaaP iframe");
1983
+ }
1984
+ const contentWindow = iframe.contentWindow;
1985
+ const suiWallet = new WaaPSuiWallet(contentWindow, options);
1986
+ suiWallet.ui.on("show_modal" /* show_modal */, () => {
1987
+ container.style.display = "flex";
1988
+ const dappKitOverlays = document.querySelectorAll('[data-dapp-kit][class*="overlay"]');
1989
+ dappKitOverlays.forEach((overlay) => {
1990
+ overlay.style.display = "none";
1991
+ });
1992
+ });
1993
+ suiWallet.ui.on("hide_modal" /* hide_modal */, () => {
1994
+ container.style.display = "none";
1995
+ const dappKitOverlays = document.querySelectorAll('[data-dapp-kit][class*="overlay"]');
1996
+ dappKitOverlays.forEach((overlay) => {
1997
+ overlay.style.display = "";
1998
+ });
1999
+ });
2000
+ return suiWallet;
2001
+ }
2002
+
2003
+ // src/lib/sui/register.ts
2004
+ import { registerWallet } from "@mysten/wallet-standard";
2005
+ function registerWaaPSuiWallet(iframeWindow, options = {}) {
2006
+ const wallet = new WaaPSuiWallet(iframeWindow, options);
2007
+ registerWallet(wallet);
2008
+ return wallet;
2009
+ }
2010
+
2011
+ // src/index.ts
2012
+ import {
2013
+ SILK_METHOD as SILK_METHOD5,
2014
+ SILK_METHOD as SILK_METHOD6
2015
+ } from "@human.tech/waap-interface-core";
2016
+
2017
+ // src/hooks/useWaapTransaction.ts
2018
+ import { useEffect, useState, useCallback, useRef } from "react";
2019
+ function useWaapTransaction(options) {
2020
+ const [pendingTransactions, setPendingTransactions] = useState(/* @__PURE__ */ new Map());
2021
+ const optionsRef = useRef(options);
2022
+ useEffect(() => {
2023
+ optionsRef.current = options;
2024
+ }, [options]);
2025
+ useEffect(() => {
2026
+ const provider = window.waap || window.silk;
2027
+ if (!provider) {
2028
+ console.warn(
2029
+ "[useWaapTransaction] WaaP provider not found. Make sure initWaaP() was called."
2030
+ );
2031
+ return;
2032
+ }
2033
+ const handleSignComplete = (event) => {
2034
+ var _a, _b;
2035
+ setPendingTransactions((prev) => {
2036
+ const next = new Map(prev);
2037
+ next.set(event.txHash, {
2038
+ status: "signed",
2039
+ txHash: event.txHash,
2040
+ pendingTxId: event.txHash,
2041
+ signature: event.signature,
2042
+ serializedTx: event.serializedTx
2043
+ });
2044
+ return next;
2045
+ });
2046
+ (_b = (_a = optionsRef.current) == null ? void 0 : _a.onSigned) == null ? void 0 : _b.call(_a, event);
2047
+ };
2048
+ const handleTxPending = (event) => {
2049
+ var _a, _b;
2050
+ setPendingTransactions((prev) => {
2051
+ const next = new Map(prev);
2052
+ const existing = next.get(event.txHash);
2053
+ if (existing) {
2054
+ next.set(event.txHash, {
2055
+ ...existing,
2056
+ status: "tx_pending"
2057
+ });
2058
+ }
2059
+ return next;
2060
+ });
2061
+ (_b = (_a = optionsRef.current) == null ? void 0 : _a.onTxPending) == null ? void 0 : _b.call(_a, event);
2062
+ };
2063
+ const handleConfirmed = (event) => {
2064
+ var _a, _b;
2065
+ setPendingTransactions((prev) => {
2066
+ const next = new Map(prev);
2067
+ const existing = next.get(event.txHash);
2068
+ if (existing) {
2069
+ next.set(event.txHash, {
2070
+ ...existing,
2071
+ status: "confirmed",
2072
+ receipt: event.receipt
2073
+ });
2074
+ }
2075
+ return next;
2076
+ });
2077
+ (_b = (_a = optionsRef.current) == null ? void 0 : _a.onConfirmed) == null ? void 0 : _b.call(_a, event);
2078
+ };
2079
+ const handleTxFailed = (event) => {
2080
+ var _a, _b;
2081
+ setPendingTransactions((prev) => {
2082
+ const next = new Map(prev);
2083
+ const existing = next.get(event.txHash);
2084
+ if (existing) {
2085
+ next.set(event.txHash, {
2086
+ ...existing,
2087
+ status: "failed",
2088
+ error: event.error,
2089
+ stage: event.stage
2090
+ });
2091
+ }
2092
+ return next;
2093
+ });
2094
+ (_b = (_a = optionsRef.current) == null ? void 0 : _a.onFailed) == null ? void 0 : _b.call(_a, event);
2095
+ };
2096
+ provider.on("waap_sign_complete", handleSignComplete);
2097
+ provider.on("waap_tx_pending", handleTxPending);
2098
+ provider.on("waap_tx_confirmed", handleConfirmed);
2099
+ provider.on("waap_tx_failed", handleTxFailed);
2100
+ return () => {
2101
+ var _a, _b, _c, _d;
2102
+ (_a = provider.removeListener) == null ? void 0 : _a.call(provider, "waap_sign_complete", handleSignComplete);
2103
+ (_b = provider.removeListener) == null ? void 0 : _b.call(provider, "waap_tx_pending", handleTxPending);
2104
+ (_c = provider.removeListener) == null ? void 0 : _c.call(provider, "waap_tx_confirmed", handleConfirmed);
2105
+ (_d = provider.removeListener) == null ? void 0 : _d.call(provider, "waap_tx_failed", handleTxFailed);
2106
+ };
2107
+ }, []);
2108
+ const sendTransaction = useCallback(
2109
+ async (txRequest) => {
2110
+ const provider = window.waap || window.silk;
2111
+ if (!provider) {
2112
+ throw new Error("WaaP provider not found");
2113
+ }
2114
+ return provider.request({
2115
+ method: "eth_sendTransaction",
2116
+ params: txRequest
2117
+ });
2118
+ },
2119
+ []
2120
+ );
2121
+ const signTransaction = useCallback(
2122
+ async (txRequest) => {
2123
+ const provider = window.waap || window.silk;
2124
+ if (!provider) {
2125
+ throw new Error("WaaP provider not found");
2126
+ }
2127
+ return provider.request({
2128
+ method: "eth_signTransaction",
2129
+ params: txRequest
2130
+ });
2131
+ },
2132
+ []
2133
+ );
2134
+ const isAnyPending = Array.from(pendingTransactions.values()).some(
2135
+ (tx) => tx.status === "signed" || tx.status === "tx_pending"
2136
+ );
2137
+ return {
2138
+ sendTransaction,
2139
+ signTransaction,
2140
+ pendingTransactions,
2141
+ isAnyPending
2142
+ };
2143
+ }
2144
+ export {
2145
+ EthereumProvider,
2146
+ EthereumProviderExtension,
2147
+ SILK_METHOD5 as SILK_METHOD,
2148
+ SilkWalletConnect,
2149
+ UIMessageManager,
2150
+ UI_EVENT_NAMES,
2151
+ SILK_METHOD6 as WAAP_METHOD,
2152
+ WaapWalletElement as WaaP,
2153
+ WaaPSuiWallet,
2154
+ SilkWalletConnect as WaaPWalletConnect,
2155
+ WalletMessageManager,
2156
+ handleWalletRequestAndResponse,
2157
+ initWaaP,
2158
+ initWaaPSui,
2159
+ registerWaaPSuiWallet,
2160
+ rpcMethodRequiresUI,
2161
+ useWaapTransaction
2162
+ };