feat: add light node upgrade top up methods (#372)
* feat: add top up * chore: remove console.log * build: add pseudo-missing dependency * feat: add missing top up components * fix: crypto route * feat(wip): add gift wallet logic * fix: fix gift wallet flows * feat: simplify flow without fund step * feat: add loading screens * fix: remove alert * fix: prepend http if needed * fix: fix bug that was reintroduced with merge * refactor: rename minusEther to minusBaseUnits * fix: remove unused setStartedAt * build: remove unused dependency
This commit is contained in:
@@ -0,0 +1,25 @@
|
||||
export const bzzContractInterface = [
|
||||
{
|
||||
type: 'function',
|
||||
stateMutability: 'nonpayable',
|
||||
payable: false,
|
||||
outputs: [
|
||||
{
|
||||
type: 'bool',
|
||||
name: '',
|
||||
},
|
||||
],
|
||||
name: 'transfer',
|
||||
inputs: [
|
||||
{
|
||||
type: 'address',
|
||||
name: '_to',
|
||||
},
|
||||
{
|
||||
type: 'uint256',
|
||||
name: '_value',
|
||||
},
|
||||
],
|
||||
constant: false,
|
||||
},
|
||||
]
|
||||
@@ -26,6 +26,12 @@ export async function upgradeToLightNode(rpcProvider: string): Promise<void> {
|
||||
})
|
||||
}
|
||||
|
||||
export async function setJsonRpcInDesktop(value: string): Promise<void> {
|
||||
await updateDesktopConfiguration({
|
||||
'swap-endpoint': value,
|
||||
})
|
||||
}
|
||||
|
||||
async function updateDesktopConfiguration(values: Record<string, unknown>): Promise<void> {
|
||||
await postJson(`http://${getDesktopHost()}/config`, values)
|
||||
}
|
||||
@@ -34,6 +40,14 @@ export async function restartBeeNode(): Promise<void> {
|
||||
await postJson(`http://${getDesktopHost()}/restart`)
|
||||
}
|
||||
|
||||
export async function createGiftWallet(address: string): Promise<void> {
|
||||
await postJson(`http://${getDesktopHost()}/gift-wallet/${address}`)
|
||||
}
|
||||
|
||||
export async function performSwap(daiAmount: string): Promise<void> {
|
||||
await postJson(`http://${getDesktopHost()}/swap`, { dai: daiAmount })
|
||||
}
|
||||
|
||||
function getDesktopHost(): string {
|
||||
return window.location.host
|
||||
}
|
||||
|
||||
@@ -79,9 +79,11 @@ function getWalletFromIdentity(identity: Identity, password?: string): Promise<W
|
||||
}
|
||||
|
||||
async function getWallet(type: IdentityType, data: string, password?: string): Promise<Wallet> {
|
||||
return type === 'PRIVATE_KEY'
|
||||
? Wallet.fromPrivateKey(Buffer.from(trimHexString(data), 'hex'))
|
||||
: await Wallet.fromV3(data, password as string)
|
||||
return type === 'PRIVATE_KEY' ? getWalletFromPrivateKeyString(data) : await Wallet.fromV3(data, password as string)
|
||||
}
|
||||
|
||||
export function getWalletFromPrivateKeyString(privateKey: string): Wallet {
|
||||
return Wallet.fromPrivateKey(Buffer.from(trimHexString(privateKey), 'hex'))
|
||||
}
|
||||
|
||||
export async function updateFeed(
|
||||
|
||||
+69
-4
@@ -1,14 +1,15 @@
|
||||
import { debounce } from '@material-ui/core'
|
||||
import axios from 'axios'
|
||||
import { Contract, providers } from 'ethers'
|
||||
import { Contract, providers, Wallet } from 'ethers'
|
||||
import { bzzContractInterface } from './bzz-contract-interface'
|
||||
|
||||
const PROVIDER = 'https://gno.getblock.io/mainnet/?api_key=d7b92d96-9784-49a8-a800-b3edd1647fc7'
|
||||
export const JSON_RPC_PROVIDER = 'https://gno.getblock.io/mainnet/?api_key=d7b92d96-9784-49a8-a800-b3edd1647fc7'
|
||||
|
||||
async function eth_getBalance(address: string): Promise<string> {
|
||||
if (!address.startsWith('0x')) {
|
||||
address = `0x${address}`
|
||||
}
|
||||
const response = await axios(PROVIDER, {
|
||||
const response = await axios(JSON_RPC_PROVIDER, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'content-type': 'application/json',
|
||||
@@ -24,6 +25,23 @@ async function eth_getBalance(address: string): Promise<string> {
|
||||
return response.data.result
|
||||
}
|
||||
|
||||
async function eth_getBlockByNumber(provider = JSON_RPC_PROVIDER): Promise<string> {
|
||||
const response = await axios(provider, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'content-type': 'application/json',
|
||||
},
|
||||
data: {
|
||||
jsonrpc: '2.0',
|
||||
method: 'eth_getBlockByNumber',
|
||||
params: ['latest', false],
|
||||
id: 1,
|
||||
},
|
||||
})
|
||||
|
||||
return response.data.result
|
||||
}
|
||||
|
||||
const partialERC20tokenABI = [
|
||||
{
|
||||
constant: true,
|
||||
@@ -45,7 +63,7 @@ const partialERC20tokenABI = [
|
||||
},
|
||||
]
|
||||
|
||||
const provider = new providers.JsonRpcProvider(PROVIDER)
|
||||
const provider = new providers.JsonRpcProvider(JSON_RPC_PROVIDER)
|
||||
|
||||
async function eth_getBalanceERC20(
|
||||
address: string,
|
||||
@@ -60,7 +78,54 @@ async function eth_getBalanceERC20(
|
||||
return balance.toString()
|
||||
}
|
||||
|
||||
interface TransferResponse {
|
||||
transaction: providers.TransactionResponse
|
||||
receipt: providers.TransactionReceipt
|
||||
}
|
||||
|
||||
export async function sendNativeTransaction(
|
||||
privateKey: string,
|
||||
to: string,
|
||||
value: string,
|
||||
jsonRpcProvider: string,
|
||||
): Promise<TransferResponse> {
|
||||
const signer = await makeReadySigner(privateKey, jsonRpcProvider)
|
||||
const gasPrice = await signer.getGasPrice()
|
||||
const transaction = await signer.sendTransaction({ to, value, gasPrice })
|
||||
const receipt = await transaction.wait(1)
|
||||
|
||||
return { transaction, receipt }
|
||||
}
|
||||
|
||||
export async function sendBzzTransaction(
|
||||
privateKey: string,
|
||||
to: string,
|
||||
value: string,
|
||||
jsonRpcProvider: string,
|
||||
): Promise<TransferResponse> {
|
||||
const signer = await makeReadySigner(privateKey, jsonRpcProvider)
|
||||
const gasPrice = await signer.getGasPrice()
|
||||
const bzz = new Contract('0xdBF3Ea6F5beE45c02255B2c26a16F300502F68da', bzzContractInterface, signer)
|
||||
const transaction = await bzz.transfer(to, value, { gasPrice })
|
||||
const receipt = await transaction.wait(1)
|
||||
|
||||
return { transaction, receipt }
|
||||
}
|
||||
|
||||
async function makeReadySigner(privateKey: string, jsonRpcProvider: string) {
|
||||
const provider = new providers.JsonRpcProvider(jsonRpcProvider, 100)
|
||||
await provider.ready
|
||||
const signer = new Wallet(privateKey, provider)
|
||||
|
||||
return signer
|
||||
}
|
||||
|
||||
export const Rpc = {
|
||||
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,
|
||||
}
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
import Wallet from 'ethereumjs-wallet'
|
||||
import { sleepMs } from '.'
|
||||
import { BzzToken } from '../models/BzzToken'
|
||||
import { DaiToken } from '../models/DaiToken'
|
||||
import { getWalletFromPrivateKeyString } from './identity'
|
||||
import { Rpc } from './rpc'
|
||||
|
||||
export class WalletAddress {
|
||||
private constructor(public address: string, public bzz: BzzToken, public dai: DaiToken) {}
|
||||
|
||||
static async make(address: string): Promise<WalletAddress> {
|
||||
const bzz = new BzzToken(await Rpc._eth_getBalanceERC20(address))
|
||||
const dai = new DaiToken(await Rpc._eth_getBalance(address))
|
||||
|
||||
return new WalletAddress(address, bzz, dai)
|
||||
}
|
||||
|
||||
public async refresh(): Promise<WalletAddress> {
|
||||
this.bzz = new BzzToken(await Rpc._eth_getBalanceERC20(this.address))
|
||||
this.dai = new DaiToken(await Rpc._eth_getBalance(this.address))
|
||||
|
||||
return this
|
||||
}
|
||||
}
|
||||
|
||||
export class ResolvedWallet {
|
||||
public address: string
|
||||
public privateKey: string
|
||||
|
||||
private constructor(public wallet: Wallet, public bzz: BzzToken, public dai: DaiToken) {
|
||||
this.address = wallet.getAddressString()
|
||||
this.privateKey = wallet.getPrivateKeyString()
|
||||
}
|
||||
|
||||
static async make(privateKeyOrWallet: string | Wallet): Promise<ResolvedWallet> {
|
||||
const wallet =
|
||||
typeof privateKeyOrWallet === 'string' ? getWalletFromPrivateKeyString(privateKeyOrWallet) : privateKeyOrWallet
|
||||
const address = wallet.getAddressString()
|
||||
const bzz = new BzzToken(await Rpc._eth_getBalanceERC20(address))
|
||||
const dai = new DaiToken(await Rpc._eth_getBalance(address))
|
||||
|
||||
return new ResolvedWallet(wallet, bzz, dai)
|
||||
}
|
||||
|
||||
public async refresh(): Promise<ResolvedWallet> {
|
||||
this.bzz = new BzzToken(await Rpc._eth_getBalanceERC20(this.address))
|
||||
this.dai = new DaiToken(await Rpc._eth_getBalance(this.address))
|
||||
|
||||
return this
|
||||
}
|
||||
|
||||
public async transfer(
|
||||
destination: string,
|
||||
jsonRpcProvider = 'https://gno.getblock.io/mainnet/?api_key=d7b92d96-9784-49a8-a800-b3edd1647fc7',
|
||||
): Promise<void> {
|
||||
const DUMMY_GAS_PRICE = '300000000000000'
|
||||
|
||||
if (this.bzz.toDecimal.gt(0.1)) {
|
||||
await Rpc.sendBzzTransaction(this.privateKey, destination, this.bzz.toString, jsonRpcProvider)
|
||||
await sleepMs(5_000)
|
||||
}
|
||||
|
||||
if (this.dai.toBigNumber.gt(DUMMY_GAS_PRICE)) {
|
||||
await Rpc.sendNativeTransaction(
|
||||
this.privateKey,
|
||||
destination,
|
||||
this.dai.toBigNumber.minus(DUMMY_GAS_PRICE).toString(),
|
||||
jsonRpcProvider,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user