@invariance/sdk 0.0.1 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -36,7 +36,7 @@ import {
36
36
  pricingTypeToEnum,
37
37
  toBytes32,
38
38
  waitForReceipt
39
- } from "./chunk-3ONNY6AX.js";
39
+ } from "./chunk-2JGPNHE3.js";
40
40
  import {
41
41
  InvarianceAtomicVerifierAbi,
42
42
  InvarianceCompactLedgerAbi,
@@ -74,6 +74,7 @@ var ABI_MAP = {
74
74
  atomicVerifier: InvarianceAtomicVerifierAbi,
75
75
  voting: InvarianceVotingAbi
76
76
  };
77
+ var ZERO_ADDRESS = "0x0000000000000000000000000000000000000000";
77
78
  var ADDRESS_KEY_MAP = {
78
79
  identity: "identity",
79
80
  policy: "policy",
@@ -167,6 +168,12 @@ var ContractFactory = class {
167
168
  `Contract address not configured: ${name}`
168
169
  );
169
170
  }
171
+ if (addr === ZERO_ADDRESS) {
172
+ throw new InvarianceError(
173
+ ErrorCode.NETWORK_ERROR,
174
+ `Contract address for ${name} is the zero address. Contracts may not be deployed on this chain yet.`
175
+ );
176
+ }
170
177
  return addr;
171
178
  }
