更新购买流程

This commit is contained in:
zhl 2022-01-27 13:59:08 +08:00
parent d918e9d580
commit 058c5e8703
10 changed files with 250 additions and 70 deletions

View File

@ -1,4 +1,4 @@
VUE_APP_WALLET_INFURAID='e7743d46923911fa8850619b7a7f6d9d'
VUE_APP_CHAIN_ID=97
VUE_APP_CHAIN_RPC='https://data-seed-prebsc-1-s1.binance.org:8545/'
VUE_APP_BASE_API='https://game2006api-test.kingsome.cn'
VUE_APP_CHAIN_ID=1338
VUE_APP_CHAIN_RPC='http://192.168.100.22:8545'
VUE_APP_BASE_API='http://game2006api-test.kingsome.cn'

View File

@ -1,4 +1,4 @@
VUE_APP_WALLET_INFURAID='e7743d46923911fa8850619b7a7f6d9d'
VUE_APP_CHAIN_ID=97
VUE_APP_CHAIN_RPC='https://data-seed-prebsc-1-s1.binance.org:8545/'
VUE_APP_CHAIN_RPC='https://data-seed-prebsc-1-s1.binance.org:8545'
VUE_APP_BASE_API='https://game2006api.kingsome.cn'

View File

@ -23,6 +23,13 @@ export const searchBox = (data: any) =>
params: data
})
export const queryPresaleStatus = (data: any) =>
request({
url: '/webapp/index.php?c=Market&a=getPreSaleInfo',
method: 'get',
params: data
})
export const getNftList = (data: any) =>
request({
url: '/webapp/index.php?c=Market&a=getNftList',
@ -43,3 +50,10 @@ export const buyBox = (data: any) =>
method: 'get',
params: data
})
export const queryOrder = (data: any) =>
request({
url: '/webapp/index.php?c=Market&a=queryOrder',
method: 'get',
params: data
})

View File

