@fizzyflow/endless-vector 0.0.1
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 +862 -0
- package/EndlessVectorArchive.js +219 -0
- package/EndlessVectorHistory.js +187 -0
- package/README.md +326 -0
- package/ids.js +11 -0
- package/index.js +10 -0
- package/package.json +36 -0
- package/test/base.test.js +433 -0
- package/test/helpers.js +32 -0
package/README.md
ADDED
|
@@ -0,0 +1,326 @@
|
|
|
1
|
+
# Endless Vector - JavaScript SDK
|
|
2
|
+
|
|
3
|
+
JavaScript/TypeScript SDK for interacting with the Endless Vector smart contract on the Sui blockchain. Endless Vector provides a scalable, on-chain data structure storing `vector<vector<u8>>` that can grow beyond Sui object size limits.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @fizzyflow/endless-vector
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Quick Start
|
|
12
|
+
|
|
13
|
+
### Creating a New Vector
|
|
14
|
+
|
|
15
|
+
```javascript
|
|
16
|
+
import { SuiClient } from '@mysten/sui/client';
|
|
17
|
+
import { EndlessVector } from '@fizzyflow/endless-vector';
|
|
18
|
+
|
|
19
|
+
const client = new SuiClient({ url: 'https://fullnode.mainnet.sui.io:443' });
|
|
20
|
+
|
|
21
|
+
// Create an empty vector
|
|
22
|
+
const vector = await EndlessVector.create({
|
|
23
|
+
suiClient: client,
|
|
24
|
+
packageId: 'testnet', // or 'mainnet' or '0xYOUR_PACKAGE_ID'
|
|
25
|
+
signAndExecuteTransaction: async (tx) => {
|
|
26
|
+
const result = await wallet.signAndExecuteTransaction({ transaction: tx });
|
|
27
|
+
return result.digest;
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
// Or create with initial data
|
|
32
|
+
const vectorWithData = await EndlessVector.create({
|
|
33
|
+
suiClient: client,
|
|
34
|
+
packageId: 'testnet', // or 'mainnet' or '0xYOUR_PACKAGE_ID'
|
|
35
|
+
items: [
|
|
36
|
+
new Uint8Array([1, 2, 3]),
|
|
37
|
+
new Uint8Array([4, 5, 6])
|
|
38
|
+
],
|
|
39
|
+
signAndExecuteTransaction: async (tx) => {
|
|
40
|
+
const result = await wallet.signAndExecuteTransaction({ transaction: tx });
|
|
41
|
+
return result.digest;
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### Reading an Existing Vector
|
|
47
|
+
|
|
48
|
+
```javascript
|
|
49
|
+
const vector = new EndlessVector({
|
|
50
|
+
suiClient: client,
|
|
51
|
+
id: '0xYOUR_VECTOR_OBJECT_ID'
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
await vector.initialize();
|
|
55
|
+
|
|
56
|
+
console.log('Total items:', vector.length);
|
|
57
|
+
console.log('Total size:', vector.binaryLength, 'bytes');
|
|
58
|
+
|
|
59
|
+
// Read items
|
|
60
|
+
const firstItem = await vector.at(0);
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## API Reference
|
|
64
|
+
|
|
65
|
+
### Static Methods
|
|
66
|
+
|
|
67
|
+
#### EndlessVector.create(params)
|
|
68
|
+
|
|
69
|
+
Creates a new EndlessVector on the blockchain.
|
|
70
|
+
|
|
71
|
+
**Parameters:**
|
|
72
|
+
- `suiClient` (SuiClient) - Sui client instance for blockchain interactions
|
|
73
|
+
- `packageId` (string) - 'testnet', 'mainnet', or ID of the Move package containing the EndlessVector module
|
|
74
|
+
- `signAndExecuteTransaction` (function) - Function to sign and execute transactions
|
|
75
|
+
- `items` (Array<Uint8Array>, optional) - Initial items to push to the vector
|
|
76
|
+
- `gasCoin` (Object, optional) - Gas coin object reference `{objectId: string, digest: string, version: string}` for transaction payment
|
|
77
|
+
- `options` (Object, optional) - Additional options:
|
|
78
|
+
- `timeout` (number) - Transaction confirmation timeout in ms (default: 30000)
|
|
79
|
+
- `pollIntervalMs` (number) - Poll interval in ms (default: 1000)
|
|
80
|
+
|
|
81
|
+
**Returns:** Promise<EndlessVector>
|
|
82
|
+
|
|
83
|
+
**Example:**
|
|
84
|
+
```javascript
|
|
85
|
+
const vector = await EndlessVector.create({
|
|
86
|
+
suiClient: client,
|
|
87
|
+
packageId: 'testnet', // or 'mainnet' or '0xPACKAGE_ID'
|
|
88
|
+
items: [new Uint8Array([1, 2, 3])],
|
|
89
|
+
gasCoin: {
|
|
90
|
+
objectId: '0xGAS_COIN_ID',
|
|
91
|
+
digest: 'DIGEST',
|
|
92
|
+
version: 'VERSION'
|
|
93
|
+
},
|
|
94
|
+
signAndExecuteTransaction: async (tx) => {
|
|
95
|
+
const result = await wallet.signAndExecuteTransaction({ transaction: tx });
|
|
96
|
+
return result.digest;
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### Constructor
|
|
102
|
+
|
|
103
|
+
```javascript
|
|
104
|
+
const vector = new EndlessVector({
|
|
105
|
+
suiClient, // SuiClient instance (required for reading)
|
|
106
|
+
id, // Object ID of the EndlessVector (required)
|
|
107
|
+
packageId, // 'testnet', 'mainnet', or Package ID for write operations (optional)
|
|
108
|
+
signAndExecuteTransaction // Function to sign/execute transactions (optional)
|
|
109
|
+
});
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
**Modes:**
|
|
113
|
+
- **Read-only mode**: Provide only `suiClient` and `id`
|
|
114
|
+
- **Writable mode**: Provide all parameters including `packageId` and `signAndExecuteTransaction`
|
|
115
|
+
|
|
116
|
+
### Properties
|
|
117
|
+
|
|
118
|
+
- `id` (string) - Object ID of the EndlessVector
|
|
119
|
+
- `isWritable` (boolean) - Whether the instance can perform write operations
|
|
120
|
+
- `length` (number) - Total number of items in the vector
|
|
121
|
+
- `binaryLength` (number) - Total binary size of all items in bytes
|
|
122
|
+
- `historyItemsCount` (number) - Number of history segments
|
|
123
|
+
- `archiveItemsCount` (number) - Number of archive segments
|
|
124
|
+
- `archivedFromLength` (number) - Starting index after burned archives
|
|
125
|
+
- `burnedArchiveCount` (number) - Number of archives that have been burned
|
|
126
|
+
- `firstNotHistoryIndex` (number) - First index stored in current object (not in history)
|
|
127
|
+
|
|
128
|
+
### Methods
|
|
129
|
+
|
|
130
|
+
#### initialize()
|
|
131
|
+
|
|
132
|
+
Loads the vector's metadata from the blockchain. Called automatically by most methods.
|
|
133
|
+
|
|
134
|
+
```javascript
|
|
135
|
+
await vector.initialize();
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
#### reInitialize()
|
|
139
|
+
|
|
140
|
+
Forces a reload of the vector's metadata, clearing caches.
|
|
141
|
+
|
|
142
|
+
```javascript
|
|
143
|
+
await vector.reInitialize();
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
#### push(arr, params)
|
|
147
|
+
|
|
148
|
+
Pushes a new byte array to the vector. Requires writable mode. Maximum size per item: ~200KB.
|
|
149
|
+
|
|
150
|
+
```javascript
|
|
151
|
+
const data = new Uint8Array([1, 2, 3, 4, 5]);
|
|
152
|
+
await vector.push(data);
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
**Parameters:**
|
|
156
|
+
- `arr` (Uint8Array) - Data to push
|
|
157
|
+
- `params` (Object, optional) - Additional parameters
|
|
158
|
+
|
|
159
|
+
#### getPushTransaction(arr, tx)
|
|
160
|
+
|
|
161
|
+
Creates a transaction for pushing data without executing it. Useful for batching multiple pushes.
|
|
162
|
+
|
|
163
|
+
```javascript
|
|
164
|
+
// Single push transaction
|
|
165
|
+
const tx = vector.getPushTransaction(new Uint8Array([1, 2, 3]));
|
|
166
|
+
await signAndExecuteTransaction(tx);
|
|
167
|
+
|
|
168
|
+
// Multiple pushes in one transaction
|
|
169
|
+
const tx = new Transaction();
|
|
170
|
+
vector.getPushTransaction(new Uint8Array([1, 2, 3]), tx);
|
|
171
|
+
vector.getPushTransaction(new Uint8Array([4, 5, 6]), tx);
|
|
172
|
+
await signAndExecuteTransaction(tx);
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
**Parameters:**
|
|
176
|
+
- `arr` (Uint8Array) - Data to push
|
|
177
|
+
- `tx` (Transaction, optional) - Existing transaction to append to
|
|
178
|
+
|
|
179
|
+
**Returns:** Transaction
|
|
180
|
+
|
|
181
|
+
#### at(index)
|
|
182
|
+
|
|
183
|
+
Retrieves an item at a specific index. Alias: `get(index)`
|
|
184
|
+
|
|
185
|
+
```javascript
|
|
186
|
+
const item = await vector.at(42); // Returns Uint8Array
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
**Parameters:**
|
|
190
|
+
- `index` (number) - Zero-based index
|
|
191
|
+
|
|
192
|
+
**Returns:** Promise<Uint8Array>
|
|
193
|
+
|
|
194
|
+
#### concat(other)
|
|
195
|
+
|
|
196
|
+
Concatenates another EndlessVector (or array of vectors) into this one. The other vector(s) will be consumed.
|
|
197
|
+
|
|
198
|
+
```javascript
|
|
199
|
+
// Concat single vector
|
|
200
|
+
await vector1.concat(vector2);
|
|
201
|
+
|
|
202
|
+
// Concat multiple vectors at once
|
|
203
|
+
await vector1.concat([vector2, vector3, vector4]);
|
|
204
|
+
|
|
205
|
+
// Also accepts object IDs
|
|
206
|
+
await vector1.concat('0xVECTOR2_ID');
|
|
207
|
+
await vector1.concat(['0xVECTOR2_ID', '0xVECTOR3_ID']);
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
**Parameters:**
|
|
211
|
+
- `other` (string | EndlessVector | Array<string | EndlessVector>) - Vector(s) to concatenate
|
|
212
|
+
|
|
213
|
+
**Returns:** Promise<void>
|
|
214
|
+
|
|
215
|
+
**Note:** Cannot concat vectors that have archived items.
|
|
216
|
+
|
|
217
|
+
#### getConcatTransaction(other, tx)
|
|
218
|
+
|
|
219
|
+
Creates a transaction for concatenation without executing it.
|
|
220
|
+
|
|
221
|
+
```javascript
|
|
222
|
+
const tx = vector1.getConcatTransaction(vector2);
|
|
223
|
+
await signAndExecuteTransaction(tx);
|
|
224
|
+
|
|
225
|
+
// Or append to existing transaction
|
|
226
|
+
const tx = new Transaction();
|
|
227
|
+
vector1.getConcatTransaction([vector2, vector3], tx);
|
|
228
|
+
await signAndExecuteTransaction(tx);
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
**Parameters:**
|
|
232
|
+
- `other` (string | EndlessVector | Array<string | EndlessVector>) - Vector(s) to concatenate
|
|
233
|
+
- `tx` (Transaction, optional) - Existing transaction to append to
|
|
234
|
+
|
|
235
|
+
**Returns:** Transaction
|
|
236
|
+
|
|
237
|
+
## Usage Examples
|
|
238
|
+
|
|
239
|
+
```javascript
|
|
240
|
+
const vector = new EndlessVector({
|
|
241
|
+
suiClient: client,
|
|
242
|
+
id: '0xVECTOR_ID'
|
|
243
|
+
});
|
|
244
|
+
|
|
245
|
+
await vector.initialize();
|
|
246
|
+
|
|
247
|
+
// Read metadata
|
|
248
|
+
console.log('Items:', vector.length);
|
|
249
|
+
console.log('Size:', vector.binaryLength, 'bytes');
|
|
250
|
+
console.log('History segments:', vector.historyItemsCount);
|
|
251
|
+
console.log('Archive segments:', vector.archiveItemsCount);
|
|
252
|
+
|
|
253
|
+
// Read specific item
|
|
254
|
+
const item = await vector.at(42); // Uint8Array
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
### Custom Gas Coin for Parallel Operations
|
|
258
|
+
|
|
259
|
+
To execute transactions in parallel, speeding up data upload process, you would probably need separate gas coin for each tx:
|
|
260
|
+
|
|
261
|
+
```javascript
|
|
262
|
+
// Get available gas coins
|
|
263
|
+
const coins = await client.getCoins({
|
|
264
|
+
owner: address,
|
|
265
|
+
coinType: '0x2::sui::SUI'
|
|
266
|
+
});
|
|
267
|
+
const gasCoinRefs = coins.data.map(c => ({
|
|
268
|
+
objectId: c.coinObjectId,
|
|
269
|
+
digest: c.digest,
|
|
270
|
+
version: c.version
|
|
271
|
+
}));
|
|
272
|
+
|
|
273
|
+
// Create vectors in parallel, each with its own gas coin
|
|
274
|
+
const vectors = await Promise.all(
|
|
275
|
+
testData.map((items, i) =>
|
|
276
|
+
EndlessVector.create({
|
|
277
|
+
suiClient: client,
|
|
278
|
+
packageId: 'testnet', // or 'mainnet' or '0xPACKAGE_ID'
|
|
279
|
+
items: items,
|
|
280
|
+
gasCoin: gasCoinRefs[i],
|
|
281
|
+
signAndExecuteTransaction: async (tx) => {
|
|
282
|
+
const result = await wallet.signAndExecuteTransaction({ transaction: tx });
|
|
283
|
+
return result.digest;
|
|
284
|
+
}
|
|
285
|
+
})
|
|
286
|
+
)
|
|
287
|
+
);
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
## Testing
|
|
291
|
+
|
|
292
|
+
Run the test suite:
|
|
293
|
+
|
|
294
|
+
```bash
|
|
295
|
+
npm test
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
Tests use the TAP framework and require a configured local sui validator installed.
|
|
299
|
+
|
|
300
|
+
### Performance Considerations
|
|
301
|
+
|
|
302
|
+
- **Caching**: Loaded history and archive segments are cached
|
|
303
|
+
- **Lazy Loading**: History/archive data is only loaded when accessed
|
|
304
|
+
- **Batch Writes**: Use `getPushTransaction()` to combine multiple pushes in one transaction
|
|
305
|
+
- **Re-initialization**: After `push()` or `concat()`, metadata is refreshed on next read
|
|
306
|
+
|
|
307
|
+
### Concatenation
|
|
308
|
+
|
|
309
|
+
The `concat()` method efficiently merges vectors by transferring ownership of internal data structures rather than copying items one by one. This makes it very efficient for combining large datasets.
|
|
310
|
+
|
|
311
|
+
**Restrictions:**
|
|
312
|
+
- Cannot concatenate vectors that have archived items
|
|
313
|
+
- The concatenated vector is consumed (destroyed) in the process
|
|
314
|
+
- All items from concatenated vector(s) are appended in order
|
|
315
|
+
|
|
316
|
+
## License
|
|
317
|
+
|
|
318
|
+
Apache-2.0
|
|
319
|
+
|
|
320
|
+
## Repository
|
|
321
|
+
|
|
322
|
+
https://github.com/fizzyFlow/endless_vector
|
|
323
|
+
|
|
324
|
+
## Author
|
|
325
|
+
|
|
326
|
+
[suidouble](https://github.com/suidouble)
|
package/ids.js
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
|
|
2
|
+
export default {
|
|
3
|
+
'testnet': {
|
|
4
|
+
packageId: '0x5e35ef9e8ea315a4db40047b9133c028603168e7b41a27511e9f7eea38313685', // should be the same as in Move.lock
|
|
5
|
+
originalPackageId: '0x5e35ef9e8ea315a4db40047b9133c028603168e7b41a27511e9f7eea38313685',
|
|
6
|
+
},
|
|
7
|
+
'mainnet': {
|
|
8
|
+
packageId: '0xa81971816c632022658736d464d35bd47a7d6b5ad60e0903697e4adda0aa1331', // should be the same as in Move.lock
|
|
9
|
+
originalPackageId: '0xa81971816c632022658736d464d35bd47a7d6b5ad60e0903697e4adda0aa1331',
|
|
10
|
+
},
|
|
11
|
+
};
|
package/index.js
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import EndlessVector from "./EndlessVector.js";
|
|
2
|
+
import EndlessVectorArchive from "./EndlessVectorArchive.js";
|
|
3
|
+
import EndlessVectorHistory from "./EndlessVectorHistory.js";
|
|
4
|
+
|
|
5
|
+
export {
|
|
6
|
+
EndlessVector as default,
|
|
7
|
+
EndlessVector,
|
|
8
|
+
EndlessVectorArchive,
|
|
9
|
+
EndlessVectorHistory
|
|
10
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@fizzyflow/endless-vector",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./index.js",
|
|
7
|
+
"keywords": [
|
|
8
|
+
"sui",
|
|
9
|
+
"vector",
|
|
10
|
+
"database",
|
|
11
|
+
"storage",
|
|
12
|
+
"sui.js",
|
|
13
|
+
"web3",
|
|
14
|
+
"dapps",
|
|
15
|
+
"dapp"
|
|
16
|
+
],
|
|
17
|
+
"repository": {
|
|
18
|
+
"type": "git",
|
|
19
|
+
"url": "git+https://github.com/fizzyFlow/endless_vector.git"
|
|
20
|
+
},
|
|
21
|
+
"publishConfig": {
|
|
22
|
+
"access": "public"
|
|
23
|
+
},
|
|
24
|
+
"author": "suidouble (https://github.com/suidouble)",
|
|
25
|
+
"license": "Apache-2.0",
|
|
26
|
+
"scripts": {
|
|
27
|
+
"test": "tap -j1 -t240 ./test/*.test.js"
|
|
28
|
+
},
|
|
29
|
+
"peerDependencies": {
|
|
30
|
+
"@mysten/sui": "^1.44.0"
|
|
31
|
+
},
|
|
32
|
+
"devDependencies": {
|
|
33
|
+
"suidouble": "^1.44.0",
|
|
34
|
+
"tap": "^21.1.0"
|
|
35
|
+
}
|
|
36
|
+
}
|