@temple-digital-group/temple-canton-js 2.0.2 → 2.0.3-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/README.md +457 -457
  2. package/index.js +15 -15
  3. package/package.json +50 -49
  4. package/src/api/config.d.ts +20 -20
  5. package/src/api/index.ts +322 -322
  6. package/src/api/tokenStore.ts +30 -30
  7. package/src/api/types.ts +196 -196
  8. package/src/auth0/index.d.ts +1 -1
  9. package/src/auth0/index.js +50 -50
  10. package/src/canton/deposits.ts +563 -563
  11. package/src/canton/helpers.ts +266 -266
  12. package/src/canton/index.d.ts +41 -41
  13. package/src/canton/index.js +3301 -3472
  14. package/src/canton/instrumentCatalog.d.ts +7 -7
  15. package/src/canton/instrumentCatalog.js +283 -283
  16. package/src/canton/request_schemas/cancel_orders_amulet.json +77 -77
  17. package/src/canton/request_schemas/cancel_orders_utility.json +68 -68
  18. package/src/canton/request_schemas/create_order_proposal_amulet.json +94 -94
  19. package/src/canton/request_schemas/create_order_proposal_utility.json +121 -121
  20. package/src/canton/request_schemas/create_utility_credential.json +31 -31
  21. package/src/canton/request_schemas/execute_transfer_factory.json +43 -43
  22. package/src/canton/request_schemas/get_allocation_factory.json +21 -21
  23. package/src/canton/request_schemas/get_amulet_holdings.json +21 -21
  24. package/src/canton/request_schemas/get_instrument_configurations.json +21 -21
  25. package/src/canton/request_schemas/get_locked_amulet_holdings.json +21 -21
  26. package/src/canton/request_schemas/get_order_proposals.json +21 -21
  27. package/src/canton/request_schemas/get_orders.json +21 -21
  28. package/src/canton/request_schemas/get_sender_credentials.json +22 -22
  29. package/src/canton/request_schemas/get_transfer_factory.json +28 -28
  30. package/src/canton/request_schemas/get_utility_holdings.json +21 -21
  31. package/src/canton/request_schemas/unlock_amulet.json +38 -38
  32. package/src/canton/walletAdapter.d.ts +7 -7
  33. package/src/canton/walletAdapter.js +112 -112
  34. package/src/canton/withdrawals.ts +511 -511
  35. package/src/config/index.d.ts +63 -63
  36. package/src/config/index.js +188 -188
  37. package/src/websocket/index.ts +341 -341
  38. package/src/websocket/ws.d.ts +24 -24
