emblem-vault-sdk 2.3.6 → 3.0.0-experimental

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 (147) hide show
  1. package/.traces/blockchain-provider-abstraction-plan.md +302 -0
  2. package/.traces/notes.md +43 -0
  3. package/.traces/readme-verification-trace.md +988 -0
  4. package/.traces/test-migration-status.md +227 -0
  5. package/.traces/tests-consolidated-trace.md +667 -0
  6. package/dist/abi/abi.json +53 -0
  7. package/dist/bundle.js +21602 -17419
  8. package/dist/clients/emblemVaultSolanaWalletClient.d.ts +74 -0
  9. package/dist/clients/emblemVaultSolanaWalletClient.js +149 -0
  10. package/dist/clients/emblemVaultSolanaWalletClient.js.map +1 -0
  11. package/dist/clients/emblemVaultWalletClient.d.ts +52 -0
  12. package/dist/clients/emblemVaultWalletClient.js +110 -0
  13. package/dist/clients/emblemVaultWalletClient.js.map +1 -0
  14. package/dist/derive.js +7 -0
  15. package/dist/derive.js.map +1 -0
  16. package/dist/index.js +319 -114
  17. package/dist/index.js.map +1 -0
  18. package/dist/providers/ProviderManager.d.ts +57 -0
  19. package/dist/providers/ProviderManager.js +283 -0
  20. package/dist/providers/ProviderManager.js.map +1 -0
  21. package/dist/providers.d.ts +101 -0
  22. package/dist/providers.js +96 -0
  23. package/dist/providers.js.map +1 -0
  24. package/dist/types.js +1 -0
  25. package/dist/types.js.map +1 -0
  26. package/dist/utils.js +61 -58
  27. package/dist/utils.js.map +1 -0
  28. package/docs/bundle.js +21602 -17419
  29. package/docs/index.html +150 -13
  30. package/docs/local.html +385 -0
  31. package/docs/steps.html +420 -53
  32. package/package.json +22 -13
  33. package/readme.md +795 -21
  34. package/src/abi/abi.json +54 -1
  35. package/src/clients/emblemVaultSolanaWalletClient.ts +257 -0
  36. package/src/clients/emblemVaultWalletClient.ts +159 -0
  37. package/src/derive.ts +5 -5
  38. package/src/index.ts +320 -102
  39. package/src/providers/ProviderManager.ts +254 -0
  40. package/src/providers.ts +163 -0
  41. package/src/types.ts +50 -0
  42. package/src/utils.ts +63 -62
  43. package/test/.mocharc.js +8 -0
  44. package/test/README.md +212 -0
  45. package/test/fixtures/ethscriptions/balance-with-native-first.json +24 -0
  46. package/test/fixtures/ethscriptions/balance-with-native.json +23 -0
  47. package/test/fixtures/ethscriptions/balance.json +18 -0
  48. package/test/helpers/sdkLoader.js +88 -0
  49. package/test/helpers/setup.js +55 -0
  50. package/test/integration/ApiOperations.spec.js +102 -0
  51. package/test/integration/VaultAI.spec.js +57 -0
  52. package/test/integration/VaultCreation.spec.js +95 -0
  53. package/test/mocks.js +127 -0
  54. package/test/tsconfig.json +25 -0
  55. package/test/unit/AllowedBells.spec.js +53 -0
  56. package/test/unit/AllowedBitcoinDeGods.spec.js +53 -0
  57. package/test/unit/AllowedBitcoinOrdinals.spec.js +46 -0
  58. package/test/unit/AllowedCounterparty.spec.js +66 -0
  59. package/test/unit/AllowedCursedOrdinals.spec.js +68 -0
  60. package/test/unit/AllowedEmbells.spec.js +11 -0
  61. package/test/unit/AllowedEmbels.spec.js +11 -0
  62. package/test/unit/AllowedEmblemOpen.spec.js +20 -0
  63. package/test/unit/AllowedEthscriptions.spec.js +53 -0
  64. package/test/unit/AllowedHardcodedNfts.spec.js +77 -0
  65. package/test/unit/AllowedNamecoin.spec.js +33 -0
  66. package/test/unit/AllowedOrdi.spec.js +46 -0
  67. package/test/unit/AllowedOxbt.spec.js +46 -0
  68. package/test/unit/AllowedProjectCollection.spec.js +51 -0
  69. package/test/unit/AllowedProtocolCollection.spec.js +44 -0
  70. package/test/unit/AllowedStamps.spec.js +78 -0
  71. package/test/unit/DarkfarmsMetadata.spec.js +10 -0
  72. package/test/unit/EmblemVaultSdk.spec.js +188 -0
  73. package/test/unit/Providers.spec.js +290 -0
  74. package/test/unit/ResourceMonitor.spec.js +111 -0
  75. package/test/unit/SDKMemoryLeaks.spec.js +176 -0
  76. package/test/unit/Signing.spec.js +321 -0
  77. package/test/unit/VaultAI.spec.js +140 -0
  78. package/test/unit/clients/EmblemVaultSolanaWalletClient.spec.js +296 -0
  79. package/test/unit/clients/EmblemVaultWalletClient.spec.js +246 -0
  80. package/test/utils/ResourceMonitor.js +169 -0
  81. package/test/windsurf-rules.md +68 -0
  82. package/tsconfig.json +7 -3
  83. package/types/derive.d.ts +0 -5
  84. package/types/index.d.ts +152 -32
  85. package/types/types.d.ts +43 -0
  86. package/types/utils.d.ts +7 -1
  87. package/dist/abi/quote.js +0 -29
  88. package/dist/abi/quote.json +0 -26
  89. package/jest.config.js +0 -6
  90. package/tests/AllowedBells.test.ts +0 -53
  91. package/tests/AllowedBitcoinDeGods.test.ts +0 -53
  92. package/tests/AllowedBitcoinOrdinals.test.ts +0 -46
  93. package/tests/AllowedCounterparty.test.ts +0 -45
  94. package/tests/AllowedCursedOrdinals.test.ts +0 -68
  95. package/tests/AllowedEmbells.test.ts +0 -12
  96. package/tests/AllowedEmbels.test.ts +0 -16
  97. package/tests/AllowedEmblemOpen.test.ts +0 -20
  98. package/tests/AllowedEthscriptions.test.ts +0 -39
  99. package/tests/AllowedHardcodedNfts.test.ts +0 -78
  100. package/tests/AllowedNamecoin.test.ts +0 -33
  101. package/tests/AllowedOrdi.test.ts +0 -47
  102. package/tests/AllowedOxbt.test.ts +0 -47
  103. package/tests/AllowedProjectlCollection.test.ts +0 -51
  104. package/tests/AllowedProtocolCollection.test.ts +0 -44
  105. package/tests/AllowedStamps.test.ts +0 -73
  106. package/tests/DarkfarmsMetadata.test.ts +0 -10
  107. package/tests/EmblemVaultSdk.test.ts +0 -124
  108. package/tests/fixtures/embels/balance.json +0 -10
  109. package/tests/fixtures/ethscriptions/balance-with-native-first.json +0 -69
  110. package/tests/fixtures/ethscriptions/balance-with-native.json +0 -37
  111. package/tests/fixtures/ethscriptions/balance.json +0 -64
  112. /package/{tests → test}/fixtures/bells/balance-with-non-bell-first.json +0 -0
  113. /package/{tests → test}/fixtures/bells/balance-with-non-bell.json +0 -0
  114. /package/{tests → test}/fixtures/bells/balance.json +0 -0
  115. /package/{tests → test}/fixtures/bitcoin-degods/balance-with-non-degods-first.json +0 -0
  116. /package/{tests → test}/fixtures/bitcoin-degods/balance-with-non-degods.json +0 -0
  117. /package/{tests → test}/fixtures/bitcoin-degods/balance.json +0 -0
  118. /package/{tests → test}/fixtures/bitcoin-ordinals/balance-with-native-first.json +0 -0
  119. /package/{tests → test}/fixtures/bitcoin-ordinals/balance-with-only-native.json +0 -0
  120. /package/{tests → test}/fixtures/bitcoin-ordinals/balance.json +0 -0
  121. /package/{tests → test}/fixtures/counterparty/balance-with-multiple.json +0 -0
  122. /package/{tests → test}/fixtures/counterparty/balance.json +0 -0
  123. /package/{tests → test}/fixtures/cursed-ordinals/balance-with-native-first.json +0 -0
  124. /package/{tests → test}/fixtures/cursed-ordinals/balance-with-native.json +0 -0
  125. /package/{tests → test}/fixtures/cursed-ordinals/balance.json +0 -0
  126. /package/{tests → test}/fixtures/dogeparty/balance-with-non-dogeparty-first.json +0 -0
  127. /package/{tests → test}/fixtures/dogeparty/balance-with-non-dogeparty.json +0 -0
  128. /package/{tests → test}/fixtures/dogeparty/balance.json +0 -0
  129. /package/{tests → test}/fixtures/emblem-open/balance.json +0 -0
  130. /package/{tests → test}/fixtures/hardcoded-nfts/balance-witn-non-hardcoded-first.json +0 -0
  131. /package/{tests → test}/fixtures/hardcoded-nfts/balance-witn-non-hardcoded.json +0 -0
  132. /package/{tests → test}/fixtures/hardcoded-nfts/balance.json +0 -0
  133. /package/{tests → test}/fixtures/megapunks/balance-with-non-megapunk-first.json +0 -0
  134. /package/{tests → test}/fixtures/megapunks/balance-with-non-megapunk.json +0 -0
  135. /package/{tests → test}/fixtures/megapunks/balance.json +0 -0
  136. /package/{tests → test}/fixtures/namecoin/balance-with-native-first.json +0 -0
  137. /package/{tests → test}/fixtures/namecoin/balance-with-native.json +0 -0
  138. /package/{tests → test}/fixtures/namecoin/balance.json +0 -0
  139. /package/{tests → test}/fixtures/ordi/balance-with-native-first.json +0 -0
  140. /package/{tests → test}/fixtures/ordi/balance-with-native.json +0 -0
  141. /package/{tests → test}/fixtures/ordi/balance.json +0 -0
  142. /package/{tests → test}/fixtures/oxbt/balance-with-native-first.json +0 -0
  143. /package/{tests → test}/fixtures/oxbt/balance-with-native.json +0 -0
  144. /package/{tests → test}/fixtures/oxbt/balance.json +0 -0
  145. /package/{tests → test}/fixtures/stamps/balance-with-non-stamps-first.json +0 -0
  146. /package/{tests → test}/fixtures/stamps/balance-with-non-stamps.json +0 -0
  147. /package/{tests → test}/fixtures/stamps/balance.json +0 -0
