Fixed Price Sale

Technical Description

Creators to sell something have to:

  1. Create store

    • It's necessary because we have to filter Markets somehow

    • It will contain name, admin key, description

  2. Initialise Selling resource. It can be either created one or our platform will create it.

    • Once user initialise selling resource we have an object with resource which we can sell
  3. Create a Market

    • Create object with info about items selling, all apart from max supply such as we defined it in Selling resource

Users to buy tokens have to:

  1. Go to store.

  2. Choose token and click "Buy"

    • Under the hood next things will happen:

      • TradeHistory account will be created where we track how many tokens this user already bought

      • Debit and credit operations

      • New NFT created(create mint, mint token, create Metadata, create MasterEdition)

  3. Token will be shown in their wallets

Accounts

Store

FieldTypeDescription
adminPubkeyAdmin key who can create selling resources and markets in specific store
nameString
descriptionString

Selling resource

FieldTypeDescription
storePubkey
ownerPubkeyOwner of resource. This account can receive back resource once sail is ended
resourcePubkeyMint account Metadata attached to. We don’t need store Metadata key because it’s PDA and we can calculate it knowing the mint key
vaultPubkeyToken account which holds MasterEdition
vault_ownerPubkeyPDA with seeds [“mt_vault“, resource.key(), store.key()]
supplyu64Amount of tokens already sold
max_supplyOption<u64>Max amount of token can be sold
stateEnum{Uninitialised, Created, InUse, Exhausted, Stoped,}State of resource

Market

FieldTypeDescription
storePubkey
selling_resourcePubkey
treasury_mintPubkeyMint account of tokens which market will accept as a payment
treasury_holderPubkeyToken account buyers will send tokens to. Only market owner can withdraw assets
treasury_ownerPubkeyPDA[“holder“, treasury_mint.key(), selling_resource.key()]
ownerPubkeyMarket owner
nameString
descriptionString
mutablebool
priceu64
pieces_in_one_walletOption<u64>How many tokens we can sell to one wallet
start_dateu64
end_dateOption<u64>
stateEnum {Uninitialised, Created, Active, Ended,}
funds_collectedu64

TradeHistory

PDA [“history“, wallet.key(), market.key()]

FieldTypeDescription
marketPubkey
walletPubkey
already_boughtu64How many tokens user already bought from specific Market

PrimaryMetadataCreators

PDA [“primary_creators“, metadata.key()]

FieldTypeDescription
creatorsVec<mpl_token_metadata::state::Creator>List of creators to receive primary sales royalties

Instructions

CreateStore

Creates new Store account.

ParameterTypeDescription
adminKey, Signer, Writable
storeKey, Signer, WritableUninitialized account
nameString
descriptionString

InitSellingResource

Initialize SellingResource account which will be used by Market.

ParameterTypeDescription
storeKey
store_adminKey, Signer, WritableHolds resource_token and pays for selling_resource account creating
selling_resourceKey, Signer, WritableUninitialized account
selling_resource_ownerKeyKey which can withdraw MasterEdition once sale is ended
resource_mintKeyMint account Metadata attached to
master_editionKeyPDA with seeds [“metadata”, tokenMetadataProgramID, resource_mint, “edition”]
metadataKeyMaster edition’s metadata
vaultKey, WritableToken account to hold resource
vault_ownerPDA [“mt_vault“, resource_mint.key(), store.key()]Owner of vault token account
resource_tokenKey, WritableUser’s token account which holds token from resource_mint
max_supplyOption<u64>Max amount of tokens to sell

CreateMarket

Initialize Market account. Set state to Created, it means that owner can change some data before it will be activated, off course if Market marked as mutable.

:::warning

If user want sell art for native SOL as treasury_mint should be set 11111111111111111111111111111111 also treasury_holder and treasury_owner should be the same accounts PDA. It’s necessary for security reasons so only program will be able to spend that SOL.

:::

