feat: sync and update with all changes from fork (#720)

* feat: sync and update with all changes from fork
* refactor: extract clipboard copy logic into custom hook
* fix: correct spelling of DEFAULT_REFRESH_FREQUENCY_MS in Stamps and WalletBalance providers
* refactor(ui-tests): replace fixed sleeps with condition-based waits
* fix: handle null values for size and granteeCount in infoGroups
* fix(lint): add newline at end of file in useClipboardCopy hook
* fix(ui-tests): page.goto URL
* refactor: update import paths for useClipboardCopy

---------

Co-authored-by: Ferenc Sárai <sarai.ferenc@gmail.com>
This commit is contained in:
Bálint Ujvári
2026-03-02 11:34:39 +01:00
committed by GitHub
parent b0f00a624a
commit 519c411db0
303 changed files with 16609 additions and 29415 deletions
+86 -37
View File
@@ -1,27 +1,25 @@
import { debounce } from '@material-ui/core'
import { BZZ, DAI, EthAddress, PrivateKey } from '@ethersphere/bee-js'
import { BigNumber as BN, Contract, providers, Wallet } from 'ethers'
import { BZZ_TOKEN_ADDRESS, bzzABI } from './bzz-abi'
import { debounce } from '@mui/material'
import { Contract, JsonRpcProvider, TransactionReceipt, TransactionResponse, Wallet } from 'ethers'
const NETWORK_ID = 100
import { BZZ_TOKEN_ADDRESS, bzzABI } from './bzzAbi'
import { ethAddressString, newGnosisProvider } from './chain'
async function getNetworkChainId(url: string): Promise<number> {
const provider = new providers.JsonRpcProvider(url, NETWORK_ID)
await provider.ready
async function getNetworkChainId(url: string): Promise<bigint> {
const provider = newGnosisProvider(url)
const network = await provider.getNetwork()
return network.chainId
}
async function eth_getBalance(address: EthAddress | string, provider: providers.JsonRpcProvider): Promise<DAI> {
address = new EthAddress(address)
const balance = await provider.getBalance(address.toHex())
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: providers.JsonRpcProvider): Promise<string> {
async function eth_getBlockByNumber(provider: JsonRpcProvider): Promise<string> {
const blockNumber = await provider.getBlockNumber()
return blockNumber.toString()
@@ -29,56 +27,75 @@ async function eth_getBlockByNumber(provider: providers.JsonRpcProvider): Promis
async function eth_getBalanceERC20(
address: EthAddress | string,
provider: providers.JsonRpcProvider,
provider: JsonRpcProvider,
tokenAddress = BZZ_TOKEN_ADDRESS,
): Promise<BZZ> {
address = new EthAddress(address)
const addressString = ethAddressString(address)
const contract = new Contract(tokenAddress, bzzABI, provider)
const balance = await contract.balanceOf(address.toHex())
// Use staticCall directly to bypass argument resolution
const balance = await contract.balanceOf.staticCall(addressString)
return BZZ.fromPLUR(balance.toString())
}
interface TransferResponse {
transaction: providers.TransactionResponse
receipt: providers.TransactionReceipt
transaction: TransactionResponse
receipt: TransactionReceipt
}
export async function estimateNativeTransferTransactionCost(
privateKey: PrivateKey | string,
jsonRpcProvider: string,
jsonRpcProviderUrl: string,
): Promise<{ gasPrice: DAI; totalCost: DAI }> {
privateKey = new PrivateKey(privateKey)
const signer = await makeReadySigner(privateKey, jsonRpcProvider)
const gasLimit = '21000'
const gasPrice = await signer.getGasPrice()
const signer = await makeReadySigner(privateKey, jsonRpcProviderUrl)
return { gasPrice: DAI.fromWei(gasPrice.toString()), totalCost: DAI.fromWei(gasPrice.mul(gasLimit).toString()) }
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,
jsonRpcProvider: string,
jsonRpcProviderUrl: string,
externalGasPrice?: DAI,
): Promise<TransferResponse> {
privateKey = new PrivateKey(privateKey)
to = new EthAddress(to)
const signer = await makeReadySigner(privateKey, jsonRpcProvider)
const gasPrice = externalGasPrice ?? DAI.fromWei((await signer.getGasPrice()).toString())
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.toHex(),
value: BN.from(value.toWeiString()),
gasPrice: BN.from(gasPrice.toWeiString()),
gasLimit: BN.from(21000),
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 }
}
@@ -86,29 +103,61 @@ export async function sendBzzTransaction(
privateKey: PrivateKey | string,
to: EthAddress | string,
value: BZZ,
jsonRpcProvider: string,
jsonRpcProviderUrl: string,
): Promise<TransferResponse> {
privateKey = new PrivateKey(privateKey)
to = new EthAddress(to)
const signer = await makeReadySigner(privateKey, jsonRpcProvider)
const gasPrice = await signer.getGasPrice()
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, value, { gasPrice })
const receipt = await transaction.wait(1)
if (!receipt) {
throw new Error('Invalid receipt!')
}
return { transaction, receipt }
}
async function makeReadySigner(privateKey: PrivateKey, jsonRpcProvider: string) {
const provider = new providers.JsonRpcProvider(jsonRpcProvider, NETWORK_ID)
await provider.ready
const signer = new Wallet(privateKey.toUint8Array(), provider)
async function makeReadySigner(privateKey: PrivateKey, jsonRpcProviderUrl: string) {
const provider = newGnosisProvider(jsonRpcProviderUrl)
await provider.getNetwork()
const signer = new Wallet(privateKey.toString(), provider)
return signer
}
export const Rpc = {
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,