Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/python.yml
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ jobs:
python -m pip install --only-binary payjoin --find-links dist "payjoin==$version"
python -c '
import payjoin
payjoin.Url.parse("bitcoin:12c6DSiU4Rq3P4ZxziKxzrL5LmMBrzjrJX?amount=1&pj=https://example.com")
payjoin.Uri.parse("bitcoin:12c6DSiU4Rq3P4ZxziKxzrL5LmMBrzjrJX?amount=1&pj=https://example.com")
print("smoke ok")
'

Expand Down
36 changes: 14 additions & 22 deletions Cargo-minimal.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1792,21 +1792,14 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"

[[package]]
name = "idna"
version = "1.0.3"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e"
checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6"
dependencies = [
"idna_adapter",
"smallvec",
"utf8_iter",
"unicode-bidi",
"unicode-normalization",
]

[[package]]
name = "idna_adapter"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cfdf4f5d937a025381f5ab13624b1c5f51414bfe5c9885663226eae8d6d39560"

[[package]]
name = "indexmap"
version = "1.8.0"
Expand Down Expand Up @@ -2400,7 +2393,6 @@ dependencies = [
"uniffi",
"uniffi-bindgen-cs",
"uniffi-dart",
"url",
"yoke-derive",
]

Expand Down Expand Up @@ -3398,9 +3390,9 @@ checksum = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8"

[[package]]
name = "smallvec"
version = "1.13.1"
version = "1.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7"
checksum = "2593d31f82ead8df961d8bd23a64c2ccf2eb5dd34b0a34bfb4dd54011c72009e"

[[package]]
name = "smawk"
Expand Down Expand Up @@ -4062,6 +4054,12 @@ version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3ac9567e27ca9fc45bac22f987fd62547b0ac65d2e6502dfc09cdab7dbdba31f"

[[package]]
name = "unicode-bidi"
version = "0.3.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d54675592c1dbefd78cbd98db9bacd89886e1ca50692a0692baefffdeb92dd58"

[[package]]
name = "unicode-ident"
version = "1.0.5"
Expand Down Expand Up @@ -4299,9 +4297,9 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1"

