NFTX
v3.0
Search
K

Marketplace Integration

These are the pseudo steps to integrate NFTX NFTs and liquidity into your application
  1. 1.
    Retrieve all NFTX vaults from the subgraph, including global fees, and holdings
  2. 2.
    Use the asset > id in the subgraph response to link the NFTX vault with the appropriate NFT collection in your application
  3. 3.
    Verify that the vault has features > enableRedeems set to true so specific NFTs can be bought from the vault.
  4. 4.
    Check if the vault uses default fees using usesFactoryFees , if true use the global fees to calculate the tokens required to buy an NFT, if false use the fees > redeemFee associated with the vault. To buy an NFT you need 1 token + vTokenToEth value of the fee.
  5. 5.
    Using the NFTX Universal Router API, check the ETH cost to buy the required tokens. As the number of tokens required increases (i.e. the user adds more items to their basket) the average price of the NFT will increase due to price impact on the token buy.
  6. 6.
    When the user buys, call the MarketplaceUniversalRouterZap to complete the purchase.

Contract Addresses

Sepolia Contract Addresses

"sepolia": {
"CreateVaultZap": "0x50f69c6556338965bf77C16ADb462Fdb5bE01C09",
"MarketplaceUniversalRouterZap": "0x5Af324A8c90966Bef28386A67c6bE0A16aA03c19",
"NFTXFeeDistributorV3": "0x66EF5B4b6ee05639194844CE4867515665F14fED",
"NFTXInventoryStakingV3Upgradeable": "0xfBFf0635f7c5327FD138E1EBa72BD9877A6a7C1C",
"NFTXRouter": "0xD36ece08F76c50EC3F01db65BBc5Ef5Aa5fbE849",
"nftxUniversalRouter": "0x12156cCA1958B6591CC49EaE03a5553458a4b424",
"NFTXVaultFactoryUpgradeableV3": "0x31C56CaF49125043e80B4d3C7f8734f949d8178C",
"NonfungiblePositionManager": "0x55BDc76262B1e6e791D0636A0bC61cee23CDFa87",
"permit2": "0x000000000022d473030f116ddee9f6b43ac78ba3",
"QuoterV2": "0xb8EB27ca4715f7A04228c6F83935379D1f5AbABd",
"SwapRouter": "0xa7069da6a7e600e0348620484fD2B1f24E075d5f",
"TickLens": "0xA13E04fAEe08E784A44C27e9E77Ca7a02D45BFd7",
"UniswapV3FactoryUpgradeable": "0xDD2dce9C403f93c10af1846543870D065419E70b",
"WETH": "0xfFf9976782d46CC05630D1f6eBAb18b2324d6B14"
}

New features of note in V3

There have been some updates to the way in which the NFTX V3 protocol works if you are used to NFTX v2. The two updates that are most relevant for

Vault Fees paid in ETH

In V2 the fees paid were done using the native vToken. This meant if there was a 5% fee for buying an NFT, you needed to swap 1.05 vTokens with 1 vToken being burned and the other 0.05 vTokens distributed to liquidity and inventory providers
In NFTX V3 the fees are now paid in ETH as part of the transaction. Using the same 5% fee example, users will now buy 1 vToken through the NFTX Universal AMM Router, and the additional fee amount can be worked out by passing the fee amount to the vault contract vTokenToEth function.
redeemFee = 5000000000000000
vTokenAmount = 49995022529647 wei
The vTokenToETH function is based on the TWAP and does not flucuate based on the available liquidity in the pool. For example, if you were buying 5 items the fee amount would be 5 * 5000000000000000 = 25000000000000000
which would equate to
5 * 49995022529647 = 249975112648235
Buying more tokens doesn't impact the spread for the vTokenToETH calculation

Premium NFT auctions

