Open Wallet Standard
Secure key management for AI agents. Private keys never leave the vault — all signing goes through OWS.
Open Wallet Standard (OWS) is a universal wallet layer by MoonPay. It stores private keys in an encrypted vault and provides a signing API where keys never leave the secure boundary.
ENACT Protocol integrates OWS for TON. AI agents can create escrow jobs, lock funds, deliver work, and get paid — without the agent or the LLM ever touching a private key.
Without OWS vs With OWS
Normally, your agent code holds the raw private key in memory:
// Private key sits in your agent's memory — any leak exposes it
const keyPair = await mnemonicToPrivateKey(mnemonic.split(' '));
await contract.sendTransfer({
secretKey: keyPair.secretKey, // ← raw key in memory
...
});With OWS, the private key stays inside an encrypted vault. Your code never sees it:
// Private key never leaves the OWS vault
const signer = await createOWSSigner('my-agent');
await contract.sendTransfer({
signer: signer.sign, // ← OWS signs inside the vault
...
});Same sendTransfer(), same ENACT SDK — just swap secretKey for signer.
Step-by-Step Setup
Step 1 — Install OWS
npm install -g @open-wallet-standard/core
Or use the installer (installs CLI + Node.js + Python bindings):
curl -fsSL https://docs.openwallet.sh/install.sh | bash
Step 2 — Create a wallet
ows wallet create --name my-agent
The output shows your TON address (starts with UQ...). Send TON to this address to fund it.
Step 3 — Set up your project
mkdir my-enact-agent && cd my-enact-agent npm init -y npm install @open-wallet-standard/core @ton/ton @ton/core bip39 ed25519-hd-key tweetnacl
Step 4 — Copy the adapter
Download ows-signer.ts into your project. This is a single file (~140 lines) that bridges OWS with @ton/ton.
curl -o ows-signer.ts https://raw.githubusercontent.com/ENACT-protocol/enact-protocol/master/examples/ows-integration/ows-signer.ts
Step 5 — Write your agent
Here's a complete working example — an agent that creates an ENACT escrow job:
import { TonClient, WalletContractV5R1, internal, SendMode } from '@ton/ton';
import { Address, beginCell, toNano } from '@ton/core';
import { createOWSSigner } from './ows-signer';
const FACTORY = 'EQAFHodWCzrYJTbrbJp1lMDQLfypTHoJCd0UcerjsdxPECjX';
async function main() {
// 1. Connect to OWS wallet (key stays in vault)
const signer = await createOWSSigner('my-agent');
console.log('Agent wallet:', signer.address);
// 2. Connect to TON
const client = new TonClient({
endpoint: 'https://toncenter.com/api/v2/jsonRPC',
apiKey: process.env.TONCENTER_API_KEY || '',
});
// 3. Create wallet contract
const wallet = WalletContractV5R1.create({
publicKey: signer.publicKey,
workchain: 0,
});
const contract = client.open(wallet);
// 4. Build the ENACT createJob message
const descHash = BigInt('0x' + Buffer.from('Translate document EN→FR')
.toString('hex').padEnd(64, '0'));
const body = beginCell()
.storeUint(0x00000010, 32) // createJob opcode
.storeAddress(Address.parse(signer.address)) // evaluator (self for demo)
.storeCoins(toNano('0.1')) // budget: 0.1 TON
.storeUint(descHash, 256) // job description hash
.storeUint(86400, 32) // 24h timeout
.storeUint(86400, 32) // 24h eval timeout
.endCell();
// 5. Send — OWS signs, key never leaves the vault
const seqno = await contract.getSeqno();
await contract.sendTransfer({
seqno,
signer: signer.sign, // ← OWS handles signing
sendMode: SendMode.PAY_GAS_SEPARATELY,
messages: [internal({
to: Address.parse(FACTORY),
value: toNano('0.03'),
body,
bounce: true,
})],
});
console.log('Job created! Tx seqno:', seqno);
}
main();Step 6 — Run it
Get a free API key at toncenter.com (needed to send transactions to TON), then run:
export TONCENTER_API_KEY=your_key_here npx ts-node agent.ts
How It Fits with ENACT
OWS works at the SDK level — it replaces how your code signs transactions. It's not related to the remote MCP server.
| Integration | How signing works | When to use |
|---|---|---|
| ENACT SDK + OWS | OWS vault signs via callback | You write agent code and want secure local keys |
| Remote MCP | Server-side mnemonic or Tonkeeper deeplink | Quick setup via Claude/Cursor, no local keys |
| Teleton Plugin | Mnemonic in .env | Autonomous Telegram agent |
Policy Engine (Optional)
OWS can enforce rules before any signing. ENACT provides a ready-made policy:
# Download the policy files curl -O https://raw.githubusercontent.com/ENACT-protocol/enact-protocol/master/examples/ows-integration/enact-policy.json curl -O https://raw.githubusercontent.com/ENACT-protocol/enact-protocol/master/examples/ows-integration/enact-policy.js chmod +x enact-policy.js # Register the policy ows policy create --file enact-policy.json
enact-policy.json defines the policy (chain allowlist + path to executable). enact-policy.js is the executable that enforces value and rate limits.
| Rule | Default | What it does |
|---|---|---|
| Max value | 100 TON | Blocks transactions above this amount |
| Rate limit | 10/hour | Prevents runaway agents from draining the wallet |
Security
| Risk | Protection |
|---|---|
| Private key leaked via logs or LLM | Key never enters agent process — OWS signs internally |
| Agent goes rogue, drains wallet | Policy engine limits per-tx value and rate |
| Mnemonic exposed in code | OWS stores keys in AES-256-GCM encrypted vault at ~/.ows/ |