@neuraiproject/neurai-assets 1.3.0 → 1.3.2
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 +45 -6
- package/dist/NeuraiAssets.global.js +42 -11
- package/dist/NeuraiAssets.global.js.map +1 -1
- package/dist/browser.js +42 -11
- package/dist/browser.js.map +1 -1
- package/dist/index.cjs +42 -11
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +42 -11
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -24,6 +24,31 @@ Complete asset management library for Neurai blockchain. Supports creation, reis
|
|
|
24
24
|
| **RESTRICTED** | `$SECURITY` | 3000 XNA | Security token with compliance |
|
|
25
25
|
| **DEPIN** | `&DEVICE` or `&DEVICE/ROUTER001` | 10 XNA | Soulbound asset with holder validity controls |
|
|
26
26
|
|
|
27
|
+
## Quantities and asset units
|
|
28
|
+
|
|
29
|
+
Every `quantity` / `asset_quantity` parameter accepted by this library is a
|
|
30
|
+
**user-facing display amount** — the same number a human would write to mean
|
|
31
|
+
"this many tokens". For an asset with `units = 2`, `quantity: 10.50` means
|
|
32
|
+
ten and a half tokens; for an asset with `units = 0`, `quantity: 1` means
|
|
33
|
+
one whole token.
|
|
34
|
+
|
|
35
|
+
Internally the daemon parses the JSON `asset_quantity` field with
|
|
36
|
+
`AmountFromValue` ([Bitcoin-style decimal → 10⁸ sats][amount-from-value])
|
|
37
|
+
and validates that the resulting CAmount is a multiple of `10^(8 − units)`
|
|
38
|
+
via `CheckAmountWithUnits`. Because the chain already does the ×10⁸ scaling
|
|
39
|
+
itself, **the library must NOT pre-multiply** the value. Sending the raw
|
|
40
|
+
display number is the only correct behavior; any extra factor on the wire
|
|
41
|
+
either silently inflates the minted supply (`× 10⁸ → 100,000,000` tokens
|
|
42
|
+
where the user asked for 1) or trips the daemon's
|
|
43
|
+
`ParseFixedPoint` cap with `Invalid amount (3): …`.
|
|
44
|
+
|
|
45
|
+
This was regressed in `1.2.2`/`1.3.x` (a hardcoded `× 10⁸` was added to
|
|
46
|
+
`BaseAssetTransactionBuilder.toSatoshis`) and fixed in the version after
|
|
47
|
+
`1.3.1`. If you write a custom builder, follow the same convention: pass
|
|
48
|
+
the user amount through unchanged, let the daemon scale.
|
|
49
|
+
|
|
50
|
+
[amount-from-value]: https://github.com/NeuraiProject/Neurai-DePIN/blob/main/src/rpc/server.cpp
|
|
51
|
+
|
|
27
52
|
## Installation
|
|
28
53
|
|
|
29
54
|
```bash
|
|
@@ -105,8 +130,9 @@ const assetsPQ = new NeuraiAssets(rpc, {
|
|
|
105
130
|
```javascript
|
|
106
131
|
const result = await assets.createRootAsset({
|
|
107
132
|
assetName: 'MYTOKEN',
|
|
108
|
-
quantity: 1000000, // Total supply
|
|
109
|
-
units: 2, //
|
|
133
|
+
quantity: 1000000, // Total supply, in display units (1,000,000 tokens)
|
|
134
|
+
units: 2, // Decimal precision (0–8). With units=2, fractional
|
|
135
|
+
// values down to 0.01 are allowed.
|
|
110
136
|
reissuable: true, // Allow reissuance
|
|
111
137
|
hasIpfs: true,
|
|
112
138
|
ipfsHash: 'QmYwAPJzv5CZsnA625s3Xf2nemtYgPpHdWEz79ojWnPbdG'
|
|
@@ -131,12 +157,18 @@ const result = await assets.createSubAsset({
|
|
|
131
157
|
// Requires the asset's owner token (MYTOKEN!)
|
|
132
158
|
const result = await assets.reissueAsset({
|
|
133
159
|
assetName: 'MYTOKEN',
|
|
134
|
-
quantity: 500000, // Additional amount to mint
|
|
160
|
+
quantity: 500000, // Additional amount to mint, in display units.
|
|
161
|
+
// For an asset with units=0, `quantity: 1`
|
|
162
|
+
// mints exactly 1 token (NOT 100,000,000).
|
|
135
163
|
reissuable: true, // false = lock supply permanently
|
|
136
|
-
newIpfs: 'Qm...'
|
|
164
|
+
newIpfs: 'Qm...' // Update IPFS (optional)
|
|
137
165
|
});
|
|
138
166
|
```
|
|
139
167
|
|
|
168
|
+
> **Note**: `units` cannot be passed to `reissueAsset` — the chain inherits
|
|
169
|
+
> the asset's existing precision (use `new_units` in the raw output if you
|
|
170
|
+
> ever need to change it, but this library doesn't expose that today).
|
|
171
|
+
|
|
140
172
|
### Create DEPIN Asset
|
|
141
173
|
|
|
142
174
|
```javascript
|
|
@@ -465,7 +497,7 @@ The library automatically validates that the owner token is returned in each ope
|
|
|
465
497
|
| Reissue ROOT/SUB | 200 |
|
|
466
498
|
| Reissue DEPIN | 200 |
|
|
467
499
|
| Reissue RESTRICTED | 200 |
|
|
468
|
-
| Tag/Untag address | 0
|
|
500
|
+
| Tag/Untag address | 0 (network fee only; spends 1 unit of the qualifier per address) |
|
|
469
501
|
| Freeze/Unfreeze address | 0 (network fee only) |
|
|
470
502
|
| Freeze/Unfreeze global | 0 (network fee only) |
|
|
471
503
|
|
|
@@ -476,7 +508,7 @@ The library automatically validates that the owner token is returned in each ope
|
|
|
476
508
|
The library validates client-side:
|
|
477
509
|
|
|
478
510
|
✅ Asset names (format, length, allowed characters)
|
|
479
|
-
✅ Amounts (not exceeding max supply of 21 billion)
|
|
511
|
+
✅ Amounts (not exceeding max supply of 21 billion display tokens)
|
|
480
512
|
✅ Decimals (0-8)
|
|
481
513
|
✅ IPFS hashes (valid format)
|
|
482
514
|
✅ Verifier strings (boolean logic syntax)
|
|
@@ -485,6 +517,11 @@ The library validates client-side:
|
|
|
485
517
|
✅ Owner tokens returned (prevents loss)
|
|
486
518
|
✅ Address prefixes by network
|
|
487
519
|
|
|
520
|
+
The daemon also enforces server-side that quantities respect the asset's
|
|
521
|
+
precision (`CheckAmountWithUnits` — see [Quantities and asset units](#quantities-and-asset-units)),
|
|
522
|
+
so e.g. trying to issue `0.1` of a `units=0` asset is rejected with
|
|
523
|
+
`min-qty-not-multiple-of-units` regardless of what the client sent.
|
|
524
|
+
|
|
488
525
|
## Network Configuration
|
|
489
526
|
|
|
490
527
|
```javascript
|
|
@@ -656,6 +693,8 @@ are `xna` and `xna-test`; `xna-pq` and `xna-pq-test` remain available as compati
|
|
|
656
693
|
|
|
657
694
|
Asset transactions are usually built with one or two XNA inputs plus, depending on the operation, an owner-token or qualifier UTXO. The library estimates the fee twice per build: a rough pre-estimate to size the initial XNA selection, and a final estimate once the actual UTXOs are known.
|
|
658
695
|
|
|
696
|
+
Both estimates share a single `estimatesmartfee` lookup. The fee rate is stable for the lifetime of one build, so it is fetched on the first `estimateFee` call and cached on the builder instance for the second — half as many RPC round trips as before `1.3.1`.
|
|
697
|
+
|
|
659
698
|
Both estimates use the helpers in [`src/utils/feeSizing.js`](src/utils/feeSizing.js) and distinguish PQ AuthScript inputs/outputs from legacy P2PKH ones. PQ inputs spend ~977 vbytes vs ~148 for legacy — without this distinction, transactions built from PQ addresses fall under the node's `min relay fee` and are rejected with `code -26: min relay fee not met`.
|
|
660
699
|
|
|
661
700
|
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.
|
|
@@ -4418,6 +4418,11 @@ var NeuraiAssetsBundle = (function (exports) {
|
|
|
4418
4418
|
this.ownerTokenManager = new OwnerTokenManager(rpc);
|
|
4419
4419
|
this.utxoSelector = new UTXOSelector(rpc);
|
|
4420
4420
|
this.outputOrderer = new OutputOrderer();
|
|
4421
|
+
|
|
4422
|
+
// `estimatesmartfee` is called twice per build (pre-selection guess and
|
|
4423
|
+
// post-selection recompute). The fee rate is stable for the duration of
|
|
4424
|
+
// a single build, so cache the first lookup and reuse it.
|
|
4425
|
+
this._feeRatePromise = null;
|
|
4421
4426
|
}
|
|
4422
4427
|
|
|
4423
4428
|
/**
|
|
@@ -4464,7 +4469,10 @@ var NeuraiAssetsBundle = (function (exports) {
|
|
|
4464
4469
|
* @returns {Promise<number>} Estimated fee in XNA
|
|
4465
4470
|
*/
|
|
4466
4471
|
async estimateFee(inputs, outputs) {
|
|
4467
|
-
|
|
4472
|
+
if (!this._feeRatePromise) {
|
|
4473
|
+
this._feeRatePromise = this.utxoSelector.getFeeRate();
|
|
4474
|
+
}
|
|
4475
|
+
const feeRate = await this._feeRatePromise;
|
|
4468
4476
|
return this.utxoSelector.estimateFee(inputs, outputs, feeRate);
|
|
4469
4477
|
}
|
|
4470
4478
|
|
|
@@ -4598,24 +4606,47 @@ var NeuraiAssetsBundle = (function (exports) {
|
|
|
4598
4606
|
}
|
|
4599
4607
|
|
|
4600
4608
|
/**
|
|
4601
|
-
*
|
|
4602
|
-
*
|
|
4603
|
-
*
|
|
4609
|
+
* Build the JSON `asset_quantity` value for a `createrawtransaction`
|
|
4610
|
+
* output (issue / reissue / tag change_quantity / etc.).
|
|
4611
|
+
*
|
|
4612
|
+
* The chain parses this field with `AmountFromValue()` (Bitcoin-style
|
|
4613
|
+
* decimal-XNA → 10^8 sats), then validates that the resulting CAmount
|
|
4614
|
+
* is a multiple of `10^(8 - units)` via `CheckAmountWithUnits`
|
|
4615
|
+
* (assets.cpp). So:
|
|
4616
|
+
*
|
|
4617
|
+
* - The JSON value MUST be the user-facing display amount
|
|
4618
|
+
* (e.g. "1" for one token, "1.5" for one and a half tokens).
|
|
4619
|
+
* - The lib must NOT pre-multiply by 10^8 or 10^units; the daemon
|
|
4620
|
+
* does the 10^8 scaling itself, and any extra factor here lands
|
|
4621
|
+
* duplicated and inflates the minted supply (or trips the
|
|
4622
|
+
* ParseFixedPoint `exponent >= 18` cap → "Invalid amount (3)").
|
|
4623
|
+
*
|
|
4624
|
+
* History: pre-1.2.2 multiplied by 10^units (correct only for units=0
|
|
4625
|
+
* assets, inflated everything else by 10^units). v1.2.2 changed to
|
|
4626
|
+
* always 10^8 (correct only for units=8, inflated everything else by
|
|
4627
|
+
* 10^8 — e.g. reissuing 1 token of a units=0 asset minted 100,000,000).
|
|
4628
|
+
* The right answer is to send the value untouched.
|
|
4629
|
+
*
|
|
4630
|
+
* The `units` parameter is kept for API compatibility but is unused.
|
|
4604
4631
|
*
|
|
4605
4632
|
* @param {number} amount - User-facing asset amount
|
|
4606
|
-
* @param {number} units - Asset decimal places (kept for API
|
|
4607
|
-
* @returns {number}
|
|
4633
|
+
* @param {number} units - Asset decimal places (unused; kept for API)
|
|
4634
|
+
* @returns {number} The user-facing amount, ready for the JSON output
|
|
4608
4635
|
*/
|
|
4609
4636
|
toSatoshis(amount, units) {
|
|
4610
|
-
return
|
|
4637
|
+
return amount;
|
|
4611
4638
|
}
|
|
4612
4639
|
|
|
4613
4640
|
/**
|
|
4614
|
-
* Convert
|
|
4641
|
+
* Convert a chain-side asset balance / UTXO satoshis value back to a
|
|
4642
|
+
* user-facing amount. The chain consistently encodes asset balances
|
|
4643
|
+
* in 10^8 sats (because everything goes through AmountFromValue on
|
|
4644
|
+
* the way in), so the divisor is always 10^8 — independent of the
|
|
4645
|
+
* asset's `units`.
|
|
4615
4646
|
*
|
|
4616
|
-
* @param {number} satoshis -
|
|
4617
|
-
* @param {number} units - Asset decimal places (kept for API
|
|
4618
|
-
* @returns {number}
|
|
4647
|
+
* @param {number} satoshis - Chain value in 10^8 sats
|
|
4648
|
+
* @param {number} units - Asset decimal places (unused; kept for API)
|
|
4649
|
+
* @returns {number} User-facing asset amount
|
|
4619
4650
|
*/
|
|
4620
4651
|
fromSatoshis(satoshis, units) {
|
|
4621
4652
|
return satoshis / 100000000;
|