[esplora] Support proxies in EsploraBlockchain - #429

Merged
notmandatory merged 1 commit into
bitcoindevkit:masterfrom
afilini:feat/socks5-esplora
Sep 23, 2021
Merged

[esplora] Support proxies in EsploraBlockchain#429
notmandatory merged 1 commit into
bitcoindevkit:masterfrom
afilini:feat/socks5-esplora

Conversation

@afilini

Copy link
Copy Markdown
Member

Description

Add support for http/socks proxies in Esplora

Notes to the reviewers

Opening this as a draft, since I think it's gonna break for wasm32.

This is also technically an API break, which according to the new updated guidelines shouldn't happen. On the other hand, I can't think of a better way to do this. Am I supposed to make a different EsploraBlockchainConfig struct with the new field added and only deprecate the current one?

Checklists

All Submissions:

  • I've signed all my commits
  • I followed the contribution guidelines
  • I ran cargo fmt and cargo clippy before committing

New Features:

  • I've added tests for the new feature
  • I've added docs for the new feature
  • I've updated CHANGELOG.md
  • This pull request breaks the existing API

@afilini
afiliniforce-pushed the feat/socks5-esplora branch from 79afac4 to 47a7a9cCompareAugust 30, 2021 14:14
@notmandatory

Copy link
Copy Markdown
Member

On the question of how to make this sort of API change, since it's an additive change with an Option value I think it can be considered backward compatible. It does still technically break the API since anyone adopting the new version will have to do something. But it doesn't change the name or functionality of any existing struct fields or functions or function arguments. The alternative would be to make a whole new struct and new versions of all the functions that use it, which seems more disruptive when the original struct is eventually removed.

@thomaseizinger, as a user, what do you think about his sort of change? would it disrupt your workflow to have to add a new None value for this field after upgrading to a new version of bdk?

@thomaseizinger

thomaseizinger commented Aug 31, 2021

Copy link
Copy Markdown
Contributor

It is technically breaking yes.

I see two ways of changing the code so this change would be non breaking:

  1. Put #[non_exhaustive] on such kind of structs which forces users to use ::default or ::new to make an instance.
  2. Make all fields private and use a builder pattern to initialize such configurations:
EsploraBlockchainConfig::default().with_xyz().with_abc()

(1) is less code (no builders and getters) and would result in usage such as:

let config = EsploraBlockchainConfig{concurrency:Some(4),
..EsploraBlockchainConfig::default()};

Personally, I think (1) would be the better option unless you want to support Rust < 1.40.

For this particular PR, it is still a breaking change but we might at least take this opportunity to make future changes non-breaking :)

@RCasatta

Copy link
Copy Markdown
Contributor

is less code (no builders and getters) and would result in usage such as:

 let config = EsploraBlockchainConfig {
concurrency: Some(4),
..EsploraBlockchainConfig::default()
};

It looks this doesn't work for users outside the bdk crate (while logically flawless)

@thomaseizinger

Copy link
Copy Markdown
Contributor

is less code (no builders and getters) and would result in usage such as:

 let config = EsploraBlockchainConfig {
concurrency: Some(4),
..EsploraBlockchainConfig::default()
};

It looks this doesn't work for users outside the bdk crate (while logically flawless)

Damn, sorry about that. I swear I did this before with non-exhaustive structs. In guess it will have to be something like this then:

letmut config = ElectrumBlockchainConfig::new("foo".to_owned());
config.retry = 1;

@notmandatory

notmandatory commented Sep 3, 2021

Copy link
Copy Markdown
Member

What about the option:

  1. implement the Default trait for structs that are part of our public API? We can then state in the docs that users who want to maintain forward compatibility with new fields must add ..Default::default() whenever using a struct expression for a struct that implements the Default trait.

If we go this route I'll add an issue to implement Default for all the bdk structs.

And maybe someday a future version of Rust will let us add the #[non_exhaustive] macro and have it work as we'd like for option 1.

@thomaseizinger

Copy link
Copy Markdown
Contributor

What about the option:

1. implement the `Default` trait for structs that are part of our public API? We can then state in the docs that users who want to maintain forward compatibility with new fields must add `..Default::default()` whenever using a struct expression for a struct that implements the `Default` trait.

If we go this route I'll add an issue to implement Default for all the bdk structs.

And maybe someday a future version of Rust will let us add the #[non_exhaustive] macro and have it work as we'd like for option 1.

For EsploraBlockchainConfig though, there isn't really a sensible default I am afraid unless you want to default the URL to something?

In that case, providing a constructor that only takes the mandatory arguments (in this case url) requires rather little code and allows the use of #[non_exhaustive] as well. The only difference being that users need to make the struct mutable and override the defaults instead of being able to use struct initializer syntax.

@notmandatorynotmandatory mentioned this pull request Sep 8, 2021
6 tasks
@afilini

Copy link
Copy Markdown
MemberAuthor

We've talked about this yesterday during our team meeting and we reached the conclusion that it's better to just add the field and technically break the API: the reasoning is that we think it's better to force the user to use the explicit initialization syntax so that they are aware of all the existing fields of the struct.

Ideally we would also implement Default, but as you said we can't since we can't assume a default URL.

@notmandatory

Copy link
Copy Markdown
Member

Needs a rebase and then I think this one is ready to review.

@afilini
afilini marked this pull request as ready for review September 23, 2021 19:38

@notmandatorynotmandatory left a comment

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.

@notmandatory
notmandatory merged commit 3fe2380 into bitcoindevkit:masterSep 23, 2021
@afilini
afilini deleted the feat/socks5-esplora branch September 24, 2021 08:00
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@afilini@notmandatory@thomaseizinger@RCasatta
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

