UNPKG

accounts

Version:

Tempo Accounts SDK

154 lines 5 kB
import { Address, Hex } from 'ox'; import { prepareTransactionRequest } from 'viem/actions'; import * as AccessKey from '../AccessKey.js'; import * as ExecutionError from '../ExecutionError.js'; const removalErrorNames = new Set([ 'InvalidSignature', 'InvalidSignatureFormat', 'InvalidSignatureType', 'KeyAlreadyRevoked', 'KeyExpired', 'KeyNotFound', 'SignatureTypeMismatch', ]); /** Creates a transaction helper for a matching locally-signable access key. */ export async function create(options) { const { address, calls, chainId, client, store } = options; const account = await AccessKey.select({ account: address, calls, chainId, store, }); if (!account) return undefined; return createTransaction({ account, address, chainId, client, store }); } function createTransaction(options) { const { account, address, chainId, client, store } = options; return { async fill(parameters) { try { // Run prepareTransactionRequest to attach any pending key authorizations. // `eth_fillTransaction` below needs to return the node's fill response. const request = await prepareTransactionRequest(client, { account, ...parameters, parameters: [], type: 'tempo', }); return await fillTransaction(client, request); } catch (error) { removeForError(error, { account, address, chainId, store }); throw error; } }, async prepare(parameters) { try { const request = await prepareTransactionRequest(client, { account, ...parameters, type: 'tempo', }); return createPreparedTransaction({ account, address, chainId, client, request: request, store, }); } catch (error) { removeForError(error, { account, address, chainId, store }); throw error; } }, }; } function createPreparedTransaction(options) { const { account, address, chainId, client, request, store } = options; async function sign() { try { return await account.signTransaction(request); } catch (error) { removeForError(error, { account, address, chainId, store }); throw error; } } return { request, sign, async send() { try { const signed = await sign(); return (await client.request({ method: 'eth_sendRawTransaction', params: [signed], })); } catch (error) { removeForError(error, { account, address, chainId, store }); throw error; } }, async sendSync() { try { const signed = await sign(); return (await client.request({ method: 'eth_sendRawTransactionSync', params: [signed], })); } catch (error) { removeForError(error, { account, address, chainId, store }); throw error; } }, }; } async function fillTransaction(client, parameters) { const formatter = client.chain?.formatters?.transactionRequest; const formatted = formatter ? formatter.format({ ...parameters }, 'fillTransaction') : parameters; return (await client.request({ method: 'eth_fillTransaction', params: [formatted], })); } function removeForError(error, options) { if (!shouldRemoveForError(error)) return; AccessKey.remove({ accessKey: options.account.accessKeyAddress, account: options.address, chainId: options.chainId, store: options.store, }); } function shouldRemoveForError(error) { if (!(error instanceof Error)) return false; const parsed = ExecutionError.parse(error); if (removalErrorNames.has(parsed.errorName)) return true; const text = getErrorText(error); return [...removalErrorNames].some((name) => text.includes(name)); } function getErrorText(error) { if (!(error instanceof Error)) return ''; const details = error.details; const shortMessage = error.shortMessage; const cause = error.cause; return [ error.message, typeof details === 'string' ? details : '', typeof shortMessage === 'string' ? shortMessage : '', getErrorText(cause), ].join('\n'); } //# sourceMappingURL=AccessKeyTransaction.js.map