Skip to main content

x402_cli/x402/
wallet.rs

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}