[esplora] Support proxies in EsploraBlockchain - #429

Merged
notmandatory merged 1 commit into
bitcoindevkit:masterfrom
afilini:feat/socks5-esplora
Sep 23, 2021
Merged

[esplora] Support proxies in EsploraBlockchain#429
notmandatory merged 1 commit into
bitcoindevkit:masterfrom
afilini:feat/socks5-esplora

Conversation

@afilini

Copy link
Copy Markdown
Member

Description

Add support for http/socks proxies in Esplora

Notes to the reviewers

Opening this as a draft, since I think it's gonna break for wasm32.

This is also technically an API break, which according to the new updated guidelines shouldn't happen. On the other hand, I can't think of a better way to do this. Am I supposed to make a different EsploraBlockchainConfig struct with the new field added and only deprecate the current one?

Checklists

All Submissions:

  • I've signed all my commits
  • I followed the contribution guidelines
  • I ran cargo fmt and cargo clippy before committing

New Features:

  • I've added tests for the new feature
  • I've added docs for the new feature
  • I've updated CHANGELOG.md
  • This pull request breaks the existing API

@afilini
afiliniforce-pushed the feat/socks5-esplora branch from 79afac4 to 47a7a9cCompareAugust 30, 2021 14:14
@notmandatory

Copy link
Copy Markdown
Member

On the question of how to make this sort of API change, since it's an additive change with an Option value I think it can be considered backward compatible. It does still technically break the API since anyone adopting the new version will have to do something. But it doesn't change the name or functionality of any existing struct fields or functions or function arguments. The alternative would be to make a whole new struct and new versions of all the functions that use it, which seems more disruptive when the original struct is eventually removed.

@thomaseizinger, as a user, what do you think about his sort of change? would it disrupt your workflow to have to add a new None value for this field after upgrading to a new version of bdk?

@thomaseizinger

thomaseizinger commented Aug 31, 2021

Copy link
Copy Markdown
Contributor

It is technically breaking yes.

I see two ways of changing the code so this change would be non breaking:

  1. Put #[non_exhaustive] on such kind of structs which forces users to use ::default or ::new to make an instance.
  2. Make all fields private and use a builder pattern to initialize such configurations:
EsploraBlockchainConfig::default().with_xyz().with_abc()

(1) is less code (no builders and getters) and would result in usage such as:

let config = EsploraBlockchainConfig{concurrency:Some(4),
..EsploraBlockchainConfig::default()};

Personally, I think (1) would be the better option unless you want to support Rust < 1.40.

For this particular PR, it is still a breaking change but we might at least take this opportunity to make future changes non-breaking :)

@RCasatta

Copy link
Copy Markdown
Contributor

is less code (no builders and getters) and would result in usage such as:

 let config = EsploraBlockchainConfig {
concurrency: Some(4),
..EsploraBlockchainConfig::default()
};

It looks this doesn't work for users outside the bdk crate (while logically flawless)

@thomaseizinger

Copy link
Copy Markdown
Contributor

is less code (no builders and getters) and would result in usage such as:

 let config = EsploraBlockchainConfig {
concurrency: Some(4),
..EsploraBlockchainConfig::default()
};

It looks this doesn't work for users outside the bdk crate (while logically flawless)

Damn, sorry about that. I swear I did this before with non-exhaustive structs. In guess it will have to be something like this then:

letmut config = ElectrumBlockchainConfig::new("foo".to_owned());
config.retry = 1;

@notmandatory

notmandatory commented Sep 3, 2021

Copy link
Copy Markdown
Member

What about the option:

  1. implement the Default trait for structs that are part of our public API? We can then state in the docs that users who want to maintain forward compatibility with new fields must add ..Default::default() whenever using a struct expression for a struct that implements the Default trait.

If we go this route I'll add an issue to implement Default for all the bdk structs.

And maybe someday a future version of Rust will let us add the #[non_exhaustive] macro and have it work as we'd like for option 1.

@thomaseizinger

Copy link
Copy Markdown
Contributor

What about the option:

1. implement the `Default` trait for structs that are part of our public API? We can then state in the docs that users who want to maintain forward compatibility with new fields must add `..Default::default()` whenever using a struct expression for a struct that implements the `Default` trait.

If we go this route I'll add an issue to implement Default for all the bdk structs.

And maybe someday a future version of Rust will let us add the #[non_exhaustive] macro and have it work as we'd like for option 1.

For EsploraBlockchainConfig though, there isn't really a sensible default I am afraid unless you want to default the URL to something?

In that case, providing a constructor that only takes the mandatory arguments (in this case url) requires rather little code and allows the use of #[non_exhaustive] as well. The only difference being that users need to make the struct mutable and override the defaults instead of being able to use struct initializer syntax.

@notmandatorynotmandatory mentioned this pull request Sep 8, 2021
6 tasks
@afilini

Copy link
Copy Markdown
MemberAuthor

We've talked about this yesterday during our team meeting and we reached the conclusion that it's better to just add the field and technically break the API: the reasoning is that we think it's better to force the user to use the explicit initialization syntax so that they are aware of all the existing fields of the struct.

Ideally we would also implement Default, but as you said we can't since we can't assume a default URL.

@notmandatory

Copy link
Copy Markdown
Member

Needs a rebase and then I think this one is ready to review.

@afilini
afilini marked this pull request as ready for review September 23, 2021 19:38

@notmandatorynotmandatory left a comment

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.

@notmandatory
notmandatory merged commit 3fe2380 into bitcoindevkit:masterSep 23, 2021
@afilini
afilini deleted the feat/socks5-esplora branch September 24, 2021 08:00
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@afilini@notmandatory@thomaseizinger@RCasatta
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

