UNPKG

accounts

Version:

Tempo Accounts SDK

141 lines 4.58 kB
import { Provider as ox_Provider, RpcRequest } from 'ox'; const contexts = new Map(); /** Attaches a provider to the host request coordinator and starts the transport driver. */ export function attach(host, options) { const context = get(host); const attachment = Symbol(); context.attachments.add(attachment); const next = options.dialog({ host: options.host, onReject: (ids) => reject(host, ids), onResponse: (response) => respond(host, response), store: options.store, theme: options.theme, }); const changed = Boolean(context.dialog && context.dialog !== next); if (context.dialog && context.dialog !== next) context.dialog.destroy(); context.dialog = next; if (changed) for (const request of context.requestQueue) request.synced = false; sync(host); return () => { context.attachments.delete(attachment); release(host); }; } /** Enqueues an RPC request in the host request coordinator and waits for completion. */ export function request(host, options) { const context = get(host); const request = context.ids.prepare(options.request); return new Promise((resolve, reject) => { context.requestQueue.push({ account: options.account, chainId: options.chainId, reject, request, resolve, status: 'pending', synced: false, }); sync(host); }); } /** Clears a host-scoped request coordinator. */ export function reset(host) { const context = contexts.get(key(host)); context?.dialog?.destroy(); contexts.delete(key(host)); } /** Converts a host URL into a request coordinator key. */ function key(host) { return new URL(host).host; } /** Returns the request context shared by remotes on the same host. */ function get(host) { const key_ = key(host); const current = contexts.get(key_); if (current) return current; const context = { attachments: new Set(), dialog: undefined, ids: RpcRequest.createStore(), requestQueue: [], synced: false, }; contexts.set(key_, context); return context; } /** Releases idle transport resources. */ function release(host) { const context = get(host); if (context.attachments.size > 0) return; if (context.requestQueue.length > 0) return; context.dialog?.destroy(); context.dialog = undefined; context.synced = false; } /** Marks displayed pending requests as rejected. */ function reject(host, ids) { if (ids.length === 0) return; const context = get(host); const ids_ = new Set(ids); const rejected = context.requestQueue.filter((queued) => ids_.has(queued.request.id)); if (rejected.length === 0) return; context.requestQueue = context.requestQueue.filter((queued) => !ids_.has(queued.request.id)); for (const request of rejected) request.reject(new ox_Provider.UserRejectedRequestError()); sync(host, { force: true }); } /** Resolves or rejects a pending request with an RPC response from the remote UI. */ function respond(host, response) { const context = get(host); const queued = context.requestQueue.find((queued) => queued.request.id === response.id); if (!queued) return; context.requestQueue = context.requestQueue.filter((queued) => queued.request.id !== response.id); if (response.error) queued.reject(ox_Provider.parseError(response.error)); else queued.resolve(response.result); sync(host, { force: true }); } /** Syncs newly pending host requests to the remote dialog. */ function sync(host, options = {}) { const context = get(host); const dialog = context.dialog; if (!dialog) return; const pending = context.requestQueue; if (pending.length === 0) { if (context.synced) dialog.close(); context.synced = false; release(host); return; } const request = pending[0]; if (!options.force && request.synced) return; request.synced = true; context.synced = true; dialog.syncRequests({ account: request.account, chainId: request.chainId, requests: [toRequest(request)], }); } /** Removes host-only metadata before syncing requests to the remote UI. */ function toRequest(request) { return { request: request.request, status: request.status, }; } //# sourceMappingURL=RemoteRequests.js.map