From aaf0a7e9e8c10c5fc1044fdec3a2fd2e044f1442 Mon Sep 17 00:00:00 2001 From: a1denvalu3 Date: Thu, 26 Mar 2026 15:48:59 +0100 Subject: [PATCH 1/7] feat: add preferred_mints field to payment requests --- 18.md | 2 ++ 26.md | 21 +++++++++++---------- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/18.md b/18.md index 34571360..952495b5 100644 --- a/18.md +++ b/18.md @@ -24,6 +24,7 @@ A Payment Request is defined as follows "u": str , "s": bool , "m": Array[str] , + "pm": Array[str] , "d": str , "t": Array[Transport] , "nut10": NUT10Option , @@ -37,6 +38,7 @@ Here, the fields are - `u`: The unit of the requested payment (MUST be set if `a` is set) - `s`: Whether the payment request is for single use - `m`: A set of mints from which the payment is requested +- `pm`: A set of preferred mints the receiver supports. The sender can choose to pay from one of these mints for faster and cheaper transactions - `d`: A human readable description that the sending wallet will display after scanning the request - `t`: The method of `Transport` chosen to transmit the payment (can be multiple, sorted by preference) - `nut10`: The required [NUT-10][10] locking condition diff --git a/26.md b/26.md index 555d8bcf..74bbb257 100644 --- a/26.md +++ b/26.md @@ -33,16 +33,17 @@ The payment request is encoded as a sequence of TLV fields. Each TLV entry consi ### Top-Level TLV Tags -| Tag | Field | Type | Description | -| ---- | ----------- | --------- | -------------------------------------------------------------------- | -| 0x01 | id | string | Payment identifier (corresponds to `i` in JSON) | -| 0x02 | amount | u64 | Amount in base units (corresponds to `a` in JSON) | -| 0x03 | unit | u8/string | Currency unit (corresponds to `u` in JSON) | -| 0x04 | single_use | u8 | Single-use flag: 0=false, 1=true (corresponds to `s` in JSON) | -| 0x05 | mint | string | Mint URL (repeatable for multiple mints, corresponds to `m` in JSON) | -| 0x06 | description | string | Human-readable description (corresponds to `d` in JSON) | -| 0x07 | transport | sub-TLV | Transport configuration (repeatable, corresponds to `t` in JSON) | -| 0x08 | nut10 | sub-TLV | NUT-10 spending conditions (corresponds to `nut10` in JSON) | +| Tag | Field | Type | Description | +| ---- | -------------- | --------- | -------------------------------------------------------------------- | +| 0x01 | id | string | Payment identifier (corresponds to `i` in JSON) | +| 0x02 | amount | u64 | Amount in base units (corresponds to `a` in JSON) | +| 0x03 | unit | u8/string | Currency unit (corresponds to `u` in JSON) | +| 0x04 | single_use | u8 | Single-use flag: 0=false, 1=true (corresponds to `s` in JSON) | +| 0x05 | mint | string | Mint URL (repeatable for multiple mints, corresponds to `m` in JSON) | +| 0x06 | description | string | Human-readable description (corresponds to `d` in JSON) | +| 0x07 | transport | sub-TLV | Transport configuration (repeatable, corresponds to `t` in JSON) | +| 0x08 | nut10 | sub-TLV | NUT-10 spending conditions (corresponds to `nut10` in JSON) | +| 0x09 | preferred_mint | string | Preferred mint URL (repeatable for multiple mints, corresponds to `pm` in JSON) | All fields are optional. Unknown tags MUST be ignored to maintain forward compatibility. From 2f792837c4ef2e860c387f93e3cb652fcc722b02 Mon Sep 17 00:00:00 2001 From: a1denvalu3 Date: Thu, 26 Mar 2026 15:56:30 +0100 Subject: [PATCH 2/7] prettier --- 26.md | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/26.md b/26.md index 74bbb257..52471395 100644 --- a/26.md +++ b/26.md @@ -33,16 +33,16 @@ The payment request is encoded as a sequence of TLV fields. Each TLV entry consi ### Top-Level TLV Tags -| Tag | Field | Type | Description | -| ---- | -------------- | --------- | -------------------------------------------------------------------- | -| 0x01 | id | string | Payment identifier (corresponds to `i` in JSON) | -| 0x02 | amount | u64 | Amount in base units (corresponds to `a` in JSON) | -| 0x03 | unit | u8/string | Currency unit (corresponds to `u` in JSON) | -| 0x04 | single_use | u8 | Single-use flag: 0=false, 1=true (corresponds to `s` in JSON) | -| 0x05 | mint | string | Mint URL (repeatable for multiple mints, corresponds to `m` in JSON) | -| 0x06 | description | string | Human-readable description (corresponds to `d` in JSON) | -| 0x07 | transport | sub-TLV | Transport configuration (repeatable, corresponds to `t` in JSON) | -| 0x08 | nut10 | sub-TLV | NUT-10 spending conditions (corresponds to `nut10` in JSON) | +| Tag | Field | Type | Description | +| ---- | -------------- | --------- | ------------------------------------------------------------------------------- | +| 0x01 | id | string | Payment identifier (corresponds to `i` in JSON) | +| 0x02 | amount | u64 | Amount in base units (corresponds to `a` in JSON) | +| 0x03 | unit | u8/string | Currency unit (corresponds to `u` in JSON) | +| 0x04 | single_use | u8 | Single-use flag: 0=false, 1=true (corresponds to `s` in JSON) | +| 0x05 | mint | string | Mint URL (repeatable for multiple mints, corresponds to `m` in JSON) | +| 0x06 | description | string | Human-readable description (corresponds to `d` in JSON) | +| 0x07 | transport | sub-TLV | Transport configuration (repeatable, corresponds to `t` in JSON) | +| 0x08 | nut10 | sub-TLV | NUT-10 spending conditions (corresponds to `nut10` in JSON) | | 0x09 | preferred_mint | string | Preferred mint URL (repeatable for multiple mints, corresponds to `pm` in JSON) | All fields are optional. Unknown tags MUST be ignored to maintain forward compatibility. From 16247e7fd0330177de8f90015c0cc1550338db1b Mon Sep 17 00:00:00 2001 From: a1denvalu3 Date: Thu, 26 Mar 2026 15:58:34 +0100 Subject: [PATCH 3/7] fix(nut-26): rename preferred_mint to preferred_mints --- 26.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/26.md b/26.md index 52471395..4a45edd3 100644 --- a/26.md +++ b/26.md @@ -42,8 +42,8 @@ The payment request is encoded as a sequence of TLV fields. Each TLV entry consi | 0x05 | mint | string | Mint URL (repeatable for multiple mints, corresponds to `m` in JSON) | | 0x06 | description | string | Human-readable description (corresponds to `d` in JSON) | | 0x07 | transport | sub-TLV | Transport configuration (repeatable, corresponds to `t` in JSON) | -| 0x08 | nut10 | sub-TLV | NUT-10 spending conditions (corresponds to `nut10` in JSON) | -| 0x09 | preferred_mint | string | Preferred mint URL (repeatable for multiple mints, corresponds to `pm` in JSON) | +| 0x08 | nut10 | sub-TLV | NUT-10 spending conditions (corresponds to `nut10` in JSON) | +| 0x09 | preferred_mints | string | Preferred mint URL (repeatable for multiple mints, corresponds to `pm` in JSON) | All fields are optional. Unknown tags MUST be ignored to maintain forward compatibility. From 9e4c32ca258e19b1d691e47c4b8bb6dcb40a7428 Mon Sep 17 00:00:00 2001 From: a1denvalu3 Date: Thu, 26 Mar 2026 15:59:46 +0100 Subject: [PATCH 4/7] prettier --- 26.md | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/26.md b/26.md index 4a45edd3..8d8bc3c6 100644 --- a/26.md +++ b/26.md @@ -33,16 +33,16 @@ The payment request is encoded as a sequence of TLV fields. Each TLV entry consi ### Top-Level TLV Tags -| Tag | Field | Type | Description | -| ---- | -------------- | --------- | ------------------------------------------------------------------------------- | -| 0x01 | id | string | Payment identifier (corresponds to `i` in JSON) | -| 0x02 | amount | u64 | Amount in base units (corresponds to `a` in JSON) | -| 0x03 | unit | u8/string | Currency unit (corresponds to `u` in JSON) | -| 0x04 | single_use | u8 | Single-use flag: 0=false, 1=true (corresponds to `s` in JSON) | -| 0x05 | mint | string | Mint URL (repeatable for multiple mints, corresponds to `m` in JSON) | -| 0x06 | description | string | Human-readable description (corresponds to `d` in JSON) | -| 0x07 | transport | sub-TLV | Transport configuration (repeatable, corresponds to `t` in JSON) | -| 0x08 | nut10 | sub-TLV | NUT-10 spending conditions (corresponds to `nut10` in JSON) | +| Tag | Field | Type | Description | +| ---- | --------------- | --------- | ------------------------------------------------------------------------------- | +| 0x01 | id | string | Payment identifier (corresponds to `i` in JSON) | +| 0x02 | amount | u64 | Amount in base units (corresponds to `a` in JSON) | +| 0x03 | unit | u8/string | Currency unit (corresponds to `u` in JSON) | +| 0x04 | single_use | u8 | Single-use flag: 0=false, 1=true (corresponds to `s` in JSON) | +| 0x05 | mint | string | Mint URL (repeatable for multiple mints, corresponds to `m` in JSON) | +| 0x06 | description | string | Human-readable description (corresponds to `d` in JSON) | +| 0x07 | transport | sub-TLV | Transport configuration (repeatable, corresponds to `t` in JSON) | +| 0x08 | nut10 | sub-TLV | NUT-10 spending conditions (corresponds to `nut10` in JSON) | | 0x09 | preferred_mints | string | Preferred mint URL (repeatable for multiple mints, corresponds to `pm` in JSON) | All fields are optional. Unknown tags MUST be ignored to maintain forward compatibility. From 38cfb2f9d86a086df30b942075f4c5e7ebdc79ec Mon Sep 17 00:00:00 2001 From: a1denvalu3 Date: Thu, 26 Mar 2026 16:07:23 +0100 Subject: [PATCH 5/7] fix(nut-18): clarify mints vs preferred_mints usage --- 18.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/18.md b/18.md index 952495b5..1e0d0338 100644 --- a/18.md +++ b/18.md @@ -37,8 +37,8 @@ Here, the fields are - `a`: The amount of the requested payment - `u`: The unit of the requested payment (MUST be set if `a` is set) - `s`: Whether the payment request is for single use -- `m`: A set of mints from which the payment is requested -- `pm`: A set of preferred mints the receiver supports. The sender can choose to pay from one of these mints for faster and cheaper transactions +- `m`: A set of mints from which the payment is requested. If this field is defined, the receiver SHOULD only accept proofs from these mints. +- `pm`: A set of preferred mints the receiver supports. If this field is defined, the receiver will accept proofs from any mint but prefers these mints for faster and cheaper transactions. - `d`: A human readable description that the sending wallet will display after scanning the request - `t`: The method of `Transport` chosen to transmit the payment (can be multiple, sorted by preference) - `nut10`: The required [NUT-10][10] locking condition From bdd99d4bff42146c6712758a2023a51ba864657b Mon Sep 17 00:00:00 2001 From: a1denvalu3 <43107113+a1denvalu3@users.noreply.github.com> Date: Sat, 28 Mar 2026 19:46:57 +0100 Subject: [PATCH 6/7] Update 18.md Co-authored-by: Rob Woodgate --- 18.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/18.md b/18.md index 1e0d0338..a44b9ee0 100644 --- a/18.md +++ b/18.md @@ -37,7 +37,7 @@ Here, the fields are - `a`: The amount of the requested payment - `u`: The unit of the requested payment (MUST be set if `a` is set) - `s`: Whether the payment request is for single use -- `m`: A set of mints from which the payment is requested. If this field is defined, the receiver SHOULD only accept proofs from these mints. +- `m`: A set of mints from which the payment is requested. If this field is defined, the sender SHOULD only send proofs from these mints. - `pm`: A set of preferred mints the receiver supports. If this field is defined, the receiver will accept proofs from any mint but prefers these mints for faster and cheaper transactions. - `d`: A human readable description that the sending wallet will display after scanning the request - `t`: The method of `Transport` chosen to transmit the payment (can be multiple, sorted by preference) From fb34d43a13d21bda8e20ab208e3f64d148c50cde Mon Sep 17 00:00:00 2001 From: a1denvalu3 Date: Thu, 16 Apr 2026 14:13:57 +0200 Subject: [PATCH 7/7] fix(nut-18, nut-26): make m and pm mutually exclusive, add test vectors --- 18.md | 4 ++-- tests/18-tests.md | 19 +++++++++++++++++++ tests/26-test.md | 21 +++++++++++++++++++++ 3 files changed, 42 insertions(+), 2 deletions(-) diff --git a/18.md b/18.md index a44b9ee0..e4e58bff 100644 --- a/18.md +++ b/18.md @@ -37,8 +37,8 @@ Here, the fields are - `a`: The amount of the requested payment - `u`: The unit of the requested payment (MUST be set if `a` is set) - `s`: Whether the payment request is for single use -- `m`: A set of mints from which the payment is requested. If this field is defined, the sender SHOULD only send proofs from these mints. -- `pm`: A set of preferred mints the receiver supports. If this field is defined, the receiver will accept proofs from any mint but prefers these mints for faster and cheaper transactions. +- `m`: A set of mints from which the payment is requested. If this field is defined, the sender SHOULD only send proofs from these mints. The fields `m` and `pm` are mutually exclusive; a payment request MUST NOT contain both fields. +- `pm`: A set of preferred mints the receiver supports. If this field is defined, the receiver will accept proofs from any mint but prefers these mints for faster and cheaper transactions. The fields `m` and `pm` are mutually exclusive; a payment request MUST NOT contain both fields. - `d`: A human readable description that the sending wallet will display after scanning the request - `t`: The method of `Transport` chosen to transmit the payment (can be multiple, sorted by preference) - `nut10`: The required [NUT-10][10] locking condition diff --git a/tests/18-tests.md b/tests/18-tests.md index e88a9570..cf8eaf97 100644 --- a/tests/18-tests.md +++ b/tests/18-tests.md @@ -157,3 +157,22 @@ Encoded: ``` creqApWFpaGM5ZTQ1ZDJhYWEZAfRhdWNzYXRhbYF4GGh0dHBzOi8vbWludC5leGFtcGxlLmNvbWVudXQxMKNha2RQMlBLYWR4QjAyYzNiNWJiMjdlMzYxNDU3YzkyZDkzZDc4ZGQ3M2QzZDUzNzMyMTEwYjJjZmU4YjUwZmJjMGFiYzYxNWU5YzMzMWF0gYJndGltZW91dGQzNjAw ``` + +### Preferred Mints Field + +A payment request specifying preferred mints using the `pm` field. + +```json +{ + "i": "pm_test", + "a": 100, + "u": "sat", + "pm": ["https://mint.example.com"] +} +``` + +Encoded: + +``` +creqApGFpZ3BtX3Rlc3RhYRhkYXVjc2F0YnBtgXgYaHR0cHM6Ly9taW50LmV4YW1wbGUuY29t +``` diff --git a/tests/26-test.md b/tests/26-test.md index e6a2dde7..ea2e2394 100644 --- a/tests/26-test.md +++ b/tests/26-test.md @@ -413,3 +413,24 @@ Encoded: ``` CREQB1QYQQKCM4WD6X7M2LW4HXJAQZQQYQQQQQQQQQQQRYQVQQXCN5VVZSQXRGW368QUE69UHK66TWWSHX27RPD4CXCEFWVDHK6PZHCW8 ``` + +--- + +### Preferred Mints Field + +A payment request specifying preferred mints using the `pm` field (tag 0x09). + +```json +{ + "i": "pm_test", + "a": 100, + "u": "sat", + "pm": ["https://mint.example.com"] +} +``` + +Encoded: + +``` +CREQB1QYQQWURDTA6X2UM5QGQQSQQQQQQQQQQQVSPSQQGQPYQPS6R5W3C8XW309AKKJMN59EJHSCTDWPKX2TNRDAKSYWN0VM +```