Skip to content

Commit 0965970

Browse files
authored
✨ Introduce hyli-wallet script to register accounts from node cli (#36)
* ✨ wallet-script * ✨ Instroduce hyli-wallet script to register accounts from node cli * update deps * Update default ports * prepare script for publish * print wallet api url * fix installed script * fix config example * fix example
1 parent b88b733 commit 0965970

File tree

8 files changed

+674
-0
lines changed

8 files changed

+674
-0
lines changed

README.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,3 +40,21 @@ from server's Cargo.toml and build the contracts using:
4040
```bash
4141
cargo build -p contracts --features build --features all
4242
```
43+
44+
## Scripts
45+
46+
For wallet account registration and management, see the [`script/`](./script/) folder which contains:
47+
48+
- **Wallet Registration Script**: A standalone Node.js script for registering wallet accounts
49+
- **Examples**: Usage examples and batch registration scripts
50+
- **Configuration**: Environment-specific configuration templates
51+
52+
### Quick Script Usage
53+
54+
```bash
55+
cd script
56+
npm install
57+
node hyli-wallet.js <username> <password> <inviteCode>
58+
```
59+
60+
For detailed documentation, see [script/README.md](./script/README.md).

script/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
node_modules

script/README.md

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
# Hyli Wallet CLI
2+
3+
A standalone command-line tool for managing Hyli wallet accounts.
4+
5+
## 🚀 Quick Start
6+
7+
### Option 1: Install from NPM (Recommended)
8+
9+
```bash
10+
# Install globally
11+
npm install -g hyli-wallet-cli
12+
13+
# Use the command
14+
hyli-wallet --help
15+
```
16+
17+
### Option 2: Install from Source
18+
19+
```bash
20+
# Clone just this package
21+
git clone https://github.com/hyli-org/wallet.git
22+
cd wallet/script
23+
24+
# Install dependencies
25+
npm install
26+
27+
# Make it globally available
28+
npm link
29+
30+
# Use the command
31+
hyli-wallet --help
32+
```
33+
34+
## 📖 Usage
35+
36+
```bash
37+
hyli-wallet <username> <password> <inviteCode> [salt] [enableSessionKey]
38+
```
39+
40+
### Arguments
41+
42+
- **username** - The username for the account
43+
- **password** - The password (must be at least 8 characters)
44+
- **inviteCode** - The invite code to use
45+
- **salt** - Optional salt (defaults to random string)
46+
- **enableSessionKey** - Optional: 'true' to enable session key (default: false)
47+
48+
### Environment Variables
49+
50+
- `NODE_BASE_URL` - Node service URL (default: http://localhost:4321)
51+
- `INDEXER_BASE_URL` - Indexer service URL (default: http://localhost:4322)
52+
- `WALLET_API_BASE_URL` - Wallet API URL (default: http://localhost:4000)
53+
54+
### Examples
55+
56+
```bash
57+
# Basic registration
58+
hyli-wallet myuser mypassword123 INVITE123
59+
60+
# With custom salt
61+
hyli-wallet myuser mypassword123 INVITE123 mysalt
62+
63+
# With session key enabled
64+
hyli-wallet myuser mypassword123 INVITE123 mysalt true
65+
66+
# With custom service URLs
67+
NODE_BASE_URL=http://localhost:4321 \
68+
INDEXER_BASE_URL=http://localhost:4322 \
69+
hyli-wallet myuser mypassword123 INVITE123
70+
```
71+
72+
## 🔧 Configuration
73+
74+
The script automatically detects your environment and uses sensible defaults. You can override these by setting environment variables:
75+
76+
```bash
77+
export NODE_BASE_URL="http://your-node:4321"
78+
export INDEXER_BASE_URL="http://your-indexer:4322"
79+
export WALLET_API_BASE_URL="http://your-wallet-api:4000"
80+
```
81+
82+
## 📦 What's Included
83+
84+
This standalone package includes:
85+
86+
- ✅ Complete wallet registration functionality
87+
- ✅ Session key generation
88+
- ✅ Invite code validation
89+
- ✅ Blob transaction handling
90+
- ✅ Proof transaction generation
91+
92+
## 🛠️ Development
93+
94+
### Prerequisites
95+
96+
- Node.js 16.0.0 or higher
97+
- npm or yarn
98+
99+
### Local Development
100+
101+
```bash
102+
# Clone the repository
103+
git clone https://github.com/hyli/wallet.git
104+
cd wallet/script
105+
106+
# Install dependencies
107+
bun install
108+
109+
# Run the script
110+
bun register myuser mypassword123 INVITE123
111+
```
112+
113+
### Building for Distribution
114+
115+
```bash
116+
# Publish to NPM (if you have access)
117+
bun run pub
118+
```
119+
120+
## 🐛 Troubleshooting
121+
122+
## 📄 License
123+
124+
MIT License
125+
126+
## 🤝 Contributing
127+
128+
Contributions are welcome! Please see the [contributing guide](https://github.com/hyli-org/hyli/blob/main/CONTRIBUTING.md) for details.
129+
130+
---
131+
132+
**Made with ❤️ by the Hyli Team**

script/bun.lockb

18.7 KB
Binary file not shown.

script/config.example.js

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
// Configuration template for the wallet registration script
2+
// Copy this file to config.js and update the values
3+
4+
export const CONFIG = {
5+
// Hyli Node Service URL
6+
NODE_BASE_URL: process.env.NODE_BASE_URL || "http://localhost:4321",
7+
8+
// Hyli Indexer Service URL
9+
INDEXER_BASE_URL: process.env.INDEXER_BASE_URL || "http://localhost:4322",
10+
11+
// Wallet Contract Name
12+
WALLET_CONTRACT_NAME: "wallet",
13+
14+
// Default session key duration (24 hours in milliseconds)
15+
DEFAULT_SESSION_KEY_DURATION: 24 * 60 * 60 * 1000,
16+
17+
// Default whitelist for session keys (empty array means no restrictions)
18+
DEFAULT_SESSION_KEY_WHITELIST: [],
19+
20+
// Timeout for operations (in milliseconds)
21+
OPERATION_TIMEOUT: 60000,
22+
23+
// Retry configuration
24+
RETRY_CONFIG: {
25+
maxRetries: 3,
26+
retryDelay: 1000, // 1 second
27+
backoffMultiplier: 2
28+
},
29+
30+
// Logging configuration
31+
LOGGING: {
32+
level: "info", // debug, info, warn, error
33+
enableConsole: true,
34+
enableFile: false,
35+
logFile: "registration.log"
36+
}
37+
};
38+
39+
// Environment-specific configurations
40+
export const ENV_CONFIGS = {
41+
local: {
42+
NODE_BASE_URL: "http://localhost:4321",
43+
INDEXER_BASE_URL: "http://localhost:4322",
44+
WALLET_API_BASE_URL: "http://localhost:4000",
45+
LOGGING: { level: "debug" }
46+
},
47+
48+
devnet: {
49+
NODE_BASE_URL: "https://node.devnet.hyli.org",
50+
INDEXER_BASE_URL: "https://indexer.devnet.hyli.org",
51+
WALLET_API_BASE_URL: "https://wallet.devnet.hyli.org",
52+
LOGGING: { level: "info" }
53+
},
54+
55+
testnet: {
56+
NODE_BASE_URL: "https://node.testnet.hyli.org",
57+
INDEXER_BASE_URL: "https://indexer.testnet.hyli.org",
58+
WALLET_API_BASE_URL: "https://wallet.testnet.hyli.org",
59+
LOGGING: { level: "warn" }
60+
}
61+
};
62+
63+
// Helper function to get configuration based on environment
64+
export function getConfig(environment = process.env.NODE_ENV || "local") {
65+
const envConfig = ENV_CONFIGS[environment] || {};
66+
return { ...CONFIG, ...envConfig };
67+
}
68+
69+
// Helper function to validate configuration
70+
export function validateConfig(config) {
71+
const required = ['NODE_BASE_URL', 'INDEXER_BASE_URL', 'WALLET_CONTRACT_NAME', 'WALLET_API_BASE_URL'];
72+
const missing = required.filter(key => !config[key]);
73+
74+
if (missing.length > 0) {
75+
throw new Error(`Missing required configuration: ${missing.join(', ')}`);
76+
}
77+
78+
// Validate URLs
79+
try {
80+
new URL(config.NODE_BASE_URL);
81+
new URL(config.INDEXER_BASE_URL);
82+
new URL(config.WALLET_API_BASE_URL);
83+
} catch (error) {
84+
throw new Error(`Invalid URL in configuration: ${error.message}`);
85+
}
86+
87+
return true;
88+
}

script/example-usage.js

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
#!/usr/bin/env node
2+
3+
import { registerAccount } from './hyli-wallet.js';
4+
5+
// Example of using the registration function programmatically
6+
async function exampleUsage() {
7+
console.log("=== Example: Programmatic Account Registration ===\n");
8+
9+
// Configuration
10+
const config = {
11+
username: "testuser",
12+
password: "mypassword123",
13+
inviteCode: "INVITE123",
14+
salt: "customsalt",
15+
enableSessionKey: true
16+
};
17+
18+
console.log("Configuration:", config);
19+
console.log("");
20+
21+
try {
22+
// Register the account
23+
const result = await registerAccount(
24+
config.username,
25+
config.password,
26+
config.inviteCode,
27+
config.salt,
28+
config.enableSessionKey
29+
);
30+
31+
if (result.success) {
32+
console.log("✅ Registration successful!");
33+
console.log("Wallet details:", JSON.stringify(result.wallet, null, 2));
34+
35+
// You can now use the wallet object for other operations
36+
console.log(`\nAccount address: ${result.wallet.address}`);
37+
if (result.wallet.sessionKey) {
38+
console.log(`Session key public: ${result.wallet.sessionKey.publicKey}`);
39+
console.log(`Session key expires: ${new Date(result.wallet.sessionKey.expiration).toISOString()}`);
40+
}
41+
} else {
42+
console.log("❌ Registration failed:", result.error);
43+
}
44+
45+
} catch (error) {
46+
console.error("Error during registration:", error);
47+
}
48+
}
49+
50+
// Example of batch registration
51+
async function batchRegistration() {
52+
console.log("\n=== Example: Batch Registration ===\n");
53+
54+
const users = [
55+
{ username: "alice", password: "alicepass123", inviteCode: "INVITE001" },
56+
{ username: "bob", password: "bobpass123", inviteCode: "INVITE002" },
57+
{ username: "charlie", password: "charliepass123", inviteCode: "INVITE003" }
58+
];
59+
60+
for (const user of users) {
61+
console.log(`Registering user: ${user.username}`);
62+
63+
try {
64+
const result = await registerAccount(
65+
user.username,
66+
user.password,
67+
user.inviteCode,
68+
undefined, // Use random salt
69+
false // No session key
70+
);
71+
72+
if (result.success) {
73+
console.log(`✅ ${user.username} registered successfully`);
74+
} else {
75+
console.log(`❌ ${user.username} failed: ${result.error}`);
76+
}
77+
78+
} catch (error) {
79+
console.log(`❌ ${user.username} error: ${error.message}`);
80+
}
81+
82+
console.log("---");
83+
}
84+
}
85+
86+
// Example of error handling
87+
async function errorHandlingExample() {
88+
console.log("\n=== Example: Error Handling ===\n");
89+
90+
// Test with invalid password
91+
try {
92+
const result = await registerAccount(
93+
"testuser",
94+
"123", // Too short
95+
"INVITE123"
96+
);
97+
98+
console.log("Result:", result);
99+
100+
} catch (error) {
101+
console.log("Caught error:", error.message);
102+
}
103+
104+
// Test with missing parameters
105+
try {
106+
const result = await registerAccount(
107+
"testuser",
108+
"", // Empty password
109+
"INVITE123"
110+
);
111+
112+
console.log("Result:", result);
113+
114+
} catch (error) {
115+
console.log("Caught error:", error.message);
116+
}
117+
}
118+
119+
// Run examples
120+
async function runExamples() {
121+
// Set environment variables for the examples
122+
process.env.NODE_BASE_URL = "http://localhost:4321";
123+
process.env.INDEXER_BASE_URL = "http://localhost:4322";
124+
process.env.WALLET_API_BASE_URL = "http://localhost:4000";
125+
126+
await exampleUsage();
127+
await batchRegistration();
128+
await errorHandlingExample();
129+
130+
console.log("\n=== Examples completed ===");
131+
}
132+
133+
// Run if this file is executed directly
134+
if (import.meta.url === `file://${process.argv[1]}`) {
135+
runExamples().catch(error => {
136+
console.error("Example execution failed:", error);
137+
process.exit(1);
138+
});
139+
}
140+
141+
export { exampleUsage, batchRegistration, errorHandlingExample };

0 commit comments

Comments
 (0)