Skip to content

Commit aea5f0c

Browse files
authored
Merge pull request #8 from gnolang/feat/fetch
feat: add fetch method
2 parents 676fa6d + 3559ce7 commit aea5f0c

File tree

12 files changed

+73
-97
lines changed

12 files changed

+73
-97
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@
1313
"gsap": "^3.12.5",
1414
"pinia": "^2.1.7",
1515
"vue": "^3.4.15",
16-
"vue-router": "^4.2.5",
1716
"vue-recaptcha": "2.0.3",
17+
"vue-router": "^4.2.5",
1818
"vue3-lottie": "^3.2.0"
1919
},
2020
"devDependencies": {

src/components/faucet/FaucetCard.vue

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
</template>
1010

1111
<script setup lang="ts">
12-
import { computed } from 'vue'
12+
import { computed, ref } from 'vue'
1313
1414
import Card from '@/components/ui/Card.vue'
1515
import FaucetAvailability from './FaucetAvailability.vue'
@@ -26,6 +26,9 @@ interface Props {
2626
2727
const props = defineProps<Props>()
2828
29+
//TODO: request to get availibility (or from props - parent req)
30+
const availability = ref(true)
31+
2932
const tracker = computed(() => {
3033
return {
3134
x: props.motion?.value?.x ?? 0,

src/components/faucet/FaucetDetail.vue

Lines changed: 37 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
ref="DOMpopup"
66
class="popup fixed flex flex-col items-center rounded w-[90vw] max-w-[36rem] bg-grey-300 top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 z-[1000] justify-center text-grey-50 before:absolute before:top-0 before:bottom-0 before:left-0 before:right-0 before:rounded before:bg-500 before:z-min after:absolute after:top-px after:left-px after:bottom-px after:right-px after:bg-grey-500 after:rounded after:z-min"
77
>
8-
<div ref="DOMFaucetRequest" class="p-12">
8+
<div ref="DOMFaucetRequest" class="py-12 px-20 w-full">
99
<FaucetContentForm :name="store.selectedFaucet.name ?? 'Faucet'" :options="store.faucetAmount" v-show="store.contentStep === 0" class="js-faucetform opacity-100" :error="error" @requestFaucet="requestFaucet" />
1010
<div>
1111
<div ref="gnoRequestLogo" v-show="store.contentStep >= 1" class="opacity-0">
@@ -30,9 +30,6 @@ import GnoJSON from '@/assets/lottie/logo.json'
3030
3131
import { useFaucetDetail } from '@/stores/faucetDetail'
3232
33-
import { req } from '@/data/mockedRequest'
34-
import { Status } from '@/types'
35-
3633
const txLink = ref('')
3734
3835
const store = useFaucetDetail()
@@ -43,7 +40,7 @@ const DOMFaucetRequest = ref<HTMLElement | null>(null)
4340
const gnoRequestLogo = ref<HTMLElement | null>(null)
4441
4542
const popupHeight = reactive({ from: 0, to: 0 })
46-
const error = ref<Status | null>(null)
43+
const error = ref<string | null>(null)
4744
4845
const requestFaucet = async (address: string, amount: number, secret: string) => {
4946
popupHeight.from = DOMpopup.value?.getBoundingClientRect().height ?? 0
@@ -59,19 +56,44 @@ const requestFaucet = async (address: string, amount: number, secret: string) =>
5956
})
6057
gsap.to(gnoRequestLogo.value, { autoAlpha: 1, delay: 0.5 })
6158
62-
//TODO: Request - replace fake request
63-
console.log(address)
64-
console.log(amount)
59+
// min default loading timer
60+
const minTimer = new Promise((resolve) => setTimeout(resolve, 2000))
6561
console.log(secret)
6662
67-
const res = await req('success')
68-
store.status = res.code
69-
70-
if (store.status === 'error') {
71-
error.value = res.status
63+
const displayError = (e: string) => {
64+
store.status = 'error'
65+
error.value = e
7266
store.contentStep = 0
73-
} else {
74-
txLink.value = res.txLink ?? ''
67+
console.error(e)
68+
}
69+
try {
70+
const response = await fetch(store.selectedFaucet.url, {
71+
method: 'POST',
72+
headers: {
73+
'Content-Type': 'application/json',
74+
},
75+
body: JSON.stringify({
76+
to: address,
77+
amount: amount * 1000000 + 'ugnot',
78+
captcha: secret,
79+
}),
80+
})
81+
82+
await minTimer
83+
const faucetResponse = await response.json()
84+
85+
store.status = !faucetResponse.result ? 'error' : 'success'
86+
87+
// Check the faucet response
88+
if (!response.ok || store.status === 'error') {
89+
displayError(faucetResponse.error.message)
90+
} else {
91+
store.status = 'success'
92+
txLink.value = faucetResponse.result ?? '' //TODO: get tx link
93+
}
94+
} catch (e) {
95+
await minTimer
96+
displayError(e as string)
7597
}
7698
}
7799

src/components/faucet/FaucetsList.vue

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,19 +14,19 @@
1414

1515
<script setup lang="ts">
1616
import { ref, onMounted } from 'vue'
17+
import { useWindowSize } from '@vueuse/core'
1718
1819
import Carousel from '@/components/ui/Carousel.vue'
1920
import FaucetCard from '@/components/faucet/FaucetCard.vue'
2021
2122
import { useMouseDelegation } from '@/composables/useMouseDelegation'
2223
import { useFaucetDetail } from '@/stores/faucetDetail'
2324
24-
import { useWindowSize } from '@vueuse/core'
25-
2625
import { Faucet } from '@/types'
2726
28-
// TODO: Top replace with real data
29-
import { faucets } from '@/data/faucets.json'
27+
import { faucets as faucetJson } from '@/data/faucets.json'
28+
29+
const faucets = ref(faucetJson as Faucet[])
3030
3131
// slider & cards
3232
const projectCarouselEL = ref<HTMLElement | null>(null)
@@ -37,7 +37,7 @@ let isLoading = false
3737
3838
const { width } = useWindowSize()
3939
40-
const { motions } = useMouseDelegation(projectCarouselEL, faucets, 'ref')
40+
const { motions } = useMouseDelegation(projectCarouselEL, faucets.value, 'ref')
4141
4242
const store = useFaucetDetail()
4343
@@ -48,7 +48,6 @@ const openFaucet = (faucet: Faucet) => {
4848
4949
onMounted(() => {
5050
window.addEventListener('load', () => {
51-
// TODO: To custom with async data
5251
if (cards.value && cards.value?.length > 0) {
5352
store.DOM.cards = cards.value
5453
store.cardDisplay()

src/components/faucet/content/FaucetContentForm.vue

Lines changed: 7 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,15 @@
22
<div>
33
<h2 class="text-600 mb-12">{{ name }}</h2>
44
<form class="w-full space-y-12" @submit.prevent="requestFaucet">
5-
<Input :label="'Enter your wallet address'" :placeholder="'e.g. g1juwee0ynsdvaukvxk3j5s4cl6nn24uxwlydxrl'" v-model="bindAddress" />
5+
<Input :label="'Enter your wallet address'" :placeholder="'e.g. g1juwee0ynsdvaukvxk3j5s4cl6nn24uxwlydxrl'" v-model="bindAddress" required />
66
<Select v-if="store.selectedFaucet.amounts" :label="'Select faucet amount'" :options="options" @update="(option) => SelectAmount(option)" />
77
<Recaptcha @validation="captchaValidation" />
88
<div>
99
<div class="flex gap-4">
10-
<Button text="Request drip" class="w-full" type="submit" />
1110
<Button text="Cancel" variant="outline" @click.prevent="() => closePopup()" class="w-full" />
11+
<Button text="Request drip" class="w-full" type="submit" :disabled="captchaValid === false || bindAddress === ''" />
1212
</div>
13-
<div v-if="error" class="text-center text-red-200 mt-6">{{ errorDetail[error] }}</div>
13+
<div v-if="error" class="text-center text-red-200 mt-6">{{ error }}</div>
1414
</div>
1515
</form>
1616
</div>
@@ -19,8 +19,6 @@
1919
<script setup lang="ts">
2020
import { ref } from 'vue'
2121
22-
import VueRecaptcha from 'vue-recaptcha'
23-
2422
import Input from '@/components/ui/Input.vue'
2523
import Select from '@/components/ui/Select.vue'
2624
import Button from '@/components/ui/Button.vue'
@@ -29,12 +27,12 @@ import Recaptcha from '@/components/ui/Recaptcha.vue'
2927
import { useFaucetDetail } from '@/stores/faucetDetail'
3028
3129
import { SelectOption } from '@/components/ui/Select.vue'
32-
import { Status } from '@/types'
30+
import { Faucet } from '@/types'
3331
3432
type Props = {
35-
name: string
33+
name: Faucet['name']
3634
options: SelectOption[]
37-
error?: Status | null
35+
error?: string | null
3836
}
3937
defineProps<Props>()
4038
const store = useFaucetDetail()
@@ -56,15 +54,8 @@ const closePopup = () => store.popupToggle()
5654
5755
const emit = defineEmits(['requestFaucet'])
5856
59-
const errorDetail = {
60-
FAIL: 'Request failed',
61-
EMPTY: 'Not sufficient tokens available on this network. Try lowering the requested amount or try again later.',
62-
INVALID_ADDRESS: 'Invalid wallet address',
63-
BUSY_FAUCET: 'Too many requests',
64-
}
65-
6657
const requestFaucet = () => {
67-
if (captchaValid.value === false) return
58+
if (captchaValid.value === false || bindAddress.value === '') return
6859
emit('requestFaucet', bindAddress.value, store.selectedFaucet.amounts && amount.value?.value, captchaSecret.value)
6960
}
7061
</script>

src/components/ui/Button.vue

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
<template>
2-
<button class="p-4 rounded border border-light ease-in-out duration-300" :class="css[variant]">
3-
{{ text }}
4-
</button>
2+
<button class="p-4 rounded border border-light ease-in-out duration-300" :class="[css[variant], disabled && ['!bg-grey-100 !border-grey-100 hover:bg-grey-100 hover:!border-grey-100 hover:cursor-not-allowed']]">{{ text }} {{ disabled }}</button>
53
</template>
64

75
<script setup lang="ts">
86
type Props = {
97
text: string
108
variant?: 'default' | 'outline'
9+
disabled?: boolean
1110
}
1211
const props = withDefaults(defineProps<Props>(), {
1312
variant: 'default',
13+
disabled: false,
1414
})
1515
1616
const css = {

src/components/ui/Recaptcha.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ const siteKey = ref(import.meta.env.VITE_reCAPTCHA_SITE_KEY ?? '')
1010
const emit = defineEmits(['validation'])
1111
1212
const handleError = (res: string) => {
13-
emit('validation', { code: 'error', secret: res })
13+
emit('validation', { code: 'error', secret: res ?? 'error' })
1414
}
1515
1616
const handleSuccess = (res: string) => {

src/data/faucets.json

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,9 @@
33
{
44
"name": "Gno Portal Loop",
55
"chain_id": "portal-loop",
6-
"amounts": [
7-
1,
8-
5,
9-
10
10-
],
11-
"url": "https://rpc.gno.land:443",
12-
"recaptcha": "6Lc245EpAAAAAJHI6WezI7VSsy6NiKTq1I7OLlUy"
6+
"amounts": [1, 5, 10],
7+
"url": "https://faucet-api.portal.gnoteam.com",
8+
"recaptcha": "6Ldp0pgpAAAAANZxTw4oy4XkOKhhkmpDl8Yoq6uw"
139
}
1410
]
1511
}

src/data/mockedRequest.ts

Lines changed: 0 additions & 28 deletions
This file was deleted.

src/main.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { createApp } from 'vue'
22
import { createPinia } from 'pinia'
33
import { VueRecaptcha } from 'vue-recaptcha'
4+
45
import './style.css'
56
import App from './App.vue'
67

0 commit comments

Comments
 (0)