172
179
  /**
@@ -5012,7 +5019,7 @@ var AutoBatchedEventLedgerCompact = class {
5012
5019
  const optimistic = this.contracts.getConfirmation() === "optimistic";
5013
5020
  const receiptClient = this.contracts.getReceiptClient();
5014
5021
  const receipt = await waitForReceipt(receiptClient, txHash, { optimistic });
5015
- const { parseCompactEntryIdFromLogs: parseCompactEntryIdFromLogs2 } = await import("./contract-helpers-XI4NOQLS.js");
5022
+ const { parseCompactEntryIdFromLogs: parseCompactEntryIdFromLogs2 } = await import("./contract-helpers-2XZGNKCO.js");
5016
5023
  const entryId = optimistic ? toBytes32(txHash) : parseCompactEntryIdFromLogs2(receipt.logs);
5017
5024
  const explorerBase = this.contracts.getExplorerBaseUrl();
5018
5025
  const result = {
@@ -8175,8 +8182,189 @@ var VotingManager = class {
8175
8182
  }
8176
8183
  };
8177
8184
 
8185
+ // src/modules/ledger/OffchainLedger.ts
8186
+ var OffchainLedger = class {
8187
+ events;
8188
+ telemetry;
8189
+ failOpen;
8190
+ adapter;
8191
+ constructor(events, telemetry, options) {
8192
+ this.events = events;
8193
+ this.telemetry = telemetry;
8194
+ this.adapter = options.adapter;
8195
+ this.failOpen = options.failOpen ?? true;
8196
+ }
8197
+ /**
8198
+ * Log a ledger event.
8199
+ *
8200
+ * @param event - Same `LedgerEventInput` used by on-chain ledger
8201
+ * @returns The created off-chain ledger entry
8202
+ */
8203
+ async log(event) {
8204
+ this.telemetry.track("offchain_ledger.log", { action: event.action });
8205
+ const entryId = crypto.randomUUID();
8206
+ const timestamp = Date.now();
8207
+ const category = event.category ?? "custom";
8208
+ const severity = event.severity ?? "info";
8209
+ const entry = {
8210
+ entryId,
8211
+ action: event.action,
8212
+ actor: event.actor,
8213
+ category,
8214
+ severity,
8215
+ timestamp,
8216
+ createdAt: new Date(timestamp).toISOString()
8217
+ };
8218
+ if (event.metadata) {
8219
+ entry.metadata = event.metadata;
8220
+ }
8221
+ try {
8222
+ const persisted = await this.adapter.insert(entry);
8223
+ this.events.emit("ledger.logged", { entryId: persisted.entryId, action: persisted.action });
8224
+ return persisted;
8225
+ } catch (err) {
8226
+ if (this.failOpen) {
8227
+ this.events.emit("ledger.logged", { entryId: entry.entryId, action: entry.action });
8228
+ return entry;
8229
+ }
8230
+ throw err;
8231
+ }
8232
+ }
8233
+ /**
8234
+ * Query off-chain ledger entries.
8235
+ *
8236
+ * @param filters - Same `LedgerQueryFilters` used by on-chain ledger
8237
+ * @returns Matching off-chain ledger entries
8238
+ */
8239
+ async query(filters) {
8240
+ this.telemetry.track("offchain_ledger.query", { action: filters.action });
8241
+ try {
8242
+ return await this.adapter.query(filters);
8243
+ } catch (err) {
8244
+ if (this.failOpen) {
8245
+ return [];
8246
+ }
8247
+ throw err;
8248
+ }
8249
+ }
8250
+ };
8251
+
8252
+ // src/modules/ledger/adapters/SupabaseLedgerAdapter.ts
8253
+ var TABLE_NAME = "offchain_ledger_entries";
8254
+ var SupabaseLedgerAdapter = class _SupabaseLedgerAdapter {
8255
+ url;
8256
+ key;
8257
+ client = null;
8258
+ clientPromise = null;
8259
+ constructor(options) {
8260
+ this.url = options.url;
8261
+ this.key = options.key;
8262
+ }
8263
+ /** @internal */
8264
+ async getClient() {
8265
+ if (this.client) return this.client;
8266
+ if (this.clientPromise) return this.clientPromise;
8267
+ this.clientPromise = (async () => {
8268
+ try {
8269
+ const { createClient } = await import("@supabase/supabase-js");
8270
+ this.client = createClient(this.url, this.key);
8271
+ return this.client;
8272
+ } catch {
8273
+ throw new InvarianceError(
8274
+ ErrorCode.NETWORK_ERROR,
8275
+ "Failed to import @supabase/supabase-js. Install it with: npm install @supabase/supabase-js"
8276
+ );
8277
+ }
8278
+ })();
8279
+ return this.clientPromise;
8280
+ }
8281
+ /** Persist a ledger entry to Supabase. */
8282
+ async insert(entry) {
8283
+ const row = {
8284
+ entry_id: entry.entryId,
8285
+ action: entry.action,
8286
+ actor_type: entry.actor.type,
8287
+ actor_address: entry.actor.address,
8288
+ category: entry.category,
8289
+ severity: entry.severity,
8290
+ metadata: entry.metadata ?? null,
8291
+ timestamp: entry.timestamp
8292
+ };
8293
+ const client = await this.getClient();
8294
+ const { data, error } = await client.from(TABLE_NAME).insert(row).select().single();
8295
+ if (error) {
8296
+ throw new InvarianceError(ErrorCode.NETWORK_ERROR, `Supabase insert failed: ${error.message}`);
8297
+ }
8298
+ return _SupabaseLedgerAdapter.toEntry(data);
8299
+ }
8300
+ /** Query ledger entries from Supabase. */
8301
+ async query(filters) {
8302
+ const client = await this.getClient();
8303
+ let q = client.from(TABLE_NAME).select("*");
8304
+ if (filters.actor) {
8305
+ q = q.eq("actor_address", filters.actor);
8306
+ }
8307
+ if (filters.actorType) {
8308
+ q = q.eq("actor_type", filters.actorType);
8309
+ }
8310
+ if (filters.action) {
8311
+ if (Array.isArray(filters.action)) {
8312
+ q = q.in("action", filters.action);
8313
+ } else {
8314
+ q = q.eq("action", filters.action);
8315
+ }
8316
+ }
8317
+ if (filters.category) {
8318
+ q = q.eq("category", filters.category);
8319
+ }
8320
+ if (filters.from !== void 0) {
8321
+ const fromTs = typeof filters.from === "string" ? new Date(filters.from).getTime() : filters.from;
8322
+ q = q.gte("timestamp", fromTs);
8323
+ }
8324
+ if (filters.to !== void 0) {
8325
+ const toTs = typeof filters.to === "string" ? new Date(filters.to).getTime() : filters.to;
8326
+ q = q.lte("timestamp", toTs);
8327
+ }
8328
+ const orderCol = filters.orderBy ?? "timestamp";
8329
+ const ascending = (filters.order ?? "desc") === "asc";
8330
+ q = q.order(orderCol, { ascending });
8331
+ if (filters.limit) {
8332
+ q = q.limit(filters.limit);
8333
+ }
8334
+ if (filters.offset) {
8335
+ q = q.range(filters.offset, filters.offset + (filters.limit ?? 100) - 1);
8336
+ }
8337
+ const { data, error } = await q;
8338
+ if (error) {
8339
+ throw new InvarianceError(ErrorCode.NETWORK_ERROR, `Supabase query failed: ${error.message}`);
8340
+ }
8341
+ return data.map(
8342
+ (row) => _SupabaseLedgerAdapter.toEntry(row)
8343
+ );
8344
+ }
8345
+ /** Map a Supabase row to an OffchainLedgerEntry. */
8346
+ static toEntry(row) {
8347
+ const entry = {
8348
+ entryId: row["entry_id"],
8349
+ action: row["action"],
8350
+ actor: {
8351
+ type: row["actor_type"],
8352
+ address: row["actor_address"]
8353
+ },
8354
+ category: row["category"],
8355
+ severity: row["severity"],
8356
+ timestamp: row["timestamp"],
8357
+ createdAt: row["created_at"]
8358
+ };
8359
+ if (row["metadata"] != null) {
8360
+ entry.metadata = row["metadata"];
8361
+ }
8362
+ return entry;
8363
+ }
8364
+ };
8365
+
8178
8366
  // src/core/InvarianceClient.ts
