git.delta.rocks / unique-network / refs/commits / 275806de5a21

difftreelog

Add collection creation example

Greg Zaitsev2020-08-31parent: #0817ae5.patch.diff
in: master

12 files changed

addedexamples/.gitignorediffbeforeafterboth
--- /dev/null
+++ b/examples/.gitignore
@@ -0,0 +1 @@
+node_modules
\ No newline at end of file
addedexamples/package.jsondiffbeforeafterboth
--- /dev/null
+++ b/examples/package.json
@@ -0,0 +1,43 @@
+{
+  "name": "SubstraPunks",
+  "version": "1.0.0",
+  "description": "Substrate Based Remake of CryptoPunks",
+  "main": "",
+  "directories": {
+    "test": "test"
+  },
+  "devDependencies": {
+    "got": "^10.7.0"
+  },
+  "scripts": {
+    "test": ""
+  },
+  "author": "",
+  "license": "Apache 2.0",
+  "homepage": "",
+  "dependencies": {
+    "bn.js": "^5.1.2",
+    "body-parser": "^1.18.3",
+    "express": "^4.17.1",
+    "express-session": "^1.17.0",
+    "fs": "^0.0.1-security",
+    "path": "^0.12.7",
+    "png-crop": "^0.0.2",
+    "@polkadot/api": "1.27.1",
+    "@polkadot/api-contract": "1.27.1",
+    "@polkadot/extension-dapp": "0.31.1",
+    "pug": "^2.0.4",
+    "sprintf-js": "^1.1.2"
+  },
+  "standard": {
+    "globals": [
+      "it",
+      "assert",
+      "beforeEach",
+      "afterEach",
+      "describe",
+      "contract",
+      "artifacts"
+    ]
+  }
+}
addedexamples/re-fungible/collection.txtdiffbeforeafterboth
--- /dev/null
+++ b/examples/re-fungible/collection.txt
@@ -0,0 +1,10 @@
+https://conv.darkbyte.ru/
+
+Artwork
+65 114 116 119 111 114 107
+
+Collection of photos
+67 111 108 108 101 99 116 105 111 110 32 111 102 32 112 104 111 116 111 115
+
+ART
+65 82 84
addedexamples/re-fungible/config.jsdiffbeforeafterboth
--- /dev/null
+++ b/examples/re-fungible/config.js
@@ -0,0 +1,19 @@
+// Local
+// const config = {
+//   wsEndpoint : 'ws://127.0.0.1:9944',
+//   collectionDataSize: 0,
+//   decimalPoints: 4,
+
+//   ownerSeed : '//Alice',
+// };
+
+// Production
+const config = {
+  wsEndpoint : 'wss://unique.usetech.com',
+  collectionDataSize: 0,
+  decimalPoints: 4,
+
+  ownerSeed : 'tunnel hair company air cage velvet egg crunch height fetch resource estate',
+};
+
+module.exports = config;
\ No newline at end of file
addedexamples/re-fungible/create_collection.jsdiffbeforeafterboth
--- /dev/null
+++ b/examples/re-fungible/create_collection.js
@@ -0,0 +1,67 @@
+const { ApiPromise, WsProvider, Keyring } = require('@polkadot/api');
+const config = require('./config');
+const fs = require('fs');
+
+function submitTransaction(sender, transaction) {
+  return new Promise(async function(resolve, reject) {
+    try {
+      const unsub = await transaction
+      .signAndSend(sender, (result) => {
+        console.log(`Current tx status is ${result.status}`);
+    
+        if (result.status.isInBlock) {
+          console.log(`Transaction included at blockHash ${result.status.asInBlock}`);
+          resolve();
+          unsub();
+        } else if (result.status.isFinalized) {
+          console.log(`Transaction finalized at blockHash ${result.status.asFinalized}`);
+          resolve();
+          unsub();
+        }
+      });
+    }
+    catch (e) {
+      reject(e.toString());
+    }
+  });
+}
+
+async function createCollectionAsync(api, alice) {
+  // Artwork
+  const name = [65, 114, 116, 119, 111, 114, 107];
+  // Collection of photos
+  const description = [67, 111, 108, 108, 101, 99, 116, 105, 111, 110, 32, 111, 102, 32, 112, 104, 111, 116, 111, 115];
+  // ART
+  const tokenPrefix = [65, 82, 84];
+  
+  // Mode: Re-Fungible
+  const tx = api.tx.nft.createCollection(name, description, tokenPrefix, {"ReFungible": [config.collectionDataSize, config.decimalPoints]});
+  await submitTransaction(alice, tx);
+
+  const tx2 = api.tx.nft.setOffchainSchema(2, "https://ipfs-gateway.usetech.com/ipfs/QmUSv64cUmL2m44QYkUFWmH89qykC8VLPFwjhpeAScjejS/image{id}.jpg");
+  await submitTransaction(alice, tx2);
+}
+
+async function main() {
+  // Initialise the provider to connect to the node
+  const wsProvider = new WsProvider(config.wsEndpoint);
+  const rtt = JSON.parse(fs.readFileSync("runtime_types.json"));
+
+  // Create the API and wait until ready
+  const api = await ApiPromise.create({ 
+    provider: wsProvider,
+    types: rtt
+  });
+
+  // Owners's keypair
+  const keyring = new Keyring({ type: 'sr25519' });
+  const owner = keyring.addFromUri(config.ownerSeed);
+  console.log("Collection owner address: ", owner.address);  
+
+  // Create collection as owner
+  console.log("=== Create collection ===");
+  await createCollectionAsync(api, owner);
+
+}
+
+main().catch(console.error).finally(() => process.exit());
addedexamples/re-fungible/ipfs.txtdiffbeforeafterboth
--- /dev/null
+++ b/examples/re-fungible/ipfs.txt
@@ -0,0 +1,4 @@
+https://ipfs-gateway.usetech.com/ipfs/QmUSv64cUmL2m44QYkUFWmH89qykC8VLPFwjhpeAScjejS/image{id}.jpg
+
+Orchids:
+https://ipfs-gateway.usetech.com/ipfs/QmUSv64cUmL2m44QYkUFWmH89qykC8VLPFwjhpeAScjejS/image1.jpg
\ No newline at end of file
addedexamples/re-fungible/runtime_types.jsondiffbeforeafterboth
--- /dev/null
+++ b/examples/re-fungible/runtime_types.json
@@ -0,0 +1,64 @@
+{
+  "Schedule": {
+    "version": "u32",
+    "put_code_per_byte_cost": "Gas",
+    "grow_mem_cost": "Gas",
+    "regular_op_cost": "Gas",
+    "return_data_per_byte_cost": "Gas",
+    "event_data_per_byte_cost": "Gas",
+    "event_per_topic_cost": "Gas",
+    "event_base_cost": "Gas",
+    "call_base_cost": "Gas",
+    "instantiate_base_cost": "Gas",
+    "dispatch_base_cost": "Gas",
+    "sandbox_data_read_cost": "Gas",
+    "sandbox_data_write_cost": "Gas",
+    "transfer_cost": "Gas",
+    "instantiate_cost": "Gas",
+    "max_event_topics": "u32",
+    "max_stack_height": "u32",
+    "max_memory_pages": "u32",
+    "max_table_size": "u32",
+    "enable_println": "bool",
+    "max_subject_len": "u32"
+  },
+  "CollectionMode": {
+    "_enum": {
+      "Invalid": null,
+      "NFT": "u32",
+      "Fungible": "u32",
+      "ReFungible": "(u32, u32)"
+    }
+  },
+  "NftItemType": {
+    "Collection": "u64",
+    "Owner": "AccountId",
+    "Data": "Vec<u8>"
+  },
+  "Ownership": {
+    "owner": "AccountId",
+    "fraction": "u128"
+  },
+  "ReFungibleItemType": {
+    "Collection": "u64",
+    "Owner": "Vec<Ownership<AccountId>>",
+    "Data": "Vec<u8>"
+  },
+  "CollectionType": {
+    "Owner": "AccountId",
+    "Mode": "CollectionMode",
+    "Access": "u8",
+    "DecimalPoints": "u32",
+    "Name": "Vec<u16>",
+    "Description": "Vec<u16>",
+    "TokenPrefix": "Vec<u8>",
+    "CustomDataSize": "u32",
+    "OffchainSchema": "Vec<u8>",
+    "Sponsor": "AccountId",
+    "UnconfirmedSponsor": "AccountId"
+  },
+  "RawData": "Vec<u8>",
+  "Address": "AccountId",
+  "LookupSource": "AccountId",
+  "Weight": "u64"
+}
\ No newline at end of file
addedexamples/testnft/config.jsdiffbeforeafterboth
--- /dev/null
+++ b/examples/testnft/config.js
@@ -0,0 +1,19 @@
+// Local
+// const config = {
+//   wsEndpoint : 'ws://127.0.0.1:9944',
+//   collectionDataSize: 0,
+//   totalTokens: 10,
+
+//   ownerSeed : '//Alice',
+// };
+
+// Testnet
+const config = {
+  wsEndpoint : 'wss://unique.usetech.com',
+  collectionDataSize: 0,
+  totalTokens: 10,
+
+  ownerSeed : 'tunnel hair company air cage velvet egg crunch height fetch resource estate',
+};
+
+module.exports = config;
\ No newline at end of file
addedexamples/testnft/create_collection.jsdiffbeforeafterboth
--- /dev/null
+++ b/examples/testnft/create_collection.js
@@ -0,0 +1,69 @@
+const { ApiPromise, WsProvider, Keyring } = require('@polkadot/api');
+const config = require('./config');
+var BigNumber = require('bn.js');
+const fs = require('fs');
+
+function submitTransaction(sender, transaction) {
+  return new Promise(async function(resolve, reject) {
+    try {
+      const unsub = await transaction
+      .signAndSend(sender, (result) => {
+        console.log(`Current tx status is ${result.status}`);
+    
+        if (result.status.isInBlock) {
+          console.log(`Transaction included at blockHash ${result.status.asInBlock}`);
+          resolve();
+          unsub();
+        } else if (result.status.isFinalized) {
+          console.log(`Transaction finalized at blockHash ${result.status.asFinalized}`);
+          resolve();
+          unsub();
+        }
+      });
+    }
+    catch (e) {
+      reject(e.toString());
+    }
+  });
+}
+
+async function createCollectionAsync(api, alice) {
+  // Test NFT
+  const name = [0x54, 0x65, 0x73, 0x74, 0x20, 0x4e, 0x46, 0x54];
+  // Test NFT Collection
+  const description = [0x54, 0x65, 0x73, 0x74, 0x20, 0x4e, 0x46, 0x54, 0x20, 0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e];
+  // TestNFT
+  const tokenPrefix = [0x54, 0x65, 0x73, 0x74, 0x4e, 0x46, 0x54];
+  
+  // Mode: NFT
+  const tx = api.tx.nft.createCollection(name, description, tokenPrefix, {"NFT": config.collectionDataSize});
+  await submitTransaction(alice, tx);
+
+  const collectionId = 1;
+
+  const tx2 = api.tx.nft.setOffchainSchema(collectionId, "https://ipfs-gateway.usetech.com/ipfs/QmVdFFZjnq6i3fNDjm6FQe2tfAtUDnqMNkBh8e4sYWUmbH/images/image{id}.png");
+  await submitTransaction(alice, tx2);
+}
+
+async function main() {
+  // Initialise the provider to connect to the node
+  const wsProvider = new WsProvider(config.wsEndpoint);
+  const rtt = JSON.parse(fs.readFileSync("runtime_types.json"));
+
+  // Create the API and wait until ready
+  const api = await ApiPromise.create({ 
+    provider: wsProvider,
+    types: rtt
+  });
+
+  // Owners's keypair
+  const keyring = new Keyring({ type: 'sr25519' });
+  const owner = keyring.addFromUri(config.ownerSeed);
+  console.log("Collection owner address: ", owner.address);  
+
+  // Create collection as owner
+  console.log("=== Create collection ===");
+  await createCollectionAsync(api, owner);
+}
+
+main().catch(console.error).finally(() => process.exit());
addedexamples/testnft/create_tokens.jsdiffbeforeafterboth
--- /dev/null
+++ b/examples/testnft/create_tokens.js
@@ -0,0 +1,77 @@
+const { ApiPromise, WsProvider, Keyring } = require('@polkadot/api');
+const config = require('./config');
+const fs = require('fs');
+
+const collectionId = 1;
+
+function checkOwner(owner) {
+  for (let i=0; i<32; i++) {
+    if (owner[i] != 0) return true;
+  }
+  return false;
+}
+
+function mintAsync(api, admin) {
+  return new Promise(async function(resolve, reject) {
+    const unsub = await api.tx.nft
+      .createItem(collectionId, "0x", admin.address)
+      .signAndSend(admin, (result) => {
+        console.log(`Current tx status is ${result.status}`);
+    
+        if (result.status.isInBlock) {
+          console.log(`Transaction included at blockHash ${result.status.asInBlock}`);
+          resolve();
+          unsub();
+        } else if (result.status.isFinalized) {
+          console.log(`Transaction finalized at blockHash ${result.status.asFinalized}`);
+          resolve();
+          unsub();
+        }
+      });
+  });
+}
+
+async function main() {
+  // Initialise the provider to connect to the node
+  const wsProvider = new WsProvider(config.wsEndpoint);
+  const rtt = require("./runtime_types.json");
+
+  // Create the API and wait until ready
+  const api = await ApiPromise.create({ 
+    provider: wsProvider,
+    types: rtt
+  });
+
+  // Retrieve the chain & node information information via rpc calls
+  const [chain, nodeName, nodeVersion, collection] = await Promise.all([
+    api.rpc.system.chain(),
+    api.rpc.system.name(),
+    api.rpc.system.version(),
+    api.query.nft.collection(collectionId)
+  ]);
+
+  console.log(`You are connected to chain ${chain} using ${nodeName} v${nodeVersion}`);
+  console.log(`Collection: ${collection}`);
+
+  if (checkOwner(collection.Owner.toString())) {
+    // Import account from mnemonic phrase in config file
+    const keyring = new Keyring({ type: 'sr25519' });
+    const owner = keyring.addFromUri(config.ownerSeed);
+    console.log("Owner address: ", owner.address)
+
+    // Create Tokens
+    for (let i=0; i<config.totalTokens; i++) {
+      console.log(`=== Importing Token ${i+1} of ${config.totalTokens} ===`);
+
+      // Mint
+      await mintAsync(api, owner);
+    }
+
+  }
+  else {
+    console.log("\nERROR: Collection not found.\nCheck the ID and make sure you have created collection and set the admin");
+  }
+
+}
+
+main().catch(console.error).finally(() => process.exit());
addedexamples/testnft/info.txtdiffbeforeafterboth

