@arcanetech/privacy-sdk-automatization-service keeps no state of its own. You pass ports: small objects whose methods the service calls. Every port method returns a Promise, except NoteDeriver.derive. serviceAccount is the Stellar account that signs each submitted transaction envelope. serviceScalar is the key that owns the pinned notes. Keep serviceScalar on the service host.

Where the implementations live

The /stellar entry runs on Node.js. See Wire the Stellar ports.

NoteDeriver

Returns the commitment and nullifier hash of a note plaintext. compose calls it for every pinned note, so derive each locked note for the service scalar. derive is synchronous because Plan editing calls it on every change.
SDK implementation: createStellarNoteDeriver(config) from /stellar. It derives every note from your service secret and a note salt. Persist the salt: a new salt changes every commitment, so Plans confirmed under the old salt no longer match.

PlanStore

Keeps confirmed Plans and everything needed to run them. PlanStore is seven role interfaces. Each use case takes only the roles it calls.
stepKey is ${rowIndex}:${role}. read throws PlanNotFoundError for an unknown id. rememberExecutedAt and recordAcceptedInitialQuote keep the first value they receive. Combine the roles with composePlanStore. Its cancel marks the Plan cancelled, then calls discard to drop the Plan’s Deposit authorizations and prepared Deposits. Each role ships as a memory part. Replace any part with your own:
composePlanStore does not wrap calls in a transaction. A confirm that fails halfway leaves the rows it already wrote. Run one use case at a time per Plan.
SDK implementation: createMemoryPlanStore() keeps everything in memory and numbers ids from plan-1. clear() empties it. To keep Plans across restarts, see Persist Plans.

Clock

Returns the current time. Intervals and execution times use the same unit.
SDK implementation: systemClock returns Date.now(), so intervals are milliseconds.

FeeQuotes

Quotes the fee for one Step. The service skips a Step whose quote is above its Free tokens. A changed quote before the Initial Deposit runs cancels the Plan.
SDK implementation: createKytFeeQuotes(config) from /stellar asks your compliance service for the required fee and caches each quote for one minute.

CurrentRoot and Presence

CurrentRoot returns the pool’s current Merkle root. Presence reports which pinned nullifier hashes are consumed and which pinned commitments are in the pool tree. runDueSteps reads one report for every Plan in the store.
SDK implementation: createSorobanPoolReader(config) from /stellar returns both ports. It reads the pool contract and the pinned notes of every Plan in the store, and caches each read for two seconds. Call forget() to read again at once.

Proofs

Builds the pool transaction for one Step. The request carries the Step’s pinned notes, the fee note, the Unspent note, the public amounts, and the recipient.
For a Deposit, return the current root and the Step’s pinned output commitments. Otherwise confirm and authorizeDeposit throw DepositAuthorizationMismatchError. SDK implementation: createStellarStepTransactions(config).proofs from /stellar.

FreshScalars

Returns a new owner scalar for each Unspent note. The service stores the scalar with the note.
SDK implementation: createStellarStepTransactions(config).freshScalars from /stellar.

Inspection

Runs the compliance check on a transaction before the service submits it. A refused Step is not submitted.
SDK implementation: createStellarStepTransactions(config).inspection from /stellar.

PoolSubmission

Submits a transaction to the pool. For a Deposit, the service passes the depositor’s authorization. Return ok: false when the pool does not accept it. The Step stays unsubmitted, and the next run tries again.
SDK implementation: createStellarStepTransactions(config).pool from /stellar.

DepositSigning

Returns the Soroban authorization entries the depositor signs for a Deposit. depositToSign calls it after the proof and the compliance check.
SDK implementation: createStellarStepTransactions(config).depositSigning from /stellar. Call setDepositor(account) first, so the Deposit spends from the depositor’s account.

NoteOwnership

Reports whether the service scalar owns a pinned note. confirm calls it for every locked note and throws UnownedNoteError when it returns false. Notes with no lock are skipped.
SDK implementation: createDerivedNoteOwnership(notes, serviceScalar) derives the note again with your NoteDeriver and compares the commitment and nullifier hash.

Test without a pool

createInMemoryPool(store) from /testing returns every pool port: currentRoot, presence, feeQuotes, freshScalars, proofs, inspection, pool, and depositSigning. It accepts every transaction and reports submitted notes as present. Pair it with inMemoryNoteDeriver.