@bigmi/client
Version:
Reactive primitives for Bitcoin apps.
113 lines (112 loc) • 5.5 kB
JavaScript
import { ConnectorChainIdDetectionError } from "../errors/connectors.js";
import { createConnector } from "../factories/createConnector.js";
import { BaseError, MethodNotSupportedRpcError, ProviderNotFoundError, UserRejectedRequestError, base64ToHex, getAddressChainId, hexToBase64 } from "@bigmi/core";
//#region src/connectors/ctrl.ts
function ctrl(parameters = {}) {
const { chainId, shimDisconnect = true } = parameters;
let accountsChanged;
return createConnector((config) => ({
id: "io.xdefi",
name: "Ctrl Wallet",
type: ctrl.type,
icon: "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTc1IiBoZWlnaHQ9IjE3NSIgdmlld0JveD0iMCAwIDE3NSAxNzUiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxyZWN0IHdpZHRoPSIxNzUiIGhlaWdodD0iMTc1IiByeD0iODcuNSIgZmlsbD0id2hpdGUiLz4KPHBhdGggZD0iTTY3LjMzMyAxMTYuMzI1VjE0Mi4zMzdDNjcuMzMzIDE0Ni41NzYgNzAuNzY3MSAxNTAuMDAxIDc0Ljk5NTMgMTUwLjAwMUgxMDEuMDA0QzEwNS4yNDIgMTUwLjAwMSAxMDguNjY2IDE0Ni41NjYgMTA4LjY2NiAxNDIuMzM3VjEyOS4zMzFDMTA4LjY2NiAxMjMuNjE3IDExMC45NzYgMTE4LjQ1IDExNC43MiAxMTQuNzE2QzExOC40NjMgMTEwLjk3MiAxMjMuNjMgMTA4LjY2MiAxMjkuMzMzIDEwOC42NjJIMTQyLjMzN0MxNDYuNTc2IDEwOC42NjIgMTUwIDEwNS4yMjggMTUwIDEwMC45OTlWNzQuOTk3M0MxNTAgNzAuNzU4MiAxNDYuNTY2IDY3LjMzNCAxNDIuMzM3IDY3LjMzNEgxMTYuMzM5QzExMi4xIDY3LjMzNCAxMDguNjc3IDcwLjc2ODUgMTA4LjY3NyA3NC45OTczVjg4LjYzMjRDMTA4LjY3NyA5OS42OTkzIDk5LjcwNDYgMTA4LjY2MiA4OC42NDk0IDEwOC42NjJINzUuMDE2QzcwLjc3NzQgMTA4LjY2MiA2Ny4zNTM2IDExMi4wOTcgNjcuMzUzNiAxMTYuMzI1SDY3LjMzM1oiIGZpbGw9IiMwMDE0MDUiLz4KPHBhdGggZD0iTTI2IDc0Ljk5NTdWMTAxLjAwNEMyNiAxMDUuMjQzIDI5LjQzNDEgMTA4LjY2NyAzMy42NjIzIDEwOC42NjdINTkuNjcxQzYzLjkwOTUgMTA4LjY2NyA2Ny4zMzMzIDEwNS4yMzMgNjcuMzMzMyAxMDEuMDA0Vjg4QzY3LjMzMzMgODIuMjg2OCA2OS42NDM0IDc3LjEyMDEgNzMuMzg2OSA3My4zODY5Qzc3LjEzMDQgNjkuNjQzNCA4Mi4yOTcxIDY3LjMzMzMgODggNjcuMzMzM0gxMDEuMDA0QzEwNS4yNDMgNjcuMzMzMyAxMDguNjY3IDYzLjg5OTIgMTA4LjY2NyA1OS42NzFWMzMuNjYyM0MxMDguNjY3IDI5LjQyMzggMTA1LjIzMyAyNiAxMDEuMDA0IDI2SDc1LjAwNkM3MC43Njc1IDI2IDY3LjM0MzYgMjkuNDM0MSA2Ny4zNDM2IDMzLjY2MjNWNDcuMjk1N0M2Ny4zNDM2IDU4LjM2MTMgNTguMzcxNiA2Ny4zMjMgNDcuMzE2NCA2Ny4zMjNIMzMuNjYyM0MyOS40MjM4IDY3LjMyMyAyNiA3MC43NTcyIDI2IDc0Ljk4NTRWNzQuOTk1N1oiIGZpbGw9IiMwMDE0MDUiLz4KPC9zdmc+Cg==",
async setup() {},
async getInternalProvider() {
if (typeof window === "undefined") return;
if ("xfi" in window) return window.xfi?.bitcoin;
},
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 psbt64 = hexToBase64(psbt);
const response = await this.signPsbt({
psbt: psbt64,
broadcast: Boolean(options.finalize)
});
if (response.status === "success") return base64ToHex(response.result.psbt);
throw new BaseError(response.error);
}
default: throw new MethodNotSupportedRpcError(method);
}
},
async connect() {
const provider = await this.getInternalProvider();
if (!provider) throw new ProviderNotFoundError();
try {
const accounts = await this.getAccounts();
const chainId = getAddressChainId(accounts[0].address);
if (!accountsChanged) {
accountsChanged = this.onAccountsChanged.bind(this);
provider.addListener("accountsChanged", accountsChanged);
}
if (shimDisconnect) await Promise.all([config.storage?.setItem(`${this.id}.connected`, true), config.storage?.removeItem(`${this.id}.disconnected`)]);
return {
accounts,
chainId
};
} catch (error) {
console.error({ error });
throw new UserRejectedRequestError(error.message);
}
},
async disconnect() {
const provider = await this.getInternalProvider();
if (accountsChanged) {
provider?.removeListener("accountsChanged", accountsChanged);
accountsChanged = void 0;
}
if (shimDisconnect) await Promise.all([config.storage?.setItem(`${this.id}.disconnected`, true), config.storage?.removeItem(`${this.id}.connected`)]);
},
async getAccounts() {
const provider = await this.getInternalProvider();
if (!provider) throw new ProviderNotFoundError();
const { status, result } = await provider.request({
method: "request_accounts_and_keys",
params: { purposes: ["payment"] }
});
if (status === "success") return result.map((account) => ({
address: account.address,
addressType: account.addressType.toLowerCase(),
publicKey: account.publicKey,
purpose: account.purpose
}));
throw new BaseError("Error getting accounts");
},
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 {
return shimDisconnect && Boolean(await config.storage?.getItem(`${this.id}.connected`));
} catch {
return false;
}
},
async onAccountsChanged(accounts) {
if (accounts.length === 0) this.onDisconnect();
else {
const newAccounts = await this.getAccounts();
config.emitter.emit("change", { accounts: newAccounts });
}
},
onChainChanged(chainId) {
config.emitter.emit("change", { chainId });
},
async onDisconnect(_error) {
config.emitter.emit("disconnect");
}
}));
}
ctrl.type = "UTXO";
//#endregion
export { ctrl };
//# sourceMappingURL=ctrl.js.map