UNPKG

@wagmi/core

Version:

VanillaJS library for Ethereum

890 lines 29.6 kB
import { encodeAbiParameters, encodeFunctionData, zeroHash, } from 'viem'; import { readContract as viem_readContract, sendTransaction as viem_sendTransaction, sendTransactionSync as viem_sendTransactionSync, } from 'viem/actions'; import { Abis, Actions, Bytes, PublicKey, Secp256k1, TokenId } from 'viem/tempo'; import { Abis as ZoneAbis } from 'viem/tempo/zones'; import { parseAccount } from 'viem/utils'; import { getConnectorClient } from '../../actions/getConnectorClient.js'; import { filterQueryOptions } from './utils.js'; /** * Gets information about the currently stored zone authorization token. * * @example * ```ts * import { createConfig } from '@wagmi/core' * import { Actions, dangerous_secp256k1 } from '@wagmi/core/tempo' * import { Account } from 'viem/tempo' * import { http as zoneHttp, zone } from 'viem/tempo/zones' * * const zoneChain = zone(7) * const account = Account.fromSecp256k1('0x...') * const config = createConfig({ * chains: [zoneChain], * connectors: [dangerous_secp256k1({ account })], * transports: { * [zoneChain.id]: zoneHttp(), * }, * }) * * await Actions.zone.signAuthorizationToken(config, { * chainId: zoneChain.id, * }) * * const info = await Actions.zone.getAuthorizationTokenInfo(config, { * chainId: zoneChain.id, * }) * * console.log(info.expiresAt) * ``` * * @param config - Config. * @param parameters - Parameters. * @returns The authorization token info. */ export function getAuthorizationTokenInfo(config, parameters) { const client = config.getClient({ chainId: parameters.chainId }); return Actions.zone.getAuthorizationTokenInfo(client); } (function (getAuthorizationTokenInfo) { function queryKey(parameters) { return [ 'getAuthorizationTokenInfo', filterQueryOptions(parameters), ]; } getAuthorizationTokenInfo.queryKey = queryKey; function queryOptions(config, parameters) { const { query, ...rest } = parameters; return { ...query, enabled: Boolean(query?.enabled ?? true), queryKey: queryKey(rest), async queryFn(context) { const [, parameters] = context.queryKey; return await getAuthorizationTokenInfo(config, parameters); }, }; } getAuthorizationTokenInfo.queryOptions = queryOptions; })(getAuthorizationTokenInfo || (getAuthorizationTokenInfo = {})); /** * Gets deposit processing status for a Tempo block number. * * @example * ```ts * import { createConfig } from '@wagmi/core' * import { Actions, dangerous_secp256k1 } from '@wagmi/core/tempo' * import { Account } from 'viem/tempo' * import { http as zoneHttp, zone } from 'viem/tempo/zones' * * const zoneChain = zone(7) * const account = Account.fromSecp256k1('0x...') * const config = createConfig({ * chains: [zoneChain], * connectors: [dangerous_secp256k1({ account })], * transports: { * [zoneChain.id]: zoneHttp(), * }, * }) * * await Actions.zone.signAuthorizationToken(config, { * chainId: zoneChain.id, * }) * * const status = await Actions.zone.getDepositStatus(config, { * chainId: zoneChain.id, * tempoBlockNumber: 42n, * }) * * console.log(status.processed) * ``` * * @param config - Config. * @param parameters - Parameters. * @returns The deposit status. */ export function getDepositStatus(config, parameters) { const { chainId, ...rest } = parameters; const client = config.getClient({ chainId }); return Actions.zone.getDepositStatus(client, rest); } (function (getDepositStatus) { function queryKey(parameters) { return ['getDepositStatus', filterQueryOptions(parameters)]; } getDepositStatus.queryKey = queryKey; function queryOptions(config, parameters) { const { query, ...rest } = parameters; return { ...query, enabled: Boolean(rest.tempoBlockNumber !== undefined && (query?.enabled ?? true)), queryKey: queryKey(rest), async queryFn(context) { const [, { tempoBlockNumber, ...parameters }] = context.queryKey; if (tempoBlockNumber === undefined) throw new Error('tempoBlockNumber is required.'); return await getDepositStatus(config, { ...parameters, tempoBlockNumber, }); }, }; } getDepositStatus.queryOptions = queryOptions; })(getDepositStatus || (getDepositStatus = {})); /** * Gets the withdrawal fee for a given gas limit. * * @example * ```ts * import { createConfig } from '@wagmi/core' * import { Actions } from '@wagmi/core/tempo' * import { http as zoneHttp, zone } from 'viem/tempo/zones' * * const zoneChain = zone(7) * const config = createConfig({ * chains: [zoneChain], * transports: { * [zoneChain.id]: zoneHttp(), * }, * }) * * const fee = await Actions.zone.getWithdrawalFee(config, { * chainId: zoneChain.id, * gas: 21_000n, * }) * * console.log(fee) * ``` * * @param config - Config. * @param parameters - Parameters. * @returns The withdrawal fee. */ export function getWithdrawalFee(config, parameters) { const { chainId, ...rest } = parameters; const client = config.getClient({ chainId }); return Actions.zone.getWithdrawalFee(client, rest); } (function (getWithdrawalFee) { function queryKey(parameters) { return ['getWithdrawalFee', filterQueryOptions(parameters)]; } getWithdrawalFee.queryKey = queryKey; function queryOptions(config, parameters) { const { query, ...rest } = parameters; return { ...query, enabled: Boolean(query?.enabled ?? true), queryKey: queryKey(rest), async queryFn(context) { const [, parameters] = context.queryKey; return await getWithdrawalFee(config, parameters); }, }; } getWithdrawalFee.queryOptions = queryOptions; })(getWithdrawalFee || (getWithdrawalFee = {})); /** * Gets the current zone metadata. * * @example * ```ts * import { createConfig } from '@wagmi/core' * import { Actions } from '@wagmi/core/tempo' * import { http as zoneHttp, zone } from 'viem/tempo/zones' * * const zoneChain = zone(7) * const config = createConfig({ * chains: [zoneChain], * transports: { * [zoneChain.id]: zoneHttp(), * }, * }) * * const info = await Actions.zone.getZoneInfo(config, { * chainId: zoneChain.id, * }) * * console.log(info.zoneId) * ``` * * @param config - Config. * @param parameters - Parameters. * @returns The zone metadata. */ export function getZoneInfo(config, parameters) { const client = config.getClient({ chainId: parameters.chainId }); return Actions.zone.getZoneInfo(client); } (function (getZoneInfo) { function queryKey(parameters) { return ['getZoneInfo', filterQueryOptions(parameters)]; } getZoneInfo.queryKey = queryKey; function queryOptions(config, parameters) { const { query, ...rest } = parameters; return { ...query, enabled: Boolean(query?.enabled ?? true), queryKey: queryKey(rest), async queryFn(context) { const [, parameters] = context.queryKey; return await getZoneInfo(config, parameters); }, }; } getZoneInfo.queryOptions = queryOptions; })(getZoneInfo || (getZoneInfo = {})); /** * Signs and stores a zone authorization token for the configured zone transport. * * @example * ```ts * import { createConfig } from '@wagmi/core' * import { Actions, dangerous_secp256k1 } from '@wagmi/core/tempo' * import { Account } from 'viem/tempo' * import { http as zoneHttp, zone } from 'viem/tempo/zones' * * const zoneChain = zone(7) * const account = Account.fromSecp256k1('0x...') * const config = createConfig({ * chains: [zoneChain], * connectors: [dangerous_secp256k1({ account })], * transports: { * [zoneChain.id]: zoneHttp(), * }, * }) * * const result = await Actions.zone.signAuthorizationToken(config, { * chainId: zoneChain.id, * }) * * console.log(result.token) * ``` * * @param config - Config. * @param parameters - Parameters. * @returns The authentication payload and serialized token. */ export async function signAuthorizationToken(config, parameters) { const { account, chainId, connector, ...rest } = parameters; const client = await getZoneWalletClient(config, { account, chainId, connector, }); return Actions.zone.signAuthorizationToken(client, rest); } /** * Deposits tokens into a zone on the parent Tempo chain. * * @example * ```ts * import { createConfig, http } from '@wagmi/core' * import { tempoModerato } from '@wagmi/core/chains' * import { Actions } from '@wagmi/core/tempo' * * const config = createConfig({ * chains: [tempoModerato], * transports: { * [tempoModerato.id]: http(), * }, * }) * * const hash = await Actions.zone.deposit(config, { * amount: 1_000_000n, * token: '0x20c0000000000000000000000000000000000001', * zoneId: 7, * }) * ``` * * @param config - Config. * @param parameters - Parameters. * @returns Transaction hash. */ export async function deposit(config, parameters) { const { account, chainId, connector, ...rest } = parameters; const client = await getConnectorClient(config, { account, assertChainId: false, chainId, connector, }); const resolvedChainId = chainId ?? client.chain?.id; if (!resolvedChainId) throw new Error('`chainId` is required.'); const account_ = account ?? client.account; if (!account_) throw new Error('`account` is required.'); const accountAddress = parseAccount(account_).address; const { amount, memo = zeroHash, recipient = accountAddress, token, zoneId, ...tx } = rest; const { address: portalAddress } = resolvePortal(config, resolvedChainId, zoneId); const tokenAddress = TokenId.toAddress(token); return viem_sendTransaction(client, { ...tx, calls: [ { data: encodeFunctionData({ abi: Abis.tip20, functionName: 'approve', args: [portalAddress, amount], }), to: tokenAddress, }, { data: encodeFunctionData({ abi: ZoneAbis.zonePortal, functionName: 'deposit', args: [tokenAddress, recipient, amount, memo], }), to: portalAddress, }, ], }); } /** * Deposits tokens into a zone on the parent Tempo chain. * * Note: This is a synchronous action that waits for the transaction to * be included on a block before returning a response. * * @example * ```ts * import { createConfig, http } from '@wagmi/core' * import { tempoModerato } from '@wagmi/core/chains' * import { Actions } from '@wagmi/core/tempo' * * const config = createConfig({ * chains: [tempoModerato], * transports: { * [tempoModerato.id]: http(), * }, * }) * * const result = await Actions.zone.depositSync(config, { * amount: 1_000_000n, * token: '0x20c0000000000000000000000000000000000001', * zoneId: 7, * }) * * console.log(result.receipt.transactionHash) * ``` * * @param config - Config. * @param parameters - Parameters. * @returns The transaction receipt. */ export async function depositSync(config, parameters) { const { account, chainId, connector, throwOnReceiptRevert = true, ...rest } = parameters; const client = await getConnectorClient(config, { account, assertChainId: false, chainId, connector, }); const resolvedChainId = chainId ?? client.chain?.id; if (!resolvedChainId) throw new Error('`chainId` is required.'); const account_ = account ?? client.account; if (!account_) throw new Error('`account` is required.'); const accountAddress = parseAccount(account_).address; const { amount, memo = zeroHash, recipient = accountAddress, token, zoneId, ...tx } = rest; const { address: portalAddress } = resolvePortal(config, resolvedChainId, zoneId); const tokenAddress = TokenId.toAddress(token); const receipt = await viem_sendTransactionSync(client, { ...tx, calls: [ { data: encodeFunctionData({ abi: Abis.tip20, functionName: 'approve', args: [portalAddress, amount], }), to: tokenAddress, }, { data: encodeFunctionData({ abi: ZoneAbis.zonePortal, functionName: 'deposit', args: [tokenAddress, recipient, amount, memo], }), to: portalAddress, }, ], throwOnReceiptRevert, }); return { receipt }; } /** * Deposits tokens into a zone on the parent Tempo chain with an encrypted * recipient and memo. * * @example * ```ts * import { createConfig, http } from '@wagmi/core' * import { tempoModerato } from '@wagmi/core/chains' * import { Actions } from '@wagmi/core/tempo' * * const config = createConfig({ * chains: [tempoModerato], * transports: { * [tempoModerato.id]: http(), * }, * }) * * const hash = await Actions.zone.encryptedDeposit(config, { * amount: 1_000_000n, * token: '0x20c0000000000000000000000000000000000001', * zoneId: 7, * }) * ``` * * @param config - Config. * @param parameters - Parameters. * @returns Transaction hash. */ export async function encryptedDeposit(config, parameters) { const { account, chainId, connector, ...rest } = parameters; const client = await getConnectorClient(config, { account, assertChainId: false, chainId, connector, }); const resolvedChainId = chainId ?? client.chain?.id; if (!resolvedChainId) throw new Error('`chainId` is required.'); const account_ = account ?? client.account; if (!account_) throw new Error('`account` is required.'); const accountAddress = parseAccount(account_).address; const { amount, memo, recipient = accountAddress, token, zoneId, ...tx } = rest; const portal = resolvePortal(config, resolvedChainId, zoneId); const portalAddress = portal.address; const tokenAddress = TokenId.toAddress(token); const [publicKey, keyIndex] = portal.sequencerEncryptionKey && portal.encryptionKeyCount !== undefined ? [portal.sequencerEncryptionKey, portal.encryptionKeyCount] : await Promise.all([ viem_readContract(client, { address: portalAddress, abi: ZoneAbis.zonePortal, functionName: 'sequencerEncryptionKey', }).then(([x, yParity]) => ({ x, yParity: Number(yParity) })), viem_readContract(client, { address: portalAddress, abi: ZoneAbis.zonePortal, functionName: 'encryptionKeyCount', }), ]); if (keyIndex === 0n) throw new Error('No sequencer encryption key configured.'); const encrypted = await encryptDepositPayload(publicKey, recipient, memo); return viem_sendTransaction(client, { ...tx, calls: [ { data: encodeFunctionData({ abi: Abis.tip20, functionName: 'approve', args: [portalAddress, amount], }), to: tokenAddress, }, { data: encodeFunctionData({ abi: ZoneAbis.zonePortal, functionName: 'depositEncrypted', args: [tokenAddress, amount, keyIndex - 1n, encrypted], }), to: portalAddress, }, ], }); } /** * Deposits tokens into a zone on the parent Tempo chain with an encrypted * recipient and memo. * * Note: This is a synchronous action that waits for the transaction to * be included on a block before returning a response. * * @example * ```ts * import { createConfig, http } from '@wagmi/core' * import { tempoModerato } from '@wagmi/core/chains' * import { Actions } from '@wagmi/core/tempo' * * const config = createConfig({ * chains: [tempoModerato], * transports: { * [tempoModerato.id]: http(), * }, * }) * * const result = await Actions.zone.encryptedDepositSync(config, { * amount: 1_000_000n, * token: '0x20c0000000000000000000000000000000000001', * zoneId: 7, * }) * * console.log(result.receipt.transactionHash) * ``` * * @param config - Config. * @param parameters - Parameters. * @returns The transaction receipt. */ export async function encryptedDepositSync(config, parameters) { const { account, chainId, connector, throwOnReceiptRevert = true, ...rest } = parameters; const client = await getConnectorClient(config, { account, assertChainId: false, chainId, connector, }); const resolvedChainId = chainId ?? client.chain?.id; if (!resolvedChainId) throw new Error('`chainId` is required.'); const account_ = account ?? client.account; if (!account_) throw new Error('`account` is required.'); const accountAddress = parseAccount(account_).address; const { amount, memo, recipient = accountAddress, token, zoneId, ...tx } = rest; const portal = resolvePortal(config, resolvedChainId, zoneId); const portalAddress = portal.address; const tokenAddress = TokenId.toAddress(token); const [publicKey, keyIndex] = portal.sequencerEncryptionKey && portal.encryptionKeyCount !== undefined ? [portal.sequencerEncryptionKey, portal.encryptionKeyCount] : await Promise.all([ viem_readContract(client, { address: portalAddress, abi: ZoneAbis.zonePortal, functionName: 'sequencerEncryptionKey', }).then(([x, yParity]) => ({ x, yParity: Number(yParity) })), viem_readContract(client, { address: portalAddress, abi: ZoneAbis.zonePortal, functionName: 'encryptionKeyCount', }), ]); if (keyIndex === 0n) throw new Error('No sequencer encryption key configured.'); const encrypted = await encryptDepositPayload(publicKey, recipient, memo); const receipt = await viem_sendTransactionSync(client, { ...tx, calls: [ { data: encodeFunctionData({ abi: Abis.tip20, functionName: 'approve', args: [portalAddress, amount], }), to: tokenAddress, }, { data: encodeFunctionData({ abi: ZoneAbis.zonePortal, functionName: 'depositEncrypted', args: [tokenAddress, amount, keyIndex - 1n, encrypted], }), to: portalAddress, }, ], throwOnReceiptRevert, }); return { receipt }; } /** * Requests a withdrawal from a zone to the parent Tempo chain. * * @example * ```ts * import { createConfig } from '@wagmi/core' * import { Actions, dangerous_secp256k1 } from '@wagmi/core/tempo' * import { Account } from 'viem/tempo' * import { http as zoneHttp, zone } from 'viem/tempo/zones' * * const zoneChain = zone(7) * const account = Account.fromSecp256k1('0x...') * const config = createConfig({ * chains: [zoneChain], * connectors: [dangerous_secp256k1({ account })], * transports: { * [zoneChain.id]: zoneHttp(), * }, * }) * * const hash = await Actions.zone.requestWithdrawal(config, { * amount: 1_000_000n, * chainId: zoneChain.id, * token: '0x20c0000000000000000000000000000000000001', * }) * * console.log(hash) * ``` * * @param config - Config. * @param parameters - Parameters. * @returns Transaction hash. */ export async function requestWithdrawal(config, parameters) { const { account, chainId, connector } = parameters; const client = await getZoneWalletClient(config, { account, chainId, connector, }); return Actions.zone.requestWithdrawal(client, parameters); } /** * Requests a withdrawal from a zone to the parent Tempo chain. * * Note: This is a synchronous action that waits for the transaction to * be included on a block before returning a response. * * @example * ```ts * import { createConfig } from '@wagmi/core' * import { Actions, dangerous_secp256k1 } from '@wagmi/core/tempo' * import { Account } from 'viem/tempo' * import { http as zoneHttp, zone } from 'viem/tempo/zones' * * const zoneChain = zone(7) * const account = Account.fromSecp256k1('0x...') * const config = createConfig({ * chains: [zoneChain], * connectors: [dangerous_secp256k1({ account })], * transports: { * [zoneChain.id]: zoneHttp(), * }, * }) * * const result = await Actions.zone.requestWithdrawalSync(config, { * amount: 1_000_000n, * chainId: zoneChain.id, * token: '0x20c0000000000000000000000000000000000001', * }) * * console.log(result.receipt.transactionHash) * ``` * * @param config - Config. * @param parameters - Parameters. * @returns The transaction receipt. */ export async function requestWithdrawalSync(config, parameters) { const { account, chainId, connector } = parameters; const client = await getZoneWalletClient(config, { account, chainId, connector, }); return Actions.zone.requestWithdrawalSync(client, parameters); } /** * Requests a verifiable withdrawal from a zone to the parent Tempo chain. * * @example * ```ts * import { createConfig } from '@wagmi/core' * import { Actions, dangerous_secp256k1 } from '@wagmi/core/tempo' * import { Account } from 'viem/tempo' * import { http as zoneHttp, zone } from 'viem/tempo/zones' * * const zoneChain = zone(7) * const account = Account.fromSecp256k1('0x...') * const config = createConfig({ * chains: [zoneChain], * connectors: [dangerous_secp256k1({ account })], * transports: { * [zoneChain.id]: zoneHttp(), * }, * }) * * const hash = await Actions.zone.requestVerifiableWithdrawal(config, { * amount: 1_000_000n, * chainId: zoneChain.id, * revealTo: * '0x0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798', * token: '0x20c0000000000000000000000000000000000001', * }) * * console.log(hash) * ``` * * @param config - Config. * @param parameters - Parameters. * @returns Transaction hash. */ export async function requestVerifiableWithdrawal(config, parameters) { const { account, chainId, connector } = parameters; const client = await getZoneWalletClient(config, { account, chainId, connector, }); return Actions.zone.requestVerifiableWithdrawal(client, parameters); } /** * Requests a verifiable withdrawal from a zone to the parent Tempo chain. * * Note: This is a synchronous action that waits for the transaction to * be included on a block before returning a response. * * @example * ```ts * import { createConfig } from '@wagmi/core' * import { Actions, dangerous_secp256k1 } from '@wagmi/core/tempo' * import { Account } from 'viem/tempo' * import { http as zoneHttp, zone } from 'viem/tempo/zones' * * const zoneChain = zone(7) * const account = Account.fromSecp256k1('0x...') * const config = createConfig({ * chains: [zoneChain], * connectors: [dangerous_secp256k1({ account })], * transports: { * [zoneChain.id]: zoneHttp(), * }, * }) * * const result = await Actions.zone.requestVerifiableWithdrawalSync(config, { * amount: 1_000_000n, * chainId: zoneChain.id, * revealTo: * '0x0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798', * token: '0x20c0000000000000000000000000000000000001', * }) * * console.log(result.receipt.transactionHash) * ``` * * @param config - Config. * @param parameters - Parameters. * @returns The transaction receipt. */ export async function requestVerifiableWithdrawalSync(config, parameters) { const { account, chainId, connector } = parameters; const client = await getZoneWalletClient(config, { account, chainId, connector, }); return Actions.zone.requestVerifiableWithdrawalSync(client, parameters); } const portalAddresses = { 42431: { 6: '0x7069DeC4E64Fd07334A0933eDe836C17259c9B23', 7: '0x3F5296303400B56271b476F5A0B9cBF74350D6Ac', }, }; async function getZoneWalletClient(config, parameters) { const client = await getConnectorClient(config, { ...parameters, assertChainId: false, }); const resolvedChainId = parameters.chainId ?? client.chain?.id; const account = resolveSignableAccount(parameters.account) ?? (await getSignableConnectorAccount(config, { account: parameters.account ?? client.account, chainId: resolvedChainId, connector: parameters.connector, })); if (!account || resolvedChainId === undefined) return client; // Local accounts can sign against the zone transport directly without // depending on the connector provider's currently selected chain. return Object.assign(config.getClient({ chainId: resolvedChainId }), { account, }); } async function getSignableConnectorAccount(config, parameters) { const connector = parameters.connector ?? config.state.connections.get(config.state.current)?.connector; const provider = (await connector?.getProvider?.({ chainId: parameters.chainId, })); if (typeof provider?.getAccount !== 'function') return; try { return provider.getAccount({ address: parameters.account ? parseAccount(parameters.account).address : undefined, signable: true, }); } catch { return; } } function resolveSignableAccount(account) { if (typeof account !== 'object' || account === null) return; return 'sign' in account ? account : undefined; } function resolvePortal(config, chainId, zoneId) { const chain = config.chains.find((chain) => chain.id === chainId); const zonePortal = chain?.contracts?.zonePortal; // Allow custom chains to supply portal addresses until viem exposes a // generic resolver for non-hardcoded Tempo networks. if (typeof zonePortal === 'string') return { address: zonePortal }; if (zonePortal && typeof zonePortal === 'object') { const portal = 'address' in zonePortal && typeof zonePortal.address === 'string' ? zonePortal : zonePortal[zoneId]; if (typeof portal === 'string') return { address: portal }; if (portal && typeof portal === 'object' && typeof portal.address === 'string') { return { address: portal.address, encryptionKeyCount: portal.encryptionKeyCount, sequencerEncryptionKey: portal.sequencerEncryptionKey, }; } } const address = portalAddresses[chainId]?.[zoneId]; if (address) return { address }; throw new Error(`No portal address configured for zone ${zoneId} on chain ${chainId}.`); } async function encryptDepositPayload(publicKey, recipient, memo = zeroHash) { const sequencerPublicKey = PublicKey.from({ prefix: publicKey.yParity, x: BigInt(publicKey.x), }); const { privateKey: ephemeralPrivateKey, publicKey: ephemeralPublicKey } = Secp256k1.createKeyPair(); const sharedSecret = Secp256k1.getSharedSecret({ privateKey: ephemeralPrivateKey, publicKey: sequencerPublicKey, as: 'Bytes', }); const hkdfKey = await globalThis.crypto.subtle.importKey('raw', sharedSecret.buffer, 'HKDF', false, ['deriveKey']); const aesKey = await globalThis.crypto.subtle.deriveKey({ name: 'HKDF', hash: 'SHA-256', salt: new Uint8Array(12), info: new TextEncoder().encode('ecies-aes-key'), }, hkdfKey, { name: 'AES-GCM', length: 256 }, false, ['encrypt']); const nonce = Bytes.random(12); const plaintext = encodeAbiParameters([{ type: 'address' }, { type: 'bytes32' }], [recipient, memo]); const ciphertextWithTag = new Uint8Array(await globalThis.crypto.subtle.encrypt({ name: 'AES-GCM', iv: nonce, tagLength: 128 }, aesKey, Bytes.from(plaintext))); const ciphertext = ciphertextWithTag.slice(0, -16); const tag = ciphertextWithTag.slice(-16); const compressedEphemeral = PublicKey.compress(ephemeralPublicKey); return { ciphertext: bytesToHex(ciphertext), ephemeralPubkeyX: `0x${compressedEphemeral.x.toString(16).padStart(64, '0')}`, ephemeralPubkeyYParity: compressedEphemeral.prefix, nonce: bytesToHex(nonce), tag: bytesToHex(tag), }; } function bytesToHex(bytes) { return `0x${Array.from(bytes, (value) => value.toString(16).padStart(2, '0')).join('')}`; } //# sourceMappingURL=zone.js.map