学習して使用する-ReactのMaterialUIフレームワークを使用して、EthereumウォレットのシンプルなMetaMaskのようなWebバージョンを開発します(7)

       前回の記事では、ウォレットのアカウントエクスポート機能を完了しました。今回は、ERC20トークンのリストを表示するウォレットの機能を開発する予定です。MetaMaskを模倣しているため、Erc20トークンを手動で追加することしかできません。

1.主な機能のデモンストレーション

       ユーザーがウォレットにログインした後、左上隅のメニューボタンをクリックすると、[マイアカウント]インターフェイスが表示されます。
ここに写真の説明を挿入

       このインターフェイスは、ドロワーを使用してMetaMaskに実装されています。つまり、ドロワーアニメーションがあります。Material UIのDrawerアニメーションはすべて全画面表示であり、ウォレットはWebページの画面中央のごく一部しか占めていないため、何度も試行した後、個人的な能力の問題により、Drawerを実装できません。そのため、この部分の処理を簡素化するために、一般的に使用されるルーティング機能を使用してジャンプします。興味のある読者は、マテリアルUIのドロワーアニメーションを調べることができます。

       インターフェイスでアカウントアドレスをクリックしてコピーし、[詳細]ボタンをクリックして、前の記事で実装したユーザー詳細インターフェイスを表示します。クリックしてトークン(ここではERC20トークン)を追加すると、次のインターフェイスが表示されます。
ここに写真の説明を挿入
       ここでは、MetaMaskインターフェイスと比較していくつかの簡略化も行っています。上部のテキストボックスに対応するネットワークのトークン契約アドレスを入力し、[クエリ]をクリックします。クエリが完了すると、トークンのシンボル、精度、およびトークンの残高が表示されます。入力したアドレスが有効なトークンアドレスでない場合は、アドレスが無効であるというプロンプトが表示されます。
ここに写真の説明を挿入
       [追加]ボタンをクリックして、トークンリストに追加します。ここのリストは上下にスクロールできることに注意してください。[キャンセル]をクリックすると、メインのウォレットインターフェイスに戻ります。トークンが追加されている場合は、プロンプトが表示されます。
ここに写真の説明を挿入
       リストにすでにGECトークンがあることがわかり
ここに写真の説明を挿入
       ます。GECトークンの右側にある展開ボタンをクリックすると、非表示のトークンを含むメニューが表示され、EtherScanで表示されます。非表示のトークンをクリックします(非表示はリストに表示されず、トークンが失われることはありません)、確認画面が表示されます。
ここに写真の説明を挿入
       [キャンセル]をクリックしてリストに戻り、[非表示]をクリックすると、GECトークンがリストから削除され、トークンに戻ります。通貨リストは、追加されなかったときと同じ画面が表示されます。GECトークンを再度表示する場合は、再度追加することしかできません。

       エアコインKHC(ウォレットはKHWalletと呼ばれ、コインはもちろんKHCoinsと呼ばれます)を発行し、それとGECをリストに
ここに写真の説明を挿入
       追加します。これですべてのトークンをリストに追加できます。追加された特定のトークンの関連情報を知りたい場合は、右側の拡張ボタンをクリックしてから、etherscanの表示ボタンをクリックすると、ブラウザーに表示されます。アドレスバーにはトークンアドレスが含まれていることに注意してください。
ここに写真の説明を挿入
       この開発では、リスト内のERC20トークンの追加、表示、および非表示のみが完了します。トークンをクリックして、ウォレットのメインインターフェイスにトークンを表示および転送する機能は開発されていません。これは次の開発で使用されますが、現在のアカウントのトークンバランス監視が実装されており、トークンバランスをリアルタイムで更新するために使用できます。

2.トークンバランス表示をテストします

       トークンの残高をリアルタイムで更新できるかどうかをテストしてみましょう。無料操作のためにKovanテストネットに切り替えましょう。前回の記事でKovantestnetのテストETH取得方法について説明しましたが、読者は私の一連の記事全体をチェックして、ウォレットを包括的に理解することを歓迎します。

       ウォレットとMetaMaskの両方を開いて、2つのアカウントを準備しましょう。1つはウォレットで使用し、もう1つはMetaMaskで使用します。次の図に示すように、どちらも同じトークンを追加します。
