乐趣区

关于区块链:Near-Protocol-Near开发Demo浅析Gamble-Game-Near二Dapp

[Near Protocol] Near 开发 Demo 浅析 -Gamble Game Near

Dapp

接着上一期持续分享

源代码在 Github 上能够找到,以下是 Dapp 链接:

https://github.com/Yang94J/Gamble_Game_Near_Front

简介

本我的项目依靠 Vue,搭建前端利用,调用 near-api-js 与部署好的合约进行交互,实现掷骰子性能。

环境搭建

  • Prerequisite : 零碎中该当曾经装置好 Nodejs,Vue3
  • 我的项目搭建:

      vue create gamble_gamble_near_front

    最终代码框架如下:

    次要对 /components/GambleGame.vue、App.vue、config.js、main.js、store.js、.env、package.json 及 vue.config.js 进行介绍。

<h3> 代码解析 </h3>

package.json

以下是 package.json 重点局部

  "dependencies": {
    "@rollup/plugin-inject": "^4.0.4",
    "buffer": "^6.0.3",
    "core-js": "^3.8.3",
    "near-api-js": "^0.44.2",
    "vue": "^3.2.13",
    "vuex": "^4.0.2"
  },

此处指明了对 buffer、near-api-js、vue、vuex 等依赖(尤其是 buffer,必须要引入并显式申明,否则工程会呈现相似 Can't find variable: Buffer 之类的谬误)

.env

VUE_APP_CONTRACT_NAME=gamble_game1.XXX.testnet

指明 dapp 所需调用的合约名称(测试网)

main.js

import {createApp} from 'vue'
import App from './App.vue'
import store from './store'

import {Buffer} from "buffer"; 
global.Buffer = Buffer;

createApp(App).use(store).mount('#app')

请留神此处显式申明了 global.Buffer

config.js

const CONTRACT_NAME = process.env.VUE_APP_CONTRACT_NAME;

从.env 文件中读取合约名称

case 'testnet':
      return {
        networkId: 'testnet',
        nodeUrl: 'https://rpc.testnet.near.org',
        contractName: CONTRACT_NAME,
        walletUrl: 'https://wallet.testnet.near.org',
        helperUrl: 'https://helper.testnet.near.org',
        explorerUrl: 'https://explorer.testnet.near.org',
      };

依据用户输出环境,抉择对应的网络配置(此处为测试网)。

store.js

store.js 存储数据到本地浏览器,获取缓存等,能够参考该链接

state: {
    contract: null,
    currentUser: null,
    wallet: null,
    nearConfig: null
  },

存储状态包含合约、以后用户、钱包和 near 配置

  mutations: {setupNear(state, payload) {
      state.contract = payload.contract;
      state.currentUser = payload.currentUser;
      state.wallet = payload.wallet;
      state.nearConfig = payload.nearConfig;
    }
  }

设置 state 对象

 async initNear({commit}) {const nearConfig = getConfigurations('testnet');

      const near = await nearApi.connect({
        deps: {keyStore: new nearApi.keyStores.BrowserLocalStorageKeyStore()
        },
        ...nearConfig
      });

      const wallet = new nearApi.WalletConnection(near);
      console.log(wallet)

      let currentUser;

      if (wallet.getAccountId()) {
        currentUser = {accountId: wallet.getAccountId(),
          balance: (await wallet.account().state()).amount,
          balanceInNear : (await wallet.account().state()).amount / (10 ** 24),
        }
      }

      console.log(currentUser)

      const contract = await new nearApi.Contract(wallet.account(), process.env.VUE_APP_CONTRACT_NAME || 'gamble_game1.young_cn.testnet', {viewMethods: ['get_maximum_gamble_price'],
        changeMethods: ['gamble','sponsor'],
        sender: wallet.getAccountId()});
      console.log(contract);
      // Commit and send to mutation.
      commit('setupNear', { contract, currentUser, wallet, nearConfig});
    }
  }

