Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Reuse unused tokens for the next offer #11204

Merged
merged 21 commits into from
Jan 8, 2025
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
a299af4
add(offers): use unsued offered nft tokens
hassnian Dec 2, 2024
5143869
ref(offers): unsued offer tokens check by `id` and `currentOwner`
hassnian Dec 2, 2024
54f4951
Merge branch 'main' into issue-offer-reuse-nft
hassnian Dec 2, 2024
98715f6
ref(offers): `execMakingOffer` transaction action param type
hassnian Dec 2, 2024
78a6d60
Merge branch 'issue-offer-reuse-nft' of https://github.com/hassnian/n…
hassnian Dec 2, 2024
c3996ea
fix(offers): action params in modal
hassnian Dec 2, 2024
3273b99
Merge branch 'main' into issue-offer-reuse-nft
hassnian Dec 8, 2024
3d1e9db
Merge branch 'main' into issue-offer-reuse-nft
hassnian Dec 11, 2024
e812186
Merge branch 'main' into issue-offer-reuse-nft
hassnian Dec 19, 2024
ee9d345
Merge branch 'main' into issue-offer-reuse-nft
hassnian Dec 20, 2024
b86eed5
Merge branch 'main' into issue-offer-reuse-nft
hassnian Dec 28, 2024
17f2533
fix(transaction/utils.ts): `isActionValid` accept swap action validation
hassnian Dec 29, 2024
936a127
fix(MakeOfferModal.vue): freeze action on modal signing
hassnian Dec 29, 2024
6c2c6ce
ref(MakeOfferModal.vue): remove default offer expiration duration mag…
hassnian Dec 29, 2024
c8157cf
fix(transactionOffer.ts): dont allow offers with `0` price
hassnian Dec 29, 2024
ee457d8
ref(transactionOffer.ts): use `isAssetHub` util
hassnian Dec 29, 2024
73c896d
fix(transactionExecutor.ts): ts warning
hassnian Dec 29, 2024
9ca79ac
Merge branch 'main' into issue-offer-reuse-nft
hassnian Dec 29, 2024
c663b01
Merge branch 'main' into issue-offer-reuse-nft
hassnian Jan 2, 2025
3382e01
Merge branch 'main' into issue-offer-reuse-nft
hassnian Jan 4, 2025
facfc9d
Merge branch 'main' into issue-offer-reuse-nft
vikiival Jan 8, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
add(offers): use unsued offered nft tokens
  • Loading branch information
hassnian committed Dec 2, 2024
commit a299af4c5a31f791ffe321647e75ec521e33df33
55 changes: 51 additions & 4 deletions components/trade/makeOffer/MakeOfferModal.vue
Original file line number Diff line number Diff line change
Expand Up @@ -59,11 +59,12 @@

<script setup lang="ts">
import { NeoModal } from '@kodadot1/brick'
import { shuffle } from 'lodash'
import type { MakingOfferItem } from '@/components/trade/types'
import MakeOfferSingleItem from '@/components/trade/makeOffer/MakeOfferSingleItem.vue'
import ModalBody from '@/components/shared/modals/ModalBody.vue'
import { usePreferencesStore } from '@/stores/preferences'
import type { Actions, TokenToOffer } from '@/composables/transaction/types'
import type { ActionOffer, TokenToOffer } from '@/composables/transaction/types'
import { useMakingOfferStore } from '@/stores/makeOffer'
import format, { calculateBalance } from '@/utils/format/balance'
import { warningMessage } from '@/utils/notification'
Expand Down Expand Up @@ -98,13 +99,17 @@ const { itemsInChain, hasInvalidOfferPrices, count } = storeToRefs(offerStore)
const { decimals, chainSymbol } = useChain()
const { $i18n } = useNuxtApp()
const items = ref<MakingOfferItem[]>([])
const unusedOfferedItemsSubscription = ref(() => {})
const usedOfferedItems = ref<string[]>([])
const offeredItem = ref<string>()

const getAction = (items: MakingOfferItem[]): Actions => {
const getAction = (items: MakingOfferItem[]): ActionOffer => {
return {
interaction: ShoppingActions.MAKE_OFFER,
urlPrefix: urlPrefix.value,
token: items.map(item => ({
price: String(calculateBalance(Number(item.offerPrice), decimals.value)),
offeredItem: offeredItem.value,
collectionId: item.collection.id,
duration: item.offerExpiration || 7,
nftSn: item.sn,
Expand All @@ -120,15 +125,15 @@ const teleportTransitionTxFees = computed(() =>
),
)

const { action, autoTeleport, autoTeleportButton, autoTeleportLoaded } = useAutoTeleportActionButton({
const { action, autoTeleport, autoTeleportButton, autoTeleportLoaded } = useAutoTeleportActionButton<ActionOffer>({
getActionFn: () => getAction(itemsInChain.value),
})

const totalOfferAmount = computed(
() => calculateBalance(sum(itemsInChain.value.map(nft => Number(nft.offerPrice))), decimals.value),
)

const totalNeededAmount = computed(() => totalOfferAmount.value + OFFER_MINT_PRICE)
const totalNeededAmount = computed(() => totalOfferAmount.value + (!offeredItem.value ? OFFER_MINT_PRICE : 0))

const actions = computed<AutoTeleportAction[]>(() => [
{
Expand Down Expand Up @@ -176,6 +181,7 @@ const submitOffer = () => {
async function confirm({ autoteleport }: AutoTeleportActionButtonConfirmEvent) {
try {
clearTransaction()
unusedOfferedItemsSubscription.value()

autoTeleport.value = autoteleport
items.value = [...itemsInChain.value]
Expand Down Expand Up @@ -210,6 +216,47 @@ useModalIsOpenTracker({
isOpen: computed(() => preferencesStore.makeOfferModalOpen),
onChange: () => {
offerStore.clear()
unusedOfferedItemsSubscription.value()
},
})

useModalIsOpenTracker({
isOpen: computed(() => preferencesStore.makeOfferModalOpen),
onClose: false,
onChange: () => {
unusedOfferedItemsSubscription.value = useSubscriptionGraphql({
query: `
offers(where: {
status_not_in: [ACTIVE, ACCEPTED]
caller_eq: "${accountId.value}"
}) {
nft {
sn
}
}`,
onChange: ({ data: { offers: items } }) => {
const tokensSn = items
.map(({ nft }) => nft.sn)
.filter((tokenSn: string) => !usedOfferedItems.value.includes(tokenSn))

const unusedOfferedItems = shuffle(tokensSn)

offeredItem.value = unusedOfferedItems[0]
},
})
},
})

useTransactionTracker({
transaction: {
isError,
status,
},
onSuccess: () => {
if (offeredItem.value) {
usedOfferedItems.value.push(offeredItem.value)
offeredItem.value = undefined
}
},
})

Expand Down
4 changes: 2 additions & 2 deletions composables/autoTeleport/useAutoTeleportActionButton.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import type { Actions } from '@/composables/transaction/types'

export default ({
export default <T = Actions>({
getActionFn,
}) => {
const { decimals, chainSymbol } = useChain()

const autoTeleport = ref(false)
const autoTeleportButton = ref()
const autoTeleportLoaded = ref(false)
const action = ref<Actions>(emptyObject<Actions>())
const action = ref<T>(emptyObject<T>())

const txFees = computed(() => autoTeleportButton.value?.optimalTransition.txFees || 0)
const { formatted: formattedTxFees } = useAmount(txFees, decimals, chainSymbol)
Expand Down
45 changes: 28 additions & 17 deletions composables/transaction/transactionOffer.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import type { ApiPromise } from '@polkadot/api'
import type { SubmittableExtrinsic } from '@polkadot/api-base/types'
import type { Prefix } from '@kodadot1/static'
import type { ActionOffer } from './types'
import { generateId } from '@/services/dyndata'
Expand All @@ -17,35 +19,44 @@ export const OFFER_MINT_PRICE = 5e8

const BLOCKS_PER_DAY = 300 * 24 // 12sec /block --> 300blocks/hr

async function execMakingOffer(item: ActionOffer, api, executeTransaction) {
async function execMakingOffer(item: ActionOffer, api: ApiPromise, executeTransaction) {
const { accountId } = useAuth()
const nfts = Array.isArray(item.token) ? item.token : [item.token]
const transactions = await Promise.all(
nfts.map(async ({ price, nftSn, collectionId, duration }) => {
const offerId = getOfferCollectionId(item.urlPrefix as Prefix)
const nextId = Number.parseInt(await generateId())
const create = api.tx.nfts.mint(
offerId,
nextId,
accountId.value,
{
mintPrice: String(OFFER_MINT_PRICE),
},
)
nfts.map(async ({ price, nftSn: desiredItem, collectionId: desiredCollectionId, duration, offeredItem: offeredSn }) => {
const offeredCollectionId = getOfferCollectionId(item.urlPrefix as Prefix)
let offeredItem = Number(offeredSn)

const transactions: SubmittableExtrinsic<'promise'>[] = []

if (!offeredItem) {
offeredItem = Number.parseInt(await generateId())
const create = api.tx.nfts.mint(
offeredCollectionId,
offeredItem,
accountId.value,
{
mintPrice: String(OFFER_MINT_PRICE),
},
)
transactions.push(create)
}

const offer = api.tx.nfts.createSwap(
offerId,
nextId,
collectionId,
nftSn,
offeredCollectionId,
offeredItem,
desiredCollectionId,
desiredItem,
{
amount: Number(price) || 0,
direction: 'Send',
},
vikiival marked this conversation as resolved.
Show resolved Hide resolved
BLOCKS_PER_DAY * duration,
)

return [create, offer]
transactions.push(offer)

return transactions
}),
)

Expand Down
1 change: 1 addition & 0 deletions composables/transaction/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,7 @@ export type TokenToList = {

export type TokenToOffer = {
price: string
offeredItem?: string
collectionId: string
nftSn: string
duration: number
Expand Down