Skip to content

Commit

Permalink
Merge pull request #21 from Apillon/dev
Browse files Browse the repository at this point in the history
Dev
  • Loading branch information
MoMannn authored Feb 19, 2024
2 parents b5923be + 91484e7 commit f171f59
Show file tree
Hide file tree
Showing 11 changed files with 175 additions and 19 deletions.
38 changes: 38 additions & 0 deletions .github/workflows/deploy_production.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
name: Deploy production Website

on:
push:
branches:
- main

defaults:
run:
working-directory: ./frontend

jobs:
deploy:
runs-on: ubuntu-latest

steps:
- name: Checkout repository
uses: actions/checkout@v3

- name: Set up Node.js
uses: actions/setup-node@v3
with:
node-version: 18

- name: Install dependencies
run: npm install

- name: Build application
run: npm run generate

- name: Deploy website
env:
APILLON_API_KEY: ${{ secrets.APILLON_API_KEY }}
APILLON_API_SECRET: ${{ secrets.APILLON_API_SECRET }}
WEBSITE_UUID: ${{ secrets.WEBSITE_UUID }}
run: |
npm i -g @apillon/cli
apillon hosting deploy-website ./.output/public --uuid $WEBSITE_UUID --key $APILLON_API_KEY --secret $APILLON_API_SECRET
1 change: 1 addition & 0 deletions frontend/components/general/Spinner.vue
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ defineProps({
position: absolute;
top: 50%;
left: 50%;
color: black;
.path {
stroke-dasharray: 8, 10;
Expand Down
6 changes: 5 additions & 1 deletion frontend/components/parts/Table/Users.vue
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,11 @@ const newUser = ref<UserInterface>({
});
function isEditable(row: UserInterface, index: number) {
return !row.email && props.users.length === index + 1;
return (
!row.email &&
(props.users.length === index + 1 ||
props.users.length % PaginationValues.PAGE_DEFAULT_LIMIT === index + 1)
);
}
const createColumns = (): DataTableColumns<UserInterface> => {
Expand Down
35 changes: 34 additions & 1 deletion frontend/composables/useContract.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,42 @@ export default function useContract() {
const usedChain = config.public.CHAIN_ID === Chains.MOONBASE ? moonbaseAlpha : moonbeam;
const contract = ref();

async function getTokenOfOwner(index: number) {
return (await contract.value.read.tokenOfOwnerByIndex([address.value, index])) as number;
}

async function getTokenUri(id: number) {
return (await contract.value.read.tokenURI([id])) as string;
}

async function watchAsset(nftId: string | number) {
if (!walletClient.value) {
await refetch();
await sleep(200);
}
try {
const contractAddress = contract.value?.address
? contract.value.address
: config.public.CONTRACT_ADDRESS;

await walletClient.value.watchAsset({
type: 'ERC721',
options: {
address: contractAddress,
tokenId: `${nftId}`,
},
});
return true;
} catch (e) {
contractError(e);
return false;
}
}

/**
* Helper for initializing specific contract
*/
async function initContract(contractAddress: string) {
async function initContract(contractAddress: `0x${string}`) {
if (!walletClient.value) {
await refetch();
await sleep(200);
Expand Down Expand Up @@ -85,6 +113,9 @@ export default function useContract() {
} else if (errorData.includes('valid recovery code')) {
// Problem with embedded signature
msg = 'Problem with embedded wallet';
} else if (errorData.includes('Suggested NFT is not owned by the selected account ')) {
msg =
'Suggested NFT is not owned by the selected account, please try again with other wallet.';
} else if (
errorData.includes('user rejected transaction') ||
errorData.includes('User rejected the request')
Expand All @@ -103,7 +134,9 @@ export default function useContract() {
return {
contract,
contractError,
getTokenOfOwner,
getTokenUri,
initContract,
watchAsset,
};
}
5 changes: 3 additions & 2 deletions frontend/lib/config/development.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { ConfigInterface } from '~/lib/types/general.types';

const config: ConfigInterface = {
APP_URL: 'http://localhost:3000',
API_BASE: 'http://localhost:3001',
CAPTCHA_KEY: '10000000-ffff-ffff-ffff-000000000001',
CHAIN_ID: 1287,
CONTRACT_ADDRESS: null,
METADATA_BASE_URI: null,
METADATA_TOKEN: null,
};

export default config;
9 changes: 6 additions & 3 deletions frontend/lib/config/production.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import { ConfigInterface } from '~/lib/types/general.types';

const config: ConfigInterface = {
APP_URL: 'https://ment-stg.nectarnode.io',
APP_URL: 'https://nft.ment.si',
API_BASE: 'https://ment-api.apillon.io',
CAPTCHA_KEY: 'f363ce6d-7543-4284-9caa-cf3219723f04',
CHAIN_ID: 1287,
CONTRACT_ADDRESS: '0x208C1bfa90faC3aED3587a1D9d6F8119aF45FdA6',
METADATA_BASE_URI:
'https://k2k4r8p41ygxp9ogebtgstf7ix8qqn11qdcu2ld4u08896kei1wmcbj3.ipns.nectarnode.io/',
METADATA_TOKEN:
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJjaWQiOiJrMms0cjhwNDF5Z3hwOW9nZWJ0Z3N0ZjdpeDhxcW4xMXFkY3UybGQ0dTA4ODk2a2VpMXdtY2JqMyIsInByb2plY3RfdXVpZCI6IjdhMGQzNzgyLTVhODgtNGYxNS04Yjg4LTA1MTNiOTczNDhjMyIsImlhdCI6MTcwODMyNzg2OCwic3ViIjoiSVBGUy10b2tlbiJ9.dByI1FQ8rj8_dd89r_BtpF0DEdsLNOIovt-7J2mRsB0',
};

export default config;
5 changes: 3 additions & 2 deletions frontend/lib/config/staging.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { ConfigInterface } from '~/lib/types/general.types';

const config: ConfigInterface = {
APP_URL: 'https://app-stg.apillon.io',
API_BASE: 'https://api-stg.apillon.io',
CAPTCHA_KEY: '10000000-ffff-ffff-ffff-000000000001',
CHAIN_ID: 1284,
CONTRACT_ADDRESS: null,
METADATA_BASE_URI: null,
METADATA_TOKEN: null,
};

export default config;
3 changes: 3 additions & 0 deletions frontend/lib/types/general.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ declare global {
API_BASE: string;
CHAIN_ID: number;
CAPTCHA_KEY: string;
CONTRACT_ADDRESS: string | null;
METADATA_BASE_URI: string | null;
METADATA_TOKEN: string | null;
}

type AuthResponseProfile = {
Expand Down
69 changes: 60 additions & 9 deletions frontend/pages/claim.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<script lang="ts" setup>
type Address = `0x${string}`;
import SuccessSVG from '~/assets/images/success.svg';
import colors from '~/tailwind.colors';
import { useAccount, useConnect, useWalletClient } from 'use-wagmi';
Expand All @@ -11,6 +12,7 @@ useHead({
title: 'MENT token airdrop',
});
const config = useRuntimeConfig();
const { query } = useRoute();
const router = useRouter();
const message = useMessage();
Expand All @@ -20,7 +22,7 @@ const { handleError } = useErrors();
const { address, isConnected } = useAccount();
const { data: walletClient, refetch } = useWalletClient();
const { connect, connectors } = useConnect();
const { initContract, getTokenUri } = useContract();
const { initContract, getTokenOfOwner, getTokenUri } = useContract();
const loading = ref<boolean>(false);
Expand All @@ -46,7 +48,9 @@ async function claimAirdrop() {
}
}
const signature = await walletClient.value.signMessage({ message: `Sign to verify and mint your free Ment NFT!\n${timestamp}` });
const signature = await walletClient.value.signMessage({
message: `Sign to verify and mint your free Ment NFT!\n${timestamp}`,
});
const res = await $api.post<ClaimResponse>('/users/claim', {
jwt: query.token?.toString() || '',
signature,
Expand All @@ -63,7 +67,13 @@ async function claimAirdrop() {
console.debug(receipt);
message.success("You've successfully claimed your MENT token.");
if (receipt.data?.to && receipt.data?.logs[0].topics[3]) {
if (
config.public.METADATA_BASE_URI &&
config.public.METADATA_TOKEN &&
receipt.data?.logs[0].topics[3]
) {
getMetadata(Number(receipt.data?.logs[0].topics[3]), res.data.transactionHash);
} else if (receipt.data?.to && receipt.data?.logs[0].topics[3]) {
const nftId = Number(receipt.data?.logs[0].topics[3]);
await loadNft(receipt.data.to, nftId, res.data.transactionHash);
Expand All @@ -72,20 +82,61 @@ async function claimAirdrop() {
}
}
} catch (e) {
handleError(e);
if (
!config.public.CONTRACT_ADDRESS ||
!(await getMyNFT(config.public.CONTRACT_ADDRESS as Address))
) {
handleError(e);
}
}
loading.value = false;
}
async function loadNft(contract: Address, id: number, transactionHash: string) {
async function loadNft(contractAddress: Address, id: number, transactionHash: string) {
try {
await initContract(contract);
await initContract(contractAddress);
const url = await getTokenUri(id);
const metadata = await fetch(url).then(response => {
return response.json();
});
router.push({ name: 'share', query: { ...metadata, txHash: transactionHash } });
router.push({ name: 'share', query: { ...metadata, nftId: id, txHash: transactionHash } });
} catch (e) {
console.error(e);
message.error('Fetch failed, missing NFT metadata!');
}
}
async function getMyNFT(contract: Address) {
try {
await initContract(contract);
const id = await getTokenOfOwner(0);
const url = await getTokenUri(Number(id));
const metadata = await fetch(url).then(response => {
return response.json();
});
if (metadata) {
message.success('You already claimed NFT');
router.push({ name: 'share', query: { ...metadata } });
} else {
return false;
}
} catch (e) {
console.error(e);
return false;
}
}
async function getMetadata(id: number, transactionHash: string) {
try {
const url = `${config.public.METADATA_BASE_URI}${id}.json?token=${config.public.METADATA_TOKEN}`;
const metadata = await fetch(url).then(response => {
return response.json();
});
router.push({ name: 'share', query: { ...metadata, nftId: id, txHash: transactionHash } });
} catch (e) {
console.error(e);
message.error('Fetch failed, missing NFT metadata!');
Expand All @@ -100,8 +151,8 @@ async function loadNft(contract: Address, id: number, transactionHash: string) {
<div v-if="!isConnected" class="my-8 text-center">
<h3 class="mb-6">Almost there!</h3>
<p>
But first, connect a compatible digital wallet. This step is crucial
for securely receiving and managing the MENT token you’re about to receive.
But first, connect a compatible digital wallet. This step is crucial for securely receiving
and managing the MENT token you’re about to receive.
</p>
</div>

Expand Down
4 changes: 3 additions & 1 deletion frontend/pages/index.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
<script lang="ts" setup>
import SuperRareJpg from '~/assets/images/superrare.jpg';
const { isMd } = useScreen();
useHead({
title: 'MENT token airdrop',
});
Expand All @@ -21,7 +23,7 @@ useHead({
<FormSighUp btn-text="Sign up" />
</div>
</div>
<div class="flex-cc relative w-full">
<div v-if="isMd" class="flex-cc relative w-full">
<img :src="SuperRareJpg" class="mx-auto" width="461" height="461" alt="Super rare NFT" />
</div>
</div>
Expand Down
19 changes: 19 additions & 0 deletions frontend/pages/share.vue
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ useHead({
const router = useRouter();
const { query } = useRoute();
const message = useMessage();
const config = useRuntimeConfig();
const { watchAsset } = useContract();
useSeoMeta(
prepareOG(`Just minted my ${query.name} NFT on https://nft.ment.si!`, ``, `${query.image}`)
Expand All @@ -25,6 +27,7 @@ const metadata = ref<Metadata | null>({
description: `${query?.description}`,
image: `${query?.image}`,
});
const nftId = ref<string | undefined>(`${query?.nftId}`);
const txHash = ref<string | undefined>(`${query?.txHash}`);
function transactionLink(transactionHash?: string | null): string {
Expand All @@ -46,6 +49,14 @@ function transactionLink(transactionHash?: string | null): string {
return '';
}
}
async function importNft(nftId: string) {
const imported = await watchAsset(nftId);
if (imported) {
message.success("You've successfully imported your MENT token to your wallet.");
}
}
</script>

<template>
Expand All @@ -63,6 +74,14 @@ function transactionLink(transactionHash?: string | null): string {
</div>
<div class="mt-4 text-center">
<p class="mb-4">{{ metadata.description }}</p>
<Btn
v-if="query?.nftId && nftId"
size="large"
class="!text-black mb-6"
@click="importNft(nftId)"
>
Import NFT to wallet
</Btn>
<a
v-if="query?.txHash && txHash"
:href="transactionLink(txHash)"
Expand Down

0 comments on commit f171f59

Please sign in to comment.