[esplora] Support proxies in EsploraBlockchain - #429

Merged
notmandatory merged 1 commit into
bitcoindevkit:masterfrom
afilini:feat/socks5-esplora
Sep 23, 2021
Merged

[esplora] Support proxies in EsploraBlockchain#429
notmandatory merged 1 commit into
bitcoindevkit:masterfrom
afilini:feat/socks5-esplora

Conversation

@afilini

Copy link
Copy Markdown
Member

Description

Add support for http/socks proxies in Esplora

Notes to the reviewers

Opening this as a draft, since I think it's gonna break for wasm32.

This is also technically an API break, which according to the new updated guidelines shouldn't happen. On the other hand, I can't think of a better way to do this. Am I supposed to make a different EsploraBlockchainConfig struct with the new field added and only deprecate the current one?

Checklists

All Submissions:

  • I've signed all my commits
  • I followed the contribution guidelines
  • I ran cargo fmt and cargo clippy before committing

New Features:

  • I've added tests for the new feature
  • I've added docs for the new feature
  • I've updated CHANGELOG.md
  • This pull request breaks the existing API

@afilini
afiliniforce-pushed the feat/socks5-esplora branch from 79afac4 to 47a7a9cCompareAugust 30, 2021 14:14
@notmandatory

Copy link
Copy Markdown
Member

On the question of how to make this sort of API change, since it's an additive change with an Option value I think it can be considered backward compatible. It does still technically break the API since anyone adopting the new version will have to do something. But it doesn't change the name or functionality of any existing struct fields or functions or function arguments. The alternative would be to make a whole new struct and new versions of all the functions that use it, which seems more disruptive when the original struct is eventually removed.

@thomaseizinger, as a user, what do you think about his sort of change? would it disrupt your workflow to have to add a new None value for this field after upgrading to a new version of bdk?

@thomaseizinger

thomaseizinger commented Aug 31, 2021

Copy link
Copy Markdown
Contributor

It is technically breaking yes.

I see two ways of changing the code so this change would be non breaking:

  1. Put #[non_exhaustive] on such kind of structs which forces users to use ::default or ::new to make an instance.
  2. Make all fields private and use a builder pattern to initialize such configurations:
EsploraBlockchainConfig::default().with_xyz().with_abc()

(1) is less code (no builders and getters) and would result in usage such as:

let config = EsploraBlockchainConfig{concurrency:Some(4),
..EsploraBlockchainConfig::default()};

Personally, I think (1) would be the better option unless you want to support Rust < 1.40.

For this particular PR, it is still a breaking change but we might at least take this opportunity to make future changes non-breaking :)

@RCasatta

Copy link
Copy Markdown
Contributor

is less code (no builders and getters) and would result in usage such as:

 let config = EsploraBlockchainConfig {
concurrency: Some(4),
..EsploraBlockchainConfig::default()
};

It looks this doesn't work for users outside the bdk crate (while logically flawless)

@thomaseizinger

Copy link
Copy Markdown
Contributor

is less code (no builders and getters) and would result in usage such as:

 let config = EsploraBlockchainConfig {
concurrency: Some(4),
..EsploraBlockchainConfig::default()
};

It looks this doesn't work for users outside the bdk crate (while logically flawless)

Damn, sorry about that. I swear I did this before with non-exhaustive structs. In guess it will have to be something like this then:

letmut config = ElectrumBlockchainConfig::new("foo".to_owned());
config.retry = 1;

@notmandatory

notmandatory commented Sep 3, 2021

Copy link
Copy Markdown
Member

What about the option:

  1. implement the Default trait for structs that are part of our public API? We can then state in the docs that users who want to maintain forward compatibility with new fields must add ..Default::default() whenever using a struct expression for a struct that implements the Default trait.

If we go this route I'll add an issue to implement Default for all the bdk structs.

And maybe someday a future version of Rust will let us add the #[non_exhaustive] macro and have it work as we'd like for option 1.

@thomaseizinger

Copy link
Copy Markdown
Contributor

What about the option:

1. implement the `Default` trait for structs that are part of our public API? We can then state in the docs that users who want to maintain forward compatibility with new fields must add `..Default::default()` whenever using a struct expression for a struct that implements the `Default` trait.

If we go this route I'll add an issue to implement Default for all the bdk structs.

And maybe someday a future version of Rust will let us add the #[non_exhaustive] macro and have it work as we'd like for option 1.

For EsploraBlockchainConfig though, there isn't really a sensible default I am afraid unless you want to default the URL to something?

In that case, providing a constructor that only takes the mandatory arguments (in this case url) requires rather little code and allows the use of #[non_exhaustive] as well. The only difference being that users need to make the struct mutable and override the defaults instead of being able to use struct initializer syntax.

@notmandatorynotmandatory mentioned this pull request Sep 8, 2021
6 tasks
@afilini

Copy link
Copy Markdown
MemberAuthor

We've talked about this yesterday during our team meeting and we reached the conclusion that it's better to just add the field and technically break the API: the reasoning is that we think it's better to force the user to use the explicit initialization syntax so that they are aware of all the existing fields of the struct.

Ideally we would also implement Default, but as you said we can't since we can't assume a default URL.

@notmandatory

Copy link
Copy Markdown
Member

Needs a rebase and then I think this one is ready to review.

@afilini
afilini marked this pull request as ready for review September 23, 2021 19:38

@notmandatorynotmandatory left a comment

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.

@notmandatory
notmandatory merged commit 3fe2380 into bitcoindevkit:masterSep 23, 2021
@afilini
afilini deleted the feat/socks5-esplora branch September 24, 2021 08:00
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@afilini@notmandatory@thomaseizinger@RCasatta
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

