Skip to content

Latest commit

 

History

History
270 lines (232 loc) · 11.5 KB

04.md

File metadata and controls

270 lines (232 loc) · 11.5 KB
title actions requireLogin material
Approve ERC20 token transfers
checkAnswer
hints
false
editor
language startingCode answer
JavaScript
src/alice.js src/bob.js src/utils.js
(async () => { const ethers = require('ethers') const zksync = require('zksync') const utils = require('./utils') const token = 'USDT' const amountToDeposit = '6.0' const amountToTransfer = '2.0' const amountToWithdraw = '2.0' const zkSyncProvider = await utils.getZkSyncProvider(zksync, process.env.NETWORK_NAME) const ethersProvider = await utils.getEthereumProvider(ethers, process.env.NETWORK_NAME) console.log('Creating a new Rinkeby wallet for Alice') const aliceRinkebyWallet = new ethers.Wallet(process.env.ALICE_PRIVATE_KEY, ethersProvider) console.log(`Alice's Rinkeby address is: ${aliceRinkebyWallet.address}`) console.log('Creating a zkSync wallet for Alice') const aliceZkSyncWallet = await utils.initAccount(aliceRinkebyWallet, zkSyncProvider, zksync) const tokenSet = zkSyncProvider.tokenSet const aliceInitialRinkebyBalance = await aliceZkSyncWallet.getEthereumBalance(token) console.log(`Alice's initial balance on Rinkeby is: ${tokenSet.formatToken(token, aliceInitialRinkebyBalance)}`) await aliceZkSyncWallet.approveERC20TokenDeposits(token) console.log('Depositing') await utils.depositToZkSync(aliceZkSyncWallet, token, amountToDeposit, ethers) // Update this line await utils.displayZkSyncBalance(aliceZkSyncWallet, ethers) // Update this line await utils.registerAccount(aliceZkSyncWallet) console.log('Transferring') const transferFee = await utils.getFee('Transfer', aliceRinkebyWallet.address, token, zkSyncProvider, ethers) // Update this line await utils.transfer(aliceZkSyncWallet, process.env.BOB_ADDRESS, amountToTransfer, transferFee, token, zksync, ethers) // Update this line console.log('Withdrawing') const withdrawalFee = await utils.getFee('Withdraw', aliceRinkebyWallet.address, token, zkSyncProvider, ethers) // Update this line await utils.withdrawToEthereum(aliceZkSyncWallet, amountToWithdraw, withdrawalFee, token, zksync, ethers) // Update this line })()
(async () => { const ethers = require('ethers') const zksync = require('zksync') const utils = require('./utils') const SLEEP_INTERVAL = process.env.SLEEP_INTERVAL || 5000 const zkSyncProvider = await utils.getZkSyncProvider(zksync, process.env.NETWORK_NAME) const ethersProvider = await utils.getEthereumProvider(ethers, process.env.NETWORK_NAME) const bobRinkebyWallet = new ethers.Wallet(process.env.BOB_PRIVATE_KEY, ethersProvider) console.log(`Bob's Rinkeby address is: ${bobRinkebyWallet.address}`) console.log(`Bob's initial balance on Rinkeby is: ${ethers.utils.formatEther(await bobRinkebyWallet.getBalance())}`) const bobZkSyncWallet = await utils.initAccount(bobRinkebyWallet, zkSyncProvider, zksync) process.on('SIGINT', () => { console.log('Disconnecting') // Disconnect process.exit() }) setInterval(async () => { await utils.displayZkSyncBalance(bobZkSyncWallet, ethers) console.log('---') }, SLEEP_INTERVAL) })()
async function getZkSyncProvider (zksync, networkName) { let zkSyncProvider try { zkSyncProvider = await zksync.getDefaultProvider(networkName) } catch (error) { console.log('Unable to connect to zkSync.') console.log(error) } return zkSyncProvider } async function getEthereumProvider (ethers, networkName) { let ethersProvider try { // eslint-disable-next-line new-cap ethersProvider = new ethers.getDefaultProvider(networkName) } catch (error) { console.log('Could not connect to Rinkeby') console.log(error) } return ethersProvider } async function initAccount (rinkebyWallet, zkSyncProvider, zksync) { const zkSyncWallet = await zksync.Wallet.fromEthSigner(rinkebyWallet, zkSyncProvider) return zkSyncWallet } async function registerAccount (wallet) { console.log(`Registering the ${wallet.address()} account on zkSync`) if (!await wallet.isSigningKeySet()) { if (await wallet.getAccountId() === undefined) { throw new Error('Unknown account') } const changePubkey = await wallet.setSigningKey() await changePubkey.awaitReceipt() } console.log(`Account ${wallet.address()} registered`) } async function depositToZkSync (zkSyncWallet, token, amountToDeposit, ethers) { const deposit = await zkSyncWallet.depositToSyncFromEthereum({ depositTo: zkSyncWallet.address(), token: token, amount: ethers.utils.parseEther(amountToDeposit) }) try { await deposit.awaitReceipt() } catch (error) { console.log('Error while awaiting confirmation from the zkSync operators.') console.log(error) } } async function transfer (from, toAddress, amountToTransfer, transferFee, token, zksync, ethers) { const closestPackableAmount = zksync.utils.closestPackableTransactionAmount( ethers.utils.parseEther(amountToTransfer)) const closestPackableFee = zksync.utils.closestPackableTransactionFee( ethers.utils.parseEther(transferFee)) const transfer = await from.syncTransfer({ to: toAddress, token: token, amount: closestPackableAmount, fee: closestPackableFee }) const transferReceipt = await transfer.awaitReceipt() console.log('Got transfer receipt.') console.log(transferReceipt) } async function getFee(transactionType, address, token, zkSyncProvider, ethers) { const feeInWei = await zkSyncProvider.getTransactionFee(transactionType, address, token) return ethers.utils.formatEther(feeInWei.totalFee.toString()) } async function withdrawToEthereum (wallet, amountToWithdraw, withdrawalFee, token, zksync, ethers) { const closestPackableAmount = zksync.utils.closestPackableTransactionAmount(ethers.utils.parseEther(amountToWithdraw)) const closestPackableFee = zksync.utils.closestPackableTransactionFee(ethers.utils.parseEther(withdrawalFee)) const withdraw = await wallet.withdrawFromSyncToEthereum({ ethAddress: wallet.address(), token: token, amount: closestPackableAmount, fee: closestPackableFee }) await withdraw.awaitVerifyReceipt() console.log('ZKP verification is complete') } async function displayZkSyncBalance (wallet, ethers) { const state = await wallet.getAccountState() if (state.committed.balances.ETH) { console.log(`Commited ETH balance for ${wallet.address()}: ${ethers.utils.formatEther(state.committed.balances.ETH)}`) } else { console.log(`Commited ETH balance for ${wallet.address()}: 0`) } if (state.verified.balances.ETH) { console.log(`Verified ETH balance for ${wallet.address()}: ${ethers.utils.formatEther(state.verified.balances.ETH)}`) } else { console.log(`Verified ETH balance for ${wallet.address()}: 0`) } } module.exports = { getZkSyncProvider, getEthereumProvider, depositToZkSync, registerAccount, displayZkSyncBalance, transfer, withdrawToEthereum, getFee, initAccount }
(async () => { const ethers = require('ethers') const zksync = require('zksync') const utils = require('./utils') const token = 'USDT' const amountToDeposit = '6.0' const amountToTransfer = '2.0' const amountToWithdraw = '2.0' const zkSyncProvider = await utils.getZkSyncProvider(zksync, process.env.NETWORK_NAME) const ethersProvider = await utils.getEthereumProvider(ethers, process.env.NETWORK_NAME) console.log('Creating a new Rinkeby wallet for Alice') const aliceRinkebyWallet = new ethers.Wallet(process.env.ALICE_PRIVATE_KEY, ethersProvider) console.log(`Alice's Rinkeby address is: ${aliceRinkebyWallet.address}`) console.log('Creating a zkSync wallet for Alice') const aliceZkSyncWallet = await utils.initAccount(aliceRinkebyWallet, zkSyncProvider, zksync) const tokenSet = zkSyncProvider.tokenSet const aliceInitialRinkebyBalance = await aliceZkSyncWallet.getEthereumBalance(token) console.log(`Alice's initial balance on Rinkeby is: ${tokenSet.formatToken(token, aliceInitialRinkebyBalance)}`) await aliceZkSyncWallet.approveERC20TokenDeposits(token) console.log('Depositing') await utils.depositToZkSync(aliceZkSyncWallet, token, amountToDeposit, tokenSet) await utils.displayZkSyncBalance(aliceZkSyncWallet, tokenSet) await utils.registerAccount(aliceZkSyncWallet) console.log('Transferring') const transferFee = await utils.getFee('Transfer', aliceRinkebyWallet.address, token, zkSyncProvider, tokenSet) await utils.transfer(aliceZkSyncWallet, process.env.BOB_ADDRESS, amountToTransfer, transferFee, token, zksync, tokenSet) console.log('Withdrawing') const withdrawalFee = await utils.getFee('Withdraw', aliceRinkebyWallet.address, token, zkSyncProvider, tokenSet) await utils.withdrawToEthereum(aliceZkSyncWallet, amountToWithdraw, withdrawalFee, token, zksync, tokenSet) })()

Awesome! Now, there's one last thing left before we move to the utils.js file.

Your application will use the tokenSet object to convert values between BigNumber and a human-readable format (and vice versa), so the functions in the utils.js module will need to be updated to take a TokenSet instance as a parameter instead of ethers.

Put it to the test

  1. In the tab to the right, update the lines of code that call the following functions:
  • utils.depositToZkSync. This function should take the following parameters:
    • aliceZkSyncWallet
    • token
    • amountToDeposit
    • tokenSet
  • utils.displayZkSyncBalance. This function should take the following parameters:
    • aliceZkSyncWallet
    • tokenSet
  • utils.getFee. This function should take the following parameters:
    • 'Transfer' or 'Withdraw'
    • aliceRinkebyWallet.address
    • token
    • zkSyncProvider
    • tokenSet
  • utils.transfer. This function should take the following parameters:
    • aliceZkSyncWallet
    • process.env.BOB_ADDRESS
    • amountToTransfer
    • transferFee
    • token
    • zksync
    • tokenSet
  • utils.withdrawToEthereum. This function should take the following parameters:
    • aliceZkSyncWallet
    • amountToWithdraw
    • withdrawalFee
    • token
    • zksync
    • tokenSet

👉🏻 Be careful, the utils.getFee and utils.displayZkSyncBalance functions are invoked twice!