complete ERC-20 transfer, approve & transferFrom

This commit is contained in:
snsd0805 2023-05-08 20:57:40 +08:00
parent 5921a62812
commit bd22b56a32
Signed by: snsd0805
GPG Key ID: 569349933C77A854
2 changed files with 252 additions and 18 deletions

View File

@ -13,8 +13,8 @@ import { RouterLink, RouterView } from "vue-router";
</button>
<div class="collapse navbar-collapse" id="navbarResponsive">
<ul class="navbar-nav ms-auto">
<li class="nav-item mx-0 mx-lg-1"><router-link class="nav-link py-3 px-0 px-lg-3 rounded" to="/">Withdraw</router-link></li>
<li class="nav-item mx-0 mx-lg-1"><router-link class="nav-link py-3 px-0 px-lg-3 rounded" to="/manage">Management</router-link></li>
<!-- <li class="nav-item mx-0 mx-lg-1"><router-link class="nav-link py-3 px-0 px-lg-3 rounded" to="/">Withdraw</router-link></li> -->
<!-- <li class="nav-item mx-0 mx-lg-1"><router-link class="nav-link py-3 px-0 px-lg-3 rounded" to="/manage">Management</router-link></li> -->
</ul>
</div>
</div>

View File

@ -7,16 +7,26 @@ export default {
name: 'MyComponent',
data() {
return {
account: "",
msg: '',
linked: false,
amount: "0",
contract_address: "",
token: null,
token_name: "",
token_symbol: "",
token_balance: "0",
token_decimal: "1",
address: "",
transfer_address: "",
transfer_amount: "",
approve_address: "",
approve_amount: "",
approve_logs: {},
transfer_from_owner_addresss: "",
transfer_from_receiver_addresss: "",
transfer_from_amount: "",
transfer_from_logs: {},
}
},
async mounted() {
@ -43,8 +53,9 @@ export default {
if (provider) {
this.msg = "Detect Metamask."
const chainId = await ethereum.request({method: 'eth_chainId'})
if(chainId == 1337){ // Sepolia 1337
if(chainId == 11155111){ // Sepolia 1337
const account = await ethereum.request({ method: 'eth_requestAccounts' });
this.account = account[0];
this.msg += "> Network which you connected is Sepolia. @ " + account[0]
this.linked = true
}else{
@ -64,8 +75,7 @@ export default {
this.token_name = await this.token.methods.name().call();
this.token_symbol = await this.token.methods.symbol().call();
const account = await ethereum.request({ method: 'eth_requestAccounts' });
this.token_balance = await this.token.methods.balanceOf(account[0]).call();
this.token_balance = await this.token.methods.balanceOf(this.account).call();
let decimal = await this.token.methods.decimals().call();
this.token_decimal = decimal
@ -75,6 +85,45 @@ export default {
this.token_name = "ERROR";
this.token_symbol = "ERROR";
}
// get approve events
try{
let events = await this.token.getPastEvents("Approval", {fromBlock: 0, toBlock: 'latest', filter: {owner: this.account}})
this.approve_logs = {};
for(let event of events){
this.approve_logs[event['returnValues']['spender']] = {
'owner': event['returnValues']['owner'],
'value': event['returnValues']['value'],
}
}
for(let event in this.approve_logs){
let remain = await this.token.methods.allowance(this.account, event).call();
this.approve_logs[event]['remain'] = remain;
console.log(this.approve_logs[event])
}
}catch(error){
this.approve_logs = {};
}
// get approve events
try{
let events = await this.token.getPastEvents("Approval", {fromBlock: 0, toBlock: 'latest', filter: {spender: this.account}})
this.transfer_from_logs = {};
for(let event of events){
this.transfer_from_logs[event['returnValues']['owner']] = {
'owner': event['returnValues']['owner'],
'value': event['returnValues']['value'],
}
}
for(let event in this.transfer_from_logs){
let remain = await this.token.methods.allowance(event, this.account).call();
this.transfer_from_logs[event]['remain'] = remain;
}
}catch(error){
this.transfer_from_logs = {};
}
},
async transfer() {
@ -90,7 +139,7 @@ export default {
type: "uint256",
name: "amount"
}]
}, [this.address, web3.utils.toBN(this.amount * Math.pow(10, this.token_decimal))])
}, [this.transfer_address, web3.utils.toBN(this.transfer_amount)])
console.log(this.token.options.address)
const transactionParameters = {
from: ethereum.selectedAddress,
@ -98,18 +147,85 @@ export default {
data: encodeFunctionCall,
value: '0x00',
}
console.log(encodeFunctionCall)
console.log(transactionParameters)
const txHash = await ethereum.request({
method: 'eth_sendTransaction',
params: [transactionParameters]
})
console.log(txHash)
this.transfer_amount = "";
this.transfer_address = "";
},
async approve() {
const web3 = new Web3()
const encodeFunctionCall = web3.eth.abi.encodeFunctionCall({
name: "approve",
type: "function",
inputs: [{
type: "address",
name: "spender"
},
{
type: "uint256",
name: "amount"
}]
}, [this.approve_address, web3.utils.toBN(this.approve_amount)])
console.log(this.token.options.address)
const transactionParameters = {
from: ethereum.selectedAddress,
to: this.token.options.address, // smart contract's address
data: encodeFunctionCall,
value: '0x00',
}
const txHash = await ethereum.request({
method: 'eth_sendTransaction',
params: [transactionParameters]
})
this.approve_amount = "";
this.approve_address = "";
},
async transferFrom() {
const web3 = new Web3()
const encodeFunctionCall = web3.eth.abi.encodeFunctionCall({
name: "transferFrom",
type: "function",
inputs: [{
type: "address",
name: "from"
},
{
type: "address",
name: "to"
},
{
type: "uint256",
name: "amount"
}]
}, [this.transfer_from_owner_addresss, this.transfer_from_receiver_addresss, web3.utils.toBN(this.transfer_from_amount)])
const transactionParameters = {
from: ethereum.selectedAddress,
to: this.token.options.address, // smart contract's address
data: encodeFunctionCall,
value: '0x00',
}
const txHash = await ethereum.request({
method: 'eth_sendTransaction',
params: [transactionParameters]
})
this.transfer_from_amount = "";
this.transfer_from_owner_addresss = "";
this.transfer_from_receiver_addresss = "";
},
}
}
</script>
@ -143,6 +259,7 @@ export default {
<div class="col-sm-4">
<button class='btn btn-info' v-on:click="get_info"> GET </button>
</div>
</div>
</div>
</div>
@ -174,18 +291,135 @@ export default {
<div>
<div class="container">
<div class="row">
<div class="col-sm-8">
<input type='text' class="form-control" v-model="address" placeholder="Receiver's address">
<div class="col-sm-10">
<div class="form-group row">
<label for="inputPassword" class="col-sm-2 col-form-label">Receiver</label>
<div class="col-sm-10">
<input type='text' class="form-control" v-model="transfer_address" placeholder="Receiver's address">
</div>
</div>
<div class="form-group row">
<label for="inputPassword" class="col-sm-2 col-form-label">Value</label>
<div class="col-sm-10">
<input type='number' class="form-control" v-model="transfer_amount" v-bind:placeholder="'(int) 個單位. Decimals: '+token_decimal">
</div>
</div>
</div>
<div class="col-sm-8">
<input type='number' class="form-control" v-model="amount" v-bind:placeholder="'Amount (float). Decimals: '+token_decimal">
<div class="col-sm-2">
<br><br>
<button class='btn btn-info' v-on:click="transfer"> Transfer {{transfer_amount}} 單位 ({{transfer_amount / Math.pow(10, token_decimal)}} {{token_symbol}})</button>
</div>
<div class="col-sm-4">
<button class='btn btn-info' v-on:click="transfer"> Transfer {{amount}} {{token_symbol}} ({{amount * Math.pow(10, token_decimal)}}單位)</button>
</div>
</div>
</div>
<br><br>
<br><br>
<h3>Approve</h3>
You have {{token_balance/Math.pow(10, token_decimal)}} {{token_symbol}} (<a href="#" v-on:click="update">Refresh</a>)
<br><br>
<div>
<div class="container">
<div class="row">
<div class="col-sm-10">
<div class="form-group row">
<label for="inputPassword" class="col-sm-2 col-form-label">Owner</label>
<div class="col-sm-10">
<input type='text' class="form-control" v-model="approve_address" placeholder="Spender's address">
</div>
</div>
<div class="form-group row">
<label for="inputPassword" class="col-sm-2 col-form-label">Value</label>
<div class="col-sm-10">
<input type='number' class="form-control" v-model="approve_amount" v-bind:placeholder="'(int) 個單位. Decimals: '+token_decimal">
</div>
</div>
</div>
<div class="col-sm-2">
<br><br>
<button class='btn btn-info' v-on:click="approve"> Approve {{approve_amount}} 單位 ({{approve_amount / Math.pow(10, token_decimal)}} {{token_symbol}})</button>
</div>
</div>
</div>
</div>
<br>
<table class="table table-hover">
<thead>
<tr>
<th scope="col">Spender</th>
<th scope="col">Value</th>
<th scope="col">{{token_symbol}} Token</th>
</tr>
</thead>
<tbody>
<template v-for="(event, index) of approve_logs">
<tr>
<th scope="row">{{index}}</th>
<td>{{event['value']}} 單位</td>
<td>{{event['value'] / Math.pow(10, token_decimal)}} {{token_symbol}} </td>
</tr>
</template>
</tbody>
</table>
<br><br>
<br><br>
<h3>TransferFrom</h3>
You have {{token_balance/Math.pow(10, token_decimal)}} {{token_symbol}} (<a href="#" v-on:click="update">Refresh</a>)
<br><br>
<div>
<div class="container">
<div class="row">
<div class="col-sm-10">
<div class="form-group row">
<label for="inputPassword" class="col-sm-2 col-form-label">Owner</label>
<div class="col-sm-10">
<input type='text' class="form-control" v-model="transfer_from_owner_addresss" placeholder="Owner's address">
</div>
</div>
<div class="form-group row">
<label for="inputPassword" class="col-sm-2 col-form-label">Receiver</label>
<div class="col-sm-10">
<input type='text' class="form-control" v-model="transfer_from_receiver_addresss" placeholder="Receiver's address">
</div>
</div>
<div class="form-group row">
<label for="inputPassword" class="col-sm-2 col-form-label">Value</label>
<div class="col-sm-10">
<input type='number' class="form-control" v-model="transfer_from_amount" v-bind:placeholder="'(int) 個單位. Decimals: '+token_decimal">
</div>
</div>
</div>
<div class="col-sm-2">
<br><br>
<button class='btn btn-info' v-on:click="transferFrom"> Transfer {{transfer_from_amount}} 單位 ({{transfer_from_amount / Math.pow(10, token_decimal)}} {{token_symbol}}) (From Owner)</button>
</div>
</div>
</div>
</div>
<br>
<table class="table table-hover">
<thead>
<tr>
<th scope="col">Owner</th>
<th scope="col">Value</th>
<th scope="col">{{token_symbol}} Token</th>
</tr>
</thead>
<tbody>
<template v-for="(event, index) of transfer_from_logs">
<tr>
<th scope="row">{{index}}</th>
<td>{{event['value']}} 單位</td>
<td>{{event['value'] / Math.pow(10, token_decimal)}} {{token_symbol}} </td>
</tr>
</template>
</tbody>
</table>
</template>