@qrlwallet/connect 5.1.0 → 5.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +58 -34
- package/dist/index.mjs +58 -34
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -3197,17 +3197,20 @@ function consumeValue(budget) {
|
|
|
3197
3197
|
budget.remainingValues--;
|
|
3198
3198
|
if (budget.remainingValues < 0) throw new Error("typed data contains too many encoded values");
|
|
3199
3199
|
}
|
|
3200
|
+
function inputPreview(value) {
|
|
3201
|
+
return value.length > 32 ? `${value.slice(0, 32)}... (length ${value.length})` : value;
|
|
3202
|
+
}
|
|
3200
3203
|
function assertIdentifier(value, label) {
|
|
3201
3204
|
if (!IDENTIFIER_RE.test(value) || value.length > TYPED_DATA_LIMITS.maxIdentifierLength || UNSAFE_OBJECT_KEYS.has(value)) {
|
|
3202
|
-
throw new Error(`invalid ${label}: ${value}`);
|
|
3205
|
+
throw new Error(`invalid ${label}: ${inputPreview(value)}`);
|
|
3203
3206
|
}
|
|
3204
3207
|
}
|
|
3205
3208
|
function parseFieldType(type, types, depth = 0) {
|
|
3206
3209
|
if (depth > TYPED_DATA_LIMITS.maxArrayNesting) {
|
|
3207
|
-
throw new Error(`type nesting too deep: ${type}`);
|
|
3210
|
+
throw new Error(`type nesting too deep: ${inputPreview(type)}`);
|
|
3208
3211
|
}
|
|
3209
3212
|
if (type.length > TYPED_DATA_LIMITS.maxFieldTypeLength) {
|
|
3210
|
-
throw new Error(`field type too long: ${type}`);
|
|
3213
|
+
throw new Error(`field type too long: ${inputPreview(type)}`);
|
|
3211
3214
|
}
|
|
3212
3215
|
const m = ATOMIC_RE.exec(type);
|
|
3213
3216
|
if (m) {
|
|
@@ -3218,14 +3221,14 @@ function parseFieldType(type, types, depth = 0) {
|
|
|
3218
3221
|
if (intKind) {
|
|
3219
3222
|
const width = Number(intWidthStr);
|
|
3220
3223
|
if (!Number.isInteger(width) || width < 8 || width > 256 || width % 8 !== 0) {
|
|
3221
|
-
throw new Error(`invalid int width: ${type}`);
|
|
3224
|
+
throw new Error(`invalid int width: ${inputPreview(type)}`);
|
|
3222
3225
|
}
|
|
3223
3226
|
return { kind: intKind === "uint" ? "uintN" : "intN", width };
|
|
3224
3227
|
}
|
|
3225
3228
|
if (bytesWidthStr) {
|
|
3226
3229
|
const width = Number(bytesWidthStr);
|
|
3227
3230
|
if (!Number.isInteger(width) || width < 1 || width > 32) {
|
|
3228
|
-
throw new Error(`invalid bytesN width: ${type}`);
|
|
3231
|
+
throw new Error(`invalid bytesN width: ${inputPreview(type)}`);
|
|
3229
3232
|
}
|
|
3230
3233
|
return { kind: "bytesN", width };
|
|
3231
3234
|
}
|
|
@@ -3234,7 +3237,7 @@ function parseFieldType(type, types, depth = 0) {
|
|
|
3234
3237
|
if (sizeStr) {
|
|
3235
3238
|
const size = Number(sizeStr);
|
|
3236
3239
|
if (!Number.isSafeInteger(size) || size <= 0 || size > TYPED_DATA_LIMITS.maxArrayLength) {
|
|
3237
|
-
throw new Error(`invalid array size: ${type}`);
|
|
3240
|
+
throw new Error(`invalid array size: ${inputPreview(type)}`);
|
|
3238
3241
|
}
|
|
3239
3242
|
return { kind: "array", inner: innerType, size };
|
|
3240
3243
|
}
|
|
@@ -3244,7 +3247,7 @@ function parseFieldType(type, types, depth = 0) {
|
|
|
3244
3247
|
if (Object.prototype.hasOwnProperty.call(types, type)) {
|
|
3245
3248
|
return { kind: "ref", name: type };
|
|
3246
3249
|
}
|
|
3247
|
-
throw new Error(`unknown type: ${type}`);
|
|
3250
|
+
throw new Error(`unknown type: ${inputPreview(type)}`);
|
|
3248
3251
|
}
|
|
3249
3252
|
function isReservedAtomicTypeName(name) {
|
|
3250
3253
|
if (/^(?:address|bool|string|bytes)$/.test(name)) return true;
|
|
@@ -3261,24 +3264,35 @@ function isReservedAtomicTypeName(name) {
|
|
|
3261
3264
|
return false;
|
|
3262
3265
|
}
|
|
3263
3266
|
function baseTypeName(type) {
|
|
3264
|
-
|
|
3267
|
+
let end = type.length;
|
|
3268
|
+
while (end > 0 && type[end - 1] === "]") {
|
|
3269
|
+
let start = end - 2;
|
|
3270
|
+
while (start >= 0) {
|
|
3271
|
+
const code = type.charCodeAt(start);
|
|
3272
|
+
if (code < 48 || code > 57) break;
|
|
3273
|
+
start--;
|
|
3274
|
+
}
|
|
3275
|
+
if (start < 0 || type[start] !== "[") break;
|
|
3276
|
+
end = start;
|
|
3277
|
+
}
|
|
3278
|
+
return type.slice(0, end);
|
|
3265
3279
|
}
|
|
3266
3280
|
function collectDependencies(primary, types) {
|
|
3267
3281
|
if (!Object.prototype.hasOwnProperty.call(types, primary)) {
|
|
3268
|
-
throw new Error(`unknown primary type: ${primary}`);
|
|
3282
|
+
throw new Error(`unknown primary type: ${inputPreview(primary)}`);
|
|
3269
3283
|
}
|
|
3270
3284
|
const visited = /* @__PURE__ */ new Set();
|
|
3271
3285
|
const visit = (name, path) => {
|
|
3272
3286
|
if (path.length > TYPED_DATA_LIMITS.maxTypeGraphDepth) {
|
|
3273
|
-
throw new Error(`type graph nesting too deep: ${[...path, name].join(" -> ")}`);
|
|
3287
|
+
throw new Error(`type graph nesting too deep: ${inputPreview([...path, name].join(" -> "))}`);
|
|
3274
3288
|
}
|
|
3275
3289
|
if (path.includes(name)) {
|
|
3276
|
-
throw new Error(`cyclic type reference: ${[...path, name].join(" -> ")}`);
|
|
3290
|
+
throw new Error(`cyclic type reference: ${inputPreview([...path, name].join(" -> "))}`);
|
|
3277
3291
|
}
|
|
3278
3292
|
if (visited.has(name)) return;
|
|
3279
3293
|
visited.add(name);
|
|
3280
3294
|
const def = types[name];
|
|
3281
|
-
if (!def) throw new Error(`unknown type: ${name}`);
|
|
3295
|
+
if (!def) throw new Error(`unknown type: ${inputPreview(name)}`);
|
|
3282
3296
|
for (const f of def) {
|
|
3283
3297
|
const base = baseTypeName(f.type);
|
|
3284
3298
|
if (Object.prototype.hasOwnProperty.call(types, base)) {
|
|
@@ -3299,11 +3313,11 @@ function validateTypeMap(types) {
|
|
|
3299
3313
|
for (const [name, def] of entries) {
|
|
3300
3314
|
assertIdentifier(name, "struct name");
|
|
3301
3315
|
if (name !== "QRLDomain" && isReservedAtomicTypeName(name)) {
|
|
3302
|
-
throw new Error(`struct name is reserved by an atomic type: ${name}`);
|
|
3316
|
+
throw new Error(`struct name is reserved by an atomic type: ${inputPreview(name)}`);
|
|
3303
3317
|
}
|
|
3304
3318
|
const defUnknown = def;
|
|
3305
3319
|
if (!Array.isArray(defUnknown) || def.length === 0 || def.length > TYPED_DATA_LIMITS.maxFieldsPerType) {
|
|
3306
|
-
throw new Error(`empty or invalid struct: ${name}`);
|
|
3320
|
+
throw new Error(`empty or invalid struct: ${inputPreview(name)}`);
|
|
3307
3321
|
}
|
|
3308
3322
|
totalFields += def.length;
|
|
3309
3323
|
if (totalFields > TYPED_DATA_LIMITS.maxTotalFields) {
|
|
@@ -3312,14 +3326,17 @@ function validateTypeMap(types) {
|
|
|
3312
3326
|
const seen = /* @__PURE__ */ new Set();
|
|
3313
3327
|
for (const f of def) {
|
|
3314
3328
|
if (!f || typeof f.name !== "string" || !f.name) {
|
|
3315
|
-
throw new Error(`bad field in ${name}`);
|
|
3329
|
+
throw new Error(`bad field in ${inputPreview(name)}`);
|
|
3316
3330
|
}
|
|
3317
|
-
assertIdentifier(f.name, `field name in ${name}`);
|
|
3331
|
+
assertIdentifier(f.name, `field name in ${inputPreview(name)}`);
|
|
3318
3332
|
if (typeof f.type !== "string" || !f.type) {
|
|
3319
|
-
throw new Error(`bad field type in ${name}.${f.name}`);
|
|
3333
|
+
throw new Error(`bad field type in ${inputPreview(name)}.${inputPreview(f.name)}`);
|
|
3334
|
+
}
|
|
3335
|
+
if (f.type.length > TYPED_DATA_LIMITS.maxFieldTypeLength) {
|
|
3336
|
+
throw new Error(`field type too long: ${inputPreview(f.type)}`);
|
|
3320
3337
|
}
|
|
3321
3338
|
if (seen.has(f.name)) {
|
|
3322
|
-
throw new Error(`duplicate field "${f.name}" in ${name}`);
|
|
3339
|
+
throw new Error(`duplicate field "${inputPreview(f.name)}" in ${inputPreview(name)}`);
|
|
3323
3340
|
}
|
|
3324
3341
|
seen.add(f.name);
|
|
3325
3342
|
}
|
|
@@ -3331,7 +3348,7 @@ function encodeType(primary, types) {
|
|
|
3331
3348
|
const others = [...deps].filter((n) => n !== primary).sort();
|
|
3332
3349
|
return [primary, ...others].map((name) => {
|
|
3333
3350
|
const fields = types[name];
|
|
3334
|
-
if (!fields) throw new Error(`unknown type: ${name}`);
|
|
3351
|
+
if (!fields) throw new Error(`unknown type: ${inputPreview(name)}`);
|
|
3335
3352
|
const inner = fields.map((f) => `${f.type} ${f.name}`).join(",");
|
|
3336
3353
|
return `${name}(${inner})`;
|
|
3337
3354
|
}).join("");
|
|
@@ -3341,7 +3358,7 @@ function typeHash(primary, types) {
|
|
|
3341
3358
|
}
|
|
3342
3359
|
function parseQAddress(addr, slot) {
|
|
3343
3360
|
if (!isCurrentQrlAddress(addr)) {
|
|
3344
|
-
throw new Error(`invalid Q-address: ${String(addr)}`);
|
|
3361
|
+
throw new Error(`invalid Q-address: ${inputPreview(String(addr))}`);
|
|
3345
3362
|
}
|
|
3346
3363
|
const bytes = hexToBytes("0x" + addr.slice(1).toLowerCase());
|
|
3347
3364
|
if (bytes.length > slot) {
|
|
@@ -3365,12 +3382,13 @@ function bigIntToSlot(value, width, signed, slot) {
|
|
|
3365
3382
|
if (signed) {
|
|
3366
3383
|
const limit = 1n << BigInt(width - 1);
|
|
3367
3384
|
if (value >= limit || value < -limit) {
|
|
3368
|
-
throw new Error(`int${width} out of range: ${value}`);
|
|
3385
|
+
throw new Error(`int${width} out of range: ${inputPreview(String(value))}`);
|
|
3369
3386
|
}
|
|
3370
3387
|
} else {
|
|
3371
|
-
if (value < 0n) throw new Error(`uint${width} negative: ${value}`);
|
|
3388
|
+
if (value < 0n) throw new Error(`uint${width} negative: ${inputPreview(String(value))}`);
|
|
3372
3389
|
const limit = 1n << BigInt(width);
|
|
3373
|
-
if (value >= limit)
|
|
3390
|
+
if (value >= limit)
|
|
3391
|
+
throw new Error(`uint${width} out of range: ${inputPreview(String(value))}`);
|
|
3374
3392
|
}
|
|
3375
3393
|
const slotBits = BigInt(slot * 8);
|
|
3376
3394
|
const slotMask = (1n << slotBits) - 1n;
|
|
@@ -3393,7 +3411,7 @@ function parseIntValue(v, typeLabel) {
|
|
|
3393
3411
|
return isNegative ? -abs : abs;
|
|
3394
3412
|
}
|
|
3395
3413
|
if (!/^-?(0|[1-9]\d*)$/.test(v)) {
|
|
3396
|
-
throw new Error(`invalid ${typeLabel} string: ${v}`);
|
|
3414
|
+
throw new Error(`invalid ${typeLabel} string: ${inputPreview(v)}`);
|
|
3397
3415
|
}
|
|
3398
3416
|
return BigInt(v);
|
|
3399
3417
|
}
|
|
@@ -3407,14 +3425,14 @@ function parseIntValue(v, typeLabel) {
|
|
|
3407
3425
|
}
|
|
3408
3426
|
function encodeFieldWithBudget(type, value, types, budget, depth) {
|
|
3409
3427
|
if (depth > TYPED_DATA_LIMITS.maxTypeGraphDepth + TYPED_DATA_LIMITS.maxArrayNesting) {
|
|
3410
|
-
throw new Error(`value nesting too deep: ${type}`);
|
|
3428
|
+
throw new Error(`value nesting too deep: ${inputPreview(type)}`);
|
|
3411
3429
|
}
|
|
3412
3430
|
consumeValue(budget);
|
|
3413
3431
|
const parsed = parseFieldType(type, types);
|
|
3414
3432
|
switch (parsed.kind) {
|
|
3415
3433
|
case "ref":
|
|
3416
3434
|
if (!isMessageObject(value)) {
|
|
3417
|
-
throw new Error(`struct field expects object: ${type}`);
|
|
3435
|
+
throw new Error(`struct field expects object: ${inputPreview(type)}`);
|
|
3418
3436
|
}
|
|
3419
3437
|
return hashStructWithBudget(parsed.name, value, types, budget, depth + 1);
|
|
3420
3438
|
case "address":
|
|
@@ -3480,10 +3498,12 @@ function encodeFieldWithBudget(type, value, types, budget, depth) {
|
|
|
3480
3498
|
throw new Error(`array field expects array: ${typeof value}`);
|
|
3481
3499
|
}
|
|
3482
3500
|
if (value.length > TYPED_DATA_LIMITS.maxArrayLength) {
|
|
3483
|
-
throw new Error(`array ${type} exceeds length limit`);
|
|
3501
|
+
throw new Error(`array ${inputPreview(type)} exceeds length limit`);
|
|
3484
3502
|
}
|
|
3485
3503
|
if (parsed.size !== void 0 && value.length !== parsed.size) {
|
|
3486
|
-
throw new Error(
|
|
3504
|
+
throw new Error(
|
|
3505
|
+
`fixed array ${inputPreview(type)} requires length ${parsed.size}, got ${value.length}`
|
|
3506
|
+
);
|
|
3487
3507
|
}
|
|
3488
3508
|
const chunks = value.map(
|
|
3489
3509
|
(v) => encodeFieldWithBudget(parsed.inner, v, types, budget, depth + 1)
|
|
@@ -3500,7 +3520,7 @@ function encodeField(type, value, types, schemeVersion) {
|
|
|
3500
3520
|
function hashStructWithBudget(primary, data, types, budget, depth) {
|
|
3501
3521
|
consumeValue(budget);
|
|
3502
3522
|
const fields = types[primary];
|
|
3503
|
-
if (!fields) throw new Error(`unknown struct: ${primary}`);
|
|
3523
|
+
if (!fields) throw new Error(`unknown struct: ${inputPreview(primary)}`);
|
|
3504
3524
|
const expected = new Set(fields.map((f) => f.name));
|
|
3505
3525
|
let ownFieldCount = 0;
|
|
3506
3526
|
for (const k in data) {
|
|
@@ -3509,12 +3529,14 @@ function hashStructWithBudget(primary, data, types, budget, depth) {
|
|
|
3509
3529
|
if (ownFieldCount > TYPED_DATA_LIMITS.maxEncodedValues) {
|
|
3510
3530
|
throw new Error("typed data object contains too many fields");
|
|
3511
3531
|
}
|
|
3512
|
-
if (!expected.has(k))
|
|
3532
|
+
if (!expected.has(k)) {
|
|
3533
|
+
throw new Error(`unknown field in ${inputPreview(primary)}: ${inputPreview(k)}`);
|
|
3534
|
+
}
|
|
3513
3535
|
}
|
|
3514
3536
|
const parts = [typeHash(primary, types)];
|
|
3515
3537
|
for (const f of fields) {
|
|
3516
3538
|
if (!Object.prototype.hasOwnProperty.call(data, f.name)) {
|
|
3517
|
-
throw new Error(`missing field ${primary}.${f.name}`);
|
|
3539
|
+
throw new Error(`missing field ${inputPreview(primary)}.${inputPreview(f.name)}`);
|
|
3518
3540
|
}
|
|
3519
3541
|
parts.push(encodeFieldWithBudget(f.type, data[f.name], types, budget, depth + 1));
|
|
3520
3542
|
}
|
|
@@ -3540,11 +3562,13 @@ function validateDomainTypes(types) {
|
|
|
3540
3562
|
const expected = RESERVED_DOMAIN_FIELDS[f.name];
|
|
3541
3563
|
if (!expected) {
|
|
3542
3564
|
throw new Error(
|
|
3543
|
-
`QRLDomain field "${f.name}" not in reserved set (name, version, chainId, verifyingContract, salt)`
|
|
3565
|
+
`QRLDomain field "${inputPreview(f.name)}" not in reserved set (name, version, chainId, verifyingContract, salt)`
|
|
3544
3566
|
);
|
|
3545
3567
|
}
|
|
3546
3568
|
if (f.type !== expected) {
|
|
3547
|
-
throw new Error(
|
|
3569
|
+
throw new Error(
|
|
3570
|
+
`QRLDomain field "${inputPreview(f.name)}" must be type "${expected}", got "${inputPreview(f.type)}"`
|
|
3571
|
+
);
|
|
3548
3572
|
}
|
|
3549
3573
|
if (f.name === "name") hasName = true;
|
|
3550
3574
|
}
|
|
@@ -3556,7 +3580,7 @@ function validatePayloadReachability(primary, types) {
|
|
|
3556
3580
|
for (const t of collectDependencies(root, types)) reachable.add(t);
|
|
3557
3581
|
}
|
|
3558
3582
|
for (const k of Object.keys(types)) {
|
|
3559
|
-
if (!reachable.has(k)) throw new Error(`unused referenced type: ${k}`);
|
|
3583
|
+
if (!reachable.has(k)) throw new Error(`unused referenced type: ${inputPreview(k)}`);
|
|
3560
3584
|
}
|
|
3561
3585
|
}
|
|
3562
3586
|
function parseAndValidatePayload(payload) {
|
package/dist/index.mjs
CHANGED
|
@@ -3088,17 +3088,20 @@ function consumeValue(budget) {
|
|
|
3088
3088
|
budget.remainingValues--;
|
|
3089
3089
|
if (budget.remainingValues < 0) throw new Error("typed data contains too many encoded values");
|
|
3090
3090
|
}
|
|
3091
|
+
function inputPreview(value) {
|
|
3092
|
+
return value.length > 32 ? `${value.slice(0, 32)}... (length ${value.length})` : value;
|
|
3093
|
+
}
|
|
3091
3094
|
function assertIdentifier(value, label) {
|
|
3092
3095
|
if (!IDENTIFIER_RE.test(value) || value.length > TYPED_DATA_LIMITS.maxIdentifierLength || UNSAFE_OBJECT_KEYS.has(value)) {
|
|
3093
|
-
throw new Error(`invalid ${label}: ${value}`);
|
|
3096
|
+
throw new Error(`invalid ${label}: ${inputPreview(value)}`);
|
|
3094
3097
|
}
|
|
3095
3098
|
}
|
|
3096
3099
|
function parseFieldType(type, types, depth = 0) {
|
|
3097
3100
|
if (depth > TYPED_DATA_LIMITS.maxArrayNesting) {
|
|
3098
|
-
throw new Error(`type nesting too deep: ${type}`);
|
|
3101
|
+
throw new Error(`type nesting too deep: ${inputPreview(type)}`);
|
|
3099
3102
|
}
|
|
3100
3103
|
if (type.length > TYPED_DATA_LIMITS.maxFieldTypeLength) {
|
|
3101
|
-
throw new Error(`field type too long: ${type}`);
|
|
3104
|
+
throw new Error(`field type too long: ${inputPreview(type)}`);
|
|
3102
3105
|
}
|
|
3103
3106
|
const m = ATOMIC_RE.exec(type);
|
|
3104
3107
|
if (m) {
|
|
@@ -3109,14 +3112,14 @@ function parseFieldType(type, types, depth = 0) {
|
|
|
3109
3112
|
if (intKind) {
|
|
3110
3113
|
const width = Number(intWidthStr);
|
|
3111
3114
|
if (!Number.isInteger(width) || width < 8 || width > 256 || width % 8 !== 0) {
|
|
3112
|
-
throw new Error(`invalid int width: ${type}`);
|
|
3115
|
+
throw new Error(`invalid int width: ${inputPreview(type)}`);
|
|
3113
3116
|
}
|
|
3114
3117
|
return { kind: intKind === "uint" ? "uintN" : "intN", width };
|
|
3115
3118
|
}
|
|
3116
3119
|
if (bytesWidthStr) {
|
|
3117
3120
|
const width = Number(bytesWidthStr);
|
|
3118
3121
|
if (!Number.isInteger(width) || width < 1 || width > 32) {
|
|
3119
|
-
throw new Error(`invalid bytesN width: ${type}`);
|
|
3122
|
+
throw new Error(`invalid bytesN width: ${inputPreview(type)}`);
|
|
3120
3123
|
}
|
|
3121
3124
|
return { kind: "bytesN", width };
|
|
3122
3125
|
}
|
|
@@ -3125,7 +3128,7 @@ function parseFieldType(type, types, depth = 0) {
|
|
|
3125
3128
|
if (sizeStr) {
|
|
3126
3129
|
const size = Number(sizeStr);
|
|
3127
3130
|
if (!Number.isSafeInteger(size) || size <= 0 || size > TYPED_DATA_LIMITS.maxArrayLength) {
|
|
3128
|
-
throw new Error(`invalid array size: ${type}`);
|
|
3131
|
+
throw new Error(`invalid array size: ${inputPreview(type)}`);
|
|
3129
3132
|
}
|
|
3130
3133
|
return { kind: "array", inner: innerType, size };
|
|
3131
3134
|
}
|
|
@@ -3135,7 +3138,7 @@ function parseFieldType(type, types, depth = 0) {
|
|
|
3135
3138
|
if (Object.prototype.hasOwnProperty.call(types, type)) {
|
|
3136
3139
|
return { kind: "ref", name: type };
|
|
3137
3140
|
}
|
|
3138
|
-
throw new Error(`unknown type: ${type}`);
|
|
3141
|
+
throw new Error(`unknown type: ${inputPreview(type)}`);
|
|
3139
3142
|
}
|
|
3140
3143
|
function isReservedAtomicTypeName(name) {
|
|
3141
3144
|
if (/^(?:address|bool|string|bytes)$/.test(name)) return true;
|
|
@@ -3152,24 +3155,35 @@ function isReservedAtomicTypeName(name) {
|
|
|
3152
3155
|
return false;
|
|
3153
3156
|
}
|
|
3154
3157
|
function baseTypeName(type) {
|
|
3155
|
-
|
|
3158
|
+
let end = type.length;
|
|
3159
|
+
while (end > 0 && type[end - 1] === "]") {
|
|
3160
|
+
let start = end - 2;
|
|
3161
|
+
while (start >= 0) {
|
|
3162
|
+
const code = type.charCodeAt(start);
|
|
3163
|
+
if (code < 48 || code > 57) break;
|
|
3164
|
+
start--;
|
|
3165
|
+
}
|
|
3166
|
+
if (start < 0 || type[start] !== "[") break;
|
|
3167
|
+
end = start;
|
|
3168
|
+
}
|
|
3169
|
+
return type.slice(0, end);
|
|
3156
3170
|
}
|
|
3157
3171
|
function collectDependencies(primary, types) {
|
|
3158
3172
|
if (!Object.prototype.hasOwnProperty.call(types, primary)) {
|
|
3159
|
-
throw new Error(`unknown primary type: ${primary}`);
|
|
3173
|
+
throw new Error(`unknown primary type: ${inputPreview(primary)}`);
|
|
3160
3174
|
}
|
|
3161
3175
|
const visited = /* @__PURE__ */ new Set();
|
|
3162
3176
|
const visit = (name, path) => {
|
|
3163
3177
|
if (path.length > TYPED_DATA_LIMITS.maxTypeGraphDepth) {
|
|
3164
|
-
throw new Error(`type graph nesting too deep: ${[...path, name].join(" -> ")}`);
|
|
3178
|
+
throw new Error(`type graph nesting too deep: ${inputPreview([...path, name].join(" -> "))}`);
|
|
3165
3179
|
}
|
|
3166
3180
|
if (path.includes(name)) {
|
|
3167
|
-
throw new Error(`cyclic type reference: ${[...path, name].join(" -> ")}`);
|
|
3181
|
+
throw new Error(`cyclic type reference: ${inputPreview([...path, name].join(" -> "))}`);
|
|
3168
3182
|
}
|
|
3169
3183
|
if (visited.has(name)) return;
|
|
3170
3184
|
visited.add(name);
|
|
3171
3185
|
const def = types[name];
|
|
3172
|
-
if (!def) throw new Error(`unknown type: ${name}`);
|
|
3186
|
+
if (!def) throw new Error(`unknown type: ${inputPreview(name)}`);
|
|
3173
3187
|
for (const f of def) {
|
|
3174
3188
|
const base = baseTypeName(f.type);
|
|
3175
3189
|
if (Object.prototype.hasOwnProperty.call(types, base)) {
|
|
@@ -3190,11 +3204,11 @@ function validateTypeMap(types) {
|
|
|
3190
3204
|
for (const [name, def] of entries) {
|
|
3191
3205
|
assertIdentifier(name, "struct name");
|
|
3192
3206
|
if (name !== "QRLDomain" && isReservedAtomicTypeName(name)) {
|
|
3193
|
-
throw new Error(`struct name is reserved by an atomic type: ${name}`);
|
|
3207
|
+
throw new Error(`struct name is reserved by an atomic type: ${inputPreview(name)}`);
|
|
3194
3208
|
}
|
|
3195
3209
|
const defUnknown = def;
|
|
3196
3210
|
if (!Array.isArray(defUnknown) || def.length === 0 || def.length > TYPED_DATA_LIMITS.maxFieldsPerType) {
|
|
3197
|
-
throw new Error(`empty or invalid struct: ${name}`);
|
|
3211
|
+
throw new Error(`empty or invalid struct: ${inputPreview(name)}`);
|
|
3198
3212
|
}
|
|
3199
3213
|
totalFields += def.length;
|
|
3200
3214
|
if (totalFields > TYPED_DATA_LIMITS.maxTotalFields) {
|
|
@@ -3203,14 +3217,17 @@ function validateTypeMap(types) {
|
|
|
3203
3217
|
const seen = /* @__PURE__ */ new Set();
|
|
3204
3218
|
for (const f of def) {
|
|
3205
3219
|
if (!f || typeof f.name !== "string" || !f.name) {
|
|
3206
|
-
throw new Error(`bad field in ${name}`);
|
|
3220
|
+
throw new Error(`bad field in ${inputPreview(name)}`);
|
|
3207
3221
|
}
|
|
3208
|
-
assertIdentifier(f.name, `field name in ${name}`);
|
|
3222
|
+
assertIdentifier(f.name, `field name in ${inputPreview(name)}`);
|
|
3209
3223
|
if (typeof f.type !== "string" || !f.type) {
|
|
3210
|
-
throw new Error(`bad field type in ${name}.${f.name}`);
|
|
3224
|
+
throw new Error(`bad field type in ${inputPreview(name)}.${inputPreview(f.name)}`);
|
|
3225
|
+
}
|
|
3226
|
+
if (f.type.length > TYPED_DATA_LIMITS.maxFieldTypeLength) {
|
|
3227
|
+
throw new Error(`field type too long: ${inputPreview(f.type)}`);
|
|
3211
3228
|
}
|
|
3212
3229
|
if (seen.has(f.name)) {
|
|
3213
|
-
throw new Error(`duplicate field "${f.name}" in ${name}`);
|
|
3230
|
+
throw new Error(`duplicate field "${inputPreview(f.name)}" in ${inputPreview(name)}`);
|
|
3214
3231
|
}
|
|
3215
3232
|
seen.add(f.name);
|
|
3216
3233
|
}
|
|
@@ -3222,7 +3239,7 @@ function encodeType(primary, types) {
|
|
|
3222
3239
|
const others = [...deps].filter((n) => n !== primary).sort();
|
|
3223
3240
|
return [primary, ...others].map((name) => {
|
|
3224
3241
|
const fields = types[name];
|
|
3225
|
-
if (!fields) throw new Error(`unknown type: ${name}`);
|
|
3242
|
+
if (!fields) throw new Error(`unknown type: ${inputPreview(name)}`);
|
|
3226
3243
|
const inner = fields.map((f) => `${f.type} ${f.name}`).join(",");
|
|
3227
3244
|
return `${name}(${inner})`;
|
|
3228
3245
|
}).join("");
|
|
@@ -3232,7 +3249,7 @@ function typeHash(primary, types) {
|
|
|
3232
3249
|
}
|
|
3233
3250
|
function parseQAddress(addr, slot) {
|
|
3234
3251
|
if (!isCurrentQrlAddress(addr)) {
|
|
3235
|
-
throw new Error(`invalid Q-address: ${String(addr)}`);
|
|
3252
|
+
throw new Error(`invalid Q-address: ${inputPreview(String(addr))}`);
|
|
3236
3253
|
}
|
|
3237
3254
|
const bytes = hexToBytes("0x" + addr.slice(1).toLowerCase());
|
|
3238
3255
|
if (bytes.length > slot) {
|
|
@@ -3256,12 +3273,13 @@ function bigIntToSlot(value, width, signed, slot) {
|
|
|
3256
3273
|
if (signed) {
|
|
3257
3274
|
const limit = 1n << BigInt(width - 1);
|
|
3258
3275
|
if (value >= limit || value < -limit) {
|
|
3259
|
-
throw new Error(`int${width} out of range: ${value}`);
|
|
3276
|
+
throw new Error(`int${width} out of range: ${inputPreview(String(value))}`);
|
|
3260
3277
|
}
|
|
3261
3278
|
} else {
|
|
3262
|
-
if (value < 0n) throw new Error(`uint${width} negative: ${value}`);
|
|
3279
|
+
if (value < 0n) throw new Error(`uint${width} negative: ${inputPreview(String(value))}`);
|
|
3263
3280
|
const limit = 1n << BigInt(width);
|
|
3264
|
-
if (value >= limit)
|
|
3281
|
+
if (value >= limit)
|
|
3282
|
+
throw new Error(`uint${width} out of range: ${inputPreview(String(value))}`);
|
|
3265
3283
|
}
|
|
3266
3284
|
const slotBits = BigInt(slot * 8);
|
|
3267
3285
|
const slotMask = (1n << slotBits) - 1n;
|
|
@@ -3284,7 +3302,7 @@ function parseIntValue(v, typeLabel) {
|
|
|
3284
3302
|
return isNegative ? -abs : abs;
|
|
3285
3303
|
}
|
|
3286
3304
|
if (!/^-?(0|[1-9]\d*)$/.test(v)) {
|
|
3287
|
-
throw new Error(`invalid ${typeLabel} string: ${v}`);
|
|
3305
|
+
throw new Error(`invalid ${typeLabel} string: ${inputPreview(v)}`);
|
|
3288
3306
|
}
|
|
3289
3307
|
return BigInt(v);
|
|
3290
3308
|
}
|
|
@@ -3298,14 +3316,14 @@ function parseIntValue(v, typeLabel) {
|
|
|
3298
3316
|
}
|
|
3299
3317
|
function encodeFieldWithBudget(type, value, types, budget, depth) {
|
|
3300
3318
|
if (depth > TYPED_DATA_LIMITS.maxTypeGraphDepth + TYPED_DATA_LIMITS.maxArrayNesting) {
|
|
3301
|
-
throw new Error(`value nesting too deep: ${type}`);
|
|
3319
|
+
throw new Error(`value nesting too deep: ${inputPreview(type)}`);
|
|
3302
3320
|
}
|
|
3303
3321
|
consumeValue(budget);
|
|
3304
3322
|
const parsed = parseFieldType(type, types);
|
|
3305
3323
|
switch (parsed.kind) {
|
|
3306
3324
|
case "ref":
|
|
3307
3325
|
if (!isMessageObject(value)) {
|
|
3308
|
-
throw new Error(`struct field expects object: ${type}`);
|
|
3326
|
+
throw new Error(`struct field expects object: ${inputPreview(type)}`);
|
|
3309
3327
|
}
|
|
3310
3328
|
return hashStructWithBudget(parsed.name, value, types, budget, depth + 1);
|
|
3311
3329
|
case "address":
|
|
@@ -3371,10 +3389,12 @@ function encodeFieldWithBudget(type, value, types, budget, depth) {
|
|
|
3371
3389
|
throw new Error(`array field expects array: ${typeof value}`);
|
|
3372
3390
|
}
|
|
3373
3391
|
if (value.length > TYPED_DATA_LIMITS.maxArrayLength) {
|
|
3374
|
-
throw new Error(`array ${type} exceeds length limit`);
|
|
3392
|
+
throw new Error(`array ${inputPreview(type)} exceeds length limit`);
|
|
3375
3393
|
}
|
|
3376
3394
|
if (parsed.size !== void 0 && value.length !== parsed.size) {
|
|
3377
|
-
throw new Error(
|
|
3395
|
+
throw new Error(
|
|
3396
|
+
`fixed array ${inputPreview(type)} requires length ${parsed.size}, got ${value.length}`
|
|
3397
|
+
);
|
|
3378
3398
|
}
|
|
3379
3399
|
const chunks = value.map(
|
|
3380
3400
|
(v) => encodeFieldWithBudget(parsed.inner, v, types, budget, depth + 1)
|
|
@@ -3391,7 +3411,7 @@ function encodeField(type, value, types, schemeVersion) {
|
|
|
3391
3411
|
function hashStructWithBudget(primary, data, types, budget, depth) {
|
|
3392
3412
|
consumeValue(budget);
|
|
3393
3413
|
const fields = types[primary];
|
|
3394
|
-
if (!fields) throw new Error(`unknown struct: ${primary}`);
|
|
3414
|
+
if (!fields) throw new Error(`unknown struct: ${inputPreview(primary)}`);
|
|
3395
3415
|
const expected = new Set(fields.map((f) => f.name));
|
|
3396
3416
|
let ownFieldCount = 0;
|
|
3397
3417
|
for (const k in data) {
|
|
@@ -3400,12 +3420,14 @@ function hashStructWithBudget(primary, data, types, budget, depth) {
|
|
|
3400
3420
|
if (ownFieldCount > TYPED_DATA_LIMITS.maxEncodedValues) {
|
|
3401
3421
|
throw new Error("typed data object contains too many fields");
|
|
3402
3422
|
}
|
|
3403
|
-
if (!expected.has(k))
|
|
3423
|
+
if (!expected.has(k)) {
|
|
3424
|
+
throw new Error(`unknown field in ${inputPreview(primary)}: ${inputPreview(k)}`);
|
|
3425
|
+
}
|
|
3404
3426
|
}
|
|
3405
3427
|
const parts = [typeHash(primary, types)];
|
|
3406
3428
|
for (const f of fields) {
|
|
3407
3429
|
if (!Object.prototype.hasOwnProperty.call(data, f.name)) {
|
|
3408
|
-
throw new Error(`missing field ${primary}.${f.name}`);
|
|
3430
|
+
throw new Error(`missing field ${inputPreview(primary)}.${inputPreview(f.name)}`);
|
|
3409
3431
|
}
|
|
3410
3432
|
parts.push(encodeFieldWithBudget(f.type, data[f.name], types, budget, depth + 1));
|
|
3411
3433
|
}
|
|
@@ -3431,11 +3453,13 @@ function validateDomainTypes(types) {
|
|
|
3431
3453
|
const expected = RESERVED_DOMAIN_FIELDS[f.name];
|
|
3432
3454
|
if (!expected) {
|
|
3433
3455
|
throw new Error(
|
|
3434
|
-
`QRLDomain field "${f.name}" not in reserved set (name, version, chainId, verifyingContract, salt)`
|
|
3456
|
+
`QRLDomain field "${inputPreview(f.name)}" not in reserved set (name, version, chainId, verifyingContract, salt)`
|
|
3435
3457
|
);
|
|
3436
3458
|
}
|
|
3437
3459
|
if (f.type !== expected) {
|
|
3438
|
-
throw new Error(
|
|
3460
|
+
throw new Error(
|
|
3461
|
+
`QRLDomain field "${inputPreview(f.name)}" must be type "${expected}", got "${inputPreview(f.type)}"`
|
|
3462
|
+
);
|
|
3439
3463
|
}
|
|
3440
3464
|
if (f.name === "name") hasName = true;
|
|
3441
3465
|
}
|
|
@@ -3447,7 +3471,7 @@ function validatePayloadReachability(primary, types) {
|
|
|
3447
3471
|
for (const t of collectDependencies(root, types)) reachable.add(t);
|
|
3448
3472
|
}
|
|
3449
3473
|
for (const k of Object.keys(types)) {
|
|
3450
|
-
if (!reachable.has(k)) throw new Error(`unused referenced type: ${k}`);
|
|
3474
|
+
if (!reachable.has(k)) throw new Error(`unused referenced type: ${inputPreview(k)}`);
|
|
3451
3475
|
}
|
|
3452
3476
|
}
|
|
3453
3477
|
function parseAndValidatePayload(payload) {
|