1use anyhow::{Context, Result};
2use colored::Colorize;
3use ed25519_dalek::{SigningKey, VerifyingKey};
4use serde::{Deserialize, Serialize};
5use sha2::{Digest, Sha256};
6use std::fs;
7
8#[derive(Debug, Clone, Serialize, Deserialize)]
9pub struct Wallet {
10 pub address: String,
11 pub private_key: String,
12 pub network: String,
13 pub seed_phrase: String,
14}
15
16impl Wallet {
17 pub async fn create(network: &str) -> Result<Self> {
18 println!("{}", "Creating wallet...".cyan());
19
20 let seed_phrase = Self::generate_seed_phrase();
21 let (private_key, address) = Self::derive_keys(&seed_phrase);
22
23 let wallet = Wallet {
24 address,
25 private_key,
26 network: network.to_string(),
27 seed_phrase,
28 };
29
30 println!("{}", "✓ Wallet created successfully".green().bold());
31
32 Ok(wallet)
33 }
34
35 pub fn save_to_file(&self) -> Result<()> {
36 let mut wallets_dir = dirs::home_dir().context("Failed to determine home directory")?;
37
38 wallets_dir.push(".x402");
39 wallets_dir.push("wallets");
40
41 fs::create_dir_all(&wallets_dir)
42 .with_context(|| format!("Failed to create wallets directory"))?;
43
44 let wallet_file = wallets_dir.join(format!("{}.json", self.address));
45
46 let wallet_data =
47 serde_json::to_string_pretty(self).context("Failed to serialize wallet data")?;
48
49 fs::write(&wallet_file, wallet_data)
50 .with_context(|| format!("Failed to save wallet file: {}", wallet_file.display()))?;
51
52 let display = wallet_file.display();
53 println!(
54 "{}",
55 format!(" ✓ Wallet saved to {}", display).cyan().dimmed()
56 );
57
58 Ok(())
59 }
60
61 pub fn import(private_key: &str, network: &str) -> Result<Self> {
62 println!("{}", "Importing wallet from private key...".cyan());
63
64 let private_key_clean = private_key.trim_start_matches("0x");
65 let private_key_bytes = hex::decode(private_key_clean)
66 .map_err(|e| anyhow::anyhow!("Failed to decode private key hex: {}", e))?;
67
68 if private_key_bytes.len() < 32 {
69 return Err(anyhow::anyhow!("Private key must be at least 32 bytes"));
70 }
71
72 let mut key_bytes = [0u8; 32];
73 key_bytes.copy_from_slice(&private_key_bytes[..32]);
74
75 let signing_key = SigningKey::from_bytes(&key_bytes);
76 let public_key = signing_key.verifying_key();
77 let public_key_bytes = public_key.as_bytes();
78 let address = hex::encode(&public_key_bytes[1..]);
79 let address = format!("0x{}", address);
80
81 let wallet = Wallet {
82 address,
83 private_key: private_key_clean.to_string(),
84 network: network.to_string(),
85 seed_phrase: String::new(),
86 };
87
88 println!("{}", "✓ Wallet imported successfully".green().bold());
89
90 Ok(wallet)
91 }
92
93 pub fn load_from_address(address: &str) -> Result<Self> {
94 let mut wallets_dir = dirs::home_dir().context("Failed to determine home directory")?;
95 wallets_dir.push(".x402");
96 wallets_dir.push("wallets");
97
98 let wallet_file = wallets_dir.join(format!("{}.json", address));
99
100 if !wallet_file.exists() {
101 anyhow::bail!("Wallet file not found: {}", wallet_file.display());
102 }
103
104 let wallet_data = fs::read_to_string(&wallet_file)
105 .with_context(|| format!("Failed to read wallet file: {}", wallet_file.display()))?;
106
107 let wallet: Wallet = serde_json::from_str(&wallet_data)
108 .context("Failed to parse wallet data")?;
109
110 Ok(wallet)
111 }
112
113 pub fn find_default() -> Result<Self> {
114 let mut wallets_dir = dirs::home_dir().context("Failed to determine home directory")?;
115 wallets_dir.push(".x402");
116 wallets_dir.push("wallets");
117
118 if !wallets_dir.exists() {
119 anyhow::bail!("No wallets directory found. Create a wallet first using `x402 wallet create`");
120 }
121
122 let entries: Vec<_> = fs::read_dir(&wallets_dir)
123 .context("Failed to read wallets directory")?
124 .filter_map(|e| e.ok())
125 .collect();
126
127 if entries.is_empty() {
128 anyhow::bail!("No wallets found. Create a wallet first using `x402 wallet create`");
129 }
130
131 let first_wallet = entries
132 .first()
133 .context("No wallets found")?;
134
135 let wallet_file = first_wallet.path();
136 let wallet_data = fs::read_to_string(&wallet_file)
137 .with_context(|| format!("Failed to read wallet file: {}", wallet_file.display()))?;
138
139 let wallet: Wallet = serde_json::from_str(&wallet_data)
140 .context("Failed to parse wallet data")?;
141
142 Ok(wallet)
143 }
144
145 pub async fn fund_from_faucet(&self) -> Result<()> {
146 if self.network != "testnet" {
147 println!(
148 "{}",
149 " ℹ Skipping faucet funding (not on testnet)"
150 .yellow()
151 .dimmed()
152 );
153 return Ok(());
154 }
155
156 let faucet_url = "https://faucet.testnet.aptoslabs.com";
157
158 let client = reqwest::Client::new();
159 let request_body = serde_json::json!({
160 "address": self.address,
161 "amount": 100_000_000
162 });
163
164 let response = client
165 .post(faucet_url)
166 .header("Content-Type", "application/json")
167 .json(&request_body)
168 .send()
169 .await
170 .context("Failed to contact faucet")?;
171
172 if response.status().is_success() {
173 let _output = response.text().await.unwrap_or_default();
174 println!(
175 "{}",
176 format!(" ✓ Funded with 1 APT from faucet")
177 .green()
178 .dimmed()
179 );
180 } else {
181 let status = response.status();
182 let error = response.text().await.unwrap_or_default();
183 println!(
184 "{}",
185 format!(" ⚠ Faucet request failed: {} - {}", status, error)
186 .yellow()
187 .dimmed()
188 );
189 }
190
191 Ok(())
192 }
193
194 fn generate_seed_phrase() -> String {
195 const WORDS: &[&str] = &[
196 "abandon",
197 "ability",
198 "able",
199 "about",
200 "above",
201 "absent",
202 "absorb",
203 "abstract",
204 "absurd",
205 "abuse",
206 "access",
207 "accident",
208 "account",
209 "accuse",
210 "achieve",
211 "acid",
212 "acoustic",
213 "acquire",
214 "across",
215 "act",
216 "action",
217 "actor",
218 "actress",
219 "actual",
220 "adapt",
221 "add",
222 "addict",
223 "address",
224 "adjust",
225 "admit",
226 "adult",
227 "advance",
228 "advice",
229 "aerobic",
230 "affair",
231 "afford",
232 "afraid",
233 "again",
234 "age",
235 "agent",
236 "agree",
237 "ahead",
238 "aim",
239 "air",
240 "airport",
241 "aisle",
242 "alarm",
243 "album",
244 "alcohol",
245 "alert",
246 "alien",
247 "all",
248 "alley",
249 "allow",
250 "almost",
251 "alone",
252 "alpha",
253 "already",
254 "also",
255 "alter",
256 "always",
257 "amateur",
258 "amazing",
259 "among",
260 "amount",
261 "amused",
262 "analyst",
263 "anchor",
264 "ancient",
265 "anger",
266 "angle",
267 "angry",
268 "animal",
269 "ankle",
270 "announce",
271 "annual",
272 "another",
273 "answer",
274 "antenna",
275 "antique",
276 "anxiety",
277 "any",
278 "apart",
279 "apology",
280 "appear",
281 "apple",
282 "approve",
283 "april",
284 "arch",
285 "arctic",
286 "area",
287 "arena",
288 "argue",
289 "arm",
290 "armed",
291 "armor",
292 "army",
293 "around",
294 "arrange",
295 "arrest",
296 "arrive",
297 "arrow",
298 "art",
299 "artist",
300 "artwork",
301 "ask",
302 "aspect",
303 "assault",
304 "asset",
305 "assist",
306 "assume",
307 "asthma",
308 "athlete",
309 "atom",
310 "attack",
311 "attend",
312 "attract",
313 "auction",
314 "audit",
315 "august",
316 "aunt",
317 "author",
318 "auto",
319 "autumn",
320 "average",
321 "avocado",
322 "avoid",
323 "awake",
324 "aware",
325 "away",
326 "awesome",
327 "awful",
328 "awkward",
329 "axis",
330 "baby",
331 "bachelor",
332 "bacon",
333 "badge",
334 "bag",
335 "balance",
336 "balcony",
337 "ball",
338 "bamboo",
339 "banana",
340 "banner",
341 "bar",
342 "barely",
343 "bargain",
344 "barrel",
345 "base",
346 "basic",
347 "basket",
348 "battle",
349 "beach",
350 "bean",
351 "beauty",
352 "become",
353 "beef",
354 "before",
355 "begin",
356 "behave",
357 "behind",
358 "believe",
359 "below",
360 "belt",
361 "bench",
362 "benefit",
363 "best",
364 "betray",
365 "better",
366 "between",
367 "beyond",
368 "bicycle",
369 "bid",
370 "bike",
371 "bind",
372 "biology",
373 "bird",
374 "birth",
375 "bitter",
376 "black",
377 "blade",
378 "blame",
379 "blanket",
380 "blast",
381 "bleak",
382 "bless",
383 "blind",
384 "blood",
385 "blossom",
386 "blouse",
387 "blue",
388 "blur",
389 "blush",
390 "board",
391 "boat",
392 "body",
393 "boil",
394 "bomb",
395 "bone",
396 "bonus",
397 "book",
398 "boost",
399 "border",
400 "bored",
401 "borrow",
402 "boss",
403 "bottom",
404 "bounce",
405 "box",
406 "boy",
407 "bracket",
408 "brain",
409 "brand",
410 "brass",
411 "brave",
412 "bread",
413 "breeze",
414 "brick",
415 "bridge",
416 "brief",
417 "bright",
418 "bring",
419 "brisk",
420 "broken",
421 "bronze",
422 "broom",
423 "brother",
424 "brown",
425 "brush",
426 "bubble",
427 "buddy",
428 "budget",
429 "buffalo",
430 "build",
431 "bulb",
432 "bulk",
433 "bullet",
434 "bundle",
435 "bunker",
436 "burden",
437 "burger",
438 "burst",
439 "bus",
440 "business",
441 "busy",
442 "butter",
443 "buyer",
444 "buzz",
445 "cabbage",
446 "cabin",
447 "cable",
448 "cactus",
449 "cage",
450 "cake",
451 "call",
452 "calm",
453 "camera",
454 "camp",
455 "can",
456 "canal",
457 "cancel",
458 "candy",
459 "cannon",
460 "canoe",
461 "canvas",
462 "canyon",
463 "capable",
464 "capital",
465 "captain",
466 "car",
467 "carbon",
468 "card",
469 "cargo",
470 "carpet",
471 "carry",
472 "cart",
473 "case",
474 "cash",
475 "casino",
476 "castle",
477 "casual",
478 "cat",
479 "catalog",
480 "catch",
481 "category",
482 "cattle",
483 "caught",
484 "cause",
485 "caution",
486 "cave",
487 "ceiling",
488 "celery",
489 "cement",
490 "census",
491 "century",
492 "cereal",
493 "certain",
494 "chair",
495 "chalk",
496 "champion",
497 "change",
498 "chaos",
499 "chapter",
500 "charge",
501 "chase",
502 "chat",
503 "cheap",
504 "check",
505 "cheese",
506 "chef",
507 "cherry",
508 "chest",
509 "chicken",
510 "chief",
511 "child",
512 "chimney",
513 "choice",
514 "choose",
515 "chronic",
516 "chuckle",
517 "chunk",
518 "churn",
519 "cigar",
520 "cinnamon",
521 "circle",
522 "citizen",
523 "city",
524 "civil",
525 "claim",
526 "clap",
527 "clarify",
528 "claw",
529 "clay",
530 "clean",
531 "clerk",
532 "clever",
533 "click",
534 "client",
535 "cliff",
536 "climb",
537 "clinic",
538 "clip",
539 "clock",
540 "clog",
541 "close",
542 "cloth",
543 "cloud",
544 "clown",
545 "club",
546 "clump",
547 "cluster",
548 "clutch",
549 "coach",
550 "coast",
551 "coconut",
552 "code",
553 "coffee",
554 "coil",
555 "coin",
556 "collect",
557 "color",
558 "column",
559 "combine",
560 "come",
561 "comfort",
562 "comic",
563 "common",
564 "company",
565 "concert",
566 "conduct",
567 "confirm",
568 "congress",
569 "connect",
570 "consider",
571 "control",
572 "convince",
573 "cook",
574 "cool",
575 "copper",
576 "copy",
577 "coral",
578 "core",
579 "corn",
580 "corner",
581 "correct",
582 "cost",
583 "cotton",
584 "couch",
585 "country",
586 "couple",
587 "course",
588 "cousin",
589 "cover",
590 "coyote",
591 "crack",
592 "cradle",
593 "craft",
594 "cram",
595 "crane",
596 "crash",
597 "crater",
598 "crawl",
599 "crazy",
600 "cream",
601 "credit",
602 "creek",
603 "crew",
604 "cricket",
605 "crime",
606 "crisp",
607 "critic",
608 "crop",
609 "cross",
610 "crouch",
611 "crowd",
612 "crucial",
613 "cruel",
614 "cruise",
615 "crumble",
616 "crunch",
617 "crush",
618 "cry",
619 "crystal",
620 "cube",
621 "culture",
622 "cup",
623 "cupboard",
624 "curious",
625 "current",
626 "curtain",
627 "curve",
628 "cushion",
629 "custom",
630 "cute",
631 "cycle",
632 "dad",
633 "damage",
634 "damp",
635 "dance",
636 "danger",
637 "daring",
638 "dash",
639 "daughter",
640 "dawn",
641 "day",
642 "deal",
643 "debate",
644 "debris",
645 "decade",
646 "december",
647 "decide",
648 "decline",
649 "decorate",
650 "decrease",
651 "deer",
652 "defense",
653 "define",
654 "defy",
655 "degree",
656 "delay",
657 "deliver",
658 "demand",
659 "demise",
660 "denial",
661 "dentist",
662 "deny",
663 "depart",
664 "depend",
665 "deposit",
666 "depth",
667 "deputy",
668 "derive",
669 "describe",
670 "desert",
671 "design",
672 "desk",
673 "despair",
674 "destroy",
675 "detail",
676 "detect",
677 "develop",
678 "device",
679 "devote",
680 "diagram",
681 "dial",
682 "diamond",
683 "diary",
684 "dice",
685 "diesel",
686 "diet",
687 "differ",
688 "digital",
689 "dignity",
690 "dilemma",
691 "dinner",
692 "dinosaur",
693 "direct",
694 "dirt",
695 "disagree",
696 "discover",
697 "disease",
698 "dish",
699 "dismiss",
700 "disorder",
701 "display",
702 "distance",
703 "divert",
704 "divide",
705 "divorce",
706 "dizzy",
707 "doctor",
708 "document",
709 "dog",
710 "doll",
711 "dolphin",
712 "domain",
713 "donate",
714 "donkey",
715 "donor",
716 "door",
717 "dose",
718 "double",
719 "dove",
720 "draft",
721 "dragon",
722 "drama",
723 "draw",
724 "dream",
725 "dress",
726 "drift",
727 "drill",
728 "drink",
729 "drip",
730 "drive",
731 "drop",
732 "drum",
733 "dry",
734 "duck",
735 "dumb",
736 "dune",
737 "during",
738 "dust",
739 "dutch",
740 "duty",
741 "dwarf",
742 "dynamic",
743 "eager",
744 "eagle",
745 "early",
746 "earn",
747 "earth",
748 "easily",
749 "east",
750 "easy",
751 "echo",
752 "ecology",
753 "economy",
754 "edge",
755 "edit",
756 "educate",
757 "effort",
758 "egg",
759 "eight",
760 "elbow",
761 "elder",
762 "electric",
763 "elegant",
764 "element",
765 "elephant",
766 "elevator",
767 "elite",
768 "else",
769 "embark",
770 "embody",
771 "embrace",
772 "emerge",
773 "emotion",
774 "employ",
775 "empower",
776 "empty",
777 "enable",
778 "enact",
779 "end",
780 "endless",
781 "endorse",
782 "enemy",
783 "energy",
784 "enforce",
785 "engage",
786 "engine",
787 "enhance",
788 "enjoy",
789 "enlist",
790 "enough",
791 "enrich",
792 "enroll",
793 "ensure",
794 "enter",
795 "entire",
796 "entry",
797 "envelope",
798 "episode",
799 "equal",
800 "equip",
801 "era",
802 "erase",
803 "erode",
804 "erosion",
805 "error",
806 "erupt",
807 "escape",
808 "essay",
809 "essence",
810 "estate",
811 "eternal",
812 "ethics",
813 "evidence",
814 "evil",
815 "evoke",
816 "evolve",
817 "exact",
818 "example",
819 "excess",
820 "exchange",
821 "excite",
822 "exclude",
823 "excuse",
824 "execute",
825 "exercise",
826 "exhaust",
827 "exhibit",
828 "exile",
829 "exist",
830 "exit",
831 "exotic",
832 "expand",
833 "expect",
834 "expire",
835 "explain",
836 "expose",
837 "express",
838 "extend",
839 "extra",
840 "eye",
841 "eyebrow",
842 "fabric",
843 "face",
844 "faculty",
845 "fade",
846 "faint",
847 "faith",
848 "fall",
849 "false",
850 "fame",
851 "family",
852 "famous",
853 "fan",
854 "fancy",
855 "fantasy",
856 "farm",
857 "fashion",
858 "fat",
859 "fatal",
860 "father",
861 "fatigue",
862 "fault",
863 "favorite",
864 "feature",
865 "february",
866 "federal",
867 "fee",
868 "feed",
869 "feel",
870 "female",
871 "fence",
872 "festival",
873 "fetch",
874 "fever",
875 "few",
876 "fiber",
877 "fiction",
878 "field",
879 "figure",
880 "file",
881 "film",
882 "filter",
883 "final",
884 "find",
885 "fine",
886 "finger",
887 "finish",
888 "fire",
889 "firm",
890 "first",
891 "fiscal",
892 "fish",
893 "fit",
894 "fitness",
895 "fix",
896 "flag",
897 "flame",
898 "flash",
899 "flat",
900 "flavor",
901 "flee",
902 "flight",
903 "flip",
904 "float",
905 "flock",
906 "floor",
907 "flower",
908 "fluid",
909 "flush",
910 "fly",
911 "foam",
912 "focus",
913 "fog",
914 "foil",
915 "fold",
916 "follow",
917 "food",
918 "foot",
919 "force",
920 "forest",
921 "forget",
922 "fork",
923 "fortune",
924 "forum",
925 "forward",
926 "fossil",
927 "foster",
928 "found",
929 "fox",
930 "fragile",
931 "frame",
932 "frequent",
933 "fresh",
934 "friend",
935 "fringe",
936 "frog",
937 "front",
938 "frost",
939 "frown",
940 "frozen",
941 "fruit",
942 "fuel",
943 "fun",
944 "funny",
945 "furnace",
946 "fury",
947 "future",
948 "gadget",
949 "gain",
950 "galaxy",
951 "gallery",
952 "game",
953 "gap",
954 "garage",
955 "garbage",
956 "garden",
957 "garlic",
958 "garment",
959 "gas",
960 "gasp",
961 "gate",
962 "gather",
963 "gauge",
964 "gaze",
965 "general",
966 "genius",
967 "genre",
968 "gentle",
969 "genuine",
970 "gesture",
971 "ghost",
972 "giant",
973 "gift",
974 "giggle",
975 "ginger",
976 "giraffe",
977 "girl",
978 "give",
979 "glad",
980 "glance",
981 "glare",
982 "glass",
983 "glide",
984 "glimpse",
985 "globe",
986 "gloom",
987 "glory",
988 "glove",
989 "glow",
990 "glue",
991 "goat",
992 "goddess",
993 "gold",
994 "good",
995 "goose",
996 "gorilla",
997 "gospel",
998 "gossip",
999 "govern",
1000 "gown",
1001 "grab",
1002 "grace",
1003 "grain",
1004 "grant",
1005 "grape",
1006 "grass",
1007 "gravity",
1008 "great",
1009 "green",
1010 "grid",
1011 "grief",
1012 "grit",
1013 "grocery",
1014 "group",
1015 "grow",
1016 "grunt",
1017 "guard",
1018 "guess",
1019 "guide",
1020 "guilt",
1021 "guitar",
1022 "gun",
1023 "gym",
1024 "habit",
1025 "hair",
1026 "half",
1027 "hammer",
1028 "hamster",
1029 "hand",
1030 "handle",
1031 "harbor",
1032 "hard",
1033 "harsh",
1034 "harvest",
1035 "hat",
1036 "have",
1037 "hawk",
1038 "hazard",
1039 "head",
1040 "health",
1041 "heart",
1042 "heavy",
1043 "hedgehog",
1044 "height",
1045 "hello",
1046 "helmet",
1047 "help",
1048 "hen",
1049 "hero",
1050 "hidden",
1051 "high",
1052 "hill",
1053 "hint",
1054 "hip",
1055 "hire",
1056 "history",
1057 "hobby",
1058 "hockey",
1059 "hold",
1060 "hole",
1061 "holiday",
1062 "hollow",
1063 "home",
1064 "honey",
1065 "hood",
1066 "hope",
1067 "horn",
1068 "horror",
1069 "horse",
1070 "hospital",
1071 "host",
1072 "hotel",
1073 "hour",
1074 "hover",
1075 "hub",
1076 "huge",
1077 "human",
1078 "humble",
1079 "humor",
1080 "hundred",
1081 "hungry",
1082 "hunt",
1083 "hurdle",
1084 "hurry",
1085 "hurt",
1086 "husband",
1087 "hybrid",
1088 "ice",
1089 "icon",
1090 "idea",
1091 "identify",
1092 "idle",
1093 "ignore",
1094 "ill",
1095 "illegal",
1096 "illness",
1097 "image",
1098 "imitate",
1099 "immense",
1100 "immune",
1101 "impact",
1102 "impose",
1103 "improve",
1104 "impulse",
1105 "inch",
1106 "include",
1107 "income",
1108 "increase",
1109 "index",
1110 "indicate",
1111 "indoor",
1112 "industry",
1113 "infant",
1114 "inflict",
1115 "inform",
1116 "inhale",
1117 "inherit",
1118 "initial",
1119 "inject",
1120 "injury",
1121 "inmate",
1122 "inner",
1123 "innocent",
1124 "input",
1125 "inquiry",
1126 "insane",
1127 "insect",
1128 "inside",
1129 "inspire",
1130 "install",
1131 "intact",
1132 "interest",
1133 "into",
1134 "invest",
1135 "invite",
1136 "involve",
1137 "iron",
1138 "island",
1139 "isolate",
1140 "issue",
1141 "item",
1142 "ivory",
1143 "jacket",
1144 "jaguar",
1145 "jar",
1146 "jazz",
1147 "jealous",
1148 "jeans",
1149 "jelly",
1150 "jewel",
1151 "job",
1152 "join",
1153 "joke",
1154 "journey",
1155 "joy",
1156 "judge",
1157 "juggle",
1158 "juice",
1159 "jump",
1160 "jungle",
1161 "junior",
1162 "junk",
1163 "just",
1164 "kangaroo",
1165 "keen",
1166 "keep",
1167 "ketchup",
1168 "key",
1169 "kick",
1170 "kid",
1171 "kidney",
1172 "kind",
1173 "kingdom",
1174 "kiss",
1175 "kit",
1176 "kitchen",
1177 "kite",
1178 "kitten",
1179 "kiwi",
1180 "knee",
1181 "knife",
1182 "knock",
1183 "know",
1184 "lab",
1185 "label",
1186 "labor",
1187 "ladder",
1188 "lady",
1189 "lake",
1190 "lamp",
1191 "language",
1192 "laptop",
1193 "large",
1194 "later",
1195 "latin",
1196 "laugh",
1197 "laundry",
1198 "lava",
1199 "law",
1200 "lawn",
1201 "lawsuit",
1202 "layer",
1203 "lazy",
1204 "leader",
1205 "leaf",
1206 "learn",
1207 "leave",
1208 "lecture",
1209 "left",
1210 "leg",
1211 "legal",
1212 "legend",
1213 "leisure",
1214 "lemon",
1215 "lend",
1216 "length",
1217 "lens",
1218 "leopard",
1219 "lesson",
1220 "letter",
1221 "level",
1222 "liar",
1223 "liberty",
1224 "library",
1225 "license",
1226 "life",
1227 "lift",
1228 "light",
1229 "like",
1230 "limb",
1231 "limit",
1232 "link",
1233 "lion",
1234 "liquid",
1235 "list",
1236 "little",
1237 "live",
1238 "lizard",
1239 "load",
1240 "loan",
1241 "lobster",
1242 "local",
1243 "lock",
1244 "logic",
1245 "lonely",
1246 "long",
1247 "loop",
1248 "lottery",
1249 "loud",
1250 "lounge",
1251 "love",
1252 "loyal",
1253 "lucky",
1254 "luggage",
1255 "lumber",
1256 "lunar",
1257 "lunch",
1258 "luxury",
1259 "lyrics",
1260 "machine",
1261 "mad",
1262 "magic",
1263 "magnet",
1264 "maid",
1265 "mail",
1266 "main",
1267 "major",
1268 "make",
1269 "mammal",
1270 "man",
1271 "manage",
1272 "mandate",
1273 "mango",
1274 "mansion",
1275 "manual",
1276 "maple",
1277 "marble",
1278 "march",
1279 "margin",
1280 "marine",
1281 "market",
1282 "marriage",
1283 "mask",
1284 "mass",
1285 "master",
1286 "match",
1287 "material",
1288 "math",
1289 "matrix",
1290 "matter",
1291 "maximum",
1292 "maze",
1293 "meadow",
1294 "mean",
1295 "measure",
1296 "meat",
1297 "mechanic",
1298 "medal",
1299 "media",
1300 "melody",
1301 "melt",
1302 "member",
1303 "memory",
1304 "mention",
1305 "menu",
1306 "mercy",
1307 "merge",
1308 "merit",
1309 "merry",
1310 "mesh",
1311 "message",
1312 "metal",
1313 "method",
1314 "middle",
1315 "midnight",
1316 "milk",
1317 "million",
1318 "mimic",
1319 "mind",
1320 "minimum",
1321 "minor",
1322 "minute",
1323 "miracle",
1324 "mirror",
1325 "misery",
1326 "miss",
1327 "mistake",
1328 "mix",
1329 "mixed",
1330 "mixture",
1331 "mobile",
1332 "model",
1333 "modify",
1334 "mom",
1335 "moment",
1336 "monitor",
1337 "monkey",
1338 "monster",
1339 "month",
1340 "moon",
1341 "moral",
1342 "more",
1343 "morning",
1344 "mosquito",
1345 "mother",
1346 "motion",
1347 "motor",
1348 "mountain",
1349 "mouse",
1350 "move",
1351 "movie",
1352 "much",
1353 "muffin",
1354 "mule",
1355 "multiply",
1356 "muscle",
1357 "museum",
1358 "mushroom",
1359 "music",
1360 "must",
1361 "mutual",
1362 "myself",
1363 "mystery",
1364 "myth",
1365 "naive",
1366 "name",
1367 "napkin",
1368 "narrow",
1369 "nasty",
1370 "nation",
1371 "nature",
1372 "near",
1373 "neck",
1374 "need",
1375 "negative",
1376 "neglect",
1377 "neither",
1378 "nephew",
1379 "nerve",
1380 "nest",
1381 "net",
1382 "network",
1383 "neutral",
1384 "never",
1385 "news",
1386 "next",
1387 "nice",
1388 "night",
1389 "noble",
1390 "noise",
1391 "nominee",
1392 "noodle",
1393 "normal",
1394 "north",
1395 "nose",
1396 "notable",
1397 "note",
1398 "nothing",
1399 "notice",
1400 "novel",
1401 "now",
1402 "nuclear",
1403 "number",
1404 "nurse",
1405 "nut",
1406 "oak",
1407 "obey",
1408 "object",
1409 "oblige",
1410 "obscure",
1411 "observe",
1412 "obtain",
1413 "obvious",
1414 "occur",
1415 "ocean",
1416 "october",
1417 "odor",
1418 "off",
1419 "offer",
1420 "office",
1421 "often",
1422 "oil",
1423 "okay",
1424 "old",
1425 "olive",
1426 "olympic",
1427 "omit",
1428 "once",
1429 "one",
1430 "onion",
1431 "online",
1432 "only",
1433 "open",
1434 "opera",
1435 "opinion",
1436 "oppose",
1437 "option",
1438 "orange",
1439 "orbit",
1440 "orchard",
1441 "order",
1442 "ordinary",
1443 "organ",
1444 "orient",
1445 "original",
1446 "orphan",
1447 "ostrich",
1448 "other",
1449 "outdoor",
1450 "outer",
1451 "output",
1452 "outside",
1453 "oval",
1454 "oven",
1455 "over",
1456 "own",
1457 "owner",
1458 "oxygen",
1459 "oyster",
1460 "ozone",
1461 "pact",
1462 "paddle",
1463 "page",
1464 "pair",
1465 "palace",
1466 "palm",
1467 "panda",
1468 "panel",
1469 "panic",
1470 "panther",
1471 "paper",
1472 "parade",
1473 "parent",
1474 "park",
1475 "parrot",
1476 "party",
1477 "pass",
1478 "patch",
1479 "path",
1480 "patient",
1481 "patrol",
1482 "pattern",
1483 "pause",
1484 "pave",
1485 "payment",
1486 "peace",
1487 "peanut",
1488 "pear",
1489 "peasant",
1490 "pelican",
1491 "pen",
1492 "penalty",
1493 "pencil",
1494 "people",
1495 "pepper",
1496 "perfect",
1497 "permit",
1498 "person",
1499 "pet",
1500 "phone",
1501 "photo",
1502 "phrase",
1503 "physical",
1504 "piano",
1505 "picnic",
1506 "picture",
1507 "piece",
1508 "pig",
1509 "pigeon",
1510 "pill",
1511 "pilot",
1512 "pink",
1513 "pioneer",
1514 "pipe",
1515 "pistol",
1516 "pitch",
1517 "pizza",
1518 "place",
1519 "planet",
1520 "plastic",
1521 "plate",
1522 "play",
1523 "please",
1524 "pledge",
1525 "pluck",
1526 "plug",
1527 "plunge",
1528 "poem",
1529 "poet",
1530 "point",
1531 "polar",
1532 "pole",
1533 "police",
1534 "pond",
1535 "pony",
1536 "pool",
1537 "popular",
1538 "portion",
1539 "position",
1540 "possible",
1541 "post",
1542 "potato",
1543 "pottery",
1544 "poverty",
1545 "powder",
1546 "power",
1547 "practice",
1548 "praise",
1549 "predict",
1550 "prefer",
1551 "prepare",
1552 "present",
1553 "pretty",
1554 "prevent",
1555 "price",
1556 "pride",
1557 "primary",
1558 "print",
1559 "priority",
1560 "prison",
1561 "private",
1562 "prize",
1563 "problem",
1564 "process",
1565 "produce",
1566 "profit",
1567 "program",
1568 "project",
1569 "promote",
1570 "proof",
1571 "property",
1572 "prosper",
1573 "protect",
1574 "proud",
1575 "provide",
1576 "public",
1577 "pudding",
1578 "pull",
1579 "pulp",
1580 "pulse",
1581 "pumpkin",
1582 "punch",
1583 "pupil",
1584 "puppy",
1585 "purchase",
1586 "purity",
1587 "purpose",
1588 "purse",
1589 "push",
1590 "put",
1591 "puzzle",
1592 "pyramid",
1593 "quality",
1594 "quantum",
1595 "quarter",
1596 "question",
1597 "quick",
1598 "quit",
1599 "quiz",
1600 "quote",
1601 "rabbit",
1602 "raccoon",
1603 "race",
1604 "rack",
1605 "radar",
1606 "radio",
1607 "rail",
1608 "rain",
1609 "raise",
1610 "rally",
1611 "ramp",
1612 "ranch",
1613 "random",
1614 "range",
1615 "rapid",
1616 "rare",
1617 "rate",
1618 "rather",
1619 "raven",
1620 "raw",
1621 "reach",
1622 "react",
1623 "read",
1624 "real",
1625 "realm",
1626 "reason",
1627 "rebel",
1628 "rebuild",
1629 "receipt",
1630 "receive",
1631 "recipe",
1632 "record",
1633 "recycle",
1634 "red",
1635 "reduce",
1636 "reflect",
1637 "reform",
1638 "refuge",
1639 "refuse",
1640 "region",
1641 "regret",
1642 "regular",
1643 "reject",
1644 "relax",
1645 "release",
1646 "relief",
1647 "rely",
1648 "remain",
1649 "remember",
1650 "remind",
1651 "remote",
1652 "remove",
1653 "render",
1654 "renew",
1655 "rent",
1656 "reopen",
1657 "repair",
1658 "repeat",
1659 "replace",
1660 "reply",
1661 "report",
1662 "represent",
1663 "reptile",
1664 "require",
1665 "rescue",
1666 "resemble",
1667 "resist",
1668 "resource",
1669 "response",
1670 "result",
1671 "retire",
1672 "retreat",
1673 "return",
1674 "reunion",
1675 "reveal",
1676 "review",
1677 "reward",
1678 "rhythm",
1679 "rib",
1680 "ribbon",
1681 "rice",
1682 "rich",
1683 "ride",
1684 "ridge",
1685 "rifle",
1686 "right",
1687 "rigid",
1688 "ring",
1689 "riot",
1690 "ripple",
1691 "risk",
1692 "ritual",
1693 "rival",
1694 "river",
1695 "road",
1696 "roast",
1697 "robot",
1698 "robust",
1699 "rocket",
1700 "romance",
1701 "roof",
1702 "rookie",
1703 "room",
1704 "rose",
1705 "rotate",
1706 "rough",
1707 "round",
1708 "route",
1709 "royal",
1710 "rubber",
1711 "rude",
1712 "rug",
1713 "rule",
1714 "run",
1715 "runway",
1716 "rural",
1717 "sad",
1718 "saddle",
1719 "sadness",
1720 "safe",
1721 "sail",
1722 "salad",
1723 "salmon",
1724 "salon",
1725 "salt",
1726 "salute",
1727 "same",
1728 "sample",
1729 "sand",
1730 "satisfy",
1731 "satoshi",
1732 "sauce",
1733 "sausage",
1734 "save",
1735 "say",
1736 "scale",
1737 "scan",
1738 "scare",
1739 "scatter",
1740 "scene",
1741 "scheme",
1742 "school",
1743 "science",
1744 "scissors",
1745 "scorpion",
1746 "scout",
1747 "scrap",
1748 "screen",
1749 "script",
1750 "scrub",
1751 "sea",
1752 "search",
1753 "season",
1754 "seat",
1755 "second",
1756 "secret",
1757 "section",
1758 "security",
1759 "seed",
1760 "seek",
1761 "segment",
1762 "select",
1763 "sell",
1764 "seminar",
1765 "senior",
1766 "sense",
1767 "sentence",
1768 "series",
1769 "service",
1770 "session",
1771 "settle",
1772 "setup",
1773 "seven",
1774 "shadow",
1775 "shaft",
1776 "shallow",
1777 "share",
1778 "shed",
1779 "shell",
1780 "sheriff",
1781 "shield",
1782 "shift",
1783 "shine",
1784 "ship",
1785 "shiver",
1786 "shock",
1787 "shoe",
1788 "shoot",
1789 "shop",
1790 "short",
1791 "shoulder",
1792 "shove",
1793 "shrimp",
1794 "shrug",
1795 "shuffle",
1796 "shy",
1797 "sibling",
1798 "sick",
1799 "side",
1800 "siege",
1801 "sight",
1802 "sign",
1803 "silent",
1804 "silk",
1805 "silly",
1806 "silver",
1807 "similar",
1808 "simple",
1809 "since",
1810 "sing",
1811 "siren",
1812 "sister",
1813 "sit",
1814 "situation",
1815 "six",
1816 "size",
1817 "skate",
1818 " sketch",
1819 "ski",
1820 "skill",
1821 "skin",
1822 "skirt",
1823 "skull",
1824 "slab",
1825 "slam",
1826 "sleep",
1827 "slender",
1828 "slice",
1829 "slide",
1830 "slight",
1831 "slim",
1832 "slogan",
1833 "slot",
1834 "slow",
1835 "slush",
1836 "small",
1837 "smart",
1838 "smile",
1839 "smoke",
1840 "smooth",
1841 "snack",
1842 "snake",
1843 "snap",
1844 "sniff",
1845 "snow",
1846 "soap",
1847 "soccer",
1848 "social",
1849 "sock",
1850 "soda",
1851 "soft",
1852 "solar",
1853 "soldier",
1854 "solid",
1855 "solution",
1856 "solve",
1857 "someone",
1858 "song",
1859 "soon",
1860 "sorry",
1861 "sort",
1862 "soul",
1863 "sound",
1864 "soup",
1865 "source",
1866 "south",
1867 "space",
1868 "spare",
1869 "spatial",
1870 "spawn",
1871 "speak",
1872 "special",
1873 "speed",
1874 "spell",
1875 "spend",
1876 "sphere",
1877 "spice",
1878 "spider",
1879 "spike",
1880 "spin",
1881 "spirit",
1882 "split",
1883 "spoil",
1884 "sponsor",
1885 "spoon",
1886 "sport",
1887 "spot",
1888 "spray",
1889 "spread",
1890 "spring",
1891 "spy",
1892 "square",
1893 "squeeze",
1894 "squirrel",
1895 "stable",
1896 "stadium",
1897 "staff",
1898 "stage",
1899 "stairs",
1900 "stamp",
1901 "stand",
1902 "start",
1903 "state",
1904 "stay",
1905 "steak",
1906 "steel",
1907 "stem",
1908 "step",
1909 "stereo",
1910 "stick",
1911 "still",
1912 "sting",
1913 "stock",
1914 "stomach",
1915 "stone",
1916 "stool",
1917 "story",
1918 "stove",
1919 "strategy",
1920 "street",
1921 "strike",
1922 "strong",
1923 "struggle",
1924 "student",
1925 "stuff",
1926 "stumble",
1927 "style",
1928 "subject",
1929 "submit",
1930 "subway",
1931 "success",
1932 "such",
1933 "sudden",
1934 "suffer",
1935 "sugar",
1936 "suggest",
1937 "suit",
1938 "summer",
1939 "sun",
1940 "sunny",
1941 "sunset",
1942 "super",
1943 "supply",
1944 "supreme",
1945 "sure",
1946 "surface",
1947 "surge",
1948 "surprise",
1949 "surround",
1950 "survey",
1951 "suspect",
1952 "sustain",
1953 "swallow",
1954 "swamp",
1955 "swap",
1956 "swarm",
1957 "swear",
1958 "sweet",
1959 "swift",
1960 "swim",
1961 "swing",
1962 "switch",
1963 "sword",
1964 "symbol",
1965 "symptom",
1966 "syrup",
1967 "system",
1968 "table",
1969 "tackle",
1970 "tag",
1971 "tail",
1972 "talent",
1973 "talk",
1974 "tank",
1975 "tape",
1976 "target",
1977 "task",
1978 "taste",
1979 "tattoo",
1980 "taxi",
1981 "teach",
1982 "team",
1983 "tell",
1984 "ten",
1985 "tenant",
1986 "tennis",
1987 "tent",
1988 "term",
1989 "test",
1990 "text",
1991 "thank",
1992 "that",
1993 "theme",
1994 "then",
1995 "theory",
1996 "there",
1997 "they",
1998 "thing",
1999 "this",
2000 "thought",
2001 "three",
2002 "thrive",
2003 "throw",
2004 "thumb",
2005 "thunder",
2006 "ticket",
2007 "tide",
2008 "tiger",
2009 "tilt",
2010 "timber",
2011 "time",
2012 "tiny",
2013 "tip",
2014 "tired",
2015 "tissue",
2016 "title",
2017 "toast",
2018 "tobacco",
2019 "today",
2020 "toddler",
2021 "toe",
2022 "together",
2023 "toilet",
2024 "token",
2025 "tomato",
2026 "tomorrow",
2027 "tone",
2028 "tongue",
2029 "tonight",
2030 "tool",
2031 "tooth",
2032 "top",
2033 "topic",
2034 "topple",
2035 "torch",
2036 "tornado",
2037 "tortoise",
2038 "toss",
2039 "total",
2040 "tourist",
2041 "toward",
2042 "tower",
2043 "town",
2044 "toy",
2045 "track",
2046 "trade",
2047 "traffic",
2048 "tragic",
2049 "train",
2050 "transfer",
2051 "trap",
2052 "trash",
2053 "travel",
2054 "tray",
2055 "treat",
2056 "tree",
2057 "trend",
2058 "trial",
2059 "tribe",
2060 "trick",
2061 "trigger",
2062 "trim",
2063 "trip",
2064 "trophy",
2065 "trouble",
2066 "truck",
2067 "true",
2068 "truly",
2069 "trumpet",
2070 "trust",
2071 "truth",
2072 "try",
2073 "tube",
2074 "tuition",
2075 "tumble",
2076 "tuna",
2077 "tunnel",
2078 "turkey",
2079 "turn",
2080 "turtle",
2081 "twelve",
2082 "twenty",
2083 "twice",
2084 "twin",
2085 "twist",
2086 "two",
2087 "type",
2088 "typical",
2089 "ugly",
2090 "umbrella",
2091 "unable",
2092 "unaware",
2093 "uncle",
2094 "uncover",
2095 "under",
2096 "undo",
2097 "unfair",
2098 "unfold",
2099 "unhappy",
2100 "uniform",
2101 "unique",
2102 "unit",
2103 "universe",
2104 "unknown",
2105 "unlock",
2106 "until",
2107 "unusual",
2108 "unveil",
2109 "update",
2110 "upgrade",
2111 "uphold",
2112 "upon",
2113 "upper",
2114 "upset",
2115 "urban",
2116 "urge",
2117 "usage",
2118 "use",
2119 "used",
2120 "useful",
2121 "useless",
2122 "user",
2123 "utility",
2124 "vacant",
2125 "vacuum",
2126 "vague",
2127 "valid",
2128 "valley",
2129 "valve",
2130 "van",
2131 "vanish",
2132 "vapor",
2133 "various",
2134 "vegan",
2135 "velvet",
2136 "vendor",
2137 "venture",
2138 "venue",
2139 "verb",
2140 "verify",
2141 "version",
2142 "very",
2143 "vessel",
2144 "veteran",
2145 "viable",
2146 "vibrant",
2147 "vicious",
2148 "victory",
2149 "video",
2150 "view",
2151 "village",
2152 "vintage",
2153 "violin",
2154 "virtual",
2155 "virus",
2156 "visa",
2157 "visit",
2158 "visual",
2159 "vital",
2160 "vivid",
2161 "vocal",
2162 "voice",
2163 "void",
2164 "volcano",
2165 "volume",
2166 "vote",
2167 "voyage",
2168 "wage",
2169 "wagon",
2170 "wait",
2171 "walk",
2172 "wall",
2173 "walnut",
2174 "want",
2175 "warfare",
2176 "warm",
2177 "warrior",
2178 "wash",
2179 "wasp",
2180 "waste",
2181 "water",
2182 "wave",
2183 "way",
2184 "wealth",
2185 "weapon",
2186 "wear",
2187 "weasel",
2188 "weather",
2189 "web",
2190 "wedding",
2191 "weekend",
2192 "weird",
2193 "welcome",
2194 "west",
2195 "wet",
2196 "whale",
2197 "what",
2198 "wheat",
2199 "wheel",
2200 "when",
2201 "where",
2202 "whip",
2203 "whisper",
2204 "wide",
2205 "width",
2206 "wife",
2207 "wild",
2208 "will",
2209 "win",
2210 "window",
2211 "wine",
2212 "wing",
2213 "wink",
2214 "winner",
2215 "winter",
2216 "wire",
2217 "wisdom",
2218 "wise",
2219 "wish",
2220 "witness",
2221 "wolf",
2222 "woman",
2223 "wonder",
2224 "wood",
2225 "wool",
2226 "word",
2227 "work",
2228 "world",
2229 "worry",
2230 "worth",
2231 "wrap",
2232 "wreck",
2233 "wrestle",
2234 "wrist",
2235 "write",
2236 "wrong",
2237 "yard",
2238 "year",
2239 "yellow",
2240 "you",
2241 "young",
2242 "youth",
2243 "zebra",
2244 "zero",
2245 "zone",
2246 "zoo",
2247 ];
2248
2249 use rand::Rng;
2250 let mut rng = rand::thread_rng();
2251 let mut phrase = Vec::new();
2252 for _ in 0..12 {
2253 phrase.push(WORDS[rng.gen_range(0..WORDS.len())]);
2254 }
2255 phrase.join(" ")
2256 }
2257
2258 fn derive_keys(seed: &str) -> (String, String) {
2259 let mut hasher = Sha256::new();
2260 hasher.update(seed.as_bytes());
2261 let hash_result = hasher.finalize();
2262
2263 let mut key_bytes = [0u8; 32];
2264 key_bytes.copy_from_slice(&hash_result[..32]);
2265
2266 let signing_key = SigningKey::from_bytes(&key_bytes);
2267 let verifying_key: VerifyingKey = signing_key.verifying_key();
2268
2269 let private_key_hex = hex::encode(signing_key.to_bytes());
2270 let address = hex::encode(&verifying_key.as_bytes()[1..]);
2271
2272 let formatted_address = format!("0x{}", address);
2273 let formatted_private_key = format!("0x{}", private_key_hex);
2274
2275 (formatted_private_key, formatted_address)
2276 }
2277
2278 fn derive_address_from_public_key(public_key_bytes: &[u8]) -> String {
2279 let address = hex::encode(&public_key_bytes[1..]);
2280 format!("0x{}", address)
2281 }
2282}
2283
2284impl Default for Wallet {
2285 fn default() -> Self {
2286 Wallet {
2287 address: "0x0000000000000000000000000000000000000000000000000000000000000000"
2288 .to_string(),
2289 private_key: "0x0000000000000000000000000000000000000000000000000000000000000000"
2290 .to_string(),
2291 network: "testnet".to_string(),
2292 seed_phrase: String::new(),
2293 }
2294 }
2295}