package/docs/steps.html CHANGED
@@ -1,68 +1,425 @@
1
1
  <!DOCTYPE html>
2
2
  <html>
3
3
  <head>
4
- <title>Steps
5
- </title>
4
+ <title>Emblem Vault SDK - Step by Step Guide</title>
6
5
  <style>
7
- input, select, button {
6
+ input, select, button, textarea {
8
7
  padding: 10px;
9
8
  margin: 5px;
10
9
  }
11
10
  #tokenImage{
12
11
  max-width: 300px;
13
12
  }
13
+ #contractSelectContainer {
14
+ margin: 15px 0;
15
+ }
16
+ pre {
17
+ background-color: #f5f5f5;
18
+ padding: 10px;
19
+ border-radius: 5px;
20
+ overflow-x: auto;
21
+ }
22
+ .step-button {
23
+ background-color: #4CAF50;
24
+ color: white;
25
+ border: none;
26
+ border-radius: 4px;
27
+ cursor: pointer;
28
+ }
29
+ .step-button:disabled {
30
+ background-color: #cccccc;
31
+ cursor: not-allowed;
32
+ }
33
+ #userInputForm {
34
+ display: none;
35
+ border: 1px solid #ccc;
36
+ padding: 15px;
37
+ margin: 15px 0;
38
+ background-color: #f9f9f9;
39
+ }
40
+ .form-group {
41
+ margin-bottom: 10px;
42
+ }
43
+ .form-group label {
44
+ display: block;
45
+ margin-bottom: 5px;
46
+ font-weight: bold;
47
+ }
48
+ .required {
49
+ color: red;
50
+ }
14
51
  </style>
