accounts
Version:
Tempo Accounts SDK
142 lines • 5.8 kB
JavaScript
import {} from 'ox';
import { createClient, http, } from 'viem';
import { Transaction } from 'viem/tempo';
const defaultClients = new Map();
const clients = new WeakMap();
/** Resolves a viem Client for a given chain ID (cached). */
export function fromChainId(chainId, options) {
const { chains, feePayer: feePayerOption, provider, store, transports } = options;
const feePayerUrl = (() => {
if (feePayerOption === false)
return undefined;
if (typeof feePayerOption === 'string')
return normalizeFeePayerUrl(feePayerOption);
if (feePayerOption?.url)
return normalizeFeePayerUrl(feePayerOption.url);
return undefined;
})();
const precedence = (() => {
if (typeof feePayerOption === 'object' && feePayerOption !== null)
return feePayerOption.precedence ?? 'fee-payer-first';
return 'fee-payer-first';
})();
const id = chainId ?? store.getState().chainId;
const key = `${id}:${provider ? 'p' : ''}:${feePayerOption === false ? 'no-fp' : (feePayerUrl ?? '')}:${precedence}`;
const scope = provider ?? transports;
const cache = (() => {
if (!scope)
return defaultClients;
let map = clients.get(scope);
if (!map) {
map = new Map();
clients.set(scope, map);
}
return map;
})();
let client = cache.get(key);
if (!client) {
const chain = chains.find((c) => c.id === id) ?? chains[0];
const base = transports?.[id] ?? http();
const transport_base = provider
? providerTransport(provider, base, chainId === undefined ? undefined : chain.id)
: base;
const transport = feePayerUrl
? feePayerTransport(transport_base, feePayerUrl, precedence)
: transport_base;
client = createClient({ chain, transport, pollingInterval: 1000 });
cache.set(key, client);
}
return client;
}
/**
* Routes account operations through the provider and explicit-chain RPCs
* through the requested chain's transport.
*/
function providerTransport(provider, base, chainId) {
return (params) => {
const baseTransport = base(params);
return {
...baseTransport,
async request({ method, params: reqParams }) {
if (chainId !== undefined && !usesProvider(method))
return baseTransport.request({ method, params: reqParams });
const params = (() => {
if (method !== 'eth_fillTransaction' || chainId === undefined)
return reqParams;
const request = reqParams?.[0];
if (!request || typeof request !== 'object')
return reqParams;
return [{ ...request, chainId }];
})();
return provider.request({
method,
params,
});
},
};
};
}
function usesProvider(method) {
return (method.startsWith('wallet_') ||
[
'eth_accounts',
'eth_fillTransaction',
'eth_requestAccounts',
'eth_sendTransaction',
'eth_sendTransactionSync',
'eth_signTransaction',
'eth_signTypedData_v4',
'personal_sign',
].includes(method));
}
/**
* Resolves a fee payer URL to an absolute URL string. Relative paths (e.g.
* `/relay`) are resolved against `window.location.origin` when running in a
* browser; on the server, relative paths are returned as-is.
*/
function normalizeFeePayerUrl(url) {
if (url.startsWith('http://') || url.startsWith('https://'))
return url;
if (typeof window !== 'undefined')
return new URL(url, window.location.origin).href;
return url;
}
function feePayerTransport(base, url, precedence) {
return (params) => {
const baseTransport = base(params);
const sponsor = http(url)(params);
return {
...baseTransport,
async request({ method, params: rpcParams }) {
const args = rpcParams;
if (precedence === 'fee-payer-first' && method === 'eth_fillTransaction') {
const request = args?.[0];
if (request &&
typeof request === 'object' &&
'feePayer' in request &&
(request.feePayer === true || typeof request.feePayer === 'string'))
return sponsor.request({
method,
params: [{ ...request, feePayer: true }],
});
}
if (method === 'eth_sendRawTransaction' || method === 'eth_sendRawTransactionSync') {
const serialized = args?.[0];
if (typeof serialized === 'string' &&
(serialized.startsWith('0x76') || serialized.startsWith('0x78'))) {
const deserialized = Transaction.deserialize(serialized);
if ('feePayerSignature' in deserialized && deserialized.feePayerSignature === null) {
const signed = await sponsor.request({
method: 'eth_signRawTransaction',
params: [serialized],
});
return await baseTransport.request({ method, params: [signed] });
}
}
}
return await baseTransport.request({ method, params: rpcParams });
},
};
};
}
//# sourceMappingURL=Client.js.map