@fizzyflow/endless-vector 0.0.3 → 0.0.5

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/EndlessVector.js CHANGED
@@ -8,6 +8,7 @@ import ids from './ids.js';
8
8
  * @typedef {import('@mysten/sui/client').SuiClient} SuiClient
9
9
  * @typedef {import('@mysten/sui/client').GetObjectParams} GetObjectParams
10
10
  * @typedef {import('@mysten/sui/client').GetDynamicFieldsParams} GetDynamicFieldsParams
11
+ * @typedef {import('@mysten/sui/transactions').TransactionResult} TransactionResult
11
12
  */
12
13
 
13
14
  /**
@@ -94,7 +95,7 @@ export default class EndlessVector {
94
95
  * @param {SuiClient} params.suiClient - Sui client instance for blockchain interactions
95
96
  * @param {string} params.packageId - ID of the Move package containing the EndlessVector module
96
97
  * @param {CustomSignAndExecuteTransactionFunction} params.signAndExecuteTransaction - Function to sign and execute transactions
97
- * @param {?Array<Uint8Array>} [params.items] - Optional array of Uint8Array items to initialize the vector with. If provided, uses empty_entry_and_push, otherwise uses empty_entry
98
+ * @param {?Uint8Array|Uint8Array[]} [params.array] - Optional Uint8Array to initialize the vector with as the first item to get with .at(0)
98
99
  * @param {?Object} [params.gasCoin] - Optional gas coin object reference {objectId: string, digest: string, version: string} to use for transaction payment
99
100
  * @param {?Object} [params.options] - Optional transaction parameters
100
101
  * @param {?Number} [params.options.timeout] - Transaction confirmation timeout in ms, default 30000
@@ -103,7 +104,7 @@ export default class EndlessVector {
103
104
  * @throws {Error} If the transaction fails or no EndlessVector object is created
104
105
  */
