web3ql-client 1.2.0

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.
Files changed (86) hide show
  1. package/README.md +66 -0
  2. package/contracts/PublicKeyRegistry.sol +87 -0
  3. package/dist/src/access.d.ts +176 -0
  4. package/dist/src/access.d.ts.map +1 -0
  5. package/dist/src/access.js +283 -0
  6. package/dist/src/access.js.map +1 -0
  7. package/dist/src/batch.d.ts +107 -0
  8. package/dist/src/batch.d.ts.map +1 -0
  9. package/dist/src/batch.js +188 -0
  10. package/dist/src/batch.js.map +1 -0
  11. package/dist/src/cli.d.ts +40 -0
  12. package/dist/src/cli.d.ts.map +1 -0
  13. package/dist/src/cli.js +361 -0
  14. package/dist/src/cli.js.map +1 -0
  15. package/dist/src/constraints.d.ts +126 -0
  16. package/dist/src/constraints.d.ts.map +1 -0
  17. package/dist/src/constraints.js +192 -0
  18. package/dist/src/constraints.js.map +1 -0
  19. package/dist/src/crypto.d.ts +118 -0
  20. package/dist/src/crypto.d.ts.map +1 -0
  21. package/dist/src/crypto.js +192 -0
  22. package/dist/src/crypto.js.map +1 -0
  23. package/dist/src/factory-client.d.ts +106 -0
  24. package/dist/src/factory-client.d.ts.map +1 -0
  25. package/dist/src/factory-client.js +202 -0
  26. package/dist/src/factory-client.js.map +1 -0
  27. package/dist/src/index-cache.d.ts +156 -0
  28. package/dist/src/index-cache.d.ts.map +1 -0
  29. package/dist/src/index-cache.js +265 -0
  30. package/dist/src/index-cache.js.map +1 -0
  31. package/dist/src/index.d.ts +60 -0
  32. package/dist/src/index.d.ts.map +1 -0
  33. package/dist/src/index.js +60 -0
  34. package/dist/src/index.js.map +1 -0
  35. package/dist/src/migrations.d.ts +114 -0
  36. package/dist/src/migrations.d.ts.map +1 -0
  37. package/dist/src/migrations.js +173 -0
  38. package/dist/src/migrations.js.map +1 -0
  39. package/dist/src/model.d.ts +198 -0
  40. package/dist/src/model.d.ts.map +1 -0
  41. package/dist/src/model.js +379 -0
  42. package/dist/src/model.js.map +1 -0
  43. package/dist/src/query.d.ts +155 -0
  44. package/dist/src/query.d.ts.map +1 -0
  45. package/dist/src/query.js +386 -0
  46. package/dist/src/query.js.map +1 -0
  47. package/dist/src/registry.d.ts +45 -0
  48. package/dist/src/registry.d.ts.map +1 -0
  49. package/dist/src/registry.js +80 -0
  50. package/dist/src/registry.js.map +1 -0
  51. package/dist/src/schema-manager.d.ts +109 -0
  52. package/dist/src/schema-manager.d.ts.map +1 -0
  53. package/dist/src/schema-manager.js +259 -0
  54. package/dist/src/schema-manager.js.map +1 -0
  55. package/dist/src/table-client.d.ts +156 -0
  56. package/dist/src/table-client.d.ts.map +1 -0
  57. package/dist/src/table-client.js +292 -0
  58. package/dist/src/table-client.js.map +1 -0
  59. package/dist/src/typed-table.d.ts +159 -0
  60. package/dist/src/typed-table.d.ts.map +1 -0
  61. package/dist/src/typed-table.js +246 -0
  62. package/dist/src/typed-table.js.map +1 -0
  63. package/dist/src/types.d.ts +48 -0
  64. package/dist/src/types.d.ts.map +1 -0
  65. package/dist/src/types.js +222 -0
  66. package/dist/src/types.js.map +1 -0
  67. package/keyManager.js +337 -0
  68. package/package.json +38 -0
  69. package/src/access.ts +421 -0
  70. package/src/batch.ts +259 -0
  71. package/src/cli.ts +349 -0
  72. package/src/constraints.ts +283 -0
  73. package/src/crypto.ts +239 -0
  74. package/src/factory-client.ts +237 -0
  75. package/src/index-cache.ts +351 -0
  76. package/src/index.ts +171 -0
  77. package/src/migrations.ts +215 -0
  78. package/src/model.ts +538 -0
  79. package/src/query.ts +508 -0
  80. package/src/registry.ts +100 -0
  81. package/src/schema-manager.ts +301 -0
  82. package/src/table-client.ts +393 -0
  83. package/src/typed-table.ts +340 -0
  84. package/src/types.ts +284 -0
  85. package/tsconfig.json +22 -0
  86. package/walletUtils.js +204 -0
