{"version":3,"file":"react.mjs","sources":["../src/BitcoinConnectionProvider.tsx"],"sourcesContent":["import {\n  createContext,\n  FC,\n  ReactNode,\n  useCallback,\n  useContext,\n  useEffect,\n  useMemo,\n  useRef,\n  useState,\n} from \"react\"\nimport { BitcoinWalletConnector } from \"./BitcoinWalletConnector\"\nimport {\n  WalletAdapter,\n  WalletAdapterAddress,\n  WalletAdapterFactory,\n} from \"./WalletAdapters.types\"\n\nexport interface WalletSession {\n  adapterId: string\n  adapter: WalletAdapter\n  addresses: WalletAdapterAddress[]\n}\n\nexport interface BitcoinConnectionContextValue {\n  // Core connection state\n  walletSession: null | WalletSession\n  isConnectionInitializing: boolean\n  connect: (adapterId: string, adapter: WalletAdapter) => Promise<void>\n  disconnect: () => Promise<void>\n\n  // Wallet management (for UI)\n  adapterFactories: WalletAdapterFactory<WalletAdapter>[]\n  availableAdapters: (readonly [adapterId: string, adapter: WalletAdapter])[]\n}\n\nconst BitcoinConnectionContext =\n  createContext<null | BitcoinConnectionContextValue>(null)\n\nfunction useConnectorState<T>(\n  subscribe: (listener: (value: T) => void) => { unsubscribe: () => void },\n  getSnapshot: () => T,\n  deps: ReadonlyArray<unknown>,\n): T {\n  const [value, setValue] = useState(getSnapshot)\n\n  useEffect(() => {\n    const subscription = subscribe(setValue)\n    return () => subscription.unsubscribe()\n    // eslint-disable-next-line react-hooks/exhaustive-deps\n  }, deps)\n\n  return value\n}\n\nexport const BitcoinConnectionProvider: FC<{\n  children: ReactNode\n  adapterFactories: WalletAdapterFactory<WalletAdapter>[]\n  onWalletConnected?: (session: WalletSession) => void\n  onWalletAddressesChanged?: (addresses: WalletAdapterAddress[]) => void\n  onWalletDisconnected?: () => void\n}> = props => {\n  const [isConnectionInitializing, setIsConnectionInitializing] =\n    useState(false)\n  const [walletSession, setWalletSession] = useState<null | WalletSession>(null)\n\n  const onWalletConnected = usePersistFn(props.onWalletConnected ?? noop)\n  const onWalletAddressesChanged = usePersistFn(\n    props.onWalletAddressesChanged ?? noop,\n  )\n  const onWalletDisconnected = usePersistFn(props.onWalletDisconnected ?? noop)\n\n  const connector = useMemo(\n    () => new BitcoinWalletConnector(props.adapterFactories),\n    [props.adapterFactories],\n  )\n\n  useEffect(\n    () => () => {\n      connector.dispose()\n    },\n    [connector],\n  )\n\n  const availableAdapters = useConnectorState(\n    listener => connector.subscribeAvailableAdapters(listener),\n    () => connector.getAvailableAdapters(),\n    [connector],\n  )\n\n  const connectInfo = useConnectorState(\n    listener => connector.subscribeConnectedInfo(listener),\n    () => connector.getConnectedInfo(),\n    [connector],\n  )\n\n  const ctxValue = useMemo(\n    (): BitcoinConnectionContextValue => ({\n      walletSession,\n      isConnectionInitializing,\n      connect: connector.connect.bind(connector),\n      disconnect: connector.disconnect.bind(connector),\n\n      adapterFactories: props.adapterFactories,\n      availableAdapters,\n    }),\n    [\n      walletSession,\n      isConnectionInitializing,\n      connector,\n      props.adapterFactories,\n      availableAdapters,\n    ],\n  )\n\n  useEffect(() => {\n    const abortController = new AbortController()\n\n    const sub = connector.subscribeConnectedInfo(info => {\n      if (info == null) {\n        try {\n          onWalletDisconnected()\n        } catch (e) {\n          console.error(\n            \"[BitcoinConnectionProvider] onWalletDisconnected error\",\n            e,\n          )\n        }\n\n        setWalletSession(null)\n        setIsConnectionInitializing(false)\n        return\n      }\n\n      setIsConnectionInitializing(true)\n      info.adapter\n        .getAddresses()\n        .then(addresses => {\n          if (abortController.signal.aborted) return\n\n          const walletSession: WalletSession = {\n            adapterId: info.adapterId,\n            adapter: info.adapter,\n            addresses,\n          }\n\n          try {\n            onWalletConnected(walletSession)\n          } catch (e) {\n            console.error(\n              \"[BitcoinConnectionProvider] onWalletConnected error\",\n              e,\n            )\n          }\n\n          setWalletSession(walletSession)\n          setIsConnectionInitializing(false)\n        })\n        .catch(err => {\n          if (abortController.signal.aborted) return\n          setIsConnectionInitializing(false)\n          console.error(\"[BitcoinConnectionProvider] connect error\", err)\n        })\n    })\n\n    return () => {\n      abortController.abort()\n      sub.unsubscribe()\n    }\n  }, [connector, onWalletDisconnected, onWalletConnected])\n\n  // Listen to address changes from wallet\n  useEffect(() => {\n    if (connectInfo == null) return\n\n    const abortController = new AbortController()\n\n    const sub = connectInfo.adapter.onAddressesChanged(({ addresses }) => {\n      if (abortController.signal.aborted) return\n\n      setWalletSession(prev => {\n        if (prev == null) {\n          console.warn(\n            \"[BitcoinConnectionProvider] onWalletAddressesChanged event received while disconnected, skipping...\",\n          )\n          return prev\n        }\n\n        try {\n          onWalletAddressesChanged(addresses)\n        } catch (e) {\n          console.error(\n            \"[BitcoinConnectionProvider] onWalletAddressesChanged error\",\n            e,\n          )\n        }\n\n        return { ...prev, addresses }\n      })\n    })\n    return () => {\n      abortController.abort()\n      sub.unsubscribe()\n    }\n  }, [connectInfo, onWalletAddressesChanged])\n\n  return (\n    <BitcoinConnectionContext.Provider value={ctxValue}>\n      {props.children}\n    </BitcoinConnectionContext.Provider>\n  )\n}\n\nexport function useBitcoinConnectionContext(): BitcoinConnectionContextValue {\n  const ctx = useContext(BitcoinConnectionContext)\n  if (!ctx) {\n    throw new Error(\n      \"useBitcoinConnectionContext must be used within BitcoinConnectionProvider\",\n    )\n  }\n\n  return ctx\n}\n\nconst noop = (): void => {}\n\nconst usePersistFn = <T extends (...args: any[]) => any>(\n  fn: T,\n): ((...args: Parameters<T>) => ReturnType<T>) => {\n  const fnRef = useRef(fn)\n  fnRef.current = fn\n\n  return useCallback((...args) => fnRef.current(...args), [])\n}\n"],"names":["BitcoinConnectionContext","createContext","useConnectorState","subscribe","getSnapshot","deps","value","setValue","useState","useEffect","subscription","BitcoinConnectionProvider","props","isConnectionInitializing","setIsConnectionInitializing","walletSession","setWalletSession","onWalletConnected","usePersistFn","noop","onWalletAddressesChanged","onWalletDisconnected","connector","useMemo","BitcoinWalletConnector","availableAdapters","listener","connectInfo","ctxValue","abortController","sub","info","e","addresses","err","prev","useBitcoinConnectionContext","ctx","useContext","fn","fnRef","useRef","useCallback","args"],"mappings":";;;AAoCA,MAAMA,IACJC,EAAoD,IAAI;AAE1D,SAASC,EACPC,GACAC,GACAC,GACG;AACH,QAAM,CAACC,GAAOC,CAAQ,IAAIC,EAASJ,CAAW;AAE9C,SAAAK,EAAU,MAAM;AACd,UAAMC,IAAeP,EAAUI,CAAQ;AACvC,WAAO,MAAMG,EAAa,YAAA;AAAA,EAE5B,GAAGL,CAAI,GAEAC;AACT;AAEO,MAAMK,IAMR,CAAAC,MAAS;AACZ,QAAM,CAACC,GAA0BC,CAA2B,IAC1DN,EAAS,EAAK,GACV,CAACO,GAAeC,CAAgB,IAAIR,EAA+B,IAAI,GAEvES,IAAoBC,EAAaN,EAAM,qBAAqBO,CAAI,GAChEC,IAA2BF;AAAA,IAC/BN,EAAM,4BAA4BO;AAAA,EAAA,GAE9BE,IAAuBH,EAAaN,EAAM,wBAAwBO,CAAI,GAEtEG,IAAYC;AAAA,IAChB,MAAM,IAAIC,EAAuBZ,EAAM,gBAAgB;AAAA,IACvD,CAACA,EAAM,gBAAgB;AAAA,EAAA;AAGzB,EAAAH;AAAA,IACE,MAAM,MAAM;AACV,MAAAa,EAAU,QAAA;AAAA,IACZ;AAAA,IACA,CAACA,CAAS;AAAA,EAAA;AAGZ,QAAMG,IAAoBvB;AAAA,IACxB,CAAAwB,MAAYJ,EAAU,2BAA2BI,CAAQ;AAAA,IACzD,MAAMJ,EAAU,qBAAA;AAAA,IAChB,CAACA,CAAS;AAAA,EAAA,GAGNK,IAAczB;AAAA,IAClB,CAAAwB,MAAYJ,EAAU,uBAAuBI,CAAQ;AAAA,IACrD,MAAMJ,EAAU,iBAAA;AAAA,IAChB,CAACA,CAAS;AAAA,EAAA,GAGNM,IAAWL;AAAA,IACf,OAAsC;AAAA,MACpC,eAAAR;AAAA,MACA,0BAAAF;AAAA,MACA,SAASS,EAAU,QAAQ,KAAKA,CAAS;AAAA,MACzC,YAAYA,EAAU,WAAW,KAAKA,CAAS;AAAA,MAE/C,kBAAkBV,EAAM;AAAA,MACxB,mBAAAa;AAAA,IAAA;AAAA,IAEF;AAAA,MACEV;AAAA,MACAF;AAAA,MACAS;AAAA,MACAV,EAAM;AAAA,MACNa;AAAA,IAAA;AAAA,EACF;AAGF,SAAAhB,EAAU,MAAM;AACd,UAAMoB,IAAkB,IAAI,gBAAA,GAEtBC,IAAMR,EAAU,uBAAuB,CAAAS,MAAQ;AACnD,UAAIA,KAAQ,MAAM;AAChB,YAAI;AACF,UAAAV,EAAA;AAAA,QACF,SAASW,GAAG;AACV,kBAAQ;AAAA,YACN;AAAA,YACAA;AAAA,UAAA;AAAA,QAEJ;AAEA,QAAAhB,EAAiB,IAAI,GACrBF,EAA4B,EAAK;AACjC;AAAA,MACF;AAEA,MAAAA,EAA4B,EAAI,GAChCiB,EAAK,QACF,aAAA,EACA,KAAK,CAAAE,MAAa;AACjB,YAAIJ,EAAgB,OAAO,QAAS;AAEpC,cAAMd,IAA+B;AAAA,UACnC,WAAWgB,EAAK;AAAA,UAChB,SAASA,EAAK;AAAA,UACd,WAAAE;AAAA,QAAA;AAGF,YAAI;AACF,UAAAhB,EAAkBF,CAAa;AAAA,QACjC,SAASiB,GAAG;AACV,kBAAQ;AAAA,YACN;AAAA,YACAA;AAAA,UAAA;AAAA,QAEJ;AAEA,QAAAhB,EAAiBD,CAAa,GAC9BD,EAA4B,EAAK;AAAA,MACnC,CAAC,EACA,MAAM,CAAAoB,MAAO;AACZ,QAAIL,EAAgB,OAAO,YAC3Bf,EAA4B,EAAK,GACjC,QAAQ,MAAM,6CAA6CoB,CAAG;AAAA,MAChE,CAAC;AAAA,IACL,CAAC;AAED,WAAO,MAAM;AACX,MAAAL,EAAgB,MAAA,GAChBC,EAAI,YAAA;AAAA,IACN;AAAA,EACF,GAAG,CAACR,GAAWD,GAAsBJ,CAAiB,CAAC,GAGvDR,EAAU,MAAM;AACd,QAAIkB,KAAe,KAAM;AAEzB,UAAME,IAAkB,IAAI,gBAAA,GAEtBC,IAAMH,EAAY,QAAQ,mBAAmB,CAAC,EAAE,WAAAM,QAAgB;AACpE,MAAIJ,EAAgB,OAAO,WAE3Bb,EAAiB,CAAAmB,MAAQ;AACvB,YAAIA,KAAQ;AACV,yBAAQ;AAAA,YACN;AAAA,UAAA,GAEKA;AAGT,YAAI;AACF,UAAAf,EAAyBa,CAAS;AAAA,QACpC,SAASD,GAAG;AACV,kBAAQ;AAAA,YACN;AAAA,YACAA;AAAA,UAAA;AAAA,QAEJ;AAEA,eAAO,EAAE,GAAGG,GAAM,WAAAF,EAAA;AAAA,MACpB,CAAC;AAAA,IACH,CAAC;AACD,WAAO,MAAM;AACX,MAAAJ,EAAgB,MAAA,GAChBC,EAAI,YAAA;AAAA,IACN;AAAA,EACF,GAAG,CAACH,GAAaP,CAAwB,CAAC,qBAGvCpB,EAAyB,UAAzB,EAAkC,OAAO4B,GACvC,YAAM,UACT;AAEJ;AAEO,SAASQ,IAA6D;AAC3E,QAAMC,IAAMC,EAAWtC,CAAwB;AAC/C,MAAI,CAACqC;AACH,UAAM,IAAI;AAAA,MACR;AAAA,IAAA;AAIJ,SAAOA;AACT;AAEA,MAAMlB,IAAO,MAAY;AAAC,GAEpBD,IAAe,CACnBqB,MACgD;AAChD,QAAMC,IAAQC,EAAOF,CAAE;AACvB,SAAAC,EAAM,UAAUD,GAETG,EAAY,IAAIC,MAASH,EAAM,QAAQ,GAAGG,CAAI,GAAG,EAAE;AAC5D;"}