Fixes World
Github
  • 💡What is Fixes?
  • 📓Concepts
    • 🔡Fixes Inscription
    • 💹Fixes Coins
      • Guide 1: How to Launch a new Coin?
    • 🎟️Lottery Game
    • 👻𝔉rc20s
    • 📔Token List
      • 📘Query TokenList
      • 📙Query Reviewers
  • 👨‍💻Developer
    • On-chain Interactions
      • 🔯𝔉rc20
        • Deploy - tx
        • Mint(batch) - tx
        • Transfer - tx
        • Burn - tx
        • List for Sale - tx
        • Take list as buyer - tx
        • List for Purchase - tx
        • Take list as seller - tx
        • Cancel Listing - tx
      • 🔡Fixes Inscription
        • EstimateCost - read
    • Open API Service
      • 🔯𝔉rc20 Basics
        • Query 𝔉rc20 Tokens
        • Fetch 𝔉rc20 Token Info
        • Check 𝔉rc20 registered
        • Get 𝔉rc20 balances
        • Get 𝔉rc20 balance
      • 🛒𝔉rc20 Marketplace
        • Query all 𝔉rc20 Markets
        • Fetch 𝔉rc20 Market detailed info
        • Check 𝔉rc20 Market enabled
        • Query 𝔉rc20 Listings
        • Query Market Trading History
        • Query Address Trading History
      • 🔧Utilities
        • Estimate Fixes inscribing cost
        • Get current $FLOW price
      • 📃Legal Disclaimer
  • 🔗LINKS
    • Official Website
    • Linktree
Powered by GitBook
On this page
Edit on GitHub
  1. Developer
  2. On-chain Interactions
  3. 𝔉rc20

Take list as seller - tx

Take the 𝔉rc20 token purchase listing as a seller

PreviousList for Purchase - txNextCancel Listing - tx

Last updated 1 year ago

Example of Fixes Inscription data string:

op=list-take-sellnow,tick=fixes,amt=10000.0

Transaction parameters:

Key
Required
FType
Description

tick

t.String

Ticker: identity of the 𝔉rc20 token

batchSellItems

t.Dictionary({ key: t.String, value: t.UFix64 })

The dictionary for selling:

rankedId => Amount You can get RankedListingId by querying the marketplace

Note: The key of batchSellItems should be itemInMarket.rankedId which can be obtained in the response of querying listings. and the value is how much tokens you will take in the order. 𝔉rc20 trading orders support partial deal.

Transaction code example:

import txUserTakeAsSeller from "@fixes/contracts/transactions/marketplace/user-take-as-seller-with-commission.cdc?raw";

async function userTakeAsSeller(
  tick: string,
  batchSellItems: Record<string, number>
) {
  let args: Array<{ key: string; value: string }> = [];
  for (const key in batchSellItems) {
    if (!Object.prototype.hasOwnProperty.call(batchSellItems, key)) continue;
    args.push({
      key,
      value: batchSellItems[key].toFixed(8),
    });
  }
  const txid = await flow.sendTransaction(txUserTakeAsSeller, (arg, t) => [
    arg(tick, t.String),
    arg(args, t.Dictionary({ key: t.String, value: t.UFix64 })),
  ]);
  return txid;
}

Transaction source code

Related docs

  • EstimateCost - read

  • Query 𝔉rc20 Listings

👨‍💻
🔯
📓
How to send a transaction to Flow blockchain or query data from Flow blockchain?
https://github.com/fixes-world/fixes/blob/main/cadence/transactions/marketplace/user-take-as-seller-with-commission.cdc
// Thirdparty imports
import "MetadataViews"
import "FungibleToken"
import "FlowToken"
// Fixes imports
import "Fixes"
import "FixesInscriptionFactory"
import "FixesAvatar"
import "FixesHeartbeat"
import "FRC20FTShared"
import "FRC20Indexer"
import "FRC20TradingRecord"
import "FRC20Storefront"
import "FRC20Marketplace"
import "FRC20MarketManager"

