@bloque/sdk 0.0.23 → 0.0.25
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 +494 -1658
- 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, Polygon wallets, 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,610 @@ 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
|
-
###
|
|
146
|
+
### Full Configuration Options
|
|
136
147
|
|
|
137
|
-
|
|
148
|
+
```typescript
|
|
149
|
+
interface BloqueSDKConfig {
|
|
150
|
+
// Required
|
|
151
|
+
origin: string; // Your origin identifier
|
|
152
|
+
auth: AuthStrategy; // Authentication strategy
|
|
138
153
|
|
|
139
|
-
|
|
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
|
+
}
|
|
140
161
|
|
|
141
|
-
|
|
162
|
+
// Authentication strategies
|
|
163
|
+
type AuthStrategy =
|
|
164
|
+
| { type: 'apiKey'; apiKey: string } // Backend only
|
|
165
|
+
| { type: 'jwt' }; // Frontend (browser/react-native)
|
|
142
166
|
|
|
143
|
-
|
|
144
|
-
|
|
167
|
+
// Platforms
|
|
168
|
+
type Platform = 'node' | 'bun' | 'deno' | 'browser' | 'react-native';
|
|
145
169
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
170
|
+
// Modes
|
|
171
|
+
type Mode = 'production' | 'sandbox';
|
|
172
|
+
|
|
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
|
+
}
|
|
154
180
|
```
|
|
155
181
|
|
|
156
|
-
|
|
182
|
+
## SDK Structure
|
|
157
183
|
|
|
158
|
-
|
|
184
|
+
After connecting to a user session, you have access to these clients:
|
|
159
185
|
|
|
160
186
|
```typescript
|
|
161
|
-
|
|
187
|
+
const session = await bloque.connect('did:bloque:your-origin:user-alias');
|
|
162
188
|
|
|
163
|
-
//
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
});
|
|
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
|
+
```
|
|
170
195
|
|
|
171
|
-
|
|
172
|
-
import AsyncStorage from '@react-native-async-storage/async-storage';
|
|
196
|
+
## Accounts Client
|
|
173
197
|
|
|
174
|
-
|
|
175
|
-
auth: { type: 'jwt' },
|
|
176
|
-
mode: 'production',
|
|
177
|
-
platform: 'react-native',
|
|
178
|
-
tokenStorage: {
|
|
179
|
-
get: async () => await AsyncStorage.getItem('access_token'),
|
|
180
|
-
set: async (token: string) => await AsyncStorage.setItem('access_token', token),
|
|
181
|
-
clear: async () => await AsyncStorage.removeItem('access_token'),
|
|
182
|
-
},
|
|
183
|
-
});
|
|
184
|
-
```
|
|
198
|
+
The accounts client provides access to multiple account types:
|
|
185
199
|
|
|
186
|
-
###
|
|
200
|
+
### Virtual Cards
|
|
201
|
+
|
|
202
|
+
```typescript
|
|
203
|
+
// Create a virtual card
|
|
204
|
+
const card = await session.accounts.card.create({
|
|
205
|
+
name: 'My Card',
|
|
206
|
+
webhookUrl: 'https://your-app.com/webhooks/card',
|
|
207
|
+
});
|
|
187
208
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
- Example: `'my-app'`, `'bloque-root'`, `'ethereum-mainnet'`
|
|
209
|
+
// List cards
|
|
210
|
+
const cards = await session.accounts.card.list();
|
|
191
211
|
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
- Requires storing and managing JWT tokens via `tokenStorage`
|
|
212
|
+
// Check balance
|
|
213
|
+
const balance = await session.accounts.card.balance({
|
|
214
|
+
urn: card.urn,
|
|
215
|
+
});
|
|
197
216
|
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
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
|
+
});
|
|
201
224
|
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
225
|
+
// Update card
|
|
226
|
+
const updated = await session.accounts.card.updateMetadata({
|
|
227
|
+
urn: card.urn,
|
|
228
|
+
metadata: { name: 'Updated Name' },
|
|
229
|
+
});
|
|
206
230
|
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
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
|
+
```
|
|
211
236
|
|
|
212
|
-
###
|
|
237
|
+
### Virtual Accounts
|
|
213
238
|
|
|
214
|
-
|
|
239
|
+
Virtual accounts are simple testing accounts requiring only basic personal information:
|
|
215
240
|
|
|
216
241
|
```typescript
|
|
217
|
-
//
|
|
218
|
-
const
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
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',
|
|
223
249
|
},
|
|
224
|
-
mode: 'production',
|
|
225
250
|
});
|
|
226
251
|
|
|
227
|
-
//
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
const card = await userSession.accounts.card.create({
|
|
232
|
-
urn: 'did:bloque:your-origin:user-alias',
|
|
233
|
-
name: 'My Card',
|
|
252
|
+
// Update metadata
|
|
253
|
+
await session.accounts.virtual.updateMetadata({
|
|
254
|
+
urn: account.urn,
|
|
255
|
+
metadata: { updated_by: 'admin' },
|
|
234
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);
|
|
235
262
|
```
|
|
236
263
|
|
|
237
|
-
|
|
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`
|
|
264
|
+
### Polygon Wallets
|
|
241
265
|
|
|
242
|
-
|
|
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
|
|
266
|
+
Cryptocurrency wallets on the Polygon network for Web3 transactions:
|
|
247
267
|
|
|
248
|
-
|
|
268
|
+
```typescript
|
|
269
|
+
// Create a Polygon wallet (no additional input required)
|
|
270
|
+
const wallet = await session.accounts.polygon.create({
|
|
271
|
+
metadata: {
|
|
272
|
+
purpose: 'web3-transactions',
|
|
273
|
+
project: 'my-dapp',
|
|
274
|
+
},
|
|
275
|
+
});
|
|
249
276
|
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
| `node` | ✅ | ✅ | Required for JWT |
|
|
253
|
-
| `bun` | ✅ | ✅ | Required for JWT |
|
|
254
|
-
| `deno` | ✅ | ✅ | Required for JWT |
|
|
255
|
-
| `browser` | ❌ | ✅ | Optional (uses localStorage) |
|
|
256
|
-
| `react-native` | ❌ | ✅ | Required |
|
|
277
|
+
console.log('Wallet address:', wallet.address);
|
|
278
|
+
console.log('Network:', wallet.network); // "polygon"
|
|
257
279
|
|
|
258
|
-
|
|
280
|
+
// Update metadata
|
|
281
|
+
await session.accounts.polygon.updateMetadata({
|
|
282
|
+
urn: wallet.urn,
|
|
283
|
+
metadata: { environment: 'production' },
|
|
284
|
+
});
|
|
259
285
|
|
|
260
|
-
|
|
286
|
+
// Manage account state
|
|
287
|
+
await session.accounts.polygon.activate(wallet.urn);
|
|
288
|
+
await session.accounts.polygon.freeze(wallet.urn);
|
|
289
|
+
await session.accounts.polygon.disable(wallet.urn);
|
|
290
|
+
```
|
|
261
291
|
|
|
262
|
-
|
|
292
|
+
### Bancolombia Accounts
|
|
263
293
|
|
|
264
|
-
|
|
294
|
+
Colombian virtual accounts with unique reference code system:
|
|
265
295
|
|
|
266
296
|
```typescript
|
|
267
|
-
//
|
|
268
|
-
const
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
```
|
|
297
|
+
// Create a Bancolombia account
|
|
298
|
+
const account = await session.accounts.bancolombia.create({
|
|
299
|
+
name: 'Main Account',
|
|
300
|
+
webhookUrl: 'https://your-app.com/webhooks/bancolombia',
|
|
301
|
+
});
|
|
273
302
|
|
|
274
|
-
|
|
303
|
+
console.log('Reference code:', account.referenceCode);
|
|
275
304
|
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
}
|
|
305
|
+
// Update metadata or name
|
|
306
|
+
await session.accounts.bancolombia.updateMetadata({
|
|
307
|
+
urn: account.urn,
|
|
308
|
+
metadata: { category: 'savings' },
|
|
309
|
+
});
|
|
282
310
|
|
|
283
|
-
|
|
284
|
-
legal_name: string; // Legal name of the organization
|
|
285
|
-
tax_id: string; // Tax ID number
|
|
286
|
-
incorporation_date: string; // Date of incorporation (YYYY-MM-DD)
|
|
287
|
-
business_type: string; // Type of business (e.g., 'llc', 'corporation')
|
|
288
|
-
incorporation_country_code: string; // Country code (ISO 3166-1 alpha-2)
|
|
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
|
-
}
|
|
311
|
+
await session.accounts.bancolombia.updateName(account.urn, 'Savings Account');
|
|
297
312
|
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
postal_code: string; // Postal code
|
|
303
|
-
city: string; // City
|
|
304
|
-
is_primary: boolean; // Whether this is the primary place
|
|
305
|
-
}
|
|
313
|
+
// Manage account state
|
|
314
|
+
await session.accounts.bancolombia.activate(account.urn);
|
|
315
|
+
await session.accounts.bancolombia.freeze(account.urn);
|
|
316
|
+
await session.accounts.bancolombia.disable(account.urn);
|
|
306
317
|
```
|
|
307
318
|
|
|
308
|
-
|
|
319
|
+
### Transfers
|
|
320
|
+
|
|
321
|
+
Transfer funds between any account types:
|
|
309
322
|
|
|
310
323
|
```typescript
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
324
|
+
const result = await session.accounts.transfer({
|
|
325
|
+
sourceUrn: 'did:bloque:account:card:usr-123:crd-456',
|
|
326
|
+
destinationUrn: 'did:bloque:account:virtual:acc-789',
|
|
327
|
+
amount: '1000000', // Amount in smallest unit
|
|
328
|
+
asset: 'DUSD/6', // 'DUSD/6' | 'KSM/12'
|
|
329
|
+
metadata: {
|
|
330
|
+
description: 'Payment for services',
|
|
331
|
+
},
|
|
332
|
+
});
|
|
318
333
|
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
| 'active'
|
|
322
|
-
| 'suspended'
|
|
323
|
-
| 'closed';
|
|
334
|
+
console.log('Transfer queued:', result.queueId);
|
|
335
|
+
console.log('Status:', result.status); // 'queued' | 'processing' | 'completed' | 'failed'
|
|
324
336
|
```
|
|
325
337
|
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
The compliance resource provides KYC (Know Your Customer) verification functionality.
|
|
329
|
-
|
|
330
|
-
#### Start KYC Verification
|
|
338
|
+
## Identity Client
|
|
331
339
|
|
|
332
|
-
|
|
340
|
+
Manage user identities and authentication:
|
|
333
341
|
|
|
334
342
|
```typescript
|
|
335
|
-
//
|
|
336
|
-
const
|
|
337
|
-
|
|
338
|
-
// Start KYC verification
|
|
339
|
-
const verification = await userSession.compliance.kyc.startVerification({
|
|
340
|
-
urn: 'did:bloque:your-origin:user-alias',
|
|
341
|
-
});
|
|
342
|
-
```
|
|
343
|
-
|
|
344
|
-
**Parameters**:
|
|
343
|
+
// Get alias information
|
|
344
|
+
const alias = await session.identity.aliases.get('user@example.com');
|
|
345
345
|
|
|
346
|
-
|
|
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
|
-
```
|
|
346
|
+
// List available origins
|
|
347
|
+
const origins = await session.identity.origins.list();
|
|
366
348
|
|
|
367
|
-
|
|
349
|
+
// Register a new identity (individual)
|
|
350
|
+
const result = await bloque.identity.origins.register(
|
|
351
|
+
'did:bloque:your-origin:ethereum-mainnet',
|
|
352
|
+
{
|
|
353
|
+
assertionResult: {
|
|
354
|
+
alias: '0x742d35Cc...',
|
|
355
|
+
challengeType: 'SIGNING_CHALLENGE',
|
|
356
|
+
value: {
|
|
357
|
+
signature: '0x...',
|
|
358
|
+
alias: '0x742d35Cc...',
|
|
359
|
+
},
|
|
360
|
+
},
|
|
361
|
+
type: 'individual',
|
|
362
|
+
profile: {
|
|
363
|
+
firstName: 'John',
|
|
364
|
+
lastName: 'Doe',
|
|
365
|
+
email: 'john@example.com',
|
|
366
|
+
birthdate: '1990-01-15',
|
|
367
|
+
countryOfResidenceCode: 'US',
|
|
368
|
+
},
|
|
369
|
+
}
|
|
370
|
+
);
|
|
371
|
+
|
|
372
|
+
// Register a business
|
|
373
|
+
const businessResult = await bloque.identity.origins.register(
|
|
374
|
+
'did:bloque:your-origin:ethereum-mainnet',
|
|
375
|
+
{
|
|
376
|
+
assertionResult: { /* ... */ },
|
|
377
|
+
type: 'business',
|
|
378
|
+
profile: {
|
|
379
|
+
legalName: 'Acme Corporation',
|
|
380
|
+
taxId: '123456789',
|
|
381
|
+
incorporationDate: '2020-01-01',
|
|
382
|
+
type: 'llc',
|
|
383
|
+
addressLine1: '123 Main St',
|
|
384
|
+
city: 'San Francisco',
|
|
385
|
+
state: 'CA',
|
|
386
|
+
country: 'US',
|
|
387
|
+
postalCode: '12345',
|
|
388
|
+
// ... other required fields
|
|
389
|
+
},
|
|
390
|
+
}
|
|
391
|
+
);
|
|
368
392
|
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
}
|
|
393
|
+
// OTP-based authentication
|
|
394
|
+
const otpEmail = await bloque.identity.origins.email.assert('user@example.com');
|
|
395
|
+
const otpWhatsApp = await bloque.identity.origins.whatsapp.assert('+1234567890');
|
|
396
|
+
const otpCustom = await bloque.identity.origins.custom('my-origin').assert('user-id');
|
|
374
397
|
```
|
|
375
398
|
|
|
376
|
-
|
|
399
|
+
## Compliance Client
|
|
377
400
|
|
|
378
|
-
|
|
401
|
+
KYC/KYB verification workflows:
|
|
379
402
|
|
|
380
403
|
```typescript
|
|
381
|
-
|
|
404
|
+
// Start KYC verification
|
|
405
|
+
const verification = await session.compliance.kyc.startVerification({
|
|
382
406
|
urn: 'did:bloque:user:123e4567',
|
|
407
|
+
webhookUrl: 'https://your-app.com/webhooks/kyc',
|
|
383
408
|
});
|
|
384
|
-
```
|
|
385
409
|
|
|
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
|
-
```
|
|
410
|
+
console.log('Verification URL:', verification.url);
|
|
411
|
+
console.log('Status:', verification.status);
|
|
399
412
|
|
|
400
|
-
|
|
413
|
+
// Get verification status
|
|
414
|
+
const status = await session.compliance.kyc.getVerification({
|
|
415
|
+
urn: 'did:bloque:user:123e4567',
|
|
416
|
+
});
|
|
401
417
|
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
status: 'awaiting_compliance_verification' | 'approved' | 'rejected';
|
|
405
|
-
url: string; // URL for verification
|
|
406
|
-
completedAt: string | null; // Completion date (ISO 8601)
|
|
407
|
-
}
|
|
418
|
+
console.log('Status:', status.status);
|
|
419
|
+
console.log('Completed at:', status.completedAt);
|
|
408
420
|
```
|
|
409
421
|
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
The accounts resource allows you to create virtual cards for users.
|
|
422
|
+
## Organizations Client
|
|
413
423
|
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
Create a virtual card for a user:
|
|
424
|
+
Create and manage organizations:
|
|
417
425
|
|
|
418
426
|
```typescript
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
427
|
+
const org = await session.orgs.create({
|
|
428
|
+
org_type: 'business',
|
|
429
|
+
profile: {
|
|
430
|
+
legal_name: 'Acme Corporation',
|
|
431
|
+
tax_id: '123456789',
|
|
432
|
+
incorporation_date: '2020-01-01',
|
|
433
|
+
business_type: 'llc',
|
|
434
|
+
incorporation_country_code: 'US',
|
|
435
|
+
incorporation_state: 'CA',
|
|
436
|
+
address_line1: '123 Main St',
|
|
437
|
+
address_line2: 'Suite 100',
|
|
438
|
+
postal_code: '12345',
|
|
439
|
+
city: 'San Francisco',
|
|
440
|
+
},
|
|
441
|
+
metadata: {
|
|
442
|
+
industry: 'technology',
|
|
443
|
+
},
|
|
426
444
|
});
|
|
427
|
-
```
|
|
428
445
|
|
|
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
|
-
}
|
|
446
|
+
console.log('Organization created:', org.urn);
|
|
447
|
+
console.log('Status:', org.status);
|
|
444
448
|
```
|
|
445
449
|
|
|
446
|
-
|
|
450
|
+
## Error Handling
|
|
451
|
+
|
|
452
|
+
The SDK provides specific error types for better error handling:
|
|
447
453
|
|
|
448
454
|
```typescript
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
}
|
|
455
|
+
import {
|
|
456
|
+
BloqueRateLimitError,
|
|
457
|
+
BloqueAuthenticationError,
|
|
458
|
+
BloqueValidationError,
|
|
459
|
+
BloqueNotFoundError,
|
|
460
|
+
BloqueInsufficientFundsError,
|
|
461
|
+
BloqueNetworkError,
|
|
462
|
+
BloqueTimeoutError,
|
|
463
|
+
} from '@bloque/sdk';
|
|
464
|
+
|
|
465
|
+
try {
|
|
466
|
+
const card = await session.accounts.card.create({ name: 'My Card' });
|
|
467
|
+
} catch (error) {
|
|
468
|
+
if (error instanceof BloqueRateLimitError) {
|
|
469
|
+
console.log(`Rate limited. Retry after ${error.retryAfter} seconds`);
|
|
470
|
+
console.log(`Request ID: ${error.requestId}`);
|
|
471
|
+
} else if (error instanceof BloqueValidationError) {
|
|
472
|
+
console.log('Validation errors:', error.validationErrors);
|
|
473
|
+
} else if (error instanceof BloqueAuthenticationError) {
|
|
474
|
+
console.log('Authentication failed. Check your API key.');
|
|
475
|
+
} else if (error instanceof BloqueNotFoundError) {
|
|
476
|
+
console.log(`Resource not found: ${error.resourceType}`);
|
|
477
|
+
} else if (error instanceof BloqueInsufficientFundsError) {
|
|
478
|
+
console.log(`Insufficient funds: ${error.requestedAmount} ${error.currency}`);
|
|
479
|
+
console.log(`Available: ${error.availableBalance} ${error.currency}`);
|
|
480
|
+
} else if (error instanceof BloqueTimeoutError) {
|
|
481
|
+
console.log(`Request timed out after ${error.timeoutMs}ms`);
|
|
482
|
+
} else if (error instanceof BloqueNetworkError) {
|
|
483
|
+
console.log('Network error:', error.message);
|
|
484
|
+
}
|
|
464
485
|
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
pending: string; // Pending balance
|
|
468
|
-
in: string; // Total incoming
|
|
469
|
-
out: string; // Total outgoing
|
|
486
|
+
// All errors have these fields
|
|
487
|
+
console.log('Error details:', error.toJSON());
|
|
470
488
|
}
|
|
471
489
|
```
|
|
472
490
|
|
|
473
|
-
|
|
491
|
+
### Error Metadata
|
|
474
492
|
|
|
475
|
-
|
|
493
|
+
All errors include rich metadata for debugging:
|
|
476
494
|
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
495
|
+
- `message`: Human-readable error message
|
|
496
|
+
- `status`: HTTP status code (if applicable)
|
|
497
|
+
- `code`: Error code from the API
|
|
498
|
+
- `requestId`: Unique request ID for tracing
|
|
499
|
+
- `timestamp`: When the error occurred
|
|
500
|
+
- `response`: Original response body (for debugging)
|
|
501
|
+
- `cause`: Original error (for error chaining)
|
|
481
502
|
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
});
|
|
486
|
-
```
|
|
503
|
+
## Retry Logic
|
|
504
|
+
|
|
505
|
+
The SDK automatically retries failed requests with exponential backoff:
|
|
487
506
|
|
|
488
|
-
**
|
|
507
|
+
- **Retried scenarios**: 429 (Rate Limit), 503 (Service Unavailable), network errors, timeouts
|
|
508
|
+
- **Exponential backoff**: Delay increases exponentially (1s → 2s → 4s)
|
|
509
|
+
- **Jitter**: ±25% random jitter to prevent thundering herd
|
|
510
|
+
- **Respects Retry-After**: Honors the `Retry-After` header when present
|
|
489
511
|
|
|
490
512
|
```typescript
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
513
|
+
const bloque = new SDK({
|
|
514
|
+
origin: 'your-origin',
|
|
515
|
+
auth: { type: 'apiKey', apiKey: 'key' },
|
|
516
|
+
retry: {
|
|
517
|
+
enabled: true, // default: true
|
|
518
|
+
maxRetries: 3, // default: 3
|
|
519
|
+
initialDelay: 1000, // default: 1000ms
|
|
520
|
+
maxDelay: 30000, // default: 30000ms
|
|
521
|
+
},
|
|
522
|
+
});
|
|
499
523
|
```
|
|
500
524
|
|
|
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.
|
|
525
|
+
## Timeout Configuration
|
|
504
526
|
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
Get the current balance for a specific card account:
|
|
527
|
+
Configure request timeouts globally or per-request:
|
|
508
528
|
|
|
509
529
|
```typescript
|
|
510
|
-
|
|
511
|
-
|
|
530
|
+
// Global timeout
|
|
531
|
+
const bloque = new SDK({
|
|
532
|
+
origin: 'your-origin',
|
|
533
|
+
auth: { type: 'apiKey', apiKey: 'key' },
|
|
534
|
+
timeout: 15000, // 15 seconds
|
|
512
535
|
});
|
|
513
|
-
```
|
|
514
536
|
|
|
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
|
-
}
|
|
537
|
+
// Per-request timeout (override global)
|
|
538
|
+
const card = await session.accounts.card.create(
|
|
539
|
+
{ name: 'My Card' },
|
|
540
|
+
{ timeout: 5000 } // 5 seconds for this request
|
|
541
|
+
);
|
|
525
542
|
```
|
|
526
543
|
|
|
527
|
-
|
|
544
|
+
## Security Best Practices
|
|
528
545
|
|
|
529
|
-
|
|
546
|
+
### API Keys
|
|
530
547
|
|
|
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
|
-
```
|
|
548
|
+
- ✅ Store API keys in environment variables
|
|
549
|
+
- ✅ Use different keys for development and production
|
|
550
|
+
- ✅ Never commit API keys to version control
|
|
551
|
+
- ✅ Rotate API keys regularly
|
|
552
|
+
- ❌ Never expose API keys in client-side code
|
|
547
553
|
|
|
548
|
-
|
|
554
|
+
### Token Storage (Frontend)
|
|
549
555
|
|
|
550
|
-
|
|
556
|
+
The SDK warns when using insecure storage:
|
|
551
557
|
|
|
552
558
|
```typescript
|
|
553
|
-
//
|
|
554
|
-
const
|
|
555
|
-
|
|
556
|
-
|
|
559
|
+
// Browser: localStorage (⚠️ vulnerable to XSS)
|
|
560
|
+
const bloque = new SDK({
|
|
561
|
+
auth: { type: 'jwt' },
|
|
562
|
+
platform: 'browser',
|
|
563
|
+
// Uses localStorage by default with security warning
|
|
557
564
|
});
|
|
558
565
|
|
|
559
|
-
//
|
|
560
|
-
const
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
+
// Recommended: httpOnly cookies (immune to XSS)
|
|
567
|
+
const cookieStorage: TokenStorage = {
|
|
568
|
+
get: () => null, // Token sent automatically in cookie
|
|
569
|
+
set: async (token) => {
|
|
570
|
+
await fetch('/api/auth/set-token', {
|
|
571
|
+
method: 'POST',
|
|
572
|
+
body: JSON.stringify({ token }),
|
|
573
|
+
});
|
|
574
|
+
},
|
|
575
|
+
clear: async () => {
|
|
576
|
+
await fetch('/api/auth/logout', { method: 'POST' });
|
|
577
|
+
},
|
|
578
|
+
};
|
|
579
|
+
|
|
580
|
+
const bloque = new SDK({
|
|
581
|
+
auth: { type: 'jwt' },
|
|
582
|
+
platform: 'browser',
|
|
583
|
+
tokenStorage: cookieStorage,
|
|
566
584
|
});
|
|
567
585
|
```
|
|
568
586
|
|
|
569
|
-
|
|
587
|
+
## TypeScript Support
|
|
588
|
+
|
|
589
|
+
The SDK is built with TypeScript and provides full type safety:
|
|
570
590
|
|
|
571
591
|
```typescript
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
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
|
-
```
|
|
592
|
+
import type {
|
|
593
|
+
BloqueSDKConfig,
|
|
594
|
+
CardAccount,
|
|
595
|
+
CreateCardParams,
|
|
596
|
+
VirtualAccount,
|
|
597
|
+
CreateVirtualAccountParams,
|
|
598
|
+
PolygonAccount,
|
|
599
|
+
CreatePolygonAccountParams,
|
|
600
|
+
TransferParams,
|
|
601
|
+
TransferResult,
|
|
602
|
+
} from '@bloque/sdk';
|
|
619
603
|
|
|
620
|
-
|
|
604
|
+
// Type-safe configuration
|
|
605
|
+
const config: BloqueSDKConfig = {
|
|
606
|
+
origin: 'your-origin',
|
|
607
|
+
auth: { type: 'apiKey', apiKey: 'key' },
|
|
608
|
+
mode: 'production',
|
|
609
|
+
};
|
|
621
610
|
|
|
622
|
-
|
|
611
|
+
// Type-safe parameters
|
|
612
|
+
const params: CreateCardParams = {
|
|
613
|
+
name: 'My Card',
|
|
614
|
+
};
|
|
623
615
|
|
|
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
|
-
}
|
|
616
|
+
// Type-safe responses
|
|
617
|
+
const card: CardAccount = await session.accounts.card.create(params);
|
|
651
618
|
```
|
|
652
619
|
|
|
653
|
-
|
|
620
|
+
## Package Exports
|
|
654
621
|
|
|
655
|
-
|
|
622
|
+
The SDK supports modular imports:
|
|
656
623
|
|
|
657
624
|
```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**:
|
|
625
|
+
// Main SDK
|
|
626
|
+
import { SDK } from '@bloque/sdk';
|
|
671
627
|
|
|
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
|
-
```
|
|
628
|
+
// Initialization helper
|
|
629
|
+
import { init } from '@bloque/sdk/init';
|
|
706
630
|
|
|
707
|
-
|
|
631
|
+
// Modular clients (tree-shakeable)
|
|
632
|
+
import { AccountsClient } from '@bloque/sdk/accounts';
|
|
633
|
+
import { IdentityClient } from '@bloque/sdk/identity';
|
|
634
|
+
import { ComplianceClient } from '@bloque/sdk/compliance';
|
|
635
|
+
import { OrgsClient } from '@bloque/sdk/orgs';
|
|
708
636
|
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
637
|
+
// Types
|
|
638
|
+
import type {
|
|
639
|
+
BloqueSDKConfig,
|
|
640
|
+
CardAccount,
|
|
641
|
+
VirtualAccount,
|
|
642
|
+
PolygonAccount,
|
|
643
|
+
BancolombiaAccount,
|
|
644
|
+
} from '@bloque/sdk';
|
|
715
645
|
```
|
|
716
646
|
|
|
717
|
-
|
|
647
|
+
## Advanced Usage
|
|
718
648
|
|
|
719
|
-
###
|
|
649
|
+
### Custom HTTP Client
|
|
720
650
|
|
|
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):
|
|
651
|
+
For advanced use cases, access the HTTP client directly:
|
|
726
652
|
|
|
727
653
|
```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
|
-
});
|
|
654
|
+
const session = await bloque.connect('did:bloque:your-origin:user-alias');
|
|
745
655
|
|
|
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
|
-
}
|
|
656
|
+
// Access the HTTP client
|
|
657
|
+
const httpClient = session.accounts.card['httpClient'];
|
|
658
|
+
|
|
659
|
+
// Make custom requests
|
|
660
|
+
const response = await httpClient.request({
|
|
661
|
+
method: 'GET',
|
|
662
|
+
path: '/api/custom-endpoint',
|
|
663
|
+
timeout: 10000,
|
|
769
664
|
});
|
|
770
665
|
```
|
|
771
666
|
|
|
772
|
-
|
|
667
|
+
### Environment-Specific Configuration
|
|
773
668
|
|
|
774
669
|
```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
|
-
}
|
|
670
|
+
const config: BloqueSDKConfig = {
|
|
671
|
+
origin: process.env.BLOQUE_ORIGIN!,
|
|
672
|
+
auth: {
|
|
673
|
+
type: 'apiKey',
|
|
674
|
+
apiKey: process.env.BLOQUE_API_KEY!,
|
|
675
|
+
},
|
|
676
|
+
mode: process.env.NODE_ENV === 'production' ? 'production' : 'sandbox',
|
|
677
|
+
platform: 'node',
|
|
678
|
+
timeout: Number.parseInt(process.env.BLOQUE_TIMEOUT || '30000', 10),
|
|
679
|
+
retry: {
|
|
680
|
+
enabled: process.env.BLOQUE_RETRY_ENABLED !== 'false',
|
|
681
|
+
maxRetries: Number.parseInt(process.env.BLOQUE_MAX_RETRIES || '3', 10),
|
|
682
|
+
},
|
|
683
|
+
};
|
|
826
684
|
|
|
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
|
-
}
|
|
685
|
+
const bloque = new SDK(config);
|
|
858
686
|
```
|
|
859
687
|
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
```typescript
|
|
863
|
-
interface RegisterResult {
|
|
864
|
-
accessToken: string; // JWT access token for authenticated sessions
|
|
865
|
-
}
|
|
866
|
-
```
|
|
688
|
+
## Examples
|
|
867
689
|
|
|
868
|
-
|
|
690
|
+
See the [`examples/`](./examples) directory for complete working examples:
|
|
869
691
|
|
|
870
|
-
|
|
692
|
+
- `basic-usage.ts` - Basic SDK usage
|
|
693
|
+
- `virtual-cards.ts` - Virtual card management
|
|
694
|
+
- `virtual-accounts.ts` - Virtual account management
|
|
695
|
+
- `transfers.ts` - Account transfers
|
|
696
|
+
- `identity-registration.ts` - User registration
|
|
697
|
+
- `kyc-verification.ts` - KYC workflows
|
|
698
|
+
- `error-handling.ts` - Advanced error handling
|
|
871
699
|
|
|
872
|
-
|
|
873
|
-
const alias = await bloque.identity.aliases.get('user@example.com');
|
|
874
|
-
```
|
|
700
|
+
## API Documentation
|
|
875
701
|
|
|
876
|
-
|
|
702
|
+
For detailed API documentation, visit [docs.bloque.app/sdk](https://docs.bloque.app/sdk).
|
|
877
703
|
|
|
878
|
-
|
|
879
|
-
// Pass the alias string directly
|
|
880
|
-
const alias: string = 'user@example.com' | '+1234567890';
|
|
881
|
-
```
|
|
704
|
+
## Support
|
|
882
705
|
|
|
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
|
|
706
|
+
- 📧 Email: [support@bloque.app](mailto:support@bloque.app)
|
|
707
|
+
- 💬 Discord: [discord.gg/bloque](https://discord.gg/bloque)
|
|
708
|
+
- 📖 Docs: [docs.bloque.app](https://docs.bloque.app)
|
|
709
|
+
- 🐛 Issues: [GitHub Issues](https://github.com/bloque/sdk/issues)
|
|
1873
710
|
|
|
1874
711
|
## License
|
|
1875
712
|
|
|
1876
|
-
[
|
|
1877
|
-
|
|
713
|
+
MIT © [Bloque](https://www.bloque.app)
|