Skip to content

Instantly share code, notes, and snippets.

@denniswon
Created September 22, 2025 16:36
Show Gist options
  • Select an option

  • Save denniswon/94b77627250b44347703055ec4ebfff0 to your computer and use it in GitHub Desktop.

Select an option

Save denniswon/94b77627250b44347703055ec4ebfff0 to your computer and use it in GitHub Desktop.
newton client side: rpc request for simulatePolicyEvaluation
import {
createWalletClient,
createPublicClient,
http,
parseEther,
keccak256,
encodePacked,
Address,
Hex,
PrivateKeyAccount,
privateKeyToAccount,
} from "viem";
import { mainnet, sepolia, holesky } from "viem/chains";
// Types for Newton RPC API
interface Intent {
from: Address;
to: Address;
value: bigint;
data: Hex;
chainId: bigint;
functionSignature: Hex;
}
interface PolicyData {
data: Hex;
attestation: Hex;
policyDataAddress: Address;
expireBlock: number;
}
interface PolicyTaskData {
policyId: Hex;
policyAddress: Address;
policy: Hex;
policyData: PolicyData[];
}
interface SimulatePolicyEvaluationRequest {
signature: string;
intent: Intent;
policy_task_data: PolicyTaskData;
}
interface SimulatePolicyEvaluationResponse {
/// something like this
result: {
policy: string,
parsed_intent: ParsedIntent,
policy_params_and_data: JsonObject,
entrypoint: string,
result: JsonObject,
expire_after: number,
}
}
// Newton RPC Client Class
export class NewtonRpcClient {
private rpcUrl: string;
private walletClient: any;
private publicClient: any;
constructor(
rpcUrl: string,
privateKey: Hex,
chainId: number = 11155111
) {
this.rpcUrl = rpcUrl;
// Create account from private key
const account = privateKeyToAccount(privateKey);
// Select chain based on chainId
const chain = this.getChainById(chainId);
// Create clients
this.walletClient = createWalletClient({
account,
chain,
transport: http(),
});
this.publicClient = createPublicClient({
chain,
transport: http(),
});
}
private getChainById(chainId: number) {
switch (chainId) {
case 1:
return mainnet;
case 11155111:
return sepolia;
case 17000:
return holesky;
default:
return mainnet;
}
}
/**
* Creates the hash for signing the request
* This matches the Rust implementation: keccak256(abi_encode_packed(request))
*/
private createRequestHash(
intent: Intent,
policyTaskData: PolicyTaskData
): Hex {
// ABI encode packed the request data
// This matches the ISimulatePolicyEvaluationRequest struct
const encoded = encodePacked(
["address", "address", "uint256", "bytes", "uint256", "bytes"], // Intent fields
[
intent.from,
intent.to,
intent.value,
intent.data,
intent.chainId,
intent.functionSignature,
]
);
// Add PolicyTaskData fields
const policyTaskDataEncoded = encodePacked(
["bytes32", "address", "bytes", "uint256"], // policyId, policyAddress, policy, policyData length
[
policyTaskData.policyId,
policyTaskData.policyAddress,
policyTaskData.policy,
BigInt(policyTaskData.policyData.length),
]
);
// Encode each PolicyData item
let policyDataEncoded = "0x";
for (const pd of policyTaskData.policyData) {
const pdEncoded = encodePacked(
["bytes", "bytes", "address", "uint32"],
[pd.data, pd.attestation, pd.policyDataAddress, pd.expireBlock]
);
policyDataEncoded += pdEncoded.slice(2); // Remove 0x prefix
}
// Combine all encoded data
const fullEncoded =
encoded + policyTaskDataEncoded.slice(2) + policyDataEncoded.slice(2);
// Create keccak256 hash
return keccak256(fullEncoded as Hex);
}
/**
* Signs the request hash with the wallet's private key
*/
private async signRequest(hash: Hex): Promise<string> {
const signature = await this.walletClient.signMessage({
message: { raw: hash },
});
return signature;
}
/**
* Simulates policy evaluation by calling the Newton RPC endpoint
*/
async simulatePolicyEvaluation(
intent: Intent,
policyTaskData: PolicyTaskData
): Promise<SimulatePolicyEvaluationResponse> {
// Create the hash for signing
const requestHash = this.createRequestHash(intent, policyTaskData);
// Sign the request
const signature = await this.signRequest(requestHash);
// Create the request object
const request: SimulatePolicyEvaluationRequest = {
signature,
intent,
policy_task_data: policyTaskData,
};
// Make the RPC call
const response = await fetch(this.rpcUrl, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
jsonrpc: "2.0",
method: "newton_simulatePolicyEvaluation",
params: [request],
id: 1,
}),
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const result = await response.json();
if (result.error) {
throw new Error(`RPC error: ${result.error.message}`);
}
return result.result;
}
/**
* Get the current account address
*/
getAddress(): Address {
return this.walletClient.account.address;
}
}
// Example usage
export async function exampleUsage() {
// Initialize the client
const rpcUrl = "https://prover-avs.stagef.newt.foundation";
const privateKey = "0x..." as Hex; // Your private key of an account that is whitelisted
const client = new NewtonRpcClient(rpcUrl, privateKey, 1); // mainnet
console.log("Using address:", client.getAddress());
// Example intent - replace with your actual values
const intent: Intent = {
from: "0x1234567890123456789012345678901234567890" as Address,
to: "0x0987654321098765432109876543210987654321" as Address,
value: parseEther("1.0"), // 1 ETH
data: "0x" as Hex, // Transaction data
chainId: BigInt(1), // Mainnet
functionSignature: "0x" as Hex, // Function signature
};
// Example policy task data - replace with your actual values
const policyTaskData: PolicyTaskData = {
policyId:
"0x1234567890123456789012345678901234567890123456789012345678901234" as Hex,
policyAddress: "0x1234567890123456789012345678901234567890" as Address,
policy: "0x" as Hex, // Policy bytes
policyData: [
{
data: "0x" as Hex,
attestation: "0x" as Hex,
policyDataAddress:
"0x1234567890123456789012345678901234567890" as Address,
expireBlock: 19000000,
},
],
};
try {
// Call the simulate policy evaluation endpoint
const result = await client.simulatePolicyEvaluation(
intent,
policyTaskData
);
console.log("Policy evaluation result:", result);
} catch (error) {
console.error("Error calling simulate policy evaluation:", error);
}
}
// Export for use in other modules
export {
NewtonRpcClient,
type Intent,
type PolicyData,
type PolicyTaskData,
type SimulatePolicyEvaluationRequest,
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment