@wagmi/core
Version:
VanillaJS library for Ethereum
890 lines • 29.6 kB
JavaScript
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