@neuraiproject/neurai-assets 1.5.2 → 1.5.3
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/dist/NeuraiAssets.global.js +274 -107
- package/dist/NeuraiAssets.global.js.map +1 -1
- package/dist/browser.js +274 -107
- package/dist/browser.js.map +1 -1
- package/dist/index.cjs +274 -107
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +274 -107
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -5999,66 +5999,116 @@ var NeuraiAssetsBundle = (function (exports) {
|
|
|
5999
5999
|
}
|
|
6000
6000
|
|
|
6001
6001
|
/**
|
|
6002
|
-
*
|
|
6003
|
-
*
|
|
6004
|
-
* An asset output is `<destination script> OP_XNA_ASSET <pushdata payload>
|
|
6005
|
-
* OP_DROP`, so it costs the destination plus the wrapper (OP_XNA_ASSET,
|
|
6006
|
-
* the pushdata prefix and OP_DROP) plus the payload itself:
|
|
6002
|
+
* Encoders that produce the exact scriptPubKey the node will see.
|
|
6007
6003
|
*
|
|
6008
|
-
*
|
|
6004
|
+
* Sizing asset outputs from a hand-written byte formula drifted: the owner
|
|
6005
|
+
* token a reissue RETURNS is serialized as a transfer (it carries an amount),
|
|
6006
|
+
* not as the owner payload an issuance CREATES, and the null-asset-data
|
|
6007
|
+
* outputs of tag/freeze were not counted at all — those outputs are not
|
|
6008
|
+
* P2PKH-plus-payload, they replace the destination script entirely. The result
|
|
6009
|
+
* was twelve of eighteen operations budgeting below what the node charges.
|
|
6009
6010
|
*
|
|
6010
|
-
*
|
|
6011
|
-
*
|
|
6012
|
-
* above its minimum relay fee, and becomes `min relay fee not met` as soon as
|
|
6013
|
-
* it does not — which is exactly the failure this file's header warns about.
|
|
6014
|
-
*
|
|
6015
|
-
* @param {object} descriptor - Output descriptor with `assetName` and `kind`
|
|
6016
|
-
* @returns {number} Extra bytes, or 0 when the output carries no asset payload
|
|
6011
|
+
* Asking the serializer is the only way to keep this from drifting again: the
|
|
6012
|
+
* numbers below are not a model of the encoding, they ARE the encoding.
|
|
6017
6013
|
*/
|
|
6018
|
-
|
|
6019
|
-
if (!descriptor || typeof descriptor !== 'object' || !descriptor.assetName) {
|
|
6020
|
-
return 0;
|
|
6021
|
-
}
|
|
6014
|
+
const ct = requireDist_1();
|
|
6022
6015
|
|
|
6023
|
-
|
|
6024
|
-
|
|
6025
|
-
|
|
6026
|
-
|
|
6027
|
-
|
|
6028
|
-
|
|
6029
|
-
|
|
6016
|
+
/** Bytes a CompactSize length prefix occupies for `n`. */
|
|
6017
|
+
function compactSizeBytes(n) {
|
|
6018
|
+
if (n < 253) return 1;
|
|
6019
|
+
if (n <= 0xffff) return 3;
|
|
6020
|
+
if (n <= 0xffffffff) return 5;
|
|
6021
|
+
return 9;
|
|
6022
|
+
}
|
|
6030
6023
|
|
|
6031
|
-
|
|
6032
|
-
|
|
6024
|
+
/** An IPFS hash of the right LENGTH; only its size matters here. */
|
|
6025
|
+
const IPFS_PLACEHOLDER = 'Qm' + 'a'.repeat(44);
|
|
6026
|
+
|
|
6027
|
+
/**
|
|
6028
|
+
* The exact scriptPubKey for an asset-bearing output descriptor, or null when
|
|
6029
|
+
* the descriptor names no asset operation.
|
|
6030
|
+
*
|
|
6031
|
+
* Values are placeholders on purpose: every field the amount or the flag lands
|
|
6032
|
+
* in is fixed-width, so a zero costs the same bytes as the real number. The
|
|
6033
|
+
* name, the address and the presence of IPFS are the only things that move the
|
|
6034
|
+
* size, and those come from the descriptor.
|
|
6035
|
+
*
|
|
6036
|
+
* @param {object} descriptor - Output descriptor
|
|
6037
|
+
* @returns {Uint8Array|null} Encoded script, or null
|
|
6038
|
+
*/
|
|
6039
|
+
function assetOutputScript(descriptor) {
|
|
6040
|
+
const { address, assetName, kind = 'transfer' } = descriptor;
|
|
6041
|
+
const ipfs = descriptor.hasIpfs ? (descriptor.ipfsHash || IPFS_PLACEHOLDER) : undefined;
|
|
6033
6042
|
|
|
6034
6043
|
switch (kind) {
|
|
6035
6044
|
case 'owner':
|
|
6036
|
-
|
|
6037
|
-
break;
|
|
6045
|
+
return ct.encodeOwnerAssetScript(address, assetName);
|
|
6038
6046
|
case 'issue':
|
|
6039
|
-
|
|
6040
|
-
payload += 11;
|
|
6041
|
-
break;
|
|
6047
|
+
return ct.encodeNewAssetScript(address, assetName, 0n, 0, true, ipfs);
|
|
6042
6048
|
case 'reissue':
|
|
6043
|
-
|
|
6044
|
-
|
|
6045
|
-
|
|
6049
|
+
return ct.encodeReissueAssetScript(address, assetName, 0n, undefined, true, ipfs);
|
|
6050
|
+
case 'tag':
|
|
6051
|
+
return ct.encodeNullAssetTagScript(address, assetName, 'tag');
|
|
6052
|
+
case 'restriction':
|
|
6053
|
+
return ct.encodeNullAssetRestrictionScript(address, assetName, 1);
|
|
6054
|
+
case 'globalRestriction':
|
|
6055
|
+
return ct.encodeGlobalRestrictionScript(assetName, 1);
|
|
6056
|
+
case 'verifier':
|
|
6057
|
+
return ct.encodeVerifierStringScript(descriptor.verifierString || '');
|
|
6058
|
+
case 'transfer':
|
|
6059
|
+
return ct.encodeAssetTransferScript(address, assetName, 0n);
|
|
6046
6060
|
default:
|
|
6047
|
-
|
|
6048
|
-
payload += 8;
|
|
6049
|
-
break;
|
|
6061
|
+
return null;
|
|
6050
6062
|
}
|
|
6063
|
+
}
|
|
6051
6064
|
|
|
6052
|
-
|
|
6053
|
-
|
|
6054
|
-
|
|
6065
|
+
/**
|
|
6066
|
+
* Kinds whose script REPLACES the destination rather than extending it.
|
|
6067
|
+
*
|
|
6068
|
+
* A tag, a restriction or a verifier string is not "a payment with a payload
|
|
6069
|
+
* bolted on": there is no P2PKH to pay. Adding a destination's bytes to these
|
|
6070
|
+
* over-counts; treating them as plain destinations, which is what the builders
|
|
6071
|
+
* used to do, under-counts by far more.
|
|
6072
|
+
*/
|
|
6073
|
+
const STANDALONE_KINDS = new Set(['tag', 'restriction', 'globalRestriction', 'verifier']);
|
|
6055
6074
|
|
|
6056
|
-
|
|
6057
|
-
|
|
6058
|
-
|
|
6059
|
-
|
|
6075
|
+
/**
|
|
6076
|
+
* Fallback used only when the encoders cannot express a descriptor — an
|
|
6077
|
+
* address family they do not accept, say. Keeps the previous behaviour rather
|
|
6078
|
+
* than throwing in the middle of a fee estimate.
|
|
6079
|
+
*/
|
|
6080
|
+
function assetPayloadBytesApprox(descriptor) {
|
|
6081
|
+
const nameLength = String(descriptor.assetName || '').length;
|
|
6082
|
+
const kind = descriptor.kind || 'transfer';
|
|
6083
|
+
let payload = 5 + nameLength;
|
|
6084
|
+
if (kind === 'issue') payload += 11;
|
|
6085
|
+
else if (kind === 'reissue') payload += 10;
|
|
6086
|
+
else if (kind !== 'owner') payload += 8;
|
|
6087
|
+
if (descriptor.hasIpfs) payload += 34;
|
|
6088
|
+
return 1 + (payload > 75 ? 2 : 1) + payload + 1;
|
|
6089
|
+
}
|
|
6060
6090
|
|
|
6061
|
-
|
|
6091
|
+
/**
|
|
6092
|
+
* Bytes an asset payload adds on top of a plain destination output.
|
|
6093
|
+
*
|
|
6094
|
+
* Kept for callers that only want the delta. Standalone kinds have no
|
|
6095
|
+
* destination to add to, so this is not meaningful for them.
|
|
6096
|
+
*
|
|
6097
|
+
* @param {object} descriptor - Output descriptor with `assetName` and `kind`
|
|
6098
|
+
* @returns {number} Extra bytes, or 0 when the output carries no asset payload
|
|
6099
|
+
*/
|
|
6100
|
+
function assetPayloadBytes(descriptor) {
|
|
6101
|
+
if (!descriptor || typeof descriptor !== 'object' || !descriptor.assetName) {
|
|
6102
|
+
return 0;
|
|
6103
|
+
}
|
|
6104
|
+
try {
|
|
6105
|
+
const script = assetOutputScript(descriptor);
|
|
6106
|
+
if (!script) return 0;
|
|
6107
|
+
const base = isPQAddress(descriptor.address) ? 34 : 25;
|
|
6108
|
+
return script.length - base;
|
|
6109
|
+
} catch {
|
|
6110
|
+
return assetPayloadBytesApprox(descriptor);
|
|
6111
|
+
}
|
|
6062
6112
|
}
|
|
6063
6113
|
|
|
6064
6114
|
/**
|
|
@@ -6072,10 +6122,26 @@ var NeuraiAssetsBundle = (function (exports) {
|
|
|
6072
6122
|
* @returns {number} Estimated bytes
|
|
6073
6123
|
*/
|
|
6074
6124
|
function estimateOutputBytes(target) {
|
|
6125
|
+
if (typeof target !== 'string' && target && (target.assetName || target.kind === 'verifier')) {
|
|
6126
|
+
try {
|
|
6127
|
+
const script = assetOutputScript(target);
|
|
6128
|
+
if (script) {
|
|
6129
|
+
// value(8) + CompactSize(scriptLen) + script
|
|
6130
|
+
return 8 + compactSizeBytes(script.length) + script.length;
|
|
6131
|
+
}
|
|
6132
|
+
} catch {
|
|
6133
|
+
// fall through to the approximation
|
|
6134
|
+
}
|
|
6135
|
+
if (STANDALONE_KINDS.has(target.kind)) {
|
|
6136
|
+
return VBYTES.legacyOutputBytes;
|
|
6137
|
+
}
|
|
6138
|
+
const base = isPQAddress(target.address) ? VBYTES.pqOutputBytes : VBYTES.legacyOutputBytes;
|
|
6139
|
+
return base + assetPayloadBytesApprox(target);
|
|
6140
|
+
}
|
|
6141
|
+
|
|
6075
6142
|
const address =
|
|
6076
6143
|
typeof target === 'string' ? target : (target && target.address) || '';
|
|
6077
|
-
|
|
6078
|
-
return base + assetPayloadBytes(typeof target === 'string' ? null : target);
|
|
6144
|
+
return isPQAddress(address) ? VBYTES.pqOutputBytes : VBYTES.legacyOutputBytes;
|
|
6079
6145
|
}
|
|
6080
6146
|
|
|
6081
6147
|
/**
|
|
@@ -6105,6 +6171,8 @@ var NeuraiAssetsBundle = (function (exports) {
|
|
|
6105
6171
|
|
|
6106
6172
|
feeSizing = {
|
|
6107
6173
|
VBYTES,
|
|
6174
|
+
compactSizeBytes,
|
|
6175
|
+
assetOutputScript,
|
|
6108
6176
|
isPQAddress,
|
|
6109
6177
|
isPQScript,
|
|
6110
6178
|
estimateInputVbytes,
|
|
@@ -9083,8 +9151,24 @@ var NeuraiAssetsBundle = (function (exports) {
|
|
|
9083
9151
|
throw new Error('Cannot parse parent asset from SUB asset name');
|
|
9084
9152
|
}
|
|
9085
9153
|
|
|
9086
|
-
//
|
|
9087
|
-
|
|
9154
|
+
// El token owner no depende de nada de lo que sigue: pedirlo a la vez que
|
|
9155
|
+
// las lecturas del asset ahorra una ida y vuelta completa. Se ESPERA en su
|
|
9156
|
+
// sitio de siempre, así que el orden de los errores no cambia.
|
|
9157
|
+
const ownerTokenName = AssetNameParser.getOwnerTokenName(parentAssetName);
|
|
9158
|
+
const addresses = await this._getAddresses();
|
|
9159
|
+
const ownerTokenLookup = this.ownerTokenManager.findOwnerTokenUTXO(
|
|
9160
|
+
ownerTokenName,
|
|
9161
|
+
addresses
|
|
9162
|
+
);
|
|
9163
|
+
ownerTokenLookup.catch(() => {});
|
|
9164
|
+
|
|
9165
|
+
// 3-4. Existencia del padre y del sub: independientes entre sí, así que
|
|
9166
|
+
// se preguntan a la vez. Se comprueban en el mismo orden de antes, luego
|
|
9167
|
+
// «no existe el padre» sigue ganando a «el sub ya existe».
|
|
9168
|
+
const [parentExists, subExists] = await Promise.all([
|
|
9169
|
+
this.assetExists(parentAssetName),
|
|
9170
|
+
this.assetExists(assetName)
|
|
9171
|
+
]);
|
|
9088
9172
|
if (!parentExists) {
|
|
9089
9173
|
throw new ParentAssetNotFoundError(
|
|
9090
9174
|
`Parent asset ${parentAssetName} does not exist. You must create the ROOT asset first.`,
|
|
@@ -9092,8 +9176,6 @@ var NeuraiAssetsBundle = (function (exports) {
|
|
|
9092
9176
|
);
|
|
9093
9177
|
}
|
|
9094
9178
|
|
|
9095
|
-
// 4. Check if SUB asset already exists
|
|
9096
|
-
const subExists = await this.assetExists(assetName);
|
|
9097
9179
|
if (subExists) {
|
|
9098
9180
|
throw new AssetExistsError(
|
|
9099
9181
|
`Asset ${assetName} already exists on the blockchain`,
|
|
@@ -9102,18 +9184,13 @@ var NeuraiAssetsBundle = (function (exports) {
|
|
|
9102
9184
|
}
|
|
9103
9185
|
|
|
9104
9186
|
// 5. Get addresses
|
|
9105
|
-
const addresses = await this._getAddresses();
|
|
9106
9187
|
const toAddress = await this.getToAddress();
|
|
9107
9188
|
const changeAddress = await this.getChangeAddress();
|
|
9108
9189
|
|
|
9109
9190
|
// 6. Find parent's owner token (CRITICAL: must have this)
|
|
9110
|
-
const ownerTokenName = AssetNameParser.getOwnerTokenName(parentAssetName);
|
|
9111
9191
|
let ownerTokenUTXO;
|
|
9112
9192
|
try {
|
|
9113
|
-
ownerTokenUTXO = await
|
|
9114
|
-
ownerTokenName,
|
|
9115
|
-
addresses
|
|
9116
|
-
);
|
|
9193
|
+
ownerTokenUTXO = await ownerTokenLookup;
|
|
9117
9194
|
} catch (error) {
|
|
9118
9195
|
if (error instanceof OwnerTokenNotFoundError) {
|
|
9119
9196
|
throw new OwnerTokenNotFoundError(
|
|
@@ -9134,7 +9211,11 @@ var NeuraiAssetsBundle = (function (exports) {
|
|
|
9134
9211
|
const outputAddresses = [
|
|
9135
9212
|
burnInfo.address,
|
|
9136
9213
|
changeAddress,
|
|
9137
|
-
|
|
9214
|
+
// El token owner que la operación GASTA y devuelve viaja como
|
|
9215
|
+
// transferencia (lleva importe), no con el payload 'owner', que sólo
|
|
9216
|
+
// describe el token que una emisión CREA. Estimarlo como 'owner' dejaba
|
|
9217
|
+
// la transacción 8 bytes por debajo de lo que el nodo cobra.
|
|
9218
|
+
{ address: changeAddress, assetName: ownerTokenName },
|
|
9138
9219
|
{ address: toAddress, assetName, kind: 'issue', hasIpfs },
|
|
9139
9220
|
{ address: changeAddress, assetName: `${assetName}!`, kind: 'owner' },
|
|
9140
9221
|
];
|
|
@@ -9518,6 +9599,19 @@ var NeuraiAssetsBundle = (function (exports) {
|
|
|
9518
9599
|
newIpfs
|
|
9519
9600
|
} = this.params;
|
|
9520
9601
|
|
|
9602
|
+
// El token owner no depende de nada de lo que sigue: pedirlo a la vez que
|
|
9603
|
+
// los datos del asset ahorra una ida y vuelta completa. Se ESPERA en su
|
|
9604
|
+
// sitio de siempre (paso 6), así que el orden de los errores no cambia:
|
|
9605
|
+
// «el asset no existe» y «no es reemitible» se siguen lanzando antes que
|
|
9606
|
+
// «no tienes el token owner».
|
|
9607
|
+
const ownerTokenName = AssetNameParser.getOwnerTokenName(assetName);
|
|
9608
|
+
const addresses = await this._getAddresses();
|
|
9609
|
+
const ownerTokenLookup = this.ownerTokenManager.findOwnerTokenUTXO(
|
|
9610
|
+
ownerTokenName,
|
|
9611
|
+
addresses
|
|
9612
|
+
);
|
|
9613
|
+
ownerTokenLookup.catch(() => {});
|
|
9614
|
+
|
|
9521
9615
|
// 2. Get asset data to verify it exists and is reissuable
|
|
9522
9616
|
const assetData = await this.getAssetData(assetName);
|
|
9523
9617
|
if (!assetData) {
|
|
@@ -9553,19 +9647,14 @@ var NeuraiAssetsBundle = (function (exports) {
|
|
|
9553
9647
|
}
|
|
9554
9648
|
|
|
9555
9649
|
// 5. Get addresses
|
|
9556
|
-
const addresses = await this._getAddresses();
|
|
9557
9650
|
const toAddress = await this.getToAddress();
|
|
9558
9651
|
const changeAddress = await this.getChangeAddress();
|
|
9559
9652
|
const isDepinAsset = AssetNameParser.isDepin(assetName);
|
|
9560
9653
|
|
|
9561
9654
|
// 6. Find owner token (CRITICAL: must have this)
|
|
9562
|
-
const ownerTokenName = AssetNameParser.getOwnerTokenName(assetName);
|
|
9563
9655
|
let ownerTokenUTXO;
|
|
9564
9656
|
try {
|
|
9565
|
-
ownerTokenUTXO = await
|
|
9566
|
-
ownerTokenName,
|
|
9567
|
-
addresses
|
|
9568
|
-
);
|
|
9657
|
+
ownerTokenUTXO = await ownerTokenLookup;
|
|
9569
9658
|
} catch (error) {
|
|
9570
9659
|
if (error instanceof OwnerTokenNotFoundError) {
|
|
9571
9660
|
throw new OwnerTokenNotFoundError(
|
|
@@ -9586,7 +9675,11 @@ var NeuraiAssetsBundle = (function (exports) {
|
|
|
9586
9675
|
const outputAddresses = [
|
|
9587
9676
|
burnInfo.address,
|
|
9588
9677
|
changeAddress,
|
|
9589
|
-
|
|
9678
|
+
// El token owner que la operación GASTA y devuelve viaja como
|
|
9679
|
+
// transferencia (lleva importe), no con el payload 'owner', que sólo
|
|
9680
|
+
// describe el token que una emisión CREA. Estimarlo como 'owner' dejaba
|
|
9681
|
+
// la transacción 8 bytes por debajo de lo que el nodo cobra.
|
|
9682
|
+
{ address: changeAddress, assetName: ownerTokenName },
|
|
9590
9683
|
{ address: toAddress, assetName, kind: 'reissue', hasIpfs: Boolean(newIpfs) },
|
|
9591
9684
|
];
|
|
9592
9685
|
// Fund the XNA side. The owner-token input counts towards the size
|
|
@@ -9854,7 +9947,8 @@ var NeuraiAssetsBundle = (function (exports) {
|
|
|
9854
9947
|
...recipients.map(r => ({ address: r.address, assetName })),
|
|
9855
9948
|
{ address: changeAddress, assetName }, // asset change (harmless over-count if absent)
|
|
9856
9949
|
...(isDepin
|
|
9857
|
-
|
|
9950
|
+
// Escolta: se gasta y se devuelve, luego es una transferencia.
|
|
9951
|
+
? [{ address: changeAddress, assetName: ownerTokenName }]
|
|
9858
9952
|
: []),
|
|
9859
9953
|
];
|
|
9860
9954
|
|
|
@@ -10138,6 +10232,17 @@ var NeuraiAssetsBundle = (function (exports) {
|
|
|
10138
10232
|
ipfsHashes = []
|
|
10139
10233
|
} = this.params;
|
|
10140
10234
|
|
|
10235
|
+
// El token owner no depende de nada de lo que sigue: pedirlo a la vez que
|
|
10236
|
+
// las lecturas del asset ahorra una ida y vuelta completa. Se ESPERA en su
|
|
10237
|
+
// sitio de siempre, así que el orden de los errores no cambia.
|
|
10238
|
+
const ownerTokenName = AssetNameParser.getOwnerTokenName(rootName);
|
|
10239
|
+
const addresses = await this._getAddresses();
|
|
10240
|
+
const ownerTokenLookup = this.ownerTokenManager.findOwnerTokenUTXO(
|
|
10241
|
+
ownerTokenName,
|
|
10242
|
+
addresses
|
|
10243
|
+
);
|
|
10244
|
+
ownerTokenLookup.catch(() => {});
|
|
10245
|
+
|
|
10141
10246
|
// 2. Check if parent asset exists
|
|
10142
10247
|
const parentExists = await this.assetExists(rootName);
|
|
10143
10248
|
if (!parentExists) {
|
|
@@ -10147,31 +10252,31 @@ var NeuraiAssetsBundle = (function (exports) {
|
|
|
10147
10252
|
);
|
|
10148
10253
|
}
|
|
10149
10254
|
|
|
10150
|
-
// 3. Check if any of the unique assets already exist
|
|
10151
|
-
|
|
10152
|
-
|
|
10153
|
-
|
|
10154
|
-
|
|
10155
|
-
|
|
10156
|
-
|
|
10157
|
-
|
|
10158
|
-
|
|
10159
|
-
|
|
10255
|
+
// 3. Check if any of the unique assets already exist.
|
|
10256
|
+
// En fila, emitir diez únicos costaba diez idas y vueltas antes de
|
|
10257
|
+
// empezar a construir. Ninguna depende de la anterior. El resultado se
|
|
10258
|
+
// recorre en orden, así que el error sigue nombrando el primer nombre
|
|
10259
|
+
// repetido de la lista, no el que el nodo conteste primero.
|
|
10260
|
+
const uniqueNames = assetTags.map(tag => `${rootName}#${tag}`);
|
|
10261
|
+
const uniqueExists = await Promise.all(
|
|
10262
|
+
uniqueNames.map(fullName => this.assetExists(fullName))
|
|
10263
|
+
);
|
|
10264
|
+
const takenIndex = uniqueExists.findIndex(Boolean);
|
|
10265
|
+
if (takenIndex !== -1) {
|
|
10266
|
+
throw new AssetExistsError(
|
|
10267
|
+
`Unique asset ${uniqueNames[takenIndex]} already exists on the blockchain`,
|
|
10268
|
+
uniqueNames[takenIndex]
|
|
10269
|
+
);
|
|
10160
10270
|
}
|
|
10161
10271
|
|
|
10162
10272
|
// 4. Get addresses
|
|
10163
|
-
const addresses = await this._getAddresses();
|
|
10164
10273
|
const toAddress = await this.getToAddress();
|
|
10165
10274
|
const changeAddress = await this.getChangeAddress();
|
|
10166
10275
|
|
|
10167
10276
|
// 5. Find parent's owner token (CRITICAL: must have this)
|
|
10168
|
-
const ownerTokenName = AssetNameParser.getOwnerTokenName(rootName);
|
|
10169
10277
|
let ownerTokenUTXO;
|
|
10170
10278
|
try {
|
|
10171
|
-
ownerTokenUTXO = await
|
|
10172
|
-
ownerTokenName,
|
|
10173
|
-
addresses
|
|
10174
|
-
);
|
|
10279
|
+
ownerTokenUTXO = await ownerTokenLookup;
|
|
10175
10280
|
} catch (error) {
|
|
10176
10281
|
if (error instanceof OwnerTokenNotFoundError) {
|
|
10177
10282
|
throw new OwnerTokenNotFoundError(
|
|
@@ -10193,7 +10298,11 @@ var NeuraiAssetsBundle = (function (exports) {
|
|
|
10193
10298
|
const outputAddresses = [
|
|
10194
10299
|
burnInfo.address,
|
|
10195
10300
|
changeAddress,
|
|
10196
|
-
|
|
10301
|
+
// El token owner que la operación GASTA y devuelve viaja como
|
|
10302
|
+
// transferencia (lleva importe), no con el payload 'owner', que sólo
|
|
10303
|
+
// describe el token que una emisión CREA. Estimarlo como 'owner' dejaba
|
|
10304
|
+
// la transacción 8 bytes por debajo de lo que el nodo cobra.
|
|
10305
|
+
{ address: changeAddress, assetName: ownerTokenName },
|
|
10197
10306
|
...assetTags.map(tag => ({
|
|
10198
10307
|
address: toAddress,
|
|
10199
10308
|
assetName: `${rootName}#${tag}`,
|
|
@@ -10677,6 +10786,17 @@ var NeuraiAssetsBundle = (function (exports) {
|
|
|
10677
10786
|
ipfsHash = ''
|
|
10678
10787
|
} = this.params;
|
|
10679
10788
|
|
|
10789
|
+
// El token owner no depende de nada de lo que sigue: pedirlo a la vez que
|
|
10790
|
+
// las lecturas del asset ahorra una ida y vuelta completa. Se ESPERA en su
|
|
10791
|
+
// sitio de siempre, así que el orden de los errores no cambia.
|
|
10792
|
+
const ownerTokenName = AssetNameParser.getOwnerTokenName(assetName);
|
|
10793
|
+
const addresses = await this._getAddresses();
|
|
10794
|
+
const ownerTokenLookup = this.ownerTokenManager.findOwnerTokenUTXO(
|
|
10795
|
+
ownerTokenName,
|
|
10796
|
+
addresses
|
|
10797
|
+
);
|
|
10798
|
+
ownerTokenLookup.catch(() => {});
|
|
10799
|
+
|
|
10680
10800
|
// 2. Check if asset already exists
|
|
10681
10801
|
const exists = await this.assetExists(assetName);
|
|
10682
10802
|
if (exists) {
|
|
@@ -10693,18 +10813,13 @@ var NeuraiAssetsBundle = (function (exports) {
|
|
|
10693
10813
|
const burnInfo = this.burnManager.getIssueRestrictedBurn();
|
|
10694
10814
|
|
|
10695
10815
|
// 5. Get addresses
|
|
10696
|
-
const addresses = await this._getAddresses();
|
|
10697
10816
|
const toAddress = await this.getToAddress();
|
|
10698
10817
|
const changeAddress = await this.getChangeAddress();
|
|
10699
10818
|
|
|
10700
10819
|
// 6. Find owner token UTXO (CRITICAL: node requires it as input)
|
|
10701
|
-
const ownerTokenName = AssetNameParser.getOwnerTokenName(assetName);
|
|
10702
10820
|
let ownerTokenUTXO;
|
|
10703
10821
|
try {
|
|
10704
|
-
ownerTokenUTXO = await
|
|
10705
|
-
ownerTokenName,
|
|
10706
|
-
addresses
|
|
10707
|
-
);
|
|
10822
|
+
ownerTokenUTXO = await ownerTokenLookup;
|
|
10708
10823
|
} catch (error) {
|
|
10709
10824
|
if (error instanceof OwnerTokenNotFoundError) {
|
|
10710
10825
|
throw new OwnerTokenNotFoundError(
|
|
@@ -10716,11 +10831,16 @@ var NeuraiAssetsBundle = (function (exports) {
|
|
|
10716
10831
|
}
|
|
10717
10832
|
|
|
10718
10833
|
// 7. Estimate fee (+1 for owner token input)
|
|
10834
|
+
// Las salidas de asset deben describirse como lo que el nodo serializa.
|
|
10835
|
+
// Como direcciones desnudas se contaban 34 bytes por salida y el payload
|
|
10836
|
+
// entero quedaba sin pagar; las de datos nulos (tag, congelación,
|
|
10837
|
+
// verificador) ni siquiera llevan destino: su script SUSTITUYE al P2PKH.
|
|
10719
10838
|
const outputAddresses = [
|
|
10720
10839
|
burnInfo.address,
|
|
10721
10840
|
changeAddress,
|
|
10722
|
-
|
|
10723
|
-
|
|
10841
|
+
{ kind: 'verifier', assetName, verifierString },
|
|
10842
|
+
{ address: changeAddress, assetName: ownerTokenName },
|
|
10843
|
+
{ address: toAddress, assetName, kind: 'issue', hasIpfs: Boolean(this.params.ipfsHash) },
|
|
10724
10844
|
];
|
|
10725
10845
|
// Fund the XNA side. The owner-token input counts towards the size
|
|
10726
10846
|
// estimate from the first round and is excluded from XNA selection.
|
|
@@ -10930,6 +11050,17 @@ var NeuraiAssetsBundle = (function (exports) {
|
|
|
10930
11050
|
newIpfs
|
|
10931
11051
|
} = this.params;
|
|
10932
11052
|
|
|
11053
|
+
// El token owner no depende de nada de lo que sigue: pedirlo a la vez que
|
|
11054
|
+
// las lecturas del asset ahorra una ida y vuelta completa. Se ESPERA en su
|
|
11055
|
+
// sitio de siempre, así que el orden de los errores no cambia.
|
|
11056
|
+
const ownerTokenName = AssetNameParser.getOwnerTokenName(assetName);
|
|
11057
|
+
const addresses = await this._getAddresses();
|
|
11058
|
+
const ownerTokenLookup = this.ownerTokenManager.findOwnerTokenUTXO(
|
|
11059
|
+
ownerTokenName,
|
|
11060
|
+
addresses
|
|
11061
|
+
);
|
|
11062
|
+
ownerTokenLookup.catch(() => {});
|
|
11063
|
+
|
|
10933
11064
|
// 2. Get asset data to verify it exists and is reissuable
|
|
10934
11065
|
const assetData = await this.getAssetData(assetName);
|
|
10935
11066
|
if (!assetData) {
|
|
@@ -10965,18 +11096,13 @@ var NeuraiAssetsBundle = (function (exports) {
|
|
|
10965
11096
|
}
|
|
10966
11097
|
|
|
10967
11098
|
// 5. Get addresses
|
|
10968
|
-
const addresses = await this._getAddresses();
|
|
10969
11099
|
const toAddress = await this.getToAddress();
|
|
10970
11100
|
const changeAddress = await this.getChangeAddress();
|
|
10971
11101
|
|
|
10972
11102
|
// 6. Find owner token (CRITICAL: must have this)
|
|
10973
|
-
const ownerTokenName = AssetNameParser.getOwnerTokenName(assetName);
|
|
10974
11103
|
let ownerTokenUTXO;
|
|
10975
11104
|
try {
|
|
10976
|
-
ownerTokenUTXO = await
|
|
10977
|
-
ownerTokenName,
|
|
10978
|
-
addresses
|
|
10979
|
-
);
|
|
11105
|
+
ownerTokenUTXO = await ownerTokenLookup;
|
|
10980
11106
|
} catch (error) {
|
|
10981
11107
|
if (error instanceof OwnerTokenNotFoundError) {
|
|
10982
11108
|
throw new OwnerTokenNotFoundError(
|
|
@@ -10992,11 +11118,18 @@ var NeuraiAssetsBundle = (function (exports) {
|
|
|
10992
11118
|
const burnInfo = this.burnManager.getReissueBurn();
|
|
10993
11119
|
|
|
10994
11120
|
// 8. Estimate fee
|
|
11121
|
+
// Las salidas de asset deben describirse como lo que el nodo serializa.
|
|
11122
|
+
// Como direcciones desnudas se contaban 34 bytes por salida y el payload
|
|
11123
|
+
// entero quedaba sin pagar; las de datos nulos (tag, congelación,
|
|
11124
|
+
// verificador) ni siquiera llevan destino: su script SUSTITUYE al P2PKH.
|
|
10995
11125
|
const outputAddresses = [
|
|
10996
11126
|
burnInfo.address,
|
|
10997
11127
|
changeAddress,
|
|
10998
|
-
|
|
10999
|
-
|
|
11128
|
+
...(changeVerifier && newVerifier
|
|
11129
|
+
? [{ kind: 'verifier', assetName, verifierString: newVerifier }]
|
|
11130
|
+
: []),
|
|
11131
|
+
{ address: changeAddress, assetName: ownerTokenName },
|
|
11132
|
+
{ address: toAddress, assetName, kind: 'reissue', hasIpfs: Boolean(this.params.ipfsHash) },
|
|
11000
11133
|
];
|
|
11001
11134
|
// Fund the XNA side. The owner-token input counts towards the size
|
|
11002
11135
|
// estimate from the first round and is excluded from XNA selection.
|
|
@@ -11256,7 +11389,20 @@ var NeuraiAssetsBundle = (function (exports) {
|
|
|
11256
11389
|
|
|
11257
11390
|
// 6. Estimate fee
|
|
11258
11391
|
// Outputs: burn + XNA change + tag/untag operation (sent to changeAddress)
|
|
11259
|
-
|
|
11392
|
+
// Las salidas de asset deben describirse como lo que el nodo serializa.
|
|
11393
|
+
// Como direcciones desnudas se contaban 34 bytes por salida y el payload
|
|
11394
|
+
// entero quedaba sin pagar; las de datos nulos (tag, congelación,
|
|
11395
|
+
// verificador) ni siquiera llevan destino: su script SUSTITUYE al P2PKH.
|
|
11396
|
+
const outputAddresses = [
|
|
11397
|
+
burnInfo.address,
|
|
11398
|
+
changeAddress,
|
|
11399
|
+
// El nodo devuelve el resto del qualifier a la dirección de cambio.
|
|
11400
|
+
{ address: changeAddress, assetName: qualifierName },
|
|
11401
|
+
// Una salida de datos nulos por dirección etiquetada.
|
|
11402
|
+
...targetAddresses.map(target => ({
|
|
11403
|
+
address: target, assetName: qualifierName, kind: 'tag'
|
|
11404
|
+
}))
|
|
11405
|
+
];
|
|
11260
11406
|
// 7-11. Fund the XNA side. The qualifier inputs count towards the size
|
|
11261
11407
|
// estimate from the first round and are excluded from XNA selection.
|
|
11262
11408
|
const burnSats = this.xnaAmountToSats(burnInfo.amount, { label: 'burn amount' });
|
|
@@ -11470,6 +11616,17 @@ var NeuraiAssetsBundle = (function (exports) {
|
|
|
11470
11616
|
|
|
11471
11617
|
const { assetName } = this.params;
|
|
11472
11618
|
|
|
11619
|
+
// El token owner no depende de nada de lo que sigue: pedirlo a la vez que
|
|
11620
|
+
// las lecturas del asset ahorra una ida y vuelta completa. Se ESPERA en su
|
|
11621
|
+
// sitio de siempre, así que el orden de los errores no cambia.
|
|
11622
|
+
const ownerTokenName = AssetNameParser.getOwnerTokenName(assetName);
|
|
11623
|
+
const addresses = await this._getAddresses();
|
|
11624
|
+
const ownerTokenLookup = this.ownerTokenManager.findOwnerTokenUTXO(
|
|
11625
|
+
ownerTokenName,
|
|
11626
|
+
addresses
|
|
11627
|
+
);
|
|
11628
|
+
ownerTokenLookup.catch(() => {});
|
|
11629
|
+
|
|
11473
11630
|
// 2. Check if asset exists and is restricted
|
|
11474
11631
|
const assetData = await this.getAssetData(assetName);
|
|
11475
11632
|
if (!assetData) {
|
|
@@ -11480,17 +11637,12 @@ var NeuraiAssetsBundle = (function (exports) {
|
|
|
11480
11637
|
}
|
|
11481
11638
|
|
|
11482
11639
|
// 3. Get wallet addresses
|
|
11483
|
-
const addresses = await this._getAddresses();
|
|
11484
11640
|
const changeAddress = await this.getChangeAddress();
|
|
11485
11641
|
|
|
11486
11642
|
// 4. Find owner token (CRITICAL: must have this)
|
|
11487
|
-
const ownerTokenName = AssetNameParser.getOwnerTokenName(assetName);
|
|
11488
11643
|
let ownerTokenUTXO;
|
|
11489
11644
|
try {
|
|
11490
|
-
ownerTokenUTXO = await
|
|
11491
|
-
ownerTokenName,
|
|
11492
|
-
addresses
|
|
11493
|
-
);
|
|
11645
|
+
ownerTokenUTXO = await ownerTokenLookup;
|
|
11494
11646
|
} catch (error) {
|
|
11495
11647
|
if (error instanceof OwnerTokenNotFoundError) {
|
|
11496
11648
|
throw new OwnerTokenNotFoundError(
|
|
@@ -11506,7 +11658,22 @@ var NeuraiAssetsBundle = (function (exports) {
|
|
|
11506
11658
|
|
|
11507
11659
|
// 6. Estimate fee
|
|
11508
11660
|
// Outputs: XNA change + freeze/unfreeze operation (sent to changeAddress)
|
|
11509
|
-
|
|
11661
|
+
// Las salidas de asset deben describirse como lo que el nodo serializa.
|
|
11662
|
+
// Como direcciones desnudas se contaban 34 bytes por salida y el payload
|
|
11663
|
+
// entero quedaba sin pagar; las de datos nulos (tag, congelación,
|
|
11664
|
+
// verificador) ni siquiera llevan destino: su script SUSTITUYE al P2PKH.
|
|
11665
|
+
const isGlobal = operationType === 'FREEZE_ASSET' || operationType === 'UNFREEZE_ASSET';
|
|
11666
|
+
const frozenAddresses = isGlobal ? [] : (this.params.addresses || []);
|
|
11667
|
+
const outputAddresses = [
|
|
11668
|
+
changeAddress,
|
|
11669
|
+
// El token owner se gasta y se devuelve: transferencia.
|
|
11670
|
+
{ address: changeAddress, assetName: ownerTokenName },
|
|
11671
|
+
...(isGlobal
|
|
11672
|
+
? [{ assetName, kind: 'globalRestriction' }]
|
|
11673
|
+
: frozenAddresses.map(target => ({
|
|
11674
|
+
address: target, assetName, kind: 'restriction'
|
|
11675
|
+
})))
|
|
11676
|
+
];
|
|
11510
11677
|
// 7-10. Fund the XNA side (fee only, this operation does not burn). The
|
|
11511
11678
|
// owner-token input counts towards the size estimate from the first
|
|
11512
11679
|
// round and is excluded from XNA selection.
|