diff --git a/meta_dir/.gitattributes b/meta_dir/.gitattributes new file mode 100644 index 0000000..da6a065 --- /dev/null +++ b/meta_dir/.gitattributes @@ -0,0 +1,3 @@ +tests/** linguist-vendored +vitest.config.js linguist-vendored +* text=lf diff --git a/meta_dir/.gitignore b/meta_dir/.gitignore new file mode 100644 index 0000000..76c2842 --- /dev/null +++ b/meta_dir/.gitignore @@ -0,0 +1,13 @@ + +**/settings/Mainnet.toml +**/settings/Testnet.toml +.cache/** +history.txt + +logs +*.log +npm-debug.log* +coverage +*.info +costs-reports.json +node_modules diff --git a/meta_dir/.vscode/settings.json b/meta_dir/.vscode/settings.json new file mode 100644 index 0000000..3062519 --- /dev/null +++ b/meta_dir/.vscode/settings.json @@ -0,0 +1,4 @@ + +{ + "files.eol": "\n" +} diff --git a/meta_dir/.vscode/tasks.json b/meta_dir/.vscode/tasks.json new file mode 100644 index 0000000..4dec0ff --- /dev/null +++ b/meta_dir/.vscode/tasks.json @@ -0,0 +1,19 @@ + +{ + "version": "2.0.0", + "tasks": [ + { + "label": "check contracts", + "group": "test", + "type": "shell", + "command": "clarinet check" + }, + { + "type": "npm", + "script": "test", + "group": "test", + "problemMatcher": [], + "label": "npm test" + } + ] +} diff --git a/meta_dir/Clarinet.toml b/meta_dir/Clarinet.toml new file mode 100644 index 0000000..dc2814b --- /dev/null +++ b/meta_dir/Clarinet.toml @@ -0,0 +1,19 @@ +[project] +name = 'meta_dir' +description = '' +authors = [] +telemetry = true +cache_dir = '.\.cache' +requirements = [] +[contracts.codehub] +path = 'contracts/codehub.clar' +clarity_version = 3 +epoch = 3.0 +[repl.analysis] +passes = ['check_checker'] + +[repl.analysis.check_checker] +strict = false +trusted_sender = false +trusted_caller = false +callee_filter = false diff --git a/meta_dir/README.md b/meta_dir/README.md new file mode 100644 index 0000000..cb48747 --- /dev/null +++ b/meta_dir/README.md @@ -0,0 +1,136 @@ +# Digital Art Authentication and Licensing System (DAALS) + +**Project Overview** +The Digital Art Authentication and Licensing System (DAALS) is a smart contract application built on the Stacks blockchain. It provides a secure and transparent platform for authenticating digital artwork, managing licensing, and tracking ownership history. By leveraging blockchain technology, DAALS ensures that artists, galleries, and collectors can trust the authenticity and licensing status of digital artworks. + +--- + +## Features +1. **Artwork Registration**: + - Artists can register their digital artwork with details such as the artist name, collection, and a unique token ID. + - Automatically tracks the creation timestamp and assigns the creator as the initial licensee. + +2. **License Transfer**: + - Enables transferring artwork licenses securely between users (e.g., from artist to gallery). + - Records all license transfers in a historical ledger for transparency. + +3. **Artwork Verification**: + - Provides a mechanism to verify the authenticity of digital artworks. + - Ensures only authorized creators and galleries are listed. + +4. **License Status Management**: + - Allows creators to update the license status of their artworks (e.g., valid, revoked, or expired). + +5. **License History Tracking**: + - Maintains a comprehensive history of all license-related actions, including transfers and updates. + +--- + +## Architecture +The system is implemented using Clarity smart contracts and comprises the following core components: + +- **Data Maps**: + - `artworks`: Stores metadata about each artwork. + - `license-history`: Tracks the history of licenses for each artwork. + - `creators` and `galleries`: Registers authorized creators and galleries. + +- **Constants**: + - Define reusable values like error codes and license statuses. + +- **Read-Only Functions**: + - `get-artwork`: Fetch artwork details. + - `is-creator` and `is-gallery`: Check authorization for creators and galleries. + - `get-license-history`: Retrieve license history records. + +- **Public Functions**: + - `register-creator` and `register-gallery`: Add authorized creators and galleries. + - `mint-artwork`: Register a new artwork. + - `transfer-license`: Transfer license ownership. + - `verify-artwork`: Validate authenticity. + - `update-license-status`: Modify the license status. + +--- + +## Installation + +### Prerequisites +- [Stacks Blockchain CLI](https://docs.hiro.so/get-started) +- Node.js (for running a local development server if needed) +- A text editor like VS Code + +### Steps +1. Clone the repository: + ```bash + git clone https://github.com/your-repo/DAALS.git + cd DAALS + ``` +2. Deploy the contract: + - Use the Stacks CLI to deploy the Clarity smart contract: + ```bash + clarity-cli deploy ./contracts/daals.clar + ``` + +3. Test the contract (optional): + - Write and run test cases in Clarity to validate the functionality. + +--- + +## Usage + +### Artwork Registration +1. Register yourself as a creator using the `register-creator` function. + Example: + ```clarity + (contract-call? .daals register-creator tx-sender) + ``` +2. Mint a new artwork: + ```clarity + (contract-call? .daals mint-artwork "unique-token-id" "artist-name" "collection-name") + ``` + +### Transferring Licenses +To transfer a license to a new owner: +```clarity +(contract-call? .daals transfer-license "unique-token-id" new-licensee-principal) +``` + +### Verifying Artworks +To verify the authenticity of an artwork: +```clarity +(contract-call? .daals verify-artwork "unique-token-id") +``` + +### Updating License Status +To update the license status (e.g., revoke or expire): +```clarity +(contract-call? .daals update-license-status "unique-token-id" "revoked") +``` + +--- + +## Error Codes +- `ERR_NOT_AUTHORIZED (u100)`: The caller does not have permission. +- `ERR_INVALID_INPUT (u101)`: Invalid input provided. +- `ERR_NOT_FOUND (u102)`: The requested artwork or record does not exist. +- `ERR_ALREADY_EXISTS (u103)`: The artwork or record already exists. +- `ERR_INVALID_STATUS (u104)`: Invalid license status provided. + +--- + +## Roadmap +1. **Phase 1**: Initial release with core features for registration, transfer, and verification. +2. **Phase 2**: Integration with NFT standards for tokenized artworks. +3. **Phase 3**: Build a web-based interface for creators and galleries. +4. **Phase 4**: Support for multi-chain compatibility. + +--- + +## Contributing +Contributions are welcome! Please fork the repository and submit a pull request with your changes. + +--- + + +## Contact +For any inquiries or suggestions, please contact **Amobi Ndubuisi** at dev.triggerfish@gmail.com. + diff --git a/meta_dir/contracts/codehub.clar b/meta_dir/contracts/codehub.clar new file mode 100644 index 0000000..f2f37f1 --- /dev/null +++ b/meta_dir/contracts/codehub.clar @@ -0,0 +1,237 @@ +;; Digital Art Authentication and Licensing System +;; Description: Smart contract system for authenticating and managing digital artwork licenses on Stacks blockchain + +;; Constants +(define-constant CONTRACT_OWNER tx-sender) +(define-constant ERR_NOT_AUTHORIZED (err u100)) +(define-constant ERR_INVALID_INPUT (err u101)) +(define-constant ERR_NOT_FOUND (err u102)) +(define-constant ERR_ALREADY_EXISTS (err u103)) +(define-constant ERR_INVALID_STATUS (err u104)) + +;; Status constants with explicit type casting +(define-constant LICENSE_VALID "valid") +(define-constant LICENSE_REVOKED "revoked") +(define-constant LICENSE_EXPIRED "expired") + +;; Data Variables +(define-data-var license-counter uint u0) + +;; Data Maps +(define-map artworks + {token-id: (string-ascii 50)} + { + artist: (string-ascii 50), + collection: (string-ascii 50), + creator: principal, + timestamp: uint, + status: (string-ascii 20), + current-licensee: principal + } +) + +(define-map creators principal bool) +(define-map galleries principal bool) + +;; Artwork license history tracking +(define-map license-history + {token-id: (string-ascii 50), index: uint} + { + licensee: principal, + timestamp: uint, + action: (string-ascii 20) + } +) + +;; Track history indices +(define-map history-indices + (string-ascii 50) ;; token-id + uint ;; current index +) + +;; Read-only functions +(define-read-only (get-artwork (token-id (string-ascii 50))) + (map-get? artworks {token-id: token-id}) +) + +(define-read-only (is-creator (address principal)) + (default-to false (map-get? creators address)) +) + +(define-read-only (is-gallery (address principal)) + (default-to false (map-get? galleries address)) +) + +(define-read-only (get-current-timestamp) + (var-get license-counter) +) + +;; Administrative functions +(define-public (register-creator (creator principal)) + (begin + (asserts! (is-eq tx-sender CONTRACT_OWNER) ERR_NOT_AUTHORIZED) + (asserts! (is-none (map-get? creators creator)) ERR_ALREADY_EXISTS) + (ok (map-set creators creator true)) + ) +) + +(define-public (register-gallery (gallery principal)) + (begin + (asserts! (is-eq tx-sender CONTRACT_OWNER) ERR_NOT_AUTHORIZED) + (asserts! (is-none (map-get? galleries gallery)) ERR_ALREADY_EXISTS) + (ok (map-set galleries gallery true)) + ) +) + +;; Artwork registration +(define-public (mint-artwork + (token-id (string-ascii 50)) + (artist (string-ascii 50)) + (collection (string-ascii 50))) + + (let + ( + (creator tx-sender) + (timestamp (var-get license-counter)) + ) + + ;; Verify creator authorization + (asserts! (is-creator creator) ERR_NOT_AUTHORIZED) + + ;; Check artwork doesn't already exist + (asserts! (is-none (get-artwork token-id)) ERR_ALREADY_EXISTS) + + ;; Validate input + (asserts! (> (len artist) u0) ERR_INVALID_INPUT) + (asserts! (> (len collection) u0) ERR_INVALID_INPUT) + + ;; Register artwork + (map-set artworks + {token-id: token-id} + { + artist: artist, + collection: collection, + creator: creator, + timestamp: timestamp, + status: LICENSE_VALID, + current-licensee: creator + } + ) + + ;; Initialize history + (map-set license-history + {token-id: token-id, index: u0} + { + licensee: creator, + timestamp: timestamp, + action: "minted" + } + ) + (map-set history-indices token-id u1) + + ;; Increment license counter + (var-set license-counter (+ timestamp u1)) + + (ok true) + ) +) + +;; Transfer license +(define-public (transfer-license + (token-id (string-ascii 50)) + (new-licensee principal)) + + (let + ( + (artwork (unwrap! (get-artwork token-id) ERR_NOT_FOUND)) + (timestamp (var-get license-counter)) + (current-index (default-to u0 (map-get? history-indices token-id))) + ) + + ;; Verify sender owns the license + (asserts! (is-eq (get current-licensee artwork) tx-sender) ERR_NOT_AUTHORIZED) + + ;; Validate new licensee + (asserts! (or (is-creator new-licensee) (is-gallery new-licensee)) ERR_INVALID_INPUT) + + ;; Update artwork license + (map-set artworks + {token-id: token-id} + (merge artwork {current-licensee: new-licensee}) + ) + + ;; Record transfer in history + (map-set license-history + {token-id: token-id, index: current-index} + { + licensee: new-licensee, + timestamp: timestamp, + action: "transferred" + } + ) + (map-set history-indices token-id (+ current-index u1)) + + ;; Increment license counter + (var-set license-counter (+ timestamp u1)) + + (ok true) + ) +) + +;; Verify artwork authenticity +(define-public (verify-artwork + (token-id (string-ascii 50))) + + (let + ( + (artwork (unwrap! (get-artwork token-id) ERR_NOT_FOUND)) + ) + + ;; Verify creator is still authorized + (asserts! (is-creator (get creator artwork)) ERR_NOT_AUTHORIZED) + + ;; Return verification result + (ok { + is-authentic: true, + creator: (get creator artwork), + current-licensee: (get current-licensee artwork), + status: (get status artwork) + }) + ) +) + +;; Get license history +(define-read-only (get-license-history + (token-id (string-ascii 50)) + (index uint)) + + (map-get? license-history {token-id: token-id, index: index}) +) + +;; Update license status +(define-public (update-license-status + (token-id (string-ascii 50)) + (new-status (string-ascii 20))) + + (let + ( + (artwork (unwrap! (get-artwork token-id) ERR_NOT_FOUND)) + ) + + ;; Only creator can update status + (asserts! (is-eq (get creator artwork) tx-sender) ERR_NOT_AUTHORIZED) + + ;; Validate status + (asserts! (or + (is-eq new-status LICENSE_VALID) + (is-eq new-status LICENSE_REVOKED) + (is-eq new-status LICENSE_EXPIRED) + ) ERR_INVALID_STATUS) + + ;; Update status + (ok (map-set artworks + {token-id: token-id} + (merge artwork {status: new-status}) + )) + ) +) \ No newline at end of file diff --git a/meta_dir/package.json b/meta_dir/package.json new file mode 100644 index 0000000..a3a9e8a --- /dev/null +++ b/meta_dir/package.json @@ -0,0 +1,24 @@ + +{ + "name": "meta_dir-tests", + "version": "1.0.0", + "description": "Run unit tests on this project.", + "type": "module", + "private": true, + "scripts": { + "test": "vitest run", + "test:report": "vitest run -- --coverage --costs", + "test:watch": "chokidar \"tests/**/*.ts\" \"contracts/**/*.clar\" -c \"npm run test:report\"" + }, + "author": "", + "license": "ISC", + "dependencies": { + "@hirosystems/clarinet-sdk": "^2.3.2", + "@stacks/transactions": "^6.12.0", + "chokidar-cli": "^3.0.0", + "typescript": "^5.3.3", + "vite": "^5.1.4", + "vitest": "^1.3.1", + "vitest-environment-clarinet": "^2.0.0" + } +} diff --git a/meta_dir/settings/Devnet.toml b/meta_dir/settings/Devnet.toml new file mode 100644 index 0000000..54a2c35 --- /dev/null +++ b/meta_dir/settings/Devnet.toml @@ -0,0 +1,157 @@ +[network] +name = "devnet" +deployment_fee_rate = 10 + +[accounts.deployer] +mnemonic = "twice kind fence tip hidden tilt action fragile skin nothing glory cousin green tomorrow spring wrist shed math olympic multiply hip blue scout claw" +balance = 100_000_000_000_000 +# secret_key: 753b7cc01a1a2e86221266a154af739463fce51219d97e4f856cd7200c3bd2a601 +# stx_address: ST1PQHQKV0RJXZFY1DGX8MNSNYVE3VGZJSRTPGZGM +# btc_address: mqVnk6NPRdhntvfm4hh9vvjiRkFDUuSYsH + +[accounts.wallet_1] +mnemonic = "sell invite acquire kitten bamboo drastic jelly vivid peace spawn twice guilt pave pen trash pretty park cube fragile unaware remain midnight betray rebuild" +balance = 100_000_000_000_000 +# secret_key: 7287ba251d44a4d3fd9276c88ce34c5c52a038955511cccaf77e61068649c17801 +# stx_address: ST1SJ3DTE5DN7X54YDH5D64R3BCB6A2AG2ZQ8YPD5 +# btc_address: mr1iPkD9N3RJZZxXRk7xF9d36gffa6exNC + +[accounts.wallet_2] +mnemonic = "hold excess usual excess ring elephant install account glad dry fragile donkey gaze humble truck breeze nation gasp vacuum limb head keep delay hospital" +balance = 100_000_000_000_000 +# secret_key: 530d9f61984c888536871c6573073bdfc0058896dc1adfe9a6a10dfacadc209101 +# stx_address: ST2CY5V39NHDPWSXMW9QDT3HC3GD6Q6XX4CFRK9AG +# btc_address: muYdXKmX9bByAueDe6KFfHd5Ff1gdN9ErG + +[accounts.wallet_3] +mnemonic = "cycle puppy glare enroll cost improve round trend wrist mushroom scorpion tower claim oppose clever elephant dinosaur eight problem before frozen dune wagon high" +balance = 100_000_000_000_000 +# secret_key: d655b2523bcd65e34889725c73064feb17ceb796831c0e111ba1a552b0f31b3901 +# stx_address: ST2JHG361ZXG51QTKY2NQCVBPPRRE2KZB1HR05NNC +# btc_address: mvZtbibDAAA3WLpY7zXXFqRa3T4XSknBX7 + +[accounts.wallet_4] +mnemonic = "board list obtain sugar hour worth raven scout denial thunder horse logic fury scorpion fold genuine phrase wealth news aim below celery when cabin" +balance = 100_000_000_000_000 +# secret_key: f9d7206a47f14d2870c163ebab4bf3e70d18f5d14ce1031f3902fbbc894fe4c701 +# stx_address: ST2NEB84ASENDXKYGJPQW86YXQCEFEX2ZQPG87ND +# btc_address: mg1C76bNTutiCDV3t9nWhZs3Dc8LzUufj8 + +[accounts.wallet_5] +mnemonic = "hurry aunt blame peanut heavy update captain human rice crime juice adult scale device promote vast project quiz unit note reform update climb purchase" +balance = 100_000_000_000_000 +# secret_key: 3eccc5dac8056590432db6a35d52b9896876a3d5cbdea53b72400bc9c2099fe801 +# stx_address: ST2REHHS5J3CERCRBEPMGH7921Q6PYKAADT7JP2VB +# btc_address: mweN5WVqadScHdA81aATSdcVr4B6dNokqx + +[accounts.wallet_6] +mnemonic = "area desk dutch sign gold cricket dawn toward giggle vibrant indoor bench warfare wagon number tiny universe sand talk dilemma pottery bone trap buddy" +balance = 100_000_000_000_000 +# secret_key: 7036b29cb5e235e5fd9b09ae3e8eec4404e44906814d5d01cbca968a60ed4bfb01 +# stx_address: ST3AM1A56AK2C1XAFJ4115ZSV26EB49BVQ10MGCS0 +# btc_address: mzxXgV6e4BZSsz8zVHm3TmqbECt7mbuErt + +[accounts.wallet_7] +mnemonic = "prevent gallery kind limb income control noise together echo rival record wedding sense uncover school version force bleak nuclear include danger skirt enact arrow" +balance = 100_000_000_000_000 +# secret_key: b463f0df6c05d2f156393eee73f8016c5372caa0e9e29a901bb7171d90dc4f1401 +# stx_address: ST3PF13W7Z0RRM42A8VZRVFQ75SV1K26RXEP8YGKJ +# btc_address: n37mwmru2oaVosgfuvzBwgV2ysCQRrLko7 + +[accounts.wallet_8] +mnemonic = "female adjust gallery certain visit token during great side clown fitness like hurt clip knife warm bench start reunion globe detail dream depend fortune" +balance = 100_000_000_000_000 +# secret_key: 6a1a754ba863d7bab14adbbc3f8ebb090af9e871ace621d3e5ab634e1422885e01 +# stx_address: ST3NBRSFKX28FQ2ZJ1MAKX58HKHSDGNV5N7R21XCP +# btc_address: n2v875jbJ4RjBnTjgbfikDfnwsDV5iUByw + +[accounts.faucet] +mnemonic = "shadow private easily thought say logic fault paddle word top book during ignore notable orange flight clock image wealth health outside kitten belt reform" +balance = 100_000_000_000_000 +# secret_key: de433bdfa14ec43aa1098d5be594c8ffb20a31485ff9de2923b2689471c401b801 +# stx_address: STNHKEPYEPJ8ET55ZZ0M5A34J0R3N5FM2CMMMAZ6 +# btc_address: mjSrB3wS4xab3kYqFktwBzfTdPg367ZJ2d + +[devnet] +disable_stacks_explorer = false +disable_stacks_api = false +# disable_postgres = false +# disable_subnet_api = false +# disable_bitcoin_explorer = true +# working_dir = "tmp/devnet" +# stacks_node_events_observers = ["host.docker.internal:8002"] +# miner_mnemonic = "fragile loan twenty basic net assault jazz absorb diet talk art shock innocent float punch travel gadget embrace caught blossom hockey surround initial reduce" +# miner_derivation_path = "m/44'/5757'/0'/0/0" +# faucet_mnemonic = "shadow private easily thought say logic fault paddle word top book during ignore notable orange flight clock image wealth health outside kitten belt reform" +# faucet_derivation_path = "m/44'/5757'/0'/0/0" +# stacker_mnemonic = "empty lens any direct brother then drop fury rule pole win claim scissors list rescue horn rent inform relief jump sword weekend half legend" +# stacker_derivation_path = "m/44'/5757'/0'/0/0" +# orchestrator_port = 20445 +# bitcoin_node_p2p_port = 18444 +# bitcoin_node_rpc_port = 18443 +# bitcoin_node_username = "devnet" +# bitcoin_node_password = "devnet" +# bitcoin_controller_block_time = 30_000 +# stacks_node_rpc_port = 20443 +# stacks_node_p2p_port = 20444 +# stacks_api_port = 3999 +# stacks_api_events_port = 3700 +# bitcoin_explorer_port = 8001 +# stacks_explorer_port = 8000 +# postgres_port = 5432 +# postgres_username = "postgres" +# postgres_password = "postgres" +# postgres_database = "postgres" +# bitcoin_node_image_url = "quay.io/hirosystems/bitcoind:26.0" +# stacks_node_image_url = "quay.io/hirosystems/stacks-node:devnet-3.0" +# stacks_signer_image_url = "quay.io/hirosystems/stacks-signer:devnet-3.0" +# stacks_api_image_url = "hirosystems/stacks-blockchain-api:master" +# stacks_explorer_image_url = "hirosystems/explorer:latest" +# bitcoin_explorer_image_url = "quay.io/hirosystems/bitcoin-explorer:devnet" +# postgres_image_url = "postgres:alpine" +# enable_subnet_node = true +# subnet_node_image_url = "hirosystems/stacks-subnets:0.8.1" +# subnet_leader_mnemonic = "twice kind fence tip hidden tilt action fragile skin nothing glory cousin green tomorrow spring wrist shed math olympic multiply hip blue scout claw" +# subnet_leader_derivation_path = "m/44'/5757'/0'/0/0" +# subnet_contract_id = "ST173JK7NZBA4BS05ZRATQH1K89YJMTGEH1Z5J52E.subnet-v3-0-1" +# subnet_node_rpc_port = 30443 +# subnet_node_p2p_port = 30444 +# subnet_events_ingestion_port = 30445 +# subnet_node_events_observers = ["host.docker.internal:8002"] +# subnet_api_image_url = "hirosystems/stacks-blockchain-api:master" +# subnet_api_postgres_database = "subnet_api" + +# epoch_2_0 = 100 +# epoch_2_05 = 100 +# epoch_2_1 = 101 +# epoch_2_2 = 102 +# epoch_2_3 = 103 +# epoch_2_4 = 104 +# epoch_2_5 = 108 +# epoch_3_0 = 142 + +# Send some stacking orders +[[devnet.pox_stacking_orders]] +start_at_cycle = 1 +duration = 10 +auto_extend = true +wallet = "wallet_1" +slots = 2 +btc_address = "mr1iPkD9N3RJZZxXRk7xF9d36gffa6exNC" + +[[devnet.pox_stacking_orders]] +start_at_cycle = 1 +duration = 10 +auto_extend = true +wallet = "wallet_2" +slots = 2 +btc_address = "muYdXKmX9bByAueDe6KFfHd5Ff1gdN9ErG" + +[[devnet.pox_stacking_orders]] +start_at_cycle = 1 +duration = 10 +auto_extend = true +wallet = "wallet_3" +slots = 2 +btc_address = "mvZtbibDAAA3WLpY7zXXFqRa3T4XSknBX7" + diff --git a/meta_dir/tests/codehub.test.ts b/meta_dir/tests/codehub.test.ts new file mode 100644 index 0000000..4bb9cf3 --- /dev/null +++ b/meta_dir/tests/codehub.test.ts @@ -0,0 +1,21 @@ + +import { describe, expect, it } from "vitest"; + +const accounts = simnet.getAccounts(); +const address1 = accounts.get("wallet_1")!; + +/* + The test below is an example. To learn more, read the testing documentation here: + https://docs.hiro.so/stacks/clarinet-js-sdk +*/ + +describe("example tests", () => { + it("ensures simnet is well initalised", () => { + expect(simnet.blockHeight).toBeDefined(); + }); + + // it("shows an example", () => { + // const { result } = simnet.callReadOnlyFn("counter", "get-counter", [], address1); + // expect(result).toBeUint(0); + // }); +}); diff --git a/meta_dir/tsconfig.json b/meta_dir/tsconfig.json new file mode 100644 index 0000000..1bdaf36 --- /dev/null +++ b/meta_dir/tsconfig.json @@ -0,0 +1,26 @@ + +{ + "compilerOptions": { + "target": "ESNext", + "useDefineForClassFields": true, + "module": "ESNext", + "lib": ["ESNext"], + "skipLibCheck": true, + + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + + "strict": true, + "noImplicitAny": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true + }, + "include": [ + "node_modules/@hirosystems/clarinet-sdk/vitest-helpers/src", + "tests" + ] +} diff --git a/meta_dir/vitest.config.js b/meta_dir/vitest.config.js new file mode 100644 index 0000000..c6a8506 --- /dev/null +++ b/meta_dir/vitest.config.js @@ -0,0 +1,42 @@ + +/// + +import { defineConfig } from "vite"; +import { vitestSetupFilePath, getClarinetVitestsArgv } from "@hirosystems/clarinet-sdk/vitest"; + +/* + In this file, Vitest is configured so that it works seamlessly with Clarinet and the Simnet. + + The `vitest-environment-clarinet` will initialise the clarinet-sdk + and make the `simnet` object available globally in the test files. + + `vitestSetupFilePath` points to a file in the `@hirosystems/clarinet-sdk` package that does two things: + - run `before` hooks to initialize the simnet and `after` hooks to collect costs and coverage reports. + - load custom vitest matchers to work with Clarity values (such as `expect(...).toBeUint()`) + + The `getClarinetVitestsArgv()` will parse options passed to the command `vitest run --` + - vitest run -- --manifest ./Clarinet.toml # pass a custom path + - vitest run -- --coverage --costs # collect coverage and cost reports +*/ + +export default defineConfig({ + test: { + environment: "clarinet", // use vitest-environment-clarinet + pool: "forks", + poolOptions: { + threads: { singleThread: true }, + forks: { singleFork: true }, + }, + setupFiles: [ + vitestSetupFilePath, + // custom setup files can be added here + ], + environmentOptions: { + clarinet: { + ...getClarinetVitestsArgv(), + // add or override options + }, + }, + }, +}); +