transaction(
    tick: String,
    // RankedId => SellAmount
    batchSellItems: {String: UFix64},
) {
    let market: &{FRC20Marketplace.MarketPublic}

    prepare(acct: auth(Storage, Capabilities) &Account) {
        /** ------------- Prepare the Inscription Store - Start ---------------- */
        let storePath = Fixes.getFixesStoreStoragePath()
        if acct.storage
            .borrow<auth(Fixes.Manage) &Fixes.InscriptionsStore>(from: storePath) == nil {
            acct.storage.save(<- Fixes.createInscriptionsStore(), to: storePath)
        }

        let store = acct.storage
            .borrow<auth(Fixes.Manage) &Fixes.InscriptionsStore>(from: storePath)
            ?? panic("Could not borrow a reference to the Inscriptions Store!")
        /** ------------- End -------------------------------------------------- */

        /** ------------- Start -- FRC20 Marketplace -------------  */
        // Borrow a reference to the FRC20Marketplace contract
        self.market = FRC20MarketManager.borrowMarket(tick)
            ?? panic("Could not borrow reference to the FRC20Market")

        assert(
            self.market.getTickerName() == tick,
            message: "The market is not for the FRC20 token with tick ".concat(tick)
        )
        assert(
            self.market.canAccess(addr: acct.address),
            message: "You are not allowed to access this market for now."
        )
        /** ------------- End -------------------------------------  */

        /** ------------- Start -- TradingRecords General Initialization -------------  */
        // Ensure hooks are initialized
        if acct.storage.borrow<&AnyResource>(from: FRC20FTShared.TransactionHookStoragePath) == nil {
            let hooks <- FRC20FTShared.createHooks()
            acct.storage.save(<- hooks, to: FRC20FTShared.TransactionHookStoragePath)
        }

        // link the hooks to the public path
        if acct
            .capabilities.get<&FRC20FTShared.Hooks>(FRC20FTShared.TransactionHookPublicPath)
            .borrow() == nil {
            // link the hooks to the public path
            acct.capabilities.unpublish(FRC20FTShared.TransactionHookPublicPath)
            acct.capabilities.publish(
                acct.capabilities.storage.issue<&FRC20FTShared.Hooks>(FRC20FTShared.TransactionHookStoragePath),
                at: FRC20FTShared.TransactionHookPublicPath
            )
        }

        // borrow the hooks reference
        let hooksRef = acct.storage
            .borrow<auth(FRC20FTShared.Manage) &FRC20FTShared.Hooks>(from: FRC20FTShared.TransactionHookStoragePath)
            ?? panic("The hooks were not created")

        // Ensure Trading Records is initialized
        if acct.storage.borrow<&AnyResource>(from: FRC20TradingRecord.TradingRecordsStoragePath) == nil {
            let tradingRecords <- FRC20TradingRecord.createTradingRecords(nil)
            acct.storage.save(<- tradingRecords, to: FRC20TradingRecord.TradingRecordsStoragePath)
            // link the trading records to the public path
            acct.capabilities.unpublish(FRC20TradingRecord.TradingRecordsPublicPath)
            acct.capabilities.publish(
                acct.capabilities.storage.issue<&FRC20TradingRecord.TradingRecords>(FRC20TradingRecord.TradingRecordsStoragePath),
                at: FRC20TradingRecord.TradingRecordsPublicPath
            )
        }

        // Ensure trading record hook is added to the hooks
        // get the public capability of the trading record hook
        let tradingRecordsCap = acct
            .capabilities.get<&FRC20TradingRecord.TradingRecords>(
                FRC20TradingRecord.TradingRecordsPublicPath
            )
        assert(tradingRecordsCap.check(), message: "The trading record hook is not valid")
        // get the reference of the trading record hook
        let recordsRef = tradingRecordsCap.borrow() ?? panic("The trading record hook is not valid")
        if !hooksRef.hasHook(recordsRef.getType()) {
            hooksRef.addHook(tradingRecordsCap)
        }

        // Ensure Fixes Avatar is initialized
        if acct.storage.borrow<&AnyResource>(from: FixesAvatar.AvatarStoragePath) == nil {
            acct.storage.save(<- FixesAvatar.createProfile(), to: FixesAvatar.AvatarStoragePath)
            // link the avatar to the public path
            acct.capabilities.unpublish(FixesAvatar.AvatarPublicPath)
            acct.capabilities.publish(
                acct.capabilities.storage.issue<&FixesAvatar.Profile>(FixesAvatar.AvatarStoragePath),
                at: FixesAvatar.AvatarPublicPath
            )
        }
        let profileCap = FixesAvatar.getProfileCap(acct.address)
        assert(profileCap.check(), message: "The profile is not valid")
        let profileRef = profileCap.borrow() ?? panic("The profile is not valid")
        if !hooksRef.hasHook(profileRef.getType()) {
            hooksRef.addHook(profileCap)
        }
        /** ------------- End -----------------------------------------------------------------  */

        // Get a reference to the signer's stored vault
        let vaultRef = acct.storage
            .borrow<auth(FungibleToken.Withdraw) &FlowToken.Vault>(from: /storage/flowTokenVault)
            ?? panic("Could not borrow reference to the owner's Vault!")

        // For each buy item, check the listing
        for rankedId in batchSellItems.keys {
            let listedItem = self.market.getListedItemByRankdedId(rankedId: rankedId)
            /** ------------- Start -- FRC20 Storefront Initialization -------------  */
            // Do not panic for better UX
            if listedItem == nil {
                continue
            }
            let storefront = listedItem!.borrowStorefront()
            let listing = listedItem!.borrowListing()
            // Do not panic for better UX
            if storefront == nil || listing == nil {
                continue
            }
            let listingDetails = listing!.getDetails()
            // Do not panic for better UX
            if listingDetails.status != FRC20Storefront.ListingStatus.Available {
                continue
            }
            if listingDetails.type != FRC20Storefront.ListingType.FixedPriceSellNow {
                continue
            }
            if listingDetails.tick != tick {
                continue
            }
            /** ------------- End --------------------------------------------------  */

            var commissionFlowRecipient: Capability<&FlowToken.Vault>? = nil
            if let receivers = listing!.getAllowedCommissionReceivers() {
                if receivers.length > 0 {
                    commissionFlowRecipient = receivers[0]
                    assert(commissionFlowRecipient!.check(), message: "Invalid commission recipient")
                }
            }

            let sellAmount = batchSellItems[rankedId]!

            /** ------------- Start -- Inscription Initialization -------------  */
            // create the metadata
            let dataStr = FixesInscriptionFactory.buildMarketTakeSellNow(tick: tick, amount: sellAmount)

            // estimate the required storage
            let estimatedReqValue = FixesInscriptionFactory.estimateFrc20InsribeCost(dataStr)

            // Withdraw tokens from the signer's stored vault
            // Total amount to withdraw is the estimated required value + the buy price
            let flowToReserve <- vaultRef.withdraw(amount: estimatedReqValue)

            // Create the Inscription first
            let newInsId = FixesInscriptionFactory.createAndStoreFrc20Inscription(
                dataStr,
                <- (flowToReserve as! @FlowToken.Vault),
                store
            )
            // borrow a reference to the new Inscription
            let insRef = store.borrowInscriptionWritableRef(newInsId)
                ?? panic("Could not borrow reference to the new Inscription!")
            /** ------------- End ---------------------------------------------  */

            // execute taking
            listing?.takeSellNow(ins: insRef, commissionRecipient: commissionFlowRecipient)

            // cleanup
            self.market.tryRemoveCompletedListing(rankedId: listedItem!.rankedId)
        }
    }

    execute {
        log("Done: user take as seller with commission")
    }
}