A package for deploying AO contracts. Supports both Node.js and web environments.
npm install ao-deploy[![npm version][npm-version-src]][npm-version-href]
[![npm downloads][npm-downloads-src]][npm-downloads-href]
[![JSDocs][jsdocs-src]][jsdocs-href]
[![License][license-src]][license-href]
A package for deploying AO contracts with support for both Node.js and web environments.
> [!Important]
> Mainnet is now the default! Starting from the latest version, ao-deploy uses the mainnet network powered by Hyperbeam by default. If you need to deploy to the legacy network, use the --network legacy, --legacy flag or set network: "legacy" in your configuration.
- Features
- Installation
- Install Locally
- Use without installation
- Optional Dependencies
- Usage
- CLI Examples
- Basic Deployment
- Network Configuration
- Mainnet Network (Default)
- Legacy Network
- Custom Hyperbeam Node
- Browser Wallet
- Advanced Browser Configuration
- Using a Configuration File
- Configuration File
- Advanced Options
- Minify Contract
- Deploy with On-Boot
- Deploy Blueprints
- Build Contracts
- Build to Default Directory
- Build to Custom Directory
- Build Using Configuration File
- API Reference
- deployContract
- Node.js Examples
- Web Example
- Parameters
- deployContracts
- Node.js Example
- Web Example
- Related
- Contributing
- š Build and deploy contracts with ease
- š Cross-platform support
- š Browser wallet support (Wander or other compatible wallet) for secure signing
- š§ Custom LUA_PATH support
- š¦ LuaRocks package support
- āļø Flexible deployment configuration
- š Concurrent deployments with retry options
- š Contract minification and transformation
- š§© Blueprint support
- š ļø CLI and API interfaces
- š Hyperbeam mainnet support
``sh`
npm install ao-deploy --save-dev
pnpm add ao-deploy --save-dev
yarn add ao-deploy --dev
bun add ao-deploy --dev
You can use ao-deploy without installing it locally by using package runners:
Using npx (npm):
`sh`
npx ao-deploy process.lua -n tictactoe -w wallet.json
Using bunx (bun):
`sh`
bunx ao-deploy process.lua -n tictactoe -w wallet.json
Using pnpm dlx (pnpm):
`sh`
pnpm dlx ao-deploy process.lua -n tictactoe -w wallet.json
Using yarn dlx (yarn):
`sh`
yarn dlx ao-deploy process.lua -n tictactoe -w wallet.json
If you plan to use the --minify option, you'll need to install lua-format:
`sh`
npm install lua-format --save-dev # npm
pnpm add lua-format --save-dev # pnpm
yarn add lua-format --dev # yarn
bun add lua-format --dev # bun
> [!Note]
> The CLI is only available in Node.js environments. For web environments, use the API directly.
`sh
Usage: ao-deploy [options]
Deploy AO contracts using a CLI.
Arguments:
contractOrConfigPath Path to the main contract file or deployment configuration.
Options:
-V, --version output the version number
-n, --name [name] Specify the process name. (default: "default")
-w, --wallet [wallet] Path to the wallet JWK file. (Autogenerated if not passed)
--use-browser-wallet Use browser wallet (Wander or other compatible wallet) for signing transactions.
--browser [browser] Browser to use for signing transactions. (default: "system default")
--browser-profile [profile] Browser profile to use for signing transactions.
-l, --lua-path [luaPath] Specify the Lua modules path seperated by semicolon.
-d, --deploy [deploy] List of deployment configuration names, separated by commas.
-b, --build [build] List of deployment configuration names, separated by commas.
-s, --scheduler [scheduler] Scheduler to be used for the process.
-m, --module [module] Module source for spawning the process.
-c, --cron [interval] Cron interval for the process (e.g. 1-minute, 5-minutes).
--cron-action [cronAction] Cron tag action for the process. (default: "Cron")
-t, --tags [tags...] Additional tags for spawning the process.
-p, --process-id [processId] Specify process Id of existing process.
--build-only Bundle the contract into a single file and store it in the process-dist directory.
--out-dir [outDir] Used with --build-only to output the single bundle contract file to a specified directory.
--gateway-url [url] Custom Gateway URL to connect to. (default: "https://arweave.net")
--cu-url [url] Custom Compute Unit (CU) URL to connect to. (default: "https://cu.ao-testnet.xyz")
--mu-url [url] Custom Messenger Unit (MU) URL to connect to. (default: "https://mu.ao-testnet.xyz")
--hb-url [url] Hyperbeam Node URL to connect to. (default: "https://push.forward.computer")
--concurrency [limit] Concurrency limit for deploying multiple processes. (default: 5)
--sqlite Use sqlite aos module when spawning new process.
--retry-count [count] Number of retries for deploying contract. (default: 3)
--retry-delay [delay] Delay between retries in milliseconds. (default: 1000)
--minify Reduce the size of the contract before deployment. (default: false)
--on-boot Load contract when process is spawned. (default: false)
--blueprints [blueprints...] Blueprints to use for the contract.
--force-spawn Force spawning a new process without checking for existing ones. (default: false)
--network [network] Network to use for deployment. (choices: "mainnet", "legacy", default: "mainnet")
--legacy Deploy to legacy network. (default: false)
-h, --help display help for command
`
#### Basic Deployment
`sh`
ao-deploy process.lua -n tictactoe -w wallet.json --tags name1:value1 name2:value2
> [!Note]
> By default, deployments use the mainnet network powered by Hyperbeam. To deploy to the legacy network, use the --network legacy flag.
#### Network Configuration
##### Mainnet Network (Default)
By default, ao-deploy uses the mainnet network powered by Hyperbeam:
`sh`
ao-deploy process.lua -n tictactoe -w wallet.jsonor explicitly specify mainnet
ao-deploy process.lua -n tictactoe -w wallet.json --network mainnet
##### Legacy Network
To deploy to the legacy AO network:
`sh`
ao-deploy process.lua -n tictactoe -w wallet.json --network legacy
Or use the --legacy flag:
`sh`
ao-deploy process.lua -n tictactoe -w wallet.json --legacy
##### Custom Hyperbeam Node
You can specify a custom Hyperbeam node URL for mainnet deployments:
`sh`
ao-deploy process.lua -n tictactoe -w wallet.json --hb-url https://custom-hyperbeam-node.com
#### Advanced Options
##### Minify Contract
> [!Note]
> Make sure to install lua-format as mentioned in Optional Dependencies section.
`sh`
ao-deploy process.lua -n tictactoe -w wallet.json --tags name1:value1 name2:value2 --minify
##### Deploy with On-Boot
`sh`
ao-deploy process.lua -n tictactoe -w wallet.json --tags name1:value1 name2:value2 --on-boot
##### Deploy Blueprints
`sh`
ao-deploy -n tictactoe -w wallet.json --blueprints arns token
#### Browser Wallet
> [!Important]
> When deploying multiple contracts with browser wallets, the first browser configuration found in the deployment configs will be used for all browser deployments. This ensures a single browser session is shared across all deployments.
Use your browser wallet for secure transaction signing:
`sh`
ao-deploy process.lua --use-browser-wallet -n MyProcess
##### Advanced Browser Configuration
`shUse specific browser
ao-deploy process.lua --use-browser-wallet --browser firefox -n MyProcess
##### Using a Configuration File
`ts
export default defineConfig({
main: {
name: "my-process",
contractPath: "./src/main.lua",
wallet: "browser", // Use browser wallet for signing
browserConfig: {
browser: "chrome", // Optional: specify browser (chrome, firefox, edge, brave, safari, opera, zen, vivaldi)
browserProfile: "Profile 1" // Optional: specify browser profile
}
},
});
`Then deploy with:
`sh
ao-deploy ao.config.ts
`#### Configuration File
> [!Note]
> Configuration files are only supported in Node.js environments. For web environments, use the API directly with individual contract configurations.
Deploy multiple contracts using a configuration file:
`ts
// aod.config.ts
import { defineConfig } from "ao-deploy";const wallet = "wallet.json";
const luaPath = "./?.lua;./src/?.lua";
const config = defineConfig({
contract_1: {
luaPath,
name:
contract-1,
contractPath: "contract-1.lua",
wallet,
minify: true, // Minify the contract before deployment
network: "mainnet" // Deploy to mainnet (default)
},
contract_2: {
luaPath,
name: contract-2,
contractPath: "contract-2.lua",
wallet: "browser", // Use browser wallet
browserConfig: {
browser: "brave", // Use Brave browser
browserProfile: "Work" // Use profile 1
},
network: "legacy", // Deploy to legacy network
services: {
cuUrl: "https://cu.ao-testnet.xyz",
muUrl: "https://mu.ao-testnet.xyz"
},
// Custom source transformer function
contractTransformer: (source) => {
// Example: Remove all comments from the source code
return source.replace(/\s--.\n/g, "");
}
},
contract_3: {
luaPath,
name: contract-3,
contractPath: "contract-3.lua",
wallet,
network: "mainnet",
services: {
hbUrl: "https://push.forward.computer" // Custom Hyperbeam node
}
}
});export default config;
`Deploy all specified contracts:
`sh
ao-deploy aod.config.ts
`Deploy specific contracts:
`sh
ao-deploy aod.config.ts --deploy=contract_1,contract_3
`#### Build Contracts
> [!Note]
> Contract building is only available in Node.js environments. For web environments, you need to bundle your contracts using your own build process.
##### Build to Default Directory
`sh
aod src/process.lua -n my-process --build-only
`##### Build to Custom Directory
`sh
aod src/process.lua -n my-process --build-only --out-dir
aod src/process.lua -n my-process --build-only --out-dir ./dist
`##### Build Using Configuration File
> [!Note]
> Configuration-based building is only available in Node.js environments.
To Build contracts using config, take a look at below provided example
Here is an example using a deployment configuration:
`ts
// aod.config.ts
import { defineConfig } from "ao-deploy";const luaPath = "./?.lua;./src/?.lua";
const config = defineConfig({
contract_1: {
luaPath,
name:
contract-1,
contractPath: "contract-1.lua",
outDir: "./dist"
},
contract_2: {
luaPath,
name: contract-2,
contractPath: "contract-2.lua",
outDir: "./dist"
},
contract_3: {
luaPath,
name: contract-3,
contractPath: "contract-3.lua",
outDir: "./dist"
}
});export default config;
`Build all specified contracts:
`sh
ao-deploy aod.config.ts --build-only
`Build specific contracts:
`sh
ao-deploy aod.config.ts --build=contract_1,contract_3 --build-only
`> [!Note]
> A wallet is generated and saved if not passed.
Retrieve the generated wallet path:
`sh
node -e "const path = require('path'); const os = require('os'); console.log(path.resolve(os.homedir(), '.aos.json'));"
`$3
#### deployContract
Deploy a single contract using the
deployContract function.##### Basic Deployment (Node.js)
`ts
import { deployContract } from "ao-deploy";async function main() {
try {
const { messageId, processId } = await deployContract({
name: "demo",
wallet: "wallet.json",
contractPath: "process.lua",
tags: [{ name: "Custom", value: "Tag" }],
retry: {
count: 10,
delay: 3000
}
});
const processUrl =
https://aolink.arweave.net/#/entity/${processId};
console.log(Deployed Process: ${processUrl});
if (messageId) {
const messageUrl = https://aolink.arweave.net/#/message/${messageId};
console.log(Deployment Message: ${messageUrl});
}
} catch (error: any) {
console.log(
Deployment failed!: ${error?.message ?? "Failed to deploy contract!"}\n
);
}
}main();
`##### Mainnet Deployment with Custom Hyperbeam Node
`ts
import { deployContract } from "ao-deploy";async function main() {
try {
const { messageId, processId } = await deployContract({
name: "demo",
wallet: "wallet.json",
contractPath: "process.lua",
network: "mainnet", // Use mainnet (default)
services: {
hbUrl: "https://push.forward.computer" // Custom Hyperbeam node (optional)
},
tags: [{ name: "Custom", value: "Tag" }]
});
const processUrl =
https://aolink.arweave.net/#/entity/${processId};
console.log(Deployed Process: ${processUrl});
} catch (error: any) {
console.log(
Deployment failed!: ${error?.message ?? "Failed to deploy contract!"}\n
);
}
}main();
`##### Legacy Network Deployment
`ts
import { deployContract } from "ao-deploy";async function main() {
try {
const { messageId, processId } = await deployContract({
name: "demo",
wallet: "wallet.json",
contractPath: "process.lua",
network: "legacy", // Use legacy network
services: {
cuUrl: "https://cu.ao-testnet.xyz",
muUrl: "https://mu.ao-testnet.xyz",
gatewayUrl: "https://arweave.net"
},
tags: [{ name: "Custom", value: "Tag" }]
});
const processUrl =
https://aolink.arweave.net/#/entity/${processId};
console.log(Deployed Process: ${processUrl});
} catch (error: any) {
console.log(
Deployment failed!: ${error?.message ?? "Failed to deploy contract!"}\n
);
}
}main();
`##### Browser Wallet (Node.js)
`ts
import { deployContract } from "ao-deploy";async function main() {
try {
const { messageId, processId } = await deployContract({
name: "demo",
wallet: "browser", // Use browser wallet
contractPath: "process.lua",
browserConfig: {
browser: "chrome", // Optional: specify browser
browserProfile: "Profile 1" // Optional: specify browser profile
},
tags: [{ name: "Custom", value: "Tag" }],
retry: {
count: 10,
delay: 3000
}
});
const processUrl =
https://aolink.arweave.net/#/entity/${processId};
console.log(Deployed Process: ${processUrl});
if (messageId) {
const messageUrl = https://aolink.arweave.net/#/message/${messageId};
console.log(Deployment Message: ${messageUrl});
}
} catch (error: any) {
console.log(
Deployment failed!: ${error?.message ?? "Failed to deploy contract!"}\n
);
}
}main();
`##### Web Deployment
> [!Note]
> For web/browser environments, you need to provide the contract source directly since file system access is not available.
`ts
import { deployContract } from "ao-deploy/web";async function main() {
try {
// Contract source as a string (loaded from your build process, CDN, etc.)
// Simple AO process that responds to ping messages with "pong"
const contractSrc =
; const { messageId, processId } = await deployContract({
name: "web-demo",
contractSrc: contractSrc,
network: "mainnet", // Use mainnet (default)
tags: [{ name: "Environment", value: "Web" }],
retry: {
count: 5,
delay: 2000
}
});
const processUrl =
https://aolink.arweave.net/#/entity/${processId};
console.log(Deployed Process: ${processUrl});
if (messageId) {
const messageUrl = https://aolink.arweave.net/#/message/${messageId};
console.log(Deployment Message: ${messageUrl});
}
} catch (error: any) {
console.log(
Deployment failed!: ${error?.message ?? "Failed to deploy contract!"}\n
);
}
}main();
`##### Parameters Reference
The
deployContract function accepts the following parameters within the DeployArgs object:Common Parameters (Node.js & Web):
-
name (optional): The process name to spawn. Defaults to "default".
- contractSrc (optional): The contract source code as a string. Required for web environments.
- module (optional): The module source to use. Defaults to fetching from the AOS's GitHub repository.
- scheduler (optional): The scheduler to use for the process. Defaults to n_XZJhUnmldNFo4dhajoPZWhBXuJk-OcQr5JQ49c4Zo for mainnet and _GQ33BkPtZrqxA84vM8Zk-N2aO0toNNu_C-l-rawrBA for legacy.
- tags (optional): Additional tags to use for spawning the process.
- cron (optional): The cron interval for the process, e.g., "1-minute", "5-minutes". Use format interval-(second, seconds, minute, minutes, hour, hours, day, days, month, months, year, years, block, blocks, Second, Seconds, Minute, Minutes, Hour, Hours, Day, Days, Month, Months, Year, Years, Block, Blocks)
- cronAction (optional): The cron tag action to use for the process. Defaults to "Cron".
- retry (optional): Retry options with count and delay properties. By default, it will retry up to 3 times with a 1000 milliseconds delay between attempts.
- processId (optional): The process id of existing process.
- minify (optional): Reduce the size of the contract before deployment.
- contractTransformer (optional): Custom function to transform source code before deployment.
- onBoot (optional): Load contract when process is spawned. (default: false)
- silent (optional): Disable logging to console. (default: false)
- blueprints (optional): Blueprints to use for the contract.
- forceSpawn (optional): Force spawning a new process without checking for existing ones. (default: false)
- network (optional): Network to use for deployment. Options: "mainnet" (default) or "legacy".
- services (optional): Configuration for AO services.
- gatewayUrl (optional): Gateway URL. Defaults to https://arweave.net.
- cuUrl (optional): Compute Unit URL (legacy network only). Defaults to https://cu.ao-testnet.xyz.
- muUrl (optional): Messenger Unit URL (legacy network only). Defaults to https://mu.ao-testnet.xyz.
- hbUrl (optional): Hyperbeam Node URL (mainnet only). Defaults to https://push.forward.computer.Node.js Only Parameters:
-
contractPath: The path to the contract's main file. Required for Node.js when contractSrc is not provided.
- wallet (optional): The wallet path, JWK itself, or "browser" to use browser wallet (Autogenerated if not passed).
- luaPath (optional): The path to the Lua modules seperated by semicolon.
- browserConfig (optional): Browser configuration for browser wallet usage.
- browser (optional): Browser to use ("chrome", "firefox", "edge", "brave", "safari", "opera", "zen", "vivaldi", or custom string).
- browserProfile (optional): Browser profile to use for signing transactions.> [!Note]
> In web environments, you must provide
contractSrc directly as a string. The contractPath, wallet, and luaPath parameters are not supported in web environments.#### deployContracts
Deploy multiple contracts concurrently using the
deployContracts function.##### Multiple Contracts (Node.js)
`ts
import { deployContracts } from "ao-deploy";async function main() {
try {
const results = await deployContracts(
[
{
name: "demo1",
wallet: "wallet.json",
contractPath: "process1.lua",
tags: [{ name: "Custom", value: "Tag" }],
retry: {
count: 10,
delay: 3000
},
network: "mainnet"
},
{
name: "demo2",
wallet: "wallet.json",
contractPath: "process2.lua",
tags: [{ name: "Custom", value: "Tag" }],
retry: {
count: 10,
delay: 3000
},
network: "legacy"
}
],
2
);
results.forEach((result, idx) => {
if (result.status === "fulfilled") {
const { processId, messageId } = result.value;
const processUrl =
https://aolink.arweave.net/#/entity/${processId};
console.log(Deployed Process: ${processUrl});
if (messageId) {
const messageUrl = https://aolink.arweave.net/#/message/${messageId};
console.log(Deployment Message: ${messageUrl});
}
} else {
console.log(Failed to deploy contract!: ${result.reason}\n);
}
});
} catch (error: any) {
console.log(
Deployment failed!: ${error?.message ?? "Failed to deploy contract!"}\n
);
}
}main();
`##### Multiple Contracts (Web)
> [!Note]
> For web/browser environments, you need to provide the contract source directly since file system access is not available.
`ts
import { deployContracts } from "ao-deploy/web";async function main() {
try {
const contract1Src =
Handlers.add("increment", function(msg)
count = count + 1
return ao.send({
Action = "Count",
Target = msg.From,
Data = tostring(count)
})
end)
;
const contract2Src =
-- Simple echo process
Handlers.add("echo", function(msg)
return ao.send({
Action = "Echo",
Target = msg.From,
Data = msg.Data or "No data provided"
})
end)
;
const results = await deployContracts(
[
{
name: "web-demo1",
contractSrc: contract1Src,
tags: [{ name: "Environment", value: "Web" }],
retry: {
count: 5,
delay: 2000
}
},
{
name: "web-demo2",
contractSrc: contract2Src,
tags: [{ name: "Environment", value: "Web" }],
retry: {
count: 5,
delay: 2000
}
}
],
2
);
results.forEach((result, idx) => {
if (result.status === "fulfilled") {
const { processId, messageId } = result.value;
const processUrl = https://aolink.arweave.net/#/entity/${processId};Deployed Process ${idx + 1}: ${processUrl}
console.log();https://aolink.arweave.net/#/message/${messageId}
if (messageId) {
const messageUrl = ;Deployment Message: ${messageUrl}
console.log();Failed to deploy contract ${idx + 1}!: ${result.reason}\n
}
} else {
console.log();Deployment failed!: ${error?.message ?? "Failed to deploy contract!"}\n
}
});
} catch (error: any) {
console.log(
);
}
}
main();
``
- create-ao-contract: A CLI tool for scaffolding AO contracts.
- node-arweave-wallet: A library for interacting with Arweave browser wallets.
š¤ Pawan Paudel
- Github: @pawanpaudel93
Contributions, issues and feature requests are welcome! \ Feel free to check issues page.
Give a āļø if this project helped you!
Copyright Ā© 2024 Pawan Paudel.
[npm-version-src]: https://img.shields.io/npm/v/ao-deploy?style=flat&colorA=080f12&colorB=1fa669
[npm-version-href]: https://npmjs.com/package/ao-deploy
[npm-downloads-src]: https://img.shields.io/npm/dm/ao-deploy?style=flat&colorA=080f12&colorB=1fa669
[npm-downloads-href]: https://npmjs.com/package/ao-deploy
[license-src]: https://img.shields.io/github/license/pawanpaudel93/ao-deploy.svg?style=flat&colorA=080f12&colorB=1fa669
[license-href]: https://github.com/pawanpaudel93/ao-deploy/blob/main/LICENSE
[jsdocs-src]: https://img.shields.io/badge/jsdocs-reference-080f12?style=flat&colorA=080f12&colorB=1fa669
[jsdocs-href]: https://www.jsdocs.io/package/ao-deploy