105
106
  static async create(params) {
106
- const { suiClient, packageId, signAndExecuteTransaction, items, gasCoin, options = {} } = params;
107
+ const { suiClient, packageId, signAndExecuteTransaction, array, gasCoin, options = {} } = params;
107
108
 
108
109
  let normalizedPackageId = packageId;
109
110
  if (normalizedPackageId == 'mainnet' || (!normalizedPackageId && suiClient?.network == 'mainnet')) {
@@ -129,11 +130,31 @@ export default class EndlessVector {
129
130
  tx.setGasPayment([gasCoin]);
130
131
  }
131
132
 
132
- if (items && Array.isArray(items) && items.length) {
133
- tx.moveCall({
134
- target: `${normalizedPackageId}::endless_vector::empty_entry_and_push`,
135
- arguments: [tx.pure(bcs.vector(bcs.vector(bcs.u8())).serialize(items))],
136
- });
133
+ if (array && array.length) {
134
+ if ((array instanceof Uint8Array)) {
135
+ // single chunk
136
+ const vectorInput = await EndlessVector.getCreateTransactionAndReturnVectorInput({
137
+ packageId: normalizedPackageId,
138
+ }, array, tx);
139
+ tx.moveCall({
140
+ target: `${normalizedPackageId}::endless_vector::transfer_to_sender`,
141
+ arguments: [vectorInput],
142
+ });
143
+ } else if (array[0] && (array[0] instanceof Uint8Array)) {
144
+ // multiple chunks
145
+ const vectorInput = await EndlessVector.getCreateTransactionAndReturnVectorInput({
146
+ packageId: normalizedPackageId,
147
+ }, null, tx);
148
+ for (let i = 0; i < array.length; i++) {
149
+ EndlessVector.composePushTransaction(normalizedPackageId, vectorInput, array[i], tx);
150
+ }
151
+ tx.moveCall({
152
+ target: `${normalizedPackageId}::endless_vector::transfer_to_sender`,
153
+ arguments: [vectorInput],
154
+ });
155
+ } else {
156
+ throw new Error('.array must be Uint8Array or array of Uint8Array');
157
+ }
137
158
  } else {
138
159
  tx.moveCall({
139
160
  target: `${normalizedPackageId}::endless_vector::empty_entry`,
@@ -180,33 +201,92 @@ export default class EndlessVector {
180
201
  });
181
202
  }
182
203
 
183
- get isWritable() {
184
- return !!(this._packageId && this._signAndExecuteTransaction);
185
- }
186
-
187
204
  /**
188
- * Creates a transaction to push new byte arrays to the EndlessVector.
189
- * Note: this method only creates the transaction, it does not sign or execute it.
205
+ * Creates an empty EndlessVector and returns the vector input reference.
206
+ * Appends vector creation to existing transaction or makes new one.
207
+ *
208
+ * Returns the vector input reference for use in subsequent move calls as argument or to be transferred.
209
+ *
210
+ * @param {Object} params - Configuration parameters
211
+ * @param {string} params.packageId - The package ID ('mainnet', 'testnet', or explicit package ID)
212
+ * @param {Uint8Array|null} [arr=null] - Optional Uint8Array to push back to the new vector as the first item
213
+ * @param {Transaction|null} [txToAppendTo=null] - Optional existing transaction to append the move calls to
214
+ * @returns {Promise<TransactionResult>} Vector input reference for use in subsequent move calls
215
+ * @throws {Error} Throws if packageId is not provided or invalid
216
+ *
217
+ * @example
218
+ * // Create an empty vector
219
+ * const vectorInput = await EndlessVector.getCreateTransactionAndReturnVectorInput({
220
+ * packageId: 'mainnet'
221
+ * });
222
+ *
223
+ * @example
224
+ * // Create and populate a vector within an existing transaction
225
+ * const data = new Uint8Array([1, 2, 3, 4]);
226
+ * const tx = new Transaction();
227
+ * const vectorInput = await EndlessVector.getCreateTransactionAndReturnVectorInput({
228
+ * packageId: contract.id
229
+ * }, data, tx);
230
+ */
231
+ static async getCreateTransactionAndReturnVectorInput(params, arr = null, txToAppendTo = null) {
232
+ const { packageId } = params;
233
+ let normalizedPackageId = packageId;
234
+ if (normalizedPackageId == 'mainnet') {
235
+ normalizedPackageId = ids['mainnet'].packageId;
236
+ } else if (normalizedPackageId == 'testnet') {
237
+ normalizedPackageId = ids['testnet'].packageId;
238
+ }
190
239
 
191
- * @param {Uint8Array} arr - Array of byte arrays to push
192
- * @returns {Transaction} The transaction object to be signed and executed
193
- */
194
- getPushTransaction(arr, txToAppendTo = null) {
195
- if (!this._packageId) {
196
- throw new Error('packageId is required to compose push transaction');
240
+ if (!normalizedPackageId) {
241
+ throw new Error('packageId is required');
197
242
  }
243
+ // Create transaction to call empty_entry
198
244
 
199
245
  let tx = txToAppendTo;
200
246
  if (!tx) {
201
247
  tx = new Transaction();
202
248
  }
203
249
 
250
+ const vectorInput = tx.moveCall({
251
+ target: `${normalizedPackageId}::endless_vector::empty`,
252
+ arguments: [],
253
+ });
254
+
255
+ if (arr && arr) {
256
+ EndlessVector.composePushTransaction(normalizedPackageId, vectorInput, arr, tx);
257
+ }
258
+
259
+ return vectorInput;
260
+ }
261
+
262
+ get isWritable() {
263
+ return !!(this._packageId && this._signAndExecuteTransaction);
264
+ }
265
+
266
+ /**
267
+ * Attach move calls to transaction, to push item into endlessvector, handling large arrays by chunking them.
268
+ * This static method can be used to compose transactions for any existing EndlessVector instance:
269
+ * tx.object(vector.id)
270
+ * or newly created one, accepting TransactionResult as vectorInput, see: getCreateTransactionAndReturnVectorInput
271
+ *
272
+ * For arrays smaller than 12KB, it uses a single push_back call.
273
+ * For arrays between 12KB and 120KB, it splits the data into 10 chunks and uses compose_and_push_back.
274
+ *
275
+ * @static
276
+ * @param {string} packageId - The package ID of the Move module containing the endless_vector functions
277
+ * @param {TransactionObjectArgument} vectorInput - The transaction object argument representing the EndlessVector
278
+ * @param {Uint8Array} arr - The byte array to push to the vector
279
+ * @param {Transaction} tx - The transaction object to append the move calls to
280
+ * @returns {Transaction} The transaction object with the push operations added
281
+ * @throws {Error} If the array is larger than 120KB (10 * 12KB)
282
+ */
283
+ static composePushTransaction(packageId, vectorInput, arr, tx) {
204
284
  const maxArgLength = 12 * 1024;
205
285
  if (arr.length < maxArgLength) {
206
286
  tx.moveCall({
207
- target: `${this._packageId}::endless_vector::push_back`,
287
+ target: `${packageId}::endless_vector::push_back`,
208
288
  arguments: [
209
- tx.object(this.id),
289
+ vectorInput,
210
290
  tx.pure(bcs.vector(bcs.u8()).serialize(arr)),
211
291
  ],
212
292
  });
@@ -223,17 +303,49 @@ export default class EndlessVector {
223
303
  chunks.push(new Uint8Array()); // empty chunk
224
304
  }
225
305
  }
226
- const args = [tx.object(this.id)];
306
+ const args = [vectorInput];
227
307
  for (let i = 0; i < N; i++) {
228
308
  args.push(tx.pure(bcs.vector(bcs.u8()).serialize(chunks[i])));
229
309
  }
230
310
  tx.moveCall({
231
- target: `${this._packageId}::endless_vector::compose_and_push_back`,
311
+ target: `${packageId}::endless_vector::compose_and_push_back`,
232
312
  arguments: args,
233
313
  });
234
314
  } else {
235
315
  throw new Error('Array too large, max '+(10*maxArgLength)+' bytes supported per single tx');
236
316
  }
317
+
318
+ return tx;
319
+ }
320
+
321
+
322
+ /**
323
+ * Creates a transaction to push new byte arrays to the EndlessVector.
324
+ * Note: this method only creates the transaction, it does not sign or execute it.
325
+
326
+ * @param {Uint8Array|Uint8Array[]} arr - Uint8Array to push
327
+ * @returns {Transaction} The transaction object to be signed and executed
328
+ */
329
+ getPushTransaction(arr, txToAppendTo = null) {
330
+ if (!this._packageId) {
331
+ throw new Error('packageId is required to compose push transaction');
332
+ }
333
+
334
+ let tx = txToAppendTo;
335
+ if (!tx) {
336
+ tx = new Transaction();
337
+ }
338
+
339
+ if (arr instanceof Uint8Array) {
340
+ EndlessVector.composePushTransaction(this._packageId, tx.object(this.id), arr, tx);
341
+ } else if (Array.isArray(arr) && arr[0] && (arr[0] instanceof Uint8Array)) {
342
+ for (let i = 0; i < arr.length; i++) {
343
+ EndlessVector.composePushTransaction(this._packageId, tx.object(this.id), arr[i], tx);
344
+ }
345
+ } else {
346
+ throw new Error('.array must be Uint8Array or array of Uint8Array');
347
+ }
348
+
237
349
  return tx;
238
350
  }
239
351
 
@@ -243,7 +355,7 @@ export default class EndlessVector {
243
355
  * Requires the instance to be writable (packageId and signAndExecuteTransaction must be provided).
244
356
  * @throws {Error} If the instance is not writable or if the transaction fails
245
357
  *
246
- * @param {Uint8Array} arr - Byte array to push
358
+ * @param {Uint8Array|Uint8Array[]} arr - Byte array or array of byte arrays to push
247
359
  * @param {?Object} params - Configuration parameters
248
360
  * @param {?Number} [params.timeout] - wait for transaction confirmation timeout in ms, default 30000
249
361
  * @param {?Number} [params.pollIntervalMs] - wait for transaction confirmation poll interval in ms, default 1000
package/README.md CHANGED
@@ -32,10 +32,8 @@ const vector = await EndlessVector.create({
32
32
  const vectorWithData = await EndlessVector.create({
33
33
  suiClient: client,
34
34
  packageId: 'testnet', // or 'mainnet' or '0xYOUR_PACKAGE_ID'
35
- items: [
36
- new Uint8Array([1, 2, 3]),
37
- new Uint8Array([4, 5, 6])
38
- ],
35
+ array: new Uint8Array([1, 2, 3]), // [0] to append to EndlessVector
36
+ //array: [new Uint8Array([1, 2, 3]), new Uint8Array([5, 6, 7])], // or [0] and [1] to append to EndlessVector
39
37
  signAndExecuteTransaction: async (tx) => {
40
38
  const result = await wallet.signAndExecuteTransaction({ transaction: tx });
41
39
  return result.digest;
@@ -57,7 +55,7 @@ console.log('Total items:', vector.length);
57
55
  console.log('Total size:', vector.binaryLength, 'bytes');
58
56
 
59
57
  // Read items
60
- const firstItem = await vector.at(0);
58
+ const firstItem = await vector.at(0); // Uint8Array
61
59
  ```
62
60
 
63
61
  ## API Reference
@@ -72,7 +70,7 @@ Creates a new EndlessVector on the blockchain.
72
70
  - `suiClient` (SuiClient) - Sui client instance for blockchain interactions
73
71
  - `packageId` (string) - 'testnet', 'mainnet', or ID of the Move package containing the EndlessVector module
74
72
  - `signAndExecuteTransaction` (function) - Function to sign and execute transactions
75
- - `items` (Array<Uint8Array>, optional) - Initial items to push to the vector
73
+ - `array` (Uint8Array or Uint8Array[], optional) - Optional first vector<u8>(s) to push back to the new vector
76
74
  - `gasCoin` (Object, optional) - Gas coin object reference `{objectId: string, digest: string, version: string}` for transaction payment
77
75
  - `options` (Object, optional) - Additional options:
78
76
  - `timeout` (number) - Transaction confirmation timeout in ms (default: 30000)
@@ -85,7 +83,7 @@ Creates a new EndlessVector on the blockchain.
85
83
  const vector = await EndlessVector.create({
86
84
  suiClient: client,
87
85
  packageId: 'testnet', // or 'mainnet' or '0xPACKAGE_ID'
88
- items: [new Uint8Array([1, 2, 3])],
86
+ array: new Uint8Array([1, 2, 3]),
89
87
  gasCoin: {
90
88
  objectId: '0xGAS_COIN_ID',
91
89
  digest: 'DIGEST',
@@ -145,7 +143,7 @@ await vector.reInitialize();
145
143
 
146
144
  #### push(arr, params)
147
145
 
148
- Pushes a new byte array to the vector. Requires writable mode. Maximum size per item: ~200KB.
146
+ Pushes a Uint8Array or few Uint8Array(Uint8Array[]) to the vector. Requires writable mode. Maximum size per push: ~120KB.
149
147
 
150
148
  ```javascript
151
149
  const data = new Uint8Array([1, 2, 3, 4, 5]);
@@ -153,7 +151,7 @@ await vector.push(data);
153
151
  ```
154
152
 
155
153
  **Parameters:**
156
- - `arr` (Uint8Array) - Data to push
154
+ - `arr` (Uint8Array or Uint8Array[]) - Data to push
157
155
  - `params` (Object, optional) - Additional parameters
158
156
 
159
157
  #### getPushTransaction(arr, tx)
@@ -173,7 +171,7 @@ await signAndExecuteTransaction(tx);
173
171
  ```
174
172
 
175
173
  **Parameters:**
176
- - `arr` (Uint8Array) - Data to push
174
+ - `arr` (Uint8Array or Uint8Array[]) - Data to push
177
175
  - `tx` (Transaction, optional) - Existing transaction to append to
178
176
 
179
177
  **Returns:** Transaction
@@ -276,7 +274,7 @@ const vectors = await Promise.all(
276
274
  EndlessVector.create({
277
275
  suiClient: client,
278
276
  packageId: 'testnet', // or 'mainnet' or '0xPACKAGE_ID'
279
- items: items,
277
+ array: items,
280
278
  gasCoin: gasCoinRefs[i],
281
279
  signAndExecuteTransaction: async (tx) => {
282
280
  const result = await wallet.signAndExecuteTransaction({ transaction: tx });
package/ids.js CHANGED
@@ -1,11 +1,11 @@
1
1
 
2
2
  export default {
3
3
  'testnet': {
4
- packageId: '0x5e35ef9e8ea315a4db40047b9133c028603168e7b41a27511e9f7eea38313685', // should be the same as in Move.lock
5
- originalPackageId: '0x5e35ef9e8ea315a4db40047b9133c028603168e7b41a27511e9f7eea38313685',
4
+ packageId: '0x30bf8e91f40774ed08234f767360b4154562232903928b5f2f8fe5b2d51655bc', // should be the same as in Move.lock
5
+ originalPackageId: '0x30bf8e91f40774ed08234f767360b4154562232903928b5f2f8fe5b2d51655bc',
6
6
  },
7
7
  'mainnet': {
8
- packageId: '0xa81971816c632022658736d464d35bd47a7d6b5ad60e0903697e4adda0aa1331', // should be the same as in Move.lock
9
- originalPackageId: '0xa81971816c632022658736d464d35bd47a7d6b5ad60e0903697e4adda0aa1331',
8
+ packageId: '0x94cf19d164f014cfe73dda1121f27b54b69f0dbfa89d8b6ed48ae8a9144f5d65', // should be the same as in Move.lock
9
+ originalPackageId: '0x94cf19d164f014cfe73dda1121f27b54b69f0dbfa89d8b6ed48ae8a9144f5d65',
10
10
  },
11
11
  };
package/index.d.ts ADDED
@@ -0,0 +1,347 @@
1
+ import type { SuiClient, GetObjectParams, GetDynamicFieldsParams } from '@mysten/sui/client';
2
+ import type { Transaction, TransactionResult, TransactionObjectArgument } from '@mysten/sui/transactions';
3
+
4
+ /**
5
+ * Custom function to sign and execute transactions
6
+ */
7
+ export type CustomSignAndExecuteTransactionFunction = (tx: Transaction) => Promise<string>;
8
+
9
+ /**
10
+ * Configuration parameters for creating an EndlessVector instance
11
+ */
12
+ export interface EndlessVectorConstructorParams {
13
+ /** Sui client instance for blockchain interactions */
14
+ suiClient?: SuiClient;
15
+ /** ID or address of the EndlessVector on the Sui blockchain */
16
+ id?: string;
17
+ /** Adds write capability if provided, ID of the Move package containing the EndlessVector module or 'mainnet', 'testnet' to use known IDs */
18
+ packageId?: string | null;
19
+ /** Adds write capability if provided, function should accept Sui transaction, sign and submit it to the blockchain and return its digest */
20
+ signAndExecuteTransaction?: CustomSignAndExecuteTransactionFunction | null;
21
+ }
22
+
23
+ /**
24
+ * Configuration parameters for creating a new EndlessVector via static create method
25
+ */
26
+ export interface EndlessVectorCreateParams {
27
+ /** Sui client instance for blockchain interactions */
28
+ suiClient: SuiClient;
29
+ /** ID of the Move package containing the EndlessVector module */
30
+ packageId: string;
31
+ /** Function to sign and execute transactions */
32
+ signAndExecuteTransaction: CustomSignAndExecuteTransactionFunction;
33
+ /** Optional Uint8Array or array of Uint8Arrays to initialize the vector with */
34
+ array?: Uint8Array | Uint8Array[] | null;
35
+ /** Optional gas coin object reference {objectId: string, digest: string, version: string} to use for transaction payment */
36
+ gasCoin?: { objectId: string; digest: string; version: string } | null;
37
+ /** Optional transaction parameters */
38
+ options?: {
39
+ /** Transaction confirmation timeout in ms, default 30000 */
40
+ timeout?: number;
41
+ /** Poll interval in ms, default 1000 */
42
+ pollIntervalMs?: number;
43
+ };
44
+ }
45
+
46
+ /**
47
+ * Configuration parameters for getCreateTransactionAndReturnVectorInput
48
+ */
49
+ export interface GetCreateTransactionParams {
50
+ /** The package ID ('mainnet', 'testnet', or explicit package ID) */
51
+ packageId: string;
52
+ }
53
+
54
+ /**
55
+ * Configuration parameters for push and concat operations
56
+ */
57
+ export interface TransactionOptions {
58
+ /** wait for transaction confirmation timeout in ms, default 30000 */
59
+ timeout?: number;
60
+ /** wait for transaction confirmation poll interval in ms, default 1000 */
61
+ pollIntervalMs?: number;
62
+ }
63
+
64
+ /**
65
+ * Configuration parameters for creating an EndlessVectorHistory instance
66
+ */
67
+ export interface EndlessVectorHistoryConstructorParams {
68
+ /** Sui client instance for blockchain interactions */
69
+ suiClient?: SuiClient;
70
+ /** Unique identifier for this history item */
71
+ id?: string;
72
+ /** Index position of this history item in the sequence */
73
+ index?: number;
74
+ /** Raw field data from the blockchain object */
75
+ fields?: any | null;
76
+ /** Reference to the parent EndlessVector instance */
77
+ endlessVector?: EndlessVector;
78
+ /** Reference to the parent EndlessVectorArchive instance */
79
+ endlessVectorArchive?: EndlessVectorArchive | null;
80
+ }
81
+
82
+ /**
83
+ * Configuration parameters for creating an EndlessVectorArchive instance
84
+ */
85
+ export interface EndlessVectorArchiveConstructorParams {
86
+ /** Sui client instance for blockchain interactions */
87
+ suiClient?: SuiClient;
88
+ /** ID or address of the EndlessVectorArchive on the Sui blockchain */
89
+ id?: string;
90
+ /** Index position of this archive item in the sequence */
91
+ index?: number;
92
+ /** Reference to the parent EndlessVector instance */
93
+ endlessVector?: EndlessVector;
94
+ /** Raw field data from the blockchain object */
95
+ fields?: any;
96
+ }
97
+
98
+ /**
99
+ * Represents a history item in an EndlessVector, managing a segment of the vector's data.
100
+ * Each history item stores a portion of the vector's elements and maintains metadata
101
+ * about its position and relationships with adjacent history items.
102
+ */
103
+ export declare class EndlessVectorHistory {
104
+ suiClient: SuiClient;
105
+ id: string;
106
+ index: number;
107
+
108
+ constructor(params?: EndlessVectorHistoryConstructorParams);
109
+
110
+ /**
111
+ * Sets the fields data for this history item. Called by loader of EndlessVector.
112
+ */
113
+ setFields(fields: any): void;
114
+
115
+ /**
116
+ * Checks if this history item has been initialized and is ready for use.
117
+ */
118
+ isReady(): boolean;
119
+
120
+ /**
121
+ * Initializes this history item by loading its data from the blockchain.
122
+ * Uses promise-based synchronization to prevent multiple concurrent initializations.
123
+ */
124
+ initialize(): Promise<boolean>;
125
+
126
+ /**
127
+ * Gets the last index position that this history item covers.
128
+ */
129
+ get endsAt(): number | undefined;
130
+
131
+ /**
132
+ * Indicates whether the first item in this history contains suffix bytes that should be
133
+ * added to the last item from the previous history segment.
134
+ */
135
+ get firstItemIsFromPreviousHistory(): boolean;
136
+
137
+ /**
138
+ * Gets the first index position that this history item covers.
139
+ */
140
+ get startsAt(): number;
141
+
142
+ /**
143
+ * Gets the number of bytes from the next history item that should be appended
144
+ * to the last item in this history segment.
145
+ */
146
+ get followedByNextBytes(): number;
147
+
148
+ /**
149
+ * Retrieves the byte array at the specified index within this history segment.
150
+ */
151
+ at(i: number): Promise<Uint8Array>;
152
+
153
+ /**
154
+ * Gets the suffix bytes stored in this history item that should be appended
155
+ * to the last item of the previous history segment.
156
+ */
157
+ getSuffixStoredBytes(): Uint8Array;
158
+ }
159
+
160
+ /**
161
+ * Represents an archive item in an EndlessVector
162
+ */
163
+ export declare class EndlessVectorArchive {
164
+ suiClient: SuiClient;
165
+ id: string;
166
+ index: number;
167
+ historyTableId: string | null;
168
+ historyItemsCount: number;
169
+
170
+ constructor(params?: EndlessVectorArchiveConstructorParams);
171
+
172
+ /**
173
+ * Sets the fields data for this archive item. Called by loader of EndlessVector.
174
+ */
175
+ setFields(fields: any): void;
176
+
177
+ /**
178
+ * Checks if this archive item has been initialized and is ready for use.
179
+ */
180
+ isReady(): boolean;
181
+
182
+ /**
183
+ * Gets the total number of items stored in this archive.
184
+ */
185
+ get length(): number;
186
+
187
+ /**
188
+ * Gets the first index position that this archive covers.
189
+ */
190
+ get startsAt(): number;
191
+
192
+ /**
193
+ * Gets the last index position that this archive covers.
194
+ */
195
+ get endsAt(): number | undefined;
196
+
197
+ /**
198
+ * Initializes this archive item by loading its data from the blockchain.
199
+ */
200
+ initialize(): Promise<boolean>;
201
+
202
+ /**
203
+ * Gets a history item within this archive by its index.
204
+ */
205
+ getHistory(historyIndex: number | string): Promise<EndlessVectorHistory>;
206
+
207
+ /**
208
+ * Retrieves the byte array at the specified index within this archive.
209
+ */
210
+ at(i: number): Promise<Uint8Array>;
211
+
212
+ /**
213
+ * Gets suffix bytes from a history item at the specified index within this archive.
214
+ */
215
+ getSuffixFromHistoryItemOfIndex(i: number): Promise<Uint8Array>;
216
+ }
217
+
218
+ /**
219
+ * Represents an endless vector data structure that can grow beyond Sui object size limits
220
+ * by storing overflow data in history items. Provides seamless access to all elements regardless
221
+ * of whether they're stored in the current object or historical segments.
222
+ */
223
+ export declare class EndlessVector {
224
+ suiClient: SuiClient;
225
+ id: string;
226
+ binaryLength: number;
227
+ length: number;
228
+ historyItemsCount: number;
229
+ historyTableId: string | null;
230
+ firstItemIsFromPreviousHistory: boolean;
231
+ archiveTableId: string | null;
232
+ archiveItemsCount: number;
233
+ archivedAtLength: number;
234
+ archivedFromLength: number;
235
+ burnedArchiveCount: number;
236
+
237
+ constructor(params?: EndlessVectorConstructorParams);
238
+
239
+ /**
240
+ * Static factory method to create a new empty EndlessVector on the blockchain.
241
+ */
242
+ static create(params: EndlessVectorCreateParams): Promise<EndlessVector>;
243
+
244
+ /**
245
+ * Creates an empty EndlessVector and returns the vector input reference.
246
+ */
247
+ static getCreateTransactionAndReturnVectorInput(
248
+ params: GetCreateTransactionParams,
249
+ arr?: Uint8Array | null,
250
+ txToAppendTo?: Transaction | null
251
+ ): Promise<TransactionResult>;
252
+
253
+ /**
254
+ * Attach move calls to transaction, to push item into endlessvector, handling large arrays by chunking them.
255
+ */
256
+ static composePushTransaction(
257
+ packageId: string,
258
+ vectorInput: TransactionObjectArgument,
259
+ arr: Uint8Array,
260
+ tx: Transaction
261
+ ): Transaction;
262
+
263
+ /**
264
+ * Check if the EndlessVector instance is writable
265
+ */
266
+ get isWritable(): boolean;
267
+
268
+ /**
269
+ * Gets the first index that is stored in the current EndlessVector object (not in history items).
270
+ */
271
+ get firstNotHistoryIndex(): number;
272
+
273
+ /**
274
+ * Forces re-initialization of the EndlessVector to reload data from the blockchain.
275
+ */
276
+ reInitialize(): void;
277
+
278
+ /**
279
+ * Initializes the EndlessVector by loading data from the Sui blockchain.
280
+ */
281
+ initialize(): Promise<void>;
282
+
283
+ /**
284
+ * Gets a history item by its index, loading it from the blockchain if needed.
285
+ */
286
+ getHistory(historyIndex: number | string): Promise<EndlessVectorHistory>;
287
+
288
+ /**
289
+ * Gets an archive item by its index, loading it from the blockchain if needed.
290
+ */
291
+ getArchive(archiveIndex: number | string): Promise<EndlessVectorArchive>;
292
+
293
+ /**
294
+ * Loads multiple history items in a single batch request for efficiency.
295
+ */
296
+ loadHistoryItemsBunch(historyItems: EndlessVectorHistory[]): Promise<void>;
297
+
298
+ /**
299
+ * Loads a single history item, batching requests for efficiency.
300
+ */
301
+ loadHistoryItem(historyItem: EndlessVectorHistory): Promise<EndlessVectorHistory>;
302
+
303
+ /**
304
+ * Loads multiple archive items in a single batch request for efficiency.
305
+ */
306
+ loadArchiveItemsBunch(archiveItems: EndlessVectorArchive[]): Promise<void>;
307
+
308
+ /**
309
+ * Loads a single archive item, batching requests for efficiency.
310
+ */
311
+ loadArchiveItem(archiveItem: EndlessVectorArchive): Promise<EndlessVectorArchive>;
312
+
313
+ /**
314
+ * Retrieves the byte array at the specified index from either current items or history.
315
+ */
316
+ at(i: number): Promise<Uint8Array>;
317
+
318
+ /**
319
+ * Gets suffix bytes from a history item at the specified index.
320
+ */
321
+ getSuffixFromHistoryItemOfIndex(i: number): Promise<Uint8Array | undefined>;
322
+
323
+ /**
324
+ * Creates a transaction to push new byte arrays to the EndlessVector.
325
+ */
326
+ getPushTransaction(arr: Uint8Array | Uint8Array[], txToAppendTo?: Transaction | null): Transaction;
327
+
328
+ /**
329
+ * Pushes new byte array to the EndlessVector, creating and executing the necessary transaction.
330
+ */
331
+ push(arr: Uint8Array | Uint8Array[], params?: TransactionOptions): Promise<boolean>;
332
+
333
+ /**
334
+ * Creates a transaction to concatenate EndlessVector(s) into this one.
335
+ */
336
+ getConcatTransaction(
337
+ other: string | EndlessVector | Array<string | EndlessVector>,
338
+ txToAppendTo?: Transaction | null
339
+ ): Transaction;
340
+
341
+ /**
342
+ * Concatenates EndlessVector(s) into this one, creating and executing the necessary transaction.
343
+ */
344
+ concat(other: string | EndlessVector | Array<string | EndlessVector>, params?: TransactionOptions): Promise<boolean>;
345
+ }
346
+
347
+ export { EndlessVector as default };
package/package.json CHANGED
@@ -1,9 +1,10 @@
1
1
  {
2
2
  "name": "@fizzyflow/endless-vector",
3
- "version": "0.0.3",
3
+ "version": "0.0.5",
4
4
  "description": "",
5
5
  "type": "module",
6
6
  "main": "./index.js",
7
+ "types": "./index.d.ts",
7
8
  "keywords": [
8
9
  "sui",
9
10
  "vector",
@@ -24,7 +25,7 @@
24
25
  "author": "suidouble (https://github.com/suidouble)",
25
26
  "license": "Apache-2.0",
26
27
  "scripts": {
27
- "test": "tap -j1 -t240 ./test/*.test.js"
28
+ "test": "tap -j1 -t320 ./test/*.test.js"
28
29
  },
29
30
  "peerDependencies": {
30
31
  "@mysten/sui": "^1.44.0"
package/test/base.test.js CHANGED
@@ -71,8 +71,78 @@ test('attach a local package', async t => {
71
71
  });
72
72
 
73
73
 
74
+ test('test raw create transaction', async t => {
75
+ const arr = randomBytesOfLength(120 * 1024); // 100KB
76
+
77
+ const tx = new suiMaster.Transaction();
78
+ const vectorTxInput = await EndlessVector.getCreateTransactionAndReturnVectorInput({
79
+ packageId: contract.id,
80
+ }, arr, tx);
81
+ tx.transferObjects([vectorTxInput], tx.pure.address(suiMaster.address));
82
+
83
+ t.ok(tx);
84
+ let digest = null;
85
+ try {
86
+ digest = await signAndExecuteTransaction(tx);
87
+ t.ok(digest);
88
+ } catch (e) {
89
+ console.error('Error preparing transaction:', e);
90
+ }
91
+
92
+ const transactionBlockResponse = await suiMaster.client.waitForTransaction({
93
+ digest: digest,
94
+ options: { showObjectChanges: true, },
95
+ });
96
+
97
+ // Find the created EndlessVector object
98
+ const objectChanges = transactionBlockResponse.objectChanges || [];
99
+ const createdVector = objectChanges.find(
100
+ change => change.type === 'created' &&
101
+ change.objectType &&
102
+ change.objectType.includes('endless_vector::EndlessVector')
103
+ );
104
+
105
+ const createdVectorId = createdVector ? createdVector.objectId : null;
106
+ t.ok(createdVectorId, 'Created EndlessVector object should have an ID');
107
+
108
+ const loadBack = new EndlessVector({
109
+ suiClient: suiMaster.client,
110
+ id: createdVectorId,
111
+ });
112
+ await loadBack.initialize();
113
+
114
+ t.ok(loadBack.length === 1, `Loaded vector should have length 1, got ${loadBack.length}`);
115
+ const getBack = await loadBack.at(0);
116
+ t.ok(equalUint8Arrays(getBack, arr), 'Data retrieved from loaded vector should match original data');
117
+ });
74
118
 
75
119
 
120
+ test('make a test EndlessVector with few chunks in a single tx', async t => {
121
+ const data = [
122
+ randomBytesOfLength(1 * 1024),
123
+ randomBytesOfLength(2 * 1024),
124
+ randomBytesOfLength(3 * 1024),
125
+ ];
126
+
127
+ const testEndlessVector = await EndlessVector.create({
128
+ array: data,
129
+ suiClient: suiMaster.client, // instance of Sui SDK SuiClient
130
+ packageId: contract.id, // provide packageId and signAndExecuteTransaction to make EndlessVector writable
131
+ signAndExecuteTransaction: signAndExecuteTransaction,
132
+ });
133
+
134
+ const getBack0 = await testEndlessVector.at(0);
135
+ const getBack1 = await testEndlessVector.at(1);
136
+ const getBack2 = await testEndlessVector.at(2);
137
+
138
+ t.ok(equalUint8Arrays(getBack0, data[0]));
139
+ t.ok(equalUint8Arrays(getBack1, data[1]));
140
+ t.ok(equalUint8Arrays(getBack2, data[2]));
141
+
142
+ t.ok(testEndlessVector.length === 3);
143
+ t.ok(testEndlessVector.binaryLength === 6 * 1024);
144
+ });
145
+
76
146
  test('make a test EndlessVector and push single Uint8Array to it', async t => {
77
147
  endlessVector = await EndlessVector.create({
78
148
  suiClient: suiMaster.client, // instance of Sui SDK SuiClient
@@ -358,7 +428,7 @@ test('test parallel creation, push, and append of 6 vectors', async t => {
358
428
  // Prepare test data for each vector
359
429
  const testData = [];
360
430
  for (let i = 0; i < vectorCount; i++) {
361
- testData.push([randomBytesOfLength(1024), new Uint8Array([0, 1, i])]);
431
+ testData.push(randomBytesOfLength(1024));
362
432
  }
363
433
 
364
434
  // Create N EndlessVectors in parallel using static create method
@@ -368,7 +438,7 @@ test('test parallel creation, push, and append of 6 vectors', async t => {
368
438
  EndlessVector.create({
369
439
  suiClient: suiMaster.client,
370
440
  packageId: contract.id,
371
- items: testData[i] ? testData[i] : [],
441
+ array: testData[i] ? testData[i] : null,
372
442
  gasCoin: gasCoinInputs[i],
373
443
  signAndExecuteTransaction: async (tx) => {
374
444
  console.log(`Creating vector ${i}...`);
@@ -407,24 +477,20 @@ test('test parallel creation, push, and append of 6 vectors', async t => {
407
477
  // Verify the data after concatenation
408
478
  await mainVector.initialize();
409
479
 
410
- // Each vector has 2 items, so total should be vectorCount * 2
411
- const expectedLength = vectorCount * 2;
480
+ const expectedLength = vectorCount;
412
481
  t.ok(mainVector.length === expectedLength, `mainVector should have ${expectedLength} items, got ${mainVector.length}`);
413
482
 
414
483
  console.log(`Verifying ${expectedLength} items in concatenated vector...`);
415
484
 
416
485
  // Verify each item matches the original testData
417
486
  for (let vectorIdx = 0; vectorIdx < vectorCount; vectorIdx++) {
418
- for (let itemIdx = 0; itemIdx < testData[vectorIdx].length; itemIdx++) {
419
- const globalIdx = vectorIdx * testData[vectorIdx].length + itemIdx;
420
- const retrieved = await mainVector.at(globalIdx);
421
- const expected = testData[vectorIdx][itemIdx];
422
-
423
- t.ok(
424
- equalUint8Arrays(retrieved, expected),
425
- `Item ${globalIdx} (vector ${vectorIdx}, item ${itemIdx}) should match`
426
- );
427
- }
487
+ const expected = testData[vectorIdx];
488
+ const retrieved = await mainVector.at(vectorIdx);
489
+
490
+ t.ok(
491
+ equalUint8Arrays(retrieved, expected),
492
+ `Item ${vectorIdx} (vector ${vectorIdx}, item ${vectorIdx}) should match`
493
+ );
428
494
  }
429
495
  });
430
496