Budowanie frontendów
dla aplikacji Ethereum

Co wiedzieć, zanim zaczniesz web3

w 6 księgach zapisane

Księgi

  • Blockchain dla nerdów
  • Dapps
  • Testy
  • Wyzwania
  • Tokeny ERC-20
  • Przegląd projektów
  • blockchain
  • crypto
  • web3

Pytania

  • Czy wiesz, co to web3?
  • Czy uczysz się czegoś o web3?
  • Czy robisz już coś w web3?
  • Czy uważasz, że warto inwestować czas na naukę?

10 miesięcy

Od rozpoczęcia pracy z blockchain

web2 vs web3

o różnicach, o tradeoffach

Kim jestem, co robię…

  • Mam na imię Kuba
  • Prowadzę kanał JS Dżem
  • +5 lat doświadczenia na frontendzie
  • TypeScript
  • React + Redux
JS Dżem on YouTube

Księga pierwsza

Blockchain dla nerdów

Po co Ci blockchain?

  • Zaufana trzecia strona jest niezbędna, aby zapobiec podwójnemu wydaniu tych samych środków
  • Dowód kryptograficzny zamiast centralnego zaufania
  • Zaufanie do sieci, a nie do instytucji

“Z punktu widzenia tworzenia oprogramowania jedną z największych zmian wydaje się zakwestionowanie tradycyjnej, centralnej bazy danych. Musimy więc dogłębnie przemyśleć w jaki sposób blockchain zmusza nas do przemyślenia istniejących konstrukcji baz danych.”

—William Mougayar, Vitalik Buterin,
The Business Blockchain
Rafał Kiełbus wyjaśnia krypto

Dlaczego dotychczas nie płaciłeś PRZEZ INTERNET?

Co to w ogóle znaczy "płacić przez internet"?

Wire transfer? 😂

Wire
p2p vs banks

publiczny i (ale) anonimowy

  • Transakcje są publiczne (id)
  • Jesteś anonimowy, dopóki nie znają twojego adresu 🧵
  • Transparentność
    • Pewność że moje pieniądze nigdzie nie znikną
    • Łatwość wyśledzenia przestępców

Open source

Księga druga

Dapps

Disclaimer

  • only MetaMask wallet 🦊
  • ⚛️ React + optional Redux
  • ethers.js
  • no high level solutions (useDapp, Drizzle)
  • 🙅‍♂️ no Solidity, no smart contracts
  • only ERC-20, no NFTs

Dlaczego Ethereum?

Infura https://a16zcrypto.com/state-of-crypto-report-a16z-2022/

Decentralized front-end

  • no backend (❌CRUD, ❌REST, ❌HTTP)
  • no HTTP requests (❌fetch, ❌axios)
  • Talks directly to blockchain ✅
  • blockchain node (read) ✅
  • wallet (read, write) ✅
  • no matter where deployed ✅
  • IPFS ✅

Wszystko jest to samo

😎

tylko łączysz się z węzłem sieci Ethereum
zamiast serwerem HTTP.

Nie wyklucza to, że pewne dane
mogą być pobierane
z centralizowanych serwerów

🗯

  • optymalizacji kosztów
  • dane wtórne
  • mało istotne dane
  • niewraliwe

How to get connected to the blockchain?

  1. Get smartcontract address and its ABI (Application Binary Interface)
  2. Initialize a provider (wallet, node)
  3. Create a smartcontract class instance - SM abstraction in JS
  4. Call a contract method to get or set data in a blockchain
  5. You can also Listen to the events on smartcontract (pooling, web sockets)

Smartcontract address & ABI

Czy ABI to takie inne API?

❌ Nie pobieram ABI z zewnętrznych źródeł

✅ Zawsze hardkoduję adresy smartkontraktów

dlaczego ❓

Connecting to a node

  • Why do I need a node?
  • When to use my own node (Infura, Alchemy)?
  • Can any front-end connect to any smart contract?

Node providers

Infura Infura
Alchemy Alchemy

Platforms

Using smart contract methods

  • type of methods: read and write
  • no put/patch and delete substitutes (blockchain design)

