@onchaindb/sdk 0.4.0 → 0.4.2
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/.DS_Store +0 -0
- package/.claude/settings.local.json +8 -0
- package/.gitignore +5 -0
- package/.idea/.gitignore +5 -0
- package/.idea/compiler.xml +6 -0
- package/.idea/inspectionProfiles/Project_Default.xml +6 -0
- package/.idea/jsLinters/eslint.xml +6 -0
- package/.idea/modules.xml +8 -0
- package/.idea/prettier.xml +7 -0
- package/.idea/sdk.iml +12 -0
- package/.idea/vcs.xml +6 -0
- package/.idea/workspace.xml +257 -0
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +11 -3
- package/dist/client.js.map +1 -1
- package/dist/database.d.ts +0 -20
- package/dist/database.d.ts.map +1 -1
- package/dist/database.js +0 -40
- package/dist/database.js.map +1 -1
- package/dist/query-sdk/tests/setup.d.ts +16 -0
- package/dist/query-sdk/tests/setup.d.ts.map +1 -0
- package/dist/query-sdk/tests/setup.js +49 -0
- package/dist/query-sdk/tests/setup.js.map +1 -0
- package/examples/basic-usage.ts +136 -0
- package/examples/blob-upload-example.ts +140 -0
- package/examples/collection-schema-example.ts +304 -0
- package/examples/server-side-joins.ts +201 -0
- package/examples/tweet-self-joins-example.ts +352 -0
- package/package-lock.json +3823 -0
- package/package.json +1 -1
- package/skills.md +1096 -0
- package/src/.env +1 -0
- package/src/batch.d.ts +121 -0
- package/src/batch.js +205 -0
- package/src/batch.ts +257 -0
- package/src/client.ts +1856 -0
- package/src/database.d.ts +268 -0
- package/src/database.js +294 -0
- package/src/database.ts +695 -0
- package/src/index.d.ts +160 -0
- package/src/index.js +186 -0
- package/src/index.ts +253 -0
- package/src/query-sdk/ConditionBuilder.ts +103 -0
- package/src/query-sdk/FieldConditionBuilder.ts +2 -0
- package/src/query-sdk/NestedBuilders.ts +186 -0
- package/src/query-sdk/OnChainDB.ts +294 -0
- package/src/query-sdk/QueryBuilder.ts +1191 -0
- package/src/query-sdk/QueryResult.ts +375 -0
- package/src/query-sdk/README.md +866 -0
- package/src/query-sdk/SelectionBuilder.ts +94 -0
- package/src/query-sdk/adapters/HttpClientAdapter.ts +249 -0
- package/src/query-sdk/dist/ConditionBuilder.d.ts +22 -0
- package/src/query-sdk/dist/ConditionBuilder.js +90 -0
- package/src/query-sdk/dist/FieldConditionBuilder.d.ts +1 -0
- package/src/query-sdk/dist/FieldConditionBuilder.js +6 -0
- package/src/query-sdk/dist/NestedBuilders.d.ts +43 -0
- package/src/query-sdk/dist/NestedBuilders.js +144 -0
- package/src/query-sdk/dist/OnChainDB.d.ts +19 -0
- package/src/query-sdk/dist/OnChainDB.js +123 -0
- package/src/query-sdk/dist/QueryBuilder.d.ts +70 -0
- package/src/query-sdk/dist/QueryBuilder.js +295 -0
- package/src/query-sdk/dist/QueryResult.d.ts +52 -0
- package/src/query-sdk/dist/QueryResult.js +293 -0
- package/src/query-sdk/dist/SelectionBuilder.d.ts +20 -0
- package/src/query-sdk/dist/SelectionBuilder.js +80 -0
- package/src/query-sdk/dist/adapters/HttpClientAdapter.d.ts +27 -0
- package/src/query-sdk/dist/adapters/HttpClientAdapter.js +170 -0
- package/src/query-sdk/dist/index.d.ts +36 -0
- package/src/query-sdk/dist/index.js +27 -0
- package/src/query-sdk/dist/operators.d.ts +56 -0
- package/src/query-sdk/dist/operators.js +289 -0
- package/src/query-sdk/dist/tests/setup.d.ts +15 -0
- package/src/query-sdk/dist/tests/setup.js +46 -0
- package/src/query-sdk/index.ts +59 -0
- package/src/query-sdk/jest.config.js +25 -0
- package/src/query-sdk/operators.ts +335 -0
- package/src/query-sdk/package.json +46 -0
- package/src/query-sdk/tests/FieldConditionBuilder.test.ts +84 -0
- package/src/query-sdk/tests/LogicalOperator.test.ts +85 -0
- package/src/query-sdk/tests/NestedBuilders.test.ts +321 -0
- package/src/query-sdk/tests/QueryBuilder.test.ts +348 -0
- package/src/query-sdk/tests/QueryResult.test.ts +464 -0
- package/src/query-sdk/tests/aggregations.test.ts +653 -0
- package/src/query-sdk/tests/comprehensive.test.ts +279 -0
- package/src/query-sdk/tests/integration.test.ts +608 -0
- package/src/query-sdk/tests/operators.test.ts +327 -0
- package/src/query-sdk/tests/setup.ts +59 -0
- package/src/query-sdk/tests/unit.test.ts +794 -0
- package/src/query-sdk/tsconfig.json +26 -0
- package/src/query-sdk/yarn.lock +3092 -0
- package/src/types.d.ts +131 -0
- package/src/types.js +46 -0
- package/src/types.ts +534 -0
- package/src/x402/index.ts +12 -0
- package/src/x402/types.ts +250 -0
- package/src/x402/utils.ts +332 -0
- package/tsconfig.json +20 -0
- package/yarn.lock +2309 -0
package/src/.env
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
NODE_AUTH_TOKEN=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
|
package/src/batch.d.ts
ADDED
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import { OnChainDBClient } from './client';
|
|
2
|
+
import { StoreRequest, StoreResponse, TransactionStatus } from './types';
|
|
3
|
+
import { EventEmitter } from 'eventemitter3';
|
|
4
|
+
/**
|
|
5
|
+
* Batch operations for OnChainDB
|
|
6
|
+
*
|
|
7
|
+
* Allows efficient batch insertion with transaction management
|
|
8
|
+
* and progress tracking for large datasets.
|
|
9
|
+
*/
|
|
10
|
+
export declare class BatchOperations extends EventEmitter {
|
|
11
|
+
private client;
|
|
12
|
+
constructor(client: OnChainDBClient);
|
|
13
|
+
/**
|
|
14
|
+
* Batch store multiple records
|
|
15
|
+
*
|
|
16
|
+
* @param requests - Array of store requests
|
|
17
|
+
* @param options - Batch options including payment configuration
|
|
18
|
+
* @returns Promise resolving to array of store responses
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```typescript
|
|
22
|
+
* const batch = new BatchOperations(db);
|
|
23
|
+
*
|
|
24
|
+
* const results = await batch.store([
|
|
25
|
+
* { data: { message: 'Tweet 1' }, collection: 'tweets' },
|
|
26
|
+
* { data: { message: 'Tweet 2' }, collection: 'tweets' },
|
|
27
|
+
* { data: { message: 'Tweet 3' }, collection: 'tweets' }
|
|
28
|
+
* ], {
|
|
29
|
+
* concurrency: 5,
|
|
30
|
+
* waitForConfirmation: true,
|
|
31
|
+
* paymentOptions: {
|
|
32
|
+
* userWallet: keplrWallet,
|
|
33
|
+
* brokerAddress: 'celestia1xyz...'
|
|
34
|
+
* }
|
|
35
|
+
* });
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
38
|
+
store(requests: StoreRequest[], options?: {
|
|
39
|
+
concurrency?: number;
|
|
40
|
+
waitForConfirmation?: boolean;
|
|
41
|
+
onProgress?: (completed: number, total: number) => void;
|
|
42
|
+
paymentOptions?: {
|
|
43
|
+
userWallet?: any;
|
|
44
|
+
brokerAddress?: string;
|
|
45
|
+
};
|
|
46
|
+
}): Promise<StoreResponse[]>;
|
|
47
|
+
/**
|
|
48
|
+
* Batch store with retry logic
|
|
49
|
+
*
|
|
50
|
+
* @param requests - Store requests
|
|
51
|
+
* @param options - Batch options with retry configuration and payment support
|
|
52
|
+
* @returns Store responses
|
|
53
|
+
*/
|
|
54
|
+
storeWithRetry(requests: StoreRequest[], options?: {
|
|
55
|
+
concurrency?: number;
|
|
56
|
+
waitForConfirmation?: boolean;
|
|
57
|
+
maxRetries?: number;
|
|
58
|
+
retryDelay?: number;
|
|
59
|
+
onProgress?: (completed: number, total: number) => void;
|
|
60
|
+
paymentOptions?: {
|
|
61
|
+
userWallet?: any;
|
|
62
|
+
brokerAddress?: string;
|
|
63
|
+
};
|
|
64
|
+
}): Promise<StoreResponse[]>;
|
|
65
|
+
/**
|
|
66
|
+
* Monitor multiple transactions for confirmation
|
|
67
|
+
*
|
|
68
|
+
* @param transactionIds - Array of transaction IDs to monitor
|
|
69
|
+
* @param maxWaitTime - Maximum wait time per transaction
|
|
70
|
+
* @returns Promise resolving when all transactions are confirmed
|
|
71
|
+
*/
|
|
72
|
+
waitForBatchConfirmation(transactionIds: string[], maxWaitTime?: number): Promise<TransactionStatus[]>;
|
|
73
|
+
private sleep;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Utility class for building bulk operations
|
|
77
|
+
*
|
|
78
|
+
* @example
|
|
79
|
+
* ```typescript
|
|
80
|
+
* const builder = new BulkBuilder()
|
|
81
|
+
* .collection('tweets')
|
|
82
|
+
* .add({ message: 'Tweet 1', author: 'alice' })
|
|
83
|
+
* .add({ message: 'Tweet 2', author: 'bob' })
|
|
84
|
+
* .add({ message: 'Tweet 3', author: 'charlie' });
|
|
85
|
+
*
|
|
86
|
+
* const results = await db.batch().store(builder.build());
|
|
87
|
+
* ```
|
|
88
|
+
*/
|
|
89
|
+
export declare class BulkBuilder {
|
|
90
|
+
private requests;
|
|
91
|
+
private defaultCollection?;
|
|
92
|
+
private defaultApp?;
|
|
93
|
+
/**
|
|
94
|
+
* Set default collection for all subsequent operations
|
|
95
|
+
*/
|
|
96
|
+
collection(name: string): this;
|
|
97
|
+
/**
|
|
98
|
+
* Set default app for all subsequent operations
|
|
99
|
+
*/
|
|
100
|
+
app(name: string): this;
|
|
101
|
+
/**
|
|
102
|
+
* Add a data record to the bulk operation
|
|
103
|
+
*/
|
|
104
|
+
add(data: Record<string, any>, collection?: string, app?: string): this;
|
|
105
|
+
/**
|
|
106
|
+
* Add multiple data records
|
|
107
|
+
*/
|
|
108
|
+
addMany(records: Record<string, any>[], collection?: string, app?: string): this;
|
|
109
|
+
/**
|
|
110
|
+
* Build the final array of store requests
|
|
111
|
+
*/
|
|
112
|
+
build(): StoreRequest[];
|
|
113
|
+
/**
|
|
114
|
+
* Get the number of operations in the builder
|
|
115
|
+
*/
|
|
116
|
+
count(): number;
|
|
117
|
+
/**
|
|
118
|
+
* Clear all operations
|
|
119
|
+
*/
|
|
120
|
+
clear(): this;
|
|
121
|
+
}
|
package/src/batch.js
ADDED
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.BulkBuilder = exports.BatchOperations = void 0;
|
|
4
|
+
const eventemitter3_1 = require("eventemitter3");
|
|
5
|
+
/**
|
|
6
|
+
* Batch operations for OnChainDB
|
|
7
|
+
*
|
|
8
|
+
* Allows efficient batch insertion with transaction management
|
|
9
|
+
* and progress tracking for large datasets.
|
|
10
|
+
*/
|
|
11
|
+
class BatchOperations extends eventemitter3_1.EventEmitter {
|
|
12
|
+
constructor(client) {
|
|
13
|
+
super();
|
|
14
|
+
this.client = client;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Batch store multiple records
|
|
18
|
+
*
|
|
19
|
+
* @param requests - Array of store requests
|
|
20
|
+
* @param options - Batch options including payment configuration
|
|
21
|
+
* @returns Promise resolving to array of store responses
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* ```typescript
|
|
25
|
+
* const batch = new BatchOperations(db);
|
|
26
|
+
*
|
|
27
|
+
* const results = await batch.store([
|
|
28
|
+
* { data: { message: 'Tweet 1' }, collection: 'tweets' },
|
|
29
|
+
* { data: { message: 'Tweet 2' }, collection: 'tweets' },
|
|
30
|
+
* { data: { message: 'Tweet 3' }, collection: 'tweets' }
|
|
31
|
+
* ], {
|
|
32
|
+
* concurrency: 5,
|
|
33
|
+
* waitForConfirmation: true,
|
|
34
|
+
* paymentOptions: {
|
|
35
|
+
* userWallet: keplrWallet,
|
|
36
|
+
* brokerAddress: 'celestia1xyz...'
|
|
37
|
+
* }
|
|
38
|
+
* });
|
|
39
|
+
* ```
|
|
40
|
+
*/
|
|
41
|
+
async store(requests, options = {}) {
|
|
42
|
+
const { concurrency = 10, waitForConfirmation = false, onProgress, paymentOptions } = options;
|
|
43
|
+
const results = [];
|
|
44
|
+
const errors = [];
|
|
45
|
+
let completed = 0;
|
|
46
|
+
// Process requests in batches with concurrency limit
|
|
47
|
+
for (let i = 0; i < requests.length; i += concurrency) {
|
|
48
|
+
const batch = requests.slice(i, i + concurrency);
|
|
49
|
+
const batchPromises = batch.map(async (request, batchIndex) => {
|
|
50
|
+
const globalIndex = i + batchIndex;
|
|
51
|
+
try {
|
|
52
|
+
const result = await this.client.store(request, paymentOptions, waitForConfirmation);
|
|
53
|
+
results[globalIndex] = result;
|
|
54
|
+
completed++;
|
|
55
|
+
onProgress?.(completed, requests.length);
|
|
56
|
+
this.emit('progress', { completed, total: requests.length, success: true });
|
|
57
|
+
return result;
|
|
58
|
+
}
|
|
59
|
+
catch (error) {
|
|
60
|
+
errors.push({ index: globalIndex, error: error });
|
|
61
|
+
completed++;
|
|
62
|
+
onProgress?.(completed, requests.length);
|
|
63
|
+
this.emit('progress', { completed, total: requests.length, success: false, error });
|
|
64
|
+
throw error;
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
// Wait for current batch to complete before starting next
|
|
68
|
+
await Promise.allSettled(batchPromises);
|
|
69
|
+
}
|
|
70
|
+
if (errors.length > 0) {
|
|
71
|
+
this.emit('batchComplete', { results, errors });
|
|
72
|
+
throw new Error(`Batch operation failed: ${errors.length}/${requests.length} requests failed`);
|
|
73
|
+
}
|
|
74
|
+
this.emit('batchComplete', { results, errors: [] });
|
|
75
|
+
return results;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Batch store with retry logic
|
|
79
|
+
*
|
|
80
|
+
* @param requests - Store requests
|
|
81
|
+
* @param options - Batch options with retry configuration and payment support
|
|
82
|
+
* @returns Store responses
|
|
83
|
+
*/
|
|
84
|
+
async storeWithRetry(requests, options = {}) {
|
|
85
|
+
const { maxRetries = 3, retryDelay = 1000, ...batchOptions } = options;
|
|
86
|
+
let attempt = 0;
|
|
87
|
+
let lastError;
|
|
88
|
+
while (attempt <= maxRetries) {
|
|
89
|
+
try {
|
|
90
|
+
return await this.store(requests, batchOptions);
|
|
91
|
+
}
|
|
92
|
+
catch (error) {
|
|
93
|
+
lastError = error;
|
|
94
|
+
attempt++;
|
|
95
|
+
if (attempt <= maxRetries) {
|
|
96
|
+
this.emit('retryAttempt', { attempt, maxRetries, error });
|
|
97
|
+
await this.sleep(retryDelay * attempt); // Exponential backoff
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
throw lastError;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Monitor multiple transactions for confirmation
|
|
105
|
+
*
|
|
106
|
+
* @param transactionIds - Array of transaction IDs to monitor
|
|
107
|
+
* @param maxWaitTime - Maximum wait time per transaction
|
|
108
|
+
* @returns Promise resolving when all transactions are confirmed
|
|
109
|
+
*/
|
|
110
|
+
async waitForBatchConfirmation(transactionIds, maxWaitTime = 300000) {
|
|
111
|
+
const confirmationPromises = transactionIds.map(async (id, index) => {
|
|
112
|
+
try {
|
|
113
|
+
const result = await this.client.waitForConfirmation(id, maxWaitTime);
|
|
114
|
+
this.emit('transactionConfirmed', { id, index, result });
|
|
115
|
+
return {
|
|
116
|
+
id,
|
|
117
|
+
status: 'confirmed',
|
|
118
|
+
block_height: result.block_height,
|
|
119
|
+
transaction_hash: result.transaction_hash,
|
|
120
|
+
celestia_height: result.celestia_height
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
catch (error) {
|
|
124
|
+
this.emit('transactionFailed', { id, index, error });
|
|
125
|
+
return {
|
|
126
|
+
id,
|
|
127
|
+
status: 'failed',
|
|
128
|
+
error: error.message
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
});
|
|
132
|
+
return Promise.all(confirmationPromises);
|
|
133
|
+
}
|
|
134
|
+
sleep(ms) {
|
|
135
|
+
return new Promise(resolve => setTimeout(resolve, ms));
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
exports.BatchOperations = BatchOperations;
|
|
139
|
+
/**
|
|
140
|
+
* Utility class for building bulk operations
|
|
141
|
+
*
|
|
142
|
+
* @example
|
|
143
|
+
* ```typescript
|
|
144
|
+
* const builder = new BulkBuilder()
|
|
145
|
+
* .collection('tweets')
|
|
146
|
+
* .add({ message: 'Tweet 1', author: 'alice' })
|
|
147
|
+
* .add({ message: 'Tweet 2', author: 'bob' })
|
|
148
|
+
* .add({ message: 'Tweet 3', author: 'charlie' });
|
|
149
|
+
*
|
|
150
|
+
* const results = await db.batch().store(builder.build());
|
|
151
|
+
* ```
|
|
152
|
+
*/
|
|
153
|
+
class BulkBuilder {
|
|
154
|
+
constructor() {
|
|
155
|
+
this.requests = [];
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Set default collection for all subsequent operations
|
|
159
|
+
*/
|
|
160
|
+
collection(name) {
|
|
161
|
+
this.defaultCollection = name;
|
|
162
|
+
return this;
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Set default app for all subsequent operations
|
|
166
|
+
*/
|
|
167
|
+
app(name) {
|
|
168
|
+
this.defaultApp = name;
|
|
169
|
+
return this;
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Add a data record to the bulk operation
|
|
173
|
+
*/
|
|
174
|
+
add(data, collection, app) {
|
|
175
|
+
this.requests.push({ data: [data], root: `${app}::${collection}` });
|
|
176
|
+
return this;
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Add multiple data records
|
|
180
|
+
*/
|
|
181
|
+
addMany(records, collection, app) {
|
|
182
|
+
records.forEach(data => this.add(data, collection, app));
|
|
183
|
+
return this;
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Build the final array of store requests
|
|
187
|
+
*/
|
|
188
|
+
build() {
|
|
189
|
+
return [...this.requests];
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Get the number of operations in the builder
|
|
193
|
+
*/
|
|
194
|
+
count() {
|
|
195
|
+
return this.requests.length;
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Clear all operations
|
|
199
|
+
*/
|
|
200
|
+
clear() {
|
|
201
|
+
this.requests = [];
|
|
202
|
+
return this;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
exports.BulkBuilder = BulkBuilder;
|
package/src/batch.ts
ADDED
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
import { OnChainDBClient } from './client';
|
|
2
|
+
import { StoreRequest, StoreResponse, TransactionStatus } from './types';
|
|
3
|
+
import { EventEmitter } from 'eventemitter3';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Batch operations for OnChainDB
|
|
7
|
+
*
|
|
8
|
+
* Allows efficient batch insertion with transaction management
|
|
9
|
+
* and progress tracking for large datasets.
|
|
10
|
+
*/
|
|
11
|
+
export class BatchOperations extends EventEmitter {
|
|
12
|
+
constructor(private client: OnChainDBClient) {
|
|
13
|
+
super();
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Batch store multiple records
|
|
18
|
+
*
|
|
19
|
+
* @param requests - Array of store requests
|
|
20
|
+
* @param options - Batch options including payment configuration
|
|
21
|
+
* @returns Promise resolving to array of store responses
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* ```typescript
|
|
25
|
+
* const batch = new BatchOperations(db);
|
|
26
|
+
*
|
|
27
|
+
* const results = await batch.store([
|
|
28
|
+
* { data: { message: 'Tweet 1' }, collection: 'tweets' },
|
|
29
|
+
* { data: { message: 'Tweet 2' }, collection: 'tweets' },
|
|
30
|
+
* { data: { message: 'Tweet 3' }, collection: 'tweets' }
|
|
31
|
+
* ], {
|
|
32
|
+
* concurrency: 5,
|
|
33
|
+
* waitForConfirmation: true,
|
|
34
|
+
* paymentOptions: {
|
|
35
|
+
* userWallet: keplrWallet,
|
|
36
|
+
* brokerAddress: 'celestia1xyz...'
|
|
37
|
+
* }
|
|
38
|
+
* });
|
|
39
|
+
* ```
|
|
40
|
+
*/
|
|
41
|
+
async store(
|
|
42
|
+
requests: StoreRequest[],
|
|
43
|
+
options: {
|
|
44
|
+
concurrency?: number;
|
|
45
|
+
waitForConfirmation?: boolean;
|
|
46
|
+
onProgress?: (completed: number, total: number) => void;
|
|
47
|
+
paymentOptions?: {
|
|
48
|
+
userWallet?: any;
|
|
49
|
+
brokerAddress?: string;
|
|
50
|
+
};
|
|
51
|
+
} = {}
|
|
52
|
+
): Promise<StoreResponse[]> {
|
|
53
|
+
const {
|
|
54
|
+
concurrency = 10,
|
|
55
|
+
waitForConfirmation = false,
|
|
56
|
+
onProgress,
|
|
57
|
+
paymentOptions
|
|
58
|
+
} = options;
|
|
59
|
+
|
|
60
|
+
const results: StoreResponse[] = [];
|
|
61
|
+
const errors: Array<{ index: number; error: Error }> = [];
|
|
62
|
+
let completed = 0;
|
|
63
|
+
|
|
64
|
+
// Process requests in batches with concurrency limit
|
|
65
|
+
for (let i = 0; i < requests.length; i += concurrency) {
|
|
66
|
+
const batch = requests.slice(i, i + concurrency);
|
|
67
|
+
const batchPromises = batch.map(async (request, batchIndex) => {
|
|
68
|
+
const globalIndex = i + batchIndex;
|
|
69
|
+
try {
|
|
70
|
+
const result = await this.client.store(request, undefined, waitForConfirmation);
|
|
71
|
+
results[globalIndex] = result;
|
|
72
|
+
completed++;
|
|
73
|
+
onProgress?.(completed, requests.length);
|
|
74
|
+
this.emit('progress', { completed, total: requests.length, success: true });
|
|
75
|
+
return result;
|
|
76
|
+
} catch (error) {
|
|
77
|
+
errors.push({ index: globalIndex, error: error as Error });
|
|
78
|
+
completed++;
|
|
79
|
+
onProgress?.(completed, requests.length);
|
|
80
|
+
this.emit('progress', { completed, total: requests.length, success: false, error });
|
|
81
|
+
throw error;
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
// Wait for current batch to complete before starting next
|
|
86
|
+
await Promise.allSettled(batchPromises);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
if (errors.length > 0) {
|
|
90
|
+
this.emit('batchComplete', { results, errors });
|
|
91
|
+
throw new Error(`Batch operation failed: ${errors.length}/${requests.length} requests failed`);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
this.emit('batchComplete', { results, errors: [] });
|
|
95
|
+
return results;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Batch store with retry logic
|
|
100
|
+
*
|
|
101
|
+
* @param requests - Store requests
|
|
102
|
+
* @param options - Batch options with retry configuration and payment support
|
|
103
|
+
* @returns Store responses
|
|
104
|
+
*/
|
|
105
|
+
async storeWithRetry(
|
|
106
|
+
requests: StoreRequest[],
|
|
107
|
+
options: {
|
|
108
|
+
concurrency?: number;
|
|
109
|
+
waitForConfirmation?: boolean;
|
|
110
|
+
maxRetries?: number;
|
|
111
|
+
retryDelay?: number;
|
|
112
|
+
onProgress?: (completed: number, total: number) => void;
|
|
113
|
+
paymentOptions?: {
|
|
114
|
+
userWallet?: any;
|
|
115
|
+
brokerAddress?: string;
|
|
116
|
+
};
|
|
117
|
+
} = {}
|
|
118
|
+
): Promise<StoreResponse[]> {
|
|
119
|
+
const {
|
|
120
|
+
maxRetries = 3,
|
|
121
|
+
retryDelay = 1000,
|
|
122
|
+
...batchOptions
|
|
123
|
+
} = options;
|
|
124
|
+
|
|
125
|
+
let attempt = 0;
|
|
126
|
+
let lastError: Error;
|
|
127
|
+
|
|
128
|
+
while (attempt <= maxRetries) {
|
|
129
|
+
try {
|
|
130
|
+
return await this.store(requests, batchOptions);
|
|
131
|
+
} catch (error) {
|
|
132
|
+
lastError = error as Error;
|
|
133
|
+
attempt++;
|
|
134
|
+
|
|
135
|
+
if (attempt <= maxRetries) {
|
|
136
|
+
this.emit('retryAttempt', { attempt, maxRetries, error });
|
|
137
|
+
await this.sleep(retryDelay * attempt); // Exponential backoff
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
throw lastError!;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Monitor multiple transactions for confirmation
|
|
147
|
+
*
|
|
148
|
+
* @param transactionIds - Array of transaction IDs to monitor
|
|
149
|
+
* @param maxWaitTime - Maximum wait time per transaction
|
|
150
|
+
* @returns Promise resolving when all transactions are confirmed
|
|
151
|
+
*/
|
|
152
|
+
async waitForBatchConfirmation(
|
|
153
|
+
transactionIds: string[],
|
|
154
|
+
maxWaitTime: number = 300000
|
|
155
|
+
): Promise<TransactionStatus[]> {
|
|
156
|
+
const confirmationPromises = transactionIds.map(async (id, index) => {
|
|
157
|
+
try {
|
|
158
|
+
const result = await this.client.waitForConfirmation(id, maxWaitTime);
|
|
159
|
+
this.emit('transactionConfirmed', { id, index, result });
|
|
160
|
+
return {
|
|
161
|
+
id,
|
|
162
|
+
status: 'confirmed' as const,
|
|
163
|
+
block_height: result.block_height,
|
|
164
|
+
transaction_hash: result.transaction_hash,
|
|
165
|
+
celestia_height: result.celestia_height
|
|
166
|
+
};
|
|
167
|
+
} catch (error) {
|
|
168
|
+
this.emit('transactionFailed', { id, index, error });
|
|
169
|
+
return {
|
|
170
|
+
id,
|
|
171
|
+
status: 'failed' as const,
|
|
172
|
+
error: (error as Error).message
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
return Promise.all(confirmationPromises);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
private sleep(ms: number): Promise<void> {
|
|
181
|
+
return new Promise(resolve => setTimeout(resolve, ms));
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Utility class for building bulk operations
|
|
187
|
+
*
|
|
188
|
+
* @example
|
|
189
|
+
* ```typescript
|
|
190
|
+
* const builder = new BulkBuilder()
|
|
191
|
+
* .collection('tweets')
|
|
192
|
+
* .add({ message: 'Tweet 1', author: 'alice' })
|
|
193
|
+
* .add({ message: 'Tweet 2', author: 'bob' })
|
|
194
|
+
* .add({ message: 'Tweet 3', author: 'charlie' });
|
|
195
|
+
*
|
|
196
|
+
* const results = await db.batch().store(builder.build());
|
|
197
|
+
* ```
|
|
198
|
+
*/
|
|
199
|
+
export class BulkBuilder {
|
|
200
|
+
private requests: StoreRequest[] = [];
|
|
201
|
+
private defaultCollection?: string;
|
|
202
|
+
private defaultApp?: string;
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* Set default collection for all subsequent operations
|
|
206
|
+
*/
|
|
207
|
+
collection(name: string): this {
|
|
208
|
+
this.defaultCollection = name;
|
|
209
|
+
return this;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* Set default app for all subsequent operations
|
|
214
|
+
*/
|
|
215
|
+
app(name: string): this {
|
|
216
|
+
this.defaultApp = name;
|
|
217
|
+
return this;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* Add a data record to the bulk operation
|
|
222
|
+
*/
|
|
223
|
+
add(data: Record<string, any>, collection?: string, app?: string): this {
|
|
224
|
+
this.requests.push({data: [data], root: `${app}::${collection}`});
|
|
225
|
+
return this;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* Add multiple data records
|
|
230
|
+
*/
|
|
231
|
+
addMany(records: Record<string, any>[], collection?: string, app?: string): this {
|
|
232
|
+
records.forEach(data => this.add(data, collection, app));
|
|
233
|
+
return this;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* Build the final array of store requests
|
|
238
|
+
*/
|
|
239
|
+
build(): StoreRequest[] {
|
|
240
|
+
return [...this.requests];
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
/**
|
|
244
|
+
* Get the number of operations in the builder
|
|
245
|
+
*/
|
|
246
|
+
count(): number {
|
|
247
|
+
return this.requests.length;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
* Clear all operations
|
|
252
|
+
*/
|
|
253
|
+
clear(): this {
|
|
254
|
+
this.requests = [];
|
|
255
|
+
return this;
|
|
256
|
+
}
|
|
257
|
+
}
|