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
1
fn internal_process_purchase(
2
&mut self,
3
nft_contract_id: AccountId,
4
token_id: TokenId,
5
buyer_id: AccountId,
6
) -> Promise {
7
8
let market_data = self.internal_delete_market_data(&nft_contract_id, &token_id);
9
10
ext_contract::nft_transfer_payout(
11
buyer_id.clone(),
12
token_id,
13
Some(market_data.approval_id),
14
Some(U128::from(market_data.price)),
15
Some(10u32), // max length payout
16
&nft_contract_id,
17
1,
18
GAS_FOR_NFT_TRANSFER,
19
)
20
.then(ext_self::resolve_purchase(
21
buyer_id,
22
market_data,
23
&env::current_account_id(),
24
NO_DEPOSIT,
25
GAS_FOR_ROYALTIES,
26
))
27
}
Copied!

Implementation Standard

https://nomicon.io/Standards/NonFungibleToken/Payout.html
1
#[derive(Serialize, Deserialize)]
2
#[serde(crate = "near_sdk::serde")]
3
pub struct Payout {
4
pub payout: HashMap<AccountId, U128>,
5
}
6
7
pub trait Payouts{
8
/// Given a `token_id` and NEAR-denominated balance, return the `Payout`.
9
/// struct for the given token. Panic if the length of the payout exceeds
10
/// `max_len_payout.`
11
fn nft_payout(&self, token_id: String, balance: U128, max_len_payout: u32) -> Payout;
12
/// Given a `token_id` and NEAR-denominated balance, transfer the token
13
/// and return the `Payout` struct for the given token. Panic if the
14
/// length of the payout exceeds `max_len_payout.`
15
#[payable]
16
fn nft_transfer_payout(
17
&mut self,
18
receiver_id: AccountId,
19
token_id: String,
20
approval_id: u64,
21
balance: U128,
22
max_len_payout: u32,
23
) -> Payout{
24
assert_one_yocto();
25
let payout = self.nft_payout(token_id, balance);
26
self.nft_transfer(receiver_id, token_id, approval_id);
27
payout
28
}
29
}
Copied!
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.
1
#[payable]
2
pub fn nft_transfer_payout(
3
&mut self,
4
receiver_id: ValidAccountId,
5
token_id: String,
6
approval_id: u64,
7
balance: U128,
8
max_len_payout: u32,
9
) -> HashMap<AccountId, U128> {
10
assert_one_yocto();
11
12
let owner_id = self.tokens.owner_by_id.get(&token_id).expect("Token id does not exist");
13
self.tokens.nft_transfer(receiver_id.clone(), token_id.clone(), Some(approval_id), None);
14
15
env::log(
16
json!({
17
"type": "nft_transfer",
18
"params": {
19
"token_id": token_id,
20
"sender_id": owner_id,
21
"receiver_id": receiver_id,
22
}
23
})
24
.to_string()
25
.as_bytes(),
26
);
27
28
let mut result: HashMap<AccountId, U128> = HashMap::new();
29
result.insert(owner_id, balance);
30
result
31
}
Copied!

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)
1
env::log(
2
json!({
3
"type": "nft_transfer",
4
"params": {
5
"token_id": token_id,
6
"sender_id": sender_id,
7
"receiver_id": receiver_id_str
8
}
9
})
10
.to_string()
11
.as_bytes(),
12
);
Copied!

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:
1
near call paras-marketplace-v1.testnet storage_deposit '{"accountId":"orang.testnet"}' --accountId orang.testnet --depositYocto 8590000000000000000000
Copied!
nft_approve function call:
1
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\"}"}'
Copied!