{"version":3,"file":"UnisatCompatibleWalletAdapterImpl-CgYhzoSj.mjs","sources":["../src/utils/UnisatCompatibleWalletAdapterImpl.ts"],"sourcesContent":["import { hex } from \"@scure/base\"\nimport * as btc from \"@scure/btc-signer\"\nimport { hasAny } from \"./misc\"\nimport {\n  addressToScriptPubKey,\n  getAddressType,\n  getRedeemScriptOf_P2SH_P2WPKH_publicKey,\n  getTapInternalKeyOf_P2TR_publicKey,\n} from \"./bitcoinAddressHelpers\"\nimport { getBitcoinNetwork } from \"./bitcoinNetworkHelpers\"\nimport { UserRejectError, BitcoinWalletAdapterError } from \"../utils/error\"\nimport {\n  SignMessageAlgorithm,\n  SignMessageResult,\n  WalletAdapter,\n  WalletAdapter_onAddressesChanged_callback,\n  WalletAdapterAddress,\n  WalletAdapterAddressPurpose,\n  WalletAdapterAddressType,\n  WalletAdapterBitcoinNetwork,\n  WalletAdapterNotConnectedError,\n  WalletAdapter_sendBitcoinFeeRateCapability,\n} from \"../WalletAdapters.types\"\n\n/**\n * https://docs.unisat.io/dev-center/open-api-documentation/unisat-wallet#events\n */\nexport interface UniSatEvents {\n  accountsChanged: [accounts: Array<string>]\n  networkChanged: [network: string]\n}\n\nexport interface UnisatCompatibleProviderAPI {\n  /**\n   * https://docs.unisat.io/dev/unisat-developer-service/unisat-wallet#getaccounts\n   */\n  getAccounts(): Promise<string[]>\n\n  /**\n   * https://docs.unisat.io/dev/unisat-developer-service/unisat-wallet#requestaccounts\n   */\n  requestAccounts(): Promise<string[]>\n\n  /**\n   * https://docs.unisat.io/dev/unisat-developer-service/unisat-wallet#getpublickey\n   */\n  getPublicKey(): Promise<string>\n\n  /**\n   * https://docs.unisat.io/dev/unisat-developer-service/unisat-wallet#getnetwork\n   */\n  getNetwork(): Promise<\"livenet\" | \"testnet\">\n\n  /**\n   * https://docs.unisat.io/dev/unisat-developer-service/unisat-wallet#signmessage\n   */\n  signMessage(\n    message: string,\n    algorithm: \"ecdsa\" | \"bip322-simple\",\n  ): Promise<string>\n\n  /**\n   * https://docs.unisat.io/dev/unisat-developer-service/unisat-wallet#sendbitcoin\n   */\n  sendBitcoin(\n    receiverAddress: string,\n    satoshiAmount: number,\n    options?: { feeRate?: number },\n  ): Promise<string>\n\n  /**\n   * https://docs.unisat.io/dev/unisat-developer-service/unisat-wallet#sendInscription\n   */\n  sendInscription(\n    receiverAddress: string,\n    inscriptionId: string,\n    options?: { feeRate?: number },\n  ): Promise<string>\n\n  /**\n   * https://docs.unisat.io/dev/unisat-developer-service/unisat-wallet#signpsbt\n   */\n  signPsbt(\n    psbtHex: string,\n    options?: {\n      autoFinalized?: boolean\n      toSignInputs?: {\n        index: number\n        address?: string\n        publicKey?: string\n        sighashTypes?: number[]\n        disableTweakSigner?: boolean\n      }[]\n    },\n  ): Promise<string>\n\n  /**\n   * https://docs.unisat.io/dev/unisat-developer-service/unisat-wallet#events\n   */\n  on<K extends keyof UniSatEvents>(\n    event: K,\n    handler: (...args: UniSatEvents[K]) => void,\n  ): void\n  removeListener(event: keyof UniSatEvents, handler: () => void): void\n}\n\nexport type UnisatCompatibleWalletAdapterAddresses = (WalletAdapterAddress & {\n  publicKey: string\n})[]\n\nexport class UnisatCompatibleWalletAdapterImpl implements WalletAdapter {\n  constructor(\n    private unisat: UnisatCompatibleProviderAPI,\n    private walletDisplayName: string,\n  ) {}\n\n  async connect(): Promise<void> {\n    if ((await this.unisat.getAccounts()).length === 0) {\n      await this.unisat.requestAccounts()\n    }\n  }\n\n  disconnect(): Promise<void> {\n    // do nothing\n    return Promise.resolve()\n  }\n\n  async getAddresses(): Promise<UnisatCompatibleWalletAdapterAddresses> {\n    const addresses: string[] = await this.unisat.getAccounts()\n\n    if (addresses.length === 0) {\n      throw new WalletAdapterNotConnectedError(this.walletDisplayName)\n    }\n\n    const publicKey: string = await this.unisat.getPublicKey()\n\n    const _network: \"livenet\" | \"testnet\" = await this.unisat.getNetwork()\n    const network = _network === \"livenet\" ? \"mainnet\" : \"testnet\"\n\n    if (!hasAny(addresses)) {\n      throw new BitcoinWalletAdapterError(\"Request wallet addresses failed\")\n    }\n\n    const address = addresses[0]\n    const addrType = getAddressType(getBitcoinNetwork(network), address)\n    // prettier-ignore\n    const addressType =\n      addrType === \"p2tr\" ? WalletAdapterAddressType.P2TR :\n      addrType === \"p2sh\" ? WalletAdapterAddressType.P2SH_P2WPKH :\n      addrType === \"p2wpkh\" ? WalletAdapterAddressType.P2WPKH :\n      undefined\n\n    if (addressType == null) {\n      throw new BitcoinWalletAdapterError(\"Please select a SegWit address\")\n    }\n\n    const scriptPubKey = hex.encode(\n      addressToScriptPubKey(getBitcoinNetwork(network), address),\n    )\n\n    const tapInternalKey =\n      addressType !== WalletAdapterAddressType.P2TR\n        ? undefined\n        : hex.encode(\n            getTapInternalKeyOf_P2TR_publicKey(\n              getBitcoinNetwork(network),\n              hex.decode(publicKey),\n            ),\n          )\n\n    const redeemScript =\n      addressType !== WalletAdapterAddressType.P2SH_P2WPKH\n        ? undefined\n        : hex.encode(\n            getRedeemScriptOf_P2SH_P2WPKH_publicKey(\n              getBitcoinNetwork(network),\n              hex.decode(publicKey),\n            ),\n          )\n\n    return [\n      {\n        addressType,\n        address,\n        scriptPubKey,\n        redeemScript,\n        tapInternalKey,\n        publicKey,\n        network:\n          network === \"mainnet\"\n            ? WalletAdapterBitcoinNetwork.MAINNET\n            : WalletAdapterBitcoinNetwork.TESTNET,\n        purposes: [\n          WalletAdapterAddressPurpose.Bitcoin,\n          WalletAdapterAddressPurpose.Ordinals,\n          WalletAdapterAddressPurpose.BRC20,\n          WalletAdapterAddressPurpose.Runes,\n        ],\n      },\n    ]\n  }\n\n  async signMessage(\n    address: string,\n    message: string,\n  ): Promise<SignMessageResult> {\n    const result = await handleRpcError(\n      this.unisat.signMessage(message, \"bip322-simple\"),\n    )\n\n    return {\n      result,\n      address,\n      algorithm: SignMessageAlgorithm.BIP322,\n    }\n  }\n\n  sendBitcoinFeeRateCapability: WalletAdapter_sendBitcoinFeeRateCapability =\n    \"available\" as const\n  async sendBitcoin(\n    fromAddress: string,\n    receiverAddress: string,\n    satoshiAmount: bigint,\n    options?: { feeRate?: number },\n  ): Promise<{ txid: string }> {\n    const txid = await handleRpcError(\n      this.unisat.sendBitcoin(receiverAddress, Number(satoshiAmount), {\n        feeRate: options?.feeRate,\n      }),\n    )\n    return { txid }\n  }\n\n  /**\n   * @internal\n   * @experimental\n   */\n  sendInscriptionFeeRateCapability: \"unavailable\" | \"available\" | \"required\" =\n    \"available\" as const\n  /**\n   * @internal\n   * @experimental\n   */\n  async sendInscription(\n    fromAddress: string,\n    receiverAddress: string,\n    inscriptionId: string,\n    options?: { feeRate?: number },\n  ): Promise<{ txid: string }> {\n    const txid = await handleRpcError(\n      this.unisat.sendInscription(receiverAddress, inscriptionId, {\n        feeRate: options?.feeRate,\n      }),\n    )\n    return { txid }\n  }\n\n  async signAndFinalizePsbt(\n    psbtHex: string,\n    signIndices: [address: string, signIndex: number][],\n  ): Promise<{\n    signedPsbtHex: string\n  }> {\n    const signedPsbtHex = await handleRpcError(\n      this.unisat.signPsbt(psbtHex, {\n        autoFinalized: false,\n        toSignInputs: signIndices.map(([address, signIndex]) => ({\n          index: signIndex,\n          address,\n        })),\n      }),\n    )\n\n    /**\n     * Some version of unisat's signPsbt API does not working well with the autoFinalized option,\n     * so we finalize the PSBT manually.\n     */\n    const tx = btc.Transaction.fromPSBT(hex.decode(signedPsbtHex), {\n      allowUnknownInputs: true,\n      allowUnknownOutputs: true,\n      disableScriptCheck: true,\n      allowLegacyWitnessUtxo: true,\n    })\n    tx.finalize()\n\n    return { signedPsbtHex: hex.encode(tx.toPSBT()) }\n  }\n\n  onAddressesChanged(callback: WalletAdapter_onAddressesChanged_callback): {\n    unsubscribe: () => void\n  } {\n    const handler = async (): Promise<void> => {\n      try {\n        const addresses = await this.getAddresses()\n        callback({ addresses })\n      } catch (error) {\n        // Ignore errors from getAddresses (e.g., wallet disconnected)\n        console.warn(\n          `[${this.walletDisplayName}] Failed to get addresses on change:`,\n          error,\n        )\n      }\n    }\n\n    // Listen to both account and network changes\n    this.unisat.on(\"accountsChanged\", handler)\n    this.unisat.on(\"networkChanged\", handler)\n\n    return {\n      unsubscribe: () => {\n        this.unisat.removeListener(\"accountsChanged\", handler)\n        this.unisat.removeListener(\"networkChanged\", handler)\n      },\n    }\n  }\n}\n\ninterface UnisatCompatibleProviderAPIThrownError {\n  code: number\n  message: string\n}\nfunction isUnisatCompatibleProviderAPIThrownError(\n  err: any,\n): err is UnisatCompatibleProviderAPIThrownError {\n  return err != null && \"code\" in err && \"message\" in err\n}\n\nexport class UnisatCompatibleProviderError extends Error {\n  readonly code: number\n  constructor(err: UnisatCompatibleProviderAPIThrownError) {\n    super(err.message)\n    this.code = err.code\n    this.cause = err\n  }\n}\n\nconst handleRpcError = async <T>(promise: Promise<T>): Promise<T> => {\n  try {\n    return await promise\n  } catch (e: any) {\n    if (isUnisatCompatibleProviderAPIThrownError(e)) {\n      if (e.code === 4001) {\n        throw new UserRejectError()\n      }\n      throw new UnisatCompatibleProviderError(e)\n    }\n    throw e\n  }\n}\n"],"names":["UnisatCompatibleWalletAdapterImpl","unisat","walletDisplayName","addresses","WalletAdapterNotConnectedError","publicKey","network","hasAny","BitcoinWalletAdapterError","address","addrType","getAddressType","getBitcoinNetwork","addressType","WalletAdapterAddressType","scriptPubKey","hex","addressToScriptPubKey","tapInternalKey","getTapInternalKeyOf_P2TR_publicKey","redeemScript","getRedeemScriptOf_P2SH_P2WPKH_publicKey","WalletAdapterBitcoinNetwork","WalletAdapterAddressPurpose","message","handleRpcError","SignMessageAlgorithm","fromAddress","receiverAddress","satoshiAmount","options","inscriptionId","psbtHex","signIndices","signedPsbtHex","signIndex","tx","btc.Transaction","callback","handler","error","isUnisatCompatibleProviderAPIThrownError","err","UnisatCompatibleProviderError","promise","UserRejectError"],"mappings":"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"}