@sat20/btc-connect
Version:
Btc connect for sat20, unisat, okx
1,341 lines (1,331 loc) • 49.9 kB
JavaScript
// src/components/WalletConnectReact.tsx
import React3, { useMemo } from "react";
import { useEffect as useEffect2, useState as useState2 } from "react";
// src/components/WalletSelectModal.tsx
import React, { useEffect, useState } from "react";
import ReactDOM from "react-dom";
// src/assets/index.ts
var unisatLogo = `data:image/svg+xml;base64,Cjxzdmcgd2lkdGg9IjEwMHB4IiBoZWlnaHQ9IjEwMHB4IiB2aWV3Qm94PSIwIDAgMTAwIDEwMCIgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIj4KICAgIDxkZWZzPgogICAgICAgIDxsaW5lYXJHcmFkaWVudCB4MT0iOTEuODc1NTY2NyUiIHkxPSIyOS43Mjg4NjIyJSIgeDI9IjUuNTkzNTkzODUlIiB5Mj0iNjcuNzM4NzI0OCUiIGlkPSJsaW5lYXJHcmFkaWVudC1leXZkOXN5Z2Z5LTEiPgogICAgICAgICAgICA8c3RvcCBzdG9wLWNvbG9yPSIjMjAxQzFCIiBvZmZzZXQ9IjAlIj48L3N0b3A+CiAgICAgICAgICAgIDxzdG9wIHN0b3AtY29sb3I9IiM3NzM5MEQiIG9mZnNldD0iMzYlIj48L3N0b3A+CiAgICAgICAgICAgIDxzdG9wIHN0b3AtY29sb3I9IiNFQTgxMDEiIG9mZnNldD0iNjclIj48L3N0b3A+CiAgICAgICAgICAgIDxzdG9wIHN0b3AtY29sb3I9IiNGNEI4NTIiIG9mZnNldD0iMTAwJSI+PC9zdG9wPgogICAgICAgIDwvbGluZWFyR3JhZGllbnQ+CiAgICAgICAgPGxpbmVhckdyYWRpZW50IHgxPSIxMC41MTQwNjI0JSIgeTE9IjYyLjg4MzE2ODglIiB4Mj0iMTEwLjc4ODYyJSIgeTI9IjM3LjMyMTc0MDIlIiBpZD0ibGluZWFyR3JhZGllbnQtZXl2ZDlzeWdmeS0yIj4KICAgICAgICAgICAgPHN0b3Agc3RvcC1jb2xvcj0iIzFGMUQxQyIgb2Zmc2V0PSIwJSI+PC9zdG9wPgogICAgICAgICAgICA8c3RvcCBzdG9wLWNvbG9yPSIjNzczOTBEIiBvZmZzZXQ9IjM3JSI+PC9zdG9wPgogICAgICAgICAgICA8c3RvcCBzdG9wLWNvbG9yPSIjRUE4MTAxIiBvZmZzZXQ9IjY3JSI+PC9zdG9wPgogICAgICAgICAgICA8c3RvcCBzdG9wLWNvbG9yPSIjRjRGQjUyIiBvZmZzZXQ9IjEwMCUiPjwvc3RvcD4KICAgICAgICA8L2xpbmVhckdyYWRpZW50PgogICAgICAgIDxyYWRpYWxHcmFkaWVudCBjeD0iNTAlIiBjeT0iNTAuMDQ1MDk4OCUiIGZ4PSI1MCUiIGZ5PSI1MC4wNDUwOTg4JSIgcj0iNTAuODMyODIzNiUiIGdyYWRpZW50VHJhbnNmb3JtPSJ0cmFuc2xhdGUoMC41MDAwMDAsMC41MDA0NTEpLHNjYWxlKDAuOTgzNjEyLDEuMDAwMDAwKSx0cmFuc2xhdGUoLTAuNTAwMDAwLC0wLjUwMDQ1MSkiIGlkPSJyYWRpYWxHcmFkaWVudC1leXZkOXN5Z2Z5LTMiPgogICAgICAgICAgICA8c3RvcCBzdG9wLWNvbG9yPSIjRjRCODUyIiBvZmZzZXQ9IjAlIj48L3N0b3A+CiAgICAgICAgICAgIDxzdG9wIHN0b3AtY29sb3I9IiNFQTgxMDEiIG9mZnNldD0iMzMlIj48L3N0b3A+CiAgICAgICAgICAgIDxzdG9wIHN0b3AtY29sb3I9IiM3NzM5MEQiIG9mZnNldD0iNjQlIj48L3N0b3A+CiAgICAgICAgICAgIDxzdG9wIHN0b3AtY29sb3I9IiMyMTFDMUQiIG9mZnNldD0iMTAwJSI+PC9zdG9wPgogICAgICAgIDwvcmFkaWFsR3JhZGllbnQ+CiAgICA8L2RlZnM+CiAgICA8ZyBpZD0iUGFnZS0xIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMSIgZmlsbD0ibm9uZSIgZmlsbC1ydWxlPSJldmVub2RkIj4KICAgICAgICA8ZyBpZD0iR3JvdXAiPgogICAgICAgICAgICA8ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgxNS4wMDAwMDAsIDYuMDAwMDAwKSIgZmlsbC1ydWxlPSJub256ZXJvIiBpZD0iUGF0aCI+CiAgICAgICAgICAgICAgICA8cGF0aCBkPSJNNDkuMzcxMDQwNiw3LjkwMTkzODMzIEw2Ny42OTU5OTYsMjUuNzU0MjQ5NyBDNjkuMjU1ODc2MiwyNy4yNzA2MjQ1IDcwLjAyMzYwMTgsMjguODA0OTc3OSA3MCwzMC4zNTExMzQgQzY5Ljk3NTI5MywzMS44OTcyOTAxIDY5LjMwNDE4NSwzMy4zMDY2MTcgNjcuOTkyMjk5MSwzNC41ODUxNTMzIEM2Ni42MTk4OSwzNS45MjMyNTIyIDY1LjEzODY0ODksMzYuNjAxMjIyMyA2My41NTQ2MTQzLDM2LjYzMDg2NjMgQzYxLjk3MDU3OTcsMzYuNjU0NzQ2MiA2MC4zOTg2MjIzLDM1LjkwNTQxMDkgNTguODM4NzQyMSwzNC4zODkwMzYxIEw0MC4wOTY3MTE2LDE2LjEzMjI4OTUgQzM3Ljk2ODUxNjgsMTQuMDU2OTMyNCAzNS45MTI5MjI1LDEyLjU4ODAxNTUgMzMuOTM1OTY3MiwxMS43MjU3MzA5IEMzMS45NTg4NzQ2LDEwLjg2MzQ0NjIgMjkuODc5MTI1OSwxMC43MjY2NzE5IDI3LjcwMjYyMjMsMTEuMzIxMzUwNSBDMjUuNTIwMDgwMSwxMS45MTAwODY2IDIzLjE4MDM5NywxMy40MjY1MTYzIDIwLjY3MTM1ODcsMTUuODY0NjY5NyBDMTcuMjEzMTYyMiwxOS4yMzY1NDE2IDE1LjU2MjU2NTgsMjIuNDAwMjE5MSAxNS43MzE5MjExLDI1LjM1NTgzOTMgQzE1LjkwMTEzOTEsMjguMzExMzIyMyAxNy42MTgxNjAyLDMxLjM3OTg5MTkgMjAuODc2OTQ1NiwzNC41NDk2MDc5IEwzOS43NzAyMTU1LDUyLjk2MDg4NzggQzQxLjM0ODIxMTUsNTQuNDk1MTAzOSA0Mi4xMjE5NzU4LDU2LjAyOTMyMDEgNDIuMDk3ODIxNCw1Ny41NTE3MzM1IEM0Mi4wNzM2NjcsNTkuMDgwMDQ4MyA0MS4zOTY1MjAzLDYwLjQ4OTUxMjQgNDAuMDYwMzQyOCw2MS43OTE3OTE0IEMzOC43MzAzNDExLDYzLjA4ODE2OTEgMzcuMjYxMTc3Miw2My43NjYxMzkxIDM1LjY2NTA2NTQsNjMuODE5NjYzMSBDMzQuMDY4OTUzNiw2My44NzMxODcxIDMyLjQ3ODg4MDQsNjMuMTI5ODkwMyAzMC45MDY5MjMsNjEuNTk1NTM2OSBMMTIuNTgxOTY3Nyw0My43NDMyMzkzIEM5LjYwMTM2OTYxLDQwLjg0MTI4MDIgNy40NDkwMzQxMywzOC4wOTM4NTQ0IDYuMTI1MDAyNDUsMzUuNTAwOTYxOSBDNC44MDA5NTcwNCwzMi45MDgyMDY2IDQuMzA1MjAxNywyOS45NzY0NjYzIDQuNjQ5ODEzNjIsMjYuNzA1NzQwOSBDNC45NTgxNTI3OCwyMy45MDQ3OTEyIDUuODcxMDY1NTksMjEuMTkzMDQ4IDcuMzk0NjMxODMsMTguNTY0NjEwMSBDOC45MTIxMzIwMywxNS45MzYwMzUgMTEuMDg4NjQ5NCwxMy4yNDgxMTY4IDEzLjkxMjEwNjYsMTAuNDk0NzQ4NSBDMTcuMjczNTQ4Miw3LjIxODA2Njg3IDIwLjQ4Mzg4NzYsNC43MDg1MjA3NSAyMy41NDMxMjQ3LDIuOTYwMTUzOSBDMjYuNTk2MzIzMywxLjIxMTc5OTQgMjkuNTUyNjI5NywwLjI0MjQ3MDk2MyAzMi40MDYyOCwwLjA0MDI4MDI0MjIgQzM1LjI2NTk2ODgsLTAuMTYxOTEwNzUzIDM4LjA4MzM4NzUsMC4zOTcwODc5NDUgNDAuODcwNDc1OSwxLjcxNzI3Mjc3IEM0My42NTc3MDE1LDMuMDM3NDYxNyA0Ni40ODcxOTc0LDUuMDk1MDU5NzggNDkuMzY1MDAyLDcuOTAxOTM4MzMgTDQ5LjM3MTA0MDYsNy45MDE5MzgzMyBaIiBmaWxsPSJ1cmwoI2xpbmVhckdyYWRpZW50LWV5dmQ5c3lnZnktMSkiPjwvcGF0aD4KICAgICAgICAgICAgICAgIDxwYXRoIGQ9Ik0yMC42MjI5MTI2LDc5LjkzNTQ1MTUgTDIuMzA0MDIzMzYsNjIuMDgzMTUzOSBDMC43NDQxOTM5NTIsNjAuNTYwNzQwNCAtMC4wMjM2Mjk1NTQxLDU5LjAzMjQyNTcgMi4wNDU4MDg0OWUtMTUsNTcuNDg2MjY5NiBDMC4wMjQ3MzcyOTkzLDU1Ljk0MDExMzUgMC42OTU4Mjc1MSw1NC41MzA3ODY2IDIuMDA3Nzc1MTMsNTMuMjUyMTEzIEMzLjM4MDE4NDI0LDUxLjkxNDE1MTQgNC44NjE0MjUzOCw1MS4yMzYxODEzIDYuNDQ1NDMyNTIsNTEuMjA2NCBDOC4wMjk0NTMzOSw1MS4xODI2NTczIDkuNjAxMzY5NjEsNTEuOTI1OTU0MSAxMS4xNjEyMDg2LDUzLjQ0ODM2NzUgTDI5Ljg5NzI0MTcsNzEuNzA1MTE0MSBDMzIuMDMxNDc1MSw3My43ODA0NzExIDM0LjA4MTAzMDgsNzUuMjQ5MzYwNiAzNi4wNTc5ODYxLDc2LjExMTY0NTMgQzM4LjAzNTA3ODcsNzYuOTczOTI5OSA0MC4xMTQ4Mjc0LDc3LjEwNDcyMDUgNDIuMjk3MzY5Niw3Ni41MTU5NTcgQzQ0LjQ3OTkxMTgsNzUuOTI3MzMwNyA0Ni44MTk1OTQ5LDc0LjQxMDgxODYgNDkuMzI4NjMzMiw3MS45NjY2OTUzIEM1Mi43ODY5NjY5LDY4LjU5NDgyMzMgNTQuNDM3NDI2MSw2NS40MzExNDU5IDU0LjI2ODIwODEsNjIuNDc1NjYyOSBDNTQuMDk4ODUyOCw1OS41MjAwNDI2IDUyLjM4MTgzMTcsNTYuNDUxNDczMSA0OS4xMjMxODM2LDUzLjI3NTk5MjkgTDM5LjA1NjgzNzMsNDMuNTUyODg2MSBDMzcuNDc4ODQxMyw0Mi4wMTg2NyAzNi43MDQ5Mzk4LDQwLjQ4NDMxNjYgMzYuNzI5MDk0MiwzOC45NjIwNDA0IEMzNi43NTMyNDg2LDM3LjQzMzcyNTcgMzcuNDMwMzk1MiwzNi4wMjQyNjE1IDM4Ljc2NjU3MjcsMzQuNzIxOTgyNSBDNDAuMDk2NzExNiwzMy40MjU0Njc2IDQxLjU2NTg3NTYsMzIuNzQ3NjM0OCA0My4xNjE4NTAxLDMyLjY5NDExMDggQzQ0Ljc1Nzk2MTksMzIuNjQwNTg2OSA0Ni4zNDgwMzUxLDMzLjM4Mzg4MzYgNDcuOTE5OTkyNSwzNC45MTgyMzcgTDU3LjQxMTk4NTYsNDQuMDgyMjI0MyBDNjAuMzkyNTgzNyw0Ni45ODQxODM0IDYyLjU0NDkzMjksNDkuNzMxNjA5MiA2My44NjkwMzMyLDUyLjMyNDUwMTcgQzY1LjE5Mjk5NjMsNTQuOTE3MjU3IDY1LjY4ODcxMDQsNTcuODQ4OTk3MyA2NS4zNDQwOTg1LDYxLjExOTcyMjcgQzY1LjAzNTg1NTQsNjMuOTIwNjcyNCA2NC4xMjI5Mjg5LDY2LjYzMjQxNTYgNjIuNTk5MjgwMyw2OS4yNjA5OTA3IEM2MS4wODE4MDc1LDcxLjg4OTQyODYgNTguOTA1MzAzOSw3NC41Nzc0MjkxIDU2LjA4MTg0NjcsNzcuMzMwNzU2MyBDNTIuNzIwNDA1MSw4MC42MDczODMgNDkuNTEwMDY1Nyw4My4xMTY5NzAzIDQ2LjQ1MDgyODYsODQuODY1MjgyMiBDNDMuMzkxNTkxNCw4Ni42MTM3MzE0IDQwLjQzNTI4NSw4Ny41ODg5NjU0IDM3LjU3NTU5NjEsODcuNzkxMTIxMiBDMzQuNzE1OTA3Myw4Ny45OTM0MTQzIDMxLjg5ODQ4ODYsODcuNDM0Mjk0OSAyOS4xMTE0MDAyLDg2LjExNDE3NDUgQzI2LjMyNDE3NDUsODQuNzkzOTE3IDIzLjQ5NDY3ODcsODIuNzM2NDAxMiAyMC42MTY4NzQsNzkuOTI5NTUwMSBMMjAuNjIyOTEyNiw3OS45MzU0NTE1IFoiIGZpbGw9InVybCgjbGluZWFyR3JhZGllbnQtZXl2ZDlzeWdmeS0yKSI+PC9wYXRoPgogICAgICAgICAgICAgICAgPHBhdGggZD0iTTMyLjA0OTU5MDksMzMuODcxNjM3OCBDMzUuNzY1OTM3NSwzMy44NzE2Mzc4IDM4Ljc3ODY0OTksMzAuOTA4MzMyMSAzOC43Nzg2NDk5LDI3LjI1Mjc4MzIgQzM4Ljc3ODY0OTksMjMuNTk3MzcxNSAzNS43NjU5Mzc1LDIwLjYzNDA2NTggMzIuMDQ5NTkwOSwyMC42MzQwNjU4IEMyOC4zMzMyNDQyLDIwLjYzNDA2NTggMjUuMzIwNTMxOCwyMy41OTczNzE1IDI1LjMyMDUzMTgsMjcuMjUyNzgzMiBDMjUuMzIwNTMxOCwzMC45MDgzMzIxIDI4LjMzMzI0NDIsMzMuODcxNjM3OCAzMi4wNDk1OTA5LDMzLjg3MTYzNzggWiIgZmlsbD0idXJsKCNyYWRpYWxHcmFkaWVudC1leXZkOXN5Z2Z5LTMpIj48L3BhdGg+CiAgICAgICAgICAgIDwvZz4KICAgICAgICAgICAgPHJlY3QgaWQ9IlJlY3RhbmdsZSIgeD0iMCIgeT0iMCIgd2lkdGg9IjEwMCIgaGVpZ2h0PSIxMDAiPjwvcmVjdD4KICAgICAgICA8L2c+CiAgICA8L2c+Cjwvc3ZnPg==`;
var sat20Logo = `data:image/svg+xml;base64,PHN2ZyBpZD0i5Zu+5bGCXzEiIGRhdGEtbmFtZT0i5Zu+5bGCIDEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDIwNy41OCAyMDguMDIiPjxwYXRoIGQ9Ik0yMjcsMTc2Ljc4Yy04LjE0LDQuMTYtMTYuMjcsOC4yMy0yMy42NCwxMy44M2ExMDIuNjUsMTAyLjY1LDAsMCwwLTI5LDM0LjgsMTAwLjUxLDEwMC41MSwwLDAsMC0xMS41NCw0NS41Yy0uMjEsMTEuODktNC4xLDIyLjQ2LTE0LDI5LjUzLTEyLjUzLDguOTQtMjUuMjQsMTAuMi0zOS4yLDEuODMtMTIuNzEtNy42MS0xOC43NS0yMy41My0xNS4xLTM3LjcsMy43MS0xNC4zNiwxNS4yMS0yNC40LDI5LjY5LTI1LjY3LDkuMjEtLjgxLDE4LjE3LTIuMDcsMjUuNTYtOC40MiwxMC44My05LjMyLDE1LjA5LTIxLjA2LDExLjYyLTM0Ljg1LTMuNjctMTQuNjMtMTMuNTYtMjMuMjMtMjguNDQtMjUuODYtNy0xLjI0LTE0LjIxLTEuMDgtMjAuNzctNC42NS0xMi4zLTYuNjctMTguNzMtMTcuMDYtMTguNTgtMzAuNzUuMTctMTUuNDksOC0yNi43MiwyMi41OC0zMi4xMSwxMy4wOC00LjgzLDI1LjM5LTIuMzIsMzUuNjEsNy4zOCw3LjU3LDcuMTgsMTAuNjUsMTYuNDUsMTEuMjIsMjYuODMsMSwxNy45MywxMy42OCwzMC41OCwzMi4xMiwzMi40OCwxNS42MiwxLjYxLDMxLjUyLTEwLDM1LjU0LTI2LjE0QTc4LDc4LDAsMCwwLDIzMi4xMSwxMzFjMS4wOS0xMi42LDEwLjY5LTI1LjYyLDIyLjkxLTI4Ljc4LDcuODUtMiwxNi4yOC0zLDI0LjI2LjY2LTEuNDMsNS42OS01LjU4LDkuODItOC40MSwxNC43Mi0zLjI1LDEuMzYtNi44NS44OS0xMC4xOSwyLjEtNy42OCwyLjc4LTExLjUyLDkuMDktMTAuMDcsMTcuMTQuMzQsMS45NCwxLjQxLDMuNzcuODgsNS44NC05LjQ5LDkuMjEtMTYuMDUsMjAuNTUtMjMsMzEuNkMyMjgsMTc1LjA2LDIyNy43NywxNzYuMDksMjI3LDE3Ni43OFoiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC05My40NSAtOTkuODcpIiBmaWxsPSIjOTQ1ZWY4Ii8+PHBhdGggZD0iTTE4OC44MywyNTAuODVhNTUuNzIsNTUuNzIsMCwwLDEsNTYuNTEtNTUuNzNjMzIuMDkuMjUsNTUuMjksMjYuNiw1NS42Niw1Ni41My4zOCwzMC45LTI1LjMxLDU2LjExLTU2LjMzLDU2LjFDMjEzLjMyLDMwNy43NCwxODguODIsMjgyLjc3LDE4OC44MywyNTAuODVaIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtOTMuNDUgLTk5Ljg3KSIgZmlsbD0iIzllNGVmNSIvPjxwYXRoIGQ9Ik0yNzAuODIsMTE3LjQ1YzEuMTktNS44Miw1LjQ1LTkuODYsOC40Ni0xNC42MiwyMC43Nyw3LjE2LDI4LjYzLDM1LDE0Ljg2LDUyLjM1LTcuMjgsOS4xOC0xNi42MSwxMy44Ni0yOC4zNSwxNC0xMy4zOS4xMi0yNi4yNiwzLjExLTM4LjgsNy42NC0uMTUtNi4xMSw0LjY2LTkuNzEsNy40Mi0xNC4yOCwzLjQyLTUuNjYsNy42OC0xMC44LDExLjQxLTE2LjI3LDEuMzEtMS45MiwyLjYtMy40NCw1LjEzLTMuMTksMywyLjU4LDYuMDcsNS4wOCw5LjkyLDYuNDZhMTUuNjUsMTUuNjUsMCwwLDAsMTkuNTctNy4zYzQtNy41NywyLjA4LTE1Ljg1LTQuOC0yMC43NUMyNzMuOTQsMTIwLjI0LDI3MS40OSwxMTkuOSwyNzAuODIsMTE3LjQ1WiIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTkzLjQ1IC05OS44NykiIGZpbGw9IiM5ZTRlZjUiLz48cGF0aCBkPSJNMjcwLjgyLDExNy40NWM0LjI1LDIuMjEsOC41MSw0LjMzLDEwLjg4LDguOTQsMy40MSw2LjY2LDIuNywxNC0yLjEzLDE5LjQxLTUuMTUsNS43Ni0xMi40Miw3LjY5LTE5LjM1LDQuNzQtMy43Mi0xLjU4LTcuOC0zLTkuMjctNy41LTEuNjUtNS44NS0zLjMxLTExLjY1LjI1LTE3LjQ5QzI1NS43OSwxMTgsMjYyLjg5LDExNi43OCwyNzAuODIsMTE3LjQ1WiIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTkzLjQ1IC05OS44NykiIGZpbGw9IiNmY2ZiZmUiLz48cGF0aCBkPSJNMTI4LjI0LDI1NS44MmExNy4xNywxNy4xNywwLDAsMS0uNTIsMzQuMzRjLTkuMDctLjIxLTE3LjIyLTYuNTMtMTcuMjgtMTcuMjlDMTEwLjM5LDI2My40NiwxMTguNjgsMjU1LjYsMTI4LjI0LDI1NS44MloiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC05My40NSAtOTkuODcpIiBmaWxsPSIjZmNmYmZlIi8+PHBhdGggZD0iTTExMC45MiwxMzQuNDlhMTcuNTEsMTcuNTEsMCwwLDEsMTctMTcuMzNjOS4xOC0uMSwxNy4xOCw3Ljg2LDE3LjI2LDE3LjE3LjA4LDkuNjEtOCwxNy44LTE3LjM1LDE3LjYyQTE3LjU3LDE3LjU3LDAsMCwxLDExMC45MiwxMzQuNDlaIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtOTMuNDUgLTk5Ljg3KSIgZmlsbD0iI2ZjZmJmZSIvPjwvc3ZnPg==`;
var okxLogo = `data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPHN2ZyB4bWxuczp4b2RtPSJodHRwOi8vd3d3LmNvcmVsLmNvbS9jb3JlbGRyYXcvb2RtLzIwMDMiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHZlcnNpb249IjEuMSIgaWQ9IkxheWVyXzEiIHg9IjBweCIgeT0iMHB4IiB2aWV3Qm94PSIwIDAgMjUwMCAyNTAwIiBzdHlsZT0iZW5hYmxlLWJhY2tncm91bmQ6bmV3IDAgMCAyNTAwIDI1MDA7IiB4bWw6c3BhY2U9InByZXNlcnZlIj4KPHN0eWxlIHR5cGU9InRleHQvY3NzIj4KCS5zdDB7ZmlsbC1ydWxlOmV2ZW5vZGQ7Y2xpcC1ydWxlOmV2ZW5vZGQ7fQoJLnN0MXtmaWxsOiNGRkZGRkY7fQo8L3N0eWxlPgo8ZyBpZD0iTGF5ZXJfeDAwMjBfMSI+Cgk8ZyBpZD0iXzIxODczODEzMjM4NTYiPgoJCTxyZWN0IHk9IjAiIGNsYXNzPSJzdDAiIHdpZHRoPSIyNTAwIiBoZWlnaHQ9IjI1MDAiPjwvcmVjdD4KCQk8Zz4KCQkJPHBhdGggY2xhc3M9InN0MSIgZD0iTTE0NjMsMTAxNWgtNDA0Yy0xNywwLTMxLDE0LTMxLDMxdjQwNGMwLDE3LDE0LDMxLDMxLDMxaDQwNGMxNywwLDMxLTE0LDMxLTMxdi00MDQgICAgIEMxNDk0LDEwMjksMTQ4MCwxMDE1LDE0NjMsMTAxNXoiPjwvcGF0aD4KCQkJPHBhdGggY2xhc3M9InN0MSIgZD0iTTk5Niw1NDlINTkyYy0xNywwLTMxLDE0LTMxLDMxdjQwNGMwLDE3LDE0LDMxLDMxLDMxaDQwNGMxNywwLDMxLTE0LDMxLTMxVjU4MEMxMDI3LDU2MywxMDEzLDU0OSw5OTYsNTQ5eiI+PC9wYXRoPgoJCQk8cGF0aCBjbGFzcz0ic3QxIiBkPSJNMTkzMCw1NDloLTQwNGMtMTcsMC0zMSwxNC0zMSwzMXY0MDRjMCwxNywxNCwzMSwzMSwzMWg0MDRjMTcsMCwzMS0xNCwzMS0zMVY1ODAgICAgIEMxOTYxLDU2MywxOTQ3LDU0OSwxOTMwLDU0OXoiPjwvcGF0aD4KCQkJPHBhdGggY2xhc3M9InN0MSIgZD0iTTk5NiwxNDgySDU5MmMtMTcsMC0zMSwxNC0zMSwzMXY0MDRjMCwxNywxNCwzMSwzMSwzMWg0MDRjMTcsMCwzMS0xNCwzMS0zMXYtNDA0ICAgICBDMTAyNywxNDk2LDEwMTMsMTQ4Miw5OTYsMTQ4MnoiPjwvcGF0aD4KCQkJPHBhdGggY2xhc3M9InN0MSIgZD0iTTE5MzAsMTQ4MmgtNDA0Yy0xNywwLTMxLDE0LTMxLDMxdjQwNGMwLDE3LDE0LDMxLDMxLDMxaDQwNGMxNywwLDMxLTE0LDMxLTMxdi00MDQgICAgIEMxOTYxLDE0OTYsMTk0NywxNDgyLDE5MzAsMTQ4MnoiPjwvcGF0aD4KCQk8L2c+Cgk8L2c+CjwvZz4KPC9zdmc+Cg==`;
var closeIcon = `data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxZW0iIGhlaWdodD0iMWVtIiB2aWV3Qm94PSIwIDAgMjQgMjQiPjxwYXRoIGZpbGw9ImN1cnJlbnRDb2xvciIgZD0iTTEzLjQ2IDEyTDE5IDE3LjU0VjE5aC0xLjQ2TDEyIDEzLjQ2TDYuNDYgMTlINXYtMS40NkwxMC41NCAxMkw1IDYuNDZWNWgxLjQ2TDEyIDEwLjU0TDE3LjU0IDVIMTl2MS40NkwxMy40NiAxMloiLz48L3N2Zz4=`;
// src/components/WalletSelectModal.tsx
var styles = {
modalRoot: (zIndex) => ({
position: "fixed",
top: 0,
left: 0,
width: "100vw",
height: "100vh",
zIndex
}),
overlay: (theme) => ({
backgroundColor: theme === "dark" ? "rgba(0, 0, 0, 0.7)" : "rgba(0, 0, 0, 0.3)",
width: "100%",
height: "100%",
position: "absolute",
top: 0,
left: 0
}),
modalContentBoxBase: (theme) => ({
position: "absolute",
top: "50%",
left: "50%",
transform: "translate(-50%, -50%)",
width: "18rem",
maxWidth: "90%",
minHeight: "7.5rem",
maxHeight: "90vh",
borderRadius: "0.75rem",
overflow: "hidden",
backgroundColor: theme === "dark" ? "#18181b" : "#ffffff",
color: theme === "dark" ? "#ecedee" : "#000000",
display: "flex",
flexDirection: "column",
boxShadow: "0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06)"
}),
headerBase: (theme) => ({
padding: "1rem",
position: "relative",
borderBottom: `1px solid ${theme === "dark" ? "#3f3f46" : "#e5e7eb"}`,
flexShrink: 0
}),
title: {
fontSize: "1.125rem",
lineHeight: "1.75rem",
fontWeight: "600",
textAlign: "center"
},
closeButton: {
position: "absolute",
top: "50%",
transform: "translateY(-50%)",
right: "1rem",
background: "none",
border: "none",
padding: "0.25rem",
cursor: "pointer",
borderRadius: "50%",
display: "flex",
alignItems: "center",
justifyContent: "center",
transition: "background-color 0.2s ease"
},
closeButtonHover: (theme) => ({
backgroundColor: theme === "dark" ? "rgba(255, 255, 255, 0.1)" : "rgba(0, 0, 0, 0.05)"
}),
closeIconBase: (theme) => ({
width: "1.25rem",
height: "1.25rem",
filter: theme === "dark" ? "invert(1)" : "none",
display: "block"
}),
walletListContainer: {
padding: "0.5rem",
display: "flex",
flexDirection: "column",
gap: "0.25rem",
flexGrow: 1,
overflowY: "auto"
},
walletItemBase: (theme, installed) => ({
height: "3.5rem",
cursor: installed ? "pointer" : "default",
display: "flex",
alignItems: "center",
justifyContent: "space-between",
padding: "0 0.75rem",
gap: "0.75rem",
borderRadius: "0.375rem",
position: "relative",
overflow: "hidden",
backgroundColor: "transparent",
color: theme === "dark" ? "#ecedee" : "#1f2937",
opacity: installed ? 1 : 0.5,
transition: "background-color 0.15s ease-out"
}),
walletItemHoverActive: (theme) => ({
backgroundColor: theme === "dark" ? "#27272a" : "#f3f4f6"
}),
loadingOverlay: {
position: "absolute",
top: 0,
left: 0,
width: "100%",
height: "100%",
backgroundColor: "rgba(0, 0, 0, 0.6)",
display: "flex",
alignItems: "center",
justifyContent: "center",
zIndex: 1,
borderRadius: "inherit"
},
loadingIcon: (theme) => ({
width: "1.5rem",
height: "1.5rem",
color: theme === "dark" ? "#a1a1aa" : "#9ca3af"
}),
walletInfoContainer: {
display: "flex",
alignItems: "center",
flex: "1 1 0%",
minWidth: 0
},
walletLogo: {
width: "2rem",
height: "2rem",
marginRight: "0.75rem",
flexShrink: 0
},
walletName: {
flex: "1 1 auto",
overflow: "hidden",
textOverflow: "ellipsis",
whiteSpace: "nowrap",
fontWeight: "500"
},
notInstalledText: (theme) => ({
fontSize: "0.75rem",
lineHeight: "1rem",
color: theme === "dark" ? "#a16207" : "#9a3412",
backgroundColor: theme === "dark" ? "rgba(252, 211, 77, 0.1)" : "rgba(255, 237, 213, 0.5)",
padding: "0.125rem 0.375rem",
borderRadius: "0.25rem",
whiteSpace: "nowrap",
marginLeft: "0.5rem",
flexShrink: 0,
fontWeight: "500"
})
};
var spinAnimation = `
spin {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
.animate-spin-modal { /* Use a specific class name */
animation: spin 1s linear infinite;
}
`;
var WalletSelectModal = ({
visible,
title = "Select Wallet",
theme = "light",
wallets = [],
zIndex = 100,
className,
onClick,
onClose
}) => {
const [isBrowser, setIsBrowser] = useState(false);
const [loading, setLoading] = useState(null);
const [hoveredWallet, setHoveredWallet] = useState(null);
const [hoveredClose, setHoveredClose] = useState(false);
const clickHandler = async (id, installed) => {
if (loading || !installed)
return;
setLoading(id);
try {
await onClick?.(id);
} catch (error) {
console.error("Wallet connection failed:", error);
} finally {
setLoading(null);
}
};
useEffect(() => {
setIsBrowser(true);
const styleTag = document.createElement("style");
styleTag.id = "spin-animation-style";
styleTag.innerHTML = spinAnimation;
if (!document.getElementById(styleTag.id)) {
document.head.appendChild(styleTag);
}
return () => {
const existingStyleTag = document.getElementById(styleTag.id);
if (existingStyleTag) {
if (existingStyleTag.parentNode) {
existingStyleTag.parentNode.removeChild(existingStyleTag);
}
}
};
}, []);
const modalContent = visible ? /* @__PURE__ */ React.createElement("div", {
style: styles.modalRoot(zIndex)
}, /* @__PURE__ */ React.createElement("div", {
style: styles.overlay(theme),
onClick: () => !loading && onClose?.()
}), /* @__PURE__ */ React.createElement("div", {
style: styles.modalContentBoxBase(theme),
className
}, /* @__PURE__ */ React.createElement("div", {
style: styles.headerBase(theme)
}, /* @__PURE__ */ React.createElement("h2", {
style: styles.title
}, title), /* @__PURE__ */ React.createElement("button", {
onClick: () => !loading && onClose?.(),
style: {
...styles.closeButton,
...hoveredClose ? styles.closeButtonHover(theme) : {}
},
onMouseEnter: () => setHoveredClose(true),
onMouseLeave: () => setHoveredClose(false),
disabled: !!loading,
"aria-label": "Close Wallet Select Modal"
}, /* @__PURE__ */ React.createElement("img", {
src: closeIcon,
alt: "close",
style: styles.closeIconBase(theme)
}))), /* @__PURE__ */ React.createElement("div", {
style: styles.walletListContainer
}, wallets.map((wallet) => {
const isLoadingThis = loading === wallet.id;
const isHovered = hoveredWallet === wallet.id;
const itemStyle = {
...styles.walletItemBase(theme, wallet.installed),
...(isHovered || isLoadingThis) && wallet.installed ? styles.walletItemHoverActive(theme) : {}
};
return /* @__PURE__ */ React.createElement("div", {
key: wallet.id,
onClick: () => clickHandler?.(wallet.id, wallet.installed),
style: itemStyle,
onMouseEnter: () => wallet.installed && setHoveredWallet(wallet.id),
onMouseLeave: () => setHoveredWallet(null),
"aria-disabled": !wallet.installed || !!loading,
role: "button",
tabIndex: wallet.installed && !loading ? 0 : -1
}, isLoadingThis && /* @__PURE__ */ React.createElement("div", {
style: styles.loadingOverlay
}, /* @__PURE__ */ React.createElement("svg", {
style: styles.loadingIcon(theme),
className: "animate-spin-modal",
xmlns: "http://www.w3.org/2000/svg",
fill: "none",
viewBox: "0 0 24 24"
}, /* @__PURE__ */ React.createElement("circle", {
className: "opacity-25",
cx: "12",
cy: "12",
r: "10",
stroke: "currentColor",
strokeWidth: "4"
}), /* @__PURE__ */ React.createElement("path", {
className: "opacity-75",
fill: "currentColor",
d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
}))), /* @__PURE__ */ React.createElement("div", {
style: styles.walletInfoContainer
}, /* @__PURE__ */ React.createElement("img", {
src: wallet.logo,
alt: `${wallet.name} logo`,
style: styles.walletLogo
}), /* @__PURE__ */ React.createElement("span", {
style: styles.walletName
}, wallet.name)), !wallet.installed && (wallet.downloadUrl ? /* @__PURE__ */ React.createElement("a", {
href: wallet.downloadUrl,
target: "_blank",
rel: "noopener noreferrer"
}, "Download") : /* @__PURE__ */ React.createElement("div", {
style: styles.notInstalledText(theme)
}, "Not Installed")));
})))) : null;
if (isBrowser) {
let portalContainer = document.getElementById("wallet-modal-portal");
if (!portalContainer) {
portalContainer = document.createElement("div");
portalContainer.id = "wallet-modal-portal";
document.body.appendChild(portalContainer);
}
return ReactDOM.createPortal(modalContent, portalContainer);
} else {
return null;
}
};
// src/utils/index.ts
var hideStr = (str, num = 10, placeholder = "*****") => {
if (typeof str === "string" && str) {
return `${str?.substring(0, num)}${placeholder}${str?.substring(str?.length - num)}`;
}
return "";
};
// src/components/ExitIcon.tsx
import React2 from "react";
function ExitIcon(props) {
return /* @__PURE__ */ React2.createElement("svg", {
xmlns: "http://www.w3.org/2000/svg",
width: "1em",
height: "1em",
viewBox: "0 0 24 24",
...props
}, /* @__PURE__ */ React2.createElement("path", {
fill: "currentColor",
d: "M13.34 8.17c-.93 0-1.69-.77-1.69-1.7a1.69 1.69 0 0 1 1.69-1.69c.94 0 1.7.76 1.7 1.69c0 .93-.76 1.7-1.7 1.7M10.3 19.93l-5.93-1.18l.34-1.7l4.15.85l1.35-6.86l-1.52.6v2.86H7v-3.96l4.4-1.87l.67-.08c.6 0 1.1.34 1.43.85l.86 1.35c.68 1.21 2.03 2.03 3.64 2.03v1.68c-1.86 0-3.56-.83-4.66-2.1l-.5 2.54l1.77 1.69V23h-1.69v-5.1l-1.78-1.69l-.84 3.72M21 23h-2V3H6v13.11l-2-.42V1h17v22M6 23H4v-3.22l2 .42V23Z"
}));
}
// src/hooks/react.ts
import { create } from "zustand";
import { devtools } from "zustand/middleware";
// src/connectors/base.ts
class BtcConnector {
ready = false;
connected = false;
address = "";
downloadUrl = "";
publicKey;
network;
networks = ["mainnet", "testnet"];
constructor(network) {
this.network = network;
}
get installed() {
return false;
}
disconnect() {
this.address = undefined;
this.publicKey = undefined;
}
getAccount() {
return this.address;
}
isAuthorized() {
const address = this.getAccount();
return !!address;
}
async getNetwork() {
if (!this.network) {
throw new Error("Something went wrong while connecting");
}
return this.network;
}
async getPublicKey() {
if (!this.publicKey) {
throw new Error("Something went wrong while connecting");
}
return this.publicKey;
}
}
// src/connectors/unisat.ts
class UnisatConnector extends BtcConnector {
id = "unisat";
name = "Unisat";
logo = unisatLogo;
networks = ["mainnet", "testnet"];
homepage = "https://unisat.io";
banance = { confirmed: 0, unconfirmed: 0, total: 0 };
constructor(network) {
super(network);
}
get wallet() {
return window.unisat;
}
get installed() {
return !!window.unisat;
}
on(event, handler) {
if (!this.wallet) {
throw new Error("Unisat not installed");
}
this.wallet.on(event, handler);
}
removeListener(event, handler) {
if (!this.wallet) {
throw new Error("Unisat not installed");
}
this.wallet.removeListener(event, handler);
}
async connect() {
this.connected = false;
try {
if (!this.wallet) {
throw new Error("Unisat not installed");
}
await this.requestAccounts();
await this.getCurrentInfo();
this.connected = true;
return true;
} catch (error) {
throw error;
}
}
async requestAccounts() {
if (!this.wallet) {
throw new Error("Unisat not installed");
}
return this.wallet.requestAccounts();
}
async getCurrentInfo() {
if (!this.wallet) {
throw new Error("Unisat not installed");
}
const accounts = await this.wallet.getAccounts();
if (accounts.length) {
this.address = accounts[0];
const [publicKey, network, banance] = await Promise.all([
this.wallet.getPublicKey(),
this.wallet.getNetwork(),
this.wallet.getBalance()
]);
this.publicKey = publicKey;
this.network = network;
this.banance = banance;
this.connected = true;
}
}
async disconnect() {
this.address = undefined;
this.publicKey = undefined;
this.connected = false;
this.banance = { confirmed: 0, unconfirmed: 0, total: 0 };
}
async getAccounts() {
if (!this.wallet) {
throw new Error("Unisat not installed");
}
return this.wallet.getAccounts();
}
async sendToAddress(toAddress, amount) {
if (!this.wallet) {
throw new Error("Unisat not installed");
}
return this.wallet?.sendBitcoin(toAddress, amount);
}
async switchNetwork(network) {
if (!this.wallet) {
throw new Error("Unisat not installed");
}
await this.wallet.switchNetwork(network);
}
async getPublicKey() {
if (!this.wallet) {
throw new Error("Unisat not installed");
}
return this.wallet.getPublicKey();
}
async getBalance() {
if (!this.wallet) {
throw new Error("Unisat not installed");
}
return this.wallet.getBalance();
}
async signPsbt(psbtHex, options) {
if (!this.wallet) {
throw new Error("Unisat not installed");
}
return this.wallet.signPsbt(psbtHex, options);
}
async signMessage(message) {
if (!this.wallet) {
throw new Error("Unisat not installed");
}
return this.wallet.signMessage(message);
}
async signPsbts(psbtHexs, options) {
if (!this.wallet) {
throw new Error("Unisat not installed");
}
return this.wallet.signPsbts(psbtHexs, options);
}
async pushTx(rawTx) {
if (!this.wallet) {
throw new Error("Unisat not installed");
}
return this.wallet.pushTx({ rawtx: rawTx });
}
async pushPsbt(psbtHex) {
if (!this.wallet) {
throw new Error("Unisat not installed");
}
return this.wallet.pushPsbt(psbtHex);
}
}
// src/connectors/sat20.ts
class Sat20Connector extends BtcConnector {
id = "sat20";
name = "SAT20";
logo = sat20Logo;
networks = ["mainnet", "testnet"];
homepage = "https://sat20.org";
downloadUrl = "https://github.com/sat20-labs/sat20wallet/releases/download/0.0.1/sat20wallet-chrome.zip";
banance = { confirmed: 0, unconfirmed: 0, total: 0 };
constructor(network) {
super(network);
}
get wallet() {
return window.sat20;
}
get installed() {
return !!window.sat20;
}
on(event, handler) {
if (!this.wallet) {
throw new Error("SAT20 not installed");
}
this.wallet.on(event, handler);
}
removeListener(event, handler) {
if (!this.wallet) {
throw new Error("SAT20 not installed");
}
this.wallet.removeListener(event, handler);
}
async connect() {
this.connected = false;
try {
if (!this.wallet) {
throw new Error("SAT20 not installed");
}
await this.requestAccounts();
await this.getCurrentInfo();
this.connected = true;
return true;
} catch (error) {
throw error;
}
}
async requestAccounts() {
if (!this.wallet) {
throw new Error("SAT20 not installed");
}
return this.wallet.requestAccounts();
}
async getCurrentInfo() {
if (!this.wallet) {
throw new Error("SAT20 not installed");
}
const accounts = await this.wallet.getAccounts();
if (accounts.length) {
this.address = accounts[0];
const [publicKey, network, banance] = await Promise.all([
this.wallet.getPublicKey(),
this.wallet.getNetwork(),
this.wallet.getBalance()
]);
this.publicKey = publicKey;
this.network = network;
this.banance = banance;
this.connected = true;
}
}
async disconnect() {
this.address = undefined;
this.publicKey = undefined;
this.connected = false;
this.banance = { confirmed: 0, unconfirmed: 0, total: 0 };
}
async getAccounts() {
if (!this.wallet) {
throw new Error("SAT20 not installed");
}
return this.wallet.getAccounts();
}
async sendToAddress(toAddress, amount) {
if (!this.wallet) {
throw new Error("SAT20 not installed");
}
return this.wallet?.sendBitcoin(toAddress, amount);
}
async switchNetwork(network) {
if (!this.wallet) {
throw new Error("SAT20 not installed");
}
await this.wallet.switchNetwork(network);
}
async getPublicKey() {
if (!this.wallet) {
throw new Error("SAT20 not installed");
}
return this.wallet.getPublicKey();
}
async getBalance() {
if (!this.wallet) {
throw new Error("SAT20 not installed");
}
return this.wallet.getBalance();
}
async signPsbt(psbtHex, options) {
if (!this.wallet) {
throw new Error("SAT20 not installed");
}
return this.wallet.signPsbt(psbtHex, options);
}
async signMessage(message) {
if (!this.wallet) {
throw new Error("SAT20 not installed");
}
return this.wallet.signMessage(message);
}
async signPsbts(psbtHexs, options) {
if (!this.wallet) {
throw new Error("SAT20 not installed");
}
return this.wallet.signPsbts(psbtHexs, options);
}
async pushTx(rawTx) {
if (!this.wallet) {
throw new Error("SAT20 not installed");
}
return this.wallet.pushTx({ rawtx: rawTx });
}
async pushPsbt(psbtHex) {
if (!this.wallet) {
throw new Error("SAT20 not installed");
}
return this.wallet.pushPsbt(psbtHex);
}
async addAccounts(count) {
if (!this.wallet) {
throw new Error("SAT20 not installed");
}
return this.wallet.addAccounts(count);
}
}
// src/connectors/okx.ts
class OkxConnector extends BtcConnector {
id = "okx";
name = "OKX";
logo = okxLogo;
networks = ["mainnet"];
homepage = "https://www.okx.com/web3/build/docs/sdks/chains/bitcoin/provider";
banance = { confirmed: 0, unconfirmed: 0, total: 0 };
constructor(network) {
super(network);
this.network = "mainnet";
}
get wallet() {
return window.okxwallet?.bitcoin;
}
get installed() {
return !!window.okxwallet;
}
on(event, handler) {
if (this.network === "mainnet") {
this.wallet?.on(event, handler);
}
}
async connect() {
this.connected = false;
try {
if (!this.wallet) {
throw new Error("OkxWallet not installed");
}
const res = await this.wallet.connect();
this.connected = true;
this.address = res.address;
this.publicKey = res.publicKey;
await this.switchNetwork("mainnet");
await this.getCurrentInfo();
} catch (error) {
throw error;
}
return this.connected;
}
async getCurrentInfo() {
if (!this.wallet) {
throw new Error("OkxWallet not installed");
}
const accounts = await this.wallet.getAccounts();
if (accounts.length) {
this.address = accounts[0];
const [publicKey, network, banance] = await Promise.all([
this.wallet.getPublicKey(),
this.wallet.getNetwork(),
this.wallet.getBalance()
]);
this.publicKey = publicKey;
this.banance = banance;
this.connected = true;
}
}
async disconnect() {
this.address = undefined;
this.publicKey = undefined;
this.connected = false;
this.banance = { confirmed: 0, unconfirmed: 0, total: 0 };
}
async getAccounts() {
if (!this.wallet) {
throw new Error("OkxWallet not installed");
}
return this.wallet.getAccounts();
}
async getNetwork() {
return this.network;
}
async getPublicKey() {
if (!this.wallet) {
throw new Error("OkxWallet not installed");
}
return this.wallet.getPublicKey();
}
async getBalance() {
if (!this.wallet) {
throw new Error("OkxWallet not installed");
}
return this.wallet.getBalance();
}
async sendToAddress(toAddress, amount) {
if (!this.wallet) {
throw new Error("OkxWallet not installed");
}
return this.wallet?.sendBitcoin(toAddress, amount);
}
async switchNetwork(network) {
if (!this.wallet) {
throw new Error("Unisat not installed");
}
switch (network) {
case "mainnet":
break;
case "testnet":
throw new Error("no implementation for okx testnet");
}
this.network = network;
}
async signPsbt(psbtHex, options) {
if (!this.wallet) {
throw new Error("OkxWallet not installed");
}
return this.wallet.signPsbt(psbtHex, options);
}
async signMessage(message) {
if (!this.wallet) {
throw new Error("OkxWallet not installed");
}
return this.wallet.signMessage(message);
}
async signPsbts(psbtHexs, options) {
if (!this.wallet) {
throw new Error("OkxWallet not installed");
}
return this.wallet.signPsbts(psbtHexs, options);
}
async pushTx(rawTx) {
if (this.network !== "mainnet") {
throw new Error("Can't get accounts on testnet");
}
if (!this.wallet) {
throw new Error("OkxWallet not installed");
}
return this.wallet.pushTx(rawTx);
}
async pushPsbt(psbtHex) {
if (this.network !== "mainnet") {
throw new Error("Can't get accounts on testnet");
}
if (!this.wallet) {
throw new Error("OkxWallet not installed");
}
return this.wallet.pushPsbt(psbtHex);
}
}
// src/connect.ts
class BtcWalletConnect {
local_storage_key = "_btc_connector_id_1";
local_disconnect_key = "_btc_disconnect_status_1";
connectorId;
localConnectorId;
disConnectStatus = false;
connected = false;
address;
publicKey;
network;
balance = { confirmed: 0, unconfirmed: 0, total: 0 };
connectors;
_connector;
get connector() {
if (!this.connectorId) {
return;
}
return this.connectors.find((c) => c.id === this.connectorId && c.instance.installed)?.instance;
}
constructor({
network = "mainnet",
enabledConnectors = ["sat20", "unisat", "okx"]
}) {
this.network = network;
const allConnectors = [
{ id: "sat20", instance: new Sat20Connector(this.network) },
{ id: "unisat", instance: new UnisatConnector(this.network) },
{ id: "okx", instance: new OkxConnector(this.network) }
];
if (enabledConnectors?.length) {
this.connectors = allConnectors.filter((c) => enabledConnectors.includes(c.id));
} else {
this.connectors = allConnectors;
}
this.localConnectorId = localStorage.getItem(this.local_storage_key) || undefined;
this.disConnectStatus = localStorage.getItem(this.local_disconnect_key) == "1";
}
switchConnector(id) {
const _c = this.connectors.find((c) => c.id === id && c.instance.installed)?.instance;
if (!_c) {
this.reset();
console.error("switchConnector: Connector not found: " + id);
return;
}
this.connectorId = id;
return _c;
}
async connect() {
if (!this.connector) {
this.reset();
console.error("connect: Connector not found");
return;
}
this.connected = await this.connector.connect();
if (this.connected) {
this.address = this.connector.address;
this.publicKey = this.connector.publicKey;
this.balance = this.connector.banance;
this.network = this.connector.network;
}
localStorage.setItem(this.local_storage_key, this.connectorId || "");
localStorage.removeItem(this.local_disconnect_key);
return this.connected;
}
async getCurrentInfo() {
if (!this.connector) {
this.reset();
console.error("getCurrentInfo: Connector not found");
return;
}
try {
if (this.connector.getCurrentInfo) {
await this.connector.getCurrentInfo();
this.address = this.connector.address;
this.publicKey = this.connector.publicKey;
this.network = this.connector.network;
this.balance = this.connector.banance;
this.connected = this.connector.connected;
}
} catch (error) {
throw error;
}
}
async check() {
if (this.disConnectStatus) {
return false;
}
this.connectorId = this.localConnectorId || this.connectorId;
const _c = this.connectors.find((c) => c.id === this.connectorId && c.instance.installed)?.instance;
if (!_c) {
this.reset();
console.error("check: Connector not found");
return;
}
try {
await this.getCurrentInfo();
} catch (error) {
console.error(error);
}
}
async disconnect() {
if (!this.connector) {
this.reset();
console.error("disconnect: Connector not found");
return;
}
await this.connector.disconnect();
this.reset();
}
async getAccounts() {
if (!this.connector) {
this.reset();
console.error("getAccounts: Connector not found");
return;
}
return this.connector.getAccounts();
}
reset() {
this.connectorId = undefined;
this.connected = false;
this.address = undefined;
this.publicKey = undefined;
this.balance = { confirmed: 0, unconfirmed: 0, total: 0 };
localStorage.setItem(this.local_disconnect_key, "1");
}
async getNetwork() {
if (!this.connector) {
this.reset();
console.error("getNetwork: Connector not found");
return;
}
return this.connector.network;
}
async switchNetwork(network) {
if (!this.connector) {
this.reset();
console.error("switchNetwork: Connector not found");
return;
}
await this.connector.switchNetwork(network);
this.network = network;
await this.getCurrentInfo();
}
async sendToAddress(toAddress, amount) {
if (!this.connector) {
this.reset();
console.error("sendToAddress: Connector not found");
return;
}
if (amount <= 0) {
console.error("sendToAddress: Invalid amount");
return;
}
return this.connector.sendToAddress(toAddress, amount);
}
async signMessage(message, type) {
if (!this.connector) {
this.reset();
console.error("signMessage: Connector not found");
return;
}
return this.connector.signMessage(message);
}
async signPsbt(psbtHex, options) {
if (!this.connector) {
this.reset();
console.error("signPsbt: Connector not found");
return;
}
return this.connector.signPsbt(psbtHex, options);
}
async signPsbts(psbtHexs, options) {
if (!this.connector) {
this.reset();
console.error("signPsbts: Connector not found");
return;
}
return this.connector.signPsbts(psbtHexs, options);
}
async pushTx(rawTx) {
if (!this.connector) {
this.reset();
console.error("pushTx: Connector not found");
return;
}
return this.connector.pushTx(rawTx);
}
async pushPsbt(psbtHex) {
if (!this.connector) {
this.reset();
console.error("pushPsbt: Connector not found");
return;
}
return this.connector.pushPsbt(psbtHex);
}
on(event, handler) {
if (!this.connector) {
return;
}
if (this.connector instanceof Sat20Connector) {
this.connector.on(event, handler);
} else if (this.connector instanceof UnisatConnector) {
this.connector.on(event, handler);
} else if (this.connector instanceof OkxConnector) {
this.connector.on(event, handler);
}
}
removeListener(event, handler) {
if (!this.connector) {
return;
}
if (this.connector instanceof Sat20Connector) {
this.connector.removeListener(event, handler);
} else if (this.connector instanceof UnisatConnector) {
this.connector.removeListener(event, handler);
} else if (this.connector instanceof OkxConnector) {
return;
}
}
addAccounts(count) {
if (!this.connector) {
console.error("addAccounts: Connector not found");
this.reset();
return false;
}
if (this.connector instanceof Sat20Connector) {
this.connector.addAccounts(count);
} else if (this.connector instanceof UnisatConnector) {
console.error("no implement");
return false;
} else if (this.connector instanceof OkxConnector) {
console.error("no implement");
return false;
}
}
}
var connect_default = BtcWalletConnect;
// src/hooks/react.ts
var defaultInitState = {
initStatus: false,
modalVisible: false,
balance: { confirmed: 0, unconfirmed: 0, total: 0 },
connectors: [],
publicKey: "",
address: "",
connected: false,
network: "mainnet"
};
var useReactWalletStore = create()(devtools((set, get) => ({
...defaultInitState,
setModalVisible: (visible) => {
set(() => ({ modalVisible: visible }));
},
init: (config = {}) => {
try {
const { network = "mainnet" } = config;
const btcWallet = new connect_default(config);
window.btcWallet = btcWallet;
set(() => ({
btcWallet,
network,
connector: btcWallet.connector,
localConnectorId: btcWallet.localConnectorId,
connectors: btcWallet.connectors.map((con) => ({
id: con.id,
name: con.instance.name,
logo: con.instance.logo,
downloadUrl: con.instance.downloadUrl,
connector: con.instance,
get installed() {
return con.instance.installed;
}
})),
initStatus: true
}));
} catch (error) {
console.error("Error initializing Wallet", error);
set(() => ({ initStatus: false }));
throw error;
}
},
switchConnector(id) {
const btcWallet = get().btcWallet;
if (!btcWallet) {
throw new Error("Wallet not initialized");
}
btcWallet.switchConnector(id);
set(() => ({
connectorId: id,
connector: btcWallet.connector,
localConnectorId: btcWallet.localConnectorId
}));
},
check: async () => {
try {
const btcWallet = get().btcWallet;
if (!btcWallet) {
throw new Error("Wallet not initialized");
}
await btcWallet.check();
const address = btcWallet.address;
const publicKey = btcWallet.publicKey;
const balance = btcWallet.balance;
const connected = btcWallet.connected;
const network = btcWallet.network;
const localConnectorId = btcWallet.localConnectorId;
set((state) => ({
publicKey,
address,
balance,
connected,
network,
localConnectorId
}));
} catch (error) {
throw error;
}
},
connect: async () => {
try {
const btcWallet = get().btcWallet;
if (!btcWallet) {
throw new Error("Wallet not initialized");
}
await btcWallet.connect();
const address = btcWallet.address;
const publicKey = btcWallet.publicKey;
const balance = btcWallet.balance;
const connected = btcWallet.connected;
const network = btcWallet.network;
const localConnectorId = btcWallet.localConnectorId;
set((state) => ({
publicKey,
address,
balance,
connected,
network,
localConnectorId
}));
} catch (error) {
console.error("Error connecting Wallet", error);
throw error;
}
},
disconnect: async () => {
const { btcWallet } = get();
if (!btcWallet) {
throw new Error("Wallet not initialized");
}
await btcWallet.disconnect();
set((state) => ({
balance: { confirmed: 0, unconfirmed: 0, total: 0 },
connectorId: undefined,
publicKey: "",
address: "",
initStatus: false,
connected: false,
network: "mainnet"
}));
},
switchNetwork: async () => {
try {
const btcWallet = get().btcWallet;
if (!btcWallet) {
throw new Error("Wallet not initialized");
}
const network = get().network === "testnet" ? "mainnet" : "testnet";
await btcWallet.switchNetwork(network);
const newNetwork = await btcWallet.getNetwork();
const address = btcWallet.address;
const publicKey = btcWallet.publicKey;
const balance = btcWallet.balance;
const connected = btcWallet.connected;
const localConnectorId = btcWallet.localConnectorId;
set((state) => ({
publicKey,
address,
balance,
connected,
localConnectorId,
network: newNetwork
}));
} catch (error) {
throw error;
}
}
})));
// src/components/WalletConnectReact.tsx
var styles2 = {
buttonBase: {
borderWidth: "1px",
borderStyle: "solid",
borderRadius: "0.75rem",
height: "2.5rem",
paddingLeft: "1rem",
paddingRight: "1rem",
lineHeight: "1",
backgroundClip: "text",
WebkitBackgroundClip: "text",
color: "transparent",
cursor: "pointer",
transition: "border-color 0.2s ease",
display: "inline-flex",
alignItems: "center",
justifyContent: "center"
},
connectButtonTheme: (theme) => ({
backgroundImage: theme === "dark" ? "linear-gradient(to right, #ec4899, #8b5cf6)" : "linear-gradient(to right, #3b82f6, #22c55e)",
borderColor: theme === "dark" ? "#4b5563" : "#d1d5db"
}),
disconnectButtonTheme: (theme) => ({
backgroundImage: theme === "dark" ? "linear-gradient(to right, #ec4899, #8b5cf6)" : "linear-gradient(to right, #3b82f6, #22c55e)",
borderColor: "#d1d5db"
}),
buttonHover: {
borderColor: "#f59e0b"
},
disconnectButtonLayout: {
display: "flex",
justifyContent: "center",
alignItems: "center"
},
disconnectText: {
marginRight: "0.25rem"
},
exitIcon: (theme) => ({
color: theme === "dark" ? "#ffffff" : "#000000",
width: "1em",
height: "1em"
})
};
var WalletConnectReact = ({
config: { network = "mainnet", enabledConnectors } = {},
theme = "dark",
isSwitchNetwork = false,
ui: {
connectClass = "",
disconnectClass = "",
modalClass = "",
modalZIndex = 100
} = {},
text: {
connectText = "Connect",
disconnectText = "Disconnect",
modalTitle = "Select Wallet"
} = {},
onConnectSuccess,
onConnectError,
onDisconnectSuccess,
onDisconnectError,
children
}) => {
const {
connect,
modalVisible,
setModalVisible,
connectors,
connected,
address,
init,
disconnect,
initStatus,
btcWallet,
switchNetwork,
switchConnector
} = useReactWalletStore((state) => state);
const [connectHover, setConnectHover] = useState2(false);
const [disconnectHover, setDisconnectHover] = useState2(false);
const handleConnect = () => {
setModalVisible(true);
};
const walletSelect = async (id) => {
switchConnector(id);
try {
if (isSwitchNetwork) {
await btcWallet?.switchNetwork(network);
}
console.log("walletSelect");
await connect();
btcWallet && onConnectSuccess?.(btcWallet);
} catch (error) {
onConnectError?.(error);
} finally {
setModalVisible(false);
}
};
const handlerDisconnect = async () => {
try {
onDisconnectSuccess?.();
disconnect();
} catch (error) {
onDisconnectError?.(error);
}
};
const wallets = useMemo(() => {
return connectors?.map((c) => ({
id: c.id,
name: c.name,
logo: c.logo,
downloadUrl: c.connector.downloadUrl,
get installed() {
return c.installed;
}
})) || [];
}, [connectors]);
useEffect2(() => {
init({ network, enabledConnectors });
}, []);
useEffect2(() => {
init({ network, enabledConnectors });
}, [network]);
return /* @__PURE__ */ React3.createElement(React3.Fragment, null, !connected ? /* @__PURE__ */ React3.createElement(React3.Fragment, null, /* @__PURE__ */ React3.createElement("button", {
onClick: handleConnect,
style: {
...styles2.buttonBase,
...styles2.connectButtonTheme(theme),
...connectHover ? styles2.buttonHover : {}
},
onMouseEnter: () => setConnectHover(true),
onMouseLeave: () => setConnectHover(false),
className: connectClass
}, connectText), /* @__PURE__ */ React3.createElement(WalletSelectModal, {
theme,
className: modalClass,
zIndex: modalZIndex,
title: modalTitle,
onClose: () => setModalVisible(false),
visible: modalVisible,
wallets,
onClick: walletSelect
})) : children ? children : /* @__PURE__ */ React3.createElement("button", {
onClick: handlerDisconnect,
style: {
...styles2.buttonBase,
...styles2.disconnectButtonTheme(theme),
...styles2.disconnectButtonLayout,
...disconnectHover ? styles2.buttonHover : {}
},
onMouseEnter: () => setDisconnectHover(true),
onMouseLeave: () => setDisconnectHover(false),
className: disconnectClass
}, /* @__PURE__ */ React3.createElement("span", {
style: styles2.disconnectText
}, hideStr(address, 4, "***")), /* @__PURE__ */ React3.createElement(ExitIcon, {
style: styles2.exitIcon(theme)
})));
};
export {
useReactWalletStore,
WalletConnectReact
};