@temple-digital-group/temple-canton-js 1.0.40 → 2.0.0-beta.10
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 +303 -207
- package/dist/api/index.d.ts +32 -26
- package/dist/api/index.js +82 -117
- package/dist/api/tokenStore.d.ts +6 -30
- package/dist/api/tokenStore.js +9 -60
- package/dist/api/types.d.ts +57 -25
- package/dist/api/types.js +1 -1
- package/dist/canton/deposits.js +2 -0
- package/index.js +3 -0
- package/package.json +4 -2
- package/src/api/index.ts +103 -136
- package/src/api/tokenStore.ts +10 -67
- package/src/api/types.ts +79 -32
- package/src/auth0/index.d.ts +1 -0
- package/src/canton/deposits.ts +561 -0
- package/src/canton/helpers.ts +266 -0
- package/src/canton/index.d.ts +41 -0
- package/src/canton/index.js +748 -1451
- package/src/canton/instrumentCatalog.d.ts +6 -0
- package/src/canton/instrumentCatalog.js +9 -0
- package/src/canton/walletAdapter.d.ts +6 -0
- package/src/canton/walletAdapter.js +42 -2
- package/src/canton/withdrawals.ts +489 -0
- package/src/config/index.d.ts +6 -0
- package/src/config/index.js +35 -1
- package/src/websocket/index.ts +341 -0
- package/src/websocket/ws.d.ts +24 -0
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Temple Canton JS
|
|
2
2
|
|
|
3
|
-
JavaScript SDK for interacting with the Temple Canton blockchain exchange. Supports CC, USDCx, and CBTC tokens on the Canton network.
|
|
3
|
+
JavaScript SDK for interacting with the Temple Canton blockchain exchange. Supports Amulet (CC), USDCx, and CBTC tokens on the Canton network.
|
|
4
4
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
@@ -12,73 +12,6 @@ npm install @temple-digital-group/temple-canton-js
|
|
|
12
12
|
|
|
13
13
|
Call `initialize()` before using any SDK functions. It sets up the config and optionally authenticates with the Temple REST API.
|
|
14
14
|
|
|
15
|
-
### Custom Validator
|
|
16
|
-
|
|
17
|
-
For apps connecting to your own validator (browser or server-side):
|
|
18
|
-
|
|
19
|
-
```javascript
|
|
20
|
-
import { initialize } from "@temple-digital-group/temple-canton-js";
|
|
21
|
-
|
|
22
|
-
await initialize({
|
|
23
|
-
NETWORK: "mainnet",
|
|
24
|
-
VALIDATOR_API_URL: "https://your-validator-url",
|
|
25
|
-
VALIDATOR_SCAN_API_URL: "https://your-scan-api-url",
|
|
26
|
-
VALIDATOR_USER_PARTY_ID: "your-user-party-id",
|
|
27
|
-
AUTH0_TOKEN_URL: "https://your-auth0-domain/oauth/token",
|
|
28
|
-
AUTH0_USER_ID: "your-auth0-user-id",
|
|
29
|
-
AUTH0_CLIENT_ID: "your-client-id",
|
|
30
|
-
AUTH0_CLIENT_SECRET: "your-client-secret",
|
|
31
|
-
AUTH0_AUDIENCE: "your-audience",
|
|
32
|
-
});
|
|
33
|
-
```
|
|
34
|
-
|
|
35
|
-
### Custom Validator + REST API
|
|
36
|
-
|
|
37
|
-
To also authenticate with the Temple REST API at init time, pass `API_EMAIL`/`API_PASSWORD`:
|
|
38
|
-
|
|
39
|
-
```javascript
|
|
40
|
-
import { initialize } from "@temple-digital-group/temple-canton-js";
|
|
41
|
-
|
|
42
|
-
await initialize({
|
|
43
|
-
NETWORK: "mainnet",
|
|
44
|
-
VALIDATOR_API_URL: "https://your-validator-url",
|
|
45
|
-
VALIDATOR_SCAN_API_URL: "https://your-scan-api-url",
|
|
46
|
-
VALIDATOR_USER_PARTY_ID: "your-user-party-id",
|
|
47
|
-
AUTH0_TOKEN_URL: "https://your-auth0-domain/oauth/token",
|
|
48
|
-
AUTH0_USER_ID: "your-auth0-user-id",
|
|
49
|
-
AUTH0_CLIENT_ID: "your-client-id",
|
|
50
|
-
AUTH0_CLIENT_SECRET: "your-client-secret",
|
|
51
|
-
AUTH0_AUDIENCE: "your-audience",
|
|
52
|
-
API_EMAIL: "user@example.com", // REST API login (optional)
|
|
53
|
-
API_PASSWORD: "password",
|
|
54
|
-
});
|
|
55
|
-
```
|
|
56
|
-
|
|
57
|
-
| Key | Required | Description |
|
|
58
|
-
| ------------------------- | -------- | ---------------------------------------------------- |
|
|
59
|
-
| `NETWORK` | Yes | `mainnet`, `testnet`, or `localhost` |
|
|
60
|
-
| `VALIDATOR_API_URL` | Yes | Base URL of the Canton validator ledger API |
|
|
61
|
-
| `VALIDATOR_SCAN_API_URL` | Yes | Base URL of the Canton Scan API |
|
|
62
|
-
| `VALIDATOR_USER_PARTY_ID` | Yes | The user's party ID on the network |
|
|
63
|
-
| `JWT_TOKEN` | Yes\* | Pre-authenticated JWT token for ledger API calls |
|
|
64
|
-
| `AUTH0_TOKEN_URL` | Yes\* | Auth0 OAuth token endpoint |
|
|
65
|
-
| `AUTH0_CLIENT_ID` | Yes\* | Auth0 application client ID |
|
|
66
|
-
| `AUTH0_CLIENT_SECRET` | Yes\* | Auth0 application client secret |
|
|
67
|
-
| `AUTH0_AUDIENCE` | Yes\* | Auth0 API audience identifier |
|
|
68
|
-
| `AUTH0_USER_ID` | Yes\* | Auth0 user ID for the service account |
|
|
69
|
-
| `API_EMAIL` | No | Temple REST API email (triggers login at init) |
|
|
70
|
-
| `API_PASSWORD` | No | Temple REST API password (required with `API_EMAIL`) |
|
|
71
|
-
|
|
72
|
-
\* Provide either `JWT_TOKEN` (browser) or the `AUTH0_*` fields (server-side). The SDK fetches and caches JWT tokens automatically when Auth0 credentials are provided.
|
|
73
|
-
|
|
74
|
-
To update the JWT token later without re-initializing:
|
|
75
|
-
|
|
76
|
-
```javascript
|
|
77
|
-
import { setJWTToken } from "@temple-digital-group/temple-canton-js";
|
|
78
|
-
|
|
79
|
-
setJWTToken(newToken);
|
|
80
|
-
```
|
|
81
|
-
|
|
82
15
|
### Wallet Adapter
|
|
83
16
|
|
|
84
17
|
For apps using Loop Wallet. Pass the Loop SDK instance as `WALLET_ADAPTER` — the SDK auto-detects server vs client mode.
|
|
@@ -87,18 +20,13 @@ For apps using Loop Wallet. Pass the Loop SDK instance as `WALLET_ADAPTER` — t
|
|
|
87
20
|
- **Client-side:** uses `loop.provider.submitTransaction()` (delegates signing to Loop Wallet via WebSocket)
|
|
88
21
|
|
|
89
22
|
```javascript
|
|
90
|
-
import { initialize
|
|
23
|
+
import { initialize } from "@temple-digital-group/temple-canton-js";
|
|
91
24
|
|
|
92
|
-
|
|
25
|
+
initialize({
|
|
26
|
+
API_KEY: "your-api-key",
|
|
93
27
|
NETWORK: "mainnet",
|
|
94
28
|
WALLET_ADAPTER: loop, // Pass the Loop SDK instance
|
|
95
29
|
});
|
|
96
|
-
|
|
97
|
-
// Auto-submit: SDK handles signing and submission
|
|
98
|
-
const result = await createOrderProposal(orderArgs);
|
|
99
|
-
|
|
100
|
-
// Or get the raw command back for manual submission
|
|
101
|
-
const command = await createOrderProposal(orderArgs, true);
|
|
102
30
|
```
|
|
103
31
|
|
|
104
32
|
You can also set or change the wallet adapter after init:
|
|
@@ -111,12 +39,9 @@ setWalletAdapter(loop);
|
|
|
111
39
|
|
|
112
40
|
| Key | Required | Description |
|
|
113
41
|
| ---------------- | -------- | --------------------------------------------------------------- |
|
|
114
|
-
| `
|
|
115
|
-
| `
|
|
116
|
-
|
|
117
|
-
> You can optionally pass `API_EMAIL`/`API_PASSWORD` to any `initialize()` call to also authenticate with the REST API at init time.
|
|
118
|
-
|
|
119
|
-
> **Legacy:** `initializeConfig()` is still available as a sync-only alternative (no REST API auth). `initialize()` is the recommended approach.
|
|
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 |
|
|
120
45
|
|
|
121
46
|
## Supported Instruments
|
|
122
47
|
|
|
@@ -126,128 +51,184 @@ setWalletAdapter(loop);
|
|
|
126
51
|
| USDCx | Utility | testnet, mainnet |
|
|
127
52
|
| CBTC | Utility | testnet, mainnet |
|
|
128
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
|
+
|
|
129
56
|
## Supported Trading Pairs
|
|
130
57
|
|
|
131
58
|
- `CC/USDCx`
|
|
132
59
|
- `CBTC/USDCx`
|
|
133
60
|
|
|
134
|
-
##
|
|
61
|
+
## v2 Trading Flow
|
|
135
62
|
|
|
136
|
-
|
|
63
|
+
The v2 flow covers the full trading lifecycle: onboarding, deposits, trading, and withdrawals.
|
|
137
64
|
|
|
138
|
-
```
|
|
139
|
-
|
|
65
|
+
```
|
|
66
|
+
1. Check onboarding → isUserOnboarded(party)
|
|
67
|
+
If NOT onboarded → onboardUser(party)
|
|
140
68
|
|
|
141
|
-
|
|
142
|
-
const balances = await getUserBalances();
|
|
69
|
+
2. Deposit funds → deposit(amount, symbol)
|
|
143
70
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
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)
|
|
147
80
|
```
|
|
148
81
|
|
|
149
|
-
|
|
82
|
+
### 1. Onboarding
|
|
83
|
+
|
|
84
|
+
Check if a user has a delegation contract, and create one if not:
|
|
150
85
|
|
|
151
86
|
```javascript
|
|
152
|
-
{
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
operator: '...', // Operator party
|
|
160
|
-
provider: '...', // Provider party
|
|
161
|
-
merge_warning: true, // true if multiple unlocked holdings exist
|
|
162
|
-
holdings: [...], // Unlocked holding contracts
|
|
163
|
-
locked_holdings: [...], // Locked holding contracts
|
|
164
|
-
utilityContext: { ... } // CIP-56 context (null when using wallet provider)
|
|
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
|
|
165
94
|
}
|
|
166
95
|
```
|
|
167
96
|
|
|
168
|
-
|
|
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.
|
|
169
98
|
|
|
170
|
-
###
|
|
99
|
+
### 2. Deposit Funds
|
|
100
|
+
|
|
101
|
+
The simplest way to deposit is the `deposit()` helper — pass the amount and symbol, and it handles everything:
|
|
171
102
|
|
|
172
103
|
```javascript
|
|
173
|
-
import {
|
|
104
|
+
import { deposit } from "@temple-digital-group/temple-canton-js";
|
|
174
105
|
|
|
175
|
-
const result = await
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
side: "Buy",
|
|
179
|
-
quantity: "100",
|
|
180
|
-
pricePerUnit: "1.5",
|
|
181
|
-
expiration: new Date(Date.now() + 3600000).toISOString(),
|
|
182
|
-
userId: auth0UserId, // Optional if authenticated via REST API — auto-resolved from login
|
|
183
|
-
orderType: "limit",
|
|
184
|
-
});
|
|
106
|
+
const result = await deposit(100, "USDCx");
|
|
107
|
+
// or
|
|
108
|
+
const result = await deposit(10, "CC");
|
|
185
109
|
```
|
|
186
110
|
|
|
187
|
-
|
|
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:
|
|
188
118
|
|
|
189
|
-
|
|
119
|
+
```javascript
|
|
120
|
+
import { prepareDepositHoldings, depositFunds } from "@temple-digital-group/temple-canton-js";
|
|
190
121
|
|
|
191
|
-
|
|
122
|
+
const depositOpts = await prepareDepositHoldings(100, "USDCx");
|
|
123
|
+
const result = await depositFunds(depositOpts);
|
|
124
|
+
```
|
|
192
125
|
|
|
193
|
-
|
|
126
|
+
### 3. Trading Balance
|
|
194
127
|
|
|
195
128
|
```javascript
|
|
196
|
-
import {
|
|
129
|
+
import { getTradingBalance } from "@temple-digital-group/temple-canton-js";
|
|
197
130
|
|
|
198
|
-
const
|
|
199
|
-
|
|
131
|
+
const balances = await getTradingBalance();
|
|
132
|
+
// Returns { balances: [{ asset, unlocked, locked, in_flight, ... }] }
|
|
133
|
+
```
|
|
200
134
|
|
|
201
|
-
|
|
202
|
-
async function waitForProviderSync(contractId, party, provider, interval = 500, maxAttempts = 20) {
|
|
203
|
-
for (let i = 0; i < maxAttempts; i++) {
|
|
204
|
-
const holdings = await getAmuletHoldingsForParty(party, false, provider);
|
|
205
|
-
const stillActive = holdings?.some((h) => h.contractEntry?.JsActiveContract?.createdEvent?.contractId === contractId);
|
|
206
|
-
if (!stillActive) return true; // Provider caught up
|
|
207
|
-
await new Promise((r) => setTimeout(r, interval));
|
|
208
|
-
}
|
|
209
|
-
return false; // Timed out
|
|
210
|
-
}
|
|
135
|
+
Use this to check available funds before placing orders or withdrawals.
|
|
211
136
|
|
|
212
|
-
|
|
213
|
-
// Safe to create next order
|
|
214
|
-
```
|
|
137
|
+
### 4. Place Orders
|
|
215
138
|
|
|
216
|
-
|
|
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
|
+
});
|
|
217
149
|
|
|
218
|
-
|
|
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
|
|
219
162
|
|
|
220
163
|
```javascript
|
|
221
|
-
import {
|
|
164
|
+
import { cancelOrder, cancelAllOrders } from "@temple-digital-group/temple-canton-js";
|
|
165
|
+
|
|
166
|
+
// Cancel a specific order
|
|
167
|
+
await cancelOrder("ord_abc123");
|
|
222
168
|
|
|
223
|
-
|
|
224
|
-
|
|
169
|
+
// Cancel all orders for a symbol
|
|
170
|
+
await cancelAllOrders({ symbol: "CC/USDCx" });
|
|
171
|
+
|
|
172
|
+
// Cancel ALL orders
|
|
173
|
+
await cancelAllOrders();
|
|
225
174
|
```
|
|
226
175
|
|
|
227
|
-
###
|
|
176
|
+
### 6. Withdraw Funds
|
|
228
177
|
|
|
229
|
-
|
|
178
|
+
Withdraws available (unlocked, non-in-flight) trading balance back to the user's wallet.
|
|
230
179
|
|
|
231
180
|
```javascript
|
|
232
|
-
import {
|
|
181
|
+
import { withdrawFunds } from "@temple-digital-group/temple-canton-js";
|
|
233
182
|
|
|
234
|
-
await
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
API_PASSWORD: "password",
|
|
183
|
+
const result = await withdrawFunds({
|
|
184
|
+
asset_id: "USDCx",
|
|
185
|
+
amount: "250.50",
|
|
238
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
|
+
```
|
|
239
202
|
|
|
240
|
-
|
|
241
|
-
const ticker = await getTicker("CC/USDCx");
|
|
242
|
-
const book = await getOrderBook("CC/USDCx", { levels: 10 });
|
|
203
|
+
### Get User Balances
|
|
243
204
|
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
const result = await cancelOrder("order-id-123");
|
|
205
|
+
```javascript
|
|
206
|
+
import { getUserBalances } from "@temple-digital-group/temple-canton-js";
|
|
247
207
|
|
|
248
|
-
//
|
|
249
|
-
|
|
250
|
-
|
|
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: { ... }
|
|
251
232
|
}
|
|
252
233
|
```
|
|
253
234
|
|
|
@@ -256,7 +237,7 @@ if (result.error) {
|
|
|
256
237
|
```javascript
|
|
257
238
|
import { mergeAmuletHoldingsForParty, mergeUtilityHoldingsForParty, getAmuletDisclosures, getUtxoCount } from "@temple-digital-group/temple-canton-js";
|
|
258
239
|
|
|
259
|
-
//
|
|
240
|
+
// Merge all Amulet or utility holdings
|
|
260
241
|
await mergeAmuletHoldingsForParty(partyId);
|
|
261
242
|
await mergeUtilityHoldingsForParty(partyId, "USDCx");
|
|
262
243
|
|
|
@@ -269,24 +250,107 @@ const disclosures = await getAmuletDisclosures(partyId);
|
|
|
269
250
|
const cmd = await mergeAmuletHoldingsForParty(partyId, true, walletProvider, 5, disclosures);
|
|
270
251
|
const res = await walletProvider.submitTransaction(cmd);
|
|
271
252
|
|
|
272
|
-
// Check UTXO status after merge
|
|
253
|
+
// Check UTXO status after merge
|
|
273
254
|
const counts = await getUtxoCount(partyId, "USDCx", walletProvider);
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
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) => { ... });
|
|
278
343
|
```
|
|
279
344
|
|
|
280
345
|
## API Reference
|
|
281
346
|
|
|
282
|
-
> Functions marked with **W** support Loop Wallet via the wallet adapter.
|
|
347
|
+
> Functions marked with **W** support Loop Wallet via the wallet adapter.
|
|
283
348
|
|
|
284
349
|
### Configuration
|
|
285
350
|
|
|
286
351
|
| Function | Description |
|
|
287
352
|
| --------------------------- | ----------------------------------------------------------------------------- |
|
|
288
353
|
| `initialize(config)` | Initialize the SDK, set config, and optionally authenticate with the REST API |
|
|
289
|
-
| `setJWTToken(token)` | Update the JWT token without re-initializing the config |
|
|
290
354
|
| `setWalletAdapter(adapter)` | Set or update the Loop SDK instance for all wallet-aware functions |
|
|
291
355
|
|
|
292
356
|
### Instrument Catalog
|
|
@@ -296,45 +360,51 @@ if (counts.largestUnlocked >= requiredAmount) {
|
|
|
296
360
|
| `getSupportedTradingPairs()` | Get the list of supported trading pairs |
|
|
297
361
|
| `getInstrumentCatalog()` | Get the full instrument catalog |
|
|
298
362
|
|
|
299
|
-
###
|
|
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) |
|
|
300
370
|
|
|
301
|
-
|
|
302
|
-
| ----------------------------------------------------------------- | -------- | -------------------------------------------------------------- |
|
|
303
|
-
| `getUserBalances(party?, provider?)` | **W** | Get all balances grouped by asset (CC, locked CC, and utility) |
|
|
304
|
-
| `getAmuletHoldingsForParty(party, returnCommand, provider)` | **W** | Get CC holdings |
|
|
305
|
-
| `getLockedAmuletHoldingsForParty(party, returnCommand, provider)`| **W** | Get locked CC holdings |
|
|
306
|
-
| `getUtilityHoldingsForParty(party, returnCommand, provider)` | **W** | Get utility token holdings |
|
|
307
|
-
| `getUtxoCount(party, assetId, provider)` | **W** | Get UTXO summary: counts, largest unlocked amount, and total unlocked balance |
|
|
371
|
+
### Deposits & Withdrawals
|
|
308
372
|
|
|
309
|
-
|
|
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
|
|
310
382
|
|
|
311
|
-
| Function
|
|
312
|
-
|
|
|
313
|
-
| `
|
|
314
|
-
| `
|
|
315
|
-
| `
|
|
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 |
|
|
316
390
|
|
|
317
391
|
### Holding Operations
|
|
318
392
|
|
|
319
|
-
| Function | Provider | Description
|
|
320
|
-
| ------------------------------------------------------------------------------------------ | -------- |
|
|
321
|
-
| `mergeAmuletHoldingsForParty(party, returnCommand, provider, maxUtxos, amuletDisclosures)` | **W** | Merge
|
|
393
|
+
| Function | Provider | Description |
|
|
394
|
+
| ------------------------------------------------------------------------------------------ | -------- | ------------------------------- |
|
|
395
|
+
| `mergeAmuletHoldingsForParty(party, returnCommand, provider, maxUtxos, amuletDisclosures)` | **W** | Merge Amulet holdings into one |
|
|
322
396
|
| `mergeUtilityHoldingsForParty(party, utilityAsset, returnCommand, provider, maxUtxos)` | **W** | Merge utility holdings into one |
|
|
323
|
-
| `splitAmuletHoldingForParty(party, outputQuantity)` | | Split a CC holding |
|
|
324
|
-
| `unlockLockedAmulets(party)` | | Unlock locked CC holdings |
|
|
325
397
|
|
|
326
|
-
### Temple REST API
|
|
398
|
+
### Temple REST API
|
|
327
399
|
|
|
328
|
-
> These functions call the Temple
|
|
400
|
+
> These functions call the Temple REST API. Pass `API_KEY` in `initialize()` or call `setApiKey()` to authenticate.
|
|
329
401
|
|
|
330
402
|
#### Auth
|
|
331
403
|
|
|
332
|
-
| Function
|
|
333
|
-
|
|
|
334
|
-
| `
|
|
335
|
-
| `
|
|
336
|
-
| `logout()` | Clear stored tokens |
|
|
337
|
-
| `getUserId()` | Get the stored user ID from login (used automatically by `createOrderProposal`) |
|
|
404
|
+
| Function | Description |
|
|
405
|
+
| ---------------- | ------------------------------------------- |
|
|
406
|
+
| `setApiKey(key)` | Set the API key for REST API authentication |
|
|
407
|
+
| `getUserId()` | Get the stored user ID |
|
|
338
408
|
|
|
339
409
|
#### Market Data
|
|
340
410
|
|
|
@@ -346,16 +416,42 @@ if (counts.largestUnlocked >= requiredAmount) {
|
|
|
346
416
|
| `getOpenInterest(symbol)` | Get open interest for a trading pair |
|
|
347
417
|
| `getRecentTrades(symbol, options?)` | Get recent trades (options: `limit`, max 500) |
|
|
348
418
|
|
|
349
|
-
####
|
|
350
|
-
|
|
351
|
-
| Function
|
|
352
|
-
|
|
|
353
|
-
| `
|
|
354
|
-
| `cancelOrder(orderId)`
|
|
355
|
-
| `cancelAllOrders(options?)`
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
|
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)|
|