damus

nostr ios client
git clone git://jb55.com/damus
Log | Files | Refs | README | LICENSE

commit cf615b82b24206b258d25931455013feb259d232
parent b65d9a49ffc1fb85266584ff9468350e55f68c47
Author: William Casarin <jb55@jb55.com>
Date:   Sun,  1 Jan 2023 11:02:44 -0800

bolt11: fix any amount invoices

Diffstat:
Mdamus/Components/InvoiceView.swift | 4++--
Mdamus/Components/InvoicesView.swift | 2+-
Mdamus/Models/Mentions.swift | 24+++++++++++++++++++-----
MdamusTests/InvoiceTests.swift | 41+++++++++++++++++++++++++++++++++++++++--
4 files changed, 61 insertions(+), 10 deletions(-)

diff --git a/damus/Components/InvoiceView.swift b/damus/Components/InvoiceView.swift @@ -60,7 +60,7 @@ struct InvoiceView: View { } Divider() Text(invoice.description) - Text("\(invoice.amount / 1000) sats") + Text(invoice.amount.amount_sats_str()) .font(.title) PayButton .frame(height: 50) @@ -74,7 +74,7 @@ struct InvoiceView: View { } } -let test_invoice = Invoice(description: "this is a description", amount: 10000, string: "lnbc100n1p357sl0sp5t9n56wdztun39lgdqlr30xqwksg3k69q4q2rkr52aplujw0esn0qpp5mrqgljk62z20q4nvgr6lzcyn6fhylzccwdvu4k77apg3zmrkujjqdpzw35xjueqd9ejqcfqv3jhxcmjd9c8g6t0dcxqyjw5qcqpjrzjqt56h4gvp5yx36u2uzqa6qwcsk3e2duunfxppzj9vhypc3wfe2wswz607uqq3xqqqsqqqqqqqqqqqlqqyg9qyysgqagx5h20aeulj3gdwx3kxs8u9f4mcakdkwuakasamm9562ffyr9en8yg20lg0ygnr9zpwp68524kmda0t5xp2wytex35pu8hapyjajxqpsql29r", expiry: 604800, payment_hash: Data(), created_at: 1666139119) +let test_invoice = Invoice(description: "this is a description", amount: .specific(10000), string: "lnbc100n1p357sl0sp5t9n56wdztun39lgdqlr30xqwksg3k69q4q2rkr52aplujw0esn0qpp5mrqgljk62z20q4nvgr6lzcyn6fhylzccwdvu4k77apg3zmrkujjqdpzw35xjueqd9ejqcfqv3jhxcmjd9c8g6t0dcxqyjw5qcqpjrzjqt56h4gvp5yx36u2uzqa6qwcsk3e2duunfxppzj9vhypc3wfe2wswz607uqq3xqqqsqqqqqqqqqqqlqqyg9qyysgqagx5h20aeulj3gdwx3kxs8u9f4mcakdkwuakasamm9562ffyr9en8yg20lg0ygnr9zpwp68524kmda0t5xp2wytex35pu8hapyjajxqpsql29r", expiry: 604800, payment_hash: Data(), created_at: 1666139119) struct InvoiceView_Previews: PreviewProvider { static var previews: some View { diff --git a/damus/Components/InvoicesView.swift b/damus/Components/InvoicesView.swift @@ -30,7 +30,7 @@ struct InvoicesView: View { struct InvoicesView_Previews: PreviewProvider { static var previews: some View { - InvoicesView(invoices: [Invoice.init(description: "description", amount: 10000, string: "invstr", expiry: 100000, payment_hash: Data(), created_at: 1000000)]) + InvoicesView(invoices: [Invoice.init(description: "description", amount: .specific(10000), string: "invstr", expiry: 100000, payment_hash: Data(), created_at: 1000000)]) .frame(width: 300) } } diff --git a/damus/Models/Mentions.swift b/damus/Models/Mentions.swift @@ -34,7 +34,7 @@ struct IdBlock: Identifiable { struct Invoice { let description: String - let amount: Int64 + let amount: Amount let string: String let expiry: UInt64 let payment_hash: Data @@ -180,6 +180,23 @@ func maybe_pointee<T>(_ p: UnsafeMutablePointer<T>!) -> T? { return p.pointee } +enum Amount: Equatable { + case any + case specific(Int64) + + func amount_sats_str() -> String { + switch self { + case .any: + return "Any" + case .specific(let amt): + if amt < 1000 { + return "\(Double(amt) / 1000.0) sats" + } + return "\(amt / 1000) sats" + } + } +} + func convert_invoice_block(_ b: invoice_block) -> Block? { guard let invstr = strblock_to_string(b.invstr) else { return nil @@ -194,10 +211,7 @@ func convert_invoice_block(_ b: invoice_block) -> Block? { description = String(cString: b11.description) } - guard let msat = maybe_pointee(b11.msat) else { - return nil - } - let amount = Int64(msat.millisatoshis) + let amount: Amount = maybe_pointee(b11.msat).map { .specific(Int64($0.millisatoshis)) } ?? .any let payment_hash = Data(bytes: &b11.payment_hash, count: 32) let created_at = b11.timestamp diff --git a/damusTests/InvoiceTests.swift b/damusTests/InvoiceTests.swift @@ -18,6 +18,43 @@ final class InvoiceTests: XCTestCase { // Put teardown code here. This method is called after the invocation of each test method in the class. } + func testParseAnyAmountInvoice() throws { + let invstr = "LNBC1P3MR5UJSP5G7SA48YD4JWTTPCHWMY4QYN4UWZQCJQ8NMWKD6QE3HCRVYTDLH9SPP57YM9TSA9NN4M4XU59XMJCXKR7YDV29DDP6LVQUT46ZW6CU3KE9GQDQ9V9H8JXQ8P3MYLZJCQPJRZJQF60PZDVNGGQWQDNERZSQN35L8CVQ3QG2Z5NSZYD0D3Q0JW2TL6VUZA7FYQQWKGQQYQQQQLGQQQQXJQQ9Q9QXPQYSGQ39EM4QJMQFKZGJXZVGL7QJMYNSWA8PGDTAGXXRG5Z92M7VLCGKQK2L2THDF8LM0AUKAURH7FVAWDLRNMVF38W4EYJDNVN9V4Z9CRS5CQCV465C" + let parsed = parse_mentions(content: invstr, tags: []) + + XCTAssertNotNil(parsed) + XCTAssertEqual(parsed.count, 1) + XCTAssertNotNil(parsed[0].is_invoice) + guard let invoice = parsed[0].is_invoice else { + return + } + XCTAssertEqual(invoice.amount, .any) + //XCTAssertEqual(invoice.expiry, 604800) + //XCTAssertEqual(invoice.created_at, 1666139119) + XCTAssertEqual(invoice.string, invstr) + } + + func testTextAfterInvoice() throws { + let invstr = """ +LNBC1P3MR5UJSP5G7SA48YD4JWTTPCHWMY4QYN4UWZQCJQ8NMWKD6QE3HCRVYTDLH9SPP57YM9TSA9NN4M4XU59XMJCXKR7YDV29DDP6LVQUT46ZW6CU3KE9GQDQ9V9H8JXQ8P3MYLZJCQPJRZJQF60PZDVNGGQWQDNERZSQN35L8CVQ3QG2Z5NSZYD0D3Q0JW2TL6VUZA7FYQQWKGQQYQQQQLGQQQQXJQQ9Q9QXPQYSGQ39EM4QJMQFKZGJXZVGL7QJMYNSWA8PGDTAGXXRG5Z92M7VLCGKQK2L2THDF8LM0AUKAURH7FVAWDLRNMVF38W4EYJDNVN9V4Z9CRS5CQCV465C + +hi there +""" + let parsed = parse_mentions(content: invstr, tags: []) + + XCTAssertNotNil(parsed) + XCTAssertEqual(parsed.count, 2) + print(parsed) + XCTAssertNotNil(parsed[0].is_invoice) + XCTAssertNotNil(parsed[1].is_text, "hi there") + guard let invoice = parsed[0].is_invoice else { + return + } + XCTAssertEqual(invoice.amount, .any) + //XCTAssertEqual(invoice.expiry, 604800) + //XCTAssertEqual(invoice.created_at, 1666139119) + } + func testParseInvoiceUpper() throws { let invstr = "LNBC100N1P357SL0SP5T9N56WDZTUN39LGDQLR30XQWKSG3K69Q4Q2RKR52APLUJW0ESN0QPP5MRQGLJK62Z20Q4NVGR6LZCYN6FHYLZCCWDVU4K77APG3ZMRKUJJQDPZW35XJUEQD9EJQCFQV3JHXCMJD9C8G6T0DCXQYJW5QCQPJRZJQT56H4GVP5YX36U2UZQA6QWCSK3E2DUUNFXPPZJ9VHYPC3WFE2WSWZ607UQQ3XQQQSQQQQQQQQQQQLQQYG9QYYSGQAGX5H20AEULJ3GDWX3KXS8U9F4MCAKDKWUAKASAMM9562FFYR9EN8YG20LG0YGNR9ZPWP68524KMDA0T5XP2WYTEX35PU8HAPYJAJXQPSQL29R" let parsed = parse_mentions(content: invstr, tags: []) @@ -28,7 +65,7 @@ final class InvoiceTests: XCTestCase { guard let invoice = parsed[0].is_invoice else { return } - XCTAssertEqual(invoice.amount, 10000) + XCTAssertEqual(invoice.amount, .specific(10000)) XCTAssertEqual(invoice.expiry, 604800) XCTAssertEqual(invoice.created_at, 1666139119) XCTAssertEqual(invoice.string, invstr) @@ -62,7 +99,7 @@ final class InvoiceTests: XCTestCase { guard let invoice = parsed[0].is_invoice else { return } - XCTAssertEqual(invoice.amount, 10000) + XCTAssertEqual(invoice.amount, .specific(10000)) XCTAssertEqual(invoice.expiry, 604800) XCTAssertEqual(invoice.created_at, 1666139119) XCTAssertEqual(invoice.string, invstr)