Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions examples/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# OWS Examples

Runnable examples for common OWS use cases.

## Prerequisites

npm install -g @open-wallet-standard/core
ows wallet create --name my-wallet

Get test USDC on Base Sepolia: https://faucet.circle.com

## Examples

| File | Description |
|---|---|
| [x402-pay-request.js](x402-pay-request.js) | Pay an x402-enabled API endpoint |
| [x402-discover-services.js](x402-discover-services.js) | Discover payable services in the marketplace |
| [agent-with-policy.js](agent-with-policy.js) | Create a policy-gated API key for an agent |

## Running

node examples/x402-pay-request.js
node examples/x402-discover-services.js
node examples/agent-with-policy.js
78 changes: 78 additions & 0 deletions examples/agent-with-policy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
/**
* agent-with-policy.js
*
* Create a policy-gated API key for an agent.
* The agent can only sign on allowed chains and within expiry.
*
* Usage:
* node examples/agent-with-policy.js
*/

import { createWallet, signMessage } from "@open-wallet-standard/core";
import { writeFileSync, existsSync } from "fs";
import { execSync } from "child_process";

const WALLET_NAME = "agent-treasury";
const POLICY_ID = "base-agent-limits";
const POLICY_FILE = "/tmp/base-agent-limits.json";

function createPolicyFile() {
const expiry = new Date();
expiry.setFullYear(expiry.getFullYear() + 1);

const policy = {
id: POLICY_ID,
name: "Base Agent Safety Limits",
version: 1,
created_at: new Date().toISOString(),
rules: [
{ type: "allowed_chains", chain_ids: ["eip155:8453", "eip155:84532"] },
{ type: "expires_at", timestamp: expiry.toISOString() }
],
action: "deny"
};

writeFileSync(POLICY_FILE, JSON.stringify(policy, null, 2));
console.log("Policy file written to:", POLICY_FILE);
return POLICY_FILE;
}

async function main() {
console.log("Setting up policy-gated agent wallet...");
console.log("-".repeat(50));

// Step 1: Create wallet
console.log("Step 1: Creating wallet:", WALLET_NAME);
const wallet = createWallet(WALLET_NAME);
console.log("EVM address :", wallet.accounts.find(a => a.chain === "evm")?.address);
console.log("SOL address :", wallet.accounts.find(a => a.chain === "solana")?.address);

// Step 2: Create and register policy
console.log("");
console.log("Step 2: Registering policy:", POLICY_ID);
createPolicyFile();
execSync("ows policy create --file " + POLICY_FILE, { stdio: "inherit" });

// Step 3: Create API key with policy
console.log("");
console.log("Step 3: Creating API key for agent...");
console.log("Run the following command and store the token securely:");
console.log("");
console.log(" ows key create --name claude-agent --wallet " + WALLET_NAME + " --policy " + POLICY_ID);
console.log("");
console.log("The agent token (ows_key_...) is shown once.");
console.log("Pass it to your agent as OWS_API_KEY environment variable.");

// Step 4: Show what the agent can do
console.log("");
console.log("-".repeat(50));
console.log("Agent policy summary:");
console.log(" Allowed chains : eip155:8453 (Base), eip155:84532 (Base Sepolia)");
console.log(" Expiry : 1 year from now");
console.log(" Access tier : agent (policy enforced, no passphrase)");
}

main().catch(err => {
console.error("Error:", err.message);
process.exit(1);
});
45 changes: 45 additions & 0 deletions examples/x402-discover-services.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/**
* x402-discover-services.js
*
* Discover x402-enabled payable services in the OWS marketplace.
*
* Usage:
* node examples/x402-discover-services.js
* node examples/x402-discover-services.js ai
*/

import { discover } from "@open-wallet-standard/core";

const query = process.argv[2] || null;

async function main() {
console.log("Discovering x402 services" + (query ? " matching: " + query : "") + "...");
console.log("-".repeat(50));

try {
const result = await discover(query, 10, 0);

console.log("Total services found:", result.total);
console.log("Showing:", result.services.length);
console.log("");

for (const svc of result.services) {
console.log("Name :", svc.name);
console.log("URL :", svc.url);
console.log("Price :", svc.price);
console.log("Network :", svc.network);
console.log("Tags :", svc.tags.join(", ") || "none");
console.log("Desc :", svc.description);
console.log("-".repeat(50));
}

if (result.total > result.services.length) {
console.log("More services available — use offset to page through results.");
}
} catch (err) {
console.error("Error:", err.message);
process.exit(1);
}
}

main();
41 changes: 41 additions & 0 deletions examples/x402-pay-request.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/**
* x402-pay-request.js
*
* Make a paid HTTP request to an x402-enabled API endpoint.
* OWS handles the 402 -> sign -> retry flow automatically.
*
* Usage:
* node examples/x402-pay-request.js
*/

import { pay } from "@open-wallet-standard/core";

const WALLET_NAME = "my-wallet";
const API_URL = "https://api.cdp.coinbase.com/platform/v1/price?ids=ethereum";

async function main() {
console.log("Making x402 payment request...");
console.log("Wallet :", WALLET_NAME);
console.log("URL :", API_URL);
console.log("-".repeat(50));

try {
const result = await pay(WALLET_NAME, API_URL, "GET");

console.log("Status :", result.status);
console.log("Protocol:", result.protocol);

if (result.payment) {
console.log("Payment :", result.payment.amount, result.payment.token, "on", result.payment.network);
} else {
console.log("Payment : none required");
}

console.log("Response:", result.body.slice(0, 200));
} catch (err) {
console.error("Error:", err.message);
process.exit(1);
}
}

main();