Skip to content

Latest commit

 

History

History
246 lines (211 loc) · 11.5 KB

01.md

File metadata and controls

246 lines (211 loc) · 11.5 KB
title actions requireLogin material
Intro
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 = 'ETH' // Update this line const amountToDeposit = '0.05' // Update this line const amountToTransfer = '0.02' // Update this line const amountToWithdraw = '0.002' // Update this line 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}`) const aliceInitialRinkebyBalance = await aliceRinkebyWallet.getBalance() console.log(`Alice's initial balance on Rinkeby is: ${ethers.utils.formatEther(aliceInitialRinkebyBalance)}`) console.log('Creating a zkSync wallet for Alice') const aliceZkSyncWallet = await utils.initAccount(aliceRinkebyWallet, zkSyncProvider, zksync) console.log('Depositing') await utils.depositToZkSync(aliceZkSyncWallet, token, amountToDeposit, ethers) await utils.displayZkSyncBalance(aliceZkSyncWallet, ethers) await utils.registerAccount(aliceZkSyncWallet) console.log('Transferring') const transferFee = await utils.getFee('Transfer', aliceRinkebyWallet.address, token, zkSyncProvider, ethers) await utils.transfer(aliceZkSyncWallet, process.env.BOB_ADDRESS, amountToTransfer, transferFee, token, zksync, ethers) console.log('Withdrawing') const withdrawalFee = await utils.getFee('Withdraw', aliceRinkebyWallet.address, token, zkSyncProvider, ethers) await utils.withdrawToEthereum(aliceZkSyncWallet, amountToWithdraw, withdrawalFee, token, zksync, ethers) })()
(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}`) const aliceInitialRinkebyBalance = await aliceRinkebyWallet.getBalance() console.log(`Alice's initial balance on Rinkeby is: ${ethers.utils.formatEther(aliceInitialRinkebyBalance)}`) console.log('Creating a zkSync wallet for Alice') const aliceZkSyncWallet = await utils.initAccount(aliceRinkebyWallet, zkSyncProvider, zksync) console.log('Depositing') await utils.depositToZkSync(aliceZkSyncWallet, token, amountToDeposit, ethers) await utils.displayZkSyncBalance(aliceZkSyncWallet, ethers) await utils.registerAccount(aliceZkSyncWallet) console.log('Transferring') const transferFee = await utils.getFee('Transfer', aliceRinkebyWallet.address, token, zkSyncProvider, ethers) await utils.transfer(aliceZkSyncWallet, process.env.BOB_ADDRESS, amountToTransfer, transferFee, token, zksync, ethers) console.log('Withdrawing') const withdrawalFee = await utils.getFee('Withdraw', aliceRinkebyWallet.address, token, zkSyncProvider, ethers) await utils.withdrawToEthereum(aliceZkSyncWallet, amountToWithdraw, withdrawalFee, token, zksync, ethers) })()

By completing Lesson 17, you got a good grasp of the basic functions and concepts of zkSync. Now you're going to modify the Node.js applications you've created so that Alice could pay Bob using ERC20 tokens. In this tutorial, we are going to use USDT, a stablecoin pegged against the U.S. dollar, but your application can use any ERC20 token supported by the protocol.

👉🏻For the full list of supported tokens, see the supported tokens on Rinkeby page.

Before we get into the meat and potatoes, let's get yourself some Rinkeby USDT tokens. All you have to do is to follow these steps:

  1. Navigate to this contract address
  2. Click the Connect to Web3 link, and then select the wallet you want to use. Note that we recommend MetaMask.
  3. Select the Write Contract tab
  4. To get to the end of this lesson, you must mint at least six USDT tokens. Scroll down to the mint function, and populate the following fields:
  • _to: enter your Rinkeby address
  • _amount: enter 6000000 (the USDT token has six decimal places)
  1. Select the Write button.
  2. You'll see a Metamask popup. To approve the transaction, select the Confirm button.

Now let's get back to why we're here. The first thing you'll have to do is to configure the src/alice.js script to use USDT instead of ETH for deposits, transfer, and withdrawals.

Put it to the test

  1. Change the value of the token variable to 'USDT'
  2. Change the value of the amountToDeposit to '6.0'
  3. Change the value of the amountToTransfer and amountToWithdraw variables to '2.0'

👉🏻 We've left comments in the code to make these lines easy to find.