package/README.md CHANGED
@@ -1,457 +1,457 @@
1
- # Temple Canton JS
2
-
3
- JavaScript SDK for interacting with the Temple Canton blockchain exchange. Supports Amulet (CC), USDCx, and CBTC tokens on the Canton network.
4
-
5
- ## Installation
6
-
7
- ```bash
8
- npm install @temple-digital-group/temple-canton-js
9
- ```
10
-
11
- ## Configuration
12
-
13
- Call `initialize()` before using any SDK functions. It sets up the config and optionally authenticates with the Temple REST API.
14
-
15
- ### Wallet Adapter
16
-
17
- For apps using Loop Wallet. Pass the Loop SDK instance as `WALLET_ADAPTER` — the SDK auto-detects server vs client mode.
18
-
19
- - **Server-side:** uses `loop.executeTransaction()` (signs locally with private key)
20
- - **Client-side:** uses `loop.provider.submitTransaction()` (delegates signing to Loop Wallet via WebSocket)
21
-
22
- ```javascript
23
- import { initialize } from "@temple-digital-group/temple-canton-js";
24
-
25
- initialize({
26
- API_KEY: "your-api-key",
27
- NETWORK: "mainnet",
28
- WALLET_ADAPTER: loop, // Pass the Loop SDK instance
29
- });
30
- ```
31
-
32
- You can also set or change the wallet adapter after init:
33
-
34
- ```javascript
35
- import { setWalletAdapter } from "@temple-digital-group/temple-canton-js";
36
-
37
- setWalletAdapter(loop);
38
- ```
39
-
40
- | Key | Required | Description |
41
- | ---------------- | -------- | --------------------------------------------------------------- |
42
- | `API_KEY` | Yes | Temple REST API key |
43
- | `NETWORK` | Yes | `mainnet` or `testnet` |
44
- | `WALLET_ADAPTER` | Yes | Loop SDK instance — auto-detects server/client mode for signing |
45
-
46
- ## Supported Instruments
47
-
48
- | Asset | Type | Networks |
49
- | ----- | ----------- | ---------------- |
50
- | CC | Canton Coin | testnet, mainnet |
51
- | USDCx | Utility | testnet, mainnet |
52
- | CBTC | Utility | testnet, mainnet |
53
-
54
- > **Symbol normalization:** Use `CC` for Canton Coin in all SDK methods. The SDK handles the internal conversion to `Amulet` where required by the ledger. The `Amulet` symbol is deprecated — all API responses now return `CC`.
55
-
56
- ## Supported Trading Pairs
57
-
58
- - `CC/USDCx`
59
- - `CBTC/USDCx`
60
-
61
- ## v2 Trading Flow
62
-
63
- The v2 flow covers the full trading lifecycle: onboarding, deposits, trading, and withdrawals.
64
-
65
- ```
66
- 1. Check onboarding → isUserOnboarded(party)
67
- If NOT onboarded → onboardUser(party)
68
-
69
- 2. Deposit funds → deposit(amount, symbol)
70
-
71
- 3. Check balance → getTradingBalance()
72
-
73
- 4. Place orders → createOrderRequest({ symbol, side, quantity, price, ... })
74
-
75
- 5. Cancel orders → cancelOrder(orderId) or cancelAllOrders({ symbol })
76
-
77
- 6. Withdraw funds → withdrawFunds({ asset_id, amount })
78
-
79
- 7. Withdraw delegation → withdrawDelegation(delegationId, user)
80
- ```
81
-
82
- ### 1. Onboarding
83
-
84
- Check if a user has a delegation contract, and create one if not:
85
-
86
- ```javascript
87
- import { isUserOnboarded, onboardUser } from "@temple-digital-group/temple-canton-js";
88
-
89
- const delegation = await isUserOnboarded(party);
90
- if (!delegation) {
91
- const result = await onboardUser({ partyId: party });
92
- // result.delegation — the confirmed delegation contract
93
- // result.warning — set if onboarding was submitted but not confirmed within 60s
94
- }
95
- ```
96
-
97
- `onboardUser` submits the onboarding request and then polls `isUserOnboarded` every 5 seconds for up to 60 seconds. It returns once the delegation is confirmed, or with a `warning` field if the timeout is reached.
98
-
99
- ### 2. Deposit Funds
100
-
101
- The simplest way to deposit is the `deposit()` helper — pass the amount and symbol, and it handles everything:
102
-
103
- ```javascript
104
- import { deposit } from "@temple-digital-group/temple-canton-js";
105
-
106
- const result = await deposit(100, "USDCx");
107
- // or
108
- const result = await deposit(10, "CC");
109
- ```
110
-
111
- `deposit()` requires the wallet adapter to be connected. It:
112
- 1. Checks your CC balance to ensure at least 10 CC is reserved for transaction fees
113
- 2. For utility deposits (USDCx, CBTC), verifies you have enough of the token **and** 10 CC for fees
114
- 3. Selects the right UTXOs from your wallet
115
- 4. Submits the deposit allocation
116
-
117
- If you need more control, use `prepareDepositHoldings` + `depositFunds` directly:
118
-
119
- ```javascript
120
- import { prepareDepositHoldings, depositFunds } from "@temple-digital-group/temple-canton-js";
121
-
122
- const depositOpts = await prepareDepositHoldings(100, "USDCx");
123
- const result = await depositFunds(depositOpts);
124
- ```
125
-
126
- ### 3. Trading Balance
127
-
128
- ```javascript
129
- import { getTradingBalance } from "@temple-digital-group/temple-canton-js";
130
-
131
- const balances = await getTradingBalance();
132
- // Returns { balances: [{ asset, unlocked, locked, in_flight, ... }] }
133
- ```
134
-
135
- Use this to check available funds before placing orders or withdrawals.
136
-
137
- ### 4. Place Orders
138
-
139
- ```javascript
140
- import { createOrderRequest } from "@temple-digital-group/temple-canton-js";
141
-
142
- const result = await createOrderRequest({
143
- symbol: "CC/USDCx",
144
- side: "buy",
145
- quantity: 10.5,
146
- price: 1.25,
147
- order_type: "limit",
148
- });
149
-
150
- // Post-only order (rejected if it would match immediately)
151
- const postOnly = await createOrderRequest({
152
- symbol: "CC/USDCx",
153
- side: "buy",
154
- quantity: 10.5,
155
- price: 1.25,
156
- order_type: "limit",
157
- order_subtype: "post_only",
158
- });
159
- ```
160
-
161
- ### 5. Cancel Orders
162
-
163
- ```javascript
164
- import { cancelOrder, cancelAllOrders } from "@temple-digital-group/temple-canton-js";
165
-
166
- // Cancel a specific order
167
- await cancelOrder("ord_abc123");
168
-
169
- // Cancel all orders for a symbol
170
- await cancelAllOrders({ symbol: "CC/USDCx" });
171
-
172
- // Cancel ALL orders
173
- await cancelAllOrders();
174
- ```
175
-
176
- ### 6. Withdraw Funds
177
-
178
- Withdraws available (unlocked, non-in-flight) trading balance back to the user's wallet.
179
-
180
- ```javascript
181
- import { withdrawFunds } from "@temple-digital-group/temple-canton-js";
182
-
183
- const result = await withdrawFunds({
184
- asset_id: "USDCx",
185
- amount: "250.50",
186
- });
187
- ```
188
-
189
- ### 7. Withdraw Delegation
190
-
191
- Archives the user's delegation contract. The user must re-onboard to trade again.
192
-
193
- ```javascript
194
- import { withdrawDelegation } from "@temple-digital-group/temple-canton-js";
195
-
196
- // Auto-fetches delegation from API if not passed
197
- await withdrawDelegation();
198
-
199
- // Or pass explicitly
200
- await withdrawDelegation(delegationContractId, partyId);
201
- ```
202
-
203
- ### Get User Balances
204
-
205
- ```javascript
206
- import { getUserBalances } from "@temple-digital-group/temple-canton-js";
207
-
208
- // Both params are optional — falls back to wallet adapter / config
209
- const balances = await getUserBalances();
210
-
211
- // Or pass explicitly
212
- const balances = await getUserBalances(partyId);
213
- const balances = await getUserBalances(partyId, walletProvider);
214
- ```
215
-
216
- Each entry in the returned array contains:
217
-
218
- ```javascript
219
- {
220
- asset: 'USDCx',
221
- total_balance: 170.5,
222
- available_balance: 150.5,
223
- locked_balance: 20.0,
224
- dso: null,
225
- registrar: '...',
226
- operator: '...',
227
- provider: '...',
228
- merge_warning: true,
229
- holdings: [...],
230
- locked_holdings: [...],
231
- utilityContext: { ... }
232
- }
233
- ```
234
-
235
- ### Merge Holdings
236
-
237
- ```javascript
238
- import { mergeAmuletHoldingsForParty, mergeUtilityHoldingsForParty, getAmuletDisclosures, getUtxoCount } from "@temple-digital-group/temple-canton-js";
239
-
240
- // Merge all Amulet or utility holdings
241
- await mergeAmuletHoldingsForParty(partyId);
242
- await mergeUtilityHoldingsForParty(partyId, "USDCx");
243
-
244
- // Wallet Provider — merge up to 5 smallest USDCx UTXOs
245
- const command = await mergeUtilityHoldingsForParty(partyId, "USDCx", true, walletProvider, 5);
246
- const result = await walletProvider.submitTransaction(command);
247
-
248
- // Wallet Provider — merge CC (requires disclosures)
249
- const disclosures = await getAmuletDisclosures(partyId);
250
- const cmd = await mergeAmuletHoldingsForParty(partyId, true, walletProvider, 5, disclosures);
251
- const res = await walletProvider.submitTransaction(cmd);
252
-
253
- // Check UTXO status after merge
254
- const counts = await getUtxoCount(partyId, "USDCx", walletProvider);
255
- ```
256
-
257
- ## WebSocket — Real-Time Data
258
-
259
- Subscribe to live market data and user events via WebSocket. Works in both Node.js and browsers.
260
-
261
- The server has two types of data:
262
-
263
- - **Market data** — public channels you explicitly subscribe to (orderbook, trades, ticker, candles, oracle)
264
- - **User data** — automatically pushed after authentication, no subscribe needed (orders, trades, balances)
265
-
266
- ```javascript
267
- import {
268
- subscribeOrderbook,
269
- subscribeTrades,
270
- subscribeTicker,
271
- subscribeCandles,
272
- subscribeUserOrders,
273
- subscribeUserTrades,
274
- subscribeUserBalances,
275
- disconnectWebSocket,
276
- } from "@temple-digital-group/temple-canton-js";
277
-
278
- // Market data — sends a subscribe message to the server
279
- const unsub = subscribeOrderbook("Amulet/USDCx", (data) => {
280
- console.log("Orderbook update:", data);
281
- });
282
- subscribeTrades("Amulet/USDCx", (data) => console.log("Trade:", data));
283
- subscribeTicker("CBTC/USDCx", (data) => console.log("Ticker:", data));
284
- subscribeCandles("Amulet/USDCx", 60, (data) => console.log("1m candle:", data));
285
-
286
- // User data — auto-delivered after auth, no subscribe message needed
287
- subscribeUserOrders((data) => console.log("Order update:", data));
288
- subscribeUserTrades((data) => console.log("Trade fill:", data));
289
- subscribeUserBalances((data) => console.log("Balance update:", data));
290
-
291
- // Unsubscribe from a specific channel
292
- unsub();
293
-
294
- // Disconnect everything
295
- disconnectWebSocket();
296
- ```
297
-
298
- ### Market Data Channels
299
-
300
- These require an explicit subscribe message. The SDK handles this automatically.
301
-
302
- | Function | Channel | Example |
303
- | ------------------------------------------- | -------------------------------- | ------------------------- |
304
- | `subscribeOrderbook(symbol, cb)` | `orderbook:{symbol}` | `orderbook:Amulet/USDCx` |
305
- | `subscribeTrades(symbol, cb)` | `trades:{symbol}` | `trades:Amulet/USDCx` |
306
- | `subscribeTicker(symbol, cb)` | `ticker:{symbol}` | `ticker:CBTC/USDCx` |
307
- | `subscribeCandles(symbol, granularity, cb)` | `candles:{symbol}:{granularity}` | `candles:Amulet/USDCx:60`|
308
- | `subscribeOracle(symbol, cb)` | `oracle:{symbol}` | `oracle:cc` |
309
- | `subscribeOracleVolume(symbol, cb)` | `oracle_volume:{symbol}` | `oracle_volume:cc` |
310
-
311
- **Candle granularity values:** `60` (1m), `300` (5m), `900` (15m), `3600` (1h), `14400` (4h), `86400` (1d)
312
-
313
- ### User Data Events
314
-
315
- Pushed automatically by the server after authentication. No subscribe message is sent — you just register a local handler. Requires `API_KEY` (Node.js) or cookie auth (browser).
316
-
317
- | Function | Server Event | Description |
318
- | -------------------------- | -------------- | -------------------------------------------------- |
319
- | `subscribeUserOrders(cb)` | `user_order` | Order lifecycle updates (created, filled, cancelled)|
320
- | `subscribeUserTrades(cb)` | `user_trade` | Trade fill confirmations |
321
- | `subscribeUserBalances(cb)`| `user_balance` | Balance changes |
322
-
323
- ### Advanced Usage
324
-
325
- Use the `TempleWebSocket` class directly for full control:
326
-
327
- ```javascript
328
- import { TempleWebSocket } from "@temple-digital-group/temple-canton-js";
329
-
330
- const ws = new TempleWebSocket();
331
- ws.onConnect = () => console.log("Connected");
332
- ws.onDisconnect = (code, reason) => console.log("Disconnected:", code, reason);
333
- ws.onAuth = (success, userId) => console.log("Auth:", success, userId);
334
- ws.onError = (err) => console.error("WS error:", err);
335
- ws.autoReconnect = true; // default — reconnects with exponential backoff
336
- ws.connect();
337
-
338
- // Market data — sends subscribe to server
339
- const unsub = ws.subscribe("orderbook:Amulet/USDCx", (data) => { ... });
340
-
341
- // User data — no subscribe message, just local handler
342
- const unsubOrder = ws.onUserEvent("user_order", (data) => { ... });
343
- ```
344
-
345
- ## API Reference
346
-
347
- > Functions marked with **W** support Loop Wallet via the wallet adapter.
348
-
349
- ### Configuration
350
-
351
- | Function | Description |
352
- | --------------------------- | ----------------------------------------------------------------------------- |
353
- | `initialize(config)` | Initialize the SDK, set config, and optionally authenticate with the REST API |
354
- | `setWalletAdapter(adapter)` | Set or update the Loop SDK instance for all wallet-aware functions |
355
-
356
- ### Instrument Catalog
357
-
358
- | Function | Description |
359
- | ---------------------------- | --------------------------------------- |
360
- | `getSupportedTradingPairs()` | Get the list of supported trading pairs |
361
- | `getInstrumentCatalog()` | Get the full instrument catalog |
362
-
363
- ### Onboarding & Delegation
364
-
365
- | Function | Provider | Description |
366
- | ------------------------------------------ | -------- | ------------------------------------------------------ |
367
- | `isUserOnboarded(party)` | **W** | Check if user has a delegation contract on ledger |
368
- | `onboardUser(party)` | **W** | Create the delegation contract needed for trading |
369
- | `withdrawDelegation(delegationId?, user?)` | **W** | Archive the delegation contract (user must re-onboard) |
370
-
371
- ### Deposits & Withdrawals
372
-
373
- | Function | Provider | Description |
374
- | ----------------------------------------- | -------- | ----------------------------------------------------- |
375
- | `deposit(amount, symbol)` | **W** | Deposit funds (validates balance, reserves 10 CC for fees) |
376
- | `prepareDepositHoldings(amount, assetId)` | **W** | Resolve holdings for a deposit amount (low-level) |
377
- | `depositFunds(opts)` | **W** | Submit deposit allocation (low-level) |
378
- | `withdrawFunds({ asset_id, amount })` | **W** | Withdraw available trading balance back to wallet |
379
- | `emergencyWithdrawFunds(opts)` | **W** | Cancel all orders and withdraw everything immediately |
380
-
381
- ### Holdings
382
-
383
- | Function | Provider | Description |
384
- | ----------------------------------------------------------------- | -------- | ----------------------------------------------------------------------------- |
385
- | `getUserBalances(party?, provider?)` | **W** | Get all balances grouped by asset (Amulet, locked, and utility) |
386
- | `getAmuletHoldingsForParty(party, returnCommand, provider)` | **W** | Get Amulet holdings |
387
- | `getLockedAmuletHoldingsForParty(party, returnCommand, provider)` | **W** | Get locked Amulet holdings |
388
- | `getUtilityHoldingsForParty(party, returnCommand, provider)` | **W** | Get utility token holdings |
389
- | `getUtxoCount(party, assetId, provider)` | **W** | Get UTXO summary: counts, largest unlocked amount, and total unlocked balance |
390
-
391
- ### Holding Operations
392
-
393
- | Function | Provider | Description |
394
- | ------------------------------------------------------------------------------------------ | -------- | ------------------------------- |
395
- | `mergeAmuletHoldingsForParty(party, returnCommand, provider, maxUtxos, amuletDisclosures)` | **W** | Merge Amulet holdings into one |
396
- | `mergeUtilityHoldingsForParty(party, utilityAsset, returnCommand, provider, maxUtxos)` | **W** | Merge utility holdings into one |
397
-
398
- ### Temple REST API
399
-
400
- > These functions call the Temple REST API. Pass `API_KEY` in `initialize()` or call `setApiKey()` to authenticate.
401
-
402
- #### Auth
403
-
404
- | Function | Description |
405
- | ---------------- | ------------------------------------------- |
406
- | `setApiKey(key)` | Set the API key for REST API authentication |
407
- | `getUserId()` | Get the stored user ID |
408
-
409
- #### Market Data
410
-
411
- | Function | Description |
412
- | ----------------------------------- | --------------------------------------------------------- |
413
- | `getTicker(symbol?)` | Get ticker data for one or all trading pairs |
414
- | `getOrderBook(symbol, options?)` | Get the order book (options: `levels`, `precision`) |
415
- | `getSymbolConfig(symbol)` | Get symbol configuration (paused, decimals, min quantity) |
416
- | `getOpenInterest(symbol)` | Get open interest for a trading pair |
417
- | `getRecentTrades(symbol, options?)` | Get recent trades (options: `limit`, max 500) |
418
-
419
- #### Trading
420
-
421
- | Function | Description |
422
- | ----------------------------------- | ------------------------------------------------------ |
423
- | `createOrderRequest(opts)` | Place a buy/sell order via the trading backend |
424
- | `cancelOrder(orderId)` | Cancel a specific order |
425
- | `cancelAllOrders(options?)` | Cancel all orders (options: `symbol` filter) |
426
- | `getTradingBalance()` | Get user's trading balance (unlocked/locked/in-flight) |
427
- | `getActiveOrders(options?)` | Get active orders (options: `symbol`, `limit`) |
428
-
429
- #### Withdrawals
430
-
431
- | Function | Description |
432
- | ------------------------------------------ | ------------------------------------------ |
433
- | `createWithdrawalRequest(assetId, amount)` | Submit a withdrawal request to the backend |
434
- | `getWithdrawalRequestStatus(requestId)` | Poll withdrawal status until ready |
435
-
436
- #### Disclosures & Delegation
437
-
438
- | Function | Description |
439
- | ------------------------- | ---------------------------------------------------------------------------- |
440
- | `getDisclosures(partyId)` | Get Amulet disclosure data (factory ID, choice context, disclosed contracts) |
441
- | `getDelegation()` | Get the user's delegation contract from the API |
442
-
443
- ### WebSocket
444
-
445
- | Function | Description |
446
- | ------------------------------------------- | -------------------------------------------------------------- |
447
- | `createWebSocket()` | Get or create the shared WS instance (auto-connects) |
448
- | `disconnectWebSocket()` | Disconnect and destroy the shared WS instance |
449
- | `subscribeOrderbook(symbol, cb)` | Subscribe to orderbook updates |
450
- | `subscribeTrades(symbol, cb)` | Subscribe to trade updates |
451
- | `subscribeTicker(symbol, cb)` | Subscribe to ticker updates |
452
- | `subscribeCandles(symbol, granularity, cb)` | Subscribe to candle updates |
453
- | `subscribeOracle(symbol, cb)` | Subscribe to oracle price updates |
454
- | `subscribeOracleVolume(symbol, cb)` | Subscribe to oracle volume updates |
455
- | `subscribeUserOrders(cb)` | Listen to user order events (auto-pushed, no subscribe needed) |
456
- | `subscribeUserTrades(cb)` | Listen to user trade events (auto-pushed, no subscribe needed) |
457
- | `subscribeUserBalances(cb)` | Listen to user balance events (auto-pushed, no subscribe needed)|
1
+ # Temple Canton JS
2
+
3
+ JavaScript SDK for interacting with the Temple Canton blockchain exchange. Supports Amulet (CC), USDCx, and CBTC tokens on the Canton network.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @temple-digital-group/temple-canton-js
9
+ ```
10
+
11
+ ## Configuration
12
+
13
+ Call `initialize()` before using any SDK functions. It sets up the config and optionally authenticates with the Temple REST API.
14
+
15
+ ### Wallet Adapter
16
+
17
+ For apps using Loop Wallet. Pass the Loop SDK instance as `WALLET_ADAPTER` — the SDK auto-detects server vs client mode.
18
+
19
+ - **Server-side:** uses `loop.executeTransaction()` (signs locally with private key)
20
+ - **Client-side:** uses `loop.provider.submitTransaction()` (delegates signing to Loop Wallet via WebSocket)
21
+
22
+ ```javascript
23
+ import { initialize } from "@temple-digital-group/temple-canton-js";
24
+
25
+ initialize({
26
+ API_KEY: "your-api-key",
27
+ NETWORK: "mainnet",
28
+ WALLET_ADAPTER: loop, // Pass the Loop SDK instance
29
+ });
30
+ ```
31
+
32
+ You can also set or change the wallet adapter after init:
33
+
34
+ ```javascript
35
+ import { setWalletAdapter } from "@temple-digital-group/temple-canton-js";
36
+
37
+ setWalletAdapter(loop);
38
+ ```
39
+
40
+ | Key | Required | Description |
41
+ | ---------------- | -------- | --------------------------------------------------------------- |
42
+ | `API_KEY` | Yes | Temple REST API key |
43
+ | `NETWORK` | Yes | `mainnet` or `testnet` |
44
+ | `WALLET_ADAPTER` | Yes | Loop SDK instance — auto-detects server/client mode for signing |
45
+
46
+ ## Supported Instruments
47
+
48
+ | Asset | Type | Networks |
49
+ | ----- | ----------- | ---------------- |
50
+ | CC | Canton Coin | testnet, mainnet |
51
+ | USDCx | Utility | testnet, mainnet |
52
+ | CBTC | Utility | testnet, mainnet |
53
+
54
+ > **Symbol normalization:** Use `CC` for Canton Coin in all SDK methods. The SDK handles the internal conversion to `Amulet` where required by the ledger. The `Amulet` symbol is deprecated — all API responses now return `CC`.
55
+
56
+ ## Supported Trading Pairs
57
+
58
+ - `CC/USDCx`
59
+ - `CBTC/USDCx`
60
+
61
+ ## v2 Trading Flow
62
+
63
+ The v2 flow covers the full trading lifecycle: onboarding, deposits, trading, and withdrawals.
64
+
65
+ ```
66
+ 1. Check onboarding → isUserOnboarded(party)
67
+ If NOT onboarded → onboardUser(party)
68
+
69
+ 2. Deposit funds → deposit(amount, symbol)
70
+
71
+ 3. Check balance → getTradingBalance()
72
+
73
+ 4. Place orders → createOrderRequest({ symbol, side, quantity, price, ... })
74
+
75
+ 5. Cancel orders → cancelOrder(orderId) or cancelAllOrders({ symbol })
76
+
77
+ 6. Withdraw funds → withdrawFunds({ asset_id, amount })
78
+
79
+ 7. Withdraw delegation → withdrawDelegation(delegationId, user)
80
+ ```
81
+
82
+ ### 1. Onboarding
83
+
84
+ Check if a user has a delegation contract, and create one if not:
85
+
86
+ ```javascript
87
+ import { isUserOnboarded, onboardUser } from "@temple-digital-group/temple-canton-js";
88
+
89
+ const delegation = await isUserOnboarded(party);
90
+ if (!delegation) {
91
+ const result = await onboardUser({ partyId: party });
92
+ // result.delegation — the confirmed delegation contract
93
+ // result.warning — set if onboarding was submitted but not confirmed within 60s
94
+ }
95
+ ```
96
+
97
+ `onboardUser` submits the onboarding request and then polls `isUserOnboarded` every 5 seconds for up to 60 seconds. It returns once the delegation is confirmed, or with a `warning` field if the timeout is reached.
98
+
99
+ ### 2. Deposit Funds
100
+
101
+ The simplest way to deposit is the `deposit()` helper — pass the amount and symbol, and it handles everything:
102
+
103
+ ```javascript
104
+ import { deposit } from "@temple-digital-group/temple-canton-js";
105
+
106
+ const result = await deposit(100, "USDCx");
107
+ // or
108
+ const result = await deposit(10, "CC");
109
+ ```
110
+
111
+ `deposit()` requires the wallet adapter to be connected. It:
112
+ 1. Checks your CC balance to ensure at least 10 CC is reserved for transaction fees
113
+ 2. For utility deposits (USDCx, CBTC), verifies you have enough of the token **and** 10 CC for fees
114
+ 3. Selects the right UTXOs from your wallet
115
+ 4. Submits the deposit allocation
116
+
117
+ If you need more control, use `prepareDepositHoldings` + `depositFunds` directly:
118
+
119
+ ```javascript
120
+ import { prepareDepositHoldings, depositFunds } from "@temple-digital-group/temple-canton-js";
121
+
122
+ const depositOpts = await prepareDepositHoldings(100, "USDCx");
123
+ const result = await depositFunds(depositOpts);
124
+ ```
125
+
126
+ ### 3. Trading Balance
127
+
128
+ ```javascript
129
+ import { getTradingBalance } from "@temple-digital-group/temple-canton-js";
130
+
131
+ const balances = await getTradingBalance();
132
+ // Returns { balances: [{ asset, unlocked, locked, in_flight, ... }] }
133
+ ```
134
+
135
+ Use this to check available funds before placing orders or withdrawals.
136
+
137
+ ### 4. Place Orders
138
+
139
+ ```javascript
140
+ import { createOrderRequest } from "@temple-digital-group/temple-canton-js";
141
+
142
+ const result = await createOrderRequest({
143
+ symbol: "CC/USDCx",
144
+ side: "buy",
145
+ quantity: 10.5,
146
+ price: 1.25,
147
+ order_type: "limit",
148
+ });
149
+
150
+ // Post-only order (rejected if it would match immediately)
151
+ const postOnly = await createOrderRequest({
152
+ symbol: "CC/USDCx",
153
+ side: "buy",
154
+ quantity: 10.5,
155
+ price: 1.25,
156
+ order_type: "limit",
157
+ order_subtype: "post_only",
158
+ });
159
+ ```
160
+
161
+ ### 5. Cancel Orders
162
+
163
+ ```javascript
164
+ import { cancelOrder, cancelAllOrders } from "@temple-digital-group/temple-canton-js";
165
+
166
+ // Cancel a specific order
167
+ await cancelOrder("ord_abc123");
168
+
169
+ // Cancel all orders for a symbol
170
+ await cancelAllOrders({ symbol: "CC/USDCx" });
171
+
172
+ // Cancel ALL orders
173
+ await cancelAllOrders();
174
+ ```
175
+
176
+ ### 6. Withdraw Funds
177
+
178
+ Withdraws available (unlocked, non-in-flight) trading balance back to the user's wallet.
179
+
180
+ ```javascript
181
+ import { withdrawFunds } from "@temple-digital-group/temple-canton-js";
182
+
183
+ const result = await withdrawFunds({
184
+ asset_id: "USDCx",
185
+ amount: "250.50",
186
+ });
187
+ ```
188
+
189
+ ### 7. Withdraw Delegation
190
+
191
+ Archives the user's delegation contract. The user must re-onboard to trade again.
192
+
193
+ ```javascript
194
+ import { withdrawDelegation } from "@temple-digital-group/temple-canton-js";
195
+
196
+ // Auto-fetches delegation from API if not passed
197
+ await withdrawDelegation();
198
+
199
+ // Or pass explicitly
200
+ await withdrawDelegation(delegationContractId, partyId);
201
+ ```
202
+
203
+ ### Get User Balances
204
+
205
+ ```javascript
206
+ import { getUserBalances } from "@temple-digital-group/temple-canton-js";
207
+
208
+ // Both params are optional — falls back to wallet adapter / config
209
+ const balances = await getUserBalances();
210
+
211
+ // Or pass explicitly
212
+ const balances = await getUserBalances(partyId);
213
+ const balances = await getUserBalances(partyId, walletProvider);
214
+ ```
215
+
216
+ Each entry in the returned array contains:
217
+
218
+ ```javascript
219
+ {
220
+ asset: 'USDCx',
221
+ total_balance: 170.5,
222
+ available_balance: 150.5,
223
+ locked_balance: 20.0,
224
+ dso: null,
225
+ registrar: '...',
226
+ operator: '...',
227
+ provider: '...',
228
+ merge_warning: true,
229
+ holdings: [...],
230
+ locked_holdings: [...],
231
+ utilityContext: { ... }
232
+ }
233
+ ```
234
+
235
+ ### Merge Holdings
236
+
237
+ ```javascript
238
+ import { mergeAmuletHoldingsForParty, mergeUtilityHoldingsForParty, getAmuletDisclosures, getUtxoCount } from "@temple-digital-group/temple-canton-js";
239
+
240
+ // Merge all Amulet or utility holdings
241
+ await mergeAmuletHoldingsForParty(partyId);
242
+ await mergeUtilityHoldingsForParty(partyId, "USDCx");
243
+
244
+ // Wallet Provider — merge up to 5 smallest USDCx UTXOs
245
+ const command = await mergeUtilityHoldingsForParty(partyId, "USDCx", true, walletProvider, 5);
246
+ const result = await walletProvider.submitTransaction(command);
247
+
248
+ // Wallet Provider — merge CC (requires disclosures)
249
+ const disclosures = await getAmuletDisclosures(partyId);
250
+ const cmd = await mergeAmuletHoldingsForParty(partyId, true, walletProvider, 5, disclosures);
251
+ const res = await walletProvider.submitTransaction(cmd);
252
+
253
+ // Check UTXO status after merge
254
+ const counts = await getUtxoCount(partyId, "USDCx", walletProvider);
255
+ ```
256
+
257
+ ## WebSocket — Real-Time Data
258
+
259
+ Subscribe to live market data and user events via WebSocket. Works in both Node.js and browsers.
260
+
261
+ The server has two types of data:
262
+
263
+ - **Market data** — public channels you explicitly subscribe to (orderbook, trades, ticker, candles, oracle)
264
+ - **User data** — automatically pushed after authentication, no subscribe needed (orders, trades, balances)
265
+
266
+ ```javascript
267
+ import {
268
+ subscribeOrderbook,
269
+ subscribeTrades,
270
+ subscribeTicker,
271
+ subscribeCandles,
272
+ subscribeUserOrders,
273
+ subscribeUserTrades,
274
+ subscribeUserBalances,
275
+ disconnectWebSocket,
276
+ } from "@temple-digital-group/temple-canton-js";
277
+
278
+ // Market data — sends a subscribe message to the server
279
+ const unsub = subscribeOrderbook("Amulet/USDCx", (data) => {
280
+ console.log("Orderbook update:", data);
281
+ });
282
+ subscribeTrades("Amulet/USDCx", (data) => console.log("Trade:", data));
283
+ subscribeTicker("CBTC/USDCx", (data) => console.log("Ticker:", data));
284
+ subscribeCandles("Amulet/USDCx", 60, (data) => console.log("1m candle:", data));
285
+
286
+ // User data — auto-delivered after auth, no subscribe message needed
287
+ subscribeUserOrders((data) => console.log("Order update:", data));
288
+ subscribeUserTrades((data) => console.log("Trade fill:", data));
289
+ subscribeUserBalances((data) => console.log("Balance update:", data));
290
+
291
+ // Unsubscribe from a specific channel
292
+ unsub();
293
+
294
+ // Disconnect everything
295
+ disconnectWebSocket();
296
+ ```
297
+
298
+ ### Market Data Channels
299
+
300
+ These require an explicit subscribe message. The SDK handles this automatically.
301
+
302
+ | Function | Channel | Example |
303
+ | ------------------------------------------- | -------------------------------- | ------------------------- |
304
+ | `subscribeOrderbook(symbol, cb)` | `orderbook:{symbol}` | `orderbook:Amulet/USDCx` |
305
+ | `subscribeTrades(symbol, cb)` | `trades:{symbol}` | `trades:Amulet/USDCx` |
306
+ | `subscribeTicker(symbol, cb)` | `ticker:{symbol}` | `ticker:CBTC/USDCx` |
307
+ | `subscribeCandles(symbol, granularity, cb)` | `candles:{symbol}:{granularity}` | `candles:Amulet/USDCx:60`|
308
+ | `subscribeOracle(symbol, cb)` | `oracle:{symbol}` | `oracle:cc` |
309
+ | `subscribeOracleVolume(symbol, cb)` | `oracle_volume:{symbol}` | `oracle_volume:cc` |
310
+
311
+ **Candle granularity values:** `60` (1m), `300` (5m), `900` (15m), `3600` (1h), `14400` (4h), `86400` (1d)
312
+
313
+ ### User Data Events
314
+
315
+ Pushed automatically by the server after authentication. No subscribe message is sent — you just register a local handler. Requires `API_KEY` (Node.js) or cookie auth (browser).
316
+
317
+ | Function | Server Event | Description |
318
+ | -------------------------- | -------------- | -------------------------------------------------- |
319
+ | `subscribeUserOrders(cb)` | `user_order` | Order lifecycle updates (created, filled, cancelled)|
320
+ | `subscribeUserTrades(cb)` | `user_trade` | Trade fill confirmations |
321
+ | `subscribeUserBalances(cb)`| `user_balance` | Balance changes |
322
+
323
+ ### Advanced Usage
324
+
325
+ Use the `TempleWebSocket` class directly for full control:
326
+
327
+ ```javascript
328
+ import { TempleWebSocket } from "@temple-digital-group/temple-canton-js";
329
+
330
+ const ws = new TempleWebSocket();
331
+ ws.onConnect = () => console.log("Connected");
332
+ ws.onDisconnect = (code, reason) => console.log("Disconnected:", code, reason);
333
+ ws.onAuth = (success, userId) => console.log("Auth:", success, userId);
334
+ ws.onError = (err) => console.error("WS error:", err);
335
+ ws.autoReconnect = true; // default — reconnects with exponential backoff
336
+ ws.connect();
337
+
338
+ // Market data — sends subscribe to server
339
+ const unsub = ws.subscribe("orderbook:Amulet/USDCx", (data) => { ... });
340
+
341
+ // User data — no subscribe message, just local handler
342
+ const unsubOrder = ws.onUserEvent("user_order", (data) => { ... });
343
+ ```
344
+
345
+ ## API Reference
346
+
347
+ > Functions marked with **W** support Loop Wallet via the wallet adapter.
348
+
349
+ ### Configuration
350
+
351
+ | Function | Description |
352
+ | --------------------------- | ----------------------------------------------------------------------------- |
353
+ | `initialize(config)` | Initialize the SDK, set config, and optionally authenticate with the REST API |
354
+ | `setWalletAdapter(adapter)` | Set or update the Loop SDK instance for all wallet-aware functions |
355
+
356
+ ### Instrument Catalog
357
+
358
+ | Function | Description |
359
+ | ---------------------------- | --------------------------------------- |
360
+ | `getSupportedTradingPairs()` | Get the list of supported trading pairs |
361
+ | `getInstrumentCatalog()` | Get the full instrument catalog |
362
+
363
+ ### Onboarding & Delegation
364
+
365
+ | Function | Provider | Description |
366
+ | ------------------------------------------ | -------- | ------------------------------------------------------ |
367
+ | `isUserOnboarded(party)` | **W** | Check if user has a delegation contract on ledger |
368
+ | `onboardUser(party)` | **W** | Create the delegation contract needed for trading |
369
+ | `withdrawDelegation(delegationId?, user?)` | **W** | Archive the delegation contract (user must re-onboard) |
370
+
371
+ ### Deposits & Withdrawals
372
+
373
+ | Function | Provider | Description |
374
+ | ----------------------------------------- | -------- | ----------------------------------------------------- |
375
+ | `deposit(amount, symbol)` | **W** | Deposit funds (validates balance, reserves 10 CC for fees) |
376
+ | `prepareDepositHoldings(amount, assetId)` | **W** | Resolve holdings for a deposit amount (low-level) |
377
+ | `depositFunds(opts)` | **W** | Submit deposit allocation (low-level) |
378
+ | `withdrawFunds({ asset_id, amount })` | **W** | Withdraw available trading balance back to wallet |
379
+ | `emergencyWithdrawFunds(opts)` | **W** | Cancel all orders and withdraw everything immediately |
380
+
381
+ ### Holdings
382
+
383
+ | Function | Provider | Description |
384
+ | ----------------------------------------------------------------- | -------- | ----------------------------------------------------------------------------- |
385
+ | `getUserBalances(party?, provider?)` | **W** | Get all balances grouped by asset (Amulet, locked, and utility) |
386
+ | `getAmuletHoldingsForParty(party, returnCommand, provider)` | **W** | Get Amulet holdings |
387
+ | `getLockedAmuletHoldingsForParty(party, returnCommand, provider)` | **W** | Get locked Amulet holdings |
388
+ | `getUtilityHoldingsForParty(party, returnCommand, provider)` | **W** | Get utility token holdings |
389
+ | `getUtxoCount(party, assetId, provider)` | **W** | Get UTXO summary: counts, largest unlocked amount, and total unlocked balance |
390
+
391
+ ### Holding Operations
392
+
393
+ | Function | Provider | Description |
394
+ | ------------------------------------------------------------------------------------------ | -------- | ------------------------------- |
395
+ | `mergeAmuletHoldingsForParty(party, returnCommand, provider, maxUtxos, amuletDisclosures)` | **W** | Merge Amulet holdings into one |
396
+ | `mergeUtilityHoldingsForParty(party, utilityAsset, returnCommand, provider, maxUtxos)` | **W** | Merge utility holdings into one |
397
+
398
+ ### Temple REST API
399
+
400
+ > These functions call the Temple REST API. Pass `API_KEY` in `initialize()` or call `setApiKey()` to authenticate.
401
+
402
+ #### Auth
403
+
404
+ | Function | Description |
405
+ | ---------------- | ------------------------------------------- |
406
+ | `setApiKey(key)` | Set the API key for REST API authentication |
407
+ | `getUserId()` | Get the stored user ID |
408
+
409
+ #### Market Data
410
+
411
+ | Function | Description |
412
+ | ----------------------------------- | --------------------------------------------------------- |
413
+ | `getTicker(symbol?)` | Get ticker data for one or all trading pairs |
414
+ | `getOrderBook(symbol, options?)` | Get the order book (options: `levels`, `precision`) |
415
+ | `getSymbolConfig(symbol)` | Get symbol configuration (paused, decimals, min quantity) |
416
+ | `getOpenInterest(symbol)` | Get open interest for a trading pair |
417
+ | `getRecentTrades(symbol, options?)` | Get recent trades (options: `limit`, max 500) |
418
+
419
+ #### Trading
420
+
421
+ | Function | Description |
422
+ | ----------------------------------- | ------------------------------------------------------ |
423
+ | `createOrderRequest(opts)` | Place a buy/sell order via the trading backend |
424
+ | `cancelOrder(orderId)` | Cancel a specific order |
425
+ | `cancelAllOrders(options?)` | Cancel all orders (options: `symbol` filter) |
426
+ | `getTradingBalance()` | Get user's trading balance (unlocked/locked/in-flight) |
427
+ | `getActiveOrders(options?)` | Get active orders (options: `symbol`, `limit`) |
428
+
429
+ #### Withdrawals
430
+
431
+ | Function | Description |
432
+ | ------------------------------------------ | ------------------------------------------ |
433
+ | `createWithdrawalRequest(assetId, amount)` | Submit a withdrawal request to the backend |
434
+ | `getWithdrawalRequestStatus(requestId)` | Poll withdrawal status until ready |
435
+
436
+ #### Disclosures & Delegation
437
+
438
+ | Function | Description |
439
+ | ------------------------- | ---------------------------------------------------------------------------- |
440
+ | `getDisclosures(partyId)` | Get Amulet disclosure data (factory ID, choice context, disclosed contracts) |
441
+ | `getDelegation()` | Get the user's delegation contract from the API |
442
+
443
+ ### WebSocket
444
+
445
+ | Function | Description |
446
+ | ------------------------------------------- | -------------------------------------------------------------- |
447
+ | `createWebSocket()` | Get or create the shared WS instance (auto-connects) |
448
+ | `disconnectWebSocket()` | Disconnect and destroy the shared WS instance |
449
+ | `subscribeOrderbook(symbol, cb)` | Subscribe to orderbook updates |
450
+ | `subscribeTrades(symbol, cb)` | Subscribe to trade updates |
451
+ | `subscribeTicker(symbol, cb)` | Subscribe to ticker updates |
452
+ | `subscribeCandles(symbol, granularity, cb)` | Subscribe to candle updates |
453
+ | `subscribeOracle(symbol, cb)` | Subscribe to oracle price updates |
454
+ | `subscribeOracleVolume(symbol, cb)` | Subscribe to oracle volume updates |
455
+ | `subscribeUserOrders(cb)` | Listen to user order events (auto-pushed, no subscribe needed) |
456
+ | `subscribeUserTrades(cb)` | Listen to user trade events (auto-pushed, no subscribe needed) |
457
+ | `subscribeUserBalances(cb)` | Listen to user balance events (auto-pushed, no subscribe needed)|