First Onchain Script
This is the shortest end-to-end Beav3r onchain flow for the current model:
- Create a project and API key.
- Provision an onchain actor and get its
accountand trustedexecutor. - Whitelist that
executorat the destination contract. - Submit an action and wait for approval.
- Mint authorization artifact.
- Execute onchain through the trusted executor.
Use:
- staging:
https://staging.server.beav3r.ai - production:
https://server.beav3r.ai
Package setup
mkdir beav3r-onchain-quickstart && cd beav3r-onchain-quickstart
npm init -y
npm install @beav3r/sdk@beta viemBefore starting
Required:
- Beav3r dashboard access:
https://dashboard.beav3r.ai - one project API key with onchain scopes
- one provisioned onchain actor (
account+executor) - onchain signer registration configured in signer registry for that actor account and key id
- one destination contract that whitelists the returned
executor - funded wallet to submit the
executeWithAuth(...)transaction on the target chain
Trusted executor model
Provisioning returns:
account: the actor identity bound into the authorization payloadexecutor: the contract address the destination should trust
The destination contract grants permissions to the executor address, such as
an allowlist entry or role. At execution time, the destination sees
msg.sender = executor.
Beav3r does not ask the destination to trust an EOA signer directly. The destination trusts the provisioned executor contract, and the executor only runs calls with a valid Beav3r authorization artifact.
If setup is incomplete, start with:
Script
Load these variables before running the example:
# Beav3r API configuration
export BEAV3R_BASE_URL=https://staging.server.beav3r.ai
export BEAV3R_API_KEY=project_api_key
export BEAV3R_AGENT_ID=onchain_quickstart
# Provisioned actor returned by Beav3r
export ONCHAIN_ACTOR_ACCOUNT=0xactor_account
export ONCHAIN_EXECUTOR_ADDRESS=0xtrusted_executor
# Target chain and destination contract
export ONCHAIN_CHAIN_ID=84532
export ONCHAIN_RPC_URL=https://base-sepolia-rpc.example
export ONCHAIN_TOKEN_ADDRESS=0xtoken_contract
# Funded EOA that submits executeWithAuth(...) onchain
export ONCHAIN_EXECUTOR_CALLER_PRIVATE_KEY=0xyour_private_keyTypeScript
first-onchain-script.mjs
import { Beav3r, prepareOnchainExecution } from '@beav3r/sdk'
import {
createPublicClient,
createWalletClient,
encodeFunctionData,
http,
parseAbi
} from 'viem'
import { privateKeyToAccount } from 'viem/accounts'
// 1. Load Beav3r API configuration.
const baseUrl = process.env.BEAV3R_BASE_URL ?? 'https://staging.server.beav3r.ai'
const apiKey = process.env.BEAV3R_API_KEY
const agentId = process.env.BEAV3R_AGENT_ID ?? 'onchain_quickstart'
if (!apiKey) {
throw new Error('Missing BEAV3R_API_KEY')
}
// 2. Load the provisioned actor returned by Beav3r.
const chainId = Number(process.env.ONCHAIN_CHAIN_ID ?? 84532)
const account = process.env.ONCHAIN_ACTOR_ACCOUNT
const executor = process.env.ONCHAIN_EXECUTOR_ADDRESS
const token = process.env.ONCHAIN_TOKEN_ADDRESS
if (!account || !executor || !token) {
throw new Error('Missing ONCHAIN_ACTOR_ACCOUNT / ONCHAIN_EXECUTOR_ADDRESS / ONCHAIN_TOKEN_ADDRESS')
}
// 3. Load the RPC and funded EOA that will submit executeWithAuth(...).
const rpcUrl = process.env.ONCHAIN_RPC_URL
const pk = process.env.ONCHAIN_EXECUTOR_CALLER_PRIVATE_KEY
if (!rpcUrl || !pk) {
throw new Error('Missing ONCHAIN_RPC_URL / ONCHAIN_EXECUTOR_CALLER_PRIVATE_KEY')
}
const client = new Beav3r({
baseUrl,
apiKey,
agentId
})
// 4. Prepare the destination call the trusted executor will make.
const recipient = '0x1111111111111111111111111111111111111111'
const amount = 25n * 10n ** 6n
const transferData = encodeFunctionData({
abi: parseAbi(['function transfer(address to, uint256 amount) returns (bool)']),
functionName: 'transfer',
args: [recipient, amount]
})
// 5. Submit the action to Beav3r and wait for approval.
await client.guardAndWait(
{
actionType: 'payments.send_usdt',
payload: { amount: '25', recipient, chainId, calldata: transferData }
},
{ pollIntervalMs: 2000, timeoutMs: 5 * 60 * 1000 }
)
// 6. Ask Beav3r for an authorization artifact bound to this actor + executor.
const now = Math.floor(Date.now() / 1000)
const auth = await client.authorizeOnchainAction({
account,
to: token,
value: '0',
data: transferData,
chainId,
nonce: BigInt(now),
expiresAt: BigInt(now + 1200),
executor
})
// 7. Submit executeWithAuth(...) onchain through the trusted executor.
const caller = privateKeyToAccount(pk)
const publicClient = createPublicClient({ transport: http(rpcUrl) })
const walletClient = createWalletClient({ account: caller, transport: http(rpcUrl) })
const prepared = prepareOnchainExecution({
actor: {
accountAddress: account,
executorAddress: executor,
chainId
},
action: {
to: token,
value: '0',
data: transferData,
nonce: BigInt(now)
},
artifact: auth.item.artifact
})
const txHash = await walletClient.writeContract({
address: executor,
abi: parseAbi([
'function executeWithAuth(address to,uint256 value,bytes data,(bytes32 actionHash,address account,address executor,uint256 chainId,uint256 nonce,uint256 expiresAt,bytes32 keyId) auth,bytes signature) payable returns (bytes)'
]),
functionName: 'executeWithAuth',
args: [
prepared.to,
prepared.value,
prepared.data,
prepared.auth,
prepared.signature
]
})
const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash })
console.log({ txHash, status: receipt.status })The TypeScript example uses prepareOnchainExecution(...) from @beav3r/sdk to:
- verify the returned artifact matches the actor and request
- normalize the auth payload fields
- prepare the final
executeWithAuth(...)call arguments
The Python example stays more explicit because the current helper lives in the JavaScript SDK.
Run it
BEAV3R_BASE_URL=https://staging.server.beav3r.ai \
BEAV3R_API_KEY=project_api_key \
ONCHAIN_RPC_URL=https://base-sepolia.infura.io/v3/<key> \
ONCHAIN_CHAIN_ID=84532 \
ONCHAIN_ACTOR_ACCOUNT=0x... \
ONCHAIN_EXECUTOR_ADDRESS=0x... \
ONCHAIN_TOKEN_ADDRESS=0x... \
ONCHAIN_EXECUTOR_CALLER_PRIVATE_KEY=0x... \
node first-onchain-script.mjsExpected result
- action reaches approval flow
- authorization artifact is minted
- executor call succeeds onchain
- destination contract accepts execution because the trusted executor is caller
Continue with: