@bloque/sdk 0.0.23 → 0.0.24
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 +469 -1664
- package/dist/bloque.d.ts +14 -5
- package/dist/config.d.ts +3 -3
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/init.d.ts +2 -2
- package/package.json +6 -6
package/README.md
CHANGED
|
@@ -15,7 +15,7 @@ The official TypeScript/JavaScript SDK for integrating [Bloque](https://www.bloq
|
|
|
15
15
|
> }
|
|
16
16
|
> ```
|
|
17
17
|
>
|
|
18
|
-
> Replace
|
|
18
|
+
> Replace with the latest version from [npm](https://www.npmjs.com/package/@bloque/sdk).
|
|
19
19
|
|
|
20
20
|
## Platform Support
|
|
21
21
|
|
|
@@ -25,24 +25,40 @@ This SDK is compatible with multiple JavaScript runtimes:
|
|
|
25
25
|
- **Bun** 1.x or higher
|
|
26
26
|
- **Deno** Latest version
|
|
27
27
|
- **Web/Browsers** Modern browsers with ES2020+ support
|
|
28
|
+
- **React Native** Latest version
|
|
28
29
|
|
|
29
30
|
## Features
|
|
30
31
|
|
|
31
32
|
- **TypeScript First**: Built with TypeScript for complete type safety
|
|
32
|
-
- **
|
|
33
|
-
- **
|
|
34
|
-
- **
|
|
35
|
-
- **
|
|
36
|
-
- **
|
|
33
|
+
- **Modular Architecture**: Import only what you need - accounts, identity, compliance, or organizations
|
|
34
|
+
- **Multi-Runtime**: Works seamlessly across Node.js, Bun, Deno, browsers, and React Native
|
|
35
|
+
- **Account Management**: Create and manage virtual cards, virtual accounts, and Bancolombia accounts
|
|
36
|
+
- **Identity System**: Register individual users (KYC) and businesses (KYB) with multi-method authentication
|
|
37
|
+
- **Compliance Ready**: Built-in KYC/KYB verification workflows
|
|
38
|
+
- **Transfer System**: Transfer funds between accounts with multiple asset support
|
|
39
|
+
- **Production Ready**:
|
|
40
|
+
- ✅ Automatic retry with exponential backoff
|
|
41
|
+
- ✅ Configurable timeouts (default: 30s)
|
|
42
|
+
- ✅ Specific error types for better error handling
|
|
43
|
+
- ✅ Request ID tracking for debugging
|
|
44
|
+
- ✅ Security warnings for insecure practices
|
|
37
45
|
- **Lightweight**: Minimal dependencies for optimal bundle size
|
|
38
|
-
- **
|
|
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.
|
|
46
|
+
- **Fully Async**: Promise-based API for modern JavaScript workflows
|
|
41
47
|
|
|
42
48
|
## Installation
|
|
43
49
|
|
|
44
50
|
```bash
|
|
51
|
+
# npm
|
|
52
|
+
npm install @bloque/sdk
|
|
53
|
+
|
|
54
|
+
# bun
|
|
45
55
|
bun add @bloque/sdk
|
|
56
|
+
|
|
57
|
+
# pnpm
|
|
58
|
+
pnpm add @bloque/sdk
|
|
59
|
+
|
|
60
|
+
# yarn
|
|
61
|
+
yarn add @bloque/sdk
|
|
46
62
|
```
|
|
47
63
|
|
|
48
64
|
## Quick Start
|
|
@@ -51,58 +67,34 @@ bun add @bloque/sdk
|
|
|
51
67
|
|
|
52
68
|
```typescript
|
|
53
69
|
import { SDK } from '@bloque/sdk';
|
|
54
|
-
import type { CreateOrgParams } from '@bloque/sdk/orgs';
|
|
55
70
|
|
|
56
71
|
// Initialize the SDK with API key (backend only)
|
|
57
72
|
const bloque = new SDK({
|
|
58
|
-
origin: 'your-origin-name',
|
|
73
|
+
origin: 'your-origin-name',
|
|
59
74
|
auth: {
|
|
60
75
|
type: 'apiKey',
|
|
61
76
|
apiKey: process.env.BLOQUE_API_KEY!,
|
|
62
77
|
},
|
|
63
78
|
mode: 'production', // or 'sandbox' for testing
|
|
64
79
|
platform: 'node', // optional: 'node' | 'bun' | 'deno'
|
|
80
|
+
timeout: 30000, // optional: request timeout in ms
|
|
81
|
+
retry: { // optional: retry configuration
|
|
82
|
+
enabled: true,
|
|
83
|
+
maxRetries: 3,
|
|
84
|
+
initialDelay: 1000,
|
|
85
|
+
},
|
|
65
86
|
});
|
|
66
87
|
|
|
67
|
-
// Connect to user session
|
|
68
|
-
|
|
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
|
-
}
|
|
88
|
+
// Connect to user session
|
|
89
|
+
const session = await bloque.connect('did:bloque:your-origin:user-alias');
|
|
81
90
|
|
|
82
|
-
// Create
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
profile: {
|
|
87
|
-
legal_name: 'Acme Corporation',
|
|
88
|
-
tax_id: '123456789',
|
|
89
|
-
incorporation_date: '2020-01-01',
|
|
90
|
-
business_type: 'llc',
|
|
91
|
-
incorporation_country_code: 'US',
|
|
92
|
-
incorporation_state: 'CA',
|
|
93
|
-
address_line1: '123 Main St',
|
|
94
|
-
postal_code: '12345',
|
|
95
|
-
city: 'San Francisco',
|
|
96
|
-
},
|
|
97
|
-
metadata: {
|
|
98
|
-
source: 'api',
|
|
99
|
-
},
|
|
100
|
-
};
|
|
91
|
+
// Create a virtual card
|
|
92
|
+
const card = await session.accounts.card.create({
|
|
93
|
+
name: 'My Virtual Card',
|
|
94
|
+
});
|
|
101
95
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
console.log('Organization created:', organization);
|
|
105
|
-
}
|
|
96
|
+
console.log('Card created:', card.urn);
|
|
97
|
+
console.log('Last four digits:', card.lastFour);
|
|
106
98
|
```
|
|
107
99
|
|
|
108
100
|
### Frontend (Browser, React Native)
|
|
@@ -112,1766 +104,579 @@ import { SDK } from '@bloque/sdk';
|
|
|
112
104
|
|
|
113
105
|
// Initialize the SDK with JWT authentication
|
|
114
106
|
const bloque = new SDK({
|
|
107
|
+
origin: 'your-origin-name',
|
|
115
108
|
auth: { type: 'jwt' },
|
|
116
109
|
mode: 'production',
|
|
117
110
|
platform: 'browser', // or 'react-native'
|
|
118
|
-
//
|
|
119
|
-
//
|
|
111
|
+
// For browser: uses localStorage by default (with security warning)
|
|
112
|
+
// For react-native: provide custom tokenStorage
|
|
113
|
+
tokenStorage: {
|
|
114
|
+
get: () => {
|
|
115
|
+
// Your secure storage implementation
|
|
116
|
+
return AsyncStorage.getItem('bloque_token');
|
|
117
|
+
},
|
|
118
|
+
set: (token) => {
|
|
119
|
+
AsyncStorage.setItem('bloque_token', token);
|
|
120
|
+
},
|
|
121
|
+
clear: () => {
|
|
122
|
+
AsyncStorage.removeItem('bloque_token');
|
|
123
|
+
},
|
|
124
|
+
},
|
|
120
125
|
});
|
|
121
126
|
|
|
122
|
-
//
|
|
123
|
-
const result = await bloque.identity.origins.register(
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
127
|
+
// Register a new user
|
|
128
|
+
const result = await bloque.identity.origins.register(
|
|
129
|
+
'did:bloque:your-origin:ethereum-mainnet',
|
|
130
|
+
{
|
|
131
|
+
assertionResult: { /* signing challenge result */ },
|
|
132
|
+
type: 'individual',
|
|
133
|
+
profile: {
|
|
134
|
+
firstName: 'John',
|
|
135
|
+
lastName: 'Doe',
|
|
136
|
+
email: 'john@example.com',
|
|
137
|
+
},
|
|
138
|
+
}
|
|
139
|
+
);
|
|
128
140
|
|
|
129
|
-
// The
|
|
130
|
-
const alias = await bloque.identity.aliases.get('user@example.com');
|
|
141
|
+
// The JWT is automatically stored and used for subsequent requests
|
|
131
142
|
```
|
|
132
143
|
|
|
133
144
|
## Configuration
|
|
134
145
|
|
|
135
|
-
###
|
|
136
|
-
|
|
137
|
-
The SDK supports different authentication methods depending on where it's running:
|
|
138
|
-
|
|
139
|
-
#### Backend Configuration (API Key)
|
|
140
|
-
|
|
141
|
-
For server-side applications (Node.js, Bun, Deno):
|
|
146
|
+
### Full Configuration Options
|
|
142
147
|
|
|
143
148
|
```typescript
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
auth:
|
|
148
|
-
type: 'apiKey',
|
|
149
|
-
apiKey: process.env.BLOQUE_API_KEY!, // Your Bloque API key
|
|
150
|
-
},
|
|
151
|
-
mode: 'production', // 'sandbox' or 'production'
|
|
152
|
-
platform: 'node', // optional: 'node' | 'bun' | 'deno' (defaults to 'node')
|
|
153
|
-
});
|
|
154
|
-
```
|
|
149
|
+
interface BloqueSDKConfig {
|
|
150
|
+
// Required
|
|
151
|
+
origin: string; // Your origin identifier
|
|
152
|
+
auth: AuthStrategy; // Authentication strategy
|
|
155
153
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
154
|
+
// Optional
|
|
155
|
+
platform?: Platform; // Runtime platform (default: 'node')
|
|
156
|
+
mode?: Mode; // Environment mode (default: 'production')
|
|
157
|
+
timeout?: number; // Request timeout in ms (default: 30000)
|
|
158
|
+
tokenStorage?: TokenStorage; // JWT storage (required for react-native)
|
|
159
|
+
retry?: RetryConfig; // Retry configuration
|
|
160
|
+
}
|
|
159
161
|
|
|
160
|
-
|
|
161
|
-
|
|
162
|
+
// Authentication strategies
|
|
163
|
+
type AuthStrategy =
|
|
164
|
+
| { type: 'apiKey'; apiKey: string } // Backend only
|
|
165
|
+
| { type: 'jwt' }; // Frontend (browser/react-native)
|
|
162
166
|
|
|
163
|
-
//
|
|
164
|
-
|
|
165
|
-
auth: { type: 'jwt' },
|
|
166
|
-
mode: 'production',
|
|
167
|
-
platform: 'browser',
|
|
168
|
-
// tokenStorage is optional - uses localStorage by default
|
|
169
|
-
});
|
|
167
|
+
// Platforms
|
|
168
|
+
type Platform = 'node' | 'bun' | 'deno' | 'browser' | 'react-native';
|
|
170
169
|
|
|
171
|
-
//
|
|
172
|
-
|
|
170
|
+
// Modes
|
|
171
|
+
type Mode = 'production' | 'sandbox';
|
|
173
172
|
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
clear: async () => await AsyncStorage.removeItem('access_token'),
|
|
182
|
-
},
|
|
183
|
-
});
|
|
173
|
+
// Retry configuration
|
|
174
|
+
interface RetryConfig {
|
|
175
|
+
enabled?: boolean; // default: true
|
|
176
|
+
maxRetries?: number; // default: 3
|
|
177
|
+
initialDelay?: number; // default: 1000ms
|
|
178
|
+
maxDelay?: number; // default: 30000ms
|
|
179
|
+
}
|
|
184
180
|
```
|
|
185
181
|
|
|
186
|
-
|
|
182
|
+
## SDK Structure
|
|
187
183
|
|
|
188
|
-
|
|
189
|
-
- This identifies your application or organization in the Bloque platform
|
|
190
|
-
- Example: `'my-app'`, `'bloque-root'`, `'ethereum-mainnet'`
|
|
184
|
+
After connecting to a user session, you have access to these clients:
|
|
191
185
|
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
- `apiKey` (string, required): Your Bloque API key
|
|
195
|
-
- `type: 'jwt'`: For frontend platforms
|
|
196
|
-
- Requires storing and managing JWT tokens via `tokenStorage`
|
|
197
|
-
|
|
198
|
-
- **`mode`** ('sandbox' | 'production', optional): Environment mode
|
|
199
|
-
- `sandbox`: For testing and development
|
|
200
|
-
- `production`: For live operations (default)
|
|
186
|
+
```typescript
|
|
187
|
+
const session = await bloque.connect('did:bloque:your-origin:user-alias');
|
|
201
188
|
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
189
|
+
// Available clients
|
|
190
|
+
session.accounts // Account management
|
|
191
|
+
session.identity // Identity and aliases
|
|
192
|
+
session.compliance // KYC/KYB verification
|
|
193
|
+
session.orgs // Organization management
|
|
194
|
+
```
|
|
206
195
|
|
|
207
|
-
|
|
208
|
-
- Required for JWT authentication on non-browser platforms
|
|
209
|
-
- Browser automatically uses `localStorage` if not provided
|
|
210
|
-
- Must implement: `get()`, `set(token)`, `clear()`
|
|
196
|
+
## Accounts Client
|
|
211
197
|
|
|
212
|
-
|
|
198
|
+
The accounts client provides access to multiple account types:
|
|
213
199
|
|
|
214
|
-
|
|
200
|
+
### Virtual Cards
|
|
215
201
|
|
|
216
202
|
```typescript
|
|
217
|
-
//
|
|
218
|
-
const
|
|
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',
|
|
203
|
+
// Create a virtual card
|
|
204
|
+
const card = await session.accounts.card.create({
|
|
233
205
|
name: 'My Card',
|
|
206
|
+
webhookUrl: 'https://your-app.com/webhooks/card',
|
|
234
207
|
});
|
|
235
|
-
```
|
|
236
208
|
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
- Obtains an access token for the user session
|
|
240
|
-
- Returns a session object with access to: `accounts`, `compliance`, `identity`, `orgs`
|
|
209
|
+
// List cards
|
|
210
|
+
const cards = await session.accounts.card.list();
|
|
241
211
|
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
- The `{user-alias}` is the user's unique identifier in your origin
|
|
247
|
-
|
|
248
|
-
### Platform and Authentication Compatibility
|
|
212
|
+
// Check balance
|
|
213
|
+
const balance = await session.accounts.card.balance({
|
|
214
|
+
urn: card.urn,
|
|
215
|
+
});
|
|
249
216
|
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
217
|
+
// Get movements/transactions
|
|
218
|
+
const movements = await session.accounts.card.movements({
|
|
219
|
+
urn: card.urn,
|
|
220
|
+
asset: 'DUSD/6',
|
|
221
|
+
limit: 50,
|
|
222
|
+
direction: 'in', // 'in' | 'out'
|
|
223
|
+
});
|
|
257
224
|
|
|
258
|
-
|
|
225
|
+
// Update card
|
|
226
|
+
const updated = await session.accounts.card.updateMetadata({
|
|
227
|
+
urn: card.urn,
|
|
228
|
+
metadata: { name: 'Updated Name' },
|
|
229
|
+
});
|
|
259
230
|
|
|
260
|
-
|
|
231
|
+
// Manage card state
|
|
232
|
+
await session.accounts.card.activate(card.urn);
|
|
233
|
+
await session.accounts.card.freeze(card.urn);
|
|
234
|
+
await session.accounts.card.disable(card.urn);
|
|
235
|
+
```
|
|
261
236
|
|
|
262
|
-
|
|
237
|
+
### Virtual Accounts
|
|
263
238
|
|
|
264
|
-
|
|
239
|
+
Virtual accounts are simple testing accounts requiring only basic personal information:
|
|
265
240
|
|
|
266
241
|
```typescript
|
|
267
|
-
//
|
|
268
|
-
const
|
|
242
|
+
// Create a virtual account
|
|
243
|
+
const account = await session.accounts.virtual.create({
|
|
244
|
+
firstName: 'John',
|
|
245
|
+
lastName: 'Doe',
|
|
246
|
+
metadata: {
|
|
247
|
+
environment: 'testing',
|
|
248
|
+
purpose: 'integration-test',
|
|
249
|
+
},
|
|
250
|
+
});
|
|
269
251
|
|
|
270
|
-
//
|
|
271
|
-
|
|
252
|
+
// Update metadata
|
|
253
|
+
await session.accounts.virtual.updateMetadata({
|
|
254
|
+
urn: account.urn,
|
|
255
|
+
metadata: { updated_by: 'admin' },
|
|
256
|
+
});
|
|
257
|
+
|
|
258
|
+
// Manage account state
|
|
259
|
+
await session.accounts.virtual.activate(account.urn);
|
|
260
|
+
await session.accounts.virtual.freeze(account.urn);
|
|
261
|
+
await session.accounts.virtual.disable(account.urn);
|
|
272
262
|
```
|
|
273
263
|
|
|
274
|
-
|
|
264
|
+
### Bancolombia Accounts
|
|
275
265
|
|
|
276
|
-
|
|
277
|
-
interface CreateOrgParams {
|
|
278
|
-
org_type: 'business' | 'individual'; // Organization type
|
|
279
|
-
profile: OrgProfile; // Organization profile details
|
|
280
|
-
metadata?: Record<string, unknown>; // Optional custom metadata
|
|
281
|
-
}
|
|
266
|
+
Colombian virtual accounts with unique reference code system:
|
|
282
267
|
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
incorporation_state?: string; // State/province (optional)
|
|
290
|
-
address_line1: string; // Primary address line
|
|
291
|
-
address_line2?: string; // Secondary address line (optional)
|
|
292
|
-
postal_code: string; // Postal/ZIP code
|
|
293
|
-
city: string; // City
|
|
294
|
-
logo_url?: string; // Logo URL (optional)
|
|
295
|
-
places?: Place[]; // Additional places/locations (optional)
|
|
296
|
-
}
|
|
268
|
+
```typescript
|
|
269
|
+
// Create a Bancolombia account
|
|
270
|
+
const account = await session.accounts.bancolombia.create({
|
|
271
|
+
name: 'Main Account',
|
|
272
|
+
webhookUrl: 'https://your-app.com/webhooks/bancolombia',
|
|
273
|
+
});
|
|
297
274
|
|
|
298
|
-
|
|
299
|
-
country_code: string; // Country code
|
|
300
|
-
state: string; // State/province
|
|
301
|
-
address_line1: string; // Address line 1
|
|
302
|
-
postal_code: string; // Postal code
|
|
303
|
-
city: string; // City
|
|
304
|
-
is_primary: boolean; // Whether this is the primary place
|
|
305
|
-
}
|
|
306
|
-
```
|
|
275
|
+
console.log('Reference code:', account.referenceCode);
|
|
307
276
|
|
|
308
|
-
|
|
277
|
+
// Update metadata or name
|
|
278
|
+
await session.accounts.bancolombia.updateMetadata({
|
|
279
|
+
urn: account.urn,
|
|
280
|
+
metadata: { category: 'savings' },
|
|
281
|
+
});
|
|
309
282
|
|
|
310
|
-
|
|
311
|
-
interface Organization {
|
|
312
|
-
urn: string; // Unique resource name
|
|
313
|
-
org_type: 'business' | 'individual'; // Organization type
|
|
314
|
-
profile: OrgProfile; // Organization profile
|
|
315
|
-
metadata?: Record<string, unknown>; // Custom metadata
|
|
316
|
-
status: OrgStatus; // Organization status
|
|
317
|
-
}
|
|
283
|
+
await session.accounts.bancolombia.updateName(account.urn, 'Savings Account');
|
|
318
284
|
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
| 'closed';
|
|
285
|
+
// Manage account state
|
|
286
|
+
await session.accounts.bancolombia.activate(account.urn);
|
|
287
|
+
await session.accounts.bancolombia.freeze(account.urn);
|
|
288
|
+
await session.accounts.bancolombia.disable(account.urn);
|
|
324
289
|
```
|
|
325
290
|
|
|
326
|
-
###
|
|
291
|
+
### Transfers
|
|
327
292
|
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
#### Start KYC Verification
|
|
331
|
-
|
|
332
|
-
Start a KYC verification process for a user:
|
|
293
|
+
Transfer funds between any account types:
|
|
333
294
|
|
|
334
295
|
```typescript
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
//
|
|
339
|
-
|
|
340
|
-
|
|
296
|
+
const result = await session.accounts.transfer({
|
|
297
|
+
sourceUrn: 'did:bloque:account:card:usr-123:crd-456',
|
|
298
|
+
destinationUrn: 'did:bloque:account:virtual:acc-789',
|
|
299
|
+
amount: '1000000', // Amount in smallest unit
|
|
300
|
+
asset: 'DUSD/6', // 'DUSD/6' | 'KSM/12'
|
|
301
|
+
metadata: {
|
|
302
|
+
description: 'Payment for services',
|
|
303
|
+
},
|
|
341
304
|
});
|
|
305
|
+
|
|
306
|
+
console.log('Transfer queued:', result.queueId);
|
|
307
|
+
console.log('Status:', result.status); // 'queued' | 'processing' | 'completed' | 'failed'
|
|
342
308
|
```
|
|
343
309
|
|
|
344
|
-
|
|
310
|
+
## Identity Client
|
|
311
|
+
|
|
312
|
+
Manage user identities and authentication:
|
|
345
313
|
|
|
346
314
|
```typescript
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
* URN (Uniform Resource Name) that uniquely identifies the user
|
|
350
|
-
* within the system. This value is used to associate the KYC
|
|
351
|
-
* verification process with a specific user.
|
|
352
|
-
*
|
|
353
|
-
* @example "did:bloque:origin:..."
|
|
354
|
-
*/
|
|
355
|
-
urn: string;
|
|
356
|
-
|
|
357
|
-
/**
|
|
358
|
-
* URL where webhook notifications will be sent when the verification
|
|
359
|
-
* status changes (optional).
|
|
360
|
-
*
|
|
361
|
-
* @example "https://api.example.com/webhooks/kyc"
|
|
362
|
-
*/
|
|
363
|
-
webhookUrl?: string;
|
|
364
|
-
}
|
|
365
|
-
```
|
|
315
|
+
// Get alias information
|
|
316
|
+
const alias = await session.identity.aliases.get('user@example.com');
|
|
366
317
|
|
|
367
|
-
|
|
318
|
+
// List available origins
|
|
319
|
+
const origins = await session.identity.origins.list();
|
|
368
320
|
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
321
|
+
// Register a new identity (individual)
|
|
322
|
+
const result = await bloque.identity.origins.register(
|
|
323
|
+
'did:bloque:your-origin:ethereum-mainnet',
|
|
324
|
+
{
|
|
325
|
+
assertionResult: {
|
|
326
|
+
alias: '0x742d35Cc...',
|
|
327
|
+
challengeType: 'SIGNING_CHALLENGE',
|
|
328
|
+
value: {
|
|
329
|
+
signature: '0x...',
|
|
330
|
+
alias: '0x742d35Cc...',
|
|
331
|
+
},
|
|
332
|
+
},
|
|
333
|
+
type: 'individual',
|
|
334
|
+
profile: {
|
|
335
|
+
firstName: 'John',
|
|
336
|
+
lastName: 'Doe',
|
|
337
|
+
email: 'john@example.com',
|
|
338
|
+
birthdate: '1990-01-15',
|
|
339
|
+
countryOfResidenceCode: 'US',
|
|
340
|
+
},
|
|
341
|
+
}
|
|
342
|
+
);
|
|
343
|
+
|
|
344
|
+
// Register a business
|
|
345
|
+
const businessResult = await bloque.identity.origins.register(
|
|
346
|
+
'did:bloque:your-origin:ethereum-mainnet',
|
|
347
|
+
{
|
|
348
|
+
assertionResult: { /* ... */ },
|
|
349
|
+
type: 'business',
|
|
350
|
+
profile: {
|
|
351
|
+
legalName: 'Acme Corporation',
|
|
352
|
+
taxId: '123456789',
|
|
353
|
+
incorporationDate: '2020-01-01',
|
|
354
|
+
type: 'llc',
|
|
355
|
+
addressLine1: '123 Main St',
|
|
356
|
+
city: 'San Francisco',
|
|
357
|
+
state: 'CA',
|
|
358
|
+
country: 'US',
|
|
359
|
+
postalCode: '12345',
|
|
360
|
+
// ... other required fields
|
|
361
|
+
},
|
|
362
|
+
}
|
|
363
|
+
);
|
|
364
|
+
|
|
365
|
+
// OTP-based authentication
|
|
366
|
+
const otpEmail = await bloque.identity.origins.email.assert('user@example.com');
|
|
367
|
+
const otpWhatsApp = await bloque.identity.origins.whatsapp.assert('+1234567890');
|
|
368
|
+
const otpCustom = await bloque.identity.origins.custom('my-origin').assert('user-id');
|
|
374
369
|
```
|
|
375
370
|
|
|
376
|
-
|
|
371
|
+
## Compliance Client
|
|
377
372
|
|
|
378
|
-
|
|
373
|
+
KYC/KYB verification workflows:
|
|
379
374
|
|
|
380
375
|
```typescript
|
|
381
|
-
|
|
376
|
+
// Start KYC verification
|
|
377
|
+
const verification = await session.compliance.kyc.startVerification({
|
|
382
378
|
urn: 'did:bloque:user:123e4567',
|
|
379
|
+
webhookUrl: 'https://your-app.com/webhooks/kyc',
|
|
383
380
|
});
|
|
384
|
-
```
|
|
385
381
|
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
```typescript
|
|
389
|
-
interface GetKycVerificationParams {
|
|
390
|
-
/**
|
|
391
|
-
* URN (Uniform Resource Name) that uniquely identifies the user
|
|
392
|
-
* within the system.
|
|
393
|
-
*
|
|
394
|
-
* @example "did:bloque:user:123e4567"
|
|
395
|
-
*/
|
|
396
|
-
urn: string;
|
|
397
|
-
}
|
|
398
|
-
```
|
|
382
|
+
console.log('Verification URL:', verification.url);
|
|
383
|
+
console.log('Status:', verification.status);
|
|
399
384
|
|
|
400
|
-
|
|
385
|
+
// Get verification status
|
|
386
|
+
const status = await session.compliance.kyc.getVerification({
|
|
387
|
+
urn: 'did:bloque:user:123e4567',
|
|
388
|
+
});
|
|
401
389
|
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
status: 'awaiting_compliance_verification' | 'approved' | 'rejected';
|
|
405
|
-
url: string; // URL for verification
|
|
406
|
-
completedAt: string | null; // Completion date (ISO 8601)
|
|
407
|
-
}
|
|
390
|
+
console.log('Status:', status.status);
|
|
391
|
+
console.log('Completed at:', status.completedAt);
|
|
408
392
|
```
|
|
409
393
|
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
The accounts resource allows you to create virtual cards for users.
|
|
394
|
+
## Organizations Client
|
|
413
395
|
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
Create a virtual card for a user:
|
|
396
|
+
Create and manage organizations:
|
|
417
397
|
|
|
418
398
|
```typescript
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
399
|
+
const org = await session.orgs.create({
|
|
400
|
+
org_type: 'business',
|
|
401
|
+
profile: {
|
|
402
|
+
legal_name: 'Acme Corporation',
|
|
403
|
+
tax_id: '123456789',
|
|
404
|
+
incorporation_date: '2020-01-01',
|
|
405
|
+
business_type: 'llc',
|
|
406
|
+
incorporation_country_code: 'US',
|
|
407
|
+
incorporation_state: 'CA',
|
|
408
|
+
address_line1: '123 Main St',
|
|
409
|
+
address_line2: 'Suite 100',
|
|
410
|
+
postal_code: '12345',
|
|
411
|
+
city: 'San Francisco',
|
|
412
|
+
},
|
|
413
|
+
metadata: {
|
|
414
|
+
industry: 'technology',
|
|
415
|
+
},
|
|
426
416
|
});
|
|
427
|
-
```
|
|
428
417
|
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
```typescript
|
|
432
|
-
interface CreateCardParams {
|
|
433
|
-
/**
|
|
434
|
-
* URN of the account holder (user or organization)
|
|
435
|
-
* @example "did:bloque:user:123e4567"
|
|
436
|
-
*/
|
|
437
|
-
urn: string;
|
|
438
|
-
|
|
439
|
-
/**
|
|
440
|
-
* Display name for the card (optional)
|
|
441
|
-
*/
|
|
442
|
-
name?: string;
|
|
443
|
-
}
|
|
418
|
+
console.log('Organization created:', org.urn);
|
|
419
|
+
console.log('Status:', org.status);
|
|
444
420
|
```
|
|
445
421
|
|
|
446
|
-
|
|
422
|
+
## Error Handling
|
|
423
|
+
|
|
424
|
+
The SDK provides specific error types for better error handling:
|
|
447
425
|
|
|
448
426
|
```typescript
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
}
|
|
427
|
+
import {
|
|
428
|
+
BloqueRateLimitError,
|
|
429
|
+
BloqueAuthenticationError,
|
|
430
|
+
BloqueValidationError,
|
|
431
|
+
BloqueNotFoundError,
|
|
432
|
+
BloqueInsufficientFundsError,
|
|
433
|
+
BloqueNetworkError,
|
|
434
|
+
BloqueTimeoutError,
|
|
435
|
+
} from '@bloque/sdk';
|
|
436
|
+
|
|
437
|
+
try {
|
|
438
|
+
const card = await session.accounts.card.create({ name: 'My Card' });
|
|
439
|
+
} catch (error) {
|
|
440
|
+
if (error instanceof BloqueRateLimitError) {
|
|
441
|
+
console.log(`Rate limited. Retry after ${error.retryAfter} seconds`);
|
|
442
|
+
console.log(`Request ID: ${error.requestId}`);
|
|
443
|
+
} else if (error instanceof BloqueValidationError) {
|
|
444
|
+
console.log('Validation errors:', error.validationErrors);
|
|
445
|
+
} else if (error instanceof BloqueAuthenticationError) {
|
|
446
|
+
console.log('Authentication failed. Check your API key.');
|
|
447
|
+
} else if (error instanceof BloqueNotFoundError) {
|
|
448
|
+
console.log(`Resource not found: ${error.resourceType}`);
|
|
449
|
+
} else if (error instanceof BloqueInsufficientFundsError) {
|
|
450
|
+
console.log(`Insufficient funds: ${error.requestedAmount} ${error.currency}`);
|
|
451
|
+
console.log(`Available: ${error.availableBalance} ${error.currency}`);
|
|
452
|
+
} else if (error instanceof BloqueTimeoutError) {
|
|
453
|
+
console.log(`Request timed out after ${error.timeoutMs}ms`);
|
|
454
|
+
} else if (error instanceof BloqueNetworkError) {
|
|
455
|
+
console.log('Network error:', error.message);
|
|
456
|
+
}
|
|
464
457
|
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
pending: string; // Pending balance
|
|
468
|
-
in: string; // Total incoming
|
|
469
|
-
out: string; // Total outgoing
|
|
458
|
+
// All errors have these fields
|
|
459
|
+
console.log('Error details:', error.toJSON());
|
|
470
460
|
}
|
|
471
461
|
```
|
|
472
462
|
|
|
473
|
-
|
|
463
|
+
### Error Metadata
|
|
474
464
|
|
|
475
|
-
|
|
465
|
+
All errors include rich metadata for debugging:
|
|
476
466
|
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
467
|
+
- `message`: Human-readable error message
|
|
468
|
+
- `status`: HTTP status code (if applicable)
|
|
469
|
+
- `code`: Error code from the API
|
|
470
|
+
- `requestId`: Unique request ID for tracing
|
|
471
|
+
- `timestamp`: When the error occurred
|
|
472
|
+
- `response`: Original response body (for debugging)
|
|
473
|
+
- `cause`: Original error (for error chaining)
|
|
481
474
|
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
});
|
|
486
|
-
```
|
|
475
|
+
## Retry Logic
|
|
476
|
+
|
|
477
|
+
The SDK automatically retries failed requests with exponential backoff:
|
|
487
478
|
|
|
488
|
-
**
|
|
479
|
+
- **Retried scenarios**: 429 (Rate Limit), 503 (Service Unavailable), network errors, timeouts
|
|
480
|
+
- **Exponential backoff**: Delay increases exponentially (1s → 2s → 4s)
|
|
481
|
+
- **Jitter**: ±25% random jitter to prevent thundering herd
|
|
482
|
+
- **Respects Retry-After**: Honors the `Retry-After` header when present
|
|
489
483
|
|
|
490
484
|
```typescript
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
485
|
+
const bloque = new SDK({
|
|
486
|
+
origin: 'your-origin',
|
|
487
|
+
auth: { type: 'apiKey', apiKey: 'key' },
|
|
488
|
+
retry: {
|
|
489
|
+
enabled: true, // default: true
|
|
490
|
+
maxRetries: 3, // default: 3
|
|
491
|
+
initialDelay: 1000, // default: 1000ms
|
|
492
|
+
maxDelay: 30000, // default: 30000ms
|
|
493
|
+
},
|
|
494
|
+
});
|
|
499
495
|
```
|
|
500
496
|
|
|
501
|
-
|
|
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.
|
|
497
|
+
## Timeout Configuration
|
|
504
498
|
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
Get the current balance for a specific card account:
|
|
499
|
+
Configure request timeouts globally or per-request:
|
|
508
500
|
|
|
509
501
|
```typescript
|
|
510
|
-
|
|
511
|
-
|
|
502
|
+
// Global timeout
|
|
503
|
+
const bloque = new SDK({
|
|
504
|
+
origin: 'your-origin',
|
|
505
|
+
auth: { type: 'apiKey', apiKey: 'key' },
|
|
506
|
+
timeout: 15000, // 15 seconds
|
|
512
507
|
});
|
|
513
|
-
```
|
|
514
508
|
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
* URN of the card account
|
|
521
|
-
* @example "did:bloque:account:card:usr-123:crd-456"
|
|
522
|
-
*/
|
|
523
|
-
urn: string;
|
|
524
|
-
}
|
|
509
|
+
// Per-request timeout (override global)
|
|
510
|
+
const card = await session.accounts.card.create(
|
|
511
|
+
{ name: 'My Card' },
|
|
512
|
+
{ timeout: 5000 } // 5 seconds for this request
|
|
513
|
+
);
|
|
525
514
|
```
|
|
526
515
|
|
|
527
|
-
|
|
516
|
+
## Security Best Practices
|
|
528
517
|
|
|
529
|
-
|
|
518
|
+
### API Keys
|
|
530
519
|
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
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
|
-
```
|
|
520
|
+
- ✅ Store API keys in environment variables
|
|
521
|
+
- ✅ Use different keys for development and production
|
|
522
|
+
- ✅ Never commit API keys to version control
|
|
523
|
+
- ✅ Rotate API keys regularly
|
|
524
|
+
- ❌ Never expose API keys in client-side code
|
|
547
525
|
|
|
548
|
-
|
|
526
|
+
### Token Storage (Frontend)
|
|
549
527
|
|
|
550
|
-
|
|
528
|
+
The SDK warns when using insecure storage:
|
|
551
529
|
|
|
552
530
|
```typescript
|
|
553
|
-
//
|
|
554
|
-
const
|
|
555
|
-
|
|
556
|
-
|
|
531
|
+
// Browser: localStorage (⚠️ vulnerable to XSS)
|
|
532
|
+
const bloque = new SDK({
|
|
533
|
+
auth: { type: 'jwt' },
|
|
534
|
+
platform: 'browser',
|
|
535
|
+
// Uses localStorage by default with security warning
|
|
557
536
|
});
|
|
558
537
|
|
|
559
|
-
//
|
|
560
|
-
const
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
538
|
+
// Recommended: httpOnly cookies (immune to XSS)
|
|
539
|
+
const cookieStorage: TokenStorage = {
|
|
540
|
+
get: () => null, // Token sent automatically in cookie
|
|
541
|
+
set: async (token) => {
|
|
542
|
+
await fetch('/api/auth/set-token', {
|
|
543
|
+
method: 'POST',
|
|
544
|
+
body: JSON.stringify({ token }),
|
|
545
|
+
});
|
|
546
|
+
},
|
|
547
|
+
clear: async () => {
|
|
548
|
+
await fetch('/api/auth/logout', { method: 'POST' });
|
|
549
|
+
},
|
|
550
|
+
};
|
|
551
|
+
|
|
552
|
+
const bloque = new SDK({
|
|
553
|
+
auth: { type: 'jwt' },
|
|
554
|
+
platform: 'browser',
|
|
555
|
+
tokenStorage: cookieStorage,
|
|
566
556
|
});
|
|
567
557
|
```
|
|
568
558
|
|
|
569
|
-
|
|
559
|
+
## TypeScript Support
|
|
560
|
+
|
|
561
|
+
The SDK is built with TypeScript and provides full type safety:
|
|
570
562
|
|
|
571
563
|
```typescript
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
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
|
-
```
|
|
564
|
+
import type {
|
|
565
|
+
BloqueSDKConfig,
|
|
566
|
+
CardAccount,
|
|
567
|
+
CreateCardParams,
|
|
568
|
+
VirtualAccount,
|
|
569
|
+
CreateVirtualAccountParams,
|
|
570
|
+
TransferParams,
|
|
571
|
+
TransferResult,
|
|
572
|
+
} from '@bloque/sdk';
|
|
619
573
|
|
|
620
|
-
|
|
574
|
+
// Type-safe configuration
|
|
575
|
+
const config: BloqueSDKConfig = {
|
|
576
|
+
origin: 'your-origin',
|
|
577
|
+
auth: { type: 'apiKey', apiKey: 'key' },
|
|
578
|
+
mode: 'production',
|
|
579
|
+
};
|
|
621
580
|
|
|
622
|
-
|
|
581
|
+
// Type-safe parameters
|
|
582
|
+
const params: CreateCardParams = {
|
|
583
|
+
name: 'My Card',
|
|
584
|
+
};
|
|
623
585
|
|
|
624
|
-
|
|
625
|
-
|
|
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
|
-
}
|
|
586
|
+
// Type-safe responses
|
|
587
|
+
const card: CardAccount = await session.accounts.card.create(params);
|
|
651
588
|
```
|
|
652
589
|
|
|
653
|
-
|
|
590
|
+
## Package Exports
|
|
654
591
|
|
|
655
|
-
|
|
592
|
+
The SDK supports modular imports:
|
|
656
593
|
|
|
657
594
|
```typescript
|
|
658
|
-
|
|
659
|
-
|
|
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**:
|
|
595
|
+
// Main SDK
|
|
596
|
+
import { SDK } from '@bloque/sdk';
|
|
671
597
|
|
|
672
|
-
|
|
673
|
-
|
|
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
|
-
```
|
|
598
|
+
// Initialization helper
|
|
599
|
+
import { init } from '@bloque/sdk/init';
|
|
706
600
|
|
|
707
|
-
|
|
601
|
+
// Modular clients (tree-shakeable)
|
|
602
|
+
import { AccountsClient } from '@bloque/sdk/accounts';
|
|
603
|
+
import { IdentityClient } from '@bloque/sdk/identity';
|
|
604
|
+
import { ComplianceClient } from '@bloque/sdk/compliance';
|
|
605
|
+
import { OrgsClient } from '@bloque/sdk/orgs';
|
|
708
606
|
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
607
|
+
// Types
|
|
608
|
+
import type {
|
|
609
|
+
BloqueSDKConfig,
|
|
610
|
+
CardAccount,
|
|
611
|
+
VirtualAccount,
|
|
612
|
+
BancolombiaAccount,
|
|
613
|
+
} from '@bloque/sdk';
|
|
715
614
|
```
|
|
716
615
|
|
|
717
|
-
|
|
616
|
+
## Advanced Usage
|
|
718
617
|
|
|
719
|
-
###
|
|
618
|
+
### Custom HTTP Client
|
|
720
619
|
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
#### Register Identity
|
|
724
|
-
|
|
725
|
-
Register a new user or business identity to an authentication origin. Supports individual users (KYC) and businesses (KYB):
|
|
620
|
+
For advanced use cases, access the HTTP client directly:
|
|
726
621
|
|
|
727
622
|
```typescript
|
|
728
|
-
|
|
729
|
-
const individual = await bloque.identity.origins.register('ethereum-mainnet', {
|
|
730
|
-
assertionResult: {
|
|
731
|
-
alias: '0x742d35Cc6634C0532925a3b8D4C9db96C4b4d8b6',
|
|
732
|
-
challengeType: 'SIGNING_CHALLENGE',
|
|
733
|
-
value: {
|
|
734
|
-
signature: '0x1234567890abcdef...',
|
|
735
|
-
alias: '0x742d35Cc6634C0532925a3b8D4C9db96C4b4d8b6'
|
|
736
|
-
}
|
|
737
|
-
},
|
|
738
|
-
type: 'individual',
|
|
739
|
-
profile: {
|
|
740
|
-
firstName: 'John',
|
|
741
|
-
lastName: 'Doe',
|
|
742
|
-
email: 'john@example.com'
|
|
743
|
-
}
|
|
744
|
-
});
|
|
623
|
+
const session = await bloque.connect('did:bloque:your-origin:user-alias');
|
|
745
624
|
|
|
746
|
-
//
|
|
747
|
-
const
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
}
|
|
755
|
-
},
|
|
756
|
-
type: 'business',
|
|
757
|
-
profile: {
|
|
758
|
-
legalName: 'Acme Corporation',
|
|
759
|
-
name: 'Acme Corp',
|
|
760
|
-
taxId: '12-3456789',
|
|
761
|
-
type: 'LLC',
|
|
762
|
-
incorporationDate: '2020-01-15',
|
|
763
|
-
addressLine1: '123 Business St',
|
|
764
|
-
city: 'New York',
|
|
765
|
-
state: 'NY',
|
|
766
|
-
postalCode: '10001',
|
|
767
|
-
country: 'United States'
|
|
768
|
-
}
|
|
625
|
+
// Access the HTTP client
|
|
626
|
+
const httpClient = session.accounts.card['httpClient'];
|
|
627
|
+
|
|
628
|
+
// Make custom requests
|
|
629
|
+
const response = await httpClient.request({
|
|
630
|
+
method: 'GET',
|
|
631
|
+
path: '/api/custom-endpoint',
|
|
632
|
+
timeout: 10000,
|
|
769
633
|
});
|
|
770
634
|
```
|
|
771
635
|
|
|
772
|
-
|
|
636
|
+
### Environment-Specific Configuration
|
|
773
637
|
|
|
774
638
|
```typescript
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
profile: BusinessProfile;
|
|
790
|
-
}
|
|
791
|
-
|
|
792
|
-
// Assertion result for challenge verification
|
|
793
|
-
interface AssertionResult {
|
|
794
|
-
alias: string; // Identity identifier
|
|
795
|
-
challengeType: 'SIGNING_CHALLENGE' | 'API_KEY' | 'OAUTH_REDIRECT' | 'WEBAUTHN' | 'OTP' | 'PASSWORD';
|
|
796
|
-
value: {
|
|
797
|
-
signature?: string; // For SIGNING_CHALLENGE
|
|
798
|
-
apiKey?: string; // For API_KEY
|
|
799
|
-
alias: string;
|
|
800
|
-
};
|
|
801
|
-
originalChallengeParams?: {
|
|
802
|
-
challenge: string;
|
|
803
|
-
timestamp: number;
|
|
804
|
-
};
|
|
805
|
-
}
|
|
806
|
-
|
|
807
|
-
// Individual user profile (KYC)
|
|
808
|
-
interface UserProfile {
|
|
809
|
-
firstName?: string;
|
|
810
|
-
lastName?: string;
|
|
811
|
-
birthdate?: string; // ISO 8601 (YYYY-MM-DD)
|
|
812
|
-
email?: string;
|
|
813
|
-
phone?: string;
|
|
814
|
-
gender?: string;
|
|
815
|
-
addressLine1?: string;
|
|
816
|
-
addressLine2?: string;
|
|
817
|
-
city?: string;
|
|
818
|
-
state?: string;
|
|
819
|
-
postalCode?: string;
|
|
820
|
-
neighborhood?: string;
|
|
821
|
-
countryOfBirthCode?: string;
|
|
822
|
-
countryOfResidenceCode?: string;
|
|
823
|
-
personalIdType?: string;
|
|
824
|
-
personalIdNumber?: string;
|
|
825
|
-
}
|
|
639
|
+
const config: BloqueSDKConfig = {
|
|
640
|
+
origin: process.env.BLOQUE_ORIGIN!,
|
|
641
|
+
auth: {
|
|
642
|
+
type: 'apiKey',
|
|
643
|
+
apiKey: process.env.BLOQUE_API_KEY!,
|
|
644
|
+
},
|
|
645
|
+
mode: process.env.NODE_ENV === 'production' ? 'production' : 'sandbox',
|
|
646
|
+
platform: 'node',
|
|
647
|
+
timeout: Number.parseInt(process.env.BLOQUE_TIMEOUT || '30000', 10),
|
|
648
|
+
retry: {
|
|
649
|
+
enabled: process.env.BLOQUE_RETRY_ENABLED !== 'false',
|
|
650
|
+
maxRetries: Number.parseInt(process.env.BLOQUE_MAX_RETRIES || '3', 10),
|
|
651
|
+
},
|
|
652
|
+
};
|
|
826
653
|
|
|
827
|
-
|
|
828
|
-
interface BusinessProfile {
|
|
829
|
-
// Required fields
|
|
830
|
-
addressLine1: string;
|
|
831
|
-
city: string;
|
|
832
|
-
country: string;
|
|
833
|
-
incorporationDate: string;
|
|
834
|
-
legalName: string;
|
|
835
|
-
name: string;
|
|
836
|
-
postalCode: string;
|
|
837
|
-
state: string;
|
|
838
|
-
taxId: string;
|
|
839
|
-
type: string;
|
|
840
|
-
|
|
841
|
-
// Optional fields
|
|
842
|
-
addressLine2?: string;
|
|
843
|
-
countryCode?: string;
|
|
844
|
-
email?: string;
|
|
845
|
-
logo?: string;
|
|
846
|
-
phone?: string;
|
|
847
|
-
|
|
848
|
-
// Beneficial owner information
|
|
849
|
-
ownerName?: string;
|
|
850
|
-
ownerIdType?: string;
|
|
851
|
-
ownerIdNumber?: string;
|
|
852
|
-
ownerAddressLine1?: string;
|
|
853
|
-
ownerCity?: string;
|
|
854
|
-
ownerState?: string;
|
|
855
|
-
ownerPostalCode?: string;
|
|
856
|
-
ownerCountryCode?: string;
|
|
857
|
-
}
|
|
654
|
+
const bloque = new SDK(config);
|
|
858
655
|
```
|
|
859
656
|
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
```typescript
|
|
863
|
-
interface RegisterResult {
|
|
864
|
-
accessToken: string; // JWT access token for authenticated sessions
|
|
865
|
-
}
|
|
866
|
-
```
|
|
657
|
+
## Examples
|
|
867
658
|
|
|
868
|
-
|
|
659
|
+
See the [`examples/`](./examples) directory for complete working examples:
|
|
869
660
|
|
|
870
|
-
|
|
661
|
+
- `basic-usage.ts` - Basic SDK usage
|
|
662
|
+
- `virtual-cards.ts` - Virtual card management
|
|
663
|
+
- `virtual-accounts.ts` - Virtual account management
|
|
664
|
+
- `transfers.ts` - Account transfers
|
|
665
|
+
- `identity-registration.ts` - User registration
|
|
666
|
+
- `kyc-verification.ts` - KYC workflows
|
|
667
|
+
- `error-handling.ts` - Advanced error handling
|
|
871
668
|
|
|
872
|
-
|
|
873
|
-
const alias = await bloque.identity.aliases.get('user@example.com');
|
|
874
|
-
```
|
|
669
|
+
## API Documentation
|
|
875
670
|
|
|
876
|
-
|
|
671
|
+
For detailed API documentation, visit [docs.bloque.app/sdk](https://docs.bloque.app/sdk).
|
|
877
672
|
|
|
878
|
-
|
|
879
|
-
// Pass the alias string directly
|
|
880
|
-
const alias: string = 'user@example.com' | '+1234567890';
|
|
881
|
-
```
|
|
673
|
+
## Support
|
|
882
674
|
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
id: string; // Unique alias ID
|
|
888
|
-
alias: string; // Alias value
|
|
889
|
-
type: 'phone' | 'email' | string; // Alias type
|
|
890
|
-
urn: string; // Associated user URN
|
|
891
|
-
origin: string; // Origin identifier
|
|
892
|
-
details: {
|
|
893
|
-
phone?: string; // Phone details (if applicable)
|
|
894
|
-
};
|
|
895
|
-
metadata: {
|
|
896
|
-
alias: string; // Alias in metadata
|
|
897
|
-
[key: string]: unknown; // Additional metadata
|
|
898
|
-
};
|
|
899
|
-
status: 'active' | 'inactive' | 'revoked'; // Alias status
|
|
900
|
-
is_public: boolean; // Whether alias is public
|
|
901
|
-
is_primary: boolean; // Whether this is the primary alias
|
|
902
|
-
created_at: string; // Creation timestamp (ISO 8601)
|
|
903
|
-
updated_at: string; // Last update timestamp (ISO 8601)
|
|
904
|
-
}
|
|
905
|
-
```
|
|
906
|
-
|
|
907
|
-
## Examples
|
|
908
|
-
|
|
909
|
-
### Creating a Business Organization
|
|
910
|
-
|
|
911
|
-
```typescript
|
|
912
|
-
import { SDK } from '@bloque/sdk';
|
|
913
|
-
import type { CreateOrgParams } from '@bloque/sdk/orgs';
|
|
914
|
-
|
|
915
|
-
// Initialize SDK with your API key
|
|
916
|
-
const bloque = new SDK({
|
|
917
|
-
auth: {
|
|
918
|
-
type: 'apiKey',
|
|
919
|
-
apiKey: process.env.BLOQUE_API_KEY!,
|
|
920
|
-
},
|
|
921
|
-
mode: 'production',
|
|
922
|
-
});
|
|
923
|
-
|
|
924
|
-
// Create a business organization
|
|
925
|
-
const params: CreateOrgParams = {
|
|
926
|
-
org_type: 'business',
|
|
927
|
-
profile: {
|
|
928
|
-
legal_name: 'Acme Corporation',
|
|
929
|
-
tax_id: '12-3456789',
|
|
930
|
-
incorporation_date: '2020-01-15',
|
|
931
|
-
business_type: 'llc',
|
|
932
|
-
incorporation_country_code: 'US',
|
|
933
|
-
incorporation_state: 'CA',
|
|
934
|
-
address_line1: '123 Market Street',
|
|
935
|
-
address_line2: 'Suite 400',
|
|
936
|
-
postal_code: '94103',
|
|
937
|
-
city: 'San Francisco',
|
|
938
|
-
logo_url: 'https://example.com/logo.png',
|
|
939
|
-
},
|
|
940
|
-
metadata: {
|
|
941
|
-
source: 'web_app',
|
|
942
|
-
campaign: 'q1_2024',
|
|
943
|
-
},
|
|
944
|
-
};
|
|
945
|
-
|
|
946
|
-
try {
|
|
947
|
-
const organization = await bloque.orgs.create(params);
|
|
948
|
-
console.log('Organization created:', organization.urn);
|
|
949
|
-
console.log('Status:', organization.status);
|
|
950
|
-
} catch (error) {
|
|
951
|
-
console.error('Failed to create organization:', error);
|
|
952
|
-
}
|
|
953
|
-
```
|
|
954
|
-
|
|
955
|
-
### Creating an Individual Organization
|
|
956
|
-
|
|
957
|
-
```typescript
|
|
958
|
-
import { SDK } from '@bloque/sdk';
|
|
959
|
-
import type { CreateOrgParams } from '@bloque/sdk/orgs';
|
|
960
|
-
|
|
961
|
-
const bloque = new SDK({
|
|
962
|
-
auth: {
|
|
963
|
-
type: 'apiKey',
|
|
964
|
-
apiKey: process.env.BLOQUE_API_KEY!,
|
|
965
|
-
},
|
|
966
|
-
mode: 'sandbox',
|
|
967
|
-
});
|
|
968
|
-
|
|
969
|
-
const params: CreateOrgParams = {
|
|
970
|
-
org_type: 'individual',
|
|
971
|
-
profile: {
|
|
972
|
-
legal_name: 'John Doe',
|
|
973
|
-
tax_id: '123-45-6789',
|
|
974
|
-
incorporation_date: '1990-05-20',
|
|
975
|
-
business_type: 'sole_proprietorship',
|
|
976
|
-
incorporation_country_code: 'US',
|
|
977
|
-
address_line1: '456 Oak Avenue',
|
|
978
|
-
postal_code: '10001',
|
|
979
|
-
city: 'New York',
|
|
980
|
-
},
|
|
981
|
-
};
|
|
982
|
-
|
|
983
|
-
const organization = await bloque.orgs.create(params);
|
|
984
|
-
console.log('Individual organization created:', organization);
|
|
985
|
-
```
|
|
986
|
-
|
|
987
|
-
### Organization with Multiple Locations
|
|
988
|
-
|
|
989
|
-
```typescript
|
|
990
|
-
import { SDK } from '@bloque/sdk';
|
|
991
|
-
import type { CreateOrgParams } from '@bloque/sdk/orgs';
|
|
992
|
-
|
|
993
|
-
const bloque = new SDK({
|
|
994
|
-
auth: {
|
|
995
|
-
type: 'apiKey',
|
|
996
|
-
apiKey: process.env.BLOQUE_API_KEY!,
|
|
997
|
-
},
|
|
998
|
-
mode: 'production',
|
|
999
|
-
});
|
|
1000
|
-
|
|
1001
|
-
const params: CreateOrgParams = {
|
|
1002
|
-
org_type: 'business',
|
|
1003
|
-
profile: {
|
|
1004
|
-
legal_name: 'Global Tech Solutions Inc.',
|
|
1005
|
-
tax_id: '98-7654321',
|
|
1006
|
-
incorporation_date: '2018-03-10',
|
|
1007
|
-
business_type: 'corporation',
|
|
1008
|
-
incorporation_country_code: 'US',
|
|
1009
|
-
incorporation_state: 'DE',
|
|
1010
|
-
address_line1: '789 Corporate Blvd',
|
|
1011
|
-
postal_code: '19801',
|
|
1012
|
-
city: 'Wilmington',
|
|
1013
|
-
places: [
|
|
1014
|
-
{
|
|
1015
|
-
country_code: 'US',
|
|
1016
|
-
state: 'CA',
|
|
1017
|
-
address_line1: '100 Silicon Valley Drive',
|
|
1018
|
-
postal_code: '94025',
|
|
1019
|
-
city: 'Menlo Park',
|
|
1020
|
-
is_primary: true,
|
|
1021
|
-
},
|
|
1022
|
-
{
|
|
1023
|
-
country_code: 'US',
|
|
1024
|
-
state: 'NY',
|
|
1025
|
-
address_line1: '250 Broadway',
|
|
1026
|
-
postal_code: '10007',
|
|
1027
|
-
city: 'New York',
|
|
1028
|
-
is_primary: false,
|
|
1029
|
-
},
|
|
1030
|
-
],
|
|
1031
|
-
},
|
|
1032
|
-
};
|
|
1033
|
-
|
|
1034
|
-
const organization = await bloque.orgs.create(params);
|
|
1035
|
-
console.log('Multi-location organization created');
|
|
1036
|
-
```
|
|
1037
|
-
|
|
1038
|
-
### Starting KYC Verification
|
|
1039
|
-
|
|
1040
|
-
```typescript
|
|
1041
|
-
import { SDK } from '@bloque/sdk';
|
|
1042
|
-
import type { KycVerificationParams } from '@bloque/sdk/compliance';
|
|
1043
|
-
|
|
1044
|
-
const bloque = new SDK({
|
|
1045
|
-
auth: {
|
|
1046
|
-
type: 'apiKey',
|
|
1047
|
-
apiKey: process.env.BLOQUE_API_KEY!,
|
|
1048
|
-
},
|
|
1049
|
-
mode: 'production',
|
|
1050
|
-
});
|
|
1051
|
-
|
|
1052
|
-
// Start KYC verification for a user
|
|
1053
|
-
const params: KycVerificationParams = {
|
|
1054
|
-
urn: 'did:bloque:origin:user-123',
|
|
1055
|
-
webhookUrl: 'https://api.example.com/webhooks/kyc', // Optional webhook URL
|
|
1056
|
-
};
|
|
1057
|
-
|
|
1058
|
-
try {
|
|
1059
|
-
const verification = await bloque.compliance.kyc.startVerification(params);
|
|
1060
|
-
|
|
1061
|
-
console.log('Verification URL:', verification.url);
|
|
1062
|
-
console.log('Status:', verification.status);
|
|
1063
|
-
|
|
1064
|
-
// Redirect the user to verification.url to complete KYC
|
|
1065
|
-
// Webhook notifications will be sent to the provided webhookUrl
|
|
1066
|
-
} catch (error) {
|
|
1067
|
-
console.error('Failed to start KYC verification:', error);
|
|
1068
|
-
}
|
|
1069
|
-
```
|
|
1070
|
-
|
|
1071
|
-
### Getting KYC Verification Status
|
|
1072
|
-
|
|
1073
|
-
```typescript
|
|
1074
|
-
import { SDK } from '@bloque/sdk';
|
|
1075
|
-
import type { GetKycVerificationParams } from '@bloque/sdk/compliance';
|
|
1076
|
-
|
|
1077
|
-
const bloque = new SDK({
|
|
1078
|
-
auth: {
|
|
1079
|
-
type: 'apiKey',
|
|
1080
|
-
apiKey: process.env.BLOQUE_API_KEY!,
|
|
1081
|
-
},
|
|
1082
|
-
mode: 'production',
|
|
1083
|
-
});
|
|
1084
|
-
|
|
1085
|
-
// Get verification status
|
|
1086
|
-
const params: GetKycVerificationParams = {
|
|
1087
|
-
urn: 'did:bloque:user:123e4567',
|
|
1088
|
-
};
|
|
1089
|
-
|
|
1090
|
-
try {
|
|
1091
|
-
const status = await bloque.compliance.kyc.getVerification(params);
|
|
1092
|
-
|
|
1093
|
-
console.log('Status:', status.status);
|
|
1094
|
-
console.log('Verification URL:', status.url);
|
|
1095
|
-
console.log('Completed At:', status.completedAt);
|
|
1096
|
-
|
|
1097
|
-
if (status.status === 'approved') {
|
|
1098
|
-
console.log('User verification approved!');
|
|
1099
|
-
} else if (status.status === 'rejected') {
|
|
1100
|
-
console.log('User verification rejected');
|
|
1101
|
-
} else {
|
|
1102
|
-
console.log('Verification still pending');
|
|
1103
|
-
}
|
|
1104
|
-
} catch (error) {
|
|
1105
|
-
console.error('Failed to get verification status:', error);
|
|
1106
|
-
}
|
|
1107
|
-
```
|
|
1108
|
-
|
|
1109
|
-
### Creating a Virtual Card
|
|
1110
|
-
|
|
1111
|
-
```typescript
|
|
1112
|
-
import { SDK } from '@bloque/sdk';
|
|
1113
|
-
import type { CreateCardParams } from '@bloque/sdk/accounts';
|
|
1114
|
-
|
|
1115
|
-
const bloque = new SDK({
|
|
1116
|
-
auth: {
|
|
1117
|
-
type: 'apiKey',
|
|
1118
|
-
apiKey: process.env.BLOQUE_API_KEY!,
|
|
1119
|
-
},
|
|
1120
|
-
mode: 'production',
|
|
1121
|
-
});
|
|
1122
|
-
|
|
1123
|
-
// Create a virtual card
|
|
1124
|
-
const params: CreateCardParams = {
|
|
1125
|
-
urn: 'did:bloque:user:123e4567',
|
|
1126
|
-
name: 'My Business Card', // Optional
|
|
1127
|
-
};
|
|
1128
|
-
|
|
1129
|
-
try {
|
|
1130
|
-
const card = await bloque.accounts.card.create(params);
|
|
1131
|
-
|
|
1132
|
-
console.log('Card created:', card.urn);
|
|
1133
|
-
console.log('Last four digits:', card.lastFour);
|
|
1134
|
-
console.log('Card type:', card.cardType);
|
|
1135
|
-
console.log('Status:', card.status);
|
|
1136
|
-
console.log('Details URL:', card.detailsUrl);
|
|
1137
|
-
|
|
1138
|
-
// Check if card is ready to use
|
|
1139
|
-
if (card.status === 'active') {
|
|
1140
|
-
console.log('Card is active and ready to use!');
|
|
1141
|
-
} else if (card.status === 'creation_in_progress') {
|
|
1142
|
-
console.log('Card is being created...');
|
|
1143
|
-
}
|
|
1144
|
-
} catch (error) {
|
|
1145
|
-
console.error('Failed to create card:', error);
|
|
1146
|
-
}
|
|
1147
|
-
```
|
|
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
|
-
|
|
1480
|
-
### Retrieving User Alias Information
|
|
1481
|
-
|
|
1482
|
-
```typescript
|
|
1483
|
-
import { SDK } from '@bloque/sdk';
|
|
1484
|
-
|
|
1485
|
-
const bloque = new SDK({
|
|
1486
|
-
auth: {
|
|
1487
|
-
type: 'apiKey',
|
|
1488
|
-
apiKey: process.env.BLOQUE_API_KEY!,
|
|
1489
|
-
},
|
|
1490
|
-
mode: 'production',
|
|
1491
|
-
});
|
|
1492
|
-
|
|
1493
|
-
// Get alias information by email
|
|
1494
|
-
try {
|
|
1495
|
-
const alias = await bloque.identity.aliases.get('user@example.com');
|
|
1496
|
-
|
|
1497
|
-
console.log('Alias ID:', alias.id);
|
|
1498
|
-
console.log('Alias type:', alias.type);
|
|
1499
|
-
console.log('Associated URN:', alias.urn);
|
|
1500
|
-
console.log('Status:', alias.status);
|
|
1501
|
-
console.log('Is primary:', alias.is_primary);
|
|
1502
|
-
console.log('Is public:', alias.is_public);
|
|
1503
|
-
|
|
1504
|
-
if (alias.status === 'active') {
|
|
1505
|
-
console.log('Alias is active');
|
|
1506
|
-
}
|
|
1507
|
-
} catch (error) {
|
|
1508
|
-
console.error('Failed to retrieve alias:', error);
|
|
1509
|
-
}
|
|
1510
|
-
|
|
1511
|
-
// Get alias information by phone number
|
|
1512
|
-
try {
|
|
1513
|
-
const phoneAlias = await bloque.identity.aliases.get('+1234567890');
|
|
1514
|
-
|
|
1515
|
-
console.log('Phone alias:', phoneAlias.alias);
|
|
1516
|
-
console.log('Phone details:', phoneAlias.details.phone);
|
|
1517
|
-
} catch (error) {
|
|
1518
|
-
console.error('Failed to retrieve phone alias:', error);
|
|
1519
|
-
}
|
|
1520
|
-
```
|
|
1521
|
-
|
|
1522
|
-
### Registering Individual User Identity (KYC)
|
|
1523
|
-
|
|
1524
|
-
```typescript
|
|
1525
|
-
import { SDK } from '@bloque/sdk';
|
|
1526
|
-
import type { IndividualRegisterParams } from '@bloque/sdk/identity';
|
|
1527
|
-
|
|
1528
|
-
const bloque = new SDK({
|
|
1529
|
-
auth: {
|
|
1530
|
-
type: 'apiKey',
|
|
1531
|
-
apiKey: process.env.BLOQUE_API_KEY!,
|
|
1532
|
-
},
|
|
1533
|
-
mode: 'production',
|
|
1534
|
-
});
|
|
1535
|
-
|
|
1536
|
-
// Register an individual with blockchain signature
|
|
1537
|
-
const params: IndividualRegisterParams = {
|
|
1538
|
-
assertionResult: {
|
|
1539
|
-
alias: '0x742d35Cc6634C0532925a3b8D4C9db96C4b4d8b6',
|
|
1540
|
-
challengeType: 'SIGNING_CHALLENGE',
|
|
1541
|
-
value: {
|
|
1542
|
-
signature: '0x1234567890abcdef...',
|
|
1543
|
-
alias: '0x742d35Cc6634C0532925a3b8D4C9db96C4b4d8b6'
|
|
1544
|
-
},
|
|
1545
|
-
originalChallengeParams: {
|
|
1546
|
-
challenge: 'bloque-challenge-1234567890',
|
|
1547
|
-
timestamp: 1640995200
|
|
1548
|
-
}
|
|
1549
|
-
},
|
|
1550
|
-
type: 'individual',
|
|
1551
|
-
profile: {
|
|
1552
|
-
firstName: 'John',
|
|
1553
|
-
lastName: 'Doe',
|
|
1554
|
-
email: 'john.doe@example.com',
|
|
1555
|
-
phone: '+1234567890',
|
|
1556
|
-
birthdate: '1990-01-15',
|
|
1557
|
-
city: 'New York',
|
|
1558
|
-
state: 'NY',
|
|
1559
|
-
postalCode: '10001',
|
|
1560
|
-
addressLine1: '123 Main St',
|
|
1561
|
-
countryOfBirthCode: 'USA',
|
|
1562
|
-
countryOfResidenceCode: 'USA',
|
|
1563
|
-
personalIdType: 'SSN',
|
|
1564
|
-
personalIdNumber: '123-45-6789'
|
|
1565
|
-
}
|
|
1566
|
-
};
|
|
1567
|
-
|
|
1568
|
-
try {
|
|
1569
|
-
const result = await bloque.identity.origins.register('ethereum-mainnet', params);
|
|
1570
|
-
|
|
1571
|
-
console.log('User registered successfully!');
|
|
1572
|
-
console.log('Access token:', result.accessToken);
|
|
1573
|
-
|
|
1574
|
-
// Store the access token securely for the user's session
|
|
1575
|
-
// Use it for subsequent authenticated API calls
|
|
1576
|
-
} catch (error) {
|
|
1577
|
-
console.error('Registration failed:', error);
|
|
1578
|
-
}
|
|
1579
|
-
```
|
|
1580
|
-
|
|
1581
|
-
### Registering Business Identity (KYB)
|
|
1582
|
-
|
|
1583
|
-
```typescript
|
|
1584
|
-
import { SDK } from '@bloque/sdk';
|
|
1585
|
-
import type { BusinessRegisterParams } from '@bloque/sdk/identity';
|
|
1586
|
-
|
|
1587
|
-
const bloque = new SDK({
|
|
1588
|
-
auth: {
|
|
1589
|
-
type: 'apiKey',
|
|
1590
|
-
apiKey: process.env.BLOQUE_API_KEY!,
|
|
1591
|
-
},
|
|
1592
|
-
mode: 'production',
|
|
1593
|
-
});
|
|
1594
|
-
|
|
1595
|
-
// Register a business with API key authentication
|
|
1596
|
-
const params: BusinessRegisterParams = {
|
|
1597
|
-
assertionResult: {
|
|
1598
|
-
alias: 'business-123',
|
|
1599
|
-
challengeType: 'API_KEY',
|
|
1600
|
-
value: {
|
|
1601
|
-
apiKey: 'sk_live_abc123def456',
|
|
1602
|
-
alias: 'business-123'
|
|
1603
|
-
}
|
|
1604
|
-
},
|
|
1605
|
-
type: 'business',
|
|
1606
|
-
profile: {
|
|
1607
|
-
// Required business information
|
|
1608
|
-
legalName: 'Acme Corporation',
|
|
1609
|
-
name: 'Acme Corp',
|
|
1610
|
-
taxId: '12-3456789',
|
|
1611
|
-
type: 'LLC',
|
|
1612
|
-
incorporationDate: '2020-01-15',
|
|
1613
|
-
addressLine1: '123 Business St',
|
|
1614
|
-
city: 'New York',
|
|
1615
|
-
state: 'NY',
|
|
1616
|
-
postalCode: '10001',
|
|
1617
|
-
country: 'United States',
|
|
1618
|
-
|
|
1619
|
-
// Optional business information
|
|
1620
|
-
addressLine2: 'Suite 100',
|
|
1621
|
-
countryCode: 'US',
|
|
1622
|
-
email: 'contact@acme.com',
|
|
1623
|
-
phone: '+1-555-0123',
|
|
1624
|
-
logo: 'https://acme.com/logo.png',
|
|
1625
|
-
|
|
1626
|
-
// Beneficial owner information (for compliance)
|
|
1627
|
-
ownerName: 'Jane Smith',
|
|
1628
|
-
ownerIdType: 'SSN',
|
|
1629
|
-
ownerIdNumber: '123-45-6789',
|
|
1630
|
-
ownerAddressLine1: '456 Owner Ave',
|
|
1631
|
-
ownerCity: 'New York',
|
|
1632
|
-
ownerState: 'NY',
|
|
1633
|
-
ownerPostalCode: '10002',
|
|
1634
|
-
ownerCountryCode: 'US'
|
|
1635
|
-
}
|
|
1636
|
-
};
|
|
1637
|
-
|
|
1638
|
-
try {
|
|
1639
|
-
const result = await bloque.identity.origins.register('bloque-api', params);
|
|
1640
|
-
|
|
1641
|
-
console.log('Business registered successfully!');
|
|
1642
|
-
console.log('Access token:', result.accessToken);
|
|
1643
|
-
|
|
1644
|
-
// Use the access token for authenticated API calls
|
|
1645
|
-
} catch (error) {
|
|
1646
|
-
console.error('Business registration failed:', error);
|
|
1647
|
-
}
|
|
1648
|
-
```
|
|
1649
|
-
|
|
1650
|
-
### Using in an API Endpoint
|
|
1651
|
-
|
|
1652
|
-
```typescript
|
|
1653
|
-
import { SDK } from '@bloque/sdk';
|
|
1654
|
-
import type { CreateOrgParams } from '@bloque/sdk/orgs';
|
|
1655
|
-
|
|
1656
|
-
const bloque = new SDK({
|
|
1657
|
-
auth: {
|
|
1658
|
-
type: 'apiKey',
|
|
1659
|
-
apiKey: process.env.BLOQUE_API_KEY!,
|
|
1660
|
-
},
|
|
1661
|
-
mode: process.env.NODE_ENV === 'production' ? 'production' : 'sandbox',
|
|
1662
|
-
});
|
|
1663
|
-
|
|
1664
|
-
app.post('/api/organizations', async (req, res) => {
|
|
1665
|
-
try {
|
|
1666
|
-
const params: CreateOrgParams = req.body;
|
|
1667
|
-
|
|
1668
|
-
const organization = await bloque.orgs.create(params);
|
|
1669
|
-
|
|
1670
|
-
res.json({
|
|
1671
|
-
success: true,
|
|
1672
|
-
organization,
|
|
1673
|
-
});
|
|
1674
|
-
} catch (error) {
|
|
1675
|
-
console.error('Organization creation failed:', error);
|
|
1676
|
-
res.status(500).json({
|
|
1677
|
-
success: false,
|
|
1678
|
-
error: error instanceof Error ? error.message : 'Unknown error',
|
|
1679
|
-
});
|
|
1680
|
-
}
|
|
1681
|
-
});
|
|
1682
|
-
```
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
## Error Handling
|
|
1686
|
-
|
|
1687
|
-
The SDK uses standard JavaScript errors. Always wrap API calls in try-catch blocks:
|
|
1688
|
-
|
|
1689
|
-
```typescript
|
|
1690
|
-
import { SDK } from '@bloque/sdk';
|
|
1691
|
-
|
|
1692
|
-
const bloque = new SDK({
|
|
1693
|
-
apiKey: process.env.BLOQUE_API_KEY!,
|
|
1694
|
-
mode: 'production',
|
|
1695
|
-
});
|
|
1696
|
-
|
|
1697
|
-
try {
|
|
1698
|
-
const organization = await bloque.orgs.create({
|
|
1699
|
-
org_type: 'business',
|
|
1700
|
-
profile: {
|
|
1701
|
-
legal_name: 'Acme Corp',
|
|
1702
|
-
tax_id: '123456789',
|
|
1703
|
-
incorporation_date: '2020-01-01',
|
|
1704
|
-
business_type: 'llc',
|
|
1705
|
-
incorporation_country_code: 'US',
|
|
1706
|
-
address_line1: '123 Main St',
|
|
1707
|
-
postal_code: '12345',
|
|
1708
|
-
city: 'San Francisco',
|
|
1709
|
-
},
|
|
1710
|
-
});
|
|
1711
|
-
console.log('Success:', organization);
|
|
1712
|
-
} catch (error) {
|
|
1713
|
-
if (error instanceof Error) {
|
|
1714
|
-
console.error('Failed to create organization:', error.message);
|
|
1715
|
-
} else {
|
|
1716
|
-
console.error('Unknown error:', error);
|
|
1717
|
-
}
|
|
1718
|
-
}
|
|
1719
|
-
```
|
|
1720
|
-
|
|
1721
|
-
## TypeScript Support
|
|
1722
|
-
|
|
1723
|
-
This SDK is written in TypeScript and includes complete type definitions. You'll get full autocomplete and type checking when using TypeScript or modern editors like VS Code:
|
|
1724
|
-
|
|
1725
|
-
```typescript
|
|
1726
|
-
import { SDK } from '@bloque/sdk';
|
|
1727
|
-
import type {
|
|
1728
|
-
BloqueConfig,
|
|
1729
|
-
CreateOrgParams,
|
|
1730
|
-
Organization,
|
|
1731
|
-
OrgProfile,
|
|
1732
|
-
OrgStatus,
|
|
1733
|
-
OrgType,
|
|
1734
|
-
Place,
|
|
1735
|
-
} from '@bloque/sdk/orgs';
|
|
1736
|
-
|
|
1737
|
-
// Type-safe configuration
|
|
1738
|
-
const config: BloqueConfig = {
|
|
1739
|
-
apiKey: 'your-api-key',
|
|
1740
|
-
mode: 'sandbox',
|
|
1741
|
-
};
|
|
1742
|
-
|
|
1743
|
-
const bloque = new SDK(config);
|
|
1744
|
-
|
|
1745
|
-
// Type-safe organization profile
|
|
1746
|
-
const profile: OrgProfile = {
|
|
1747
|
-
legal_name: 'Tech Startup Inc.',
|
|
1748
|
-
tax_id: '12-3456789',
|
|
1749
|
-
incorporation_date: '2023-01-15',
|
|
1750
|
-
business_type: 'llc',
|
|
1751
|
-
incorporation_country_code: 'US',
|
|
1752
|
-
incorporation_state: 'CA',
|
|
1753
|
-
address_line1: '456 Innovation Dr',
|
|
1754
|
-
postal_code: '94025',
|
|
1755
|
-
city: 'Menlo Park',
|
|
1756
|
-
};
|
|
1757
|
-
|
|
1758
|
-
// Type-safe organization creation
|
|
1759
|
-
const params: CreateOrgParams = {
|
|
1760
|
-
org_type: 'business',
|
|
1761
|
-
profile,
|
|
1762
|
-
metadata: {
|
|
1763
|
-
vertical: 'fintech',
|
|
1764
|
-
employees: 50,
|
|
1765
|
-
},
|
|
1766
|
-
};
|
|
1767
|
-
|
|
1768
|
-
// TypeScript infers the return type as Organization
|
|
1769
|
-
const org = await bloque.orgs.create(params);
|
|
1770
|
-
```
|
|
1771
|
-
|
|
1772
|
-
**Available Types**:
|
|
1773
|
-
|
|
1774
|
-
The SDK exports all necessary types for type-safe development:
|
|
1775
|
-
|
|
1776
|
-
```typescript
|
|
1777
|
-
// Main SDK types
|
|
1778
|
-
import type { SDK, BloqueConfig } from '@bloque/sdk';
|
|
1779
|
-
|
|
1780
|
-
// Organization types
|
|
1781
|
-
import type {
|
|
1782
|
-
Organization,
|
|
1783
|
-
CreateOrgParams,
|
|
1784
|
-
CreateOrgResponse,
|
|
1785
|
-
OrgProfile,
|
|
1786
|
-
OrgType,
|
|
1787
|
-
OrgStatus,
|
|
1788
|
-
Place,
|
|
1789
|
-
} from '@bloque/sdk/orgs';
|
|
1790
|
-
|
|
1791
|
-
// Compliance types
|
|
1792
|
-
import type {
|
|
1793
|
-
KycVerificationParams,
|
|
1794
|
-
KycVerificationResponse,
|
|
1795
|
-
GetKycVerificationParams,
|
|
1796
|
-
KycVerificationStatus,
|
|
1797
|
-
} from '@bloque/sdk/compliance';
|
|
1798
|
-
|
|
1799
|
-
// Accounts types
|
|
1800
|
-
import type {
|
|
1801
|
-
CardAccount,
|
|
1802
|
-
CardMovement,
|
|
1803
|
-
CreateCardParams,
|
|
1804
|
-
GetBalanceParams,
|
|
1805
|
-
ListCardParams,
|
|
1806
|
-
ListMovementsParams,
|
|
1807
|
-
TokenBalance,
|
|
1808
|
-
TransferParams,
|
|
1809
|
-
TransferResult,
|
|
1810
|
-
} from '@bloque/sdk/accounts';
|
|
1811
|
-
|
|
1812
|
-
// Identity types
|
|
1813
|
-
import type {
|
|
1814
|
-
Alias,
|
|
1815
|
-
RegisterParams,
|
|
1816
|
-
IndividualRegisterParams,
|
|
1817
|
-
BusinessRegisterParams,
|
|
1818
|
-
RegisterResult,
|
|
1819
|
-
UserProfile,
|
|
1820
|
-
BusinessProfile,
|
|
1821
|
-
AssertionResult,
|
|
1822
|
-
} from '@bloque/sdk/identity';
|
|
1823
|
-
```
|
|
1824
|
-
|
|
1825
|
-
## Development
|
|
1826
|
-
|
|
1827
|
-
### Building the SDK
|
|
1828
|
-
|
|
1829
|
-
```bash
|
|
1830
|
-
bun install
|
|
1831
|
-
bun run build
|
|
1832
|
-
```
|
|
1833
|
-
|
|
1834
|
-
### Development Mode (Watch)
|
|
1835
|
-
|
|
1836
|
-
```bash
|
|
1837
|
-
bun run dev
|
|
1838
|
-
```
|
|
1839
|
-
|
|
1840
|
-
### Type Checking
|
|
1841
|
-
|
|
1842
|
-
```bash
|
|
1843
|
-
bun run typecheck
|
|
1844
|
-
```
|
|
1845
|
-
|
|
1846
|
-
### Code Quality
|
|
1847
|
-
|
|
1848
|
-
```bash
|
|
1849
|
-
bun run check
|
|
1850
|
-
```
|
|
1851
|
-
|
|
1852
|
-
## Requirements
|
|
1853
|
-
|
|
1854
|
-
- One of the supported runtimes: Node.js 22.x+, Bun 1.x+, Deno, or modern browsers
|
|
1855
|
-
- TypeScript 5.x or higher (for TypeScript projects, optional)
|
|
1856
|
-
|
|
1857
|
-
## Links
|
|
1858
|
-
|
|
1859
|
-
- [Homepage](https://www.bloque.app)
|
|
1860
|
-
- [GitHub Repository](https://github.com/bloque-app/sdk)
|
|
1861
|
-
- [Issue Tracker](https://github.com/bloque-app/sdk/issues)
|
|
1862
|
-
|
|
1863
|
-
## Package Structure
|
|
1864
|
-
|
|
1865
|
-
This monorepo contains the following packages:
|
|
1866
|
-
|
|
1867
|
-
- **`@bloque/sdk`**: Main SDK package
|
|
1868
|
-
- **`@bloque/sdk-core`**: Core utilities and HTTP client
|
|
1869
|
-
- **`@bloque/sdk-orgs`**: Organizations API client
|
|
1870
|
-
- **`@bloque/sdk-compliance`**: Compliance and KYC verification API client
|
|
1871
|
-
- **`@bloque/sdk-accounts`**: Accounts and virtual cards API client
|
|
1872
|
-
- **`@bloque/sdk-identity`**: Identity and aliases API client
|
|
675
|
+
- 📧 Email: [support@bloque.app](mailto:support@bloque.app)
|
|
676
|
+
- 💬 Discord: [discord.gg/bloque](https://discord.gg/bloque)
|
|
677
|
+
- 📖 Docs: [docs.bloque.app](https://docs.bloque.app)
|
|
678
|
+
- 🐛 Issues: [GitHub Issues](https://github.com/bloque/sdk/issues)
|
|
1873
679
|
|
|
1874
680
|
## License
|
|
1875
681
|
|
|
1876
|
-
[
|
|
1877
|
-
|
|
682
|
+
MIT © [Bloque](https://www.bloque.app)
|