@flarenetwork/multichain-wallet-connector 0.0.2-rc.25 → 0.0.2-rc.27

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-CJ2Ge7oD.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-CwmjYh7S.mjs";
2
2
  export { Bip44, ChainGuards, ConfigResolver, DcentConnector, DcentError, ErrorCode, EvmClient, LedgerError, MetaMaskError, MultiChain, WalletConnectError, WalletError, WalletErrorHelper, XamanError, objectEntries, objectFromEntries, objectKeys, objectValues, shortenAddress };
@@ -2507,6 +2507,34 @@ var WalletConnectConnector = class extends BaseConnector {
2507
2507
  }
2508
2508
  };
2509
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
2510
2538
  //#region src/core/connectors/xaman/xaman-xrpl-client.ts
2511
2539
  var XamanClient = class XamanClient extends Xumm {
2512
2540
  static {
@@ -2520,6 +2548,12 @@ var XamanClient = class XamanClient extends Xumm {
2520
2548
  this.resolvedConfig = resolvedConfig;
2521
2549
  }
2522
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) {
2523
2557
  if (!this.payload) throw new XamanError("XAMAN_SDK_NOT_READY");
2524
2558
  const { reference } = parseCaip2(await this.getCaip2());
2525
2559
  const networkKey = XamanClient.NETWORK_KEYS[reference];
@@ -2535,12 +2569,60 @@ var XamanClient = class XamanClient extends Xumm {
2535
2569
  };
2536
2570
  const subscription = await this.payload.createAndSubscribe(payload, (event) => "signed" in event.data ? event : void 0);
2537
2571
  if (!subscription?.created) throw new XamanError("XAMAN_SDK_NOT_READY");
2538
- const txid = (await subscription.resolved)?.payload?.response?.txid;
2539
- if (!txid) throw new XamanError("XAMAN_SIGN_REJECTED");
2540
- 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
+ };
2541
2622
  }
2542
2623
  async getCaip2() {
2543
2624
  const networkId = await this.user.networkId;
2625
+ if (networkId == null) throw new XamanError("XAMAN_SDK_NOT_READY");
2544
2626
  return this.toCaip2Network(networkId);
2545
2627
  }
2546
2628
  async onDestroy() {
@@ -2937,4 +3019,4 @@ var MultiChain = class {
2937
3019
  //#endregion
2938
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 };
2939
3021
 
2940
- //# sourceMappingURL=core-CJ2Ge7oD.mjs.map
3022
+ //# sourceMappingURL=core-CwmjYh7S.mjs.map