When an NFT is "minted" into the vault on Sepolia a premium fee of 500% placed on the item at an exponential reduction to 0% over 3600 seconds. The fee is reduced every second. mainnet duration will be 10 hours (36000 seconds)
To find the current fee required for the NFT pass the ID of the NFT into the getVTokenPremium function on the vault contract. The response includes the premium amount and the depositor address. The depositor will receieve the majority of the premium fee, with the liquidity and inventory providers also sharing in a portion, but this address is not required for the marketplace integration, only the premium amount.
Checking the getVTokenPremium721 for tokenId 310
If you want to omit the premium NFTs from your integration you can add a filter to the subgraph call to require the holdings.dateAdded is less than now - 3600.
Add this to your Get all NFT holdings query
holdings(first: 1000, orderBy: tokenId, orderDirection: asc, where: { dateAdded_lt: "$(now - 3600)"})
Remember that the premium reduces every second even though the blocks are only every 12 seconds. This will mean that what ever calculation you make for the buyer, the actual buy price is going to be lower because more time has elapsed before the next block is mined. This additional ETH is returned to the user as part of the transaction.

Get all NFT holdings

Send a request to the NFTX V3 subgraph for all vaults.

Graph Endpoints

Mainnet Graph Endpoint: Not yet deployed.
Arbitrum Graph Endpoint: Not yet deployed.
Graph request:
{
globals {
fees {
mintFee
randomRedeemFee
targetRedeemFee
randomSwapFee
targetSwapFee
}
}
vaults(
first: 1000
where: {vaultId_gte: 0, isFinalized: true, totalHoldings_gt: 0}
) {
vaultId
id
is1155
isFinalized
totalHoldings
totalMints
totalRedeems
totalFees
totalSwaps
createdAt
holdings(first: 1000, orderBy: tokenId, orderDirection: asc) {
id
tokenId
amount
dateAdded
}
# holdings(
# first: 1000,
# orderBy: tokenId,
# orderDirection: asc,
# where: { dateAdded_lt: "$(now - 3600)"}
# ) {
# id
# tokenId
# amount
# dateAdded
# }
token {
id
name
symbol
}
fees {
mintFee
redeemFee
swapFee
}
usesFactoryFees
asset {
id
name
symbol
}
manager {
id
}
createdBy {
id
}
eligibilityModule {
id
eligibleIds
eligibleRange
}
features {
enableMint
enableRedeem
enableSwap
}
}
}

Buying an NFT(s) from the vaults

When buying items from the vault you need
  1. 1.
    redeemFee amount to calculate the ETH fee required (subgraph).
  2. 2.
    vTokenPremium amount to calculate the ETH required for new items in the vault (onchain)
  3. 3.
    quoteDecimals amount to calculate the cost of the vTokens for redeeming the NFTs (this comes from the NFTX Router API request)
  4. 4.
    nftIds of the NFT you want to purchase
  5. 5.
    to address of the person buying
In this example we're buying 2 NFTs, 351, 346 from the following vault. Vault Name: Fringoooor vaultId: 0 vTokenAddress: 0x6f4d645d1645e65db2E7f9Aa11Eb5Fc45a65592A

Calculate the NFT premium cost

When an NFT goes into the vault there is a 3600 second premium placed upon it which reduces each second exponentially from 500% - 0%.
To calculate the premium for an NFT being bought you can pass the nftId to the getVTokenPremium721 function. The response will contain the amount of additional vToken that is set as the premium.
Below is an example of two tokens, one with almost the highest premium (token 351) and the other no premium (token 346).
This token has a premium of 4983601988461962229 vTokens.
This token has a premium of 0 vTokens.
These values should be added to the ETH fee (see next step).

Calculate ETH fee

Find the fee amount for redeemFee, either by using the subgraph response or by making an onchain call to the vault contract (see below).
In this example we are buying two NFTs, we need to double the redeemFee from 50000000000000000 to 100000000000000000

Calculate Fee + Premium to ETH

Add the redeemFee and the nftPremiumFee together and pass that to the vTokenToETH function on the vault contract.
100000000000000000 + 4983601988461962229 = 5083601988461962229
We're passing the sum of the fee and NFT Premium amounts to find the ETH value
580380454730343582 wei is equivalent to 0.5080380454730343582 ETH.
This amount is then added to the cost of the token buy quote price.

Calculate the token price

