NFT smart contract integration

Follow these requirements before you integrate with our marketplace

NFT requirements

There are two requirements:
  1. 1.
    Implement nft_transfer_payout and nft_payout
  2. 2.
    Implement logging for nft_transfer, nft_transfer_call, nft_transfer_payout. Please follow the event standard

Implement nft_transfer_payout

Paras marketplace will call nft_transfer_payout when user purchase the NFT. https://github.com/ParasHQ/paras-marketplace-contract/blob/master/paras-marketplace-contract/src/lib.rs#L213
fn internal_process_purchase(
&mut self,
nft_contract_id: AccountId,
token_id: TokenId,
buyer_id: AccountId,
) -> Promise {
let market_data = self.internal_delete_market_data(&nft_contract_id, &token_id);
ext_contract::nft_transfer_payout(
buyer_id.clone(),
token_id,
Some(market_data.approval_id),
Some(U128::from(market_data.price)),
Some(10u32), // max length payout
&nft_contract_id,
1,
GAS_FOR_NFT_TRANSFER,
)
.then(ext_self::resolve_purchase(
buyer_id,
market_data,
&env::current_account_id(),
NO_DEPOSIT,
GAS_FOR_ROYALTIES,
))
}

Implementation Standard

https://nomicon.io/Standards/NonFungibleToken/Payout.html
#[derive(Serialize, Deserialize)]
#[serde(crate = "near_sdk::serde")]
pub struct Payout {
pub payout: HashMap<AccountId, U128>,
}
pub trait Payouts{
/// Given a `token_id` and NEAR-denominated balance, return the `Payout`.
/// struct for the given token. Panic if the length of the payout exceeds
/// `max_len_payout.`
fn nft_payout(&self, token_id: String, balance: U128, max_len_payout: u32) -> Payout;
/// Given a `token_id` and NEAR-denominated balance, transfer the token
/// and return the `Payout` struct for the given token. Panic if the
/// length of the payout exceeds `max_len_payout.`
#[payable]
fn nft_transfer_payout(
&mut self,
receiver_id: AccountId,
token_id: String,
approval_id: u64,
balance: U128,
max_len_payout: u32,
) -> Payout{
assert_one_yocto();
let payout = self.nft_payout(token_id, balance);
self.nft_transfer(receiver_id, token_id, approval_id);
payout
}
}
NOTE: If you are not using royalty, then implement nft_transfer_payout as a wrapper for nft_transfer and return HashMap of {"<owner_id>": balance}, e.g.
#[payable]
pub fn nft_transfer_payout(
&mut self,
receiver_id: ValidAccountId,
token_id: String,
approval_id: u64,
balance: U128,
max_len_payout: u32,
) -> HashMap<AccountId, U128> {
assert_one_yocto();
let owner_id = self.tokens.owner_by_id.get(&token_id).expect("Token id does not exist");
self.tokens.nft_transfer(receiver_id.clone(), token_id.clone(), Some(approval_id), None);
env::log(
json!({
"type": "nft_transfer",
"params": {
"token_id": token_id,
"sender_id": owner_id,
"receiver_id": receiver_id,
}
})
.to_string()
.as_bytes(),
);
let mut result: HashMap<AccountId, U128> = HashMap::new();
result.insert(owner_id, balance);
result
}

Other nft_transfer_payout implementation

NFT series: https://github.com/near-apps/nft-series/blob/main/contract/src/lib.rs#L207
NFT simple: https://github.com/near-apps/nft-market/blob/main/contracts/nft-simple/src/nft_core.rs#L165
Paras NFT: https://github.com/ParasHQ/paras-nft-contract/blob/main/paras-nft-contract/src/lib.rs#L839

Implement logging (prefered)

Please implement the NFT event standard (https://github.com/near/NEPs/blob/master/specs/Standards/NonFungibleToken/Event.md) on your NFT contract.
Example: https://github.com/near/near-sdk-rs/pull/627

Implement logging (old)

Example : Paras NFT contract (https://github.com/ParasHQ/paras-nft-contract/blob/main/paras-nft-contract/src/lib.rs#L697)
env::log(
json!({
"type": "nft_transfer",
"params": {
"token_id": token_id,
"sender_id": sender_id,
"receiver_id": receiver_id_str
}
})
.to_string()
.as_bytes(),
);

Listing your NFTs on Paras marketplace

By event standard

Any function calls with NFT event standard will automatically trigger a listing on our indexer.

By cold start

Our team will list all of your NFTs into Paras without having to place a sale in the first place.

By nft_approve

Every time there is an nft_approve into paras-marketplace contract then it will be automatically listed on Paras.
Before calling nft_approve, please deposit storage fee for your sale.
storage deposit function call:
near call paras-marketplace-v1.testnet storage_deposit '{"accountId":"orang.testnet"}' --accountId orang.testnet --depositYocto 8590000000000000000000
nft_approve function call:
near call nft_contract_id nft_approve '{"token_id":"<token_id>","account_id":"paras-marketplace-v1.testnet","msg":"{\"market_type\":\"sale\",\"price\":\"1000000000000000000000000\",\"ft_token_id\":\"near\"}"}'