e6f882d7e1
* 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>
170 lines
5.3 KiB
TypeScript
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,
|
|
}
|