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.
- package/.traces/blockchain-provider-abstraction-plan.md +302 -0
- package/.traces/notes.md +43 -0
- package/.traces/readme-verification-trace.md +988 -0
- package/.traces/test-migration-status.md +227 -0
- package/.traces/tests-consolidated-trace.md +667 -0
- package/dist/abi/abi.json +53 -0
- package/dist/bundle.js +21602 -17419
- package/dist/clients/emblemVaultSolanaWalletClient.d.ts +74 -0
- package/dist/clients/emblemVaultSolanaWalletClient.js +149 -0
- package/dist/clients/emblemVaultSolanaWalletClient.js.map +1 -0
- package/dist/clients/emblemVaultWalletClient.d.ts +52 -0
- package/dist/clients/emblemVaultWalletClient.js +110 -0
- package/dist/clients/emblemVaultWalletClient.js.map +1 -0
- package/dist/derive.js +7 -0
- package/dist/derive.js.map +1 -0
- package/dist/index.js +319 -114
- package/dist/index.js.map +1 -0
- package/dist/providers/ProviderManager.d.ts +57 -0
- package/dist/providers/ProviderManager.js +283 -0
- package/dist/providers/ProviderManager.js.map +1 -0
- package/dist/providers.d.ts +101 -0
- package/dist/providers.js +96 -0
- package/dist/providers.js.map +1 -0
- package/dist/types.js +1 -0
- package/dist/types.js.map +1 -0
- package/dist/utils.js +61 -58
- package/dist/utils.js.map +1 -0
- package/docs/bundle.js +21602 -17419
- package/docs/index.html +150 -13
- package/docs/local.html +385 -0
- package/docs/steps.html +420 -53
- package/package.json +22 -13
- package/readme.md +795 -21
- package/src/abi/abi.json +54 -1
- package/src/clients/emblemVaultSolanaWalletClient.ts +257 -0
- package/src/clients/emblemVaultWalletClient.ts +159 -0
- package/src/derive.ts +5 -5
- package/src/index.ts +320 -102
- package/src/providers/ProviderManager.ts +254 -0
- package/src/providers.ts +163 -0
- package/src/types.ts +50 -0
- package/src/utils.ts +63 -62
- package/test/.mocharc.js +8 -0
- package/test/README.md +212 -0
- package/test/fixtures/ethscriptions/balance-with-native-first.json +24 -0
- package/test/fixtures/ethscriptions/balance-with-native.json +23 -0
- package/test/fixtures/ethscriptions/balance.json +18 -0
- package/test/helpers/sdkLoader.js +88 -0
- package/test/helpers/setup.js +55 -0
- package/test/integration/ApiOperations.spec.js +102 -0
- package/test/integration/VaultAI.spec.js +57 -0
- package/test/integration/VaultCreation.spec.js +95 -0
- package/test/mocks.js +127 -0
- package/test/tsconfig.json +25 -0
- package/test/unit/AllowedBells.spec.js +53 -0
- package/test/unit/AllowedBitcoinDeGods.spec.js +53 -0
- package/test/unit/AllowedBitcoinOrdinals.spec.js +46 -0
- package/test/unit/AllowedCounterparty.spec.js +66 -0
- package/test/unit/AllowedCursedOrdinals.spec.js +68 -0
- package/test/unit/AllowedEmbells.spec.js +11 -0
- package/test/unit/AllowedEmbels.spec.js +11 -0
- package/test/unit/AllowedEmblemOpen.spec.js +20 -0
- package/test/unit/AllowedEthscriptions.spec.js +53 -0
- package/test/unit/AllowedHardcodedNfts.spec.js +77 -0
- package/test/unit/AllowedNamecoin.spec.js +33 -0
- package/test/unit/AllowedOrdi.spec.js +46 -0
- package/test/unit/AllowedOxbt.spec.js +46 -0
- package/test/unit/AllowedProjectCollection.spec.js +51 -0
- package/test/unit/AllowedProtocolCollection.spec.js +44 -0
- package/test/unit/AllowedStamps.spec.js +78 -0
- package/test/unit/DarkfarmsMetadata.spec.js +10 -0
- package/test/unit/EmblemVaultSdk.spec.js +188 -0
- package/test/unit/Providers.spec.js +290 -0
- package/test/unit/ResourceMonitor.spec.js +111 -0
- package/test/unit/SDKMemoryLeaks.spec.js +176 -0
- package/test/unit/Signing.spec.js +321 -0
- package/test/unit/VaultAI.spec.js +140 -0
- package/test/unit/clients/EmblemVaultSolanaWalletClient.spec.js +296 -0
- package/test/unit/clients/EmblemVaultWalletClient.spec.js +246 -0
- package/test/utils/ResourceMonitor.js +169 -0
- package/test/windsurf-rules.md +68 -0
- package/tsconfig.json +7 -3
- package/types/derive.d.ts +0 -5
- package/types/index.d.ts +152 -32
- package/types/types.d.ts +43 -0
- package/types/utils.d.ts +7 -1
- package/dist/abi/quote.js +0 -29
- package/dist/abi/quote.json +0 -26
- package/jest.config.js +0 -6
- package/tests/AllowedBells.test.ts +0 -53
- package/tests/AllowedBitcoinDeGods.test.ts +0 -53
- package/tests/AllowedBitcoinOrdinals.test.ts +0 -46
- package/tests/AllowedCounterparty.test.ts +0 -45
- package/tests/AllowedCursedOrdinals.test.ts +0 -68
- package/tests/AllowedEmbells.test.ts +0 -12
- package/tests/AllowedEmbels.test.ts +0 -16
- package/tests/AllowedEmblemOpen.test.ts +0 -20
- package/tests/AllowedEthscriptions.test.ts +0 -39
- package/tests/AllowedHardcodedNfts.test.ts +0 -78
- package/tests/AllowedNamecoin.test.ts +0 -33
- package/tests/AllowedOrdi.test.ts +0 -47
- package/tests/AllowedOxbt.test.ts +0 -47
- package/tests/AllowedProjectlCollection.test.ts +0 -51
- package/tests/AllowedProtocolCollection.test.ts +0 -44
- package/tests/AllowedStamps.test.ts +0 -73
- package/tests/DarkfarmsMetadata.test.ts +0 -10
- package/tests/EmblemVaultSdk.test.ts +0 -124
- package/tests/fixtures/embels/balance.json +0 -10
- package/tests/fixtures/ethscriptions/balance-with-native-first.json +0 -69
- package/tests/fixtures/ethscriptions/balance-with-native.json +0 -37
- package/tests/fixtures/ethscriptions/balance.json +0 -64
- /package/{tests → test}/fixtures/bells/balance-with-non-bell-first.json +0 -0
- /package/{tests → test}/fixtures/bells/balance-with-non-bell.json +0 -0
- /package/{tests → test}/fixtures/bells/balance.json +0 -0
- /package/{tests → test}/fixtures/bitcoin-degods/balance-with-non-degods-first.json +0 -0
- /package/{tests → test}/fixtures/bitcoin-degods/balance-with-non-degods.json +0 -0
- /package/{tests → test}/fixtures/bitcoin-degods/balance.json +0 -0
- /package/{tests → test}/fixtures/bitcoin-ordinals/balance-with-native-first.json +0 -0
- /package/{tests → test}/fixtures/bitcoin-ordinals/balance-with-only-native.json +0 -0
- /package/{tests → test}/fixtures/bitcoin-ordinals/balance.json +0 -0
- /package/{tests → test}/fixtures/counterparty/balance-with-multiple.json +0 -0
- /package/{tests → test}/fixtures/counterparty/balance.json +0 -0
- /package/{tests → test}/fixtures/cursed-ordinals/balance-with-native-first.json +0 -0
- /package/{tests → test}/fixtures/cursed-ordinals/balance-with-native.json +0 -0
- /package/{tests → test}/fixtures/cursed-ordinals/balance.json +0 -0
- /package/{tests → test}/fixtures/dogeparty/balance-with-non-dogeparty-first.json +0 -0
- /package/{tests → test}/fixtures/dogeparty/balance-with-non-dogeparty.json +0 -0
- /package/{tests → test}/fixtures/dogeparty/balance.json +0 -0
- /package/{tests → test}/fixtures/emblem-open/balance.json +0 -0
- /package/{tests → test}/fixtures/hardcoded-nfts/balance-witn-non-hardcoded-first.json +0 -0
- /package/{tests → test}/fixtures/hardcoded-nfts/balance-witn-non-hardcoded.json +0 -0
- /package/{tests → test}/fixtures/hardcoded-nfts/balance.json +0 -0
- /package/{tests → test}/fixtures/megapunks/balance-with-non-megapunk-first.json +0 -0
- /package/{tests → test}/fixtures/megapunks/balance-with-non-megapunk.json +0 -0
- /package/{tests → test}/fixtures/megapunks/balance.json +0 -0
- /package/{tests → test}/fixtures/namecoin/balance-with-native-first.json +0 -0
- /package/{tests → test}/fixtures/namecoin/balance-with-native.json +0 -0
- /package/{tests → test}/fixtures/namecoin/balance.json +0 -0
- /package/{tests → test}/fixtures/ordi/balance-with-native-first.json +0 -0
- /package/{tests → test}/fixtures/ordi/balance-with-native.json +0 -0
- /package/{tests → test}/fixtures/ordi/balance.json +0 -0
- /package/{tests → test}/fixtures/oxbt/balance-with-native-first.json +0 -0
- /package/{tests → test}/fixtures/oxbt/balance-with-native.json +0 -0
- /package/{tests → test}/fixtures/oxbt/balance.json +0 -0
- /package/{tests → test}/fixtures/stamps/balance-with-non-stamps-first.json +0 -0
- /package/{tests → test}/fixtures/stamps/balance-with-non-stamps.json +0 -0
- /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>
|
|
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
|
-
|
|
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
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
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 (
|
|
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
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
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
|
-
|
|
62
|
-
|
|
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
|
-
|
|
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('
|
|
77
|
-
|
|
78
|
-
|
|
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
|
-
|
|
86
|
-
let mintable = contractObject.allowed(vaultBalance, contractObject);
|
|
87
|
-
if (mintable) {
|
|
88
|
-
performMint();
|
|
89
|
-
}
|
|
457
|
+
performMint();
|
|
90
458
|
} else {
|
|
91
|
-
|
|
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
|
-
|
|
99
|
-
|
|
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
|
-
|
|
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": "
|
|
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": "
|
|
11
|
-
"test:
|
|
12
|
-
"test:
|
|
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
|
|
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/
|
|
26
|
-
"
|
|
27
|
-
"
|
|
28
|
-
"
|
|
29
|
-
"
|
|
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
|
-
"
|
|
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
|
+
}
|