15
52
  </head>
16
53
  <body>
17
- note: this demo uses 0x345eF9d7E75aEEb979053AA41BB6330683353B7b the BTC DeGods contract on mainnet
18
- <h1>Vault it</h1>
54
+ <h1>Emblem Vault - Step by Step Guide</h1>
19
55
  <script src="./bundle.js"></script>
56
+ <script src="./bitcoinjs-lib.js"></script>
20
57
  <script>
58
+ window.bitcoin = bitcoin;
21
59
  const sdk = new EmblemVaultSDK('demo'); // Instantiate SDK
60
+ let vaultBalance, vaultData, defaultAccount;
61
+ let mintTemplate = {};
62
+ let curatedContracts = [];
63
+ let selectedContract = null;
64
+
65
+ // Set connected Account
66
+ // Load curated contracts when the page loads
67
+ window.onload = async function() {
68
+ try {
69
+ // defaultAccount = await sdk.getConnectedEthAccount();
70
+ curatedContracts = await sdk.fetchCuratedContracts(false);
71
+ generateContractDropdown(curatedContracts);
72
+ updateLogCallback('Loaded', curatedContracts.length + ' curated contracts');
73
+ } catch (error) {
74
+ updateLogCallback('Error loading contracts', error.message);
75
+ }
76
+ };
77
+
78
+ // Generate dropdown for contract selection
79
+ function generateContractDropdown(contracts) {
80
+ const selectElement = document.getElementById('contractSelect');
81
+ selectElement.innerHTML = ''; // Clear existing options
82
+
83
+ // Add default option
84
+ const defaultOption = document.createElement('option');
85
+ defaultOption.value = '';
86
+ defaultOption.text = 'Select a contract';
87
+ selectElement.appendChild(defaultOption);
88
+
89
+ // Add contract options
90
+ contracts.forEach((contract, index) => {
91
+ if (contract.mintable) { // Only show mintable contracts
92
+ const option = document.createElement('option');
93
+ option.value = index;
94
+ option.text = contract.name;
95
+ selectElement.appendChild(option);
96
+ }
97
+ });
22
98
 
23
- // Template used for creating vaults
24
- let contractTemplate = {
25
- "fromAddress": null,
26
- "toAddress": null,
27
- "chainId":1,
28
- "experimental":true,
29
- "targetContract":{
30
- "1":"0x345eF9d7E75aEEb979053AA41BB6330683353B7b",
31
- "5":"0x582699d2c58A38056Cf02875540705137f0bbbF7",
32
- "name":"Bitcoin DeGods",
33
- "description":"Bitcoin DeGods is a collection of 535 Bitcoin Ordinals inscribed in the 77236 to 77770 range. This collection is curated by Emblem Vault. "
34
- },
35
- "targetAsset":{
36
- "image":"https://emblem.finance/btcdegods.jpg",
37
- "name":"Loading...",
38
- "xtra": "anything else you need here"
99
+ // Add change event listener
100
+ selectElement.addEventListener('change', selectContract);
101
+ }
102
+
103
+ // Handle contract selection
104
+ async function selectContract() {
105
+ const selectElement = document.getElementById('contractSelect');
106
+ const selectedIndex = selectElement.value;
107
+
108
+ if (selectedIndex === '') {
109
+ updateLogCallback('Error', 'Please select a contract');
110
+ document.getElementById('step1Button').disabled = true;
111
+ return;
112
+ }
113
+
114
+ selectedContract = curatedContracts[selectedIndex];
115
+ updateLogCallback('Selected contract', selectedContract.name);
116
+
117
+ // Get mint template from contract
118
+ mintTemplate = selectedContract.mintTemplate
119
+ updateLogCallback('Mint template acquired', mintTemplate);
120
+
121
+ // Function to populate template with account info
122
+ async function populateTemplateWithAccountInfo() {
123
+ if (!defaultAccount) { // Only load web3 if not already loaded
124
+ await sdk.loadWeb3(); // Can be any web3 provider
125
+ defaultAccount = (await sdk.getProvider("ethereum").eth.getAccounts())[0]; // Minter's address
126
+ updateLogCallback('Loading default account from web3:', defaultAccount);
127
+ }
128
+
129
+ let chainId = Number(await sdk.getProvider("ethereum").eth.net.getId());
130
+
131
+ // populate the template
132
+ mintTemplate.toAddress = defaultAccount;
133
+ mintTemplate.fromAddress = defaultAccount;
134
+ mintTemplate.chainId = chainId;
135
+ updateLogCallback('Mint template fromAddress populated with default account:', mintTemplate.fromAddress);
136
+ updateLogCallback('Mint template toAddress populated with default account:', mintTemplate.toAddress);
137
+ updateLogCallback('Mint template populated with chainId:', mintTemplate.chainId);
138
+
139
+ // Validate template after population
140
+ await validateMintTemplate();
141
+ }
142
+
143
+ // Call the function to populate the template
144
+ await populateTemplateWithAccountInfo();
145
+
146
+ // Hide the user input form by default
147
+ document.getElementById('userInputForm').style.display = 'none';
148
+ document.getElementById('assetSelectContainer').style.display = 'none';
149
+
150
+ // Check if this is an open collection that requires user input
151
+ if (selectedContract.loadTypes.includes("detailed")) {
152
+ // Show the user input form
153
+ document.getElementById('userInputForm').style.display = 'block';
154
+ } else if (selectedContract.loadTypes.includes("select")) {
155
+ // Show the asset selection dropdown
156
+ document.getElementById('assetSelectContainer').style.display = 'block';
157
+ await loadAssetsForSelection();
158
+ }
159
+ }
160
+
161
+ // Function to update template from form inputs
162
+ async function updateTemplateFromForm() {
163
+ if (!mintTemplate || !mintTemplate.targetAsset) return;
164
+
165
+ // Get user input values
166
+ if (document.getElementById('userInputName') && document.getElementById('userInputName').value){
167
+ const nameInput = document.getElementById('userInputName').value? document.getElementById('userInputName').value.trim(): null;
168
+ if (nameInput) mintTemplate.targetAsset.name = nameInput;
169
+ }
170
+
171
+ if (document.getElementById('userInputImage') && document.getElementById('userInputImage').value){
172
+ const imageInput = document.getElementById('userInputImage').value? document.getElementById('userInputImage').value.trim(): null;
173
+ if (imageInput) mintTemplate.targetAsset.image = imageInput;
174
+ }
175
+ if (document.getElementById('userInputDescription') && document.getElementById('userInputDescription').value){
176
+ const descriptionInput = document.getElementById('userInputDescription').value? document.getElementById('userInputDescription').value.trim(): null;
177
+ if (descriptionInput) mintTemplate.targetAsset.description = descriptionInput;
178
+ }
179
+ updateLogCallback('Mint template updated with target asset:', mintTemplate.targetAsset);
180
+ await validateMintTemplate();
181
+ }
182
+
183
+ // Function to load assets for selection
184
+ async function loadAssetsForSelection() {
185
+ const assets = sdk.getAssetMetadata(selectedContract.name);
186
+ const selectElement = document.getElementById('vaultAssetSelect');
187
+ selectElement.innerHTML = ''; // Clear existing options
188
+
189
+ // Add default option
190
+ const defaultOption = document.createElement('option');
191
+ defaultOption.value = '';
192
+ defaultOption.text = 'Select an asset';
193
+ selectElement.appendChild(defaultOption);
194
+
195
+ // Add asset options
196
+ assets.forEach((asset, index) => {
197
+ const option = document.createElement('option');
198
+ option.value = index;
199
+ option.text = asset.assetName;
200
+ selectElement.appendChild(option);
201
+ });
202
+
203
+ // Store assets in window for later use
204
+ window.assets = assets;
205
+ }
206
+
207
+ // Function to update template from selected asset
208
+ async function updateTemplateFromSelectedAsset() {
209
+ const selectElement = document.getElementById('vaultAssetSelect');
210
+ const selectedIndex = selectElement.value;
211
+
212
+ if (selectedIndex === '') {
213
+ updateLogCallback('Error', 'Please select an asset');
214
+ return;
215
+ }
216
+
217
+ const selectedAsset = window.assets[selectedIndex];
218
+
219
+ // Update the template with the selected asset
220
+ if (mintTemplate.targetAsset) {
221
+ if (selectedAsset.assetName) mintTemplate.targetAsset.name = selectedAsset.assetName;
222
+ if (selectedAsset.image) mintTemplate.targetAsset.image = selectedAsset.image;
223
+ if (selectedAsset.description) mintTemplate.targetAsset.description = selectedAsset.description;
224
+ }
225
+
226
+ updateLogCallback('Mint template updated with selected asset:', mintTemplate.targetAsset);
227
+ await validateMintTemplate();
228
+ }
229
+
230
+ async function validateMintTemplate() {
231
+ if (!mintTemplate || !mintTemplate.targetContract ||!selectedContract) {
232
+ document.getElementById('step1Button').disabled = true;
233
+ updateLogCallback('Mint template validation failed', 'Template or contract not initialized');
234
+ return;
235
+ }
236
+ console.log('mintTemplate', mintTemplate);
237
+
238
+ selectedContract.validateTemplate(mintTemplate, (mintTemplateValidation) => {
239
+ if (mintTemplateValidation.valid) {
240
+ document.getElementById('step1Button').disabled = false;
241
+ updateLogCallback('Mint template validated successfully', JSON.stringify(mintTemplateValidation.valid));
242
+ } else {
243
+ document.getElementById('step1Button').disabled = true;
244
+ // Format errors for better readability - simple approach
245
+ let errorText = '';
246
+ try {
247
+ // Just get the first error for simplicity
248
+ if (mintTemplateValidation.errors && mintTemplateValidation.errors.length > 0) {
249
+ // Get the raw error text and strip ALL quotes and formatting
250
+ const rawError = mintTemplateValidation.errors[0].toString();
251
+ errorText = rawError.replace(/['"]/g, '');
252
+ }
253
+ } catch (e) {
254
+ errorText = 'Invalid template format';
255
+ }
256
+ updateLogCallback('Mint template validation failed', errorText);
257
+ }
258
+ });
259
+
260
+ }
261
+
262
+ // Function to format object for logging
263
+ function formatObjectForLog(obj) {
264
+ if (!obj) return 'empty';
265
+
266
+ // Create a simplified representation
267
+ const formatted = {};
268
+ Object.keys(obj).forEach(key => {
269
+ if (typeof obj[key] === 'object' && obj[key] !== null) {
270
+ formatted[key] = 'object';
271
+ } else {
272
+ formatted[key] = obj[key];
273
+ }
274
+ });
275
+
276
+ return Object.entries(formatted)
277
+ .map(([key, value]) => `${key}: ${value}`)
278
+ .join(', ');
279
+ }
280
+
281
+ // Update log callback function
282
+ function updateLogCallback(title, message) {
283
+ let formattedMessage = message;
284
+
285
+ // Format objects for better readability
286
+ if (typeof message === 'object' && message !== null) {
287
+ formattedMessage = formatObjectForLog(message);
288
+ }
289
+
290
+ const logElement = document.getElementById('log');
291
+ logElement.innerHTML += `<div><strong>${title}:</strong> ${formattedMessage}</div>`;
292
+ logElement.scrollTop = logElement.scrollHeight;
293
+ }
294
+
295
+ // Function to fetch metadata for an existing vault
296
+ async function fetchExistingVault() {
297
+ const tokenId = document.getElementById('existingVaultId').value.trim();
298
+ if (!tokenId) {
299
+ updateLogCallback('Error', 'Please enter a valid token ID');
300
+ return;
301
+ }
302
+
303
+ try {
304
+ updateLogCallback('Fetching metadata for token ID', tokenId);
305
+ const metadata = await sdk.fetchMetadata(tokenId);
306
+
307
+ if (metadata) {
308
+ vaultData = metadata;
309
+ updateLogCallback('Metadata fetched successfully', metadata);
310
+
311
+ // Log all deposit addresses
312
+ if (metadata.addresses && metadata.addresses.length > 0) {
313
+ updateLogCallback('Available Deposit Addresses:', '');
314
+ metadata.addresses.forEach(addr => {
315
+ updateLogCallback(`${addr.coin} Address:`, addr.address);
316
+ });
317
+ }
318
+
319
+ // Enable step 2 button
320
+ document.getElementById('step1Button').disabled = true;
321
+ document.getElementById('step2Button').disabled = false;
322
+
323
+ // Find the contract for this vault
324
+ if (metadata.targetContract && metadata.targetContract.name) {
325
+ const contractName = metadata.targetContract.name;
326
+ const contract = await sdk.fetchCuratedContractByName(contractName);
327
+ if (contract) {
328
+ selectedContract = contract;
329
+ mintTemplate = { targetContract: { name: contractName } };
330
+ updateLogCallback('Found contract for vault', contractName);
331
+ }
332
+ }
333
+ } else {
334
+ updateLogCallback('Error', 'No metadata found for this token ID');
335
+ }
336
+ } catch (error) {
337
+ updateLogCallback('Error fetching metadata', error.message || 'Unknown error');
39
338
  }
40
339
  }
41
- let defaultAccount, vaultBalance, vaultData;
42
340
  </script>
43
341
 
342
+ <div id="contractSelectContainer">
343
+ <h3>Step 0: Select a Contract</h3>
344
+ <select id="contractSelect"></select>
345
+ </div>
346
+
347
+ <!-- <div id="existingVaultContainer" style="margin: 15px 0; padding: 15px; border: 1px solid #ccc; background-color: #f9f9f9;">
348
+ <h3>Or Load an Existing Vault</h3>
349
+ <div class="form-group">
350
+ <label for="existingVaultId">Enter Vault Token ID:</label>
351
+ <input type="text" id="existingVaultId" placeholder="Enter token ID">
352
+ <button onclick="fetchExistingVault()" class="step-button">Load Vault</button>
353
+ </div>
354
+ </div> -->
355
+
356
+ <!-- User Input Form for Open Collections -->
357
+ <div id="userInputForm">
358
+ <h3>Enter Vault Details</h3>
359
+ <div class="form-group">
360
+ <label for="userInputName">Name <span class="required">*</span></label>
361
+ <input type="text" id="userInputName" placeholder="Enter vault name" required onchange="updateTemplateFromForm()">
362
+ </div>
363
+ <div class="form-group">
364
+ <label for="userInputImage">Image URL <span class="required">*</span></label>
365
+ <input type="text" id="userInputImage" placeholder="Enter image URL" required onchange="updateTemplateFromForm()">
366
+ </div>
367
+ <div class="form-group">
368
+ <label for="userInputDescription">Description</label>
369
+ <textarea id="userInputDescription" placeholder="Enter description" rows="3" onchange="updateTemplateFromForm()"></textarea>
370
+ </div>
371
+ </div>
372
+
373
+ <!-- Asset Selection Dropdown for Select Collections -->
374
+ <div id="assetSelectContainer" style="display: none;">
375
+ <h3>Select Asset</h3>
376
+ <div class="form-group">
377
+ <label for="vaultAssetSelect">Available Assets <span class="required">*</span></label>
378
+ <select id="vaultAssetSelect" onchange="updateTemplateFromSelectedAsset()"></select>
379
+ </div>
380
+ </div>
44
381
 
45
- <button id="step1Button" onclick="Step1()">Step 1 (Create Vault)</button>
46
- <button id="step2Button" onclick="Step2()" disabled>Step 2 (Refresh Vault)</button>
47
- <button id="step3Button" onclick="Step3()" disabled>Step 3 (Validate Mintability)</button>
382
+ <button id="step1Button" class="step-button" onclick="Step1()" disabled>Step 1 (Create Vault)</button>
383
+ <button id="step2Button" class="step-button" onclick="Step2()" disabled>Step 2 (Refresh Vault)</button>
384
+ <button id="step3Button" class="step-button" onclick="Step3()" disabled>Step 3 (Mint)</button>
385
+ <button onclick="clearLog()">Clear Log</button>
386
+
48
387
  <script>
49
388
  async function Step1() {
50
- if (!defaultAccount) { // Only load web3 if not already loaded
51
- await sdk.loadWeb3() // Can be any web3 provider
52
- defaultAccount = await web3.eth.getAccounts().then(accounts => accounts[0]).catch(err=>console) // Minter's address
53
- }
54
389
  if (!vaultData) {
55
- let chainId = Number(await web3.eth.net.getId())
56
- // populate the template
57
- contractTemplate.toAddress = defaultAccount;
58
- contractTemplate.fromAddress = defaultAccount;
59
- contractTemplate.chainId = chainId;
390
+ if (mintTemplate.targetContract.vaultCollectionType === "open") {
391
+
392
+ const nameInput = document.getElementById('userInputName').value;
393
+ const imageInput = document.getElementById('userInputImage').value;
394
+
395
+ if (!nameInput || !imageInput) {
396
+ updateLogCallback("Error", "Name and Image URL are required for open collections");
397
+ return;
398
+ }
399
+
400
+ // Update the template one last time to ensure latest values
401
+ updateTemplateFromForm();
402
+ }
403
+
60
404
  // Create a vault
61
- vaultData = await sdk.createCuratedVault(contractTemplate, updateLogCallback).catch(err=>console.log(err));
62
- if (!vaultData || vaultData.err) { // Temporary fix while I fix a race condition
405
+ updateLogCallback("Creating vault for contract", mintTemplate.targetContract.name);
406
+ vaultData = await sdk.createCuratedVault(mintTemplate, updateLogCallback).catch(err=>console.log(err));
407
+ // disable and add timer to button
408
+ document.getElementById('step1Button').disabled = true;
409
+ document.getElementById('step1Button').textContent = "Creating...";
410
+ if (!vaultData || vaultData.err) {
411
+ updateLogCallback("Error creating vault", vaultData ? vaultData.err : "Unknown error");
63
412
  setTimeout(Step1, 1000); // should Back off and try again
64
413
  } else {
65
- updateLogCallback("deposit Address", vaultData.addresses.find(address=>{return address.coin == 'TAP'}).address)
414
+ const depositAddress = vaultData.addresses.find(address => address.coin === 'TAP')?.address;
415
+ updateLogCallback("Vault created successfully", "Token ID: " + vaultData.tokenId);
416
+
417
+ // Log all deposit addresses
418
+ updateLogCallback("Available Deposit Addresses:", "");
419
+ vaultData.addresses.forEach(addr => {
420
+ updateLogCallback(`${addr.coin} Address:`, addr.address);
421
+ });
422
+
66
423
  document.getElementById('step1Button').disabled = true;
67
424
  document.getElementById('step2Button').disabled = false;
68
425
  }
@@ -71,48 +428,58 @@
71
428
 
72
429
  async function Step2() {
73
430
  if (vaultData) {
431
+ updateLogCallback("Refreshing balance for token ID", vaultData.tokenId);
74
432
  vaultBalance = await sdk.refreshBalance(vaultData.tokenId, updateLogCallback).catch(err=>console); // Refresh the balance
75
433
  if (vaultBalance.length > 0) { // We have a balance!!
76
- updateLogCallback('Step','complete')
77
- document.getElementById('step2Button').disabled = true;
78
- document.getElementById('step3Button').disabled = false;
434
+ updateLogCallback('Balance refreshed', JSON.stringify(vaultBalance));
435
+
436
+ // Check if the vault is mintable
437
+ updateLogCallback("Validating mintability for", mintTemplate.targetContract.name);
438
+ let contractObject = await sdk.fetchCuratedContractByName(mintTemplate.targetContract.name);
439
+ let mintable = contractObject.allowed(vaultBalance, contractObject);
440
+
441
+ if (mintable) {
442
+ updateLogCallback("Vault is mintable", "Proceed to Step 3 to mint");
443
+ document.getElementById('step2Button').disabled = true;
444
+ document.getElementById('step3Button').disabled = false;
445
+ } else {
446
+ updateLogCallback("Vault is not mintable", "Please check balance requirements");
447
+ // Keep Step 2 button enabled so user can refresh balance again
448
+ }
449
+ } else {
450
+ updateLogCallback('No balance found', 'Please deposit assets to the vault address');
79
451
  }
80
452
  }
81
453
  }
82
454
 
83
455
  async function Step3() {
84
456
  if (vaultBalance.length > 0) {
85
- let contractObject = await sdk.fetchCuratedContractByName(contractTemplate.targetContract.name);
86
- let mintable = contractObject.allowed(vaultBalance, contractObject);
87
- if (mintable) {
88
- performMint();
89
- }
457
+ performMint();
90
458
  } else {
91
- // Handle error
459
+ updateLogCallback("Error", "No balance found");
92
460
  }
93
461
  }
94
462
 
95
463
  async function performMint() {
96
464
  if (vaultData.tokenId) {
97
465
  // Perform Mint steps
98
- sdk.performMintChain(web3, vaultData.tokenId, contractTemplate.targetContract.name, updateLogCallback).then(result => {
99
- updateLogCallback('Minting success', 'tokenId: ' + vaultData.tokenId)
466
+ updateLogCallback("Starting mint process for token ID", vaultData.tokenId);
467
+ sdk.performMintChain(web3, vaultData.tokenId, mintTemplate.targetContract.name, updateLogCallback).then(result => {
468
+ updateLogCallback('Minting success', 'tokenId: ' + vaultData.tokenId);
100
469
  })
101
470
  .catch(error => {
102
- updateLogCallback('',error.message)
471
+ updateLogCallback('Minting error', error.message);
103
472
  });
104
473
  } else {
105
- // Handle error
474
+ updateLogCallback("Error", "No token ID found");
106
475
  }
107
476
  }
108
477
 
109
- function updateLogCallback(action, result){
110
- document.getElementById('log').innerHTML += '\r\n' + action + ' ' + (result ? JSON.stringify(result) : '');
111
- }
112
478
  function clearLog(){
113
479
  document.getElementById('log').innerHTML = '';
114
480
  }
115
481
  </script>
482
+ <h3>Log Output:</h3>
116
483
  <pre id="log"></pre>
117
484
  </body>
118
485
  </html>
package/package.json CHANGED
@@ -1,40 +1,48 @@
1
1
  {
2
2
  "name": "emblem-vault-sdk",
3
- "version": "2.3.6",
3
+ "version": "3.0.0-experimental",
4
4
  "description": "Emblem Vault Software Development Kit",
5
5
  "main": "dist/index.js",
6
6
  "scripts": {
7
7
  "bump:major": "node ./script/bump.js major",
8
8
  "bump:minor": "node ./script/bump.js minor",
9
9
  "bump:patch": "node ./script/bump.js patch",
10
- "test": "npm run build && jest",
11
- "test:node": "JEST_ENV=node jest",
12
- "test:browser": "JEST_ENV=browser jest",
13
- "test:all": "npm run test:node && npm run test:browser",
10
+ "test": "tsc && mocha 'test/**/*.spec.js'",
11
+ "test:watch": "mocha --watch 'test/**/*.spec.js'",
12
+ "test:coverage": "nyc mocha 'test/**/*.spec.js'",
14
13
  "build": "tsc",
15
14
  "postbuild": "node ./script/version.js && mv dist/index.d.ts types/index.d.ts && mv dist/types.d.ts types/types.d.ts && mv dist/utils.d.ts types/utils.d.ts && mv dist/derive.d.ts types/derive.d.ts",
16
15
  "bundle": "npm run build && browserify dist/index.js -o dist/bundle.js && cp dist/bundle.js docs/bundle.js",
17
- "watch": "onchange 'src/*.ts' -- npm run bundle"
16
+ "watch": "onchange 'src/**/*.ts' -- npm run bundle"
17
+ },
18
+ "browser": {
19
+ "./dist/clients/emblemVaultSolanaWalletClient.js": false,
20
+ "./dist/clients/emblemVaultWalletClient.js": false
18
21
  },
19
22
  "types": "types/index.d.ts",
20
23
  "keywords": [],
21
24
  "author": "",
22
25
  "license": "MIT",
23
26
  "devDependencies": {
27
+ "@types/chai": "^5.2.0",
24
28
  "@types/crypto-js": "^4.2.2",
25
- "@types/jest": "^29.5.11",
26
- "browserify": "^17.0.0",
27
- "jest": "^29.7.0",
28
- "jest-environment-jsdom": "^29.7.0",
29
- "jest-puppeteer": "^9.0.2",
29
+ "@types/mocha": "^10.0.10",
30
+ "@types/sinon": "^17.0.4",
31
+ "browserify": "^17.0.1",
32
+ "chai": "^4.5.0",
33
+ "mocha": "^11.1.0",
34
+ "nyc": "^17.1.0",
35
+ "onchange": "^7.1.0",
30
36
  "puppeteer": "^21.6.1",
31
- "ts-jest": "^29.1.1",
37
+ "sinon": "^17.0.1",
38
+ "ts-node": "^10.9.2",
32
39
  "tsify": "^5.0.2",
33
40
  "typescript": "^5.3.3"
34
41
  },
35
42
  "dependencies": {
36
43
  "@bitcoin-js/tiny-secp256k1-asmjs": "^2.2.3",
37
44
  "@ethersproject/bignumber": "^5.7.0",
45
+ "@solana/web3.js": "^1.98.0",
38
46
  "@toruslabs/fetch-node-details": "^8.0.0",
39
47
  "@toruslabs/torus.js": "^6.2.0",
40
48
  "bchaddrjs": "^0.5.2",
@@ -49,9 +57,10 @@
49
57
  "sats-connect": "^1.4.1",
50
58
  "tiny-secp256k1": "^2.2.3",
51
59
  "uninstall": "^0.0.0",
60
+ "viem": "^2.26.3",
52
61
  "web3": "^4.4.0"
53
62
  },
54
63
  "engines": {
55
64
  "node": ">=20.5.1"
56
65
  }
57
- }
66
+ }