@neuraiproject/neurai-assets 1.5.3 → 1.6.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 +148 -20
- package/dist/NeuraiAssets.global.js +430 -40
- package/dist/NeuraiAssets.global.js.map +1 -1
- package/dist/browser.js +430 -40
- package/dist/browser.js.map +1 -1
- package/dist/index.cjs +430 -40
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +430 -40
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -2,6 +2,30 @@
|
|
|
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.6.0**: full DEPIN support — sub-DEPIN issuance (which needs the
|
|
6
|
+
> **immediate** parent's owner token), holder freeze/unfreeze through the same
|
|
7
|
+
> `freezeAddresses`/`unfreezeAddresses` calls, `selfRevokeDepin` and
|
|
8
|
+
> `listDepinAddresses`. Also a fix beyond DEPIN: the parent of `A/B/C` resolved
|
|
9
|
+
> to `A` instead of `A/B`, so every third-level issuance — sub-asset,
|
|
10
|
+
> sub-qualifier or sub-DEPIN — was rejected by the node.
|
|
11
|
+
>
|
|
12
|
+
> **1.5.3**: fee estimation stopped modelling the payload encoding and started
|
|
13
|
+
> measuring it. Twelve of eighteen operations were budgeting below the node's
|
|
14
|
+
> minimum, which forced a rebuild-and-re-sign on every one of them (see
|
|
15
|
+
> *Fee estimation*).
|
|
16
|
+
>
|
|
17
|
+
> **1.5.2**: same RPC calls, fewer round trips. The UTXO and mempool reads run
|
|
18
|
+
> together, and the fee rate and NIP-040 marker start alongside the first read
|
|
19
|
+
> instead of queuing behind it — 6 calls in 3 round trips instead of 6, which
|
|
20
|
+
> against a remote proxy halves the time to build anything.
|
|
21
|
+
>
|
|
22
|
+
> **1.5.1**: fix — `Buffer` reached the browser bundle through the fee sizing
|
|
23
|
+
> helper and broke any asset build in an extension.
|
|
24
|
+
>
|
|
25
|
+
> **1.5.0**: `createTransactionBuild` canonical contract; decimal strings for
|
|
26
|
+
> amounts; exact-satoshi funding loop; reissue built locally so assets with
|
|
27
|
+
> `units > 0` can be reissued at all.
|
|
28
|
+
>
|
|
5
29
|
> **1.4.1**: fix — the constructor dropped `config.assetMarker`, so the
|
|
6
30
|
> wallet-level override documented in 1.4.0 never reached the builders
|
|
7
31
|
> (per-operation `params.assetMarker` was unaffected). Precedence is now
|
|
@@ -18,6 +42,7 @@ Complete asset management library for Neurai blockchain. Supports creation, reis
|
|
|
18
42
|
- ✅ **Non-custodial**: Library builds unsigned transactions, your wallet signs them
|
|
19
43
|
- ✅ **All asset types**: ROOT, SUB, UNIQUE (NFTs), QUALIFIER, RESTRICTED, DEPIN
|
|
20
44
|
- ✅ **Complete operations**: Creation, reissuance, tagging, freezing
|
|
45
|
+
- ✅ **DEPIN management**: sub-assets, holder freeze/unfreeze, self-revocation, validity queries
|
|
21
46
|
- ✅ **RPC queries**: Complete wrapper for all asset query methods
|
|
22
47
|
- ✅ **Client-side validation**: Prevents errors before creating transactions
|
|
23
48
|
- ✅ **Owner token protection**: Validation to prevent permanent loss
|
|
@@ -33,7 +58,8 @@ Complete asset management library for Neurai blockchain. Supports creation, reis
|
|
|
33
58
|
| **QUALIFIER** | `#KYC` | 2000 XNA | Compliance tag |
|
|
34
59
|
| **SUB_QUALIFIER** | `#PARENT/#SUB` | 200 XNA | Sub-qualifier |
|
|
35
60
|
| **RESTRICTED** | `$SECURITY` | 3000 XNA | Security token with compliance |
|
|
36
|
-
| **DEPIN** | `&DEVICE`
|
|
61
|
+
| **DEPIN** | `&DEVICE` | 10 XNA | Soulbound asset with holder validity controls |
|
|
62
|
+
| **SUB DEPIN** | `&DEVICE/ROUTER001` | 10 XNA | Same burn as a root DEPIN, but requires the **immediate parent's** owner token |
|
|
37
63
|
|
|
38
64
|
## Quantities and asset units
|
|
39
65
|
|
|
@@ -194,6 +220,16 @@ const result = await assets.createDepinAsset({
|
|
|
194
220
|
> **Note**: DEPIN assets always use `units = 0`. Recipient and change destinations
|
|
195
221
|
> can be either legacy or AuthScript, as long as they belong to the same chain family.
|
|
196
222
|
|
|
223
|
+
A **sub-DEPIN** (`&DEVICE/ROUTER001`) costs the same as a root DEPIN, but the
|
|
224
|
+
node requires the transaction to spend and return the **immediate parent's**
|
|
225
|
+
owner token — `&DEVICE!` here, and `&DEVICE/ROUTER001!` for a third level. The
|
|
226
|
+
library finds it, adds it as an input and returns it automatically; without it
|
|
227
|
+
the node rejects the transaction with
|
|
228
|
+
`Trying to create outpoint for asset that you don't have`.
|
|
229
|
+
|
|
230
|
+
So `&A/B/C` needs `&A/B!`, **not** `&A!`. Before 1.6.0 the library resolved the
|
|
231
|
+
parent as the root and every third-level issuance was rejected.
|
|
232
|
+
|
|
197
233
|
### Transfer Asset
|
|
198
234
|
|
|
199
235
|
```javascript
|
|
@@ -299,13 +335,31 @@ const result = await assets.reissueRestrictedAsset({
|
|
|
299
335
|
### Freeze Addresses
|
|
300
336
|
|
|
301
337
|
```javascript
|
|
302
|
-
// Requires the
|
|
338
|
+
// Requires the asset's owner token ($SECURITY! or &DEVICE!)
|
|
303
339
|
const result = await assets.freezeAddresses({
|
|
304
340
|
assetName: '$SECURITY',
|
|
305
341
|
addresses: ['NAddress1...', 'NAddress2...']
|
|
306
342
|
});
|
|
343
|
+
|
|
344
|
+
// Since 1.6.0, the same call freezes a DEPIN holder
|
|
345
|
+
await assets.freezeAddresses({
|
|
346
|
+
assetName: '&DEVICE',
|
|
347
|
+
addresses: ['NDevice1...']
|
|
348
|
+
});
|
|
307
349
|
```
|
|
308
350
|
|
|
351
|
+
Both asset kinds share this operation because the node builds them identically:
|
|
352
|
+
an owner-token escort plus one null-asset-data output carrying `(name, flag)`.
|
|
353
|
+
A frozen DEPIN holder keeps the asset but `checkDepinValidity` reports
|
|
354
|
+
`valid: 0`.
|
|
355
|
+
|
|
356
|
+
Two rules the library enforces before the node does:
|
|
357
|
+
|
|
358
|
+
- the address holding the owner token **cannot** be frozen or revoked — if it
|
|
359
|
+
were, nobody could undo it;
|
|
360
|
+
- **global** freeze does not apply to DEPIN assets; manage them holder by
|
|
361
|
+
holder.
|
|
362
|
+
|
|
309
363
|
### Unfreeze Addresses
|
|
310
364
|
|
|
311
365
|
```javascript
|
|
@@ -315,6 +369,8 @@ const result = await assets.unfreezeAddresses({
|
|
|
315
369
|
});
|
|
316
370
|
```
|
|
317
371
|
|
|
372
|
+
This is also how an owner undoes a holder's self-revocation.
|
|
373
|
+
|
|
318
374
|
### Freeze Asset Globally
|
|
319
375
|
|
|
320
376
|
```javascript
|
|
@@ -323,6 +379,24 @@ const result = await assets.freezeAssetGlobally({
|
|
|
323
379
|
});
|
|
324
380
|
```
|
|
325
381
|
|
|
382
|
+
> Restricted assets only. Calling it on a DEPIN asset throws: the node has no
|
|
383
|
+
> global restriction for them.
|
|
384
|
+
|
|
385
|
+
### Self-Revoke a DEPIN Asset (1.6.0+)
|
|
386
|
+
|
|
387
|
+
```javascript
|
|
388
|
+
// Run from the wallet that HOLDS the device asset — no owner token needed.
|
|
389
|
+
const result = await assets.selfRevokeDepin({ assetName: '&DEVICE' });
|
|
390
|
+
```
|
|
391
|
+
|
|
392
|
+
A holder renouncing its own asset. The proof of ownership is spending its own
|
|
393
|
+
asset UTXO, which returns to the same address together with the revocation
|
|
394
|
+
mark, so the operation needs no owner token and no burn.
|
|
395
|
+
|
|
396
|
+
⚠️ Only the asset owner can undo it, with `unfreezeAddresses`. If the revoking
|
|
397
|
+
address also held the owner token nobody could, so the library refuses that
|
|
398
|
+
case — move the owner token elsewhere first.
|
|
399
|
+
|
|
326
400
|
### Unfreeze Asset Globally
|
|
327
401
|
|
|
328
402
|
```javascript
|
|
@@ -466,6 +540,21 @@ console.log(validity);
|
|
|
466
540
|
// }
|
|
467
541
|
```
|
|
468
542
|
|
|
543
|
+
### List DEPIN Addresses With a Revealed Public Key (1.6.0+)
|
|
544
|
+
|
|
545
|
+
```javascript
|
|
546
|
+
const addresses = await assets.listDepinAddresses('&DEVICE');
|
|
547
|
+
console.log(addresses);
|
|
548
|
+
// [ { address: 'tAhTaUnh...', pubkey: '03d0813ea333...' } ]
|
|
549
|
+
```
|
|
550
|
+
|
|
551
|
+
The subset of holders that can take part in DEPIN messaging, which needs the
|
|
552
|
+
public key. It is **not** a replacement for `listDepinHolders`: it says nothing
|
|
553
|
+
about validity or amounts, and a holder that has never spent does not appear.
|
|
554
|
+
|
|
555
|
+
Requires the node running with `-pubkeyindex` (and a reindex). Without it the
|
|
556
|
+
error says so instead of hiding behind a generic failure.
|
|
557
|
+
|
|
469
558
|
### Detect Asset Type
|
|
470
559
|
|
|
471
560
|
```javascript
|
|
@@ -589,6 +678,16 @@ rule: sign, decimals, `units` divisibility and `MAX_MONEY` apply equally.
|
|
|
589
678
|
consumer has to move on this release. New integrations should read
|
|
590
679
|
`createTransactionBuild` only.
|
|
591
680
|
|
|
681
|
+
**1.6.0** adds DEPIN management and fixes two things that were silently broken.
|
|
682
|
+
No API changed shape:
|
|
683
|
+
|
|
684
|
+
| | Before 1.6.0 | 1.6.0 |
|
|
685
|
+
| --- | --- | --- |
|
|
686
|
+
| Parent of `A/B/C` | `A` — every third-level issuance was rejected | `A/B`, as the node resolves it |
|
|
687
|
+
| Create `&A/B` | rejected: the parent's owner token was never spent | works |
|
|
688
|
+
| `freezeAddresses` / `unfreezeAddresses` | restricted assets only | also DEPIN (`&NAME`) |
|
|
689
|
+
| Self-revoke, `listDepinAddresses` | — | new |
|
|
690
|
+
|
|
592
691
|
### Serializer version
|
|
593
692
|
|
|
594
693
|
The canonical contract needs `@neuraiproject/neurai-create-transaction`
|
|
@@ -615,13 +714,18 @@ The value read from the chain is still used, to check that the requested
|
|
|
615
714
|
|
|
616
715
|
### Reissue is built locally
|
|
617
716
|
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
717
|
+
Some operations cannot be expressed through the node's `createrawtransaction`,
|
|
718
|
+
even though the node accepts the resulting transaction perfectly well. Those
|
|
719
|
+
build their `rawTx` with `createFromOperation` instead and report
|
|
720
|
+
`buildStrategy: 'local-builder'`; everything else still reports `'rpc-node'`.
|
|
721
|
+
|
|
722
|
+
| Operation | Why the RPC cannot express it | Since |
|
|
723
|
+
| --- | --- | --- |
|
|
724
|
+
| `reissueAsset`, `reissueRestrictedAsset` | the `reissue` object has no units field, so the node assumes `0` and refuses any asset with units above zero (`unit must be larger than current unit selection`) | 1.5.0 |
|
|
725
|
+
| `freezeAddresses` / `unfreezeAddresses` on a **DEPIN** asset | `freeze_addresses` demands a restricted name: `a valid restricted asset name must be provided` | 1.6.0 |
|
|
726
|
+
| `selfRevokeDepin` | no equivalent RPC object | 1.6.0 |
|
|
727
|
+
|
|
728
|
+
Restricted-asset freezing keeps the RPC path unchanged.
|
|
625
729
|
|
|
626
730
|
This is why `@neuraiproject/neurai-create-transaction` is a runtime
|
|
627
731
|
**dependency**, not just a dev one.
|
|
@@ -640,10 +744,13 @@ When you create an asset, an **owner token** is automatically generated (e.g., `
|
|
|
640
744
|
|
|
641
745
|
⚠️ **CRITICAL**: The owner token is required to:
|
|
642
746
|
- Reissue (mint more supply)
|
|
643
|
-
- Create SUB assets
|
|
747
|
+
- Create SUB assets — the **immediate** parent's token: `A/B/C` needs `A/B!`
|
|
748
|
+
- Create sub-DEPIN assets — likewise, `&A/B` needs `&A!`
|
|
644
749
|
- Manage tags (if qualifier)
|
|
645
|
-
- Freeze/unfreeze (
|
|
646
|
-
|
|
750
|
+
- Freeze/unfreeze holders (restricted **and** DEPIN)
|
|
751
|
+
|
|
752
|
+
A holder can always self-revoke its own DEPIN asset without any owner token
|
|
753
|
+
(`selfRevokeDepin`), but only the owner can undo that.
|
|
647
754
|
|
|
648
755
|
⚠️ **If you lose the owner token, you lose these capabilities PERMANENTLY**
|
|
649
756
|
|
|
@@ -664,13 +771,14 @@ The library automatically validates that the owner token is returned in each ope
|
|
|
664
771
|
| Create QUALIFIER (root) | 2000 |
|
|
665
772
|
| Create QUALIFIER (sub) | 200 |
|
|
666
773
|
| Create RESTRICTED asset | 3000 |
|
|
667
|
-
| Create DEPIN asset | 10 |
|
|
774
|
+
| Create DEPIN asset (root or sub) | 10 |
|
|
668
775
|
| Reissue ROOT/SUB | 200 |
|
|
669
776
|
| Reissue DEPIN | 200 |
|
|
670
777
|
| Reissue RESTRICTED | 200 |
|
|
671
778
|
| Tag/Untag address | 0 (network fee only; spends 1 unit of the qualifier per address) |
|
|
672
779
|
| Freeze/Unfreeze address | 0 (network fee only) |
|
|
673
780
|
| Freeze/Unfreeze global | 0 (network fee only) |
|
|
781
|
+
| Self-revoke DEPIN | 0 (network fee only) |
|
|
674
782
|
|
|
675
783
|
**Note**: In addition to the burned cost, all operations pay a network fee (calculated automatically).
|
|
676
784
|
|
|
@@ -813,16 +921,20 @@ const builder = new builders.IssueRootBuilder(rpc, {
|
|
|
813
921
|
const result = await builder.build();
|
|
814
922
|
```
|
|
815
923
|
|
|
816
|
-
The builders module
|
|
924
|
+
The builders module exports:
|
|
817
925
|
|
|
926
|
+
- `DepinSelfRevokeBuilder`
|
|
927
|
+
- `FreezeAddressBuilder`
|
|
818
928
|
- `IssueDepinBuilder`
|
|
929
|
+
- `IssueQualifierBuilder`
|
|
930
|
+
- `IssueRestrictedBuilder`
|
|
819
931
|
- `IssueRootBuilder`
|
|
820
932
|
- `IssueSubBuilder`
|
|
821
933
|
- `IssueUniqueBuilder`
|
|
822
|
-
- `IssueQualifierBuilder`
|
|
823
|
-
- `IssueRestrictedBuilder`
|
|
824
934
|
- `ReissueBuilder`
|
|
825
935
|
- `ReissueRestrictedBuilder`
|
|
936
|
+
- `TagAddressBuilder`
|
|
937
|
+
- `TransferBuilder`
|
|
826
938
|
|
|
827
939
|
## Error Handling
|
|
828
940
|
|
|
@@ -917,6 +1029,8 @@ Estimates use the helpers in [`src/utils/feeSizing.js`](src/utils/feeSizing.js)
|
|
|
917
1029
|
|
|
918
1030
|
Outputs that carry an asset payload are sized as such, not as bare P2PKH outputs. An asset output is `<destination> OP_XNA_ASSET <pushdata payload> OP_DROP`, which adds roughly 20-60 bytes; ignoring that under-counts a transaction by a few percent, and that is enough to fall below the floor whenever the node's fee rate sits close to its minimum relay fee.
|
|
919
1031
|
|
|
1032
|
+
Since `1.5.3` those sizes are **not modelled, they are measured**: `feeSizing` asks `@neuraiproject/neurai-create-transaction` to encode the very script the output will carry and takes its length. The hand-written formula it replaced had drifted in two ways — the owner token an operation *returns* is serialized as a transfer (it carries an amount), not with the `owner` payload that an issuance *creates*, and the null-asset-data outputs of tag/freeze were not counted at all, since their script **replaces** the destination instead of extending it. Twelve of eighteen operations were budgeting below what the node charges. The regtest e2e now asserts, for every operation, that the budgeted fee reaches the node's minimum for the signed vsize.
|
|
1033
|
+
|
|
920
1034
|
You should not need to call these helpers directly; they are wired into every builder. They are documented here so you can audit the fee math or use the same constants if you compose transactions outside the standard builder flow.
|
|
921
1035
|
|
|
922
1036
|
```js
|
|
@@ -939,11 +1053,23 @@ estimateInputVbytes({ address: 'nq1…' }); // 977
|
|
|
939
1053
|
estimateInputVbytes({ address: 'mgRYHdMq…' }); // 148
|
|
940
1054
|
estimateOutputBytes('tnq1…'); // 43
|
|
941
1055
|
|
|
942
|
-
// Asset outputs declare their payload
|
|
943
|
-
//
|
|
944
|
-
estimateOutputBytes({ address: 't7pv…', assetName: 'ROOTX' }); // 55
|
|
945
|
-
estimateOutputBytes({ address: 't7pv…', assetName: 'ROOTX!', kind: 'owner' }); // 48
|
|
1056
|
+
// Asset outputs declare their payload. Sizes come from the real encoder, so
|
|
1057
|
+
// they match the bytes the node will see.
|
|
1058
|
+
estimateOutputBytes({ address: 't7pv…', assetName: 'ROOTX' }); // 55 transfer (default)
|
|
946
1059
|
estimateOutputBytes({ address: 't7pv…', assetName: 'ROOTX', kind: 'issue' }); // 58
|
|
1060
|
+
estimateOutputBytes({ address: 't7pv…', assetName: 'ROOTX', kind: 'reissue' }); // 57
|
|
1061
|
+
|
|
1062
|
+
// 'owner' describes the token an ISSUANCE CREATES — it carries no amount.
|
|
1063
|
+
estimateOutputBytes({ address: 't7pv…', assetName: 'ROOTX!', kind: 'owner' }); // 48
|
|
1064
|
+
// The token an operation SPENDS AND RETURNS is a transfer, 8 bytes wider.
|
|
1065
|
+
estimateOutputBytes({ address: 't7pv…', assetName: 'ROOTX!' }); // 56
|
|
1066
|
+
|
|
1067
|
+
// Null-asset-data kinds have no destination: their script replaces it, so
|
|
1068
|
+
// nothing is added on top.
|
|
1069
|
+
estimateOutputBytes({ address: 't7pv…', assetName: '#KYC', kind: 'tag' }); // 38
|
|
1070
|
+
estimateOutputBytes({ address: 't7pv…', assetName: '$SEC', kind: 'restriction' }); // 38
|
|
1071
|
+
estimateOutputBytes({ assetName: '$SEC', kind: 'globalRestriction' }); // 19
|
|
1072
|
+
estimateOutputBytes({ kind: 'verifier', verifierString: '#KYC' }); // 17
|
|
947
1073
|
|
|
948
1074
|
const vbytes = estimateTransactionVbytes(
|
|
949
1075
|
[{ script: '5120…' }, { address: 'mgRYHdMq…' }], // 1 PQ + 1 legacy input
|
|
@@ -953,6 +1079,8 @@ const vbytes = estimateTransactionVbytes(
|
|
|
953
1079
|
|
|
954
1080
|
The constants mirror those exported from `@neuraiproject/neurai-sign-transaction` (`VBYTES`). They are inlined here on purpose: depending on the full signer would pull `bitcoinjs-lib` and `@noble/post-quantum` into the IIFE / browser bundles, far more weight than these constants need. The signer remains the source of truth — if it ever bumps a vbytes value, this file must follow.
|
|
955
1081
|
|
|
1082
|
+
`feeSizing` does depend on `neurai-create-transaction` for the payload sizes above, which is already a runtime dependency and is bundled anyway. If an encoder cannot express a descriptor — an address family it does not accept — the estimate falls back to the previous formula rather than throwing in the middle of a fee calculation.
|
|
1083
|
+
|
|
956
1084
|
### Limitations
|
|
957
1085
|
|
|
958
1086
|
The estimator assumes the most common spend layout for every input:
|