READ methods

  • free 🆓 you don't pay ETH for gas
  • no wallet required, shared node is enough
  • () ⇒ Promise<Result>
  • no event emitted

WRITE methods

  • cost you to pay for gas
  • connected wallet required
  • () ⇒ Promise<{ wait: () ⇒ Promise<Receipt> }>
  • can emit events
  • one SC can contain read and write methods

You have to pay for gas,
even if transaction failed

pay the bill

👮‍♂️ DDos protection

Jeśli to możliwe,
łącz się przez wallet

Read and write 1 Read and write 2
https://www.youtube.com/watch?v=kDan1tp4hpA

Księga trzecia

Testy

Unit test

  • smart contracts covered on Solidity level
  • there's no difference if you use web3
  • unit test should be blockchain unaware, detached
  • if you use React, just test components or functions

E2E tests

Dev tools

MetaMask requests
doesn't affect network tab
in browser dev tools

  • no throttling
  • browser doesn't treat SC call like HTTP request
  • MetaMask is a black box

Wallet is a blackbox

Integration tests

  • @testing-library
  • implementation agnostic
  • how front-end deals with errors
  • only services are mocked

Services

Services Services Services

Environments

Environments

Księga czwarta

Wyzwania

Arytmetyka na frontendzie

  • biblioteka BigNumber
  • nawet do 27 miejsc po przecinku
  • ewentualnie liczby w stringach

Primitive obsession


export type LiquidationDepositAmount = string & {
  type: 'LIQUIDATION_DEPOSIT_AMOUNT';
};
export type OpeningFeeRate = string & {
  type: 'OPENING_FEE_RATE';
};
export type OpeningFeeAmount = BigNumber & {
  type: 'OPENING_FEE_AMOUNT';
};
          

Data received from blockchain to JS

  • fake Array - actually it has fields like object
  • depends on provided ABI format
  • TypeScript typings rather expect Array. If you want to read it as object, you need to assert your own type.
  • example: getMySwaps

Non-serializable data

Non-serializable data

Non-serializable data

  • BigNumber is non-serializable - redux, localStorage 😞
  • ethers.js returns BigNumber instance for uint256 and other number format
  • UI wants text representation
  • number string?
  • What if I have many calcs and conversion?
  • Referential equality matters, no value equality - React 🙈

Redux architecture case

service ➡️ BN ➡️ string ➡️ reducer ➡️ store ➡️ selector (BN for calcs) ➡️ component ➡️ (BN)

Inaczej są wyrzucane błędy przez metamask a inaczej przez Infurę


const getErrorCode = (error: unknown): UserErrorCode => {
  if (!(error instanceof Error)) {
    /**
      * If contract method is called via Metamask wallet
      * then error is non-Error type
      * and has different structure than thrown via public RCP provider
      */
    if (isErrorFromWallet(error)) {
      const code = getErrorFromWalletCode(error);

      if (code) {
        return code;
      }
    }

    /**
      * Non contract related errors
      * Metamask's errors are non-Error type
      */
    if (isMetamaskError(error)) {
      const code = getMetamaskErrorCode(error);

      if (code) {
        return code;
      }
    }

    return 'UNEXPECTED_ERROR';
  }

  /**
    * If contract method is called via Public RCP provider
    * then error is Error type
    * and has different structure than thrown via Metamask wallet
    */
  if (isErrorFromPublicRcp(error)) {
    const code = getErrorFromPublicRcpCode(error);

    if (code) {
      return code;
    }
  }

  if (error instanceof TypeError) {
    return 'UNEXPECTED_ERROR';
  }

  return 'UNEXPECTED_ERROR';
};
          

Error logging

  • No server logs
  • No idea what's on client side

It's a good practice to log errors anyway,
regardless it's either web3 or web2

TypeScript vs Smart Contract (ABI)

  • Typechain
  • Custom class interface - code editor: UserAsset.ts

Czytanie danych z logów i eventów

Księga piąta

Tokeny ERC-20

Smart Contracs interactions

ERC20 standard

https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/IERC20.sol

UX vs security

unlimited allowance

https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/IERC20.sol

Księga szósta

Przegląd projektów

Web3 Devs PL

https://web3devs.pl/