8179
- var SDK_VERSION = "0.0.1";
8367
+ var SDK_VERSION = "0.1.1";
8180
8368
  var Invariance = class _Invariance {
8181
8369
  config;
8182
8370
  contracts;
@@ -8201,6 +8389,7 @@ var Invariance = class _Invariance {
8201
8389
  _marketplace;
8202
8390
  _auditTrail;
8203
8391
  _voting;
8392
+ _ledgerOffchain;
8204
8393
  // ===========================================================================
8205
8394
  // Static Factory Methods
8206
8395
  // ===========================================================================
@@ -8579,6 +8768,39 @@ var Invariance = class _Invariance {
8579
8768
  }
8580
8769
  return this._auditTrail;
8581
8770
  }
8771
+ /**
8772
+ * Off-chain ledger module backed by a pluggable {@link LedgerAdapter}.
8773
+ *
8774
+ * Same `LedgerEventInput` interface as on-chain, zero gas.
8775
+ * Resolution order: `config.ledgerAdapter` > `config.supabase` > env vars.
8776
+ *
8777
+ * @example
8778
+ * ```typescript
8779
+ * const entry = await inv.ledgerOffchain.log({
8780
+ * action: 'model-inference',
8781
+ * actor: { type: 'agent', address: '0xBot' },
8782
+ * });
8783
+ * ```
8784
+ */
8785
+ get ledgerOffchain() {
8786
+ if (!this._ledgerOffchain) {
8787
+ let adapter = this.config.ledgerAdapter;
8788
+ if (!adapter) {
8789
+ const url = this.config.supabase?.url ?? process.env["INVARIANCE_SUPABASE_URL"];
8790
+ const key = this.config.supabase?.key ?? process.env["INVARIANCE_SUPABASE_KEY"];
8791
+ if (!url || !key) {
8792
+ throw new InvarianceError(
8793
+ ErrorCode.INVALID_INPUT,
8794
+ "Off-chain ledger requires either config.ledgerAdapter, config.supabase (url + key), or INVARIANCE_SUPABASE_URL / INVARIANCE_SUPABASE_KEY env vars."
8795
+ );
8796
+ }
8797
+ adapter = new SupabaseLedgerAdapter({ url, key });
8798
+ }
8799
+ const failOpen = this.config.supabase?.failOpen ?? true;
8800
+ this._ledgerOffchain = new OffchainLedger(this.events, this.telemetry, { adapter, failOpen });
8801
+ }
8802
+ return this._ledgerOffchain;
8803
+ }
8582
8804
  /**
8583
8805
  * Off-chain batch voting with merkle root settlement.
8584
8806
  *
@@ -9143,6 +9365,59 @@ var Invariance = class _Invariance {
9143
9365
  }
9144
9366
  };
9145
9367
 
9368
+ // src/modules/ledger/adapters/InMemoryLedgerAdapter.ts
9369
+ var InMemoryLedgerAdapter = class {
9370
+ /** @internal */
9371
+ entries = [];
9372
+ async insert(entry) {
9373
+ this.entries.push(entry);
9374
+ return entry;
9375
+ }
9376
+ async query(filters) {
9377
+ let results = [...this.entries];
9378
+ if (filters.actor) {
9379
+ results = results.filter((e) => e.actor.address === filters.actor);
9380
+ }
9381
+ if (filters.actorType) {
9382
+ results = results.filter((e) => e.actor.type === filters.actorType);
9383
+ }
9384
+ if (filters.action) {
9385
+ if (Array.isArray(filters.action)) {
9386
+ results = results.filter((e) => filters.action.includes(e.action));
9387
+ } else {
9388
+ results = results.filter((e) => e.action === filters.action);
9389
+ }
9390
+ }
9391
+ if (filters.category) {
9392
+ results = results.filter((e) => e.category === filters.category);
9393
+ }
9394
+ if (filters.from !== void 0) {
9395
+ const fromTs = typeof filters.from === "string" ? new Date(filters.from).getTime() : filters.from;
9396
+ results = results.filter((e) => e.timestamp >= fromTs);
9397
+ }
9398
+ if (filters.to !== void 0) {
9399
+ const toTs = typeof filters.to === "string" ? new Date(filters.to).getTime() : filters.to;
9400
+ results = results.filter((e) => e.timestamp <= toTs);
9401
+ }
9402
+ const ascending = (filters.order ?? "desc") === "asc";
9403
+ const orderBy = filters.orderBy ?? "timestamp";
9404
+ results.sort((a, b) => {
9405
+ const aVal = a[orderBy];
9406
+ const bVal = b[orderBy];
9407
+ if (aVal < bVal) return ascending ? -1 : 1;
9408
+ if (aVal > bVal) return ascending ? 1 : -1;
9409
+ return 0;
9410
+ });
9411
+ if (filters.offset) {
9412
+ results = results.slice(filters.offset);
9413
+ }
9414
+ if (filters.limit) {
9415
+ results = results.slice(0, filters.limit);
9416
+ }
9417
+ return results;
9418
+ }
9419
+ };
9420
+
9146
9421
  // src/utils/webhook.ts
