Skip to content

Instantly share code, notes, and snippets.

@thor314
Created May 19, 2021 13:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save thor314/f68df03cbd778c1405e381ef9032e2d7 to your computer and use it in GitHub Desktop.
Save thor314/f68df03cbd778c1405e381ef9032e2d7 to your computer and use it in GitHub Desktop.
//! Usage:
//!
//! Use `nft_move` to Burn tokens on this Contract and re-mint it on
//! another Contract.
use crate::{internal::loggers, *};
use near_sdk::{ext_contract, json_types::U64, near_bindgen};
use std::convert::TryInto;
#[ext_contract(ext_move)]
pub trait Move {
fn nft_on_move(&mut self, token: Token, token_metadata: TokenMetadata, royalty: Option<Royalty>);
}
#[ext_contract(ext_self)]
pub trait ExtSelf {
fn on_move_callback(&mut self, token_id: U64, contract_id: AccountId);
}
#[near_bindgen]
impl MintbaseStore {
#[payable]
pub fn nft_move(&mut self, token_id: U64, contract_id: ValidAccountId) {
near_sdk::assert_one_yocto();
assert!(self.allow_moves);
let token = self.nft_token_internal(token_id.into());
assert!(!token.is_loaned());
assert!(token.is_pred_owner());
let token_bytes = token.try_to_vec().unwrap().len();
let metadata = self
.token_metadata
.get(&token_id.into())
.map(|tuple| tuple.1)
.expect("no metadata for token");
let metadata_bytes = metadata.try_to_vec().unwrap().len();
let royalty = self
.token_royalty
.get(&token_id.into())
.map(|tuple| tuple.1);
let royalty_bytes = royalty.try_to_vec().unwrap().len();
let storage = token_bytes + metadata_bytes + royalty_bytes;
let tx_amt = storage as u128 * self.storage_costs.storage_price_per_byte;
let contract_id: AccountId = contract_id.try_into().unwrap();
ext_move::nft_on_move(
token,
metadata,
royalty,
&contract_id,
// allow user to attach deposit if other contract requires more for storage payment
tx_amt + env::attached_deposit(),
mintbase_utils::DEFAULT_GAS / 2,
)
.then(ext_self::on_move_callback(
token_id,
contract_id,
&env::current_account_id(),
mintbase_utils::NO_DEPOSIT,
mintbase_utils::DEFAULT_GAS / 2,
));
}
pub fn nft_on_move(
&mut self,
mut token: Token,
metadata: TokenMetadata,
royalty: Option<Royalty>,
) {
assert!(self.allow_moves);
token.origin_contract = Some(env::predecessor_account_id());
let token_bytes = token.try_to_vec().unwrap().len();
let metadata_bytes = metadata.try_to_vec().unwrap().len();
let royalty_bytes = royalty.try_to_vec().unwrap().len();
let storage = token_bytes + metadata_bytes + royalty_bytes;
let storage_cost =
storage as u128 * self.storage_costs.storage_price_per_byte + self.storage_costs.common;
assert!(env::attached_deposit() >= storage_cost);
// Update token_id so it doesn't collide with existing token_ids.
// Also cache the lookup_id for looking up royalty and metadata.
let lookup_id = self.tokens_minted;
self.tokens_minted += 1;
token.id = lookup_id;
token.metadata_id = lookup_id;
token.royalty_id = royalty.clone().map(|royalty| {
self.token_royalty.insert(&lookup_id, &(1, royalty));
lookup_id
});
let mut owned_set = self.get_or_make_new_owner_set(&token.owner_id.to_string());
owned_set.insert(&lookup_id);
self
.tokens_per_owner
.insert(&token.owner_id.to_string(), &owned_set);
loggers::log_on_move(
token.id.into(),
&token.minter,
&token.owner_id.to_string(),
&royalty,
&token.split_owners,
&metadata.reference,
&metadata.extra,
&token.origin_contract.unwrap(),
);
}
#[private]
pub fn on_move_callback(&mut self, token_id: U64, contract_id: AccountId) {
if near_sdk::is_promise_success() {
self.burn_tokens(vec![token_id]);
loggers::log_nft_moved(token_id, contract_id);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment