import { BigNumberish, providers } from 'ethers'; import BaseService from '../commons/BaseService'; import { eEthereumTxType, EthereumTransactionTypeExtended, ProtocolAction, tEthereumAddress, transactionType, } from '../commons/types'; import { WPunkValidator } from '../commons/validators/methodValidators'; import { is0OrPositiveAmount, isEthAddress, isValidTokenIdArray, } from '../commons/validators/paramValidators'; import { CrytoPunkInterface, CrytoPunkService } from '../crypto-punk'; import { ERC721Service, IERC721ServiceInterface } from '../erc721-contract'; import { IWPunkGateway } from './typechain/IWPunkGateway'; import { IWPunkGateway__factory as IWPunkGatewayFactory } from './typechain/IWPunkGateway__factory'; export type WPunkSupplyParamsType = { user: tEthereumAddress; token_ids: number[]; onBehalfOf?: tEthereumAddress; referralCode?: string; }; export type WPunkWithdrawParamsType = { user: tEthereumAddress; token_ids: string[]; xpunkAddress: tEthereumAddress; onBehalfOf?: tEthereumAddress; }; export interface WPunkGatewayInterface { supplyPunk: ( args: WPunkSupplyParamsType, ) => EthereumTransactionTypeExtended[]; withdrawPunk: ( args: WPunkWithdrawParamsType, ) => Promise; } export class WPunkGatewayService extends BaseService implements WPunkGatewayInterface { readonly wpunkGatewayAddress: string; readonly cryptoPunkService: CrytoPunkInterface; readonly erc721Service: IERC721ServiceInterface; constructor( provider: providers.Provider, wpunkGatewayAddress?: tEthereumAddress, crytoPunkAddress?: tEthereumAddress, ) { super(provider, IWPunkGatewayFactory); this.wpunkGatewayAddress = wpunkGatewayAddress ?? ''; this.cryptoPunkService = new CrytoPunkService(provider, crytoPunkAddress); this.erc721Service = new ERC721Service(provider); this.supplyPunk = this.supplyPunk.bind(this); this.withdrawPunk = this.withdrawPunk.bind(this); } @WPunkValidator public supplyPunk( @isEthAddress('user') @isValidTokenIdArray('token_ids') @isEthAddress('onBehalfOf') @is0OrPositiveAmount('referralCode') { user, token_ids, onBehalfOf, referralCode }: WPunkSupplyParamsType, ): EthereumTransactionTypeExtended[] { const params: Array<{ tokenId: BigNumberish; useAsCollateral: boolean }> = []; const txs: EthereumTransactionTypeExtended[] = []; const { offerPunkForSaleToAddress }: CrytoPunkInterface = this.cryptoPunkService; for (const value of token_ids) { params.push({ tokenId: value, useAsCollateral: true, }); const offerTx: EthereumTransactionTypeExtended = offerPunkForSaleToAddress({ user, punkIndex: value, minSalePriceInWei: '0', targetAddress: this.wpunkGatewayAddress, }); txs.push(offerTx); } const wpuckGatewayContract: IWPunkGateway = this.getContractInstance( this.wpunkGatewayAddress, ); const txCallback: () => Promise = this.generateTxCallback({ rawTxMethod: async () => wpuckGatewayContract.populateTransaction.supplyPunk( params, onBehalfOf ?? user, referralCode ?? '0', ), from: user, }); txs.push({ tx: txCallback, txType: eEthereumTxType.DLP_ACTION, gas: this.generateTxPriceEstimation(txs, txCallback), }); return [ { tx: txCallback, txType: eEthereumTxType.DLP_ACTION, gas: this.generateTxPriceEstimation([], txCallback), }, ]; } @WPunkValidator public async withdrawPunk( @isEthAddress('user') @isValidTokenIdArray('token_ids') @isEthAddress('xpunkAddress') @isEthAddress('onBehalfOf') { user, token_ids, xpunkAddress, onBehalfOf }: WPunkWithdrawParamsType, ): Promise { const wpuckGatewayContract: IWPunkGateway = this.getContractInstance( this.wpunkGatewayAddress, ); const txs: EthereumTransactionTypeExtended[] = []; const { isApprovedForAll, setApprovalForAll }: IERC721ServiceInterface = this.erc721Service; const allApproved = await isApprovedForAll({ token: xpunkAddress, user, spender: this.wpunkGatewayAddress, token_ids, }); if (!allApproved) { const approveTx: EthereumTransactionTypeExtended = setApprovalForAll({ token: xpunkAddress, user, spender: this.wpunkGatewayAddress, }); txs.push(approveTx); } const txCallback: () => Promise = this.generateTxCallback({ rawTxMethod: async () => wpuckGatewayContract.populateTransaction.withdrawPunk( token_ids, onBehalfOf ?? user, ), from: user, }); txs.push({ tx: txCallback, txType: eEthereumTxType.DLP_ACTION, gas: this.generateTxPriceEstimation( txs, txCallback, ProtocolAction.supplyErc721, ), }); return txs; } }