[esplora] Support proxies in EsploraBlockchain - #429

Merged
notmandatory merged 1 commit into
bitcoindevkit:masterfrom
afilini:feat/socks5-esplora
Sep 23, 2021
Merged

[esplora] Support proxies in EsploraBlockchain#429
notmandatory merged 1 commit into
bitcoindevkit:masterfrom
afilini:feat/socks5-esplora

Conversation

@afilini

Copy link
Copy Markdown
Member

Description

Add support for http/socks proxies in Esplora

Notes to the reviewers

Opening this as a draft, since I think it's gonna break for wasm32.

This is also technically an API break, which according to the new updated guidelines shouldn't happen. On the other hand, I can't think of a better way to do this. Am I supposed to make a different EsploraBlockchainConfig struct with the new field added and only deprecate the current one?

Checklists

All Submissions:

  • I've signed all my commits
  • I followed the contribution guidelines
  • I ran cargo fmt and cargo clippy before committing

New Features:

  • I've added tests for the new feature
  • I've added docs for the new feature
  • I've updated CHANGELOG.md
  • This pull request breaks the existing API

@afilini
afiliniforce-pushed the feat/socks5-esplora branch from 79afac4 to 47a7a9cCompareAugust 30, 2021 14:14
@notmandatory

Copy link
Copy Markdown
Member

On the question of how to make this sort of API change, since it's an additive change with an Option value I think it can be considered backward compatible. It does still technically break the API since anyone adopting the new version will have to do something. But it doesn't change the name or functionality of any existing struct fields or functions or function arguments. The alternative would be to make a whole new struct and new versions of all the functions that use it, which seems more disruptive when the original struct is eventually removed.

@thomaseizinger, as a user, what do you think about his sort of change? would it disrupt your workflow to have to add a new None value for this field after upgrading to a new version of bdk?

@thomaseizinger

thomaseizinger commented Aug 31, 2021

Copy link
Copy Markdown
Contributor

It is technically breaking yes.

I see two ways of changing the code so this change would be non breaking:

  1. Put #[non_exhaustive] on such kind of structs which forces users to use ::default or ::new to make an instance.
  2. Make all fields private and use a builder pattern to initialize such configurations:
EsploraBlockchainConfig::default().with_xyz().with_abc()

(1) is less code (no builders and getters) and would result in usage such as:

let config = EsploraBlockchainConfig{concurrency:Some(4),
..EsploraBlockchainConfig::default()};

Personally, I think (1) would be the better option unless you want to support Rust < 1.40.

For this particular PR, it is still a breaking change but we might at least take this opportunity to make future changes non-breaking :)

@RCasatta

Copy link
Copy Markdown
Contributor

is less code (no builders and getters) and would result in usage such as:

 let config = EsploraBlockchainConfig {
concurrency: Some(4),
..EsploraBlockchainConfig::default()
};

It looks this doesn't work for users outside the bdk crate (while logically flawless)

@thomaseizinger

Copy link
Copy Markdown
Contributor

is less code (no builders and getters) and would result in usage such as:

 let config = EsploraBlockchainConfig {
concurrency: Some(4),
..EsploraBlockchainConfig::default()
};

It looks this doesn't work for users outside the bdk crate (while logically flawless)

Damn, sorry about that. I swear I did this before with non-exhaustive structs. In guess it will have to be something like this then:

letmut config = ElectrumBlockchainConfig::new("foo".to_owned());
config.retry = 1;

@notmandatory

notmandatory commented Sep 3, 2021

Copy link
Copy Markdown
Member

What about the option:

  1. implement the Default trait for structs that are part of our public API? We can then state in the docs that users who want to maintain forward compatibility with new fields must add ..Default::default() whenever using a struct expression for a struct that implements the Default trait.

If we go this route I'll add an issue to implement Default for all the bdk structs.

And maybe someday a future version of Rust will let us add the #[non_exhaustive] macro and have it work as we'd like for option 1.

@thomaseizinger

Copy link
Copy Markdown
Contributor

What about the option:

1. implement the `Default` trait for structs that are part of our public API? We can then state in the docs that users who want to maintain forward compatibility with new fields must add `..Default::default()` whenever using a struct expression for a struct that implements the `Default` trait.

If we go this route I'll add an issue to implement Default for all the bdk structs.

And maybe someday a future version of Rust will let us add the #[non_exhaustive] macro and have it work as we'd like for option 1.

For EsploraBlockchainConfig though, there isn't really a sensible default I am afraid unless you want to default the URL to something?

In that case, providing a constructor that only takes the mandatory arguments (in this case url) requires rather little code and allows the use of #[non_exhaustive] as well. The only difference being that users need to make the struct mutable and override the defaults instead of being able to use struct initializer syntax.

@notmandatorynotmandatory mentioned this pull request Sep 8, 2021
6 tasks
@afilini

Copy link
Copy Markdown
MemberAuthor

We've talked about this yesterday during our team meeting and we reached the conclusion that it's better to just add the field and technically break the API: the reasoning is that we think it's better to force the user to use the explicit initialization syntax so that they are aware of all the existing fields of the struct.

Ideally we would also implement Default, but as you said we can't since we can't assume a default URL.

@notmandatory

Copy link
Copy Markdown
Member

Needs a rebase and then I think this one is ready to review.

@afilini
afilini marked this pull request as ready for review September 23, 2021 19:38

@notmandatorynotmandatory left a comment

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.

@notmandatory
notmandatory merged commit 3fe2380 into bitcoindevkit:masterSep 23, 2021
@afilini
afilini deleted the feat/socks5-esplora branch September 24, 2021 08:00
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@afilini@notmandatory@thomaseizinger@RCasatta
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

