-
Notifications
You must be signed in to change notification settings - Fork 14
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Create CollectFeesHandler for admin. Added tests. * Print balance. * Add debug log. * Added regex validation for ethereum addresses. * Added checks for zero address. Refactor transfer call. * Debug logs. * Tweak for addresses length in regex. * fix. * Added debug logs for handle function and refactored test for fee amount. * Fix call. * Fix provider wallet. * Fix breaking change for provider wallet. * Print error. * Replace ReadableString with Readable. * Added more debug logs. * More debug. * Use readStream instead of streamToString. * Move test position. * increase timeout. * remove message from handler response. * store tx receipt in a separate var. * Fix unit for parseUnit. * Fix wallet. * Change token address. * Print addresses. * Changed wallet private key. * Added logs for expected failure cases. * Fix log for balance. * cleanup. * Fix review part 1. * Fix review part 2. * Fix review part 3. * tweak. * Resolve conditions. Refactor code. * Fix review. * Updated provider wallet. * Make tokenAmount optional.
- Loading branch information
1 parent
a91157e
commit f0ec9f4
Showing
9 changed files
with
307 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,163 @@ | ||
import { AdminHandler } from './adminHandler.js' | ||
import { | ||
AdminCollectFeesCommand, | ||
AdminCollectFeesHandlerResponse | ||
} from '../../../@types/commands.js' | ||
import { P2PCommandResponse } from '../../../@types/OceanNode.js' | ||
import { | ||
ValidateParams, | ||
buildInvalidParametersResponse, | ||
buildErrorResponse, | ||
buildInvalidRequestMessage, | ||
validateCommandParameters | ||
} from '../../httpRoutes/validateCommands.js' | ||
import { | ||
getConfiguration, | ||
checkSupportedChainId, | ||
Blockchain | ||
} from '../../../utils/index.js' | ||
import { parseUnits, Contract, ZeroAddress, isAddress, Wallet } from 'ethers' | ||
import ERC20Template from '@oceanprotocol/contracts/artifacts/contracts/templates/ERC20Template.sol/ERC20Template.json' assert { type: 'json' } | ||
import { CORE_LOGGER } from '../../../utils/logging/common.js' | ||
import { Readable } from 'stream' | ||
|
||
export class CollectFeesHandler extends AdminHandler { | ||
validate(command: AdminCollectFeesCommand): ValidateParams { | ||
if ( | ||
!validateCommandParameters(command, [ | ||
'chainId', | ||
'tokenAddress', | ||
'tokenAmount', | ||
'destinationAddress' | ||
]) | ||
) { | ||
return buildInvalidRequestMessage( | ||
`Missing chainId field for command: "${command}".` | ||
) | ||
} | ||
if (!isAddress(command.tokenAddress) || !isAddress(command.destinationAddress)) { | ||
const msg: string = `Invalid format for token address or destination address.` | ||
CORE_LOGGER.error(msg) | ||
return buildInvalidRequestMessage(msg) | ||
} | ||
return super.validate(command) | ||
} | ||
|
||
async handle(task: AdminCollectFeesCommand): Promise<P2PCommandResponse> { | ||
const validation = this.validate(task) | ||
if (!validation.valid) { | ||
return buildInvalidParametersResponse(validation) | ||
} | ||
const config = await getConfiguration() | ||
if (task.node && task.node !== config.keys.peerId.toString()) { | ||
const msg: string = `Cannot run this command ${JSON.stringify( | ||
task | ||
)} on a different node.` | ||
CORE_LOGGER.error(msg) | ||
return buildErrorResponse(msg) | ||
} | ||
const checkChainId = await checkSupportedChainId(task.chainId) | ||
if (!checkChainId.validation) { | ||
return buildErrorResponse( | ||
`Chain ID ${task.chainId} is not supported in the node's config` | ||
) | ||
} | ||
|
||
try { | ||
const { rpc, network, chainId, fallbackRPCs } = | ||
config.supportedNetworks[task.chainId] | ||
const blockchain = new Blockchain(rpc, network, chainId, fallbackRPCs) | ||
const provider = blockchain.getProvider() | ||
const providerWallet = blockchain.getSigner() as Wallet | ||
const providerWalletAddress = await providerWallet.getAddress() | ||
const ammountInEther = task.tokenAmount | ||
? parseUnits(task.tokenAmount.toString(), 'ether') | ||
: await provider.getBalance(providerWalletAddress) | ||
|
||
let receipt | ||
if (task.tokenAddress.toLowerCase() === ZeroAddress) { | ||
if ( | ||
(await provider.getBalance(providerWalletAddress)) < | ||
(await blockchain.calculateGasCost( | ||
task.destinationAddress.toLowerCase(), | ||
ammountInEther | ||
)) | ||
) { | ||
const msg: string = `Amount too high to transfer native token! Balance: ${await provider.getBalance( | ||
providerWalletAddress | ||
)} vs. amount provided: ${ammountInEther}` | ||
CORE_LOGGER.error(msg) | ||
return buildErrorResponse(msg) | ||
} | ||
|
||
receipt = await blockchain.sendTransaction( | ||
providerWallet, | ||
task.destinationAddress.toLowerCase(), | ||
ammountInEther | ||
) | ||
} else { | ||
const token = new Contract( | ||
task.tokenAddress.toLowerCase(), | ||
ERC20Template.abi, | ||
providerWallet | ||
) | ||
const tokenAmount = task.tokenAmount | ||
? parseUnits(task.tokenAmount.toString(), 'ether') | ||
: await token.balanceOf(providerWalletAddress) | ||
|
||
if ((await token.balanceOf(providerWalletAddress)) < tokenAmount) { | ||
const msg: string = `Amount too high to transfer! Balance: ${await token.balanceOf( | ||
providerWalletAddress | ||
)} vs. amount provided: ${tokenAmount}` | ||
CORE_LOGGER.error(msg) | ||
return buildErrorResponse(msg) | ||
} | ||
const tx = await token.transfer( | ||
task.destinationAddress.toLowerCase(), | ||
tokenAmount | ||
) | ||
receipt = await tx.wait() | ||
} | ||
if (!receipt) { | ||
const msg: string = `Receipt does not exist` | ||
CORE_LOGGER.error(msg) | ||
return { | ||
stream: null, | ||
status: { | ||
httpStatus: 404, | ||
error: msg | ||
} | ||
} | ||
} | ||
if (receipt.status !== 1) { | ||
const msg: string = `Reverted transaction: ${JSON.stringify(receipt.logs)}` | ||
CORE_LOGGER.error(msg) | ||
return { | ||
stream: null, | ||
status: { | ||
httpStatus: 404, | ||
error: msg | ||
} | ||
} | ||
} | ||
const response: AdminCollectFeesHandlerResponse = { | ||
tx: receipt.hash, | ||
message: 'Fees successfully transfered to admin!' | ||
} | ||
return { | ||
status: { httpStatus: 200 }, | ||
stream: Readable.from(JSON.stringify(response)) | ||
} | ||
} catch (e) { | ||
const msg: string = `Error in collecting provider fees: ${e}` | ||
CORE_LOGGER.error(msg) | ||
return { | ||
stream: null, | ||
status: { | ||
httpStatus: 500, | ||
error: msg | ||
} | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.