Transactions
The SDK exposes one typed helper per current NOOSChain transaction type. These helpers use the same payload schemas as the chain executor through src/protocol/public-api.ts.
For bucket concepts, encryption modes, schemas, and permissions, see Data Buckets and Permission Model.
Example transaction REGISTER_ORGANIZATION:
await client.transactions.registerOrganization({
signer,
nonce: "auto",
payload: {
id: "org-example",
name: "Example Organization",
metadata: {},
},
});Use build for generic flows. This example builds transaction CREATE_BUCKET:
await client.transactions.build({
type: DomainTransactionType.CreateBucket,
signer,
nonce: 2n,
payload,
});nonce: "auto" resolves the next nonce from the node through GET /identity/nonce. The SDK sends the signer public key in x-noos-signer-public-key-base64, not in the URL query string. Use explicit nonces for offline signing, batch coordination, or air-gapped workflows.
Use submit(tx) to post the signed transaction to /transactions. The SDK never writes database rows directly.
Transaction CREATE_BUCKET field indexSchema.indexes[].type supports string, number, integer, float, boolean, date, and datetime. number is the backward-compatible finite JSON number type, integer rejects fractional values, and float accepts any finite JSON number. Use date for calendar-only YYYY-MM-DD values, and datetime for exact ISO-8601 UTC timestamps such as 2026-05-26T14:30:00.000Z.
Use updateBucketIndexSchema for compatible public-index schema evolution. This builds transaction UPDATE_BUCKET_INDEX_SCHEMA:
await client.transactions.updateBucketIndexSchema({
signer,
nonce: "auto",
payload: {
bucketId: "bucket-project-data",
mode: "compatible",
indexSchema: {
indexes: [
{ key: "projectId", type: "string", required: true },
{ key: "score", type: "float" },
],
},
},
});The chain accepts optional fields and widened allowedValues. It rejects removing fields, changing types, adding required fields, changing requiredness, or narrowing allowedValues. Updates affect future record validation and search validation only; historical records are not rewritten.
Encrypted Records From Plaintext
For browser/public API clients, prefer addEncryptedRecordFromPlaintext(...) or submitAddEncryptedRecordFromPlaintext(...) instead of collecting transaction ADD_ENCRYPTED_RECORD low-level JSON from users.
const { transaction, submission } =
await client.transactions.submitAddEncryptedRecordFromPlaintext({
signer,
payload: {
bucketId: "bucket-project-data",
plaintextUtf8: JSON.stringify({ private: "payload" }),
},
publicQueryData: {
projectId: "project-a",
reviewed: true,
},
actorPublicKey: signer.publicKey,
});The helper performs the frontend work for encrypted records:
- calls
POST /buckets/:id/records/prepare-add-encrypted-recordwith the actor public key and plaintext; - lets the node verify
bucket:write, generate a raw UUID record id, encrypt the payload, calculatepayloadHash, and derive record envelopes or bucket-key references; - receives a short-lived
preparedTransactionIdand exact unsigned transactionADD_ENCRYPTED_RECORDenvelope; - signs that exact envelope;
- submits the signed transaction to
/transactionswith thepreparedTransactionId.
The node rejects altered, expired, reused, or unprepared transaction ADD_ENCRYPTED_RECORD submissions. The prepare endpoint also rejects client-supplied record ids; deterministic record ids are not supported by this public write flow. For per_record_key, the prepared transaction carries record-level key envelopes for the generated record DEK. For per_bucket_key, record-level key envelopes are normally empty; the prepared transaction references the active bucketKeyId/bucketKeyVersion, and the SDK does not receive bucket-key envelopes during write preparation.
The SDK does not send user private keys to the node. Plaintext does reach the API in this prepared write flow, and the API temporarily sees generated per-record DEKs unless encryption is moved behind KMS/HSM/enclave custody. Choose this helper only when that trust boundary is acceptable for the application.
Tests
Run the SDK transaction tests from the repository root:
npm run nooschain-ts:testThe prepared encrypted-record regression coverage lives in apps/nooschain-ts/test/sdk.test.ts. It verifies that the plaintext helper:
- calls
POST /buckets/:id/records/prepare-add-encrypted-record; - sends the actor public key and plaintext to the prepare endpoint;
- does not send a client-generated record id;
- does not call the legacy
encrypted-wrap-dekpath; - signs the exact prepared transaction
ADD_ENCRYPTED_RECORDenvelope; - submits the signed transaction to
/transactionswith the returnedpreparedTransactionId.
Run npm run nooschain-ts:build after changing exported SDK types, and npm run typecheck when the change may affect monorepo consumers such as apps/noos-web-gui.