UNPKG

@bigmi/client

Version:

Reactive primitives for Bitcoin apps.

128 lines (127 loc) 5.83 kB
import { ConnectorChainIdDetectionError } from "../errors/connectors.js"; import { createConnector } from "../factories/createConnector.js"; import { MethodNotSupportedRpcError, ProviderNotFoundError, UserRejectedRequestError, getAddressChainId } from "@bigmi/core"; //#region src/connectors/leather.ts function leather(parameters = {}) { const { chainId, shimDisconnect = true } = parameters; return createConnector((config) => ({ id: "LeatherProvider", name: "Leather", type: leather.type, icon: "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxMjgiIGhlaWdodD0iMTI4IiBmaWxsPSJub25lIj4KICAgIDxwYXRoIGZpbGw9IiMxMjEwMEYiIGQ9Ik0wIDBoMTI4djEyOEgweiIvPgogICAgPHBhdGggZmlsbD0iI0Y1RjFFRCIgZD0iTTc0LjkxNyA1Mi43MTFjNy41Ni0xLjE3IDE4LjQ5Mi05LjEzIDE4LjQ5Mi0xNS4zMzUgMC0xLjg3My0xLjUxMi0zLjE2LTMuNzIyLTMuMTYtNC4xODcgMC0xMS4yOCA2LjMyLTE0Ljc3IDE4LjQ5NU0zOS45MTEgODMuNWMtOS44ODUgMC0xMC43IDkuODMzLS44MTQgOS44MzMgNC40MiAwIDkuNzctMS43NTYgMTIuNTYtNC45MTYtNC4wNy0zLjUxMi03LjQ0My00LjkxNy0xMS43NDYtNC45MTdtNjIuOTE4LTQuMjE0Yy41ODEgMTYuNTA2LTcuNzkyIDI1Ljc1NC0yMS45OCAyNS43NTQtOC4zNzQgMC0xMi41Ni0zLjE2MS0yMS41MTYtOS4wMTQtNC42NTIgNS4xNTEtMTMuNDkgOS4wMTQtMjAuODE4IDkuMDE0LTI1LjIzNiAwLTI0LjE5LTMyLjE5MyAxLjUxMi0zMi4xOTMgNS4zNSAwIDkuODg2IDEuNDA1IDE1LjcgNS4wMzRsMy44MzktMTMuNDYyQzQzLjc0OSA2MC4wODYgMzUuODQgNDcuOTEyIDQzLjYzMyAzMC40NjloMTIuNTZjLTYuOTc4IDExLjU5LTIuMjEgMjEuMTg5IDYuNjI5IDIyLjI0MkM2Ny41OSAzNS43MzcgNzcuODI1IDIyLjUxIDkxLjQzMiAyMi41MWM3LjY3NSAwIDEzLjcyMyA1LjAzNCAxMy43MjMgMTQuMTY1IDAgMTQuNjMzLTE5LjA3MyAyNi41NzMtMzMuNDk0IDI3Ljc0NEw2NS43MyA4NS4zNzJjNi43NDUgNy44NDMgMjUuNDY5IDE1LjQ1MiAyNS40NjktNi4wODd6Ii8+Cjwvc3ZnPg==", async setup() {}, async getInternalProvider() { if (typeof window === "undefined") return; if ("LeatherProvider" in window) return window.LeatherProvider; }, async getProvider() { const internalProvider = await this.getInternalProvider(); if (!internalProvider) return; return { request: this.request.bind(internalProvider) }; }, async request({ method, params }) { switch (method) { case "signPsbt": { const { psbt, ...options } = params; const signedPsbt = await this.request("signPsbt", { hex: psbt, broadcast: options.finalize }); if (signedPsbt?.error) throw signedPsbt?.error; if (!signedPsbt?.result?.hex) throw new Error("Missing hex result from signed PSBT"); return signedPsbt.result.hex; } default: throw new MethodNotSupportedRpcError(method); } }, async connect() { if (!await this.getInternalProvider()) throw new ProviderNotFoundError(); try { const accounts = await this.getAccounts(); const chainId = getAddressChainId(accounts[0].address); if (shimDisconnect) await Promise.all([ config.storage?.setItem(`${this.id}.connected`, true), config.storage?.setItem(`${this.id}.lastConnected`, Date.now().toString()), config.storage?.removeItem(`${this.id}.disconnected`) ]); return { accounts, chainId }; } catch (error) { throw new UserRejectedRequestError(error.message); } }, async disconnect() { if (!await this.getInternalProvider()) throw new ProviderNotFoundError(); if (shimDisconnect) await Promise.all([ config.storage?.setItem(`${this.id}.disconnected`, true), config.storage?.removeItem(`${this.id}.connected`), config.storage?.removeItem(`${this.id}.accounts`), config.storage?.removeItem(`${this.id}.lastConnected`) ]); }, async getAccounts() { const provider = await this.getInternalProvider(); if (!provider) throw new ProviderNotFoundError(); if (shimDisconnect && await this.isAuthorized()) { const accounts = await config.storage?.getItem(`${this.id}.accounts`); if (accounts && Array.isArray(accounts) && accounts.length > 0) return accounts; } const accounts = await provider.request("getAddresses"); if (!accounts.result) throw new UserRejectedRequestError(accounts.error?.message ?? "Unknown error"); if (shimDisconnect) await config.storage?.setItem(`${this.id}.accounts`, accounts.result.addresses); return accounts.result.addresses; }, async getChainId() { if (chainId) return chainId; const accounts = await this.getAccounts(); if (accounts.length === 0) throw new ConnectorChainIdDetectionError({ connector: this.name }); return getAddressChainId(accounts[0].address); }, async isAuthorized() { try { if (!shimDisconnect) return false; const lastConnected = await config.storage?.getItem(`${this.id}.lastConnected`); if (!lastConnected) return false; const timestamp = parseInt(lastConnected, 10); if (Number.isNaN(timestamp) || timestamp <= 0) { await Promise.all([ config.storage?.setItem(`${this.id}.disconnected`, true), config.storage?.removeItem(`${this.id}.connected`), config.storage?.removeItem(`${this.id}.accounts`), config.storage?.removeItem(`${this.id}.lastConnected`) ]); return false; } const isExpired = Date.now() - timestamp > 1440 * 60 * 1e3; if (isExpired) { await Promise.all([ config.storage?.setItem(`${this.id}.disconnected`, true), config.storage?.removeItem(`${this.id}.connected`), config.storage?.removeItem(`${this.id}.accounts`), config.storage?.removeItem(`${this.id}.lastConnected`) ]); return false; } return !isExpired; } catch { return false; } }, async onAccountsChanged() { const { accounts } = await this.connect(); config.emitter.emit("change", { accounts }); }, onChainChanged(chainId) { config.emitter.emit("change", { chainId }); }, async onDisconnect(_error) { config.emitter.emit("disconnect"); } })); } leather.type = "UTXO"; //#endregion export { leather }; //# sourceMappingURL=leather.js.map