@onchaindb/sdk 0.4.5 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (117) hide show
  1. package/.claude/settings.local.json +10 -2
  2. package/README.md +422 -355
  3. package/dist/batch.d.ts +1 -10
  4. package/dist/batch.d.ts.map +1 -1
  5. package/dist/batch.js +4 -26
  6. package/dist/batch.js.map +1 -1
  7. package/dist/client.d.ts +31 -46
  8. package/dist/client.d.ts.map +1 -1
  9. package/dist/client.js +222 -357
  10. package/dist/client.js.map +1 -1
  11. package/dist/database.d.ts +14 -131
  12. package/dist/database.d.ts.map +1 -1
  13. package/dist/database.js +35 -131
  14. package/dist/database.js.map +1 -1
  15. package/dist/index.d.ts +10 -13
  16. package/dist/index.d.ts.map +1 -1
  17. package/dist/index.js +4 -18
  18. package/dist/index.js.map +1 -1
  19. package/dist/query-sdk/ConditionBuilder.d.ts +3 -11
  20. package/dist/query-sdk/ConditionBuilder.d.ts.map +1 -1
  21. package/dist/query-sdk/ConditionBuilder.js +10 -48
  22. package/dist/query-sdk/ConditionBuilder.js.map +1 -1
  23. package/dist/query-sdk/NestedBuilders.d.ts +33 -30
  24. package/dist/query-sdk/NestedBuilders.d.ts.map +1 -1
  25. package/dist/query-sdk/NestedBuilders.js +46 -43
  26. package/dist/query-sdk/NestedBuilders.js.map +1 -1
  27. package/{src/query-sdk/dist/OnChainDB.d.ts → dist/query-sdk/OnDB.d.ts} +10 -2
  28. package/dist/query-sdk/OnDB.d.ts.map +1 -0
  29. package/{src/query-sdk/dist/OnChainDB.js → dist/query-sdk/OnDB.js} +86 -18
  30. package/dist/query-sdk/OnDB.js.map +1 -0
  31. package/dist/query-sdk/QueryBuilder.d.ts +4 -2
  32. package/dist/query-sdk/QueryBuilder.d.ts.map +1 -1
  33. package/dist/query-sdk/QueryBuilder.js +47 -169
  34. package/dist/query-sdk/QueryBuilder.js.map +1 -1
  35. package/dist/query-sdk/QueryResult.d.ts +0 -38
  36. package/dist/query-sdk/QueryResult.d.ts.map +1 -1
  37. package/dist/query-sdk/QueryResult.js +1 -227
  38. package/dist/query-sdk/QueryResult.js.map +1 -1
  39. package/dist/query-sdk/index.d.ts +2 -2
  40. package/dist/query-sdk/index.d.ts.map +1 -1
  41. package/dist/query-sdk/index.js +3 -3
  42. package/dist/query-sdk/index.js.map +1 -1
  43. package/dist/query-sdk/operators.d.ts +32 -28
  44. package/dist/query-sdk/operators.d.ts.map +1 -1
  45. package/dist/query-sdk/operators.js +45 -155
  46. package/dist/query-sdk/operators.js.map +1 -1
  47. package/dist/types.d.ts +159 -36
  48. package/dist/types.d.ts.map +1 -1
  49. package/dist/types.js +8 -8
  50. package/dist/types.js.map +1 -1
  51. package/dist/x402/types.d.ts +1 -1
  52. package/dist/x402/types.d.ts.map +1 -1
  53. package/dist/x402/utils.js +2 -2
  54. package/dist/x402/utils.js.map +1 -1
  55. package/jest.config.js +4 -0
  56. package/package.json +1 -1
  57. package/skills.md +0 -1
  58. package/src/batch.d.ts +3 -3
  59. package/src/batch.js +1 -1
  60. package/src/client.ts +287 -823
  61. package/src/database.d.ts +1 -1
  62. package/src/database.js +4 -4
  63. package/src/database.ts +71 -494
  64. package/src/index.d.ts +18 -18
  65. package/src/index.js +16 -16
  66. package/src/index.ts +44 -198
  67. package/src/query-sdk/ConditionBuilder.ts +37 -89
  68. package/src/query-sdk/NestedBuilders.ts +90 -92
  69. package/src/query-sdk/{OnChainDB.ts → OnDB.ts} +1 -1
  70. package/src/query-sdk/QueryBuilder.ts +59 -218
  71. package/src/query-sdk/QueryResult.ts +4 -330
  72. package/src/query-sdk/README.md +218 -587
  73. package/src/query-sdk/index.ts +2 -2
  74. package/src/query-sdk/operators.ts +91 -200
  75. package/src/query-sdk/tests/FieldConditionBuilder.test.ts +70 -71
  76. package/src/query-sdk/tests/LogicalOperator.test.ts +43 -82
  77. package/src/query-sdk/tests/NestedBuilders.test.ts +229 -309
  78. package/src/query-sdk/tests/QueryBuilder.test.ts +5 -5
  79. package/src/query-sdk/tests/QueryResult.test.ts +41 -435
  80. package/src/query-sdk/tests/comprehensive.test.ts +4 -185
  81. package/src/tests/client-requests.test.ts +280 -0
  82. package/src/tests/client-validation.test.ts +80 -0
  83. package/src/types.d.ts +6 -6
  84. package/src/types.js +8 -8
  85. package/src/types.ts +239 -54
  86. package/src/x402/types.ts +3 -3
  87. package/src/x402/utils.ts +3 -3
  88. package/examples/blob-upload-example.ts +0 -140
  89. package/src/batch.ts +0 -257
  90. package/src/query-sdk/dist/ConditionBuilder.d.ts +0 -22
  91. package/src/query-sdk/dist/ConditionBuilder.js +0 -90
  92. package/src/query-sdk/dist/FieldConditionBuilder.d.ts +0 -1
  93. package/src/query-sdk/dist/FieldConditionBuilder.js +0 -6
  94. package/src/query-sdk/dist/NestedBuilders.d.ts +0 -43
  95. package/src/query-sdk/dist/NestedBuilders.js +0 -144
  96. package/src/query-sdk/dist/QueryBuilder.d.ts +0 -70
  97. package/src/query-sdk/dist/QueryBuilder.js +0 -295
  98. package/src/query-sdk/dist/QueryResult.d.ts +0 -52
  99. package/src/query-sdk/dist/QueryResult.js +0 -293
  100. package/src/query-sdk/dist/SelectionBuilder.d.ts +0 -20
  101. package/src/query-sdk/dist/SelectionBuilder.js +0 -80
  102. package/src/query-sdk/dist/adapters/HttpClientAdapter.d.ts +0 -27
  103. package/src/query-sdk/dist/adapters/HttpClientAdapter.js +0 -170
  104. package/src/query-sdk/dist/index.d.ts +0 -36
  105. package/src/query-sdk/dist/index.js +0 -27
  106. package/src/query-sdk/dist/operators.d.ts +0 -56
  107. package/src/query-sdk/dist/operators.js +0 -289
  108. package/src/query-sdk/dist/tests/setup.d.ts +0 -15
  109. package/src/query-sdk/dist/tests/setup.js +0 -46
  110. package/src/query-sdk/jest.config.js +0 -25
  111. package/src/query-sdk/package.json +0 -46
  112. package/src/query-sdk/tests/aggregations.test.ts +0 -653
  113. package/src/query-sdk/tests/integration.test.ts +0 -608
  114. package/src/query-sdk/tests/operators.test.ts +0 -327
  115. package/src/query-sdk/tests/unit.test.ts +0 -794
  116. package/src/query-sdk/tsconfig.json +0 -26
  117. package/src/query-sdk/yarn.lock +0 -3092
