Source Code

;; xWallet - Simple Custodial STX Wallet Contract

;; Error constants
(define-constant ERR-INSUFFICIENT-BALANCE (err u100))
(define-constant ERR-ZERO-AMOUNT (err u101))
(define-constant ERR-SELF-SEND (err u102))
(define-constant ERR-TRANSFER-FAILED (err u103))

;; Data maps
(define-map balances principal uint)

;; Private helper: get balance or default to 0
(define-private (get-balance-or-default (user principal))
  (default-to u0 (map-get? balances user))
)

;; Read-only: get user balance
(define-read-only (get-balance (user principal))
  (ok (get-balance-or-default user))
)

;; Public: deposit STX into the contract
(define-public (deposit (amount uint))
  (let
    (
      (sender tx-sender)
      (current-balance (get-balance-or-default sender))
    )
    ;; Check for zero amount
    (asserts! (> amount u0) ERR-ZERO-AMOUNT)
    
    ;; Transfer STX from sender to contract BEFORE updating balance
    (match (stx-transfer? amount sender contract-caller)
      success (begin
        ;; Update sender's balance
        (map-set balances sender (+ current-balance amount))
        (ok amount)
      )
      error ERR-TRANSFER-FAILED
    )
  )
)

;; Public: send STX from your balance to another principal
(define-public (send-stx (amount uint) (recipient principal))
  (let
    (
      (sender tx-sender)
      (sender-balance (get-balance-or-default sender))
    )
    ;; Check for zero amount
    (asserts! (> amount u0) ERR-ZERO-AMOUNT)
    
    ;; Prevent self-send (use withdraw instead)
    (asserts! (not (is-eq sender recipient)) ERR-SELF-SEND)
    
    ;; Check sufficient balance
    (asserts! (>= sender-balance amount) ERR-INSUFFICIENT-BALANCE)
    
    ;; Transfer STX from contract to recipient BEFORE updating balances
    (try! (stx-transfer? amount tx-sender recipient))
    
    ;; Deduct from sender's balance
    (map-set balances sender (- sender-balance amount))
    ;; Add to recipient's balance
    (map-set balances recipient (+ (get-balance-or-default recipient) amount))
    (ok amount)
  )
)

;; Public: withdraw STX from your balance back to your address
(define-public (withdraw (amount uint))
  (let
    (
      (sender tx-sender)
      (sender-balance (get-balance-or-default sender))
    )
    ;; Check for zero amount
    (asserts! (> amount u0) ERR-ZERO-AMOUNT)
    
    ;; Check sufficient balance
    (asserts! (>= sender-balance amount) ERR-INSUFFICIENT-BALANCE)
    
    ;; Transfer STX from contract to sender BEFORE updating balance
    (try! (stx-transfer? amount tx-sender sender))
    
    ;; Deduct from sender's balance
    (map-set balances sender (- sender-balance amount))
    (ok amount)
  )
)

Functions (5)

FunctionAccessArgs
get-balance-or-defaultprivateuser: principal
get-balanceread-onlyuser: principal
depositpublicamount: uint
send-stxpublicamount: uint, recipient: principal
withdrawpublicamount: uint