@bloque/sdk 0.0.21 → 0.0.23

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -30,11 +30,15 @@ This SDK is compatible with multiple JavaScript runtimes:
30
30
 
31
31
  - **TypeScript First**: Built with TypeScript for complete type safety
32
32
  - **Simple API**: Intuitive interface for managing organizations, compliance, accounts, and identity
33
+ - **Virtual Cards**: Create and manage virtual cards with real-time balance tracking
33
34
  - **Identity Registration**: Register individual users (KYC) and businesses (KYB) with multi-method authentication
35
+ - **User Sessions**: Secure user session management with `connect()` for authenticated operations
34
36
  - **Fully Async**: Promise-based API for modern JavaScript workflows
35
37
  - **Lightweight**: Minimal dependencies for optimal bundle size
36
38
  - **Modular**: Import only what you need with tree-shakeable exports
37
39
 
40
+ > **📌 Important:** Most operations require connecting to a user session first using `bloque.connect(urn)`. This ensures proper authentication and authorization. See the [User Sessions](#user-sessions-with-connect) section for details.
41
+
38
42
  ## Installation
39
43
 
40
44
  ```bash
@@ -51,6 +55,7 @@ import type { CreateOrgParams } from '@bloque/sdk/orgs';
51
55
 
52
56
  // Initialize the SDK with API key (backend only)
53
57
  const bloque = new SDK({
58
+ origin: 'your-origin-name', // Required: your origin identifier
54
59
  auth: {
55
60
  type: 'apiKey',
56
61
  apiKey: process.env.BLOQUE_API_KEY!,
@@ -59,7 +64,22 @@ const bloque = new SDK({
59
64
  platform: 'node', // optional: 'node' | 'bun' | 'deno'
60
65
  });
61
66
 
62
- // Create an organization
67
+ // Connect to user session for account operations
68
+ async function createCard() {
69
+ // First, connect to the user's session
70
+ const userSession = await bloque.connect('did:bloque:your-origin:user-alias');
71
+
72
+ // Now create a virtual card through the session
73
+ const card = await userSession.accounts.card.create({
74
+ urn: 'did:bloque:your-origin:user-alias',
75
+ name: 'My Virtual Card',
76
+ });
77
+
78
+ console.log('Card created:', card.urn);
79
+ console.log('Last four digits:', card.lastFour);
80
+ }
81
+
82
+ // Create an organization (direct SDK access, no connect needed)
63
83
  async function createOrganization() {
64
84
  const params: CreateOrgParams = {
65
85
  org_type: 'business',
@@ -79,20 +99,10 @@ async function createOrganization() {
79
99
  },
80
100
  };
81
101
 
82
- const organization = await bloque.orgs.create(params);
102
+ const userSession = await bloque.connect('did:bloque:your-origin:user-alias');
103
+ const organization = await userSession.orgs.create(params);
83
104
  console.log('Organization created:', organization);
84
105
  }
85
-
86
- // Create a virtual card
87
- async function createCard() {
88
- const card = await bloque.accounts.card.create({
89
- urn: 'did:bloque:user:123e4567',
90
- name: 'My Virtual Card',
91
- });
92
-
93
- console.log('Card created:', card.urn);
94
- console.log('Last four digits:', card.lastFour);
95
- }
96
106
  ```
97
107
 
98
108
  ### Frontend (Browser, React Native)
@@ -175,6 +185,10 @@ const bloque = new SDK({
175
185
 
176
186
  ### Configuration Options
177
187
 
188
+ - **`origin`** (string, required): Your origin identifier/namespace
189
+ - This identifies your application or organization in the Bloque platform
190
+ - Example: `'my-app'`, `'bloque-root'`, `'ethereum-mainnet'`
191
+
178
192
  - **`auth`** (object, required): Authentication configuration
179
193
  - `type: 'apiKey'`: For backend platforms
180
194
  - `apiKey` (string, required): Your Bloque API key
@@ -195,6 +209,42 @@ const bloque = new SDK({
195
209
  - Browser automatically uses `localStorage` if not provided
196
210
  - Must implement: `get()`, `set(token)`, `clear()`
197
211
 
212
+ ### User Sessions with `connect()`
213
+
214
+ Most operations in the SDK require connecting to a user session first. This ensures proper authentication and authorization for user-specific operations.
215
+
216
+ ```typescript
217
+ // Initialize SDK
218
+ const bloque = new SDK({
219
+ origin: 'your-origin',
220
+ auth: {
221
+ type: 'apiKey',
222
+ apiKey: process.env.BLOQUE_API_KEY!,
223
+ },
224
+ mode: 'production',
225
+ });
226
+
227
+ // Connect to user session
228
+ const userSession = await bloque.connect('did:bloque:your-origin:user-alias');
229
+
230
+ // Now perform operations through the session
231
+ const card = await userSession.accounts.card.create({
232
+ urn: 'did:bloque:your-origin:user-alias',
233
+ name: 'My Card',
234
+ });
235
+ ```
236
+
237
+ **What `connect()` does:**
238
+ - Authenticates the user with the specified URN
239
+ - Obtains an access token for the user session
240
+ - Returns a session object with access to: `accounts`, `compliance`, `identity`, `orgs`
241
+
242
+ **URN Format:**
243
+ - Pattern: `did:bloque:{origin}:{user-alias}`
244
+ - Example: `did:bloque:my-app:john-doe`
245
+ - The `{origin}` must match the origin specified in SDK configuration
246
+ - The `{user-alias}` is the user's unique identifier in your origin
247
+
198
248
  ### Platform and Authentication Compatibility
199
249
 
200
250
  | Platform | API Key Auth | JWT Auth | Token Storage |
@@ -214,7 +264,11 @@ The organizations resource allows you to create and manage organizations in the
214
264
  #### Create an Organization
215
265
 
216
266
  ```typescript
217
- const organization = await bloque.orgs.create(params);
267
+ // Connect to user session first
268
+ const userSession = await bloque.connect('did:bloque:your-origin:user-alias');
269
+
270
+ // Create organization through the session
271
+ const organization = await userSession.orgs.create(params);
218
272
  ```
219
273
 
220
274
  **Parameters**:
@@ -278,8 +332,12 @@ The compliance resource provides KYC (Know Your Customer) verification functiona
278
332
  Start a KYC verification process for a user:
279
333
 
280
334
  ```typescript
281
- const verification = await bloque.compliance.kyc.startVerification({
282
- urn: 'did:bloque:origin:user-id',
335
+ // Connect to user session
336
+ const userSession = await bloque.connect('did:bloque:your-origin:user-alias');
337
+
338
+ // Start KYC verification
339
+ const verification = await userSession.compliance.kyc.startVerification({
340
+ urn: 'did:bloque:your-origin:user-alias',
283
341
  });
284
342
  ```
285
343
 
@@ -358,8 +416,12 @@ The accounts resource allows you to create virtual cards for users.
358
416
  Create a virtual card for a user:
359
417
 
360
418
  ```typescript
361
- const card = await bloque.accounts.card.create({
362
- urn: 'did:bloque:user:123e4567',
419
+ // Connect to user session
420
+ const userSession = await bloque.connect('did:bloque:your-origin:user-alias');
421
+
422
+ // Create virtual card
423
+ const card = await userSession.accounts.card.create({
424
+ urn: 'did:bloque:your-origin:user-alias',
363
425
  name: 'My Virtual Card', // Optional
364
426
  });
365
427
  ```
@@ -397,9 +459,263 @@ interface CardAccount {
397
459
  metadata?: Record<string, unknown>; // Custom metadata
398
460
  createdAt: string; // Creation timestamp (ISO 8601)
399
461
  updatedAt: string; // Last update timestamp (ISO 8601)
462
+ balance?: Record<string, TokenBalance>; // Token balances (only in list responses)
463
+ }
464
+
465
+ interface TokenBalance {
466
+ current: string; // Current balance
467
+ pending: string; // Pending balance
468
+ in: string; // Total incoming
469
+ out: string; // Total outgoing
470
+ }
471
+ ```
472
+
473
+ #### List Card Accounts
474
+
475
+ List all card accounts for a holder with their current balances:
476
+
477
+ ```typescript
478
+ // Using connected user session (recommended)
479
+ const userSession = await bloque.connect('did:bloque:your-origin:user-alias');
480
+ const cards = await userSession.accounts.card.list();
481
+
482
+ // Or with explicit holder URN
483
+ const cards = await bloque.accounts.card.list({
484
+ holderUrn: 'did:bloque:bloque-whatsapp:573023348486',
485
+ });
486
+ ```
487
+
488
+ **Parameters**:
489
+
490
+ ```typescript
491
+ interface ListCardParams {
492
+ /**
493
+ * URN of the account holder to filter by
494
+ * Optional when using a connected session - defaults to session URN
495
+ * @example "did:bloque:bloque-whatsapp:573023348486"
496
+ */
497
+ holderUrn?: string;
498
+ }
499
+ ```
500
+
501
+ **Response**: `Promise<CardAccount[]>` - Array of card accounts with balances
502
+
503
+ Each card in the response includes all standard fields plus a `balance` object containing token balances with current, pending, in, and out amounts for each token.
504
+
505
+ #### Get Card Balance
506
+
507
+ Get the current balance for a specific card account:
508
+
509
+ ```typescript
510
+ const balances = await bloque.accounts.card.balance({
511
+ urn: 'did:bloque:account:card:usr-123:crd-456',
512
+ });
513
+ ```
514
+
515
+ **Parameters**:
516
+
517
+ ```typescript
518
+ interface GetBalanceParams {
519
+ /**
520
+ * URN of the card account
521
+ * @example "did:bloque:account:card:usr-123:crd-456"
522
+ */
523
+ urn: string;
524
+ }
525
+ ```
526
+
527
+ **Response**: `Promise<Record<string, TokenBalance>>` - Token balances by asset
528
+
529
+ Returns an object with token balances for each asset:
530
+
531
+ ```typescript
532
+ {
533
+ 'DUSD/6': {
534
+ current: '1262500', // Current balance
535
+ pending: '0', // Pending balance
536
+ in: '5072000', // Total incoming
537
+ out: '3809500' // Total outgoing
538
+ },
539
+ 'KSM/12': {
540
+ current: '1989000011',
541
+ pending: '0',
542
+ in: '2000000000',
543
+ out: '10999989'
544
+ }
545
+ }
546
+ ```
547
+
548
+ #### List Card Movements
549
+
550
+ List transactions/movements for a card account with pagination and filtering:
551
+
552
+ ```typescript
553
+ // Basic usage
554
+ const movements = await bloque.accounts.card.movements({
555
+ urn: 'did:bloque:account:card:usr-123:crd-456',
556
+ asset: 'DUSD/6',
557
+ });
558
+
559
+ // With pagination and filters
560
+ const recentIncoming = await bloque.accounts.card.movements({
561
+ urn: 'did:bloque:account:card:usr-123:crd-456',
562
+ asset: 'DUSD/6',
563
+ limit: 50,
564
+ direction: 'in', // Only incoming transactions
565
+ after: '2025-01-01T00:00:00Z',
566
+ });
567
+ ```
568
+
569
+ **Parameters**:
570
+
571
+ ```typescript
572
+ interface ListMovementsParams {
573
+ /**
574
+ * URN of the card account
575
+ * @example "did:bloque:account:card:usr-123:crd-456"
576
+ */
577
+ urn: string;
578
+
579
+ /**
580
+ * Asset to filter transactions by
581
+ * Supported assets: 'DUSD/6' | 'KSM/12'
582
+ * Defaults to "DUSD/6" if not provided
583
+ * @example "DUSD/6" or "KSM/12"
584
+ */
585
+ asset?: 'DUSD/6' | 'KSM/12';
586
+
587
+ /**
588
+ * Maximum number of transactions to return
589
+ * @example 50
590
+ */
591
+ limit?: number;
592
+
593
+ /**
594
+ * Filter transactions before this date (ISO 8601)
595
+ * @example "2025-01-01T00:00:00Z"
596
+ */
597
+ before?: string;
598
+
599
+ /**
600
+ * Filter transactions after this date (ISO 8601)
601
+ * @example "2025-01-01T00:00:00Z"
602
+ */
603
+ after?: string;
604
+
605
+ /**
606
+ * Filter by transaction reference
607
+ * @example "0xbff43fa587e0efa275f8b643d95881713c0f0ee13682d049cc452f607241b752"
608
+ */
609
+ reference?: string;
610
+
611
+ /**
612
+ * Filter by transaction direction
613
+ * 'in' for incoming funds (deposits, transfers received)
614
+ * 'out' for outgoing funds (withdrawals, transfers sent)
615
+ */
616
+ direction?: 'in' | 'out';
617
+ }
618
+ ```
619
+
620
+ **Response**: `Promise<CardMovement[]>` - Array of card transactions
621
+
622
+ Each movement includes:
623
+
624
+ ```typescript
625
+ interface CardMovement {
626
+ amount: string; // Transaction amount
627
+ asset: string; // Asset identifier (e.g., "DUSD/6")
628
+ from_account_id: string; // Source account ID
629
+ to_account_id: string; // Destination account ID
630
+ direction: 'in' | 'out'; // Transaction direction
631
+ reference: string; // Blockchain transaction reference
632
+ rail_name: string; // Payment rail used
633
+ created_at: string; // Transaction timestamp (ISO 8601)
634
+
635
+ details: {
636
+ type: string; // Transaction type (e.g., "CREDIT_ADJUSTMENT")
637
+ metadata: {
638
+ // Transaction details
639
+ merchant_name?: string;
640
+ merchant_city?: string;
641
+ merchant_country?: string;
642
+ transaction_type?: string;
643
+ local_amount?: string;
644
+ local_currency?: string;
645
+ usd_amount?: string;
646
+ card_last_four?: string;
647
+ // ... and more
648
+ };
649
+ };
650
+ }
651
+ ```
652
+
653
+ #### Transfer Between Accounts
654
+
655
+ Transfer funds between any accounts (card, virtual, bancolombia, etc.):
656
+
657
+ ```typescript
658
+ const transfer = await bloque.accounts.transfer({
659
+ sourceUrn: 'did:bloque:account:card:usr-123:crd-456',
660
+ destinationUrn: 'did:bloque:account:virtual:acc-67890',
661
+ amount: '1000000000000',
662
+ asset: 'KSM/12',
663
+ metadata: {
664
+ reference: 'payment-123',
665
+ note: 'Monthly subscription'
666
+ }
667
+ });
668
+ ```
669
+
670
+ **Parameters**:
671
+
672
+ ```typescript
673
+ interface TransferParams {
674
+ /**
675
+ * URN of the source account
676
+ * @example "did:bloque:account:card:usr-123:crd-456"
677
+ */
678
+ sourceUrn: string;
679
+
680
+ /**
681
+ * URN of the destination account
682
+ * @example "did:bloque:account:virtual:acc-67890"
683
+ */
684
+ destinationUrn: string;
685
+
686
+ /**
687
+ * Amount to transfer
688
+ * @example "1000000000000"
689
+ */
690
+ amount: string;
691
+
692
+ /**
693
+ * Asset to transfer
694
+ * Supported assets: 'DUSD/6' | 'KSM/12'
695
+ * @example "KSM/12"
696
+ */
697
+ asset: 'DUSD/6' | 'KSM/12';
698
+
699
+ /**
700
+ * Optional metadata for the transfer
701
+ * @example { reference: "payment-123", note: "Monthly subscription" }
702
+ */
703
+ metadata?: Record<string, unknown>;
704
+ }
705
+ ```
706
+
707
+ **Response**: `Promise<TransferResult>` - Transfer result
708
+
709
+ ```typescript
710
+ interface TransferResult {
711
+ queueId: string; // Queue ID for tracking the transfer
712
+ status: 'queued' | 'processing' | 'completed' | 'failed';
713
+ message: string; // Status message
400
714
  }
401
715
  ```
402
716
 
717
+ The transfer is queued for signing and submission. You can track its progress using the returned `queueId`.
718
+
403
719
  ### Identity
404
720
 
405
721
  The identity resource allows you to register identities, retrieve user aliases, and manage authentication origins.
@@ -830,6 +1146,337 @@ try {
830
1146
  }
831
1147
  ```
832
1148
 
1149
+ ### Listing Card Accounts
1150
+
1151
+ ```typescript
1152
+ import { SDK } from '@bloque/sdk';
1153
+
1154
+ const bloque = new SDK({
1155
+ origin: 'your-origin',
1156
+ auth: {
1157
+ type: 'apiKey',
1158
+ apiKey: process.env.BLOQUE_API_KEY!,
1159
+ },
1160
+ mode: 'production',
1161
+ });
1162
+
1163
+ // Connect to user session
1164
+ const userSession = await bloque.connect('did:bloque:bloque-whatsapp:573023348486');
1165
+
1166
+ // List all cards for the connected user
1167
+ try {
1168
+ const cards = await userSession.accounts.card.list();
1169
+
1170
+ console.log(`Found ${cards.length} card accounts`);
1171
+
1172
+ cards.forEach((card) => {
1173
+ console.log('\n---');
1174
+ console.log('Card URN:', card.urn);
1175
+ console.log('Last Four:', card.lastFour);
1176
+ console.log('Status:', card.status);
1177
+ console.log('Card Name:', card.metadata?.name);
1178
+
1179
+ // Display balances
1180
+ if (card.balance) {
1181
+ console.log('Balances:');
1182
+ Object.entries(card.balance).forEach(([token, balance]) => {
1183
+ console.log(` ${token}:`);
1184
+ console.log(` Current: ${balance.current}`);
1185
+ console.log(` Pending: ${balance.pending}`);
1186
+ console.log(` In: ${balance.in}`);
1187
+ console.log(` Out: ${balance.out}`);
1188
+ });
1189
+ }
1190
+ });
1191
+
1192
+ // Find active cards only
1193
+ const activeCards = cards.filter(card => card.status === 'active');
1194
+ console.log(`\n${activeCards.length} cards are active`);
1195
+
1196
+ // Calculate total balance across all cards
1197
+ const totalBalances: Record<string, bigint> = {};
1198
+
1199
+ activeCards.forEach(card => {
1200
+ if (card.balance) {
1201
+ Object.entries(card.balance).forEach(([token, balance]) => {
1202
+ if (!totalBalances[token]) {
1203
+ totalBalances[token] = BigInt(0);
1204
+ }
1205
+ totalBalances[token] += BigInt(balance.current);
1206
+ });
1207
+ }
1208
+ });
1209
+
1210
+ console.log('\nTotal balances across all active cards:');
1211
+ Object.entries(totalBalances).forEach(([token, total]) => {
1212
+ console.log(` ${token}: ${total.toString()}`);
1213
+ });
1214
+ } catch (error) {
1215
+ console.error('Failed to list cards:', error);
1216
+ }
1217
+ ```
1218
+
1219
+ ### Getting Card Balance
1220
+
1221
+ ```typescript
1222
+ import { SDK } from '@bloque/sdk';
1223
+
1224
+ const bloque = new SDK({
1225
+ origin: 'your-origin',
1226
+ auth: {
1227
+ type: 'apiKey',
1228
+ apiKey: process.env.BLOQUE_API_KEY!,
1229
+ },
1230
+ mode: 'production',
1231
+ });
1232
+
1233
+ // Get balance for a specific card
1234
+ try {
1235
+ const balances = await bloque.accounts.card.balance({
1236
+ urn: 'did:bloque:account:card:usr-123:crd-456',
1237
+ });
1238
+
1239
+ console.log('Card Balances:\n');
1240
+
1241
+ Object.entries(balances).forEach(([token, balance]) => {
1242
+ console.log(`${token}:`);
1243
+ console.log(` Current: ${balance.current}`);
1244
+ console.log(` Pending: ${balance.pending}`);
1245
+ console.log(` Total In: ${balance.in}`);
1246
+ console.log(` Total Out: ${balance.out}`);
1247
+
1248
+ const net = BigInt(balance.in) - BigInt(balance.out);
1249
+ console.log(` Net: ${net.toString()}`);
1250
+ console.log('');
1251
+ });
1252
+
1253
+ // Calculate total current balance across all assets
1254
+ const totalCurrent = Object.entries(balances).reduce(
1255
+ (acc, [token, balance]) => {
1256
+ acc[token] = BigInt(balance.current);
1257
+ return acc;
1258
+ },
1259
+ {} as Record<string, bigint>,
1260
+ );
1261
+
1262
+ console.log('Total Current Balances:');
1263
+ Object.entries(totalCurrent).forEach(([token, amount]) => {
1264
+ console.log(` ${token}: ${amount.toString()}`);
1265
+ });
1266
+ } catch (error) {
1267
+ console.error('Failed to get balance:', error);
1268
+ }
1269
+ ```
1270
+
1271
+ ### Listing Card Movements
1272
+
1273
+ ```typescript
1274
+ import { SDK } from '@bloque/sdk';
1275
+
1276
+ const bloque = new SDK({
1277
+ origin: 'your-origin',
1278
+ auth: {
1279
+ type: 'apiKey',
1280
+ apiKey: process.env.BLOQUE_API_KEY!,
1281
+ },
1282
+ mode: 'production',
1283
+ });
1284
+
1285
+ // List recent transactions with pagination
1286
+ try {
1287
+ const movements = await bloque.accounts.card.movements({
1288
+ urn: 'did:bloque:account:card:usr-123:crd-456',
1289
+ asset: 'DUSD/6',
1290
+ limit: 50,
1291
+ direction: 'in', // Only incoming transactions
1292
+ after: '2025-01-01T00:00:00Z',
1293
+ });
1294
+
1295
+ console.log(`Found ${movements.length} incoming transactions\n`);
1296
+
1297
+ movements.forEach((transaction) => {
1298
+ console.log('---');
1299
+ console.log(`Amount: ${transaction.amount} ${transaction.asset}`);
1300
+ console.log(`Direction: ${transaction.direction.toUpperCase()}`);
1301
+ console.log(`Date: ${transaction.created_at}`);
1302
+ console.log(`Reference: ${transaction.reference}`);
1303
+
1304
+ // Show merchant details if available
1305
+ if (transaction.details?.metadata) {
1306
+ const meta = transaction.details.metadata;
1307
+ if (meta.merchant_name) {
1308
+ console.log(`Merchant: ${meta.merchant_name}`);
1309
+ }
1310
+ if (meta.merchant_city && meta.merchant_country) {
1311
+ console.log(`Location: ${meta.merchant_city}, ${meta.merchant_country}`);
1312
+ }
1313
+ if (meta.transaction_type) {
1314
+ console.log(`Type: ${meta.transaction_type}`);
1315
+ }
1316
+ if (meta.usd_amount) {
1317
+ console.log(`USD Amount: $${meta.usd_amount}`);
1318
+ }
1319
+ }
1320
+ console.log('');
1321
+ });
1322
+
1323
+ // Calculate total
1324
+ const total = movements.reduce(
1325
+ (sum, t) => sum + BigInt(t.amount),
1326
+ BigInt(0),
1327
+ );
1328
+
1329
+ console.log(`Total received: ${total.toString()}`);
1330
+ } catch (error) {
1331
+ console.error('Failed to list movements:', error);
1332
+ }
1333
+ ```
1334
+
1335
+ ### Paginating Through Card Movements
1336
+
1337
+ ```typescript
1338
+ import { SDK } from '@bloque/sdk';
1339
+
1340
+ const bloque = new SDK({
1341
+ origin: 'your-origin',
1342
+ auth: {
1343
+ type: 'apiKey',
1344
+ apiKey: process.env.BLOQUE_API_KEY!,
1345
+ },
1346
+ mode: 'production',
1347
+ });
1348
+
1349
+ // Paginate through all transactions
1350
+ async function getAllTransactions() {
1351
+ const cardUrn = 'did:bloque:account:card:usr-123:crd-456';
1352
+ const pageSize = 100;
1353
+ let allMovements = [];
1354
+ let hasMore = true;
1355
+ let lastDate: string | undefined;
1356
+
1357
+ try {
1358
+ while (hasMore) {
1359
+ const movements = await bloque.accounts.card.movements({
1360
+ urn: cardUrn,
1361
+ asset: 'DUSD/6',
1362
+ limit: pageSize,
1363
+ before: lastDate, // Get transactions before the last one we saw
1364
+ });
1365
+
1366
+ allMovements.push(...movements);
1367
+ console.log(`Fetched ${movements.length} transactions`);
1368
+
1369
+ if (movements.length < pageSize) {
1370
+ hasMore = false; // Last page
1371
+ } else {
1372
+ lastDate = movements[movements.length - 1].created_at;
1373
+ }
1374
+ }
1375
+
1376
+ console.log(`\nTotal transactions: ${allMovements.length}`);
1377
+
1378
+ // Analyze all transactions
1379
+ const totalIn = allMovements
1380
+ .filter((t) => t.direction === 'in')
1381
+ .reduce((sum, t) => sum + BigInt(t.amount), BigInt(0));
1382
+
1383
+ const totalOut = allMovements
1384
+ .filter((t) => t.direction === 'out')
1385
+ .reduce((sum, t) => sum + BigInt(t.amount), BigInt(0));
1386
+
1387
+ console.log(`Total incoming: ${totalIn.toString()}`);
1388
+ console.log(`Total outgoing: ${totalOut.toString()}`);
1389
+ console.log(`Net balance: ${(totalIn - totalOut).toString()}`);
1390
+ } catch (error) {
1391
+ console.error('Error:', error);
1392
+ }
1393
+ }
1394
+
1395
+ getAllTransactions();
1396
+ ```
1397
+
1398
+ ### Transferring Funds Between Accounts
1399
+
1400
+ ```typescript
1401
+ import { SDK } from '@bloque/sdk';
1402
+
1403
+ const bloque = new SDK({
1404
+ origin: 'your-origin',
1405
+ auth: {
1406
+ type: 'apiKey',
1407
+ apiKey: process.env.BLOQUE_API_KEY!,
1408
+ },
1409
+ mode: 'production',
1410
+ });
1411
+
1412
+ // Transfer from card to virtual account
1413
+ try {
1414
+ const transfer = await bloque.accounts.transfer({
1415
+ sourceUrn: 'did:bloque:account:card:usr-123:crd-456',
1416
+ destinationUrn: 'did:bloque:account:virtual:acc-67890',
1417
+ amount: '1000000000000',
1418
+ asset: 'KSM/12',
1419
+ metadata: {
1420
+ reference: 'payment-123',
1421
+ note: 'Monthly subscription payment'
1422
+ }
1423
+ });
1424
+
1425
+ console.log('Transfer initiated:');
1426
+ console.log(' Queue ID:', transfer.queueId);
1427
+ console.log(' Status:', transfer.status);
1428
+ console.log(' Message:', transfer.message);
1429
+
1430
+ // The transfer is now queued for processing
1431
+ // You can track its status using the queueId
1432
+ } catch (error) {
1433
+ console.error('Transfer failed:', error);
1434
+ }
1435
+ ```
1436
+
1437
+ ### Different Transfer Scenarios
1438
+
1439
+ ```typescript
1440
+ import { SDK } from '@bloque/sdk';
1441
+
1442
+ const bloque = new SDK({
1443
+ origin: 'your-origin',
1444
+ auth: {
1445
+ type: 'apiKey',
1446
+ apiKey: process.env.BLOQUE_API_KEY!,
1447
+ },
1448
+ mode: 'production',
1449
+ });
1450
+
1451
+ // Transfer DUSD from card to Bancolombia account
1452
+ const dusdTransfer = await bloque.accounts.transfer({
1453
+ sourceUrn: 'did:bloque:account:card:usr-123:crd-456',
1454
+ destinationUrn: 'did:bloque:account:bancolombia:acc-12345',
1455
+ amount: '5000000', // 5 DUSD (6 decimals)
1456
+ asset: 'DUSD/6',
1457
+ metadata: {
1458
+ reference: 'withdrawal-001',
1459
+ type: 'savings'
1460
+ }
1461
+ });
1462
+
1463
+ console.log(`DUSD transfer queued: ${dusdTransfer.queueId}`);
1464
+
1465
+ // Transfer KSM between virtual accounts
1466
+ const ksmTransfer = await bloque.accounts.transfer({
1467
+ sourceUrn: 'did:bloque:account:virtual:acc-11111',
1468
+ destinationUrn: 'did:bloque:account:virtual:acc-22222',
1469
+ amount: '2000000000000', // 2 KSM (12 decimals)
1470
+ asset: 'KSM/12',
1471
+ metadata: {
1472
+ reference: 'internal-transfer-42',
1473
+ department: 'operations'
1474
+ }
1475
+ });
1476
+
1477
+ console.log(`KSM transfer queued: ${ksmTransfer.queueId}`);
1478
+ ```
1479
+
833
1480
  ### Retrieving User Alias Information
834
1481
 
835
1482
  ```typescript
@@ -1152,7 +1799,14 @@ import type {
1152
1799
  // Accounts types
1153
1800
  import type {
1154
1801
  CardAccount,
1802
+ CardMovement,
1155
1803
  CreateCardParams,
1804
+ GetBalanceParams,
1805
+ ListCardParams,
1806
+ ListMovementsParams,
1807
+ TokenBalance,
1808
+ TransferParams,
1809
+ TransferResult,
1156
1810
  } from '@bloque/sdk/accounts';
1157
1811
 
1158
1812
  // Identity types
package/dist/bloque.d.ts CHANGED
@@ -5,9 +5,12 @@ import { IdentityClient } from '@bloque/sdk-identity';
5
5
  import { OrgsClient } from '@bloque/sdk-orgs';
6
6
  export declare class SDK {
7
7
  private readonly httpClient;
8
- readonly accounts: AccountsClient;
9
- readonly compliance: ComplianceClient;
10
- readonly identity: IdentityClient;
11
- readonly orgs: OrgsClient;
12
8
  constructor(config: BloqueConfig);
9
+ private extractUserAlias;
10
+ connect(urn: string): Promise<{
11
+ accounts: AccountsClient;
12
+ compliance: ComplianceClient;
13
+ identity: IdentityClient;
14
+ orgs: OrgsClient;
15
+ }>;
13
16
  }
package/dist/index.cjs CHANGED
@@ -1 +1 @@
1
- "use strict";const __rslib_import_meta_url__="u"<typeof document?new(require("url".replace("",""))).URL("file:"+__filename).href:document.currentScript&&document.currentScript.src||new URL("main.js",document.baseURI).href;var __webpack_require__={};__webpack_require__.d=(e,_)=>{for(var t in _)__webpack_require__.o(_,t)&&!__webpack_require__.o(e,t)&&Object.defineProperty(e,t,{enumerable:!0,get:_[t]})},__webpack_require__.o=(e,_)=>Object.prototype.hasOwnProperty.call(e,_),__webpack_require__.r=e=>{"u">typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})};var __webpack_exports__={};__webpack_require__.r(__webpack_exports__),__webpack_require__.d(__webpack_exports__,{SDK:()=>SDK});const sdk_accounts_namespaceObject=require("@bloque/sdk-accounts"),sdk_compliance_namespaceObject=require("@bloque/sdk-compliance"),sdk_core_namespaceObject=require("@bloque/sdk-core"),sdk_identity_namespaceObject=require("@bloque/sdk-identity"),sdk_orgs_namespaceObject=require("@bloque/sdk-orgs");class SDK{httpClient;accounts;compliance;identity;orgs;constructor(e){this.httpClient=new sdk_core_namespaceObject.HttpClient(e),this.accounts=new sdk_accounts_namespaceObject.AccountsClient(this.httpClient),this.compliance=new sdk_compliance_namespaceObject.ComplianceClient(this.httpClient),this.identity=new sdk_identity_namespaceObject.IdentityClient(this.httpClient),this.orgs=new sdk_orgs_namespaceObject.OrgsClient(this.httpClient)}}for(var __rspack_i in exports.SDK=__webpack_exports__.SDK,__webpack_exports__)-1===["SDK"].indexOf(__rspack_i)&&(exports[__rspack_i]=__webpack_exports__[__rspack_i]);Object.defineProperty(exports,"__esModule",{value:!0});
1
+ "use strict";const __rslib_import_meta_url__="u"<typeof document?new(require("url".replace("",""))).URL("file:"+__filename).href:document.currentScript&&document.currentScript.src||new URL("main.js",document.baseURI).href;var __webpack_require__={};__webpack_require__.d=(e,t)=>{for(var _ in t)__webpack_require__.o(t,_)&&!__webpack_require__.o(e,_)&&Object.defineProperty(e,_,{enumerable:!0,get:t[_]})},__webpack_require__.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),__webpack_require__.r=e=>{"u">typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})};var __webpack_exports__={};__webpack_require__.r(__webpack_exports__),__webpack_require__.d(__webpack_exports__,{SDK:()=>SDK});const sdk_accounts_namespaceObject=require("@bloque/sdk-accounts"),sdk_compliance_namespaceObject=require("@bloque/sdk-compliance"),sdk_core_namespaceObject=require("@bloque/sdk-core"),sdk_identity_namespaceObject=require("@bloque/sdk-identity"),sdk_orgs_namespaceObject=require("@bloque/sdk-orgs");class SDK{httpClient;constructor(e){this.httpClient=new sdk_core_namespaceObject.HttpClient(e)}extractUserAlias(e){let t=e.match(/^did:bloque:[^:]+:([^:]+)$/);if(!t)throw Error(`Invalid user alias URN: ${e}`);return t[1]}async connect(e){let t=this.httpClient.config;t.urn=e;let _=await this.httpClient.request({path:`/api/origins/${t.origin}/connect`,method:"POST",body:{assertion_result:{challengeType:"API_KEY",value:{api_key:"apiKey"===t.auth.type?t.auth.apiKey:"",alias:this.extractUserAlias(e)}},extra_context:{}}});return t.accessToken=_.result.access_token,{accounts:new sdk_accounts_namespaceObject.AccountsClient(this.httpClient),compliance:new sdk_compliance_namespaceObject.ComplianceClient(this.httpClient),identity:new sdk_identity_namespaceObject.IdentityClient(this.httpClient),orgs:new sdk_orgs_namespaceObject.OrgsClient(this.httpClient)}}}for(var __rspack_i in exports.SDK=__webpack_exports__.SDK,__webpack_exports__)-1===["SDK"].indexOf(__rspack_i)&&(exports[__rspack_i]=__webpack_exports__[__rspack_i]);Object.defineProperty(exports,"__esModule",{value:!0});
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- import{AccountsClient as t}from"@bloque/sdk-accounts";import{ComplianceClient as i}from"@bloque/sdk-compliance";import{HttpClient as o}from"@bloque/sdk-core";import{IdentityClient as e}from"@bloque/sdk-identity";import{OrgsClient as s}from"@bloque/sdk-orgs";class n{httpClient;accounts;compliance;identity;orgs;constructor(n){this.httpClient=new o(n),this.accounts=new t(this.httpClient),this.compliance=new i(this.httpClient),this.identity=new e(this.httpClient),this.orgs=new s(this.httpClient)}}export{n as SDK};
1
+ import{AccountsClient as t}from"@bloque/sdk-accounts";import{ComplianceClient as e}from"@bloque/sdk-compliance";import{HttpClient as i}from"@bloque/sdk-core";import{IdentityClient as o}from"@bloque/sdk-identity";import{OrgsClient as s}from"@bloque/sdk-orgs";class n{httpClient;constructor(t){this.httpClient=new i(t)}extractUserAlias(t){let e=t.match(/^did:bloque:[^:]+:([^:]+)$/);if(!e)throw Error(`Invalid user alias URN: ${t}`);return e[1]}async connect(i){let n=this.httpClient.config;n.urn=i;let r=await this.httpClient.request({path:`/api/origins/${n.origin}/connect`,method:"POST",body:{assertion_result:{challengeType:"API_KEY",value:{api_key:"apiKey"===n.auth.type?n.auth.apiKey:"",alias:this.extractUserAlias(i)}},extra_context:{}}});return n.accessToken=r.result.access_token,{accounts:new t(this.httpClient),compliance:new e(this.httpClient),identity:new o(this.httpClient),orgs:new s(this.httpClient)}}}export{n as SDK};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bloque/sdk",
3
- "version": "0.0.21",
3
+ "version": "0.0.23",
4
4
  "description": "Official Bloque SDK",
5
5
  "type": "module",
6
6
  "keywords": [
@@ -63,10 +63,10 @@
63
63
  "node": ">=22"
64
64
  },
65
65
  "dependencies": {
66
- "@bloque/sdk-accounts": "0.0.21",
67
- "@bloque/sdk-compliance": "0.0.21",
68
- "@bloque/sdk-core": "0.0.21",
69
- "@bloque/sdk-identity": "0.0.21",
70
- "@bloque/sdk-orgs": "0.0.21"
66
+ "@bloque/sdk-accounts": "0.0.23",
67
+ "@bloque/sdk-compliance": "0.0.23",
68
+ "@bloque/sdk-core": "0.0.23",
69
+ "@bloque/sdk-identity": "0.0.23",
70
+ "@bloque/sdk-orgs": "0.0.23"
71
71
  }
72
72
  }