movehat 0.0.1-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +236 -0
- package/bin/movehat.js +21 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +93 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/compile.d.ts +2 -0
- package/dist/commands/compile.d.ts.map +1 -0
- package/dist/commands/compile.js +71 -0
- package/dist/commands/compile.js.map +1 -0
- package/dist/commands/fork/create.d.ts +11 -0
- package/dist/commands/fork/create.d.ts.map +1 -0
- package/dist/commands/fork/create.js +56 -0
- package/dist/commands/fork/create.js.map +1 -0
- package/dist/commands/fork/fund.d.ts +12 -0
- package/dist/commands/fork/fund.d.ts.map +1 -0
- package/dist/commands/fork/fund.js +42 -0
- package/dist/commands/fork/fund.js.map +1 -0
- package/dist/commands/fork/list.d.ts +5 -0
- package/dist/commands/fork/list.d.ts.map +1 -0
- package/dist/commands/fork/list.js +61 -0
- package/dist/commands/fork/list.js.map +1 -0
- package/dist/commands/fork/serve.d.ts +10 -0
- package/dist/commands/fork/serve.d.ts.map +1 -0
- package/dist/commands/fork/serve.js +64 -0
- package/dist/commands/fork/serve.js.map +1 -0
- package/dist/commands/fork/view-resource.d.ts +11 -0
- package/dist/commands/fork/view-resource.d.ts.map +1 -0
- package/dist/commands/fork/view-resource.js +34 -0
- package/dist/commands/fork/view-resource.js.map +1 -0
- package/dist/commands/init.d.ts +2 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +90 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/run.d.ts +2 -0
- package/dist/commands/run.d.ts.map +1 -0
- package/dist/commands/run.js +51 -0
- package/dist/commands/run.js.map +1 -0
- package/dist/commands/test.d.ts +2 -0
- package/dist/commands/test.d.ts.map +1 -0
- package/dist/commands/test.js +35 -0
- package/dist/commands/test.js.map +1 -0
- package/dist/core/config.d.ts +15 -0
- package/dist/core/config.d.ts.map +1 -0
- package/dist/core/config.js +121 -0
- package/dist/core/config.js.map +1 -0
- package/dist/core/contract.d.ts +20 -0
- package/dist/core/contract.d.ts.map +1 -0
- package/dist/core/contract.js +59 -0
- package/dist/core/contract.js.map +1 -0
- package/dist/core/deployments.d.ts +32 -0
- package/dist/core/deployments.d.ts.map +1 -0
- package/dist/core/deployments.js +122 -0
- package/dist/core/deployments.js.map +1 -0
- package/dist/core/shell.d.ts +25 -0
- package/dist/core/shell.d.ts.map +1 -0
- package/dist/core/shell.js +56 -0
- package/dist/core/shell.js.map +1 -0
- package/dist/errors.d.ts +12 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +24 -0
- package/dist/errors.js.map +1 -0
- package/dist/fork/api.d.ts +33 -0
- package/dist/fork/api.d.ts.map +1 -0
- package/dist/fork/api.js +98 -0
- package/dist/fork/api.js.map +1 -0
- package/dist/fork/manager.d.ts +52 -0
- package/dist/fork/manager.d.ts.map +1 -0
- package/dist/fork/manager.js +221 -0
- package/dist/fork/manager.js.map +1 -0
- package/dist/fork/server.d.ts +55 -0
- package/dist/fork/server.d.ts.map +1 -0
- package/dist/fork/server.js +274 -0
- package/dist/fork/server.js.map +1 -0
- package/dist/fork/storage.d.ts +63 -0
- package/dist/fork/storage.d.ts.map +1 -0
- package/dist/fork/storage.js +183 -0
- package/dist/fork/storage.js.map +1 -0
- package/dist/fork/test.d.ts +75 -0
- package/dist/fork/test.d.ts.map +1 -0
- package/dist/fork/test.js +157 -0
- package/dist/fork/test.js.map +1 -0
- package/dist/helpers/assertions.d.ts +7 -0
- package/dist/helpers/assertions.d.ts.map +1 -0
- package/dist/helpers/assertions.js +17 -0
- package/dist/helpers/assertions.js.map +1 -0
- package/dist/helpers/banner.d.ts +3 -0
- package/dist/helpers/banner.d.ts.map +1 -0
- package/dist/helpers/banner.js +38 -0
- package/dist/helpers/banner.js.map +1 -0
- package/dist/helpers/index.d.ts +11 -0
- package/dist/helpers/index.d.ts.map +1 -0
- package/dist/helpers/index.js +7 -0
- package/dist/helpers/index.js.map +1 -0
- package/dist/helpers/setup.d.ts +10 -0
- package/dist/helpers/setup.d.ts.map +1 -0
- package/dist/helpers/setup.js +28 -0
- package/dist/helpers/setup.js.map +1 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +12 -0
- package/dist/index.js.map +1 -0
- package/dist/runtime.d.ts +26 -0
- package/dist/runtime.d.ts.map +1 -0
- package/dist/runtime.js +247 -0
- package/dist/runtime.js.map +1 -0
- package/dist/templates/.env.example +9 -0
- package/dist/templates/.mocharc.json +8 -0
- package/dist/templates/README.md +92 -0
- package/dist/templates/move/Counter.move +64 -0
- package/dist/templates/move/Move.toml +16 -0
- package/dist/templates/movehat.config.ts +37 -0
- package/dist/templates/package.json +24 -0
- package/dist/templates/scripts/deploy-counter.ts +48 -0
- package/dist/templates/tests/Counter.test.ts +75 -0
- package/dist/templates/tsconfig.json +15 -0
- package/dist/templates/types/movehat.d.ts +104 -0
- package/dist/types/config.d.ts +35 -0
- package/dist/types/config.d.ts.map +1 -0
- package/dist/types/config.js +2 -0
- package/dist/types/config.js.map +1 -0
- package/dist/types/fork.d.ts +37 -0
- package/dist/types/fork.d.ts.map +1 -0
- package/dist/types/fork.js +5 -0
- package/dist/types/fork.js.map +1 -0
- package/dist/types/runtime.d.ts +28 -0
- package/dist/types/runtime.d.ts.map +1 -0
- package/dist/types/runtime.js +2 -0
- package/dist/types/runtime.js.map +1 -0
- package/package.json +66 -0
- package/src/cli.ts +106 -0
- package/src/commands/compile.ts +84 -0
- package/src/commands/fork/create.ts +70 -0
- package/src/commands/fork/fund.ts +57 -0
- package/src/commands/fork/list.ts +67 -0
- package/src/commands/fork/serve.ts +77 -0
- package/src/commands/fork/view-resource.ts +46 -0
- package/src/commands/init.ts +150 -0
- package/src/commands/run.ts +59 -0
- package/src/commands/test.ts +42 -0
- package/src/core/config.ts +151 -0
- package/src/core/contract.ts +97 -0
- package/src/core/deployments.ts +164 -0
- package/src/core/shell.ts +66 -0
- package/src/errors.ts +21 -0
- package/src/fork/api.ts +117 -0
- package/src/fork/manager.ts +264 -0
- package/src/fork/server.ts +311 -0
- package/src/fork/storage.ts +224 -0
- package/src/fork/test.ts +195 -0
- package/src/helpers/assertions.ts +29 -0
- package/src/helpers/banner.ts +47 -0
- package/src/helpers/index.ts +26 -0
- package/src/helpers/setup.ts +49 -0
- package/src/index.ts +17 -0
- package/src/runtime.ts +322 -0
- package/src/templates/.env.example +9 -0
- package/src/templates/.mocharc.json +8 -0
- package/src/templates/README.md +92 -0
- package/src/templates/move/Counter.move +64 -0
- package/src/templates/move/Move.toml +16 -0
- package/src/templates/movehat.config.ts +37 -0
- package/src/templates/package.json +24 -0
- package/src/templates/scripts/deploy-counter.ts +48 -0
- package/src/templates/tests/Counter.test.ts +75 -0
- package/src/templates/tsconfig.json +15 -0
- package/src/templates/types/movehat.d.ts +104 -0
- package/src/types/config.ts +36 -0
- package/src/types/fork.ts +41 -0
- package/src/types/runtime.ts +49 -0
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { MovehatRuntime } from "./types/runtime.js";
|
|
2
|
+
import { MovehatUserConfig } from "./types/config.js";
|
|
3
|
+
export interface InitRuntimeOptions {
|
|
4
|
+
network?: string;
|
|
5
|
+
accountIndex?: number;
|
|
6
|
+
configOverride?: Partial<MovehatUserConfig>;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Initialize the Movehat Runtime Environment
|
|
10
|
+
* This function loads the configuration and creates the runtime context
|
|
11
|
+
*/
|
|
12
|
+
export declare function initRuntime(options?: InitRuntimeOptions): Promise<MovehatRuntime>;
|
|
13
|
+
/**
|
|
14
|
+
* Get the current Movehat Runtime Environment
|
|
15
|
+
* Throws error if runtime hasn't been initialized
|
|
16
|
+
*/
|
|
17
|
+
export declare function getRuntime(): MovehatRuntime;
|
|
18
|
+
/**
|
|
19
|
+
* Get or initialize the Movehat Runtime Environment
|
|
20
|
+
* This is a convenience function that initializes if needed
|
|
21
|
+
*/
|
|
22
|
+
export declare function getMovehat(): Promise<MovehatRuntime>;
|
|
23
|
+
export declare const mh: {
|
|
24
|
+
readonly runtime: MovehatRuntime;
|
|
25
|
+
};
|
|
26
|
+
//# sourceMappingURL=runtime.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,cAAc,EAAe,MAAM,oBAAoB,CAAC;AACjE,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAetD,MAAM,WAAW,kBAAkB;IACjC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,cAAc,CAAC,EAAE,OAAO,CAAC,iBAAiB,CAAC,CAAC;CAC7C;AAED;;;GAGG;AACH,wBAAsB,WAAW,CAC/B,OAAO,GAAE,kBAAuB,GAC/B,OAAO,CAAC,cAAc,CAAC,CA+PzB;AAED;;;GAGG;AACH,wBAAgB,UAAU,IAAI,cAAc,CAO3C;AAED;;;GAGG;AACH,wBAAsB,UAAU,IAAI,OAAO,CAAC,cAAc,CAAC,CAK1D;AAGD,eAAO,MAAM,EAAE;;CAId,CAAC"}
|
package/dist/runtime.js
ADDED
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
import { Account, Aptos, AptosConfig, Ed25519PrivateKey, } from "@aptos-labs/ts-sdk";
|
|
2
|
+
import { loadUserConfig, resolveNetworkConfig } from "./core/config.js";
|
|
3
|
+
import { getContract } from "./core/contract.js";
|
|
4
|
+
import { saveDeployment, loadDeployment, getAllDeployments, getDeployedAddress, validateSafeName, } from "./core/deployments.js";
|
|
5
|
+
import { ModuleAlreadyDeployedError } from "./errors.js";
|
|
6
|
+
let cachedRuntime = null;
|
|
7
|
+
/**
|
|
8
|
+
* Initialize the Movehat Runtime Environment
|
|
9
|
+
* This function loads the configuration and creates the runtime context
|
|
10
|
+
*/
|
|
11
|
+
export async function initRuntime(options = {}) {
|
|
12
|
+
// Load user config from movehat.config.ts
|
|
13
|
+
const userConfig = await loadUserConfig();
|
|
14
|
+
// Apply config override if provided
|
|
15
|
+
const mergedUserConfig = options.configOverride
|
|
16
|
+
? { ...userConfig, ...options.configOverride }
|
|
17
|
+
: userConfig;
|
|
18
|
+
// Resolve configuration for selected network
|
|
19
|
+
const config = await resolveNetworkConfig(mergedUserConfig, options.network);
|
|
20
|
+
// Setup Aptos client
|
|
21
|
+
const aptosConfig = new AptosConfig({
|
|
22
|
+
network: config.network,
|
|
23
|
+
fullnode: config.rpc,
|
|
24
|
+
});
|
|
25
|
+
const aptos = new Aptos(aptosConfig);
|
|
26
|
+
// Setup accounts
|
|
27
|
+
const accountIndex = options.accountIndex || 0;
|
|
28
|
+
const accounts = config.allAccounts.map((pk) => {
|
|
29
|
+
const privateKey = new Ed25519PrivateKey(pk);
|
|
30
|
+
return Account.fromPrivateKey({ privateKey });
|
|
31
|
+
});
|
|
32
|
+
// Primary account (accounts[0] or selected index)
|
|
33
|
+
const account = accounts[accountIndex];
|
|
34
|
+
if (!account) {
|
|
35
|
+
throw new Error(`Account index ${accountIndex} not found. Only ${accounts.length} accounts configured.`);
|
|
36
|
+
}
|
|
37
|
+
// Update config.account with derived address
|
|
38
|
+
config.account = account.accountAddress.toString();
|
|
39
|
+
// Network info
|
|
40
|
+
const network = {
|
|
41
|
+
name: config.network,
|
|
42
|
+
rpc: config.rpc,
|
|
43
|
+
};
|
|
44
|
+
// Helper functions
|
|
45
|
+
const getContractHelper = (address, moduleName) => {
|
|
46
|
+
return getContract(aptos, address, moduleName);
|
|
47
|
+
};
|
|
48
|
+
const deployContract = async (moduleName, options) => {
|
|
49
|
+
// Validate moduleName early
|
|
50
|
+
validateSafeName(moduleName, "module");
|
|
51
|
+
const { exec } = await import("child_process");
|
|
52
|
+
const { promisify } = await import("util");
|
|
53
|
+
const { existsSync, mkdirSync, writeFileSync, chmodSync } = await import("fs");
|
|
54
|
+
const { join } = await import("path");
|
|
55
|
+
const { homedir } = await import("os");
|
|
56
|
+
const yaml = await import("js-yaml");
|
|
57
|
+
const { validateAndEscapePath, validateAndEscapeProfile } = await import("./core/shell.js");
|
|
58
|
+
const execAsync = promisify(exec);
|
|
59
|
+
// Check if --redeploy flag was passed via CLI
|
|
60
|
+
const forceRedeploy = process.env.MH_CLI_REDEPLOY === 'true';
|
|
61
|
+
// Check if already deployed
|
|
62
|
+
const existingDeployment = loadDeployment(config.network, moduleName);
|
|
63
|
+
if (existingDeployment && !forceRedeploy) {
|
|
64
|
+
// Build detailed error message with all deployment info
|
|
65
|
+
const errorDetails = [
|
|
66
|
+
`Module "${moduleName}" is already deployed on ${config.network}`,
|
|
67
|
+
`Address: ${existingDeployment.address}`,
|
|
68
|
+
`Deployed at: ${new Date(existingDeployment.timestamp).toLocaleString()}`,
|
|
69
|
+
existingDeployment.txHash ? `Transaction: ${existingDeployment.txHash}` : null,
|
|
70
|
+
`\nTo redeploy, run with the --redeploy flag:`,
|
|
71
|
+
`movehat run <script> --network ${config.network} --redeploy`,
|
|
72
|
+
].filter(Boolean).join('\n');
|
|
73
|
+
// Log formatted error message for user
|
|
74
|
+
const formattedMessage = [
|
|
75
|
+
`\nā Module "${moduleName}" is already deployed on ${config.network}`,
|
|
76
|
+
` Address: ${existingDeployment.address}`,
|
|
77
|
+
` Deployed at: ${new Date(existingDeployment.timestamp).toLocaleString()}`,
|
|
78
|
+
existingDeployment.txHash ? ` Transaction: ${existingDeployment.txHash}` : null,
|
|
79
|
+
`\nš” To redeploy, run with the --redeploy flag:`,
|
|
80
|
+
` movehat run <script> --network ${config.network} --redeploy\n`,
|
|
81
|
+
].filter(Boolean).join('\n');
|
|
82
|
+
console.error(formattedMessage);
|
|
83
|
+
// Throw custom error with complete context for programmatic handling
|
|
84
|
+
throw new ModuleAlreadyDeployedError(errorDetails, moduleName, config.network, existingDeployment.address, existingDeployment.timestamp, existingDeployment.txHash);
|
|
85
|
+
}
|
|
86
|
+
if (forceRedeploy && existingDeployment) {
|
|
87
|
+
console.log(`š Redeploying module "${moduleName}" on ${config.network}...`);
|
|
88
|
+
}
|
|
89
|
+
const dir = options?.packageDir || config.moveDir;
|
|
90
|
+
const profile = config.profile || "default";
|
|
91
|
+
// Validate and escape to prevent command injection
|
|
92
|
+
const safeDir = validateAndEscapePath(dir, "package directory");
|
|
93
|
+
const safeProfile = validateAndEscapeProfile(profile);
|
|
94
|
+
console.log(`š¦ Publishing module "${moduleName}" from ${dir}...`);
|
|
95
|
+
try {
|
|
96
|
+
// Ensure Movement CLI config exists
|
|
97
|
+
const aptosConfigDir = join(homedir(), ".aptos");
|
|
98
|
+
const aptosConfigPath = join(aptosConfigDir, "config.yaml");
|
|
99
|
+
if (!existsSync(aptosConfigPath)) {
|
|
100
|
+
console.log("āļø Creating Movement CLI configuration...");
|
|
101
|
+
if (!existsSync(aptosConfigDir)) {
|
|
102
|
+
mkdirSync(aptosConfigDir, { recursive: true });
|
|
103
|
+
}
|
|
104
|
+
// Create minimal config.yaml using js-yaml to prevent YAML injection
|
|
105
|
+
const configData = {
|
|
106
|
+
profiles: {
|
|
107
|
+
[profile]: {
|
|
108
|
+
private_key: config.privateKey,
|
|
109
|
+
public_key: account.publicKey.toString(),
|
|
110
|
+
account: account.accountAddress.toString(),
|
|
111
|
+
rest_url: config.rpc,
|
|
112
|
+
},
|
|
113
|
+
},
|
|
114
|
+
};
|
|
115
|
+
const configContent = yaml.dump(configData);
|
|
116
|
+
writeFileSync(aptosConfigPath, configContent, "utf-8");
|
|
117
|
+
// Restrict file permissions to owner only (600) for security
|
|
118
|
+
// This prevents other users from reading the private key
|
|
119
|
+
try {
|
|
120
|
+
chmodSync(aptosConfigPath, 0o600);
|
|
121
|
+
}
|
|
122
|
+
catch (error) {
|
|
123
|
+
// chmod may fail on Windows, but that's okay
|
|
124
|
+
// Windows has different permission model (ACLs)
|
|
125
|
+
console.warn("ā ļø Could not set file permissions (this is normal on Windows)");
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
// Build first
|
|
129
|
+
console.log("šØ Building package...");
|
|
130
|
+
const buildCmd = `movement move build --package-dir ${safeDir}`;
|
|
131
|
+
const { stdout: buildOut } = await execAsync(buildCmd);
|
|
132
|
+
if (buildOut)
|
|
133
|
+
console.log(buildOut.trim());
|
|
134
|
+
// Publish
|
|
135
|
+
console.log("š¤ Publishing to blockchain...");
|
|
136
|
+
const publishCmd = `movement move publish --profile ${safeProfile} --package-dir ${safeDir} --assume-yes`;
|
|
137
|
+
const { stdout: publishOut } = await execAsync(publishCmd);
|
|
138
|
+
if (publishOut)
|
|
139
|
+
console.log(publishOut.trim());
|
|
140
|
+
// Extract transaction hash from output
|
|
141
|
+
// Look for patterns like "Transaction hash: 0x..." or "Txn: 0x..." or just a 64-char hex
|
|
142
|
+
// The regex tries to match with context first, then falls back to any 64-char hex
|
|
143
|
+
let txHash;
|
|
144
|
+
const txHashMatchWithContext = publishOut.match(/(?:transaction\s*(?:hash)?|txn\s*(?:hash)?|hash):\s*(0x[a-fA-F0-9]{64})\b/i);
|
|
145
|
+
if (txHashMatchWithContext) {
|
|
146
|
+
txHash = txHashMatchWithContext[1];
|
|
147
|
+
}
|
|
148
|
+
else {
|
|
149
|
+
// Fallback: try to find any 64-char hex string (exactly, not more)
|
|
150
|
+
const txHashMatch = publishOut.match(/\b(0x[a-fA-F0-9]{64})\b/);
|
|
151
|
+
if (txHashMatch) {
|
|
152
|
+
txHash = txHashMatch[1];
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
console.log(`ā
Module published successfully!`);
|
|
156
|
+
// Create deployment info
|
|
157
|
+
const deployment = {
|
|
158
|
+
address: account.accountAddress.toString(),
|
|
159
|
+
moduleName,
|
|
160
|
+
network: config.network,
|
|
161
|
+
deployer: account.accountAddress.toString(),
|
|
162
|
+
timestamp: Date.now(),
|
|
163
|
+
txHash,
|
|
164
|
+
};
|
|
165
|
+
// Save deployment
|
|
166
|
+
saveDeployment(deployment);
|
|
167
|
+
return deployment;
|
|
168
|
+
}
|
|
169
|
+
catch (error) {
|
|
170
|
+
console.error(`ā Failed to publish module: ${error.message}`);
|
|
171
|
+
throw error;
|
|
172
|
+
}
|
|
173
|
+
};
|
|
174
|
+
const getDeployment = (moduleName) => {
|
|
175
|
+
return loadDeployment(config.network, moduleName);
|
|
176
|
+
};
|
|
177
|
+
const getDeployments = () => {
|
|
178
|
+
return getAllDeployments(config.network);
|
|
179
|
+
};
|
|
180
|
+
const getDeploymentAddress = (moduleName) => {
|
|
181
|
+
return getDeployedAddress(config.network, moduleName);
|
|
182
|
+
};
|
|
183
|
+
const createAccount = () => {
|
|
184
|
+
return Account.generate();
|
|
185
|
+
};
|
|
186
|
+
const getAccountHelper = (privateKeyHex) => {
|
|
187
|
+
const pk = new Ed25519PrivateKey(privateKeyHex);
|
|
188
|
+
return Account.fromPrivateKey({ privateKey: pk });
|
|
189
|
+
};
|
|
190
|
+
const getAccountByIndex = (index) => {
|
|
191
|
+
if (index < 0 || index >= accounts.length) {
|
|
192
|
+
throw new Error(`Account index ${index} out of range. Available accounts: 0-${accounts.length - 1}`);
|
|
193
|
+
}
|
|
194
|
+
return accounts[index];
|
|
195
|
+
};
|
|
196
|
+
const switchNetwork = async (networkName) => {
|
|
197
|
+
// Clear cache and reinitialize with new network
|
|
198
|
+
cachedRuntime = null;
|
|
199
|
+
await initRuntime({ ...options, network: networkName });
|
|
200
|
+
};
|
|
201
|
+
// Build runtime object
|
|
202
|
+
const runtime = {
|
|
203
|
+
config,
|
|
204
|
+
network,
|
|
205
|
+
aptos,
|
|
206
|
+
account,
|
|
207
|
+
accounts,
|
|
208
|
+
getContract: getContractHelper,
|
|
209
|
+
deployContract,
|
|
210
|
+
getDeployment,
|
|
211
|
+
getDeployments,
|
|
212
|
+
getDeploymentAddress,
|
|
213
|
+
createAccount,
|
|
214
|
+
getAccount: getAccountHelper,
|
|
215
|
+
getAccountByIndex,
|
|
216
|
+
switchNetwork,
|
|
217
|
+
};
|
|
218
|
+
cachedRuntime = runtime;
|
|
219
|
+
return runtime;
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* Get the current Movehat Runtime Environment
|
|
223
|
+
* Throws error if runtime hasn't been initialized
|
|
224
|
+
*/
|
|
225
|
+
export function getRuntime() {
|
|
226
|
+
if (!cachedRuntime) {
|
|
227
|
+
throw new Error("Movehat Runtime not initialized. Call initRuntime() first or use getMovehat().");
|
|
228
|
+
}
|
|
229
|
+
return cachedRuntime;
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* Get or initialize the Movehat Runtime Environment
|
|
233
|
+
* This is a convenience function that initializes if needed
|
|
234
|
+
*/
|
|
235
|
+
export async function getMovehat() {
|
|
236
|
+
if (cachedRuntime) {
|
|
237
|
+
return cachedRuntime;
|
|
238
|
+
}
|
|
239
|
+
return initRuntime();
|
|
240
|
+
}
|
|
241
|
+
// Export a default instance getter for convenience
|
|
242
|
+
export const mh = {
|
|
243
|
+
get runtime() {
|
|
244
|
+
return getRuntime();
|
|
245
|
+
},
|
|
246
|
+
};
|
|
247
|
+
//# sourceMappingURL=runtime.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime.js","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,OAAO,EACP,KAAK,EACL,WAAW,EACX,iBAAiB,GAElB,MAAM,oBAAoB,CAAC;AAG5B,OAAO,EAAE,cAAc,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AACxE,OAAO,EAAE,WAAW,EAAgB,MAAM,oBAAoB,CAAC;AAC/D,OAAO,EACL,cAAc,EACd,cAAc,EACd,iBAAiB,EACjB,kBAAkB,EAElB,gBAAgB,GACjB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,0BAA0B,EAAE,MAAM,aAAa,CAAC;AAEzD,IAAI,aAAa,GAA0B,IAAI,CAAC;AAQhD;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,UAA8B,EAAE;IAEhC,0CAA0C;IAC1C,MAAM,UAAU,GAAG,MAAM,cAAc,EAAE,CAAC;IAE1C,oCAAoC;IACpC,MAAM,gBAAgB,GAAsB,OAAO,CAAC,cAAc;QAChE,CAAC,CAAC,EAAE,GAAG,UAAU,EAAE,GAAG,OAAO,CAAC,cAAc,EAAE;QAC9C,CAAC,CAAC,UAAU,CAAC;IAEf,6CAA6C;IAC7C,MAAM,MAAM,GAAG,MAAM,oBAAoB,CAAC,gBAAgB,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;IAE7E,qBAAqB;IACrB,MAAM,WAAW,GAAG,IAAI,WAAW,CAAC;QAClC,OAAO,EAAE,MAAM,CAAC,OAAkB;QAClC,QAAQ,EAAE,MAAM,CAAC,GAAG;KACrB,CAAC,CAAC;IACH,MAAM,KAAK,GAAG,IAAI,KAAK,CAAC,WAAW,CAAC,CAAC;IAErC,iBAAiB;IACjB,MAAM,YAAY,GAAG,OAAO,CAAC,YAAY,IAAI,CAAC,CAAC;IAC/C,MAAM,QAAQ,GAAc,MAAM,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE;QACxD,MAAM,UAAU,GAAG,IAAI,iBAAiB,CAAC,EAAE,CAAC,CAAC;QAC7C,OAAO,OAAO,CAAC,cAAc,CAAC,EAAE,UAAU,EAAE,CAAC,CAAC;IAChD,CAAC,CAAC,CAAC;IAEH,kDAAkD;IAClD,MAAM,OAAO,GAAG,QAAQ,CAAC,YAAY,CAAC,CAAC;IACvC,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CAAC,iBAAiB,YAAY,oBAAoB,QAAQ,CAAC,MAAM,uBAAuB,CAAC,CAAC;IAC3G,CAAC;IAED,6CAA6C;IAC7C,MAAM,CAAC,OAAO,GAAG,OAAO,CAAC,cAAc,CAAC,QAAQ,EAAE,CAAC;IAEnD,eAAe;IACf,MAAM,OAAO,GAAgB;QAC3B,IAAI,EAAE,MAAM,CAAC,OAAO;QACpB,GAAG,EAAE,MAAM,CAAC,GAAG;KAChB,CAAC;IAEF,mBAAmB;IACnB,MAAM,iBAAiB,GAAG,CAAC,OAAe,EAAE,UAAkB,EAAgB,EAAE;QAC9E,OAAO,WAAW,CAAC,KAAK,EAAE,OAAO,EAAE,UAAU,CAAC,CAAC;IACjD,CAAC,CAAC;IAEF,MAAM,cAAc,GAAG,KAAK,EAC1B,UAAkB,EAClB,OAEC,EACwB,EAAE;QAC3B,4BAA4B;QAC5B,gBAAgB,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;QAEvC,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,MAAM,CAAC,eAAe,CAAC,CAAC;QAC/C,MAAM,EAAE,SAAS,EAAE,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,CAAC;QAC3C,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,aAAa,EAAE,SAAS,EAAE,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,CAAC;QAC/E,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,CAAC;QACtC,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,CAAC;QACvC,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,SAAS,CAAC,CAAC;QACrC,MAAM,EAAE,qBAAqB,EAAE,wBAAwB,EAAE,GAAG,MAAM,MAAM,CAAC,iBAAiB,CAAC,CAAC;QAC5F,MAAM,SAAS,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;QAElC,8CAA8C;QAC9C,MAAM,aAAa,GAAG,OAAO,CAAC,GAAG,CAAC,eAAe,KAAK,MAAM,CAAC;QAE7D,4BAA4B;QAC5B,MAAM,kBAAkB,GAAG,cAAc,CAAC,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;QACtE,IAAI,kBAAkB,IAAI,CAAC,aAAa,EAAE,CAAC;YACzC,wDAAwD;YACxD,MAAM,YAAY,GAAG;gBACnB,WAAW,UAAU,4BAA4B,MAAM,CAAC,OAAO,EAAE;gBACjE,YAAY,kBAAkB,CAAC,OAAO,EAAE;gBACxC,gBAAgB,IAAI,IAAI,CAAC,kBAAkB,CAAC,SAAS,CAAC,CAAC,cAAc,EAAE,EAAE;gBACzE,kBAAkB,CAAC,MAAM,CAAC,CAAC,CAAC,gBAAgB,kBAAkB,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,IAAI;gBAC9E,8CAA8C;gBAC9C,kCAAkC,MAAM,CAAC,OAAO,aAAa;aAC9D,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAE7B,uCAAuC;YACvC,MAAM,gBAAgB,GAAG;gBACvB,eAAe,UAAU,4BAA4B,MAAM,CAAC,OAAO,EAAE;gBACrE,eAAe,kBAAkB,CAAC,OAAO,EAAE;gBAC3C,mBAAmB,IAAI,IAAI,CAAC,kBAAkB,CAAC,SAAS,CAAC,CAAC,cAAc,EAAE,EAAE;gBAC5E,kBAAkB,CAAC,MAAM,CAAC,CAAC,CAAC,mBAAmB,kBAAkB,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,IAAI;gBACjF,iDAAiD;gBACjD,qCAAqC,MAAM,CAAC,OAAO,eAAe;aACnE,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAE7B,OAAO,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC;YAEhC,qEAAqE;YACrE,MAAM,IAAI,0BAA0B,CAClC,YAAY,EACZ,UAAU,EACV,MAAM,CAAC,OAAO,EACd,kBAAkB,CAAC,OAAO,EAC1B,kBAAkB,CAAC,SAAS,EAC5B,kBAAkB,CAAC,MAAM,CAC1B,CAAC;QACJ,CAAC;QAED,IAAI,aAAa,IAAI,kBAAkB,EAAE,CAAC;YACxC,OAAO,CAAC,GAAG,CAAC,0BAA0B,UAAU,QAAQ,MAAM,CAAC,OAAO,KAAK,CAAC,CAAC;QAC/E,CAAC;QAED,MAAM,GAAG,GAAG,OAAO,EAAE,UAAU,IAAI,MAAM,CAAC,OAAO,CAAC;QAClD,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,IAAI,SAAS,CAAC;QAE5C,mDAAmD;QACnD,MAAM,OAAO,GAAG,qBAAqB,CAAC,GAAG,EAAE,mBAAmB,CAAC,CAAC;QAChE,MAAM,WAAW,GAAG,wBAAwB,CAAC,OAAO,CAAC,CAAC;QAEtD,OAAO,CAAC,GAAG,CAAC,yBAAyB,UAAU,UAAU,GAAG,KAAK,CAAC,CAAC;QAEnE,IAAI,CAAC;YACH,oCAAoC;YACpC,MAAM,cAAc,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,QAAQ,CAAC,CAAC;YACjD,MAAM,eAAe,GAAG,IAAI,CAAC,cAAc,EAAE,aAAa,CAAC,CAAC;YAE5D,IAAI,CAAC,UAAU,CAAC,eAAe,CAAC,EAAE,CAAC;gBACjC,OAAO,CAAC,GAAG,CAAC,4CAA4C,CAAC,CAAC;gBAC1D,IAAI,CAAC,UAAU,CAAC,cAAc,CAAC,EAAE,CAAC;oBAChC,SAAS,CAAC,cAAc,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;gBACjD,CAAC;gBAED,qEAAqE;gBACrE,MAAM,UAAU,GAAG;oBACjB,QAAQ,EAAE;wBACR,CAAC,OAAO,CAAC,EAAE;4BACT,WAAW,EAAE,MAAM,CAAC,UAAU;4BAC9B,UAAU,EAAE,OAAO,CAAC,SAAS,CAAC,QAAQ,EAAE;4BACxC,OAAO,EAAE,OAAO,CAAC,cAAc,CAAC,QAAQ,EAAE;4BAC1C,QAAQ,EAAE,MAAM,CAAC,GAAG;yBACrB;qBACF;iBACF,CAAC;gBACF,MAAM,aAAa,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;gBAC5C,aAAa,CAAC,eAAe,EAAE,aAAa,EAAE,OAAO,CAAC,CAAC;gBAEvD,6DAA6D;gBAC7D,yDAAyD;gBACzD,IAAI,CAAC;oBACH,SAAS,CAAC,eAAe,EAAE,KAAK,CAAC,CAAC;gBACpC,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBACf,6CAA6C;oBAC7C,gDAAgD;oBAChD,OAAO,CAAC,IAAI,CAAC,gEAAgE,CAAC,CAAC;gBACjF,CAAC;YACH,CAAC;YAED,cAAc;YACd,OAAO,CAAC,GAAG,CAAC,wBAAwB,CAAC,CAAC;YACtC,MAAM,QAAQ,GAAG,qCAAqC,OAAO,EAAE,CAAC;YAChE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,MAAM,SAAS,CAAC,QAAQ,CAAC,CAAC;YACvD,IAAI,QAAQ;gBAAE,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC;YAE3C,UAAU;YACV,OAAO,CAAC,GAAG,CAAC,gCAAgC,CAAC,CAAC;YAC9C,MAAM,UAAU,GAAG,mCAAmC,WAAW,kBAAkB,OAAO,eAAe,CAAC;YAC1G,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,GAAG,MAAM,SAAS,CAAC,UAAU,CAAC,CAAC;YAC3D,IAAI,UAAU;gBAAE,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC,CAAC;YAE/C,uCAAuC;YACvC,yFAAyF;YACzF,kFAAkF;YAClF,IAAI,MAA0B,CAAC;YAC/B,MAAM,sBAAsB,GAAG,UAAU,CAAC,KAAK,CAAC,4EAA4E,CAAC,CAAC;YAC9H,IAAI,sBAAsB,EAAE,CAAC;gBAC3B,MAAM,GAAG,sBAAsB,CAAC,CAAC,CAAC,CAAC;YACrC,CAAC;iBAAM,CAAC;gBACN,mEAAmE;gBACnE,MAAM,WAAW,GAAG,UAAU,CAAC,KAAK,CAAC,yBAAyB,CAAC,CAAC;gBAChE,IAAI,WAAW,EAAE,CAAC;oBAChB,MAAM,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC;gBAC1B,CAAC;YACH,CAAC;YAED,OAAO,CAAC,GAAG,CAAC,kCAAkC,CAAC,CAAC;YAEhD,yBAAyB;YACzB,MAAM,UAAU,GAAmB;gBACjC,OAAO,EAAE,OAAO,CAAC,cAAc,CAAC,QAAQ,EAAE;gBAC1C,UAAU;gBACV,OAAO,EAAE,MAAM,CAAC,OAAO;gBACvB,QAAQ,EAAE,OAAO,CAAC,cAAc,CAAC,QAAQ,EAAE;gBAC3C,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;gBACrB,MAAM;aACP,CAAC;YAEF,kBAAkB;YAClB,cAAc,CAAC,UAAU,CAAC,CAAC;YAE3B,OAAO,UAAU,CAAC;QACpB,CAAC;QAAC,OAAO,KAAU,EAAE,CAAC;YACpB,OAAO,CAAC,KAAK,CAAC,+BAA+B,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;YAC9D,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC,CAAC;IAEF,MAAM,aAAa,GAAG,CAAC,UAAkB,EAAyB,EAAE;QAClE,OAAO,cAAc,CAAC,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;IACpD,CAAC,CAAC;IAEF,MAAM,cAAc,GAAG,GAAmC,EAAE;QAC1D,OAAO,iBAAiB,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAC3C,CAAC,CAAC;IAEF,MAAM,oBAAoB,GAAG,CAAC,UAAkB,EAAiB,EAAE;QACjE,OAAO,kBAAkB,CAAC,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;IACxD,CAAC,CAAC;IAEF,MAAM,aAAa,GAAG,GAAY,EAAE;QAClC,OAAO,OAAO,CAAC,QAAQ,EAAE,CAAC;IAC5B,CAAC,CAAC;IAEF,MAAM,gBAAgB,GAAG,CAAC,aAAqB,EAAW,EAAE;QAC1D,MAAM,EAAE,GAAG,IAAI,iBAAiB,CAAC,aAAa,CAAC,CAAC;QAChD,OAAO,OAAO,CAAC,cAAc,CAAC,EAAE,UAAU,EAAE,EAAE,EAAE,CAAC,CAAC;IACpD,CAAC,CAAC;IAEF,MAAM,iBAAiB,GAAG,CAAC,KAAa,EAAW,EAAE;QACnD,IAAI,KAAK,GAAG,CAAC,IAAI,KAAK,IAAI,QAAQ,CAAC,MAAM,EAAE,CAAC;YAC1C,MAAM,IAAI,KAAK,CAAC,iBAAiB,KAAK,wCAAwC,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,CAAC;QACvG,CAAC;QACD,OAAO,QAAQ,CAAC,KAAK,CAAC,CAAC;IACzB,CAAC,CAAC;IAEF,MAAM,aAAa,GAAG,KAAK,EAAE,WAAmB,EAAiB,EAAE;QACjE,gDAAgD;QAChD,aAAa,GAAG,IAAI,CAAC;QACrB,MAAM,WAAW,CAAC,EAAE,GAAG,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,CAAC,CAAC;IAC1D,CAAC,CAAC;IAEF,uBAAuB;IACvB,MAAM,OAAO,GAAmB;QAC9B,MAAM;QACN,OAAO;QACP,KAAK;QACL,OAAO;QACP,QAAQ;QACR,WAAW,EAAE,iBAAiB;QAC9B,cAAc;QACd,aAAa;QACb,cAAc;QACd,oBAAoB;QACpB,aAAa;QACb,UAAU,EAAE,gBAAgB;QAC5B,iBAAiB;QACjB,aAAa;KACd,CAAC;IAEF,aAAa,GAAG,OAAO,CAAC;IACxB,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,UAAU;IACxB,IAAI,CAAC,aAAa,EAAE,CAAC;QACnB,MAAM,IAAI,KAAK,CACb,gFAAgF,CACjF,CAAC;IACJ,CAAC;IACD,OAAO,aAAa,CAAC;AACvB,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU;IAC9B,IAAI,aAAa,EAAE,CAAC;QAClB,OAAO,aAAa,CAAC;IACvB,CAAC;IACD,OAAO,WAAW,EAAE,CAAC;AACvB,CAAC;AAED,mDAAmD;AACnD,MAAM,CAAC,MAAM,EAAE,GAAG;IAChB,IAAI,OAAO;QACT,OAAO,UAAU,EAAE,CAAC;IACtB,CAAC;CACF,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# Private Key (used for all networks - Hardhat-style)
|
|
2
|
+
# This is your wallet's private key that will be used to deploy and interact with contracts
|
|
3
|
+
PRIVATE_KEY=your_private_key_here
|
|
4
|
+
|
|
5
|
+
# Optional: Override RPC URL (useful for custom endpoints)
|
|
6
|
+
# MOVEMENT_RPC_URL=https://custom-testnet.movementnetwork.xyz/v1
|
|
7
|
+
|
|
8
|
+
# Optional: Override default network from config
|
|
9
|
+
# MH_DEFAULT_NETWORK=testnet
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
# {{PROJECT_NAME}}
|
|
2
|
+
|
|
3
|
+
A Move smart contract project built with Movehat.
|
|
4
|
+
|
|
5
|
+
## Prerequisites
|
|
6
|
+
|
|
7
|
+
- Node.js v18+
|
|
8
|
+
- [Movement CLI](https://docs.movementnetwork.xyz/devs/movementCLI)
|
|
9
|
+
|
|
10
|
+
## Getting Started
|
|
11
|
+
|
|
12
|
+
### 1. Install dependencies
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
npm install
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
### 2. Configure environment
|
|
19
|
+
|
|
20
|
+
Copy `.env.example` to `.env` and fill in your credentials:
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
cp .env.example .env
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Edit `.env`:
|
|
27
|
+
```
|
|
28
|
+
MH_PRIVATE_KEY=your_private_key_here
|
|
29
|
+
MH_ACCOUNT=your_account_address_here
|
|
30
|
+
MH_NETWORK=testnet
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
### 3. Update Move.toml
|
|
34
|
+
|
|
35
|
+
Edit `move/Move.toml` and set the `counter` address to your account address:
|
|
36
|
+
|
|
37
|
+
```toml
|
|
38
|
+
[addresses]
|
|
39
|
+
counter = "0xYOUR_ACCOUNT_ADDRESS"
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### 4. Compile contracts
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
npm run compile
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### 5. Deploy
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
npx tsx scripts/deploy-counter.ts
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Or use the Movement CLI directly:
|
|
55
|
+
```bash
|
|
56
|
+
movement move publish --package-dir ./move --profile default --assume-yes
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### 6. Run tests
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
npm test
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## Project Structure
|
|
66
|
+
|
|
67
|
+
```
|
|
68
|
+
{{PROJECT_NAME}}/
|
|
69
|
+
āāā move/ # Move smart contracts
|
|
70
|
+
ā āāā sources/
|
|
71
|
+
ā ā āāā Counter.move
|
|
72
|
+
ā āāā Move.toml
|
|
73
|
+
āāā scripts/ # Deployment scripts
|
|
74
|
+
ā āāā deploy-counter.ts
|
|
75
|
+
āāā tests/ # Integration tests
|
|
76
|
+
ā āāā Counter.test.ts
|
|
77
|
+
āāā movehat.config.ts # Movehat configuration
|
|
78
|
+
āāā .env # Environment variables (git-ignored)
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
## Available Commands
|
|
82
|
+
|
|
83
|
+
- `npm run compile` - Compile Move contracts
|
|
84
|
+
- `npm test` - Run integration tests
|
|
85
|
+
- `npm run test:watch` - Run tests in watch mode
|
|
86
|
+
- `npx tsx scripts/deploy-counter.ts` - Deploy and initialize counter
|
|
87
|
+
|
|
88
|
+
## Learn More
|
|
89
|
+
|
|
90
|
+
- [Movement Documentation](https://docs.movementnetwork.xyz)
|
|
91
|
+
- [Aptos Move Book](https://move-language.github.io/move/)
|
|
92
|
+
- [Movehat GitHub](https://github.com/gilbertsahumada/movehat)
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
module counter::counter {
|
|
2
|
+
use std::signer;
|
|
3
|
+
use aptos_framework::event;
|
|
4
|
+
use aptos_framework::account;
|
|
5
|
+
|
|
6
|
+
struct Counter has key {
|
|
7
|
+
value: u64,
|
|
8
|
+
increment_events: event::EventHandle<IncrementEvent>,
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
struct IncrementEvent has drop, store {
|
|
12
|
+
old_value: u64,
|
|
13
|
+
new_value: u64,
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/// Initialize counter for an account
|
|
17
|
+
public entry fun init(account: &signer) {
|
|
18
|
+
let account_addr = signer::address_of(account);
|
|
19
|
+
|
|
20
|
+
if (!exists<Counter>(account_addr)) {
|
|
21
|
+
move_to(account, Counter {
|
|
22
|
+
value: 0,
|
|
23
|
+
increment_events: account::new_event_handle<IncrementEvent>(account),
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/// Increment the counter
|
|
29
|
+
public entry fun increment(account: &signer) acquires Counter {
|
|
30
|
+
let account_addr = signer::address_of(account);
|
|
31
|
+
assert!(exists<Counter>(account_addr), 1);
|
|
32
|
+
|
|
33
|
+
let counter = borrow_global_mut<Counter>(account_addr);
|
|
34
|
+
let old_value = counter.value;
|
|
35
|
+
counter.value = old_value + 1;
|
|
36
|
+
|
|
37
|
+
event::emit_event(&mut counter.increment_events, IncrementEvent {
|
|
38
|
+
old_value,
|
|
39
|
+
new_value: counter.value,
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/// Get counter value
|
|
44
|
+
#[view]
|
|
45
|
+
public fun get(addr: address): u64 acquires Counter {
|
|
46
|
+
assert!(exists<Counter>(addr), 1);
|
|
47
|
+
borrow_global<Counter>(addr).value
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
#[test(account = @0x1)]
|
|
51
|
+
public fun test_increment(account: &signer) acquires Counter {
|
|
52
|
+
let addr = signer::address_of(account);
|
|
53
|
+
aptos_framework::account::create_account_for_test(addr);
|
|
54
|
+
|
|
55
|
+
init(account);
|
|
56
|
+
assert!(get(addr) == 0, 0);
|
|
57
|
+
|
|
58
|
+
increment(account);
|
|
59
|
+
assert!(get(addr) == 1, 1);
|
|
60
|
+
|
|
61
|
+
increment(account);
|
|
62
|
+
assert!(get(addr) == 2, 2);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
[package]
|
|
2
|
+
name = "{{PROJECT_NAME}}"
|
|
3
|
+
version = "1.0.0"
|
|
4
|
+
authors = []
|
|
5
|
+
|
|
6
|
+
[addresses]
|
|
7
|
+
counter = "_"
|
|
8
|
+
|
|
9
|
+
[dev-addresses]
|
|
10
|
+
|
|
11
|
+
[dependencies.AptosFramework]
|
|
12
|
+
git = "https://github.com/movementlabsxyz/aptos-core.git"
|
|
13
|
+
rev = "movement"
|
|
14
|
+
subdir = "aptos-move/framework/aptos-framework"
|
|
15
|
+
|
|
16
|
+
[dev-dependencies]
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import dotenv from "dotenv";
|
|
2
|
+
dotenv.config();
|
|
3
|
+
|
|
4
|
+
export default {
|
|
5
|
+
// Default network to use when no --network flag is provided
|
|
6
|
+
defaultNetwork: "testnet",
|
|
7
|
+
|
|
8
|
+
// Network configurations
|
|
9
|
+
networks: {
|
|
10
|
+
testnet: {
|
|
11
|
+
url: process.env.MOVEMENT_RPC_URL || "https://testnet.movementnetwork.xyz/v1",
|
|
12
|
+
chainId: "testnet",
|
|
13
|
+
},
|
|
14
|
+
mainnet: {
|
|
15
|
+
url: "https://mainnet.movementnetwork.xyz/v1",
|
|
16
|
+
chainId: "mainnet",
|
|
17
|
+
},
|
|
18
|
+
local: {
|
|
19
|
+
url: "http://localhost:8080/v1",
|
|
20
|
+
chainId: "local",
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
|
|
24
|
+
// Global accounts configuration (Hardhat-style)
|
|
25
|
+
// Uses PRIVATE_KEY from .env by default
|
|
26
|
+
// You can also specify accounts here directly:
|
|
27
|
+
// accounts: ["0x1234..."],
|
|
28
|
+
accounts: process.env.PRIVATE_KEY ? [process.env.PRIVATE_KEY] : [],
|
|
29
|
+
|
|
30
|
+
// Global settings
|
|
31
|
+
moveDir: "./move",
|
|
32
|
+
|
|
33
|
+
// Named addresses (can be overridden per-network in network config)
|
|
34
|
+
namedAddresses: {
|
|
35
|
+
// Example: counter: "0x1234...",
|
|
36
|
+
},
|
|
37
|
+
};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "{{projectName}}",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"scripts": {
|
|
6
|
+
"test": "mocha",
|
|
7
|
+
"test:watch": "mocha --watch",
|
|
8
|
+
"deploy": "movehat run scripts/deploy-counter.ts"
|
|
9
|
+
},
|
|
10
|
+
"dependencies": {
|
|
11
|
+
"movehat": "^0.0.1-alpha.0",
|
|
12
|
+
"@aptos-labs/ts-sdk": "^5.1.5",
|
|
13
|
+
"dotenv": "^17.2.3"
|
|
14
|
+
},
|
|
15
|
+
"devDependencies": {
|
|
16
|
+
"@types/chai": "^5.2.3",
|
|
17
|
+
"@types/mocha": "^10.0.10",
|
|
18
|
+
"@types/node": "^24.10.1",
|
|
19
|
+
"chai": "^6.2.1",
|
|
20
|
+
"mocha": "^11.7.5",
|
|
21
|
+
"tsx": "^4.7.0",
|
|
22
|
+
"typescript": "^5.9.3"
|
|
23
|
+
}
|
|
24
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { getMovehat, ModuleAlreadyDeployedError } from "movehat";
|
|
2
|
+
|
|
3
|
+
async function main() {
|
|
4
|
+
console.log("š Deploying Counter contract...\n");
|
|
5
|
+
|
|
6
|
+
// Get the Movehat Runtime Environment
|
|
7
|
+
const mh = await getMovehat();
|
|
8
|
+
|
|
9
|
+
console.log(`ā
Runtime initialized`);
|
|
10
|
+
console.log(` Account: ${mh.account.accountAddress.toString()}`);
|
|
11
|
+
console.log(` Network: ${mh.network.name}`);
|
|
12
|
+
console.log(` RPC: ${mh.network.rpc}\n`);
|
|
13
|
+
|
|
14
|
+
// Deploy (publish) the module
|
|
15
|
+
// Automatically checks if already deployed and suggests --redeploy if needed
|
|
16
|
+
const deployment = await mh.deployContract("counter");
|
|
17
|
+
|
|
18
|
+
console.log(`\nā
Module deployed at: ${deployment.address}::counter`);
|
|
19
|
+
if (deployment.txHash) {
|
|
20
|
+
console.log(` Transaction: ${deployment.txHash}`);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// Get contract instance
|
|
24
|
+
const counter = mh.getContract(deployment.address, "counter");
|
|
25
|
+
|
|
26
|
+
// Initialize the counter
|
|
27
|
+
console.log("\nš Initializing counter...");
|
|
28
|
+
const txResult = await counter.call(mh.account, "init", []);
|
|
29
|
+
|
|
30
|
+
console.log(`ā
Transaction hash: ${txResult.hash}`);
|
|
31
|
+
console.log(`ā
Counter initialized successfully!`);
|
|
32
|
+
|
|
33
|
+
// Verify
|
|
34
|
+
const value = await counter.view<number>("get", [
|
|
35
|
+
mh.account.accountAddress.toString()
|
|
36
|
+
]);
|
|
37
|
+
|
|
38
|
+
console.log(`\nš Initial counter value: ${value}`);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
main().catch((error) => {
|
|
42
|
+
// ModuleAlreadyDeployedError is already logged with full details by deployContract()
|
|
43
|
+
// For other errors, show the message
|
|
44
|
+
if (!(error instanceof ModuleAlreadyDeployedError)) {
|
|
45
|
+
console.error("ā Deployment failed:", error?.message || error);
|
|
46
|
+
}
|
|
47
|
+
process.exit(1);
|
|
48
|
+
});
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { describe, it, before, after } from "mocha";
|
|
2
|
+
import { expect } from "chai";
|
|
3
|
+
import { getMovehat, type MovehatRuntime } from "movehat";
|
|
4
|
+
import type { MoveContract } from "movehat/helpers";
|
|
5
|
+
import { assertTransactionSuccess, snapshot } from "movehat/helpers";
|
|
6
|
+
|
|
7
|
+
describe("Counter Contract", () => {
|
|
8
|
+
let mh: MovehatRuntime;
|
|
9
|
+
let counter: MoveContract;
|
|
10
|
+
|
|
11
|
+
before(async function () {
|
|
12
|
+
this.timeout(30000);
|
|
13
|
+
|
|
14
|
+
// Initialize Movehat Runtime Environment
|
|
15
|
+
mh = await getMovehat();
|
|
16
|
+
|
|
17
|
+
console.log(`\nā
Testing on ${mh.network.name}`);
|
|
18
|
+
console.log(` Account: ${mh.account.accountAddress.toString()}\n`);
|
|
19
|
+
|
|
20
|
+
// Get counter contract instance
|
|
21
|
+
counter = mh.getContract(
|
|
22
|
+
mh.account.accountAddress.toString(),
|
|
23
|
+
"counter"
|
|
24
|
+
);
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
describe("Counter functionality", () => {
|
|
28
|
+
it("should initialize counter", async function () {
|
|
29
|
+
this.timeout(30000);
|
|
30
|
+
|
|
31
|
+
const txResult = await counter.call(mh.account, "init", []);
|
|
32
|
+
assertTransactionSuccess(txResult);
|
|
33
|
+
|
|
34
|
+
const value = await counter.view<number>("get", [
|
|
35
|
+
mh.account.accountAddress.toString()
|
|
36
|
+
]);
|
|
37
|
+
|
|
38
|
+
expect(value).to.equal(0);
|
|
39
|
+
console.log(` ā Counter initialized with value: ${value}`);
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
it("should increment counter", async function () {
|
|
43
|
+
this.timeout(30000);
|
|
44
|
+
|
|
45
|
+
const initialValue = await counter.view<number>("get", [
|
|
46
|
+
mh.account.accountAddress.toString()
|
|
47
|
+
]);
|
|
48
|
+
|
|
49
|
+
const txResult = await counter.call(mh.account, "increment", []);
|
|
50
|
+
assertTransactionSuccess(txResult);
|
|
51
|
+
|
|
52
|
+
const newValue = await counter.view<number>("get", [
|
|
53
|
+
mh.account.accountAddress.toString()
|
|
54
|
+
]);
|
|
55
|
+
|
|
56
|
+
expect(newValue).to.equal(initialValue + 1);
|
|
57
|
+
console.log(` ā Counter incremented: ${initialValue} ā ${newValue}`);
|
|
58
|
+
});
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
// Optional: Create a snapshot after tests for debugging
|
|
62
|
+
// Uncomment to enable
|
|
63
|
+
/*
|
|
64
|
+
after(async function () {
|
|
65
|
+
this.timeout(30000);
|
|
66
|
+
|
|
67
|
+
const snapshotPath = await snapshot({
|
|
68
|
+
name: 'counter-test-final'
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
console.log(`\nšø Snapshot created: ${snapshotPath}`);
|
|
72
|
+
console.log(` Use 'aptos move sim view-resource --session ${snapshotPath}' to inspect state\n`);
|
|
73
|
+
});
|
|
74
|
+
*/
|
|
75
|
+
});
|