@temple-digital-group/temple-canton-js 1.0.35 → 1.0.36
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 +29 -4
- package/package.json +1 -1
- package/src/canton/index.js +90 -73
- package/src/canton/instrumentCatalog.js +24 -1
package/README.md
CHANGED
|
@@ -98,9 +98,34 @@ const command = await createOrderProposal(orderArgs, true, walletProvider);
|
|
|
98
98
|
```javascript
|
|
99
99
|
import { getUserBalances } from '@temple-digital-group/temple-canton-js';
|
|
100
100
|
|
|
101
|
+
// Custom Validator
|
|
101
102
|
const balances = await getUserBalances(partyId);
|
|
103
|
+
|
|
104
|
+
// Wallet Provider
|
|
105
|
+
const balances = await getUserBalances(partyId, walletProvider);
|
|
102
106
|
```
|
|
103
107
|
|
|
108
|
+
Each entry in the returned array contains:
|
|
109
|
+
|
|
110
|
+
```javascript
|
|
111
|
+
{
|
|
112
|
+
asset: 'USDCx', // Catalog symbol
|
|
113
|
+
total_balance: 170.5, // Unlocked + locked combined
|
|
114
|
+
available_balance: 150.5, // Unlocked balance (usable for orders)
|
|
115
|
+
locked_balance: 20.0, // Locked balance
|
|
116
|
+
dso: null, // DSO party (Amulet only)
|
|
117
|
+
registrar: '...', // Registrar party (utility tokens)
|
|
118
|
+
operator: '...', // Operator party
|
|
119
|
+
provider: '...', // Provider party
|
|
120
|
+
merge_warning: true, // true if multiple unlocked holdings exist
|
|
121
|
+
holdings: [...], // Unlocked holding contracts
|
|
122
|
+
locked_holdings: [...], // Locked holding contracts
|
|
123
|
+
utilityContext: { ... } // CIP-56 context (null when using wallet provider)
|
|
124
|
+
}
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
> **Note:** `utilityContext` is only resolved when using a custom validator (ledger API access). When using a wallet provider, it will be `null`.
|
|
128
|
+
|
|
104
129
|
### Create an Order
|
|
105
130
|
|
|
106
131
|
```javascript
|
|
@@ -187,11 +212,11 @@ These functions are synchronous and work in all environments (no ledger or provi
|
|
|
187
212
|
|
|
188
213
|
| Function | Provider | Description |
|
|
189
214
|
|----------|----------|-------------|
|
|
190
|
-
| `getAmuletHoldingsForParty(party)` | **W** | Get Amulet holdings |
|
|
191
|
-
| `
|
|
215
|
+
| `getAmuletHoldingsForParty(party, returnCommand, provider)` | **W** | Get Amulet holdings |
|
|
216
|
+
| `getLockedAmuletHoldingsForParty(party, returnCommand, provider)` | **W** | Get locked Amulet holdings |
|
|
217
|
+
| `getUtilityHoldingsForParty(party, returnCommand, provider)` | **W** | Get utility token holdings |
|
|
192
218
|
| `getCandidateHoldingForOrderCreation(party, isAmulet, quantity, assetId)` | **W** | Find a holding suitable for an order |
|
|
193
|
-
| `getUserBalances(party)` | | Get all balances
|
|
194
|
-
| `getLockedAmuletHoldingsForParty(party)` | | Get locked Amulet holdings |
|
|
219
|
+
| `getUserBalances(party, provider)` | **W** | Get all balances grouped by asset (Amulet, locked Amulet, and utility) |
|
|
195
220
|
|
|
196
221
|
### Orders
|
|
197
222
|
|
package/package.json
CHANGED
package/src/canton/index.js
CHANGED
|
@@ -26,6 +26,7 @@ import {
|
|
|
26
26
|
InstrumentKindAmulet,
|
|
27
27
|
RegistrarInternalScheme,
|
|
28
28
|
instrumentCatalog,
|
|
29
|
+
instrumentIdToSymbol,
|
|
29
30
|
supportedTradingPairs,
|
|
30
31
|
supportedSymbols
|
|
31
32
|
} from "./instrumentCatalog.js";
|
|
@@ -1943,12 +1944,26 @@ export async function getAmuletHoldingsForParty(party, returnCommand = false, pr
|
|
|
1943
1944
|
}
|
|
1944
1945
|
|
|
1945
1946
|
/**
|
|
1946
|
-
* Get locked Amulet holdings for a party from the ledger.
|
|
1947
|
+
* Get locked Amulet holdings for a party from the ledger or a provider.
|
|
1947
1948
|
* @param {string} party - The party ID
|
|
1948
1949
|
* @param {boolean} [returnCommand=false] - If true, returns the raw command/endpoint instead of executing
|
|
1950
|
+
* @param {Object|null} [provider=null] - Optional external provider to use instead of ledger API
|
|
1949
1951
|
* @returns {Promise<Object|null>} Locked holdings data, or null on failure
|
|
1950
1952
|
*/
|
|
1951
|
-
export async function getLockedAmuletHoldingsForParty(party, returnCommand = false) {
|
|
1953
|
+
export async function getLockedAmuletHoldingsForParty(party, returnCommand = false, provider = null) {
|
|
1954
|
+
// When using provider, skip ledger API calls entirely
|
|
1955
|
+
if (provider) {
|
|
1956
|
+
const args = {
|
|
1957
|
+
templateId: '#splice-amulet:Splice.Amulet:LockedAmulet'
|
|
1958
|
+
};
|
|
1959
|
+
try {
|
|
1960
|
+
return await provider.getActiveContracts(args);
|
|
1961
|
+
} catch (error) {
|
|
1962
|
+
console.error(`Error fetching locked Amulet holdings via provider: ${error}`);
|
|
1963
|
+
return null;
|
|
1964
|
+
}
|
|
1965
|
+
}
|
|
1966
|
+
|
|
1952
1967
|
const ledgerEnd = await getLedgerEnd();
|
|
1953
1968
|
if (ledgerEnd === null) {
|
|
1954
1969
|
console.error(
|
|
@@ -3857,20 +3872,21 @@ export async function unlockLockedAmulets(party, returnCommand = false) {
|
|
|
3857
3872
|
* Get all balances for a party, grouped by asset type.
|
|
3858
3873
|
* Returns Amulet, locked Amulet, and utility token holdings with totals.
|
|
3859
3874
|
* @param {string} party - The party ID
|
|
3875
|
+
* @param {Object|null} [provider=null] - Optional wallet provider to use instead of ledger API
|
|
3860
3876
|
* @returns {Promise<Object>} Balances grouped by registrar and asset, each with total_balance, holdings, etc.
|
|
3861
3877
|
*/
|
|
3862
|
-
export async function getUserBalances(party) {
|
|
3863
|
-
// Get all supported instrument IDs from the catalog
|
|
3864
|
-
const supportedInstruments = new Set(Object.keys(instrumentCatalog));
|
|
3865
|
-
|
|
3878
|
+
export async function getUserBalances(party, provider = null) {
|
|
3866
3879
|
const promises = [
|
|
3867
|
-
getAmuletHoldingsForParty(party),
|
|
3868
|
-
getLockedAmuletHoldingsForParty(party),
|
|
3869
|
-
getUtilityHoldingsForParty(party)
|
|
3880
|
+
getAmuletHoldingsForParty(party, false, provider),
|
|
3881
|
+
getLockedAmuletHoldingsForParty(party, false, provider),
|
|
3882
|
+
getUtilityHoldingsForParty(party, false, provider)
|
|
3870
3883
|
];
|
|
3871
3884
|
|
|
3872
3885
|
const [amuletHoldings, lockedAmuletHoldings, utilityHoldings] = await Promise.all(promises);
|
|
3873
3886
|
|
|
3887
|
+
// Get all supported instrument IDs from the catalog
|
|
3888
|
+
const supportedInstruments = new Set(Object.keys(instrumentCatalog));
|
|
3889
|
+
|
|
3874
3890
|
// Structure: assetsByKey[registrar][asset] = { ... }
|
|
3875
3891
|
const assetsByKey = {};
|
|
3876
3892
|
|
|
@@ -3881,8 +3897,8 @@ export async function getUserBalances(party) {
|
|
|
3881
3897
|
}
|
|
3882
3898
|
if (!assetsByKey[key][asset]) {
|
|
3883
3899
|
assetsByKey[key][asset] = {
|
|
3884
|
-
|
|
3885
|
-
|
|
3900
|
+
available_balance: 0,
|
|
3901
|
+
locked_balance: 0,
|
|
3886
3902
|
holdings: [],
|
|
3887
3903
|
locked_holdings: [],
|
|
3888
3904
|
registrar: metadata.registrar || null,
|
|
@@ -3905,19 +3921,16 @@ export async function getUserBalances(party) {
|
|
|
3905
3921
|
const synchronizerId = holdingData.contractEntry?.JsActiveContract?.synchronizerId || null;
|
|
3906
3922
|
const disclosure = createdEvent.createdEventBlob || null;
|
|
3907
3923
|
|
|
3908
|
-
// Only include if Amulet is a supported instrument
|
|
3909
|
-
if (!supportedInstruments.has("Amulet")) continue;
|
|
3910
|
-
|
|
3911
3924
|
const catalogEntry = instrumentCatalog["Amulet"];
|
|
3912
3925
|
const key = dso; // For Amulet, use DSO as the key
|
|
3913
3926
|
const entry = initAssetEntry(key, "Amulet", {
|
|
3914
|
-
registrar: catalogEntry
|
|
3927
|
+
registrar: catalogEntry?.registrar || dso,
|
|
3915
3928
|
dso: dso,
|
|
3916
|
-
operator: catalogEntry
|
|
3917
|
-
provider: catalogEntry
|
|
3929
|
+
operator: catalogEntry?.operator || null,
|
|
3930
|
+
provider: catalogEntry?.provider || null
|
|
3918
3931
|
});
|
|
3919
3932
|
|
|
3920
|
-
entry.
|
|
3933
|
+
entry.available_balance += quantity;
|
|
3921
3934
|
entry.holdings.push({
|
|
3922
3935
|
contractId: createdEvent.contractId,
|
|
3923
3936
|
quantity: quantity,
|
|
@@ -3931,7 +3944,7 @@ export async function getUserBalances(party) {
|
|
|
3931
3944
|
for (const holdingData of lockedAmuletHoldings || []) {
|
|
3932
3945
|
const createdEvent = holdingData.contractEntry?.JsActiveContract?.createdEvent;
|
|
3933
3946
|
if (!createdEvent) continue;
|
|
3934
|
-
|
|
3947
|
+
|
|
3935
3948
|
const quantity = parseFloat(createdEvent.createArgument?.amulet?.amount?.initialAmount || 0);
|
|
3936
3949
|
const dso = createdEvent.createArgument?.amulet?.dso || "Unknown DSO";
|
|
3937
3950
|
const synchronizerId = holdingData.contractEntry?.JsActiveContract?.synchronizerId || null;
|
|
@@ -3939,19 +3952,16 @@ export async function getUserBalances(party) {
|
|
|
3939
3952
|
const lockHolder = createdEvent.createArgument?.lock?.holders?.[0] || null;
|
|
3940
3953
|
const lockExpiry = createdEvent.createArgument?.lock?.expiresAt || null;
|
|
3941
3954
|
|
|
3942
|
-
// Only include if Amulet is a supported instrument
|
|
3943
|
-
if (!supportedInstruments.has("Amulet")) continue;
|
|
3944
|
-
|
|
3945
3955
|
const catalogEntry = instrumentCatalog["Amulet"];
|
|
3946
3956
|
const key = dso;
|
|
3947
3957
|
const entry = initAssetEntry(key, "Amulet", {
|
|
3948
|
-
registrar: catalogEntry
|
|
3958
|
+
registrar: catalogEntry?.registrar || dso,
|
|
3949
3959
|
dso: dso,
|
|
3950
|
-
operator: catalogEntry
|
|
3951
|
-
provider: catalogEntry
|
|
3960
|
+
operator: catalogEntry?.operator || null,
|
|
3961
|
+
provider: catalogEntry?.provider || null
|
|
3952
3962
|
});
|
|
3953
3963
|
|
|
3954
|
-
entry.
|
|
3964
|
+
entry.locked_balance += quantity;
|
|
3955
3965
|
entry.locked_holdings.push({
|
|
3956
3966
|
contractId: createdEvent.contractId,
|
|
3957
3967
|
quantity: quantity,
|
|
@@ -3970,11 +3980,16 @@ export async function getUserBalances(party) {
|
|
|
3970
3980
|
|
|
3971
3981
|
const quantity = parseFloat(createdEvent.createArgument?.amount || 0);
|
|
3972
3982
|
let asset = createdEvent.createArgument?.instrument?.id || "Unknown Utility";
|
|
3983
|
+
// Resolve on-chain instrument ID to catalog symbol (e.g. UUID -> "SBC")
|
|
3984
|
+
asset = instrumentIdToSymbol[asset] || asset;
|
|
3973
3985
|
// Normalize "Amulet" utility tokens to "tAmulet" to distinguish from native Amulet
|
|
3974
3986
|
if (asset === "Amulet") {
|
|
3975
3987
|
asset = "tAmulet";
|
|
3976
3988
|
}
|
|
3977
|
-
|
|
3989
|
+
|
|
3990
|
+
// Only include supported instruments
|
|
3991
|
+
if (!supportedInstruments.has(asset)) continue;
|
|
3992
|
+
|
|
3978
3993
|
const registrar = createdEvent.createArgument?.instrument?.source || "Unknown Registrar";
|
|
3979
3994
|
const synchronizerId = holdingData.contractEntry?.JsActiveContract?.synchronizerId || null;
|
|
3980
3995
|
const disclosure = createdEvent.createdEventBlob || null;
|
|
@@ -3985,9 +4000,6 @@ export async function getUserBalances(party) {
|
|
|
3985
4000
|
const lockHolder = lockData?.holders?.[0] || null;
|
|
3986
4001
|
const lockExpiry = lockData?.expiresAt || null;
|
|
3987
4002
|
|
|
3988
|
-
// Only include if this is a supported instrument
|
|
3989
|
-
if (!supportedInstruments.has(asset)) continue;
|
|
3990
|
-
|
|
3991
4003
|
const catalogEntry = instrumentCatalog[asset];
|
|
3992
4004
|
const key = registrar;
|
|
3993
4005
|
const entry = initAssetEntry(key, asset, {
|
|
@@ -3998,7 +4010,7 @@ export async function getUserBalances(party) {
|
|
|
3998
4010
|
});
|
|
3999
4011
|
|
|
4000
4012
|
if (isLocked) {
|
|
4001
|
-
entry.
|
|
4013
|
+
entry.locked_balance += quantity;
|
|
4002
4014
|
entry.locked_holdings.push({
|
|
4003
4015
|
contractId: createdEvent.contractId,
|
|
4004
4016
|
quantity: quantity,
|
|
@@ -4009,7 +4021,7 @@ export async function getUserBalances(party) {
|
|
|
4009
4021
|
lockExpiry
|
|
4010
4022
|
});
|
|
4011
4023
|
} else {
|
|
4012
|
-
entry.
|
|
4024
|
+
entry.available_balance += quantity;
|
|
4013
4025
|
entry.holdings.push({
|
|
4014
4026
|
contractId: createdEvent.contractId,
|
|
4015
4027
|
quantity: quantity,
|
|
@@ -4020,49 +4032,53 @@ export async function getUserBalances(party) {
|
|
|
4020
4032
|
}
|
|
4021
4033
|
}
|
|
4022
4034
|
|
|
4023
|
-
//
|
|
4024
|
-
|
|
4025
|
-
|
|
4026
|
-
|
|
4027
|
-
|
|
4028
|
-
|
|
4029
|
-
|
|
4030
|
-
|
|
4031
|
-
|
|
4032
|
-
|
|
4033
|
-
|
|
4034
|
-
|
|
4035
|
-
|
|
4036
|
-
|
|
4037
|
-
|
|
4038
|
-
|
|
4039
|
-
|
|
4040
|
-
|
|
4041
|
-
|
|
4035
|
+
// Only resolve utility contexts when NOT using a wallet provider
|
|
4036
|
+
// (resolveUtilityCip56Context requires ledger API access)
|
|
4037
|
+
if (!provider) {
|
|
4038
|
+
// Resolve utility contexts for non-Amulet assets
|
|
4039
|
+
const utilityContextPromises = new Map();
|
|
4040
|
+
for (const key of Object.keys(assetsByKey)) {
|
|
4041
|
+
for (const asset of Object.keys(assetsByKey[key])) {
|
|
4042
|
+
if (asset === "Amulet") {
|
|
4043
|
+
continue;
|
|
4044
|
+
}
|
|
4045
|
+
const assetEntry = assetsByKey[key][asset];
|
|
4046
|
+
if (assetEntry.utilityContext) {
|
|
4047
|
+
continue;
|
|
4048
|
+
}
|
|
4049
|
+
const registrar = assetEntry.registrar || key;
|
|
4050
|
+
const cacheKey = `${registrar || "*"}::${asset}`;
|
|
4051
|
+
if (!utilityContextPromises.has(cacheKey)) {
|
|
4052
|
+
utilityContextPromises.set(cacheKey, resolveUtilityCip56Context({
|
|
4053
|
+
party,
|
|
4054
|
+
registrar,
|
|
4055
|
+
utilityAsset: asset
|
|
4056
|
+
}));
|
|
4057
|
+
}
|
|
4042
4058
|
}
|
|
4043
4059
|
}
|
|
4044
|
-
}
|
|
4045
4060
|
|
|
4046
|
-
|
|
4047
|
-
|
|
4048
|
-
|
|
4049
|
-
|
|
4061
|
+
// Await all utility context promises
|
|
4062
|
+
for (const [key, promise] of utilityContextPromises.entries()) {
|
|
4063
|
+
utilityContextPromises.set(key, await promise);
|
|
4064
|
+
}
|
|
4050
4065
|
|
|
4051
|
-
|
|
4052
|
-
|
|
4053
|
-
|
|
4054
|
-
|
|
4055
|
-
|
|
4056
|
-
|
|
4057
|
-
|
|
4058
|
-
|
|
4059
|
-
|
|
4060
|
-
|
|
4061
|
-
|
|
4062
|
-
|
|
4063
|
-
|
|
4064
|
-
|
|
4065
|
-
|
|
4066
|
+
// Assign utility contexts
|
|
4067
|
+
for (const key of Object.keys(assetsByKey)) {
|
|
4068
|
+
for (const asset of Object.keys(assetsByKey[key])) {
|
|
4069
|
+
if (asset === "Amulet") {
|
|
4070
|
+
continue;
|
|
4071
|
+
}
|
|
4072
|
+
const assetEntry = assetsByKey[key][asset];
|
|
4073
|
+
if (assetEntry.utilityContext) {
|
|
4074
|
+
continue;
|
|
4075
|
+
}
|
|
4076
|
+
const registrar = assetEntry.registrar || key;
|
|
4077
|
+
const cacheKey = `${registrar || "*"}::${asset}`;
|
|
4078
|
+
assetEntry.utilityContext = utilityContextPromises.get(cacheKey) || null;
|
|
4079
|
+
if (!assetEntry.registrar && assetEntry.utilityContext?.registrar) {
|
|
4080
|
+
assetEntry.registrar = assetEntry.utilityContext.registrar;
|
|
4081
|
+
}
|
|
4066
4082
|
}
|
|
4067
4083
|
}
|
|
4068
4084
|
}
|
|
@@ -4074,8 +4090,9 @@ export async function getUserBalances(party) {
|
|
|
4074
4090
|
const assetEntry = assetsByKey[key][asset];
|
|
4075
4091
|
balances.push({
|
|
4076
4092
|
asset: asset,
|
|
4077
|
-
total_balance: assetEntry.
|
|
4078
|
-
|
|
4093
|
+
total_balance: assetEntry.available_balance + assetEntry.locked_balance,
|
|
4094
|
+
available_balance: assetEntry.available_balance,
|
|
4095
|
+
locked_balance: assetEntry.locked_balance,
|
|
4079
4096
|
dso: assetEntry.dso,
|
|
4080
4097
|
registrar: assetEntry.registrar,
|
|
4081
4098
|
operator: assetEntry.operator,
|
|
@@ -132,9 +132,32 @@ export const instrumentCatalog = {
|
|
|
132
132
|
eventBlob: "CgMyLjESigcKRQBctH85ukdhXkql3QKxd2PMDtoDCHrmye6OOOgsE0YqrsoREiAtJTdNPPLAo2qNBxCDbU4BocW3NHP0W2qBACxdqoygyxITdXRpbGl0eS1yZWdpc3RyeS12MBqLAQpAZWQ3M2Q1YjlhYjcxNzMzM2YzZGJkMTIyZGU3YmUzMTU2ZjhiZjI2MTRhNjczNjBjM2RkNjFmYzAxMzUxMzNmYRIHVXRpbGl0eRIIUmVnaXN0cnkSAlYwEg1Db25maWd1cmF0aW9uEglBcHBSZXdhcmQaFkFwcFJld2FyZENvbmZpZ3VyYXRpb24iqgNqpwMKbApqOmhhdXRoMF8wMDdjNjY0MzUzOGYyZWFkZDNlNTczZGQwNWI5OjoxMjIwNWJjYzEwNmVmYTBlYWE3ZjE4ZGM0OTFlNWM2ZjVmYjliMGNjNjhkYzExMGFlNjZmNGVkNjQ2NzQ3NWQ3Yzc4ZQpWClQ6UmNidGMtbmV0d29yazo6MTIyMDVhZjNiOTQ5YTA0Nzc2ZmM0OGNkY2MwNWEwNjBmNmJkYTJlNDcwNjMyOTM1ZjM3NWQxMDQ5YTg1NDZhM2IyNjIK3gEK2wFq2AEKTQpLOklEU086OjEyMjBiMTQzMWVmMjE3MzQyZGI0NGQ1MTZiYjliZWZkZTgwMmJlN2Q4ODk5NjM3ZDI5MDg5NWZhNTg4ODBmMTlhY2NjCoYBCoMBaoABCmwKajpoYXV0aDBfMDA3YzY3ZGM3YzRhZmJmNWJjMzdmOTgwNWUzMTo6MTIyMDViY2MxMDZlZmEwZWFhN2YxOGRjNDkxZTVjNmY1ZmI5YjBjYzY4ZGMxMTBhZTY2ZjRlZDY0Njc0NzVkN2M3OGUKEAoOMgwwLjIwMDAwMDAwMDAqaGF1dGgwXzAwN2M2NjQzNTM4ZjJlYWRkM2U1NzNkZDA1Yjk6OjEyMjA1YmNjMTA2ZWZhMGVhYTdmMThkYzQ5MWU1YzZmNWZiOWIwY2M2OGRjMTEwYWU2NmY0ZWQ2NDY3NDc1ZDdjNzhlMlJjYnRjLW5ldHdvcms6OjEyMjA1YWYzYjk0OWEwNDc3NmZjNDhjZGNjMDVhMDYwZjZiZGEyZTQ3MDYzMjkzNWYzNzVkMTA0OWE4NTQ2YTNiMjYyOSqKuWddQgYAQioKJgokCAESIP6u2ZhXB5fXuwvdDvhv+mn6JPF20D2scQdCh/yRSuNsEB4="
|
|
133
133
|
}
|
|
134
134
|
}
|
|
135
|
-
}
|
|
135
|
+
},
|
|
136
|
+
|
|
137
|
+
// SBC (Stablecoin) -- used for balance reporting, but not a tradable instrument itself
|
|
138
|
+
"SBC": {
|
|
139
|
+
id: "f29bdd7a-1469-498a-ba2a-796bf5387b31",
|
|
140
|
+
scheme: RegistrarInternalScheme,
|
|
141
|
+
kind: InstrumentKindUtility,
|
|
142
|
+
disclosureURL: null,
|
|
143
|
+
requireCredentials: false,
|
|
144
|
+
mainnet: {
|
|
145
|
+
synchronizerId: "global-domain::1220b1431ef217342db44d516bb9befde802be7d8899637d290895fa58880f19accc",
|
|
146
|
+
registrar: "party-28dc4516-b5ca-44ff-86c7-2107e90a6807::1220b8301e18aa8a401d6e34e6c20f8b0243183c514373bca8f1b6b9270246341a9e",
|
|
147
|
+
operator: "auth0_007c6643538f2eadd3e573dd05b9::12205bcc106efa0eaa7f18dc491e5c6f5fb9b0cc68dc110ae66f4ed6467475d7c78e",
|
|
148
|
+
provider: "party-28dc4516-b5ca-44ff-86c7-2107e90a6807::1220b8301e18aa8a401d6e34e6c20f8b0243183c514373bca8f1b6b9270246341a9e",
|
|
149
|
+
}
|
|
150
|
+
},
|
|
136
151
|
};
|
|
137
152
|
|
|
153
|
+
// Reverse lookup: maps on-chain instrument IDs to catalog keys
|
|
154
|
+
// (for instruments where the on-chain ID differs from the catalog key, e.g. UUID -> "SBC")
|
|
155
|
+
export const instrumentIdToSymbol = Object.fromEntries(
|
|
156
|
+
Object.entries(instrumentCatalog)
|
|
157
|
+
.filter(([key, entry]) => entry.id && entry.id !== key)
|
|
158
|
+
.map(([key, entry]) => [entry.id, key])
|
|
159
|
+
);
|
|
160
|
+
|
|
138
161
|
// Supported trading pairs (like Go's supportedTradingPairs)
|
|
139
162
|
export const supportedTradingPairs = [
|
|
140
163
|
{ baseAsset: "Amulet", quoteAsset: "USDCx" },
|