Neo N3 NFT Creation
A developers guide to creating Neo N3 NFTs compatible with GhostMarket
Last updated
% npm install @cityofzion/neon-js@next
% npm install unicode-encodeconst { utoa, atou } = require("unicode-encode");
const { CONST, rpc, sc, wallet, tx, u } = require("@cityofzion/neon-core");// Define the NFT attributes
const attributes = [
{
trait_type: "color", // The attribute type/key
value: "red", // The attribute value
display_type: "", // The display format
},
{
trait_type: "size", // The attribute type/key
value: "small", // The attribute value
display_type: "", // The display format
},
// No third attribute
// An arbitrary number of attributes may be added for custom apps
];
// Define the NFT properties
const properties = {
has_locked: true, // Is there locked content
type: 1,
};
// Put it together
const jsonMetadata = JSON.stringify({
name: "My Shiny NFT",
description: "This NFT will be a classic",
image: "ipfs://QmTy8w65yBXgyfG2ZBg5TrfB2hPjrDQH3RCQFJGkARStJb",
tokenURI: "",
attributes,
properties,
});const creatorPrivateKey =
"L1QqQJnpBwbsPGAuutuzPTac8piqvbR1HRjrY5qHup48TBCBFe4g";
const creatorAccount = new wallet.Account(creatorPrivateKey);
const rpcClient = new rpc.RPCClient("http://neo3.edgeofneo.com:10332");
// The locked content - ToDo - Describe fully
// Node.js only - add module "npm i buffer" for browsers
const lockedContent = Buffer.from("My secret Locked Content", "utf8").toString(
"hex"
);// construct the royalties ARRAY.
const royaltyBPS = 2000; // royalties - 20% expressed in Basis Points (BPS) (0.01%)
const contractRoyalties = JSON.stringify([
{
address: creatorAccount.address,
value: royaltyBPS.toString(),
},
// Additional royalty address/value pairs may be added here
]);// Define the minting arguments to be used in the transaction script
const mintArgs = [
sc.ContractParam.hash160(creatorAccount.address),
sc.ContractParam.byteArray(utoa(jsonMetadata)),
sc.ContractParam.byteArray(utoa(lockedContent)),
sc.ContractParam.byteArray(btoa(contractRoyalties.toString())),
sc.ContractParam.string(""), //Data - empty
];
// Build the script - ready for transaction
const script = sc.createScript({
scriptHash: "577a51f7d39162c9de1db12a6b319c848e4c54e5", // GhostMarket NFT contract
operation: "mint",
args: mintArgs,
});
let currentHeight = 0;
// Retrieve the current block height to calculate expiry
currentHeight = await rpcClient.getBlockCount();
// specify the contracts that this transaction may interract with
const allowedContracts = [
"d2a4cff31913016155e38e474a2c06d08be276cf", // GAS script hash
"577a51f7d39162c9de1db12a6b319c848e4c54e5", // GhostMarket NFT Contract
];// Build the transaction
txn = new tx.Transaction({
sender: creatorAccount.scriptHash,
signers: [
{
account: creatorAccount.scriptHash,
scopes: tx.WitnessScope.CustomContracts,
allowedContracts,
},
],
validUntilBlock: currentHeight + 1000000,
systemFee: 0,
script: script,
});
// Sign the transaction
const signedTransaction = txn.sign(
creatorAccount,
CONST.MAGIC_NUMBER["MainNet"]
);const result = await rpcClient.sendRawTransaction(
signedTransaction.serialize(true)
);
console.log("Txn ID: ", result);