@@ -0,0 +1,259 @@
1
+ /**
2
+ * @file schema-manager.ts
3
+ * @notice Web3QL v1.2 — schema management: drop tables, rename, introspection.
4
+ *
5
+ * Schema is stored as ABI-encoded bytes in the database contract.
6
+ * This module provides:
7
+ *
8
+ * 1. SCHEMA INTROSPECTION — decode raw schema bytes → FieldDescriptor[]
9
+ * 2. DROP TABLE — bulk delete all owner records, then rename table to __dropped__
10
+ * 3. RENAME TABLE — soft-rename via a meta record (contract doesn't support rename natively)
11
+ * 4. SCHEMA DIFF — compare two schemas, produce a list of changes
12
+ * 5. SCHEMA VERSION — read + write the schema version stored in a meta record
13
+ *
14
+ * Usage:
15
+ * ─────────────────────────────────────────────────────────────
16
+ * const mgr = new SchemaManager(db, tableAddress, tableClient);
17
+ *
18
+ * // Inspect a deployed table's schema
19
+ * const fields = await mgr.introspect();
20
+ *
21
+ * // Diff two versions
22
+ * const changes = diffSchema(oldFields, newFields);
23
+ *
24
+ * // Soft-drop: mark table as dropped + purge all owner records
25
+ * await mgr.dropTable(ownerAddress);
26
+ *
27
+ * // Soft-rename: store alias mapping in meta record
28
+ * await mgr.renameTable('users', 'app_users');
29
+ * ─────────────────────────────────────────────────────────────
30
+ */
31
+ import { ethers } from 'ethers';
32
+ // ─────────────────────────────────────────────────────────────
33
+ // Schema introspection
34
+ // ─────────────────────────────────────────────────────────────
35
+ /**
36
+ * Minimal ABI type tags used in Web3QL schema encoding.
37
+ * Must stay in sync with protocol/compiler/generator.ts.
38
+ */
39
+ const SOLIDITY_TO_FIELD_TYPE = {
40
+ 'uint256': 'INT',
41
+ 'int256': 'INT',
42
+ 'int64': 'INT',
43
+ 'uint64': 'UINT64',
44
+ 'uint32': 'UINT32',
45
+ 'uint16': 'UINT16',
46
+ 'uint8': 'UINT8',
47
+ 'string': 'TEXT',
48
+ 'bool': 'BOOL',
49
+ 'address': 'ADDRESS',
50
+ 'bytes32': 'BYTES32',
51
+ 'bytes': 'BYTES32',
52
+ };
53
+ /**
54
+ * Decode raw schema bytes from the contract into an array of FieldDescriptors.
55
+ *
56
+ * Web3QL encodes schema as ABI-encoded:
57
+ * tuple(string name, string solidityType, bool primaryKey, bool notNull)[]
58
+ *
59
+ * This mirrors protocol/compiler/generator.ts compileSchema().
60
+ */
61
+ export function decodeSchemaBytes(schemaBytes) {
62
+ try {
63
+ const bytes = typeof schemaBytes === 'string' ? ethers.getBytes(schemaBytes) : schemaBytes;
64
+ if (bytes.length === 0)
65
+ return [];
66
+ const abiCoder = ethers.AbiCoder.defaultAbiCoder();
67
+ const decoded = abiCoder.decode(['tuple(string name, string solidityType, bool primaryKey, bool notNull)[]'], bytes);
68
+ const fields = decoded[0];
69
+ return fields.map((f) => ({
70
+ name: f.name,
71
+ type: (SOLIDITY_TO_FIELD_TYPE[f.solidityType] ?? 'TEXT'),
72
+ primaryKey: f.primaryKey || undefined,
73
+ notNull: f.notNull || undefined,
74
+ }));
75
+ }
76
+ catch {
77
+ return [];
78
+ }
79
+ }
80
+ /**
81
+ * Compute the diff between two schema versions.
82
+ * Returns an ordered list of changes from `from` → `to`.
83
+ */
84
+ export function diffSchema(from, to) {
85
+ const changes = [];
86
+ const fromMap = new Map(from.map((f) => [f.name, f]));
87
+ const toMap = new Map(to.map((f) => [f.name, f]));
88
+ // Added or changed
89
+ for (const [name, toField] of toMap) {
90
+ const fromField = fromMap.get(name);
91
+ if (!fromField) {
92
+ changes.push({ type: 'added', column: name, newValue: toField.type });
93
+ }
94
+ else {
95
+ if (fromField.type !== toField.type) {
96
+ changes.push({ type: 'typeChanged', column: name, oldValue: fromField.type, newValue: toField.type });
97
+ }
98
+ if (Boolean(fromField.notNull) !== Boolean(toField.notNull)) {
99
+ changes.push({
100
+ type: 'notNullChanged',
101
+ column: name,
102
+ oldValue: fromField.notNull ? 'NOT NULL' : 'NULLABLE',
103
+ newValue: toField.notNull ? 'NOT NULL' : 'NULLABLE',
104
+ });
105
+ }
106
+ }
107
+ }
108
+ // Dropped
109
+ for (const name of fromMap.keys()) {
110
+ if (!toMap.has(name)) {
111
+ changes.push({ type: 'dropped', column: name });
112
+ }
113
+ }
114
+ return changes;
115
+ }
116
+ // ─────────────────────────────────────────────────────────────
117
+ // SchemaManager
118
+ // ─────────────────────────────────────────────────────────────
119
+ const DATABASE_INTROSPECT_ABI = [
120
+ 'function getTableSchema(string calldata name) external view returns (bytes memory)',
121
+ 'function getTable(string calldata name) external view returns (address)',
122
+ 'function listTables() external view returns (string[] memory)',
123
+ ];
124
+ export class SchemaManager {
125
+ db;
126
+ tableAddress;
127
+ tableClient;
128
+ dbContract;
129
+ constructor(db, tableAddress, tableClient, signer) {
130
+ this.db = db;
131
+ this.tableAddress = tableAddress;
132
+ this.tableClient = tableClient;
133
+ this.dbContract = new ethers.Contract(db.address, DATABASE_INTROSPECT_ABI, signer);
134
+ }
135
+ // ── Introspection ───────────────────────────────────────────
136
+ /**
137
+ * Read the schema bytes from the database contract and decode them
138
+ * into a usable FieldDescriptor array.
139
+ *
140
+ * @param tableName The name used when the table was created.
141
+ */
142
+ async introspect(tableName) {
143
+ try {
144
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
145
+ const schemaBytes = await this.dbContract.getTableSchema(tableName);
146
+ return decodeSchemaBytes(schemaBytes);
147
+ }
148
+ catch {
149
+ return [];
150
+ }
151
+ }
152
+ /**
153
+ * List all table names in this database.
154
+ */
155
+ async listTables() {
156
+ return this.db.listTables();
157
+ }
158
+ // ── Schema version tracking ─────────────────────────────────
159
+ /**
160
+ * Read the schema version stored in a meta record on-chain.
161
+ * Returns 0 if no version record has been written yet.
162
+ */
163
+ async getSchemaVersion(tableName) {
164
+ const versionKey = this.tableClient.deriveKey(`__schema_version__${tableName}`, 0n);
165
+ try {
166
+ const exists = await this.tableClient.exists(versionKey);
167
+ if (!exists)
168
+ return 0;
169
+ const json = await this.tableClient.readPlaintext(versionKey);
170
+ const { version } = JSON.parse(json);
171
+ return version;
172
+ }
173
+ catch {
174
+ return 0;
175
+ }
176
+ }
177
+ /**
178
+ * Write (or update) the schema version meta record.
179
+ */
180
+ async setSchemaVersion(tableName, version) {
181
+ const versionKey = this.tableClient.deriveKey(`__schema_version__${tableName}`, 0n);
182
+ const payload = JSON.stringify({ version, updatedAt: Date.now() });
183
+ const exists = await this.tableClient.exists(versionKey);
184
+ if (exists) {
185
+ await this.tableClient.updateRaw(versionKey, payload);
186
+ }
187
+ else {
188
+ await this.tableClient.writeRaw(versionKey, payload);
189
+ }
190
+ }
191
+ // ── Soft-rename ─────────────────────────────────────────────
192
+ /**
193
+ * Store a name alias mapping in a meta record.
194
+ * Future `introspect()` calls should use the new name.
195
+ *
196
+ * ⚠ The contract still uses the old name internally. This is a
197
+ * client-side alias only. To hard-rename, re-create the table.
198
+ */
199
+ async renameTable(oldName, newName) {
200
+ const renameKey = this.tableClient.deriveKey(`__rename__${oldName}`, 0n);
201
+ const payload = JSON.stringify({ from: oldName, to: newName, renamedAt: Date.now() });
202
+ const exists = await this.tableClient.exists(renameKey);
203
+ if (exists) {
204
+ await this.tableClient.updateRaw(renameKey, payload);
205
+ }
206
+ else {
207
+ await this.tableClient.writeRaw(renameKey, payload);
208
+ }
209
+ }
210
+ /** Check if a table has been soft-renamed. Returns the new name or null. */
211
+ async getRenamedTo(tableName) {
212
+ const renameKey = this.tableClient.deriveKey(`__rename__${tableName}`, 0n);
213
+ try {
214
+ const exists = await this.tableClient.exists(renameKey);
215
+ if (!exists)
216
+ return null;
217
+ const json = await this.tableClient.readPlaintext(renameKey);
218
+ const { to } = JSON.parse(json);
219
+ return to;
220
+ }
221
+ catch {
222
+ return null;
223
+ }
224
+ }
225
+ // ── Soft-drop ───────────────────────────────────────────────
226
+ /**
227
+ * "Drop" a table by:
228
+ * 1. Deleting all owner records (batch, up to `maxRecords`).
229
+ * 2. Writing a __dropped__ meta record so the SDK knows to ignore it.
230
+ *
231
+ * ⚠ This is irreversible. The on-chain key->ciphertext mapping for
232
+ * deleted records is permanently unreadable (symmetric key scrubbed).
233
+ *
234
+ * @param ownerAddress Address whose records to delete.
235
+ * @param maxRecords Safety cap. Default: 500. Increase for large tables.
236
+ */
237
+ async dropTable(ownerAddress, maxRecords = 500) {
238
+ const keys = await this.tableClient.listOwnerRecords(ownerAddress, 0n, BigInt(maxRecords));
239
+ let deleted = 0;
240
+ for (const key of keys) {
241
+ try {
242
+ await this.tableClient.deleteRecord(key);
243
+ deleted++;
244
+ }
245
+ catch { /* already deleted or no access — skip */ }
246
+ }
247
+ // Write tombstone
248
+ const tombstoneKey = this.tableClient.deriveKey(`__dropped__${this.tableAddress}`, 0n);
249
+ const payload = JSON.stringify({ droppedAt: Date.now(), ownerAddress });
250
+ await this.tableClient.writeRaw(tombstoneKey, payload);
251
+ return { deleted };
252
+ }
253
+ /** Check if a table has been soft-dropped. */
254
+ async isDropped() {
255
+ const tombstoneKey = this.tableClient.deriveKey(`__dropped__${this.tableAddress}`, 0n);
256
+ return this.tableClient.exists(tombstoneKey);
257
+ }
258
+ }
259
+ //# sourceMappingURL=schema-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema-manager.js","sourceRoot":"","sources":["../../src/schema-manager.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,156 @@
1
+ /**
2
+ * @file table-client.ts
3
+ * @notice Base encrypted table client.
4
+ *
5
+ * This class wraps a Web3QL table contract proxy and handles ALL
6
+ * encryption/decryption client-side. The chain only ever sees:
7
+ * • ciphertext blobs (AES-equivalent via NaCl secretbox)
8
+ * • per-user encrypted key blobs (NaCl box)
9
+ *
10
+ * Plaintext and symmetric keys never leave this class.
11
+ *
12
+ * Usage pattern:
13
+ * ─────────────────────────────────────────────────────────────
14
+ * const client = new EncryptedTableClient(tableAddress, signer, keypair);
15
+ *
16
+ * // Write — encrypts automatically
17
+ * await client.write(1n, JSON.stringify({ name: 'Alice' }));
18
+ *
19
+ * // Read — decrypts automatically
20
+ * const data = await client.read(1n); // '{"name":"Alice"}'
21
+ *
22
+ * // Share with Bob (needs Bob registered in registry)
23
+ * await client.share(1n, bobAddress, Role.VIEWER, registry);
24
+ *
25
+ * // Revoke
26
+ * await client.revoke(1n, bobAddress);
27
+ */
28
+ import { ethers } from 'ethers';
29
+ import { EncryptionKeypair } from './crypto.js';
30
+ import type { PublicKeyRegistryClient } from './registry.js';
31
+ export declare enum Role {
32
+ VIEWER = 1,
33
+ EDITOR = 2
34
+ }
35
+ export interface RawRecord {
36
+ ciphertext: Uint8Array;
37
+ deleted: boolean;
38
+ version: bigint;
39
+ updatedAt: bigint;
40
+ owner: string;
41
+ }
42
+ export declare class EncryptedTableClient {
43
+ readonly tableAddress: string;
44
+ protected contract: ethers.Contract;
45
+ protected signer: ethers.Signer;
46
+ /** The caller's X25519 keypair — private key STAYS in memory only. */
47
+ private keypair;
48
+ /** Shorthand for casting contract to any so strict index checks don't block calls. */
49
+ private get c();
50
+ constructor(tableAddress: string, signer: ethers.Signer, keypair: EncryptionKeypair, abi?: readonly string[]);
51
+ /**
52
+ * Derive the bytes32 on-chain record key from a table name + primary key.
53
+ * Canonical scheme: keccak256(abi.encodePacked(tableName, id))
54
+ * Matches the Solidity generator and connector — all three layers are aligned.
55
+ */
56
+ deriveKey(tableName: string, id: bigint): string;
57
+ /**
58
+ * Encrypt `plaintext` and store it as a new record.
59
+ * The symmetric key is encrypted for the caller (owner).
60
+ *
61
+ * @param key bytes32 record key (use deriveKey or pass directly).
62
+ * @param plaintext Any data you want to store — string or raw bytes.
63
+ */
64
+ writeRaw(key: string, plaintext: string | Uint8Array): Promise<ethers.TransactionReceipt>;
65
+ /**
66
+ * Encrypt `plaintext` for self — returns the raw ciphertext and
67
+ * encrypted symmetric key bytes WITHOUT submitting any transaction.
68
+ *
69
+ * Used by Model.relatedCreate() to hand the encrypted bytes to a
70
+ * RelationWire contract that will call table.write() on behalf of
71
+ * the user within an atomic transaction.
72
+ */
73
+ encryptForSelf(plaintext: string | Uint8Array): Promise<{
74
+ ciphertext: Uint8Array;
75
+ encryptedKey: Uint8Array;
76
+ }>;
77
+ /**
78
+ * Read and decrypt a record.
79
+ * Returns the plaintext as a UTF-8 string.
80
+ * Throws if the record is deleted, doesn't exist, or you lack access.
81
+ */
82
+ readPlaintext(key: string): Promise<string>;
83
+ /**
84
+ * Read and decrypt a record — returns raw bytes.
85
+ */
86
+ readBytes(key: string): Promise<Uint8Array>;
87
+ /**
88
+ * Get the raw (still-encrypted) record from chain.
89
+ */
90
+ readRaw(key: string): Promise<RawRecord>;
91
+ /**
92
+ * Update an existing record with new plaintext.
93
+ * Re-encrypts with a FRESH symmetric key — old key copies are NOT
94
+ * automatically re-shared. Call reshareAfterUpdate() afterwards
95
+ * if collaborators need access to the updated version.
96
+ */
97
+ updateRaw(key: string, plaintext: string | Uint8Array): Promise<ethers.TransactionReceipt>;
98
+ /**
99
+ * Delete a record. The contract scrubs ALL collaborator key copies
100
+ * on-chain. Ciphertext remains but is permanently unreadable by
101
+ * anyone (the symmetric key is gone).
102
+ */
103
+ deleteRecord(key: string): Promise<ethers.TransactionReceipt>;
104
+ /**
105
+ * Share a record with another user.
106
+ *
107
+ * Flow:
108
+ * 1. Fetch caller's encrypted key from chain
109
+ * 2. Decrypt to recover the symmetric key (requires caller's privkey)
110
+ * 3. Fetch recipient's X25519 public key from the registry
111
+ * 4. Re-encrypt the symmetric key for the recipient
112
+ * 5. Call grantAccess on-chain with the new encrypted key copy
113
+ *
114
+ * @param key bytes32 record key
115
+ * @param recipient Address to share with
116
+ * @param role Role.VIEWER or Role.EDITOR
117
+ * @param registry PublicKeyRegistryClient to look up recipient's pubkey
118
+ */
119
+ share(key: string, recipient: string, role: Role, registry: PublicKeyRegistryClient): Promise<ethers.TransactionReceipt>;
120
+ /**
121
+ * Revoke a user's access. Their encrypted key copy is scrubbed
122
+ * on-chain — they can no longer decrypt the record.
123
+ * (They may have decrypted and cached it locally — that is a
124
+ * client-side concern, not something the chain can prevent.)
125
+ */
126
+ revoke(key: string, user: string): Promise<ethers.TransactionReceipt>;
127
+ /**
128
+ * After updating a record (which rotates the key), re-share with
129
+ * all current collaborators so they can decrypt the new ciphertext.
130
+ *
131
+ * @param key bytes32 record key
132
+ * @param collaborators List of addresses to re-share with
133
+ * @param roles Role for each address (parallel array)
134
+ * @param registry PublicKeyRegistryClient
135
+ */
136
+ reshareAfterUpdate(key: string, collaborators: string[], roles: Role[], registry: PublicKeyRegistryClient): Promise<void>;
137
+ /** Fetch this caller's encrypted key blob from chain (still encrypted). */
138
+ getMyEncryptedKey(key: string): Promise<Uint8Array>;
139
+ /**
140
+ * Decrypt a symmetric key blob that was encrypted by a known sender
141
+ * (use when you are a collaborator, not the owner — the sender's
142
+ * public key must be passed explicitly).
143
+ */
144
+ decryptSharedKey(encryptedKey: Uint8Array, senderPublicKey: Uint8Array): Uint8Array;
145
+ exists(key: string): Promise<boolean>;
146
+ owner(key: string): Promise<string>;
147
+ collaboratorCount(key: string): Promise<number>;
148
+ /** List bytes32 record keys owned by `addr` (paginated).
149
+ * Prefers getActiveOwnerRecords (skips deleted) when available;
150
+ * falls back to getOwnerRecords for older contract versions.
151
+ */
152
+ listOwnerRecords(addr: string, start?: bigint, limit?: bigint): Promise<string[]>;
153
+ /** Total number of records written by `addr` (including deleted). */
154
+ ownerRecordCount(addr: string): Promise<bigint>;
155
+ }
156
+ //# sourceMappingURL=table-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"table-client.d.ts","sourceRoot":"","sources":["../../src/table-client.ts"],"names":[],"mappings":"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"}