@neuraiproject/neurai-assets 1.0.0
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 +522 -0
- package/examples/01-create-root-asset.js +71 -0
- package/examples/02-create-sub-asset.js +79 -0
- package/examples/03-create-nfts.js +140 -0
- package/examples/04-reissue-asset.js +164 -0
- package/examples/05-create-qualifier-and-tag.js +209 -0
- package/examples/06-create-restricted-asset.js +223 -0
- package/examples/07-freeze-and-unfreeze.js +292 -0
- package/examples/08-query-assets.js +332 -0
- package/examples/09-wallet-integration.js +320 -0
- package/examples/README.md +319 -0
- package/package.json +43 -0
- package/src/NeuraiAssets.js +468 -0
- package/src/builders/BaseAssetTransactionBuilder.js +303 -0
- package/src/builders/FreezeAddressBuilder.js +271 -0
- package/src/builders/IssueQualifierBuilder.js +251 -0
- package/src/builders/IssueRestrictedBuilder.js +187 -0
- package/src/builders/IssueRootBuilder.js +173 -0
- package/src/builders/IssueSubBuilder.js +237 -0
- package/src/builders/IssueUniqueBuilder.js +255 -0
- package/src/builders/ReissueBuilder.js +246 -0
- package/src/builders/ReissueRestrictedBuilder.js +264 -0
- package/src/builders/TagAddressBuilder.js +243 -0
- package/src/builders/index.js +38 -0
- package/src/constants/assetTypes.js +23 -0
- package/src/constants/burnAddresses.js +65 -0
- package/src/constants/fees.js +61 -0
- package/src/constants/index.js +44 -0
- package/src/constants/networks.js +112 -0
- package/src/errors/AssetErrors.js +135 -0
- package/src/errors/ValidationErrors.js +87 -0
- package/src/errors/index.js +56 -0
- package/src/index.js +68 -0
- package/src/managers/BurnManager.js +222 -0
- package/src/managers/OutputOrderer.js +289 -0
- package/src/managers/OwnerTokenManager.js +265 -0
- package/src/managers/UTXOSelector.js +309 -0
- package/src/managers/index.js +16 -0
- package/src/queries/AssetQueries.js +447 -0
- package/src/queries/index.js +10 -0
- package/src/utils/amountConverter.js +115 -0
- package/src/utils/assetNameParser.js +203 -0
- package/src/utils/index.js +16 -0
- package/src/utils/networkDetector.js +144 -0
- package/src/utils/outputFormatter.js +292 -0
- package/src/validators/amountValidator.js +149 -0
- package/src/validators/assetNameValidator.js +296 -0
- package/src/validators/index.js +16 -0
- package/src/validators/ipfsValidator.js +101 -0
- package/src/validators/verifierValidator.js +146 -0
- package/tests/README.md +126 -0
- package/tests/integration/assetLifecycle.test.js +244 -0
- package/tests/mocks/rpcMock.js +156 -0
- package/tests/unit/NeuraiAssets.test.js +217 -0
- package/tests/unit/utils/amountConverter.test.js +171 -0
- package/tests/unit/utils/assetNameParser.test.js +203 -0
- package/tests/unit/validators/amountValidator.test.js +143 -0
- package/tests/unit/validators/assetNameValidator.test.js +228 -0
|
@@ -0,0 +1,332 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Example: Query Asset Information
|
|
3
|
+
*
|
|
4
|
+
* This example demonstrates how to query asset information from the blockchain.
|
|
5
|
+
* Includes various query methods for asset metadata, holders, balances, and more.
|
|
6
|
+
*
|
|
7
|
+
* All query methods are read-only and do not require signing transactions.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
const NeuraiAssets = require('@neuraiproject/neurai-assets');
|
|
11
|
+
|
|
12
|
+
async function queryAssetMetadata() {
|
|
13
|
+
// Mock RPC function (replace with your actual RPC client)
|
|
14
|
+
const rpc = async (method, params) => {
|
|
15
|
+
console.log(`RPC Call: ${method}`, params);
|
|
16
|
+
// Your RPC implementation here
|
|
17
|
+
// Mock response:
|
|
18
|
+
return {
|
|
19
|
+
name: 'MYTOKEN',
|
|
20
|
+
amount: 1000000,
|
|
21
|
+
units: 2,
|
|
22
|
+
reissuable: true,
|
|
23
|
+
has_ipfs: true,
|
|
24
|
+
ipfs_hash: 'QmExample...'
|
|
25
|
+
};
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
// Initialize NeuraiAssets
|
|
29
|
+
const assets = new NeuraiAssets(rpc, {
|
|
30
|
+
network: 'xna',
|
|
31
|
+
addresses: ['NYourAddress1...'],
|
|
32
|
+
changeAddress: 'NChangeAddress...',
|
|
33
|
+
toAddress: 'NReceivingAddress...'
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
try {
|
|
37
|
+
console.log('=== Query Asset Metadata ===\n');
|
|
38
|
+
|
|
39
|
+
// Get complete asset data
|
|
40
|
+
const assetData = await assets.getAssetData('MYTOKEN');
|
|
41
|
+
|
|
42
|
+
console.log('Asset Information:');
|
|
43
|
+
console.log('- Name:', assetData.name);
|
|
44
|
+
console.log('- Total Supply:', assetData.amount);
|
|
45
|
+
console.log('- Decimals:', assetData.units);
|
|
46
|
+
console.log('- Reissuable:', assetData.reissuable ? 'Yes' : 'No (locked)');
|
|
47
|
+
console.log('- Has IPFS:', assetData.has_ipfs ? 'Yes' : 'No');
|
|
48
|
+
if (assetData.has_ipfs) {
|
|
49
|
+
console.log('- IPFS Hash:', assetData.ipfs_hash);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Detect asset type
|
|
53
|
+
const assetType = assets.getAssetType('MYTOKEN');
|
|
54
|
+
console.log('- Type:', assetType);
|
|
55
|
+
|
|
56
|
+
} catch (error) {
|
|
57
|
+
console.error('Error querying asset:', error.message);
|
|
58
|
+
|
|
59
|
+
if (error.name === 'AssetNotFoundError') {
|
|
60
|
+
console.error('Asset does not exist on the blockchain');
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Example: List all assets
|
|
66
|
+
async function listAllAssets() {
|
|
67
|
+
const rpc = async (method, params) => {
|
|
68
|
+
console.log(`RPC Call: ${method}`, params);
|
|
69
|
+
// Mock: return list of assets
|
|
70
|
+
return ['MYTOKEN', 'ANOTHER', 'EXAMPLE'];
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
const assets = new NeuraiAssets(rpc, {
|
|
74
|
+
network: 'xna',
|
|
75
|
+
addresses: ['NYourAddress1...'],
|
|
76
|
+
changeAddress: 'NChangeAddress...',
|
|
77
|
+
toAddress: 'NReceivingAddress...'
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
try {
|
|
81
|
+
console.log('=== List All Assets ===\n');
|
|
82
|
+
|
|
83
|
+
// List all assets (simple list)
|
|
84
|
+
const allAssets = await assets.listAssets('*', false, 100, 0);
|
|
85
|
+
console.log(`Total assets found: ${allAssets.length}`);
|
|
86
|
+
console.log('Assets:', allAssets.slice(0, 10));
|
|
87
|
+
|
|
88
|
+
// Filter by pattern
|
|
89
|
+
console.log('\n=== Filter Assets by Pattern ===\n');
|
|
90
|
+
const myAssets = await assets.listAssets('MY*', false, 100, 0);
|
|
91
|
+
console.log('Assets starting with MY:', myAssets);
|
|
92
|
+
|
|
93
|
+
// Get detailed information
|
|
94
|
+
console.log('\n=== Get Detailed Information ===\n');
|
|
95
|
+
const detailed = await assets.listAssets('MYTOKEN', true, 1, 0);
|
|
96
|
+
console.log('Detailed data:', JSON.stringify(detailed, null, 2));
|
|
97
|
+
|
|
98
|
+
} catch (error) {
|
|
99
|
+
console.error('Error listing assets:', error.message);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// Example: Query wallet assets
|
|
104
|
+
async function queryMyAssets() {
|
|
105
|
+
const rpc = async (method, params) => {
|
|
106
|
+
console.log(`RPC Call: ${method}`, params);
|
|
107
|
+
// Mock: return wallet assets
|
|
108
|
+
return {
|
|
109
|
+
'MYTOKEN': 1000.50,
|
|
110
|
+
'ANOTHER': 500.25,
|
|
111
|
+
'NFT#001': 1
|
|
112
|
+
};
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
const assets = new NeuraiAssets(rpc, {
|
|
116
|
+
network: 'xna',
|
|
117
|
+
addresses: ['NYourAddress1...'],
|
|
118
|
+
changeAddress: 'NChangeAddress...',
|
|
119
|
+
toAddress: 'NReceivingAddress...'
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
try {
|
|
123
|
+
console.log('=== My Asset Balances ===\n');
|
|
124
|
+
|
|
125
|
+
// Get all assets owned by wallet
|
|
126
|
+
const myAssets = await assets.listMyAssets();
|
|
127
|
+
|
|
128
|
+
console.log('Assets in wallet:');
|
|
129
|
+
for (const [assetName, balance] of Object.entries(myAssets)) {
|
|
130
|
+
console.log(`- ${assetName}: ${balance}`);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
const totalAssets = Object.keys(myAssets).length;
|
|
134
|
+
console.log(`\nTotal different assets: ${totalAssets}`);
|
|
135
|
+
|
|
136
|
+
} catch (error) {
|
|
137
|
+
console.error('Error querying wallet assets:', error.message);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// Example: Query asset holders
|
|
142
|
+
async function queryAssetHolders() {
|
|
143
|
+
const rpc = async (method, params) => {
|
|
144
|
+
console.log(`RPC Call: ${method}`, params);
|
|
145
|
+
// Mock: return holders
|
|
146
|
+
return [
|
|
147
|
+
{ address: 'NAddress1...', amount: 500.00 },
|
|
148
|
+
{ address: 'NAddress2...', amount: 300.00 },
|
|
149
|
+
{ address: 'NAddress3...', amount: 200.00 }
|
|
150
|
+
];
|
|
151
|
+
};
|
|
152
|
+
|
|
153
|
+
const assets = new NeuraiAssets(rpc, {
|
|
154
|
+
network: 'xna',
|
|
155
|
+
addresses: ['NYourAddress1...'],
|
|
156
|
+
changeAddress: 'NChangeAddress...',
|
|
157
|
+
toAddress: 'NReceivingAddress...'
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
try {
|
|
161
|
+
console.log('=== Asset Holders ===\n');
|
|
162
|
+
|
|
163
|
+
const assetName = 'MYTOKEN';
|
|
164
|
+
|
|
165
|
+
// Get all holders
|
|
166
|
+
const holders = await assets.listAddressesByAsset(assetName);
|
|
167
|
+
|
|
168
|
+
console.log(`Holders of ${assetName}:`);
|
|
169
|
+
holders.forEach((holder, index) => {
|
|
170
|
+
console.log(`${index + 1}. ${holder.address}: ${holder.amount}`);
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
console.log(`\nTotal holders: ${holders.length}`);
|
|
174
|
+
|
|
175
|
+
// Get holder count only
|
|
176
|
+
console.log('\n=== Get Holder Count ===\n');
|
|
177
|
+
const count = await assets.listAddressesByAsset(assetName, true);
|
|
178
|
+
console.log(`Number of holders: ${count}`);
|
|
179
|
+
|
|
180
|
+
} catch (error) {
|
|
181
|
+
console.error('Error querying holders:', error.message);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
// Example: Query address balances
|
|
186
|
+
async function queryAddressBalances() {
|
|
187
|
+
const rpc = async (method, params) => {
|
|
188
|
+
console.log(`RPC Call: ${method}`, params);
|
|
189
|
+
// Mock: return balances
|
|
190
|
+
return [
|
|
191
|
+
{ asset: 'MYTOKEN', amount: 100.50 },
|
|
192
|
+
{ asset: 'ANOTHER', amount: 50.25 },
|
|
193
|
+
{ asset: 'NFT#001', amount: 1 }
|
|
194
|
+
];
|
|
195
|
+
};
|
|
196
|
+
|
|
197
|
+
const assets = new NeuraiAssets(rpc, {
|
|
198
|
+
network: 'xna',
|
|
199
|
+
addresses: ['NYourAddress1...'],
|
|
200
|
+
changeAddress: 'NChangeAddress...',
|
|
201
|
+
toAddress: 'NReceivingAddress...'
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
try {
|
|
205
|
+
console.log('=== Address Asset Balances ===\n');
|
|
206
|
+
|
|
207
|
+
const address = 'NTestAddress...';
|
|
208
|
+
|
|
209
|
+
// Get all assets for an address
|
|
210
|
+
const balances = await assets.listAssetBalancesByAddress(address);
|
|
211
|
+
|
|
212
|
+
console.log(`Assets owned by ${address}:`);
|
|
213
|
+
balances.forEach((balance, index) => {
|
|
214
|
+
console.log(`${index + 1}. ${balance.asset}: ${balance.amount}`);
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
console.log(`\nTotal assets: ${balances.length}`);
|
|
218
|
+
|
|
219
|
+
} catch (error) {
|
|
220
|
+
console.error('Error querying address balances:', error.message);
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
// Example: Check existence and detect type
|
|
225
|
+
async function checkAssetExistence() {
|
|
226
|
+
const rpc = async (method, params) => {
|
|
227
|
+
console.log(`RPC Call: ${method}`, params);
|
|
228
|
+
return null; // Mock
|
|
229
|
+
};
|
|
230
|
+
|
|
231
|
+
const assets = new NeuraiAssets(rpc, {
|
|
232
|
+
network: 'xna',
|
|
233
|
+
addresses: ['NYourAddress1...'],
|
|
234
|
+
changeAddress: 'NChangeAddress...',
|
|
235
|
+
toAddress: 'NReceivingAddress...'
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
try {
|
|
239
|
+
console.log('=== Check Asset Existence ===\n');
|
|
240
|
+
|
|
241
|
+
const assetsToCheck = [
|
|
242
|
+
'MYTOKEN',
|
|
243
|
+
'MYTOKEN/SUB',
|
|
244
|
+
'MYTOKEN#NFT001',
|
|
245
|
+
'#KYC_VERIFIED',
|
|
246
|
+
'$SECURITY',
|
|
247
|
+
'MYTOKEN!',
|
|
248
|
+
'NONEXISTENT'
|
|
249
|
+
];
|
|
250
|
+
|
|
251
|
+
for (const assetName of assetsToCheck) {
|
|
252
|
+
const exists = await assets.assetExists(assetName);
|
|
253
|
+
const type = assets.getAssetType(assetName);
|
|
254
|
+
|
|
255
|
+
console.log(`${assetName}:`);
|
|
256
|
+
console.log(` Exists: ${exists ? 'Yes ā' : 'No ā'}`);
|
|
257
|
+
console.log(` Type: ${type}`);
|
|
258
|
+
console.log('');
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
} catch (error) {
|
|
262
|
+
console.error('Error:', error.message);
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
// Example: Advanced queries with pagination
|
|
267
|
+
async function advancedQueries() {
|
|
268
|
+
const rpc = async (method, params) => {
|
|
269
|
+
console.log(`RPC Call: ${method}`, params);
|
|
270
|
+
return [];
|
|
271
|
+
};
|
|
272
|
+
|
|
273
|
+
const assets = new NeuraiAssets(rpc, {
|
|
274
|
+
network: 'xna',
|
|
275
|
+
addresses: ['NYourAddress1...'],
|
|
276
|
+
changeAddress: 'NChangeAddress...',
|
|
277
|
+
toAddress: 'NReceivingAddress...'
|
|
278
|
+
});
|
|
279
|
+
|
|
280
|
+
try {
|
|
281
|
+
console.log('=== Advanced Queries with Pagination ===\n');
|
|
282
|
+
|
|
283
|
+
// Paginate through all assets
|
|
284
|
+
console.log('Getting all assets in pages of 100:');
|
|
285
|
+
|
|
286
|
+
let page = 0;
|
|
287
|
+
let allAssets = [];
|
|
288
|
+
let hasMore = true;
|
|
289
|
+
|
|
290
|
+
while (hasMore) {
|
|
291
|
+
const assets = await assets.listAssets('*', false, 100, page * 100);
|
|
292
|
+
|
|
293
|
+
if (assets.length === 0) {
|
|
294
|
+
hasMore = false;
|
|
295
|
+
} else {
|
|
296
|
+
allAssets = allAssets.concat(assets);
|
|
297
|
+
console.log(`Page ${page + 1}: ${assets.length} assets`);
|
|
298
|
+
page++;
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
// Safety limit
|
|
302
|
+
if (page > 10) break;
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
console.log(`\nTotal assets retrieved: ${allAssets.length}`);
|
|
306
|
+
|
|
307
|
+
} catch (error) {
|
|
308
|
+
console.error('Error:', error.message);
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
// Run the examples
|
|
313
|
+
console.log('=== Example 1: Query Asset Metadata ===\n');
|
|
314
|
+
queryAssetMetadata();
|
|
315
|
+
|
|
316
|
+
console.log('\n\n=== Example 2: List All Assets ===\n');
|
|
317
|
+
listAllAssets();
|
|
318
|
+
|
|
319
|
+
console.log('\n\n=== Example 3: Query Wallet Assets ===\n');
|
|
320
|
+
queryMyAssets();
|
|
321
|
+
|
|
322
|
+
console.log('\n\n=== Example 4: Query Asset Holders ===\n');
|
|
323
|
+
queryAssetHolders();
|
|
324
|
+
|
|
325
|
+
console.log('\n\n=== Example 5: Query Address Balances ===\n');
|
|
326
|
+
queryAddressBalances();
|
|
327
|
+
|
|
328
|
+
console.log('\n\n=== Example 6: Check Asset Existence ===\n');
|
|
329
|
+
checkAssetExistence();
|
|
330
|
+
|
|
331
|
+
console.log('\n\n=== Example 7: Advanced Queries ===\n');
|
|
332
|
+
advancedQueries();
|
|
@@ -0,0 +1,320 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Example: Complete Wallet Integration
|
|
3
|
+
*
|
|
4
|
+
* This example demonstrates complete integration with neurai-jswallet.
|
|
5
|
+
* Shows the full workflow from initialization to transaction broadcasting.
|
|
6
|
+
*
|
|
7
|
+
* This is the recommended way to use neurai-assets in production.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
const NeuraiAssets = require('@neuraiproject/neurai-assets');
|
|
11
|
+
// const NeuraiWallet = require('@neuraiproject/neurai-jswallet'); // Uncomment in production
|
|
12
|
+
|
|
13
|
+
async function completeWalletIntegration() {
|
|
14
|
+
try {
|
|
15
|
+
console.log('=== Complete Wallet Integration Example ===\n');
|
|
16
|
+
|
|
17
|
+
// Step 1: Initialize wallet
|
|
18
|
+
console.log('Step 1: Initialize Wallet\n');
|
|
19
|
+
|
|
20
|
+
/*
|
|
21
|
+
// Uncomment in production:
|
|
22
|
+
const wallet = new NeuraiWallet(mnemonic, {
|
|
23
|
+
network: 'xna',
|
|
24
|
+
rpcUrl: 'http://localhost:9766',
|
|
25
|
+
rpcUser: 'your-rpc-user',
|
|
26
|
+
rpcPassword: 'your-rpc-password'
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
// Wait for wallet to sync
|
|
30
|
+
await wallet.sync();
|
|
31
|
+
console.log('ā Wallet synced');
|
|
32
|
+
*/
|
|
33
|
+
|
|
34
|
+
// Mock wallet for example
|
|
35
|
+
const wallet = {
|
|
36
|
+
rpc: async (method, params) => {
|
|
37
|
+
console.log(` RPC: ${method}`, params);
|
|
38
|
+
return null;
|
|
39
|
+
},
|
|
40
|
+
getAllAddresses: () => ['NAddress1...', 'NAddress2...'],
|
|
41
|
+
getChangeAddress: () => 'NChangeAddress...',
|
|
42
|
+
getReceivingAddress: () => 'NReceivingAddress...',
|
|
43
|
+
signTransaction: async (rawTx) => {
|
|
44
|
+
console.log(' Signing transaction...');
|
|
45
|
+
return 'signed-tx-hex';
|
|
46
|
+
},
|
|
47
|
+
broadcastTransaction: async (signedTx) => {
|
|
48
|
+
console.log(' Broadcasting transaction...');
|
|
49
|
+
return 'transaction-id-hash';
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
// Step 2: Initialize NeuraiAssets with wallet
|
|
54
|
+
console.log('\nStep 2: Initialize NeuraiAssets\n');
|
|
55
|
+
|
|
56
|
+
const assets = new NeuraiAssets(
|
|
57
|
+
wallet.rpc.bind(wallet), // Bind wallet's RPC function
|
|
58
|
+
{
|
|
59
|
+
network: 'xna',
|
|
60
|
+
addresses: wallet.getAllAddresses(),
|
|
61
|
+
changeAddress: wallet.getChangeAddress(),
|
|
62
|
+
toAddress: wallet.getReceivingAddress()
|
|
63
|
+
}
|
|
64
|
+
);
|
|
65
|
+
|
|
66
|
+
console.log('ā NeuraiAssets initialized');
|
|
67
|
+
console.log(' Network:', 'xna');
|
|
68
|
+
console.log(' Addresses:', wallet.getAllAddresses().length);
|
|
69
|
+
|
|
70
|
+
// Step 3: Create an asset
|
|
71
|
+
console.log('\nStep 3: Create ROOT Asset\n');
|
|
72
|
+
|
|
73
|
+
const createResult = await assets.createRootAsset({
|
|
74
|
+
assetName: 'MYTOKEN',
|
|
75
|
+
quantity: 1000000,
|
|
76
|
+
units: 2,
|
|
77
|
+
reissuable: true,
|
|
78
|
+
hasIpfs: true,
|
|
79
|
+
ipfsHash: 'QmYwAPJzv5CZsnA625s3Xf2nemtYgPpHdWEz79ojWnPbdG'
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
console.log('ā Transaction built');
|
|
83
|
+
console.log(' Fee:', createResult.fee, 'XNA');
|
|
84
|
+
console.log(' Burn:', createResult.burn, 'XNA');
|
|
85
|
+
console.log(' Owner Token:', createResult.metadata.ownerTokenName);
|
|
86
|
+
|
|
87
|
+
// Step 4: Sign the transaction
|
|
88
|
+
console.log('\nStep 4: Sign Transaction\n');
|
|
89
|
+
|
|
90
|
+
const signedTx = await wallet.signTransaction(createResult.rawTx);
|
|
91
|
+
console.log('ā Transaction signed');
|
|
92
|
+
|
|
93
|
+
// Step 5: Broadcast the transaction
|
|
94
|
+
console.log('\nStep 5: Broadcast Transaction\n');
|
|
95
|
+
|
|
96
|
+
const txid = await wallet.broadcastTransaction(signedTx);
|
|
97
|
+
console.log('ā Transaction broadcast');
|
|
98
|
+
console.log(' TXID:', txid);
|
|
99
|
+
|
|
100
|
+
// Step 6: Wait for confirmation (in production)
|
|
101
|
+
console.log('\nStep 6: Wait for Confirmation\n');
|
|
102
|
+
console.log(' Waiting for blockchain confirmation...');
|
|
103
|
+
console.log(' (In production, poll the transaction status)');
|
|
104
|
+
|
|
105
|
+
/*
|
|
106
|
+
// Uncomment in production:
|
|
107
|
+
let confirmed = false;
|
|
108
|
+
while (!confirmed) {
|
|
109
|
+
const tx = await wallet.getTransaction(txid);
|
|
110
|
+
if (tx.confirmations >= 1) {
|
|
111
|
+
confirmed = true;
|
|
112
|
+
console.log('ā Transaction confirmed!');
|
|
113
|
+
} else {
|
|
114
|
+
await new Promise(resolve => setTimeout(resolve, 5000));
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
*/
|
|
118
|
+
|
|
119
|
+
console.log('\nā Asset created successfully!');
|
|
120
|
+
console.log(' You now own: MYTOKEN and MYTOKEN!');
|
|
121
|
+
|
|
122
|
+
} catch (error) {
|
|
123
|
+
console.error('Error:', error.message);
|
|
124
|
+
|
|
125
|
+
// Handle specific errors
|
|
126
|
+
if (error.name === 'InsufficientFundsError') {
|
|
127
|
+
console.error('Not enough XNA in wallet');
|
|
128
|
+
console.error('Required:', error.required, 'XNA');
|
|
129
|
+
console.error('Available:', error.available, 'XNA');
|
|
130
|
+
} else if (error.name === 'AssetExistsError') {
|
|
131
|
+
console.error('Asset name already taken');
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// Example: Create multiple assets in sequence
|
|
137
|
+
async function createMultipleAssets() {
|
|
138
|
+
const wallet = {
|
|
139
|
+
rpc: async (method, params) => {
|
|
140
|
+
console.log(` RPC: ${method}`);
|
|
141
|
+
return null;
|
|
142
|
+
},
|
|
143
|
+
getAllAddresses: () => ['NAddress1...'],
|
|
144
|
+
getChangeAddress: () => 'NChangeAddress...',
|
|
145
|
+
getReceivingAddress: () => 'NReceivingAddress...',
|
|
146
|
+
signTransaction: async (rawTx) => 'signed-tx',
|
|
147
|
+
broadcastTransaction: async (signedTx) => `txid-${Date.now()}`
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
const assets = new NeuraiAssets(wallet.rpc.bind(wallet), {
|
|
151
|
+
network: 'xna',
|
|
152
|
+
addresses: wallet.getAllAddresses(),
|
|
153
|
+
changeAddress: wallet.getChangeAddress(),
|
|
154
|
+
toAddress: wallet.getReceivingAddress()
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
try {
|
|
158
|
+
console.log('=== Create Multiple Assets ===\n');
|
|
159
|
+
|
|
160
|
+
// 1. Create ROOT asset
|
|
161
|
+
console.log('1. Creating ROOT asset: MYTOKEN');
|
|
162
|
+
const rootResult = await assets.createRootAsset({
|
|
163
|
+
assetName: 'MYTOKEN',
|
|
164
|
+
quantity: 1000000,
|
|
165
|
+
units: 2,
|
|
166
|
+
reissuable: true
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
const rootTxid = await wallet.broadcastTransaction(
|
|
170
|
+
await wallet.signTransaction(rootResult.rawTx)
|
|
171
|
+
);
|
|
172
|
+
console.log(' ā TXID:', rootTxid);
|
|
173
|
+
|
|
174
|
+
// 2. Create SUB asset
|
|
175
|
+
console.log('\n2. Creating SUB asset: MYTOKEN/PREMIUM');
|
|
176
|
+
const subResult = await assets.createSubAsset({
|
|
177
|
+
assetName: 'MYTOKEN/PREMIUM',
|
|
178
|
+
quantity: 100000,
|
|
179
|
+
units: 0,
|
|
180
|
+
reissuable: true
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
const subTxid = await wallet.broadcastTransaction(
|
|
184
|
+
await wallet.signTransaction(subResult.rawTx)
|
|
185
|
+
);
|
|
186
|
+
console.log(' ā TXID:', subTxid);
|
|
187
|
+
|
|
188
|
+
// 3. Create NFTs
|
|
189
|
+
console.log('\n3. Creating NFTs: MYTOKEN#GENESIS, MYTOKEN#001');
|
|
190
|
+
const nftResult = await assets.createUniqueAssets({
|
|
191
|
+
rootAssetName: 'MYTOKEN',
|
|
192
|
+
assetTags: [
|
|
193
|
+
{ tag: 'GENESIS', hasIpfs: true, ipfsHash: 'QmGenesis...' },
|
|
194
|
+
{ tag: '001', hasIpfs: true, ipfsHash: 'QmNFT001...' }
|
|
195
|
+
]
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
const nftTxid = await wallet.broadcastTransaction(
|
|
199
|
+
await wallet.signTransaction(nftResult.rawTx)
|
|
200
|
+
);
|
|
201
|
+
console.log(' ā TXID:', nftTxid);
|
|
202
|
+
|
|
203
|
+
console.log('\nā All assets created successfully!');
|
|
204
|
+
|
|
205
|
+
} catch (error) {
|
|
206
|
+
console.error('Error:', error.message);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
// Example: Error handling
|
|
211
|
+
async function errorHandlingExample() {
|
|
212
|
+
const wallet = {
|
|
213
|
+
rpc: async (method, params) => {
|
|
214
|
+
if (method === 'listunspent') {
|
|
215
|
+
// Simulate insufficient funds
|
|
216
|
+
return [];
|
|
217
|
+
}
|
|
218
|
+
return null;
|
|
219
|
+
},
|
|
220
|
+
getAllAddresses: () => ['NAddress1...'],
|
|
221
|
+
getChangeAddress: () => 'NChangeAddress...',
|
|
222
|
+
getReceivingAddress: () => 'NReceivingAddress...'
|
|
223
|
+
};
|
|
224
|
+
|
|
225
|
+
const assets = new NeuraiAssets(wallet.rpc.bind(wallet), {
|
|
226
|
+
network: 'xna',
|
|
227
|
+
addresses: wallet.getAllAddresses(),
|
|
228
|
+
changeAddress: wallet.getChangeAddress(),
|
|
229
|
+
toAddress: wallet.getReceivingAddress()
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
try {
|
|
233
|
+
console.log('=== Error Handling Example ===\n');
|
|
234
|
+
|
|
235
|
+
const result = await assets.createRootAsset({
|
|
236
|
+
assetName: 'MYTOKEN',
|
|
237
|
+
quantity: 1000000,
|
|
238
|
+
units: 2,
|
|
239
|
+
reissuable: true
|
|
240
|
+
});
|
|
241
|
+
|
|
242
|
+
} catch (error) {
|
|
243
|
+
console.log('Caught error:', error.name);
|
|
244
|
+
console.log('Message:', error.message);
|
|
245
|
+
|
|
246
|
+
// Handle different error types
|
|
247
|
+
switch (error.name) {
|
|
248
|
+
case 'InsufficientFundsError':
|
|
249
|
+
console.log('\nš” Solution: Add more XNA to your wallet');
|
|
250
|
+
console.log(' Required:', error.required || 'N/A', 'XNA');
|
|
251
|
+
break;
|
|
252
|
+
|
|
253
|
+
case 'AssetExistsError':
|
|
254
|
+
console.log('\nš” Solution: Choose a different asset name');
|
|
255
|
+
console.log(' Taken name:', error.assetName);
|
|
256
|
+
break;
|
|
257
|
+
|
|
258
|
+
case 'OwnerTokenNotFoundError':
|
|
259
|
+
console.log('\nš” Solution: You need the owner token');
|
|
260
|
+
console.log(' Required token:', error.ownerTokenName);
|
|
261
|
+
break;
|
|
262
|
+
|
|
263
|
+
case 'InvalidAssetNameError':
|
|
264
|
+
console.log('\nš” Solution: Fix the asset name');
|
|
265
|
+
console.log(' Rules: 3-30 chars, A-Z 0-9 _ . only');
|
|
266
|
+
break;
|
|
267
|
+
|
|
268
|
+
default:
|
|
269
|
+
console.log('\nš” Solution: Check error message above');
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
// Example: Query and update configuration
|
|
275
|
+
async function dynamicConfiguration() {
|
|
276
|
+
const wallet = {
|
|
277
|
+
rpc: async (method, params) => null,
|
|
278
|
+
getAllAddresses: () => ['NAddress1...', 'NAddress2...'],
|
|
279
|
+
getChangeAddress: () => 'NChangeAddress...',
|
|
280
|
+
getReceivingAddress: () => 'NReceivingAddress...'
|
|
281
|
+
};
|
|
282
|
+
|
|
283
|
+
const assets = new NeuraiAssets(wallet.rpc.bind(wallet), {
|
|
284
|
+
network: 'xna',
|
|
285
|
+
addresses: wallet.getAllAddresses(),
|
|
286
|
+
changeAddress: wallet.getChangeAddress(),
|
|
287
|
+
toAddress: wallet.getReceivingAddress()
|
|
288
|
+
});
|
|
289
|
+
|
|
290
|
+
console.log('=== Dynamic Configuration ===\n');
|
|
291
|
+
|
|
292
|
+
console.log('Initial config:');
|
|
293
|
+
console.log(' Addresses:', wallet.getAllAddresses());
|
|
294
|
+
console.log(' Change:', wallet.getChangeAddress());
|
|
295
|
+
|
|
296
|
+
// Update configuration (e.g., after wallet generates new addresses)
|
|
297
|
+
console.log('\nUpdating configuration...');
|
|
298
|
+
|
|
299
|
+
assets.updateConfig({
|
|
300
|
+
addresses: ['NAddress1...', 'NAddress2...', 'NAddress3...'],
|
|
301
|
+
changeAddress: 'NNewChangeAddress...',
|
|
302
|
+
toAddress: 'NNewReceivingAddress...'
|
|
303
|
+
});
|
|
304
|
+
|
|
305
|
+
console.log('ā Configuration updated');
|
|
306
|
+
console.log(' New addresses: 3');
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
// Run the examples
|
|
310
|
+
console.log('=== Example 1: Complete Integration ===\n');
|
|
311
|
+
completeWalletIntegration();
|
|
312
|
+
|
|
313
|
+
console.log('\n\n=== Example 2: Create Multiple Assets ===\n');
|
|
314
|
+
createMultipleAssets();
|
|
315
|
+
|
|
316
|
+
console.log('\n\n=== Example 3: Error Handling ===\n');
|
|
317
|
+
errorHandlingExample();
|
|
318
|
+
|
|
319
|
+
console.log('\n\n=== Example 4: Dynamic Configuration ===\n');
|
|
320
|
+
dynamicConfiguration();
|