@chainvue/verus-sdk 0.7.0 → 0.8.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/dist/bundle.js +366 -255
- package/dist/core/brands.d.ts +31 -0
- package/dist/core/brands.d.ts.map +1 -0
- package/dist/core/brands.js +82 -0
- package/dist/core/brands.js.map +1 -0
- package/dist/currency/index.d.ts.map +1 -1
- package/dist/currency/index.js +6 -1
- package/dist/currency/index.js.map +1 -1
- package/dist/identity/index.d.ts +30 -13
- package/dist/identity/index.d.ts.map +1 -1
- package/dist/identity/index.js +102 -51
- package/dist/identity/index.js.map +1 -1
- package/dist/transfer/index.d.ts.map +1 -1
- package/dist/transfer/index.js +3 -2
- package/dist/transfer/index.js.map +1 -1
- package/dist/types/index.d.ts +6 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/utxo/index.d.ts +14 -0
- package/dist/utxo/index.d.ts.map +1 -1
- package/dist/utxo/index.js +41 -0
- package/dist/utxo/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
declare const brand: unique symbol;
|
|
2
|
+
type Brand<T, B extends string> = T & {
|
|
3
|
+
readonly [brand]: B;
|
|
4
|
+
};
|
|
5
|
+
/** Transparent R-address (version 0x3c, pubkey-hash). */
|
|
6
|
+
export type RAddress = Brand<string, 'RAddress'>;
|
|
7
|
+
/** Identity i-address (version 0x66) — identities AND currency ids (offline-indistinguishable). */
|
|
8
|
+
export type IAddress = Brand<string, 'IAddress'>;
|
|
9
|
+
/** P2SH address (version 0x55). */
|
|
10
|
+
export type P2shAddress = Brand<string, 'P2shAddress'>;
|
|
11
|
+
/** Any parsed base58check address of a known kind. */
|
|
12
|
+
export type Address = RAddress | IAddress | P2shAddress;
|
|
13
|
+
/**
|
|
14
|
+
* Documentation alias: a currency id IS an i-address. There is deliberately no
|
|
15
|
+
* separate `CurrencyId` brand — an offline SDK cannot tell an i-address naming a
|
|
16
|
+
* currency from one naming an identity, so a distinct brand would be a lie the
|
|
17
|
+
* type system can't check and would force unsafe casts.
|
|
18
|
+
*/
|
|
19
|
+
export type CurrencyId = IAddress;
|
|
20
|
+
/** Parse a transparent R-address; throws InvalidAddressError otherwise. */
|
|
21
|
+
export declare function parseRAddress(s: string, label?: string): RAddress;
|
|
22
|
+
/** Parse an identity/currency i-address; throws InvalidAddressError otherwise. */
|
|
23
|
+
export declare function parseIAddress(s: string, label?: string): IAddress;
|
|
24
|
+
/** Parse any supported address into the discriminated union; throws otherwise. */
|
|
25
|
+
export declare function parseAddress(s: string, label?: string): Address;
|
|
26
|
+
/** Narrow an Address to an i-address by its version byte (replaces startsWith('i')). */
|
|
27
|
+
export declare function isIAddress(a: Address): a is IAddress;
|
|
28
|
+
/** Narrow an Address to an R-address by its version byte. */
|
|
29
|
+
export declare function isRAddress(a: Address): a is RAddress;
|
|
30
|
+
export {};
|
|
31
|
+
//# sourceMappingURL=brands.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"brands.d.ts","sourceRoot":"","sources":["../../src/core/brands.ts"],"names":[],"mappings":"AAmBA,OAAO,CAAC,MAAM,KAAK,EAAE,OAAO,MAAM,CAAC;AACnC,KAAK,KAAK,CAAC,CAAC,EAAE,CAAC,SAAS,MAAM,IAAI,CAAC,GAAG;IAAE,QAAQ,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,CAAA;CAAE,CAAC;AAE9D,yDAAyD;AACzD,MAAM,MAAM,QAAQ,GAAG,KAAK,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;AACjD,mGAAmG;AACnG,MAAM,MAAM,QAAQ,GAAG,KAAK,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;AACjD,mCAAmC;AACnC,MAAM,MAAM,WAAW,GAAG,KAAK,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;AACvD,sDAAsD;AACtD,MAAM,MAAM,OAAO,GAAG,QAAQ,GAAG,QAAQ,GAAG,WAAW,CAAC;AAExD;;;;;GAKG;AACH,MAAM,MAAM,UAAU,GAAG,QAAQ,CAAC;AAkBlC,2EAA2E;AAC3E,wBAAgB,aAAa,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,SAAY,GAAG,QAAQ,CAMpE;AAED,kFAAkF;AAClF,wBAAgB,aAAa,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,SAAY,GAAG,QAAQ,CAMpE;AAED,kFAAkF;AAClF,wBAAgB,YAAY,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,SAAY,GAAG,OAAO,CAYlE;AAED,wFAAwF;AACxF,wBAAgB,UAAU,CAAC,CAAC,EAAE,OAAO,GAAG,CAAC,IAAI,QAAQ,CAEpD;AAED,6DAA6D;AAC7D,wBAAgB,UAAU,CAAC,CAAC,EAAE,OAAO,GAAG,CAAC,IAAI,QAAQ,CAEpD"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.parseRAddress = parseRAddress;
|
|
7
|
+
exports.parseIAddress = parseIAddress;
|
|
8
|
+
exports.parseAddress = parseAddress;
|
|
9
|
+
exports.isIAddress = isIAddress;
|
|
10
|
+
exports.isRAddress = isRAddress;
|
|
11
|
+
/**
|
|
12
|
+
* Branded domain types + parse-don't-validate constructors.
|
|
13
|
+
*
|
|
14
|
+
* The address-version-laundering bug class (KeyID/IdentityID.fromAddress and
|
|
15
|
+
* fromBase58Check discard the version byte) was defended by scattering
|
|
16
|
+
* assertAddressVersion at each call site. Brands move that guarantee into the
|
|
17
|
+
* type system: once an internal function's signature demands an `IAddress`, a
|
|
18
|
+
* raw `string` (or an `RAddress`) cannot be passed — the compiler rejects it,
|
|
19
|
+
* and a forgotten check is a build error instead of a live-testnet discovery.
|
|
20
|
+
*
|
|
21
|
+
* Brands are structural subtypes of `string`, so a value already flows into the
|
|
22
|
+
* fork's constructors with zero casts; the only way to MINT one is through a
|
|
23
|
+
* parser here, which validates the version byte. No fork imports (uses bs58check
|
|
24
|
+
* directly), so this stays at the dependency-free core.
|
|
25
|
+
*/
|
|
26
|
+
const bs58check_1 = __importDefault(require("bs58check"));
|
|
27
|
+
const index_js_1 = require("../constants/index.js");
|
|
28
|
+
const errors_js_1 = require("../errors.js");
|
|
29
|
+
const P2SH_VERSION = 0x55;
|
|
30
|
+
/** Decode a base58check string to its version byte + 20-byte hash, or throw typed. */
|
|
31
|
+
function decode(s, label) {
|
|
32
|
+
let decoded;
|
|
33
|
+
try {
|
|
34
|
+
decoded = bs58check_1.default.decode(s);
|
|
35
|
+
}
|
|
36
|
+
catch (err) {
|
|
37
|
+
throw new errors_js_1.InvalidAddressError(String(s), `${label} is not valid base58check: ${err.message}`);
|
|
38
|
+
}
|
|
39
|
+
if (decoded.length !== 21) {
|
|
40
|
+
throw new errors_js_1.InvalidAddressError(String(s), `${label} must decode to a 1-byte version + 20-byte hash, got ${decoded.length} bytes`);
|
|
41
|
+
}
|
|
42
|
+
return { version: decoded[0] };
|
|
43
|
+
}
|
|
44
|
+
/** Parse a transparent R-address; throws InvalidAddressError otherwise. */
|
|
45
|
+
function parseRAddress(s, label = 'address') {
|
|
46
|
+
const { version } = decode(s, label);
|
|
47
|
+
if (version !== index_js_1.PUBKEY_HASH_PREFIX) {
|
|
48
|
+
throw new errors_js_1.InvalidAddressError(s, `${label} must be an R-address (version ${index_js_1.PUBKEY_HASH_PREFIX}), got version ${version}`);
|
|
49
|
+
}
|
|
50
|
+
return s;
|
|
51
|
+
}
|
|
52
|
+
/** Parse an identity/currency i-address; throws InvalidAddressError otherwise. */
|
|
53
|
+
function parseIAddress(s, label = 'address') {
|
|
54
|
+
const { version } = decode(s, label);
|
|
55
|
+
if (version !== index_js_1.I_ADDR_VERSION) {
|
|
56
|
+
throw new errors_js_1.InvalidAddressError(s, `${label} must be an identity i-address (version ${index_js_1.I_ADDR_VERSION}), got version ${version}`);
|
|
57
|
+
}
|
|
58
|
+
return s;
|
|
59
|
+
}
|
|
60
|
+
/** Parse any supported address into the discriminated union; throws otherwise. */
|
|
61
|
+
function parseAddress(s, label = 'address') {
|
|
62
|
+
const { version } = decode(s, label);
|
|
63
|
+
switch (version) {
|
|
64
|
+
case index_js_1.PUBKEY_HASH_PREFIX:
|
|
65
|
+
return s;
|
|
66
|
+
case index_js_1.I_ADDR_VERSION:
|
|
67
|
+
return s;
|
|
68
|
+
case P2SH_VERSION:
|
|
69
|
+
return s;
|
|
70
|
+
default:
|
|
71
|
+
throw new errors_js_1.InvalidAddressError(s, `${label} has unsupported version byte ${version}`);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
/** Narrow an Address to an i-address by its version byte (replaces startsWith('i')). */
|
|
75
|
+
function isIAddress(a) {
|
|
76
|
+
return decode(a, 'address').version === index_js_1.I_ADDR_VERSION;
|
|
77
|
+
}
|
|
78
|
+
/** Narrow an Address to an R-address by its version byte. */
|
|
79
|
+
function isRAddress(a) {
|
|
80
|
+
return decode(a, 'address').version === index_js_1.PUBKEY_HASH_PREFIX;
|
|
81
|
+
}
|
|
82
|
+
//# sourceMappingURL=brands.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"brands.js","sourceRoot":"","sources":["../../src/core/brands.ts"],"names":[],"mappings":";;;;;AAwDA,sCAMC;AAGD,sCAMC;AAGD,oCAYC;AAGD,gCAEC;AAGD,gCAEC;AAhGD;;;;;;;;;;;;;;GAcG;AACH,0DAAkC;AAClC,oDAA2E;AAC3E,4CAAmD;AAsBnD,MAAM,YAAY,GAAG,IAAI,CAAC;AAE1B,sFAAsF;AACtF,SAAS,MAAM,CAAC,CAAS,EAAE,KAAa;IACtC,IAAI,OAAmB,CAAC;IACxB,IAAI,CAAC;QACH,OAAO,GAAG,mBAAS,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;IAChC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,IAAI,+BAAmB,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,GAAG,KAAK,8BAA+B,GAAa,CAAC,OAAO,EAAE,CAAC,CAAC;IAC3G,CAAC;IACD,IAAI,OAAO,CAAC,MAAM,KAAK,EAAE,EAAE,CAAC;QAC1B,MAAM,IAAI,+BAAmB,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,GAAG,KAAK,wDAAwD,OAAO,CAAC,MAAM,QAAQ,CAAC,CAAC;IACnI,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAW,EAAE,CAAC;AAC3C,CAAC;AAED,2EAA2E;AAC3E,SAAgB,aAAa,CAAC,CAAS,EAAE,KAAK,GAAG,SAAS;IACxD,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;IACrC,IAAI,OAAO,KAAK,6BAAkB,EAAE,CAAC;QACnC,MAAM,IAAI,+BAAmB,CAAC,CAAC,EAAE,GAAG,KAAK,kCAAkC,6BAAkB,kBAAkB,OAAO,EAAE,CAAC,CAAC;IAC5H,CAAC;IACD,OAAO,CAAa,CAAC;AACvB,CAAC;AAED,kFAAkF;AAClF,SAAgB,aAAa,CAAC,CAAS,EAAE,KAAK,GAAG,SAAS;IACxD,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;IACrC,IAAI,OAAO,KAAK,yBAAc,EAAE,CAAC;QAC/B,MAAM,IAAI,+BAAmB,CAAC,CAAC,EAAE,GAAG,KAAK,2CAA2C,yBAAc,kBAAkB,OAAO,EAAE,CAAC,CAAC;IACjI,CAAC;IACD,OAAO,CAAa,CAAC;AACvB,CAAC;AAED,kFAAkF;AAClF,SAAgB,YAAY,CAAC,CAAS,EAAE,KAAK,GAAG,SAAS;IACvD,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;IACrC,QAAQ,OAAO,EAAE,CAAC;QAChB,KAAK,6BAAkB;YACrB,OAAO,CAAa,CAAC;QACvB,KAAK,yBAAc;YACjB,OAAO,CAAa,CAAC;QACvB,KAAK,YAAY;YACf,OAAO,CAAgB,CAAC;QAC1B;YACE,MAAM,IAAI,+BAAmB,CAAC,CAAC,EAAE,GAAG,KAAK,iCAAiC,OAAO,EAAE,CAAC,CAAC;IACzF,CAAC;AACH,CAAC;AAED,wFAAwF;AACxF,SAAgB,UAAU,CAAC,CAAU;IACnC,OAAO,MAAM,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC,OAAO,KAAK,yBAAc,CAAC;AACzD,CAAC;AAED,6DAA6D;AAC7D,SAAgB,UAAU,CAAC,CAAU;IACnC,OAAO,MAAM,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC,OAAO,KAAK,6BAAkB,CAAC;AAC7D,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/currency/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAGH,OAAO,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AACtE,YAAY,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAMlD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/currency/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAGH,OAAO,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AACtE,YAAY,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAMlD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAQrD,OAAO,KAAK,EAAQ,oBAAoB,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAI1F;;;;GAIG;AACH,wBAAgB,cAAc,CAC5B,MAAM,EAAE,oBAAoB,EAC5B,OAAO,EAAE,OAAO,GACf,oBAAoB,CA6ItB"}
|
package/dist/currency/index.js
CHANGED
|
@@ -28,6 +28,7 @@ const index_js_2 = require("../signing/index.js");
|
|
|
28
28
|
const index_js_3 = require("../utxo/index.js");
|
|
29
29
|
const index_js_4 = require("../utils/index.js");
|
|
30
30
|
const index_js_5 = require("../identity/index.js");
|
|
31
|
+
const brands_js_1 = require("../core/brands.js");
|
|
31
32
|
const index_js_6 = require("../keys/index.js");
|
|
32
33
|
const errors_js_1 = require("../errors.js");
|
|
33
34
|
const { completeFundedIdentityUpdate } = utxo_lib_1.smarttxs;
|
|
@@ -74,6 +75,10 @@ function defineCurrency(params, network) {
|
|
|
74
75
|
// large; size the fee from their real byte length so the tx isn't estimated
|
|
75
76
|
// below the relay minimum.
|
|
76
77
|
const selection = (0, index_js_3.selectUtxos)(params.utxos, currencyDefValue, new Map(), 2, systemId, undefined, true, identityOutputScript.length + currencyDefScript.length);
|
|
78
|
+
// Currency definition pays only native and emits no token-change output, so a
|
|
79
|
+
// token-bearing funding UTXO would be silently dropped. Fail closed if one
|
|
80
|
+
// was selected (both maps empty ⇒ assert no token enters).
|
|
81
|
+
(0, index_js_3.assertTokenConservation)(selection.selected, new Map(), new Map(), systemId, 'currency definition');
|
|
77
82
|
// Build transaction
|
|
78
83
|
const txb = new utxo_lib_1.TransactionBuilder(verusNetwork);
|
|
79
84
|
txb.setVersion(4);
|
|
@@ -86,7 +91,7 @@ function defineCurrency(params, network) {
|
|
|
86
91
|
txb.addOutput(currencyDefScript, (0, index_js_4.toSafeNumber)(currencyDefValue));
|
|
87
92
|
if (selection.nativeChange > 0n) {
|
|
88
93
|
if (params.changeAddress.startsWith('i')) {
|
|
89
|
-
txb.addOutput((0, index_js_5.identityPaymentScript)(params.changeAddress), (0, index_js_4.toSafeNumber)(selection.nativeChange));
|
|
94
|
+
txb.addOutput((0, index_js_5.identityPaymentScript)((0, brands_js_1.parseIAddress)(params.changeAddress, 'changeAddress')), (0, index_js_4.toSafeNumber)(selection.nativeChange));
|
|
90
95
|
}
|
|
91
96
|
else {
|
|
92
97
|
txb.addOutput(params.changeAddress, (0, index_js_4.toSafeNumber)(selection.nativeChange));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/currency/index.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;GAUG;;;;;;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/currency/index.ts"],"names":[],"mappings":"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"}
|
package/dist/identity/index.d.ts
CHANGED
|
@@ -11,6 +11,7 @@ import { Identity } from 'verus-typescript-primitives';
|
|
|
11
11
|
import { nameAndParentAddrToIAddr } from 'verus-typescript-primitives';
|
|
12
12
|
import type { Network } from '../constants/index.js';
|
|
13
13
|
import { type VerusNetwork } from '../signing/index.js';
|
|
14
|
+
import { type IAddress, type RAddress, type Address } from '../core/brands.js';
|
|
14
15
|
import type { CreateCommitmentParams, CreateCommitmentResult, RegisterIdentityParams, RegisterIdentityResult, UpdateIdentityParams, UpdateIdentityResult } from '../types/index.js';
|
|
15
16
|
export { nameAndParentAddrToIAddr };
|
|
16
17
|
/**
|
|
@@ -55,11 +56,11 @@ export declare function serializeCommitmentHash(hash: Buffer): Buffer;
|
|
|
55
56
|
/**
|
|
56
57
|
* Build the commitment output script
|
|
57
58
|
*/
|
|
58
|
-
export declare function buildCommitmentScript(commitmentHashBuf: Buffer, controlAddress:
|
|
59
|
+
export declare function buildCommitmentScript(commitmentHashBuf: Buffer, controlAddress: RAddress): Buffer;
|
|
59
60
|
/**
|
|
60
61
|
* Build the name reservation output script
|
|
61
62
|
*/
|
|
62
|
-
export declare function buildReservationScript(newIdentityIAddress:
|
|
63
|
+
export declare function buildReservationScript(newIdentityIAddress: IAddress, serializedReservation: Buffer, isAdvanced?: boolean): Buffer;
|
|
63
64
|
/**
|
|
64
65
|
* Build an identity definition output script from an Identity object
|
|
65
66
|
*/
|
|
@@ -75,7 +76,14 @@ export declare function isVRSCParent(parentIAddress: string | undefined, network
|
|
|
75
76
|
/**
|
|
76
77
|
* Build the full commitment data needed for Step 1 of identity creation
|
|
77
78
|
*/
|
|
78
|
-
export declare function prepareNameCommitment(name: string, controlAddress: string, referralIAddress?: string, parentIAddress?: string, network?: Network
|
|
79
|
+
export declare function prepareNameCommitment(name: string, controlAddress: string, referralIAddress?: string, parentIAddress?: string, network?: Network,
|
|
80
|
+
/**
|
|
81
|
+
* Explicit 32-byte salt. Omit for a fresh random salt (the normal path); pass
|
|
82
|
+
* a fixed value only to make the commitment deterministic for golden/diff
|
|
83
|
+
* tests. A reused salt on a real registration is a privacy leak, so callers
|
|
84
|
+
* outside tests must not set it.
|
|
85
|
+
*/
|
|
86
|
+
salt?: Buffer): {
|
|
79
87
|
salt: Buffer;
|
|
80
88
|
serializedReservation: Buffer;
|
|
81
89
|
commitmentHash: Buffer;
|
|
@@ -84,7 +92,14 @@ export declare function prepareNameCommitment(name: string, controlAddress: stri
|
|
|
84
92
|
identityAddress: string;
|
|
85
93
|
};
|
|
86
94
|
/**
|
|
87
|
-
* Build a
|
|
95
|
+
* Build a pay-to-identity output script for an i-address.
|
|
96
|
+
*
|
|
97
|
+
* Alias of {@link identityPaymentScript}. This previously emitted the bare
|
|
98
|
+
* 26-byte template `OP_DUP OP_HASH160 <idhash> OP_EQUALVERIFY OP_CHECKSIG
|
|
99
|
+
* OP_CHECKCRYPTOCONDITION`, which is NOT a valid Verus scriptPubKey — a Verus
|
|
100
|
+
* P2ID is a CryptoCondition (OptCCParams) output. Funds sent to the old
|
|
101
|
+
* template would have gone to a non-standard script the daemon does not treat
|
|
102
|
+
* as identity-spendable. It now delegates to the chain-verified CC builder.
|
|
88
103
|
*/
|
|
89
104
|
export declare function buildP2IDScript(iAddress: string): Buffer;
|
|
90
105
|
/**
|
|
@@ -93,11 +108,13 @@ export declare function buildP2IDScript(iAddress: string): Buffer;
|
|
|
93
108
|
* an identity (verified against on-chain P2ID outputs). Use this for change
|
|
94
109
|
* or payment outputs to an i-address.
|
|
95
110
|
*/
|
|
96
|
-
export declare function identityPaymentScript(iAddress:
|
|
111
|
+
export declare function identityPaymentScript(iAddress: IAddress): Buffer;
|
|
97
112
|
/**
|
|
98
|
-
* Build a CC referral payment output script
|
|
113
|
+
* Build a CC referral payment output script. Requires an already-parsed
|
|
114
|
+
* i-address: IdentityID.fromAddress launders the version byte, so accepting a
|
|
115
|
+
* raw string here is exactly the hole that let a wrong-kind address through.
|
|
99
116
|
*/
|
|
100
|
-
export declare function buildReferralPaymentScript(iAddress:
|
|
117
|
+
export declare function buildReferralPaymentScript(iAddress: IAddress): Buffer;
|
|
101
118
|
/**
|
|
102
119
|
* Calculate registration fee breakdown
|
|
103
120
|
*/
|
|
@@ -111,12 +128,12 @@ export declare function calculateRegistrationFees(hasReferral: boolean, totalFee
|
|
|
111
128
|
*/
|
|
112
129
|
export declare function createIdentityObject(params: {
|
|
113
130
|
name: string;
|
|
114
|
-
primaryAddresses:
|
|
131
|
+
primaryAddresses: RAddress[];
|
|
115
132
|
minSigs?: number;
|
|
116
|
-
revocationAuthority:
|
|
117
|
-
recoveryAuthority:
|
|
118
|
-
parentIAddress:
|
|
119
|
-
systemId:
|
|
133
|
+
revocationAuthority: IAddress;
|
|
134
|
+
recoveryAuthority: IAddress;
|
|
135
|
+
parentIAddress: IAddress;
|
|
136
|
+
systemId: IAddress;
|
|
120
137
|
}): Identity;
|
|
121
138
|
/**
|
|
122
139
|
* Build the parent-currency registration-fee output for a sub-ID.
|
|
@@ -144,7 +161,7 @@ export declare function buildRegistrationFeeOutput(parentCurrencyId: string, fee
|
|
|
144
161
|
/**
|
|
145
162
|
* Build a token change output (EVAL_RESERVE_OUTPUT)
|
|
146
163
|
*/
|
|
147
|
-
export declare function buildTokenChangeOutput(changeAddress:
|
|
164
|
+
export declare function buildTokenChangeOutput(changeAddress: Address, currencyChanges: Map<string, bigint>): {
|
|
148
165
|
script: Buffer;
|
|
149
166
|
nativeValue: bigint;
|
|
150
167
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/identity/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH,OAAO,EAQL,QAAQ,EAGT,MAAM,6BAA6B,CAAC;AAErC,OAAO,EACL,wBAAwB,EAEzB,MAAM,6BAA6B,CAAC;AAUrC,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAErD,OAAO,EAAmF,KAAK,YAAY,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/identity/index.ts"],"names":[],"mappings":"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"}
|
package/dist/identity/index.js
CHANGED
|
@@ -47,6 +47,7 @@ const index_js_1 = require("../constants/index.js");
|
|
|
47
47
|
const index_js_2 = require("../utils/index.js");
|
|
48
48
|
const index_js_3 = require("../signing/index.js");
|
|
49
49
|
const index_js_4 = require("../utxo/index.js");
|
|
50
|
+
const brands_js_1 = require("../core/brands.js");
|
|
50
51
|
const errors_js_1 = require("../errors.js");
|
|
51
52
|
const index_js_5 = require("../keys/index.js");
|
|
52
53
|
const { createUnfundedIdentityUpdate, completeFundedIdentityUpdate } = utxo_lib_1.smarttxs;
|
|
@@ -214,6 +215,14 @@ function buildIdentityScript(identity) {
|
|
|
214
215
|
* Derive the identity i-address from a name and optional parent
|
|
215
216
|
*/
|
|
216
217
|
function deriveIdentityAddress(name, parentIAddress) {
|
|
218
|
+
// nameAndParentAddrToIAddr hashes fromBase58Check(parent).hash regardless of
|
|
219
|
+
// version, so an R-address parent is laundered into an identity-versioned hash
|
|
220
|
+
// that names no real currency. The derived i-address then looks valid but can
|
|
221
|
+
// never be registered — funds paid to it (pay-to-unregistered-identity) burn,
|
|
222
|
+
// and a name commitment built with it wastes its fee. Require an i-address.
|
|
223
|
+
if (parentIAddress) {
|
|
224
|
+
assertAddressVersion(parentIAddress, index_js_1.I_ADDR_VERSION, 'parent');
|
|
225
|
+
}
|
|
217
226
|
return (0, verus_typescript_primitives_3.nameAndParentAddrToIAddr)(name, parentIAddress || undefined);
|
|
218
227
|
}
|
|
219
228
|
/**
|
|
@@ -228,8 +237,14 @@ function isVRSCParent(parentIAddress, network = 'mainnet') {
|
|
|
228
237
|
/**
|
|
229
238
|
* Build the full commitment data needed for Step 1 of identity creation
|
|
230
239
|
*/
|
|
231
|
-
function prepareNameCommitment(name, controlAddress, referralIAddress, parentIAddress, network = 'mainnet'
|
|
232
|
-
|
|
240
|
+
function prepareNameCommitment(name, controlAddress, referralIAddress, parentIAddress, network = 'mainnet',
|
|
241
|
+
/**
|
|
242
|
+
* Explicit 32-byte salt. Omit for a fresh random salt (the normal path); pass
|
|
243
|
+
* a fixed value only to make the commitment deterministic for golden/diff
|
|
244
|
+
* tests. A reused salt on a real registration is a privacy leak, so callers
|
|
245
|
+
* outside tests must not set it.
|
|
246
|
+
*/
|
|
247
|
+
salt = generateSalt()) {
|
|
233
248
|
const systemId = index_js_1.NETWORK_CONFIG[network].chainId;
|
|
234
249
|
// iAddressToHash discards the version byte, so an R-address referral would be
|
|
235
250
|
// laundered into a hash that names no identity (the daemon rejects the
|
|
@@ -256,7 +271,7 @@ function prepareNameCommitment(name, controlAddress, referralIAddress, parentIAd
|
|
|
256
271
|
}
|
|
257
272
|
const commitmentHash = calculateCommitmentHash(serializedReservation);
|
|
258
273
|
const serializedCommitmentHash = serializeCommitmentHash(commitmentHash);
|
|
259
|
-
const commitmentScript = buildCommitmentScript(commitmentHash, controlAddress);
|
|
274
|
+
const commitmentScript = buildCommitmentScript(commitmentHash, (0, brands_js_1.parseRAddress)(controlAddress, 'controlAddress'));
|
|
260
275
|
return {
|
|
261
276
|
salt,
|
|
262
277
|
serializedReservation,
|
|
@@ -267,18 +282,17 @@ function prepareNameCommitment(name, controlAddress, referralIAddress, parentIAd
|
|
|
267
282
|
};
|
|
268
283
|
}
|
|
269
284
|
/**
|
|
270
|
-
* Build a
|
|
285
|
+
* Build a pay-to-identity output script for an i-address.
|
|
286
|
+
*
|
|
287
|
+
* Alias of {@link identityPaymentScript}. This previously emitted the bare
|
|
288
|
+
* 26-byte template `OP_DUP OP_HASH160 <idhash> OP_EQUALVERIFY OP_CHECKSIG
|
|
289
|
+
* OP_CHECKCRYPTOCONDITION`, which is NOT a valid Verus scriptPubKey — a Verus
|
|
290
|
+
* P2ID is a CryptoCondition (OptCCParams) output. Funds sent to the old
|
|
291
|
+
* template would have gone to a non-standard script the daemon does not treat
|
|
292
|
+
* as identity-spendable. It now delegates to the chain-verified CC builder.
|
|
271
293
|
*/
|
|
272
294
|
function buildP2IDScript(iAddress) {
|
|
273
|
-
|
|
274
|
-
return utxo_lib_1.script.compile([
|
|
275
|
-
utxo_lib_1.opcodes.OP_DUP,
|
|
276
|
-
utxo_lib_1.opcodes.OP_HASH160,
|
|
277
|
-
idHash,
|
|
278
|
-
utxo_lib_1.opcodes.OP_EQUALVERIFY,
|
|
279
|
-
utxo_lib_1.opcodes.OP_CHECKSIG,
|
|
280
|
-
utxo_lib_1.opcodes.OP_CHECKCRYPTOCONDITION,
|
|
281
|
-
]);
|
|
295
|
+
return identityPaymentScript((0, brands_js_1.parseIAddress)(iAddress, 'iAddress'));
|
|
282
296
|
}
|
|
283
297
|
/**
|
|
284
298
|
* The standard pay-to-identity output script (CC EVAL_NONE 1-of-1 to an
|
|
@@ -290,7 +304,9 @@ function identityPaymentScript(iAddress) {
|
|
|
290
304
|
return buildReferralPaymentScript(iAddress);
|
|
291
305
|
}
|
|
292
306
|
/**
|
|
293
|
-
* Build a CC referral payment output script
|
|
307
|
+
* Build a CC referral payment output script. Requires an already-parsed
|
|
308
|
+
* i-address: IdentityID.fromAddress launders the version byte, so accepting a
|
|
309
|
+
* raw string here is exactly the hole that let a wrong-kind address through.
|
|
294
310
|
*/
|
|
295
311
|
function buildReferralPaymentScript(iAddress) {
|
|
296
312
|
const identityDest = new verus_typescript_primitives_1.TxDestination(verus_typescript_primitives_1.IdentityID.fromAddress(iAddress));
|
|
@@ -331,9 +347,9 @@ function calculateRegistrationFees(hasReferral, totalFee = index_js_1.DEFAULT_RE
|
|
|
331
347
|
* Build a new Identity object for registration
|
|
332
348
|
*/
|
|
333
349
|
function createIdentityObject(params) {
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
350
|
+
// No assertAddressVersion here: the brands guarantee the version bytes. An
|
|
351
|
+
// R-address primary or an i-address authority is now a compile error at the
|
|
352
|
+
// call site, where the raw string is parsed.
|
|
337
353
|
validateMinSigs(params.minSigs ?? 1, params.primaryAddresses.length);
|
|
338
354
|
const primaryKeys = params.primaryAddresses.map(addr => verus_typescript_primitives_1.KeyID.fromAddress(addr));
|
|
339
355
|
const identity = new verus_typescript_primitives_1.Identity({
|
|
@@ -372,27 +388,25 @@ function createIdentityObject(params) {
|
|
|
372
388
|
*/
|
|
373
389
|
function buildRegistrationFeeOutput(parentCurrencyId, feeAmount, systemId, _controlAddress) {
|
|
374
390
|
void systemId;
|
|
375
|
-
return buildTokenChangeOutput(parentCurrencyId, new Map([[parentCurrencyId, feeAmount]]));
|
|
391
|
+
return buildTokenChangeOutput((0, brands_js_1.parseIAddress)(parentCurrencyId, 'parentCurrencyId'), new Map([[parentCurrencyId, feeAmount]]));
|
|
376
392
|
}
|
|
377
393
|
/**
|
|
378
394
|
* Build a token change output (EVAL_RESERVE_OUTPUT)
|
|
379
395
|
*/
|
|
380
396
|
function buildTokenChangeOutput(changeAddress, currencyChanges) {
|
|
381
|
-
//
|
|
382
|
-
//
|
|
383
|
-
//
|
|
384
|
-
//
|
|
385
|
-
// neither an R- nor an i-address rather than silently mis-routing it.
|
|
386
|
-
const version = (0, verus_typescript_primitives_3.fromBase58Check)(changeAddress).version;
|
|
397
|
+
// The brand guarantees the version; narrow it to pick the destination form.
|
|
398
|
+
// A pay-to-identity destination for i-addresses (KeyID.fromAddress would
|
|
399
|
+
// launder an i-address to a transparent script nobody controls), a KeyID for
|
|
400
|
+
// R-addresses, and reject a P2SH address (not a valid reserve destination).
|
|
387
401
|
let destination;
|
|
388
|
-
if (
|
|
402
|
+
if ((0, brands_js_1.isIAddress)(changeAddress)) {
|
|
389
403
|
destination = new verus_typescript_primitives_1.TxDestination(verus_typescript_primitives_1.IdentityID.fromAddress(changeAddress));
|
|
390
404
|
}
|
|
391
|
-
else if (
|
|
405
|
+
else if ((0, brands_js_1.isRAddress)(changeAddress)) {
|
|
392
406
|
destination = new verus_typescript_primitives_1.TxDestination(verus_typescript_primitives_1.KeyID.fromAddress(changeAddress));
|
|
393
407
|
}
|
|
394
408
|
else {
|
|
395
|
-
throw new errors_js_1.TransactionBuildError(`token change address must be an R-address or identity i-address, got
|
|
409
|
+
throw new errors_js_1.TransactionBuildError(`token change address must be an R-address or identity i-address, got: ${changeAddress}`);
|
|
396
410
|
}
|
|
397
411
|
const valueMap = new Map();
|
|
398
412
|
for (const [currency, amount] of currencyChanges) {
|
|
@@ -462,7 +476,7 @@ function buildAndSignCommitment(params, network) {
|
|
|
462
476
|
// (KeyID.fromAddress laundered it to an uncontrollable key — permanently
|
|
463
477
|
// unspendable, wasting the commitment fee). Derive it from the WIF instead.
|
|
464
478
|
const controlAddress = utxo_lib_1.ECPair.fromWIF(params.wif, verusNetwork).getAddress();
|
|
465
|
-
const commitment = prepareNameCommitment(params.name, controlAddress, params.referral, params.parent, network);
|
|
479
|
+
const commitment = prepareNameCommitment(params.name, controlAddress, params.referral, params.parent, network, params.salt);
|
|
466
480
|
const utxos = params.utxos;
|
|
467
481
|
const selection = (0, index_js_4.selectUtxos)(utxos, 0n, new Map(), 1, networkConfig.chainId, undefined, true);
|
|
468
482
|
const txb = new utxo_lib_1.TransactionBuilder(verusNetwork);
|
|
@@ -473,17 +487,29 @@ function buildAndSignCommitment(params, network) {
|
|
|
473
487
|
txb.addInput(Buffer.from(utxo.txid, 'hex').reverse(), utxo.outputIndex, 0xffffffff, Buffer.from(utxo.script, 'hex'));
|
|
474
488
|
}
|
|
475
489
|
txb.addOutput(commitment.commitmentScript, 0);
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
490
|
+
// If native-only UTXOs can't cover the fee, selectUtxos falls back to a
|
|
491
|
+
// token-bearing UTXO and returns its token value as currencyChanges. Emit it
|
|
492
|
+
// as a reserve-output change (bundled with the native change) — otherwise
|
|
493
|
+
// that token value is silently forfeited to the miner.
|
|
494
|
+
const hasTokenChange = selection.currencyChanges.size > 0;
|
|
495
|
+
if (hasTokenChange || selection.nativeChange > 0n) {
|
|
496
|
+
if (hasTokenChange) {
|
|
497
|
+
const tokenChangeScript = buildTokenChangeOutput((0, brands_js_1.parseAddress)(params.changeAddress, 'changeAddress'), selection.currencyChanges);
|
|
498
|
+
txb.addOutput(tokenChangeScript.script, (0, index_js_2.toSafeNumber)(selection.nativeChange));
|
|
499
|
+
}
|
|
500
|
+
else if (params.changeAddress.startsWith('i')) {
|
|
501
|
+
// utxo-lib's addOutput only resolves base58 R-addresses; an i-address
|
|
502
|
+
// changeAddress needs the explicit P2ID script (matching sendCurrency), or
|
|
503
|
+
// it throws an untyped "no matching Script".
|
|
504
|
+
txb.addOutput(identityPaymentScript((0, brands_js_1.parseIAddress)(params.changeAddress, 'changeAddress')), (0, index_js_2.toSafeNumber)(selection.nativeChange));
|
|
482
505
|
}
|
|
483
506
|
else {
|
|
484
507
|
txb.addOutput(params.changeAddress, (0, index_js_2.toSafeNumber)(selection.nativeChange));
|
|
485
508
|
}
|
|
486
509
|
}
|
|
510
|
+
// No token is paid out here (the commitment output carries none), so every
|
|
511
|
+
// token in the selected inputs must return as change.
|
|
512
|
+
(0, index_js_4.assertTokenConservation)(selection.selected, new Map(), selection.currencyChanges, networkConfig.chainId, 'name commitment');
|
|
487
513
|
const unsignedTx = txb.buildIncomplete();
|
|
488
514
|
const { signedTx, txid } = (0, index_js_3.signTransactionSmart)(unsignedTx.toHex(), params.wif, selection.selected, verusNetwork);
|
|
489
515
|
return {
|
|
@@ -522,15 +548,15 @@ function buildAndSignRegistration(params, network) {
|
|
|
522
548
|
const identityAddress = deriveIdentityAddress(commitData.name, effectiveParent);
|
|
523
549
|
const identity = createIdentityObject({
|
|
524
550
|
name: commitData.name,
|
|
525
|
-
primaryAddresses: params.primaryAddresses,
|
|
551
|
+
primaryAddresses: params.primaryAddresses.map((a, i) => (0, brands_js_1.parseRAddress)(a, `primaryAddresses[${i}]`)),
|
|
526
552
|
...(params.minSigs !== undefined ? { minSigs: params.minSigs } : {}),
|
|
527
|
-
revocationAuthority: params.revocationAuthority || identityAddress,
|
|
528
|
-
recoveryAuthority: params.recoveryAuthority || identityAddress,
|
|
529
|
-
parentIAddress,
|
|
530
|
-
systemId,
|
|
553
|
+
revocationAuthority: (0, brands_js_1.parseIAddress)(params.revocationAuthority || identityAddress, 'revocationAuthority'),
|
|
554
|
+
recoveryAuthority: (0, brands_js_1.parseIAddress)(params.recoveryAuthority || identityAddress, 'recoveryAuthority'),
|
|
555
|
+
parentIAddress: (0, brands_js_1.parseIAddress)(parentIAddress, 'parentIAddress'),
|
|
556
|
+
systemId: (0, brands_js_1.parseIAddress)(systemId, 'systemId'),
|
|
531
557
|
});
|
|
532
558
|
const identityScript = buildIdentityScript(identity);
|
|
533
|
-
const reservationScript = buildReservationScript(identityAddress, Buffer.from(commitData.namereservationHex, 'hex'), isSubId);
|
|
559
|
+
const reservationScript = buildReservationScript((0, brands_js_1.parseIAddress)(identityAddress, 'identityAddress'), Buffer.from(commitData.namereservationHex, 'hex'), isSubId);
|
|
534
560
|
if (isSubId) {
|
|
535
561
|
return _buildSubIdRegistration(params, identity, identityScript, reservationScript, identityAddress, parentIAddress, systemId, verusNetwork);
|
|
536
562
|
}
|
|
@@ -557,7 +583,7 @@ function _buildVrscRegistration(params, identityScript, reservationScript, ident
|
|
|
557
583
|
}
|
|
558
584
|
for (const referrerAddr of chain) {
|
|
559
585
|
referralOutputs.push({
|
|
560
|
-
script: buildReferralPaymentScript(referrerAddr),
|
|
586
|
+
script: buildReferralPaymentScript((0, brands_js_1.parseIAddress)(referrerAddr, 'referralChain entry')),
|
|
561
587
|
value: fees.referralAmount,
|
|
562
588
|
});
|
|
563
589
|
}
|
|
@@ -587,17 +613,29 @@ function _buildVrscRegistration(params, identityScript, reservationScript, ident
|
|
|
587
613
|
txb.addOutput(referralOut.script, (0, index_js_2.toSafeNumber)(referralOut.value));
|
|
588
614
|
}
|
|
589
615
|
txb.addOutput(reservationScript, 0);
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
616
|
+
// Registration needs ~80-100 native, so Phase-2 selection is especially
|
|
617
|
+
// likely to exhaust pure-native UTXOs and pull a token-bearing one; return
|
|
618
|
+
// its token value as reserve-output change instead of forfeiting it to the
|
|
619
|
+
// miner. (The commitment input carries no currency.)
|
|
620
|
+
const hasTokenChange = selection.currencyChanges.size > 0;
|
|
621
|
+
if (hasTokenChange || selection.nativeChange > 0n) {
|
|
622
|
+
if (hasTokenChange) {
|
|
623
|
+
const tokenChangeScript = buildTokenChangeOutput((0, brands_js_1.parseAddress)(params.changeAddress, 'changeAddress'), selection.currencyChanges);
|
|
624
|
+
txb.addOutput(tokenChangeScript.script, (0, index_js_2.toSafeNumber)(selection.nativeChange));
|
|
625
|
+
}
|
|
626
|
+
else if (params.changeAddress.startsWith('i')) {
|
|
627
|
+
// utxo-lib's addOutput only resolves base58 R-addresses; an i-address
|
|
628
|
+
// changeAddress needs the explicit P2ID script (matching sendCurrency), or
|
|
629
|
+
// it throws an untyped "no matching Script".
|
|
630
|
+
txb.addOutput(identityPaymentScript((0, brands_js_1.parseIAddress)(params.changeAddress, 'changeAddress')), (0, index_js_2.toSafeNumber)(selection.nativeChange));
|
|
596
631
|
}
|
|
597
632
|
else {
|
|
598
633
|
txb.addOutput(params.changeAddress, (0, index_js_2.toSafeNumber)(selection.nativeChange));
|
|
599
634
|
}
|
|
600
635
|
}
|
|
636
|
+
// Referral payouts are native; no token is paid out, so all token value in the
|
|
637
|
+
// selected inputs must return as change.
|
|
638
|
+
(0, index_js_4.assertTokenConservation)(selection.selected, new Map(), selection.currencyChanges, systemId, 'identity registration');
|
|
601
639
|
const unsignedTx = txb.buildIncomplete();
|
|
602
640
|
const allUtxos = [commitUtxo, ...selection.selected];
|
|
603
641
|
// The registration fee is burned as an IMPLICIT miner fee (identity and
|
|
@@ -648,7 +686,16 @@ function _buildSubIdRegistration(params, identity, identityScript, reservationSc
|
|
|
648
686
|
const nativeImportFee = params.nativeImportFee || 0n;
|
|
649
687
|
const nativeTarget = feeOutput.nativeValue + nativeImportFee;
|
|
650
688
|
const numOutputs = 4;
|
|
651
|
-
const selection = (0, index_js_4.selectUtxos)(params.utxos, nativeTarget, requiredCurrencies, numOutputs, systemId, undefined, true
|
|
689
|
+
const selection = (0, index_js_4.selectUtxos)(params.utxos, nativeTarget, requiredCurrencies, numOutputs, systemId, undefined, true,
|
|
690
|
+
// The identity and reservation outputs embed the full serialized identity /
|
|
691
|
+
// advanced name reservation (a large contentMultimap can make them
|
|
692
|
+
// multi-KB); size the fee from their real bytes, matching the VRSC
|
|
693
|
+
// registration / update / define paths, so a big sub-ID isn't fee-estimated
|
|
694
|
+
// below the relay minimum and rejected.
|
|
695
|
+
identityScript.length + reservationScript.length + feeOutput.script.length);
|
|
696
|
+
// The parent-currency fee (requiredCurrencies) is paid to the fee output and
|
|
697
|
+
// any excess returns as token change; guard that no token value is dropped.
|
|
698
|
+
(0, index_js_4.assertTokenConservation)(selection.selected, requiredCurrencies, selection.currencyChanges, systemId, 'sub-ID registration');
|
|
652
699
|
const txb = new utxo_lib_1.TransactionBuilder(network);
|
|
653
700
|
txb.setVersion(4);
|
|
654
701
|
txb.setExpiryHeight((0, index_js_3.resolveExpiryHeight)(params.expiryHeight));
|
|
@@ -664,7 +711,7 @@ function _buildSubIdRegistration(params, identity, identityScript, reservationSc
|
|
|
664
711
|
const hasTokenChange = selection.currencyChanges.size > 0;
|
|
665
712
|
if (hasTokenChange || selection.nativeChange > 0n) {
|
|
666
713
|
if (hasTokenChange) {
|
|
667
|
-
const tokenChangeScript = buildTokenChangeOutput(params.changeAddress, selection.currencyChanges);
|
|
714
|
+
const tokenChangeScript = buildTokenChangeOutput((0, brands_js_1.parseAddress)(params.changeAddress, 'changeAddress'), selection.currencyChanges);
|
|
668
715
|
txb.addOutput(tokenChangeScript.script, (0, index_js_2.toSafeNumber)(selection.nativeChange));
|
|
669
716
|
}
|
|
670
717
|
else {
|
|
@@ -672,7 +719,7 @@ function _buildSubIdRegistration(params, identity, identityScript, reservationSc
|
|
|
672
719
|
// changeAddress needs the explicit P2ID script (matching sendCurrency), or
|
|
673
720
|
// it throws an untyped "no matching Script".
|
|
674
721
|
if (params.changeAddress.startsWith('i')) {
|
|
675
|
-
txb.addOutput(identityPaymentScript(params.changeAddress), (0, index_js_2.toSafeNumber)(selection.nativeChange));
|
|
722
|
+
txb.addOutput(identityPaymentScript((0, brands_js_1.parseIAddress)(params.changeAddress, 'changeAddress')), (0, index_js_2.toSafeNumber)(selection.nativeChange));
|
|
676
723
|
}
|
|
677
724
|
else {
|
|
678
725
|
txb.addOutput(params.changeAddress, (0, index_js_2.toSafeNumber)(selection.nativeChange));
|
|
@@ -841,6 +888,10 @@ function buildAndSignIdentityUpdate(params, network, operation = 'update', lockU
|
|
|
841
888
|
// contentMultimap can make it multi-KB); size the fee from its real bytes
|
|
842
889
|
// so a big update isn't fee-estimated below the relay minimum.
|
|
843
890
|
unfundedHex.length / 2);
|
|
891
|
+
// Update spends only native fees and emits no token-change output, so a
|
|
892
|
+
// token-bearing funding UTXO would be silently dropped. Fail closed if one
|
|
893
|
+
// was selected (both maps empty ⇒ assert no token enters).
|
|
894
|
+
(0, index_js_4.assertTokenConservation)(selection.selected, new Map(), new Map(), systemId, 'identity update');
|
|
844
895
|
const txb = new utxo_lib_1.TransactionBuilder(verusNetwork);
|
|
845
896
|
txb.setVersion(4);
|
|
846
897
|
txb.setExpiryHeight((0, index_js_3.resolveExpiryHeight)(params.expiryHeight));
|
|
@@ -857,7 +908,7 @@ function buildAndSignIdentityUpdate(params, network, operation = 'update', lockU
|
|
|
857
908
|
// changeAddress needs the explicit P2ID script (matching sendCurrency), or
|
|
858
909
|
// it throws an untyped "no matching Script".
|
|
859
910
|
if (params.changeAddress.startsWith('i')) {
|
|
860
|
-
txb.addOutput(identityPaymentScript(params.changeAddress), (0, index_js_2.toSafeNumber)(selection.nativeChange));
|
|
911
|
+
txb.addOutput(identityPaymentScript((0, brands_js_1.parseIAddress)(params.changeAddress, 'changeAddress')), (0, index_js_2.toSafeNumber)(selection.nativeChange));
|
|
861
912
|
}
|
|
862
913
|
else {
|
|
863
914
|
txb.addOutput(params.changeAddress, (0, index_js_2.toSafeNumber)(selection.nativeChange));
|