diff --git a/Clarinet.toml b/Clarinet.toml index 5b40657..0e0663f 100644 --- a/Clarinet.toml +++ b/Clarinet.toml @@ -59,6 +59,21 @@ epoch = 2.5 path = 'contracts/ex7-sip010.clar' clarity_version = 2 epoch = 2.5 + +[contracts.ex8-01] +path = 'contracts/ex8-01.clar' +clarity_version = 2 +epoch = 2.5 + +[contracts.ex8-02] +path = 'contracts/ex8-02.clar' +clarity_version = 2 +epoch = 2.5 + +[contracts.ex8-sip009] +path = 'contracts/ex8-sip009.clar' +clarity_version = 2 +epoch = 2.5 [repl.analysis] passes = ['check_checker'] diff --git a/contracts/ex8-01.clar b/contracts/ex8-01.clar new file mode 100644 index 0000000..18e91ef --- /dev/null +++ b/contracts/ex8-01.clar @@ -0,0 +1,47 @@ + +;; title: ex8-01 +;; version: 1.0.0 +;; summary: + +;; traits +;; +(impl-trait .ex8-sip009.nft-trait) + +;; token definitions +;; + +;; constants +;; + +;; data vars +;; + +;; data maps +;; + +;; public functions +;; + +;; read only functions +;; + +;; private functions +;; + + +(define-non-fungible-token CoolNFT uint) + +(define-public (transfer-nft (tokenId uint) (sender principal) (recipient principal)) + (begin + (asserts! (is-eq tx-sender sender) (err u1)) + (try! (nft-transfer? CoolNFT tokenId sender recipient)) + ) +) + +;; Tests (uncomment and run these to check your solution) +;; (define-constant WALLET_1 'ST1PQHQKV0RJXZFY1DGX8MNSNYVE3VGZJSRTPGZGM) +;; (define-constant WALLET_2 'ST2CY5V39NHDPWSXMW9QDT3HC3GD6Q6XX4CFRK9AG) + +;; (nft-mint? CoolNFT u1 WALLET_1) +;; (transfer-nft u1 WALLET_1 WALLET_2) ;; This should return (ok true) +;; (nft-get-owner? CoolNFT u1) ;; This should return (ok WALLET_2) diff --git a/contracts/ex8-02.clar b/contracts/ex8-02.clar new file mode 100644 index 0000000..7bd5dbc --- /dev/null +++ b/contracts/ex8-02.clar @@ -0,0 +1,96 @@ + +;; title: ex8-02 +;; version: 1.0.0 +;; summary: + +;; traits +;; +(impl-trait .ex8-sip009.nft-trait) + +;; token definitions +;; + +;; constants +;; + +;; data vars +;; + +;; data maps +;; + +;; public functions +;; + +;; read only functions +;; + +;; private functions +;; + +;; Here are the requirements: +;; - Define an NFT for lottery tickets +;; - Create a function to purchase a ticket by sending STX +;; - Create a function to select a winner (does not need to be random) +;; - Allow the winner to claim their prize + +;; rounds happen every so many blocks (say 144) +;; map of round number to total tickets (also total STX if mutiplied) +;; each round has a winner determined after round ends (+1 block) +;; winner gets ??? +;; ticket price is fixed at 1 STX +;; claiming prize burns the nft + +(define-non-fungible-token Ticket uint) + +(define-data-var ticketCounter uint u0) +(define-data-var ticketPrice uint u1000000) ;; 1 STX +(define-data-var lotteryPool uint u0) + +(define-public (buy-ticket) + ;; Implement ticket purchase logic here +) + +(define-public (select-winner) + ;; Implement winner selection logic here (this can be hard coded, or however you prefer) +) + +(define-public (claim-prize) + ;; Implement prize claiming logic here +) + +;; Test cases + +;; Buy a ticket successfully +;; (contract-call? .lottery buy-ticket) ;; Should `mint` NFT to your address +;; ticketCounter should be 1, lotteryPool should be 1000000 + +;; Select a winner +;; (contract-call? .lottery select-winner) +;; Should return (ok principal) where principal is the winner's address + +;; Claim prize (assuming the caller is the winner) +;; (contract-call? .lottery claim-prize) ;; Should return (ok u...) +;; The winner's balance should increase by 3000000, lotteryPool should be 0 + +;; Attempt to select winner when no tickets are sold +;; First, reset the contract state or deploy a fresh instance +;; (contract-call? .lottery select-winner) +;; Should return an error (err u...) indicating no tickets sold + +;; Buy a ticket after a winner has been selected +;; Assuming a winner has been selected in a previous test +;; (contract-call? .lottery buy-ticket) +;; Should return an error (err u...) or start a new lottery round + +;; Get current ticket price +;; (contract-call? .lottery get-ticket-price) +;; Should return price of ticket + +;; Get total tickets sold +;; (contract-call? .lottery get-tickets-sold) +;; Should return the number of tickets sold (uint) + +;; Get current lottery pool +;; (contract-call? .lottery get-lottery-pool) +;; Should return the current amount in the lottery pool (uint) \ No newline at end of file diff --git a/contracts/ex8-sip009.clar b/contracts/ex8-sip009.clar new file mode 100644 index 0000000..c5c7f28 --- /dev/null +++ b/contracts/ex8-sip009.clar @@ -0,0 +1,23 @@ + +;; title: ex8-sip009 +;; version: 1.0.0 +;; summary: local sip-009 trait + +;; traits +;; + +(define-trait nft-trait + ( + ;; Last token ID, limited to uint range + (get-last-token-id () (response uint uint)) + + ;; URI for metadata associated with the token + (get-token-uri (uint) (response (optional (string-ascii 256)) uint)) + + ;; Owner of a given token identifier + (get-owner (uint) (response (optional principal) uint)) + + ;; Transfer from the sender to a new principal + (transfer (uint principal principal) (response bool uint)) + ) +) diff --git a/tests/ex8-01_clar.test.ts b/tests/ex8-01_clar.test.ts new file mode 100644 index 0000000..4bb9cf3 --- /dev/null +++ b/tests/ex8-01_clar.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/tests/ex8-02_clar.test.ts b/tests/ex8-02_clar.test.ts new file mode 100644 index 0000000..4bb9cf3 --- /dev/null +++ b/tests/ex8-02_clar.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/tests/ex8-sip009_clar.test.ts b/tests/ex8-sip009_clar.test.ts new file mode 100644 index 0000000..4bb9cf3 --- /dev/null +++ b/tests/ex8-sip009_clar.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); + // }); +});