accounts
Version:
Tempo Accounts SDK
141 lines • 4.58 kB
JavaScript
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