damus

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

WalletConnectTests.swift (9943B)


      1 //
      2 //  WalletConnectTests.swift
      3 //  damusTests
      4 //
      5 //  Created by William Casarin on 2023-04-02.
      6 //
      7 
      8 import XCTest
      9 @testable import damus
     10 
     11 final class WalletConnectTests: XCTestCase {
     12 
     13     override func setUpWithError() throws {
     14         // Put setup code here. This method is called before the invocation of each test method in the class.
     15     }
     16 
     17     override func tearDownWithError() throws {
     18         // Put teardown code here. This method is called after the invocation of each test method in the class.
     19     }
     20 
     21     func testWalletBalanceRequest() throws {
     22         // This is an example of a functional test case.
     23         // Use XCTAssert and related functions to verify your tests produce the correct results.
     24         // Any test you write for XCTest can be annotated as throws and async.
     25         // Mark your test throws to produce an unexpected failure when your test encounters an uncaught error.
     26         // Mark your test async to allow awaiting for asynchronous code to complete. Check the results with assertions afterwards.
     27     }
     28     
     29     func get_test_nwc() -> WalletConnectURL {
     30         let pk = "9d088f4760422443d4699b485e2ac66e565a2f5da1198c55ddc5679458e3f67a"
     31         let sec = "ff2eefd57196d42089e1b42acc39916d7ecac52e0625bd70597bbd5be14aff18"
     32         let relay = "wss://relay.getalby.com/v1"
     33         let str = "nostrwalletconnect://\(pk)?relay=\(relay)&secret=\(sec)"
     34         
     35         return WalletConnectURL(str: str)!
     36     }
     37     
     38     func testDoesNWCParse() {
     39         // Test an NWC url format which is not technically NIP-47 and RFC 3986 compliant, but still commonly used (by Alby, for example)
     40         // See Github issue #1547 for details on why this URL is non-compliant
     41         // This test URL also features:
     42         // - `nostrwalletconnect` scheme
     43         // - A non-url-encoded relay parameter
     44         // - lud16 parameter
     45         let pk = Pubkey(hex: "9d088f4760422443d4699b485e2ac66e565a2f5da1198c55ddc5679458e3f67a")!
     46         let sec = Privkey(hex: "ff2eefd57196d42089e1b42acc39916d7ecac52e0625bd70597bbd5be14aff18")!
     47         let relay = "wss://relay.getalby.com/v1"
     48         let str = "nostrwalletconnect://\(pk)?relay=\(relay)&secret=\(sec)&lud16=jb55@jb55.com"
     49         
     50         let url = WalletConnectURL(str: str)
     51         XCTAssertNotNil(url)
     52         guard let url else {
     53             return
     54         }
     55         XCTAssertEqual(url.pubkey, pk)
     56         XCTAssertEqual(url.keypair.privkey, sec)
     57         XCTAssertEqual(url.keypair.pubkey, privkey_to_pubkey(privkey: sec))
     58         XCTAssertEqual(url.relay.url.absoluteString, relay)
     59         XCTAssertEqual(url.lud16, "jb55@jb55.com")
     60 
     61         // Test an NWC url format which is NIP-47 and RFC 3986 compliant
     62         // This test URL also features:
     63         // - `nostr+walletconnect` scheme
     64         // - A url-encoded relay parameter
     65         // - No lud16 parameter
     66         let pk_2 = Pubkey(hex: "b889ff5b1513b641e2a139f661a661364979c5beee91842f8f0ef42ab558e9d4")!
     67         let sec_2 = Privkey(hex: "71a8c14c1407c113601079c4302dab36460f0ccd0ad506f1f2dc73b5100e4f3c")!
     68         let relay_2 = "wss://relay.damus.io"
     69         let str_2 = "nostr+walletconnect:b889ff5b1513b641e2a139f661a661364979c5beee91842f8f0ef42ab558e9d4?relay=wss%3A%2F%2Frelay.damus.io&secret=71a8c14c1407c113601079c4302dab36460f0ccd0ad506f1f2dc73b5100e4f3c"
     70         
     71         let url_2 = WalletConnectURL(str: str_2)
     72         XCTAssertNotNil(url_2)
     73         guard let url_2 else {
     74             return
     75         }
     76         XCTAssertEqual(url_2.pubkey, pk_2)
     77         XCTAssertEqual(url_2.keypair.privkey, sec_2)
     78         XCTAssertEqual(url_2.keypair.pubkey, privkey_to_pubkey(privkey: sec_2))
     79         XCTAssertEqual(url_2.relay.url.absoluteString, relay_2)
     80     }
     81 
     82     func testNWCEphemeralRelay() {
     83         let sec = "8ba3a6b3b57d0f4211bb1ea4d8d1e351a367e9b4ea694746e0a4a452b2bc4d37"
     84         let pk =  "89446b900c70d62438dcf66756405eea6225ad94dc61f3856f62f9699111a9a6"
     85         let nwc = WalletConnectURL(str: "nostrwalletconnect://\(pk)?relay=ws://127.0.0.1&secret=\(sec)&lud16=jb55@jb55.com")!
     86         
     87         let pool = RelayPool(ndb: .empty)
     88         let box = PostBox(pool: pool)
     89         
     90         WalletConnect.pay(url: nwc, pool: pool, post: box, invoice: "invoice", zap_request: nil)
     91         
     92         XCTAssertEqual(pool.our_descriptors.count, 0)
     93         XCTAssertEqual(pool.all_descriptors.count, 1)
     94         XCTAssertEqual(pool.all_descriptors[0].variant, .nwc)
     95         XCTAssertEqual(pool.all_descriptors[0].url.url.absoluteString, "ws://127.0.0.1")
     96         XCTAssertEqual(box.events.count, 1)
     97         let ev = box.events.first!.value
     98         XCTAssertEqual(ev.skip_ephemeral, false)
     99         XCTAssertEqual(ev.remaining.count, 1)
    100         XCTAssertEqual(ev.remaining[0].relay.url.absoluteString, "ws://127.0.0.1")
    101     }
    102     
    103     let testBolt11 = "lnbc15u1p3xnhl2pp5jptserfk3zk4qy42tlucycrfwxhydvlemu9pqr93tuzlv9cc7g3sdqsvfhkcap3xyhx7un8cqzpgxqzjcsp5f8c52y2stc300gl6s4xswtjpc37hrnnr3c9wvtgjfuvqmpm35evq9qyyssqy4lgd8tj637qcjp05rdpxxykjenthxftej7a2zzmwrmrl70fyj9hvj0rewhzj7jfyuwkwcg9g2jpwtk3wkjtwnkdks84hsnu8xps5vsq4gj5hs"
    104     let testStringEncodedZapRequest = """
    105     {"content":"","created_at":1746235486,"id":"faf5192c6805dea002e50cd52c7e553e3ee66ac42f30f41f1fe62b924f68fb22","kind":9734,"pubkey":"056b5b5966f500defb3b790a14633e5ec4a0e8883ca29bc23d0030553edb084a","sig":"21076018677656a220977c77e34bfa7427e1056a49b633afd3653d1d7466846cf6b35cf3fbf5908c712ebd647119cfadb1fa47e83121a238d77b1996f0fa26ee","tags":[["p","e8361082333142fc7f483b7dbd9bb36d671f2fbcf0a28015b2304fed79365fe8"],["relays","wss://nos.lol","wss://notify.damus.io","wss://relay.damus.io"]]}
    106     """
    107     let testDoubleStringEncodedZapRequest = """
    108     "{\\\"content\\\":\\\"\\\",\\\"created_at\\\":1746235486,\\\"id\\\":\\\"faf5192c6805dea002e50cd52c7e553e3ee66ac42f30f41f1fe62b924f68fb22\\\",\\\"kind\\\":9734,\\\"pubkey\\\":\\\"056b5b5966f500defb3b790a14633e5ec4a0e8883ca29bc23d0030553edb084a\\\",\\\"sig\\\":\\\"21076018677656a220977c77e34bfa7427e1056a49b633afd3653d1d7466846cf6b35cf3fbf5908c712ebd647119cfadb1fa47e83121a238d77b1996f0fa26ee\\\",\\\"tags\\\":[[\\\"p\\\",\\\"e8361082333142fc7f483b7dbd9bb36d671f2fbcf0a28015b2304fed79365fe8\\\"],[\\\"relays\\\",\\\"wss://nos.lol\\\",\\\"wss://notify.damus.io\\\",\\\"wss://relay.damus.io\\\"]]}"
    109     """
    110     
    111     func testEncodingPayInvoiceRequest() throws {
    112         let testZapRequest = decode_nostr_event_json(json: testStringEncodedZapRequest)!
    113         let metadata = WalletConnect.Request.Metadata(nostr: testZapRequest)
    114         let request = WalletConnect.Request.payInvoice(invoice: "lntest", description: testStringEncodedZapRequest, metadata: metadata)
    115         
    116         let encodedData = try JSONEncoder().encode(request)
    117         let encodedString = String(data: encodedData, encoding: .utf8)!
    118         
    119         XCTAssertTrue(encodedString.contains("\"method\":\"pay_invoice\""))
    120         XCTAssertTrue(encodedString.contains("\"invoice\":\"lntest\""))
    121         XCTAssertTrue(encodedString.contains("\"description\":\"{"))
    122         XCTAssertTrue(encodedString.contains("\"nostr\":{"))
    123     }
    124     
    125     func testDecodingPayInvoiceRequest() throws {
    126         let testZapRequest = decode_nostr_event_json(json: testStringEncodedZapRequest)!
    127         
    128         let jsonText = """
    129         {
    130             "method": "pay_invoice",
    131             "params": {
    132                 "invoice": "\(testBolt11)",
    133                 "description": \(testDoubleStringEncodedZapRequest),
    134                 "metadata": {
    135                     "nostr": \(testStringEncodedZapRequest)
    136                 }
    137             }
    138         }
    139         """
    140         
    141         let jsonData = jsonText.data(using: .utf8)!
    142         
    143         let decodedRequest = try JSONDecoder().decode(WalletConnect.Request.self, from: jsonData)
    144         
    145         switch decodedRequest {
    146         case .payInvoice(let invoice, let description, let metadata):
    147             XCTAssertEqual(invoice, testBolt11)
    148             XCTAssertEqual(description, testStringEncodedZapRequest)
    149             XCTAssertNotNil(metadata)
    150             XCTAssertEqual(metadata!.nostr, testZapRequest)
    151         default:
    152             XCTFail("Decoded to the wrong case")
    153         }
    154     }
    155     
    156     func testDecodingPayInvoiceRequestWithoutMetadata() throws {
    157         let jsonData = """
    158         {
    159             "method": "pay_invoice",
    160             "params": {
    161                 "invoice": "\(testBolt11)",
    162                 "description": \(testDoubleStringEncodedZapRequest)
    163             }
    164         }
    165         """.data(using: .utf8)!
    166         
    167         let decodedRequest = try JSONDecoder().decode(WalletConnect.Request.self, from: jsonData)
    168         
    169         switch decodedRequest {
    170         case .payInvoice(let invoice, let description, let metadata):
    171             XCTAssertEqual(invoice, testBolt11)
    172             XCTAssertEqual(description, testStringEncodedZapRequest)
    173             XCTAssertNil(metadata)
    174         default:
    175             XCTFail("Decoded to the wrong case")
    176         }
    177     }
    178     
    179     func testDecodingPayInvoiceRequestWithCrazyMetadata() throws {
    180         let jsonText = """
    181         {
    182             "method": "pay_invoice",
    183             "params": {
    184                 "invoice": "\(testBolt11)",
    185                 "description": \(testDoubleStringEncodedZapRequest),
    186                 "metadata": {
    187                     "nostr": "totally not a zap request because this metadata is crazy",
    188                     "lorem": "ipsum"
    189                 }
    190             }
    191         }
    192         """
    193         
    194         let jsonData = jsonText.data(using: .utf8)!
    195         
    196         let decodedRequest = try JSONDecoder().decode(WalletConnect.Request.self, from: jsonData)
    197         
    198         switch decodedRequest {
    199         case .payInvoice(let invoice, let description, let metadata):
    200             XCTAssertEqual(invoice, testBolt11)
    201             XCTAssertEqual(description, testStringEncodedZapRequest)
    202             XCTAssertEqual(metadata?.nostr, nil)
    203         default:
    204             XCTFail("Decoded to the wrong case")
    205         }
    206     }
    207 }