From 13089a1e103f134e1decfd0459cdee9c7981a998 Mon Sep 17 00:00:00 2001 From: wrap-that-potassium Date: Tue, 7 Sep 2021 10:43:28 +0200 Subject: [PATCH] New page allowing to blend NFTs airdropped. --- frontend/.env.polygon | 3 + frontend/.env.polygonstaging | 3 + frontend/package.json | 3 +- frontend/src/components/nft/NftPicture.vue | 33 +++ frontend/src/components/nft/NftReward.vue | 69 +++++ frontend/src/models/nft/ClaimGoldenRequest.ts | 9 + frontend/src/models/nft/LoadBalanceRequest.ts | 8 + frontend/src/models/nft/NftData.ts | 9 + frontend/src/pages/NftRewards.vue | 267 ++++++++++++++++++ frontend/src/router/routes.ts | 6 + frontend/src/store/modules/nft.ts | 129 +++++++++ frontend/yarn.lock | 5 + 12 files changed, 543 insertions(+), 1 deletion(-) create mode 100644 frontend/src/components/nft/NftPicture.vue create mode 100644 frontend/src/components/nft/NftReward.vue create mode 100644 frontend/src/models/nft/ClaimGoldenRequest.ts create mode 100644 frontend/src/models/nft/LoadBalanceRequest.ts create mode 100644 frontend/src/models/nft/NftData.ts create mode 100644 frontend/src/pages/NftRewards.vue create mode 100644 frontend/src/store/modules/nft.ts diff --git a/frontend/.env.polygon b/frontend/.env.polygon index e8151ca1..e5be7a34 100644 --- a/frontend/.env.polygon +++ b/frontend/.env.polygon @@ -6,3 +6,6 @@ VUE_APP_BENIS_CONTRACT=0xefa4aED9Cf41A8A0FcdA4e88EfA2F60675bAeC9F VUE_APP_EXPECTED_CHAIN_ID=0x89 VUE_APP_BLOCKCHAIN=polygon VUE_APP_DEX_URL="https://app.sushi.com" + +VUE_APP_NFT_REWARDS_CONTRACT=0xBdc2108A7ec871797325B4a67A9c31E0d1BE2f26 +VUE_APP_NFT_OPENSEA_URL=https://opensea.io/assets/matic diff --git a/frontend/.env.polygonstaging b/frontend/.env.polygonstaging index 3a0ea828..c53e5919 100644 --- a/frontend/.env.polygonstaging +++ b/frontend/.env.polygonstaging @@ -6,3 +6,6 @@ VUE_APP_BENIS_CONTRACT=0xCA24D45C36951f0969574023507F21CA636D6345 VUE_APP_EXPECTED_CHAIN_ID=0x13881 VUE_APP_BLOCKCHAIN=polygon VUE_APP_DEX_URL="https://app.apeswap.finance" + +VUE_APP_NFT_REWARDS_CONTRACT=0xb64E91801B3e1666DEc22F6a43552847162a82eb +VUE_APP_NFT_OPENSEA_URL=https://testnets.opensea.io/assets/mumbai diff --git a/frontend/package.json b/frontend/package.json index 01456724..c5914390 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -22,7 +22,8 @@ "vue-router": "^3.2.0", "vuex": "^3.4.0", "vuex-class": "^0.3.2", - "vuex-module-decorators": "^1.0.1" + "vuex-module-decorators": "^1.0.1", + "wban-nfts": "^0.2.0" }, "devDependencies": { "@quasar/app": "^2.2.4", diff --git a/frontend/src/components/nft/NftPicture.vue b/frontend/src/components/nft/NftPicture.vue new file mode 100644 index 00000000..72f58e67 --- /dev/null +++ b/frontend/src/components/nft/NftPicture.vue @@ -0,0 +1,33 @@ + + + + + diff --git a/frontend/src/components/nft/NftReward.vue b/frontend/src/components/nft/NftReward.vue new file mode 100644 index 00000000..92acc5bc --- /dev/null +++ b/frontend/src/components/nft/NftReward.vue @@ -0,0 +1,69 @@ + + + + + diff --git a/frontend/src/models/nft/ClaimGoldenRequest.ts b/frontend/src/models/nft/ClaimGoldenRequest.ts new file mode 100644 index 00000000..2bae2f88 --- /dev/null +++ b/frontend/src/models/nft/ClaimGoldenRequest.ts @@ -0,0 +1,9 @@ +import { WBANLPRewards } from "wban-nfts" + +type ClaimGoldenRequest = { + contract: WBANLPRewards + account: string + level: number +} + +export default ClaimGoldenRequest diff --git a/frontend/src/models/nft/LoadBalanceRequest.ts b/frontend/src/models/nft/LoadBalanceRequest.ts new file mode 100644 index 00000000..0503f55c --- /dev/null +++ b/frontend/src/models/nft/LoadBalanceRequest.ts @@ -0,0 +1,8 @@ +import { WBANLPRewards } from "wban-nfts" + +type LoadBalanceRequest = { + contract: WBANLPRewards + account: string +} + +export default LoadBalanceRequest diff --git a/frontend/src/models/nft/NftData.ts b/frontend/src/models/nft/NftData.ts new file mode 100644 index 00000000..554b05c8 --- /dev/null +++ b/frontend/src/models/nft/NftData.ts @@ -0,0 +1,9 @@ +type NftData = { + id: string + name: string + description: string + image: string + balance: number +} + +export default NftData diff --git a/frontend/src/pages/NftRewards.vue b/frontend/src/pages/NftRewards.vue new file mode 100644 index 00000000..b04e5101 --- /dev/null +++ b/frontend/src/pages/NftRewards.vue @@ -0,0 +1,267 @@ + + + + + diff --git a/frontend/src/router/routes.ts b/frontend/src/router/routes.ts index dc910686..15ca97c4 100644 --- a/frontend/src/router/routes.ts +++ b/frontend/src/router/routes.ts @@ -31,6 +31,12 @@ const routes: RouteConfig[] = [ children: [{ path: '', component: () => import('@/pages/About.vue') }] }, + { + path: '/nft', + component: () => import('@/layouts/MainLayout.vue'), + children: [{ path: '', component: () => import('@/pages/NftRewards.vue') }] + }, + // Always leave this as last one, // but you can also remove it { diff --git a/frontend/src/store/modules/nft.ts b/frontend/src/store/modules/nft.ts new file mode 100644 index 00000000..f92e72ad --- /dev/null +++ b/frontend/src/store/modules/nft.ts @@ -0,0 +1,129 @@ +import { getModule, VuexModule, Module, Mutation, Action } from 'vuex-module-decorators' +import { namespace } from 'vuex-class' +import { BindingHelpers } from 'vuex-class/lib/bindings' +import store from '@/store' +// eslint-disable-next-line @typescript-eslint/camelcase +import { WBANLPRewards, WBANLPRewards__factory } from 'wban-nfts' +import NftData from '@/models/nft/NftData' +import LoadBalanceRequest from '@/models/nft/LoadBalanceRequest' +import ClaimGoldenRequest from '@/models/nft/ClaimGoldenRequest' +import { ethers } from 'ethers' +import { fetchJson } from 'ethers/lib/utils' + +@Module({ + namespaced: true, + name: 'nft', + store, + dynamic: true +}) +class NftModule extends VuexModule { + private _rewards: WBANLPRewards | null = null + private _uri = '' + private _nfts: Map = new Map() + + static NFT_IDS = [0, 1, 2, 10, 11, 12, 20, 21, 22, 100, 101, 102] + static NFT_REWARDS_CONTRACT: string = process.env.VUE_APP_NFT_REWARDS_CONTRACT || '' + static NFT_OPENSEA_URL: string = process.env.VUE_APP_NFT_OPENSEA_URL || '' + + get rewardsContract() { + return this._rewards + } + + get uri() { + return this._uri + } + + get nfts() { + return this._nfts + } + + @Mutation + setRewardsContract(contract: WBANLPRewards) { + this._rewards = contract + } + + @Mutation + setUri(uri: string) { + this._uri = uri + } + + @Mutation + setNfts(nfts: Map) { + this._nfts = nfts + } + + @Action + // eslint-disable-next-line @typescript-eslint/no-explicit-any + async initContract(provider: any) { + console.debug('in initContract') + if (provider) { + // do not initialize contract if this was done earlier + if (!this._rewards) { + // eslint-disable-next-line @typescript-eslint/camelcase + const contract = WBANLPRewards__factory.connect(NftModule.NFT_REWARDS_CONTRACT, provider.getSigner()) + this.context.commit('setRewardsContract', contract) + } else { + console.warn('Already initialized') + } + // at this point the contract should be initialized + if (!this._rewards) { + console.error('Smart-contract client not initialized') + return + } + // fetch metadata URI for images + this.context.commit('setUri', await this._rewards.uri(0)) + } + } + + @Action + async loadNFTs(request: LoadBalanceRequest) { + const { contract, account } = request + console.debug(`in loadNFTs for ${account}`) + // load NFT balances + const balances = await contract.balanceOfBatch( + [account, account, account, account, account, account, account, account, account, account, account, account], + NftModule.NFT_IDS + ) + console.debug(`Balances of ${account} are ${balances}`) + // load NFT data + const uriTemplate = this._uri.replace('ipfs://', 'https://cloudflare-ipfs.com/ipfs/') + const nfts: Map = new Map() + for (let index = 0; index < NftModule.NFT_IDS.length; index++) { + const balance: number = balances[index].toNumber() + const nftId = NftModule.NFT_IDS[index].toString() + const metadataUri = uriTemplate.replace( + '{id}', + ethers.utils.hexZeroPad(`0x${NftModule.NFT_IDS[index].toString(16)}`, 32).substring(2) + ) + //console.debug(`Metadata URI is: ${metadataUri}`) + const metadata = await fetchJson(metadataUri) + //console.debug(metadata) + const name = metadata.name + const description = metadata.description + const cid = metadata.image.substring('ipfs://'.length) + const uri = `https://cloudflare-ipfs.com/ipfs/${cid}` + nfts.set(nftId.toString(), { + id: nftId, + name, + description, + image: uri, + balance + }) + } + this.context.commit('setNfts', nfts) + } + + @Action + async claimGoldenNFT(request: ClaimGoldenRequest) { + const { contract, account, level } = request + const txn = await contract.claimGoldenNFT(level) + await txn.wait() + await this.loadNFTs({ + contract, + account + }) + } +} + +export default getModule(NftModule) +export const Contracts: BindingHelpers = namespace('nft') diff --git a/frontend/yarn.lock b/frontend/yarn.lock index 54aface6..ce690640 100644 --- a/frontend/yarn.lock +++ b/frontend/yarn.lock @@ -10693,6 +10693,11 @@ watchpack@^1.7.4: chokidar "^3.4.1" watchpack-chokidar2 "^2.0.1" +wban-nfts@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/wban-nfts/-/wban-nfts-0.2.0.tgz#59726ffdcd3c133525c4f8d18fe47ead595527fa" + integrity sha512-tcz85CV/c/bQnj0GswZINXORwCybJZuqOWDp0GZRBbvBwVTGdoWB2Pg9LjGjMfe+wlQtnd06rH9tbU0vQ7TINw== + wbuf@^1.1.0, wbuf@^1.7.3: version "1.7.3" resolved "https://registry.npm.taobao.org/wbuf/download/wbuf-1.7.3.tgz#c1d8d149316d3ea852848895cb6a0bfe887b87df"