difftreelog
NFTPAR-91: SIT: Connection can be established. Fixed unhandled promise rejection. Fixed unknown type warnings.
in: master
5 files changed
README.mddiffbeforeafterboth123# NFT Parachain45## Project Description67The NFT Pallet is the core of NFT functionality. Like ERC-721 standard in Ethereum ecosystem, this pallet provides the basement for creating collections of unique non-divisible things, also called Non Fungible Tokens (NFTs), minting NFT of a given Collection, and managing their ownership.89The pallet also enables storing NFT properties. Though (according to ERC-721) NFT properties belong to logic of a concrete application that operates a Collection, so purposefully the NFT Tracking Module does not have any knowledge about properties except their byte size leaving application logic out to be controlled by Smart Contracts.1011The NFT Chain also provides:1213* Smart Contracts Pallet and example smart contract that interacts with NFT Runtime14* ERC-1155 Functionality (currently PoC as Re-Fungible tokens, i.e. items that are still unique, but that can be split between multiple users)15* Variety of economic options for dapp producers to choose from to create freemium games and other ways to attract users. As a step one, we implemented an economic model when a collection sponsor can be set to pay for collection Transfer transactions.1617Wider NFT Ecosystem (most of it was developed during Hackusama):18* [SubstraPunks Game hosted on IPFS](https://github.com/usetech-llc/substrapunks)19* [NFT Wallet and UI](https://uniqueapps.usetech.com/#/nft)20* [NFT Asset for Unity Framework](https://github.com/usetech-llc/nft_unity)2122Please see our [walk-thorugh instructions](doc/hackusama_walk_through.md) to try everything out!2324## Hackusama Update2526During the Kusama Hackaphon the following changes were made:27* Enabled Smart Contracts Pallet28* Enabled integration between Smart Contracts and NFT Pallet (required special edition of RC4 Substrate version)29* Fixed misc. bugs in NFT Pallet30* Deployed NFT TestNet. Public node available at wss://unique.usetech.com, custom UI types - see below in this README.31* New Features:32 * Re-Fungible Token Mode33 * Off-Chain Schema to store token image URLs34 * Alternative economic model35 * White Lists and Public Mint Permission36* Use example: [SubstraPunks Game](https://github.com/usetech-llc/substrapunks), fully hosted on IPFS and NFT Testnet Blockchain.3738## Application Development3940If you are building an application that operates NFT tokens, use [this document](doc/application_development.md).4142## Building4344Building NFT chain requires special versions of Rust and toolchain. We don't use the most recent versions of everything so that we can keep the builds stable.45461. Install Rust:4748```bash49curl https://sh.rustup.rs -sSf | sh50sudo apt-get install libssl-dev pkg-config libclang-dev clang51```52532. Remove all installed toolchains with `rustup toolchain list` and `rustup toolchain uninstall <toolchain>`.54553. Install Rust Toolchain 1.44.0:5657```bash58rustup install 1.44.059```60614. Make it default (actual toochain version may be different, so do a `rustup toolchain list` first)62```bash63rustup toolchain list64rustup default 1.44.0-x86_64-unknown-linux-gnu65```66675. Install nightly toolchain and add wasm target for it:6869```bash70rustup toolchain install nightly-2020-05-0171rustup target add wasm32-unknown-unknown --toolchain nightly-2020-05-01-x86_64-unknown-linux-gnu72```73746. Build:75```bash76cargo build77```7879## Run8081You can start a development chain with:8283```bash84cargo run -- --dev85```8687Detailed logs may be shown by running the node with the following environment variables set: `RUST_LOG=debug RUST_BACKTRACE=1 cargo run -- --dev`.8889If you want to see the multi-node consensus algorithm in action locally, then you can create a local testnet with two validator nodes for Alice and Bob, who are the initial authorities of the genesis chain that have been endowed with testnet units. Give each node a name and expose them so they are listed on the Polkadot [telemetry site](https://telemetry.polkadot.io/#/Local%20Testnet). You'll need two terminal windows open.9091We'll start Alice's substrate node first on default TCP port 30333 with her chain database stored locally at `/tmp/alice`. The bootnode ID of her node is `QmQZ8TjTqeDj3ciwr93EJ95hxfDsb9pEYDizUAbWpigtQN`, which is generated from the `--node-key` value that we specify below:9293```bash94cargo run -- \95 --base-path /tmp/alice \96 --chain=local \97 --alice \98 --node-key 0000000000000000000000000000000000000000000000000000000000000001 \99 --telemetry-url ws://telemetry.polkadot.io:1024 \100 --validator101```102103In the second terminal, we'll start Bob's substrate node on a different TCP port of 30334, and with his chain database stored locally at `/tmp/bob`. We'll specify a value for the `--bootnodes` option that will connect his node to Alice's bootnode ID on TCP port 30333:104105```bash106cargo run -- \107 --base-path /tmp/bob \108 --bootnodes /ip4/127.0.0.1/tcp/30333/p2p/QmQZ8TjTqeDj3ciwr93EJ95hxfDsb9pEYDizUAbWpigtQN \109 --chain=local \110 --bob \111 --port 30334 \112 --telemetry-url ws://telemetry.polkadot.io:1024 \113 --validator114```115116Additional CLI usage options are available and may be shown by running `cargo run -- --help`.117118119## UI custom types120```121{122 "Schedule": {123 "version": "u32",124 "put_code_per_byte_cost": "Gas",125 "grow_mem_cost": "Gas",126 "regular_op_cost": "Gas",127 "return_data_per_byte_cost": "Gas",128 "event_data_per_byte_cost": "Gas",129 "event_per_topic_cost": "Gas",130 "event_base_cost": "Gas",131 "call_base_cost": "Gas",132 "instantiate_base_cost": "Gas",133 "dispatch_base_cost": "Gas",134 "sandbox_data_read_cost": "Gas",135 "sandbox_data_write_cost": "Gas",136 "transfer_cost": "Gas",137 "instantiate_cost": "Gas",138 "max_event_topics": "u32",139 "max_stack_height": "u32",140 "max_memory_pages": "u32",141 "max_table_size": "u32",142 "enable_println": "bool",143 "max_subject_len": "u32"144 },145 "CollectionMode": {146 "_enum": {147 "Invalid": null,148 "NFT": "u32",149 "Fungible": "u32",150 "ReFungible": "(u32, u32)"151 }152 },153 "Ownership": {154 "Owner": "AccountId",155 "Fraction": "u128"156 },157 "FungibleItemType": {158 "Collection": "u64",159 "Owner": "AccountId",160 "Value": "u128"161 },162 "ReFungibleItemType": {163 "Collection": "u64",164 "Owner": "Vec<Ownership>",165 "Data": "Vec<u8>"166 },167 "NftItemType": {168 "Collection": "u64",169 "Owner": "AccountId",170 "Data": "Vec<u8>"171 },172 "Ownership": {173 "owner": "AccountId",174 "fraction": "u128"175 },176 "ReFungibleItemType": {177 "Collection": "u64",178 "Owner": "Vec<Ownership<AccountId>>",179 "Data": "Vec<u8>"180 },181 "CollectionType": {182 "Owner": "AccountId",183 "Mode": "CollectionMode",184 "Access": "u8",185 "DecimalPoints": "u32",186 "Name": "Vec<u16>",187 "Description": "Vec<u16>",188 "TokenPrefix": "Vec<u8>",189 "CustomDataSize": "u32",190 "OffchainSchema": "Vec<u8>",191 "Sponsor": "AccountId",192 "UnconfirmedSponsor": "AccountId"193 },194 "RawData": "Vec<u8>",195 "Address": "AccountId",196 "LookupSource": "AccountId",197 "Weight": "u64"198}199```tests/src/config.tsdiffbeforeafterboth--- a/tests/src/config.ts
+++ b/tests/src/config.ts
@@ -34,6 +34,20 @@
"ReFungible": "(u32, u32)"
}
},
+ "Ownership": {
+ "Owner": "AccountId",
+ "Fraction": "u128"
+ },
+ "FungibleItemType": {
+ "Collection": "u64",
+ "Owner": "AccountId",
+ "Value": "u128"
+ },
+ "ReFungibleItemType": {
+ "Collection": "u64",
+ "Owner": "Vec<Ownership>",
+ "Data": "Vec<u8>"
+ },
"NftItemType": {
"Collection": "u64",
"Owner": "AccountId",
@@ -57,10 +71,15 @@
"Description": "Vec<u16>",
"TokenPrefix": "Vec<u8>",
"CustomDataSize": "u32",
+ "MintMode": "bool",
"OffchainSchema": "Vec<u8>",
"Sponsor": "AccountId",
"UnconfirmedSponsor": "AccountId"
},
+ "ApprovePermissions": {
+ "Approved": "AccountId",
+ "Amount": "u64"
+ },
"RawData": "Vec<u8>",
"Address": "AccountId",
"LookupSource": "AccountId",
tests/src/connection.test.tsdiffbeforeafterboth--- a/tests/src/connection.test.ts
+++ b/tests/src/connection.test.ts
@@ -15,9 +15,9 @@
});
});
- it('Cannot connect to 0.0.0.0', () => {
- const neverConnectProvider = new WsProvider('ws://0.0.0.0:9944');
- expect((async () => {
+ it('Cannot connect to 255.255.255.255', async () => {
+ const neverConnectProvider = new WsProvider('ws://255.255.255.255:9944');
+ await expect((async () => {
await usingApi(async api => {
const health = await api.rpc.system.health();
}, { provider: neverConnectProvider });
tests/src/substrate/promisify-substrate.tsdiffbeforeafterboth--- a/tests/src/substrate/promisify-substrate.ts
+++ b/tests/src/substrate/promisify-substrate.ts
@@ -4,19 +4,21 @@
export default function promisifySubstrate<T extends (...args: any[]) => any>(api: ApiPromise, action: T): (...args: Parameters<T>) => Promise<PromiseType<ReturnType<T>>> {
return (...args: Parameters<T>) => {
- const promise = new Promise<PromiseType<ReturnType<T>>>((resolve, reject) => {
+ const promise = new Promise<PromiseType<ReturnType<T>>>((resolve: ((result: PromiseType<ReturnType<T>>) => void) | undefined, reject: ((error: any) => void) | undefined) => {
const cleanup = () => {
api.off('disconnected', fail);
api.off('error', fail);
+ resolve = undefined;
+ reject = undefined;
};
const success = (r: any) => {
+ resolve && resolve(r);
cleanup();
- resolve(r);
};
const fail = (error: any) => {
+ reject && reject(error);
cleanup();
- reject(error);
};
api.on('disconnected', fail);
tests/src/substrate/substrate-api.tsdiffbeforeafterboth--- a/tests/src/substrate/substrate-api.ts
+++ b/tests/src/substrate/substrate-api.ts
@@ -10,13 +10,16 @@
export default async function usingApi(action: (api: ApiPromise) => Promise<void>, settings: ApiOptions | undefined = undefined): Promise<void> {
settings = settings || defaultApiOptions();
- let api: ApiPromise | undefined = undefined;
+ let api: ApiPromise = new ApiPromise(settings);
try {
- api = new ApiPromise(settings);
- await promisifySubstrate(api, () => api && api.isReady)();
- await action(api);
+ await promisifySubstrate(api, async () => {
+ if(api) {
+ await api.isReadyOrError;
+ await action(api);
+ }
+ })();
} finally {
- api && api.disconnect();
+ await api.disconnect();
}
}
\ No newline at end of file