diff --git a/.eslintrc.js b/.eslintrc.js deleted file mode 100644 index 6a84c5a..0000000 --- a/.eslintrc.js +++ /dev/null @@ -1,13 +0,0 @@ -module.exports = { - parserOptions: { - ecmaVersion: 2020, - sourceType: 'module', - ecmaFeatures: { - jsx: true, - } - }, - rules: { - semi: [2, 'always'], - indent: [2, 'tab'], - } -}; diff --git a/.gitignore b/.gitignore index 41ef6d9..9b48da2 100644 --- a/.gitignore +++ b/.gitignore @@ -32,3 +32,4 @@ npm-debug.log* yarn-debug.log* yarn-error.log* neardev +Cargo.lock diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..5778b76 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,24 @@ +[package] +name = "paras-nft-contract-wrapper" +version = "0.0.1" +authors = ["Irfianto "] +edition = "2018" + +[dev-dependencies] +near-sdk = "=3.1.0" +near-contract-standards = "3.2.0" +near-sdk-sim = "=3.1.0" +paras-nft-contract = { path = "./paras-nft-contract" } + +[profile.release] +codegen-units = 1 +opt-level = "z" +lto = true +debug = false +panic = "abort" +overflow-checks = true + +[workspace] +members = [ + "paras-nft-contract", +] \ No newline at end of file diff --git a/README.md b/README.md index 49dadf1..a4e62e3 100644 --- a/README.md +++ b/README.md @@ -19,12 +19,12 @@ Everything should work if you have NEAR development env for Rust contracts set u env NEAR_ENV=local near --keyPath ~/.near/localnet/validator_key.json deploy --accountId comic.test.near ``` -### Nft init +### NFT init ``` env NEAR_ENV=local near call --keyPath ~/.near/localnet/validator_key.json --accountId comic.test.near comic.test.near new_default_meta '{"owner_id":"comic.test.near"}' ``` -### Nft create series +### NFT create series ``` env NEAR_ENV=local near call --keyPath ~/.near/localnet/validator_key.json --accountId comic.test.near comic.test.near nft_create_series '{"token_series_id":"1", "creator_id":"alice.test.near","token_metadata":{"title":"Naruto Shippuden ch.2: Menolong sasuke","media":"bafybeidzcan4nzcz7sczs4yzyxly4galgygnbjewipj6haco4kffoqpkiy", "reference":"bafybeicg4ss7qh5odijfn2eogizuxkrdh3zlv4eftcmgnljwu7dm64uwji"},"price":"1000000000000000000000000"}' --depositYocto 11790000000000000000000 ``` @@ -40,32 +40,37 @@ env NEAR_ENV=local near call --keyPath ~/.near/localnet/validator_key.json --acc ``` -### Nft buy +### NFT buy ``` env NEAR_ENV=local near call --keyPath ~/.near/localnet/validator_key.json --accountId comic.test.near comic.test.near nft_buy '{"token_series_id":"1","receiver_id":"comic.test.near"}' --depositYocto 1018320000000000000000000 ``` -### Nft mint series(Author only) +### NFT mint series(Author only) ``` env NEAR_ENV=local near call --keyPath ~/.near/localnet/validator_key.json --accountId comic.test.near comic.test.near nft_mint '{"token_series_id":"1","receiver_id":"comic.test.near"}' --depositYocto 18320000000000000000000a ``` -### Nft transfer +### NFT transfer ``` env NEAR_ENV=local near call --keyPath ~/.near/localnet/validator_key.json --accountId comic.test.near comic.test.near nft_transfer '{"token_id":"1:1","receiver_id":"comic1.test.near"}' --depositYocto 1 ``` -### Nft set series mintable (Author only ) +### NFT set series mintable (Author only ) ``` env NEAR_ENV=local near call --keyPath ~/.near/localnet/validator_key.json --accountId comic.test.near comic.test.near nft_set_series_non_mintable '{"token_series_id":"1"}' --depositYocto 1 ``` -### Nft set series price (Author only) +### NFT set series price (Author only) ``` env NEAR_ENV=local near call --keyPath ~/.near/localnet/validator_key.json --accountId comic.test.near comic.test.near nft_set_series_price '{"token_series_id":"1", "price": "2000000000000000000000000"}' --depositYocto 1 ``` -### Nft burn +### NFT burn ``` env NEAR_ENV=local near call --keyPath ~/.near/localnet/validator_key.json --accountId comic.test.near comic.test.near nft_burn '{"token_id":"1:2"}' --depositYocto 1 ``` + +### NFT approve +``` +env NEAR_ENV=local near call --keyPath ~/.near/localnet/validator_key.json --accountId alice.test.near comic.test.near nft_approve '{"token_id":"1:10","account_id":"marketplace.test.near","msg":"{\"price\":\"3000000000000000000000000\",\"ft_token_id\":\"near\"}"}' --depositYocto 1320000000000000000000 +``` diff --git a/build.sh b/build.sh new file mode 100755 index 0000000..6390363 --- /dev/null +++ b/build.sh @@ -0,0 +1,5 @@ +#!/bin/bash +set -e +cd "`dirname $0`" +RUSTFLAGS='-C link-arg=-s' cargo build --all --target wasm32-unknown-unknown --release +cp target/wasm32-unknown-unknown/release/*.wasm ./out/main.wasm diff --git a/contract/Cargo.lock b/contract/Cargo.lock deleted file mode 100644 index 99e4d9c..0000000 --- a/contract/Cargo.lock +++ /dev/null @@ -1,599 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "Inflector" -version = "0.11.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe438c63458706e03479442743baae6c88256498e6431708f6dfc520a26515d3" - -[[package]] -name = "ahash" -version = "0.4.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "739f4a8db6605981345c5654f3a85b056ce52f37a39d34da03f25bf2151ea16e" - -[[package]] -name = "aho-corasick" -version = "0.7.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f" -dependencies = [ - "memchr", -] - -[[package]] -name = "autocfg" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" - -[[package]] -name = "base64" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" - -[[package]] -name = "block-buffer" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" -dependencies = [ - "block-padding", - "generic-array", -] - -[[package]] -name = "block-padding" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d696c370c750c948ada61c69a0ee2cbbb9c50b1019ddb86d9317157a99c2cae" - -[[package]] -name = "borsh" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09a7111f797cc721407885a323fb071636aee57f750b1a4ddc27397eba168a74" -dependencies = [ - "borsh-derive", - "hashbrown", -] - -[[package]] -name = "borsh-derive" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "307f3740906bac2c118a8122fe22681232b244f1369273e45f1156b45c43d2dd" -dependencies = [ - "borsh-derive-internal", - "borsh-schema-derive-internal", - "proc-macro-crate", - "proc-macro2", - "syn", -] - -[[package]] -name = "borsh-derive-internal" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2104c73179359431cc98e016998f2f23bc7a05bc53e79741bcba705f30047bc" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "borsh-schema-derive-internal" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae29eb8418fcd46f723f8691a2ac06857d31179d33d2f2d91eb13967de97c728" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "bs58" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "771fe0050b883fcc3ea2359b1a96bcfbc090b7116eae7c3c512c7a083fdf23d3" - -[[package]] -name = "byteorder" -version = "1.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" - -[[package]] -name = "cfg-if" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" - -[[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - -[[package]] -name = "convert_case" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" - -[[package]] -name = "cpufeatures" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed00c67cb5d0a7d64a44f6ad2668db7e7530311dd53ea79bcd4fb022c64911c8" -dependencies = [ - "libc", -] - -[[package]] -name = "derive_more" -version = "0.99.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cc7b9cef1e351660e5443924e4f43ab25fbbed3e9a5f052df3677deb4d6b320" -dependencies = [ - "convert_case", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "digest" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" -dependencies = [ - "generic-array", -] - -[[package]] -name = "generic-array" -version = "0.14.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "501466ecc8a30d1d3b7fc9229b122b2ce8ed6e9d9223f1138d4babb253e51817" -dependencies = [ - "typenum", - "version_check", -] - -[[package]] -name = "hashbrown" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04" -dependencies = [ - "ahash", -] - -[[package]] -name = "hex" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" - -[[package]] -name = "indexmap" -version = "1.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "824845a0bf897a9042383849b02c1bc219c2383772efcd5c6f9766fa4b81aef3" -dependencies = [ - "autocfg", - "hashbrown", -] - -[[package]] -name = "itoa" -version = "0.4.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd25036021b0de88a0aff6b850051563c6516d0bf53f8638938edbb9de732736" - -[[package]] -name = "keccak" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67c21572b4949434e4fc1e1978b99c5f77064153c59d998bf13ecd96fb5ecba7" - -[[package]] -name = "lazy_static" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" - -[[package]] -name = "libc" -version = "0.2.96" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5600b4e6efc5421841a2138a6b082e07fe12f9aaa12783d50e5d13325b26b4fc" - -[[package]] -name = "memchr" -version = "2.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b16bd47d9e329435e309c58469fe0791c2d0d1ba96ec0954152a5ae2b04387dc" - -[[package]] -name = "memory_units" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8452105ba047068f40ff7093dd1d9da90898e63dd61736462e9cdda6a90ad3c3" - -[[package]] -name = "near-contract-standards" -version = "3.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7421d0a5c7aeb57b37a0cf3a71a7aefbbdc7727f9811d9dd86fa55e4f0de4d3" -dependencies = [ - "near-sdk", -] - -[[package]] -name = "near-primitives-core" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2b3fb5acf3a494aed4e848446ef2d6ebb47dbe91c681105d4d1786c2ee63e52" -dependencies = [ - "base64", - "borsh", - "bs58", - "derive_more", - "hex", - "lazy_static", - "num-rational", - "serde", - "serde_json", - "sha2", -] - -[[package]] -name = "near-rpc-error-core" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffa8dbf8437a28ac40fcb85859ab0d0b8385013935b000c7a51ae79631dd74d9" -dependencies = [ - "proc-macro2", - "quote", - "serde", - "serde_json", - "syn", -] - -[[package]] -name = "near-rpc-error-macro" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c6111d713e90c7c551dee937f4a06cb9ea2672243455a4454cc7566387ba2d9" -dependencies = [ - "near-rpc-error-core", - "proc-macro2", - "quote", - "serde", - "serde_json", - "syn", -] - -[[package]] -name = "near-runtime-utils" -version = "4.0.0-pre.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a48d80c4ca1d4cf99bc16490e1e3d49826c150dfc4410ac498918e45c7d98e07" -dependencies = [ - "lazy_static", - "regex", -] - -[[package]] -name = "near-sdk" -version = "3.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7383e242d3e07bf0951e8589d6eebd7f18bb1c1fc5fbec3fad796041a6aebd1" -dependencies = [ - "base64", - "borsh", - "bs58", - "near-primitives-core", - "near-sdk-macros", - "near-vm-logic", - "serde", - "serde_json", - "wee_alloc", -] - -[[package]] -name = "near-sdk-core" -version = "3.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "284a78d9eb8eda58330462fa0023a6d7014c941df1f0387095e7dfd1dc0f2bce" -dependencies = [ - "Inflector", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "near-sdk-macros" -version = "3.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2037337438f97d1ce5f7c896cf229dc56dacd5c01142d1ef95a7d778cde6ce7d" -dependencies = [ - "near-sdk-core", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "near-vm-errors" -version = "4.0.0-pre.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e281d8730ed8cb0e3e69fb689acee6b93cdb43824cd69a8ffd7e1bfcbd1177d7" -dependencies = [ - "borsh", - "hex", - "near-rpc-error-macro", - "serde", -] - -[[package]] -name = "near-vm-logic" -version = "4.0.0-pre.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e11cb28a2d07f37680efdaf860f4c9802828c44fc50c08009e7884de75d982c5" -dependencies = [ - "base64", - "borsh", - "bs58", - "byteorder", - "near-primitives-core", - "near-runtime-utils", - "near-vm-errors", - "serde", - "sha2", - "sha3", -] - -[[package]] -name = "nft-series" -version = "0.1.0" -dependencies = [ - "near-contract-standards", - "near-sdk", -] - -[[package]] -name = "num-bigint" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d0a3d5e207573f948a9e5376662aa743a2ea13f7c50a554d7af443a73fbfeba" -dependencies = [ - "autocfg", - "num-integer", - "num-traits", -] - -[[package]] -name = "num-integer" -version = "0.1.44" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db" -dependencies = [ - "autocfg", - "num-traits", -] - -[[package]] -name = "num-rational" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12ac428b1cb17fce6f731001d307d351ec70a6d202fc2e60f7d4c5e42d8f4f07" -dependencies = [ - "autocfg", - "num-bigint", - "num-integer", - "num-traits", - "serde", -] - -[[package]] -name = "num-traits" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290" -dependencies = [ - "autocfg", -] - -[[package]] -name = "opaque-debug" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" - -[[package]] -name = "proc-macro-crate" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d6ea3c4595b96363c13943497db34af4460fb474a95c43f4446ad341b8c9785" -dependencies = [ - "toml", -] - -[[package]] -name = "proc-macro2" -version = "1.0.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0d8caf72986c1a598726adc988bb5984792ef84f5ee5aa50209145ee8077038" -dependencies = [ - "unicode-xid", -] - -[[package]] -name = "quote" -version = "1.0.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "regex" -version = "1.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461" -dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax", -] - -[[package]] -name = "regex-syntax" -version = "0.6.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" - -[[package]] -name = "ryu" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e" - -[[package]] -name = "serde" -version = "1.0.118" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06c64263859d87aa2eb554587e2d23183398d617427327cf2b3d0ed8c69e4800" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde_derive" -version = "1.0.118" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c84d3526699cd55261af4b941e4e725444df67aa4f9e6a3564f18030d12672df" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "serde_json" -version = "1.0.64" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "799e97dc9fdae36a5c8b8f2cae9ce2ee9fdce2058c57a93e6099d919fd982f79" -dependencies = [ - "indexmap", - "itoa", - "ryu", - "serde", -] - -[[package]] -name = "sha2" -version = "0.9.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b362ae5752fd2137731f9fa25fd4d9058af34666ca1966fb969119cc35719f12" -dependencies = [ - "block-buffer", - "cfg-if 1.0.0", - "cpufeatures", - "digest", - "opaque-debug", -] - -[[package]] -name = "sha3" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f81199417d4e5de3f04b1e871023acea7389672c4135918f05aa9cbf2f2fa809" -dependencies = [ - "block-buffer", - "digest", - "keccak", - "opaque-debug", -] - -[[package]] -name = "syn" -version = "1.0.57" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4211ce9909eb971f111059df92c45640aad50a619cf55cd76476be803c4c68e6" -dependencies = [ - "proc-macro2", - "quote", - "unicode-xid", -] - -[[package]] -name = "toml" -version = "0.5.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a31142970826733df8241ef35dc040ef98c679ab14d7c3e54d827099b3acecaa" -dependencies = [ - "serde", -] - -[[package]] -name = "typenum" -version = "1.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "879f6906492a7cd215bfa4cf595b600146ccfac0c79bcbd1f3000162af5e8b06" - -[[package]] -name = "unicode-xid" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" - -[[package]] -name = "version_check" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe" - -[[package]] -name = "wee_alloc" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbb3b5a6b2bb17cb6ad44a2e68a43e8d2722c997da10e928665c72ec6c0a0b8e" -dependencies = [ - "cfg-if 0.1.10", - "libc", - "memory_units", - "winapi", -] - -[[package]] -name = "winapi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" -dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", -] - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" - -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/contract/build.sh b/contract/build.sh deleted file mode 100755 index e69a76f..0000000 --- a/contract/build.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/bash -set -e - -RUSTFLAGS='-C link-arg=-s' cargo build --target wasm32-unknown-unknown --release -mkdir -p ../out -cp target/wasm32-unknown-unknown/release/*.wasm ../out/main.wasm diff --git a/package.json b/package.json index 07f5a61..ae5f4c0 100644 --- a/package.json +++ b/package.json @@ -3,11 +3,11 @@ "version": "0.1.0", "license": "MIT", "scripts": { - "build:contract": "cd contract && ./build.sh && cd ..", + "build:contract": "./build.sh", "patch:config": "node ./utils/patch-config.js", "dev:deploy": "yarn build:contract && rm -rf neardev && (near dev-deploy || exit 0) && yarn patch:config", - "test:deploy": "yarn dev:deploy && mocha", - "test": "mocha" + "test:deploy": "yarn dev:deploy && yarn test", + "test": "cargo test --all -- --nocapture --color always" }, "dependencies": { "mocha": "^9.0.1" diff --git a/contract/Cargo.toml b/paras-nft-contract/Cargo.toml similarity index 83% rename from contract/Cargo.toml rename to paras-nft-contract/Cargo.toml index b2c08b9..c4e2ca3 100644 --- a/contract/Cargo.toml +++ b/paras-nft-contract/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "paras-comic-nft-contract" +name = "paras-nft-contract" version = "0.1.0" authors = ["Irfianto "] edition = "2018" @@ -17,4 +17,4 @@ opt-level = "z" lto = true debug = false panic = "abort" -overflow-checks = true +overflow-checks = true \ No newline at end of file diff --git a/contract/src/lib.rs b/paras-nft-contract/src/lib.rs similarity index 93% rename from contract/src/lib.rs rename to paras-nft-contract/src/lib.rs index f09c918..7877f0f 100644 --- a/contract/src/lib.rs +++ b/paras-nft-contract/src/lib.rs @@ -111,7 +111,7 @@ impl Contract { #[payable] pub fn nft_create_series( &mut self, - token_series_id: U64, + token_series_id: U128, token_metadata: TokenMetadata, creator_id: ValidAccountId, price: Option, @@ -195,7 +195,11 @@ impl Contract { } #[payable] - pub fn nft_buy(&mut self, token_series_id: TokenSeriesId, receiver_id: ValidAccountId) -> Token { + pub fn nft_buy( + &mut self, + token_series_id: TokenSeriesId, + receiver_id: ValidAccountId + ) -> TokenId { let initial_storage_usage = env::storage_usage(); let token_series = self.token_series_by_id.get(&token_series_id).expect("Paras: Token series not exist"); @@ -206,26 +210,34 @@ impl Contract { "Paras: attached deposit is less than price : {}", price ); - let token: Token = self._nft_mint_series(token_series_id, receiver_id); + let token_id: TokenId = self._nft_mint_series(token_series_id, receiver_id); Promise::new(token_series.creator_id).transfer(price); refund_deposit(env::storage_usage() - initial_storage_usage, price); - token + token_id } #[payable] - pub fn nft_mint(&mut self, token_series_id: TokenSeriesId, receiver_id: ValidAccountId) -> Token { + pub fn nft_mint( + &mut self, + token_series_id: TokenSeriesId, + receiver_id: ValidAccountId + ) -> TokenId { let initial_storage_usage = env::storage_usage(); let token_series = self.token_series_by_id.get(&token_series_id).expect("Paras: Token series not exist"); assert_eq!(env::predecessor_account_id(), token_series.creator_id, "Paras: not creator"); - let token: Token = self._nft_mint_series(token_series_id, receiver_id); + let token_id: TokenId = self._nft_mint_series(token_series_id, receiver_id); refund_deposit(env::storage_usage() - initial_storage_usage, 0); - token + token_id } - fn _nft_mint_series(&mut self, token_series_id: TokenSeriesId, receiver_id: ValidAccountId) -> Token { + fn _nft_mint_series( + &mut self, + token_series_id: TokenSeriesId, + receiver_id: ValidAccountId + ) -> TokenId { let mut token_series = self.token_series_by_id.get(&token_series_id).expect("Paras: Token series not exist"); assert!( token_series.is_mintable, @@ -282,8 +294,6 @@ impl Contract { tokens_per_owner.insert(&owner_id, &token_ids); } - let token_res = self.nft_token(token_id.clone()).unwrap(); - env::log( json!({ "type": "nft_transfer", @@ -297,12 +307,7 @@ impl Contract { .as_bytes(), ); - Token { - token_id, - owner_id: token_res.owner_id, - metadata: token_res.metadata, - approved_account_ids: token_res.approved_account_ids - } + token_id } #[payable] @@ -813,7 +818,7 @@ mod tests { fn create_series( contract: &mut Contract, - token_series_id: U64, + token_series_id: U128, royalty: &HashMap, price: Option, ) { @@ -854,7 +859,7 @@ mod tests { let mut royalty: HashMap = HashMap::new(); royalty.insert(accounts(1).to_string(), 1000); - create_series(&mut contract, U64::from(1), &royalty, Some(U128::from(1 * 10u128.pow(24)))); + create_series(&mut contract, U128::from(1), &royalty, Some(U128::from(1 * 10u128.pow(24)))); let nft_series_return = contract.nft_get_series_single("1".to_string()); assert_eq!( @@ -901,8 +906,8 @@ mod tests { let mut royalty: HashMap = HashMap::new(); royalty.insert(accounts(1).to_string(), 1000); - create_series(&mut contract, U64::from(1), &royalty, Some(U128::from(1 * 10u128.pow(24)))); - create_series(&mut contract, U64::from(1), &royalty, Some(U128::from(1 * 10u128.pow(24)))); + create_series(&mut contract, U128::from(1), &royalty, Some(U128::from(1 * 10u128.pow(24)))); + create_series(&mut contract, U128::from(1), &royalty, Some(U128::from(1 * 10u128.pow(24)))); } #[test] @@ -917,7 +922,7 @@ mod tests { let mut royalty: HashMap = HashMap::new(); royalty.insert(accounts(1).to_string(), 1000); - create_series(&mut contract, U64::from(1), &royalty, Some(U128::from(1 * 10u128.pow(24)))); + create_series(&mut contract, U128::from(1), &royalty, Some(U128::from(1 * 10u128.pow(24)))); testing_env!(context .predecessor_account_id(accounts(2)) @@ -925,9 +930,9 @@ mod tests { .build() ); - let token = contract.nft_buy("1".to_string(), accounts(2)); + let token_id = contract.nft_buy("1".to_string(), accounts(2)); - let token_from_nft_token = contract.nft_token(token.token_id); + let token_from_nft_token = contract.nft_token(token_id); assert_eq!( token_from_nft_token.unwrap().owner_id, accounts(2).to_string() @@ -946,7 +951,7 @@ mod tests { let mut royalty: HashMap = HashMap::new(); royalty.insert(accounts(1).to_string(), 1000); - create_series(&mut contract, U64::from(1), &royalty, None); + create_series(&mut contract, U128::from(1), &royalty, None); testing_env!(context .predecessor_account_id(accounts(1)) @@ -954,9 +959,9 @@ mod tests { .build() ); - let token = contract.nft_mint("1".to_string(), accounts(2)); + let token_id = contract.nft_mint("1".to_string(), accounts(2)); - let token_from_nft_token = contract.nft_token(token.token_id); + let token_from_nft_token = contract.nft_token(token_id); assert_eq!( token_from_nft_token.unwrap().owner_id, accounts(2).to_string() @@ -976,7 +981,7 @@ mod tests { let mut royalty: HashMap = HashMap::new(); royalty.insert(accounts(1).to_string(), 1000); - create_series(&mut contract, U64::from(1), &royalty, None); + create_series(&mut contract, U128::from(1), &royalty, None); testing_env!(context .predecessor_account_id(accounts(1)) @@ -1007,7 +1012,7 @@ mod tests { let mut royalty: HashMap = HashMap::new(); royalty.insert(accounts(1).to_string(), 1000); - create_series(&mut contract, U64::from(1), &royalty, None); + create_series(&mut contract, U128::from(1), &royalty, None); testing_env!(context .predecessor_account_id(accounts(2)) @@ -1015,9 +1020,9 @@ mod tests { .build() ); - let token = contract.nft_buy("1".to_string(), accounts(2)); + let token_id = contract.nft_buy("1".to_string(), accounts(2)); - let token_from_nft_token = contract.nft_token(token.token_id); + let token_from_nft_token = contract.nft_token(token_id); assert_eq!( token_from_nft_token.unwrap().owner_id, accounts(2).to_string() @@ -1036,7 +1041,7 @@ mod tests { let mut royalty: HashMap = HashMap::new(); royalty.insert(accounts(1).to_string(), 1000); - create_series(&mut contract, U64::from(1), &royalty, None); + create_series(&mut contract, U128::from(1), &royalty, None); testing_env!(context .predecessor_account_id(accounts(1)) @@ -1044,7 +1049,7 @@ mod tests { .build() ); - let token = contract.nft_mint("1".to_string(), accounts(2)); + let token_id = contract.nft_mint("1".to_string(), accounts(2)); testing_env!(context .predecessor_account_id(accounts(2)) @@ -1052,8 +1057,8 @@ mod tests { .build() ); - contract.nft_burn(token.token_id.clone()); - let token = contract.nft_token(token.token_id); + contract.nft_burn(token_id.clone()); + let token = contract.nft_token(token_id); assert!(token.is_none()); } @@ -1069,7 +1074,7 @@ mod tests { let mut royalty: HashMap = HashMap::new(); royalty.insert(accounts(1).to_string(), 1000); - create_series(&mut contract, U64::from(1), &royalty, None); + create_series(&mut contract, U128::from(1), &royalty, None); testing_env!(context .predecessor_account_id(accounts(1)) @@ -1077,7 +1082,7 @@ mod tests { .build() ); - let token = contract.nft_mint("1".to_string(), accounts(2)); + let token_id = contract.nft_mint("1".to_string(), accounts(2)); testing_env!(context .predecessor_account_id(accounts(2)) @@ -1085,9 +1090,9 @@ mod tests { .build() ); - contract.nft_transfer(accounts(3), token.token_id.clone(), None, None); + contract.nft_transfer(accounts(3), token_id.clone(), None, None); - let token = contract.nft_token(token.token_id).unwrap(); + let token = contract.nft_token(token_id).unwrap(); assert_eq!( token.owner_id, accounts(3).to_string() @@ -1106,7 +1111,7 @@ mod tests { let mut royalty: HashMap = HashMap::new(); royalty.insert(accounts(1).to_string(), 1000); - create_series(&mut contract, U64::from(1), &royalty, None); + create_series(&mut contract, U128::from(1), &royalty, None); testing_env!(context .predecessor_account_id(accounts(1)) @@ -1114,7 +1119,7 @@ mod tests { .build() ); - let token = contract.nft_mint("1".to_string(), accounts(2)); + let token_id = contract.nft_mint("1".to_string(), accounts(2)); testing_env!(context .predecessor_account_id(accounts(2)) @@ -1124,7 +1129,7 @@ mod tests { let payout = contract.nft_transfer_payout( accounts(3), - token.token_id.clone(), + token_id.clone(), U64::from(0), U128::from(1 * 10u128.pow(24)), 10 @@ -1142,7 +1147,7 @@ mod tests { assert_eq!(payout, payout_calc); - let token = contract.nft_token(token.token_id).unwrap(); + let token = contract.nft_token(token_id).unwrap(); assert_eq!( token.owner_id, accounts(3).to_string() diff --git a/test/api.test.js b/test/api.test.js deleted file mode 100644 index 499b349..0000000 --- a/test/api.test.js +++ /dev/null @@ -1,280 +0,0 @@ -const assert = require('assert'); -const { parseNearAmount } = require('near-api-js/lib/utils/format'); -const { contract } = require('./near-utils'); -const testUtils = require('./test-utils'); - -const { - gas, - contractId, - contractAccount, - getAccount, -} = testUtils; - -describe('NFT Series', function () { - this.timeout(10000); - - const now = Date.now().toString() - let token_type = 'dog-' + now - - /// users - const aliceId = 'alice-' + now + '.' + contractId; - let alice - it('should create user accounts', async function () { - alice = await getAccount(aliceId); - console.log('\n\n alice accountId:', aliceId, '\n\n'); - }) - - it('should be deployed', async function () { - const state = await contractAccount.state() - try { - await contractAccount.functionCall({ - contractId, - methodName: 'new_default_meta', - args: { - owner_id: contractId - }, - gas - }) - } catch (e) { - if (!/contract has already been initialized/.test(e.toString())) { - console.warn(e) - } - } - - assert.notStrictEqual(state.code_hash, '11111111111111111111111111111111'); - }); - - it('should allow owner to create a type', async function () { - await contractAccount.functionCall({ - contractId, - methodName: 'nft_create_type', - args: { - token_metadata: { - title: token_type, - media: 'https://placedog.net/500', - copies: 1, - }, - token_type: token_type, - price: "1000000000000000000000000" - }, - gas, - attachedDeposit: parseNearAmount('0.1') - }) - - const [token_type_ret, owner_id, type_metadata] = await contractAccount.viewFunction( - contractId, - 'nft_get_type_info', - { - token_type - } - ) - - assert.strictEqual(token_type_ret, token_type); - assert.strictEqual(owner_id, contractId); - assert.strictEqual(type_metadata.copies, 1); - - const types = await contractAccount.viewFunction( - contractId, - 'nft_get_types', - { - limit: 10 - } - ) - - console.log(types) - assert.strictEqual(types.length, 1); - }); - - it('should NOT allow non-owner to create type', async function() { - try { - await alice.functionCall({ - contractId, - methodName: 'nft_create_type', - args: { - token_metadata: { - title: token_type, - media: 'https://placedog.net/500', - copies: 1, - }, - token_type: token_type, - price: "1000000000000000000000000" - }, - gas, - attachedDeposit: parseNearAmount('0.1') - }) - assert(false) - } catch(e) { - assert(true) - } - }); - - it('should NOT create the same type', async function () { - try { - await contractAccount.functionCall({ - contractId, - methodName: 'nft_create_type', - args: { - token_metadata: { - title: token_type, - media: 'https://placedog.net/500', - copies: 1, - }, - token_type: token_type, - price: "1000000000000000000000000" - }, - gas, - attachedDeposit: parseNearAmount('0.1') - }) - assert(false) - } catch(e) { - assert(true) - } - - }); - - it('should NOT allow a NON owner to mint copies', async function () { - try { - await alice.functionCall({ - contractId, - methodName: 'nft_mint_type', - args: { - token_type, - receiver_id: contractId - }, - gas, - attachedDeposit: parseNearAmount('0.1') - }) - assert(false) - } catch(e) { - assert(true) - } - }); - - it('should allow the owner to mint a token of a particular type', async function () { - - // const stateBefore = await (await getAccount(contractId)).state(); - // console.log('stateBefore', stateBefore) - - await contractAccount.functionCall({ - contractId, - methodName: 'nft_mint_type', - args: { - token_type, - receiver_id: contractId - }, - gas, - attachedDeposit: parseNearAmount('0.1') - }) - - // const stateAfter = await (await getAccount(contractId)).state(); - // console.log('stateAfter', stateAfter) - - const supply_for_type = await contractAccount.viewFunction( - contractId, - 'nft_supply_for_type', - { - token_type - } - ) - assert.strictEqual(parseInt(supply_for_type, 10), 1); - - const tokens = await contractAccount.viewFunction( - contractId, - 'nft_tokens_by_type', - { - token_type - } - ) - const [TOKEN_DELIMETER, TITLE_DELIMETER, EDITION_DELIMETER] = await contractAccount.viewFunction( - contractId, - 'nft_get_type_format', - ) - const { token_id, owner_id, metadata: { title, copies } } = tokens[0] - - assert.strictEqual(token_id, token_type + ':1'); - assert.strictEqual(title, token_type); - assert.strictEqual(owner_id, contractId); - }); - - it('should allow anyone to buy', async function() { - await alice.functionCall({ - contractId, - methodName: 'nft_buy', - args: { - token_type: token_type, - receiver_id: aliceId - }, - gas, - attachedDeposit: parseNearAmount('1') - }); - - const tokens = await contractAccount.viewFunction( - contractId, - 'nft_tokens_by_type', - { - token_type - } - ) - - const { token_id, owner_id, metadata: { title, copies } } = tokens[1] - - const token_type_balance = await contractAccount.viewFunction( - contractId, - 'nft_type_balance', - { - account_id: aliceId, - token_type: token_type - } - ); - - assert.strictEqual(token_id, token_type + ":2"); - assert.strictEqual(token_type_balance, "1"); - }); - - it('should NOT allow mint after set mintable to false', async function () { - await contractAccount.functionCall({ - contractId, - methodName: 'nft_set_type_mintable', - args: { - token_type: token_type, - is_mintable: false - }, - gas, - attachedDeposit: "1" - }); - - try { - await contractAccount.functionCall({ - contractId, - methodName: 'nft_mint_type', - args: { - token_type, - receiver_id: contractId - }, - gas, - attachedDeposit: parseNearAmount('0.1') - }) - assert(false) - } catch(e) { - assert(true) - } - }); - - it('should NOT allow the owner to mint more than copies', async function () { - try { - await contractAccount.functionCall({ - contractId, - methodName: 'nft_mint_type', - args: { - token_type, - receiver_id: contractId - }, - gas, - attachedDeposit: parseNearAmount('0.1') - }) - assert(false) - } catch(e) { - assert(true) - } - }); -}) diff --git a/test/config.js b/test/config.js deleted file mode 100644 index 1486386..0000000 --- a/test/config.js +++ /dev/null @@ -1,53 +0,0 @@ -const contractName = 'dev-1628270601500-66808722179016'; - -module.exports = function getConfig(network = 'mainnet') { - let config = { - networkId: "testnet", - nodeUrl: "https://rpc.testnet.near.org", - walletUrl: "https://wallet.testnet.near.org", - helperUrl: "https://helper.testnet.near.org", - contractName, - }; - - switch (network) { - case 'testnet': - config = { - explorerUrl: "https://explorer.testnet.near.org", - ...config, - GAS: "200000000000000", - gas: "200000000000000", - DEFAULT_NEW_ACCOUNT_AMOUNT: "5", - DEFAULT_NEW_CONTRACT_AMOUNT: "5", - GUESTS_ACCOUNT_SECRET: - "7UVfzoKZL4WZGF98C3Ue7tmmA6QamHCiB1Wd5pkxVPAc7j6jf3HXz5Y9cR93Y68BfGDtMLQ9Q29Njw5ZtzGhPxv", - - contractMethods: { - changeMethods: [ - "new", - ], - viewMethods: [], - }, - - contractId: contractName, - marketId: "market." + contractName, - fungibleId: "ft.hhft.testnet", - }; - break; - case 'mainnet': - config = { - ...config, - networkId: "mainnet", - nodeUrl: "https://rpc.mainnet.near.org", - walletUrl: "https://wallet.near.org", - helperUrl: "https://helper.mainnet.near.org", - contractName: "uhhmnft.near", - contractId: "uhhmnft.near", - marketId: "market.uhhmnft.near", - fungibleId: "ft.hip-hop.near", - ownerId: 'owner.uhhmnft.near', - }; - break; - } - - return config; -}; diff --git a/test/near-utils.js b/test/near-utils.js deleted file mode 100644 index f86b723..0000000 --- a/test/near-utils.js +++ /dev/null @@ -1,64 +0,0 @@ -const fs = require("fs"); -const nearAPI = require("near-api-js"); -const getConfig = require("./config"); -const { nodeUrl, networkId, contractName, contractMethods } = getConfig('testnet'); - -const { - keyStores: { InMemoryKeyStore }, - Near, - Account, - Contract, - KeyPair, - utils: { - format: { parseNearAmount }, - }, -} = nearAPI; - -let credentials; -try { - credentials = JSON.parse( - fs.readFileSync( - `${process.env.HOME}/.near-credentials/${networkId}/${contractName}.json` - ) - ); -} catch(e) { - console.warn('credentials not found, looking in /neardev'); - credentials = JSON.parse( - fs.readFileSync( - `./neardev/${networkId}/${contractName}.json` - ) - ); -} - -const keyStore = new InMemoryKeyStore(); -keyStore.setKey( - networkId, - contractName, - KeyPair.fromString(credentials.private_key) -); -const near = new Near({ - networkId, - nodeUrl, - deps: { keyStore }, -}); -const { connection } = near; -const contractAccount = new Account(connection, contractName); -contractAccount.addAccessKey = (publicKey) => - contractAccount.addKey( - publicKey, - contractName, - contractMethods, - parseNearAmount("0.1") - ); -const contract = new Contract(contractAccount, contractName, contractMethods); - -module.exports = { - near, - credentials, - keyStore, - connection, - contract, - contractName, - contractAccount, - contractMethods, -}; diff --git a/test/test-utils.js b/test/test-utils.js deleted file mode 100644 index 9699bda..0000000 --- a/test/test-utils.js +++ /dev/null @@ -1,185 +0,0 @@ -const fs = require("fs"); -const BN = require('bn.js'); -const fetch = require('node-fetch'); -const nearAPI = require('near-api-js'); -const { KeyPair, Account, Contract, utils: { format: { parseNearAmount } } } = nearAPI; -const { near, credentials, connection, keyStore, contract, contractAccount } = require('./near-utils'); -const getConfig = require('./config'); -const { - networkId, contractName, contractMethods, gas, - DEFAULT_NEW_ACCOUNT_AMOUNT, - DEFAULT_NEW_CONTRACT_AMOUNT, -} = getConfig('testnet'); - -const TEST_HOST = 'http://localhost:3000'; -/// exports -async function initContract() { - /// try to call new on contract, swallow e if already initialized - try { - const newArgs = { - owner_id: contractAccount.accountId, - "metadata": { - "spec": "nft-1", - "name": "UHHM NFT - Hip Hop Heads", - "symbol": "HHH" - }, - supply_cap_by_type: { - test: '1000000', - }, - }; - await contract.new(newArgs); - } catch (e) { - if (!/initialized/.test(e.toString())) { - throw e; - } - } - return { contract, contractName }; -} -const getAccountBalance = async (accountId) => (new nearAPI.Account(connection, accountId)).getAccountBalance(); - -const initAccount = async(accountId, secret) => { - account = new nearAPI.Account(connection, accountId); - const newKeyPair = KeyPair.fromString(secret); - keyStore.setKey(networkId, accountId, newKeyPair); - return account -} - -const createOrInitAccount = async(accountId, secret, amount = DEFAULT_NEW_CONTRACT_AMOUNT) => { - let account; - try { - account = await createAccount(accountId, amount, secret); - } catch (e) { - if (!/because it already exists/.test(e.toString())) { - throw e; - } - account = initAccount(accountId, secret) - } - return account; -}; - -async function getAccount(accountId, fundingAmount = DEFAULT_NEW_ACCOUNT_AMOUNT, secret) { - accountId = accountId || generateUniqueSubAccount(); - const account = new nearAPI.Account(connection, accountId); - try { - await account.state(); - return account; - } catch(e) { - if (!/does not exist/.test(e.toString())) { - throw e; - } - } - return await createAccount(accountId, fundingAmount, secret); -}; - - -async function getContract(account) { - return new Contract(account || contractAccount, contractName, { - ...contractMethods, - signer: account || undefined - }); -} - - -const createAccessKeyAccount = (key) => { - connection.signer.keyStore.setKey(networkId, contractName, key); - return new Account(connection, contractName); -}; - -const postSignedJson = async ({ account, contractName, url, data = {} }) => { - return await fetch(url, { - method: 'POST', - headers: { 'content-type': 'application/json' }, - body: JSON.stringify({ - ...data, - accountId: account.accountId, - contractName, - ...(await getSignature(account)) - }) - }).then((res) => { - // console.log(res) - return res.json(); - }); -}; - -const postJson = async ({ url, data = {} }) => { - return await fetch(url, { - method: 'POST', - headers: { 'content-type': 'application/json' }, - body: JSON.stringify({ ...data }) - }).then((res) => { - console.log(res); - return res.json(); - }); -}; - -function generateUniqueSubAccount() { - return `t${Date.now()}.${contractName}`; -} - -/// internal -async function createAccount(accountId, fundingAmount = DEFAULT_NEW_ACCOUNT_AMOUNT, secret) { - const contractAccount = new Account(connection, contractName); - const newKeyPair = secret ? KeyPair.fromString(secret) : KeyPair.fromRandom('ed25519'); - await contractAccount.createAccount(accountId, newKeyPair.publicKey, new BN(parseNearAmount(fundingAmount))); - keyStore.setKey(networkId, accountId, newKeyPair); - return new nearAPI.Account(connection, accountId); -} - -const getSignature = async (account) => { - const { accountId } = account; - const block = await account.connection.provider.block({ finality: 'final' }); - const blockNumber = block.header.height.toString(); - const signer = account.inMemorySigner || account.connection.signer; - const signed = await signer.signMessage(Buffer.from(blockNumber), accountId, networkId); - const blockNumberSignature = Buffer.from(signed.signature).toString('base64'); - return { blockNumber, blockNumberSignature }; -}; - -const loadCredentials = (accountId) => { - const credPath = `./neardev/${networkId}/${accountId}.json`; - console.log( - "Loading Credentials:\n", - credPath - ); - - let credentials; - try { - credentials = JSON.parse( - fs.readFileSync( - credPath - ) - ); - } catch(e) { - console.warn('credentials not in /neardev'); - /// attempt to load backup creds from local machine - credentials = JSON.parse( - fs.readFileSync( - `${process.env.HOME}/.near-credentials/${networkId}/${accountId}.json` - ) - ); - } - - return credentials -} - -module.exports = { - TEST_HOST, - near, - gas, - connection, - credentials, - keyStore, - getContract, - getAccountBalance, - contract, - contractName, - contractId: contractName, - contractMethods, - contractAccount, - initAccount, - createOrInitAccount, - createAccessKeyAccount, - initContract, getAccount, postSignedJson, postJson, - loadCredentials, -}; - diff --git a/tests/simulation_tests.rs b/tests/simulation_tests.rs new file mode 100644 index 0000000..388becd --- /dev/null +++ b/tests/simulation_tests.rs @@ -0,0 +1,205 @@ +use paras_nft_contract::ContractContract as Contract; +use near_sdk_sim::{ + call, deploy, init_simulator, to_yocto, ContractAccount, UserAccount, DEFAULT_GAS, STORAGE_AMOUNT, +}; +use near_sdk::serde_json::json; +use std::collections::HashMap; + + +pub const NFT_CONTRACT_ID: &str = "nft"; + +near_sdk_sim::lazy_static_include::lazy_static_include_bytes! { + NFT_WASM_BYTES => "out/main.wasm", +} + +// Added after running simulation test +pub const STORAGE_MINT_ESTIMATE: u128 = 11280000000000000000000; +pub const STORAGE_CREATE_SERIES_ESTIMATE: u128 = 8540000000000000000000; +pub const STORAGE_APPROVE: u128 = 2610000000000000000000; + +pub fn init() -> (UserAccount, ContractAccount) { + let root = init_simulator(None); + + let nft_contract = deploy!( + contract: Contract, + contract_id: NFT_CONTRACT_ID, + bytes: &NFT_WASM_BYTES, + signer_account: root, + init_method: new_default_meta( + root.valid_account_id() + ) + ); + + root.create_user( + "test".repeat(16), + to_yocto("100"), + ); + + (root, nft_contract) +} + +#[test] +fn simulate_create_new_series() { + let (root, nft) = init(); + + let initial_storage_usage = nft.account().unwrap().storage_usage; + + let outcome = root.call( + nft.account_id(), + "nft_create_series", + &json!({ + "token_series_id": u128::MAX.to_string(), + "token_metadata": { + "title": "A".repeat(200), + "reference": "A".repeat(59), + "media": "A".repeat(59), + "copies": 100u64, + }, + "creator_id": "0".repeat(64), + "price": to_yocto("1").to_string(), + "royalty": { + "0".repeat(64): 1000u32 + }, + }).to_string().into_bytes(), + DEFAULT_GAS, + to_yocto("2") + ); + + let storage_price_for_adding_series = (nft.account().unwrap().storage_usage - initial_storage_usage) as u128 * 10u128.pow(19); + println!("[CREATE SERIES] Storage price: {} yoctoNEAR", storage_price_for_adding_series); + println!("[CREATE SERIES] Gas burnt price: {} TeraGas", outcome.gas_burnt() as f64 / 1e12); +} + +#[test] +fn simulate_mint() { + let (root, nft) = init(); + + root.call( + nft.account_id(), + "nft_create_series", + &json!({ + "token_series_id": u128::MAX.to_string(), + "token_metadata": { + "title": "A".repeat(200), + "reference": "A".repeat(59), + "media": "A".repeat(59), + "copies": 100u64, + }, + "creator_id": "0".repeat(64), + "price": to_yocto("1").to_string(), + "royalty": { + "0".repeat(64): 1000u32 + }, + }).to_string().into_bytes(), + DEFAULT_GAS, + to_yocto("1") + ); + + let initial_storage_usage = nft.account().unwrap().storage_usage; + + let outcome = root.call( + nft.account_id(), + "nft_buy", + &json!({ + "token_series_id": u128::MAX.to_string(), + "receiver_id": "a".repeat(64), + }).to_string().into_bytes(), + DEFAULT_GAS, + to_yocto("2") + ); + + let storage_price_for_mint = (nft.account().unwrap().storage_usage - initial_storage_usage) as u128 * 10u128.pow(19); + println!("[MINT] Storage price: {} yoctoNEAR", storage_price_for_mint); + println!("[MINT] Gas burnt price: {} TeraGas", outcome.gas_burnt() as f64 / 1e12); + + let initial_storage_usage = nft.account().unwrap().storage_usage; + + let outcome = root.call( + nft.account_id(), + "nft_buy", + &json!({ + "token_series_id": u128::MAX.to_string(), + "receiver_id": "b".repeat(64), + }).to_string().into_bytes(), + DEFAULT_GAS, + to_yocto("2") + ); + + let storage_price_for_mint = (nft.account().unwrap().storage_usage - initial_storage_usage) as u128 * 10u128.pow(19); + println!("[MINT 2nd] Storage price: {} yoctoNEAR", storage_price_for_mint); + println!("[MINT 2nd] Gas burnt price: {} TeraGas", outcome.gas_burnt() as f64 / 1e12); + + let initial_storage_usage = nft.account().unwrap().storage_usage; + + let outcome = root.call( + nft.account_id(), + "nft_buy", + &json!({ + "token_series_id": u128::MAX.to_string(), + "receiver_id": "c".repeat(64), + }).to_string().into_bytes(), + DEFAULT_GAS, + to_yocto("2") + ); + + let storage_price_for_mint = (nft.account().unwrap().storage_usage - initial_storage_usage) as u128 * 10u128.pow(19); + println!("[MINT 3nd] Storage price: {} yoctoNEAR", storage_price_for_mint); + println!("[MINT 3nd] Gas burnt price: {} TeraGas", outcome.gas_burnt() as f64 / 1e12); + +} + +#[test] +fn simulate_approve() { + let (root, nft) = init(); + + root.call( + nft.account_id(), + "nft_create_series", + &json!({ + "token_series_id": u128::MAX.to_string(), + "token_metadata": { + "title": "A".repeat(200), + "reference": "A".repeat(59), + "media": "A".repeat(59), + "copies": 100u64, + }, + "creator_id": "0".repeat(64), + "price": to_yocto("1").to_string(), + "royalty": { + "0".repeat(64): 1000u32 + }, + }).to_string().into_bytes(), + DEFAULT_GAS, + to_yocto("1") + ); + + root.call( + nft.account_id(), + "nft_buy", + &json!({ + "token_series_id": u128::MAX.to_string(), + "receiver_id": root.account_id(), + }).to_string().into_bytes(), + DEFAULT_GAS, + to_yocto("2") + ); + + + let initial_storage_usage = nft.account().unwrap().storage_usage; + + let outcome = root.call( + nft.account_id(), + "nft_approve", + &json!({ + "token_id": format!("{}:{}", u128::MAX.to_string(), "1"), + "account_id": "test".repeat(16), + "msg": "{\"price\":\"3000000000000000000000000\",\"ft_token_id\":\"near\"}", + }).to_string().into_bytes(), + DEFAULT_GAS, + to_yocto("2") + ); + + let storage_price_for_approve = (nft.account().unwrap().storage_usage - initial_storage_usage) as u128 * 10u128.pow(19); + println!("[APPROVE] Storage price: {} yoctoNEAR", storage_price_for_approve); + println!("[APPROVE] Gas burnt price: {} TeraGas", outcome.gas_burnt() as f64 / 1e12); +} \ No newline at end of file diff --git a/utils/patch-config.js b/utils/patch-config.js deleted file mode 100644 index 3b24ac1..0000000 --- a/utils/patch-config.js +++ /dev/null @@ -1,14 +0,0 @@ -const fs = require('fs'); -const contractName = fs.readFileSync('./neardev/dev-account').toString() -const path = './test/config.js' - -fs.readFile(path, 'utf-8', function(err, data) { - if (err) throw err; - - data = data.replace(/.*const contractName.*/gim, `const contractName = '${contractName}';`); - - fs.writeFile(path, data, 'utf-8', function(err) { - if (err) throw err; - console.log('Done!'); - }) -})