[esplora] Support proxies in EsploraBlockchain - #429

Merged
notmandatory merged 1 commit into
bitcoindevkit:masterfrom
afilini:feat/socks5-esplora
Sep 23, 2021
Merged

[esplora] Support proxies in EsploraBlockchain#429
notmandatory merged 1 commit into
bitcoindevkit:masterfrom
afilini:feat/socks5-esplora

Conversation

@afilini

Copy link
Copy Markdown
Member

Description

Add support for http/socks proxies in Esplora

Notes to the reviewers

Opening this as a draft, since I think it's gonna break for wasm32.

This is also technically an API break, which according to the new updated guidelines shouldn't happen. On the other hand, I can't think of a better way to do this. Am I supposed to make a different EsploraBlockchainConfig struct with the new field added and only deprecate the current one?

Checklists

All Submissions:

  • I've signed all my commits
  • I followed the contribution guidelines
  • I ran cargo fmt and cargo clippy before committing

New Features:

  • I've added tests for the new feature
  • I've added docs for the new feature
  • I've updated CHANGELOG.md
  • This pull request breaks the existing API

@afilini
afiliniforce-pushed the feat/socks5-esplora branch from 79afac4 to 47a7a9cCompareAugust 30, 2021 14:14
@notmandatory

Copy link
Copy Markdown
Member

On the question of how to make this sort of API change, since it's an additive change with an Option value I think it can be considered backward compatible. It does still technically break the API since anyone adopting the new version will have to do something. But it doesn't change the name or functionality of any existing struct fields or functions or function arguments. The alternative would be to make a whole new struct and new versions of all the functions that use it, which seems more disruptive when the original struct is eventually removed.

@thomaseizinger, as a user, what do you think about his sort of change? would it disrupt your workflow to have to add a new None value for this field after upgrading to a new version of bdk?

@thomaseizinger

thomaseizinger commented Aug 31, 2021

Copy link
Copy Markdown
Contributor

It is technically breaking yes.

I see two ways of changing the code so this change would be non breaking:

  1. Put #[non_exhaustive] on such kind of structs which forces users to use ::default or ::new to make an instance.
  2. Make all fields private and use a builder pattern to initialize such configurations:
EsploraBlockchainConfig::default().with_xyz().with_abc()

(1) is less code (no builders and getters) and would result in usage such as:

let config = EsploraBlockchainConfig{concurrency:Some(4),
..EsploraBlockchainConfig::default()};

Personally, I think (1) would be the better option unless you want to support Rust < 1.40.

For this particular PR, it is still a breaking change but we might at least take this opportunity to make future changes non-breaking :)

@RCasatta

Copy link
Copy Markdown
Contributor

is less code (no builders and getters) and would result in usage such as:

 let config = EsploraBlockchainConfig {
concurrency: Some(4),
..EsploraBlockchainConfig::default()
};

It looks this doesn't work for users outside the bdk crate (while logically flawless)

@thomaseizinger

Copy link
Copy Markdown
Contributor

is less code (no builders and getters) and would result in usage such as:

 let config = EsploraBlockchainConfig {
concurrency: Some(4),
..EsploraBlockchainConfig::default()
};

It looks this doesn't work for users outside the bdk crate (while logically flawless)

Damn, sorry about that. I swear I did this before with non-exhaustive structs. In guess it will have to be something like this then:

letmut config = ElectrumBlockchainConfig::new("foo".to_owned());
config.retry = 1;

@notmandatory

notmandatory commented Sep 3, 2021

Copy link
Copy Markdown
Member

What about the option:

  1. implement the Default trait for structs that are part of our public API? We can then state in the docs that users who want to maintain forward compatibility with new fields must add ..Default::default() whenever using a struct expression for a struct that implements the Default trait.

If we go this route I'll add an issue to implement Default for all the bdk structs.

And maybe someday a future version of Rust will let us add the #[non_exhaustive] macro and have it work as we'd like for option 1.

@thomaseizinger

Copy link
Copy Markdown
Contributor

What about the option:

1. implement the `Default` trait for structs that are part of our public API? We can then state in the docs that users who want to maintain forward compatibility with new fields must add `..Default::default()` whenever using a struct expression for a struct that implements the `Default` trait.

If we go this route I'll add an issue to implement Default for all the bdk structs.

And maybe someday a future version of Rust will let us add the #[non_exhaustive] macro and have it work as we'd like for option 1.

For EsploraBlockchainConfig though, there isn't really a sensible default I am afraid unless you want to default the URL to something?

In that case, providing a constructor that only takes the mandatory arguments (in this case url) requires rather little code and allows the use of #[non_exhaustive] as well. The only difference being that users need to make the struct mutable and override the defaults instead of being able to use struct initializer syntax.

@notmandatorynotmandatory mentioned this pull request Sep 8, 2021
6 tasks
@afilini

Copy link
Copy Markdown
MemberAuthor

We've talked about this yesterday during our team meeting and we reached the conclusion that it's better to just add the field and technically break the API: the reasoning is that we think it's better to force the user to use the explicit initialization syntax so that they are aware of all the existing fields of the struct.

Ideally we would also implement Default, but as you said we can't since we can't assume a default URL.

@notmandatory

Copy link
Copy Markdown
Member

Needs a rebase and then I think this one is ready to review.

@afilini
afilini marked this pull request as ready for review September 23, 2021 19:38

@notmandatorynotmandatory left a comment

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.

@notmandatory
notmandatory merged commit 3fe2380 into bitcoindevkit:masterSep 23, 2021
@afilini
afilini deleted the feat/socks5-esplora branch September 24, 2021 08:00
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@afilini@notmandatory@thomaseizinger@RCasatta
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

