Tag Sync Script (NomiScript)

Introduction

NomiScript version of the tag synchronization script. When a transaction is created with exactly two splits, this script copies tags bidirectionally:

  • Transaction has tags, splits don't -> copy to both splits
  • Split has tags, transaction doesn't -> copy to transaction

This demonstrates the NomiScript entity API: context queries, entity iteration, tag accessors, and output functions. Compare with the Rust SDK version.

Trigger function

Only run when the primary entity is a transaction:

(defun should-apply ()
    (= (primary-entity-type) +entity-transaction+))

Helper: collect entity indices by type and parent

Build a cons list of entity indices matching a given type and parent:

(defun entities-for (parent-idx entity-type-val)
    (let ((result nil))
        (do ((i 0 (+ i 1)))
            ((>= i (entity-count)) result)
            (when (and (= (entity-type i) entity-type-val)
                       (= (entity-parent-idx i) parent-idx))
                (setf result (cons i result))))))

Helper: count list length

(defun list-length (lst)
    (let ((count 0))
        (dolist (e lst)
            (setf count (+ count 1)))
        count))

Helper: check if a tag is a user tag

The "note" tag is a system tag set by the transaction form and should not count as a user tag for synchronization purposes:

(defun user-tag? (idx)
    (not (string= (tag-name idx) "note")))

Helper: copy user tags from one entity to another

(defun copy-tags (source-idx target-idx)
    (dolist (tag (entities-for source-idx +entity-tag+))
        (when (user-tag? tag)
            (create-tag target-idx (tag-name tag) (tag-value tag)))))

Helper: collect user tag indices for an entity

(defun user-tags-for (parent-idx)
    (let ((result nil))
        (dolist (tag (entities-for parent-idx +entity-tag+))
            (when (user-tag? tag)
                (setf result (cons tag result))))
        result))

Main logic

(let* ((tx-idx (primary-entity-idx))
       (splits (entities-for tx-idx +entity-split+))
       (tx-tags (user-tags-for tx-idx)))
    (when (= (list-length splits) 2)
        (let* ((s0 (car splits))
               (s1 (car (cdr splits)))
               (s0-tags (entities-for s0 +entity-tag+))
               (s1-tags (entities-for s1 +entity-tag+)))
            (cond
                ;; Transaction has tags, splits don't -> copy to splits
                ((and (not (null? tx-tags)) (null? s0-tags) (null? s1-tags))
                 (dolist (tag tx-tags)
                     (create-tag s0 (tag-name tag) (tag-value tag))
                     (create-tag s1 (tag-name tag) (tag-value tag))))
                ;; Split has tags, transaction doesn't -> copy to transaction
                ((and (null? tx-tags) (not (null? s0-tags)))
                 (copy-tags s0 tx-idx))
                ((and (null? tx-tags) (not (null? s1-tags)))
                 (copy-tags s1 tx-idx))))))