@ -24,11 +24,11 @@
<li data-menuanchor="chip" @click="changeSection" :class="{'active': currentSection === 'chip'}">
<a href="#chip_section">Chip</a>
</li>
<li>
<a href="mynft" v-if="accountId">Mine</a>
<li v-if="accountId">
<a href="mynft" >Mine</a>
</li>
<li data-menuanchor="market" @click.stop="comingSoon">
<a href="javascipt:void(0)">MARKETPLACE</a>
<a href="javascript:void(0)">MARKETPLACE</a>
</li>
</ul>
</div>
@ -49,11 +49,17 @@
<li data-menuanchor="chip" @click="changeSection" :class="{'active': currentSection === 'chip'}">
<a href="#chip_section">CHIP</a>
</li>
<li>
<a href="mynft" v-if="accountId">Mine</a>
<li v-if="accountId">
<a href="mynft" >Mine</a>
</li>
<li data-menuanchor="market" @click.stop="comingSoon">
<a href="javascipt:void(0)">MARKETPLACE</a>
<a href="javascript:void(0)">MARKETPLACE</a>
</li>
<li v-if="accountId" @click.stop="disconnectWallet">
<a href="javascript:void(0)" >Logout</a>
</li>
<li v-if="!accountId">
<a href="javascript:void(0)" >Connect Wallet</a>
</li>
</ul>
</div>
@ -64,6 +70,7 @@
import { Component, Vue } from 'vue-property-decorator'
import { Message } from 'element-ui'
import { AppModule } from '@/store/modules/app'
import { BlockChain } from '@/utils/blockchain'
declare module 'vue/types/vue' {
interface Vue {
@ -79,6 +86,8 @@ declare module 'vue/types/vue' {
})
export default class extends Vue {
private dropShow = false
bc = new BlockChain();
changeSection(e: PointerEvent) {
this.dropShow = false
const target = e.currentTarget as HTMLElement
@ -87,6 +96,10 @@ export default class extends Vue {
}
}
async disconnectWallet() {
return this.bc.disconnect()
}
toggleDrop() {
this.dropShow = !this.dropShow
}
@ -198,6 +211,9 @@ export default class extends Vue {
.menu_fullpage{
display: none;
}
.menu-list {
padding-right: 10px;
}
.menu_drop {
display: flex;
position: absolute;

View File

@ -14,11 +14,15 @@
</template>
<script lang="ts">
import { Component, Vue } from 'vue-property-decorator'
import { Component, Vue, Watch } from 'vue-property-decorator'
import CardScroller from '@/components/main/CardScroller.vue'
import { searchBox } from '@/api/Mall'
import { queryOrder, queryPresaleStatus, searchBox } from '@/api/Mall'
import { ISpineData } from '@/utils/SpineRender'
import { AppModule } from '@/store/modules/app'
import { secs2str } from '@/utils/time.util'
import { EventBus, PRESALE_BEGIN, PRESALE_ERROR, PRESALE_ORDER_GET, PRESALE_SUCCESS } from '@/utils/event-bus'
import { Loading } from 'element-ui'
import { ElLoadingComponent } from 'element-ui/types/loading'
@Component({
name: 'NftSection',
@ -34,55 +38,178 @@ export default class extends Vue {
presaleStatus = 0
numberTotal = 0
numberRest = 0
buyed = false
timeStr = '20:59:59'
buyed = true
timeStr = ''
countdown = 0
timer: any = null
orderTimer: any = null
loadingInstance: ElLoadingComponent
created() {
this.fetchData()
this.subscribeToEvents()
}
unmounted() {
this.removeEvents()
}
@Watch('accountId')
private accountChange() {
if (this.accountId) {
this.getPresaleInfo()
}
}
@Watch('countdown')
private countDownChange() {
this.timeStr = secs2str(this.countdown)
}
get accountId() {
return AppModule.accountId
}
async fetchData() {
await this.queryPresale()
await this.queryPresaleList()
}
async queryPresale() {
const res: any = await searchBox({ account: '', page: 0 })
console.log(res)
if (!res.errcode) {
this.heroDatas.length = 0
if (res.presale_info) {
this.numberTotal = res.presale_info.total_num || 0
this.numberRest = this.numberTotal - (res.presale_info.sold_num || 0)
this.numberRest = this.numberRest < 0 ? 0 : this.numberRest
this.hint = res.presale_info.hint.replace(/\\n/g, '<br/>')
this.buyed = !!res.presale_info.buyed
this.presaleStatus = res.presale_info.state || 0
this.presaleTitle = res.presale_info.title
AppModule.updateCanBuy(this.presaleStatus === 2 &&
this.numberRest > 0 &&
!this.buyed
)
subscribeToEvents() {
EventBus.$on(PRESALE_BEGIN, this.onPresaleBegin.bind(this))
EventBus.$on(PRESALE_SUCCESS, this.onPresaleSuccess.bind(this))
EventBus.$on(PRESALE_ERROR, this.onPresaleError.bind(this))
EventBus.$on(PRESALE_ORDER_GET, this.onOrderIDGeted.bind(this))
}
removeEvents() {
EventBus.$off(PRESALE_BEGIN, this.onPresaleBegin.bind(this))
EventBus.$off(PRESALE_SUCCESS, this.onPresaleSuccess)
EventBus.$off(PRESALE_ERROR, this.onPresaleError)
EventBus.$off(PRESALE_ORDER_GET, this.onOrderIDGeted.bind(this))
}
onPresaleBegin() {
this.loadingInstance = Loading.service({})
console.log('presale begin')
}
onOrderIDGeted(orderId: string) {
console.log('order id:', orderId)
this.beginTraceOrderStatus(orderId)
}
onPresaleError(res: any) {
console.log('presale error: ', res)
this.loadingInstance.close()
this.$alert('Some error when process presale', 'Buy Failed', { type: 'error', confirmButtonText: 'OK' })
}
async onPresaleSuccess(res: any) {
console.log('presale success', res)
this.resetTmpOrderId()
this.$alert('Congratulations', 'Buy Success', { type: 'success', confirmButtonText: 'OK' })
await this.getPresaleInfo()
}
beginTraceOrderStatus(orderId: string) {
this.orderTimer = setInterval(() => {
this.getOrderStatus(orderId)
}, 1000)
}
resetTmpOrderId() {
if (this.orderTimer !== null) {
clearInterval(this.orderTimer)
this.orderTimer = null
}
localStorage.removeItem('tmp_presale_order_id')
this.loadingInstance.close()
}
async getOrderStatus(orderId: string) {
try {
const res: any = await queryOrder({ account: this.accountId, order_id: orderId })
if (res.status === 1) {
EventBus.$emit(PRESALE_SUCCESS, {})
} else if (res.status === 3) {
EventBus.$emit(PRESALE_ERROR, {})
this.resetTmpOrderId()
} else if (res.status === 0) {
EventBus.$emit(PRESALE_ERROR, {})
this.resetTmpOrderId()
}
for (const data of res.rows) {
const heroData: any = {
name: data.name,
class: (data.job + '').toLowerCase(),
recordId: data.box_id,
id: data.box_id,
skelName: `n_${data.name.toLowerCase()}`,
directBuy: true,
stopBuy: this.buyed,
showBuy: true
}
if (data.currency_list && data.currency_list.length > 0) {
const priceData: any = data.currency_list[0]
heroData.discount = priceData.discount_rate
heroData.price = priceData.original_price
heroData.priceDiscount = priceData.discount_price
heroData.currency = priceData.name
heroData.coinAddress = priceData.contract_address
}
this.heroDatas.push(heroData)
} catch (err) {
console.log('query order status error', err)
}
}
beginCountdown() {
this.clearTimer()
this.timer = setInterval(() => {
if (this.countdown <= 0) {
this.clearTimer()
} else {
this.countdown--
}
}, 1000)
}
clearTimer() {
clearInterval(this.timer)
this.timer = null
}
async getPresaleInfo() {
const res: any = await queryPresaleStatus({ account: this.accountId })
if (res.presale_info) {
this.numberTotal = res.presale_info.total_num || 0
this.numberRest = this.numberTotal - (res.presale_info.sold_num || 0)
this.numberRest = this.numberRest < 0 ? 0 : this.numberRest
this.hint = res.presale_info.hint.replace(/\\n/g, '<br/>')
this.buyed = !!res.presale_info.buyed
this.presaleStatus = res.presale_info.state || 0
this.presaleTitle = res.presale_info.title
this.countdown = res.presale_info.countdown
if (this.presaleStatus === 2 && this.countdown > 0) {
this.beginCountdown()
}
AppModule.updateCanBuy(this.presaleStatus === 2 &&
this.numberRest > 0 &&
!this.buyed
)
for (const data of this.heroDatas) {
Vue.set(data, 'stopBuy', this.buyed)
}
}
}
async queryPresaleList() {
const reqData = {
account: '',
page: 0
}
const res: any = await searchBox(reqData)
this.heroDatas.length = 0
for (const data of res.rows) {
const heroData: any = {
name: data.name,
class: (data.job + '').toLowerCase(),
recordId: data.box_id,
id: data.box_id,
skelName: `n_${data.name.toLowerCase()}`,
directBuy: true,
stopBuy: this.buyed,
showBuy: true
}
if (data.currency_list && data.currency_list.length > 0) {
const priceData: any = data.currency_list[0]
heroData.discount = priceData.discount_rate
heroData.price = priceData.original_price
heroData.priceDiscount = priceData.discount_price
heroData.currency = priceData.name
heroData.coinAddress = priceData.contract_address
}
this.heroDatas.push(heroData)
}
}
}

View File

@ -25,6 +25,7 @@ import { BlockChain } from '@/utils/blockchain'
import { AppModule } from '@/store/modules/app'
import { buyBox } from '@/api/Mall'
import { Message } from 'element-ui'
import { EventBus, PRESALE_BEGIN, PRESALE_ERROR, PRESALE_ORDER_GET, PRESALE_SUCCESS } from '@/utils/event-bus'
declare module 'vue/types/vue' {
interface Vue {
@ -60,26 +61,34 @@ export default class extends Vue {
if (this.data.stopBuy) {
return
}
EventBus.$emit(PRESALE_BEGIN)
if (!this.walletCollected) {
await this.bc.connect()
}
const account = AppModule.accountId
const { nonce, signature } = await this.bc.signPresale({
type: this.data.recordId!,
paymentTokenAddress: this.data.coinAddress!,
price: this.data.priceDiscount!,
buyerAddress: account
})
const buyData = {
buyer_address: AppModule.accountId,
type: this.data.recordId,
price: this.data.priceDiscount,
payment_token_address: this.data.coinAddress,
nonce,
signature
try {
const { nonce, signature } = await this.bc.signPresale({
type: this.data.recordId!,
paymentTokenAddress: this.data.coinAddress!,
price: this.data.priceDiscount!,
buyerAddress: account
})
const buyData = {
buyer_address: AppModule.accountId,
type: this.data.recordId,
price: this.data.priceDiscount,
payment_token_address: this.data.coinAddress,
nonce,
signature
}
const res: any = await buyBox(buyData)
const orderId = res.order_id
localStorage.setItem('tmp_presale_order_id', orderId)
EventBus.$emit(PRESALE_ORDER_GET, orderId)
} catch (err) {
console.log('buy error: ', err)
EventBus.$emit(PRESALE_ERROR, err)
}
const res = await buyBox(buyData)
console.log('buy nft: ', res)
}
}
</script>

View File

@ -237,6 +237,7 @@ export default class extends Vue {
background-image: url('../../assets/main/p1/btn_bg.png');
background-repeat: repeat-x;
background-position: 0 17px;
padding: 0 20px;
}
@media (max-width: 767px) {

View File

@ -98,9 +98,12 @@ export class BlockChain {
price: number
buyerAddress: string
}) {
const nonce = Math.random() * 1000 | 0
const nonce = Math.random() * 100000 | 0
const signStr: string = this.web3.utils.soliditySha3(type, paymentTokenAddress, price, nonce)!
let signature = await this.web3.eth.sign(signStr, buyerAddress)
const signStr2 = this.web3.eth.accounts.hashMessage(signStr)
let signature = await this.web3.eth.sign(signStr2, buyerAddress)
// console.log(paymentTokenAddress, type, nonce, price, signature)
// const whoSigned1 = await this.web3.eth.accounts.recover(signStr2, signature, true)
signature = signature.replace(/00$/, '1b').replace(/01$/, '1c')
return { nonce, signature }
}

10
src/utils/event-bus.ts Normal file
View File

@ -0,0 +1,10 @@
import Vue from 'vue'
export const EventBus = new Vue()
export const PRESALE_BEGIN = 'presale_begin'
export const PRESALE_ORDER_GET = 'presale_order_get'
export const PRESALE_SUCCESS = 'presale_success'
export const PRESALE_ERROR = 'presale_error'

View File

@ -54,7 +54,7 @@ service.interceptors.response.use(
location.reload() // To prevent bugs from vue-router
})
}
return Promise.reject(new Error(res.msg || 'Error'))
return Promise.reject(new Error(res.errmsg || 'Error'))
} else {
return response.data
}