Skip to content

Commit

Permalink
Add multi tokens transfer logic
Browse files Browse the repository at this point in the history
  • Loading branch information
0xDmitry committed Jun 26, 2023
1 parent 6c5f91c commit c42d938
Show file tree
Hide file tree
Showing 5 changed files with 176 additions and 107 deletions.
34 changes: 31 additions & 3 deletions src/abis/AelinDeal_v1.json
Original file line number Diff line number Diff line change
Expand Up @@ -968,7 +968,7 @@
},
{
"inputs": [],
"name": "totalProtocolFee",
"name": "totalDealTokenAccepted",
"outputs": [
{
"internalType": "uint256",
Expand All @@ -981,7 +981,7 @@
},
{
"inputs": [],
"name": "totalUnderlyingAccepted",
"name": "totalProtocolFee",
"outputs": [
{
"internalType": "uint256",
Expand Down Expand Up @@ -1051,6 +1051,34 @@
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "_to",
"type": "address"
},
{
"internalType": "uint256[]",
"name": "_fullTransferTokenIds",
"type": "uint256[]"
},
{
"internalType": "uint256",
"name": "_partialTransferID",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "_partialShareAmount",
"type": "uint256"
}
],
"name": "transferManyVestTokens",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
Expand Down Expand Up @@ -1216,4 +1244,4 @@
"stateMutability": "nonpayable",
"type": "function"
}
]
]
49 changes: 29 additions & 20 deletions src/abis/AelinUpfrontDeal_v1.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,25 +36,6 @@
"name": "AcceptDeal",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "collection",
"type": "address"
},
{
"indexed": false,
"internalType": "uint256",
"name": "nftID",
"type": "uint256"
}
],
"name": "BlacklistNFT",
"type": "event"
},
{
"anonymous": false,
"inputs": [
Expand Down Expand Up @@ -1726,6 +1707,34 @@
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "_to",
"type": "address"
},
{
"internalType": "uint256[]",
"name": "_fullTransferTokenIds",
"type": "uint256[]"
},
{
"internalType": "uint256",
"name": "_partialTransferID",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "_partialShareAmount",
"type": "uint256"
}
],
"name": "transferManyVestTokens",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
Expand Down Expand Up @@ -1813,4 +1822,4 @@
"stateMutability": "nonpayable",
"type": "function"
}
]
]
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import {
TextfieldState,
} from '@/src/components/pureStyledComponents/form/Textfield'
import { Error } from '@/src/components/pureStyledComponents/text/Error'
import { BASE_DECIMALS, DISPLAY_DECIMALS } from '@/src/constants/misc'
import { BASE_DECIMALS, DISPLAY_DECIMALS, ZERO_BN } from '@/src/constants/misc'
import { formatToken } from '@/src/web3/bigNumber'

