@temple-digital-group/temple-canton-js 1.0.30

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Temple Digital Group
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,253 @@
1
+ # Temple Canton JS
2
+
3
+ JavaScript SDK for interacting with the Temple Canton blockchain exchange. Supports Amulet, 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
+ There are three ways to use the SDK depending on your environment:
14
+
15
+ ### 1. Browser with Custom Validator
16
+
17
+ For browser apps connecting to your own validator. Requires `initializeConfig()` with your validator URLs and a pre-authenticated JWT token.
18
+
19
+ ```javascript
20
+ import { initializeConfig } from '@temple-digital-group/temple-canton-js';
21
+
22
+ initializeConfig({
23
+ NETWORK: 'mainnet',
24
+ VALIDATOR_API_URL: 'https://your-validator-url',
25
+ VALIDATOR_SCAN_API_URL: 'https://your-scan-api-url',
26
+ TEMPLE_PARTY_ID: 'your-temple-party-id',
27
+ VALIDATOR_DSO_PARTY_ID: 'your-dso-party-id',
28
+ JWT_TOKEN: 'your-jwt-token',
29
+ VALIDATOR_USER_PARTY_ID: 'your-user-party-id'
30
+ });
31
+ ```
32
+
33
+ | Key | Required | Description |
34
+ |-----|----------|-------------|
35
+ | `NETWORK` | Yes | `mainnet`, `testnet`, or `localhost` |
36
+ | `VALIDATOR_API_URL` | Yes | Base URL of the Canton validator ledger API |
37
+ | `VALIDATOR_SCAN_API_URL` | Yes | Base URL of the Canton Scan API |
38
+ | `TEMPLE_PARTY_ID` | Yes | Temple's party ID on the network |
39
+ | `VALIDATOR_DSO_PARTY_ID` | Yes | The DSO (Decentralized Synchronizer Operator) party ID |
40
+ | `JWT_TOKEN` | Yes | Pre-authenticated JWT token for ledger API calls |
41
+ | `VALIDATOR_USER_PARTY_ID` | Yes | The user's party ID on the network |
42
+
43
+ ### 2. Browser with Wallet Provider
44
+
45
+ For browser apps using a wallet (e.g., Loop Wallet). Requires `initializeConfig()` with base network config only. Use `returnCommand = true` to get the command back for the wallet to sign.
46
+
47
+ ```javascript
48
+ import { initializeConfig, createOrderProposal } from '@temple-digital-group/temple-canton-js';
49
+
50
+ initializeConfig({
51
+ NETWORK: 'mainnet',
52
+ TEMPLE_PARTY_ID: 'your-temple-party-id',
53
+ VALIDATOR_DSO_PARTY_ID: 'your-dso-party-id'
54
+ });
55
+
56
+ // returnCommand=true returns the command for the wallet to sign
57
+ const command = await createOrderProposal(orderArgs, true, walletProvider);
58
+ const result = await walletProvider.signAndSubmit(command);
59
+ ```
60
+
61
+ | Key | Required | Description |
62
+ |-----|----------|-------------|
63
+ | `NETWORK` | Yes | `mainnet`, `testnet`, or `localhost` |
64
+ | `TEMPLE_PARTY_ID` | Yes | Temple's party ID on the network |
65
+ | `VALIDATOR_DSO_PARTY_ID` | Yes | The DSO (Decentralized Synchronizer Operator) party ID |
66
+
67
+ ### 3. Node.js / Server-Side
68
+
69
+ For server-side applications. Uses environment variables directly — no `initializeConfig()` call needed. Create a `.env` file:
70
+
71
+ ```env
72
+ NETWORK=mainnet
73
+ VALIDATOR_API_URL=https://your-validator-url
74
+ VALIDATOR_SCAN_API_URL=https://your-scan-api-url
75
+ TEMPLE_PARTY_ID=your-temple-party-id
76
+ VALIDATOR_DSO_PARTY_ID=your-dso-party-id
77
+
78
+ AUTH0_TOKEN_URL=https://your-auth0-domain.auth0.com/oauth/token
79
+ AUTH0_USER_ID=your-auth0-user-id
80
+ AUTH0_CLIENT_ID=your-client-id
81
+ AUTH0_CLIENT_SECRET=your-client-secret
82
+ AUTH0_AUDIENCE=https://your-audience
83
+ ```
84
+
85
+ | Parameter | Required | Description |
86
+ |-----------|----------|-------------|
87
+ | `NETWORK` | Yes | `mainnet`, `testnet`, or `localhost` |
88
+ | `VALIDATOR_API_URL` | Yes | Base URL of the Canton validator ledger API |
89
+ | `VALIDATOR_SCAN_API_URL` | Yes | Base URL of the Canton Scan API |
90
+ | `TEMPLE_PARTY_ID` | Yes | Temple's party ID on the network |
91
+ | `VALIDATOR_DSO_PARTY_ID` | Yes | The DSO (Decentralized Synchronizer Operator) party ID |
92
+ | `AUTH0_TOKEN_URL` | Yes | Auth0 OAuth token endpoint |
93
+ | `AUTH0_CLIENT_ID` | Yes | Auth0 application client ID |
94
+ | `AUTH0_CLIENT_SECRET` | Yes | Auth0 application client secret |
95
+ | `AUTH0_AUDIENCE` | Yes | Auth0 API audience identifier |
96
+ | `AUTH0_USER_ID` | Yes | Auth0 user ID for the service account |
97
+
98
+ The SDK fetches and caches JWT tokens automatically via Auth0.
99
+
100
+ You can also call `initializeConfig()` in Node.js to override specific environment variables at runtime. For example, if a frontend passes a JWT token to your server:
101
+
102
+ ```javascript
103
+ import { initializeConfig, getUserBalances } from '@temple-digital-group/temple-canton-js';
104
+
105
+ // .env provides base config (NETWORK, VALIDATOR_API_URL, etc.)
106
+ // Override with a token received from the frontend
107
+ initializeConfig({ JWT_TOKEN: tokenFromFrontend });
108
+
109
+ const balances = await getUserBalances(partyId);
110
+ ```
111
+
112
+ Runtime config values take precedence over environment variables.
113
+
114
+
115
+ ## Supported Instruments
116
+
117
+ | Asset | Type | Networks |
118
+ |---------|---------|-------------------|
119
+ | Amulet | Amulet | testnet, mainnet |
120
+ | USDCx | Utility | testnet, mainnet |
121
+ | CBTC | Utility | testnet, mainnet |
122
+
123
+ ## Supported Trading Pairs
124
+
125
+ - `Amulet/USDCx`
126
+ - `CBTC/USDCx`
127
+
128
+ ## Usage
129
+
130
+ ### Get User Balances
131
+
132
+ ```javascript
133
+ import { getUserBalances } from '@temple-digital-group/temple-canton-js';
134
+
135
+ const balances = await getUserBalances(partyId);
136
+ ```
137
+
138
+ ### Create an Order
139
+
140
+ ```javascript
141
+ import { createOrderProposal } from '@temple-digital-group/temple-canton-js';
142
+
143
+ const result = await createOrderProposal({
144
+ party: partyId,
145
+ symbol: 'Amulet/USDCx',
146
+ side: 'Buy',
147
+ quantity: '100',
148
+ pricePerUnit: '1.5',
149
+ expiration: new Date(Date.now() + 3600000).toISOString(),
150
+ userId: auth0UserId,
151
+ orderType: 'limit'
152
+ });
153
+ ```
154
+
155
+ ### Get Orders and Proposals
156
+
157
+ ```javascript
158
+ import { getOrdersForParty, getOrderProposalsForParty } from '@temple-digital-group/temple-canton-js';
159
+
160
+ const orders = await getOrdersForParty(partyId);
161
+ const proposals = await getOrderProposalsForParty(partyId);
162
+ ```
163
+
164
+ ### Merge Holdings
165
+
166
+ ```javascript
167
+ import { mergeAmuletHoldingsForParty, mergeUtilityHoldingsForParty } from '@temple-digital-group/temple-canton-js';
168
+
169
+ await mergeAmuletHoldingsForParty(partyId);
170
+ await mergeUtilityHoldingsForParty(partyId, 'USDCx');
171
+ ```
172
+
173
+ ## API Reference
174
+
175
+ > Functions marked with **W** support a wallet provider parameter. All other functions require a custom validator (ledger access via `VALIDATOR_API_URL` and `JWT_TOKEN`).
176
+
177
+ ### Configuration
178
+
179
+ | Function | Description |
180
+ |----------|-------------|
181
+ | `initializeConfig(config)` | Initialize the library with a runtime config object |
182
+ | `getConfigValue(key)` | Get a config value from runtime config or environment |
183
+
184
+ ### Authentication
185
+
186
+ | Function | Description |
187
+ |----------|-------------|
188
+ | `getJWTToken()` | Get Auth0 JWT access token (cached with auto-refresh) |
189
+
190
+ ### Instrument Catalog
191
+
192
+ These functions are synchronous and work in all environments (no ledger or provider needed).
193
+
194
+ | Function | Description |
195
+ |----------|-------------|
196
+ | `resolveInstrumentDefinition(assetId)` | Look up an instrument definition from the catalog |
197
+ | `getInstrumentRegistrar(assetId)` | Get the registrar party for a utility instrument |
198
+ | `getSupportedTradingPairs()` | Get the list of supported trading pairs |
199
+ | `getInstrumentCatalog()` | Get the full instrument catalog |
200
+ | `checkAmuletContext(baseAsset, quoteAsset, side)` | Check if an order requires Amulet context |
201
+
202
+ ### Holdings
203
+
204
+ | Function | Provider | Description |
205
+ |----------|----------|-------------|
206
+ | `getAmuletHoldingsForParty(party)` | **W** | Get Amulet holdings |
207
+ | `getUtilityHoldingsForParty(party)` | **W** | Get utility token holdings |
208
+ | `getCandidateHoldingForOrderCreation(party, isAmulet, quantity, assetId)` | **W** | Find a holding suitable for an order |
209
+ | `getUserBalances(party)` | | Get all balances for a party, grouped by asset |
210
+ | `getLockedAmuletHoldingsForParty(party)` | | Get locked Amulet holdings |
211
+
212
+ ### Orders
213
+
214
+ | Function | Provider | Description |
215
+ |----------|----------|-------------|
216
+ | `createOrderProposal(orderArguments)` | **W** | Create an order proposal |
217
+ | `getOrderProposalsForParty(party)` | | Get pending order proposals |
218
+ | `getOrdersForParty(party)` | | Get active orders |
219
+
220
+ ### Holding Operations
221
+
222
+ | Function | Description |
223
+ |----------|-------------|
224
+ | `mergeAmuletHoldingsForParty(party)` | Merge Amulet holdings into one |
225
+ | `mergeUtilityHoldingsForParty(party, utilityAsset)` | Merge utility holdings into one |
226
+ | `splitAmuletHoldingForParty(party, outputQuantity)` | Split an Amulet holding |
227
+ | `unlockLockedAmulets(party)` | Unlock locked Amulet holdings |
228
+
229
+ ### Ledger Queries
230
+
231
+ | Function | Description |
232
+ |----------|-------------|
233
+ | `getTransferFactory(investor, admin, amount, holdingIds)` | Get transfer factory from Scan API |
234
+ | `getAmuletDisclosures(party)` | Get Amulet disclosure contracts |
235
+ | `getAmuletRules(dso)` | Get AmuletRules contract |
236
+ | `getExternalAmuletRules(dso)` | Get ExternalPartyAmuletRules contract |
237
+ | `getFeaturedAppRight()` | Get FeaturedAppRight contract |
238
+ | `getOpenMiningRounds(dso)` | Get open mining rounds |
239
+ | `getCandidateMiningRoundContract(dso)` | Get a currently-open mining round |
240
+ | `getUtilityInstrumentConfigurations()` | Get utility instrument configurations |
241
+ | `getUtilityAllocationFactory()` | Get utility allocation factory |
242
+ | `getUtilitySenderCredentials(sender)` | Get sender credentials |
243
+ | `createUtilityCredential(holder, registrar)` | Create a utility credential |
244
+
245
+ ### Deprecated
246
+
247
+ | Function | Description |
248
+ |----------|-------------|
249
+ | ~~`cancelOrders(party, orderContractIds, assetType)`~~ | Batch cancel orders (deprecated) |
250
+
251
+ ## License
252
+
253
+ MIT
package/index.js ADDED
@@ -0,0 +1,9 @@
1
+ // Export Canton client functions
2
+ export * from './src/canton/index.js';
3
+
4
+ // Export Auth0 utilities
5
+ export { getJWTToken } from './src/auth0/index.js';
6
+
7
+ // Export configuration
8
+ export * from './src/config/index.js';
9
+
package/package.json ADDED
@@ -0,0 +1,40 @@
1
+ {
2
+ "name": "@temple-digital-group/temple-canton-js",
3
+ "version": "1.0.30",
4
+ "description": "JavaScript library for interacting with Temple Canton blockchain",
5
+ "type": "module",
6
+ "main": "index.js",
7
+ "exports": {
8
+ ".": "./index.js"
9
+ },
10
+ "files": [
11
+ "index.js",
12
+ "src/"
13
+ ],
14
+ "repository": {
15
+ "type": "git",
16
+ "url": "git+https://github.com/Temple-Digital-Group/temple-canton-js.git"
17
+ },
18
+ "publishConfig": {
19
+ "access": "public"
20
+ },
21
+ "author": "kakashigr <augegr@gmail.com>",
22
+ "keywords": [
23
+ "canton",
24
+ "blockchain",
25
+ "daml",
26
+ "splice",
27
+ "amulet",
28
+ "ledger",
29
+ "trading",
30
+ "temple"
31
+ ],
32
+ "license": "MIT",
33
+ "scripts": {
34
+ "start": "node index.js"
35
+ },
36
+ "dependencies": {
37
+ "axios": "^1.13.1",
38
+ "dotenv": "^17.2.3"
39
+ }
40
+ }
@@ -0,0 +1,50 @@
1
+ import config from "../config/index.js";
2
+ import axios from "axios";
3
+
4
+ let jwtToken = null;
5
+ let tokenExpiryTime = null;
6
+
7
+ /**
8
+ * Get an Auth0 JWT access token with automatic caching and refresh.
9
+ * Tokens are cached and reused until they expire (with a 60-second buffer).
10
+ * Requires AUTH0_TOKEN_URL, AUTH0_CLIENT_ID, AUTH0_CLIENT_SECRET, and AUTH0_AUDIENCE to be configured.
11
+ * @returns {Promise<string|null>} The JWT access token, or null on failure
12
+ */
13
+ export async function getJWTToken() {
14
+ // Return cached token if not expired
15
+ if (jwtToken != null && tokenExpiryTime != null) {
16
+ // Check if expired (with 60 second buffer to avoid edge cases)
17
+ const isExpired = Date.now() >= tokenExpiryTime - 60000;
18
+ if (!isExpired) {
19
+ return jwtToken.access_token;
20
+ }
21
+ }
22
+ const encodedParams = new URLSearchParams();
23
+ encodedParams.set("grant_type", config.AUTH0_GRANT_TYPE);
24
+ encodedParams.set("client_id", config.AUTH0_CLIENT_ID);
25
+ encodedParams.set("client_secret", config.AUTH0_CLIENT_SECRET);
26
+ encodedParams.set("audience", config.AUTH0_AUDIENCE);
27
+ encodedParams.set("scope", config.AUTH0_SCOPE);
28
+
29
+ const options = {
30
+ method: "POST",
31
+ url: config.AUTH0_TOKEN_URL,
32
+ headers: {
33
+ "content-type": "application/x-www-form-urlencoded",
34
+ },
35
+ data: encodedParams,
36
+ };
37
+
38
+ try {
39
+ const { data } = await axios.request(options);
40
+ jwtToken = data;
41
+ // Calculate expiry time: current time + expires_in (in seconds) * 1000 (to convert to milliseconds)
42
+ tokenExpiryTime = Date.now() + data.expires_in * 1000;
43
+ return jwtToken.access_token;
44
+ } catch (error) {
45
+ console.error(error);
46
+ tokenExpiryTime = null;
47
+ jwtToken = null;
48
+ return null;
49
+ }
50
+ }