ここに写真の説明を挿入
       ご覧のとおり、左側のアカウントには988,004,400のテストがあります。トークン、右側のKovanアカウント2には200個のテストトークンがあります。100個のテストトークンをKovan2から私のアカウントに転送しましょう。

       MetaMaskトークンリストインターフェイスでテストコインをクリックし(開く方法はウォレットと同じです)、次のインターフェイスを入力します(これは次のステップで実装し
ここに写真の説明を挿入
       ます)。MetaMaskのメインインターフェイスに200個のテストトークンが表示されていることがわかります。コピーするウォレットのアカウントアドレスをクリックしてから、MetaMaskの送信ボタンをクリックします(ページを再度開く必要がある場合があります)。
ここに写真の説明を挿入
       アカウントをアドレスバーに直接貼り付け、数量列に100と入力します。[次へ]をクリックし、次の画面で[確認]​​をクリックして、ウォレットインターフェイスを見つめながら、トランザクションが完了するのを待ちます
ここに写真の説明を挿入
       。MetaMaskトークンが送信される前确认に、左側のウォレットのトークン残高が更新されています。これは、トランザクションイベントを監視およびフィルタリングすることでトークンの残高が更新され、イベントの受信がトランザクションの受信の確認よりも早くなるためです。

       MetaMaskを使用して自分のアカウントにログインし、100個のテストトークンをKovanアカウント2に送信するという逆テストを実行することもできます。トランザクションが確認される前に、左側のウォレットのトークン残高が更新されます。ここでは、これ以上デモンストレーションは行いません。

3、この開発の要点

       UIのスプライシング、更新、または表示の比較的大きなワークロードに加えて、この開発にはいくつかの設計またはコード作成ポイントもあります。

  1. ローカルストレージの設計。アカウントのトークンリストはローカルストレージに保存する必要があります。アカウントの形式、更新方法、および読み取り方法を慎重に設計する必要があります。具体的な実装はsrc\contexts\StorageProvider.jsここにあり、読者はより良いデザインのアイデアを持つこともできます。ここにメモの1つがあります:
/**  本地存储计划示例,
{

    "0x1234....":{
                    crypt:"ifajfay08",
                    erc20Tokens:{
                                    homestead:[
                                                {
                                                    address:'0x1234....'
                                                    balance:0x78,
                                                    symbol:'',
                                                    decimals:''

                                                },
                                                {
                                                    address:'0x1234....'
                                                    symbol:'',
                                                    decimals:''
                                                }
                                            ]
                                }
                  }
}
*/

       ローカルストレージはJson形式であり、各アドレスは暗号化されたキー(ログインに使用)と20個のトークンのリストに対応しています。その中で、20個のトークンのリストはネットワークによって区別されます。特定のネットワークの下にある20個のトークンはすべて配列です。配列の各要素は、アドレス、アカウント残高、シンボル、精度を含む20個のトークンオブジェクトです。

       ここに小さな詳細があります。Jsライブラリでは、Ethereumによって返される整数値はbigNumber形式であるため、ローカルに保存するときに16進文字列形式に変換され、ローカルで読み取って使用するときに最初に変換する必要がありますbigNumber

  1. ERC20トークン契約。トークンを扱う必要があるため、トークン契約が必要です。トークン契約の主な要素は、トークンのアドレス、トークン契約のABI、そしてもちろんそれが属するネットワークです。その中で、トークンコントラクトのABIは、通常のコンパイラによって生成されたABI、または人間が読み取れるABIです(ethers両方のライブラリを使用できます。作成者は他のライブラリを使用していません。必要に応じて自分で確認してください)。このウォレットで使用されているERC20トークンコントラクトのABIは読み取り可能なABIであり、コードは次のとおりです。
[
  "function balanceOf(address owner) view returns (uint)",
  "function decimals() view returns (uint8)",
  "function symbol() view returns (string)",
  "function allowance(address tokenOwner, address spender) view returns (uint)",
  "function transfer(address to, uint amount)",
  "function approve(address spender, uint amount)",
  "event Transfer(address indexed from, address indexed to, uint amount)",
  "event Approval(address indexed tokenOwner, address indexed spender, uint amount)"
]

       契約を取得するためのコードスニペットは次のとおりです。

//获取ERC20代币合约
export function getErc20Token(tokenAddress,network,wallet) {
    
    
    if(!isAddress(tokenAddress) || !network) {
    
    
        return null;
    }
    try{
    
    
        let provider = ethers.getDefaultProvider(network);
        if(wallet) {
    
    
            provider = wallet.connect(provider)
        }
        return new ethers.Contract(tokenAddress,ERC20_ABI,provider)
    }catch{
    
    
        return null
    }
}

       ここでも、読者がEthereumでのDappの開発に興味がある場合は、ethers最初にライブラリをお読みください

  1. アカウントのERC20トークンの残高を取得して更新するには、まず取得コードを見てみましょう。
//获取某个地址在某个token余额
export async function getTokenBalance(tokenContract,address) {
    
    
    return tokenContract.balanceOf(address).catch(error => {
    
    
        error.code = ERROR_CODES.TOKEN_BALANCE
        throw error
    })
}

       このコードは非常に単純balanceOfで、契約のメソッドを直接呼び出します。promiseを返すことに注意してください。

       リフレッシュの実装をもう一度見てみましょう。これは比較的複雑であり、より良い方法または最適化がある可能性があります。

//监听用户代币变化
useEffect(()=>{
    
    
    if(tokens.length > 1) {
    
    
        let stale = false
        let allContracts = []
        for (let token of tokens) {
    
    
            if(token.symbol !== 'ETH'){
    
    
                allContracts.push(getErc20Token(token.address,network,wallet))
            }
        }
        for (let contract of allContracts) {
    
    
            let filter1 = contract.filters.Transfer(wallet.address,null)
            let filter2 = contract.filters.Transfer(null,wallet.address)
            // eslint-disable-next-line
            contract.on(filter1,(from,to,amount,event) => {
    
    
                getTokenBalance(contract,wallet.address).then(_balance => {
    
    
                    if(!stale) {
    
    
                        updateTokenBalance(wallet.address,network,contract.address,_balance)
                    }
                })
            })
            // eslint-disable-next-line
            contract.on(filter2,(from,to,amount,event) => {
    
    
                getTokenBalance(contract,wallet.address).then(_balance => {
    
    
                    if(!stale) {
    
    
                        updateTokenBalance(wallet.address,network,contract.address,_balance)
                    }
                })
            })
        }

        return () => {
    
    
            stale = true
            for (let contract of allContracts) {
    
    
                contract.removeAllListeners('Transfer')
            }
        }
    }
},[tokens,network,wallet,updateTokenBalance])

       ここでは、すべてのトークンコントラクトのリスナーを設定して、そのTransferイベントをリッスンします。フィルタを個別に設定して、送信者または受信者がユーザーアカウントであるイベントを除外します。イベントを聞いた後、ユーザーの最新の残高を取得して更新します。インターフェイスが終了したら、すべてのリスナーをキャンセルします。

       そこ懸念している配列の純粋配列(追加なしプロパティ)のために少しヒントは、もあり、for (let key of arrays)そしてfor (let key in arrays)用語が異なっている、かつての買収は、あなたが間違って使用することを注意しないと使用する場合、標準の下で得られる元素であり、 。

4、まとめ

       これまでの数回に比べて、この開発は比較的複雑で時間がかかります。詳細なテストはありません。欠陥やエラーがあれば、読者は読んだり使用したりする過程で訂正をお願いします。ありがとうございます。

       開発が深まるにつれ、マテリアルUIフレームワークのすべてのコンポーネントのすべての属性、さらにはすべてのCSSルールを明確にする必要があると感じるようになります。ただし、これは長期的なプロセスであり、基礎となる実装を深く掘り下げることは困難です。したがって、マテリアルUIフレームワークのすべてのコンポーネントを学習し続け、過去を確認して新しいコンポーネントを学習することが非常に必要です。コンポーネントの一般的に使用される属性の使用法を知る必要があるだけでなく、一般的に使用されるCSSルールとは何かおよびそれらを変更する方法も知る必要があります。Material UIを習得していなくても、Vueでいくつかのフレームワークを習得していても、同じことが言えると思います。

       特定のUIコードは煩雑で複雑なので、ここでは例を示しません。コードをダウンロードして確認できます。

       さらに、CSS、アート、科学、悪夢(知っておくべきことすべて)の記事をお勧めします私はフロントエンド開発者ではありませんが、個人的にはこれはすべてのフロントエンド開発者にとって必読の記事だと思います。

       次の開発では、ERC20トークンの転送機能を実装する予定です。

       このウォレットコードクラウド(gitee)ウェアハウスアドレスは次のとおりです。=> https://gitee.com/TianCaoJiangLin/khwallet

       読者は、エラーを指摘したり、改善を提案したりするためにメッセージを残すことができます。

おすすめ

転載: blog.csdn.net/weixin_39430411/article/details/104145456