@flarenetwork/multichain-wallet-connector 0.0.2-rc.24 → 0.0.2-rc.26

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -16,7 +16,7 @@ A TypeScript library for connecting to multiple blockchain wallets across EVM an
16
16
  ## Installation
17
17
 
18
18
  ```bash
19
- npm install @flarenetwork/multichain-wallet-connector
19
+ pnpm add @flarenetwork/multichain-wallet-connector
20
20
  ```
21
21
 
22
22
  ## Prerequisites
@@ -48,6 +48,27 @@ const multichain = new MultiChain({
48
48
 
49
49
  Only include wallets you need. Each wallet key is optional.
50
50
 
51
+ You can also pass an `events` map to the constructor to handle wallet events outside of React (e.g. logging, analytics, non-React consumers):
52
+
53
+ ```typescript
54
+ const multichain = new MultiChain({
55
+ wallets: {
56
+ /* ... */
57
+ },
58
+ events: {
59
+ onConnect: ({ walletType, caip2, address, isReconnect }) => {
60
+ console.log(`${walletType} connected to ${caip2} as ${address} (reconnect: ${isReconnect})`);
61
+ },
62
+ onDisconnect: ({ walletType }) => {},
63
+ onChainChanged: ({ walletType, caip2 }) => {},
64
+ onAccountChanged: ({ walletType, address }) => {},
65
+ onError: ({ walletType, error }) => {},
66
+ },
67
+ });
68
+ ```
69
+
70
+ Inside React components, prefer [`useMultichainEvents`](#usemultichaineventshandlers) — both can be used together.
71
+
51
72
  ### 2. Setup React provider
52
73
 
53
74
  ```tsx
@@ -398,6 +419,7 @@ const selection = useMultichainSelection();
398
419
 
399
420
  const args = selection.selectWallet("metamask");
400
421
  selection.toggleCaip2("eip155:14");
422
+ selection.setSelectedCaip2s(["eip155:14", "xrpl:0"]);
401
423
  selection.clearWallet();
402
424
  selection.reset();
403
425
 
@@ -414,6 +436,10 @@ selection.selectedWallet;
414
436
  selection.selectedCaip2s;
415
437
  selection.availableCaip2s;
416
438
  selection.wallets;
439
+
440
+ selection.mode; // active MultichainSelectionMode
441
+ selection.fixedCaip2; // pinned chain for *:single-chain modes, otherwise null
442
+ selection.chainSelectionMode; // "single" | "multi" | null — what the chain UI should render for the selected wallet
417
443
  ```
418
444
 
419
445
  #### Example A: Generic Connect Modal (app-owned view)
@@ -572,6 +598,9 @@ function LedgerAddressPicker({ caip2 }: { caip2: Caip2 }) {
572
598
  // Switch HD standard
573
599
  selection.setHdStandard("ledgerLive");
574
600
 
601
+ // Clear the selected address for this chain
602
+ selection.clearSelection();
603
+
575
604
  // Access all selections across chains
576
605
  console.log(selections); // { 'eip155:14': { address, bip44 }, ... }
577
606
  }
@@ -1,2 +1,2 @@
1
- import { $ as MultiChainEvents, A as ConnectorTypeMap, B as LedgerConnectOptions, C as ConnectorClientMap, D as ConnectorProviderMap, E as ConnectorProvider, F as XrpClient, G as ChainChangedEvent, H as LedgerPaginatedBip44, I as EvmClient, J as DcentWalletOptions, K as ChainOverride, L as ChainClient, M as XamanSendTxOptions, N as LedgerSession, O as ConnectorSendTxOptions, P as DcentConnector, Q as MetaMaskWalletOptions, R as LedgerCaip2, S as ConnectorClient, T as ConnectorConnectOptionsMap, U as Bip44, V as LedgerHDStandard, W as AccountChangedEvent, X as ErrorEvent, Y as DisconnectEvent, Z as LedgerWalletOptions, _ as ConfigResolver, _t as XRPlCaip2, a as shortenAddress, at as XamanWalletOptions, c as WalletConnectError, d as DcentError, dt as BaseChain, et as MultiChainOptions, f as WalletError, ft as Caip2, g as MultiChain, gt as NonEvmChain, h as ChainGuards, ht as EvmChain, i as objectValues, it as WalletOptions, j as ConnectorXrpClientMap, k as ConnectorSendTxOptionsMap, l as MetaMaskError, m as ErrorCodeKey, mt as Eip155Caip2, n as objectFromEntries, nt as WalletConnectWalletOptions, o as WalletErrorHelper, ot as WalletAddressState, p as ErrorCode, pt as Chain, q as ConnectEvent, r as objectKeys, rt as WalletMetadata, s as XamanError, st as WalletState, t as objectEntries, tt as ResolvedWalletConfig, u as LedgerError, ut as WalletType, vt as XrplChain, w as ConnectorConnectOptions, x as Connector, z as LedgerComputedAddress } from "../index-BoPtY6iM.mjs";
1
+ import { $ as MultiChainEvents, A as ConnectorTypeMap, B as LedgerConnectOptions, C as ConnectorClientMap, D as ConnectorProviderMap, E as ConnectorProvider, F as XrpClient, G as ChainChangedEvent, H as LedgerPaginatedBip44, I as EvmClient, J as DcentWalletOptions, K as ChainOverride, L as ChainClient, M as XamanSendTxOptions, N as LedgerSession, O as ConnectorSendTxOptions, P as DcentConnector, Q as MetaMaskWalletOptions, R as LedgerCaip2, S as ConnectorClient, T as ConnectorConnectOptionsMap, U as Bip44, V as LedgerHDStandard, W as AccountChangedEvent, X as ErrorEvent, Y as DisconnectEvent, Z as LedgerWalletOptions, _ as ConfigResolver, _t as XRPlCaip2, a as shortenAddress, at as XamanWalletOptions, c as WalletConnectError, d as DcentError, dt as BaseChain, et as MultiChainOptions, f as WalletError, ft as Caip2, g as MultiChain, gt as NonEvmChain, h as ChainGuards, ht as EvmChain, i as objectValues, it as WalletOptions, j as ConnectorXrpClientMap, k as ConnectorSendTxOptionsMap, l as MetaMaskError, m as ErrorCodeKey, mt as Eip155Caip2, n as objectFromEntries, nt as WalletConnectWalletOptions, o as WalletErrorHelper, ot as WalletAddressState, p as ErrorCode, pt as Chain, q as ConnectEvent, r as objectKeys, rt as WalletMetadata, s as XamanError, st as WalletState, t as objectEntries, tt as ResolvedWalletConfig, u as LedgerError, ut as WalletType, vt as XrplChain, w as ConnectorConnectOptions, x as Connector, z as LedgerComputedAddress } from "../index-DYYzjIvq.mjs";
2
2
  export { AccountChangedEvent, BaseChain, Bip44, Caip2, Chain, ChainChangedEvent, ChainClient, ChainGuards, ChainOverride, ConfigResolver, ConnectEvent, Connector, ConnectorClient, ConnectorClientMap, ConnectorConnectOptions, ConnectorConnectOptionsMap, ConnectorProvider, ConnectorProviderMap, ConnectorSendTxOptions, ConnectorSendTxOptionsMap, ConnectorTypeMap, ConnectorXrpClientMap, DcentConnector, DcentError, DcentWalletOptions, DisconnectEvent, Eip155Caip2, ErrorCode, ErrorCodeKey, ErrorEvent, EvmChain, EvmClient, LedgerCaip2, LedgerComputedAddress, LedgerConnectOptions, LedgerError, LedgerHDStandard, LedgerPaginatedBip44, LedgerSession, LedgerWalletOptions, MetaMaskError, MetaMaskWalletOptions, MultiChain, MultiChainEvents, MultiChainOptions, NonEvmChain, ResolvedWalletConfig, WalletAddressState, WalletConnectError, WalletConnectWalletOptions, WalletError, WalletErrorHelper, WalletMetadata, WalletOptions, WalletState, WalletType, XRPlCaip2, XamanError, XamanSendTxOptions, XamanWalletOptions, XrpClient, XrplChain, objectEntries, objectFromEntries, objectKeys, objectValues, shortenAddress };
@@ -1,2 +1,2 @@
1
- import { _ as objectFromEntries, a as WalletErrorHelper, b as shortenAddress, c as MetaMaskError, d as WalletError, f as ErrorCode, g as objectEntries, h as ChainGuards, i as DcentConnector, l as LedgerError, n as EvmClient, o as XamanError, p as ConfigResolver, r as Bip44, s as WalletConnectError, t as MultiChain, u as DcentError, v as objectKeys, y as objectValues } from "../core-CHXRAJ_7.mjs";
1
+ import { _ as objectFromEntries, a as WalletErrorHelper, b as shortenAddress, c as MetaMaskError, d as WalletError, f as ErrorCode, g as objectEntries, h as ChainGuards, i as DcentConnector, l as LedgerError, n as EvmClient, o as XamanError, p as ConfigResolver, r as Bip44, s as WalletConnectError, t as MultiChain, u as DcentError, v as objectKeys, y as objectValues } from "../core-D90YnUDE.mjs";
2
2
  export { Bip44, ChainGuards, ConfigResolver, DcentConnector, DcentError, ErrorCode, EvmClient, LedgerError, MetaMaskError, MultiChain, WalletConnectError, WalletError, WalletErrorHelper, XamanError, objectEntries, objectFromEntries, objectKeys, objectValues, shortenAddress };
@@ -1884,6 +1884,7 @@ var LedgerConnector = class extends BaseConnector {
1884
1884
  throw new LedgerError("COMMON_FEATURE_NOT_SUPPORTED");
1885
1885
  }
1886
1886
  async fetchAddressesForSelection(chain, paths) {
1887
+ await this.transportManager.close();
1887
1888
  await this.requireApp(chain);
1888
1889
  return (await LedgerAppFactory.createApp(chain, this.transportManager)).getComputedAddresses(paths, this.resolvedConfig.getChain(chain).ledgerHrp);
1889
1890
  }
@@ -2506,6 +2507,34 @@ var WalletConnectConnector = class extends BaseConnector {
2506
2507
  }
2507
2508
  };
2508
2509
  //#endregion
2510
+ //#region src/core/utils/app-resume.ts
2511
+ /**
2512
+ * Invokes `onResume` whenever the page returns to the foreground — the
2513
+ * situation after a mobile app-switch (user went to a wallet app and came
2514
+ * back), during which browsers freeze the page and let websockets die.
2515
+ *
2516
+ * Listens to both `visibilitychange` and window `focus`: iOS Safari does not
2517
+ * reliably fire visibilitychange on app-switch return, so focus backs it up.
2518
+ * `onResume` runs single-flight (a trigger while a run is still in progress
2519
+ * is ignored); its rejection is delivered to `onError`.
2520
+ *
2521
+ * Detach by aborting the provided signal. No-op outside a browser.
2522
+ */
2523
+ function onAppResume(onResume, onError, signal) {
2524
+ const doc = globalThis.document;
2525
+ if (!doc) return;
2526
+ let inFlight = false;
2527
+ const handleResume = () => {
2528
+ if (doc.visibilityState !== "visible" || inFlight) return;
2529
+ inFlight = true;
2530
+ onResume().catch(onError).finally(() => {
2531
+ inFlight = false;
2532
+ });
2533
+ };
2534
+ doc.addEventListener("visibilitychange", handleResume, { signal });
2535
+ globalThis.window?.addEventListener("focus", handleResume, { signal });
2536
+ }
2537
+ //#endregion
2509
2538
  //#region src/core/connectors/xaman/xaman-xrpl-client.ts
2510
2539
  var XamanClient = class XamanClient extends Xumm {
2511
2540
  static {
@@ -2519,6 +2548,12 @@ var XamanClient = class XamanClient extends Xumm {
2519
2548
  this.resolvedConfig = resolvedConfig;
2520
2549
  }
2521
2550
  async sendTx(tx, sendTxOptions) {
2551
+ const subscription = await this.createSignRequest(tx, sendTxOptions);
2552
+ const txid = await this.awaitSignedTxid(subscription);
2553
+ if (!txid) throw new XamanError("XAMAN_SIGN_REJECTED");
2554
+ return txid;
2555
+ }
2556
+ async createSignRequest(tx, sendTxOptions) {
2522
2557
  if (!this.payload) throw new XamanError("XAMAN_SDK_NOT_READY");
2523
2558
  const { reference } = parseCaip2(await this.getCaip2());
2524
2559
  const networkKey = XamanClient.NETWORK_KEYS[reference];
@@ -2534,12 +2569,60 @@ var XamanClient = class XamanClient extends Xumm {
2534
2569
  };
2535
2570
  const subscription = await this.payload.createAndSubscribe(payload, (event) => "signed" in event.data ? event : void 0);
2536
2571
  if (!subscription?.created) throw new XamanError("XAMAN_SDK_NOT_READY");
2537
- const txid = (await subscription.resolved)?.payload?.response?.txid;
2538
- if (!txid) throw new XamanError("XAMAN_SIGN_REJECTED");
2539
- return txid;
2572
+ return subscription;
2573
+ }
2574
+ /**
2575
+ * Waits for the sign result. Primary source: the websocket subscription.
2576
+ * Fallback: if the page was backgrounded (mobile app switch), the socket
2577
+ * may have died without delivering the result — so on every app resume the
2578
+ * payload is re-fetched over HTTP and, if settled, wins the race.
2579
+ * Returns the txid, or null when the user rejected the request.
2580
+ */
2581
+ async awaitSignedTxid(subscription) {
2582
+ const listeners = new AbortController();
2583
+ const viaSocket = Promise.resolve(subscription.resolved).then((event) => this.readSocketTxid(event));
2584
+ const viaResume = new Promise((resolve, reject) => {
2585
+ onAppResume(async () => {
2586
+ const outcome = await this.refetchSignOutcome(subscription.created.uuid);
2587
+ if (outcome.status === "pending") return;
2588
+ subscription.resolve();
2589
+ resolve(outcome.txid);
2590
+ }, reject, listeners.signal);
2591
+ });
2592
+ try {
2593
+ return await Promise.race([viaSocket, viaResume]);
2594
+ } finally {
2595
+ listeners.abort();
2596
+ }
2597
+ }
2598
+ readSocketTxid(event) {
2599
+ if (!this.isSubscriptionEvent(event)) return null;
2600
+ return event.payload.response.txid ?? null;
2601
+ }
2602
+ isSubscriptionEvent(event) {
2603
+ return typeof event === "object" && event !== null && "payload" in event;
2604
+ }
2605
+ async refetchSignOutcome(uuid) {
2606
+ if (!this.payload) throw new XamanError("XAMAN_SDK_NOT_READY");
2607
+ try {
2608
+ const refetched = await this.payload.get(uuid);
2609
+ return this.readSignOutcome(refetched);
2610
+ } catch {
2611
+ return { status: "pending" };
2612
+ }
2613
+ }
2614
+ readSignOutcome(payload) {
2615
+ if (!payload?.meta) return { status: "pending" };
2616
+ const { resolved, cancelled, expired } = payload.meta;
2617
+ if (!(resolved || cancelled || expired)) return { status: "pending" };
2618
+ return {
2619
+ status: "settled",
2620
+ txid: payload.response.txid ?? null
2621
+ };
2540
2622
  }
2541
2623
  async getCaip2() {
2542
2624
  const networkId = await this.user.networkId;
2625
+ if (typeof networkId !== "number") throw new XamanError("XAMAN_SDK_NOT_READY");
2543
2626
  return this.toCaip2Network(networkId);
2544
2627
  }
2545
2628
  async onDestroy() {
@@ -2936,4 +3019,4 @@ var MultiChain = class {
2936
3019
  //#endregion
2937
3020
  export { objectFromEntries as _, WalletErrorHelper as a, shortenAddress as b, MetaMaskError as c, WalletError as d, ErrorCode as f, objectEntries as g, ChainGuards as h, DcentConnector as i, LedgerError as l, evmCaip2s as m, EvmClient as n, XamanError as o, ConfigResolver as p, Bip44 as r, WalletConnectError as s, MultiChain as t, DcentError as u, objectKeys as v, objectValues as y };
2938
3021
 
2939
- //# sourceMappingURL=core-CHXRAJ_7.mjs.map
3022
+ //# sourceMappingURL=core-D90YnUDE.mjs.map