9147
9422
  import { createHmac, timingSafeEqual } from "crypto";
9148
9423
  function verifyWebhookSignature(body, signature, secret) {
@@ -10104,6 +10379,7 @@ export {
10104
10379
  GovernmentComplianceKit,
10105
10380
  IdentityGatekeeper,
10106
10381
  IdentityManager,
10382
+ InMemoryLedgerAdapter,
10107
10383
  IntentProtocol,
10108
10384
  Invariance,
10109
10385
  InvarianceError,
@@ -10113,6 +10389,7 @@ export {
10113
10389
  MarketplaceKit,
10114
10390
  MarketplacePlugin,
10115
10391
  MultiAgentComposer,
10392
+ OffchainLedger,
10116
10393
  PipelineBuilder,
10117
10394
  PolicyEngine,
10118
10395
  ReputationBridge,
@@ -10121,8 +10398,10 @@ export {
10121
10398
  SDK_VERSION,
10122
10399
  SessionContext,
10123
10400
  SocialGraphAdapter,
10401
+ SupabaseLedgerAdapter,
10124
10402
  Telemetry,
10125
10403
  Verifier,
10404
+ VotingManager,
10126
10405
  WalletManager,
10127
10406
  X402Manager,
10128
10407
  generatePrivateKey2 as generatePrivateKey,