NFTX is running a Universal Router API to return the best price across all of the pools and positions.
When requesting
Query Parameters
Value
Description
tokenInChainId
11155111
Sepolia: 11155111, Mainnet: 1, Arbitrum 42161
tokenOutChainId
11155111
Sepolia: 11155111, Mainnet: 1, Arbitrum 42161
protocols
v3
The Universal router is configured to also work with SushiSwap V2 router, however all V3 liquidity will be on the NFTX AMM which is v3
slippageTolerance
10
deadline
3000
The quote is valid for 3000 seconds
recipient
0x50f69c6556338965bf77C16ADb462Fdb5bE01C09
The recipient is set to the marketplaceZap address, as that will be the recipient of the tokens to then redeem the NFT from the vault.
enableUniversalRouter
true
Required to return the quote callData
tokenInAddress
0xB4FBF271143F4FBf7B91A5ded31805e42b2208d6
The token you are paying with, this should be set to wETH even if paying with ETH.
amount
2000000000000000000
The number of tokens you are buying. Remember, this is 1:1 with the NFT, the fees are now paid as ETH. We are buying 2 tokens in this example.
type
exactOut
When buying we only want the exact number of tokens out.
tokenOutAddress
0x6f4d645d1645e65db2E7f9Aa11Eb5Fc45a65592A
The vToken for the NFT we want to buy.
Response
{
"methodParameters": {
"calldata": "0x3593564c000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000064b944600000000000000000000000000000000000000000000000000000000000000001010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000010000000000000000000000000011f9ce2c92ed333115d1cb1078a1f7bbfa7de0d50000000000000000000000000000000000000000000000001bc16d674ec8000000000000000000000000000000000000000000000000000003a19200263a412600000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002b6f4d645d1645e65db2e7f9aa11eb5fc45a65592a002710b4fbf271143f4fbf7b91a5ded31805e42b2208d6000000000000000000000000000000000000000000",
"value": "0x00",
"to": "0x375e894364bEBed5388115A6BbEEfb9290C610de"
},
"blockNumber": "9376996",
"amount": "2000000000000000000",
"amountDecimals": "2",
"quote": "237864347912006086",
"quoteDecimals": "0.237864347912006086",
"quoteGasAdjusted": "251903648500922086",
"quoteGasAdjustedDecimals": "0.251903648500922086",
"gasUseEstimateQuote": "14039300588916000",
"gasUseEstimateQuoteDecimals": "0.014039300588916",
"gasUseEstimate": "113000",
"gasUseEstimateUSD": "28.078601",
"simulationStatus": "UNATTEMPTED",
"simulationError": false,
"gasPriceWei": "124241598132",
"route": [
[
{
"type": "v3-pool",
"address": "0x5E8A2433C047881D18B63AB239d02af4F4b33229",
"tokenIn": {
"chainId": 5,
"decimals": "18",
"address": "0xB4FBF271143F4FBf7B91A5ded31805e42b2208d6",
"symbol": "WETH"
},
"tokenOut": {
"chainId": 5,
"decimals": "18",
"address": "0x6f4d645d1645e65db2E7f9Aa11Eb5Fc45a65592A",
"symbol": "FRINGOOOOOOOOR"
},
"fee": "10000",
"liquidity": "22290182843350301072",
"sqrtRatioX96": "26770813048747472398292166448",
"tickCurrent": "-21702",
"amountIn": "237864347912006086",
"amountOut": "2000000000000000000"
}
]
],
"routeString": "[V3] 100.00% = WETH -- 1% [0x5E8A2433C047881D18B63AB239d02af4F4b33229] --> FRINGOOOOOOOOR",
"quoteId": "1ec15"
}
Add the quoteDecimals to the Fee + Premium ETH amount calculated in the previous step.
0.237864347912006086 + 0.574672096207709349 = 0.8125364441 ETH.

Buy NFT with MarketplaceUniversalRouterZap

With all the data collected, call the buyNFTsWithETH function on the MarketplaceUniversalRouterZap
  • ETH amount calcuated earlier: premium + fee + token.
  • The vaultId retrieved from the subgraph (or onchain against the vault contract)
  • idsOut are the NFTs being bought
  • executeCallData is the calldata in the response from the NFTX Universal Router API
  • to address is who is buying the NFT (or who should receive the NFT)
  • deductRoyalty is an optional inclusion, false for the sake of this implementation