Skip to content

Latest commit

 

History

History
177 lines (148 loc) · 7.16 KB

10.md

File metadata and controls

177 lines (148 loc) · 7.16 KB
title actions requireLogin material
The shopkeeper - Talking to the blockchain
checkAnswer
hints
true
editor
language startingCode answer
JavaScript
src/bob.js src/utils.js
(async () => { const ethers = require('ethers') const zksync = require('zksync') const utils = require('./utils') // Start here })()
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 zkSyncProvider = await utils.getZkSyncProvider(zksync, process.env.NETWORK_NAME) const ethersProvider = await utils.getEthereumProvider(ethers, process.env.NETWORK_NAME) })()

Great! Writing the functions that interact with zkSync was the difficult part — now implementing the Node.JS applications for the shopkeeper (Bob) and the customer (Alice) will be straightforward. But before you do that, note that we've added a module.exports object to the utils.js file. This specifies which functions and variables Node.js should export from this file.

Top-level await

All the functions you added to the utils.js file are asynchronous, but Node.js only allows you to place the await operator inside an async function. A common solution is to wrap your code in an immediately invoked async function.

If this sounds complicated, then let's take an example:

(async () => {
  await myAsyncFunction()
})()

Do you see? That wasn't complicated at all.

Now let's put what you've learned together and start fleshing out the shopkeeper application.

Put it to the test

We've created a new file for you called bob.js, added an immediately invoked function, and imported the following modules: ethers, zksync, ./utils.

  1. To connect to zkSync, you must create a zkSync provider by calling the utils.getZkSyncProvider function. It's an async function that takes two parameters: zksync, process.env.NETWORK_NAME. Store the result in a const variable named zkSyncProvider.

Note: The process.env property returns an object that represents your environment. Before you run this Node.js application, you must set the value of the NETWORK_NAME environment variable as follows:

  export NETWORK_NAME=rinkeby
  1. The code for creating a Rinkeby provider is almost identical. Just call a function named utils.getEthereumProvider and store the result in a const variable named ethersProvider. The function takes the following two parameters: ethers, and process.env.NETWORK_NAME.