배우고 사용하기 --React에서 Material UI 프레임 워크를 사용하여 Ethereum 지갑의 간단한 MetaMask와 유사한 웹 버전을 개발하십시오. (7)

       이전 기사에서는 지갑의 계정 내보내기 기능을 완료했습니다. 이번에는 ERC20 토큰 목록을 표시하는 지갑 기능을 개발할 계획입니다. MetaMask를 모방하고 있기 때문에 Erc20 토큰을 수동으로 만 추가 할 수 있습니다.

1. 주요 기능 데모

       사용자가 지갑에 로그인 한 후 왼쪽 상단의 메뉴 버튼을 클릭하면 내 계정 인터페이스가 나타납니다.
여기에 사진 설명 삽입

       이 인터페이스는 서랍이있는 MetaMask에서 구현됩니다. 즉, 서랍 애니메이션이 있습니다. 머티리얼 UI의 서랍 애니메이션은 모두 전체 화면이며, 우리 지갑은 웹 페이지 화면 중앙의 작은 부분 만 차지하므로 여러 번 시도하면 개인 능력 문제로 인해 서랍을 구현할 수 없습니다. 따라서 일반적으로 사용되는 라우팅 기능은이 부분의 처리를 단순화하기 위해 점프하는 데 사용됩니다. 관심있는 독자는 Material UI의 서랍 애니메이션을 공부할 수 있습니다.

       복사 할 인터페이스에서 계정 주소를 클릭하고 세부 정보 버튼을 클릭하면 이전 기사에서 구현 한 사용자 세부 정보 인터페이스가 표시됩니다. 클릭하여 토큰 (여기서는 ERC20 토큰)을 추가하면 다음과 같은 인터페이스가 나타납니다.
여기에 사진 설명 삽입
       여기서는 MetaMask 인터페이스와 비교하여 몇 가지 단순화를 수행했습니다. 상단 텍스트 상자에 해당 네트워크의 토큰 계약 주소를 입력하고 쿼리를 클릭합니다. 쿼리가 끝나면 토큰의 기호, 정확도 및 토큰 잔액이 표시됩니다. 입력 한 주소가 유효한 토큰 주소가 아닌 경우 주소가 유효하지 않다는 메시지가 표시됩니다.
여기에 사진 설명 삽입
       추가 버튼을 클릭하여 토큰 목록에 추가하세요. 여기에있는 목록은 위아래로 스크롤 할 수 있습니다. 취소를 클릭하면 메인 지갑 인터페이스로 돌아가며 토큰이 추가 된 경우 프롬프트가 표시됩니다.
여기에 사진 설명 삽입
       목록에 이미 GEC 토큰이 있음을 알 수 있습니다. GEC 토큰 오른쪽에있는 확장 버튼을 클릭하면 숨겨진 토큰이 포함 된 메뉴가 나타나고 EtherScan에서 볼 수 있습니다. 숨겨진 토큰
여기에 사진 설명 삽입
       을 클릭합니다 (숨겨진 것은 목록에 표시되지 않고 토큰을 잃지 않습니다) 확인 화면이 나타납니다.
여기에 사진 설명 삽입
       취소를 클릭하여 목록으로 돌아가고 숨기기를 클릭하면 GEC 토큰이 목록에서 삭제되고 토큰으로 반환됩니다. 통화 목록에는 추가되지 않았을 때와 동일한 화면이 표시됩니다. GEC 토큰을 다시 표시하려면 다시 추가 만 할 수 있습니다.

       에어 코인 KHC (지갑은 KHWallet, 코인은 당연히 KHCoins)를 발행하고 목록에 GEC를
여기에 사진 설명 삽입
       추가합니다. 이제 모든 토큰을 목록에 추가 할 수 있습니다. 추가 된 특정 토큰의 관련 정보를 알고 싶다면 오른쪽 확장 버튼을 클릭 한 후 etherscan에서보기 버튼을 클릭하면 브라우저에서 확인할 수 있습니다. 주소 표시 줄에는 토큰 주소가 포함되어 있습니다.
여기에 사진 설명 삽입
       이 개발은 목록에서 ERC20 토큰의 추가, 표시 및 숨기기 만 완료합니다. 토큰을 클릭하여 지갑의 메인 인터페이스에서 토큰을 표시하고 전송하는 기능은 개발되지 않았습니다. 이는 다음 개발에 적용되지만 현재 계정의 토큰 잔액 모니터링이 구현되어 토큰 잔액을 실시간으로 업데이트하는 데 사용할 수 있습니다.

2. 테스트 토큰 잔액 표시

       토큰 잔고를 실시간으로 업데이트 할 수 있는지 테스트하고 무료 운영을 위해 Kovan 테스트 넷으로 전환합시다. 이전 기사에서 Kovan 테스트 넷의 테스트 ETH 획득 방법에 대해 언급 한 바 있습니다. 독자들은 지갑에 대한 포괄적 인 이해를 위해 제 전체 기사 시리즈를 확인하실 수 있습니다.

       지갑과 메타 마스크를 모두 열고 지갑에서 사용할 수있는 계정과 메타 마스크에서 사용할 수있는 두 개의 계정을 준비해 보겠습니다. 두 계정 모두 아래 그림과 같이 동일한 토큰을 추가합니다. 보시다시피
