Source Code

;; Book Publishing Contract v2

;; --- Error Constants ---
(define-constant ERR_NOT_AUTHOR (err u1001))
(define-constant ERR_BOOK_EXISTS (err u1002))
(define-constant ERR_BOOK_NOT_FOUND (err u1003))
(define-constant ERR_INVALID_INPUT (err u1004))
(define-constant ERR_PAGE_OUT_OF_BOUNDS (err u1005))

;; --- Book ID Counter ---
(define-data-var last-book-id uint u0)

;; --- Book Metadata Map: book-id -> book info ---
(define-map books uint {
    author: principal,
    title: (string-utf8 64),
    description: (string-utf8 256)
})

;; --- Pages Map: (book-id, page-number) -> content ---
(define-map book-pages (tuple (book-id uint) (page uint)) (string-utf8 2048))

;; --- Chapter Map: (book-id, chapter) -> start-page (uint) ---
(define-map chapters (tuple (book-id uint) (chapter uint)) uint)

;; --- Read-Only Functions ---

(define-read-only (get-book-by-id (book-id uint))
    (map-get? books book-id)
)

(define-read-only (get-page (book-id uint) (page uint))
    (map-get? book-pages { book-id: book-id, page: page })
)

(define-read-only (get-chapter-start-page (book-id uint) (chapter uint))
    (map-get? chapters { book-id: book-id, chapter: chapter })
)

(define-read-only (get-last-book-id)
    (var-get last-book-id)
)

;; --- Public Functions ---

(define-public (publish-book
    (title (string-utf8 64))
    (description (string-utf8 256))
)
    (let (
        (book-id (+ (var-get last-book-id) u1))
        (caller tx-sender)
    )
        ;; Validate input
        (asserts! (> (len title) u0) ERR_INVALID_INPUT)
        (asserts! (> (len description) u0) ERR_INVALID_INPUT)

        ;; Save metadata
        (map-set books book-id {
            author: caller,
            title: title,
            description: description
        })

        ;; Update counter
        (var-set last-book-id book-id)

        (ok book-id)
    )
)

(define-public (edit-book-meta
    (book-id uint)
    (new-title (string-utf8 64))
    (new-description (string-utf8 256))
)
    (let (
        (caller tx-sender)
        (book (unwrap! (map-get? books book-id) ERR_BOOK_NOT_FOUND))
    )
        (asserts! (is-eq caller (get author book)) ERR_NOT_AUTHOR)
        (asserts! (> (len new-title) u0) ERR_INVALID_INPUT)
        (asserts! (> (len new-description) u0) ERR_INVALID_INPUT)

        (map-set books book-id {
            author: (get author book),
            title: new-title,
            description: new-description
        })

        (ok true)
    )
)

(define-public (add-or-edit-page
    (book-id uint)
    (page-number uint)
    (content (string-utf8 2048))
)
    (let (
        (caller tx-sender)
        (book (unwrap! (map-get? books book-id) ERR_BOOK_NOT_FOUND))
    )
        (asserts! (is-eq caller (get author book)) ERR_NOT_AUTHOR)
        (asserts! (> (len content) u0) ERR_INVALID_INPUT)

        (map-set book-pages { book-id: book-id, page: page-number } content)

        (ok true)
    )
)

(define-public (set-chapter
    (book-id uint)
    (chapter-number uint)
    (start-page uint)
)
    (let (
        (caller tx-sender)
        (book (unwrap! (map-get? books book-id) ERR_BOOK_NOT_FOUND))
    )
        (asserts! (is-eq caller (get author book)) ERR_NOT_AUTHOR)

        (map-set chapters { book-id: book-id, chapter: chapter-number } start-page)

        (ok true)
    )
)

Functions (7)

FunctionAccessArgs
get-book-by-idread-onlybook-id: uint
get-pageread-onlybook-id: uint, page: uint
get-chapter-start-pageread-onlybook-id: uint, chapter: uint
get-last-book-idread-only
publish-bookpublictitle: (string-utf8 64
edit-book-metapublicbook-id: uint, new-title: (string-utf8 64
add-or-edit-pagepublicbook-id: uint, page-number: uint, content: (string-utf8 2048