CLI tool for migrating PDS

Migrate identity and finalise migration

Changed files
+443 -3
src
+298
Cargo.lock
···
]
[[package]]
name = "atrium-identity"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
···
version = "0.2.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4cbbc9d0964165b47557570cce6c952866c2678457aca742aafc9fb771d30270"
[[package]]
name = "base64"
···
checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
[[package]]
name = "bitflags"
version = "2.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd"
[[package]]
name = "bumpalo"
···
]
[[package]]
name = "core-foundation"
version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
···
checksum = "b49ba7ef1ad6107f8824dbe97de947cbaac53c44e7f9756a1fba0d37c1eec505"
dependencies = [
"memchr",
]
[[package]]
···
checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28"
[[package]]
name = "dashmap"
version = "6.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
···
]
[[package]]
name = "displaydoc"
version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
···
]
[[package]]
name = "enum-as-inner"
version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
···
version = "2.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be"
[[package]]
name = "flate2"
···
]
[[package]]
name = "getrandom"
version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
···
checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f"
[[package]]
name = "hashbrown"
version = "0.14.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
···
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
[[package]]
name = "hickory-proto"
···
]
[[package]]
name = "hostname"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
···
]
[[package]]
name = "langtag"
version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
···
checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39"
[[package]]
name = "parking"
version = "2.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
···
dependencies = [
"atrium-api",
"atrium-common",
"atrium-identity",
"atrium-xrpc-client",
"hickory-resolver",
"tokio",
]
···
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
[[package]]
name = "pkg-config"
version = "0.3.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
···
checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04"
dependencies = [
"zerocopy 0.7.35",
]
[[package]]
···
]
[[package]]
name = "ring"
version = "0.17.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
···
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
[[package]]
name = "security-framework"
···
]
[[package]]
name = "sharded-slab"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
···
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
[[package]]
name = "slab"
version = "0.4.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
···
]
[[package]]
name = "stable_deref_trait"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
[[package]]
name = "syn"
···
checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b"
[[package]]
name = "unicode-ident"
version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
···
version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
[[package]]
name = "want"
···
"syn",
"synstructure",
]
[[package]]
name = "zerovec"
···
]
[[package]]
+
name = "atrium-crypto"
+
version = "0.1.2"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "73a3da430c71dd9006d61072c20771f264e5c498420a49c32305ceab8bd71955"
+
dependencies = [
+
"ecdsa",
+
"k256",
+
"multibase",
+
"p256",
+
"thiserror 1.0.69",
+
]
+
+
[[package]]
name = "atrium-identity"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
···
version = "0.2.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4cbbc9d0964165b47557570cce6c952866c2678457aca742aafc9fb771d30270"
+
+
[[package]]
+
name = "base16ct"
+
version = "0.2.0"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf"
[[package]]
name = "base64"
···
checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
[[package]]
+
name = "base64ct"
+
version = "1.7.3"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "89e25b6adfb930f02d1981565a6e5d9c547ac15a96606256d3b59040e5cd4ca3"
+
+
[[package]]
name = "bitflags"
version = "2.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd"
+
+
[[package]]
+
name = "block-buffer"
+
version = "0.10.4"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
+
dependencies = [
+
"generic-array",
+
]
[[package]]
name = "bumpalo"
···
]
[[package]]
+
name = "const-oid"
+
version = "0.9.6"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8"
+
+
[[package]]
name = "core-foundation"
version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
···
checksum = "b49ba7ef1ad6107f8824dbe97de947cbaac53c44e7f9756a1fba0d37c1eec505"
dependencies = [
"memchr",
+
]
+
+
[[package]]
+
name = "cpufeatures"
+
version = "0.2.17"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280"
+
dependencies = [
+
"libc",
]
[[package]]
···
checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28"
[[package]]
+
name = "crypto-bigint"
+
version = "0.5.5"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76"
+
dependencies = [
+
"generic-array",
+
"rand_core 0.6.4",
+
"subtle",
+
"zeroize",
+
]
+
+
[[package]]
+
name = "crypto-common"
+
version = "0.1.6"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
+
dependencies = [
+
"generic-array",
+
"typenum",
+
]
+
+
[[package]]
name = "dashmap"
version = "6.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
···
]
[[package]]
+
name = "der"
+
version = "0.7.9"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0"
+
dependencies = [
+
"const-oid",
+
"zeroize",
+
]
+
+
[[package]]
+
name = "digest"
+
version = "0.10.7"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
+
dependencies = [
+
"block-buffer",
+
"const-oid",
+
"crypto-common",
+
"subtle",
+
]
+
+
[[package]]
name = "displaydoc"
version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
···
]
[[package]]
+
name = "ecdsa"
+
version = "0.16.9"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca"
+
dependencies = [
+
"der",
+
"digest",
+
"elliptic-curve",
+
"rfc6979",
+
"signature",
+
"spki",
+
]
+
+
[[package]]
+
name = "elliptic-curve"
+
version = "0.13.8"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47"
+
dependencies = [
+
"base16ct",
+
"crypto-bigint",
+
"digest",
+
"ff",
+
"generic-array",
+
"group",
+
"pkcs8",
+
"rand_core 0.6.4",
+
"sec1",
+
"subtle",
+
"zeroize",
+
]
+
+
[[package]]
name = "enum-as-inner"
version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
···
version = "2.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be"
+
+
[[package]]
+
name = "ff"
+
version = "0.13.1"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "c0b50bfb653653f9ca9095b427bed08ab8d75a137839d9ad64eb11810d5b6393"
+
dependencies = [
+
"rand_core 0.6.4",
+
"subtle",
+
]
[[package]]
name = "flate2"
···
]
[[package]]
+
name = "generic-array"
+
version = "0.14.7"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
+
dependencies = [
+
"typenum",
+
"version_check",
+
"zeroize",
+
]
+
+
[[package]]
name = "getrandom"
version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
···
checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f"
[[package]]
+
name = "group"
+
version = "0.13.0"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63"
+
dependencies = [
+
"ff",
+
"rand_core 0.6.4",
+
"subtle",
+
]
+
+
[[package]]
name = "hashbrown"
version = "0.14.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
···
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
+
+
[[package]]
+
name = "hex"
+
version = "0.4.3"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
[[package]]
name = "hickory-proto"
···
]
[[package]]
+
name = "hmac"
+
version = "0.12.1"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e"
+
dependencies = [
+
"digest",
+
]
+
+
[[package]]
name = "hostname"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
···
]
[[package]]
+
name = "k256"
+
version = "0.13.4"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "f6e3919bbaa2945715f0bb6d3934a173d1e9a59ac23767fbaaef277265a7411b"
+
dependencies = [
+
"cfg-if",
+
"ecdsa",
+
"elliptic-curve",
+
"sha2",
+
]
+
+
[[package]]
name = "langtag"
version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
···
checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39"
[[package]]
+
name = "p256"
+
version = "0.13.2"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "c9863ad85fa8f4460f9c48cb909d38a0d689dba1f6f6988a5e3e0d31071bcd4b"
+
dependencies = [
+
"ecdsa",
+
"elliptic-curve",
+
"primeorder",
+
"sha2",
+
]
+
+
[[package]]
name = "parking"
version = "2.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
···
dependencies = [
"atrium-api",
"atrium-common",
+
"atrium-crypto",
"atrium-identity",
"atrium-xrpc-client",
+
"hex",
"hickory-resolver",
+
"rand 0.8.5",
"tokio",
]
···
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
[[package]]
+
name = "pkcs8"
+
version = "0.10.2"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7"
+
dependencies = [
+
"der",
+
"spki",
+
]
+
+
[[package]]
name = "pkg-config"
version = "0.3.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
···
checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04"
dependencies = [
"zerocopy 0.7.35",
+
]
+
+
[[package]]
+
name = "primeorder"
+
version = "0.13.6"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "353e1ca18966c16d9deb1c69278edbc5f194139612772bd9537af60ac231e1e6"
+
dependencies = [
+
"elliptic-curve",
]
[[package]]
···
]
[[package]]
+
name = "rfc6979"
+
version = "0.4.0"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2"
+
dependencies = [
+
"hmac",
+
"subtle",
+
]
+
+
[[package]]
name = "ring"
version = "0.17.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
···
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
+
+
[[package]]
+
name = "sec1"
+
version = "0.7.3"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc"
+
dependencies = [
+
"base16ct",
+
"der",
+
"generic-array",
+
"pkcs8",
+
"subtle",
+
"zeroize",
+
]
[[package]]
name = "security-framework"
···
]
[[package]]
+
name = "sha2"
+
version = "0.10.8"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8"
+
dependencies = [
+
"cfg-if",
+
"cpufeatures",
+
"digest",
+
]
+
+
[[package]]
name = "sharded-slab"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
···
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
[[package]]
+
name = "signature"
+
version = "2.2.0"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de"
+
dependencies = [
+
"digest",
+
"rand_core 0.6.4",
+
]
+
+
[[package]]
name = "slab"
version = "0.4.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
···
]
[[package]]
+
name = "spki"
+
version = "0.7.3"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d"
+
dependencies = [
+
"base64ct",
+
"der",
+
]
+
+
[[package]]
name = "stable_deref_trait"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
+
+
[[package]]
+
name = "subtle"
+
version = "2.6.1"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
[[package]]
name = "syn"
···
checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b"
[[package]]
+
name = "typenum"
+
version = "1.18.0"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f"
+
+
[[package]]
name = "unicode-ident"
version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
···
version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
+
+
[[package]]
+
name = "version_check"
+
version = "0.9.5"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
[[package]]
name = "want"
···
"syn",
"synstructure",
]
+
+
[[package]]
+
name = "zeroize"
+
version = "1.8.1"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde"
[[package]]
name = "zerovec"
+3
Cargo.toml
···
[dependencies]
atrium-api = { version = "0.25.0", default-features = false, features = ["agent", "bluesky"] }
atrium-common = "0.1.0"
atrium-identity = { version = "0.1.1", features = ["doh-handle-resolver"] }
atrium-xrpc-client = "0.5.11"
hickory-resolver = "0.25.1"
tokio = { version = "1.44.0", features = ["macros", "rt-multi-thread"]}
···
[dependencies]
atrium-api = { version = "0.25.0", default-features = false, features = ["agent", "bluesky"] }
atrium-common = "0.1.0"
+
atrium-crypto = "0.1.2"
atrium-identity = { version = "0.1.1", features = ["doh-handle-resolver"] }
atrium-xrpc-client = "0.5.11"
+
hex = "0.4.3"
hickory-resolver = "0.25.1"
+
rand = "0.8.5"
tokio = { version = "1.44.0", features = ["macros", "rt-multi-thread"]}
+142 -3
src/main.rs
···
},
app::bsky::actor::{get_preferences, put_preferences},
com::atproto::{
-
server::{create_account, get_service_auth},
sync::{get_blob, get_repo, list_blobs},
},
types::string::{Did, Handle, Nsid},
};
use atrium_common::resolver::Resolver;
use atrium_identity::{
did::{CommonDidResolver, CommonDidResolverConfig},
handle::{AtprotoHandleResolver, AtprotoHandleResolverConfig, DnsTxtResolver},
···
match new_agent.api.com.atproto.repo.upload_blob(blob).await {
Ok(_) => {
println!("Blob with CID {:?} migrated", cid)
-
},
Err(err) => {
println!("com.atproto.repo.uploadBlob at new PDS failed due to error: {err}");
return;
···
match new_agent.api.com.atproto.repo.upload_blob(blob).await {
Ok(_) => {
println!("Blob with CID {:?} migrated", cid)
-
},
Err(err) => {
println!("com.atproto.repo.uploadBlob at new PDS failed due to error: {err}");
return;
···
}
}
println!("Preferences successfully migrated!");
}
···
},
app::bsky::actor::{get_preferences, put_preferences},
com::atproto::{
+
identity::sign_plc_operation,
+
server::{create_account, deactivate_account, get_service_auth},
sync::{get_blob, get_repo, list_blobs},
},
types::string::{Did, Handle, Nsid},
};
use atrium_common::resolver::Resolver;
+
use atrium_crypto::keypair::{Did as _, Export, Secp256k1Keypair};
use atrium_identity::{
did::{CommonDidResolver, CommonDidResolverConfig},
handle::{AtprotoHandleResolver, AtprotoHandleResolverConfig, DnsTxtResolver},
···
match new_agent.api.com.atproto.repo.upload_blob(blob).await {
Ok(_) => {
println!("Blob with CID {:?} migrated", cid)
+
}
Err(err) => {
println!("com.atproto.repo.uploadBlob at new PDS failed due to error: {err}");
return;
···
match new_agent.api.com.atproto.repo.upload_blob(blob).await {
Ok(_) => {
println!("Blob with CID {:?} migrated", cid)
+
}
Err(err) => {
println!("com.atproto.repo.uploadBlob at new PDS failed due to error: {err}");
return;
···
}
}
println!("Preferences successfully migrated!");
+
+
// Update identity
+
println!("Migrating you identity (DID document) ...");
+
+
let pds_credentials = match new_agent
+
.api
+
.com
+
.atproto
+
.identity
+
.get_recommended_did_credentials()
+
.await
+
{
+
Ok(response) => response,
+
Err(err) => {
+
println!("com.atproto.identity.getRecommendedDidCredentials at new PDS failed due to error: {err}");
+
return;
+
}
+
};
+
+
match Did::new(identity.did.clone()).unwrap().method() {
+
"plc" => {
+
println!(
+
"did:plc detected! Creating a recovery key and updating your DID document ..."
+
);
+
let recovery_keypair = Secp256k1Keypair::create(&mut rand::thread_rng());
+
let private_key = hex::encode(recovery_keypair.export());
+
let mut recovery_keys = vec![recovery_keypair.did()];
+
if let Some(keys) = pds_credentials.rotation_keys.clone() {
+
recovery_keys.extend(keys);
+
}
+
+
println!("PLC operations are potentially destructive therefore you will need to complete an email challenge with your current PDS");
+
if let Err(err) = current_agent
+
.api
+
.com
+
.atproto
+
.identity
+
.request_plc_operation_signature()
+
.await
+
{
+
println!("com.atproto.identity.requestPlcOperationSignature at current PDS failed due to error: {err}")
+
};
+
let challenge_token = match readln(Some(
+
"Challenge email sent. Please provide the token you where sent over email here",
+
)) {
+
Ok(token) => token,
+
Err(err) => {
+
println!("Could not read token due to error: {err}");
+
return;
+
}
+
};
+
println!("Your private recovery key is {private_key}. Please store this in a secure location!!");
+
if let Err(err) = readln(Some("Press enter once you've saved the key securely")) {
+
println!("Could not handle enter due to error: {err}");
+
return;
+
}
+
+
match current_agent
+
.api
+
.com
+
.atproto
+
.identity
+
.sign_plc_operation(
+
sign_plc_operation::InputData {
+
also_known_as: pds_credentials.also_known_as.clone(),
+
rotation_keys: Some(recovery_keys),
+
services: pds_credentials.services.clone(),
+
token: Some(challenge_token.to_string()),
+
verification_methods: pds_credentials.verification_methods.clone(),
+
}
+
.into(),
+
)
+
.await
+
{
+
Ok(response) => response,
+
Err(err) => {
+
println!("com.atproto.identity.signPlcOperation at current PDS failed due to error: {err}");
+
return;
+
}
+
};
+
println!("DID document successfully updated!");
+
}
+
"web" => {
+
let did = identity.did;
+
println!("did:web detected! Please manually update your DID document to match these values: {pds_credentials:#?}");
+
if let Err(err) = readln(Some("Press enter once you've updated your DID document")) {
+
println!("Could not handle enter due to error: {err}");
+
return;
+
}
+
let mut valid_document = match identity_resolver.resolve(did.as_str()).await {
+
Ok(response) => response.pds == new_pds_url.to_string(),
+
Err(err) => {
+
println!("Couldn't resolve DID {did} due to error: {err}");
+
return;
+
}
+
};
+
+
while !valid_document {
+
println!("DID document not updated or updated incorretly! Needed PDS configuration: {new_pds_url}");
+
if let Err(err) = readln(Some("Press enter once you've updated your DID document"))
+
{
+
println!("Could not handle enter due to error: {err}");
+
return;
+
}
+
valid_document = match identity_resolver.resolve(did.as_str()).await {
+
Ok(response) => response.pds == new_pds_url.to_string(),
+
Err(err) => {
+
println!("Couldn't resolve DID {did} due to error: {err}");
+
return;
+
}
+
};
+
}
+
}
+
_ => {
+
println!("Unknown and invalid DID method found. This should not be possible!");
+
return;
+
}
+
}
+
println!("Identity migrated successfully!");
+
+
// Finalise migration
+
if let Err(err) = new_agent.api.com.atproto.server.activate_account().await {
+
println!("com.atproto.server.activateAccount at new PDS failed due to error: {err}")
+
};
+
if let Err(err) = current_agent
+
.api
+
.com
+
.atproto
+
.server
+
.deactivate_account(deactivate_account::InputData { delete_after: None }.into())
+
.await
+
{
+
println!("com.atproto.server.activateAccount at current PDS failed due to error: {err}")
+
};
+
+
println!("The account migration was successful!");
+
println!("The account on your old PDS has been deactivated. Please make sure everything works before fully deleting it in case you need to go back");
}