Refactor nla cli app
This commit is contained in:
parent
0d99b7521b
commit
0d5abc519c
|
|
@ -61,12 +61,12 @@ bun test tests/nlaOracle.test.ts
|
|||
```bash
|
||||
# Get Sepolia ETH from faucet first
|
||||
export DEPLOYER_PRIVATE_KEY=0x...
|
||||
bun run setups/deploy.ts --network sepolia --rpc-url https://sepolia.infura.io/v3/YOUR-KEY
|
||||
bun run cli/server/deploy.ts --network sepolia --rpc-url https://sepolia.infura.io/v3/YOUR-KEY
|
||||
|
||||
# Start oracle
|
||||
export ORACLE_PRIVATE_KEY=0x...
|
||||
export OPENAI_API_KEY=sk-...
|
||||
bun run setups/oracle.ts sepolia
|
||||
bun run cli/server/oracle.ts sepolia
|
||||
```
|
||||
|
||||
## Need Help?
|
||||
|
|
|
|||
157
cli/README.md
157
cli/README.md
|
|
@ -2,19 +2,72 @@
|
|||
|
||||
User-friendly command-line tools to interact with Natural Language Agreement escrows.
|
||||
|
||||
## Installation
|
||||
|
||||
First, install the CLI globally:
|
||||
|
||||
```bash
|
||||
bun link
|
||||
```
|
||||
|
||||
Now you can use `nla` from anywhere in your terminal!
|
||||
|
||||
## Unified CLI
|
||||
|
||||
The `nla` command provides a unified interface for all escrow operations:
|
||||
|
||||
```bash
|
||||
nla <command> [options]
|
||||
```
|
||||
|
||||
**Available Commands:**
|
||||
- `dev` - Start local development environment (Anvil + Deploy + Oracle)
|
||||
- `escrow:create` - Create a new escrow with natural language demand
|
||||
- `escrow:fulfill` - Fulfill an existing escrow
|
||||
- `escrow:collect` - Collect an approved escrow
|
||||
- `escrow:status` - Check the status of an escrow
|
||||
- `help` - Display help message
|
||||
|
||||
## Quick Start
|
||||
|
||||
### Start Development Environment
|
||||
|
||||
The easiest way to get started is with the `dev` command:
|
||||
|
||||
```bash
|
||||
nla dev
|
||||
```
|
||||
|
||||
This will:
|
||||
1. Start Anvil (local Ethereum node)
|
||||
2. Deploy all contracts
|
||||
3. Deploy mock ERC20 tokens and distribute them
|
||||
4. Start the oracle listening for arbitration requests
|
||||
|
||||
**Note:** Keep this terminal open - it runs the oracle. Open a new terminal for creating escrows.
|
||||
|
||||
### Prerequisites
|
||||
|
||||
Before running `nla dev`, set your OpenAI API key:
|
||||
|
||||
```bash
|
||||
export OPENAI_API_KEY=sk-your-key-here
|
||||
```
|
||||
|
||||
For creating escrows, also set:
|
||||
|
||||
```bash
|
||||
export PRIVATE_KEY=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80
|
||||
```
|
||||
|
||||
### 1. Create an Escrow
|
||||
|
||||
Create an escrow with a natural language demand:
|
||||
|
||||
```bash
|
||||
bun run escrow:create \
|
||||
nla escrow:create \
|
||||
--demand "The sky is blue" \
|
||||
--amount 10 \
|
||||
--token <TOKEN_ADDRESS_FROM_DEPLOYMENT> \
|
||||
--oracle 0x70997970C51812dc3A010C7d01b50e0d17dc79C8 \
|
||||
--private-key 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80
|
||||
--token 0xa513e6e4b8f2a923d98304ec87f64353c4d5c853 \
|
||||
--oracle 0x70997970C51812dc3A010C7d01b50e0d17dc79C8
|
||||
```
|
||||
|
||||
> **Note:** Get the token address from the deployment output. The deployment creates 3 test tokens (TSTA, TSTB, TSTC) and distributes 10,000 of each to all test accounts.
|
||||
|
|
@ -23,31 +76,42 @@ bun run escrow:create \
|
|||
|
||||
### 2. Fulfill the Escrow
|
||||
|
||||
Someone else (or you with a different key) can fulfill it:
|
||||
Switch to a different account:
|
||||
|
||||
```bash
|
||||
bun run escrow:fulfill \
|
||||
export PRIVATE_KEY=0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d
|
||||
|
||||
nla escrow:fulfill \
|
||||
--escrow-uid 0x... \
|
||||
--fulfillment "The sky appears blue today" \
|
||||
--oracle 0x70997970C51812dc3A010C7d01b50e0d17dc79C8 \
|
||||
--private-key 0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d
|
||||
--oracle 0x70997970C51812dc3A010C7d01b50e0d17dc79C8
|
||||
```
|
||||
|
||||
**Save the Fulfillment UID** from the output!
|
||||
|
||||
### 3. Wait for Oracle
|
||||
### 3. Check Status
|
||||
|
||||
The oracle will automatically arbitrate the fulfillment (a few seconds).
|
||||
Monitor the escrow and arbitration progress:
|
||||
|
||||
```bash
|
||||
nla escrow:status \
|
||||
--escrow-uid 0x... \
|
||||
--deployment ./cli/deployments/localhost.json
|
||||
```
|
||||
|
||||
This will show:
|
||||
- Escrow details (demand, oracle, recipient)
|
||||
- All fulfillments
|
||||
- Arbitration decisions (approved/rejected)
|
||||
|
||||
### 4. Collect the Escrow
|
||||
|
||||
If approved, collect the escrowed tokens:
|
||||
|
||||
```bash
|
||||
bun run escrow:collect \
|
||||
nla escrow:collect \
|
||||
--escrow-uid 0x... \
|
||||
--fulfillment-uid 0x... \
|
||||
--private-key 0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d
|
||||
--fulfillment-uid 0x...
|
||||
```
|
||||
|
||||
## Commands
|
||||
|
|
@ -55,15 +119,15 @@ bun run escrow:collect \
|
|||
### Create Escrow
|
||||
|
||||
```bash
|
||||
bun run escrow:create [options]
|
||||
nla escrow:create [options]
|
||||
|
||||
Options:
|
||||
--demand <text> Natural language demand (required)
|
||||
--amount <number> Amount of tokens to escrow (required)
|
||||
--token <address> ERC20 token address (required)
|
||||
--oracle <address> Oracle address (required)
|
||||
--private-key <key> Your private key (required)
|
||||
--deployment <path> Deployment file (default: ./deployments/localhost.json)
|
||||
--private-key <key> Your private key (or set PRIVATE_KEY env var)
|
||||
--deployment <path> Deployment file (default: ./cli/deployments/localhost.json)
|
||||
--rpc-url <url> RPC URL (default: from deployment)
|
||||
--help, -h Show help
|
||||
```
|
||||
|
|
@ -71,14 +135,14 @@ Options:
|
|||
### Fulfill Escrow
|
||||
|
||||
```bash
|
||||
bun run escrow:fulfill [options]
|
||||
nla escrow:fulfill [options]
|
||||
|
||||
Options:
|
||||
--escrow-uid <uid> Escrow UID to fulfill (required)
|
||||
--fulfillment <text> Your fulfillment text (required)
|
||||
--oracle <address> Oracle address (required)
|
||||
--private-key <key> Your private key (required)
|
||||
--deployment <path> Deployment file (default: ./deployments/localhost.json)
|
||||
--private-key <key> Your private key (or set PRIVATE_KEY env var)
|
||||
--deployment <path> Deployment file (default: ./cli/deployments/localhost.json)
|
||||
--rpc-url <url> RPC URL (default: from deployment)
|
||||
--help, -h Show help
|
||||
```
|
||||
|
|
@ -86,13 +150,25 @@ Options:
|
|||
### Collect Escrow
|
||||
|
||||
```bash
|
||||
bun run escrow:collect [options]
|
||||
nla escrow:collect [options]
|
||||
|
||||
Options:
|
||||
--escrow-uid <uid> Escrow UID (required)
|
||||
--fulfillment-uid <uid> Approved fulfillment UID (required)
|
||||
--private-key <key> Your private key (required)
|
||||
--deployment <path> Deployment file (default: ./deployments/localhost.json)
|
||||
--private-key <key> Your private key (or set PRIVATE_KEY env var)
|
||||
--deployment <path> Deployment file (default: ./cli/deployments/localhost.json)
|
||||
--rpc-url <url> RPC URL (default: from deployment)
|
||||
--help, -h Show help
|
||||
```
|
||||
|
||||
### Check Status
|
||||
|
||||
```bash
|
||||
nla escrow:status [options]
|
||||
|
||||
Options:
|
||||
--escrow-uid <uid> Escrow UID to check (required)
|
||||
--deployment <path> Deployment file (default: ./cli/deployments/localhost.json)
|
||||
--rpc-url <url> RPC URL (default: from deployment)
|
||||
--help, -h Show help
|
||||
```
|
||||
|
|
@ -127,37 +203,44 @@ export OPENAI_API_KEY=sk-... # Required for oracle
|
|||
## Example Workflow
|
||||
|
||||
```bash
|
||||
# Terminal 1: Start the system
|
||||
bun run setup
|
||||
# Terminal 1: Start the development environment
|
||||
nla dev
|
||||
|
||||
# Note the token addresses from the deployment output!
|
||||
# Example: Token A (TSTA): 0x5FbDB...
|
||||
# Example: Token A (TSTA): 0xa513e6e4b8f2a923d98304ec87f64353c4d5c853
|
||||
|
||||
# Terminal 2: Create an escrow (as Alice)
|
||||
# Terminal 2: Set your private key and create an escrow (as Alice)
|
||||
export PRIVATE_KEY=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80
|
||||
bun run escrow:create \
|
||||
|
||||
nla escrow:create \
|
||||
--demand "Deliver package by Friday" \
|
||||
--amount 100 \
|
||||
--token 0x5FbDB... \ # Use Token A address from deployment
|
||||
--token 0xa513e6e4b8f2a923d98304ec87f64353c4d5c853 \
|
||||
--oracle 0x70997970C51812dc3A010C7d01b50e0d17dc79C8
|
||||
|
||||
# Save the escrow UID, e.g.: 0x1234...
|
||||
# Save the escrow UID, e.g.: 0xd9e1402e96c2f7a64e60bf53a45445f7254e9b72389f6ede25181bff542d7b65
|
||||
|
||||
# Terminal 2: Fulfill the escrow (as Bob)
|
||||
export PRIVATE_KEY=0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d
|
||||
bun run escrow:fulfill \
|
||||
--escrow-uid 0x1234... \
|
||||
|
||||
nla escrow:fulfill \
|
||||
--escrow-uid 0xd9e1402e96c2f7a64e60bf53a45445f7254e9b72389f6ede25181bff542d7b65 \
|
||||
--fulfillment "Package delivered on Thursday" \
|
||||
--oracle 0x70997970C51812dc3A010C7d01b50e0d17dc79C8
|
||||
|
||||
# Save the fulfillment UID, e.g.: 0x5678...
|
||||
# Save the fulfillment UID, e.g.: 0xd124b274d5fb87e3d63b38fd2f6158730b73b53166898aa692b15f5a44178809
|
||||
|
||||
# Watch Terminal 1 - oracle will arbitrate automatically!
|
||||
|
||||
# Terminal 2: Check the status
|
||||
nla escrow:status \
|
||||
--escrow-uid 0xd9e1402e96c2f7a64e60bf53a45445f7254e9b72389f6ede25181bff542d7b65 \
|
||||
--deployment ./cli/deployments/localhost.json
|
||||
|
||||
# Terminal 2: Collect the escrow (as Bob)
|
||||
bun run escrow:collect \
|
||||
--escrow-uid 0x1234... \
|
||||
--fulfillment-uid 0x5678...
|
||||
nla escrow:collect \
|
||||
--escrow-uid 0xd9e1402e96c2f7a64e60bf53a45445f7254e9b72389f6ede25181bff542d7b65 \
|
||||
--fulfillment-uid 0xd124b274d5fb87e3d63b38fd2f6158730b73b53166898aa692b15f5a44178809
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ Options:
|
|||
--escrow-uid <uid> Escrow UID to collect (required)
|
||||
--fulfillment-uid <uid> Fulfillment UID that was approved (required)
|
||||
--private-key <key> Your private key (required)
|
||||
--deployment <path> Path to deployment file (default: ./deployments/localhost.json)
|
||||
--deployment <path> Path to deployment file (default: ./cli/deployments/localhost.json)
|
||||
--rpc-url <url> RPC URL (default: from deployment file)
|
||||
--help, -h Display this help message
|
||||
|
||||
|
|
@ -79,7 +79,7 @@ async function main() {
|
|||
const escrowUid = args["escrow-uid"];
|
||||
const fulfillmentUid = args["fulfillment-uid"];
|
||||
const privateKey = args["private-key"] || process.env.PRIVATE_KEY;
|
||||
const deploymentPath = args.deployment || "./deployments/localhost.json";
|
||||
const deploymentPath = args.deployment || "./cli/deployments/localhost.json";
|
||||
|
||||
// Validate required parameters
|
||||
if (!escrowUid) {
|
||||
|
|
@ -117,7 +117,7 @@ async function main() {
|
|||
console.log(` 🌐 RPC URL: ${rpcUrl}\n`);
|
||||
|
||||
// Import alkahest client
|
||||
const { makeClient } = await import("../../alkahest/sdks/ts/src/index.ts");
|
||||
const { makeClient } = await import("../../../alkahest/sdks/ts/src/index.ts");
|
||||
|
||||
// Create account and wallet
|
||||
const account = privateKeyToAccount(privateKey as `0x${string}`);
|
||||
|
|
@ -29,7 +29,7 @@ Options:
|
|||
--token <address> ERC20 token address (required)
|
||||
--oracle <address> Oracle address that will arbitrate (required)
|
||||
--private-key <key> Your private key (required)
|
||||
--deployment <path> Path to deployment file (default: ./deployments/localhost.json)
|
||||
--deployment <path> Path to deployment file (default: ./cli/deployments/localhost.json)
|
||||
--rpc-url <url> RPC URL (default: from deployment file)
|
||||
--help, -h Display this help message
|
||||
|
||||
|
|
@ -88,7 +88,7 @@ async function main() {
|
|||
const tokenAddress = args.token;
|
||||
const oracleAddress = args.oracle;
|
||||
const privateKey = args["private-key"] || process.env.PRIVATE_KEY;
|
||||
const deploymentPath = args.deployment || "./deployments/localhost.json";
|
||||
const deploymentPath = args.deployment || "./cli/deployments/localhost.json";
|
||||
|
||||
// Validate required parameters
|
||||
if (!demand) {
|
||||
|
|
@ -140,8 +140,8 @@ async function main() {
|
|||
console.log(` 🌐 RPC URL: ${rpcUrl}\n`);
|
||||
|
||||
// Import alkahest client
|
||||
const { makeClient } = await import("../../alkahest/sdks/ts/src/index.ts");
|
||||
const { makeLLMClient } = await import("../clients/nla.ts");
|
||||
const { makeClient } = await import("../../../alkahest/sdks/ts/src/index.ts");
|
||||
const { makeLLMClient } = await import("../../clients/nla.ts");
|
||||
|
||||
// Create account and wallet
|
||||
const account = privateKeyToAccount(privateKey as `0x${string}`);
|
||||
|
|
@ -180,7 +180,7 @@ async function main() {
|
|||
});
|
||||
|
||||
// Check token balance
|
||||
const MockERC20Permit = await import("../../alkahest/sdks/ts/tests/fixtures/MockERC20Permit.json");
|
||||
const MockERC20Permit = await import("../../../alkahest/sdks/ts/tests/fixtures/MockERC20Permit.json");
|
||||
const tokenBalance = await walletClient.readContract({
|
||||
address: tokenAddress as `0x${string}`,
|
||||
abi: MockERC20Permit.abi,
|
||||
|
|
@ -28,7 +28,7 @@ Options:
|
|||
--fulfillment <text> Your fulfillment text (required)
|
||||
--oracle <address> Oracle address that will arbitrate (required)
|
||||
--private-key <key> Your private key (required)
|
||||
--deployment <path> Path to deployment file (default: ./deployments/localhost.json)
|
||||
--deployment <path> Path to deployment file (default: ./cli/deployments/localhost.json)
|
||||
--rpc-url <url> RPC URL (default: from deployment file)
|
||||
--help, -h Display this help message
|
||||
|
||||
|
|
@ -84,7 +84,7 @@ async function main() {
|
|||
const fulfillment = args.fulfillment;
|
||||
const oracleAddress = args.oracle;
|
||||
const privateKey = args["private-key"] || process.env.PRIVATE_KEY;
|
||||
const deploymentPath = args.deployment || "./deployments/localhost.json";
|
||||
const deploymentPath = args.deployment || "./cli/deployments/localhost.json";
|
||||
|
||||
// Validate required parameters
|
||||
if (!escrowUid) {
|
||||
|
|
@ -129,7 +129,7 @@ async function main() {
|
|||
console.log(` 🌐 RPC URL: ${rpcUrl}\n`);
|
||||
|
||||
// Import alkahest client
|
||||
const { makeClient } = await import("../../alkahest/sdks/ts/src/index.ts");
|
||||
const { makeClient } = await import("../../../alkahest/sdks/ts/src/index.ts");
|
||||
|
||||
// Create account and wallet
|
||||
const account = privateKeyToAccount(privateKey as `0x${string}`);
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
"network": "localhost",
|
||||
"chainId": 31337,
|
||||
"rpcUrl": "http://localhost:8545",
|
||||
"deployedAt": "2025-12-12T05:50:31.992Z",
|
||||
"deployedAt": "2025-12-12T09:19:50.255Z",
|
||||
"deployer": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266",
|
||||
"addresses": {
|
||||
"easSchemaRegistry": "0x5fbdb2315678afecb367f032d93f642f64180aa3",
|
||||
|
|
@ -0,0 +1,315 @@
|
|||
#!/usr/bin/env bun
|
||||
import { parseArgs } from "util";
|
||||
|
||||
// Helper function to display usage
|
||||
function displayHelp() {
|
||||
console.log(`
|
||||
Natural Language Agreement CLI
|
||||
|
||||
Usage:
|
||||
nla <command> [options]
|
||||
|
||||
Commands:
|
||||
dev Start local development environment (Anvil + Deploy + Oracle)
|
||||
escrow:create Create a new escrow with natural language demand
|
||||
escrow:fulfill Fulfill an existing escrow
|
||||
escrow:collect Collect an approved escrow
|
||||
escrow:status Check the status of an escrow
|
||||
help Display this help message
|
||||
|
||||
Options (vary by command):
|
||||
--demand <text> Natural language demand (create)
|
||||
--amount <number> Amount of tokens to escrow (create)
|
||||
--token <address> ERC20 token contract address (create)
|
||||
--oracle <address> Oracle address (create, fulfill)
|
||||
--escrow-uid <uid> Escrow UID (fulfill, collect, status)
|
||||
--fulfillment <text> Fulfillment text (fulfill)
|
||||
--fulfillment-uid <uid> Fulfillment UID (collect)
|
||||
--private-key <key> Private key (all commands)
|
||||
--rpc-url <url> RPC URL (default: http://localhost:8545)
|
||||
--deployment <file> Load addresses from deployment file
|
||||
|
||||
Environment Variables:
|
||||
PRIVATE_KEY Private key for transactions
|
||||
RPC_URL RPC URL for blockchain network
|
||||
OPENAI_API_KEY OpenAI API key (for create command)
|
||||
|
||||
Examples:
|
||||
# Start development environment
|
||||
nla dev
|
||||
|
||||
# Create an escrow
|
||||
nla escrow:create \\
|
||||
--demand "The sky is blue" \\
|
||||
--amount 10 \\
|
||||
--token 0xa513E6E4b8f2a923D98304ec87F64353C4D5C853 \\
|
||||
--oracle 0x70997970C51812dc3A010C7d01b50e0d17dc79C8
|
||||
|
||||
# Fulfill an escrow
|
||||
nla escrow:fulfill \\
|
||||
--escrow-uid 0x... \\
|
||||
--fulfillment "The sky appears blue today" \\
|
||||
--oracle 0x70997970C51812dc3A010C7d01b50e0d17dc79C8
|
||||
|
||||
# Collect an escrow
|
||||
nla escrow:collect \\
|
||||
--escrow-uid 0x... \\
|
||||
--fulfillment-uid 0x...
|
||||
|
||||
# Check escrow status
|
||||
nla escrow:status --escrow-uid 0x...
|
||||
`);
|
||||
}
|
||||
|
||||
// Parse command line arguments
|
||||
function parseCliArgs() {
|
||||
const args = Bun.argv.slice(2);
|
||||
|
||||
if (args.length === 0) {
|
||||
displayHelp();
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
const command = args[0];
|
||||
|
||||
if (command === "help" || command === "--help" || command === "-h") {
|
||||
displayHelp();
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
const { values } = parseArgs({
|
||||
args: args.slice(1),
|
||||
options: {
|
||||
"demand": { type: "string" },
|
||||
"amount": { type: "string" },
|
||||
"token": { type: "string" },
|
||||
"oracle": { type: "string" },
|
||||
"escrow-uid": { type: "string" },
|
||||
"fulfillment": { type: "string" },
|
||||
"fulfillment-uid": { type: "string" },
|
||||
"private-key": { type: "string" },
|
||||
"rpc-url": { type: "string" },
|
||||
"deployment": { type: "string" },
|
||||
},
|
||||
strict: true,
|
||||
});
|
||||
|
||||
return { command, ...values };
|
||||
}
|
||||
|
||||
// Main function
|
||||
async function main() {
|
||||
try {
|
||||
const args = parseCliArgs();
|
||||
const command = args.command;
|
||||
|
||||
// Handle dev command separately (runs shell script)
|
||||
if (command === "dev") {
|
||||
await runDevCommand();
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the script path based on command
|
||||
let scriptPath: string;
|
||||
|
||||
switch (command) {
|
||||
case "escrow:create":
|
||||
scriptPath = "./client/create-escrow.ts";
|
||||
break;
|
||||
case "escrow:fulfill":
|
||||
scriptPath = "./client/fulfill-escrow.ts";
|
||||
break;
|
||||
case "escrow:collect":
|
||||
scriptPath = "./client/collect-escrow.ts";
|
||||
break;
|
||||
case "escrow:status":
|
||||
await runStatusCommand(args);
|
||||
return;
|
||||
default:
|
||||
console.error(`❌ Unknown command: ${command}`);
|
||||
console.error("Run 'nla help' for usage information.");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
// Run the command as a subprocess with the args (excluding the command name)
|
||||
const { spawnSync } = await import("child_process");
|
||||
const scriptDir = import.meta.dir;
|
||||
const fullScriptPath = `${scriptDir}/${scriptPath}`;
|
||||
|
||||
// Build args array without the command name
|
||||
const commandArgs = Bun.argv.slice(3); // Skip bun, script, and command
|
||||
|
||||
const result = spawnSync("bun", ["run", fullScriptPath, ...commandArgs], {
|
||||
stdio: "inherit",
|
||||
cwd: process.cwd(),
|
||||
});
|
||||
|
||||
process.exit(result.status || 0);
|
||||
|
||||
} catch (error) {
|
||||
console.error("❌ Error:", error);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// Dev command handler
|
||||
async function runDevCommand() {
|
||||
console.log("🚀 Starting development environment...\n");
|
||||
|
||||
const { spawnSync } = await import("child_process");
|
||||
const scriptDir = import.meta.dir;
|
||||
const devScriptPath = `${scriptDir}/scripts/dev.sh`;
|
||||
|
||||
// Run the dev.sh script
|
||||
const result = spawnSync(devScriptPath, [], {
|
||||
stdio: "inherit",
|
||||
cwd: process.cwd(),
|
||||
shell: true,
|
||||
});
|
||||
|
||||
process.exit(result.status || 0);
|
||||
}
|
||||
|
||||
// Status command handler
|
||||
async function runStatusCommand(args: any) {
|
||||
const escrowUid = args["escrow-uid"];
|
||||
const rpcUrl = args["rpc-url"] || process.env.RPC_URL || "http://localhost:8545";
|
||||
const deploymentFile = args["deployment"];
|
||||
|
||||
if (!escrowUid) {
|
||||
console.error("❌ Error: --escrow-uid is required for status command");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
console.log("🔍 Checking Escrow Status\n");
|
||||
console.log(`Configuration:`);
|
||||
console.log(` 📦 Escrow UID: ${escrowUid}`);
|
||||
console.log(` 🌐 RPC URL: ${rpcUrl}\n`);
|
||||
|
||||
// Import required modules
|
||||
const { createPublicClient, http, parseAbiParameters } = await import("viem");
|
||||
const { foundry } = await import("viem/chains");
|
||||
const { existsSync, readFileSync } = await import("fs");
|
||||
|
||||
// Load deployment addresses
|
||||
let addresses: any = {};
|
||||
if (deploymentFile && existsSync(deploymentFile)) {
|
||||
const deployment = JSON.parse(readFileSync(deploymentFile, "utf-8"));
|
||||
addresses = deployment.addresses;
|
||||
}
|
||||
|
||||
// Create public client
|
||||
const publicClient = createPublicClient({
|
||||
chain: foundry,
|
||||
transport: http(rpcUrl),
|
||||
});
|
||||
|
||||
// Load EAS ABI
|
||||
const { default: EAS } = await import("../../alkahest/contracts/out/EAS.sol/EAS.json");
|
||||
|
||||
if (!addresses.eas) {
|
||||
console.error("❌ Error: EAS address not found. Use --deployment to specify deployment file.");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
// Get escrow attestation
|
||||
console.log("📋 Fetching escrow details...\n");
|
||||
|
||||
const escrow = await publicClient.readContract({
|
||||
address: addresses.eas,
|
||||
abi: EAS.abi,
|
||||
functionName: "getAttestation",
|
||||
args: [escrowUid],
|
||||
}) as any;
|
||||
|
||||
console.log("📦 Escrow Information:");
|
||||
console.log(` UID: ${escrow.uid}`);
|
||||
console.log(` Schema: ${escrow.schema}`);
|
||||
console.log(` Attester: ${escrow.attester}`);
|
||||
console.log(` Recipient: ${escrow.recipient}`);
|
||||
console.log(` Revoked: ${escrow.revocationTime > 0n ? "Yes ❌" : "No ✅"}`);
|
||||
|
||||
// Try to decode the data
|
||||
try {
|
||||
const llmAbi = parseAbiParameters("(string demand, string arbitrationModel, address arbitrator)");
|
||||
const decoded = await import("viem").then(m =>
|
||||
m.decodeAbiParameters(llmAbi, escrow.data)
|
||||
);
|
||||
console.log(`\n📝 Escrow Details:`);
|
||||
console.log(` Demand: "${decoded[0].demand}"`);
|
||||
console.log(` Model: ${decoded[0].arbitrationModel}`);
|
||||
console.log(` Arbitrator: ${decoded[0].arbitrator}`);
|
||||
} catch (e) {
|
||||
console.log(`\n📝 Raw Data: ${escrow.data}`);
|
||||
}
|
||||
|
||||
// Check for fulfillments
|
||||
console.log(`\n🔎 Checking for fulfillments...`);
|
||||
|
||||
const filter = await publicClient.createContractEventFilter({
|
||||
address: addresses.eas,
|
||||
abi: EAS.abi,
|
||||
eventName: "Attested",
|
||||
fromBlock: 0n,
|
||||
});
|
||||
|
||||
const events = await publicClient.getFilterLogs({ filter });
|
||||
|
||||
// Find fulfillments that reference this escrow
|
||||
const fulfillments = events.filter((event: any) => {
|
||||
return (event as any).args?.refUID === escrowUid;
|
||||
});
|
||||
|
||||
if (fulfillments.length === 0) {
|
||||
console.log(` No fulfillments found yet`);
|
||||
} else {
|
||||
console.log(` Found ${fulfillments.length} fulfillment(s):\n`);
|
||||
|
||||
for (const fulfillment of fulfillments) {
|
||||
const fulfillmentUid = (fulfillment as any).args?.uid;
|
||||
const fulfillmentAttestation = await publicClient.readContract({
|
||||
address: addresses.eas,
|
||||
abi: EAS.abi,
|
||||
functionName: "getAttestation",
|
||||
args: [fulfillmentUid],
|
||||
}) as any;
|
||||
|
||||
console.log(` 📨 Fulfillment UID: ${fulfillmentUid}`);
|
||||
console.log(` Attester: ${fulfillmentAttestation.attester}`);
|
||||
console.log(` Revoked: ${fulfillmentAttestation.revocationTime > 0n ? "Yes ❌" : "No ✅"}`);
|
||||
|
||||
// Check for arbitration decision
|
||||
const decisions = events.filter((e: any) => (e as any).args?.refUID === fulfillmentUid);
|
||||
if (decisions.length > 0) {
|
||||
console.log(` ⚖️ Arbitration: Decision recorded`);
|
||||
for (const decision of decisions) {
|
||||
const decisionUid = (decision as any).args?.uid;
|
||||
const decisionAttestation = await publicClient.readContract({
|
||||
address: addresses.eas,
|
||||
abi: EAS.abi,
|
||||
functionName: "getAttestation",
|
||||
args: [decisionUid],
|
||||
}) as any;
|
||||
|
||||
try {
|
||||
const decisionAbi = parseAbiParameters("(bool item)");
|
||||
const decisionData = await import("viem").then(m =>
|
||||
m.decodeAbiParameters(decisionAbi, decisionAttestation.data)
|
||||
);
|
||||
console.log(` Result: ${decisionData[0].item ? "✅ APPROVED" : "❌ REJECTED"}`);
|
||||
} catch (e) {
|
||||
console.log(` Result: Unknown`);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
console.log(` ⚖️ Arbitration: Pending...`);
|
||||
}
|
||||
console.log();
|
||||
}
|
||||
}
|
||||
|
||||
console.log("✨ Status check complete!\n");
|
||||
}
|
||||
|
||||
// Run the CLI
|
||||
main();
|
||||
|
|
@ -42,22 +42,22 @@ echo -e "${GREEN}✅ Contract artifacts found${NC}\n"
|
|||
|
||||
# Run deployment
|
||||
echo -e "${BLUE}📝 Deploying to ${NETWORK}...${NC}"
|
||||
bun run setups/deploy.ts --network "$NETWORK" --rpc-url "$RPC_URL"
|
||||
bun run cli/server/deploy.ts --network "$NETWORK" --rpc-url "$RPC_URL"
|
||||
|
||||
# Check if deployment was successful
|
||||
if [ $? -eq 0 ]; then
|
||||
echo -e "\n${GREEN}✨ Deployment complete!${NC}"
|
||||
echo -e "${BLUE}Deployment file saved to: deployments/${NETWORK}.json${NC}\n"
|
||||
echo -e "${BLUE}Deployment file saved to: cli/deployments/${NETWORK}.json${NC}\n"
|
||||
|
||||
echo -e "${YELLOW}Next steps:${NC}"
|
||||
echo "1. Start the oracle with:"
|
||||
echo " ./scripts/start-oracle.sh $NETWORK"
|
||||
echo " ./cli/scripts/start-oracle.sh $NETWORK"
|
||||
echo ""
|
||||
echo "2. Or using npm script:"
|
||||
echo " bun run oracle"
|
||||
echo ""
|
||||
echo "3. Or manually:"
|
||||
echo " bun run setups/oracle.ts --deployment ./deployments/${NETWORK}.json"
|
||||
echo " bun run cli/server/oracle.ts --deployment ./cli/deployments/${NETWORK}.json"
|
||||
else
|
||||
echo -e "\n${RED}❌ Deployment failed${NC}"
|
||||
exit 1
|
||||
|
|
@ -103,12 +103,12 @@ fi
|
|||
# Deploy contracts
|
||||
echo -e "\n${BLUE}📝 Deploying contracts...${NC}\n"
|
||||
export DEPLOYER_PRIVATE_KEY="0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80"
|
||||
./scripts/deploy.sh localhost http://localhost:8545
|
||||
./cli/scripts/deploy.sh localhost http://localhost:8545
|
||||
|
||||
# Start oracle
|
||||
echo -e "\n${BLUE}🚀 Starting oracle...${NC}\n"
|
||||
export ORACLE_PRIVATE_KEY="0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d"
|
||||
./scripts/start-oracle.sh localhost
|
||||
./cli/scripts/start-oracle.sh localhost
|
||||
|
||||
# Cleanup function
|
||||
cleanup() {
|
||||
|
|
@ -19,7 +19,7 @@ fi
|
|||
|
||||
# Default network
|
||||
NETWORK=${1:-localhost}
|
||||
DEPLOYMENT_FILE="./deployments/${NETWORK}.json"
|
||||
DEPLOYMENT_FILE="./cli/deployments/${NETWORK}.json"
|
||||
|
||||
echo -e "${BLUE}🚀 Starting Natural Language Agreement Oracle${NC}\n"
|
||||
|
||||
|
|
@ -27,7 +27,7 @@ echo -e "${BLUE}🚀 Starting Natural Language Agreement Oracle${NC}\n"
|
|||
if [ ! -f "$DEPLOYMENT_FILE" ]; then
|
||||
echo -e "${RED}❌ Error: Deployment file not found: $DEPLOYMENT_FILE${NC}"
|
||||
echo "Please deploy contracts first:"
|
||||
echo " ./scripts/deploy.sh $NETWORK"
|
||||
echo " ./cli/scripts/deploy.sh $NETWORK"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
|
@ -54,7 +54,7 @@ echo ""
|
|||
|
||||
# Start oracle
|
||||
echo -e "${BLUE}👂 Starting oracle (Press Ctrl+C to stop)...${NC}\n"
|
||||
bun run setups/oracle.ts \
|
||||
bun run cli/server/oracle.ts \
|
||||
--deployment "$DEPLOYMENT_FILE" \
|
||||
--openai-api-key "$OPENAI_API_KEY" \
|
||||
--private-key "$ORACLE_PRIVATE_KEY"
|
||||
|
|
@ -25,7 +25,7 @@ Options:
|
|||
--network <name> Network to deploy to: mainnet, sepolia, localhost (required)
|
||||
--rpc-url <url> Custom RPC URL (overrides network default)
|
||||
--private-key <key> Deployer's private key (required)
|
||||
--output <path> Output file for deployment addresses (default: ./deployments/<network>.json)
|
||||
--output <path> Output file for deployment addresses (default: ./cli/deployments/<network>.json)
|
||||
--help, -h Display this help message
|
||||
|
||||
Environment Variables (alternative to CLI options):
|
||||
|
|
@ -152,7 +152,7 @@ async function main() {
|
|||
console.log("📦 Loading contract artifacts...\n");
|
||||
|
||||
// This requires alkahest to be properly set up
|
||||
const alkahestPath = "../../alkahest/sdks/ts";
|
||||
const alkahestPath = "../../../alkahest/sdks/ts";
|
||||
const contractsPath = `${alkahestPath}/src/contracts`;
|
||||
|
||||
// Import necessary artifacts
|
||||
|
|
@ -329,7 +329,10 @@ async function main() {
|
|||
}
|
||||
|
||||
// Save deployment addresses
|
||||
const outputPath = args.output || resolve(`./deployments/${network}.json`);
|
||||
// Get the script directory and go up to project root, then into cli/deployments
|
||||
const scriptDir = import.meta.dir;
|
||||
const projectRoot = resolve(scriptDir, "../..");
|
||||
const outputPath = args.output || resolve(projectRoot, `cli/deployments/${network}.json`);
|
||||
const outputDir = resolve(outputPath, "..");
|
||||
|
||||
if (!existsSync(outputDir)) {
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
#!/usr/bin/env bun
|
||||
import { parseArgs } from "util";
|
||||
import { parseAbiParameters } from "viem";
|
||||
import { makeLLMClient } from "../clients/nla";
|
||||
import { makeLLMClient } from "../../clients/nla";
|
||||
import { existsSync, readFileSync } from "fs";
|
||||
import { resolve } from "path";
|
||||
|
||||
|
|
@ -127,7 +127,7 @@ async function main() {
|
|||
}
|
||||
|
||||
// Import alkahest client
|
||||
const { makeClient } = await import("../../alkahest/sdks/ts/src/index.ts");
|
||||
const { makeClient } = await import("../../../alkahest/sdks/ts/src/index.ts");
|
||||
const { createWalletClient, http, publicActions } = await import("viem");
|
||||
const { privateKeyToAccount } = await import("viem/accounts");
|
||||
const { foundry } = await import("viem/chains");
|
||||
17
package.json
17
package.json
|
|
@ -5,18 +5,21 @@
|
|||
"private": true,
|
||||
"devDependencies": {
|
||||
"@types/bun": "latest"
|
||||
},
|
||||
"bin": {
|
||||
"nla": "cli/index.ts"
|
||||
},
|
||||
"scripts": {
|
||||
"dev": "bun run index.ts",
|
||||
"start": "bun run index.ts",
|
||||
"test": "bun test ./tests --exclude alkahest-ts/** ",
|
||||
"setup": "./scripts/dev.sh",
|
||||
"deploy": "./scripts/deploy.sh",
|
||||
"oracle": "./scripts/start-oracle.sh",
|
||||
"stop": "./scripts/stop.sh",
|
||||
"escrow:create": "bun run cli/create-escrow.ts",
|
||||
"escrow:fulfill": "bun run cli/fulfill-escrow.ts",
|
||||
"escrow:collect": "bun run cli/collect-escrow.ts"
|
||||
"setup": "./cli/scripts/dev.sh",
|
||||
"deploy": "./cli/scripts/deploy.sh",
|
||||
"oracle": "./cli/scripts/start-oracle.sh",
|
||||
"stop": "./cli/scripts/stop.sh",
|
||||
"escrow:create": "bun run cli/client/create-escrow.ts",
|
||||
"escrow:fulfill": "bun run cli/client/fulfill-escrow.ts",
|
||||
"escrow:collect": "bun run cli/client/collect-escrow.ts"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"typescript": "^5.9.3"
|
||||
|
|
|
|||
Loading…
Reference in New Issue