[[package]]
name = "url"
version = "2.5.4"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60"
checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633"
dependencies = [
"form_urlencoded",
"idna",
Expand All @@ -4320,12 +4318,6 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "662fab6525a98beff2921d7f61a39e7d59e0b425ebc7d0d9e66d316e55124122"

[[package]]
name = "utf8_iter"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be"

[[package]]
name = "utf8parse"
version = "0.2.1"
Expand Down
1 change: 0 additions & 1 deletion Cargo-recent.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2593,7 +2593,6 @@ dependencies = [
"uniffi",
"uniffi-bindgen-cs",
"uniffi-dart",
"url",
"yoke-derive",
]

Expand Down
1 change: 0 additions & 1 deletion payjoin-ffi/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ tokio = { version = "1.52.3", features = ["full"], optional = true }
uniffi = { version = "0.31.2", features = ["cli"] }
uniffi-bindgen-cs = { git = "https://github.com/NordSecurity/uniffi-bindgen-cs", tag = "v0.11.0+v0.31.0", optional = true }
uniffi-dart = { git = "https://github.com/Uniffi-Dart/uniffi-dart.git", tag = "v0.2.1+v0.31.2", optional = true }
url = "2.5.4"
yoke-derive = "=0.8.2"

# Pinned transitive dependencies that appear unused to cargo-machete
Expand Down
18 changes: 13 additions & 5 deletions payjoin-ffi/csharp/UnitTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,27 +5,35 @@ namespace Payjoin.Tests;

public class UriTests
{
[Fact]
public void UrlUserInfoRejectedPayjoinParameter()
{
var uri = "bitcoin:12c6DSiU4Rq3P4ZxziKxzrL5LmMBrzjrJX?amount=1&pj=https://example@evil.com?ciao";
var ex = Assert.ThrowsAny<Exception>(() => Uri.Parse(uri));
Assert.Contains("UserinfoNotSupported", ex.ToString());
}

[Fact]
public void UrlEncodedPayjoinParameter()
{
var uri = "bitcoin:12c6DSiU4Rq3P4ZxziKxzrL5LmMBrzjrJX?amount=1&pj=https://example.com?ciao";
var result = Url.Parse(uri);
var uri = "bitcoin:12c6DSiU4Rq3P4ZxziKxzrL5LmMBrzjrJX?amount=1&pj=https%3A%2F%2Fexample.com%3Fciao";
var result = Uri.Parse(uri);
Comment on lines 17 to +20

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Was this test just incorrectly written before?

Assert.NotNull(result);
}

[Fact]
public void ValidUrl()
{
var uri = "bitcoin:12c6DSiU4Rq3P4ZxziKxzrL5LmMBrzjrJX?amount=1&pj=https://example.com?ciao";
var result = Url.Parse(uri);
var result = Uri.Parse(uri);
Assert.NotNull(result);
}

[Fact]
public void MissingAmountShouldBeOk()
{
var uri = "bitcoin:12c6DSiU4Rq3P4ZxziKxzrL5LmMBrzjrJX?pj=https://testnet.demo.btcpayserver.org/BTC/pj";
var result = Url.Parse(uri);
var result = Uri.Parse(uri);
Assert.NotNull(result);
}

Expand All @@ -37,7 +45,7 @@ public void MissingAmountShouldBeOk()
public void ValidUrisWithDifferentAddressesAndEndpoints(string address, string pj)
{
var uri = $"{address}?amount=1&pj={pj}";
var result = Url.Parse(uri);
var result = Uri.Parse(uri);
Assert.NotNull(result);
}
}
Expand Down
2 changes: 1 addition & 1 deletion payjoin-ffi/csharp/scripts/smoke_nuget_package.sh
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ dotnet add "PayjoinSmoke/PayjoinSmoke.csproj" package Payjoin \
--no-restore

cat >"PayjoinSmoke/Program.cs" <<'EOF'
var uri = Payjoin.Url.Parse("bitcoin:12c6DSiU4Rq3P4ZxziKxzrL5LmMBrzjrJX?amount=1&pj=https://example.com?ciao");
var uri = Payjoin.Uri.Parse("bitcoin:12c6DSiU4Rq3P4ZxziKxzrL5LmMBrzjrJX?amount=1&pj=https://example.com?ciao");
Console.WriteLine(uri.AsString());
EOF

Expand Down
33 changes: 22 additions & 11 deletions payjoin-ffi/dart/test/test_payjoin_unit_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,29 +8,40 @@ import "utils.dart";

void main() {
group('Test URIs', () {
test('Test todo url encoded', () {
test('Test url userinfo rejection', () {
var uri =
"bitcoin:12c6DSiU4Rq3P4ZxziKxzrL5LmMBrzjrJX?amount=1&pj=https://example.com?ciao";
final result = payjoin.Url.parse(input: uri);
"bitcoin:12c6DSiU4Rq3P4ZxziKxzrL5LmMBrzjrJX?amount=1&pj=https://example@evil.com?ciao";
expect(
result,
isA<payjoin.Url>(),
reason: "pj url should be url encoded",
() => payjoin.Uri.parse(uri: uri),
throwsA(
isA<payjoin.UriParseException>().having(
(e) => e.toString(),
'display',
contains('UserinfoNotSupported'),
),
),
);
});

test('Test url encoded', () {
var uri =
"bitcoin:12c6DSiU4Rq3P4ZxziKxzrL5LmMBrzjrJX?amount=1&pj=https%3A%2F%2Fexample.com%3Fciao";
final result = payjoin.Uri.parse(uri: uri);
expect(result, isA<payjoin.Uri>(), reason: "pj url encoded is not valid");
});

test('Test valid url', () {
var uri =
"bitcoin:12c6DSiU4Rq3P4ZxziKxzrL5LmMBrzjrJX?amount=1&pj=https://example.com?ciao";
final result = payjoin.Url.parse(input: uri);
expect(result, isA<payjoin.Url>(), reason: "pj is not a valid url");
final result = payjoin.Uri.parse(uri: uri);
expect(result, isA<payjoin.Uri>(), reason: "pj is not a valid url");
});

test('Test missing amount', () {
var uri =
"bitcoin:12c6DSiU4Rq3P4ZxziKxzrL5LmMBrzjrJX?pj=https://testnet.demo.btcpayserver.org/BTC/pj";
final result = payjoin.Url.parse(input: uri);
expect(result, isA<payjoin.Url>(), reason: "missing amount should be ok");
final result = payjoin.Uri.parse(uri: uri);
expect(result, isA<payjoin.Uri>(), reason: "missing amount should be ok");
});

test('Test valid uris', () {
Expand All @@ -49,7 +60,7 @@ void main() {
for (final pj in pjs) {
final uri = "$address?amount=1&pj=$pj";
try {
payjoin.Url.parse(input: uri);
payjoin.Uri.parse(uri: uri);
} catch (e) {
fail("Failed to create a valid Uri for $uri. Error: $e");
}
Expand Down
20 changes: 13 additions & 7 deletions payjoin-ffi/javascript/test/unit.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,24 +44,30 @@ const ORIGINAL_PSBT =

function runUnitTests(name: string, payjoin: typeof nodejsPayjoin) {
describe(`[${name}] URI tests`, () => {
test("Reject userinfo URL", () => {
const uri =
"bitcoin:12c6DSiU4Rq3P4ZxziKxzrL5LmMBrzjrJX?amount=1&pj=https://example@evil.com?ciao";
assert.throws(() => payjoin.Uri.parse(uri), /UserinfoNotSupported/);
});

test("URL encoded payjoin parameter", () => {
const uri =
"bitcoin:12c6DSiU4Rq3P4ZxziKxzrL5LmMBrzjrJX?amount=1&pj=https://example.com?ciao";
const result = payjoin.Url.parse(uri);
assert.ok(result, "pj url should be url encoded");
"bitcoin:12c6DSiU4Rq3P4ZxziKxzrL5LmMBrzjrJX?amount=1&pj=https%3A%2F%2Fexample.com%3Fciao";
const result = payjoin.Uri.parse(uri);
assert.ok(result, "pj url encoded is not valid");
});

test("valid URL", () => {
test("valid URI", () => {
const uri =
"bitcoin:12c6DSiU4Rq3P4ZxziKxzrL5LmMBrzjrJX?amount=1&pj=https://example.com?ciao";
const result = payjoin.Url.parse(uri);
const result = payjoin.Uri.parse(uri);
assert.ok(result, "pj is not a valid url");
});

test("missing amount should be ok", () => {
const uri =
"bitcoin:12c6DSiU4Rq3P4ZxziKxzrL5LmMBrzjrJX?pj=https://testnet.demo.btcpayserver.org/BTC/pj";
const result = payjoin.Url.parse(uri);
const result = payjoin.Uri.parse(uri);
assert.ok(result, "missing amount should be ok");
});

Expand All @@ -83,7 +89,7 @@ function runUnitTests(name: string, payjoin: typeof nodejsPayjoin) {
for (const pj of pjs) {
const uri = `${address}?amount=1&pj=${pj}`;
assert.doesNotThrow(
() => payjoin.Url.parse(uri),
() => payjoin.Uri.parse(uri),
`Failed to create a valid Uri for ${uri}`,
);
}
Expand Down
17 changes: 11 additions & 6 deletions payjoin-ffi/python/test/test_payjoin_unit_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,22 @@


class TestURIs(unittest.TestCase):
def test_todo_url_encoded(self):
uri = "bitcoin:12c6DSiU4Rq3P4ZxziKxzrL5LmMBrzjrJX?amount=1&pj=https://example.com?ciao"
self.assertTrue(payjoin.Url.parse(uri), "pj url should be url encoded")
def test_url_userinfo_rejection(self):
uri = "bitcoin:12c6DSiU4Rq3P4ZxziKxzrL5LmMBrzjrJX?amount=1&pj=https://example@evil.com?ciao"
with self.assertRaisesRegex(payjoin.UriParseError, "UserinfoNotSupported"):
payjoin.Uri.parse(uri)

def test_url_encoded(self):
uri = "bitcoin:12c6DSiU4Rq3P4ZxziKxzrL5LmMBrzjrJX?amount=1&pj=https%3A%2F%2Fexample.com%3Fciao"
self.assertTrue(payjoin.Uri.parse(uri), "pj url encoded is not valid")

def test_valid_url(self):
uri = "bitcoin:12c6DSiU4Rq3P4ZxziKxzrL5LmMBrzjrJX?amount=1&pj=https://example.com?ciao"
self.assertTrue(payjoin.Url.parse(uri), "pj is not a valid url")
self.assertTrue(payjoin.Uri.parse(uri), "pj is not a valid uri")

def test_missing_amount(self):
uri = "bitcoin:12c6DSiU4Rq3P4ZxziKxzrL5LmMBrzjrJX?pj=https://testnet.demo.btcpayserver.org/BTC/pj"
self.assertTrue(payjoin.Url.parse(uri), "missing amount should be ok")
self.assertTrue(payjoin.Uri.parse(uri), "missing amount should be ok")

def test_valid_uris(self):
https = str(payjoin.example_url())
Expand All @@ -34,7 +39,7 @@ def test_valid_uris(self):
for pj in [https, onion]:
uri = f"{address}?amount=1&pj={pj}"
try:
payjoin.Url.parse(uri)
payjoin.Uri.parse(uri)
except Exception as e:
self.fail(f"Failed to create a valid Uri for {uri}. Error: {e}")

Expand Down
2 changes: 1 addition & 1 deletion payjoin-ffi/src/uri/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ impl PjNotSupported {
#[derive(Debug, thiserror::Error, uniffi::Object)]
#[uniffi::export(Debug, Display)]
#[error(transparent)]
pub struct UrlParseError(#[from] url::ParseError);
pub struct UrlParseError(#[from] payjoin::UrlParseError);

#[derive(Debug, thiserror::Error, uniffi::Object)]
#[uniffi::export(Debug, Display)]
Expand Down
12 changes: 6 additions & 6 deletions payjoin-ffi/src/uri/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,22 +71,22 @@ impl PjUri {
pub fn as_string(&self) -> String { self.0.clone().to_string() }
}

impl From<url::Url> for Url {
fn from(value: url::Url) -> Self { Self(value) }
impl From<payjoin::Url> for Url {
fn from(value: payjoin::Url) -> Self { Self(value) }
}

impl From<Url> for url::Url {
impl From<Url> for payjoin::Url {
fn from(value: Url) -> Self { value.0 }
}

#[derive(Clone, Debug, uniffi::Object)]
pub struct Url(url::Url);
#[derive(Debug, uniffi::Object)]
pub struct Url(payjoin::Url);

#[uniffi::export]
impl Url {
#[uniffi::constructor]
pub fn parse(input: String) -> Result<Url, UrlParseError> {
url::Url::parse(input.as_str()).map_err(Into::into).map(Self)
payjoin::Url::parse(input.as_str()).map_err(Into::into).map(Self)
}
pub fn query(&self) -> Option<String> { self.0.query().map(|x| x.to_string()) }
pub fn as_string(&self) -> String { self.0.to_string() }
Expand Down
Loading