@@ -223,8 +225,7 @@ useModalIsOpenTracker({
},
})
-const closeMakingOfferModal = () =>
- (preferencesStore.makeOfferModalOpen = false)
+const closeMakingOfferModal = () => (preferencesStore.makeOfferModalOpen = false)
onBeforeMount(closeMakingOfferModal)
onUnmounted(closeMakingOfferModal)
diff --git a/components/offer/OfferExpirationSelector.vue b/components/offer/OfferExpirationSelector.vue
index 2326dff49f..a0f18ece9e 100644
--- a/components/offer/OfferExpirationSelector.vue
+++ b/components/offer/OfferExpirationSelector.vue
@@ -59,16 +59,14 @@ const props = defineProps<{
}>()
const emit = defineEmits(['update:modelValue'])
-const selected = computed({
- get: () => props.modelValue || 7,
- set: (value) => {
- emit('update:modelValue', value)
- },
+
+const selected = useVModel(props, 'modelValue', emit, {
+ defaultValue: 7,
})
const formattedExpirationTime = computed(() => {
const date = new Date()
- date.setDate(date.getDate() + selected.value)
+ date.setDate(date.getDate() + selected.value!)
return date.toLocaleString(undefined, {
month: 'numeric',
day: '2-digit',
diff --git a/components/offer/OfferPriceInput.vue b/components/offer/OfferPriceInput.vue
index ffb4eaffc3..150151fe60 100644
--- a/components/offer/OfferPriceInput.vue
+++ b/components/offer/OfferPriceInput.vue
@@ -55,10 +55,11 @@ const props = defineProps<{
const { chainSymbol } = useChain()
const { urlPrefix } = usePrefix()
const { balance } = useDeposit(urlPrefix)
+const fiatStore = useFiatStore()
const emit = defineEmits(['update:modelValue'])
const isSymbolMode = ref(true)
-const tokenPrice = ref(0)
+const tokenPrice = computed(() => fiatStore.getCurrentTokenValue(chainSymbol.value as Token) as number)
const switchSymbolMode = () => {
isSymbolMode.value = !isSymbolMode.value
}
@@ -80,10 +81,10 @@ const model = computed({
},
})
-watch(urlPrefix, async () => {
- tokenPrice.value = Number((await getApproximatePriceOf(chainSymbol.value)).toFixed(2))
-}, {
- immediate: true,
+onMounted(() => {
+ if (fiatStore.incompleteFiatValues) {
+ fiatStore.fetchFiatPrice()
+ }
})
watch(isSymbolMode, async (isSymbol) => {
From 029e9faf79bfe667d73c4cc968c5a3d30d82ab30 Mon Sep 17 00:00:00 2001
From: Jarsen <31397967+Jarsen136@users.noreply.github.com>
Date: Wed, 28 Aug 2024 15:51:40 +0200
Subject: [PATCH 07/12] chore: remove blank
---
components/offer/OfferExpirationSelector.vue | 1 -
1 file changed, 1 deletion(-)
diff --git a/components/offer/OfferExpirationSelector.vue b/components/offer/OfferExpirationSelector.vue
index a0f18ece9e..e2af28733f 100644
--- a/components/offer/OfferExpirationSelector.vue
+++ b/components/offer/OfferExpirationSelector.vue
@@ -55,7 +55,6 @@ const selectedItem = computed(() => options.find(option => option.value === sele
const props = defineProps<{
modelValue?: number
-
}>()
const emit = defineEmits(['update:modelValue'])
From 0c0c6a3a55b7f79486a55cb8d27a58df36cda323 Mon Sep 17 00:00:00 2001
From: Jarsen <31397967+Jarsen136@users.noreply.github.com>
Date: Thu, 29 Aug 2024 00:02:44 +0200
Subject: [PATCH 08/12] feat: creating offer signing design
---
components/gallery/useGalleryItem.ts | 13 ++-
components/offer/MakeOffer.vue | 81 +++++++++++--------
.../offer/SuccessfulMakingOfferBody.vue | 76 -----------------
components/profile/create/Modal.vue | 1 +
composables/useMetaTransaction.ts | 3 +-
composables/useSubscriptionGraphql.ts | 4 +-
locales/en.json | 2 +
utils/notification.ts | 6 +-
8 files changed, 69 insertions(+), 117 deletions(-)
delete mode 100644 components/offer/SuccessfulMakingOfferBody.vue
diff --git a/components/gallery/useGalleryItem.ts b/components/gallery/useGalleryItem.ts
index 239a0b7292..d801a6079e 100644
--- a/components/gallery/useGalleryItem.ts
+++ b/components/gallery/useGalleryItem.ts
@@ -34,6 +34,7 @@ export const useGalleryItem = (nftId?: string): GalleryItem => {
const nftMetadata = ref
()
const nftResources = ref()
const nftHighestOffer = ref()
+ const isOfferIndexerDisabled = computed(() => urlPrefix.value !== 'ahp')
const { params } = useRoute()
const id = nftId || params.id
@@ -55,9 +56,9 @@ export const useGalleryItem = (nftId?: string): GalleryItem => {
},
})
- const { data: nftOfferData } = useGraphql({
+ const { data: nftOfferData, refetch: refetchHighestOffer } = useGraphql({
queryName: 'highestOfferByNftId',
- disabled: computed(() => urlPrefix.value !== 'ahp'),
+ disabled: isOfferIndexerDisabled,
variables: {
id,
},
@@ -76,6 +77,14 @@ export const useGalleryItem = (nftId?: string): GalleryItem => {
onChange: refetch,
})
+ useSubscriptionGraphql({
+ query: `offers(where: {status_eq: ACTIVE, desired: {id_eq: "${id}"}}, orderBy: price_DESC, limit: 1) {
+ id
+ }`,
+ disabled: isOfferIndexerDisabled,
+ onChange: refetchHighestOffer,
+ })
+
watch(data as unknown as NFTData, async (newData) => {
const nftEntity = newData?.nftEntity
if (!nftEntity) {
diff --git a/components/offer/MakeOffer.vue b/components/offer/MakeOffer.vue
index 58b12757ee..fb98411381 100644
--- a/components/offer/MakeOffer.vue
+++ b/components/offer/MakeOffer.vue
@@ -9,23 +9,6 @@
@try-again="submitOffer"
/>
-
-
-
-
-
-
void }>({
+ state: 'loading',
+})
+const { itemsInChain, hasInvalidOfferPrices, count } = storeToRefs(offerStore)
const { decimals } = useChain()
const { $i18n } = useNuxtApp()
const items = ref([])
-const isSuccessModalOpen = computed(
- () => Boolean(items.value.length) && isTransactionSuccessful.value,
-)
-
const getAction = (items: MakingOfferItem[]): Actions => {
return {
interaction: ShoppingActions.MAKE_OFFER,
@@ -126,8 +105,6 @@ const getAction = (items: MakingOfferItem[]): Actions => {
duration: item.offerExpiration || 7,
nftSn: item.sn,
} as TokenToOffer)),
- successMessage: $i18n.t('transaction.price.offer') as string,
- errorMessage: $i18n.t('transaction.offerError') as string,
}
}
@@ -179,7 +156,7 @@ const confirmListingLabel = computed(() => {
})
const submitOffer = () => {
- return transaction(getAction(itemsInChain.value))
+ return transaction(getAction(items.value))
}
async function confirm({ autoteleport }: AutoTeleportActionButtonConfirmEvent) {
@@ -204,9 +181,28 @@ async function confirm({ autoteleport }: AutoTeleportActionButtonConfirmEvent) {
const onClose = () => {
closeMakingOfferModal()
}
+const closeMakingOfferModal = () => (preferencesStore.makeOfferModalOpen = false)
-const handleSuccessModalClose = () => {
- items.value = []
+const showOfferCreationNotification = (session) => {
+ const isSessionState = (state: LoadingNotificationState) =>
+ session.value?.state === state
+
+ session.value.closeNotification = loadingMessage({
+ title: ref($i18n.t('offer.offerCreation')),
+ message: ref(undefined),
+ state: computed(() => session?.value.state as LoadingNotificationState),
+ action: computed(() => {
+ if (isSessionState('succeeded')) {
+ return {
+ label: $i18n.t('offer.manageOffers'),
+ icon: 'arrow-up-right',
+ url: `/${urlPrefix.value}/u/${accountId.value}`,
+ }
+ }
+
+ return undefined
+ }),
+ })
}
watch(
@@ -225,7 +221,22 @@ useModalIsOpenTracker({
},
})
-const closeMakingOfferModal = () => (preferencesStore.makeOfferModalOpen = false)
+watch(isError, (error) => {
+ if (error) {
+ offerSession.value.closeNotification?.()
+ }
+})
+
+watch(status, (status) => {
+ switch (status) {
+ case TransactionStatus.Casting:
+ showOfferCreationNotification(offerSession)
+ break
+ case TransactionStatus.Finalized:
+ offerSession.value.state = 'succeeded'
+ break
+ }
+})
onBeforeMount(closeMakingOfferModal)
onUnmounted(closeMakingOfferModal)
diff --git a/components/offer/SuccessfulMakingOfferBody.vue b/components/offer/SuccessfulMakingOfferBody.vue
deleted file mode 100644
index fac0c2ff7e..0000000000
--- a/components/offer/SuccessfulMakingOfferBody.vue
+++ /dev/null
@@ -1,76 +0,0 @@
-
-
-
-
-
-
-
diff --git a/components/profile/create/Modal.vue b/components/profile/create/Modal.vue
index f883269fbd..01205eedb3 100644
--- a/components/profile/create/Modal.vue
+++ b/components/profile/create/Modal.vue
@@ -39,6 +39,7 @@ import type { ProfileFormData } from './stages/index'
import { Form, Introduction, Select } from './stages/index'
import { deleteProfile } from '@/services/profile'
import { appClient, createChannel } from '@/services/farcaster'
+import type { NotificationAction } from '@/utils/notification'
type SessionState = {
state: LoadingNotificationState
diff --git a/composables/useMetaTransaction.ts b/composables/useMetaTransaction.ts
index ddc6f5022d..256a84ec0f 100644
--- a/composables/useMetaTransaction.ts
+++ b/composables/useMetaTransaction.ts
@@ -107,7 +107,8 @@ function useMetaTransaction() {
const onCatchError = (e) => {
if (e instanceof Error) {
- const isCancelled = e.message === 'Cancelled'
+ const errorMessage = e.message?.toLowerCase() || ''
+ const isCancelled = errorMessage.includes('cancelled') || errorMessage.includes('rejected')
if (isCancelled) {
warningMessage($i18n.t('general.tx.cancelled'), { reportable: false })
diff --git a/composables/useSubscriptionGraphql.ts b/composables/useSubscriptionGraphql.ts
index 9fee33e06b..cc2ff9ba3a 100644
--- a/composables/useSubscriptionGraphql.ts
+++ b/composables/useSubscriptionGraphql.ts
@@ -7,19 +7,21 @@ export default function ({
onChange,
onError,
pollingInterval = 6000,
+ disabled,
}: {
clientName?: string
query: string
onChange: (data) => void
onError?: (error) => void
pollingInterval?: number
+ disabled?: ComputedRef
}) {
const { client: prefixClient } = usePrefix()
const { $consola } = useNuxtApp()
const client = clientName || prefixClient.value
const httpUrl = apolloClientConfig[client]?.httpEndpoint
- if (!httpUrl) {
+ if (disabled?.value || !httpUrl) {
return () => {}
}
diff --git a/locales/en.json b/locales/en.json
index 88360ca251..e18a7f7708 100644
--- a/locales/en.json
+++ b/locales/en.json
@@ -1635,6 +1635,8 @@
"yourOfferAmount": "Your Offer Amount" ,
"newOffer": "New Offer",
"bestOffer": "Best Offer",
+ "manageOffers": "Manage Offers",
+ "offerCreation": "Offer Creation",
"collectionFloorPrice": "Collection Floor",
"expiration": "Offer Expiration",
"typeOffer": "Type An Offer",
diff --git a/utils/notification.ts b/utils/notification.ts
index 9b1d2da5cf..92b27199c1 100644
--- a/utils/notification.ts
+++ b/utils/notification.ts
@@ -49,7 +49,7 @@ export const showNotification = ({
action?: MaybeRef
holdTimer?: Ref
icon?: Ref
-}): void => {
+}): () => void => {
if (params === notificationTypes.danger) {
consola.error('[Notification Error]', message)
}
@@ -71,6 +71,8 @@ export const showNotification = ({
}
Notif.open(componentParams)
+
+ return Notif.closeAll
}
export const showLargeNotification = ({
@@ -201,7 +203,7 @@ export const loadingMessage = ({
const isLoadingState = computed(() => state.value === 'loading')
- showNotification({
+ return showNotification({
title,
message: stateMessage,
variant: computed(() => NotificationStateToVariantMap[state.value]),
From f54fbeeb960209241474c6c9af10647f911f8948 Mon Sep 17 00:00:00 2001
From: Jarsen <31397967+Jarsen136@users.noreply.github.com>
Date: Thu, 29 Aug 2024 00:08:49 +0200
Subject: [PATCH 09/12] fix: modal hide time
---
components/offer/MakeOffer.vue | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/components/offer/MakeOffer.vue b/components/offer/MakeOffer.vue
index fb98411381..7fc5ead0ff 100644
--- a/components/offer/MakeOffer.vue
+++ b/components/offer/MakeOffer.vue
@@ -229,7 +229,7 @@ watch(isError, (error) => {
watch(status, (status) => {
switch (status) {
- case TransactionStatus.Casting:
+ case TransactionStatus.Block:
showOfferCreationNotification(offerSession)
break
case TransactionStatus.Finalized:
From 06486687a9e5c9a0df623f58d7da089fd7135f77 Mon Sep 17 00:00:00 2001
From: Jarsen <31397967+Jarsen136@users.noreply.github.com>
Date: Thu, 29 Aug 2024 17:42:40 +0200
Subject: [PATCH 10/12] fix: hide offer button for owner
---
components/gallery/GalleryItemAction/GalleryItemAction.vue | 3 ++-
.../GalleryItemActionType/GalleryItemOffer.vue | 2 ++
components/offer/MakeOffer.vue | 1 -
composables/transaction/transactionOffer.ts | 4 +++-
4 files changed, 7 insertions(+), 3 deletions(-)
diff --git a/components/gallery/GalleryItemAction/GalleryItemAction.vue b/components/gallery/GalleryItemAction/GalleryItemAction.vue
index fd5fef10d7..a06c913b67 100644
--- a/components/gallery/GalleryItemAction/GalleryItemAction.vue
+++ b/components/gallery/GalleryItemAction/GalleryItemAction.vue
@@ -7,7 +7,8 @@
/>
()
const preferencesStore = usePreferencesStore()
const makeOfferStore = useMakingOfferStore()
diff --git a/components/offer/MakeOffer.vue b/components/offer/MakeOffer.vue
index 7fc5ead0ff..95b30105e6 100644
--- a/components/offer/MakeOffer.vue
+++ b/components/offer/MakeOffer.vue
@@ -189,7 +189,6 @@ const showOfferCreationNotification = (session) => {
session.value.closeNotification = loadingMessage({
title: ref($i18n.t('offer.offerCreation')),
- message: ref(undefined),
state: computed(() => session?.value.state as LoadingNotificationState),
action: computed(() => {
if (isSessionState('succeeded')) {
diff --git a/composables/transaction/transactionOffer.ts b/composables/transaction/transactionOffer.ts
index 89ac30ec79..27db522c2f 100644
--- a/composables/transaction/transactionOffer.ts
+++ b/composables/transaction/transactionOffer.ts
@@ -15,6 +15,8 @@ const getOfferId = (prefix: Prefix) => {
const OFFER_MINT_PRICE = '500000000'
+const BLOCKS_PER_DAY = 300 * 24 // 12sec /block --> 300blocks/hr
+
async function execMakingOffer(item: ActionOffer, api, executeTransaction) {
const { accountId } = useAuth()
const nfts = Array.isArray(item.token) ? item.token : [item.token]
@@ -40,7 +42,7 @@ async function execMakingOffer(item: ActionOffer, api, executeTransaction) {
amount: Number(price) || 0,
direction: 'Send',
},
- 300 * 24 * duration, // 12sec /block --> 300blocks/hr
+ BLOCKS_PER_DAY * duration,
)
return [create, offer]
From 52dff3bf4a83fa6acde13eb64a0ae4ab8aa84e49 Mon Sep 17 00:00:00 2001
From: Jarsen <31397967+Jarsen136@users.noreply.github.com>
Date: Sat, 7 Sep 2024 11:03:50 +0200
Subject: [PATCH 11/12] fix: type
---
components/gallery/GalleryItemAction/GalleryItemAction.vue | 2 +-
components/offer/OfferPriceInput.vue | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/components/gallery/GalleryItemAction/GalleryItemAction.vue b/components/gallery/GalleryItemAction/GalleryItemAction.vue
index a06c913b67..a1b4105a4a 100644
--- a/components/gallery/GalleryItemAction/GalleryItemAction.vue
+++ b/components/gallery/GalleryItemAction/GalleryItemAction.vue
@@ -42,7 +42,7 @@ import type { NFT } from '@/components/rmrk/service/scheme'
const props = defineProps<{
nft: NFT | undefined
- highestOffer: NFTOffer
+ highestOffer: NFTOffer | undefined
}>()
const { urlPrefix } = usePrefix()
diff --git a/components/offer/OfferPriceInput.vue b/components/offer/OfferPriceInput.vue
index 150151fe60..088cd98cba 100644
--- a/components/offer/OfferPriceInput.vue
+++ b/components/offer/OfferPriceInput.vue
@@ -10,7 +10,7 @@
step="0.01"
min="0.0001"
pattern="[0-9]+([\.,][0-9]+)?"
- class="indent-2.5 border-none outline-none w-20 bg-background-color text-text-color w-full"
+ class="indent-2.5 border-none outline-none bg-background-color text-text-color w-full"
:placeholder="$t('offer.typeOffer')"
>
From e5dec25c63b698b46bf3cd2f3e5ceff04fd1b4c9 Mon Sep 17 00:00:00 2001
From: Jarsen <31397967+Jarsen136@users.noreply.github.com>
Date: Sat, 7 Sep 2024 11:27:27 +0200
Subject: [PATCH 12/12] fix: type import
---
.../GalleryItemActionType/GalleryItemOffer.vue | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/components/gallery/GalleryItemAction/GalleryItemActionType/GalleryItemOffer.vue b/components/gallery/GalleryItemAction/GalleryItemActionType/GalleryItemOffer.vue
index 3ad8fe74b1..c8e654c639 100644
--- a/components/gallery/GalleryItemAction/GalleryItemActionType/GalleryItemOffer.vue
+++ b/components/gallery/GalleryItemAction/GalleryItemActionType/GalleryItemOffer.vue
@@ -26,7 +26,7 @@ import { usePreferencesStore } from '@/stores/preferences'
import { useMakingOfferStore } from '@/stores/makeOffer'
import MakeOffer from '@/components/offer/MakeOffer.vue'
import GalleryItemPriceSection from '@/components/gallery/GalleryItemAction/GalleryItemActionSection.vue'
-import type { NFTOffer } from '@/components/useNft'
+import type { NFTOffer } from '@/composables/useNft'
const props = defineProps<{
nft: NFT