viem
Version:
1,267 lines (1,178 loc) • 34.7 kB
text/typescript
import type { Address } from 'abitype'
import type { ReceivePolicyReceipt } from 'ox/tempo'
import type { Account } from '../../accounts/types.js'
import { parseAccount } from '../../accounts/utils/parseAccount.js'
import type { ReadContractReturnType } from '../../actions/public/readContract.js'
import { readContract } from '../../actions/public/readContract.js'
import type { WatchContractEventParameters } from '../../actions/public/watchContractEvent.js'
import { watchContractEvent } from '../../actions/public/watchContractEvent.js'
import type { WriteContractReturnType } from '../../actions/wallet/writeContract.js'
import { writeContract } from '../../actions/wallet/writeContract.js'
import { writeContractSync } from '../../actions/wallet/writeContractSync.js'
import type { Client } from '../../clients/createClient.js'
import type { Transport } from '../../clients/transports/createTransport.js'
import { zeroAddress } from '../../constants/address.js'
import type { BaseErrorType } from '../../errors/base.js'
import type { Chain } from '../../types/chain.js'
import type { ExtractAbiItem, GetEventArgs } from '../../types/contract.js'
import type { Log, Log as viem_Log } from '../../types/log.js'
import type { Hex } from '../../types/misc.js'
import type { Compute, UnionOmit } from '../../types/utils.js'
import { parseEventLogs } from '../../utils/abi/parseEventLogs.js'
import { isAddressEqual } from '../../utils/index.js'
import * as Abis from '../Abis.js'
import * as Addresses from '../Addresses.js'
import type {
GetAccountParameter,
ReadParameters,
WriteParameters,
} from '../internal/types.js'
import { defineCall } from '../internal/utils.js'
import type { TransactionReceipt } from '../Transaction.js'
/** TIP-403 policy type. */
export type PolicyType = 'whitelist' | 'blacklist'
/** @internal */
const policyTypes = ['whitelist', 'blacklist'] as const
/**
* Reference to a TIP-403 policy.
*
* - `'reject-all'` – built-in policy that rejects everything (id `0`).
* - `'allow-all'` – built-in policy that allows everything (id `1`).
* - `bigint` – a custom policy id (`>= 2`), e.g. one returned by
* {@link policy.create}.
*/
export type PolicyRef = 'reject-all' | 'allow-all' | bigint
/** @internal Built-in TIP-403 policy id that rejects everything. */
const rejectAllPolicyId = 0n
/** @internal Built-in TIP-403 policy id that allows everything. */
const allowAllPolicyId = 1n
/** Reason an inbound transfer or mint was blocked by a receive policy. */
export type BlockedReason = ReceivePolicyReceipt.BlockedReason
/** @internal */
const blockedReasons = ['none', 'tokenFilter', 'receivePolicy'] as const
/**
* Claimer authorized to reclaim blocked funds.
*
* - `'sender'` – the originator of the funds may reclaim them (default).
* - `'self'` – the account configuring the policy may reclaim them.
* - `Address` – a delegated third party may reclaim them.
*/
export type Claimer = 'sender' | 'self' | Address
/**
* Burns the funds backing a blocked receipt.
*
* Requires the caller to hold the token's `BURN_BLOCKED_ROLE`, and is only
* valid when the receipt's policy subject is currently unauthorized as a sender
* under the token's TIP-403 policy.
*
* @example
* ```ts
* import { createClient, http } from 'viem'
* import { tempo } from 'viem/chains'
* import { Actions } from 'viem/tempo'
* import { privateKeyToAccount } from 'viem/accounts'
*
* const client = createClient({
* account: privateKeyToAccount('0x...'),
* chain: tempo.extend({ feeToken: '0x20c0000000000000000000000000000000000001' }),
* transport: http(),
* })
*
* const hash = await Actions.receivePolicy.burn(client, {
* receipt: '0x...',
* })
* ```
*
* @param client - Client.
* @param parameters - Parameters.
* @returns The transaction hash.
*/
export async function burn<
chain extends Chain | undefined,
account extends Account | undefined,
>(
client: Client<Transport, chain, account>,
parameters: burn.Parameters<chain, account>,
): Promise<burn.ReturnValue> {
return burn.inner(writeContract, client, parameters)
}
export namespace burn {
export type Parameters<
chain extends Chain | undefined = Chain | undefined,
account extends Account | undefined = Account | undefined,
> = WriteParameters<chain, account> & Args
export type Args = {
/** The encoded claim receipt (witness from a `TransferBlocked` event). */
receipt: Hex
}
export type ReturnValue = WriteContractReturnType
// TODO: exhaustive error type
export type ErrorType = BaseErrorType
/** @internal */
export async function inner<
action extends typeof writeContract | typeof writeContractSync,
chain extends Chain | undefined,
account extends Account | undefined,
>(
action: action,
client: Client<Transport, chain, account>,
parameters: Parameters<chain, account>,
): Promise<ReturnType<action>> {
const {
account = client.account,
chain = client.chain,
receipt,
...rest
} = parameters
if (!account) throw new Error('`account` is required')
const call = burn.call({ receipt })
return action(client, {
...rest,
account,
chain,
...call,
} as never) as never
}
/**
* Defines a call to the `burnBlockedReceipt` function.
*
* @param args - Arguments.
* @returns The call.
*/
export function call(args: Args) {
const { receipt } = args
return defineCall({
address: Addresses.receivePolicyGuard,
abi: Abis.receivePolicyGuard,
functionName: 'burnBlockedReceipt',
args: [receipt],
})
}
/**
* Extracts the `ReceiptBurned` event from logs.
*
* @param logs - The logs.
* @returns The `ReceiptBurned` event.
*/
export function extractEvent(logs: Log[]) {
const [log] = parseEventLogs({
abi: Abis.receivePolicyGuard,
logs,
eventName: 'ReceiptBurned',
strict: true,
})
if (!log) throw new Error('`ReceiptBurned` event not found.')
return log
}
}
/**
* Burns the funds backing a blocked receipt and waits for the receipt.
*
* @example
* ```ts
* import { createClient, http } from 'viem'
* import { tempo } from 'viem/chains'
* import { Actions } from 'viem/tempo'
* import { privateKeyToAccount } from 'viem/accounts'
*
* const client = createClient({
* account: privateKeyToAccount('0x...'),
* chain: tempo.extend({ feeToken: '0x20c0000000000000000000000000000000000001' }),
* transport: http(),
* })
*
* const { receipt, ...result } = await Actions.receivePolicy.burnSync(client, {
* receipt: '0x...',
* })
* ```
*
* @param client - Client.
* @param parameters - Parameters.
* @returns The transaction receipt and event data.
*/
export async function burnSync<
chain extends Chain | undefined,
account extends Account | undefined,
>(
client: Client<Transport, chain, account>,
parameters: burnSync.Parameters<chain, account>,
): Promise<burnSync.ReturnValue> {
const { throwOnReceiptRevert = true, ...rest } = parameters
const receipt = await burn.inner(writeContractSync, client, {
...rest,
throwOnReceiptRevert,
} as never)
const { args } = burn.extractEvent(receipt.logs)
return {
...args,
receipt,
} as never
}
export namespace burnSync {
export type Parameters<
chain extends Chain | undefined = Chain | undefined,
account extends Account | undefined = Account | undefined,
> = burn.Parameters<chain, account>
export type Args = burn.Args
export type ReturnValue = Compute<
GetEventArgs<
typeof Abis.receivePolicyGuard,
'ReceiptBurned',
{ IndexedOnly: false; Required: true }
> & {
receipt: TransactionReceipt
}
>
// TODO: exhaustive error type
export type ErrorType = BaseErrorType
}
/**
* Claims blocked funds for a receipt, releasing them to a destination.
*
* @example
* ```ts
* import { createClient, http } from 'viem'
* import { tempo } from 'viem/chains'
* import { Actions } from 'viem/tempo'
* import { privateKeyToAccount } from 'viem/accounts'
*
* const client = createClient({
* account: privateKeyToAccount('0x...'),
* chain: tempo.extend({ feeToken: '0x20c0000000000000000000000000000000000001' }),
* transport: http(),
* })
*
* const hash = await Actions.receivePolicy.claim(client, {
* to: '0x...',
* receipt: '0x...',
* })
* ```
*
* @param client - Client.
* @param parameters - Parameters.
* @returns The transaction hash.
*/
export async function claim<
chain extends Chain | undefined,
account extends Account | undefined,
>(
client: Client<Transport, chain, account>,
parameters: claim.Parameters<chain, account>,
): Promise<claim.ReturnValue> {
return claim.inner(writeContract, client, parameters)
}
export namespace claim {
export type Parameters<
chain extends Chain | undefined = Chain | undefined,
account extends Account | undefined = Account | undefined,
> = WriteParameters<chain, account> & Args
export type Args = {
/** Destination to release the blocked funds to. */
to: Address
/** The encoded claim receipt (witness from a `TransferBlocked` event). */
receipt: Hex
}
export type ReturnValue = WriteContractReturnType
// TODO: exhaustive error type
export type ErrorType = BaseErrorType
/** @internal */
export async function inner<
action extends typeof writeContract | typeof writeContractSync,
chain extends Chain | undefined,
account extends Account | undefined,
>(
action: action,
client: Client<Transport, chain, account>,
parameters: Parameters<chain, account>,
): Promise<ReturnType<action>> {
const {
account = client.account,
chain = client.chain,
to,
receipt,
...rest
} = parameters
if (!account) throw new Error('`account` is required')
const call = claim.call({ to, receipt })
return action(client, {
...rest,
account,
chain,
...call,
} as never) as never
}
/**
* Defines a call to the `claim` function.
*
* @param args - Arguments.
* @returns The call.
*/
export function call(args: Args) {
const { to, receipt } = args
return defineCall({
address: Addresses.receivePolicyGuard,
abi: Abis.receivePolicyGuard,
functionName: 'claim',
args: [to, receipt],
})
}
/**
* Extracts the `ReceiptClaimed` event from logs.
*
* @param logs - The logs.
* @returns The `ReceiptClaimed` event.
*/
export function extractEvent(logs: Log[]) {
const [log] = parseEventLogs({
abi: Abis.receivePolicyGuard,
logs,
eventName: 'ReceiptClaimed',
strict: true,
})
if (!log) throw new Error('`ReceiptClaimed` event not found.')
return log
}
}
/**
* Claims blocked funds for a receipt and waits for the receipt.
*
* @example
* ```ts
* import { createClient, http } from 'viem'
* import { tempo } from 'viem/chains'
* import { Actions } from 'viem/tempo'
* import { privateKeyToAccount } from 'viem/accounts'
*
* const client = createClient({
* account: privateKeyToAccount('0x...'),
* chain: tempo.extend({ feeToken: '0x20c0000000000000000000000000000000000001' }),
* transport: http(),
* })
*
* const { receipt, ...result } = await Actions.receivePolicy.claimSync(client, {
* to: '0x...',
* receipt: '0x...',
* })
* ```
*
* @param client - Client.
* @param parameters - Parameters.
* @returns The transaction receipt and event data.
*/
export async function claimSync<
chain extends Chain | undefined,
account extends Account | undefined,
>(
client: Client<Transport, chain, account>,
parameters: claimSync.Parameters<chain, account>,
): Promise<claimSync.ReturnValue> {
const { throwOnReceiptRevert = true, ...rest } = parameters
const receipt = await claim.inner(writeContractSync, client, {
...rest,
throwOnReceiptRevert,
} as never)
const { args } = claim.extractEvent(receipt.logs)
return {
...args,
receipt,
} as never
}
export namespace claimSync {
export type Parameters<
chain extends Chain | undefined = Chain | undefined,
account extends Account | undefined = Account | undefined,
> = claim.Parameters<chain, account>
export type Args = claim.Args
export type ReturnValue = Compute<
GetEventArgs<
typeof Abis.receivePolicyGuard,
'ReceiptClaimed',
{ IndexedOnly: false; Required: true }
> & {
receipt: TransactionReceipt
}
>
// TODO: exhaustive error type
export type ErrorType = BaseErrorType
}
/**
* Gets the receive policy configured for an account.
*
* @example
* ```ts
* import { createClient, http } from 'viem'
* import { tempo } from 'viem/chains'
* import { Actions } from 'viem/tempo'
*
* const client = createClient({
* chain: tempo.extend({ feeToken: '0x20c0000000000000000000000000000000000001' }),
* transport: http(),
* })
*
* const policy = await Actions.receivePolicy.get(client, {
* account: '0x...',
* })
* ```
*
* @param client - Client.
* @param parameters - Parameters.
* @returns The receive policy.
*/
export async function get<
chain extends Chain | undefined,
account extends Account | undefined,
>(
client: Client<Transport, chain, account>,
parameters: get.Parameters<account>,
): Promise<get.ReturnValue> {
const { account: account_ = client.account, ...rest } = parameters
if (!account_) throw new Error('`account` is required.')
const account = parseAccount(account_)
const [
hasReceivePolicy,
senderPolicyId,
senderPolicyType,
tokenPolicyId,
tokenPolicyType,
recoveryAuthority,
] = await readContract(client, {
...rest,
account: null as never,
...get.call({ account: account.address }),
})
return {
hasReceivePolicy,
senderPolicyId: toPolicyRef(senderPolicyId),
senderPolicyType: policyTypes[senderPolicyType] ?? 'whitelist',
tokenPolicyId: toPolicyRef(tokenPolicyId),
tokenPolicyType: policyTypes[tokenPolicyType] ?? 'whitelist',
claimer: toClaimer(recoveryAuthority, account.address),
recoveryAuthority,
}
}
export namespace get {
export type Parameters<
account extends Account | undefined = Account | undefined,
> = ReadParameters & GetAccountParameter<account>
export type Args = {
/** Account address. */
account: Address
}
export type ReturnValue = Compute<{
/** Whether the account has a receive policy configured. */
hasReceivePolicy: boolean
/** TIP-403 policy restricting which senders are allowed. */
senderPolicyId: PolicyRef
/** Type of the sender policy. */
senderPolicyType: PolicyType
/** TIP-403 policy restricting which tokens are allowed. */
tokenPolicyId: PolicyRef
/** Type of the token policy. */
tokenPolicyType: PolicyType
/** Who can reclaim funds blocked by this policy. */
claimer: Claimer
/** Raw recovery authority address. */
recoveryAuthority: Address
}>
/**
* Defines a call to the `receivePolicy` function.
*
* @param args - Arguments.
* @returns The call.
*/
export function call(args: Args) {
const { account } = args
return defineCall({
address: Addresses.tip403Registry,
abi: Abis.tip403Registry,
functionName: 'receivePolicy',
args: [account],
})
}
}
/**
* Gets the blocked balance for an encoded receipt.
*
* @example
* ```ts
* import { createClient, http } from 'viem'
* import { tempo } from 'viem/chains'
* import { Actions } from 'viem/tempo'
*
* const client = createClient({
* chain: tempo.extend({ feeToken: '0x20c0000000000000000000000000000000000001' }),
* transport: http(),
* })
*
* const amount = await Actions.receivePolicy.getBlockedBalance(client, {
* receipt: '0x...',
* })
* ```
*
* @param client - Client.
* @param parameters - Parameters.
* @returns The blocked amount for the receipt.
*/
export async function getBlockedBalance<chain extends Chain | undefined>(
client: Client<Transport, chain>,
parameters: getBlockedBalance.Parameters,
): Promise<getBlockedBalance.ReturnValue> {
const { receipt, ...rest } = parameters
return readContract(client, {
...rest,
...getBlockedBalance.call({ receipt }),
})
}
export namespace getBlockedBalance {
export type Parameters = ReadParameters & Args
export type Args = {
/** The encoded claim receipt. */
receipt: Hex
}
export type ReturnValue = ReadContractReturnType<
typeof Abis.receivePolicyGuard,
'balanceOf',
never
>
/**
* Defines a call to the `balanceOf` function.
*
* @param args - Arguments.
* @returns The call.
*/
export function call(args: Args) {
const { receipt } = args
return defineCall({
address: Addresses.receivePolicyGuard,
abi: Abis.receivePolicyGuard,
functionName: 'balanceOf',
args: [receipt],
})
}
}
/**
* Sets the receive policy for the calling account.
*
* A receive policy controls which TIP-20 tokens and which senders an account
* accepts. Inbound transfers and mints that violate the policy are not
* reverted – instead the funds are redirected to the `ReceivePolicyGuard` and
* can be reclaimed later (see {@link claim}).
*
* @example
* ```ts
* import { createClient, http } from 'viem'
* import { tempo } from 'viem/chains'
* import { Actions } from 'viem/tempo'
* import { privateKeyToAccount } from 'viem/accounts'
*
* const client = createClient({
* account: privateKeyToAccount('0x...'),
* chain: tempo.extend({ feeToken: '0x20c0000000000000000000000000000000000001' }),
* transport: http(),
* })
*
* const hash = await Actions.receivePolicy.set(client, {
* senderPolicyId: 'allow-all',
* tokenPolicyId: 'allow-all',
* claimer: 'self',
* })
* ```
*
* @param client - Client.
* @param parameters - Parameters.
* @returns The transaction hash.
*/
export async function set<
chain extends Chain | undefined,
account extends Account | undefined,
>(
client: Client<Transport, chain, account>,
parameters: set.Parameters<chain, account>,
): Promise<set.ReturnValue> {
return set.inner(writeContract, client, parameters)
}
export namespace set {
export type Parameters<
chain extends Chain | undefined = Chain | undefined,
account extends Account | undefined = Account | undefined,
> = WriteParameters<chain, account> & Omit<Args, 'recoveryAuthority'>
export type Args = {
/**
* TIP-403 policy restricting which senders are allowed.
* @default 'allow-all'
*/
senderPolicyId?: PolicyRef | undefined
/**
* TIP-403 policy restricting which tokens are allowed.
* @default 'allow-all'
*/
tokenPolicyId?: PolicyRef | undefined
/**
* Who can reclaim funds blocked by this policy.
* @default 'sender'
*/
claimer?: Claimer | undefined
}
export type ReturnValue = WriteContractReturnType
// TODO: exhaustive error type
export type ErrorType = BaseErrorType
/** @internal */
export async function inner<
action extends typeof writeContract | typeof writeContractSync,
chain extends Chain | undefined,
account extends Account | undefined,
>(
action: action,
client: Client<Transport, chain, account>,
parameters: Parameters<chain, account>,
): Promise<ReturnType<action>> {
const {
account = client.account,
chain = client.chain,
senderPolicyId = 'allow-all',
tokenPolicyId = 'allow-all',
claimer = 'sender',
...rest
} = parameters
if (!account) throw new Error('`account` is required')
const address = parseAccount(account).address
const recoveryAuthority = resolveClaimer(claimer, address)
const call = set.call({
senderPolicyId: resolvePolicyRef(senderPolicyId),
tokenFilterId: resolvePolicyRef(tokenPolicyId),
recoveryAuthority,
})
return action(client, {
...rest,
account,
chain,
...call,
} as never) as never
}
/**
* Defines a call to the `setReceivePolicy` function.
*
* @param args - Arguments.
* @returns The call.
*/
export function call(args: {
/** Resolved TIP-403 sender policy id. */
senderPolicyId: bigint
/** Resolved TIP-403 token filter id. */
tokenFilterId: bigint
/** Resolved recovery authority. */
recoveryAuthority: Address
}) {
const { senderPolicyId, tokenFilterId, recoveryAuthority } = args
return defineCall({
address: Addresses.tip403Registry,
abi: Abis.tip403Registry,
functionName: 'setReceivePolicy',
args: [senderPolicyId, tokenFilterId, recoveryAuthority],
})
}
/**
* Extracts the `ReceivePolicyUpdated` event from logs.
*
* @param logs - The logs.
* @returns The `ReceivePolicyUpdated` event.
*/
export function extractEvent(logs: Log[]) {
const [log] = parseEventLogs({
abi: Abis.tip403Registry,
logs,
eventName: 'ReceivePolicyUpdated',
strict: true,
})
if (!log) throw new Error('`ReceivePolicyUpdated` event not found.')
return log
}
}
/**
* Sets the receive policy for the calling account and waits for the receipt.
*
* @example
* ```ts
* import { createClient, http } from 'viem'
* import { tempo } from 'viem/chains'
* import { Actions } from 'viem/tempo'
* import { privateKeyToAccount } from 'viem/accounts'
*
* const client = createClient({
* account: privateKeyToAccount('0x...'),
* chain: tempo.extend({ feeToken: '0x20c0000000000000000000000000000000000001' }),
* transport: http(),
* })
*
* const { receipt, ...result } = await Actions.receivePolicy.setSync(client, {
* senderPolicyId: 'allow-all',
* tokenPolicyId: 'allow-all',
* claimer: 'self',
* })
* ```
*
* @param client - Client.
* @param parameters - Parameters.
* @returns The transaction receipt and event data.
*/
export async function setSync<
chain extends Chain | undefined,
account extends Account | undefined,
>(
client: Client<Transport, chain, account>,
parameters: setSync.Parameters<chain, account>,
): Promise<setSync.ReturnValue> {
const { throwOnReceiptRevert = true, ...rest } = parameters
const receipt = await set.inner(writeContractSync, client, {
...rest,
throwOnReceiptRevert,
} as never)
const { tokenFilterId, ...args } = set.extractEvent(receipt.logs).args
return {
...args,
senderPolicyId: toPolicyRef(args.senderPolicyId),
tokenPolicyId: toPolicyRef(tokenFilterId),
claimer: toClaimer(args.recoveryAuthority, args.account),
receipt,
} as never
}
export namespace setSync {
export type Parameters<
chain extends Chain | undefined = Chain | undefined,
account extends Account | undefined = Account | undefined,
> = set.Parameters<chain, account>
export type Args = set.Args
export type ReturnValue = Compute<
UnionOmit<
GetEventArgs<
typeof Abis.tip403Registry,
'ReceivePolicyUpdated',
{ IndexedOnly: false; Required: true }
>,
'senderPolicyId' | 'tokenFilterId'
> & {
/** TIP-403 policy restricting which senders are allowed. */
senderPolicyId: PolicyRef
/** TIP-403 policy restricting which tokens are allowed. */
tokenPolicyId: PolicyRef
/** Who can reclaim funds blocked by this policy. */
claimer: Claimer
receipt: TransactionReceipt
}
>
// TODO: exhaustive error type
export type ErrorType = BaseErrorType
}
/**
* Checks whether a transfer or mint to a receiver is allowed by the receiver's
* receive policy.
*
* @example
* ```ts
* import { createClient, http } from 'viem'
* import { tempo } from 'viem/chains'
* import { Actions } from 'viem/tempo'
*
* const client = createClient({
* chain: tempo.extend({ feeToken: '0x20c0000000000000000000000000000000000001' }),
* transport: http(),
* })
*
* const { authorized, blockedReason } = await Actions.receivePolicy.validate(
* client,
* {
* token: '0x...',
* sender: '0x...',
* receiver: '0x...',
* },
* )
* ```
*
* @param client - Client.
* @param parameters - Parameters.
* @returns Whether the transfer is authorized and, if not, why.
*/
export async function validate<chain extends Chain | undefined>(
client: Client<Transport, chain>,
parameters: validate.Parameters,
): Promise<validate.ReturnValue> {
const { token, sender, receiver, ...rest } = parameters
const [authorized, blockedReason] = await readContract(client, {
...rest,
...validate.call({ token, sender, receiver }),
})
return {
authorized,
blockedReason: blockedReasons[blockedReason] ?? 'none',
}
}
export namespace validate {
export type Parameters = ReadParameters & Args
export type Args = {
/** Token address. */
token: Address
/** Sender address. */
sender: Address
/** Receiver address. */
receiver: Address
}
export type ReturnValue = Compute<{
/** Whether the transfer is authorized. */
authorized: boolean
/** Reason the transfer would be blocked. */
blockedReason: BlockedReason
}>
/**
* Defines a call to the `validateReceivePolicy` function.
*
* @param args - Arguments.
* @returns The call.
*/
export function call(args: Args) {
const { token, sender, receiver } = args
return defineCall({
address: Addresses.tip403Registry,
abi: Abis.tip403Registry,
functionName: 'validateReceivePolicy',
args: [token, sender, receiver],
})
}
}
/**
* Watches for blocked transfer events.
*
* @example
* ```ts
* import { createClient, http } from 'viem'
* import { tempo } from 'viem/chains'
* import { Actions } from 'viem/tempo'
*
* const client = createClient({
* chain: tempo.extend({ feeToken: '0x20c0000000000000000000000000000000000001' }),
* transport: http(),
* })
*
* const unwatch = Actions.receivePolicy.watchBlocked(client, {
* onBlocked: (args, log) => {
* console.log('Transfer blocked:', args)
* },
* })
* ```
*
* @param client - Client.
* @param parameters - Parameters.
* @returns A function to unsubscribe from the event.
*/
export function watchBlocked<
chain extends Chain | undefined,
account extends Account | undefined,
>(
client: Client<Transport, chain, account>,
parameters: watchBlocked.Parameters,
) {
const { onBlocked, ...rest } = parameters
return watchContractEvent(client, {
...rest,
address: Addresses.receivePolicyGuard,
abi: Abis.receivePolicyGuard,
eventName: 'TransferBlocked',
onLogs: (logs) => {
for (const log of logs) {
const { receipt, ...args } = log.args
onBlocked({ ...args, claimReceipt: receipt }, log)
}
},
strict: true,
})
}
export declare namespace watchBlocked {
export type Args = Compute<
UnionOmit<
GetEventArgs<
typeof Abis.receivePolicyGuard,
'TransferBlocked',
{ IndexedOnly: false; Required: true }
>,
'receipt'
> & {
/** The encoded claim receipt (witness for `claim`/`burn`). */
claimReceipt: Hex
}
>
export type Log = viem_Log<
bigint,
number,
false,
ExtractAbiItem<typeof Abis.receivePolicyGuard, 'TransferBlocked'>,
true
>
export type Parameters = UnionOmit<
WatchContractEventParameters<
typeof Abis.receivePolicyGuard,
'TransferBlocked',
true
>,
'abi' | 'address' | 'batch' | 'eventName' | 'onLogs' | 'strict'
> & {
/** Callback to invoke when a transfer is blocked. */
onBlocked: (args: Args, log: Log) => void
}
}
/**
* Watches for receipt burned events.
*
* @example
* ```ts
* import { createClient, http } from 'viem'
* import { tempo } from 'viem/chains'
* import { Actions } from 'viem/tempo'
*
* const client = createClient({
* chain: tempo.extend({ feeToken: '0x20c0000000000000000000000000000000000001' }),
* transport: http(),
* })
*
* const unwatch = Actions.receivePolicy.watchBurned(client, {
* onBurned: (args, log) => {
* console.log('Receipt burned:', args)
* },
* })
* ```
*
* @param client - Client.
* @param parameters - Parameters.
* @returns A function to unsubscribe from the event.
*/
export function watchBurned<
chain extends Chain | undefined,
account extends Account | undefined,
>(
client: Client<Transport, chain, account>,
parameters: watchBurned.Parameters,
) {
const { onBurned, ...rest } = parameters
return watchContractEvent(client, {
...rest,
address: Addresses.receivePolicyGuard,
abi: Abis.receivePolicyGuard,
eventName: 'ReceiptBurned',
onLogs: (logs) => {
for (const log of logs) onBurned(log.args, log)
},
strict: true,
})
}
export declare namespace watchBurned {
export type Args = Compute<
GetEventArgs<
typeof Abis.receivePolicyGuard,
'ReceiptBurned',
{ IndexedOnly: false; Required: true }
>
>
export type Log = viem_Log<
bigint,
number,
false,
ExtractAbiItem<typeof Abis.receivePolicyGuard, 'ReceiptBurned'>,
true
>
export type Parameters = UnionOmit<
WatchContractEventParameters<
typeof Abis.receivePolicyGuard,
'ReceiptBurned',
true
>,
'abi' | 'address' | 'batch' | 'eventName' | 'onLogs' | 'strict'
> & {
/** Callback to invoke when a receipt is burned. */
onBurned: (args: Args, log: Log) => void
}
}
/**
* Watches for receipt claimed events.
*
* @example
* ```ts
* import { createClient, http } from 'viem'
* import { tempo } from 'viem/chains'
* import { Actions } from 'viem/tempo'
*
* const client = createClient({
* chain: tempo.extend({ feeToken: '0x20c0000000000000000000000000000000000001' }),
* transport: http(),
* })
*
* const unwatch = Actions.receivePolicy.watchClaimed(client, {
* onClaimed: (args, log) => {
* console.log('Receipt claimed:', args)
* },
* })
* ```
*
* @param client - Client.
* @param parameters - Parameters.
* @returns A function to unsubscribe from the event.
*/
export function watchClaimed<
chain extends Chain | undefined,
account extends Account | undefined,
>(
client: Client<Transport, chain, account>,
parameters: watchClaimed.Parameters,
) {
const { onClaimed, ...rest } = parameters
return watchContractEvent(client, {
...rest,
address: Addresses.receivePolicyGuard,
abi: Abis.receivePolicyGuard,
eventName: 'ReceiptClaimed',
onLogs: (logs) => {
for (const log of logs) onClaimed(log.args, log)
},
strict: true,
})
}
export declare namespace watchClaimed {
export type Args = Compute<
GetEventArgs<
typeof Abis.receivePolicyGuard,
'ReceiptClaimed',
{ IndexedOnly: false; Required: true }
>
>
export type Log = viem_Log<
bigint,
number,
false,
ExtractAbiItem<typeof Abis.receivePolicyGuard, 'ReceiptClaimed'>,
true
>
export type Parameters = UnionOmit<
WatchContractEventParameters<
typeof Abis.receivePolicyGuard,
'ReceiptClaimed',
true
>,
'abi' | 'address' | 'batch' | 'eventName' | 'onLogs' | 'strict'
> & {
/** Callback to invoke when a receipt is claimed. */
onClaimed: (args: Args, log: Log) => void
}
}
/**
* Watches for receive policy update events.
*
* @example
* ```ts
* import { createClient, http } from 'viem'
* import { tempo } from 'viem/chains'
* import { Actions } from 'viem/tempo'
*
* const client = createClient({
* chain: tempo.extend({ feeToken: '0x20c0000000000000000000000000000000000001' }),
* transport: http(),
* })
*
* const unwatch = Actions.receivePolicy.watchUpdated(client, {
* onUpdated: (args, log) => {
* console.log('Receive policy updated:', args)
* },
* })
* ```
*
* @param client - Client.
* @param parameters - Parameters.
* @returns A function to unsubscribe from the event.
*/
export function watchUpdated<
chain extends Chain | undefined,
account extends Account | undefined,
>(
client: Client<Transport, chain, account>,
parameters: watchUpdated.Parameters,
) {
const { onUpdated, ...rest } = parameters
return watchContractEvent(client, {
...rest,
address: Addresses.tip403Registry,
abi: Abis.tip403Registry,
eventName: 'ReceivePolicyUpdated',
onLogs: (logs) => {
for (const log of logs) {
const { tokenFilterId, ...args } = log.args
onUpdated(
{
...args,
senderPolicyId: toPolicyRef(args.senderPolicyId),
tokenPolicyId: toPolicyRef(tokenFilterId),
claimer: toClaimer(args.recoveryAuthority, args.account),
},
log,
)
}
},
strict: true,
})
}
export declare namespace watchUpdated {
export type Args = Compute<
UnionOmit<
GetEventArgs<
typeof Abis.tip403Registry,
'ReceivePolicyUpdated',
{ IndexedOnly: false; Required: true }
>,
'senderPolicyId' | 'tokenFilterId'
> & {
/** TIP-403 policy restricting which senders are allowed. */
senderPolicyId: PolicyRef
/** TIP-403 policy restricting which tokens are allowed. */
tokenPolicyId: PolicyRef
/** Who can reclaim funds blocked by this policy. */
claimer: Claimer
}
>
export type Log = viem_Log<
bigint,
number,
false,
ExtractAbiItem<typeof Abis.tip403Registry, 'ReceivePolicyUpdated'>,
true
>
export type Parameters = UnionOmit<
WatchContractEventParameters<
typeof Abis.tip403Registry,
'ReceivePolicyUpdated',
true
>,
'abi' | 'address' | 'batch' | 'eventName' | 'onLogs' | 'strict'
> & {
/** Callback to invoke when a receive policy is updated. */
onUpdated: (args: Args, log: Log) => void
}
}
/** @internal */
function resolvePolicyRef(ref: PolicyRef): bigint {
if (ref === 'reject-all') return rejectAllPolicyId
if (ref === 'allow-all') return allowAllPolicyId
return ref
}
/** @internal */
function toPolicyRef(id: bigint): PolicyRef {
if (id === rejectAllPolicyId) return 'reject-all'
if (id === allowAllPolicyId) return 'allow-all'
return id
}
/** @internal */
function resolveClaimer(claimer: Claimer, self: Address): Address {
if (claimer === 'sender') return zeroAddress
if (claimer === 'self') return self
return claimer
}
/** @internal */
function toClaimer(recoveryAuthority: Address, account: Address): Claimer {
if (recoveryAuthority === zeroAddress) return 'sender'
if (isAddressEqual(recoveryAuthority, account)) return 'self'
return recoveryAuthority
}