no changes

addedexamples/testnft/runtime_types.jsondiffbeforeafterboth
--- /dev/null
+++ b/examples/testnft/runtime_types.json
@@ -0,0 +1,64 @@
+{
+  "Schedule": {
+    "version": "u32",
+    "put_code_per_byte_cost": "Gas",
+    "grow_mem_cost": "Gas",
+    "regular_op_cost": "Gas",
+    "return_data_per_byte_cost": "Gas",
+    "event_data_per_byte_cost": "Gas",
+    "event_per_topic_cost": "Gas",
+    "event_base_cost": "Gas",
+    "call_base_cost": "Gas",
+    "instantiate_base_cost": "Gas",
+    "dispatch_base_cost": "Gas",
+    "sandbox_data_read_cost": "Gas",
+    "sandbox_data_write_cost": "Gas",
+    "transfer_cost": "Gas",
+    "instantiate_cost": "Gas",
+    "max_event_topics": "u32",
+    "max_stack_height": "u32",
+    "max_memory_pages": "u32",
+    "max_table_size": "u32",
+    "enable_println": "bool",
+    "max_subject_len": "u32"
+  },
+  "CollectionMode": {
+    "_enum": {
+      "Invalid": null,
+      "NFT": "u32",
+      "Fungible": "u32",
+      "ReFungible": "(u32, u32)"
+    }
+  },
+  "NftItemType": {
+    "Collection": "u64",
+    "Owner": "AccountId",
+    "Data": "Vec<u8>"
+  },
+  "Ownership": {
+    "owner": "AccountId",
+    "fraction": "u128"
+  },
+  "ReFungibleItemType": {
+    "Collection": "u64",
+    "Owner": "Vec<Ownership<AccountId>>",
+    "Data": "Vec<u8>"
+  },
+  "CollectionType": {
+    "Owner": "AccountId",
+    "Mode": "CollectionMode",
+    "Access": "u8",
+    "DecimalPoints": "u32",
+    "Name": "Vec<u16>",
+    "Description": "Vec<u16>",
+    "TokenPrefix": "Vec<u8>",
+    "CustomDataSize": "u32",
+    "OffchainSchema": "Vec<u8>",
+    "Sponsor": "AccountId",
+    "UnconfirmedSponsor": "AccountId"
+  },
+  "RawData": "Vec<u8>",
+  "Address": "AccountId",
+  "LookupSource": "AccountId",
+  "Weight": "u64"
+}
\ No newline at end of file