前回の開発では、ユーザーアカウントのERC20トークンリストを表示したときに、リストの表示中にユーザーのトークン残高を更新する機能がありませんでした。この開発では、最初にこの関数を追加してから、ERC20トークンの転送関数を完了します。
1.ユーザーERC20トークンの残高を更新します
前回の開発では、ユーザーのERC20トークンの残高は、トークンを追加するときに1回だけ取得されました。表示リストインターフェイスでは、ユーザートークン変更イベントのみが監視されますが、ウォレットが開かれたときにこのイベントがブロードキャストされない場合、監視できないため、ユーザーアカウントのトークン残高は更新されません。また、通常のロジックによれば、以下に示すように、ユーザートークンリストが表示されると、最新のトークン残高が自動的に表示されます。
React関数コンポーネントで同様の操作を実行する通常の方法は、コンポーネントがロードさuseEffect
れた後にそれを使用してユーザートークンの残高を取得し、対応するトークン情報を更新することです。トークンバランスを取得するには、トークンアドレスなどの他のトークン情報が必要useEffect
であるため、トークン情報を更新するためのこの依存関係では、トークン情報自体を使用する必要があります。これにより、無限ループが発生します。具体的なプロセスは次のとおりです。
コンポーネントがロードされると、トークンバランスが表示されます=>最新のトークンバランスを取得し、トークン情報を更新します=>コンポーネントを再レンダリングします=>依存関係トークン情報の更新によって引き起こされた再実行のuseEffect
コンテンツ=>トークンバランスを再度取得して更新します=>レンダリングして再取得します、無限ループ。
したがって、状態変数を使用して、このユーザートークン残高の繰り返し取得を制御する必要があります。まず、この変数をfalseに設定します。残高が取得されている場合は、残高を更新する前に変数をtrueに設定します。天びんを更新して再レンダリングした後、変数がfalseであるかどうかを確認します。そうでない場合は、更新されたことを意味し、再度更新をスキップします。同時に、ユーザーアカウントまたはネットワークの変更により、この変数をfalseにリセットして、他のアカウントまたはネットワークに対応するトークンの最新の残高を取得できるようにする必要があります。コードスニペットを見てみましょう:
const [isRefresh,setIsRefresh] = useState(false)
//每次切换网络或者用户时,更新刷新状态
useEffect(()=> {
if(wallet && network){
setIsRefresh(false)
}
},[wallet,network])
//每次打开界面时只更新一次代币余额
if(!isRefresh) {
Promise.all(allPromise).then(results => {
//更新所有代币余额
for(let i=0;i<len;i++) {
tokens[i].balance = results[i]
}
if(!stale) {
setIsRefresh(true)
updateAllTokens(wallet.address,network,tokens)
}
}).catch( () =>{
})
}
ここでのコードの最初の行は、トークンの残高が取得されたかどうかをマークするために使用される状態変数を設定することです。2番目のコードは、アカウントまたはネットワークが変更されたときにステータスをリセットすることであり、3番目のコードは、ステータスがfalseの場合にすべてのトークン残高を更新することです。
更新コードはバックグラウンドに配置することもできます。つまりsrc\contexts\StorageProvider.js
、プロセスでは、更新処理はユーザーのETHバランス更新処理と同様です。ただし、ユーザートークンバランスは、トークンリストを表示してトークンを送信する場合にのみ使用され、更新回数を減らすために、対応するインターフェースに配置されて処理されます。
2.この開発の簡単な説明
この開発は、主にユーザートークン転送の機能を実現することです。今回の開発は、主に以前に実装されたETH転送に基づいていくつかの変更が行われたため、難しくありません。
ユーザーのERC20担当者の任意のトークンをクリックして、ウォレットのメインインターフェイスに入り、トークンを表示します。上
の図のメインインターフェイスはGECトークンを示しており、表示されると残高が自動的に更新されます。同時に、トランザクションイベントを監視してリアルタイムで更新します。処理方法は、上記のユーザートークン残高を更新する方法と同様です。
送信ボタンをクリックすると、ETHの送信と同様のインターフェイスが表示されます。
受信者のアドレスと送信する数量を入力します。数量は小数にすることもできます。次に、送信ボタンをクリックすると、確認ポップアップが表示され、[OK]をクリックすると、短い読み込みアニメーションの後に簡単なトランザクション情報インターフェイスが表示されます。
注:ETHの送信とトークンの両方に手数料が必要であり、少量のETHが消費されます。送信に失敗した場合は、ウォレットのメインインターフェイスに戻って、十分なETHがあるかどうかを確認してください。
注:このインターフェースでネットワークを切り替えることができます。あるネットワークのトークンは別のネットワークには存在せず、ETHも存在するため、ネットワークを切り替えると、ウォレットは自動的にETHを送信するようになります。ここで、ユーザーは間違って送信しないように注意する必要があります。
ネットワークをKovanテストネットワークに切り替えると、上記のように、100GECの送信が100ETHになることがわかります。私のETHの量はそれほど多くないので、最初のETHは送信できず、2番目のウォレットがプロンプトを表示します。ただし、ユーザーが1 GECを送信すると、ここでは1 ETHになり、送信する可能性は十分にあります。
[キャンセル]をクリックして、メインインターフェイスに戻りましょう。上記の操作に続いて、この時点でネットワークはKovanテストネットワークになりました。このネットワークでテストする必要があります。左上隅のメニューボタンをクリックします。
[FIXEDトークン]をクリックし、メインインターフェイスをもう一度入力して、送信プロセスを再開します。を
クリックします。送信すると、確認ボタンがポップアップ表示され、ユーザーは送信エラーを防ぐために送信前に最後を確認できます。
[OK]をクリックすると、読み込み中のアニメーションが表示され、Ethereumのトークンコントラクトが呼び出されてトークンが転送されます。トランザクションが送信された後、簡単なトランザクション情報インターフェイスに入ります
。ETHを送信するときのトランザクション情報と比較して、トランザクションタイプ情報を追加しました。現在、このインターフェイス上の一部のテキストの位置はあまり整列しておらず、慎重に調整する必要があります。
Kovanテストネットは非常に迅速にブロックを生成するため、トランザクションが完了するまで辛抱強く待ってください。トランザクションはすぐに確認する必要があります。完成したインターフェースは以下のとおりです。この時点で、トランザクションステータスが更新され、保留中のアニメーションが停止しています。
メインインターフェイスに入った後にトークンバランスが更新されるため、戻るボタンをクリックしてメインウォレットインターフェイスに戻ります。このインターフェイスでのトークンバランス更新アクションも確認できます。つまり、下の図では2090が1990になります。
さて、この開発の主な機能が紹介されています。完全なコードについては、まだgitリポジトリにアクセスします。ここにいくつかのポイントがあります。
第三に、コードポイントの導入
tokenSelectedIndex
ETHやGECなど、現在選択されているトークンを表すグローバル変数を追加しました。トークンリストで現在選択されている通貨には、バックグラウンドプロンプトが表示されます。
const {
network,wallet,ethPrice,tokenSelectedIndex} = useGlobal()
開発機能の紹介の最後に、ウォレットのメインインターフェイスにFIXEDトークンが表示されるので、左上隅のメニューボタンをクリックすると、トークンリストのFIXEDトークンが選択済みとして表示されます。トークンを選択しない場合、デフォルトでETHが選択され、現在選択されているトークンを非表示にすると、ETHも選択されます。
あるネットワークのトークンは別のネットワークには存在しないため、ネットワークを切り替えるたびにETHを選択するように設定されています。
const handleSelected = key => () => {
if(selectedIndex === key) {
return;
}
setSelectedIndex(key)
setOpen(false);
updateGlobal({
tokenSelectedIndex:0,
network:NET_WORKS[key]
})
};
ここではクロージャーが使用されています。関数コンポーネントにはこれがないため、クラスコンポーネントで一般的に使用されるthis.handleSelected.bind(this,key)
このメソッドを使用して、関数のバインド中にパラメーターを渡すことはできません。関数コンポーネントでクリックイベントをバインドする一般的な方法は、クロージャを使用してパラメータを渡すための新しい関数を生成することです。別の方法はvalue
、クリック関数がバインディングe.currentTarget.value
値をとるときに、オブジェクトプロパティに特定のクリックを設定することです。ただし、この値は常に使用できるとは限りません。クロージャを使用する方が便利な場合もあります。パラメータを渡す必要がある場合は、クロージャを使用してクリックイベントをバインドすることをお勧めします。
- トークンを送信するために契約を呼び出します。ここのコードは簡単に説明しています。
if(isToken) {
//将钱包绑定合约直接调用方法进行
let contract = getErc20Token(token.address,network,wallet)
if(contract) {
let amount = convertFixedToBigNumber(eth_amount,token.decimals)
let args = [_address,amount]
contract.transfer(...args).then(tx => {
setCircleOpen(false)
if(sendCallback){
sendCallback(tx,eth_amount,SYMBOL)
}
}).catch(err =>{
setCircleOpen(false)
return showSnackbar(SYMBOL + "发送失败",'error')
})
}else{
setCircleOpen(false)
return showSnackbar("合约未初始化,请稍候",'info')
}
}
コードの3行目は、対応するウォレットにバインドされているコントラクトオブジェクトを取得することです。つまり、バインドされたコントラクトは、コントラクトデータを読み取るメソッドview
またはコントラクトデータpure
を書き換えるメソッドのいずれかを呼び出すことができます。実際、contract.transfer(...args)
この関数呼び出しには、オプションである追加のオプションパラメータを含めることもできます。これは、前の記事で説明した直接ETH転送中に作成されたトランザクションオブジェクトに似ています。たとえば、トランザクションで送信されるETHの量を設定したり、chainIdを設定したりできます。
4、まとめ
この開発は、最初に前の開発からの省略を構成し、次にERC20トークン転送のETH転送に基づいて適切に変更しました。主な演習useEffect
は、ユーザートークンの残高が無制限に更新されないようにすることと、トークンを転送するために契約を呼び出す方法です。このウォレットには、変更されていない別の欠陥があります。つまり、eth価格はetherscanから取得されます。イーサスキャンAPIはラダーなしではアクセスできません。次の開発時に別のデータソースに変更する予定です。
ウォレットには、アカウントの作成、ログイン、インポートとエクスポート、ERC20トークンの追加、表示、非表示と送信、ERC20トークンの残高のリアルタイムでの表示と更新、ETHの送信とETH残高のリアルタイムでの更新、メインネットワークのサポート、 3つの主要なテストネットワークは実際にGoerliテストネットワークをサポートできますが、それほど多くを作成する必要はありません。現在、複数のアカウントと履歴レコードの保存はサポートされていません。
開発計画から実装されていないウォレットの機能は1つだけです。それは、署名トランザクションです。これは単純なWebウォレットであるため、トランザクションデータはURL経由でのみ送信してから署名することができます。実装方法は少し醜いです。次の開発で実装する予定です。
さらに、限られた時間のために、ローカルlocalhostノードのアプリケーションは開発のために計画されていません。次の開発でlocalhostネットワークをキャンセルし、開発する時間があれば後で追加する予定です。
このウォレットコードクラウド(gitee)ウェアハウスアドレスは次のとおりです。=> https://gitee.com/TianCaoJiangLin/khwallet
読者は、エラーを指摘したり、改善を提案したりするためにメッセージを残すことができます。