{"version":3,"sources":["../src/authc/authc.ts","../src/authc/index.ts"],"sourcesContent":["import { createStore } from 'zustand/vanilla'\nimport AuthcClient from '../AuthcClient'\nimport type { AuthcClientOptions, LogoutOptions, RedirectLoginOptions } from '..'\nimport type { AuthcWalletOptions as CustomWalletOptions } from '../wallet'\nimport { AuthcWalletLogin } from '../wallet'\n\ninterface AuthcWalletOptions extends CustomWalletOptions {\n\n}\n\nconst debouncePromise = (fn: (...args: any[]) => Promise<any>, delay: number) => {\n  let timer: any\n  return (...args: any[]) => {\n    clearTimeout(timer)\n    return new Promise((resolve, reject) => {\n      timer = setTimeout(() => {\n        fn(...args).then(resolve).catch(reject)\n      }, delay)\n    })\n  }\n}\n\nexport interface AuthcOptions extends AuthcClientOptions {\n  /**\n   * unlock wallet on demand\n   * @default false\n   */\n  unlockOnDemand?: boolean\n  walletOptions: AuthcWalletOptions\n  events?: {\n    afterLogout?: () => void\n  }\n}\n\nexport class Authc extends AuthcClient {\n  wallet: AuthcWalletLogin\n  private loginPromise: Promise<any>\n  private opts: AuthcOptions\n  store = createStore<{\n    status: 'login' | 'loginFailed' | 'createWallet' | 'reconstruct' | 'viewAccount' | 'reconstructFailed' | ''\n    loading: boolean\n  }>(() => ({\n    status: '',\n    loading: false,\n  }))\n\n  get events() {\n    return {\n      afterLogout: () => {},\n      ...this.opts.events,\n    }\n  }\n\n  constructor(_options: AuthcOptions) {\n    const options = {\n      unlockOnDemand: false,\n      ..._options,\n    }\n    super(options)\n    this.wallet = new AuthcWalletLogin({\n      ...this.options.walletOptions,\n      unlockOnDemand: options.unlockOnDemand,\n      authc: this,\n    })\n    this.wallet.addMessageListener('lifecycle', ({ name }) => {\n      if (name === 'reconstruct') {\n        if (this.opts.unlockOnDemand)\n          this.wallet.replace('/forward')\n\n        else\n          this.wallet.replace('/reconstruct')\n      }\n\n      this.store.setState({\n        status: name,\n        loading: name === 'login',\n      })\n    })\n\n    Reflect.deleteProperty(options, 'walletOptions')\n    this.opts = options\n\n    if (!this.inLoginIframe()) {\n      if (this.wallet.client().getAccount().isConnected) {\n        this.walletHandler()\n      }\n      else {\n        const isLogin\n        = (async () => {\n          try {\n            await this.checkSession()\n            return await this.isAuthenticated()\n          }\n          catch (err) {\n            console.log('🚀 ~ file: authc.ts:57 ~ Authc ~ err:', err)\n            return false\n          }\n        })()\n\n        isLogin.then(async (res) => {\n          if (res) {\n            const record = await this.getClientCache()\n            // authc login\n            if (record.loginMode === false) {\n              setTimeout(() => {\n                this.connectWallet()\n              }, 2500)\n            }\n          }\n        })\n      }\n\n      this.onConnectWalletByPostMessage()\n    }\n  }\n\n  onConnectWalletByPostMessage() {\n    this.wallet.onConnectWalletByPostMessage((...args) => {\n      const iframeWindow = window.document.querySelector<HTMLIFrameElement>('.authc-popup > iframe')?.contentWindow\n      // eslint-disable-next-line prefer-spread\n      return iframeWindow?.postMessage.apply(iframeWindow, args as any)\n    })\n  }\n\n  private closeWatchHandler = () => {}\n\n  walletHandler() {\n    this.closeWatchHandler()\n\n    const isLogin = async () => {\n      try {\n        await this.loginPromise\n        await this.checkSession()\n        return await this.isAuthenticated()\n      }\n      catch { return false }\n    }\n\n    const watchAccount = async (account: any) => {\n      if (account.isConnected && await isLogin()) {\n        // 钱包连接成功，但是钱包地址和缓存的地址不一致，应该登出\n        const cache = await this.getClientCache()\n        if (account.address.toLocaleUpperCase() !== cache.walletAddress?.toLocaleUpperCase()) {\n          console.warn('Current wallet address is not equal to the cached address, will logout', account.address, cache.walletAddress)\n          return this.logout()\n        }\n      }\n      const record = await this.getClientCache()\n\n      if (account.status === 'disconnected' && await isLogin()) {\n        if (this.wallet.walletName && account.isCustomWallet) {\n          return this.wallet.connectWalletCustom().catch(() => {\n            // 重连失败，应该登出\n            if (!this.opts.unlockOnDemand || record?.loginMode === true) {\n              return this.logout()\n            }\n            else {\n              // TODO: should to reconnect\n              return this.logout()\n            }\n          })\n        }\n        else if (!this.opts.unlockOnDemand || record.loginMode === true) {\n          return this.logout()\n        }\n      }\n      else if (account.isConnected && !await isLogin()) {\n        return this.wallet.disconnect()\n      }\n    }\n\n    this.closeWatchHandler = this.wallet.watchAccount(debouncePromise(watchAccount, 100))\n  }\n\n  async loginWithWallet<TAppState = any>(\n    options: RedirectLoginOptions<TAppState> = {},\n  ) {\n    this.loginPromise = new Promise(async (resolve, reject) => {\n      const res = await this.loginWithIframe(options).catch((err) => {\n        this.wallet.disconnect()\n        reject(err)\n        throw err\n      })\n      const account = this.wallet.client().getAccount()\n      await this.updateClientCache({\n        /**\n         * true: metamask, walletconnect, etc...\n         * false: custom wallet\n         */\n        loginMode: account.isConnected,\n      })\n\n      if (!account.isConnected) {\n        this.connectWallet().catch((err) => {\n          this.logout()\n          return reject(err)\n        })\n      }\n      else {\n        await this.updateClientCache({\n          walletAddress: account.address,\n        })\n        this.walletHandler()\n      }\n      resolve(res)\n    })\n\n    return this.loginPromise\n  }\n\n  async connectWallet() {\n    const res = await this.wallet.connectWalletCustom()\n    await this.updateClientCache({\n      walletAddress: res.address,\n    })\n    this.walletHandler()\n    return res\n  }\n\n  toUnlockWallet() {\n    if (this.store.getState().status === 'reconstruct')\n      this.wallet.replace('/reconstruct')\n  }\n\n  async logout(options?: LogoutOptions) {\n    if ((await this.wallet.client().getAccount()).status === 'connected')\n      return this.wallet.disconnect()\n\n    this.closeWatchHandler()\n    const logoutPromise = new Promise<void>(async (resolve, reject) => {\n      try {\n        resolve(await super.logout({\n          silent: true,\n          ...options,\n        }))\n      }\n      catch (err) {\n        reject(err)\n      }\n    })\n    return logoutPromise.finally(() => {\n      this.events.afterLogout?.()\n    })\n  }\n}\n","import type { AuthcOptions } from './authc'\nimport { Authc } from './authc'\n\nexport * from '../wallet'\nexport * from './authc'\nexport * from '../'\n\n/**\n * Asynchronously creates the AuthcClient instance and calls `checkSession`.\n *\n * **Note:** There are caveats to using this in a private browser tab, which may not silently authenticae\n * a user on page refresh. Please see [the checkSession docs](https://authc.github.io/authc-spa-js/classes/authcclient.html#checksession) for more info.\n *\n * @param options The client options\n * @returns An instance of AuthcClient\n */\nexport default function createAuthc(options: AuthcOptions) {\n  const authc = new Authc(options)\n  authc.checkSession().catch((err) => {\n    authc.logout({\n      localOnly: true,\n    })\n  })\n  return authc\n}\n"],"mappings":"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","names":["watchAccount"]}