@0xsplits/splits-sdk
Version:
SDK for the 0xSplits protocol
1,450 lines (1,173 loc) • 37.2 kB
text/typescript
import {
Address,
GetContractReturnType,
Hash,
Hex,
Log,
TypedDataDomain,
encodeEventTopics,
fromHex,
getContract,
zeroAddress,
} from 'viem'
import { warehouseAbi } from '../constants/abi/warehouse'
import {
BaseClientMixin,
BaseGasEstimatesMixin,
BaseTransactions,
} from './base'
import {
CallData,
ReadContractArgs,
SplitsClientConfig,
TransactionConfig,
TransactionFormat,
WarehouseApproveBySig,
WarehouseApproveBySigConfig,
WarehouseApproveConfig,
WarehouseBatchDepositConfig,
WarehouseBatchTransferConfig,
WarehouseBatchWithdrawConfig,
WarehouseDepositConfig,
WarehouseInvalidateNonceConfig,
WarehouseSetOperatorConfig,
WarehouseSetWithdrawConfig,
WarehouseTemporaryApproveAndCallBySig,
WarehouseTemporaryApproveAndCallBySigConfig,
WarehouseTemporaryApproveAndCallConfig,
WarehouseTransferConfig,
WarehouseTransferFromConfig,
WarehouseWithdrawConfig,
} from '../types'
import {
TransactionType,
SPLITS_V2_SUPPORTED_CHAIN_IDS,
getWarehouseAddress,
NATIVE_TOKEN_ADDRESS,
} from '../constants'
import { TransactionFailedError } from '../errors'
import { applyMixins } from './mixin'
import { getNumberFromPercent, validateAddress } from '../utils'
import { SplitsPublicClient } from '../types'
type WarehouseAbiType = typeof warehouseAbi
const nativeTokenAddress: Address = '0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE'
class WarehouseTransactions extends BaseTransactions {
protected readonly _warehouseAbi
constructor(transactionClientArgs: SplitsClientConfig & TransactionConfig) {
super({
supportedChainIds: SPLITS_V2_SUPPORTED_CHAIN_IDS,
...transactionClientArgs,
})
this._warehouseAbi = warehouseAbi
}
protected _getWarehouseContract(
chainId: number,
): GetContractReturnType<WarehouseAbiType, SplitsPublicClient> {
const publicClient = this._getPublicClient(chainId)
return getContract({
address: getWarehouseAddress(),
abi: warehouseAbi,
client: publicClient,
})
}
protected async _transfer({
receiverAddress: receiver,
tokenAddress: token,
amount,
transactionOverrides = {},
}: WarehouseTransferConfig): Promise<TransactionFormat> {
validateAddress(receiver)
validateAddress(token)
if (this._shouldRequireWalletClient) this._requireWalletClient()
const result = await this._executeContractFunction({
contractAddress: getWarehouseAddress(),
contractAbi: warehouseAbi,
functionName: 'transfer',
functionArgs: [receiver, fromHex(token, 'bigint'), amount],
transactionOverrides,
})
return result
}
protected async _transferFrom({
senderAddress: sender,
receiverAddress: receiver,
tokenAddress: token,
amount,
transactionOverrides = {},
}: WarehouseTransferFromConfig): Promise<TransactionFormat> {
validateAddress(sender)
validateAddress(receiver)
validateAddress(token)
if (this._shouldRequireWalletClient) this._requireWalletClient()
const result = await this._executeContractFunction({
contractAddress: getWarehouseAddress(),
contractAbi: warehouseAbi,
functionName: 'transferFrom',
functionArgs: [sender, receiver, fromHex(token, 'bigint'), amount],
transactionOverrides,
})
return result
}
protected async _approve({
spenderAddress: spender,
tokenAddress: token,
amount,
transactionOverrides = {},
}: WarehouseApproveConfig): Promise<TransactionFormat> {
validateAddress(spender)
validateAddress(token)
if (this._shouldRequireWalletClient) this._requireWalletClient()
const result = await this._executeContractFunction({
contractAddress: getWarehouseAddress(),
contractAbi: warehouseAbi,
functionName: 'approve',
functionArgs: [spender, fromHex(token, 'bigint'), amount],
transactionOverrides,
})
return result
}
protected async _setOperator({
operatorAddress: operator,
approved,
transactionOverrides = {},
}: WarehouseSetOperatorConfig): Promise<TransactionFormat> {
validateAddress(operator)
if (this._shouldRequireWalletClient) this._requireWalletClient()
const result = await this._executeContractFunction({
contractAddress: getWarehouseAddress(),
contractAbi: warehouseAbi,
functionName: 'setOperator',
functionArgs: [operator, approved],
transactionOverrides,
})
return result
}
protected async _invalidateNonce({
nonce,
transactionOverrides = {},
}: WarehouseInvalidateNonceConfig): Promise<TransactionFormat> {
if (this._shouldRequireWalletClient) this._requireWalletClient()
const result = await this._executeContractFunction({
contractAddress: getWarehouseAddress(),
contractAbi: warehouseAbi,
functionName: 'invalidateNonce',
functionArgs: [nonce],
transactionOverrides,
})
return result
}
protected async _temporaryApproveAndCall({
spenderAddress: spender,
operator: operator,
tokenAddress: token,
amount,
targetAddress: target,
data,
transactionOverrides = {},
}: WarehouseTemporaryApproveAndCallConfig): Promise<TransactionFormat> {
validateAddress(spender)
validateAddress(token)
validateAddress(target)
if (this._shouldRequireWalletClient) this._requireWalletClient()
const result = await this._executeContractFunction({
contractAddress: getWarehouseAddress(),
contractAbi: warehouseAbi,
functionName: 'temporaryApproveAndCall',
functionArgs: [
spender,
operator,
fromHex(token, 'bigint'),
amount,
target,
data,
],
transactionOverrides,
})
return result
}
protected async _temporaryApproveAndCallBySig({
ownerAddress: owner,
spenderAddress: spender,
operator,
tokenAddress: token,
amount,
targetAddress: target,
data,
nonce,
deadline,
signature,
transactionOverrides = {},
}: WarehouseTemporaryApproveAndCallBySigConfig): Promise<TransactionFormat> {
validateAddress(owner)
validateAddress(spender)
validateAddress(token)
validateAddress(target)
if (this._shouldRequireWalletClient) this._requireWalletClient()
const result = await this._executeContractFunction({
contractAddress: getWarehouseAddress(),
contractAbi: warehouseAbi,
functionName: 'temporaryApproveAndCallBySig',
functionArgs: [
owner,
spender,
operator,
fromHex(token, 'bigint'),
amount,
target,
data,
nonce,
deadline,
signature,
],
transactionOverrides,
})
return result
}
protected async _approveBySig({
ownerAddress: owner,
spenderAddress: spender,
operator,
tokenAddress: token,
amount,
nonce,
deadline,
signature,
transactionOverrides = {},
}: WarehouseApproveBySigConfig): Promise<TransactionFormat> {
validateAddress(owner)
validateAddress(spender)
validateAddress(token)
if (this._shouldRequireWalletClient) this._requireWalletClient()
const result = await this._executeContractFunction({
contractAddress: getWarehouseAddress(),
contractAbi: warehouseAbi,
functionName: 'approveBySig',
functionArgs: [
owner,
spender,
operator,
fromHex(token, 'bigint'),
amount,
nonce,
deadline,
signature,
],
transactionOverrides,
})
return result
}
protected async _deposit({
receiverAddress: receiver,
tokenAddress: token,
amount,
transactionOverrides = {},
}: WarehouseDepositConfig): Promise<TransactionFormat> {
validateAddress(receiver)
validateAddress(token)
if (this._shouldRequireWalletClient) this._requireWalletClient()
const result = await this._executeContractFunction({
contractAddress: getWarehouseAddress(),
contractAbi: warehouseAbi,
functionName: 'deposit',
functionArgs: [receiver, token, amount],
value: token === nativeTokenAddress ? amount : BigInt(0),
transactionOverrides,
})
return result
}
protected async _batchDeposit({
receiversAddresses: receivers,
tokenAddress: token,
amounts,
transactionOverrides = {},
}: WarehouseBatchDepositConfig): Promise<TransactionFormat> {
receivers.map((receiver) => validateAddress(receiver))
validateAddress(token)
if (this._shouldRequireWalletClient) this._requireWalletClient()
const result = await this._executeContractFunction({
contractAddress: getWarehouseAddress(),
contractAbi: warehouseAbi,
functionName: 'batchDeposit',
functionArgs: [receivers, token, amounts],
value: amounts.reduce((a, b) => a + b),
transactionOverrides,
})
return result
}
protected async _withdraw({
ownerAddress: owner,
tokenAddress: token,
transactionOverrides = {},
}: WarehouseWithdrawConfig): Promise<TransactionFormat> {
validateAddress(owner)
validateAddress(token)
if (this._shouldRequireWalletClient) this._requireWalletClient()
const result = await this._executeContractFunction({
contractAddress: getWarehouseAddress(),
contractAbi: warehouseAbi,
functionName: 'withdraw',
functionArgs: [
owner,
token === zeroAddress ? NATIVE_TOKEN_ADDRESS : token,
],
transactionOverrides,
})
return result
}
protected async _batchWithdraw({
ownerAddress: owner,
tokensAddresses: tokens,
amounts,
withdrawerAddress: withdrawer,
transactionOverrides = {},
}: WarehouseBatchWithdrawConfig): Promise<TransactionFormat> {
validateAddress(owner)
tokens.map((token) => validateAddress(token))
validateAddress(withdrawer)
if (this._shouldRequireWalletClient) this._requireWalletClient()
const result = await this._executeContractFunction({
contractAddress: getWarehouseAddress(),
contractAbi: warehouseAbi,
functionName: 'withdraw',
functionArgs: [owner, tokens, amounts, withdrawer],
transactionOverrides,
})
return result
}
protected async _batchTransfer({
receiversAddresses: receivers,
tokenAddress: token,
amounts,
transactionOverrides = {},
}: WarehouseBatchTransferConfig): Promise<TransactionFormat> {
receivers.map((receiver) => validateAddress(receiver))
validateAddress(token)
if (this._shouldRequireWalletClient) this._requireWalletClient()
const result = await this._executeContractFunction({
contractAddress: getWarehouseAddress(),
contractAbi: warehouseAbi,
functionName: 'batchTransfer',
functionArgs: [receivers, token, amounts],
transactionOverrides,
})
return result
}
protected async _setWithdrawConfig({
incentivePercent: incentive,
paused,
transactionOverrides = {},
}: WarehouseSetWithdrawConfig): Promise<TransactionFormat> {
if (this._shouldRequireWalletClient) this._requireWalletClient()
const result = await this._executeContractFunction({
contractAddress: getWarehouseAddress(),
contractAbi: warehouseAbi,
functionName: 'setWithdrawConfig',
functionArgs: [{ incentive: getNumberFromPercent(incentive), paused }],
transactionOverrides,
})
return result
}
protected async _eip712Domain(
chainId: number,
): Promise<{ domain: TypedDataDomain }> {
const eip712Domain =
await this._getWarehouseContract(chainId).read.eip712Domain()
return {
domain: {
chainId: Number(eip712Domain[3].toString()),
name: eip712Domain[1],
version: eip712Domain[2],
verifyingContract: eip712Domain[4],
salt: eip712Domain[5],
},
}
}
}
// eslint-disable-next-line @typescript-eslint/no-unsafe-declaration-merging
export class WarehouseClient extends WarehouseTransactions {
readonly eventTopics: { [key: string]: Hex[] }
readonly callData: WarehouseCallData
readonly estimateGas: WarehouseGasEstimates
readonly sign: WarehouseSignature
constructor(clientArgs: SplitsClientConfig) {
super({
transactionType: TransactionType.Transaction,
...clientArgs,
})
this.eventTopics = {
transfer: [
encodeEventTopics({
abi: warehouseAbi,
eventName: 'Transfer',
})[0],
],
withdraw: [
encodeEventTopics({
abi: warehouseAbi,
eventName: 'Withdraw',
})[0],
],
operatorSet: [
encodeEventTopics({
abi: warehouseAbi,
eventName: 'OperatorSet',
})[0],
],
approval: [
encodeEventTopics({
abi: warehouseAbi,
eventName: 'Approval',
})[0],
],
nonceInvalidation: [
encodeEventTopics({
abi: warehouseAbi,
eventName: 'NonceInvalidation',
})[0],
],
withdrawConfigUpdated: [
encodeEventTopics({
abi: warehouseAbi,
eventName: 'WithdrawConfigUpdated',
})[0],
],
}
this.callData = new WarehouseCallData(clientArgs)
this.estimateGas = new WarehouseGasEstimates(clientArgs)
this.sign = new WarehouseSignature(clientArgs)
}
// ERC6909 Metadata
async getName({
tokenAddress,
chainId,
}: ReadContractArgs & { tokenAddress: Address }): Promise<{
name: string
}> {
validateAddress(tokenAddress)
const functionChainId = this._getReadOnlyFunctionChainId(chainId)
const name = await this._getWarehouseContract(functionChainId).read.name([
fromHex(tokenAddress, 'bigint'),
])
return {
name,
}
}
async getSymbol({
tokenAddress,
chainId,
}: ReadContractArgs & { tokenAddress: Address }): Promise<{
symbol: string
}> {
validateAddress(tokenAddress)
const functionChainId = this._getReadOnlyFunctionChainId(chainId)
const symbol = await this._getWarehouseContract(
functionChainId,
).read.symbol([fromHex(tokenAddress, 'bigint')])
return {
symbol,
}
}
async getDecimals({
tokenAddress,
chainId,
}: ReadContractArgs & { tokenAddress: Address }): Promise<{
decimals: number
}> {
validateAddress(tokenAddress)
const functionChainId = this._getReadOnlyFunctionChainId(chainId)
const decimals = await this._getWarehouseContract(
functionChainId,
).read.decimals([fromHex(tokenAddress, 'bigint')])
return {
decimals,
}
}
// Warehouse withdraw config
async getWithdrawConfig({
userAddress,
chainId,
}: ReadContractArgs & {
userAddress: Address
}): Promise<{ withdrawConfig: { incentive: number; paused: boolean } }> {
validateAddress(userAddress)
const functionChainId = this._getReadOnlyFunctionChainId(chainId)
const config = await this._getWarehouseContract(
functionChainId,
).read.withdrawConfig([userAddress])
return {
withdrawConfig: {
incentive: config[0],
paused: config[1],
},
}
}
// ERC6909X nonce
async isValidNonce({
userAddress,
userNonce,
chainId,
}: ReadContractArgs & {
userAddress: Address
userNonce: bigint
}): Promise<{ isValidNonce: boolean }> {
validateAddress(userAddress)
const functionChainId = this._getReadOnlyFunctionChainId(chainId)
const isValidNonce = await this._getWarehouseContract(
functionChainId,
).read.isValidNonce([userAddress, userNonce])
return {
isValidNonce,
}
}
async eip712Domain(
args?: ReadContractArgs,
): Promise<{ domain: TypedDataDomain }> {
const chainId = args?.chainId
const functionChainId = this._getReadOnlyFunctionChainId(chainId)
return this._eip712Domain(functionChainId)
}
// ERC6909 read
async isOperator({
ownerAddress,
operatorAddress,
chainId,
}: ReadContractArgs & {
ownerAddress: Address
operatorAddress: Address
}): Promise<{ isOperator: boolean }> {
validateAddress(ownerAddress)
validateAddress(operatorAddress)
const functionChainId = this._getReadOnlyFunctionChainId(chainId)
const isOperator = await this._getWarehouseContract(
functionChainId,
).read.isOperator([ownerAddress, operatorAddress])
return {
isOperator,
}
}
async balanceOf({
ownerAddress,
tokenAddress,
chainId,
}: ReadContractArgs & {
ownerAddress: Address
tokenAddress: Address
}): Promise<{ balance: bigint }> {
validateAddress(ownerAddress)
validateAddress(tokenAddress)
const functionChainId = this._getReadOnlyFunctionChainId(chainId)
const balance = await this._getWarehouseContract(
functionChainId,
).read.balanceOf([ownerAddress, fromHex(tokenAddress, 'bigint')])
return {
balance,
}
}
async allowance({
ownerAddress,
spenderAddress,
tokenAddress,
chainId,
}: ReadContractArgs & {
ownerAddress: Address
spenderAddress: Address
tokenAddress: Address
}): Promise<{ allowance: bigint }> {
validateAddress(ownerAddress)
validateAddress(spenderAddress)
validateAddress(tokenAddress)
const functionChainId = this._getReadOnlyFunctionChainId(chainId)
const allowance = await this._getWarehouseContract(
functionChainId,
).read.allowance([
ownerAddress,
spenderAddress,
fromHex(tokenAddress, 'bigint'),
])
return {
allowance,
}
}
// erc6909 write
async transfer(
transferArgs: WarehouseTransferConfig,
): Promise<{ event: Log }> {
const txHash = await this._transfer(transferArgs)
if (!this._isContractTransaction(txHash))
throw new Error('Invalid response')
const events = await this.getTransactionEvents({
txHash,
eventTopics: this.eventTopics.transfer,
})
const event = events.length > 0 ? events[0] : undefined
if (event) {
return {
event,
}
}
throw new TransactionFailedError()
}
async transferFrom(
transferFromArgs: WarehouseTransferFromConfig,
): Promise<{ event: Log }> {
const txHash = await this._transferFrom(transferFromArgs)
if (!this._isContractTransaction(txHash))
throw new Error('Invalid response')
const events = await this.getTransactionEvents({
txHash,
eventTopics: this.eventTopics.transfer,
})
const event = events.length > 0 ? events[0] : undefined
if (event) {
return {
event,
}
}
throw new TransactionFailedError()
}
async approve(approveArgs: WarehouseApproveConfig): Promise<{ event: Log }> {
const txHash = await this._approve(approveArgs)
if (!this._isContractTransaction(txHash))
throw new Error('Invalid response')
const events = await this.getTransactionEvents({
txHash,
eventTopics: this.eventTopics.approval,
})
const event = events.length > 0 ? events[0] : undefined
if (event) {
return {
event,
}
}
throw new TransactionFailedError()
}
async setOperator(
setOperatorArgs: WarehouseSetOperatorConfig,
): Promise<{ event: Log }> {
const txHash = await this._setOperator(setOperatorArgs)
if (!this._isContractTransaction(txHash))
throw new Error('Invalid response')
const events = await this.getTransactionEvents({
txHash,
eventTopics: this.eventTopics.operatorSet,
})
const event = events.length > 0 ? events[0] : undefined
if (event) {
return {
event,
}
}
throw new TransactionFailedError()
}
async invalidateNonce(
invalidateNonceArgs: WarehouseInvalidateNonceConfig,
): Promise<{ event: Log }> {
const txHash = await this._invalidateNonce(invalidateNonceArgs)
if (!this._isContractTransaction(txHash))
throw new Error('Invalid response')
const events = await this.getTransactionEvents({
txHash,
eventTopics: this.eventTopics.nonceInvalidation,
})
const event = events.length > 0 ? events[0] : undefined
if (event) {
return {
event,
}
}
throw new TransactionFailedError()
}
async temporaryApproveAndCall(
temporaryApproveAndCallArgs: WarehouseTemporaryApproveAndCallConfig,
): Promise<{ txHash: Hex }> {
const txHash = await this._temporaryApproveAndCall(
temporaryApproveAndCallArgs,
)
if (!this._isContractTransaction(txHash))
throw new Error('Invalid response')
return { txHash }
}
async temporaryApproveAndCallBySig(
temporaryApproveAndCallBySigArgs: WarehouseTemporaryApproveAndCallBySigConfig,
): Promise<{ txHash: Hex }> {
const txHash = await this._temporaryApproveAndCallBySig(
temporaryApproveAndCallBySigArgs,
)
if (!this._isContractTransaction(txHash))
throw new Error('Invalid response')
return { txHash }
}
async approveBySig(
approveBySigArgs: WarehouseApproveBySigConfig,
): Promise<{ event: Log }> {
const txHash = await this._approveBySig(approveBySigArgs)
if (!this._isContractTransaction(txHash))
throw new Error('Invalid response')
let eventTopics: Hex[] = []
if (approveBySigArgs.operator) {
eventTopics = this.eventTopics.operatorSet
} else {
eventTopics = this.eventTopics.approval
}
const events = await this.getTransactionEvents({
txHash,
eventTopics,
})
const event = events.length > 0 ? events[0] : undefined
if (event) {
return {
event,
}
}
throw new TransactionFailedError()
}
async deposit(depositArgs: WarehouseDepositConfig): Promise<{ event: Log }> {
const txHash = await this._deposit(depositArgs)
if (!this._isContractTransaction(txHash))
throw new Error('Invalid response')
const events = await this.getTransactionEvents({
txHash,
eventTopics: this.eventTopics.transfer,
})
const event = events.length > 0 ? events[0] : undefined
if (event) {
return {
event,
}
}
throw new TransactionFailedError()
}
async batchDeposit(
batchDepositArgs: WarehouseBatchDepositConfig,
): Promise<{ events: Log[] }> {
const txHash = await this._batchDeposit(batchDepositArgs)
if (!this._isContractTransaction(txHash))
throw new Error('Invalid response')
const events = await this.getTransactionEvents({
txHash,
eventTopics: this.eventTopics.transfer,
})
if (events.length > 0) {
return {
events,
}
}
throw new TransactionFailedError()
}
async _submitWithdrawTransaction(
withdrawArgs: WarehouseWithdrawConfig,
): Promise<{
txHash: Hash
}> {
const txHash = await this._withdraw(withdrawArgs)
if (!this._isContractTransaction(txHash))
throw new Error('Invalid response')
return { txHash }
}
async withdraw(
withdrawArgs: WarehouseWithdrawConfig,
): Promise<{ event: Log }> {
const { txHash } = await this._submitWithdrawTransaction(withdrawArgs)
const events = await this.getTransactionEvents({
txHash,
eventTopics: this.eventTopics.withdraw,
})
const event = events.length > 0 ? events[0] : undefined
if (event) {
return {
event,
}
}
throw new TransactionFailedError()
}
async _submitBatchWithdrawTransaction(
batchWithdrawArgs: WarehouseBatchWithdrawConfig,
): Promise<{
txHash: Hash
}> {
const txHash = await this._batchWithdraw(batchWithdrawArgs)
if (!this._isContractTransaction(txHash))
throw new Error('Invalid response')
return { txHash }
}
async batchWithdraw(
batchWithdrawArgs: WarehouseBatchWithdrawConfig,
): Promise<{ events: Log[] }> {
const { txHash } =
await this._submitBatchWithdrawTransaction(batchWithdrawArgs)
const events = await this.getTransactionEvents({
txHash,
eventTopics: this.eventTopics.withdraw,
})
if (events.length > 0) {
return {
events,
}
}
throw new TransactionFailedError()
}
async batchTransfer(
batchTransferArgs: WarehouseBatchTransferConfig,
): Promise<{ events: Log[] }> {
const txHash = await this._batchTransfer(batchTransferArgs)
if (!this._isContractTransaction(txHash))
throw new Error('Invalid response')
const events = await this.getTransactionEvents({
txHash,
eventTopics: this.eventTopics.transfer,
})
if (events.length > 0) {
return {
events,
}
}
throw new TransactionFailedError()
}
async setWithdrawConfig(
setConfigArgs: WarehouseSetWithdrawConfig,
): Promise<{ event: Log }> {
const txHash = await this._setWithdrawConfig(setConfigArgs)
if (!this._isContractTransaction(txHash))
throw new Error('Invalid response')
const events = await this.getTransactionEvents({
txHash,
eventTopics: this.eventTopics.withdrawConfigUpdated,
})
const event = events.length > 0 ? events[0] : undefined
if (event) {
return {
event,
}
}
throw new TransactionFailedError()
}
}
// eslint-disable-next-line @typescript-eslint/no-unsafe-declaration-merging
export interface WarehouseClient extends BaseClientMixin {}
applyMixins(WarehouseClient, [BaseClientMixin])
// eslint-disable-next-line @typescript-eslint/no-unsafe-declaration-merging
class WarehouseGasEstimates extends WarehouseTransactions {
constructor(clientArgs: SplitsClientConfig) {
super({
transactionType: TransactionType.GasEstimate,
...clientArgs,
})
}
async transfer(transferArgs: WarehouseTransferConfig): Promise<bigint> {
const gasEstimate = await this._transfer(transferArgs)
if (!this._isBigInt(gasEstimate)) throw new Error('Invalid response')
return gasEstimate
}
async transferFrom(
transferFromArgs: WarehouseTransferFromConfig,
): Promise<bigint> {
const gasEstimate = await this._transferFrom(transferFromArgs)
if (!this._isBigInt(gasEstimate)) throw new Error('Invalid response')
return gasEstimate
}
async approve(approveArgs: WarehouseApproveConfig): Promise<bigint> {
const gasEstimate = await this._approve(approveArgs)
if (!this._isBigInt(gasEstimate)) throw new Error('Invalid response')
return gasEstimate
}
async setOperator(
setOperatorArgs: WarehouseSetOperatorConfig,
): Promise<bigint> {
const gasEstimate = await this._setOperator(setOperatorArgs)
if (!this._isBigInt(gasEstimate)) throw new Error('Invalid response')
return gasEstimate
}
async invalidateNonce(
invalidateNonceArgs: WarehouseInvalidateNonceConfig,
): Promise<bigint> {
const gasEstimate = await this._invalidateNonce(invalidateNonceArgs)
if (!this._isBigInt(gasEstimate)) throw new Error('Invalid response')
return gasEstimate
}
async temporaryApproveAndCall(
temporaryApproveAndCallArgs: WarehouseTemporaryApproveAndCallConfig,
): Promise<bigint> {
const gasEstimate = await this._temporaryApproveAndCall(
temporaryApproveAndCallArgs,
)
if (!this._isBigInt(gasEstimate)) throw new Error('Invalid response')
return gasEstimate
}
async temporaryApproveAndCallBySig(
temporaryApproveAndCallBySigArgs: WarehouseTemporaryApproveAndCallBySigConfig,
): Promise<bigint> {
const gasEstimate = await this._temporaryApproveAndCallBySig(
temporaryApproveAndCallBySigArgs,
)
if (!this._isBigInt(gasEstimate)) throw new Error('Invalid response')
return gasEstimate
}
async approveBySig(
approveBySigArgs: WarehouseApproveBySigConfig,
): Promise<bigint> {
const gasEstimate = await this._approveBySig(approveBySigArgs)
if (!this._isBigInt(gasEstimate)) throw new Error('Invalid response')
return gasEstimate
}
async deposit(depositArgs: WarehouseDepositConfig): Promise<bigint> {
const gasEstimate = await this._deposit(depositArgs)
if (!this._isBigInt(gasEstimate)) throw new Error('Invalid response')
return gasEstimate
}
async batchDeposit(
batchDepositArgs: WarehouseBatchDepositConfig,
): Promise<bigint> {
const gasEstimate = await this._batchDeposit(batchDepositArgs)
if (!this._isBigInt(gasEstimate)) throw new Error('Invalid response')
return gasEstimate
}
async withdraw(withdrawArgs: WarehouseWithdrawConfig): Promise<bigint> {
const gasEstimate = await this._withdraw(withdrawArgs)
if (!this._isBigInt(gasEstimate)) throw new Error('Invalid response')
return gasEstimate
}
async batchWithdraw(
batchWithdrawArgs: WarehouseBatchWithdrawConfig,
): Promise<bigint> {
const gasEstimate = await this._batchWithdraw(batchWithdrawArgs)
if (!this._isBigInt(gasEstimate)) throw new Error('Invalid response')
return gasEstimate
}
async batchTransfer(
batchTransferArgs: WarehouseBatchTransferConfig,
): Promise<bigint> {
const gasEstimate = await this._batchTransfer(batchTransferArgs)
if (!this._isBigInt(gasEstimate)) throw new Error('Invalid response')
return gasEstimate
}
async setWithdrawConfig(
setConfigArgs: WarehouseSetWithdrawConfig,
): Promise<bigint> {
const gasEstimate = await this._setWithdrawConfig(setConfigArgs)
if (!this._isBigInt(gasEstimate)) throw new Error('Invalid response')
return gasEstimate
}
}
// eslint-disable-next-line @typescript-eslint/no-unsafe-declaration-merging
interface WarehouseGasEstimates extends BaseGasEstimatesMixin {}
applyMixins(WarehouseGasEstimates, [BaseGasEstimatesMixin])
class WarehouseCallData extends WarehouseTransactions {
constructor(clientArgs: SplitsClientConfig) {
super({
transactionType: TransactionType.CallData,
...clientArgs,
})
}
async transfer(transferArgs: WarehouseTransferConfig): Promise<CallData> {
const callData = await this._transfer(transferArgs)
if (!this._isCallData(callData)) throw new Error('Invalid response')
return callData
}
async transferFrom(
transferFromArgs: WarehouseTransferFromConfig,
): Promise<CallData> {
const callData = await this._transferFrom(transferFromArgs)
if (!this._isCallData(callData)) throw new Error('Invalid response')
return callData
}
async approve(approveArgs: WarehouseApproveConfig): Promise<CallData> {
const callData = await this._approve(approveArgs)
if (!this._isCallData(callData)) throw new Error('Invalid response')
return callData
}
async setOperator(
setOperatorArgs: WarehouseSetOperatorConfig,
): Promise<CallData> {
const callData = await this._setOperator(setOperatorArgs)
if (!this._isCallData(callData)) throw new Error('Invalid response')
return callData
}
async invalidateNonce(
invalidateNonceArgs: WarehouseInvalidateNonceConfig,
): Promise<CallData> {
const callData = await this._invalidateNonce(invalidateNonceArgs)
if (!this._isCallData(callData)) throw new Error('Invalid response')
return callData
}
async temporaryApproveAndCall(
temporaryApproveAndCallArgs: WarehouseTemporaryApproveAndCallConfig,
): Promise<CallData> {
const callData = await this._temporaryApproveAndCall(
temporaryApproveAndCallArgs,
)
if (!this._isCallData(callData)) throw new Error('Invalid response')
return callData
}
async temporaryApproveAndCallBySig(
temporaryApproveAndCallBySigArgs: WarehouseTemporaryApproveAndCallBySigConfig,
): Promise<CallData> {
const callData = await this._temporaryApproveAndCallBySig(
temporaryApproveAndCallBySigArgs,
)
if (!this._isCallData(callData)) throw new Error('Invalid response')
return callData
}
async approveBySig(
approveBySigArgs: WarehouseApproveBySigConfig,
): Promise<CallData> {
const callData = await this._approveBySig(approveBySigArgs)
if (!this._isCallData(callData)) throw new Error('Invalid response')
return callData
}
async deposit(depositArgs: WarehouseDepositConfig): Promise<CallData> {
const callData = await this._deposit(depositArgs)
if (!this._isCallData(callData)) throw new Error('Invalid response')
return callData
}
async batchDeposit(
batchDepositArgs: WarehouseBatchDepositConfig,
): Promise<CallData> {
const callData = await this._batchDeposit(batchDepositArgs)
if (!this._isCallData(callData)) throw new Error('Invalid response')
return callData
}
async withdraw(withdrawArgs: WarehouseWithdrawConfig): Promise<CallData> {
const callData = await this._withdraw(withdrawArgs)
if (!this._isCallData(callData)) throw new Error('Invalid response')
return callData
}
async batchWithdraw(
withdrawArgs: WarehouseWithdrawConfig,
): Promise<CallData> {
const callData = await this._withdraw(withdrawArgs)
if (!this._isCallData(callData)) throw new Error('Invalid response')
return callData
}
async batchTransfer(
batchTransferArgs: WarehouseBatchTransferConfig,
): Promise<CallData> {
const callData = await this._batchTransfer(batchTransferArgs)
if (!this._isCallData(callData)) throw new Error('Invalid response')
return callData
}
async setWithdrawConfig(
setConfigArgs: WarehouseSetWithdrawConfig,
): Promise<CallData> {
const callData = await this._setWithdrawConfig(setConfigArgs)
if (!this._isCallData(callData)) throw new Error('Invalid response')
return callData
}
}
class WarehouseSignature extends WarehouseTransactions {
constructor(clientArgs: SplitsClientConfig) {
super({
transactionType: TransactionType.Signature,
...clientArgs,
})
}
async approveBySig(
approveBySigArgs: WarehouseApproveBySig,
): Promise<WarehouseApproveBySigConfig> {
validateAddress(approveBySigArgs.spenderAddress)
validateAddress(approveBySigArgs.tokenAddress)
this._requireWalletClient()
const { domain } = await this._eip712Domain(this._walletClient!.chain!.id)
this._requireWalletClient()
const signature = await this._walletClient!.signTypedData({
account: this._walletClient!.account!,
domain,
types: SigTypes,
primaryType: 'ERC6909XApproveAndCall',
message: {
owner: this._walletClient!.account!.address,
spender: approveBySigArgs.spenderAddress,
temporary: false,
operator: approveBySigArgs.operator,
id: fromHex(approveBySigArgs.tokenAddress, 'bigint'),
amount: approveBySigArgs.amount,
target: zeroAddress,
data: '' as Hex,
nonce: approveBySigArgs.nonce,
deadline: approveBySigArgs.deadline,
},
})
if (!signature) throw new Error('Error in signing data')
return {
ownerAddress: this._walletClient!.account!.address as Address,
signature,
...approveBySigArgs,
}
}
async temporaryApproveAndCallBySig(
temporaryApproveAndCallBySigArgs: WarehouseTemporaryApproveAndCallBySig,
): Promise<WarehouseApproveBySigConfig> {
validateAddress(temporaryApproveAndCallBySigArgs.spenderAddress)
validateAddress(temporaryApproveAndCallBySigArgs.tokenAddress)
validateAddress(temporaryApproveAndCallBySigArgs.targetAddress)
this._requireWalletClient()
const { domain } = await this._eip712Domain(this._walletClient!.chain!.id)
const signature = await this._walletClient!.signTypedData({
account: this._walletClient!.account!,
domain,
types: SigTypes,
primaryType: 'ERC6909XApproveAndCall',
message: {
owner: this._walletClient!.account!.address,
spender: temporaryApproveAndCallBySigArgs.spenderAddress,
temporary: true,
operator: temporaryApproveAndCallBySigArgs.operator,
id: fromHex(temporaryApproveAndCallBySigArgs.tokenAddress, 'bigint'),
amount: temporaryApproveAndCallBySigArgs.amount,
target: temporaryApproveAndCallBySigArgs.targetAddress,
data: temporaryApproveAndCallBySigArgs.data,
nonce: temporaryApproveAndCallBySigArgs.nonce,
deadline: temporaryApproveAndCallBySigArgs.deadline,
},
})
if (!signature) throw new Error('Error in signing data')
return {
ownerAddress: this._walletClient!.account!.address as Address,
signature,
...temporaryApproveAndCallBySigArgs,
}
}
}
const SigTypes = {
ERC6909XApproveAndCall: [
{
name: 'temporary',
type: 'bool',
},
{
name: 'owner',
type: 'address',
},
{
name: 'spender',
type: 'address',
},
{
name: 'operator',
type: 'bool',
},
{
name: 'id',
type: 'uint256',
},
{
name: 'amount',
type: 'uint256',
},
{
name: 'target',
type: 'address',
},
{
name: 'data',
type: 'bytes',
},
{
name: 'nonce',
type: 'uint256',
},
{
name: 'deadline',
type: 'uint48',
},
],
} as const