ParameterTypeDescription
marketKey, Signer, WritableUninitialized account
storeKey
selling_resource_ownerKey, Signer, Writable
selling_resourceKey, Writable
treasury_mintKeyMint of assets which we will take as a payment
treasury_holderKeyToken account
treasury_ownerPDA [“holder“, treasury_mint.key(), selling_resource.key()]
nameString
descriptionString
mutablebool
priceu64
pieces_in_one_walletOption<u64>
start_dateu64
end_dateOption<u64>
gating_configOption<GatingConfig{collection: Pubkey, expire_on_use: bool, gating_time: Option<u64>}>Gating token. If this value set only users with NFT from pointed collection can buy new NFTs from market.

ChangeMarket

Available only if Market::mutable == true. Can change: name, description, mutable, price, pieces_in_one_wallet.

ParameterTypeDescription
marketKey, Writable
market_ownerKey, Signer
new_nameOption<String>
new_descriptionOption<String>
mutableOption<bool>
new_priceOption<u64>
new_pieces_in_one_walletOption<u64>

Buy

User can call only if current date > Market::start_date.

:::warning

If user buy art for native SOL user_token_acc and user_wallet accounts should be the same.

:::

ParameterTypeDescription
marketKey, Writable
selling_resourceKey, Writable
user_token_accKey, WritableToken account to pay for the member token. Mint of this token acc should be == treasury_mint
user_walletKey, Signer, Writable
trade_historyKey, WritableAccount to track how many NFTs user already bought
treasury_holderKey, Writable
new_metadata_accKey, Writable
new_edition_accKey, Writable
master_edition_accKey, Writable
new_mintKey, Writable
edition_markerKey, WritablePDA, seeds can be found in token-metadata program
vaultKey
vault_ownerPDA [“mt_vault“, resource.key(), store.key()]
master_edition_metadataKey
Below accounts are optional and should be passed only if gating feature is enabled ↓
user_collection_token_accountKey, WritableUser’s token account from collection
token_account_mintKey, WritableToken’s mint account
metadata_accountKeyMetadata account for the mint mentioned above

SuspendMarket

Suspend Market so nobody can buy items and market owner can change data. Instruction should be available only if Market::mutable == true because in other case there is no reason to suspend it.

ParameterTypeDescription
marketKey, Writable
market_ownerKey, Signer
clockKey

ResumeMarket

Instruction to resume the market after it was suspended. Can be called only if market is in suspended state.

ParameterTypeDescription
marketKey, Writable
market_ownerKey, Signer
clockKey

CloseMarket

This instruction can be called only if Market was created with unlimited duration.

ParameterTypeDescription
marketKey, Writable
market_ownerKey, Signer
clockKey

Withdraw

Called by Market owner to withdraw collected treasury funds. Available only if Market::state == Ended.

ParameterTypeDescription
marketKey
selling_resourceKey
metadataKey
treasury_holderKey, WritableMarket::treasury_holder. Token account which holds all the tokens received from users during selling
treasury_mintKey
funderKey
payerKey, Signer
payout_ticketKey, WritablePDA[“payout_ticket“, market.key(), funder.key()]
treasury_ownerKeyPDA[“holder“, treasury_mint.key(), selling_resource.key()]
destinationKey, WritableToken account transfer tokens to
Below account is optional and should be passed only during primary sale ↓
primary_metadata_creators_dataKeyList of creators who should receive royalties from primary sale

ClaimResource

Called by Resource owner. Available only if SellingResource::state == Exhausted of Market::state == Ended.

ParameterTypeDescription
marketKey
treasury_holderKey
selling_resourceKey
selling_resource_ownerKey, Signer
sourceKey, WritableSellingResource::vault. Token account which holds master edition
metadataKeyMetadata for token which was sold
vault_ownerKeyPDA with seeds [“mt_vault“, resource.key(), store.key()]
secondary_metadata_creatorsKey
destinationKey, WritableToken account transfer master edition to

SavePrimaryMetadataCreators

Called before market is created. This list of creators will be used in withdraw instruction to distribute royalties. Take a note that if you are going to sell NFTs from master edition with primary_sale_happen = true you don't need to call this instruction.

ParameterTypeDescription
adminKey, Signer, WritableMetadata’s update authority
metadataKey, Writable
primary_metadata_creatorsKey, WritablePDA with seeds [“primary_creators“, metadata.key()]
system_programKey
primary_metadata_creatorsu8primary_metadata_creators key bump
creatorsVec<mpl_token_metadata::state::Creator>List of creators who will receive primary royalties
Previous
Introduction