[esplora] Support proxies in EsploraBlockchain - #429

Merged
notmandatory merged 1 commit into
bitcoindevkit:masterfrom
afilini:feat/socks5-esplora
Sep 23, 2021
Merged

[esplora] Support proxies in EsploraBlockchain#429
notmandatory merged 1 commit into
bitcoindevkit:masterfrom
afilini:feat/socks5-esplora

Conversation

@afilini

Copy link
Copy Markdown
Member

Description

Add support for http/socks proxies in Esplora

Notes to the reviewers

Opening this as a draft, since I think it's gonna break for wasm32.

This is also technically an API break, which according to the new updated guidelines shouldn't happen. On the other hand, I can't think of a better way to do this. Am I supposed to make a different EsploraBlockchainConfig struct with the new field added and only deprecate the current one?

Checklists

All Submissions:

  • I've signed all my commits
  • I followed the contribution guidelines
  • I ran cargo fmt and cargo clippy before committing

New Features:

  • I've added tests for the new feature
  • I've added docs for the new feature
  • I've updated CHANGELOG.md
  • This pull request breaks the existing API

@afilini
afiliniforce-pushed the feat/socks5-esplora branch from 79afac4 to 47a7a9cCompareAugust 30, 2021 14:14
@notmandatory

Copy link
Copy Markdown
Member

On the question of how to make this sort of API change, since it's an additive change with an Option value I think it can be considered backward compatible. It does still technically break the API since anyone adopting the new version will have to do something. But it doesn't change the name or functionality of any existing struct fields or functions or function arguments. The alternative would be to make a whole new struct and new versions of all the functions that use it, which seems more disruptive when the original struct is eventually removed.

@thomaseizinger, as a user, what do you think about his sort of change? would it disrupt your workflow to have to add a new None value for this field after upgrading to a new version of bdk?

@thomaseizinger

thomaseizinger commented Aug 31, 2021

Copy link
Copy Markdown
Contributor

It is technically breaking yes.

I see two ways of changing the code so this change would be non breaking:

  1. Put #[non_exhaustive] on such kind of structs which forces users to use ::default or ::new to make an instance.
  2. Make all fields private and use a builder pattern to initialize such configurations:
EsploraBlockchainConfig::default().with_xyz().with_abc()

(1) is less code (no builders and getters) and would result in usage such as:

let config = EsploraBlockchainConfig{concurrency:Some(4),
..EsploraBlockchainConfig::default()};

Personally, I think (1) would be the better option unless you want to support Rust < 1.40.

For this particular PR, it is still a breaking change but we might at least take this opportunity to make future changes non-breaking :)

@RCasatta

Copy link
Copy Markdown
Contributor

is less code (no builders and getters) and would result in usage such as:

 let config = EsploraBlockchainConfig {
concurrency: Some(4),
..EsploraBlockchainConfig::default()
};

It looks this doesn't work for users outside the bdk crate (while logically flawless)

@thomaseizinger

Copy link
Copy Markdown
Contributor

is less code (no builders and getters) and would result in usage such as:

 let config = EsploraBlockchainConfig {
concurrency: Some(4),
..EsploraBlockchainConfig::default()
};

It looks this doesn't work for users outside the bdk crate (while logically flawless)

Damn, sorry about that. I swear I did this before with non-exhaustive structs. In guess it will have to be something like this then:

letmut config = ElectrumBlockchainConfig::new("foo".to_owned());
config.retry = 1;

@notmandatory

notmandatory commented Sep 3, 2021

Copy link
Copy Markdown
Member

What about the option:

  1. implement the Default trait for structs that are part of our public API? We can then state in the docs that users who want to maintain forward compatibility with new fields must add ..Default::default() whenever using a struct expression for a struct that implements the Default trait.

If we go this route I'll add an issue to implement Default for all the bdk structs.

And maybe someday a future version of Rust will let us add the #[non_exhaustive] macro and have it work as we'd like for option 1.

@thomaseizinger

Copy link
Copy Markdown
Contributor

What about the option:

1. implement the `Default` trait for structs that are part of our public API? We can then state in the docs that users who want to maintain forward compatibility with new fields must add `..Default::default()` whenever using a struct expression for a struct that implements the `Default` trait.

If we go this route I'll add an issue to implement Default for all the bdk structs.

And maybe someday a future version of Rust will let us add the #[non_exhaustive] macro and have it work as we'd like for option 1.

For EsploraBlockchainConfig though, there isn't really a sensible default I am afraid unless you want to default the URL to something?

In that case, providing a constructor that only takes the mandatory arguments (in this case url) requires rather little code and allows the use of #[non_exhaustive] as well. The only difference being that users need to make the struct mutable and override the defaults instead of being able to use struct initializer syntax.

@notmandatorynotmandatory mentioned this pull request Sep 8, 2021
6 tasks
@afilini

Copy link
Copy Markdown
MemberAuthor

We've talked about this yesterday during our team meeting and we reached the conclusion that it's better to just add the field and technically break the API: the reasoning is that we think it's better to force the user to use the explicit initialization syntax so that they are aware of all the existing fields of the struct.

Ideally we would also implement Default, but as you said we can't since we can't assume a default URL.

@notmandatory

Copy link
Copy Markdown
Member

Needs a rebase and then I think this one is ready to review.

@afilini
afilini marked this pull request as ready for review September 23, 2021 19:38

@notmandatorynotmandatory left a comment

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.

@notmandatory
notmandatory merged commit 3fe2380 into bitcoindevkit:masterSep 23, 2021
@afilini
afilini deleted the feat/socks5-esplora branch September 24, 2021 08:00
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@afilini@notmandatory@thomaseizinger@RCasatta
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

