@lifi/sdk
Version:
LI.FI Any-to-Any Cross-Chain-Swap SDK
139 lines (127 loc) • 3.9 kB
text/typescript
import type { Address, Client, Hash, SendTransactionParameters } from 'viem'
import { encodeFunctionData } from 'viem'
import { sendTransaction } from 'viem/actions'
import { getAction } from 'viem/utils'
import { isZeroAddress } from '../../utils/isZeroAddress.js'
import type { ExecutionOptions, TransactionParameters } from '../types.js'
import { approveAbi } from './abi.js'
import { getAllowance } from './getAllowance.js'
import type { ApproveTokenRequest, RevokeApprovalRequest } from './types.js'
import { getMaxPriorityFeePerGas } from './utils.js'
export const setAllowance = async (
client: Client,
tokenAddress: Address,
contractAddress: Address,
amount: bigint,
executionOptions?: ExecutionOptions,
returnPopulatedTransaction?: boolean
): Promise<Hash> => {
const data = encodeFunctionData({
abi: approveAbi,
functionName: 'approve',
args: [contractAddress, amount],
})
if (returnPopulatedTransaction) {
return data
}
let transactionRequest: TransactionParameters = {
to: tokenAddress,
data,
maxPriorityFeePerGas:
client.account?.type === 'local'
? await getMaxPriorityFeePerGas(client)
: undefined,
}
if (executionOptions?.updateTransactionRequestHook) {
const customizedTransactionRequest: TransactionParameters =
await executionOptions.updateTransactionRequestHook({
requestType: 'approve',
...transactionRequest,
})
transactionRequest = {
...transactionRequest,
...customizedTransactionRequest,
}
}
return getAction(
client,
sendTransaction,
'sendTransaction'
)({
to: transactionRequest.to,
account: client.account!,
data: transactionRequest.data,
gas: transactionRequest.gas,
gasPrice: transactionRequest.gasPrice,
maxFeePerGas: transactionRequest.maxFeePerGas,
maxPriorityFeePerGas: transactionRequest.maxPriorityFeePerGas,
} as SendTransactionParameters)
}
/**
* Set approval for a certain token and amount.
* @param request - The approval request
* @param request.walletClient - The Viem wallet client used to send the transaction
* @param request.token - The token for which to set the allowance
* @param request.spenderAddress - The address of the spender
* @param request.amount - The amount of tokens to approve
* @returns Returns Hash or nothing
*/
export const setTokenAllowance = async ({
walletClient,
token,
spenderAddress,
amount,
}: ApproveTokenRequest): Promise<Hash | void> => {
// native token don't need approval
if (isZeroAddress(token.address)) {
return
}
const approvedAmount = await getAllowance(
walletClient,
token.address as Address,
walletClient.account!.address,
spenderAddress as Address
)
if (amount > approvedAmount) {
const approveTx = await setAllowance(
walletClient,
token.address as Address,
spenderAddress as Address,
amount
)
return approveTx
}
}
/**
* Revoke approval for a certain token.
* @param request - The revoke request
* @param request.walletClient - The Viem wallet client used to send the transaction
* @param request.token - The token for which to revoke the allowance
* @param request.spenderAddress - The address of the spender
* @returns Returns Hash or nothing
*/
export const revokeTokenApproval = async ({
walletClient,
token,
spenderAddress,
}: RevokeApprovalRequest): Promise<Hash | void> => {
// native token don't need approval
if (isZeroAddress(token.address)) {
return
}
const approvedAmount = await getAllowance(
walletClient,
token.address as Address,
walletClient.account!.address,
spenderAddress as Address
)
if (approvedAmount > 0) {
const approveTx = await setAllowance(
walletClient,
token.address as Address,
spenderAddress as Address,
0n
)
return approveTx
}
}