@neuraiproject/neurai-assets 1.3.3 → 1.4.1
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 +31 -0
- package/dist/NeuraiAssets.global.js +180 -53
- package/dist/NeuraiAssets.global.js.map +1 -1
- package/dist/browser.js +180 -53
- package/dist/browser.js.map +1 -1
- package/dist/index.cjs +180 -53
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +180 -53
- package/dist/index.js.map +1 -1
- package/index.d.ts +11 -1
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -2,6 +2,17 @@
|
|
|
2
2
|
|
|
3
3
|
Complete asset management library for Neurai blockchain. Supports creation, reissuance, and queries for all asset types in a non-custodial way.
|
|
4
4
|
|
|
5
|
+
> **1.4.1**: fix — the constructor dropped `config.assetMarker`, so the
|
|
6
|
+
> wallet-level override documented in 1.4.0 never reached the builders
|
|
7
|
+
> (per-operation `params.assetMarker` was unaffected). Precedence is now
|
|
8
|
+
> effective: `params.assetMarker` > `config.assetMarker` > node.
|
|
9
|
+
>
|
|
10
|
+
> **1.4.0**: NIP-040 `assetMarker` in `localRawBuild` (see below); RPC
|
|
11
|
+
> rejection messages from `@neuraiproject/neurai-rpc` >= 0.5 are surfaced
|
|
12
|
+
> correctly (they carry no `.message`); name-length caps now mirror the node
|
|
13
|
+
> (full name, owner `!` included: 31 mainnet / 121 testnet-regtest, validated
|
|
14
|
+
> against a regtest node); peer `neurai-rpc ^0.6.0`.
|
|
15
|
+
|
|
5
16
|
## Features
|
|
6
17
|
|
|
7
18
|
- ✅ **Non-custodial**: Library builds unsigned transactions, your wallet signs them
|
|
@@ -525,6 +536,26 @@ The library automatically validates that the owner token is returned in each ope
|
|
|
525
536
|
|
|
526
537
|
**Note**: In addition to the burned cost, all operations pay a network fee (calculated automatically).
|
|
527
538
|
|
|
539
|
+
## NIP-040 asset marker (local raw builds)
|
|
540
|
+
|
|
541
|
+
Asset payloads open with a 3-byte marker that NIP-040 migrates from the
|
|
542
|
+
Ravencoin-inherited `rvn` to `xna` at an activation height per network
|
|
543
|
+
(testnet: 303000, already crossed; regtest: 1; mainnet: not scheduled yet).
|
|
544
|
+
|
|
545
|
+
- Transactions built **through the node** (`createrawtransaction`) need
|
|
546
|
+
nothing: the node stamps the marker itself.
|
|
547
|
+
- The `localRawBuild` metadata (consumed by
|
|
548
|
+
`@neuraiproject/neurai-create-transaction createFromOperation`, >= 0.7.0)
|
|
549
|
+
now carries `params.assetMarker`. Builders resolve it once per build:
|
|
550
|
+
1. `params.assetMarker` / `config.assetMarker` if you set it (`'rvn'` |
|
|
551
|
+
`'xna'` — offline builds or tests);
|
|
552
|
+
2. otherwise the node's `getblockchaininfo.asset_marker` (node commit
|
|
553
|
+
`347362b` or later);
|
|
554
|
+
3. `'rvn'` when the node predates that field or the call fails — which
|
|
555
|
+
matches what such a node enforces.
|
|
556
|
+
|
|
557
|
+
No height tables and no network inference: the node (or you) decides.
|
|
558
|
+
|
|
528
559
|
## Validations
|
|
529
560
|
|
|
530
561
|
The library validates client-side:
|
|
@@ -7,6 +7,55 @@ var NeuraiAssetsBundle = (function (exports) {
|
|
|
7
7
|
|
|
8
8
|
var src = {exports: {}};
|
|
9
9
|
|
|
10
|
+
/**
|
|
11
|
+
* Extract a human-readable message from an RPC rejection.
|
|
12
|
+
*
|
|
13
|
+
* @neuraiproject/neurai-rpc >= 0.5 never rejects with a plain Error, so
|
|
14
|
+
* `error.message` is undefined for every node failure. It uses three shapes:
|
|
15
|
+
*
|
|
16
|
+
* 1. {error: {code, message}, description} JSON-RPC error (also on HTTP 200)
|
|
17
|
+
* 2. {statusText, status, description, error} HTTP response other than 200
|
|
18
|
+
* 3. {originalError, type: 'ServerUnreachable', error, description}
|
|
19
|
+
*
|
|
20
|
+
* In shape 3 `error` is a string, in shapes 1 and 2 it is an object (or
|
|
21
|
+
* null). Plain Errors (thrown by this library or by mocks) keep working
|
|
22
|
+
* through the `error.message` candidate.
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
var rpcErrorMessage_1;
|
|
26
|
+
var hasRequiredRpcErrorMessage;
|
|
27
|
+
|
|
28
|
+
function requireRpcErrorMessage () {
|
|
29
|
+
if (hasRequiredRpcErrorMessage) return rpcErrorMessage_1;
|
|
30
|
+
hasRequiredRpcErrorMessage = 1;
|
|
31
|
+
function rpcErrorMessage(error) {
|
|
32
|
+
if (!error) {
|
|
33
|
+
return '';
|
|
34
|
+
}
|
|
35
|
+
if (typeof error === 'string') {
|
|
36
|
+
return error;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const candidates = [
|
|
40
|
+
error.error && error.error.message,
|
|
41
|
+
typeof error.error === 'string' ? error.error : null,
|
|
42
|
+
error.description,
|
|
43
|
+
error.message,
|
|
44
|
+
error.statusText
|
|
45
|
+
];
|
|
46
|
+
|
|
47
|
+
for (const candidate of candidates) {
|
|
48
|
+
if (typeof candidate === 'string' && candidate.length > 0) {
|
|
49
|
+
return candidate;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return '';
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
rpcErrorMessage_1 = { rpcErrorMessage };
|
|
56
|
+
return rpcErrorMessage_1;
|
|
57
|
+
}
|
|
58
|
+
|
|
10
59
|
/**
|
|
11
60
|
* Validation Error Classes
|
|
12
61
|
* Errors thrown during parameter validation
|
|
@@ -332,6 +381,7 @@ var NeuraiAssetsBundle = (function (exports) {
|
|
|
332
381
|
function requireAssetQueries () {
|
|
333
382
|
if (hasRequiredAssetQueries) return AssetQueries_1;
|
|
334
383
|
hasRequiredAssetQueries = 1;
|
|
384
|
+
const { rpcErrorMessage } = requireRpcErrorMessage();
|
|
335
385
|
const { AssetNotFoundError, InvalidAddressError } = requireErrors();
|
|
336
386
|
|
|
337
387
|
class AssetQueries {
|
|
@@ -373,14 +423,14 @@ var NeuraiAssetsBundle = (function (exports) {
|
|
|
373
423
|
}
|
|
374
424
|
|
|
375
425
|
// RPC error - likely asset doesn't exist
|
|
376
|
-
if (error.
|
|
426
|
+
if (rpcErrorMessage(error).includes('not found')) {
|
|
377
427
|
throw new AssetNotFoundError(
|
|
378
428
|
`Asset ${assetName} not found on blockchain`,
|
|
379
429
|
assetName
|
|
380
430
|
);
|
|
381
431
|
}
|
|
382
432
|
|
|
383
|
-
throw new Error(`Failed to get asset data: ${error
|
|
433
|
+
throw new Error(`Failed to get asset data: ${rpcErrorMessage(error)}`);
|
|
384
434
|
}
|
|
385
435
|
}
|
|
386
436
|
|
|
@@ -397,7 +447,7 @@ var NeuraiAssetsBundle = (function (exports) {
|
|
|
397
447
|
const assets = await this.rpc('listassets', [filter, verbose, count, start]);
|
|
398
448
|
return assets || [];
|
|
399
449
|
} catch (error) {
|
|
400
|
-
throw new Error(`Failed to list assets: ${error
|
|
450
|
+
throw new Error(`Failed to list assets: ${rpcErrorMessage(error)}`);
|
|
401
451
|
}
|
|
402
452
|
}
|
|
403
453
|
|
|
@@ -415,7 +465,7 @@ var NeuraiAssetsBundle = (function (exports) {
|
|
|
415
465
|
const myAssets = await this.rpc('listmyassets', [assetName, verbose, count, start, confs]);
|
|
416
466
|
return myAssets || {};
|
|
417
467
|
} catch (error) {
|
|
418
|
-
throw new Error(`Failed to list my assets: ${error
|
|
468
|
+
throw new Error(`Failed to list my assets: ${rpcErrorMessage(error)}`);
|
|
419
469
|
}
|
|
420
470
|
}
|
|
421
471
|
|
|
@@ -436,13 +486,13 @@ var NeuraiAssetsBundle = (function (exports) {
|
|
|
436
486
|
const result = await this.rpc('listaddressesbyasset', [assetName, onlyCount, count, start]);
|
|
437
487
|
return result || (onlyCount ? 0 : []);
|
|
438
488
|
} catch (error) {
|
|
439
|
-
if (error.
|
|
489
|
+
if (rpcErrorMessage(error).includes('not found')) {
|
|
440
490
|
throw new AssetNotFoundError(
|
|
441
491
|
`Asset ${assetName} not found on blockchain`,
|
|
442
492
|
assetName
|
|
443
493
|
);
|
|
444
494
|
}
|
|
445
|
-
throw new Error(`Failed to list addresses by asset: ${error
|
|
495
|
+
throw new Error(`Failed to list addresses by asset: ${rpcErrorMessage(error)}`);
|
|
446
496
|
}
|
|
447
497
|
}
|
|
448
498
|
|
|
@@ -463,7 +513,7 @@ var NeuraiAssetsBundle = (function (exports) {
|
|
|
463
513
|
const result = await this.rpc('listassetbalancesbyaddress', [address, onlyTotal, count, start]);
|
|
464
514
|
return result || (onlyTotal ? 0 : []);
|
|
465
515
|
} catch (error) {
|
|
466
|
-
throw new Error(`Failed to list asset balances by address: ${error
|
|
516
|
+
throw new Error(`Failed to list asset balances by address: ${rpcErrorMessage(error)}`);
|
|
467
517
|
}
|
|
468
518
|
}
|
|
469
519
|
|
|
@@ -487,10 +537,10 @@ var NeuraiAssetsBundle = (function (exports) {
|
|
|
487
537
|
return result === true || result === 1;
|
|
488
538
|
} catch (error) {
|
|
489
539
|
// If tag doesn't exist or address doesn't have it, return false
|
|
490
|
-
if (
|
|
540
|
+
if (rpcErrorMessage(error).includes('not found') || rpcErrorMessage(error).includes('does not have')) {
|
|
491
541
|
return false;
|
|
492
542
|
}
|
|
493
|
-
throw new Error(`Failed to check address tag: ${error
|
|
543
|
+
throw new Error(`Failed to check address tag: ${rpcErrorMessage(error)}`);
|
|
494
544
|
}
|
|
495
545
|
}
|
|
496
546
|
|
|
@@ -509,10 +559,10 @@ var NeuraiAssetsBundle = (function (exports) {
|
|
|
509
559
|
return tags || [];
|
|
510
560
|
} catch (error) {
|
|
511
561
|
// If no tags found, return empty array
|
|
512
|
-
if (error.
|
|
562
|
+
if (rpcErrorMessage(error).includes('not found')) {
|
|
513
563
|
return [];
|
|
514
564
|
}
|
|
515
|
-
throw new Error(`Failed to list tags for address: ${error
|
|
565
|
+
throw new Error(`Failed to list tags for address: ${rpcErrorMessage(error)}`);
|
|
516
566
|
}
|
|
517
567
|
}
|
|
518
568
|
|
|
@@ -530,13 +580,13 @@ var NeuraiAssetsBundle = (function (exports) {
|
|
|
530
580
|
const addresses = await this.rpc('listaddressesfortag', [qualifierName]);
|
|
531
581
|
return addresses || [];
|
|
532
582
|
} catch (error) {
|
|
533
|
-
if (error.
|
|
583
|
+
if (rpcErrorMessage(error).includes('not found')) {
|
|
534
584
|
throw new AssetNotFoundError(
|
|
535
585
|
`Qualifier ${qualifierName} not found on blockchain`,
|
|
536
586
|
qualifierName
|
|
537
587
|
);
|
|
538
588
|
}
|
|
539
|
-
throw new Error(`Failed to list addresses for tag: ${error
|
|
589
|
+
throw new Error(`Failed to list addresses for tag: ${rpcErrorMessage(error)}`);
|
|
540
590
|
}
|
|
541
591
|
}
|
|
542
592
|
|
|
@@ -560,10 +610,10 @@ var NeuraiAssetsBundle = (function (exports) {
|
|
|
560
610
|
return result === true || result === 1;
|
|
561
611
|
} catch (error) {
|
|
562
612
|
// If address doesn't meet requirements, return false
|
|
563
|
-
if (
|
|
613
|
+
if (rpcErrorMessage(error).includes('not found') || rpcErrorMessage(error).includes('does not meet')) {
|
|
564
614
|
return false;
|
|
565
615
|
}
|
|
566
|
-
throw new Error(`Failed to check address restriction: ${error
|
|
616
|
+
throw new Error(`Failed to check address restriction: ${rpcErrorMessage(error)}`);
|
|
567
617
|
}
|
|
568
618
|
}
|
|
569
619
|
|
|
@@ -590,7 +640,7 @@ var NeuraiAssetsBundle = (function (exports) {
|
|
|
590
640
|
}
|
|
591
641
|
return false;
|
|
592
642
|
} catch (error) {
|
|
593
|
-
throw new Error(`Failed to check if address is frozen: ${error
|
|
643
|
+
throw new Error(`Failed to check if address is frozen: ${rpcErrorMessage(error)}`);
|
|
594
644
|
}
|
|
595
645
|
}
|
|
596
646
|
|
|
@@ -608,13 +658,13 @@ var NeuraiAssetsBundle = (function (exports) {
|
|
|
608
658
|
const result = await this.rpc('checkglobalrestriction', [restrictedAssetName]);
|
|
609
659
|
return result === true || result === 1;
|
|
610
660
|
} catch (error) {
|
|
611
|
-
if (error.
|
|
661
|
+
if (rpcErrorMessage(error).includes('not found')) {
|
|
612
662
|
throw new AssetNotFoundError(
|
|
613
663
|
`Restricted asset ${restrictedAssetName} not found on blockchain`,
|
|
614
664
|
restrictedAssetName
|
|
615
665
|
);
|
|
616
666
|
}
|
|
617
|
-
throw new Error(`Failed to check global restriction: ${error
|
|
667
|
+
throw new Error(`Failed to check global restriction: ${rpcErrorMessage(error)}`);
|
|
618
668
|
}
|
|
619
669
|
}
|
|
620
670
|
|
|
@@ -632,13 +682,13 @@ var NeuraiAssetsBundle = (function (exports) {
|
|
|
632
682
|
const result = await this.rpc('getverifierstring', [restrictedAssetName]);
|
|
633
683
|
return result || '';
|
|
634
684
|
} catch (error) {
|
|
635
|
-
if (error.
|
|
685
|
+
if (rpcErrorMessage(error).includes('not found')) {
|
|
636
686
|
throw new AssetNotFoundError(
|
|
637
687
|
`Restricted asset ${restrictedAssetName} not found on blockchain`,
|
|
638
688
|
restrictedAssetName
|
|
639
689
|
);
|
|
640
690
|
}
|
|
641
|
-
throw new Error(`Failed to get verifier string: ${error
|
|
691
|
+
throw new Error(`Failed to get verifier string: ${rpcErrorMessage(error)}`);
|
|
642
692
|
}
|
|
643
693
|
}
|
|
644
694
|
|
|
@@ -680,7 +730,7 @@ var NeuraiAssetsBundle = (function (exports) {
|
|
|
680
730
|
const result = await this.rpc('getsnapshotrequest', [assetName, blockHeight]);
|
|
681
731
|
return result;
|
|
682
732
|
} catch (error) {
|
|
683
|
-
throw new Error(`Failed to get snapshot request: ${error
|
|
733
|
+
throw new Error(`Failed to get snapshot request: ${rpcErrorMessage(error)}`);
|
|
684
734
|
}
|
|
685
735
|
}
|
|
686
736
|
|
|
@@ -703,7 +753,7 @@ var NeuraiAssetsBundle = (function (exports) {
|
|
|
703
753
|
const result = await this.rpc('cancelsnapshotrequest', [assetName, blockHeight]);
|
|
704
754
|
return result === true || result === 1;
|
|
705
755
|
} catch (error) {
|
|
706
|
-
throw new Error(`Failed to cancel snapshot request: ${error
|
|
756
|
+
throw new Error(`Failed to cancel snapshot request: ${rpcErrorMessage(error)}`);
|
|
707
757
|
}
|
|
708
758
|
}
|
|
709
759
|
|
|
@@ -721,13 +771,13 @@ var NeuraiAssetsBundle = (function (exports) {
|
|
|
721
771
|
const result = await this.rpc('listdepinholders', [assetName]);
|
|
722
772
|
return result || [];
|
|
723
773
|
} catch (error) {
|
|
724
|
-
if (error.
|
|
774
|
+
if (rpcErrorMessage(error).includes('not found')) {
|
|
725
775
|
throw new AssetNotFoundError(
|
|
726
776
|
`DEPIN asset ${assetName} not found on blockchain`,
|
|
727
777
|
assetName
|
|
728
778
|
);
|
|
729
779
|
}
|
|
730
|
-
throw new Error(`Failed to list DEPIN holders: ${error
|
|
780
|
+
throw new Error(`Failed to list DEPIN holders: ${rpcErrorMessage(error)}`);
|
|
731
781
|
}
|
|
732
782
|
}
|
|
733
783
|
|
|
@@ -750,7 +800,7 @@ var NeuraiAssetsBundle = (function (exports) {
|
|
|
750
800
|
const result = await this.rpc('checkdepinvalidity', [assetName, address]);
|
|
751
801
|
return result || { has_asset: false };
|
|
752
802
|
} catch (error) {
|
|
753
|
-
throw new Error(`Failed to check DEPIN validity: ${error
|
|
803
|
+
throw new Error(`Failed to check DEPIN validity: ${rpcErrorMessage(error)}`);
|
|
754
804
|
}
|
|
755
805
|
}
|
|
756
806
|
|
|
@@ -764,7 +814,7 @@ var NeuraiAssetsBundle = (function (exports) {
|
|
|
764
814
|
const assets = await this.listAssets('*', false, 1, 0);
|
|
765
815
|
return Array.isArray(assets) ? assets.length : 0;
|
|
766
816
|
} catch (error) {
|
|
767
|
-
throw new Error(`Failed to get asset count: ${error
|
|
817
|
+
throw new Error(`Failed to get asset count: ${rpcErrorMessage(error)}`);
|
|
768
818
|
}
|
|
769
819
|
}
|
|
770
820
|
|
|
@@ -1050,7 +1100,7 @@ var NeuraiAssetsBundle = (function (exports) {
|
|
|
1050
1100
|
addressPrefix: 'N',
|
|
1051
1101
|
authScriptAddressPrefix: 'nq1',
|
|
1052
1102
|
pqAddressPrefix: 'nq1',
|
|
1053
|
-
assetNameMaxLength:
|
|
1103
|
+
assetNameMaxLength: 31,
|
|
1054
1104
|
defaultRPCPort: 19001,
|
|
1055
1105
|
coin: 'XNA',
|
|
1056
1106
|
baseNetwork: 'xna'
|
|
@@ -1061,7 +1111,7 @@ var NeuraiAssetsBundle = (function (exports) {
|
|
|
1061
1111
|
addressPrefix: 't',
|
|
1062
1112
|
authScriptAddressPrefix: 'tnq1',
|
|
1063
1113
|
pqAddressPrefix: 'tnq1',
|
|
1064
|
-
assetNameMaxLength:
|
|
1114
|
+
assetNameMaxLength: 121, // DePIN networks (testnet/regtest) extend the cap
|
|
1065
1115
|
defaultRPCPort: 19101,
|
|
1066
1116
|
coin: 'TXNA',
|
|
1067
1117
|
baseNetwork: 'xna-test'
|
|
@@ -1072,7 +1122,7 @@ var NeuraiAssetsBundle = (function (exports) {
|
|
|
1072
1122
|
addressPrefix: 'N',
|
|
1073
1123
|
authScriptAddressPrefix: 'nq1',
|
|
1074
1124
|
pqAddressPrefix: 'nq1',
|
|
1075
|
-
assetNameMaxLength:
|
|
1125
|
+
assetNameMaxLength: 31,
|
|
1076
1126
|
defaultRPCPort: 19001,
|
|
1077
1127
|
coin: 'XNA',
|
|
1078
1128
|
baseNetwork: 'xna'
|
|
@@ -1083,7 +1133,7 @@ var NeuraiAssetsBundle = (function (exports) {
|
|
|
1083
1133
|
addressPrefix: 't',
|
|
1084
1134
|
authScriptAddressPrefix: 'tnq1',
|
|
1085
1135
|
pqAddressPrefix: 'tnq1',
|
|
1086
|
-
assetNameMaxLength:
|
|
1136
|
+
assetNameMaxLength: 121,
|
|
1087
1137
|
defaultRPCPort: 19101,
|
|
1088
1138
|
coin: 'TXNA',
|
|
1089
1139
|
baseNetwork: 'xna-test'
|
|
@@ -1911,6 +1961,8 @@ var NeuraiAssetsBundle = (function (exports) {
|
|
|
1911
1961
|
function requireNetworkDetector () {
|
|
1912
1962
|
if (hasRequiredNetworkDetector) return networkDetector;
|
|
1913
1963
|
hasRequiredNetworkDetector = 1;
|
|
1964
|
+
const { rpcErrorMessage } = requireRpcErrorMessage();
|
|
1965
|
+
|
|
1914
1966
|
const {
|
|
1915
1967
|
NETWORKS,
|
|
1916
1968
|
areAddressNetworksCompatible,
|
|
@@ -1945,7 +1997,7 @@ var NeuraiAssetsBundle = (function (exports) {
|
|
|
1945
1997
|
// Default to mainnet
|
|
1946
1998
|
return 'xna';
|
|
1947
1999
|
} catch (error) {
|
|
1948
|
-
throw new Error(`Failed to detect network from RPC: ${error
|
|
2000
|
+
throw new Error(`Failed to detect network from RPC: ${rpcErrorMessage(error)}`);
|
|
1949
2001
|
}
|
|
1950
2002
|
}
|
|
1951
2003
|
|
|
@@ -2465,6 +2517,7 @@ var NeuraiAssetsBundle = (function (exports) {
|
|
|
2465
2517
|
function requireOwnerTokenManager () {
|
|
2466
2518
|
if (hasRequiredOwnerTokenManager) return OwnerTokenManager_1;
|
|
2467
2519
|
hasRequiredOwnerTokenManager = 1;
|
|
2520
|
+
const { rpcErrorMessage } = requireRpcErrorMessage();
|
|
2468
2521
|
const { AssetNameParser } = requireUtils();
|
|
2469
2522
|
const {
|
|
2470
2523
|
OwnerTokenNotFoundError,
|
|
@@ -2523,7 +2576,7 @@ var NeuraiAssetsBundle = (function (exports) {
|
|
|
2523
2576
|
}
|
|
2524
2577
|
|
|
2525
2578
|
throw new AssetError(
|
|
2526
|
-
`Failed to find owner token ${ownerTokenName}: ${error
|
|
2579
|
+
`Failed to find owner token ${ownerTokenName}: ${rpcErrorMessage(error)}`
|
|
2527
2580
|
);
|
|
2528
2581
|
}
|
|
2529
2582
|
}
|
|
@@ -2661,7 +2714,7 @@ var NeuraiAssetsBundle = (function (exports) {
|
|
|
2661
2714
|
return ownerTokenUTXOs;
|
|
2662
2715
|
} catch (error) {
|
|
2663
2716
|
throw new AssetError(
|
|
2664
|
-
`Failed to get owner tokens: ${error
|
|
2717
|
+
`Failed to get owner tokens: ${rpcErrorMessage(error)}`
|
|
2665
2718
|
);
|
|
2666
2719
|
}
|
|
2667
2720
|
}
|
|
@@ -2853,6 +2906,7 @@ var NeuraiAssetsBundle = (function (exports) {
|
|
|
2853
2906
|
function requireUTXOSelector () {
|
|
2854
2907
|
if (hasRequiredUTXOSelector) return UTXOSelector_1;
|
|
2855
2908
|
hasRequiredUTXOSelector = 1;
|
|
2909
|
+
const { rpcErrorMessage } = requireRpcErrorMessage();
|
|
2856
2910
|
const { InsufficientFundsError } = requireErrors();
|
|
2857
2911
|
const { estimateTransactionVbytes } = requireFeeSizing();
|
|
2858
2912
|
|
|
@@ -2891,7 +2945,7 @@ var NeuraiAssetsBundle = (function (exports) {
|
|
|
2891
2945
|
return utxos.filter(utxo => !utxo.assetName || utxo.assetName === 'XNA');
|
|
2892
2946
|
}
|
|
2893
2947
|
} catch (error) {
|
|
2894
|
-
throw new Error(`Failed to get UTXOs: ${error
|
|
2948
|
+
throw new Error(`Failed to get UTXOs: ${rpcErrorMessage(error)}`);
|
|
2895
2949
|
}
|
|
2896
2950
|
}
|
|
2897
2951
|
|
|
@@ -3493,7 +3547,10 @@ var NeuraiAssetsBundle = (function (exports) {
|
|
|
3493
3547
|
const { InvalidAssetNameError } = requireErrors();
|
|
3494
3548
|
|
|
3495
3549
|
const MIN_ASSET_LENGTH = 3;
|
|
3496
|
-
|
|
3550
|
+
// Full-name caps, mirror of the node (assets_fromscript.cpp:31-47): the limit
|
|
3551
|
+
// applies to the COMPLETE name, owner '!' and tags included, so a mainnet
|
|
3552
|
+
// root is effectively capped at 30 (its owner token "ROOT!" must fit in 31).
|
|
3553
|
+
const MAINNET_MAX_NAME_LENGTH = 31;
|
|
3497
3554
|
const TESTNET_MAX_NAME_LENGTH = 121;
|
|
3498
3555
|
|
|
3499
3556
|
const ROOT_NAME_CHARACTERS = /^[A-Z0-9._]{3,}$/;
|
|
@@ -4363,6 +4420,7 @@ var NeuraiAssetsBundle = (function (exports) {
|
|
|
4363
4420
|
function requireBaseAssetTransactionBuilder () {
|
|
4364
4421
|
if (hasRequiredBaseAssetTransactionBuilder) return BaseAssetTransactionBuilder_1;
|
|
4365
4422
|
hasRequiredBaseAssetTransactionBuilder = 1;
|
|
4423
|
+
const { rpcErrorMessage } = requireRpcErrorMessage();
|
|
4366
4424
|
const { BurnManager, OwnerTokenManager, UTXOSelector, OutputOrderer } = requireManagers();
|
|
4367
4425
|
const { AssetNameValidator, AmountValidator } = requireValidators();
|
|
4368
4426
|
|
|
@@ -4423,6 +4481,9 @@ var NeuraiAssetsBundle = (function (exports) {
|
|
|
4423
4481
|
// post-selection recompute). The fee rate is stable for the duration of
|
|
4424
4482
|
// a single build, so cache the first lookup and reuse it.
|
|
4425
4483
|
this._feeRatePromise = null;
|
|
4484
|
+
|
|
4485
|
+
// NIP-040 marker for the localRawBuild metadata; resolved once per build.
|
|
4486
|
+
this._assetMarkerPromise = null;
|
|
4426
4487
|
}
|
|
4427
4488
|
|
|
4428
4489
|
/**
|
|
@@ -4515,7 +4576,7 @@ var NeuraiAssetsBundle = (function (exports) {
|
|
|
4515
4576
|
|
|
4516
4577
|
return rawTx;
|
|
4517
4578
|
} catch (error) {
|
|
4518
|
-
throw new Error(`Failed to create raw transaction: ${error
|
|
4579
|
+
throw new Error(`Failed to create raw transaction: ${rpcErrorMessage(error)}`);
|
|
4519
4580
|
}
|
|
4520
4581
|
}
|
|
4521
4582
|
|
|
@@ -4677,19 +4738,73 @@ var NeuraiAssetsBundle = (function (exports) {
|
|
|
4677
4738
|
return Math.round(amount * 100000000);
|
|
4678
4739
|
}
|
|
4679
4740
|
|
|
4741
|
+
/**
|
|
4742
|
+
* NIP-040 marker for every asset output of the localRawBuild metadata.
|
|
4743
|
+
*
|
|
4744
|
+
* The chain decides which marker ("rvn" or "xna") new asset outputs must
|
|
4745
|
+
* carry, per network and height, and the node reports the one required for
|
|
4746
|
+
* the next block as `getblockchaininfo.asset_marker` (node commit 347362b).
|
|
4747
|
+
* Resolution order:
|
|
4748
|
+
* 1. `params.assetMarker` (explicit caller override — offline builds,
|
|
4749
|
+
* tests, or a node this library should not ask);
|
|
4750
|
+
* 2. `getblockchaininfo.asset_marker` from the connected node;
|
|
4751
|
+
* 3. `'rvn'` when the node predates the field or the call fails
|
|
4752
|
+
* (matches what such a node enforces; documented in the README).
|
|
4753
|
+
* The RPC-built transaction path never needs this: the node stamps the
|
|
4754
|
+
* marker itself in `createrawtransaction`.
|
|
4755
|
+
*
|
|
4756
|
+
* @returns {Promise<'rvn'|'xna'>} Marker for locally built asset outputs
|
|
4757
|
+
*/
|
|
4758
|
+
resolveAssetMarker() {
|
|
4759
|
+
if (!this._assetMarkerPromise) {
|
|
4760
|
+
this._assetMarkerPromise = this._fetchAssetMarker();
|
|
4761
|
+
}
|
|
4762
|
+
return this._assetMarkerPromise;
|
|
4763
|
+
}
|
|
4764
|
+
|
|
4765
|
+
async _fetchAssetMarker() {
|
|
4766
|
+
const override = this.params.assetMarker;
|
|
4767
|
+
if (override !== undefined && override !== null) {
|
|
4768
|
+
if (override !== 'rvn' && override !== 'xna') {
|
|
4769
|
+
throw new Error(
|
|
4770
|
+
`Invalid assetMarker: ${override} (expected 'rvn' or 'xna', the value of getblockchaininfo.asset_marker)`
|
|
4771
|
+
);
|
|
4772
|
+
}
|
|
4773
|
+
return override;
|
|
4774
|
+
}
|
|
4775
|
+
|
|
4776
|
+
let info = null;
|
|
4777
|
+
try {
|
|
4778
|
+
info = await this.rpc('getblockchaininfo', []);
|
|
4779
|
+
} catch (error) {
|
|
4780
|
+
return 'rvn';
|
|
4781
|
+
}
|
|
4782
|
+
const marker = info ? info.asset_marker : undefined;
|
|
4783
|
+
if (marker === undefined || marker === null) {
|
|
4784
|
+
return 'rvn';
|
|
4785
|
+
}
|
|
4786
|
+
if (marker !== 'rvn' && marker !== 'xna') {
|
|
4787
|
+
throw new Error(`Node reported an unknown asset_marker: ${marker}`);
|
|
4788
|
+
}
|
|
4789
|
+
return marker;
|
|
4790
|
+
}
|
|
4791
|
+
|
|
4680
4792
|
/**
|
|
4681
4793
|
* Build a typed local raw build payload compatible with
|
|
4682
4794
|
* @neuraiproject/neurai-create-transaction createFromOperation(...)
|
|
4683
4795
|
*
|
|
4796
|
+
* Stamps the NIP-040 `assetMarker` (see resolveAssetMarker) so
|
|
4797
|
+
* createFromOperation >= 0.7.0 emits the marker the chain requires.
|
|
4798
|
+
*
|
|
4684
4799
|
* @param {string} operationType - Operation type
|
|
4685
4800
|
* @param {Array} inputs - Builder inputs
|
|
4686
4801
|
* @param {object|null} burnInfo - Burn metadata
|
|
4687
4802
|
* @param {string|null} changeAddress - XNA change address
|
|
4688
4803
|
* @param {number|null} changeAmount - XNA change amount in XNA
|
|
4689
4804
|
* @param {object} operationParams - Operation-specific params
|
|
4690
|
-
* @returns {{ operationType: string, params: object }} Local raw build
|
|
4805
|
+
* @returns {Promise<{ operationType: string, params: object }>} Local raw build
|
|
4691
4806
|
*/
|
|
4692
|
-
buildLocalRawBuild(
|
|
4807
|
+
async buildLocalRawBuild(
|
|
4693
4808
|
operationType,
|
|
4694
4809
|
inputs,
|
|
4695
4810
|
burnInfo = null,
|
|
@@ -4699,6 +4814,7 @@ var NeuraiAssetsBundle = (function (exports) {
|
|
|
4699
4814
|
) {
|
|
4700
4815
|
const params = {
|
|
4701
4816
|
inputs: this.toRawTxInputs(inputs),
|
|
4817
|
+
assetMarker: await this.resolveAssetMarker(),
|
|
4702
4818
|
...operationParams
|
|
4703
4819
|
};
|
|
4704
4820
|
|
|
@@ -4835,7 +4951,7 @@ var NeuraiAssetsBundle = (function (exports) {
|
|
|
4835
4951
|
return assetData !== null && assetData !== undefined;
|
|
4836
4952
|
} catch (error) {
|
|
4837
4953
|
// If asset doesn't exist, RPC will throw error
|
|
4838
|
-
if (error.
|
|
4954
|
+
if (rpcErrorMessage(error).includes('not found')) {
|
|
4839
4955
|
return false;
|
|
4840
4956
|
}
|
|
4841
4957
|
// Re-throw other errors
|
|
@@ -4852,7 +4968,7 @@ var NeuraiAssetsBundle = (function (exports) {
|
|
|
4852
4968
|
try {
|
|
4853
4969
|
return await this.rpc('getassetdata', [assetName]);
|
|
4854
4970
|
} catch (error) {
|
|
4855
|
-
if (error.
|
|
4971
|
+
if (rpcErrorMessage(error).includes('not found')) {
|
|
4856
4972
|
return null;
|
|
4857
4973
|
}
|
|
4858
4974
|
throw error;
|
|
@@ -5038,7 +5154,7 @@ var NeuraiAssetsBundle = (function (exports) {
|
|
|
5038
5154
|
assetName,
|
|
5039
5155
|
ownerTokenName: assetName + '!',
|
|
5040
5156
|
operationType: 'ISSUE_ROOT',
|
|
5041
|
-
localRawBuild: this.buildLocalRawBuild(
|
|
5157
|
+
localRawBuild: await this.buildLocalRawBuild(
|
|
5042
5158
|
'ISSUE_ROOT',
|
|
5043
5159
|
inputs,
|
|
5044
5160
|
burnInfo,
|
|
@@ -5306,7 +5422,7 @@ var NeuraiAssetsBundle = (function (exports) {
|
|
|
5306
5422
|
ownerTokenName: assetName + '!',
|
|
5307
5423
|
parentOwnerTokenUsed: ownerTokenName,
|
|
5308
5424
|
operationType: 'ISSUE_SUB',
|
|
5309
|
-
localRawBuild: this.buildLocalRawBuild(
|
|
5425
|
+
localRawBuild: await this.buildLocalRawBuild(
|
|
5310
5426
|
'ISSUE_SUB',
|
|
5311
5427
|
inputs,
|
|
5312
5428
|
burnInfo,
|
|
@@ -5476,7 +5592,7 @@ var NeuraiAssetsBundle = (function (exports) {
|
|
|
5476
5592
|
assetName,
|
|
5477
5593
|
ownerTokenName: `${assetName}!`,
|
|
5478
5594
|
operationType: 'ISSUE_DEPIN',
|
|
5479
|
-
localRawBuild: this.buildLocalRawBuild(
|
|
5595
|
+
localRawBuild: await this.buildLocalRawBuild(
|
|
5480
5596
|
'ISSUE_DEPIN',
|
|
5481
5597
|
inputs,
|
|
5482
5598
|
burnInfo,
|
|
@@ -5744,7 +5860,7 @@ var NeuraiAssetsBundle = (function (exports) {
|
|
|
5744
5860
|
previousSupply: currentSupply,
|
|
5745
5861
|
reissuableLocked: reissuable === false,
|
|
5746
5862
|
operationType: 'REISSUE',
|
|
5747
|
-
localRawBuild: this.buildLocalRawBuild(
|
|
5863
|
+
localRawBuild: await this.buildLocalRawBuild(
|
|
5748
5864
|
'REISSUE',
|
|
5749
5865
|
inputs,
|
|
5750
5866
|
burnInfo,
|
|
@@ -6007,7 +6123,7 @@ var NeuraiAssetsBundle = (function (exports) {
|
|
|
6007
6123
|
isDepin,
|
|
6008
6124
|
ownerTokenUsed: isDepin ? ownerTokenName : null,
|
|
6009
6125
|
operationType: 'TRANSFER',
|
|
6010
|
-
localRawBuild: this.buildLocalRawBuild(
|
|
6126
|
+
localRawBuild: await this.buildLocalRawBuild(
|
|
6011
6127
|
'TRANSFER',
|
|
6012
6128
|
inputs,
|
|
6013
6129
|
null, // no burn
|
|
@@ -6291,7 +6407,7 @@ var NeuraiAssetsBundle = (function (exports) {
|
|
|
6291
6407
|
nftCount,
|
|
6292
6408
|
ownerTokenUsed: ownerTokenName,
|
|
6293
6409
|
operationType: 'ISSUE_UNIQUE',
|
|
6294
|
-
localRawBuild: this.buildLocalRawBuild(
|
|
6410
|
+
localRawBuild: await this.buildLocalRawBuild(
|
|
6295
6411
|
'ISSUE_UNIQUE',
|
|
6296
6412
|
inputs,
|
|
6297
6413
|
burnInfo,
|
|
@@ -6552,7 +6668,7 @@ var NeuraiAssetsBundle = (function (exports) {
|
|
|
6552
6668
|
parentQualifier: isSub ? parsed.parent : null,
|
|
6553
6669
|
parentQualifierUsed: parentQualifierName,
|
|
6554
6670
|
operationType: isSub ? 'ISSUE_SUB_QUALIFIER' : 'ISSUE_QUALIFIER',
|
|
6555
|
-
localRawBuild: this.buildLocalRawBuild(
|
|
6671
|
+
localRawBuild: await this.buildLocalRawBuild(
|
|
6556
6672
|
isSub ? 'ISSUE_SUB_QUALIFIER' : 'ISSUE_QUALIFIER',
|
|
6557
6673
|
inputs,
|
|
6558
6674
|
burnInfo,
|
|
@@ -6806,7 +6922,7 @@ var NeuraiAssetsBundle = (function (exports) {
|
|
|
6806
6922
|
verifierString,
|
|
6807
6923
|
requiredQualifiers,
|
|
6808
6924
|
operationType: 'ISSUE_RESTRICTED',
|
|
6809
|
-
localRawBuild: this.buildLocalRawBuild(
|
|
6925
|
+
localRawBuild: await this.buildLocalRawBuild(
|
|
6810
6926
|
'ISSUE_RESTRICTED',
|
|
6811
6927
|
inputs,
|
|
6812
6928
|
burnInfo,
|
|
@@ -7092,7 +7208,7 @@ var NeuraiAssetsBundle = (function (exports) {
|
|
|
7092
7208
|
requiredQualifiers,
|
|
7093
7209
|
reissuableLocked: reissuable === false,
|
|
7094
7210
|
operationType: 'REISSUE_RESTRICTED',
|
|
7095
|
-
localRawBuild: this.buildLocalRawBuild(
|
|
7211
|
+
localRawBuild: await this.buildLocalRawBuild(
|
|
7096
7212
|
'REISSUE_RESTRICTED',
|
|
7097
7213
|
inputs,
|
|
7098
7214
|
burnInfo,
|
|
@@ -7334,7 +7450,7 @@ var NeuraiAssetsBundle = (function (exports) {
|
|
|
7334
7450
|
targetAddresses,
|
|
7335
7451
|
addressCount,
|
|
7336
7452
|
operationType: isUntag ? 'UNTAG_ADDRESSES' : 'TAG_ADDRESSES',
|
|
7337
|
-
localRawBuild: this.buildLocalRawBuild(
|
|
7453
|
+
localRawBuild: await this.buildLocalRawBuild(
|
|
7338
7454
|
isUntag ? 'UNTAG_ADDRESSES' : 'TAG_ADDRESSES',
|
|
7339
7455
|
inputs,
|
|
7340
7456
|
burnInfo,
|
|
@@ -7596,7 +7712,7 @@ var NeuraiAssetsBundle = (function (exports) {
|
|
|
7596
7712
|
targetAddresses: targetAddresses.length > 0 ? targetAddresses : null,
|
|
7597
7713
|
addressCount: targetAddresses.length,
|
|
7598
7714
|
operationType,
|
|
7599
|
-
localRawBuild: this.buildLocalRawBuild(
|
|
7715
|
+
localRawBuild: await this.buildLocalRawBuild(
|
|
7600
7716
|
operationType,
|
|
7601
7717
|
inputs,
|
|
7602
7718
|
null,
|
|
@@ -7757,6 +7873,10 @@ var NeuraiAssetsBundle = (function (exports) {
|
|
|
7757
7873
|
* @param {Array<string>} config.addresses - Wallet addresses
|
|
7758
7874
|
* @param {string} config.changeAddress - Default change address
|
|
7759
7875
|
* @param {string} config.toAddress - Default receiving address
|
|
7876
|
+
* @param {('rvn'|'xna')} [config.assetMarker] - NIP-040 marker for locally
|
|
7877
|
+
* built raw transactions. Omit to use the node's
|
|
7878
|
+
* getblockchaininfo.asset_marker (falls back to 'rvn' on nodes that do
|
|
7879
|
+
* not report it). Per-operation params.assetMarker overrides this.
|
|
7760
7880
|
*/
|
|
7761
7881
|
constructor(rpc, config = {}) {
|
|
7762
7882
|
if (!rpc || typeof rpc !== 'function') {
|
|
@@ -7768,7 +7888,11 @@ var NeuraiAssetsBundle = (function (exports) {
|
|
|
7768
7888
|
network: config.network || 'xna',
|
|
7769
7889
|
addresses: config.addresses || [],
|
|
7770
7890
|
changeAddress: config.changeAddress || null,
|
|
7771
|
-
toAddress: config.toAddress || null
|
|
7891
|
+
toAddress: config.toAddress || null,
|
|
7892
|
+
// NIP-040: documented since 1.4.0 but dropped here until 1.4.1, which
|
|
7893
|
+
// made the config-level override silently inoperative (per-operation
|
|
7894
|
+
// params.assetMarker was unaffected).
|
|
7895
|
+
assetMarker: config.assetMarker
|
|
7772
7896
|
};
|
|
7773
7897
|
|
|
7774
7898
|
// Initialize query interface
|
|
@@ -7794,7 +7918,10 @@ var NeuraiAssetsBundle = (function (exports) {
|
|
|
7794
7918
|
network: this.config.network,
|
|
7795
7919
|
walletAddresses: this.config.addresses,
|
|
7796
7920
|
changeAddress: params.changeAddress || this.config.changeAddress,
|
|
7797
|
-
toAddress: params.toAddress || this.config.toAddress
|
|
7921
|
+
toAddress: params.toAddress || this.config.toAddress,
|
|
7922
|
+
// NIP-040: marker for the localRawBuild metadata. Undefined lets the
|
|
7923
|
+
// builder ask the node (getblockchaininfo.asset_marker).
|
|
7924
|
+
assetMarker: params.assetMarker !== undefined ? params.assetMarker : this.config.assetMarker
|
|
7798
7925
|
};
|
|
7799
7926
|
}
|
|
7800
7927
|
|