- Consolidated duplicate UndoManagers to single instance - Fixed connection promise to only resolve on 'connected' status - Fixed WebSocketProvider import (WebsocketProvider) - Added proper doc.destroy() cleanup - Renamed isPresenceInitialized property to avoid conflict Co-Authored-By: Paperclip <noreply@paperclip.ing>
994 lines
30 KiB
TypeScript
994 lines
30 KiB
TypeScript
import type { Address } from 'abitype'
|
|
import type { Account } from '../../accounts/types.js'
|
|
import type { ReadContractReturnType } from '../../actions/public/readContract.js'
|
|
import { readContract } from '../../actions/public/readContract.js'
|
|
import type {
|
|
WatchContractEventParameters,
|
|
WatchContractEventReturnType,
|
|
} 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 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 { UnionOmit } from '../../types/utils.js'
|
|
import { parseEventLogs } from '../../utils/abi/parseEventLogs.js'
|
|
import * as Abis from '../Abis.js'
|
|
import type { ReadParameters, WriteParameters } from '../internal/types.js'
|
|
import { defineCall } from '../internal/utils.js'
|
|
|
|
/**
|
|
* Claims accumulated rewards for a recipient.
|
|
*
|
|
* This function allows a reward recipient to claim their accumulated rewards
|
|
* and receive them as token transfers to their own balance.
|
|
*
|
|
* - Accrues all pending rewards up to the current block timestamp.
|
|
* - Updates the caller's reward accounting.
|
|
* - Transfers the caller's accumulated `rewardBalance` from the token contract to the caller.
|
|
* - If the contract's balance is insufficient, claims up to the available amount.
|
|
* - Returns the actual amount claimed.
|
|
*
|
|
* Notes:
|
|
* - Reverts with `Paused` if the token is paused.
|
|
* - Reverts with `PolicyForbids` if the caller is not authorized to receive tokens under TIP-403.
|
|
* - If opted in, the claimed amount is added back to `optedInSupply` since it goes to the recipient's balance.
|
|
*
|
|
* @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.reward.claim(client, {
|
|
* token: '0x20c0000000000000000000000000000000000001',
|
|
* })
|
|
* ```
|
|
*
|
|
* @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 Args = {
|
|
/** The TIP20 token address */
|
|
token: Address
|
|
}
|
|
|
|
export type Parameters<
|
|
chain extends Chain | undefined = Chain | undefined,
|
|
account extends Account | undefined = Account | undefined,
|
|
> = WriteParameters<chain, account> & Args
|
|
|
|
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 { token, ...rest } = parameters
|
|
const call = claim.call({ token })
|
|
return (await action(client, {
|
|
...rest,
|
|
...call,
|
|
} as never)) as never
|
|
}
|
|
|
|
/**
|
|
* Defines a call to the `claimRewards` function.
|
|
*
|
|
* Can be passed as a parameter to:
|
|
* - [`estimateContractGas`](https://viem.sh/docs/contract/estimateContractGas): estimate the gas cost of the call
|
|
* - [`simulateContract`](https://viem.sh/docs/contract/simulateContract): simulate the call
|
|
* - [`sendCalls`](https://viem.sh/docs/actions/wallet/sendCalls): send multiple calls
|
|
*
|
|
* @example
|
|
* ```ts
|
|
* import { createClient, http, walletActions } from 'viem'
|
|
* import { tempo } from 'viem/chains'
|
|
* import { Actions } from 'viem/tempo'
|
|
*
|
|
* const client = createClient({
|
|
* chain: tempo.extend({ feeToken: '0x20c0000000000000000000000000000000000001' })
|
|
* transport: http(),
|
|
* }).extend(walletActions)
|
|
*
|
|
* const hash = await client.sendTransaction({
|
|
* calls: [actions.reward.claim.call({
|
|
* token: '0x20c0000000000000000000000000000000000001',
|
|
* })],
|
|
* })
|
|
* ```
|
|
*
|
|
* @param args - Arguments.
|
|
* @returns The call.
|
|
*/
|
|
export function call(args: Args) {
|
|
const { token } = args
|
|
return defineCall({
|
|
address: token,
|
|
abi: Abis.tip20,
|
|
args: [],
|
|
functionName: 'claimRewards',
|
|
})
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Claims accumulated rewards for a recipient and waits for confirmation.
|
|
*
|
|
* This function allows a reward recipient to claim their accumulated rewards
|
|
* and receive them as token transfers to their own balance.
|
|
*
|
|
* Behavior:
|
|
* - Accrues all pending rewards up to the current block timestamp.
|
|
* - Updates the caller's reward accounting.
|
|
* - Transfers the caller's accumulated `rewardBalance` from the token contract to the caller.
|
|
* - If the contract's balance is insufficient, claims up to the available amount.
|
|
*
|
|
* Notes:
|
|
* - Reverts with `Paused` if the token is paused.
|
|
* - Reverts with `PolicyForbids` if the caller is not authorized to receive tokens under TIP-403.
|
|
* - If opted in, the claimed amount is added back to `optedInSupply` since it goes to the recipient's balance.
|
|
*
|
|
* @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 } = await Actions.reward.claimSync(client, {
|
|
* token: '0x20c0000000000000000000000000000000000001',
|
|
* })
|
|
* ```
|
|
*
|
|
* @param client - Client.
|
|
* @param parameters - Parameters.
|
|
* @returns The amount claimed and transaction receipt.
|
|
*/
|
|
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)
|
|
return {
|
|
receipt,
|
|
} as never
|
|
}
|
|
|
|
export namespace claimSync {
|
|
export type Parameters<
|
|
chain extends Chain | undefined = Chain | undefined,
|
|
account extends Account | undefined = Account | undefined,
|
|
> = WriteParameters<chain, account> & claim.Args
|
|
|
|
export type ReturnValue = {
|
|
/** The transaction receipt */
|
|
receipt: Awaited<ReturnType<typeof writeContractSync>>
|
|
}
|
|
|
|
export type ErrorType = claim.ErrorType
|
|
}
|
|
|
|
/**
|
|
* Distributes rewards to opted-in token holders.
|
|
*
|
|
* This function transfers `amount` of tokens from the caller into the token contract's
|
|
* reward pool and immediately distributes them to current opted-in holders by increasing
|
|
* `globalRewardPerToken`.
|
|
*
|
|
* Notes:
|
|
* - Reverts with `InvalidAmount` if `amount == 0`.
|
|
* - The transfer from caller to pool is subject to TIP-403 policy checks.
|
|
*
|
|
* @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.reward.distribute(client, {
|
|
* amount: 100000000000000000000n,
|
|
* token: '0x20c0000000000000000000000000000000000001',
|
|
* })
|
|
* ```
|
|
*
|
|
* @param client - Client.
|
|
* @param parameters - Parameters.
|
|
* @returns The transaction hash.
|
|
*/
|
|
export async function distribute<
|
|
chain extends Chain | undefined,
|
|
account extends Account | undefined,
|
|
>(
|
|
client: Client<Transport, chain, account>,
|
|
parameters: distribute.Parameters<chain, account>,
|
|
): Promise<distribute.ReturnValue> {
|
|
return distribute.inner(writeContract, client, parameters)
|
|
}
|
|
|
|
/**
|
|
* Distributes rewards to opted-in token holders and waits for confirmation.
|
|
*
|
|
* This function transfers `amount` of tokens from the caller into the token contract's
|
|
* reward pool and immediately distributes them to current opted-in holders by increasing
|
|
* `globalRewardPerToken`.
|
|
*
|
|
* Notes:
|
|
* - Reverts with `InvalidAmount` if `amount == 0`.
|
|
* - The transfer from caller to pool is subject to TIP-403 policy checks.
|
|
*
|
|
* @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 { amount, funder, receipt } = await Actions.reward.distributeSync(client, {
|
|
* amount: 100000000000000000000n,
|
|
* token: '0x20c0000000000000000000000000000000000001',
|
|
* })
|
|
* ```
|
|
*
|
|
* @param client - Client.
|
|
* @param parameters - Parameters.
|
|
* @returns The funder, amount, and transaction receipt.
|
|
*/
|
|
export async function distributeSync<
|
|
chain extends Chain | undefined,
|
|
account extends Account | undefined,
|
|
>(
|
|
client: Client<Transport, chain, account>,
|
|
parameters: distributeSync.Parameters<chain, account>,
|
|
): Promise<distributeSync.ReturnValue> {
|
|
const { throwOnReceiptRevert = true, ...rest } = parameters
|
|
const receipt = await distribute.inner(writeContractSync, client, {
|
|
...rest,
|
|
throwOnReceiptRevert,
|
|
} as never)
|
|
const { args } = distribute.extractEvent(receipt.logs)
|
|
return {
|
|
...args,
|
|
receipt,
|
|
} as never
|
|
}
|
|
|
|
export namespace distribute {
|
|
export type Args = {
|
|
/** The amount of tokens to distribute (must be > 0) */
|
|
amount: bigint
|
|
/** The TIP20 token address */
|
|
token: Address
|
|
}
|
|
|
|
export type Parameters<
|
|
chain extends Chain | undefined = Chain | undefined,
|
|
account extends Account | undefined = Account | undefined,
|
|
> = WriteParameters<chain, account> & Args
|
|
|
|
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 { amount, token, ...rest } = parameters
|
|
const call = distribute.call({ amount, token })
|
|
return (await action(client, {
|
|
...rest,
|
|
...call,
|
|
} as never)) as never
|
|
}
|
|
|
|
/**
|
|
* Defines a call to the `distributeReward` function.
|
|
*
|
|
* Can be passed as a parameter to:
|
|
* - [`estimateContractGas`](https://viem.sh/docs/contract/estimateContractGas): estimate the gas cost of the call
|
|
* - [`simulateContract`](https://viem.sh/docs/contract/simulateContract): simulate the call
|
|
* - [`sendCalls`](https://viem.sh/docs/actions/wallet/sendCalls): send multiple calls
|
|
*
|
|
* @example
|
|
* ```ts
|
|
* import { createClient, http, walletActions } from 'viem'
|
|
* import { tempo } from 'viem/chains'
|
|
* import { Actions } from 'viem/tempo'
|
|
*
|
|
* const client = createClient({
|
|
* chain: tempo.extend({ feeToken: '0x20c0000000000000000000000000000000000001' })
|
|
* transport: http(),
|
|
* }).extend(walletActions)
|
|
*
|
|
* const hash = await client.sendTransaction({
|
|
* calls: [actions.reward.distribute.call({
|
|
* amount: 100000000000000000000n,
|
|
* token: '0x20c0000000000000000000000000000000000001',
|
|
* })],
|
|
* })
|
|
* ```
|
|
*
|
|
* @param args - Arguments.
|
|
* @returns The call.
|
|
*/
|
|
export function call(args: Args) {
|
|
const { amount, token } = args
|
|
return defineCall({
|
|
address: token,
|
|
abi: Abis.tip20,
|
|
args: [amount],
|
|
functionName: 'distributeReward',
|
|
})
|
|
}
|
|
|
|
/**
|
|
* Extracts the `RewardDistributed` event from logs.
|
|
*
|
|
* @param logs - The logs.
|
|
* @returns The `RewardDistributed` event.
|
|
*/
|
|
export function extractEvent(logs: Log[]) {
|
|
const [log] = parseEventLogs({
|
|
abi: Abis.tip20,
|
|
logs,
|
|
eventName: 'RewardDistributed',
|
|
strict: true,
|
|
})
|
|
if (!log) throw new Error('`RewardDistributed` event not found.')
|
|
return log
|
|
}
|
|
}
|
|
|
|
export declare namespace distributeSync {
|
|
export type Parameters<
|
|
chain extends Chain | undefined = Chain | undefined,
|
|
account extends Account | undefined = Account | undefined,
|
|
> = WriteParameters<chain, account> & distribute.Args
|
|
|
|
export type ReturnValue = {
|
|
/** The amount distributed */
|
|
amount: bigint
|
|
/** The address that funded the distribution */
|
|
funder: Address
|
|
/** The transaction receipt */
|
|
receipt: Awaited<ReturnType<typeof writeContractSync>>
|
|
}
|
|
|
|
export type ErrorType = distribute.ErrorType
|
|
}
|
|
|
|
/**
|
|
* Gets the global reward per token value.
|
|
*
|
|
* Returns the current global reward per token value scaled by `ACC_PRECISION` (1e18).
|
|
* This value increases each time rewards are distributed.
|
|
*
|
|
* @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 rewardPerToken = await Actions.reward.getGlobalRewardPerToken(client, {
|
|
* token: '0x20c0000000000000000000000000000000000001',
|
|
* })
|
|
* ```
|
|
*
|
|
* @param client - Client.
|
|
* @param parameters - Parameters.
|
|
* @returns The global reward per token (scaled by 1e18).
|
|
*/
|
|
export async function getGlobalRewardPerToken<chain extends Chain | undefined>(
|
|
client: Client<Transport, chain>,
|
|
parameters: getGlobalRewardPerToken.Parameters,
|
|
): Promise<getGlobalRewardPerToken.ReturnValue> {
|
|
return readContract(client, {
|
|
...parameters,
|
|
...getGlobalRewardPerToken.call(parameters),
|
|
})
|
|
}
|
|
|
|
export namespace getGlobalRewardPerToken {
|
|
export type Parameters = ReadParameters & Args
|
|
|
|
export type Args = {
|
|
/** The TIP20 token address */
|
|
token: Address
|
|
}
|
|
|
|
export type ReturnValue = ReadContractReturnType<
|
|
typeof Abis.tip20,
|
|
'globalRewardPerToken',
|
|
never
|
|
>
|
|
|
|
/**
|
|
* Defines a call to the `globalRewardPerToken` function.
|
|
*
|
|
* @param args - Arguments.
|
|
* @returns The call.
|
|
*/
|
|
export function call(args: Args) {
|
|
const { token } = args
|
|
return defineCall({
|
|
address: token,
|
|
abi: Abis.tip20,
|
|
args: [],
|
|
functionName: 'globalRewardPerToken',
|
|
})
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Calculates the pending claimable rewards for an account without modifying state.
|
|
*
|
|
* Returns the total pending claimable reward amount, including stored balance and newly accrued rewards.
|
|
*
|
|
* @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 pending = await Actions.reward.getPendingRewards(client, {
|
|
* token: '0x20c0000000000000000000000000000000000001',
|
|
* account: '0xa5cc3c03994DB5b0d9A5eEdD10CabaB0813678AC',
|
|
* })
|
|
* ```
|
|
*
|
|
* @param client - Client.
|
|
* @param parameters - Parameters.
|
|
* @returns The total pending claimable reward amount.
|
|
*/
|
|
export async function getPendingRewards<chain extends Chain | undefined>(
|
|
client: Client<Transport, chain>,
|
|
parameters: getPendingRewards.Parameters,
|
|
): Promise<getPendingRewards.ReturnValue> {
|
|
return readContract(client, {
|
|
...parameters,
|
|
...getPendingRewards.call(parameters),
|
|
})
|
|
}
|
|
|
|
export namespace getPendingRewards {
|
|
export type Parameters = ReadParameters & Args
|
|
|
|
export type Args = {
|
|
/** The account address to query pending rewards for */
|
|
account: Address
|
|
/** The TIP20 token address */
|
|
token: Address
|
|
}
|
|
|
|
export type ReturnValue = ReadContractReturnType<
|
|
typeof Abis.tip20,
|
|
'getPendingRewards',
|
|
never
|
|
>
|
|
|
|
/**
|
|
* Defines a call to the `getPendingRewards` function.
|
|
*
|
|
* @param args - Arguments.
|
|
* @returns The call.
|
|
*/
|
|
export function call(args: Args) {
|
|
const { account, token } = args
|
|
return defineCall({
|
|
address: token,
|
|
abi: Abis.tip20,
|
|
args: [account],
|
|
functionName: 'getPendingRewards',
|
|
})
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Gets the reward information for a specific account.
|
|
*
|
|
* Returns the reward recipient address, reward per token value, and accumulated reward balance for the specified account.
|
|
* This information includes:
|
|
* - `rewardRecipient`: The address designated to receive rewards (zero address if opted out)
|
|
* - `rewardPerToken`: The reward per token value for this account
|
|
* - `rewardBalance`: The accumulated reward balance waiting to be claimed
|
|
*
|
|
* @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 info = await Actions.reward.getUserRewardInfo(client, {
|
|
* token: '0x20c0000000000000000000000000000000000001',
|
|
* account: '0xa5cc3c03994DB5b0d9A5eEdD10CabaB0813678AC',
|
|
* })
|
|
* ```
|
|
*
|
|
* @param client - Client.
|
|
* @param parameters - Parameters.
|
|
* @returns The user's reward information (recipient, rewardPerToken, rewardBalance).
|
|
*/
|
|
export async function getUserRewardInfo<chain extends Chain | undefined>(
|
|
client: Client<Transport, chain>,
|
|
parameters: getUserRewardInfo.Parameters,
|
|
): Promise<getUserRewardInfo.ReturnValue> {
|
|
return readContract(client, {
|
|
...parameters,
|
|
...getUserRewardInfo.call(parameters),
|
|
})
|
|
}
|
|
|
|
export namespace getUserRewardInfo {
|
|
export type Parameters = ReadParameters & Args
|
|
|
|
export type Args = {
|
|
/** The account address to query reward info for */
|
|
account: Address
|
|
/** The TIP20 token address */
|
|
token: Address
|
|
}
|
|
|
|
export type ReturnValue = ReadContractReturnType<
|
|
typeof Abis.tip20,
|
|
'userRewardInfo',
|
|
never
|
|
>
|
|
|
|
/**
|
|
* Defines a call to the `userRewardInfo` function.
|
|
*
|
|
* @param args - Arguments.
|
|
* @returns The call.
|
|
*/
|
|
export function call(args: Args) {
|
|
const { account, token } = args
|
|
return defineCall({
|
|
address: token,
|
|
abi: Abis.tip20,
|
|
args: [account],
|
|
functionName: 'userRewardInfo',
|
|
})
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Sets or changes the reward recipient for a token holder.
|
|
*
|
|
* This function allows a token holder to designate who should receive their share of rewards:
|
|
* - If `recipient` is the zero address, opts out from rewards distribution.
|
|
* - Otherwise, opts in and sets `recipient` as the address that will receive accrued rewards.
|
|
* - Can be called with `recipient == msg.sender` to receive rewards directly.
|
|
* - Automatically distributes any accrued rewards to the current recipient before changing.
|
|
*
|
|
* TIP-403 Policy:
|
|
* - Reverts with `PolicyForbids` if `recipient` is not the zero address and either the holder or recipient is not authorized to receive tokens under the token's transfer 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.reward.setRecipient(client, {
|
|
* recipient: '0xa5cc3c03994DB5b0d9A5eEdD10CabaB0813678AC',
|
|
* token: '0x20c0000000000000000000000000000000000001',
|
|
* })
|
|
* ```
|
|
*
|
|
* @param client - Client.
|
|
* @param parameters - Parameters.
|
|
* @returns The transaction hash.
|
|
*/
|
|
export async function setRecipient<
|
|
chain extends Chain | undefined,
|
|
account extends Account | undefined,
|
|
>(
|
|
client: Client<Transport, chain, account>,
|
|
parameters: setRecipient.Parameters<chain, account>,
|
|
): Promise<setRecipient.ReturnValue> {
|
|
return setRecipient.inner(writeContract, client, parameters)
|
|
}
|
|
|
|
/**
|
|
* Sets or changes the reward recipient for a token holder and waits for confirmation.
|
|
*
|
|
* This function allows a token holder to designate who should receive their share of rewards:
|
|
* - If `recipient` is the zero address, opts out from rewards distribution.
|
|
* - Otherwise, opts in and sets `recipient` as the address that will receive accrued rewards.
|
|
* - Can be called with `recipient == msg.sender` to receive rewards directly.
|
|
* - Automatically distributes any accrued rewards to the current recipient before changing.
|
|
*
|
|
* TIP-403 Policy:
|
|
* - Reverts with `PolicyForbids` if `recipient` is not the zero address and either the holder or recipient is not authorized to receive tokens under the token's transfer 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 { holder, recipient, receipt } = await Actions.reward.setRecipientSync(client, {
|
|
* recipient: '0xa5cc3c03994DB5b0d9A5eEdD10CabaB0813678AC',
|
|
* token: '0x20c0000000000000000000000000000000000001',
|
|
* })
|
|
* ```
|
|
*
|
|
* @param client - Client.
|
|
* @param parameters - Parameters.
|
|
* @returns The holder, recipient, and transaction receipt.
|
|
*/
|
|
export async function setRecipientSync<
|
|
chain extends Chain | undefined,
|
|
account extends Account | undefined,
|
|
>(
|
|
client: Client<Transport, chain, account>,
|
|
parameters: setRecipientSync.Parameters<chain, account>,
|
|
): Promise<setRecipientSync.ReturnValue> {
|
|
const { throwOnReceiptRevert = true, ...rest } = parameters
|
|
const receipt = await setRecipient.inner(writeContractSync, client, {
|
|
...rest,
|
|
throwOnReceiptRevert,
|
|
} as never)
|
|
const { args } = setRecipient.extractEvent(receipt.logs)
|
|
return {
|
|
...args,
|
|
receipt,
|
|
} as never
|
|
}
|
|
|
|
export namespace setRecipient {
|
|
export type Args = {
|
|
/** The reward recipient address (use zero address to opt out of rewards) */
|
|
recipient: Address
|
|
/** The TIP20 token address */
|
|
token: Address
|
|
}
|
|
|
|
export type Parameters<
|
|
chain extends Chain | undefined = Chain | undefined,
|
|
account extends Account | undefined = Account | undefined,
|
|
> = WriteParameters<chain, account> & Args
|
|
|
|
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 { recipient, token, ...rest } = parameters
|
|
const call = setRecipient.call({ recipient, token })
|
|
return (await action(client, {
|
|
...rest,
|
|
...call,
|
|
} as never)) as never
|
|
}
|
|
|
|
/**
|
|
* Defines a call to the `setRewardRecipient` function.
|
|
*
|
|
* Can be passed as a parameter to:
|
|
* - [`estimateContractGas`](https://viem.sh/docs/contract/estimateContractGas): estimate the gas cost of the call
|
|
* - [`simulateContract`](https://viem.sh/docs/contract/simulateContract): simulate the call
|
|
* - [`sendCalls`](https://viem.sh/docs/actions/wallet/sendCalls): send multiple calls
|
|
*
|
|
* @example
|
|
* ```ts
|
|
* import { createClient, http, walletActions } from 'viem'
|
|
* import { tempo } from 'viem/chains'
|
|
* import { Actions } from 'viem/tempo'
|
|
*
|
|
* const client = createClient({
|
|
* chain: tempo.extend({ feeToken: '0x20c0000000000000000000000000000000000001' })
|
|
* transport: http(),
|
|
* }).extend(walletActions)
|
|
*
|
|
* const hash = await client.sendTransaction({
|
|
* calls: [actions.reward.setRecipient.call({
|
|
* recipient: '0xa5cc3c03994DB5b0d9A5eEdD10CabaB0813678AC',
|
|
* token: '0x20c0000000000000000000000000000000000001',
|
|
* })],
|
|
* })
|
|
* ```
|
|
*
|
|
* @param args - Arguments.
|
|
* @returns The call.
|
|
*/
|
|
export function call(args: Args) {
|
|
const { recipient, token } = args
|
|
return defineCall({
|
|
address: token,
|
|
abi: Abis.tip20,
|
|
args: [recipient],
|
|
functionName: 'setRewardRecipient',
|
|
})
|
|
}
|
|
|
|
/**
|
|
* Extracts the `RewardRecipientSet` event from logs.
|
|
*
|
|
* @param logs - The logs.
|
|
* @returns The `RewardRecipientSet` event.
|
|
*/
|
|
export function extractEvent(logs: Log[]) {
|
|
const [log] = parseEventLogs({
|
|
abi: Abis.tip20,
|
|
logs,
|
|
eventName: 'RewardRecipientSet',
|
|
strict: true,
|
|
})
|
|
if (!log) throw new Error('`RewardRecipientSet` event not found.')
|
|
return log
|
|
}
|
|
}
|
|
|
|
export declare namespace setRecipientSync {
|
|
export type Parameters<
|
|
chain extends Chain | undefined = Chain | undefined,
|
|
account extends Account | undefined = Account | undefined,
|
|
> = WriteParameters<chain, account> & setRecipient.Args
|
|
|
|
export type ReturnValue = {
|
|
/** The token holder address who set their reward recipient */
|
|
holder: Address
|
|
/** The transaction receipt */
|
|
receipt: Awaited<ReturnType<typeof writeContractSync>>
|
|
/** The reward recipient address (zero address indicates opt-out) */
|
|
recipient: Address
|
|
}
|
|
|
|
export type ErrorType = setRecipient.ErrorType
|
|
}
|
|
|
|
/**
|
|
* Watches for reward distributed 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.reward.watchRewardDistributed(client, {
|
|
* token: '0x20c0000000000000000000000000000000000001',
|
|
* onRewardDistributed: (args, log) => {
|
|
* console.log('Reward distributed:', args)
|
|
* },
|
|
* })
|
|
* ```
|
|
*
|
|
* @param client - Client.
|
|
* @param parameters - Parameters.
|
|
* @returns A function to unsubscribe from the event.
|
|
*/
|
|
export function watchRewardDistributed<
|
|
chain extends Chain | undefined,
|
|
account extends Account | undefined,
|
|
>(
|
|
client: Client<Transport, chain, account>,
|
|
parameters: watchRewardDistributed.Parameters,
|
|
) {
|
|
const { onRewardDistributed, token, ...rest } = parameters
|
|
return watchContractEvent(client, {
|
|
...rest,
|
|
address: token,
|
|
abi: Abis.tip20,
|
|
eventName: 'RewardDistributed',
|
|
onLogs: (logs) => {
|
|
for (const log of logs) onRewardDistributed(log.args, log)
|
|
},
|
|
strict: true,
|
|
})
|
|
}
|
|
|
|
export declare namespace watchRewardDistributed {
|
|
export type Args = GetEventArgs<
|
|
typeof Abis.tip20,
|
|
'RewardDistributed',
|
|
{ IndexedOnly: false; Required: true }
|
|
>
|
|
|
|
export type Log = viem_Log<
|
|
bigint,
|
|
number,
|
|
false,
|
|
ExtractAbiItem<typeof Abis.tip20, 'RewardDistributed'>,
|
|
true
|
|
>
|
|
|
|
export type Parameters = UnionOmit<
|
|
WatchContractEventParameters<typeof Abis.tip20, 'RewardDistributed', true>,
|
|
'abi' | 'address' | 'batch' | 'eventName' | 'onLogs' | 'strict'
|
|
> & {
|
|
/** Callback to invoke when rewards are distributed. */
|
|
onRewardDistributed: (args: Args, log: Log) => void
|
|
/** The TIP20 token address */
|
|
token: Address
|
|
}
|
|
|
|
export type ReturnValue = WatchContractEventReturnType
|
|
}
|
|
|
|
/**
|
|
* Watches for reward recipient set 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.reward.watchRewardRecipientSet(client, {
|
|
* token: '0x20c0000000000000000000000000000000000001',
|
|
* onRewardRecipientSet: (args, log) => {
|
|
* console.log('Reward recipient set:', args)
|
|
* },
|
|
* })
|
|
* ```
|
|
*
|
|
* @param client - Client.
|
|
* @param parameters - Parameters.
|
|
* @returns A function to unsubscribe from the event.
|
|
*/
|
|
export function watchRewardRecipientSet<
|
|
chain extends Chain | undefined,
|
|
account extends Account | undefined,
|
|
>(
|
|
client: Client<Transport, chain, account>,
|
|
parameters: watchRewardRecipientSet.Parameters,
|
|
) {
|
|
const { onRewardRecipientSet, token, ...rest } = parameters
|
|
return watchContractEvent(client, {
|
|
...rest,
|
|
address: token,
|
|
abi: Abis.tip20,
|
|
eventName: 'RewardRecipientSet',
|
|
onLogs: (logs) => {
|
|
for (const log of logs) onRewardRecipientSet(log.args, log)
|
|
},
|
|
strict: true,
|
|
})
|
|
}
|
|
|
|
export declare namespace watchRewardRecipientSet {
|
|
export type Args = GetEventArgs<
|
|
typeof Abis.tip20,
|
|
'RewardRecipientSet',
|
|
{ IndexedOnly: false; Required: true }
|
|
>
|
|
|
|
export type Log = viem_Log<
|
|
bigint,
|
|
number,
|
|
false,
|
|
ExtractAbiItem<typeof Abis.tip20, 'RewardRecipientSet'>,
|
|
true
|
|
>
|
|
|
|
export type Parameters = UnionOmit<
|
|
WatchContractEventParameters<typeof Abis.tip20, 'RewardRecipientSet', true>,
|
|
'abi' | 'address' | 'batch' | 'eventName' | 'onLogs' | 'strict'
|
|
> & {
|
|
/** Callback to invoke when a reward recipient is set. */
|
|
onRewardRecipientSet: (args: Args, log: Log) => void
|
|
/** The TIP20 token address */
|
|
token: Address
|
|
}
|
|
|
|
export type ReturnValue = WatchContractEventReturnType
|
|
}
|