[esplora] Support proxies in EsploraBlockchain - #429

Merged
notmandatory merged 1 commit into
bitcoindevkit:masterfrom
afilini:feat/socks5-esplora
Sep 23, 2021
Merged

[esplora] Support proxies in EsploraBlockchain#429
notmandatory merged 1 commit into
bitcoindevkit:masterfrom
afilini:feat/socks5-esplora

Conversation

@afilini

Copy link
Copy Markdown
Member

Description

Add support for http/socks proxies in Esplora

Notes to the reviewers

Opening this as a draft, since I think it's gonna break for wasm32.

This is also technically an API break, which according to the new updated guidelines shouldn't happen. On the other hand, I can't think of a better way to do this. Am I supposed to make a different EsploraBlockchainConfig struct with the new field added and only deprecate the current one?

Checklists

All Submissions:

  • I've signed all my commits
  • I followed the contribution guidelines
  • I ran cargo fmt and cargo clippy before committing

New Features:

  • I've added tests for the new feature
  • I've added docs for the new feature
  • I've updated CHANGELOG.md
  • This pull request breaks the existing API

@afilini
afiliniforce-pushed the feat/socks5-esplora branch from 79afac4 to 47a7a9cCompareAugust 30, 2021 14:14
@notmandatory

Copy link
Copy Markdown
Member

On the question of how to make this sort of API change, since it's an additive change with an Option value I think it can be considered backward compatible. It does still technically break the API since anyone adopting the new version will have to do something. But it doesn't change the name or functionality of any existing struct fields or functions or function arguments. The alternative would be to make a whole new struct and new versions of all the functions that use it, which seems more disruptive when the original struct is eventually removed.

@thomaseizinger, as a user, what do you think about his sort of change? would it disrupt your workflow to have to add a new None value for this field after upgrading to a new version of bdk?

@thomaseizinger

thomaseizinger commented Aug 31, 2021

Copy link
Copy Markdown
Contributor

It is technically breaking yes.

I see two ways of changing the code so this change would be non breaking:

  1. Put #[non_exhaustive] on such kind of structs which forces users to use ::default or ::new to make an instance.
  2. Make all fields private and use a builder pattern to initialize such configurations:
EsploraBlockchainConfig::default().with_xyz().with_abc()

(1) is less code (no builders and getters) and would result in usage such as:

let config = EsploraBlockchainConfig{concurrency:Some(4),
..EsploraBlockchainConfig::default()};

Personally, I think (1) would be the better option unless you want to support Rust < 1.40.

For this particular PR, it is still a breaking change but we might at least take this opportunity to make future changes non-breaking :)

@RCasatta

Copy link
Copy Markdown
Contributor

is less code (no builders and getters) and would result in usage such as:

 let config = EsploraBlockchainConfig {
concurrency: Some(4),
..EsploraBlockchainConfig::default()
};

It looks this doesn't work for users outside the bdk crate (while logically flawless)

@thomaseizinger

Copy link
Copy Markdown
Contributor

is less code (no builders and getters) and would result in usage such as:

 let config = EsploraBlockchainConfig {
concurrency: Some(4),
..EsploraBlockchainConfig::default()
};

It looks this doesn't work for users outside the bdk crate (while logically flawless)

Damn, sorry about that. I swear I did this before with non-exhaustive structs. In guess it will have to be something like this then:

letmut config = ElectrumBlockchainConfig::new("foo".to_owned());
config.retry = 1;

@notmandatory

notmandatory commented Sep 3, 2021

Copy link
Copy Markdown
Member

What about the option:

  1. implement the Default trait for structs that are part of our public API? We can then state in the docs that users who want to maintain forward compatibility with new fields must add ..Default::default() whenever using a struct expression for a struct that implements the Default trait.

If we go this route I'll add an issue to implement Default for all the bdk structs.

And maybe someday a future version of Rust will let us add the #[non_exhaustive] macro and have it work as we'd like for option 1.

@thomaseizinger

Copy link
Copy Markdown
Contributor

What about the option:

1. implement the `Default` trait for structs that are part of our public API? We can then state in the docs that users who want to maintain forward compatibility with new fields must add `..Default::default()` whenever using a struct expression for a struct that implements the `Default` trait.

If we go this route I'll add an issue to implement Default for all the bdk structs.

And maybe someday a future version of Rust will let us add the #[non_exhaustive] macro and have it work as we'd like for option 1.

For EsploraBlockchainConfig though, there isn't really a sensible default I am afraid unless you want to default the URL to something?

In that case, providing a constructor that only takes the mandatory arguments (in this case url) requires rather little code and allows the use of #[non_exhaustive] as well. The only difference being that users need to make the struct mutable and override the defaults instead of being able to use struct initializer syntax.

@notmandatorynotmandatory mentioned this pull request Sep 8, 2021
6 tasks
@afilini

Copy link
Copy Markdown
MemberAuthor

We've talked about this yesterday during our team meeting and we reached the conclusion that it's better to just add the field and technically break the API: the reasoning is that we think it's better to force the user to use the explicit initialization syntax so that they are aware of all the existing fields of the struct.

Ideally we would also implement Default, but as you said we can't since we can't assume a default URL.

@notmandatory

Copy link
Copy Markdown
Member

Needs a rebase and then I think this one is ready to review.

@afilini
afilini marked this pull request as ready for review September 23, 2021 19:38

@notmandatorynotmandatory left a comment

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.

@notmandatory
notmandatory merged commit 3fe2380 into bitcoindevkit:masterSep 23, 2021
@afilini
afilini deleted the feat/socks5-esplora branch September 24, 2021 08:00
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@afilini@notmandatory@thomaseizinger@RCasatta
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

