Files
bee-dashboard/src/utils/rpc.ts
T
Ferenc Sárai e6f882d7e1 fix: for upcoming v0.53.1 (#731)
* fix: swap error caused by invalid id and batchcount
* fix: enhance creation messages for admin drive and user drives (#238)
* fix: enhance creation messages for admin drive and user drives
* fix: update creation message to indicate longer processing time
* fix: identity and wallet creation (#240)
* fix: asset preview types
* fix: fm search unicode text
* fix: feed identity and stamp usage
* fix: ui display changes (#239)
* fix: ui layout changes

* fix: stamp buy and dilute (#242)

fix: vite polyfill warning for stream
refactor: stamp depth and amount validation

* fix: spdv-917 (#243)

* fix: spdv-917

* refactor: spdv-917

* fix: add syncing message for Bee node and update page state handling spdv-955 (#244)

* fix: spdv-1037 (#245)

* fix: spdv-1038 (#246)

* fix: spdv-1038

* refactor: spdv-1038

* fix: validate stamp before every upgrade click (#247)

* fix: validate stamp before every upgrade click
---------

Co-authored-by: Roland Seres <roland.seres90@gmail.com>

* fix: use tochecksum() and toplurbigint() for ethers v6 compatibility (#248)

---------

Co-authored-by: Balint Ujvari <balint.ujvari@solarpunk.buzz>
Co-authored-by: Bálint Ujvári <58116288+bosi95@users.noreply.github.com>
Co-authored-by: rolandlor <33499567+rolandlor@users.noreply.github.com>
Co-authored-by: Roland Seres <roland.seres90@gmail.com>
2026-04-10 10:59:20 +02:00

170 lines
5.3 KiB
TypeScript

import { BZZ, DAI, EthAddress, PrivateKey } from '@ethersphere/bee-js'
import { debounce } from '@mui/material'
import { Contract, JsonRpcProvider, TransactionReceipt, TransactionResponse, Wallet } from 'ethers'
import { BZZ_TOKEN_ADDRESS, bzzABI } from './bzzAbi'
import { ethAddressString, newGnosisProvider, newGnosisProviderForValidation } from './chain'
async function getNetworkChainId(url: string): Promise<bigint> {
const provider = newGnosisProviderForValidation(url)
const network = await provider.getNetwork()
return network.chainId
}
async function eth_getBalance(address: EthAddress | string, provider: JsonRpcProvider): Promise<DAI> {
const addressString = ethAddressString(address)
const balance = await provider.getBalance(addressString)
return DAI.fromWei(balance.toString())
}
async function eth_getBlockByNumber(provider: JsonRpcProvider): Promise<string> {
const blockNumber = await provider.getBlockNumber()
return blockNumber.toString()
}
async function eth_getBalanceERC20(
address: EthAddress | string,
provider: JsonRpcProvider,
tokenAddress = BZZ_TOKEN_ADDRESS,
): Promise<BZZ> {
const addressString = ethAddressString(address)
const contract = new Contract(tokenAddress, bzzABI, provider)
// Use staticCall directly to bypass argument resolution
const balance = await contract.balanceOf.staticCall(addressString)
return BZZ.fromPLUR(balance.toString())
}
interface TransferResponse {
transaction: TransactionResponse
receipt: TransactionReceipt
}
export async function estimateNativeTransferTransactionCost(
privateKey: PrivateKey | string,
jsonRpcProviderUrl: string,
): Promise<{ gasPrice: DAI; totalCost: DAI }> {
privateKey = new PrivateKey(privateKey)
const signer = await makeReadySigner(privateKey, jsonRpcProviderUrl)
if (!signer.provider) {
throw new Error('Signer provider is invalid!')
}
const gasLimit = BigInt(21000)
const feeData = await signer.provider.getFeeData()
const gasPrice = feeData.gasPrice || BigInt(0)
return {
gasPrice: DAI.fromWei(gasPrice.toString()),
totalCost: DAI.fromWei((gasPrice * gasLimit).toString()),
}
}
export async function sendNativeTransaction(
privateKey: PrivateKey | string,
to: EthAddress | string,
value: DAI,
jsonRpcProviderUrl: string,
externalGasPrice?: DAI,
): Promise<TransferResponse> {
privateKey = new PrivateKey(privateKey)
to = new EthAddress(to)
const signer = await makeReadySigner(privateKey, jsonRpcProviderUrl)
if (!signer.provider) {
throw new Error('Signer provider is invalid!')
}
const feedData = await signer.provider.getFeeData()
const gasPrice = externalGasPrice ?? DAI.fromWei(feedData.gasPrice?.toString() || '0')
const transaction = await signer.sendTransaction({
to: to.toChecksum(),
value: BigInt(value.toWeiString()),
gasPrice: BigInt(gasPrice.toWeiString()),
gasLimit: BigInt(21000),
type: 0,
})
const receipt = await transaction.wait(1)
if (!receipt) {
throw new Error('Invalid receipt!')
}
return { transaction, receipt }
}
export async function sendBzzTransaction(
privateKey: PrivateKey | string,
to: EthAddress | string,
value: BZZ,
jsonRpcProviderUrl: string,
): Promise<TransferResponse> {
privateKey = new PrivateKey(privateKey)
to = new EthAddress(to)
const signer = await makeReadySigner(privateKey, jsonRpcProviderUrl)
if (!signer.provider) {
throw new Error('Signer provider is invalid!')
}
const feeData = await signer.provider.getFeeData()
const gasPrice = feeData.gasPrice || BigInt(0)
const bzz = new Contract(BZZ_TOKEN_ADDRESS, bzzABI, signer)
const transaction = await bzz.transfer(to.toChecksum(), value.toPLURBigInt(), { gasPrice })
const receipt = await transaction.wait(1)
if (!receipt) {
throw new Error('Invalid receipt!')
}
return { transaction, receipt }
}
async function makeReadySigner(privateKey: PrivateKey, jsonRpcProviderUrl: string) {
const provider = newGnosisProvider(jsonRpcProviderUrl)
await provider.getNetwork()
const signer = new Wallet(privateKey.toString(), provider)
return signer
}
export interface Rpc {
getNetworkChainId: (url: string) => Promise<bigint>
sendNativeTransaction: (
privateKey: PrivateKey | string,
to: EthAddress | string,
value: DAI,
jsonRpcProviderUrl: string,
externalGasPrice?: DAI,
) => Promise<TransferResponse>
sendBzzTransaction: (
privateKey: PrivateKey | string,
to: EthAddress | string,
value: BZZ,
jsonRpcProviderUrl: string,
) => Promise<TransferResponse>
_eth_getBalance: (address: EthAddress | string, provider: JsonRpcProvider) => Promise<DAI>
_eth_getBalanceERC20: (address: EthAddress | string, provider: JsonRpcProvider, tokenAddress?: string) => Promise<BZZ>
eth_getBalance: (address: EthAddress | string, provider: JsonRpcProvider) => Promise<DAI>
eth_getBalanceERC20: (address: EthAddress | string, provider: JsonRpcProvider, tokenAddress: string) => Promise<BZZ>
eth_getBlockByNumber: (provider: JsonRpcProvider) => Promise<string>
}
export const RPC: Rpc = {
getNetworkChainId,
sendNativeTransaction,
sendBzzTransaction,
_eth_getBalance: eth_getBalance,
_eth_getBalanceERC20: eth_getBalanceERC20,
eth_getBalance: debounce(eth_getBalance, 1_000),
eth_getBalanceERC20: debounce(eth_getBalanceERC20, 1_000),
eth_getBlockByNumber,
}