const Modal = styled(BaseModal)`
Expand Down Expand Up @@ -119,13 +119,23 @@ const CommonTransferVestingShareModal = ({
totalAmount,
underlyingDealTokenDecimals,
}: Props) => {
const [amount, setAmount] = useState('0')
const [amount, setAmount] = useState('')
const [toAddress, setToAddress] = useState('')

const amountError = useMemo(() => {
return BigNumber.from(amount === '' ? 0 : amount).gt(totalAmount)
? 'Not enough deal tokens held'
: ''
if (amount === '') {
return ''
}

if (BigNumber.from(amount).gt(totalAmount)) {
return 'Not enough deal tokens held'
}

if (BigNumber.from(amount).lte(ZERO_BN)) {
return 'Amount should be greater than zero'
}

return ''
}, [amount, totalAmount])

const addressError = useMemo(() => {
Expand Down
88 changes: 50 additions & 38 deletions src/components/pools/actions/Vest/TransferVestingShareModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { BigNumber } from 'alchemy-sdk'
import ms from 'ms'

import CommonTransferVestingShareModal from './CommonTransferVestingShareModal'
import { VestingToken } from '@/graphql-schema'
import { BASE_DECIMALS, ZERO_ADDRESS, ZERO_BN } from '@/src/constants/misc'
import useAelinPool from '@/src/hooks/aelin/useAelinPool'
import useGetVestingTokens from '@/src/hooks/aelin/useGetVestingTokens'
Expand Down Expand Up @@ -37,22 +38,13 @@ const TransferVestingShareModal = ({ onClose, poolAddress }: Props) => {
},
})

const tokenIds =
vestingTokensData?.vestingTokens.map((vestingToken: any) => Number(vestingToken.tokenId)) ?? []

const allSDK = getAllGqlSDK()
const { useVestingDealById } = allSDK[pool.chainId]

const { estimate: estimateTransferVestingShare, execute: executeTransferVestingShare } =
useAelinDealTransaction(
pool.dealAddress ?? ZERO_ADDRESS,
'transferVestingShare',
pool.isDealTokenTransferable as boolean,
)

const { estimate: estimateTransfer, execute: executeTransfer } = useAelinDealTransaction(
const method = 'transferManyVestTokens'
const { estimate, execute } = useAelinDealTransaction(
pool.dealAddress ?? ZERO_ADDRESS,
'transfer',
method,
pool.isDealTokenTransferable as boolean,
)

Expand Down Expand Up @@ -88,9 +80,6 @@ const TransferVestingShareModal = ({ onClose, poolAddress }: Props) => {
])

const handleTransfer = async (amount: string, toAddress: string) => {
const isPartialTransfer = BigNumber.from(investorDealTotal).gt(BigNumber.from(amount))
const method = isPartialTransfer ? 'transferVestingShare' : 'transfer'

if (!pool.deal) {
throw new Error('Deal not found.')
}
Expand All @@ -103,36 +92,59 @@ const TransferVestingShareModal = ({ onClose, poolAddress }: Props) => {
),
)

console.log('xxx onConfirm isPartialTransfer:', isPartialTransfer)
console.log('xxx onConfirm method:', method)
console.log('xxx onConfirm tokenIds:', tokenIds)
console.log('xxx onConfirm convertedAmount:', convertedAmount.toString())
console.log('xxx onConfirm toAddress:', toAddress)
const compare = (a: VestingToken, b: VestingToken) => {
if (BigNumber.from(a.amount).lt(BigNumber.from(b.amount))) {
return -1
}

if (BigNumber.from(a.amount).gt(BigNumber.from(b.amount))) {
return 1
}

return 0
}

const ascendingVestingTokens = (vestingTokensData?.vestingTokens ?? []).sort(compare)
const transferTokenIds: number[] = []
let partialTransferTokenId: number | null = null
let partialTransferAmount = convertedAmount

for (const vestingToken of ascendingVestingTokens) {
if (partialTransferAmount.gte(vestingToken.amount)) {
transferTokenIds.push(vestingToken.tokenId)
partialTransferAmount = partialTransferAmount.sub(vestingToken.amount)
continue
}

partialTransferTokenId = vestingToken.tokenId
break
}

setConfigAndOpenModal({
onConfirm: async (txGasOptions: GasOptions) => {
isPartialTransfer
? await executeTransferVestingShare(
[toAddress, 0, convertedAmount] as Parameters<
AelinDealCombined['functions'][typeof method]
>,
txGasOptions,
)
: await executeTransfer(
[toAddress, 0, '0x00'] as Parameters<AelinDealCombined['functions'][typeof method]>,
txGasOptions,
)
await execute(
[
toAddress,
transferTokenIds,
partialTransferTokenId ?? 0,
partialTransferTokenId && partialTransferAmount.gt(ZERO_BN)
? partialTransferAmount
: ZERO_BN,
] as Parameters<AelinDealCombined['functions'][typeof method]>,
txGasOptions,
)
await refetch()
},
title: `Transfer ${tokenToVestSymbol}`,
estimate: () =>
isPartialTransfer
? estimateTransferVestingShare([toAddress, 0, convertedAmount] as Parameters<
AelinDealCombined['functions'][typeof method]
>)
: estimateTransfer([toAddress, 0, '0x00'] as Parameters<
AelinDealCombined['functions'][typeof method]
>),
estimate([
toAddress,
transferTokenIds,
partialTransferTokenId ?? 0,
partialTransferTokenId && partialTransferAmount.gt(ZERO_BN)
? partialTransferAmount
: ZERO_BN,
] as Parameters<AelinDealCombined['functions'][typeof method]>),
})
}

Expand Down
Loading

0 comments on commit c42d938

Please sign in to comment.