此处 initNear 函数获取测试网配置,生成合约、钱包信息(须要用户登录)、用户信息等。

GambleGame.vue

    <div align="center">
        <h1 align="center" title="log in and gamble to get 6X the prize">Dice Gamble game</h1>
        <button align="center" title="This enables your link to near testnet" @click="currentUser ? signOut() : signIn()">
          {{currentUser ? 'Log Out' : 'Log In'}}
        </button>
    </div>

依据以后用户状况,生成登入登出按钮

 <h3>Hi, {{currentUser.accountId}}, your balance is {{currentUser.balanceInNear}} Near</h3>

显示以后用户 id,以后余额(CurrentUser 信息参见 store.js)

    <p class="highlight">
        <label for="gamble">Maximum : {{gambleLimit}} Near </label>
        <button @click="refresh()"> Refresh</button>
     </p>

显示以后最大投注量,通过 refresh 函数拜访智能合约刷新最大投注量

      <p class="highlight">
        <label for="gamble">Gamble:</label>
        <input autocomplete="off" v-model="gamble" autofocus id="gamble" type="number" required/>
        <button @click="gamblegame()">Gamble</button>
      </p>

投注按钮,调用 gamblegame 办法进行投注

      <p class="highlight">
        <label for="sponsor">Sponsor:</label>
        <input autocomplete="off" v-model="sponsor" autofocus id="sponsor" type="number" required/>
        <button @click="sponsorus()">Sponsor us</button>
      </p>

资助按钮,调用 sponsorus 办法进行资助

  async created(){console.log("created")
    console.log(sessionStorage.getItem('gambleLimit'))
    if (sessionStorage.getItem('gambleLimit')) {this.gambleLimit = sessionStorage.getItem('gambleLimit')
    }
  },

用 created 钩子函数来主动获取最大投注量(否则数据将失落)

  async mounted() {
    var that  = this
      console.log("Mount")
      setInterval(() => {console.log("refresh")
          that.refresh()},3000
      )
  },

应用 mounted 钩子函数来设置自动更新最大投注量 - 思考合约的并发。

signIn() {
      this.wallet.requestSignIn(
        this.nearConfig.contractName,
        'Near Gamble Game'
      );
    },
    signOut() {this.wallet.signOut();
      window.location.replace(window.location.origin + window.location.pathname)
    },

signIn 和 signOut 办法调用 near.api.js 实现与钱包的交互

    async gamblegame(){
      try{
        await this.contract.gamble({},
          this.gas,
          Big(this.gamble).times(10**24).toFixed());
      }catch (e) {console.log(e);
      }
    },
    async sponsorus(){
      try{
        await this.contract.sponsor({},
          this.gas,
          Big(this.sponsor).times(10**24).toFixed());
      }catch (e) {console.log(e);
        alert('Something went wrong! Check the console.');
      }
    },
    async refresh(){this.gambleLimit = await this.contract.get_maximum_gamble_price()
      this.gambleLimit = this.gambleLimit / (10 ** 24)
      sessionStorage.setItem('gambleLimit',this.gambleLimit)
    }
  }

gambleGame、sponsorus 和 refresh 都是异步办法。具体 contract 办法信息在 store.js 里通过以下进行申明:

        viewMethods: ['get_maximum_gamble_price'],
        changeMethods: ['gamble','sponsor'],

部署

  • vue.config.js 批改其配置如下:
const {defineConfig} = require('@vue/cli-service')
module.exports = defineConfig({
  transpileDependencies: true,
  publicPath:'./',
})

将门路改为相对路径

  • 构建
        npm run build
  • 运行
    npm run serve

成果展现

至此,Dapp 局部实现。



诚然,这个 demo 很显著还有很多有余的中央,但也算一个不错的开始。大家有想法也欢送和我一起探讨。相互交换,共同进步。

退出移动版