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,192 @@
1
+ /**
2
+ * @file constraints.ts
3
+ * @notice Web3QL v1.2 — integrity constraint engine.
4
+ *
5
+ * Constraints live in the SDK layer (off-chain) with the following guarantees:
6
+ *
7
+ * • PRIMARY KEY uniqueness — contract enforces at write (requires exists() pre-check)
8
+ * • UNIQUE — SDK maintains an in-memory seen-values set per column
9
+ * • DEFAULT / NOT NULL — enforced by types.ts validateAndEncode()
10
+ * • CHECK — per-column validation function
11
+ * • FOREIGN KEY — SDK reads target table at write time
12
+ * • AUTO_INCREMENT — SDK-maintained counter (persisted in a meta record)
13
+ * • ON DELETE CASCADE — SDK fetches referencing records and deletes them
14
+ *
15
+ * None of these require contract changes for CHECK/UNIQUE (client-side enforcement).
16
+ * PK uniqueness IS enforced at the contract level via `recordExists`.
17
+ *
18
+ * Usage:
19
+ * ─────────────────────────────────────────────────────────────
20
+ * const constraints = new ConstraintEngine([
21
+ * { type: 'unique', column: 'email' },
22
+ * { type: 'check', column: 'age', check: (v) => Number(v) >= 0 },
23
+ * { type: 'fk', column: 'userId', references: { table: userTable, column: 'id' } },
24
+ * ]);
25
+ *
26
+ * // Before writing:
27
+ * await constraints.validate(row, existingRows);
28
+ *
29
+ * // Get next AUTO_INCREMENT id:
30
+ * const nextId = await constraints.nextId(tableAddress, client);
31
+ * ─────────────────────────────────────────────────────────────
32
+ */
33
+ // ─────────────────────────────────────────────────────────────
34
+ // Constraint violation error
35
+ // ─────────────────────────────────────────────────────────────
36
+ export class ConstraintViolation extends Error {
37
+ constraintType;
38
+ column;
39
+ constructor(constraintType, column, message) {
40
+ super(message);
41
+ this.constraintType = constraintType;
42
+ this.column = column;
43
+ this.name = 'ConstraintViolation';
44
+ }
45
+ }
46
+ // ─────────────────────────────────────────────────────────────
47
+ // ConstraintEngine
48
+ // ─────────────────────────────────────────────────────────────
49
+ export class ConstraintEngine {
50
+ constraints;
51
+ constructor(constraints = []) {
52
+ this.constraints = constraints;
53
+ }
54
+ /**
55
+ * Validate a new/updated row against all constraints.
56
+ *
57
+ * @param row The row being written (fully encoded, post validateAndEncode).
58
+ * @param existingRows Already-decoded rows from the same table (for UNIQUE checks).
59
+ * Pass an empty array if fetching is not possible.
60
+ */
61
+ async validate(row, existingRows = []) {
62
+ for (const c of this.constraints) {
63
+ switch (c.type) {
64
+ case 'notNull':
65
+ this._checkNotNull(c, row);
66
+ break;
67
+ case 'unique':
68
+ this._checkUnique(c, row, existingRows);
69
+ break;
70
+ case 'check':
71
+ await this._checkCheck(c, row);
72
+ break;
73
+ case 'fk':
74
+ await this._checkForeignKey(c, row);
75
+ break;
76
+ }
77
+ }
78
+ }
79
+ _checkNotNull(c, row) {
80
+ const v = row[c.column];
81
+ if (v === null || v === undefined || v === '__NULL__') {
82
+ throw new ConstraintViolation('notNull', c.column, `NOT NULL violation: column "${c.column}" cannot be null`);
83
+ }
84
+ }
85
+ _checkUnique(c, row, existingRows) {
86
+ const newVal = row[c.column];
87
+ const conflict = existingRows.find((existing) => existing[c.column] === newVal && newVal !== null && newVal !== undefined);
88
+ if (conflict) {
89
+ throw new ConstraintViolation('unique', c.column, `UNIQUE violation: column "${c.column}" already has value "${String(newVal)}"`);
90
+ }
91
+ }
92
+ async _checkCheck(c, row) {
93
+ const value = row[c.column];
94
+ const valid = await c.check(value, row);
95
+ if (!valid) {
96
+ throw new ConstraintViolation('check', c.column, `CHECK violation: column "${c.column}"${c.name ? ` (${c.name})` : ''} rejected value "${String(value)}"`);
97
+ }
98
+ }
99
+ async _checkForeignKey(c, row) {
100
+ const refValue = row[c.column];
101
+ if (refValue === null || refValue === undefined || refValue === '__NULL__')
102
+ return; // NULL FK is allowed
103
+ const { table, tableName } = c.references;
104
+ const refKey = table.deriveKey(tableName, BigInt(String(refValue)));
105
+ const exists = await table.exists(refKey);
106
+ if (!exists) {
107
+ throw new ConstraintViolation('fk', c.column, `FOREIGN KEY violation: column "${c.column}" references non-existent record "${String(refValue)}"`);
108
+ }
109
+ }
110
+ /**
111
+ * ON DELETE CASCADE — delete all records in this table that reference
112
+ * the deleted row in the foreign-key column.
113
+ *
114
+ * @param deletedValue The primary-key value of the deleted parent record.
115
+ * @param fkColumn The column in this table that holds the FK.
116
+ * @param ownedRecords All decoded records in this table (to find referencing rows).
117
+ * @param deleteRecord Callback to actually delete a record by its bytes32 key.
118
+ */
119
+ async onDeleteCascade(deletedValue, fkColumn, ownedRecords, deleteRecord) {
120
+ const toDelete = ownedRecords.filter((r) => String(r.data[fkColumn]) === String(deletedValue));
121
+ for (const r of toDelete) {
122
+ await deleteRecord(r.key);
123
+ }
124
+ }
125
+ }
126
+ // ─────────────────────────────────────────────────────────────
127
+ // AUTO_INCREMENT counter
128
+ // ─────────────────────────────────────────────────────────────
129
+ /**
130
+ * Client-side AUTO_INCREMENT counter backed by a special meta record on-chain.
131
+ *
132
+ * The counter is stored as a JSON record encrypted for the table owner under
133
+ * the key `keccak256("__auto_increment__" + tableName)`.
134
+ *
135
+ * ⚠ This is NOT atomic across multiple concurrent writers.
136
+ * For single-writer tables (personal data), it is safe.
137
+ * For multi-writer tables, use a relay-maintained counter (v1.2).
138
+ */
139
+ export class AutoIncrementCounter {
140
+ tableName;
141
+ client;
142
+ metaKey;
143
+ constructor(tableName, client) {
144
+ this.tableName = tableName;
145
+ this.client = client;
146
+ this.metaKey = client.deriveKey(`__auto_increment__${tableName}`, 0n);
147
+ }
148
+ /**
149
+ * Read the current counter value. Returns 0 if not yet initialised.
150
+ */
151
+ async current() {
152
+ try {
153
+ const exists = await this.client.exists(this.metaKey);
154
+ if (!exists)
155
+ return 0n;
156
+ const json = await this.client.readPlaintext(this.metaKey);
157
+ const { counter } = JSON.parse(json);
158
+ return BigInt(counter);
159
+ }
160
+ catch {
161
+ return 0n;
162
+ }
163
+ }
164
+ /**
165
+ * Atomically increment and return the next ID.
166
+ * Reads current → increments → writes new value → returns incremented.
167
+ */
168
+ async next() {
169
+ const cur = await this.current();
170
+ const nextId = cur + 1n;
171
+ const payload = JSON.stringify({ counter: nextId.toString() });
172
+ if (cur === 0n) {
173
+ await this.client.writeRaw(this.metaKey, payload);
174
+ }
175
+ else {
176
+ await this.client.updateRaw(this.metaKey, payload);
177
+ }
178
+ return nextId;
179
+ }
180
+ /** Reset the counter (use with caution — may cause PK collisions). */
181
+ async reset(to = 0n) {
182
+ const payload = JSON.stringify({ counter: to.toString() });
183
+ const cur = await this.current();
184
+ if (cur === 0n) {
185
+ await this.client.writeRaw(this.metaKey, payload);
186
+ }
187
+ else {
188
+ await this.client.updateRaw(this.metaKey, payload);
189
+ }
190
+ }
191
+ }
192
+ //# sourceMappingURL=constraints.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constraints.js","sourceRoot":"","sources":["../../src/constraints.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,118 @@
1
+ /**
2
+ * @file crypto.ts
3
+ * @notice Off-chain encryption layer for Web3QL.
4
+ *
5
+ * Security model:
6
+ * ─────────────────────────────────────────────────────────────
7
+ * • One random 32-byte symmetric key is generated per record.
8
+ * • Record data is encrypted with that key using NaCl secretbox
9
+ * (XSalsa20-Poly1305, 256-bit key, 192-bit nonce, 128-bit MAC).
10
+ * • The symmetric key is encrypted separately for each authorised
11
+ * user using NaCl box (X25519-XSalsa20-Poly1305, ECDH key agreement).
12
+ * • Only the encrypted blobs ever touch the chain — the symmetric key
13
+ * and plaintext never leave the client device.
14
+ *
15
+ * Key derivation from Ethereum wallet:
16
+ * ─────────────────────────────────────────────────────────────
17
+ * X25519 private key = SHA-256(Ethereum private key bytes)
18
+ * X25519 public key = scalar multiplication (computed by nacl)
19
+ *
20
+ * This means no separate key management — the wallet IS the
21
+ * encryption identity. Losing the wallet private key = losing
22
+ * access to encrypted records (same as losing any crypto key).
23
+ *
24
+ * Wire format (self-describing, no external framing needed):
25
+ * ─────────────────────────────────────────────────────────────
26
+ * secretbox blob: [ 24-byte nonce | encrypted payload ]
27
+ * box blob: [ 24-byte nonce | encrypted payload ]
28
+ */
29
+ import type { Signer } from 'ethers';
30
+ export interface EncryptionKeypair {
31
+ /** X25519 public key — safe to publish on-chain */
32
+ publicKey: Uint8Array;
33
+ /** X25519 private key — never leaves the client */
34
+ privateKey: Uint8Array;
35
+ }
36
+ /** Message signed by the wallet to derive the X25519 keypair.
37
+ * Must be identical to the constant in cloud/lib/browser-crypto.ts so
38
+ * browser and SDK produce the same keypair for the same wallet.
39
+ */
40
+ export declare const KEY_DERIVATION_MESSAGE = "Web3QL encryption key derivation v1";
41
+ /**
42
+ * Derive an X25519 keypair from an ethers Signer by signing a fixed
43
+ * derivation message. Because Ethereum personal_sign (RFC 6979) is
44
+ * deterministic, the same wallet always produces the same keypair.
45
+ *
46
+ * ✅ Use this when both SDK and browser clients need to share the same
47
+ * encryption identity — the resulting pubkey matches what the browser
48
+ * derives via `deriveKeypairFromSignature` in browser-crypto.ts.
49
+ *
50
+ * @param signer Any ethers v6 Signer (e.g. `new ethers.Wallet(privKey)`).
51
+ */
52
+ export declare function deriveKeypairFromWallet(signer: Signer): Promise<EncryptionKeypair>;
53
+ /**
54
+ * Derive an X25519 encryption keypair from an Ethereum private key.
55
+ *
56
+ * @deprecated Prefer `deriveKeypairFromWallet(signer)` — it produces a
57
+ * keypair that is compatible with the Web3QL browser Explorer and any
58
+ * other client that uses wallet-signature derivation. Raw-private-key
59
+ * derivation generates a DIFFERENT keypair, so records written with this
60
+ * function cannot be decrypted in the browser (and vice-versa).
61
+ *
62
+ * @param ethPrivateKey Hex string, with or without "0x" prefix.
63
+ */
64
+ export declare function deriveKeypair(ethPrivateKey: string): EncryptionKeypair;
65
+ /**
66
+ * Derive ONLY the public key (useful when you only have a signed
67
+ * message and want to register — not when you have the private key).
68
+ * Exposed for completeness; normally call deriveKeypair() directly.
69
+ */
70
+ export declare function publicKeyFromPrivate(ethPrivateKey: string): Uint8Array;
71
+ /**
72
+ * Generate a random 32-byte symmetric key for a new record.
73
+ * Call this once per write — never reuse across records.
74
+ */
75
+ export declare function generateSymmetricKey(): Uint8Array;
76
+ /**
77
+ * Encrypt plaintext with a symmetric key.
78
+ * Wire format: [ 24-byte nonce | MAC+ciphertext ]
79
+ */
80
+ export declare function encryptData(plaintext: Uint8Array, symmetricKey: Uint8Array): Uint8Array;
81
+ /**
82
+ * Decrypt a secretbox blob (nonce||ciphertext) with a symmetric key.
83
+ * Throws if the MAC check fails (data tampered or wrong key).
84
+ */
85
+ export declare function decryptData(blob: Uint8Array, symmetricKey: Uint8Array): Uint8Array;
86
+ /**
87
+ * Encrypt a symmetric key for a specific recipient.
88
+ *
89
+ * The caller (sharer) needs their own X25519 private key and the
90
+ * recipient's X25519 public key (registered on-chain in PublicKeyRegistry).
91
+ *
92
+ * Wire format: [ 24-byte nonce | MAC+ciphertext ]
93
+ */
94
+ export declare function encryptKeyForRecipient(symmetricKey: Uint8Array, recipientPublicKey: Uint8Array, senderPrivateKey: Uint8Array): Uint8Array;
95
+ /**
96
+ * Decrypt a symmetric key that was encrypted for us.
97
+ * Throws if authentication fails.
98
+ */
99
+ export declare function decryptKeyFromSender(blob: Uint8Array, senderPublicKey: Uint8Array, recipientPrivKey: Uint8Array): Uint8Array;
100
+ /**
101
+ * Encrypt the symmetric key to yourself — used on the initial write
102
+ * so the owner can always recover their own key.
103
+ */
104
+ export declare function encryptKeyForSelf(symmetricKey: Uint8Array, keypair: EncryptionKeypair): Uint8Array;
105
+ /**
106
+ * Decrypt a symmetric key that was encrypted to yourself.
107
+ */
108
+ export declare function decryptKeyForSelf(blob: Uint8Array, keypair: EncryptionKeypair): Uint8Array;
109
+ /**
110
+ * Encode a 32-byte X25519 public key as a 0x-prefixed hex string
111
+ * suitable for passing to PublicKeyRegistry.register().
112
+ */
113
+ export declare function publicKeyToHex(pubKey: Uint8Array): string;
114
+ /**
115
+ * Decode a 0x-prefixed hex bytes32 from the registry back to Uint8Array.
116
+ */
117
+ export declare function hexToPublicKey(hex: string): Uint8Array;
118
+ //# sourceMappingURL=crypto.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"crypto.d.ts","sourceRoot":"","sources":["../../src/crypto.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAKH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAMrC,MAAM,WAAW,iBAAiB;IAChC,mDAAmD;IACnD,SAAS,EAAI,UAAU,CAAC;IACxB,mDAAmD;IACnD,UAAU,EAAG,UAAU,CAAC;CACzB;AAMD;;;GAGG;AACH,eAAO,MAAM,sBAAsB,wCAAwC,CAAC;AAE5E;;;;;;;;;;GAUG;AACH,wBAAsB,uBAAuB,CAC3C,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,iBAAiB,CAAC,CAM5B;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,aAAa,CAAC,aAAa,EAAE,MAAM,GAAG,iBAAiB,CAOtE;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,aAAa,EAAE,MAAM,GAAG,UAAU,CAEtE;AAMD;;;GAGG;AACH,wBAAgB,oBAAoB,IAAI,UAAU,CAEjD;AAED;;;GAGG;AACH,wBAAgB,WAAW,CACzB,SAAS,EAAM,UAAU,EACzB,YAAY,EAAG,UAAU,GACxB,UAAU,CAKZ;AAED;;;GAGG;AACH,wBAAgB,WAAW,CACzB,IAAI,EAAW,UAAU,EACzB,YAAY,EAAG,UAAU,GACxB,UAAU,CAMZ;AAMD;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CACpC,YAAY,EAAS,UAAU,EAC/B,kBAAkB,EAAG,UAAU,EAC/B,gBAAgB,EAAK,UAAU,GAC9B,UAAU,CAKZ;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAClC,IAAI,EAAgB,UAAU,EAC9B,eAAe,EAAK,UAAU,EAC9B,gBAAgB,EAAI,UAAU,GAC7B,UAAU,CAMZ;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAC/B,YAAY,EAAG,UAAU,EACzB,OAAO,EAAQ,iBAAiB,GAC/B,UAAU,CAEZ;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAM,UAAU,EACpB,OAAO,EAAG,iBAAiB,GAC1B,UAAU,CAEZ;AAMD;;;GAGG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,CAGzD;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU,CAKtD"}
@@ -0,0 +1,192 @@
1
+ /**
2
+ * @file crypto.ts
3
+ * @notice Off-chain encryption layer for Web3QL.
4
+ *
5
+ * Security model:
6
+ * ─────────────────────────────────────────────────────────────
7
+ * • One random 32-byte symmetric key is generated per record.
8
+ * • Record data is encrypted with that key using NaCl secretbox
9
+ * (XSalsa20-Poly1305, 256-bit key, 192-bit nonce, 128-bit MAC).
10
+ * • The symmetric key is encrypted separately for each authorised
11
+ * user using NaCl box (X25519-XSalsa20-Poly1305, ECDH key agreement).
12
+ * • Only the encrypted blobs ever touch the chain — the symmetric key
13
+ * and plaintext never leave the client device.
14
+ *
15
+ * Key derivation from Ethereum wallet:
16
+ * ─────────────────────────────────────────────────────────────
17
+ * X25519 private key = SHA-256(Ethereum private key bytes)
18
+ * X25519 public key = scalar multiplication (computed by nacl)
19
+ *
20
+ * This means no separate key management — the wallet IS the
21
+ * encryption identity. Losing the wallet private key = losing
22
+ * access to encrypted records (same as losing any crypto key).
23
+ *
24
+ * Wire format (self-describing, no external framing needed):
25
+ * ─────────────────────────────────────────────────────────────
26
+ * secretbox blob: [ 24-byte nonce | encrypted payload ]
27
+ * box blob: [ 24-byte nonce | encrypted payload ]
28
+ */
29
+ import nacl from 'tweetnacl';
30
+ import { sha256 } from '@noble/hashes/sha256';
31
+ import { hexToBytes } from '@noble/hashes/utils';
32
+ // ─────────────────────────────────────────────────────────────
33
+ // Keypair derivation
34
+ // ─────────────────────────────────────────────────────────────
35
+ /** Message signed by the wallet to derive the X25519 keypair.
36
+ * Must be identical to the constant in cloud/lib/browser-crypto.ts so
37
+ * browser and SDK produce the same keypair for the same wallet.
38
+ */
39
+ export const KEY_DERIVATION_MESSAGE = 'Web3QL encryption key derivation v1';
40
+ /**
41
+ * Derive an X25519 keypair from an ethers Signer by signing a fixed
42
+ * derivation message. Because Ethereum personal_sign (RFC 6979) is
43
+ * deterministic, the same wallet always produces the same keypair.
44
+ *
45
+ * ✅ Use this when both SDK and browser clients need to share the same
46
+ * encryption identity — the resulting pubkey matches what the browser
47
+ * derives via `deriveKeypairFromSignature` in browser-crypto.ts.
48
+ *
49
+ * @param signer Any ethers v6 Signer (e.g. `new ethers.Wallet(privKey)`).
50
+ */
51
+ export async function deriveKeypairFromWallet(signer) {
52
+ const sig = await signer.signMessage(KEY_DERIVATION_MESSAGE);
53
+ const sigHex = sig.startsWith('0x') ? sig.slice(2) : sig;
54
+ const seed = sha256(hexToBytes(sigHex));
55
+ const kp = nacl.box.keyPair.fromSecretKey(seed);
56
+ return { publicKey: kp.publicKey, privateKey: kp.secretKey };
57
+ }
58
+ /**
59
+ * Derive an X25519 encryption keypair from an Ethereum private key.
60
+ *
61
+ * @deprecated Prefer `deriveKeypairFromWallet(signer)` — it produces a
62
+ * keypair that is compatible with the Web3QL browser Explorer and any
63
+ * other client that uses wallet-signature derivation. Raw-private-key
64
+ * derivation generates a DIFFERENT keypair, so records written with this
65
+ * function cannot be decrypted in the browser (and vice-versa).
66
+ *
67
+ * @param ethPrivateKey Hex string, with or without "0x" prefix.
68
+ */
69
+ export function deriveKeypair(ethPrivateKey) {
70
+ const stripped = ethPrivateKey.startsWith('0x')
71
+ ? ethPrivateKey.slice(2)
72
+ : ethPrivateKey;
73
+ const seed = sha256(hexToBytes(stripped));
74
+ const kp = nacl.box.keyPair.fromSecretKey(seed);
75
+ return { publicKey: kp.publicKey, privateKey: kp.secretKey };
76
+ }
77
+ /**
78
+ * Derive ONLY the public key (useful when you only have a signed
79
+ * message and want to register — not when you have the private key).
80
+ * Exposed for completeness; normally call deriveKeypair() directly.
81
+ */
82
+ export function publicKeyFromPrivate(ethPrivateKey) {
83
+ return deriveKeypair(ethPrivateKey).publicKey;
84
+ }
85
+ // ─────────────────────────────────────────────────────────────
86
+ // Symmetric encryption (record data)
87
+ // ─────────────────────────────────────────────────────────────
88
+ /**
89
+ * Generate a random 32-byte symmetric key for a new record.
90
+ * Call this once per write — never reuse across records.
91
+ */
92
+ export function generateSymmetricKey() {
93
+ return nacl.randomBytes(nacl.secretbox.keyLength); // 32 bytes
94
+ }
95
+ /**
96
+ * Encrypt plaintext with a symmetric key.
97
+ * Wire format: [ 24-byte nonce | MAC+ciphertext ]
98
+ */
99
+ export function encryptData(plaintext, symmetricKey) {
100
+ const nonce = nacl.randomBytes(nacl.secretbox.nonceLength);
101
+ const encrypted = nacl.secretbox(plaintext, nonce, symmetricKey);
102
+ if (!encrypted)
103
+ throw new Error('encryptData: nacl.secretbox returned null');
104
+ return concat(nonce, encrypted);
105
+ }
106
+ /**
107
+ * Decrypt a secretbox blob (nonce||ciphertext) with a symmetric key.
108
+ * Throws if the MAC check fails (data tampered or wrong key).
109
+ */
110
+ export function decryptData(blob, symmetricKey) {
111
+ const nonce = blob.subarray(0, nacl.secretbox.nonceLength);
112
+ const ciphertext = blob.subarray(nacl.secretbox.nonceLength);
113
+ const plaintext = nacl.secretbox.open(ciphertext, nonce, symmetricKey);
114
+ if (!plaintext)
115
+ throw new Error('decryptData: authentication failed — wrong key or tampered data');
116
+ return plaintext;
117
+ }
118
+ // ─────────────────────────────────────────────────────────────
119
+ // Asymmetric key wrapping (per-recipient symmetric key copies)
120
+ // ─────────────────────────────────────────────────────────────
121
+ /**
122
+ * Encrypt a symmetric key for a specific recipient.
123
+ *
124
+ * The caller (sharer) needs their own X25519 private key and the
125
+ * recipient's X25519 public key (registered on-chain in PublicKeyRegistry).
126
+ *
127
+ * Wire format: [ 24-byte nonce | MAC+ciphertext ]
128
+ */
129
+ export function encryptKeyForRecipient(symmetricKey, recipientPublicKey, senderPrivateKey) {
130
+ const nonce = nacl.randomBytes(nacl.box.nonceLength);
131
+ const encrypted = nacl.box(symmetricKey, nonce, recipientPublicKey, senderPrivateKey);
132
+ if (!encrypted)
133
+ throw new Error('encryptKeyForRecipient: nacl.box returned null');
134
+ return concat(nonce, encrypted);
135
+ }
136
+ /**
137
+ * Decrypt a symmetric key that was encrypted for us.
138
+ * Throws if authentication fails.
139
+ */
140
+ export function decryptKeyFromSender(blob, senderPublicKey, recipientPrivKey) {
141
+ const nonce = blob.subarray(0, nacl.box.nonceLength);
142
+ const ciphertext = blob.subarray(nacl.box.nonceLength);
143
+ const key = nacl.box.open(ciphertext, nonce, senderPublicKey, recipientPrivKey);
144
+ if (!key)
145
+ throw new Error('decryptKeyFromSender: authentication failed — wrong key or tampered data');
146
+ return key;
147
+ }
148
+ /**
149
+ * Encrypt the symmetric key to yourself — used on the initial write
150
+ * so the owner can always recover their own key.
151
+ */
152
+ export function encryptKeyForSelf(symmetricKey, keypair) {
153
+ return encryptKeyForRecipient(symmetricKey, keypair.publicKey, keypair.privateKey);
154
+ }
155
+ /**
156
+ * Decrypt a symmetric key that was encrypted to yourself.
157
+ */
158
+ export function decryptKeyForSelf(blob, keypair) {
159
+ return decryptKeyFromSender(blob, keypair.publicKey, keypair.privateKey);
160
+ }
161
+ // ─────────────────────────────────────────────────────────────
162
+ // Encode/decode public key for on-chain storage (bytes32)
163
+ // ─────────────────────────────────────────────────────────────
164
+ /**
165
+ * Encode a 32-byte X25519 public key as a 0x-prefixed hex string
166
+ * suitable for passing to PublicKeyRegistry.register().
167
+ */
168
+ export function publicKeyToHex(pubKey) {
169
+ if (pubKey.length !== 32)
170
+ throw new Error('publicKeyToHex: expected 32 bytes');
171
+ return '0x' + Buffer.from(pubKey).toString('hex');
172
+ }
173
+ /**
174
+ * Decode a 0x-prefixed hex bytes32 from the registry back to Uint8Array.
175
+ */
176
+ export function hexToPublicKey(hex) {
177
+ const stripped = hex.startsWith('0x') ? hex.slice(2) : hex;
178
+ const bytes = hexToBytes(stripped);
179
+ if (bytes.length !== 32)
180
+ throw new Error('hexToPublicKey: expected 32 hex bytes');
181
+ return bytes;
182
+ }
183
+ // ─────────────────────────────────────────────────────────────
184
+ // Utility
185
+ // ─────────────────────────────────────────────────────────────
186
+ function concat(a, b) {
187
+ const out = new Uint8Array(a.length + b.length);
188
+ out.set(a, 0);
189
+ out.set(b, a.length);
190
+ return out;
191
+ }
192
+ //# sourceMappingURL=crypto.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"crypto.js","sourceRoot":"","sources":["../../src/crypto.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAEH,OAAO,IAAI,MAAgB,WAAW,CAAC;AACvC,OAAO,EAAE,MAAM,EAAE,MAAU,sBAAsB,CAAC;AAClD,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAcjD,gEAAgE;AAChE,sBAAsB;AACtB,gEAAgE;AAEhE;;;GAGG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG,qCAAqC,CAAC;AAE5E;;;;;;;;;;GAUG;AACH,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAC3C,MAAc;IAEd,MAAM,GAAG,GAAO,MAAM,MAAM,CAAC,WAAW,CAAC,sBAAsB,CAAC,CAAC;IACjE,MAAM,MAAM,GAAI,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;IAC1D,MAAM,IAAI,GAAM,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC;IAC3C,MAAM,EAAE,GAAQ,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;IACrD,OAAO,EAAE,SAAS,EAAE,EAAE,CAAC,SAAS,EAAE,UAAU,EAAE,EAAE,CAAC,SAAS,EAAE,CAAC;AAC/D,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,aAAa,CAAC,aAAqB;IACjD,MAAM,QAAQ,GAAG,aAAa,CAAC,UAAU,CAAC,IAAI,CAAC;QAC7C,CAAC,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC,CAAC;QACxB,CAAC,CAAC,aAAa,CAAC;IAClB,MAAM,IAAI,GAAG,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC;IAC1C,MAAM,EAAE,GAAK,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;IAClD,OAAO,EAAE,SAAS,EAAE,EAAE,CAAC,SAAS,EAAE,UAAU,EAAE,EAAE,CAAC,SAAS,EAAE,CAAC;AAC/D,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,oBAAoB,CAAC,aAAqB;IACxD,OAAO,aAAa,CAAC,aAAa,CAAC,CAAC,SAAS,CAAC;AAChD,CAAC;AAED,gEAAgE;AAChE,sCAAsC;AACtC,gEAAgE;AAEhE;;;GAGG;AACH,MAAM,UAAU,oBAAoB;IAClC,OAAO,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC,CAAC,WAAW;AAChE,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,WAAW,CACzB,SAAyB,EACzB,YAAyB;IAEzB,MAAM,KAAK,GAAO,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC;IAC/D,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,SAAS,EAAE,KAAK,EAAE,YAAY,CAAC,CAAC;IACjE,IAAI,CAAC,SAAS;QAAE,MAAM,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAC;IAC7E,OAAO,MAAM,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;AAClC,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,WAAW,CACzB,IAAyB,EACzB,YAAyB;IAEzB,MAAM,KAAK,GAAQ,IAAI,CAAC,QAAQ,CAAC,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC;IAChE,MAAM,UAAU,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC;IAC7D,MAAM,SAAS,GAAI,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,UAAU,EAAE,KAAK,EAAE,YAAY,CAAC,CAAC;IACxE,IAAI,CAAC,SAAS;QAAE,MAAM,IAAI,KAAK,CAAC,iEAAiE,CAAC,CAAC;IACnG,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,gEAAgE;AAChE,gEAAgE;AAChE,gEAAgE;AAEhE;;;;;;;GAOG;AACH,MAAM,UAAU,sBAAsB,CACpC,YAA+B,EAC/B,kBAA+B,EAC/B,gBAA+B;IAE/B,MAAM,KAAK,GAAO,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;IACzD,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,KAAK,EAAE,kBAAkB,EAAE,gBAAgB,CAAC,CAAC;IACtF,IAAI,CAAC,SAAS;QAAE,MAAM,IAAI,KAAK,CAAC,gDAAgD,CAAC,CAAC;IAClF,OAAO,MAAM,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;AAClC,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,oBAAoB,CAClC,IAA8B,EAC9B,eAA8B,EAC9B,gBAA8B;IAE9B,MAAM,KAAK,GAAQ,IAAI,CAAC,QAAQ,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;IAC1D,MAAM,UAAU,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;IACvD,MAAM,GAAG,GAAU,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,UAAU,EAAE,KAAK,EAAE,eAAe,EAAE,gBAAgB,CAAC,CAAC;IACvF,IAAI,CAAC,GAAG;QAAE,MAAM,IAAI,KAAK,CAAC,0EAA0E,CAAC,CAAC;IACtG,OAAO,GAAG,CAAC;AACb,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAC/B,YAAyB,EACzB,OAAgC;IAEhC,OAAO,sBAAsB,CAAC,YAAY,EAAE,OAAO,CAAC,SAAS,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC;AACrF,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,iBAAiB,CAC/B,IAAoB,EACpB,OAA2B;IAE3B,OAAO,oBAAoB,CAAC,IAAI,EAAE,OAAO,CAAC,SAAS,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC;AAC3E,CAAC;AAED,gEAAgE;AAChE,2DAA2D;AAC3D,gEAAgE;AAEhE;;;GAGG;AACH,MAAM,UAAU,cAAc,CAAC,MAAkB;IAC/C,IAAI,MAAM,CAAC,MAAM,KAAK,EAAE;QAAE,MAAM,IAAI,KAAK,CAAC,mCAAmC,CAAC,CAAC;IAC/E,OAAO,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;AACpD,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,cAAc,CAAC,GAAW;IACxC,MAAM,QAAQ,GAAG,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;IAC3D,MAAM,KAAK,GAAM,UAAU,CAAC,QAAQ,CAAC,CAAC;IACtC,IAAI,KAAK,CAAC,MAAM,KAAK,EAAE;QAAE,MAAM,IAAI,KAAK,CAAC,uCAAuC,CAAC,CAAC;IAClF,OAAO,KAAK,CAAC;AACf,CAAC;AAED,gEAAgE;AAChE,WAAW;AACX,gEAAgE;AAEhE,SAAS,MAAM,CAAC,CAAa,EAAE,CAAa;IAC1C,MAAM,GAAG,GAAG,IAAI,UAAU,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC;IAChD,GAAG,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACd,GAAG,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC;IACrB,OAAO,GAAG,CAAC;AACb,CAAC"}
@@ -0,0 +1,106 @@
1
+ /**
2
+ * @file factory-client.ts
3
+ * @notice High-level client for the Web3QL Factory + Database contracts.
4
+ *
5
+ * Entry point for every Web3QL app:
6
+ * ─────────────────────────────────────────────────────────────
7
+ * const web3ql = new Web3QLClient(factoryAddress, signer, keypair, registryAddress);
8
+ *
9
+ * // Register your public key once (one-time, ~40k gas)
10
+ * await web3ql.register();
11
+ *
12
+ * // Create a personal database (or get existing)
13
+ * const db = await web3ql.getOrCreateDatabase();
14
+ *
15
+ * // Create a table
16
+ * const tableAddr = await db.createTable('users', schemaBytes);
17
+ *
18
+ * // Get an encrypted client for that table
19
+ * const users = db.table(tableAddr);
20
+ *
21
+ * // Write (auto-encrypts)
22
+ * await users.writeRaw(users.deriveKey('users', 1n), '{"name":"Alice"}');
23
+ */
24
+ import { ethers } from 'ethers';
25
+ import { EncryptedTableClient } from './table-client.js';
26
+ import { PublicKeyRegistryClient } from './registry.js';
27
+ import type { EncryptionKeypair } from './crypto.js';
28
+ export declare class DatabaseClient {
29
+ readonly address: string;
30
+ private contract;
31
+ private signer;
32
+ private keypair;
33
+ constructor(address: string, signer: ethers.Signer, keypair: EncryptionKeypair);
34
+ /**
35
+ * Create a new encrypted table inside this database.
36
+ * @param name Human-readable table name (matches your schema).
37
+ * @param schemaBytes ABI-encoded schema from @web3ql/compiler's compileSchema().
38
+ * @returns Address of the deployed table proxy.
39
+ */
40
+ createTable(name: string, schemaBytes: string): Promise<string>;
41
+ /**
42
+ * Get the address of an existing table by name.
43
+ * Returns ethers.ZeroAddress if not found.
44
+ */
45
+ getTable(name: string): Promise<string>;
46
+ /**
47
+ * List all table names in this database.
48
+ */
49
+ listTables(): Promise<string[]>;
50
+ /**
51
+ * Drop (remove from registry) a table by name.
52
+ * Records inside the table are NOT purged by this call — they remain
53
+ * as unreachable ciphertext. Use SchemaManager.dropTable() first to
54
+ * bulk-delete records if you want storage refunds.
55
+ */
56
+ dropTable(name: string): Promise<ethers.TransactionReceipt>;
57
+ /**
58
+ * Get an EncryptedTableClient for a specific table address.
59
+ * Use this after createTable() or getTable() to read/write records.
60
+ */
61
+ table(tableAddress: string): EncryptedTableClient;
62
+ }
63
+ export declare class Web3QLClient {
64
+ private factory;
65
+ private signer;
66
+ private keypair;
67
+ readonly registry: PublicKeyRegistryClient;
68
+ constructor(factoryAddress: string, signer: ethers.Signer, keypair: EncryptionKeypair, registryAddress: string);
69
+ /**
70
+ * Register the caller's encryption public key on-chain.
71
+ * Must be called once per address before anyone can share records
72
+ * with that address. Safe to call again — will overwrite.
73
+ */
74
+ register(): Promise<ethers.TransactionReceipt>;
75
+ /**
76
+ * Check if an address has registered its public key.
77
+ */
78
+ isRegistered(address: string): Promise<boolean>;
79
+ /**
80
+ * Create a new personal database for the calling wallet.
81
+ * Most users only ever need one database — use getOrCreateDatabase().
82
+ * @param name Human-readable label stored immutably on-chain.
83
+ */
84
+ createDatabase(name?: string): Promise<DatabaseClient>;
85
+ /**
86
+ * Get all database proxies owned by a user.
87
+ */
88
+ getDatabases(owner?: string): Promise<string[]>;
89
+ /**
90
+ * Return the first existing database for the caller, or create one
91
+ * if none exists. Idempotent — safe to call on every app startup.
92
+ * @param name Passed to createDatabase() only when a new one is created.
93
+ */
94
+ getOrCreateDatabase(name?: string): Promise<DatabaseClient>;
95
+ /**
96
+ * Wrap an already-known database address (e.g. loaded from config).
97
+ */
98
+ database(address: string): DatabaseClient;
99
+ /**
100
+ * Remove a database from the factory’s registry.
101
+ * The proxy contract is NOT destroyed — it remains on-chain.
102
+ * After calling this it will no longer appear in getDatabases().
103
+ */
104
+ removeDatabase(dbAddress: string): Promise<ethers.TransactionReceipt>;
105
+ }
106
+ //# sourceMappingURL=factory-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"factory-client.d.ts","sourceRoot":"","sources":["../../src/factory-client.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAoC,QAAQ,CAAC;AAC9D,OAAO,EAAE,oBAAoB,EAAE,MAAsB,mBAAmB,CAAC;AACzE,OAAO,EAAE,uBAAuB,EAAE,MAAmB,eAAe,CAAC;AACrE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAoB,aAAa,CAAC;AA4BnE,qBAAa,cAAc;IACzB,QAAQ,CAAC,OAAO,EAAG,MAAM,CAAC;IAC1B,OAAO,CAAC,QAAQ,CAAmB;IACnC,OAAO,CAAC,MAAM,CAAmB;IACjC,OAAO,CAAC,OAAO,CAAsB;gBAGnC,OAAO,EAAI,MAAM,EACjB,MAAM,EAAK,MAAM,CAAC,MAAM,EACxB,OAAO,EAAI,iBAAiB;IAQ9B;;;;;OAKG;IACG,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAiBrE;;;OAGG;IACG,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAK7C;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;IAKrC;;;;;OAKG;IACG,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,kBAAkB,CAAC;IAMjE;;;OAGG;IACH,KAAK,CAAC,YAAY,EAAE,MAAM,GAAG,oBAAoB;CAGlD;AAMD,qBAAa,YAAY;IACvB,OAAO,CAAC,OAAO,CAAoB;IACnC,OAAO,CAAC,MAAM,CAAmB;IACjC,OAAO,CAAC,OAAO,CAAsB;IACrC,QAAQ,CAAC,QAAQ,EAAE,uBAAuB,CAAC;gBAGzC,cAAc,EAAK,MAAM,EACzB,MAAM,EAAa,MAAM,CAAC,MAAM,EAChC,OAAO,EAAY,iBAAiB,EACpC,eAAe,EAAI,MAAM;IAQ3B;;;;OAIG;IACG,QAAQ,IAAI,OAAO,CAAC,MAAM,CAAC,kBAAkB,CAAC;IAIpD;;OAEG;IACG,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAIrD;;;;OAIG;IACG,cAAc,CAAC,IAAI,GAAE,MAAW,GAAG,OAAO,CAAC,cAAc,CAAC;IAqBhE;;OAEG;IACG,YAAY,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAMrD;;;;OAIG;IACG,mBAAmB,CAAC,IAAI,GAAE,MAAW,GAAG,OAAO,CAAC,cAAc,CAAC;IAQrE;;OAEG;IACH,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,cAAc;IAIzC;;;;OAIG;IACG,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,kBAAkB,CAAC;CAK5E"}