package/src/types.ts CHANGED
@@ -1,18 +1,74 @@
1
- // Core OnChainDB Types
1
+ // Core OnDB Types
2
2
  import {QueryValue} from "./query-sdk";
3
3
  import {X402Quote} from "./x402/types";
4
4
 
5
- export interface OnChainDBConfig {
5
+ export interface OnDBConfig {
6
6
  endpoint: string;
7
7
  apiKey?: string; // Deprecated: use appKey instead
8
8
  appKey?: string; // App API key for write operations (X-App-Key header)
9
9
  userKey?: string; // User API key for Auto-Pay (X-User-Key header)
10
+ agentKey?: string; // Agent Key with Pay permission (X-Agent-Key header)
10
11
  appId?: string; // Application ID for automatic root building
11
12
  timeout?: number;
12
13
  retryCount?: number;
13
14
  retryDelay?: number;
14
15
  }
15
16
 
17
+ // ============================================================================
18
+ // App Key Management Types
19
+ // ============================================================================
20
+
21
+ /**
22
+ * Permissions that can be granted to an app key.
23
+ * A key with "Pay" permission is an Agent Key — it can pay other apps inline
24
+ * when accessing their data using USDC via EIP-3009.
25
+ */
26
+ export type AppKeyPermission = 'Read' | 'Write' | 'Admin' | 'Pay';
27
+
28
+ /**
29
+ * Spend limits for Agent Keys (keys with "Pay" permission).
30
+ * All fields are optional — omitting a field means no limit on that dimension.
31
+ */
32
+ export interface PayLimits {
33
+ /** Optional expiry time (ISO 8601). Key stops working after this. */
34
+ expires_at?: string;
35
+ /** Max USDC per single transaction, in base units (6 decimals). e.g. 5000000 = 5 USDC */
36
+ max_payment_per_tx?: number;
37
+ /** Lifetime spend cap in USDC base units. */
38
+ spend_allowance?: number;
39
+ /** Whitelist of target app IDs this key may pay. Omit to allow all apps. */
40
+ allowed_target_apps?: string[];
41
+ }
42
+
43
+ /**
44
+ * Request body for POST /api/apps/:app_id/regenerate-key
45
+ */
46
+ export interface CreateKeyRequest {
47
+ name?: string;
48
+ permissions?: AppKeyPermission[];
49
+ /** Only used when permissions includes "Pay". Ignored otherwise. */
50
+ pay_limits?: PayLimits;
51
+ }
52
+
53
+ /**
54
+ * App key entry returned by POST /api/apps/:app_id/keys/list
55
+ */
56
+ export interface AppKeyInfo {
57
+ key_hash: string;
58
+ name: string;
59
+ permissions: AppKeyPermission[];
60
+ /** ISO 8601 expiry (only present on keys with pay_limits.expires_at set) */
61
+ expires_at?: string;
62
+ /** Max USDC per transaction in base units (6 decimals) */
63
+ max_payment_per_tx?: number;
64
+ /** Lifetime spend cap in USDC base units */
65
+ spend_allowance?: number;
66
+ /** Cumulative USDC spent so far in base units — increments after each on-chain payment */
67
+ spend_allowance_used?: number;
68
+ /** Whitelisted target app IDs (undefined = no restriction) */
69
+ allowed_target_apps?: string[];
70
+ }
71
+
16
72
  export interface StoreRequest {
17
73
  root?: string; // Format: "app::collection" or just "collection" for system
18
74
  collection?: string; // Collection name (will be combined with appId if provided)
@@ -93,8 +149,8 @@ export interface QueryRequest {
93
149
  export interface AdvancedQueryRequest {
94
150
  root?: string; // Format: "app::collection" - ONLY NEW THING
95
151
  collection?: string; // Collection name (will be combined with appId if provided)
96
- find?: any; // Flexible find conditions from onChainDBSDK
97
- select?: any; // Selection map from onChainDBSDK
152
+ find?: any; // Flexible find conditions from onDBSDK
153
+ select?: any; // Selection map from onDBSDK
98
154
 
99
155
  // All existing functionality stays the same
100
156
  filters?: Record<string, any>;
@@ -144,7 +200,7 @@ export interface TransactionEvents {
144
200
  }
145
201
 
146
202
  // Error Types
147
- export class OnChainDBError extends Error {
203
+ export class OnDBError extends Error {
148
204
  constructor(
149
205
  message: string,
150
206
  public code: string,
@@ -152,11 +208,11 @@ export class OnChainDBError extends Error {
152
208
  public details?: any
153
209
  ) {
154
210
  super(message);
155
- this.name = 'OnChainDBError';
211
+ this.name = 'OnDBError';
156
212
  }
157
213
  }
158
214
 
159
- export class TransactionError extends OnChainDBError {
215
+ export class TransactionError extends OnDBError {
160
216
  constructor(
161
217
  message: string,
162
218
  public transactionId: string,
@@ -167,14 +223,14 @@ export class TransactionError extends OnChainDBError {
167
223
  }
168
224
  }
169
225
 
170
- export class ValidationError extends OnChainDBError {
226
+ export class ValidationError extends OnDBError {
171
227
  constructor(message: string, details?: any) {
172
228
  super(message, 'VALIDATION_ERROR', 400, details);
173
229
  this.name = 'ValidationError';
174
230
  }
175
231
  }
176
232
 
177
- export class PaymentRequiredError extends OnChainDBError {
233
+ export class PaymentRequiredError extends OnDBError {
178
234
  constructor(
179
235
  message: string,
180
236
  public quote: X402Quote,
@@ -185,7 +241,7 @@ export class PaymentRequiredError extends OnChainDBError {
185
241
  }
186
242
  }
187
243
 
188
- export class PaymentVerificationError extends OnChainDBError {
244
+ export class PaymentVerificationError extends OnDBError {
189
245
  constructor(
190
246
  message: string,
191
247
  public txHash: string,
@@ -273,59 +329,15 @@ export interface PricingQuoteRequest {
273
329
  data?: any; // Sample data for price index calculation
274
330
  }
275
331
 
276
- export interface PricingQuoteResponse {
277
- type: 'write_quote_with_indexing' | 'read_quote';
278
- // Base costs
279
- base_celestia_cost: number;
280
- base_celestia_cost_utia: number;
281
- broker_fee: number;
282
- broker_fee_utia: number;
283
- // Indexing costs per field
284
- indexing_costs: Record<string, number>;
285
- indexing_costs_utia: Record<string, number>;
286
- // Total before price index fees
287
- base_total_cost: number;
288
- base_total_cost_utia: number;
289
- // Final total (includes price index fees if any)
290
- total_cost: number;
291
- total_cost_utia: number;
292
- // Metadata
293
- indexed_fields_count: number;
294
- request: PricingQuoteRequest;
295
- monthly_volume_kb: number;
296
- currency: string;
297
- // Optional breakdowns
298
- creator_premium?: {
299
- premium_total: number;
300
- premium_total_utia: number;
301
- premium_type: string;
302
- premium_amount: number;
303
- creator_revenue: number;
304
- creator_revenue_utia: number;
305
- platform_revenue: number;
306
- platform_revenue_utia: number;
307
- revenue_split: string;
308
- };
309
- price?: any; // Price index breakdown (single or multiple fields)
310
- }
311
-
312
332
  // ============================================================================
313
333
  // Collection Schema Types (for createCollection convenience method)
314
334
  // ============================================================================
315
335
 
316
336
  // Re-export from database.ts for consistency
317
337
  export type {
318
- Collection,
319
- CollectionSchema,
320
- FieldDefinition,
321
- FieldValidation,
322
- Relationship,
323
338
  Index,
324
339
  IndexOptions,
325
- IndexStatus,
326
- IndexStatistics,
327
340
  PriceConfig,
328
- CollectionMetadata
329
341
  } from './database';
330
342
 
331
343
  /**
@@ -519,10 +531,183 @@ export interface SyncCollectionResult {
519
531
  field: string;
520
532
  type: string;
521
533
  }[];
534
+ sharding_configured?: boolean;
522
535
  success: boolean;
523
536
  errors?: string[];
524
537
  }
525
538
 
539
+ // ============================================================================
540
+ // Collection Management
541
+ // ============================================================================
542
+
543
+ export interface UpdateCollectionRequest {
544
+ description?: string;
545
+ public?: boolean;
546
+ default_sort_column?: string;
547
+ retention_days?: number | null;
548
+ collection_type?: 'local' | 'offline' | 'api' | 'hybrid';
549
+ api_config?: ApiConfig;
550
+ }
551
+
552
+ export interface ApiConfig {
553
+ base_url: string;
554
+ authentication: any;
555
+ query_mapping: any;
556
+ response_mapping: any;
557
+ }
558
+
559
+ export interface CollectionResponse {
560
+ id: string;
561
+ name: string;
562
+ namespace: string;
563
+ primary_column: string;
564
+ sort_column?: string;
565
+ status: string;
566
+ collection_type: string;
567
+ document_count: number;
568
+ size_kb: number;
569
+ created_at: string;
570
+ last_modified: string;
571
+ }
572
+
573
+ export interface SetRetentionRequest {
574
+ retention_days: number | null;
575
+ }
576
+
577
+ export interface RetentionConfig {
578
+ collection: string;
579
+ retention_days?: number;
580
+ monthly_cost_per_kb: number;
581
+ last_cleanup?: string;
582
+ status: string;
583
+ }
584
+
585
+ export interface CollectionRetentionCost {
586
+ collection: string;
587
+ retention_days?: number;
588
+ size_kb: number;
589
+ monthly_cost_per_kb: number;
590
+ monthly_cost_tia: number;
591
+ projected_size_kb: number;
592
+ projected_monthly_cost_tia: number;
593
+ }
594
+
595
+ export interface RetentionCostResponse {
596
+ app_id: string;
597
+ collections: CollectionRetentionCost[];
598
+ total_monthly_cost_tia: number;
599
+ projected_next_month_cost_tia: number;
600
+ }
601
+
602
+ // ============================================================================
603
+ // SQL Interface
604
+ // ============================================================================
605
+
606
+ export interface SqlQueryRequest {
607
+ sql: string;
608
+ include_history?: boolean;
609
+ }
610
+
611
+ export interface SqlQueryResponse {
612
+ data: any[];
613
+ count: number;
614
+ query: string;
615
+ app_id: string;
616
+ collection: string;
617
+ }
618
+
619
+ export interface SqlInsertRequest {
620
+ sql: string;
621
+ }
622
+
623
+ // ============================================================================
624
+ // Predefined Queries
625
+ // ============================================================================
626
+
627
+ export interface QueryParameter {
628
+ /** Parameter name (used in URL query params) */
629
+ name: string;
630
+ /** Field path in the query (e.g., "market" or "price.$gte") */
631
+ field_path: string;
632
+ /** Default value if not provided */
633
+ default?: any;
634
+ /** Whether this parameter is required (no default, must be provided) */
635
+ required?: boolean;
636
+ /** Description of the parameter */
637
+ description?: string;
638
+ }
639
+
640
+ export interface QueryDefinition {
641
+ name: string;
642
+ source_collection: string;
643
+ base_query: any;
644
+ parameters?: QueryParameter[];
645
+ created_at: string;
646
+ description?: string;
647
+ }
648
+
649
+ export interface CreateQueryRequest {
650
+ name: string;
651
+ source_collection: string;
652
+ base_query: any;
653
+ parameters?: QueryParameter[];
654
+ description?: string;
655
+ version?: number;
656
+ response_schema?: any;
657
+ sample_response?: any;
658
+ example_request?: any;
659
+ example_response?: any;
660
+ }
661
+
662
+ export interface CreateQueryResponse {
663
+ success: boolean;
664
+ message: string;
665
+ query_name: string;
666
+ }
667
+
668
+ export interface QueryDataResponse {
669
+ success: boolean;
670
+ query_name: string;
671
+ data: any[];
672
+ count: number;
673
+ query_time_ms: number;
674
+ }
675
+
676
+ // ============================================================================
677
+ // Views
678
+ // ============================================================================
679
+
680
+ export interface SqlCreateViewRequest {
681
+ sql: string;
682
+ refresh_mode?: 'live' | 'lazy';
683
+ }
684
+
685
+ export interface ViewDataResponse<T = any> {
686
+ success: boolean;
687
+ view_name: string;
688
+ data: T[];
689
+ count: number;
690
+ query_time_ms: number;
691
+ }
692
+
693
+ export interface ViewQueryRequest {
694
+ find?: any;
695
+ select?: string[];
696
+ sort_by?: string[];
697
+ limit?: number;
698
+ offset?: number;
699
+ }
700
+
701
+ // ============================================================================
702
+ // API Collections
703
+ // ============================================================================
704
+
705
+ export interface CreateApiCollectionRequest {
706
+ name: string;
707
+ description: string;
708
+ api_config: ApiConfig;
709
+ }
710
+
526
711
  /**
527
712
  * Base document fields (auto-added when useBaseFields is true)
528
713
  */
package/src/x402/types.ts CHANGED
@@ -47,7 +47,7 @@ export interface X402PaymentRequirement {
47
47
  }
48
48
 
49
49
  /**
50
- * x402 Extra field with OnChainDB extensions
50
+ * x402 Extra field with OnDB extensions
51
51
  */
52
52
  export interface X402Extra {
53
53
  /** Extension identifier */
@@ -164,8 +164,8 @@ export interface X402PaymentResponse {
164
164
  export interface X402Quote {
165
165
  /** Quote ID */
166
166
  quoteId: string;
167
- /** Total cost in TIA */
168
- totalCostTia: number;
167
+ /** Total cost */
168
+ totalCost: number;
169
169
  /** Amount in smallest units */
170
170
  amountRaw: string;
171
171
  /** Broker/recipient address */
package/src/x402/utils.ts CHANGED
@@ -79,9 +79,9 @@ export function requirementToQuote(
79
79
  chainType = 'solana';
80
80
  }
81
81
 
82
- // Calculate TIA amount (for display purposes)
82
+ // Calculate total cost (for display purposes)
83
83
  const decimals = extra.tokenDecimals || 6;
84
- const totalCostTia = parseInt(amountRaw) / Math.pow(10, decimals);
84
+ const totalCost = parseInt(amountRaw) / Math.pow(10, decimals);
85
85
 
86
86
  // Calculate expiration
87
87
  const expiresAt = extra.pricing?.expiresAt ||
@@ -89,7 +89,7 @@ export function requirementToQuote(
89
89
 
90
90
  return {
91
91
  quoteId: extra.quoteId || '',
92
- totalCostTia,
92
+ totalCost,
93
93
  amountRaw,
94
94
  brokerAddress: requirement.payTo,
95
95
  description: requirement.description,
@@ -1,140 +0,0 @@
1
- /**
2
- * OnChainDB SDK - Blob Upload Example
3
- *
4
- * Demonstrates how to upload binary files (images, videos, documents)
5
- * to OnChainDB with the x402 payment protocol.
6
- *
7
- * Features:
8
- * - Get pricing quote for blob upload
9
- * - Upload blob with custom metadata
10
- * - Track upload progress with ticket_id
11
- * - Retrieve uploaded blob
12
- * - Query blob metadata
13
- */
14
-
15
- import { createClient } from '../src';
16
-
17
- const config = {
18
- endpoint: 'http://localhost:9092',
19
- apiKey: 'your_api_key',
20
- appId: 'my_app'
21
- };
22
-
23
- const BROKER_ADDRESS = 'celestia1broker...';
24
-
25
- async function uploadProfilePhoto() {
26
- console.log('OnChainDB Blob Upload Example\n');
27
-
28
- const client = createClient(config);
29
-
30
- // In a real app, get file from input:
31
- // const file = document.querySelector('input[type="file"]').files[0];
32
-
33
- // For this example, create a mock blob
34
- const mockBlob = new Blob(['mock image data'], { type: 'image/jpeg' });
35
- const fileSizeKB = Math.ceil(mockBlob.size / 1024);
36
-
37
- // Step 1: Get pricing quote
38
- console.log('1. Getting pricing quote...');
39
- const quote = await client.getPricingQuote({
40
- app_id: config.appId,
41
- operation_type: 'write',
42
- size_kb: fileSizeKB,
43
- collection: 'avatars'
44
- });
45
-
46
- const costInUtia = Math.ceil(quote.total_cost * 1_000_000);
47
- console.log(` Size: ${fileSizeKB}KB`);
48
- console.log(` Cost: ${quote.total_cost} TIA (${costInUtia} utia)`);
49
- console.log();
50
-
51
- // Step 2: Create payment transaction
52
- // In a real app with Keplr:
53
- // const result = await wallet.signAndBroadcast(
54
- // BROKER_ADDRESS,
55
- // `${costInUtia}utia`,
56
- // 'Image upload'
57
- // );
58
- // const paymentTxHash = result.transactionHash;
59
-
60
- const paymentTxHash = 'mock_payment_tx_hash';
61
- const userAddress = 'celestia1user...';
62
-
63
- console.log('2. Payment transaction created');
64
- console.log(` TX Hash: ${paymentTxHash}`);
65
- console.log();
66
-
67
- // Step 3: Upload blob with metadata
68
- console.log('3. Uploading blob...');
69
- const uploadResult = await client.uploadBlob({
70
- collection: 'avatars',
71
- blob: mockBlob,
72
- metadata: {
73
- user_address: userAddress,
74
- description: 'Profile photo',
75
- is_primary: true
76
- },
77
- payment_tx_hash: paymentTxHash,
78
- user_address: userAddress,
79
- broker_address: BROKER_ADDRESS,
80
- amount_utia: costInUtia
81
- });
82
-
83
- console.log(' Blob upload initiated!');
84
- console.log(` Blob ID: ${uploadResult.blob_id}`);
85
- console.log(` Ticket ID: ${uploadResult.ticket_id}`);
86
- console.log();
87
-
88
- // Step 4: Wait for upload completion
89
- console.log('4. Waiting for upload to complete...');
90
- const task = await client.waitForTaskCompletion(uploadResult.ticket_id);
91
-
92
- console.log(` Status: ${task.status}`);
93
- if (task.status === 'Completed') {
94
- console.log(` TX Hash: ${task.transaction_hash}`);
95
- console.log(` Block Height: ${task.block_height}`);
96
- }
97
- console.log();
98
-
99
- // Step 5: Query blob metadata
100
- console.log('5. Querying blob metadata...');
101
- const blobs = await client.queryBlobMetadata('avatars', {
102
- user_address: userAddress
103
- });
104
-
105
- console.log(` Found ${blobs.length} blobs for user`);
106
- for (const blob of blobs) {
107
- console.log(` - Blob ID: ${blob.blob_id}`);
108
- console.log(` Type: ${blob.content_type}`);
109
- console.log(` Size: ${blob.size_bytes} bytes`);
110
- }
111
- console.log();
112
-
113
- // Step 6: Retrieve blob
114
- console.log('6. Retrieving blob...');
115
- const retrievedBlob = await client.retrieveBlob({
116
- collection: 'avatars',
117
- blob_id: uploadResult.blob_id
118
- });
119
-
120
- console.log(' Blob retrieved successfully!');
121
- console.log(` Size: ${retrievedBlob instanceof Blob ? retrievedBlob.size : retrievedBlob.length} bytes`);
122
-
123
- // In browser, display the image:
124
- // const imageUrl = URL.createObjectURL(retrievedBlob);
125
- // document.querySelector('img').src = imageUrl;
126
-
127
- console.log('\nBlob upload example complete!');
128
- }
129
-
130
- // Run example
131
- if (require.main === module) {
132
- uploadProfilePhoto()
133
- .then(() => process.exit(0))
134
- .catch((error) => {
135
- console.error('Error:', error.message);
136
- process.exit(1);
137
- });
138
- }
139
-
140
- export { uploadProfilePhoto };