This commit is contained in:
elegant651
2020-03-24 14:39:38 +09:00
commit 6e0388b653
83 changed files with 92480 additions and 0 deletions

21
nftbapp/frontend-nftdapp/.gitignore vendored Normal file
View File

@@ -0,0 +1,21 @@
.DS_Store
node_modules
/dist
# local env files
.env.local
.env.*.local
# Log files
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw*

View File

@@ -0,0 +1,29 @@
# frontend-nftdapp
## Project setup
```
npm install
```
### Compiles and hot-reloads for development
```
npm run serve
```
### Compiles and minifies for production
```
npm run build
```
### Run your tests
```
npm run test
```
### Lints and fixes files
```
npm run lint
```
### Customize configuration
See [Configuration Reference](https://cli.vuejs.org/config/).

View File

@@ -0,0 +1,5 @@
module.exports = {
presets: [
'@vue/app'
]
}

10075
nftbapp/frontend-nftdapp/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,32 @@
{
"name": "frontend-nftdapp",
"version": "0.1.0",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build"
},
"dependencies": {
"axios": "^0.18.0",
"vue": "^2.5.21",
"vue-axios": "^2.1.4",
"vue-router": "^3.0.2",
"vuetify": "^1.4.1",
"web3": "^0.20.6"
},
"devDependencies": {
"@vue/cli-plugin-babel": "^3.1.1",
"@vue/cli-service": "^3.1.1",
"vue-template-compiler": "^2.5.21"
},
"postcss": {
"plugins": {
"autoprefixer": {}
}
},
"browserslist": [
"> 1%",
"last 2 versions",
"not ie <= 8"
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -0,0 +1,19 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<link href='https://fonts.googleapis.com/css?family=Roboto:300,400,500,700|Material+Icons' rel="stylesheet">
<link href="https://fonts.googleapis.com/css?family=Open+Sans" rel="stylesheet">
<title>frontend-nftdapp</title>
</head>
<body>
<noscript>
<strong>We're sorry but frontend-nftdapp doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>

View File

@@ -0,0 +1,52 @@
<template>
<v-app light>
<v-toolbar fixed color="teal lighten-2" app dark :clipped-left="true">
<v-toolbar-title>NFT APP</v-toolbar-title>
<v-spacer></v-spacer>
<div class="nav">
<a href="/">Home</a>
<a href="/wallet">Wallet</a>
<a href="/upload">Upload</a>
</div>
</v-toolbar>
<v-content class="contentWrapper">
<v-container fluid>
<router-view></router-view>
</v-container>
</v-content>
</v-app>
</template>
<script>
import 'vuetify/dist/vuetify.min.css'
export default {
name: 'app'
}
</script>
<style>
#app {
font-family: 'Avenir', Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
.nav a {
font-weight: bold;
color: #2c3e50;
margin: 10px;
}
.nav a.router-link-exact-active {
color: #42b983;
}
.contentWrapper {
padding-top: 20px;
}
</style>

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

View File

@@ -0,0 +1,57 @@
<template>
<div class="hello">
<h1>{{ msg }}</h1>
<p>
For a guide and recipes on how to configure / customize this project,<br>
check out the
<a href="https://cli.vuejs.org" target="_blank" rel="noopener">vue-cli documentation</a>.
</p>
<h3>Installed CLI Plugins</h3>
<ul>
<li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-babel" target="_blank" rel="noopener">babel</a></li>
</ul>
<h3>Essential Links</h3>
<ul>
<li><a href="https://vuejs.org" target="_blank" rel="noopener">Core Docs</a></li>
<li><a href="https://forum.vuejs.org" target="_blank" rel="noopener">Forum</a></li>
<li><a href="https://chat.vuejs.org" target="_blank" rel="noopener">Community Chat</a></li>
<li><a href="https://twitter.com/vuejs" target="_blank" rel="noopener">Twitter</a></li>
<li><a href="https://news.vuejs.org" target="_blank" rel="noopener">News</a></li>
</ul>
<h3>Ecosystem</h3>
<ul>
<li><a href="https://router.vuejs.org" target="_blank" rel="noopener">vue-router</a></li>
<li><a href="https://vuex.vuejs.org" target="_blank" rel="noopener">vuex</a></li>
<li><a href="https://github.com/vuejs/vue-devtools#vue-devtools" target="_blank" rel="noopener">vue-devtools</a></li>
<li><a href="https://vue-loader.vuejs.org" target="_blank" rel="noopener">vue-loader</a></li>
<li><a href="https://github.com/vuejs/awesome-vue" target="_blank" rel="noopener">awesome-vue</a></li>
</ul>
</div>
</template>
<script>
export default {
name: 'HelloWorld',
props: {
msg: String
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h3 {
margin: 40px 0 0;
}
ul {
list-style-type: none;
padding: 0;
}
li {
display: inline-block;
margin: 0 10px;
}
a {
color: #42b983;
}
</style>

View File

@@ -0,0 +1,64 @@
<template>
<v-container grid-list-md text-xs-center>
<v-layout row wrap>
<v-flex v-for="(auction, index) in auctions" :key="index" xs4>
<v-card>
<v-img :src="auction.image" height="200px"></v-img>
<div>Title: {{auction.title}}</div>
<div>Price: {{auction.price}} Ether</div>
<div>TokenId: {{auction.tokenId}}</div>
<div>Owner: {{auction.owner}}</div>
<div>Active: {{auction.active}}</div>
<div>Finalized: {{auction.finalized}}</div>
</v-card>
</v-flex>
</v-layout>
</v-container>
</template>
<script>
export default {
data() {
return {
ciMyNFT: null,
ciAuctions: null,
auctions: []
}
},
mounted() {
this.ciAuctions = this.$web3.eth.contract(this.$config.AUCTIONS_ABI).at(this.$config.AUCTIONS_CA)
this.ciMyNFT = this.$web3.eth.contract(this.$config.MYNFT_ABI).at(this.$config.MYNFT_CA)
this.getAuctions()
},
methods: {
getAuctions() {
this.ciAuctions.getCount({}, (error, result) => {
const count = result
for(let i=0; i<count; i++) {
this.ciAuctions.getAuctionById(i, {}, (err, result) => {
this.ciMyNFT.ownerOf(result[3], {}, (error, owner) => {
this.auctions.push({
title: result[0],
price: this.$web3.fromWei(result[1], 'ether'),
image: 'https://gateway.ipfs.io/ipfs/'+result[2],
tokenId: result[3],
owner: owner,
active: result[6],
finalized: result[7]
})
})
})
}
})
}
}
}
</script>

View File

@@ -0,0 +1,149 @@
<template>
<div>
<v-form class="form" ref="form">
<v-text-field
v-model="tokenId"
label="Unique ID">
</v-text-field>
<input
type="file"
@change="captureFile" />
<v-btn @click="uploadImg" outline color="teal">UploadImg</v-btn>
<img :src="uploadedImg()" width="300" />
<v-text-field
v-model="dataURI"
label="Data URI"
required
></v-text-field>
<v-btn @click="submit" outline color="teal">Submit</v-btn>
<div v-show="isRegistered">
<v-btn @click="transferToCA" outline color="teal">TransferToCA</v-btn>
</div>
</v-form>
<PostAuction v-bind:tokenid="tokenId" v-bind:metadata="dataURI" />
</div>
</template>
<script>
import PostAuction from '@/components/PostAuction.vue'
export default {
data() {
return {
account: null,
contractInstance: null,
file: null,
tokenId: null,
isRegistered: false,
dataURI: null
}
},
components: {
PostAuction
},
async mounted() {
this.account = await this.$getDefaultAccount()
this.contractInstance = this.$web3.eth.contract(this.$config.MYNFT_ABI).at(this.$config.MYNFT_CA)
this.tokenId = this._getRandomInt(123456789,999999999)
},
methods: {
_getRandomInt(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min
},
captureFile(event) {
event.stopPropagation()
this.file = event.target.files[0]
},
async uploadImg() {
if(!this.file){
alert("Please put the file on input.")
return
}
const formData = new FormData()
formData.append('file', this.file)
this.axios({
method: 'post',
baseURL: 'https://ipfs.infura.io:5001',
url: '/api/v0/add',
data: formData,
headers: {'Content-Type': 'multipart/form-data'}
}).then((response)=> {
this.dataURI = response.data.Hash
})
},
uploadedImg(){
return 'https://gateway.ipfs.io/ipfs/'+this.dataURI
},
submit() {
if(!this.dataURI){
alert("Fill in dataURI on the input")
return
}
this.contractInstance.registerUniqueToken(this.account, this.tokenId, this.dataURI, {
from: this.account,
gas: this.$config.GAS_AMOUNT
}, (error, result) => {
console.log("result",result)
})
this.watchTokenRegistered((error, result) => {
if(!error) {
alert("Token registered...!")
this.isRegistered = true
}
})
},
transferToCA() {
this.contractInstance.transferFrom(this.account, this.$config.AUCTIONS_CA, this.tokenId, {
from: this.account,
gas: this.$config.GAS_AMOUNT
}, (error, result) => {
console.log("result",result)
})
this.watchTransfered((error, result) => {
if(!error) alert("Token transfered to CA...!")
})
},
async watchTokenRegistered(cb) {
const currentBlock = await this.getCurrentBlock()
const eventWatcher = this.contractInstance.TokenRegistered({}, {fromBlock: currentBlock - 1, toBlock: 'latest'})
eventWatcher.watch(cb)
},
async watchTransfered(cb) {
const currentBlock = await this.getCurrentBlock()
const eventWatcher = this.contractInstance.Transfer({}, {fromBlock: currentBlock - 1, toBlock: 'latest'})
eventWatcher.watch(cb)
},
getCurrentBlock() {
return new Promise((resolve, reject ) => {
this.$web3.eth.getBlockNumber((err, blocknumber) => {
if(!err) resolve(blocknumber)
reject(err)
})
})
},
}
}
</script>

View File

@@ -0,0 +1,136 @@
<template>
<div class="containWrap">
<v-card class="cardG">
<div>
<p class="text-center address">
{{account}} <span class="reftxt">(Address)</span>
</p>
<p class="text-center balance">
{{balance}} Ether <span class="reftxt">(Balance)</span>
</p>
</div>
</v-card>
<h2>Transfer</h2>
<v-select v-model="selectedAuction" :items="auctionIds" label="Asset" @change="getAuctionById"></v-select>
<div v-show="selectedAuction">
<h3>Auction Info</h3>
<div>Title: {{auctionInfo.title}}</div>
<div>Price: {{auctionInfo.price}} Ether</div>
<div>TokenId: {{auctionInfo.tokenId}}</div>
<div>Owner: {{auctionInfo.owner}}</div>
</div>
<v-text-field
v-model="toAddress"
label="To Address"
required
></v-text-field>
<v-btn @click="finalizeAuction" outline color="teal">Finalize</v-btn>
</div>
</template>
<script>
export default {
data() {
return {
account: '',
balance: null,
ciMyNFT: null,
ciAuctions: null,
auctionIds:[],
toAddress: null,
selectedAuction: null,
auctionInfo: {
title: '',
price: 0,
tokenId: '',
owner: ''
}
}
},
async mounted() {
this.account = await this.$getDefaultAccount()
this.$web3.eth.getBalance(this.account, (error, result) => {
this.balance = this.$web3.fromWei(result, 'ether')
})
this.ciMyNFT = this.$web3.eth.contract(this.$config.MYNFT_ABI).at(this.$config.MYNFT_CA)
this.ciAuctions = this.$web3.eth.contract(this.$config.AUCTIONS_ABI).at(this.$config.AUCTIONS_CA)
this.getMyAuctions()
},
methods: {
getMyAuctions() {
this.ciAuctions.getAuctionsOf(this.account, {from: this.account, gas: this.$config.GAS_AMOUNT}, (error, result) => {
this.auctionIds = result
})
},
getAuctionById() {
this.ciAuctions.getAuctionById(this.selectedAuction, {from: this.account, gas: this.$config.GAS_AMOUNT}, (error, result) => {
console.log(result)
this.auctionInfo.title = result[0]
this.auctionInfo.price = this.$web3.fromWei(result[1], 'ether')
this.auctionInfo.tokenId = result[3]
this.ciMyNFT.ownerOf(result[3], {}, (error, owner) => {
this.auctionInfo.owner = owner
})
})
},
finalizeAuction() {
if(!this.toAddress) {
alert("please fill in to Address")
return
}
this.ciAuctions.finalizeAuction(this.selectedAuction, this.toAddress, {from: this.account, gas: this.$config.GAS_AMOUNT}, (error, result) => {
console.log(result)
})
this.watchFinalized((error, result) => {
if(!error) alert("Auction finalized...!")
})
},
async watchFinalized(cb) {
const currentBlock = await this.getCurrentBlock()
const eventWatcher = this.ciAuctions.AuctionFinalized({}, {fromBlock: currentBlock - 1, toBlock: 'latest'})
eventWatcher.watch(cb)
},
getCurrentBlock() {
return new Promise((resolve, reject ) => {
this.$web3.eth.getBlockNumber((err, blocknumber) => {
if(!err) resolve(blocknumber)
reject(err)
})
})
}
}
}
</script>
<style scoped>
.containWrap {
max-width: 600px;
margin: 0 auto;
}
.cardG {
margin: 10px;
padding: 10px;
}
.cardG .reftxt {
color: #b7afaf;
}
</style>

View File

@@ -0,0 +1,79 @@
<template>
<div>
<v-form class="form" ref="form">
<v-text-field
v-model="tokenid"
></v-text-field>
<v-text-field
v-model="auction.auctionTitle"
placeholder="e.g. My NFT"
label="Auction title"
persistent-hint
></v-text-field>
<v-text-field
v-model="auction.price"
placeholder="e.g. 1"
label="Price"
persistent-hint
></v-text-field>
<v-btn @click="createAuction()" outline color="teal">Create Auction</v-btn>
</v-form>
</div>
</template>
<script>
export default {
props: ['tokenid', 'metadata'],
data() {
return {
account: null,
contractInstance: null,
auction: {
auctionTitle: '',
price: null
},
}
},
async mounted() {
this.account = await this.$getDefaultAccount()
this.contractInstance = this.$web3.eth.contract(this.$config.AUCTIONS_ABI).at(this.$config.AUCTIONS_CA)
},
methods: {
async createAuction() {
if(!this.tokenid) {
alert("Check for tokenId")
return
}
const price = this.$web3.toWei(this.auction.price, 'ether')
this.contractInstance.createAuction(this.$config.MYNFT_CA, this.tokenid, this.auction.auctionTitle, this.metadata, price, {from: this.account, gas: this.$config.GAS_AMOUNT}, (error, transactionHash) => {
console.log("txhash",transactionHash)
})
this.watchCreated((error, result) => {
if(!error) alert("Creation completed...!")
})
},
async watchCreated(cb) {
const currentBlock = await this.getCurrentBlock()
const eventWatcher = this.contractInstance.AuctionCreated({}, {fromBlock: currentBlock - 1, toBlock: 'latest'})
eventWatcher.watch(cb)
},
getCurrentBlock() {
return new Promise((resolve, reject ) => {
this.$web3.eth.getBlockNumber((err, blocknumber) => {
if(!err) resolve(blocknumber)
reject(err)
})
})
}
}
}
</script>

View File

@@ -0,0 +1,12 @@
const MyNFT = require('./contracts/MyNFT')
const Auctions = require('./contracts/Auctions')
export default {
MYNFT_CA: '0x3cd92247e5331d3b51f6cbeff4e5d3ef420f1989',
AUCTIONS_CA: '0x5ffc6ca35a7ee8ed33228b47b49c21310e67339c',
MYNFT_ABI: MyNFT.abi,
AUCTIONS_ABI: Auctions.abi,
GAS_AMOUNT: 500000
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,39 @@
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import Vuetify from 'vuetify'
import axios from 'axios'
import VueAxios from 'vue-axios'
import Web3 from 'web3'
import Config from './config'
Vue.use(Vuetify)
Vue.use(VueAxios, axios)
Vue.config.productionTip = false
Vue.mixin({
created() {
const web3js = window.web3
if(typeof web3js !== 'undefined') {
this.$web3 = new Web3(web3js.currentProvider)
}
this.$getDefaultAccount = () => {
return new Promise((resolve, reject) => {
this.$web3.eth.getAccounts((err, data) => {
if(!err) resolve(data[0])
reject(err)
})
})
}
this.$config = Config
}
})
new Vue({
router,
render: h => h(App),
}).$mount('#app')

View File

@@ -0,0 +1,30 @@
import Vue from 'vue'
import Router from 'vue-router'
import Main from './views/Main.vue'
import Wallet from './views/Wallet.vue'
import Upload from './views/Upload.vue'
Vue.use(Router)
export default new Router({
mode: 'history',
base: process.env.BASE_URL,
routes: [
{
path: '/',
name: 'main',
component: Main
},
{
path: '/wallet',
name: 'wallet',
component: Wallet
},
{
path: '/upload',
name: 'upload',
component: Upload
}
]
})

View File

@@ -0,0 +1,15 @@
<template>
<div>
<h2>Main Page</h2>
<Marketplace />
</div>
</template>
<script>
import Marketplace from '@/components/Marketplace.vue'
export default {
components: {
Marketplace
}
}
</script>

View File

@@ -0,0 +1,15 @@
<template>
<div>
<h2>Upload Page</h2>
<MyUpload />
</div>
</template>
<script>
import MyUpload from '@/components/MyUpload.vue'
export default {
components: {
MyUpload
}
}
</script>

View File

@@ -0,0 +1,16 @@
<template>
<div>
<h2>Wallet Page</h2>
<MyWallet />
</div>
</template>
<script>
import MyWallet from '@/components/MyWallet.vue'
export default {
components: {
MyWallet
}
}
</script>