[esplora] Support proxies in EsploraBlockchain - #429

Merged
notmandatory merged 1 commit into
bitcoindevkit:masterfrom
afilini:feat/socks5-esplora
Sep 23, 2021
Merged

[esplora] Support proxies in EsploraBlockchain#429
notmandatory merged 1 commit into
bitcoindevkit:masterfrom
afilini:feat/socks5-esplora

Conversation

@afilini

Copy link
Copy Markdown
Member

Description

Add support for http/socks proxies in Esplora

Notes to the reviewers

Opening this as a draft, since I think it's gonna break for wasm32.

This is also technically an API break, which according to the new updated guidelines shouldn't happen. On the other hand, I can't think of a better way to do this. Am I supposed to make a different EsploraBlockchainConfig struct with the new field added and only deprecate the current one?

Checklists

All Submissions:

  • I've signed all my commits
  • I followed the contribution guidelines
  • I ran cargo fmt and cargo clippy before committing

New Features:

  • I've added tests for the new feature
  • I've added docs for the new feature
  • I've updated CHANGELOG.md
  • This pull request breaks the existing API

@afilini
afiliniforce-pushed the feat/socks5-esplora branch from 79afac4 to 47a7a9cCompareAugust 30, 2021 14:14
@notmandatory

Copy link
Copy Markdown
Member

On the question of how to make this sort of API change, since it's an additive change with an Option value I think it can be considered backward compatible. It does still technically break the API since anyone adopting the new version will have to do something. But it doesn't change the name or functionality of any existing struct fields or functions or function arguments. The alternative would be to make a whole new struct and new versions of all the functions that use it, which seems more disruptive when the original struct is eventually removed.

@thomaseizinger, as a user, what do you think about his sort of change? would it disrupt your workflow to have to add a new None value for this field after upgrading to a new version of bdk?

@thomaseizinger

thomaseizinger commented Aug 31, 2021

Copy link
Copy Markdown
Contributor

It is technically breaking yes.

I see two ways of changing the code so this change would be non breaking:

  1. Put #[non_exhaustive] on such kind of structs which forces users to use ::default or ::new to make an instance.
  2. Make all fields private and use a builder pattern to initialize such configurations:
EsploraBlockchainConfig::default().with_xyz().with_abc()

(1) is less code (no builders and getters) and would result in usage such as:

let config = EsploraBlockchainConfig{concurrency:Some(4),
..EsploraBlockchainConfig::default()};

Personally, I think (1) would be the better option unless you want to support Rust < 1.40.

For this particular PR, it is still a breaking change but we might at least take this opportunity to make future changes non-breaking :)

@RCasatta

Copy link
Copy Markdown
Contributor

is less code (no builders and getters) and would result in usage such as:

 let config = EsploraBlockchainConfig {
concurrency: Some(4),
..EsploraBlockchainConfig::default()
};

It looks this doesn't work for users outside the bdk crate (while logically flawless)

@thomaseizinger

Copy link
Copy Markdown
Contributor

is less code (no builders and getters) and would result in usage such as:

 let config = EsploraBlockchainConfig {
concurrency: Some(4),
..EsploraBlockchainConfig::default()
};

It looks this doesn't work for users outside the bdk crate (while logically flawless)

Damn, sorry about that. I swear I did this before with non-exhaustive structs. In guess it will have to be something like this then:

letmut config = ElectrumBlockchainConfig::new("foo".to_owned());
config.retry = 1;

@notmandatory

notmandatory commented Sep 3, 2021

Copy link
Copy Markdown
Member

What about the option:

  1. implement the Default trait for structs that are part of our public API? We can then state in the docs that users who want to maintain forward compatibility with new fields must add ..Default::default() whenever using a struct expression for a struct that implements the Default trait.

If we go this route I'll add an issue to implement Default for all the bdk structs.

And maybe someday a future version of Rust will let us add the #[non_exhaustive] macro and have it work as we'd like for option 1.

@thomaseizinger

Copy link
Copy Markdown
Contributor

What about the option:

1. implement the `Default` trait for structs that are part of our public API? We can then state in the docs that users who want to maintain forward compatibility with new fields must add `..Default::default()` whenever using a struct expression for a struct that implements the `Default` trait.

If we go this route I'll add an issue to implement Default for all the bdk structs.

And maybe someday a future version of Rust will let us add the #[non_exhaustive] macro and have it work as we'd like for option 1.

For EsploraBlockchainConfig though, there isn't really a sensible default I am afraid unless you want to default the URL to something?

In that case, providing a constructor that only takes the mandatory arguments (in this case url) requires rather little code and allows the use of #[non_exhaustive] as well. The only difference being that users need to make the struct mutable and override the defaults instead of being able to use struct initializer syntax.

@notmandatorynotmandatory mentioned this pull request Sep 8, 2021
6 tasks
@afilini

Copy link
Copy Markdown
MemberAuthor

We've talked about this yesterday during our team meeting and we reached the conclusion that it's better to just add the field and technically break the API: the reasoning is that we think it's better to force the user to use the explicit initialization syntax so that they are aware of all the existing fields of the struct.

Ideally we would also implement Default, but as you said we can't since we can't assume a default URL.

@notmandatory

Copy link
Copy Markdown
Member

Needs a rebase and then I think this one is ready to review.

@afilini
afilini marked this pull request as ready for review September 23, 2021 19:38

@notmandatorynotmandatory left a comment

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.

@notmandatory
notmandatory merged commit 3fe2380 into bitcoindevkit:masterSep 23, 2021
@afilini
afilini deleted the feat/socks5-esplora branch September 24, 2021 08:00
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@afilini@notmandatory@thomaseizinger@RCasatta