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.
- package/README.md +66 -0
- package/contracts/PublicKeyRegistry.sol +87 -0
- package/dist/src/access.d.ts +176 -0
- package/dist/src/access.d.ts.map +1 -0
- package/dist/src/access.js +283 -0
- package/dist/src/access.js.map +1 -0
- package/dist/src/batch.d.ts +107 -0
- package/dist/src/batch.d.ts.map +1 -0
- package/dist/src/batch.js +188 -0
- package/dist/src/batch.js.map +1 -0
- package/dist/src/cli.d.ts +40 -0
- package/dist/src/cli.d.ts.map +1 -0
- package/dist/src/cli.js +361 -0
- package/dist/src/cli.js.map +1 -0
- package/dist/src/constraints.d.ts +126 -0
- package/dist/src/constraints.d.ts.map +1 -0
- package/dist/src/constraints.js +192 -0
- package/dist/src/constraints.js.map +1 -0
- package/dist/src/crypto.d.ts +118 -0
- package/dist/src/crypto.d.ts.map +1 -0
- package/dist/src/crypto.js +192 -0
- package/dist/src/crypto.js.map +1 -0
- package/dist/src/factory-client.d.ts +106 -0
- package/dist/src/factory-client.d.ts.map +1 -0
- package/dist/src/factory-client.js +202 -0
- package/dist/src/factory-client.js.map +1 -0
- package/dist/src/index-cache.d.ts +156 -0
- package/dist/src/index-cache.d.ts.map +1 -0
- package/dist/src/index-cache.js +265 -0
- package/dist/src/index-cache.js.map +1 -0
- package/dist/src/index.d.ts +60 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +60 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/migrations.d.ts +114 -0
- package/dist/src/migrations.d.ts.map +1 -0
- package/dist/src/migrations.js +173 -0
- package/dist/src/migrations.js.map +1 -0
- package/dist/src/model.d.ts +198 -0
- package/dist/src/model.d.ts.map +1 -0
- package/dist/src/model.js +379 -0
- package/dist/src/model.js.map +1 -0
- package/dist/src/query.d.ts +155 -0
- package/dist/src/query.d.ts.map +1 -0
- package/dist/src/query.js +386 -0
- package/dist/src/query.js.map +1 -0
- package/dist/src/registry.d.ts +45 -0
- package/dist/src/registry.d.ts.map +1 -0
- package/dist/src/registry.js +80 -0
- package/dist/src/registry.js.map +1 -0
- package/dist/src/schema-manager.d.ts +109 -0
- package/dist/src/schema-manager.d.ts.map +1 -0
- package/dist/src/schema-manager.js +259 -0
- package/dist/src/schema-manager.js.map +1 -0
- package/dist/src/table-client.d.ts +156 -0
- package/dist/src/table-client.d.ts.map +1 -0
- package/dist/src/table-client.js +292 -0
- package/dist/src/table-client.js.map +1 -0
- package/dist/src/typed-table.d.ts +159 -0
- package/dist/src/typed-table.d.ts.map +1 -0
- package/dist/src/typed-table.js +246 -0
- package/dist/src/typed-table.js.map +1 -0
- package/dist/src/types.d.ts +48 -0
- package/dist/src/types.d.ts.map +1 -0
- package/dist/src/types.js +222 -0
- package/dist/src/types.js.map +1 -0
- package/keyManager.js +337 -0
- package/package.json +38 -0
- package/src/access.ts +421 -0
- package/src/batch.ts +259 -0
- package/src/cli.ts +349 -0
- package/src/constraints.ts +283 -0
- package/src/crypto.ts +239 -0
- package/src/factory-client.ts +237 -0
- package/src/index-cache.ts +351 -0
- package/src/index.ts +171 -0
- package/src/migrations.ts +215 -0
- package/src/model.ts +538 -0
- package/src/query.ts +508 -0
- package/src/registry.ts +100 -0
- package/src/schema-manager.ts +301 -0
- package/src/table-client.ts +393 -0
- package/src/typed-table.ts +340 -0
- package/src/types.ts +284 -0
- package/tsconfig.json +22 -0
- package/walletUtils.js +204 -0
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @web3ql/sdk — Public API (v1.2)
|
|
3
|
+
*
|
|
4
|
+
* ─────────────────────────────────────────────────────────────
|
|
5
|
+
* import {
|
|
6
|
+
* // Core clients
|
|
7
|
+
* Web3QLClient, DatabaseClient, EncryptedTableClient,
|
|
8
|
+
* // High-level typed API
|
|
9
|
+
* TypedTableClient,
|
|
10
|
+
* // Type system (v1.1+)
|
|
11
|
+
* validateAndEncode, decodeRow, encodeFieldValue, decodeFieldValue,
|
|
12
|
+
* // Query builder (v1.1+)
|
|
13
|
+
* query,
|
|
14
|
+
* // Migrations (v1.1+)
|
|
15
|
+
* MigrationRunner, addColumn, dropColumn, renameColumn, changeType,
|
|
16
|
+
* // Constraints (v1.2)
|
|
17
|
+
* ConstraintEngine, ConstraintViolation, AutoIncrementCounter,
|
|
18
|
+
* // Index cache (v1.2)
|
|
19
|
+
* TableIndexCache, QueryRelayClient,
|
|
20
|
+
* // Batch writes (v1.2)
|
|
21
|
+
* BatchWriter, buildCrossTableBatch,
|
|
22
|
+
* // Access control (v1.2)
|
|
23
|
+
* AccessManager, PublicTableClient,
|
|
24
|
+
* // Schema management (v1.2)
|
|
25
|
+
* SchemaManager, decodeSchemaBytes, diffSchema,
|
|
26
|
+
* // Crypto
|
|
27
|
+
* deriveKeypairFromWallet,
|
|
28
|
+
* Role,
|
|
29
|
+
* } from '@web3ql/sdk';
|
|
30
|
+
* ─────────────────────────────────────────────────────────────
|
|
31
|
+
*/
|
|
32
|
+
export { Web3QLClient, DatabaseClient } from './factory-client.js';
|
|
33
|
+
export { EncryptedTableClient, Role } from './table-client.js';
|
|
34
|
+
export type { RawRecord } from './table-client.js';
|
|
35
|
+
export { PublicKeyRegistryClient } from './registry.js';
|
|
36
|
+
export { TypedTableClient } from './typed-table.js';
|
|
37
|
+
export type { FindManyOptions, RecordWithId, WhereTuple, SchemaDefinition, } from './typed-table.js';
|
|
38
|
+
export { NULL_SENTINEL, validateAndEncode, decodeRow, encodeFieldValue, decodeFieldValue, } from './types.js';
|
|
39
|
+
export type { FieldType, FieldDescriptor } from './types.js';
|
|
40
|
+
export { query, QueryBuilder } from './query.js';
|
|
41
|
+
export type { Row, WhereOperator, WhereClause, OrderByClause, SortDirection, AggregateOptions, AggregateResult, JoinType, JoinClause, TimeBucketUnit, HavingClause, } from './query.js';
|
|
42
|
+
export { MigrationRunner, addColumn, addColumnSchema, dropColumn, dropColumnSchema, renameColumn, renameColumnSchema, changeType, computeColumn, } from './migrations.js';
|
|
43
|
+
export type { Migration, RowTransformer, SchemaTransformer } from './migrations.js';
|
|
44
|
+
export { ConstraintEngine, ConstraintViolation, AutoIncrementCounter, } from './constraints.js';
|
|
45
|
+
export type { Constraint, UniqueConstraint, CheckConstraint, ForeignKeyConstraint, NotNullConstraint, } from './constraints.js';
|
|
46
|
+
export { TableIndexCache, QueryRelayClient, } from './index-cache.js';
|
|
47
|
+
export type { IndexEntry, IndexCacheOptions, RelayQueryRequest, RelayQueryResponse, } from './index-cache.js';
|
|
48
|
+
export { BatchWriter, buildCrossTableBatch, MULTICALL3_ADDRESS, } from './batch.js';
|
|
49
|
+
export type { CrossTableOp } from './batch.js';
|
|
50
|
+
export { AccessManager, PublicTableClient, grantMetaKey, generateColumnKeySet, encryptWithColumnKeys, decryptColumnBlobs, } from './access.js';
|
|
51
|
+
export type { TimedGrant, CapabilityToken, ColumnKeySet, } from './access.js';
|
|
52
|
+
export { SchemaManager, decodeSchemaBytes, diffSchema, } from './schema-manager.js';
|
|
53
|
+
export type { SchemaChange, SchemaChangeType, } from './schema-manager.js';
|
|
54
|
+
export { KEY_DERIVATION_MESSAGE, deriveKeypairFromWallet, // ✅ browser-compatible (recommended)
|
|
55
|
+
deriveKeypair, // ⚠️ deprecated: different keypair to browser
|
|
56
|
+
publicKeyFromPrivate, generateSymmetricKey, encryptData, decryptData, encryptKeyForSelf, encryptKeyForRecipient, decryptKeyForSelf, decryptKeyFromSender, publicKeyToHex, hexToPublicKey, } from './crypto.js';
|
|
57
|
+
export type { EncryptionKeypair } from './crypto.js';
|
|
58
|
+
export { Model } from './model.js';
|
|
59
|
+
export type { ModelOptions, RelatedCreateOptions, } from './model.js';
|
|
60
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAGH,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,MAAoB,qBAAqB,CAAC;AACjF,OAAO,EAAE,oBAAoB,EAAE,IAAI,EAAE,MAAsB,mBAAmB,CAAC;AAC/E,YAAY,EAAE,SAAS,EAAE,MAAkC,mBAAmB,CAAC;AAC/E,OAAO,EAAE,uBAAuB,EAAE,MAAyB,eAAe,CAAC;AAG3E,OAAO,EAAE,gBAAgB,EAAE,MAAgC,kBAAkB,CAAC;AAC9E,YAAY,EACV,eAAe,EACf,YAAY,EACZ,UAAU,EACV,gBAAgB,GACjB,MAA0D,kBAAkB,CAAC;AAG9E,OAAO,EACL,aAAa,EACb,iBAAiB,EACjB,SAAS,EACT,gBAAgB,EAChB,gBAAgB,GACjB,MAA0D,YAAY,CAAC;AACxE,YAAY,EAAE,SAAS,EAAE,eAAe,EAAE,MAAiB,YAAY,CAAC;AAGxE,OAAO,EAAE,KAAK,EAAE,YAAY,EAAE,MAA6B,YAAY,CAAC;AACxE,YAAY,EACV,GAAG,EACH,aAAa,EACb,WAAW,EACX,aAAa,EACb,aAAa,EACb,gBAAgB,EAChB,eAAe,EACf,QAAQ,EACR,UAAU,EACV,cAAc,EACd,YAAY,GACb,MAA0D,YAAY,CAAC;AAGxE,OAAO,EACL,eAAe,EACf,SAAS,EACT,eAAe,EACf,UAAU,EACV,gBAAgB,EAChB,YAAY,EACZ,kBAAkB,EAClB,UAAU,EACV,aAAa,GACd,MAA0D,iBAAiB,CAAC;AAC7E,YAAY,EAAE,SAAS,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAGpF,OAAO,EACL,gBAAgB,EAChB,mBAAmB,EACnB,oBAAoB,GACrB,MAA0D,kBAAkB,CAAC;AAC9E,YAAY,EACV,UAAU,EACV,gBAAgB,EAChB,eAAe,EACf,oBAAoB,EACpB,iBAAiB,GAClB,MAA0D,kBAAkB,CAAC;AAG9E,OAAO,EACL,eAAe,EACf,gBAAgB,GACjB,MAA0D,kBAAkB,CAAC;AAC9E,YAAY,EACV,UAAU,EACV,iBAAiB,EACjB,iBAAiB,EACjB,kBAAkB,GACnB,MAA0D,kBAAkB,CAAC;AAG9E,OAAO,EACL,WAAW,EACX,oBAAoB,EACpB,kBAAkB,GACnB,MAA0D,YAAY,CAAC;AACxE,YAAY,EAAE,YAAY,EAAE,MAA+B,YAAY,CAAC;AAGxE,OAAO,EACL,aAAa,EACb,iBAAiB,EACjB,YAAY,EACZ,oBAAoB,EACpB,qBAAqB,EACrB,kBAAkB,GACnB,MAA0D,aAAa,CAAC;AACzE,YAAY,EACV,UAAU,EACV,eAAe,EACf,YAAY,GACb,MAA0D,aAAa,CAAC;AAGzE,OAAO,EACL,aAAa,EACb,iBAAiB,EACjB,UAAU,GACX,MAA0D,qBAAqB,CAAC;AACjF,YAAY,EACV,YAAY,EACZ,gBAAgB,GACjB,MAA0D,qBAAqB,CAAC;AAGjF,OAAO,EACL,sBAAsB,EACtB,uBAAuB,EAAG,qCAAqC;AAC/D,aAAa,EAAa,+CAA+C;AACzE,oBAAoB,EACpB,oBAAoB,EACpB,WAAW,EACX,WAAW,EACX,iBAAiB,EACjB,sBAAsB,EACtB,iBAAiB,EACjB,oBAAoB,EACpB,cAAc,EACd,cAAc,GACf,MAA0D,aAAa,CAAC;AACzE,YAAY,EAAE,iBAAiB,EAAE,MAA0B,aAAa,CAAC;AAGzE,OAAO,EAAE,KAAK,EAAE,MAA2C,YAAY,CAAC;AACxE,YAAY,EACV,YAAY,EACZ,oBAAoB,GACrB,MAA0D,YAAY,CAAC"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @web3ql/sdk — Public API (v1.2)
|
|
3
|
+
*
|
|
4
|
+
* ─────────────────────────────────────────────────────────────
|
|
5
|
+
* import {
|
|
6
|
+
* // Core clients
|
|
7
|
+
* Web3QLClient, DatabaseClient, EncryptedTableClient,
|
|
8
|
+
* // High-level typed API
|
|
9
|
+
* TypedTableClient,
|
|
10
|
+
* // Type system (v1.1+)
|
|
11
|
+
* validateAndEncode, decodeRow, encodeFieldValue, decodeFieldValue,
|
|
12
|
+
* // Query builder (v1.1+)
|
|
13
|
+
* query,
|
|
14
|
+
* // Migrations (v1.1+)
|
|
15
|
+
* MigrationRunner, addColumn, dropColumn, renameColumn, changeType,
|
|
16
|
+
* // Constraints (v1.2)
|
|
17
|
+
* ConstraintEngine, ConstraintViolation, AutoIncrementCounter,
|
|
18
|
+
* // Index cache (v1.2)
|
|
19
|
+
* TableIndexCache, QueryRelayClient,
|
|
20
|
+
* // Batch writes (v1.2)
|
|
21
|
+
* BatchWriter, buildCrossTableBatch,
|
|
22
|
+
* // Access control (v1.2)
|
|
23
|
+
* AccessManager, PublicTableClient,
|
|
24
|
+
* // Schema management (v1.2)
|
|
25
|
+
* SchemaManager, decodeSchemaBytes, diffSchema,
|
|
26
|
+
* // Crypto
|
|
27
|
+
* deriveKeypairFromWallet,
|
|
28
|
+
* Role,
|
|
29
|
+
* } from '@web3ql/sdk';
|
|
30
|
+
* ─────────────────────────────────────────────────────────────
|
|
31
|
+
*/
|
|
32
|
+
// ── Core clients ──────────────────────────────────────────────
|
|
33
|
+
export { Web3QLClient, DatabaseClient } from './factory-client.js';
|
|
34
|
+
export { EncryptedTableClient, Role } from './table-client.js';
|
|
35
|
+
export { PublicKeyRegistryClient } from './registry.js';
|
|
36
|
+
// ── High-level typed API (Prisma-style) ───────────────────────
|
|
37
|
+
export { TypedTableClient } from './typed-table.js';
|
|
38
|
+
// ── v1.1 Type system (encode/decode/validate) ─────────────────
|
|
39
|
+
export { NULL_SENTINEL, validateAndEncode, decodeRow, encodeFieldValue, decodeFieldValue, } from './types.js';
|
|
40
|
+
// ── v1.1 Query builder ────────────────────────────────────────
|
|
41
|
+
export { query, QueryBuilder } from './query.js';
|
|
42
|
+
// ── v1.1 Migration framework ──────────────────────────────────
|
|
43
|
+
export { MigrationRunner, addColumn, addColumnSchema, dropColumn, dropColumnSchema, renameColumn, renameColumnSchema, changeType, computeColumn, } from './migrations.js';
|
|
44
|
+
// ── v1.2 Integrity constraints ────────────────────────────────
|
|
45
|
+
export { ConstraintEngine, ConstraintViolation, AutoIncrementCounter, } from './constraints.js';
|
|
46
|
+
// ── v1.2 Index cache + relay query client ─────────────────────
|
|
47
|
+
export { TableIndexCache, QueryRelayClient, } from './index-cache.js';
|
|
48
|
+
// ── v1.2 Batch writes (Multicall3) ────────────────────────────
|
|
49
|
+
export { BatchWriter, buildCrossTableBatch, MULTICALL3_ADDRESS, } from './batch.js';
|
|
50
|
+
// ── v1.2 Advanced access control ─────────────────────────────
|
|
51
|
+
export { AccessManager, PublicTableClient, grantMetaKey, generateColumnKeySet, encryptWithColumnKeys, decryptColumnBlobs, } from './access.js';
|
|
52
|
+
// ── v1.2 Schema management ────────────────────────────────────
|
|
53
|
+
export { SchemaManager, decodeSchemaBytes, diffSchema, } from './schema-manager.js';
|
|
54
|
+
// ── Crypto primitives ─────────────────────────────────────────
|
|
55
|
+
export { KEY_DERIVATION_MESSAGE, deriveKeypairFromWallet, // ✅ browser-compatible (recommended)
|
|
56
|
+
deriveKeypair, // ⚠️ deprecated: different keypair to browser
|
|
57
|
+
publicKeyFromPrivate, generateSymmetricKey, encryptData, decryptData, encryptKeyForSelf, encryptKeyForRecipient, decryptKeyForSelf, decryptKeyFromSender, publicKeyToHex, hexToPublicKey, } from './crypto.js';
|
|
58
|
+
// ── v1.3 ORM — Model + Relation wires ────────────────────────
|
|
59
|
+
export { Model } from './model.js';
|
|
60
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAEH,iEAAiE;AACjE,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,MAAoB,qBAAqB,CAAC;AACjF,OAAO,EAAE,oBAAoB,EAAE,IAAI,EAAE,MAAsB,mBAAmB,CAAC;AAE/E,OAAO,EAAE,uBAAuB,EAAE,MAAyB,eAAe,CAAC;AAE3E,iEAAiE;AACjE,OAAO,EAAE,gBAAgB,EAAE,MAAgC,kBAAkB,CAAC;AAQ9E,iEAAiE;AACjE,OAAO,EACL,aAAa,EACb,iBAAiB,EACjB,SAAS,EACT,gBAAgB,EAChB,gBAAgB,GACjB,MAA0D,YAAY,CAAC;AAGxE,iEAAiE;AACjE,OAAO,EAAE,KAAK,EAAE,YAAY,EAAE,MAA6B,YAAY,CAAC;AAexE,iEAAiE;AACjE,OAAO,EACL,eAAe,EACf,SAAS,EACT,eAAe,EACf,UAAU,EACV,gBAAgB,EAChB,YAAY,EACZ,kBAAkB,EAClB,UAAU,EACV,aAAa,GACd,MAA0D,iBAAiB,CAAC;AAG7E,iEAAiE;AACjE,OAAO,EACL,gBAAgB,EAChB,mBAAmB,EACnB,oBAAoB,GACrB,MAA0D,kBAAkB,CAAC;AAS9E,iEAAiE;AACjE,OAAO,EACL,eAAe,EACf,gBAAgB,GACjB,MAA0D,kBAAkB,CAAC;AAQ9E,iEAAiE;AACjE,OAAO,EACL,WAAW,EACX,oBAAoB,EACpB,kBAAkB,GACnB,MAA0D,YAAY,CAAC;AAGxE,gEAAgE;AAChE,OAAO,EACL,aAAa,EACb,iBAAiB,EACjB,YAAY,EACZ,oBAAoB,EACpB,qBAAqB,EACrB,kBAAkB,GACnB,MAA0D,aAAa,CAAC;AAOzE,iEAAiE;AACjE,OAAO,EACL,aAAa,EACb,iBAAiB,EACjB,UAAU,GACX,MAA0D,qBAAqB,CAAC;AAMjF,iEAAiE;AACjE,OAAO,EACL,sBAAsB,EACtB,uBAAuB,EAAG,qCAAqC;AAC/D,aAAa,EAAa,+CAA+C;AACzE,oBAAoB,EACpB,oBAAoB,EACpB,WAAW,EACX,WAAW,EACX,iBAAiB,EACjB,sBAAsB,EACtB,iBAAiB,EACjB,oBAAoB,EACpB,cAAc,EACd,cAAc,GACf,MAA0D,aAAa,CAAC;AAGzE,gEAAgE;AAChE,OAAO,EAAE,KAAK,EAAE,MAA2C,YAAY,CAAC"}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file migrations.ts
|
|
3
|
+
* @notice Web3QL v1.1 — schema migration framework.
|
|
4
|
+
*
|
|
5
|
+
* Because schemas are stored as bytes on-chain, adding or removing columns
|
|
6
|
+
* is an off-chain SDK concern:
|
|
7
|
+
*
|
|
8
|
+
* • ADD COLUMN → new field appears with its DEFAULT value for old records
|
|
9
|
+
* • DROP COLUMN → field is silently ignored on read, omitted on write
|
|
10
|
+
* • RENAME → read uses old name, write uses new name
|
|
11
|
+
* • CHANGE TYPE → codec changes; old wire values are transparently converted
|
|
12
|
+
*
|
|
13
|
+
* Migrations are run client-side during read/write. They do NOT require any
|
|
14
|
+
* contract call or gas. The on-chain ciphertext is re-encrypted with the new
|
|
15
|
+
* schema on the next write (lazy migration).
|
|
16
|
+
*
|
|
17
|
+
* Usage:
|
|
18
|
+
* ─────────────────────────────────────────────────────────────
|
|
19
|
+
* const migrations = new MigrationRunner([
|
|
20
|
+
* {
|
|
21
|
+
* version: 1,
|
|
22
|
+
* description: 'Add role field',
|
|
23
|
+
* up: addColumn({ name: 'role', type: 'ENUM', enumValues: ['user','admin'], default: 'user' }),
|
|
24
|
+
* },
|
|
25
|
+
* {
|
|
26
|
+
* version: 2,
|
|
27
|
+
* description: 'Rename email → emailAddress',
|
|
28
|
+
* up: renameColumn('email', 'emailAddress'),
|
|
29
|
+
* },
|
|
30
|
+
* {
|
|
31
|
+
* version: 3,
|
|
32
|
+
* description: 'Drop legacy field',
|
|
33
|
+
* up: dropColumn('legacyField'),
|
|
34
|
+
* },
|
|
35
|
+
* ]);
|
|
36
|
+
*
|
|
37
|
+
* // Apply to a record read from chain
|
|
38
|
+
* const migratedData = migrations.applyToRecord(rawDecoded, fromVersion = 0);
|
|
39
|
+
*
|
|
40
|
+
* // Apply to a schema definition (for TypedTableClient)
|
|
41
|
+
* const latestSchema = migrations.applyToSchema(v0Schema);
|
|
42
|
+
* ─────────────────────────────────────────────────────────────
|
|
43
|
+
*/
|
|
44
|
+
import type { SchemaDefinition, FieldDescriptor } from './types.js';
|
|
45
|
+
export type RowTransformer = (row: Record<string, unknown>) => Record<string, unknown>;
|
|
46
|
+
export type SchemaTransformer = (schema: SchemaDefinition) => SchemaDefinition;
|
|
47
|
+
export interface Migration {
|
|
48
|
+
/** Monotonically increasing version number (1, 2, 3…) */
|
|
49
|
+
version: number;
|
|
50
|
+
description: string;
|
|
51
|
+
/** Transform the row data from previous version to this version */
|
|
52
|
+
up: RowTransformer;
|
|
53
|
+
/** Transform the schema definition from previous version to this version */
|
|
54
|
+
schema?: SchemaTransformer;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* ADD COLUMN — inserts the field with its default value into records
|
|
58
|
+
* that don't have it yet.
|
|
59
|
+
*/
|
|
60
|
+
export declare function addColumn(field: FieldDescriptor): RowTransformer;
|
|
61
|
+
/** Schema variant of addColumn */
|
|
62
|
+
export declare function addColumnSchema(field: FieldDescriptor): SchemaTransformer;
|
|
63
|
+
/**
|
|
64
|
+
* DROP COLUMN — removes the field from records.
|
|
65
|
+
* Old ciphertext data is discarded on next write.
|
|
66
|
+
*/
|
|
67
|
+
export declare function dropColumn(fieldName: string): RowTransformer;
|
|
68
|
+
/** Schema variant of dropColumn */
|
|
69
|
+
export declare function dropColumnSchema(fieldName: string): SchemaTransformer;
|
|
70
|
+
/**
|
|
71
|
+
* RENAME COLUMN — moves value from oldName to newName.
|
|
72
|
+
*/
|
|
73
|
+
export declare function renameColumn(oldName: string, newName: string): RowTransformer;
|
|
74
|
+
/** Schema variant of renameColumn */
|
|
75
|
+
export declare function renameColumnSchema(oldName: string, newName: string): SchemaTransformer;
|
|
76
|
+
/**
|
|
77
|
+
* CHANGE TYPE — re-encode a field's value through a transform function.
|
|
78
|
+
* Supply a function that converts the old wire value to the new wire value.
|
|
79
|
+
*
|
|
80
|
+
* @example
|
|
81
|
+
* // Convert TEXT → TIMESTAMP (ISO string → unix ms)
|
|
82
|
+
* changeType('createdAt', (v) => new Date(String(v)).getTime())
|
|
83
|
+
*/
|
|
84
|
+
export declare function changeType(fieldName: string, transform: (oldValue: unknown) => unknown): RowTransformer;
|
|
85
|
+
/**
|
|
86
|
+
* COMPUTE COLUMN — derive a new field from existing fields.
|
|
87
|
+
* Called only if the field is absent (so it doesn't overwrite on re-migrations).
|
|
88
|
+
*/
|
|
89
|
+
export declare function computeColumn(fieldName: string, compute: (row: Record<string, unknown>) => unknown): RowTransformer;
|
|
90
|
+
export declare class MigrationRunner {
|
|
91
|
+
private migrations;
|
|
92
|
+
constructor(migrations: Migration[]);
|
|
93
|
+
/**
|
|
94
|
+
* Apply all migrations with version > `fromVersion` to a single record row.
|
|
95
|
+
*
|
|
96
|
+
* @param row Decoded record from the chain (before migration)
|
|
97
|
+
* @param fromVersion The schema version the record was written at. Use the
|
|
98
|
+
* VERSION field stored in the record, or 0 if absent.
|
|
99
|
+
*/
|
|
100
|
+
applyToRecord(row: Record<string, unknown>, fromVersion?: number): Record<string, unknown>;
|
|
101
|
+
/**
|
|
102
|
+
* Apply all schema migrations from `fromVersion` to the latest version,
|
|
103
|
+
* producing an up-to-date SchemaDefinition for TypedTableClient.
|
|
104
|
+
*/
|
|
105
|
+
applyToSchema(baseSchema: SchemaDefinition, fromVersion?: number): SchemaDefinition;
|
|
106
|
+
/** The latest migration version number. */
|
|
107
|
+
get latestVersion(): number;
|
|
108
|
+
/** List all registered migrations in version order. */
|
|
109
|
+
list(): {
|
|
110
|
+
version: number;
|
|
111
|
+
description: string;
|
|
112
|
+
}[];
|
|
113
|
+
}
|
|
114
|
+
//# sourceMappingURL=migrations.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"migrations.d.ts","sourceRoot":"","sources":["../../src/migrations.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAMpE,MAAM,MAAM,cAAc,GAAG,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AACvF,MAAM,MAAM,iBAAiB,GAAG,CAAC,MAAM,EAAE,gBAAgB,KAAK,gBAAgB,CAAC;AAE/E,MAAM,WAAW,SAAS;IACxB,yDAAyD;IACzD,OAAO,EAAM,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,mEAAmE;IACnE,EAAE,EAAW,cAAc,CAAC;IAC5B,4EAA4E;IAC5E,MAAM,CAAC,EAAM,iBAAiB,CAAC;CAChC;AAMD;;;GAGG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,eAAe,GAAG,cAAc,CAQhE;AAED,kCAAkC;AAClC,wBAAgB,eAAe,CAAC,KAAK,EAAE,eAAe,GAAG,iBAAiB,CAKzE;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,cAAc,CAM5D;AAED,mCAAmC;AACnC,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,iBAAiB,CAErE;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,cAAc,CAO7E;AAED,qCAAqC;AACrC,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,iBAAiB,CAGtF;AAED;;;;;;;GAOG;AACH,wBAAgB,UAAU,CACxB,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,CAAC,QAAQ,EAAE,OAAO,KAAK,OAAO,GACxC,cAAc,CAKhB;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAC3B,SAAS,EAAE,MAAM,EACjB,OAAO,EAAI,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,GACnD,cAAc,CAKhB;AAMD,qBAAa,eAAe;IAC1B,OAAO,CAAC,UAAU,CAAc;gBAEpB,UAAU,EAAE,SAAS,EAAE;IAKnC;;;;;;OAMG;IACH,aAAa,CACX,GAAG,EAAU,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACpC,WAAW,GAAE,MAAU,GACtB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAU1B;;;OAGG;IACH,aAAa,CACX,UAAU,EAAG,gBAAgB,EAC7B,WAAW,GAAE,MAAU,GACtB,gBAAgB;IAUnB,2CAA2C;IAC3C,IAAI,aAAa,IAAI,MAAM,CAE1B;IAED,uDAAuD;IACvD,IAAI,IAAI;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,EAAE;CAGnD"}
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file migrations.ts
|
|
3
|
+
* @notice Web3QL v1.1 — schema migration framework.
|
|
4
|
+
*
|
|
5
|
+
* Because schemas are stored as bytes on-chain, adding or removing columns
|
|
6
|
+
* is an off-chain SDK concern:
|
|
7
|
+
*
|
|
8
|
+
* • ADD COLUMN → new field appears with its DEFAULT value for old records
|
|
9
|
+
* • DROP COLUMN → field is silently ignored on read, omitted on write
|
|
10
|
+
* • RENAME → read uses old name, write uses new name
|
|
11
|
+
* • CHANGE TYPE → codec changes; old wire values are transparently converted
|
|
12
|
+
*
|
|
13
|
+
* Migrations are run client-side during read/write. They do NOT require any
|
|
14
|
+
* contract call or gas. The on-chain ciphertext is re-encrypted with the new
|
|
15
|
+
* schema on the next write (lazy migration).
|
|
16
|
+
*
|
|
17
|
+
* Usage:
|
|
18
|
+
* ─────────────────────────────────────────────────────────────
|
|
19
|
+
* const migrations = new MigrationRunner([
|
|
20
|
+
* {
|
|
21
|
+
* version: 1,
|
|
22
|
+
* description: 'Add role field',
|
|
23
|
+
* up: addColumn({ name: 'role', type: 'ENUM', enumValues: ['user','admin'], default: 'user' }),
|
|
24
|
+
* },
|
|
25
|
+
* {
|
|
26
|
+
* version: 2,
|
|
27
|
+
* description: 'Rename email → emailAddress',
|
|
28
|
+
* up: renameColumn('email', 'emailAddress'),
|
|
29
|
+
* },
|
|
30
|
+
* {
|
|
31
|
+
* version: 3,
|
|
32
|
+
* description: 'Drop legacy field',
|
|
33
|
+
* up: dropColumn('legacyField'),
|
|
34
|
+
* },
|
|
35
|
+
* ]);
|
|
36
|
+
*
|
|
37
|
+
* // Apply to a record read from chain
|
|
38
|
+
* const migratedData = migrations.applyToRecord(rawDecoded, fromVersion = 0);
|
|
39
|
+
*
|
|
40
|
+
* // Apply to a schema definition (for TypedTableClient)
|
|
41
|
+
* const latestSchema = migrations.applyToSchema(v0Schema);
|
|
42
|
+
* ─────────────────────────────────────────────────────────────
|
|
43
|
+
*/
|
|
44
|
+
// ─────────────────────────────────────────────────────────────
|
|
45
|
+
// Built-in migration helpers
|
|
46
|
+
// ─────────────────────────────────────────────────────────────
|
|
47
|
+
/**
|
|
48
|
+
* ADD COLUMN — inserts the field with its default value into records
|
|
49
|
+
* that don't have it yet.
|
|
50
|
+
*/
|
|
51
|
+
export function addColumn(field) {
|
|
52
|
+
return (row) => {
|
|
53
|
+
if (row[field.name] !== undefined && row[field.name] !== null)
|
|
54
|
+
return row;
|
|
55
|
+
const defaultVal = field.default != null
|
|
56
|
+
? (typeof field.default === 'function' ? field.default() : field.default)
|
|
57
|
+
: null;
|
|
58
|
+
return { ...row, [field.name]: defaultVal };
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
/** Schema variant of addColumn */
|
|
62
|
+
export function addColumnSchema(field) {
|
|
63
|
+
return (schema) => {
|
|
64
|
+
if (schema.some((f) => f.name === field.name))
|
|
65
|
+
return schema;
|
|
66
|
+
return [...schema, field];
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* DROP COLUMN — removes the field from records.
|
|
71
|
+
* Old ciphertext data is discarded on next write.
|
|
72
|
+
*/
|
|
73
|
+
export function dropColumn(fieldName) {
|
|
74
|
+
return (row) => {
|
|
75
|
+
const out = { ...row };
|
|
76
|
+
delete out[fieldName];
|
|
77
|
+
return out;
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
/** Schema variant of dropColumn */
|
|
81
|
+
export function dropColumnSchema(fieldName) {
|
|
82
|
+
return (schema) => schema.filter((f) => f.name !== fieldName);
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* RENAME COLUMN — moves value from oldName to newName.
|
|
86
|
+
*/
|
|
87
|
+
export function renameColumn(oldName, newName) {
|
|
88
|
+
return (row) => {
|
|
89
|
+
if (!(oldName in row))
|
|
90
|
+
return row;
|
|
91
|
+
const out = { ...row, [newName]: row[oldName] };
|
|
92
|
+
delete out[oldName];
|
|
93
|
+
return out;
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
/** Schema variant of renameColumn */
|
|
97
|
+
export function renameColumnSchema(oldName, newName) {
|
|
98
|
+
return (schema) => schema.map((f) => (f.name === oldName ? { ...f, name: newName } : f));
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* CHANGE TYPE — re-encode a field's value through a transform function.
|
|
102
|
+
* Supply a function that converts the old wire value to the new wire value.
|
|
103
|
+
*
|
|
104
|
+
* @example
|
|
105
|
+
* // Convert TEXT → TIMESTAMP (ISO string → unix ms)
|
|
106
|
+
* changeType('createdAt', (v) => new Date(String(v)).getTime())
|
|
107
|
+
*/
|
|
108
|
+
export function changeType(fieldName, transform) {
|
|
109
|
+
return (row) => {
|
|
110
|
+
if (!(fieldName in row))
|
|
111
|
+
return row;
|
|
112
|
+
return { ...row, [fieldName]: transform(row[fieldName]) };
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* COMPUTE COLUMN — derive a new field from existing fields.
|
|
117
|
+
* Called only if the field is absent (so it doesn't overwrite on re-migrations).
|
|
118
|
+
*/
|
|
119
|
+
export function computeColumn(fieldName, compute) {
|
|
120
|
+
return (row) => {
|
|
121
|
+
if (row[fieldName] !== undefined && row[fieldName] !== null)
|
|
122
|
+
return row;
|
|
123
|
+
return { ...row, [fieldName]: compute(row) };
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
// ─────────────────────────────────────────────────────────────
|
|
127
|
+
// MigrationRunner
|
|
128
|
+
// ─────────────────────────────────────────────────────────────
|
|
129
|
+
export class MigrationRunner {
|
|
130
|
+
migrations;
|
|
131
|
+
constructor(migrations) {
|
|
132
|
+
// Sort ascending by version
|
|
133
|
+
this.migrations = [...migrations].sort((a, b) => a.version - b.version);
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Apply all migrations with version > `fromVersion` to a single record row.
|
|
137
|
+
*
|
|
138
|
+
* @param row Decoded record from the chain (before migration)
|
|
139
|
+
* @param fromVersion The schema version the record was written at. Use the
|
|
140
|
+
* VERSION field stored in the record, or 0 if absent.
|
|
141
|
+
*/
|
|
142
|
+
applyToRecord(row, fromVersion = 0) {
|
|
143
|
+
let current = { ...row };
|
|
144
|
+
for (const m of this.migrations) {
|
|
145
|
+
if (m.version > fromVersion) {
|
|
146
|
+
current = m.up(current);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
return current;
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Apply all schema migrations from `fromVersion` to the latest version,
|
|
153
|
+
* producing an up-to-date SchemaDefinition for TypedTableClient.
|
|
154
|
+
*/
|
|
155
|
+
applyToSchema(baseSchema, fromVersion = 0) {
|
|
156
|
+
let schema = [...baseSchema];
|
|
157
|
+
for (const m of this.migrations) {
|
|
158
|
+
if (m.version > fromVersion && m.schema) {
|
|
159
|
+
schema = m.schema(schema);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
return schema;
|
|
163
|
+
}
|
|
164
|
+
/** The latest migration version number. */
|
|
165
|
+
get latestVersion() {
|
|
166
|
+
return this.migrations.at(-1)?.version ?? 0;
|
|
167
|
+
}
|
|
168
|
+
/** List all registered migrations in version order. */
|
|
169
|
+
list() {
|
|
170
|
+
return this.migrations.map(({ version, description }) => ({ version, description }));
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
//# sourceMappingURL=migrations.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"migrations.js","sourceRoot":"","sources":["../../src/migrations.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file model.ts
|
|
3
|
+
* @notice Web3QL ORM — Prisma-style Model class that unifies:
|
|
4
|
+
*
|
|
5
|
+
* • Encrypted record CRUD (via TypedTableClient under the hood)
|
|
6
|
+
* • On-chain COUNTER fields — automatically merged into every find result
|
|
7
|
+
* • Relation writes — `relatedCreate()` pays with native CELO or any ERC-20
|
|
8
|
+
* and atomically writes the source record + increments target counters
|
|
9
|
+
*
|
|
10
|
+
* Usage:
|
|
11
|
+
* ─────────────────────────────────────────────────────────────
|
|
12
|
+
* // 1. Define your models
|
|
13
|
+
* const projects = new Model<Project>('projects', projectsTableAddr, signer, keypair, {
|
|
14
|
+
* counterFields: ['vote_total', 'vote_count', 'tip_total', 'tip_count'],
|
|
15
|
+
* schema: projectSchema,
|
|
16
|
+
* });
|
|
17
|
+
*
|
|
18
|
+
* const votes = new Model<Vote>('votes', votesTableAddr, signer, keypair);
|
|
19
|
+
*
|
|
20
|
+
* // 2. Standard CRUD
|
|
21
|
+
* await projects.create(1n, { id: 1n, name: 'Web3QL' });
|
|
22
|
+
*
|
|
23
|
+
* // 3. findUnique — counter fields merged in automatically
|
|
24
|
+
* const p = await projects.findUnique(1n);
|
|
25
|
+
* // p = { id: 1n, name: 'Web3QL', vote_total: 420n, vote_count: 3n, ... }
|
|
26
|
+
*
|
|
27
|
+
* // 4. Relation write — pay 2 CELO, atomically save vote + update project counters
|
|
28
|
+
* await votes.relatedCreate({
|
|
29
|
+
* wire : wireAddress,
|
|
30
|
+
* id : 10n,
|
|
31
|
+
* data : { project_id: 1n, voter: myAddr, amount: 2n * 10n**18n },
|
|
32
|
+
* targetId : 1n,
|
|
33
|
+
* amount : 2n * 10n**18n, // native CELO
|
|
34
|
+
* });
|
|
35
|
+
*
|
|
36
|
+
* // 5. ERC-20 vote: approve first, then:
|
|
37
|
+
* await votes.relatedCreate({
|
|
38
|
+
* wire : wireAddress,
|
|
39
|
+
* id : 11n,
|
|
40
|
+
* data : { project_id: 1n, voter: myAddr, amount: 5_000000n },
|
|
41
|
+
* targetId : 1n,
|
|
42
|
+
* amount : 5_000000n, // 5 cUSD (6 decimals)
|
|
43
|
+
* token : CUSD_ADDRESS, // ERC-20 token — pre-approve wire contract first
|
|
44
|
+
* });
|
|
45
|
+
* ─────────────────────────────────────────────────────────────
|
|
46
|
+
*/
|
|
47
|
+
import { ethers } from 'ethers';
|
|
48
|
+
import { Role } from './table-client.js';
|
|
49
|
+
import type { FindManyOptions, RecordWithId, SchemaDefinition } from './typed-table.js';
|
|
50
|
+
import type { EncryptionKeypair } from './crypto.js';
|
|
51
|
+
import type { PublicKeyRegistryClient } from './registry.js';
|
|
52
|
+
export { Role };
|
|
53
|
+
export interface ModelOptions {
|
|
54
|
+
/**
|
|
55
|
+
* Names of COUNTER fields on this table.
|
|
56
|
+
* Counter values are stored in the on-chain `counters` mapping — NOT
|
|
57
|
+
* inside the encrypted ciphertext. They are automatically fetched
|
|
58
|
+
* and merged into every `findUnique` / `findMany` result.
|
|
59
|
+
*/
|
|
60
|
+
counterFields?: string[];
|
|
61
|
+
/** Optional schema for validation, type coercion, NOT NULL, DEFAULT. */
|
|
62
|
+
schema?: SchemaDefinition;
|
|
63
|
+
}
|
|
64
|
+
/** Options for `relatedCreate()` */
|
|
65
|
+
export interface RelatedCreateOptions<T> {
|
|
66
|
+
/** Address of the deployed Web3QLRelationWire contract. */
|
|
67
|
+
wire: string;
|
|
68
|
+
/** Primary key of the NEW record being written to THIS table. */
|
|
69
|
+
id: bigint;
|
|
70
|
+
/** Payload to encrypt and store (COUNTER fields are excluded automatically). */
|
|
71
|
+
data: T;
|
|
72
|
+
/** Primary key of the TARGET record to increment counters on. */
|
|
73
|
+
targetId: bigint;
|
|
74
|
+
/** Name of the target table (needed for key derivation). */
|
|
75
|
+
targetTable: string;
|
|
76
|
+
/**
|
|
77
|
+
* Payment amount.
|
|
78
|
+
* - Native wire (token undefined / address(0)): amount in wei (msg.value)
|
|
79
|
+
* - ERC-20 wire (token set): amount in token's native units
|
|
80
|
+
*/
|
|
81
|
+
amount?: bigint;
|
|
82
|
+
/**
|
|
83
|
+
* ERC-20 token address. Omit (or pass `undefined`) for native CELO.
|
|
84
|
+
* The wire contract must be pre-approved: call `model.approveWire(wire, token, amount)` once.
|
|
85
|
+
*/
|
|
86
|
+
token?: string;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* `Model<T>` — the Web3QL ORM entry point.
|
|
90
|
+
*
|
|
91
|
+
* T is the shape of the ENCRYPTED fields only (not counter fields).
|
|
92
|
+
* Counter fields are added automatically to every returned object.
|
|
93
|
+
*/
|
|
94
|
+
export declare class Model<T extends Record<string, unknown>> {
|
|
95
|
+
readonly tableName: string;
|
|
96
|
+
readonly tableAddress: string;
|
|
97
|
+
private inner;
|
|
98
|
+
private rawClient;
|
|
99
|
+
private counterFields;
|
|
100
|
+
private counterFieldHashes;
|
|
101
|
+
private signer;
|
|
102
|
+
private provider;
|
|
103
|
+
constructor(tableName: string, tableAddress: string, signer: ethers.Signer, keypair: EncryptionKeypair, options?: ModelOptions);
|
|
104
|
+
/** Derive the on-chain bytes32 record key for a given primary key. */
|
|
105
|
+
key(id: bigint): string;
|
|
106
|
+
/** Read a single named counter for the record at `id`. */
|
|
107
|
+
counter(id: bigint, field: string): Promise<bigint>;
|
|
108
|
+
/**
|
|
109
|
+
* Read ALL registered counter fields for the record at `id`.
|
|
110
|
+
* Returns a plain object mapping field name → bigint value.
|
|
111
|
+
*/
|
|
112
|
+
counters(id: bigint): Promise<Record<string, bigint>>;
|
|
113
|
+
/**
|
|
114
|
+
* Encrypt and store a new record.
|
|
115
|
+
* Pass only encrypted fields — counter fields are managed by the chain.
|
|
116
|
+
*/
|
|
117
|
+
create(id: bigint, data: T): Promise<ethers.TransactionReceipt>;
|
|
118
|
+
/**
|
|
119
|
+
* Read and decrypt a record, with all counter values merged in.
|
|
120
|
+
* Returns `null` if the record does not exist.
|
|
121
|
+
*/
|
|
122
|
+
findUnique(id: bigint): Promise<(T & Record<string, bigint>) | null>;
|
|
123
|
+
/**
|
|
124
|
+
* List and decrypt all records owned by `ownerAddress`.
|
|
125
|
+
* Counter values are merged into every record.
|
|
126
|
+
*/
|
|
127
|
+
findMany(ownerAddress: string, options?: FindManyOptions): Promise<RecordWithId<T & Record<string, bigint>>[]>;
|
|
128
|
+
/** Get all records (no chain limit). Counter values merged. */
|
|
129
|
+
findAll(ownerAddress: string): Promise<RecordWithId<T & Record<string, bigint>>[]>;
|
|
130
|
+
/**
|
|
131
|
+
* Patch an existing record — fetches current, merges patch, re-encrypts.
|
|
132
|
+
* Counter fields in patch are silently ignored (they live on-chain, not in ciphertext).
|
|
133
|
+
*/
|
|
134
|
+
update(id: bigint, patch: Partial<T>): Promise<ethers.TransactionReceipt>;
|
|
135
|
+
/** Delete a record (soft-delete — scrubs all encrypted key copies). */
|
|
136
|
+
delete(id: bigint): Promise<ethers.TransactionReceipt>;
|
|
137
|
+
/** True if a live record exists for `id`. */
|
|
138
|
+
exists(id: bigint): Promise<boolean>;
|
|
139
|
+
/** Total record count (including deleted) for `ownerAddress`. */
|
|
140
|
+
count(ownerAddress: string): Promise<bigint>;
|
|
141
|
+
share(id: bigint, recipient: string, role: Role, registry: PublicKeyRegistryClient): Promise<ethers.TransactionReceipt>;
|
|
142
|
+
revoke(id: bigint, user: string): Promise<ethers.TransactionReceipt>;
|
|
143
|
+
/**
|
|
144
|
+
* Write a record to THIS table via a RelationWire, atomically incrementing
|
|
145
|
+
* counter fields on the TARGET table in the same transaction.
|
|
146
|
+
*
|
|
147
|
+
* For native CELO: pass `amount` in wei, do NOT pass `token`.
|
|
148
|
+
* For ERC-20: pass `token` address + `amount` in token units.
|
|
149
|
+
* You must have approved the wire contract beforehand —
|
|
150
|
+
* call `model.approveWire(wire, token, amount)` once.
|
|
151
|
+
*/
|
|
152
|
+
relatedCreate(opts: RelatedCreateOptions<T>): Promise<ethers.TransactionReceipt>;
|
|
153
|
+
/**
|
|
154
|
+
* Approve a RelationWire to spend your ERC-20 tokens.
|
|
155
|
+
* Call this once before using `relatedCreate` with an ERC-20 wire.
|
|
156
|
+
* You can approve `MaxUint256` for unlimited allowance.
|
|
157
|
+
*/
|
|
158
|
+
approveWire(wire: string, token: string, amount?: bigint): Promise<ethers.TransactionReceipt>;
|
|
159
|
+
/**
|
|
160
|
+
* Withdraw a single token's accumulated payments for a project record.
|
|
161
|
+
* Caller must be the record owner of `id` on this table.
|
|
162
|
+
*
|
|
163
|
+
* @param wire Address of the RelationWire contract
|
|
164
|
+
* @param id Primary key of THIS table's record (the project)
|
|
165
|
+
* @param token Token to withdraw (ethers.ZeroAddress = native CELO)
|
|
166
|
+
* @param to Recipient address (defaults to signer)
|
|
167
|
+
*/
|
|
168
|
+
withdrawFunds(wire: string, id: bigint, token?: string, to?: string): Promise<ethers.TransactionReceipt>;
|
|
169
|
+
/**
|
|
170
|
+
* Withdraw ALL token balances for a project in one transaction.
|
|
171
|
+
* Caller must be the record owner of `id` on this table.
|
|
172
|
+
*
|
|
173
|
+
* @param wire Address of the RelationWire contract
|
|
174
|
+
* @param id Primary key of the project record
|
|
175
|
+
* @param to Recipient address (defaults to signer)
|
|
176
|
+
*/
|
|
177
|
+
withdrawAllFunds(wire: string, id: bigint, to?: string): Promise<ethers.TransactionReceipt>;
|
|
178
|
+
/**
|
|
179
|
+
* Check pending balances for a project across all tokens accepted by the wire.
|
|
180
|
+
* Returns a plain object: { tokenAddress: bigintBalance, ... }
|
|
181
|
+
*
|
|
182
|
+
* @param wire Address of the RelationWire contract
|
|
183
|
+
* @param id Primary key of the project record
|
|
184
|
+
*/
|
|
185
|
+
projectBalances(wire: string, id: bigint): Promise<Record<string, bigint>>;
|
|
186
|
+
/**
|
|
187
|
+
* Build and sign an EIP-2612 permit signature.
|
|
188
|
+
* Works for cUSD, cEUR, cREAL, USDC and any token that implements ERC-2612.
|
|
189
|
+
* Throws if the token doesn't expose `nonces()` or `DOMAIN_SEPARATOR()`.
|
|
190
|
+
*/
|
|
191
|
+
private _signPermit;
|
|
192
|
+
private _countersFromBytes32Key;
|
|
193
|
+
/**
|
|
194
|
+
* Encrypt a payload for self, returning raw bytes for the wire contract.
|
|
195
|
+
*/
|
|
196
|
+
private _encryptPayload;
|
|
197
|
+
}
|
|
198
|
+
//# sourceMappingURL=model.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"model.d.ts","sourceRoot":"","sources":["../../src/model.ts"],"names":[],"mappings":"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"}
|