mirror of
https://github.com/comit-network/xmr-btc-swap.git
synced 2025-08-21 20:48:37 -04:00
Merge branch 'master' into redact-logs
This commit is contained in:
commit
57e80fced1
14 changed files with 385 additions and 102 deletions
2
.github/workflows/draft-new-release.yml
vendored
2
.github/workflows/draft-new-release.yml
vendored
|
@ -20,7 +20,7 @@ jobs:
|
||||||
run: git checkout -b release/${{ github.event.inputs.version }}
|
run: git checkout -b release/${{ github.event.inputs.version }}
|
||||||
|
|
||||||
- name: Update changelog
|
- name: Update changelog
|
||||||
uses: thomaseizinger/keep-a-changelog-new-release@3.0.0
|
uses: thomaseizinger/keep-a-changelog-new-release@3.1.0
|
||||||
with:
|
with:
|
||||||
version: ${{ github.event.inputs.version }}
|
version: ${{ github.event.inputs.version }}
|
||||||
changelogPath: CHANGELOG.md
|
changelogPath: CHANGELOG.md
|
||||||
|
|
|
@ -7,7 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
|
## [0.13.4] - 2024-07-25
|
||||||
|
|
||||||
- ASB: The `history` command can now be used while the asb is running.
|
- ASB: The `history` command can now be used while the asb is running.
|
||||||
|
- ASB: Retry locking of Monero if it fails on first attempt
|
||||||
|
|
||||||
## [0.13.3] - 2024-07-15
|
## [0.13.3] - 2024-07-15
|
||||||
|
|
||||||
|
@ -372,7 +375,8 @@ It is possible to migrate critical data from the old db to the sqlite but there
|
||||||
- Fixed an issue where Alice would not verify if Bob's Bitcoin lock transaction is semantically correct, i.e. pays the agreed upon amount to an output owned by both of them.
|
- Fixed an issue where Alice would not verify if Bob's Bitcoin lock transaction is semantically correct, i.e. pays the agreed upon amount to an output owned by both of them.
|
||||||
Fixing this required a **breaking change** on the network layer and hence old versions are not compatible with this version.
|
Fixing this required a **breaking change** on the network layer and hence old versions are not compatible with this version.
|
||||||
|
|
||||||
[unreleased]: https://github.com/comit-network/xmr-btc-swap/compare/0.13.3...HEAD
|
[unreleased]: https://github.com/comit-network/xmr-btc-swap/compare/0.13.4...HEAD
|
||||||
|
[0.13.4]: https://github.com/comit-network/xmr-btc-swap/compare/0.13.3...0.13.4
|
||||||
[0.13.3]: https://github.com/comit-network/xmr-btc-swap/compare/0.13.2...0.13.3
|
[0.13.3]: https://github.com/comit-network/xmr-btc-swap/compare/0.13.2...0.13.3
|
||||||
[0.13.2]: https://github.com/comit-network/xmr-btc-swap/compare/0.13.1...0.13.2
|
[0.13.2]: https://github.com/comit-network/xmr-btc-swap/compare/0.13.1...0.13.2
|
||||||
[0.13.1]: https://github.com/comit-network/xmr-btc-swap/compare/0.13.0...0.13.1
|
[0.13.1]: https://github.com/comit-network/xmr-btc-swap/compare/0.13.0...0.13.1
|
||||||
|
|
128
Cargo.lock
generated
128
Cargo.lock
generated
|
@ -752,7 +752,7 @@ dependencies = [
|
||||||
"nom",
|
"nom",
|
||||||
"pathdiff",
|
"pathdiff",
|
||||||
"serde",
|
"serde",
|
||||||
"toml 0.8.15",
|
"toml 0.8.19",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -1783,6 +1783,7 @@ dependencies = [
|
||||||
"http 1.0.0",
|
"http 1.0.0",
|
||||||
"http-body 1.0.0",
|
"http-body 1.0.0",
|
||||||
"httparse",
|
"httparse",
|
||||||
|
"httpdate",
|
||||||
"itoa",
|
"itoa",
|
||||||
"pin-project-lite 0.2.13",
|
"pin-project-lite 0.2.13",
|
||||||
"smallvec",
|
"smallvec",
|
||||||
|
@ -2602,14 +2603,19 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "mockito"
|
name = "mockito"
|
||||||
version = "1.4.0"
|
version = "1.5.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d2f6e023aa5bdf392aa06c78e4a4e6d498baab5138d0c993503350ebbc37bf1e"
|
checksum = "09b34bd91b9e5c5b06338d392463e1318d683cf82ec3d3af4014609be6e2108d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"assert-json-diff",
|
"assert-json-diff",
|
||||||
|
"bytes",
|
||||||
"colored",
|
"colored",
|
||||||
"futures-core",
|
"futures-util",
|
||||||
"hyper 0.14.28",
|
"http 1.0.0",
|
||||||
|
"http-body 1.0.0",
|
||||||
|
"http-body-util",
|
||||||
|
"hyper 1.4.1",
|
||||||
|
"hyper-util",
|
||||||
"log",
|
"log",
|
||||||
"rand 0.8.3",
|
"rand 0.8.3",
|
||||||
"regex",
|
"regex",
|
||||||
|
@ -4016,9 +4022,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde"
|
name = "serde"
|
||||||
version = "1.0.204"
|
version = "1.0.208"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bc76f558e0cbb2a839d37354c575f1dc3fdc6546b5be373ba43d95f231bf7c12"
|
checksum = "cff085d2cb684faa248efb494c39b68e522822ac0de72ccf08109abde717cfb2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"serde_derive",
|
"serde_derive",
|
||||||
]
|
]
|
||||||
|
@ -4045,9 +4051,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_derive"
|
name = "serde_derive"
|
||||||
version = "1.0.204"
|
version = "1.0.208"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e0cd7e117be63d3c3678776753929474f3b04a43a080c744d6b0ae2a8c28e222"
|
checksum = "24008e81ff7613ed8e5ba0cfaf24e2c2f1e5b8a0495711e44fcd4882fca62bcf"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
|
@ -4056,20 +4062,21 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_json"
|
name = "serde_json"
|
||||||
version = "1.0.118"
|
version = "1.0.124"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d947f6b3163d8857ea16c4fa0dd4840d52f3041039a85decd46867eb1abef2e4"
|
checksum = "66ad62847a56b3dba58cc891acd13884b9c61138d330c0d7b6181713d4fce38d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"itoa",
|
"itoa",
|
||||||
|
"memchr",
|
||||||
"ryu",
|
"ryu",
|
||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_spanned"
|
name = "serde_spanned"
|
||||||
version = "0.6.6"
|
version = "0.6.7"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "79e674e01f999af37c49f70a6ede167a8a60b2503e56c5599532a65baa5969a0"
|
checksum = "eb5b1b31579f3811bf615c144393417496f152e12ac8b7663bf664f4a815306d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
@ -4536,7 +4543,7 @@ checksum = "8049cf85f0e715d6af38dde439cb0ccb91f67fb9f5f63c80f8b43e48356e1a3f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "swap"
|
name = "swap"
|
||||||
version = "0.13.3"
|
version = "0.13.4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"async-compression",
|
"async-compression",
|
||||||
|
@ -4602,7 +4609,7 @@ dependencies = [
|
||||||
"tokio-tar",
|
"tokio-tar",
|
||||||
"tokio-tungstenite",
|
"tokio-tungstenite",
|
||||||
"tokio-util",
|
"tokio-util",
|
||||||
"toml 0.8.15",
|
"toml 0.8.19",
|
||||||
"torut",
|
"torut",
|
||||||
"tracing",
|
"tracing",
|
||||||
"tracing-appender",
|
"tracing-appender",
|
||||||
|
@ -4657,14 +4664,15 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tempfile"
|
name = "tempfile"
|
||||||
version = "3.10.1"
|
version = "3.12.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1"
|
checksum = "04cbcdd0c794ebb0d4cf35e88edd2f7d2c4c3e9a5a6dab322839b321c6a87a64"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if 1.0.0",
|
"cfg-if 1.0.0",
|
||||||
"fastrand",
|
"fastrand",
|
||||||
|
"once_cell",
|
||||||
"rustix",
|
"rustix",
|
||||||
"windows-sys 0.52.0",
|
"windows-sys 0.59.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -4864,9 +4872,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tokio-socks"
|
name = "tokio-socks"
|
||||||
version = "0.5.1"
|
version = "0.5.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "51165dfa029d2a65969413a6cc96f354b86b464498702f174a4efa13608fd8c0"
|
checksum = "0d4770b8024672c1101b3f6733eab95b18007dbe0847a8afe341fcf79e06043f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"either",
|
"either",
|
||||||
"futures-util",
|
"futures-util",
|
||||||
|
@ -4942,9 +4950,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "toml"
|
name = "toml"
|
||||||
version = "0.8.15"
|
version = "0.8.19"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ac2caab0bf757388c6c0ae23b3293fdb463fee59434529014f85e3263b995c28"
|
checksum = "a1ed1f98e3fdc28d6d910e6737ae6ab1a93bf1985935a1193e68f93eeb68d24e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
"serde_spanned",
|
"serde_spanned",
|
||||||
|
@ -4954,18 +4962,18 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "toml_datetime"
|
name = "toml_datetime"
|
||||||
version = "0.6.6"
|
version = "0.6.8"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4badfd56924ae69bcc9039335b2e017639ce3f9b001c393c1b2d1ef846ce2cbf"
|
checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "toml_edit"
|
name = "toml_edit"
|
||||||
version = "0.22.16"
|
version = "0.22.20"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "278f3d518e152219c994ce877758516bca5e118eaed6996192a774fb9fbf0788"
|
checksum = "583c44c02ad26b0c3f3066fe629275e50627026c51ac2e595cca4c230ce1ce1d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"indexmap 2.1.0",
|
"indexmap 2.1.0",
|
||||||
"serde",
|
"serde",
|
||||||
|
@ -5640,7 +5648,16 @@ version = "0.52.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
|
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"windows-targets 0.52.0",
|
"windows-targets 0.52.6",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-sys"
|
||||||
|
version = "0.59.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
|
||||||
|
dependencies = [
|
||||||
|
"windows-targets 0.52.6",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -5660,17 +5677,18 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows-targets"
|
name = "windows-targets"
|
||||||
version = "0.52.0"
|
version = "0.52.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd"
|
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"windows_aarch64_gnullvm 0.52.0",
|
"windows_aarch64_gnullvm 0.52.6",
|
||||||
"windows_aarch64_msvc 0.52.0",
|
"windows_aarch64_msvc 0.52.6",
|
||||||
"windows_i686_gnu 0.52.0",
|
"windows_i686_gnu 0.52.6",
|
||||||
"windows_i686_msvc 0.52.0",
|
"windows_i686_gnullvm",
|
||||||
"windows_x86_64_gnu 0.52.0",
|
"windows_i686_msvc 0.52.6",
|
||||||
"windows_x86_64_gnullvm 0.52.0",
|
"windows_x86_64_gnu 0.52.6",
|
||||||
"windows_x86_64_msvc 0.52.0",
|
"windows_x86_64_gnullvm 0.52.6",
|
||||||
|
"windows_x86_64_msvc 0.52.6",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -5681,9 +5699,9 @@ checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_aarch64_gnullvm"
|
name = "windows_aarch64_gnullvm"
|
||||||
version = "0.52.0"
|
version = "0.52.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea"
|
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_aarch64_msvc"
|
name = "windows_aarch64_msvc"
|
||||||
|
@ -5699,9 +5717,9 @@ checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_aarch64_msvc"
|
name = "windows_aarch64_msvc"
|
||||||
version = "0.52.0"
|
version = "0.52.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef"
|
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_i686_gnu"
|
name = "windows_i686_gnu"
|
||||||
|
@ -5717,9 +5735,15 @@ checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_i686_gnu"
|
name = "windows_i686_gnu"
|
||||||
version = "0.52.0"
|
version = "0.52.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313"
|
checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_i686_gnullvm"
|
||||||
|
version = "0.52.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_i686_msvc"
|
name = "windows_i686_msvc"
|
||||||
|
@ -5735,9 +5759,9 @@ checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_i686_msvc"
|
name = "windows_i686_msvc"
|
||||||
version = "0.52.0"
|
version = "0.52.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a"
|
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_x86_64_gnu"
|
name = "windows_x86_64_gnu"
|
||||||
|
@ -5753,9 +5777,9 @@ checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_x86_64_gnu"
|
name = "windows_x86_64_gnu"
|
||||||
version = "0.52.0"
|
version = "0.52.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd"
|
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_x86_64_gnullvm"
|
name = "windows_x86_64_gnullvm"
|
||||||
|
@ -5765,9 +5789,9 @@ checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_x86_64_gnullvm"
|
name = "windows_x86_64_gnullvm"
|
||||||
version = "0.52.0"
|
version = "0.52.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e"
|
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_x86_64_msvc"
|
name = "windows_x86_64_msvc"
|
||||||
|
@ -5783,15 +5807,15 @@ checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_x86_64_msvc"
|
name = "windows_x86_64_msvc"
|
||||||
version = "0.52.0"
|
version = "0.52.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04"
|
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "winnow"
|
name = "winnow"
|
||||||
version = "0.6.5"
|
version = "0.6.18"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "dffa400e67ed5a4dd237983829e66475f0a4a26938c4b04c21baede6262215b8"
|
checksum = "68a9bda4691f099d435ad181000724da8e5899daa10713c2d432552b9ccd3a6f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"memchr",
|
"memchr",
|
||||||
]
|
]
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "swap"
|
name = "swap"
|
||||||
version = "0.13.3"
|
version = "0.13.4"
|
||||||
authors = [ "The COMIT guys <hello@comit.network>" ]
|
authors = [ "The COMIT guys <hello@comit.network>" ]
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
description = "XMR/BTC trustless atomic swaps."
|
description = "XMR/BTC trustless atomic swaps."
|
||||||
|
@ -83,7 +83,7 @@ bitcoin-harness = { git = "https://github.com/delta1/bitcoin-harness-rs.git", re
|
||||||
get-port = "3"
|
get-port = "3"
|
||||||
hyper = "1.4"
|
hyper = "1.4"
|
||||||
jsonrpsee = { version = "0.16.2", features = [ "ws-client" ] }
|
jsonrpsee = { version = "0.16.2", features = [ "ws-client" ] }
|
||||||
mockito = "1.4"
|
mockito = "1.5"
|
||||||
monero-harness = { path = "../monero-harness" }
|
monero-harness = { path = "../monero-harness" }
|
||||||
port_check = "0.2"
|
port_check = "0.2"
|
||||||
proptest = "1"
|
proptest = "1"
|
||||||
|
|
|
@ -170,6 +170,7 @@ pub struct Context {
|
||||||
pub swap_lock: Arc<SwapLock>,
|
pub swap_lock: Arc<SwapLock>,
|
||||||
pub config: Config,
|
pub config: Config,
|
||||||
pub tasks: Arc<PendingTaskList>,
|
pub tasks: Arc<PendingTaskList>,
|
||||||
|
pub is_daemon: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
|
@ -183,6 +184,7 @@ impl Context {
|
||||||
debug: bool,
|
debug: bool,
|
||||||
json: bool,
|
json: bool,
|
||||||
server_address: Option<SocketAddr>,
|
server_address: Option<SocketAddr>,
|
||||||
|
is_daemon: bool,
|
||||||
) -> Result<Context> {
|
) -> Result<Context> {
|
||||||
let data_dir = data::data_dir_from(data, is_testnet)?;
|
let data_dir = data::data_dir_from(data, is_testnet)?;
|
||||||
let env_config = env_config_from(is_testnet);
|
let env_config = env_config_from(is_testnet);
|
||||||
|
@ -251,6 +253,7 @@ impl Context {
|
||||||
},
|
},
|
||||||
swap_lock: Arc::new(SwapLock::new()),
|
swap_lock: Arc::new(SwapLock::new()),
|
||||||
tasks: Arc::new(PendingTaskList::default()),
|
tasks: Arc::new(PendingTaskList::default()),
|
||||||
|
is_daemon,
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(context)
|
Ok(context)
|
||||||
|
@ -275,6 +278,7 @@ impl Context {
|
||||||
monero_rpc_process: None,
|
monero_rpc_process: None,
|
||||||
swap_lock: Arc::new(SwapLock::new()),
|
swap_lock: Arc::new(SwapLock::new()),
|
||||||
tasks: Arc::new(PendingTaskList::default()),
|
tasks: Arc::new(PendingTaskList::default()),
|
||||||
|
is_daemon: true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,9 +9,12 @@ use crate::protocol::bob::{BobState, Swap};
|
||||||
use crate::protocol::{bob, State};
|
use crate::protocol::{bob, State};
|
||||||
use crate::{bitcoin, cli, monero, rpc};
|
use crate::{bitcoin, cli, monero, rpc};
|
||||||
use anyhow::{bail, Context as AnyContext, Result};
|
use anyhow::{bail, Context as AnyContext, Result};
|
||||||
|
use comfy_table::Table;
|
||||||
use libp2p::core::Multiaddr;
|
use libp2p::core::Multiaddr;
|
||||||
use qrcode::render::unicode;
|
use qrcode::render::unicode;
|
||||||
use qrcode::QrCode;
|
use qrcode::QrCode;
|
||||||
|
use rust_decimal::prelude::FromPrimitive;
|
||||||
|
use rust_decimal::Decimal;
|
||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
use std::cmp::min;
|
use std::cmp::min;
|
||||||
use std::convert::TryInto;
|
use std::convert::TryInto;
|
||||||
|
@ -652,14 +655,97 @@ impl Request {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
Method::History => {
|
Method::History => {
|
||||||
let swaps = context.db.all().await?;
|
let mut table = Table::new();
|
||||||
let mut vec: Vec<(Uuid, String)> = Vec::new();
|
table.set_header(vec![
|
||||||
for (swap_id, state) in swaps {
|
"Swap ID",
|
||||||
let state: BobState = state.try_into()?;
|
"Start Date",
|
||||||
vec.push((swap_id, state.to_string()));
|
"State",
|
||||||
|
"BTC Amount",
|
||||||
|
"XMR Amount",
|
||||||
|
"Exchange Rate",
|
||||||
|
"Trading Partner Peer ID",
|
||||||
|
]);
|
||||||
|
|
||||||
|
let all_swaps = context.db.all().await?;
|
||||||
|
let mut json_results = Vec::new();
|
||||||
|
|
||||||
|
for (swap_id, state) in all_swaps {
|
||||||
|
let result: Result<_> = async {
|
||||||
|
let latest_state: BobState = state.try_into()?;
|
||||||
|
let all_states = context.db.get_states(swap_id).await?;
|
||||||
|
let state3 = all_states
|
||||||
|
.iter()
|
||||||
|
.find_map(|s| {
|
||||||
|
if let State::Bob(BobState::BtcLocked { state3, .. }) = s {
|
||||||
|
Some(state3)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.context("Failed to get \"BtcLocked\" state")?;
|
||||||
|
|
||||||
|
let swap_start_date = context.db.get_swap_start_date(swap_id).await?;
|
||||||
|
let peer_id = context.db.get_peer_id(swap_id).await?;
|
||||||
|
let btc_amount = state3.tx_lock.lock_amount();
|
||||||
|
let xmr_amount = state3.xmr;
|
||||||
|
let exchange_rate = Decimal::from_f64(btc_amount.to_btc())
|
||||||
|
.ok_or_else(|| {
|
||||||
|
anyhow::anyhow!("Failed to convert BTC amount to Decimal")
|
||||||
|
})?
|
||||||
|
.checked_div(xmr_amount.as_xmr())
|
||||||
|
.ok_or_else(|| anyhow::anyhow!("Division by zero or overflow"))?;
|
||||||
|
let exchange_rate = format!("{} XMR/BTC", exchange_rate.round_dp(8));
|
||||||
|
|
||||||
|
let swap_data = json!({
|
||||||
|
"swapId": swap_id.to_string(),
|
||||||
|
"startDate": swap_start_date.to_string(),
|
||||||
|
"state": latest_state.to_string(),
|
||||||
|
"btcAmount": btc_amount.to_string(),
|
||||||
|
"xmrAmount": xmr_amount.to_string(),
|
||||||
|
"exchangeRate": exchange_rate,
|
||||||
|
"tradingPartnerPeerId": peer_id.to_string()
|
||||||
|
});
|
||||||
|
|
||||||
|
if context.config.json {
|
||||||
|
tracing::info!(
|
||||||
|
swap_id = %swap_id,
|
||||||
|
swap_start_date = %swap_start_date,
|
||||||
|
latest_state = %latest_state,
|
||||||
|
btc_amount = %btc_amount,
|
||||||
|
xmr_amount = %xmr_amount,
|
||||||
|
exchange_rate = %exchange_rate,
|
||||||
|
trading_partner_peer_id = %peer_id,
|
||||||
|
"Found swap in database"
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
table.add_row(vec![
|
||||||
|
swap_id.to_string(),
|
||||||
|
swap_start_date.to_string(),
|
||||||
|
latest_state.to_string(),
|
||||||
|
btc_amount.to_string(),
|
||||||
|
xmr_amount.to_string(),
|
||||||
|
exchange_rate,
|
||||||
|
peer_id.to_string(),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(swap_data)
|
||||||
|
}
|
||||||
|
.await;
|
||||||
|
|
||||||
|
match result {
|
||||||
|
Ok(swap_data) => json_results.push(swap_data),
|
||||||
|
Err(e) => {
|
||||||
|
tracing::error!(swap_id = %swap_id, error = %e, "Failed to get swap details")
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(json!({ "swaps": vec }))
|
if !context.config.json && !context.is_daemon {
|
||||||
|
println!("{}", table);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(json!({"swaps": json_results}))
|
||||||
}
|
}
|
||||||
Method::Logs { logs_dir, redact, swap_id } => {
|
Method::Logs { logs_dir, redact, swap_id } => {
|
||||||
let dir = logs_dir.unwrap_or(context.config.data_dir.join("logs"));
|
let dir = logs_dir.unwrap_or(context.config.data_dir.join("logs"));
|
||||||
|
|
|
@ -31,12 +31,12 @@ where
|
||||||
env_config: env_config(testnet),
|
env_config: env_config(testnet),
|
||||||
cmd: Command::Start { resume_only },
|
cmd: Command::Start { resume_only },
|
||||||
},
|
},
|
||||||
RawCommand::History => Arguments {
|
RawCommand::History { only_unfinished } => Arguments {
|
||||||
testnet,
|
testnet,
|
||||||
json,
|
json,
|
||||||
config_path: config_path(config, testnet)?,
|
config_path: config_path(config, testnet)?,
|
||||||
env_config: env_config(testnet),
|
env_config: env_config(testnet),
|
||||||
cmd: Command::History,
|
cmd: Command::History { only_unfinished },
|
||||||
},
|
},
|
||||||
RawCommand::Logs {
|
RawCommand::Logs {
|
||||||
logs_dir: dir_path,
|
logs_dir: dir_path,
|
||||||
|
@ -197,7 +197,9 @@ pub enum Command {
|
||||||
Start {
|
Start {
|
||||||
resume_only: bool,
|
resume_only: bool,
|
||||||
},
|
},
|
||||||
History,
|
History {
|
||||||
|
only_unfinished: bool,
|
||||||
|
},
|
||||||
Config,
|
Config,
|
||||||
Logs {
|
Logs {
|
||||||
logs_dir: Option<PathBuf>,
|
logs_dir: Option<PathBuf>,
|
||||||
|
@ -275,8 +277,6 @@ pub enum RawCommand {
|
||||||
)]
|
)]
|
||||||
resume_only: bool,
|
resume_only: bool,
|
||||||
},
|
},
|
||||||
#[structopt(about = "Prints swap-id and the state of each swap ever made.")]
|
|
||||||
History,
|
|
||||||
#[structopt(about = "Prints all logging messages issued in the past.")]
|
#[structopt(about = "Prints all logging messages issued in the past.")]
|
||||||
Logs {
|
Logs {
|
||||||
#[structopt(
|
#[structopt(
|
||||||
|
@ -296,6 +296,14 @@ pub enum RawCommand {
|
||||||
)]
|
)]
|
||||||
swap_id: Option<Uuid>
|
swap_id: Option<Uuid>
|
||||||
},
|
},
|
||||||
|
#[structopt(about = "Prints swap-id and the state of each swap ever made.")]
|
||||||
|
History {
|
||||||
|
#[structopt(
|
||||||
|
long = "only-unfinished",
|
||||||
|
help = "If set, only unfinished swaps will be printed."
|
||||||
|
)]
|
||||||
|
only_unfinished: bool,
|
||||||
|
},
|
||||||
#[structopt(about = "Prints the current config")]
|
#[structopt(about = "Prints the current config")]
|
||||||
Config,
|
Config,
|
||||||
#[structopt(about = "Allows withdrawing BTC from the internal Bitcoin wallet.")]
|
#[structopt(about = "Allows withdrawing BTC from the internal Bitcoin wallet.")]
|
||||||
|
@ -411,7 +419,9 @@ mod tests {
|
||||||
json: false,
|
json: false,
|
||||||
config_path: default_mainnet_conf_path,
|
config_path: default_mainnet_conf_path,
|
||||||
env_config: mainnet_env_config,
|
env_config: mainnet_env_config,
|
||||||
cmd: Command::History,
|
cmd: Command::History {
|
||||||
|
only_unfinished: false,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
let args = parse_args(raw_ars).unwrap();
|
let args = parse_args(raw_ars).unwrap();
|
||||||
assert_eq!(expected_args, args);
|
assert_eq!(expected_args, args);
|
||||||
|
@ -586,7 +596,9 @@ mod tests {
|
||||||
json: false,
|
json: false,
|
||||||
config_path: default_testnet_conf_path,
|
config_path: default_testnet_conf_path,
|
||||||
env_config: testnet_env_config,
|
env_config: testnet_env_config,
|
||||||
cmd: Command::History,
|
cmd: Command::History {
|
||||||
|
only_unfinished: false,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
let args = parse_args(raw_ars).unwrap();
|
let args = parse_args(raw_ars).unwrap();
|
||||||
assert_eq!(expected_args, args);
|
assert_eq!(expected_args, args);
|
||||||
|
|
|
@ -19,6 +19,8 @@ use libp2p::core::Multiaddr;
|
||||||
use libp2p::swarm::AddressScore;
|
use libp2p::swarm::AddressScore;
|
||||||
use libp2p::Swarm;
|
use libp2p::Swarm;
|
||||||
use swap::common::tracing_util::Format;
|
use swap::common::tracing_util::Format;
|
||||||
|
use rust_decimal::prelude::FromPrimitive;
|
||||||
|
use rust_decimal::Decimal;
|
||||||
use std::convert::TryInto;
|
use std::convert::TryInto;
|
||||||
use std::net::{IpAddr, Ipv4Addr, SocketAddr};
|
use std::net::{IpAddr, Ipv4Addr, SocketAddr};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
@ -34,7 +36,9 @@ use swap::common::{self, check_latest_version, get_logs};
|
||||||
use swap::database::{open_db, AccessMode};
|
use swap::database::{open_db, AccessMode};
|
||||||
use swap::network::rendezvous::XmrBtcNamespace;
|
use swap::network::rendezvous::XmrBtcNamespace;
|
||||||
use swap::network::swarm;
|
use swap::network::swarm;
|
||||||
|
use swap::protocol::alice::swap::is_complete;
|
||||||
use swap::protocol::alice::{run, AliceState};
|
use swap::protocol::alice::{run, AliceState};
|
||||||
|
use swap::protocol::State;
|
||||||
use swap::seed::Seed;
|
use swap::seed::Seed;
|
||||||
use swap::tor::AuthenticatedClient;
|
use swap::tor::AuthenticatedClient;
|
||||||
use swap::{bitcoin, kraken, monero, tor};
|
use swap::{bitcoin, kraken, monero, tor};
|
||||||
|
@ -233,19 +237,87 @@ async fn main() -> Result<()> {
|
||||||
|
|
||||||
event_loop.run().await;
|
event_loop.run().await;
|
||||||
}
|
}
|
||||||
Command::History => {
|
Command::History { only_unfinished } => {
|
||||||
let db = open_db(config.data.dir.join("sqlite"), AccessMode::ReadOnly).await?;
|
let db = open_db(config.data.dir.join("sqlite"), AccessMode::ReadOnly).await?;
|
||||||
|
let mut table: Table = Table::new();
|
||||||
|
|
||||||
let mut table = Table::new();
|
table.set_header(vec![
|
||||||
|
"Swap ID",
|
||||||
|
"Start Date",
|
||||||
|
"State",
|
||||||
|
"BTC Amount",
|
||||||
|
"XMR Amount",
|
||||||
|
"Exchange Rate",
|
||||||
|
"Trading Partner Peer ID",
|
||||||
|
"Completed",
|
||||||
|
]);
|
||||||
|
|
||||||
table.set_header(vec!["SWAP ID", "STATE"]);
|
let all_swaps = db.all().await?;
|
||||||
|
for (swap_id, state) in all_swaps {
|
||||||
|
if let Err(e) = async {
|
||||||
|
let latest_state: AliceState = state.try_into()?;
|
||||||
|
let is_completed = is_complete(&latest_state);
|
||||||
|
|
||||||
for (swap_id, state) in db.all().await? {
|
if only_unfinished && is_completed {
|
||||||
let state: AliceState = state.try_into()?;
|
return Ok::<_, anyhow::Error>(());
|
||||||
table.add_row(vec![swap_id.to_string(), state.to_string()]);
|
}
|
||||||
|
|
||||||
|
let all_states = db.get_states(swap_id).await?;
|
||||||
|
let state3 = all_states
|
||||||
|
.iter()
|
||||||
|
.find_map(|s| match s {
|
||||||
|
State::Alice(AliceState::BtcLockTransactionSeen { state3 }) => {
|
||||||
|
Some(state3)
|
||||||
|
}
|
||||||
|
_ => None,
|
||||||
|
})
|
||||||
|
.context("Failed to get \"BtcLockTransactionSeen\" state")?;
|
||||||
|
|
||||||
|
let swap_start_date = db.get_swap_start_date(swap_id).await?;
|
||||||
|
let peer_id = db.get_peer_id(swap_id).await?;
|
||||||
|
|
||||||
|
let exchange_rate = Decimal::from_f64(state3.btc.to_btc())
|
||||||
|
.ok_or_else(|| anyhow::anyhow!("Failed to convert BTC amount to Decimal"))?
|
||||||
|
.checked_div(state3.xmr.as_xmr())
|
||||||
|
.ok_or_else(|| anyhow::anyhow!("Division by zero or overflow"))?;
|
||||||
|
let exchange_rate = format!("{} XMR/BTC", exchange_rate.round_dp(8));
|
||||||
|
|
||||||
|
if json {
|
||||||
|
tracing::info!(
|
||||||
|
swap_id = %swap_id,
|
||||||
|
swap_start_date = %swap_start_date,
|
||||||
|
latest_state = %latest_state,
|
||||||
|
btc_amount = %state3.btc,
|
||||||
|
xmr_amount = %state3.xmr,
|
||||||
|
exchange_rate = %exchange_rate,
|
||||||
|
trading_partner_peer_id = %peer_id,
|
||||||
|
completed = is_completed,
|
||||||
|
"Found swap in database"
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
table.add_row(vec![
|
||||||
|
swap_id.to_string(),
|
||||||
|
swap_start_date.to_string(),
|
||||||
|
latest_state.to_string(),
|
||||||
|
state3.btc.to_string(),
|
||||||
|
state3.xmr.to_string(),
|
||||||
|
exchange_rate,
|
||||||
|
peer_id.to_string(),
|
||||||
|
is_completed.to_string(),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok::<_, anyhow::Error>(())
|
||||||
|
}
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
tracing::error!(swap_id = %swap_id, error = %e, "Failed to get swap details");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
println!("{}", table);
|
if !json {
|
||||||
|
println!("{}", table);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Command::Config => {
|
Command::Config => {
|
||||||
let config_json = serde_json::to_string_pretty(&config)?;
|
let config_json = serde_json::to_string_pretty(&config)?;
|
||||||
|
|
|
@ -78,6 +78,7 @@ where
|
||||||
debug,
|
debug,
|
||||||
json,
|
json,
|
||||||
None,
|
None,
|
||||||
|
false,
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
|
@ -100,7 +101,8 @@ where
|
||||||
let request = Request::new(Method::History);
|
let request = Request::new(Method::History);
|
||||||
|
|
||||||
let context =
|
let context =
|
||||||
Context::build(None, None, None, data, is_testnet, debug, json, None).await?;
|
Context::build(None, None, None, data, is_testnet, debug, json, None, false)
|
||||||
|
.await?;
|
||||||
(context, request)
|
(context, request)
|
||||||
}
|
}
|
||||||
CliCommand::Logs {
|
CliCommand::Logs {
|
||||||
|
@ -117,7 +119,8 @@ where
|
||||||
let request = Request::new(Method::Config);
|
let request = Request::new(Method::Config);
|
||||||
|
|
||||||
let context =
|
let context =
|
||||||
Context::build(None, None, None, data, is_testnet, debug, json, None).await?;
|
Context::build(None, None, None, data, is_testnet, debug, json, None, false)
|
||||||
|
.await?;
|
||||||
(context, request)
|
(context, request)
|
||||||
}
|
}
|
||||||
CliCommand::Balance { bitcoin } => {
|
CliCommand::Balance { bitcoin } => {
|
||||||
|
@ -134,6 +137,7 @@ where
|
||||||
debug,
|
debug,
|
||||||
json,
|
json,
|
||||||
None,
|
None,
|
||||||
|
false,
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
(context, request)
|
(context, request)
|
||||||
|
@ -155,6 +159,7 @@ where
|
||||||
debug,
|
debug,
|
||||||
json,
|
json,
|
||||||
server_address,
|
server_address,
|
||||||
|
true,
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
(context, request)
|
(context, request)
|
||||||
|
@ -176,6 +181,7 @@ where
|
||||||
debug,
|
debug,
|
||||||
json,
|
json,
|
||||||
None,
|
None,
|
||||||
|
false,
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
(context, request)
|
(context, request)
|
||||||
|
@ -197,6 +203,7 @@ where
|
||||||
debug,
|
debug,
|
||||||
json,
|
json,
|
||||||
None,
|
None,
|
||||||
|
false,
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
(context, request)
|
(context, request)
|
||||||
|
@ -217,6 +224,7 @@ where
|
||||||
debug,
|
debug,
|
||||||
json,
|
json,
|
||||||
None,
|
None,
|
||||||
|
false,
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
(context, request)
|
(context, request)
|
||||||
|
@ -227,8 +235,18 @@ where
|
||||||
} => {
|
} => {
|
||||||
let request = Request::new(Method::ListSellers { rendezvous_point });
|
let request = Request::new(Method::ListSellers { rendezvous_point });
|
||||||
|
|
||||||
let context =
|
let context = Context::build(
|
||||||
Context::build(None, None, Some(tor), data, is_testnet, debug, json, None).await?;
|
None,
|
||||||
|
None,
|
||||||
|
Some(tor),
|
||||||
|
data,
|
||||||
|
is_testnet,
|
||||||
|
debug,
|
||||||
|
json,
|
||||||
|
None,
|
||||||
|
false,
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
(context, request)
|
(context, request)
|
||||||
}
|
}
|
||||||
|
@ -244,6 +262,7 @@ where
|
||||||
debug,
|
debug,
|
||||||
json,
|
json,
|
||||||
None,
|
None,
|
||||||
|
false,
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
(context, request)
|
(context, request)
|
||||||
|
@ -254,7 +273,8 @@ where
|
||||||
let request = Request::new(Method::MoneroRecovery { swap_id });
|
let request = Request::new(Method::MoneroRecovery { swap_id });
|
||||||
|
|
||||||
let context =
|
let context =
|
||||||
Context::build(None, None, None, data, is_testnet, debug, json, None).await?;
|
Context::build(None, None, None, data, is_testnet, debug, json, None, false)
|
||||||
|
.await?;
|
||||||
|
|
||||||
(context, request)
|
(context, request)
|
||||||
}
|
}
|
||||||
|
|
|
@ -142,6 +142,14 @@ impl Amount {
|
||||||
Decimal::from(self.as_piconero())
|
Decimal::from(self.as_piconero())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn as_xmr(&self) -> Decimal {
|
||||||
|
let mut decimal = Decimal::from(self.0);
|
||||||
|
decimal
|
||||||
|
.set_scale(12)
|
||||||
|
.expect("12 is smaller than max precision of 28");
|
||||||
|
decimal
|
||||||
|
}
|
||||||
|
|
||||||
fn from_decimal(amount: Decimal) -> Result<Self> {
|
fn from_decimal(amount: Decimal) -> Result<Self> {
|
||||||
let piconeros_dec =
|
let piconeros_dec =
|
||||||
amount.mul(Decimal::from_u64(PICONERO_OFFSET).expect("constant to fit into u64"));
|
amount.mul(Decimal::from_u64(PICONERO_OFFSET).expect("constant to fit into u64"));
|
||||||
|
@ -184,11 +192,8 @@ impl From<Amount> for u64 {
|
||||||
|
|
||||||
impl fmt::Display for Amount {
|
impl fmt::Display for Amount {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
let mut decimal = Decimal::from(self.0);
|
let xmr_value = self.as_xmr();
|
||||||
decimal
|
write!(f, "{} XMR", xmr_value)
|
||||||
.set_scale(12)
|
|
||||||
.expect("12 is smaller than max precision of 28");
|
|
||||||
write!(f, "{} XMR", decimal)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -384,8 +384,8 @@ pub struct State3 {
|
||||||
S_b_bitcoin: bitcoin::PublicKey,
|
S_b_bitcoin: bitcoin::PublicKey,
|
||||||
pub v: monero::PrivateViewKey,
|
pub v: monero::PrivateViewKey,
|
||||||
#[serde(with = "::bitcoin::util::amount::serde::as_sat")]
|
#[serde(with = "::bitcoin::util::amount::serde::as_sat")]
|
||||||
btc: bitcoin::Amount,
|
pub btc: bitcoin::Amount,
|
||||||
xmr: monero::Amount,
|
pub xmr: monero::Amount,
|
||||||
pub cancel_timelock: CancelTimelock,
|
pub cancel_timelock: CancelTimelock,
|
||||||
pub punish_timelock: PunishTimelock,
|
pub punish_timelock: PunishTimelock,
|
||||||
refund_address: bitcoin::Address,
|
refund_address: bitcoin::Address,
|
||||||
|
|
|
@ -1,11 +1,14 @@
|
||||||
//! Run an XMR/BTC swap in the role of Alice.
|
//! Run an XMR/BTC swap in the role of Alice.
|
||||||
//! Alice holds XMR and wishes receive BTC.
|
//! Alice holds XMR and wishes receive BTC.
|
||||||
|
use std::time::Duration;
|
||||||
|
|
||||||
use crate::asb::{EventLoopHandle, LatestRate};
|
use crate::asb::{EventLoopHandle, LatestRate};
|
||||||
use crate::bitcoin::ExpiredTimelocks;
|
use crate::bitcoin::ExpiredTimelocks;
|
||||||
use crate::env::Config;
|
use crate::env::Config;
|
||||||
use crate::protocol::alice::{AliceState, Swap};
|
use crate::protocol::alice::{AliceState, Swap};
|
||||||
use crate::{bitcoin, monero};
|
use crate::{bitcoin, monero};
|
||||||
use anyhow::{bail, Context, Result};
|
use anyhow::{bail, Context, Result};
|
||||||
|
use backoff::ExponentialBackoffBuilder;
|
||||||
use tokio::select;
|
use tokio::select;
|
||||||
use tokio::time::timeout;
|
use tokio::time::timeout;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
@ -111,23 +114,63 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
AliceState::BtcLocked { state3 } => {
|
AliceState::BtcLocked { state3 } => {
|
||||||
match state3.expired_timelocks(bitcoin_wallet).await? {
|
// We retry to lock the Monero wallet until we succeed or until the cancel timelock expires.
|
||||||
ExpiredTimelocks::None { .. } => {
|
//
|
||||||
// Record the current monero wallet block height so we don't have to scan from
|
// This is necessary because the monero-wallet-rpc can sometimes error out due to various reasons, such as
|
||||||
// block 0 for scenarios where we create a refund wallet.
|
// - no connection to the daemon
|
||||||
let monero_wallet_restore_blockheight = monero_wallet.block_height().await?;
|
// - "failed to get output distribution"
|
||||||
|
// See https://github.com/comit-network/xmr-btc-swap/issues/1726
|
||||||
|
let backoff = ExponentialBackoffBuilder::new()
|
||||||
|
.with_initial_interval(Duration::from_secs(5))
|
||||||
|
.with_max_interval(Duration::from_secs(60 * 3))
|
||||||
|
.with_max_elapsed_time(None)
|
||||||
|
.build();
|
||||||
|
|
||||||
let transfer_proof = monero_wallet
|
let result = backoff::future::retry_notify(
|
||||||
.transfer(state3.lock_xmr_transfer_request())
|
backoff,
|
||||||
.await?;
|
|| async {
|
||||||
|
match state3.expired_timelocks(bitcoin_wallet).await {
|
||||||
|
Ok(ExpiredTimelocks::None { .. }) => {
|
||||||
|
// Record the current monero wallet block height so we don't have to scan from
|
||||||
|
// block 0 for scenarios where we create a refund wallet.
|
||||||
|
let monero_wallet_restore_blockheight = monero_wallet
|
||||||
|
.block_height()
|
||||||
|
.await
|
||||||
|
.map_err(backoff::Error::transient)?;
|
||||||
|
|
||||||
|
let transfer_proof = monero_wallet
|
||||||
|
.transfer(state3.lock_xmr_transfer_request())
|
||||||
|
.await
|
||||||
|
.map_err(backoff::Error::transient)?;
|
||||||
|
|
||||||
|
Ok(Some((monero_wallet_restore_blockheight, transfer_proof)))
|
||||||
|
}
|
||||||
|
Ok(_) => Ok(None),
|
||||||
|
Err(e) => Err(backoff::Error::transient(e)),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|err, delay: Duration| {
|
||||||
|
tracing::warn!(
|
||||||
|
%err,
|
||||||
|
delay_secs = delay.as_secs(),
|
||||||
|
"Failed to lock XMR. We will retry after a delay"
|
||||||
|
);
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
match result {
|
||||||
|
Ok(Some((monero_wallet_restore_blockheight, transfer_proof))) => {
|
||||||
AliceState::XmrLockTransactionSent {
|
AliceState::XmrLockTransactionSent {
|
||||||
monero_wallet_restore_blockheight,
|
monero_wallet_restore_blockheight,
|
||||||
transfer_proof,
|
transfer_proof,
|
||||||
state3,
|
state3,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => AliceState::SafelyAborted,
|
Ok(None) => AliceState::SafelyAborted,
|
||||||
|
Err(e) => {
|
||||||
|
unreachable!("We should retry forever until the cancel timelock expires. But we got an error: {:#}", e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
AliceState::XmrLockTransactionSent {
|
AliceState::XmrLockTransactionSent {
|
||||||
|
@ -397,7 +440,7 @@ where
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn is_complete(state: &AliceState) -> bool {
|
pub fn is_complete(state: &AliceState) -> bool {
|
||||||
matches!(
|
matches!(
|
||||||
state,
|
state,
|
||||||
AliceState::XmrRefunded
|
AliceState::XmrRefunded
|
||||||
|
|
|
@ -369,7 +369,7 @@ pub struct State3 {
|
||||||
S_a_monero: monero::PublicKey,
|
S_a_monero: monero::PublicKey,
|
||||||
S_a_bitcoin: bitcoin::PublicKey,
|
S_a_bitcoin: bitcoin::PublicKey,
|
||||||
v: monero::PrivateViewKey,
|
v: monero::PrivateViewKey,
|
||||||
xmr: monero::Amount,
|
pub xmr: monero::Amount,
|
||||||
pub cancel_timelock: CancelTimelock,
|
pub cancel_timelock: CancelTimelock,
|
||||||
punish_timelock: PunishTimelock,
|
punish_timelock: PunishTimelock,
|
||||||
refund_address: bitcoin::Address,
|
refund_address: bitcoin::Address,
|
||||||
|
|
|
@ -103,13 +103,26 @@ mod test {
|
||||||
|
|
||||||
let (client, _, _) = setup_daemon(harness_ctx).await;
|
let (client, _, _) = setup_daemon(harness_ctx).await;
|
||||||
|
|
||||||
let response: HashMap<String, Vec<(Uuid, String)>> = client
|
let response: HashMap<String, Vec<Value>> = client
|
||||||
.request("get_history", ObjectParams::new())
|
.request("get_history", ObjectParams::new())
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let swaps: Vec<(Uuid, String)> = vec![(bob_swap_id, "btc is locked".to_string())];
|
|
||||||
|
|
||||||
assert_eq!(response, HashMap::from([("swaps".to_string(), swaps)]));
|
let swaps = response.get("swaps").unwrap();
|
||||||
|
assert_eq!(swaps.len(), 1);
|
||||||
|
|
||||||
|
assert_has_keys_serde(
|
||||||
|
swaps[0].as_object().unwrap(),
|
||||||
|
&[
|
||||||
|
"swapId",
|
||||||
|
"startDate",
|
||||||
|
"state",
|
||||||
|
"btcAmount",
|
||||||
|
"xmrAmount",
|
||||||
|
"exchangeRate",
|
||||||
|
"tradingPartnerPeerId",
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
let response: HashMap<String, HashMap<Uuid, Vec<Value>>> = client
|
let response: HashMap<String, HashMap<Uuid, Vec<Value>>> = client
|
||||||
.request("get_raw_states", ObjectParams::new())
|
.request("get_raw_states", ObjectParams::new())
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue