diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..a2f3d05 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,45 @@ +name: ci + +on: ["push", "pull_request", "workflow_dispatch"] + +env: + VERSION: mainnet-v1.3.0 + +jobs: + test_and_demo: + runs-on: ubuntu-latest + strategy: + matrix: + node-version: [19.x] + steps: + - uses: actions/checkout@v3 + - name: Cache Binaries and move deps + id: cache + uses: actions/cache@v3 + with: + path: | + ~/.move + ~/bin + **/node_modules + key: ${{ runner.os }}-cache-${{ env.VERSION }} + restore-keys: | + ${{ runner.os }}-cache- + - run: echo "${HOME}/bin" >> $GITHUB_PATH + - name: install sui bin + run: | + mkdir -p ~/bin + wget https://github.com/MystenLabs/sui/releases/download/${{ env.VERSION }}/sui -O ~/bin/sui + chmod +x ~/bin/sui + if: steps.cache.outputs.cache-hit != 'true' + - name: Install Task + uses: arduino/setup-task@v1 + - run: task build + - name: Use Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v3 + with: + node-version: ${{ matrix.node-version }} + - uses: pnpm/action-setup@v2.2.4 + with: + version: 8.6.2 + - run: pnpm install + - run: pnpm demo diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2882684 --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +sui.log.* +.env +build +output.bpl +.coverage_* +.trace +boilerplate +.task/ +node_modules/ +.idea/ diff --git a/.prettierrc.js b/.prettierrc.js new file mode 100644 index 0000000..db61662 --- /dev/null +++ b/.prettierrc.js @@ -0,0 +1,6 @@ +module.exports = { + printWidth: 120, + semi: true, + singleQuote: true, + trailingComma: 'all', +}; diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 0000000..7c06599 --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2023 Mynft + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/Move.lock b/Move.lock new file mode 100644 index 0000000..db12d63 --- /dev/null +++ b/Move.lock @@ -0,0 +1,20 @@ +# @generated by Move, please check-in and do not edit manually. + +[move] +version = 0 + +dependencies = [ + { name = "Sui" }, +] + +[[move.package]] +name = "MoveStdlib" +source = { git = "https://github.com/MystenLabs/sui.git", rev = "mainnet-v1.3.0", subdir = "crates/sui-framework/packages/move-stdlib" } + +[[move.package]] +name = "Sui" +source = { git = "https://github.com/MystenLabs/sui.git", rev = "mainnet-v1.3.0", subdir = "crates/sui-framework/packages/sui-framework" } + +dependencies = [ + { name = "MoveStdlib" }, +] diff --git a/Move.toml b/Move.toml new file mode 100644 index 0000000..e46e6c9 --- /dev/null +++ b/Move.toml @@ -0,0 +1,10 @@ +[package] +name = "Suibox" +version = "0.1.0" + +[dependencies] +Sui = { git = "https://github.com/MystenLabs/sui.git", subdir = "crates/sui-framework/packages/sui-framework", rev = "mainnet-v1.3.0" } + +[addresses] +suibox = "0x0" +sui = "0x2" diff --git a/README.md b/README.md new file mode 100644 index 0000000..29976ca --- /dev/null +++ b/README.md @@ -0,0 +1,9 @@ +# Suibox + +## Quick Start + +Install package: `npm install @suia/suibox` + +```typescript + +``` diff --git a/Taskfile.yml b/Taskfile.yml new file mode 100644 index 0000000..fa11dad --- /dev/null +++ b/Taskfile.yml @@ -0,0 +1,24 @@ +# https://taskfile.dev + +version: "3" + +tasks: + build: + cmds: + - sui move build + - echo "build done" + sources: + - sources/**/*.move + - Move.toml + test: + cmds: + - sui move test + sources: + - sources/**/*.move + - Move.toml + demo: + cmds: + - pnpm ts-node examples/suibox.ts + sources: + - src/**/*.ts + - examples/**/*.ts diff --git a/examples/suibox.ts b/examples/suibox.ts new file mode 100644 index 0000000..36c259f --- /dev/null +++ b/examples/suibox.ts @@ -0,0 +1,60 @@ +import { SuiboxContract } from '../src/suibox'; +import { devnetConnection, Ed25519Keypair, JsonRpcProvider, RawSigner } from '@mysten/sui.js'; + +async function main(): Promise { + console.log('Hello from Suibox'); + + // init connection and signer + const connection = devnetConnection; + const provider = new JsonRpcProvider(connection); + const keypairseed = process.env.KEY_PAIR_SEED; + const keypair = Ed25519Keypair.fromSecretKey(Uint8Array.from(Buffer.from(keypairseed!, 'hex'))); + const signer = new RawSigner(keypair, provider); + + const addr = await signer.getAddress(); + console.log('addr: ', addr); + await provider.requestSuiFromFaucet(addr); + + // wait for the faucet to send the sui + await new Promise((resolve) => setTimeout(resolve, 3000)); + + // publish a new suibox contract + const suiboxContract = await SuiboxContract.publish(signer); + // you can also specify an existing suibox contract with the function below + // const suiboxContract = new Contract(packageId, signer); + + // list all suiboxes + let suiboxes = await suiboxContract.listSuiboxes(); + console.log('suiboxes: ', suiboxes); + const suibox = await suiboxContract.createSuibox({ + name: 'suibox name', + description: 'suibox description', + image_url: 'suibox image url', + layout: '9-box grid', + }); + suiboxes = await suiboxContract.listSuiboxes(); + console.log('suiboxes: ', suiboxes); + + // create a new suibox as a nft and add it to the suibox created above + const nft = await suiboxContract.createSuibox({ + name: 'nft', + description: 'nft', + image_url: 'nft', + layout: 'nft', + }); + await new Promise((resolve) => setTimeout(resolve, 3000)); + await suibox.add({ objectId: nft.objectId }, 0); + const nftsAfterAddNFT = await suibox.listNFTs(); + console.log('nftsAfterAddNFT: ', nftsAfterAddNFT); + + // extract the nft from the suibox + await suibox.extract(`${await nft.getPackageId()}::suibox::Suibox`, 0); + const nftsAfterExtractNFT = await suibox.listNFTs(); + console.log('nftsAfterExtractNFT: ', nftsAfterExtractNFT); + console.log('----------- suibox example end -----------'); +} + +main().catch((error) => { + console.error(error); + process.exit(1); +}); diff --git a/package.json b/package.json new file mode 100644 index 0000000..a2dcff3 --- /dev/null +++ b/package.json @@ -0,0 +1,20 @@ +{ + "name": "suibox", + "version": "0.1.0", + "main": "index.js", + "license": "MIT", + "scripts": { + "demo": "ts-node examples/suibox.ts", + "fix:prettier": "prettier --write src examples" + }, + "dependencies": { + "@mysten/sui.js": "^0.36.0" + }, + "devDependencies": { + "dotenv": "^16.0.2", + "@types/node": "^20.3.1", + "ts-node": "^10.9.1", + "typescript": "^4.8.3", + "prettier": "^2.8.8" + } +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml new file mode 100644 index 0000000..7989427 --- /dev/null +++ b/pnpm-lock.yaml @@ -0,0 +1,323 @@ +lockfileVersion: '6.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +dependencies: + '@mysten/sui.js': + specifier: ^0.36.0 + version: 0.36.0 + +devDependencies: + '@types/node': + specifier: ^20.3.1 + version: 20.3.1 + dotenv: + specifier: ^16.0.2 + version: 16.0.2 + prettier: + specifier: ^2.8.8 + version: 2.8.8 + ts-node: + specifier: ^10.9.1 + version: 10.9.1(@types/node@20.3.1)(typescript@4.8.3) + typescript: + specifier: ^4.8.3 + version: 4.8.3 + +packages: + + /@cspotcode/source-map-support@0.8.1: + resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} + engines: {node: '>=12'} + dependencies: + '@jridgewell/trace-mapping': 0.3.9 + dev: true + + /@jridgewell/resolve-uri@3.1.1: + resolution: {integrity: sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==} + engines: {node: '>=6.0.0'} + dev: true + + /@jridgewell/sourcemap-codec@1.4.15: + resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==} + dev: true + + /@jridgewell/trace-mapping@0.3.9: + resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} + dependencies: + '@jridgewell/resolve-uri': 3.1.1 + '@jridgewell/sourcemap-codec': 1.4.15 + dev: true + + /@mysten/bcs@0.7.2: + resolution: {integrity: sha512-M8aUGFwoBEj9XPCJcYuVlv8UbqBINAYhrDGLavdCYZwGlN5saGgrBcnGpXk+D2/Vp+aEUFh3RCyKudn7H0G9hQ==} + dependencies: + bs58: 5.0.0 + dev: false + + /@mysten/sui.js@0.36.0: + resolution: {integrity: sha512-l/gZUxlr0oHgnwuHYxIVp+JOrdj1imhffL5iK25JYh3WV4sTxiQntCLuSen6etXyFG9c1l2GNvVaGZaV3mb4Hw==} + engines: {node: '>=16'} + dependencies: + '@mysten/bcs': 0.7.2 + '@noble/curves': 1.1.0 + '@noble/hashes': 1.3.1 + '@open-rpc/client-js': 1.8.1 + '@scure/bip32': 1.3.0 + '@scure/bip39': 1.2.0 + '@suchipi/femver': 1.0.0 + superstruct: 1.0.3 + tweetnacl: 1.0.3 + transitivePeerDependencies: + - bufferutil + - encoding + - utf-8-validate + dev: false + + /@noble/curves@1.0.0: + resolution: {integrity: sha512-2upgEu0iLiDVDZkNLeFV2+ht0BAVgQnEmCk6JsOch9Rp8xfkMCbvbAZlA2pBHQc73dbl+vFOXfqkf4uemdn0bw==} + dependencies: + '@noble/hashes': 1.3.0 + dev: false + + /@noble/curves@1.1.0: + resolution: {integrity: sha512-091oBExgENk/kGj3AZmtBDMpxQPDtxQABR2B9lb1JbVTs6ytdzZNwvhxQ4MWasRNEzlbEH8jCWFCwhF/Obj5AA==} + dependencies: + '@noble/hashes': 1.3.1 + dev: false + + /@noble/hashes@1.3.0: + resolution: {integrity: sha512-ilHEACi9DwqJB0pw7kv+Apvh50jiiSyR/cQ3y4W7lOR5mhvn/50FLUfsnfJz0BDZtl/RR16kXvptiv6q1msYZg==} + dev: false + + /@noble/hashes@1.3.1: + resolution: {integrity: sha512-EbqwksQwz9xDRGfDST86whPBgM65E0OH/pCgqW0GBVzO22bNE+NuIbeTb714+IfSjU3aRk47EUvXIb5bTsenKA==} + engines: {node: '>= 16'} + dev: false + + /@open-rpc/client-js@1.8.1: + resolution: {integrity: sha512-vV+Hetl688nY/oWI9IFY0iKDrWuLdYhf7OIKI6U1DcnJV7r4gAgwRJjEr1QVYszUc0gjkHoQJzqevmXMGLyA0g==} + dependencies: + isomorphic-fetch: 3.0.0 + isomorphic-ws: 5.0.0(ws@7.5.9) + strict-event-emitter-types: 2.0.0 + ws: 7.5.9 + transitivePeerDependencies: + - bufferutil + - encoding + - utf-8-validate + dev: false + + /@scure/base@1.1.1: + resolution: {integrity: sha512-ZxOhsSyxYwLJj3pLZCefNitxsj093tb2vq90mp2txoYeBqbcjDjqFhyM8eUjq/uFm6zJ+mUuqxlS2FkuSY1MTA==} + dev: false + + /@scure/bip32@1.3.0: + resolution: {integrity: sha512-bcKpo1oj54hGholplGLpqPHRbIsnbixFtc06nwuNM5/dwSXOq/AAYoIBRsBmnZJSdfeNW5rnff7NTAz3ZCqR9Q==} + dependencies: + '@noble/curves': 1.0.0 + '@noble/hashes': 1.3.1 + '@scure/base': 1.1.1 + dev: false + + /@scure/bip39@1.2.0: + resolution: {integrity: sha512-SX/uKq52cuxm4YFXWFaVByaSHJh2w3BnokVSeUJVCv6K7WulT9u2BuNRBhuFl8vAuYnzx9bEu9WgpcNYTrYieg==} + dependencies: + '@noble/hashes': 1.3.1 + '@scure/base': 1.1.1 + dev: false + + /@suchipi/femver@1.0.0: + resolution: {integrity: sha512-bprE8+K5V+DPX7q2e2K57ImqNBdfGHDIWaGI5xHxZoxbKOuQZn4wzPiUxOAHnsUr3w3xHrWXwN7gnG/iIuEMIg==} + dev: false + + /@tsconfig/node10@1.0.9: + resolution: {integrity: sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==} + dev: true + + /@tsconfig/node12@1.0.11: + resolution: {integrity: sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==} + dev: true + + /@tsconfig/node14@1.0.3: + resolution: {integrity: sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==} + dev: true + + /@tsconfig/node16@1.0.4: + resolution: {integrity: sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==} + dev: true + + /@types/node@20.3.1: + resolution: {integrity: sha512-EhcH/wvidPy1WeML3TtYFGR83UzjxeWRen9V402T8aUGYsCHOmfoisV3ZSg03gAFIbLq8TnWOJ0f4cALtnSEUg==} + dev: true + + /acorn-walk@8.2.0: + resolution: {integrity: sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==} + engines: {node: '>=0.4.0'} + dev: true + + /acorn@8.9.0: + resolution: {integrity: sha512-jaVNAFBHNLXspO543WnNNPZFRtavh3skAkITqD0/2aeMkKZTN+254PyhwxFYrk3vQ1xfY+2wbesJMs/JC8/PwQ==} + engines: {node: '>=0.4.0'} + hasBin: true + dev: true + + /arg@4.1.3: + resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==} + dev: true + + /base-x@4.0.0: + resolution: {integrity: sha512-FuwxlW4H5kh37X/oW59pwTzzTKRzfrrQwhmyspRM7swOEZcHtDZSCt45U6oKgtuFE+WYPblePMVIPR4RZrh/hw==} + dev: false + + /bs58@5.0.0: + resolution: {integrity: sha512-r+ihvQJvahgYT50JD05dyJNKlmmSlMoOGwn1lCcEzanPglg7TxYjioQUYehQ9mAR/+hOSd2jRc/Z2y5UxBymvQ==} + dependencies: + base-x: 4.0.0 + dev: false + + /create-require@1.1.1: + resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==} + dev: true + + /diff@4.0.2: + resolution: {integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==} + engines: {node: '>=0.3.1'} + dev: true + + /dotenv@16.0.2: + resolution: {integrity: sha512-JvpYKUmzQhYoIFgK2MOnF3bciIZoItIIoryihy0rIA+H4Jy0FmgyKYAHCTN98P5ybGSJcIFbh6QKeJdtZd1qhA==} + engines: {node: '>=12'} + dev: true + + /isomorphic-fetch@3.0.0: + resolution: {integrity: sha512-qvUtwJ3j6qwsF3jLxkZ72qCgjMysPzDfeV240JHiGZsANBYd+EEuu35v7dfrJ9Up0Ak07D7GGSkGhCHTqg/5wA==} + dependencies: + node-fetch: 2.6.11 + whatwg-fetch: 3.6.2 + transitivePeerDependencies: + - encoding + dev: false + + /isomorphic-ws@5.0.0(ws@7.5.9): + resolution: {integrity: sha512-muId7Zzn9ywDsyXgTIafTry2sV3nySZeUDe6YedVd1Hvuuep5AsIlqK+XefWpYTyJG5e503F2xIuT2lcU6rCSw==} + peerDependencies: + ws: '*' + dependencies: + ws: 7.5.9 + dev: false + + /make-error@1.3.6: + resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==} + dev: true + + /node-fetch@2.6.11: + resolution: {integrity: sha512-4I6pdBY1EthSqDmJkiNk3JIT8cswwR9nfeW/cPdUagJYEQG7R95WRH74wpz7ma8Gh/9dI9FP+OU+0E4FvtA55w==} + engines: {node: 4.x || >=6.0.0} + peerDependencies: + encoding: ^0.1.0 + peerDependenciesMeta: + encoding: + optional: true + dependencies: + whatwg-url: 5.0.0 + dev: false + + /prettier@2.8.8: + resolution: {integrity: sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==} + engines: {node: '>=10.13.0'} + hasBin: true + dev: true + + /strict-event-emitter-types@2.0.0: + resolution: {integrity: sha512-Nk/brWYpD85WlOgzw5h173aci0Teyv8YdIAEtV+N88nDB0dLlazZyJMIsN6eo1/AR61l+p6CJTG1JIyFaoNEEA==} + dev: false + + /superstruct@1.0.3: + resolution: {integrity: sha512-8iTn3oSS8nRGn+C2pgXSKPI3jmpm6FExNazNpjvqS6ZUJQCej3PUXEKM8NjHBOs54ExM+LPW/FBRhymrdcCiSg==} + engines: {node: '>=14.0.0'} + dev: false + + /tr46@0.0.3: + resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} + dev: false + + /ts-node@10.9.1(@types/node@20.3.1)(typescript@4.8.3): + resolution: {integrity: sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==} + hasBin: true + peerDependencies: + '@swc/core': '>=1.2.50' + '@swc/wasm': '>=1.2.50' + '@types/node': '*' + typescript: '>=2.7' + peerDependenciesMeta: + '@swc/core': + optional: true + '@swc/wasm': + optional: true + dependencies: + '@cspotcode/source-map-support': 0.8.1 + '@tsconfig/node10': 1.0.9 + '@tsconfig/node12': 1.0.11 + '@tsconfig/node14': 1.0.3 + '@tsconfig/node16': 1.0.4 + '@types/node': 20.3.1 + acorn: 8.9.0 + acorn-walk: 8.2.0 + arg: 4.1.3 + create-require: 1.1.1 + diff: 4.0.2 + make-error: 1.3.6 + typescript: 4.8.3 + v8-compile-cache-lib: 3.0.1 + yn: 3.1.1 + dev: true + + /tweetnacl@1.0.3: + resolution: {integrity: sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==} + dev: false + + /typescript@4.8.3: + resolution: {integrity: sha512-goMHfm00nWPa8UvR/CPSvykqf6dVV8x/dp0c5mFTMTIu0u0FlGWRioyy7Nn0PGAdHxpJZnuO/ut+PpQ8UiHAig==} + engines: {node: '>=4.2.0'} + hasBin: true + dev: true + + /v8-compile-cache-lib@3.0.1: + resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==} + dev: true + + /webidl-conversions@3.0.1: + resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} + dev: false + + /whatwg-fetch@3.6.2: + resolution: {integrity: sha512-bJlen0FcuU/0EMLrdbJ7zOnW6ITZLrZMIarMUVmdKtsGvZna8vxKYaexICWPfZ8qwf9fzNq+UEIZrnSaApt6RA==} + dev: false + + /whatwg-url@5.0.0: + resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} + dependencies: + tr46: 0.0.3 + webidl-conversions: 3.0.1 + dev: false + + /ws@7.5.9: + resolution: {integrity: sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==} + engines: {node: '>=8.3.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: ^5.0.2 + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + dev: false + + /yn@3.1.1: + resolution: {integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==} + engines: {node: '>=6'} + dev: true diff --git a/sources/suibox.move b/sources/suibox.move new file mode 100644 index 0000000..c477c68 --- /dev/null +++ b/sources/suibox.move @@ -0,0 +1,176 @@ +module suibox::suibox { + use sui::bag::{Self, Bag}; + use sui::object::{Self, UID}; + use std::string::{String, utf8}; + use sui::tx_context::{Self, TxContext, sender}; + use sui::transfer; + use sui::package; + use sui::display; + #[test_only] + use sui::test_scenario; + + // errors + const ENFT_EXISTS_AT_THIS_POSITION: u64 = 1; + const ENFT_NOT_EXISTS_AT_THIS_POSITION: u64 = 2; + + struct Suibox has key, store { + id: UID, + name: String, + description: String, + image_url: String, + layout: String, + creator: address, + nfts: Bag, + } + + struct SUIBOX has drop {} + + fun init(otw: SUIBOX, ctx: &mut TxContext) { + let keys = vector[ + utf8(b"name"), + utf8(b"image_url"), + utf8(b"description"), + ]; + + let values = vector[ + utf8(b"{name}"), + utf8(b"{image_url}"), + utf8(b"{description}"), + ]; + + let publisher = package::claim(otw, ctx); + + let display = display::new_with_fields( + &publisher, keys, values, ctx + ); + + display::update_version(&mut display); + + transfer::public_transfer(publisher, sender(ctx)); + transfer::public_transfer(display, sender(ctx)); + } + + public entry fun create_suibox( + name: vector, + description: vector, + image_url: vector, + layout: vector, + ctx: &mut TxContext, + ) { + let suibox = Suibox { + id: object::new(ctx), + layout: utf8(layout), + name: utf8(name), + description: utf8(description), + image_url: utf8(image_url), + nfts: bag::new(ctx), + creator: sender(ctx), + }; + transfer::transfer(suibox, sender(ctx)); + } + + public entry fun add_nft_to_suibox( + suibox: &mut Suibox, + nft: NFT, + position: u64, + _ctx: &mut TxContext, + ) { + if (bag::contains(&suibox.nfts, position)) { + abort ENFT_EXISTS_AT_THIS_POSITION + }; + bag::add(&mut suibox.nfts, position, nft); + } + + public entry fun extract_from_suibox( + suibox: &mut Suibox, + position: u64, + ctx: &mut TxContext, + ) { + assert!(bag::contains(&suibox.nfts, position), ENFT_NOT_EXISTS_AT_THIS_POSITION); + let nft: NFT = bag::remove(&mut suibox.nfts, position); + transfer::public_transfer(nft, tx_context::sender(ctx)) + } + + #[test_only] + struct TestNFT1 has key, store { + id: UID, + } + + #[test_only] + struct TestNFT2 has key, store { + id: UID, + } + + #[test_only] + fun create_test_nft( + ctx: &mut TxContext, + ) { + let test_nft1 = TestNFT1 { + id: object::new(ctx), + }; + let test_nft2 = TestNFT2 { + id: object::new(ctx), + }; + transfer::transfer(test_nft1, tx_context::sender(ctx)); + transfer::transfer(test_nft2, tx_context::sender(ctx)); + } + + #[test] + fun test_suibox() { + let user = @0xBABE; + + let scenario_val = test_scenario::begin(user); + let scenario = &mut scenario_val; + + // create suibox + test_scenario::next_tx(scenario, user); + let suibox_name = b"my sui space"; + let suibox_desc = b"my sui space desc"; + let suibox_url = b"my sui space url"; + let layout = b"9-box grid"; + create_suibox( + suibox_name, + suibox_desc, + suibox_url, + layout, + test_scenario::ctx(scenario), + ); + test_scenario::next_tx(scenario, user); + let suibox = test_scenario::take_from_address(scenario, user); + assert!(suibox.name == utf8(suibox_name), 0); + assert!(suibox.layout == utf8(layout), 0); + + // add nft to suibox + test_scenario::next_tx(scenario, user); + create_test_nft(test_scenario::ctx(scenario)); + test_scenario::next_tx(scenario, user); + let test_nft1 = test_scenario::take_from_address(scenario, user); + let test_nft1_id = object::id(&test_nft1); + let test_nft2 = test_scenario::take_from_address(scenario, user); + let position = 8; + add_nft_to_suibox( + &mut suibox, + test_nft1, + position, + test_scenario::ctx(scenario), + ); + + // extract nft from suibox + test_scenario::next_tx(scenario, user); + extract_from_suibox( + &mut suibox, + position, + test_scenario::ctx(scenario), + ); + test_scenario::next_tx(scenario, user); + let test_nft1_back = test_scenario::take_from_address(scenario, user); + let test_nft1_back_id = object::id(&test_nft1_back); + assert!(test_nft1_id == test_nft1_back_id, 0); + + // clean test + test_scenario::return_to_sender(scenario, suibox); + test_scenario::return_to_sender(scenario, test_nft1_back); + test_scenario::return_to_sender(scenario, test_nft2); + test_scenario::end(scenario_val); + } +} diff --git a/src/contract_assets.json b/src/contract_assets.json new file mode 100644 index 0000000..ed6fdeb --- /dev/null +++ b/src/contract_assets.json @@ -0,0 +1,13 @@ +{ + "modules": [ + "oRzrCwYAAAALAQAQAhAiAzJcBI4BFAWiAawBB84CxgIIlAVgBvQFYgrWBhwM8gb2AQ3oCAIAIQEgAgoCEAIbAhwCIgIjAAUMAAADAgABBAcAAgAMAAMBDAEIAQQHBAAFAgwABwYCAAAVAAEAAA0CAQAACQMBAQwAEgQBAQwBJQYHAAIIGwECBwQCDBgZAQcCGBQWAAIeHB0CBwQDGQwNAQgDJA4BAQgEGBQVAAULCQoBAgYdEQEBDAYiEQEBCAcfDxAADAgJCwoLDQoNEg4LBhcFGggaDR4CCAEHCAcABQoCCgIKAgoCBwgHBAcIAAkAAwcIBwMHCAADBwgHBAsEAQgACggCCAYKCAIBCgIBCAIBCAECCQAHCAcBCAYBCAAEBggGCggCCggCBwgHAQsEAQkAAQcLBAEJAAEGCAcBBQIJAAUBCwQBCAAHCAUIAggCCAIIAggDBQEHCAcBCAUBCAMBAwIGCAMJAAEBAgMJAAMHCAMJAAkBAgcIAwkAAQkBAQkAA0JhZwdEaXNwbGF5CVB1Ymxpc2hlcgZTVUlCT1gGU3RyaW5nBlN1aWJveAlUeENvbnRleHQDVUlEA2FkZBFhZGRfbmZ0X3RvX3N1aWJveANiYWcFY2xhaW0IY29udGFpbnMNY3JlYXRlX3N1aWJveAdjcmVhdG9yC2Rlc2NyaXB0aW9uB2Rpc3BsYXkLZHVtbXlfZmllbGQTZXh0cmFjdF9mcm9tX3N1aWJveAJpZAlpbWFnZV91cmwEaW5pdAZsYXlvdXQEbmFtZQNuZXcPbmV3X3dpdGhfZmllbGRzBG5mdHMGb2JqZWN0B3BhY2thZ2UPcHVibGljX3RyYW5zZmVyBnJlbW92ZQZzZW5kZXIGc3RyaW5nBnN1aWJveAh0cmFuc2Zlcgp0eF9jb250ZXh0DnVwZGF0ZV92ZXJzaW9uBHV0ZjgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIDCAEAAAAAAAAAAwgCAAAAAAAAAAoCBQRuYW1lCgIKCWltYWdlX3VybAoCDAtkZXNjcmlwdGlvbgoCBwZ7bmFtZX0KAgwLe2ltYWdlX3VybH0KAg4Ne2Rlc2NyaXB0aW9ufQACBxMIBRcIAg8IAhQIAhYIAg4FGggDAQIBEQEAAAAABScHAhEEBwMRBAcEEQRABwMAAAAAAAAADAMHBREEBwYRBAcHEQRABwMAAAAAAAAADAULAAoBOAAMBA4ECwMLBQoBOAEMAg0COAILBAoBLhEPOAMLAgsBLhEPOAQCAQEEABMjCgQRCwwFCwMRBAwGCwARBAwHCwERBAwICwIRBAwJCgQRBwwKCgQuEQ8MCwsFCwcLCAsJCwYLCwsKEgALBC4RDzgFAgIBBAABDwoAEAAKAjgGBAkLAAEHACcLAA8ACwILATgHAgMBBAABFQoAEAAKATgGBAYFDAsAAQsCAQcBJwsADwALATgICwIuEQ84CQIABgA=" + ], + "dependencies": [ + "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x0000000000000000000000000000000000000000000000000000000000000002" + ], + "digest": [ + 230, 176, 154, 186, 116, 20, 2, 11, 160, 67, 141, 155, 116, 202, 159, 86, 175, 193, 178, 70, 108, 255, 115, 191, 74, + 225, 45, 163, 68, 211, 24, 204 + ] +} diff --git a/src/index.ts b/src/index.ts new file mode 100644 index 0000000..a4cf80b --- /dev/null +++ b/src/index.ts @@ -0,0 +1 @@ +export { Suibox, SuiboxParams, NftParams, NftInSuibox, SuiboxContract } from './suibox'; diff --git a/src/suibox.ts b/src/suibox.ts new file mode 100644 index 0000000..9a42a40 --- /dev/null +++ b/src/suibox.ts @@ -0,0 +1,223 @@ +import { + JsonRpcProvider, + RawSigner, + SuiObjectChangeCreated, + SuiObjectChangePublished, + TransactionBlock, + normalizeSuiObjectId, + fromB64, + SuiObjectResponse, +} from '@mysten/sui.js'; +import * as compiledModulesAndDeps from './contract_assets.json'; + +export interface SuiboxParams { + name: string; + description: string; + image_url: string; + layout: string; +} + +export interface NftParams { + objectId: string; + typestruct?: string; +} + +export interface NftInSuibox { + position: number; + objectId: string; + objectType: string; +} + +async function getNftType(objectId: string, provider: JsonRpcProvider): Promise { + const res = await provider.getObject({ + id: objectId, + options: { + showType: true, + }, + }); + // console.log('res', JSON.stringify(res, null, 2)); + return res.data!.type!; +} + +export class SuiboxContract { + readonly packageId: string; + readonly signer: RawSigner; + + constructor(packageId: string, signer: RawSigner) { + this.packageId = packageId; + this.signer = signer; + } + + static async publish(signer: RawSigner): Promise { + const tx = new TransactionBlock(); + const [upgradeCap] = tx.publish({ + modules: compiledModulesAndDeps.modules.map((m: any) => Array.from(fromB64(m))), + dependencies: compiledModulesAndDeps.dependencies.map((addr: string) => normalizeSuiObjectId(addr)), + }); + tx.transferObjects([upgradeCap], tx.pure(await signer.getAddress())); + const publishTxn = await signer.signAndExecuteTransactionBlock({ + transactionBlock: tx, + options: { + showInput: true, + showEffects: true, + showEvents: true, + showObjectChanges: true, + }, + }); + console.log('publishTxn', JSON.stringify(publishTxn, null, 2)); + const packageId = (publishTxn.objectChanges!.filter((o) => o.type === 'published')[0] as SuiObjectChangePublished) + .packageId; + return new SuiboxContract(packageId, signer); + } + + async listSuiboxes(): Promise { + const owner = await this.signer.getAddress(); + let suiboxes: Suibox[] = []; + let cursor: string | null = null; + while (true) { + let res: any = await this.signer.provider.getOwnedObjects({ + owner, + cursor, + filter: { + StructType: `${this.packageId}::suibox::Suibox`, + }, + options: { + showType: true, + }, + }); + // console.log("res", JSON.stringify(res, null, 2)); + for (let obj of res.data) { + suiboxes.push(new Suibox(obj.data!.objectId, this.signer, this.packageId)); + } + if (res.hasNextPage) { + cursor = res.cursor; + } else { + return suiboxes; + } + } + } + + async createSuibox(params: SuiboxParams): Promise { + const tx = new TransactionBlock(); + tx.moveCall({ + target: `${this.packageId}::suibox::create_suibox`, + typeArguments: [], + arguments: [tx.pure(params.name), tx.pure(params.description), tx.pure(params.image_url), tx.pure(params.layout)], + }); + const txnRes = await this.signer.signAndExecuteTransactionBlock({ + transactionBlock: tx, + options: { + showInput: true, + showEffects: true, + showEvents: true, + showObjectChanges: true, + }, + }); + const suiboxObjectId = ( + txnRes.objectChanges!.filter( + (o) => o.type === 'created' && o.objectType.endsWith('::suibox::Suibox'), + )[0] as SuiObjectChangeCreated + ).objectId; + return new Suibox(suiboxObjectId, this.signer, this.packageId); + } +} + +export class Suibox { + objectId: string; + signer: RawSigner; + packageId: string | undefined; + + constructor(address: string, signer: RawSigner, packageId?: string) { + this.objectId = address; + this.signer = signer; + this.packageId = packageId; + } + + async listNFTs(): Promise { + const suiboxDetail: any = await this.signer.provider.getObject({ + id: this.objectId, + options: { + showContent: true, + }, + }); + const bagId = suiboxDetail.data.content.fields.nfts.fields.id.id; + let cursor: string | null = null; + let res = []; + while (true) { + const nfts: any = await this.signer.provider.getDynamicFields({ + parentId: bagId, + cursor, + }); + // console.log("nfts", JSON.stringify(nfts, null, 2)); + for (let nft of nfts.data) { + res.push({ + position: parseInt(nft.name.value), + objectId: nft.objectType, + objectType: nft.objectId, + }); + } + if (nfts.hasNextPage) { + cursor = nfts.cursor; + } else { + return res; + } + } + } + + async getPackageId(): Promise { + if (this.packageId) { + return this.packageId; + } + const res = await this.signer.provider.getObject({ + id: this.objectId, + options: { + showType: true, + }, + }); + this.packageId = res.data!.type!.split('::')[0]; + return this.packageId; + } + + async add(nft: NftParams, position: number) { + const tx = new TransactionBlock(); + if (!nft.typestruct) { + nft.typestruct = await getNftType(nft.objectId, this.signer.provider); + } + tx.moveCall({ + target: `${await this.getPackageId()}::suibox::add_nft_to_suibox`, + typeArguments: [nft.typestruct], + arguments: [tx.object(this.objectId), tx.object(nft.objectId), tx.pure(position)], + }); + await this.signer.signAndExecuteTransactionBlock({ + transactionBlock: tx, + options: { + showInput: true, + showEffects: true, + showEvents: true, + showObjectChanges: true, + }, + }); + } + + async extract(typestruct: string, position: number) { + const tx = new TransactionBlock(); + tx.moveCall({ + target: `${await this.getPackageId()}::suibox::extract_from_suibox`, + typeArguments: [typestruct], + arguments: [tx.object(this.objectId), tx.pure(position)], + }); + await this.signer.signAndExecuteTransactionBlock({ + transactionBlock: tx, + options: { + showInput: true, + showEffects: true, + showEvents: true, + showObjectChanges: true, + }, + }); + } + + connect(signer: RawSigner): Suibox { + return new Suibox(this.objectId, signer); + } +} diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..1ff5617 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,103 @@ +{ + "compilerOptions": { + /* Visit https://aka.ms/tsconfig to read more about this file */ + + /* Projects */ + // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */ + // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ + // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */ + // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */ + // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ + // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ + + /* Language and Environment */ + "target": "es2020", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */ + // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ + // "jsx": "preserve", /* Specify what JSX code is generated. */ + // "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */ + // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ + // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */ + // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ + // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */ + // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */ + // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ + // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ + // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ + + /* Modules */ + "module": "commonjs", /* Specify what module code is generated. */ + // "rootDir": "./", /* Specify the root folder within your source files. */ + // "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */ + // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ + // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ + // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ + // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */ + // "types": [], /* Specify type package names to be included without being referenced in a source file. */ + // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ + // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */ + "resolveJsonModule": true, /* Enable importing .json files. */ + // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */ + + /* JavaScript Support */ + // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */ + // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ + // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */ + + /* Emit */ + // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ + // "declarationMap": true, /* Create sourcemaps for d.ts files. */ + // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ + // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ + // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ + // "outDir": "./", /* Specify an output folder for all emitted files. */ + // "removeComments": true, /* Disable emitting comments. */ + // "noEmit": true, /* Disable emitting files from a compilation. */ + // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ + // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */ + // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ + // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ + // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ + // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ + // "newLine": "crlf", /* Set the newline character for emitting files. */ + // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */ + // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */ + // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ + // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */ + // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ + // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ + + /* Interop Constraints */ + // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ + // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ + "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */ + // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ + "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */ + + /* Type Checking */ + "strict": true, /* Enable all strict type-checking options. */ + // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */ + // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */ + // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ + // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */ + // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ + // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */ + // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */ + // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ + // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */ + // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */ + // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ + // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ + // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ + // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */ + // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ + // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */ + // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ + // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ + + /* Completeness */ + // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ + "skipLibCheck": true /* Skip type checking all .d.ts files. */ + } +}