여기에 사진 설명 삽입
       왼쪽 계정에는 988,004,400 개의 테스트가 있습니다. 토큰, 오른쪽의 Kovan 계정 2에는 200 개의 테스트 토큰이 있습니다. Kovan2에서 내 계정으로 100 개의 테스트 토큰을 전송하겠습니다.

       MetaMask 토큰 목록 인터페이스에서 테스트 코인을 클릭하고 (열리는 방법은 지갑과 동일합니다) 다음 인터페이스를 입력합니다 (다음 단계에서 구현합니다).
여기에 사진 설명 삽입
       MetaMask의 메인 인터페이스에 200 개의 테스트 토큰이 표시되는 것을 볼 수 있습니다 . 복사 할 지갑에서 계정 주소를 클릭 한 다음 MetaMask에서 보내기 버튼을 클릭합니다 (페이지를 다시 열어야 할 수 있음) :
여기에 사진 설명 삽입
       주소 표시 줄에 내 계정을 직접 붙여넣고 수량 열에 100을 입력합니다. 다음을 클릭하고 다음 화면에서 확인을 클릭하고 트랜잭션이 완료 될 때까지 기다린 다음 지갑 인터페이스를 주시
여기에 사진 설명 삽입
       합니다. 메타 마스크 토큰이 전송되기 전에 确认왼쪽 지갑의 토큰 잔액이 업데이트되었습니다. 이는 거래 이벤트를 모니터링 및 필터링하여 토큰 잔액을 업데이트하고 이벤트 수신이 거래 수신 확인보다 더 빠르기 때문입니다.

       MetaMask로 내 계정에 로그인 한 후 Kovan 계정 2에 100 개의 테스트 토큰을 보내는 역 테스트를 수행 할 수도 있습니다. 거래가 확인되기 전에 왼쪽 지갑의 토큰 잔액이 업데이트됩니다. 여기서는 더 이상 시연하지 않습니다.

세,이 발전의 요점

       UI 스 플라이 싱, 새로 고침 또는 표시의 상대적으로 큰 워크로드 외에도이 개발에는 몇 가지 디자인 또는 코드 작성 요점이 있습니다.

  1. 로컬 스토리지 설계. 계정의 토큰 목록은 로컬 저장소에 저장되어야하며 어떤 형식, 업데이트 방법, 읽는 방법에 대해 신중하게 설계해야합니다. 구체적인 구현은 src\contexts\StorageProvider.js여기에 있으며 독자는 더 나은 디자인 아이디어를 가질 수도 있습니다. 다음은 메모 중 하나입니다.
/**  本地存储计划示例,
{

    "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
    }
}

       다시 말씀 드리지만 독자들이 이더 리움에서 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합니다. contract의 메소드를 직접 호출하고 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)관련이 있고 용어가 다르기 때문에 팁이 거의 없습니다. .

네, 요약

       이전 몇 번에 비해이 개발은 상대적으로 더 복잡하고 시간이 촉박하며 세부적인 테스트가 없으며 어떤 결함이나 실수도 읽거나 사용하는 과정에서 수정을 제공하는 독자를 환영합니다. 대단히 감사합니다.

       개발이 심화됨에 따라 머티리얼 UI 프레임 워크의 모든 구성 요소, 심지어 모든 CSS 규칙의 모든 속성을 명확히해야한다는 느낌이 점점 더 커질 것입니다. 그러나 이것은 장기적인 프로세스이며 기본 구현에 대해 자세히 알아보기가 어렵습니다. 따라서 머티리얼 UI 프레임 워크의 모든 구성 요소를 계속 학습하고 과거를 복습하여 새로운 것을 배우는 것이 매우 필요합니다. 일반적으로 사용되는 구성 요소 속성의 사용법을 알아야 할뿐만 아니라 일반적으로 사용되는 CSS 규칙이 무엇이며이를 수정하는 방법도 알아야합니다. 머티리얼 UI를 배우지 않더라도 Vue에서 프레임 워크를 배우고 있어도 마찬가지라고 생각합니다.

       특정 UI 코드는 번거롭고 복잡하기 때문에 여기에서는 예제를 제공하지 않습니다. 내 코드를 다운로드하여 살펴볼 수 있습니다.

       또한 CSS, 예술, 과학 또는 악몽 (알아야 할 모든 것) 기사를 추천합니다 . 나는 개인적으로 이것이 프론트 엔드 개발자는 아니지만 모든 프론트 엔드 개발자에게 필독 기사라고 생각합니다.

       다음 개발에서는 ERC20 토큰의 전송 기능을 구현할 계획입니다.

       이 지갑 코드 클라우드 (gitee) 창고 주소 : => https://gitee.com/TianCaoJiangLin/khwallet

       독자는 오류를 지적하거나 개선 사항을 제안하는 메시지를 남길 수 있습니다.

추천

출처blog.csdn.net/weixin_39430411/article/details/104145456