From b8566bc743b6d7025d87831af4c8064e94dea395 Mon Sep 17 00:00:00 2001 From: Will Zimmerman Date: Mon, 6 Apr 2026 00:33:21 -0700 Subject: [PATCH 1/8] feat: update SDK for new fee estimation proto (Fee/NodeCOGS/ValueFee) Update proto and SDK to match EigenLayer-AVS PR #503 + #504: Proto changes: - Add Fee{amount, unit}, NativeToken, NodeCOGS, ValueFee messages - Add ExecutionTier enum (UNSPECIFIED, TIER_1, TIER_2, TIER_3) - Add INSUFFICIENT_CREDIT error code - Replace old EstimateFeesResp (gas_fees, automation_fees, creation_fees) with flat structure (execution_fee, cogs[], value_fee) - Replace Execution.total_gas_cost + automation_fee with execution_fee + cogs[] + value_fee SDK changes: - New types: Fee, NativeToken, NodeCOGS, ValueFee, FeeDiscount - Updated EstimateFeesResponse to flat structure - Updated Execution model with new fee fields - Updated convertEstimateFeesResponse() for new proto format - Removed old types: GasFeeBreakdown, NodeGasFee, AutomationFee, AutomationFeeComponent, SmartWalletCreationFee, Discount - FeeAmount kept as legacy type for backward compat --- grpc_codegen/avs.proto | 136 +- grpc_codegen/avs_pb.d.ts | 267 ++-- grpc_codegen/avs_pb.js | 1656 ++++++++++++++--------- packages/sdk-js/src/index.ts | 215 +-- packages/sdk-js/src/models/execution.ts | 67 +- packages/types/src/api.ts | 250 ++-- packages/types/src/index.ts | 11 +- packages/types/src/workflow.ts | 7 +- 8 files changed, 1470 insertions(+), 1139 deletions(-) diff --git a/grpc_codegen/avs.proto b/grpc_codegen/avs.proto index 1a01c818..c5c2aa96 100644 --- a/grpc_codegen/avs.proto +++ b/grpc_codegen/avs.proto @@ -36,6 +36,16 @@ enum NodeType { NODE_TYPE_BALANCE = 10; // Balance node for retrieving wallet token balances } +// ExecutionTier defines value-capture pricing groups for on-chain execution nodes. +// Tiers are pure pricing buckets — meaning comes from classification logic, not the label. +// Non-execution nodes use UNSPECIFIED (no fee). +enum ExecutionTier { + EXECUTION_TIER_UNSPECIFIED = 0; // No value-capture fee (non-execution nodes) + EXECUTION_TIER_1 = 1; // Pricing group 1 (default: 0.03% of tx value) + EXECUTION_TIER_2 = 2; // Pricing group 2 (default: 0.09% of tx value) + EXECUTION_TIER_3 = 3; // Pricing group 3 (default: 0.18% of tx value) +} + enum ExecutionMode { EXECUTION_MODE_SEQUENTIAL = 0; // Run iterations sequentially (default for safety) EXECUTION_MODE_PARALLEL = 1; // Run iterations in parallel @@ -323,7 +333,8 @@ enum ErrorCode { SMART_WALLET_NOT_FOUND = 8001; // Smart wallet address not found SMART_WALLET_DEPLOYMENT_ERROR = 8002; // Failed to deploy smart wallet INSUFFICIENT_BALANCE = 8003; // Insufficient balance for operation - + INSUFFICIENT_CREDIT = 8004; // Outstanding value fees exceed credit limit + // 9000-9999: Reserved for future use } @@ -688,13 +699,10 @@ message Execution { // This helps clients understand execution order without calculating based on timestamps int64 index = 6; - // Total gas cost for the entire workflow execution (sum of all blockchain operations) - // Units are in wei. Use string for large numbers to avoid overflow. - string total_gas_cost = 7; - - // Automation fee charged for monitoring and executing this workflow. - // Currently hard-coded to zero; will be populated when automation fees are enabled. - FeeAmount automation_fee = 9; + // Fees actually charged for this execution (matches EstimateFeesResp format) + Fee execution_fee = 7; // Flat platform fee charged {amount, unit: "USD"} + repeated NodeCOGS cogs = 9; // Per-node actual gas/API costs {fee: {amount, unit: "WEI"}} + ValueFee value_fee = 10; // Value-capture fee charged (post-paid) {fee: {amount, unit: "PERCENTAGE"}} message Step { string id = 1; @@ -714,8 +722,10 @@ message Execution { // Optional execution context for runtime flags and extra info (e.g., is_simulated) google.protobuf.Value execution_context = 26; - // Gas cost tracking fields for blockchain operations (contract_write, eth_transfer) - // Units are in wei for precision. Use string for large numbers to avoid overflow. + // Gas cost tracking fields for blockchain operations (contract_write, eth_transfer, + // and loop nodes containing on-chain runners). Units are in wei for precision. + // Empty string means gas data was not available (e.g., receipt unavailable, or + // non-on-chain step). For loop steps, these are aggregated from all iterations. string gas_used = 27; // Amount of gas consumed by the transaction string gas_price = 28; // Gas price in wei per gas unit string total_gas_cost = 29; // Total cost (gas_used * gas_price) in wei @@ -1379,58 +1389,74 @@ message SmartWalletCreationFee { string wallet_address = 4; // Predicted or existing wallet address } -// Automation fee structure based on trigger type and duration -message AutomationFee { - FeeAmount base_fee = 1; // Base automation fee - FeeAmount monitoring_fee = 2; // Ongoing monitoring cost (for time/event triggers) - FeeAmount execution_fee = 3; // Per-execution fee - - // Fee calculation details - string trigger_type = 4; // "manual", "cron", "event", "block", "fixed_time" - int64 estimated_executions = 5; // Estimated number of executions over workflow lifetime - int64 duration_minutes = 6; // How long monitoring will run (minutes) - string fee_calculation_method = 7; // Description of how fee was calculated +// Unit-safe fee value. Every monetary field is self-describing. +// Units: "USD" (fiat), "WEI" (native token smallest unit), "PERCENTAGE" (0.03 = 0.03%) +message Fee { + string amount = 1; // Numeric value as string (precision-safe) + string unit = 2; // "USD", "WEI", "PERCENTAGE" +} + +// Native token metadata for the chain +message NativeToken { + string symbol = 1; // e.g., "ETH" + int32 decimals = 2; // e.g., 18 +} + +// Per-node cost of goods sold (gas, external API costs, etc.) +message NodeCOGS { + string node_id = 1; + string cost_type = 2; // "gas", "external_api", "wallet_creation" + Fee fee = 3; // Cost in WEI + string gas_units = 4; // Gas units (for gas costs only) +} + +// Workflow-level value-capture fee. +// Single fee for the entire workflow based on what it does (not per-node). +message ValueFee { + Fee fee = 1; // { amount: "0.03", unit: "PERCENTAGE" } + ExecutionTier tier = 2; // Pricing group (TIER_1, TIER_2, TIER_3) + string value_base = 3; // What the percentage applies to (e.g., "input_token_value") + string classification_method = 4; // "rule_based" (V1) or "llm" (V2) + float confidence = 5; // Classification confidence (0.0–1.0) + string reason = 6; // Why this tier was assigned } -// Promotional discounts and fee reductions +// Promotional discount message FeeDiscount { - string discount_type = 1; // "new_user", "volume", "promotional", "beta_program" - string discount_name = 2; // Human-readable discount name - string applies_to = 3; // "gas_fees", "automation_fees", "creation_fees", "all" - float discount_percentage = 4; // Discount percentage (0.0 to 100.0) - FeeAmount discount_amount = 5; // Absolute discount amount - string expiry_date = 6; // When discount expires (ISO 8601 format) - string terms = 7; // Terms and conditions for discount + string discount_type = 1; // "new_user", "volume", "promotional", "beta_program" + string discount_name = 2; + Fee discount = 3; // Discount amount or percentage + string expiry_date = 4; + string terms = 5; } // Response message for EstimateFees +// All fees are per-execution. No totals — client computes. +// Components: execution_fee (USD) + cogs[] (WEI) + value_fee (PERCENTAGE) message EstimateFeesResp { - bool success = 1; // Whether fee estimation was successful - string error = 2; // Error message if estimation failed - ErrorCode error_code = 3; // Structured error code - - // Fee breakdown - GasFeeBreakdown gas_fees = 4; // Estimated gas fees - AutomationFee automation_fees = 5; // Automation and monitoring fees - SmartWalletCreationFee creation_fees = 6; // Smart wallet creation fees (if needed) - - // Total fees - FeeAmount total_fees = 7; // Sum of all fees - - // Discounts and promotions - repeated FeeDiscount discounts = 8; // Applied discounts - FeeAmount total_discounts = 9; // Total discount amount - FeeAmount final_total = 10; // Final total after discounts - - // Estimation metadata - int64 estimated_at = 11; // Timestamp when estimation was performed - string chain_id = 12; // Blockchain chain ID - string price_data_source = 13; // Source of price data ("coingecko", "chainlink", "cached") - int64 price_data_age_seconds = 14; // Age of price data in seconds - - // Warnings and recommendations - repeated string warnings = 15; // Warnings about fee estimation - repeated string recommendations = 16; // Recommendations for cost optimization + bool success = 1; + string error = 2; + ErrorCode error_code = 3; + + // Chain and token context + string chain_id = 4; + NativeToken native_token = 5; + + // Flat per-execution platform fee + Fee execution_fee = 6; + + // Cost of goods sold — per-node operational costs (gas, external API) + repeated NodeCOGS cogs = 7; + + // Workflow-level value-capture fee (single, not per-node) + ValueFee value_fee = 8; + + // Discounts (client sums if needed) + repeated FeeDiscount discounts = 9; + + // Pricing metadata + string pricing_model = 10; // "v1" + repeated string warnings = 11; } // EventCondition represents a condition to evaluate on decoded event data diff --git a/grpc_codegen/avs_pb.d.ts b/grpc_codegen/avs_pb.d.ts index 5f50a0d8..0a2dad1b 100644 --- a/grpc_codegen/avs_pb.d.ts +++ b/grpc_codegen/avs_pb.d.ts @@ -1809,13 +1809,20 @@ export class Execution extends jspb.Message { setError(value: string): Execution; getIndex(): number; setIndex(value: number): Execution; - getTotalGasCost(): string; - setTotalGasCost(value: string): Execution; - hasAutomationFee(): boolean; - clearAutomationFee(): void; - getAutomationFee(): FeeAmount | undefined; - setAutomationFee(value?: FeeAmount): Execution; + hasExecutionFee(): boolean; + clearExecutionFee(): void; + getExecutionFee(): Fee | undefined; + setExecutionFee(value?: Fee): Execution; + clearCogsList(): void; + getCogsList(): Array; + setCogsList(value: Array): Execution; + addCogs(value?: NodeCOGS, index?: number): NodeCOGS; + + hasValueFee(): boolean; + clearValueFee(): void; + getValueFee(): ValueFee | undefined; + setValueFee(value?: ValueFee): Execution; clearStepsList(): void; getStepsList(): Array; setStepsList(value: Array): Execution; @@ -1839,8 +1846,9 @@ export namespace Execution { status: ExecutionStatus, error: string, index: number, - totalGasCost: string, - automationFee?: FeeAmount.AsObject, + executionFee?: Fee.AsObject, + cogsList: Array, + valueFee?: ValueFee.AsObject, stepsList: Array, } @@ -3848,50 +3856,119 @@ export namespace SmartWalletCreationFee { } } -export class AutomationFee extends jspb.Message { +export class Fee extends jspb.Message { + getAmount(): string; + setAmount(value: string): Fee; + getUnit(): string; + setUnit(value: string): Fee; - hasBaseFee(): boolean; - clearBaseFee(): void; - getBaseFee(): FeeAmount | undefined; - setBaseFee(value?: FeeAmount): AutomationFee; + serializeBinary(): Uint8Array; + toObject(includeInstance?: boolean): Fee.AsObject; + static toObject(includeInstance: boolean, msg: Fee): Fee.AsObject; + static extensions: {[key: number]: jspb.ExtensionFieldInfo}; + static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo}; + static serializeBinaryToWriter(message: Fee, writer: jspb.BinaryWriter): void; + static deserializeBinary(bytes: Uint8Array): Fee; + static deserializeBinaryFromReader(message: Fee, reader: jspb.BinaryReader): Fee; +} - hasMonitoringFee(): boolean; - clearMonitoringFee(): void; - getMonitoringFee(): FeeAmount | undefined; - setMonitoringFee(value?: FeeAmount): AutomationFee; +export namespace Fee { + export type AsObject = { + amount: string, + unit: string, + } +} - hasExecutionFee(): boolean; - clearExecutionFee(): void; - getExecutionFee(): FeeAmount | undefined; - setExecutionFee(value?: FeeAmount): AutomationFee; - getTriggerType(): string; - setTriggerType(value: string): AutomationFee; - getEstimatedExecutions(): number; - setEstimatedExecutions(value: number): AutomationFee; - getDurationMinutes(): number; - setDurationMinutes(value: number): AutomationFee; - getFeeCalculationMethod(): string; - setFeeCalculationMethod(value: string): AutomationFee; +export class NativeToken extends jspb.Message { + getSymbol(): string; + setSymbol(value: string): NativeToken; + getDecimals(): number; + setDecimals(value: number): NativeToken; + + serializeBinary(): Uint8Array; + toObject(includeInstance?: boolean): NativeToken.AsObject; + static toObject(includeInstance: boolean, msg: NativeToken): NativeToken.AsObject; + static extensions: {[key: number]: jspb.ExtensionFieldInfo}; + static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo}; + static serializeBinaryToWriter(message: NativeToken, writer: jspb.BinaryWriter): void; + static deserializeBinary(bytes: Uint8Array): NativeToken; + static deserializeBinaryFromReader(message: NativeToken, reader: jspb.BinaryReader): NativeToken; +} + +export namespace NativeToken { + export type AsObject = { + symbol: string, + decimals: number, + } +} + +export class NodeCOGS extends jspb.Message { + getNodeId(): string; + setNodeId(value: string): NodeCOGS; + getCostType(): string; + setCostType(value: string): NodeCOGS; + + hasFee(): boolean; + clearFee(): void; + getFee(): Fee | undefined; + setFee(value?: Fee): NodeCOGS; + getGasUnits(): string; + setGasUnits(value: string): NodeCOGS; + + serializeBinary(): Uint8Array; + toObject(includeInstance?: boolean): NodeCOGS.AsObject; + static toObject(includeInstance: boolean, msg: NodeCOGS): NodeCOGS.AsObject; + static extensions: {[key: number]: jspb.ExtensionFieldInfo}; + static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo}; + static serializeBinaryToWriter(message: NodeCOGS, writer: jspb.BinaryWriter): void; + static deserializeBinary(bytes: Uint8Array): NodeCOGS; + static deserializeBinaryFromReader(message: NodeCOGS, reader: jspb.BinaryReader): NodeCOGS; +} + +export namespace NodeCOGS { + export type AsObject = { + nodeId: string, + costType: string, + fee?: Fee.AsObject, + gasUnits: string, + } +} + +export class ValueFee extends jspb.Message { + + hasFee(): boolean; + clearFee(): void; + getFee(): Fee | undefined; + setFee(value?: Fee): ValueFee; + getTier(): ExecutionTier; + setTier(value: ExecutionTier): ValueFee; + getValueBase(): string; + setValueBase(value: string): ValueFee; + getClassificationMethod(): string; + setClassificationMethod(value: string): ValueFee; + getConfidence(): number; + setConfidence(value: number): ValueFee; + getReason(): string; + setReason(value: string): ValueFee; serializeBinary(): Uint8Array; - toObject(includeInstance?: boolean): AutomationFee.AsObject; - static toObject(includeInstance: boolean, msg: AutomationFee): AutomationFee.AsObject; + toObject(includeInstance?: boolean): ValueFee.AsObject; + static toObject(includeInstance: boolean, msg: ValueFee): ValueFee.AsObject; static extensions: {[key: number]: jspb.ExtensionFieldInfo}; static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo}; - static serializeBinaryToWriter(message: AutomationFee, writer: jspb.BinaryWriter): void; - static deserializeBinary(bytes: Uint8Array): AutomationFee; - static deserializeBinaryFromReader(message: AutomationFee, reader: jspb.BinaryReader): AutomationFee; + static serializeBinaryToWriter(message: ValueFee, writer: jspb.BinaryWriter): void; + static deserializeBinary(bytes: Uint8Array): ValueFee; + static deserializeBinaryFromReader(message: ValueFee, reader: jspb.BinaryReader): ValueFee; } -export namespace AutomationFee { +export namespace ValueFee { export type AsObject = { - baseFee?: FeeAmount.AsObject, - monitoringFee?: FeeAmount.AsObject, - executionFee?: FeeAmount.AsObject, - triggerType: string, - estimatedExecutions: number, - durationMinutes: number, - feeCalculationMethod: string, + fee?: Fee.AsObject, + tier: ExecutionTier, + valueBase: string, + classificationMethod: string, + confidence: number, + reason: string, } } @@ -3900,15 +3977,11 @@ export class FeeDiscount extends jspb.Message { setDiscountType(value: string): FeeDiscount; getDiscountName(): string; setDiscountName(value: string): FeeDiscount; - getAppliesTo(): string; - setAppliesTo(value: string): FeeDiscount; - getDiscountPercentage(): number; - setDiscountPercentage(value: number): FeeDiscount; - - hasDiscountAmount(): boolean; - clearDiscountAmount(): void; - getDiscountAmount(): FeeAmount | undefined; - setDiscountAmount(value?: FeeAmount): FeeDiscount; + + hasDiscount(): boolean; + clearDiscount(): void; + getDiscount(): Fee | undefined; + setDiscount(value?: Fee): FeeDiscount; getExpiryDate(): string; setExpiryDate(value: string): FeeDiscount; getTerms(): string; @@ -3928,9 +4001,7 @@ export namespace FeeDiscount { export type AsObject = { discountType: string, discountName: string, - appliesTo: string, - discountPercentage: number, - discountAmount?: FeeAmount.AsObject, + discount?: Fee.AsObject, expiryDate: string, terms: string, } @@ -3943,56 +4014,37 @@ export class EstimateFeesResp extends jspb.Message { setError(value: string): EstimateFeesResp; getErrorCode(): ErrorCode; setErrorCode(value: ErrorCode): EstimateFeesResp; + getChainId(): string; + setChainId(value: string): EstimateFeesResp; + + hasNativeToken(): boolean; + clearNativeToken(): void; + getNativeToken(): NativeToken | undefined; + setNativeToken(value?: NativeToken): EstimateFeesResp; - hasGasFees(): boolean; - clearGasFees(): void; - getGasFees(): GasFeeBreakdown | undefined; - setGasFees(value?: GasFeeBreakdown): EstimateFeesResp; - - hasAutomationFees(): boolean; - clearAutomationFees(): void; - getAutomationFees(): AutomationFee | undefined; - setAutomationFees(value?: AutomationFee): EstimateFeesResp; - - hasCreationFees(): boolean; - clearCreationFees(): void; - getCreationFees(): SmartWalletCreationFee | undefined; - setCreationFees(value?: SmartWalletCreationFee): EstimateFeesResp; - - hasTotalFees(): boolean; - clearTotalFees(): void; - getTotalFees(): FeeAmount | undefined; - setTotalFees(value?: FeeAmount): EstimateFeesResp; + hasExecutionFee(): boolean; + clearExecutionFee(): void; + getExecutionFee(): Fee | undefined; + setExecutionFee(value?: Fee): EstimateFeesResp; + clearCogsList(): void; + getCogsList(): Array; + setCogsList(value: Array): EstimateFeesResp; + addCogs(value?: NodeCOGS, index?: number): NodeCOGS; + + hasValueFee(): boolean; + clearValueFee(): void; + getValueFee(): ValueFee | undefined; + setValueFee(value?: ValueFee): EstimateFeesResp; clearDiscountsList(): void; getDiscountsList(): Array; setDiscountsList(value: Array): EstimateFeesResp; addDiscounts(value?: FeeDiscount, index?: number): FeeDiscount; - - hasTotalDiscounts(): boolean; - clearTotalDiscounts(): void; - getTotalDiscounts(): FeeAmount | undefined; - setTotalDiscounts(value?: FeeAmount): EstimateFeesResp; - - hasFinalTotal(): boolean; - clearFinalTotal(): void; - getFinalTotal(): FeeAmount | undefined; - setFinalTotal(value?: FeeAmount): EstimateFeesResp; - getEstimatedAt(): number; - setEstimatedAt(value: number): EstimateFeesResp; - getChainId(): string; - setChainId(value: string): EstimateFeesResp; - getPriceDataSource(): string; - setPriceDataSource(value: string): EstimateFeesResp; - getPriceDataAgeSeconds(): number; - setPriceDataAgeSeconds(value: number): EstimateFeesResp; + getPricingModel(): string; + setPricingModel(value: string): EstimateFeesResp; clearWarningsList(): void; getWarningsList(): Array; setWarningsList(value: Array): EstimateFeesResp; addWarnings(value: string, index?: number): string; - clearRecommendationsList(): void; - getRecommendationsList(): Array; - setRecommendationsList(value: Array): EstimateFeesResp; - addRecommendations(value: string, index?: number): string; serializeBinary(): Uint8Array; toObject(includeInstance?: boolean): EstimateFeesResp.AsObject; @@ -4009,19 +4061,14 @@ export namespace EstimateFeesResp { success: boolean, error: string, errorCode: ErrorCode, - gasFees?: GasFeeBreakdown.AsObject, - automationFees?: AutomationFee.AsObject, - creationFees?: SmartWalletCreationFee.AsObject, - totalFees?: FeeAmount.AsObject, - discountsList: Array, - totalDiscounts?: FeeAmount.AsObject, - finalTotal?: FeeAmount.AsObject, - estimatedAt: number, chainId: string, - priceDataSource: string, - priceDataAgeSeconds: number, + nativeToken?: NativeToken.AsObject, + executionFee?: Fee.AsObject, + cogsList: Array, + valueFee?: ValueFee.AsObject, + discountsList: Array, + pricingModel: string, warningsList: Array, - recommendationsList: Array, } } @@ -4077,6 +4124,13 @@ export enum NodeType { NODE_TYPE_BALANCE = 10, } +export enum ExecutionTier { + EXECUTION_TIER_UNSPECIFIED = 0, + EXECUTION_TIER_1 = 1, + EXECUTION_TIER_2 = 2, + EXECUTION_TIER_3 = 3, +} + export enum ExecutionMode { EXECUTION_MODE_SEQUENTIAL = 0, EXECUTION_MODE_PARALLEL = 1, @@ -4130,6 +4184,7 @@ export enum ErrorCode { SMART_WALLET_NOT_FOUND = 8001, SMART_WALLET_DEPLOYMENT_ERROR = 8002, INSUFFICIENT_BALANCE = 8003, + INSUFFICIENT_CREDIT = 8004, } export enum TaskStatus { diff --git a/grpc_codegen/avs_pb.js b/grpc_codegen/avs_pb.js index 77be68fb..fd05990e 100644 --- a/grpc_codegen/avs_pb.js +++ b/grpc_codegen/avs_pb.js @@ -23,7 +23,6 @@ var global = (function() { var google_protobuf_struct_pb = require('google-protobuf/google/protobuf/struct_pb.js'); goog.object.extend(proto, google_protobuf_struct_pb); -goog.exportSymbol('proto.aggregator.AutomationFee', null, global); goog.exportSymbol('proto.aggregator.BalanceNode', null, global); goog.exportSymbol('proto.aggregator.BalanceNode.Config', null, global); goog.exportSymbol('proto.aggregator.BalanceNode.Output', null, global); @@ -77,6 +76,8 @@ goog.exportSymbol('proto.aggregator.ExecutionMode', null, global); goog.exportSymbol('proto.aggregator.ExecutionReq', null, global); goog.exportSymbol('proto.aggregator.ExecutionStatus', null, global); goog.exportSymbol('proto.aggregator.ExecutionStatusResp', null, global); +goog.exportSymbol('proto.aggregator.ExecutionTier', null, global); +goog.exportSymbol('proto.aggregator.Fee', null, global); goog.exportSymbol('proto.aggregator.FeeAmount', null, global); goog.exportSymbol('proto.aggregator.FeeDiscount', null, global); goog.exportSymbol('proto.aggregator.FilterNode', null, global); @@ -121,6 +122,8 @@ goog.exportSymbol('proto.aggregator.LoopNode.RunnerCase', null, global); goog.exportSymbol('proto.aggregator.ManualTrigger', null, global); goog.exportSymbol('proto.aggregator.ManualTrigger.Config', null, global); goog.exportSymbol('proto.aggregator.ManualTrigger.Output', null, global); +goog.exportSymbol('proto.aggregator.NativeToken', null, global); +goog.exportSymbol('proto.aggregator.NodeCOGS', null, global); goog.exportSymbol('proto.aggregator.NodeType', null, global); goog.exportSymbol('proto.aggregator.NonceRequest', null, global); goog.exportSymbol('proto.aggregator.NonceResp', null, global); @@ -154,6 +157,7 @@ goog.exportSymbol('proto.aggregator.TriggerTaskReq.TriggerOutputCase', null, glo goog.exportSymbol('proto.aggregator.TriggerTaskResp', null, global); goog.exportSymbol('proto.aggregator.TriggerType', null, global); goog.exportSymbol('proto.aggregator.UpdateSecretResp', null, global); +goog.exportSymbol('proto.aggregator.ValueFee', null, global); goog.exportSymbol('proto.aggregator.WithdrawFundsReq', null, global); goog.exportSymbol('proto.aggregator.WithdrawFundsResp', null, global); /** @@ -2581,16 +2585,79 @@ if (goog.DEBUG && !COMPILED) { * @extends {jspb.Message} * @constructor */ -proto.aggregator.AutomationFee = function(opt_data) { +proto.aggregator.Fee = function(opt_data) { jspb.Message.initialize(this, opt_data, 0, -1, null, null); }; -goog.inherits(proto.aggregator.AutomationFee, jspb.Message); +goog.inherits(proto.aggregator.Fee, jspb.Message); if (goog.DEBUG && !COMPILED) { /** * @public * @override */ - proto.aggregator.AutomationFee.displayName = 'proto.aggregator.AutomationFee'; + proto.aggregator.Fee.displayName = 'proto.aggregator.Fee'; +} +/** + * Generated by JsPbCodeGenerator. + * @param {Array=} opt_data Optional initial data array, typically from a + * server response, or constructed directly in Javascript. The array is used + * in place and becomes part of the constructed object. It is not cloned. + * If no data is provided, the constructed object will be empty, but still + * valid. + * @extends {jspb.Message} + * @constructor + */ +proto.aggregator.NativeToken = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, null, null); +}; +goog.inherits(proto.aggregator.NativeToken, jspb.Message); +if (goog.DEBUG && !COMPILED) { + /** + * @public + * @override + */ + proto.aggregator.NativeToken.displayName = 'proto.aggregator.NativeToken'; +} +/** + * Generated by JsPbCodeGenerator. + * @param {Array=} opt_data Optional initial data array, typically from a + * server response, or constructed directly in Javascript. The array is used + * in place and becomes part of the constructed object. It is not cloned. + * If no data is provided, the constructed object will be empty, but still + * valid. + * @extends {jspb.Message} + * @constructor + */ +proto.aggregator.NodeCOGS = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, null, null); +}; +goog.inherits(proto.aggregator.NodeCOGS, jspb.Message); +if (goog.DEBUG && !COMPILED) { + /** + * @public + * @override + */ + proto.aggregator.NodeCOGS.displayName = 'proto.aggregator.NodeCOGS'; +} +/** + * Generated by JsPbCodeGenerator. + * @param {Array=} opt_data Optional initial data array, typically from a + * server response, or constructed directly in Javascript. The array is used + * in place and becomes part of the constructed object. It is not cloned. + * If no data is provided, the constructed object will be empty, but still + * valid. + * @extends {jspb.Message} + * @constructor + */ +proto.aggregator.ValueFee = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, null, null); +}; +goog.inherits(proto.aggregator.ValueFee, jspb.Message); +if (goog.DEBUG && !COMPILED) { + /** + * @public + * @override + */ + proto.aggregator.ValueFee.displayName = 'proto.aggregator.ValueFee'; } /** * Generated by JsPbCodeGenerator. @@ -15120,7 +15187,7 @@ proto.aggregator.TaskNode.prototype.hasBalance = function() { * @private {!Array} * @const */ -proto.aggregator.Execution.repeatedFields_ = [8]; +proto.aggregator.Execution.repeatedFields_ = [9,8]; @@ -15159,8 +15226,10 @@ proto.aggregator.Execution.toObject = function(includeInstance, msg) { status: jspb.Message.getFieldWithDefault(msg, 4, 0), error: jspb.Message.getFieldWithDefault(msg, 5, ""), index: jspb.Message.getFieldWithDefault(msg, 6, 0), - totalGasCost: jspb.Message.getFieldWithDefault(msg, 7, ""), - automationFee: (f = msg.getAutomationFee()) && proto.aggregator.FeeAmount.toObject(includeInstance, f), + executionFee: (f = msg.getExecutionFee()) && proto.aggregator.Fee.toObject(includeInstance, f), + cogsList: jspb.Message.toObjectList(msg.getCogsList(), + proto.aggregator.NodeCOGS.toObject, includeInstance), + valueFee: (f = msg.getValueFee()) && proto.aggregator.ValueFee.toObject(includeInstance, f), stepsList: jspb.Message.toObjectList(msg.getStepsList(), proto.aggregator.Execution.Step.toObject, includeInstance) }; @@ -15224,13 +15293,19 @@ proto.aggregator.Execution.deserializeBinaryFromReader = function(msg, reader) { msg.setIndex(value); break; case 7: - var value = /** @type {string} */ (reader.readString()); - msg.setTotalGasCost(value); + var value = new proto.aggregator.Fee; + reader.readMessage(value,proto.aggregator.Fee.deserializeBinaryFromReader); + msg.setExecutionFee(value); break; case 9: - var value = new proto.aggregator.FeeAmount; - reader.readMessage(value,proto.aggregator.FeeAmount.deserializeBinaryFromReader); - msg.setAutomationFee(value); + var value = new proto.aggregator.NodeCOGS; + reader.readMessage(value,proto.aggregator.NodeCOGS.deserializeBinaryFromReader); + msg.addCogs(value); + break; + case 10: + var value = new proto.aggregator.ValueFee; + reader.readMessage(value,proto.aggregator.ValueFee.deserializeBinaryFromReader); + msg.setValueFee(value); break; case 8: var value = new proto.aggregator.Execution.Step; @@ -15308,19 +15383,28 @@ proto.aggregator.Execution.serializeBinaryToWriter = function(message, writer) { f ); } - f = message.getTotalGasCost(); - if (f.length > 0) { - writer.writeString( + f = message.getExecutionFee(); + if (f != null) { + writer.writeMessage( 7, - f + f, + proto.aggregator.Fee.serializeBinaryToWriter + ); + } + f = message.getCogsList(); + if (f.length > 0) { + writer.writeRepeatedMessage( + 9, + f, + proto.aggregator.NodeCOGS.serializeBinaryToWriter ); } - f = message.getAutomationFee(); + f = message.getValueFee(); if (f != null) { writer.writeMessage( - 9, + 10, f, - proto.aggregator.FeeAmount.serializeBinaryToWriter + proto.aggregator.ValueFee.serializeBinaryToWriter ); } f = message.getStepsList(); @@ -16916,39 +17000,96 @@ proto.aggregator.Execution.prototype.setIndex = function(value) { /** - * optional string total_gas_cost = 7; - * @return {string} + * optional Fee execution_fee = 7; + * @return {?proto.aggregator.Fee} */ -proto.aggregator.Execution.prototype.getTotalGasCost = function() { - return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 7, "")); +proto.aggregator.Execution.prototype.getExecutionFee = function() { + return /** @type{?proto.aggregator.Fee} */ ( + jspb.Message.getWrapperField(this, proto.aggregator.Fee, 7)); }; /** - * @param {string} value + * @param {?proto.aggregator.Fee|undefined} value + * @return {!proto.aggregator.Execution} returns this +*/ +proto.aggregator.Execution.prototype.setExecutionFee = function(value) { + return jspb.Message.setWrapperField(this, 7, value); +}; + + +/** + * Clears the message field making it undefined. * @return {!proto.aggregator.Execution} returns this */ -proto.aggregator.Execution.prototype.setTotalGasCost = function(value) { - return jspb.Message.setProto3StringField(this, 7, value); +proto.aggregator.Execution.prototype.clearExecutionFee = function() { + return this.setExecutionFee(undefined); }; /** - * optional FeeAmount automation_fee = 9; - * @return {?proto.aggregator.FeeAmount} + * Returns whether this field is set. + * @return {boolean} */ -proto.aggregator.Execution.prototype.getAutomationFee = function() { - return /** @type{?proto.aggregator.FeeAmount} */ ( - jspb.Message.getWrapperField(this, proto.aggregator.FeeAmount, 9)); +proto.aggregator.Execution.prototype.hasExecutionFee = function() { + return jspb.Message.getField(this, 7) != null; }; /** - * @param {?proto.aggregator.FeeAmount|undefined} value + * repeated NodeCOGS cogs = 9; + * @return {!Array} + */ +proto.aggregator.Execution.prototype.getCogsList = function() { + return /** @type{!Array} */ ( + jspb.Message.getRepeatedWrapperField(this, proto.aggregator.NodeCOGS, 9)); +}; + + +/** + * @param {!Array} value + * @return {!proto.aggregator.Execution} returns this +*/ +proto.aggregator.Execution.prototype.setCogsList = function(value) { + return jspb.Message.setRepeatedWrapperField(this, 9, value); +}; + + +/** + * @param {!proto.aggregator.NodeCOGS=} opt_value + * @param {number=} opt_index + * @return {!proto.aggregator.NodeCOGS} + */ +proto.aggregator.Execution.prototype.addCogs = function(opt_value, opt_index) { + return jspb.Message.addToRepeatedWrapperField(this, 9, opt_value, proto.aggregator.NodeCOGS, opt_index); +}; + + +/** + * Clears the list making it empty but non-null. + * @return {!proto.aggregator.Execution} returns this + */ +proto.aggregator.Execution.prototype.clearCogsList = function() { + return this.setCogsList([]); +}; + + +/** + * optional ValueFee value_fee = 10; + * @return {?proto.aggregator.ValueFee} + */ +proto.aggregator.Execution.prototype.getValueFee = function() { + return /** @type{?proto.aggregator.ValueFee} */ ( + jspb.Message.getWrapperField(this, proto.aggregator.ValueFee, 10)); +}; + + +/** + * @param {?proto.aggregator.ValueFee|undefined} value * @return {!proto.aggregator.Execution} returns this */ -proto.aggregator.Execution.prototype.setAutomationFee = function(value) { - return jspb.Message.setWrapperField(this, 9, value); +proto.aggregator.Execution.prototype.setValueFee = function(value) { + return jspb.Message.setWrapperField(this, 10, value); }; @@ -16956,8 +17097,8 @@ proto.aggregator.Execution.prototype.setAutomationFee = function(value) { * Clears the message field making it undefined. * @return {!proto.aggregator.Execution} returns this */ -proto.aggregator.Execution.prototype.clearAutomationFee = function() { - return this.setAutomationFee(undefined); +proto.aggregator.Execution.prototype.clearValueFee = function() { + return this.setValueFee(undefined); }; @@ -16965,8 +17106,8 @@ proto.aggregator.Execution.prototype.clearAutomationFee = function() { * Returns whether this field is set. * @return {boolean} */ -proto.aggregator.Execution.prototype.hasAutomationFee = function() { - return jspb.Message.getField(this, 9) != null; +proto.aggregator.Execution.prototype.hasValueFee = function() { + return jspb.Message.getField(this, 10) != null; }; @@ -30780,8 +30921,8 @@ if (jspb.Message.GENERATE_TO_OBJECT) { * http://goto/soy-param-migration * @return {!Object} */ -proto.aggregator.AutomationFee.prototype.toObject = function(opt_includeInstance) { - return proto.aggregator.AutomationFee.toObject(opt_includeInstance, this); +proto.aggregator.Fee.prototype.toObject = function(opt_includeInstance) { + return proto.aggregator.Fee.toObject(opt_includeInstance, this); }; @@ -30790,19 +30931,14 @@ proto.aggregator.AutomationFee.prototype.toObject = function(opt_includeInstance * @param {boolean|undefined} includeInstance Deprecated. Whether to include * the JSPB instance for transitional soy proto support: * http://goto/soy-param-migration - * @param {!proto.aggregator.AutomationFee} msg The msg instance to transform. + * @param {!proto.aggregator.Fee} msg The msg instance to transform. * @return {!Object} * @suppress {unusedLocalVariables} f is only used for nested messages */ -proto.aggregator.AutomationFee.toObject = function(includeInstance, msg) { +proto.aggregator.Fee.toObject = function(includeInstance, msg) { var f, obj = { - baseFee: (f = msg.getBaseFee()) && proto.aggregator.FeeAmount.toObject(includeInstance, f), - monitoringFee: (f = msg.getMonitoringFee()) && proto.aggregator.FeeAmount.toObject(includeInstance, f), - executionFee: (f = msg.getExecutionFee()) && proto.aggregator.FeeAmount.toObject(includeInstance, f), - triggerType: jspb.Message.getFieldWithDefault(msg, 4, ""), - estimatedExecutions: jspb.Message.getFieldWithDefault(msg, 5, 0), - durationMinutes: jspb.Message.getFieldWithDefault(msg, 6, 0), - feeCalculationMethod: jspb.Message.getFieldWithDefault(msg, 7, "") + amount: jspb.Message.getFieldWithDefault(msg, 1, ""), + unit: jspb.Message.getFieldWithDefault(msg, 2, "") }; if (includeInstance) { @@ -30816,23 +30952,23 @@ proto.aggregator.AutomationFee.toObject = function(includeInstance, msg) { /** * Deserializes binary data (in protobuf wire format). * @param {jspb.ByteSource} bytes The bytes to deserialize. - * @return {!proto.aggregator.AutomationFee} + * @return {!proto.aggregator.Fee} */ -proto.aggregator.AutomationFee.deserializeBinary = function(bytes) { +proto.aggregator.Fee.deserializeBinary = function(bytes) { var reader = new jspb.BinaryReader(bytes); - var msg = new proto.aggregator.AutomationFee; - return proto.aggregator.AutomationFee.deserializeBinaryFromReader(msg, reader); + var msg = new proto.aggregator.Fee; + return proto.aggregator.Fee.deserializeBinaryFromReader(msg, reader); }; /** * Deserializes binary data (in protobuf wire format) from the * given reader into the given message object. - * @param {!proto.aggregator.AutomationFee} msg The message object to deserialize into. + * @param {!proto.aggregator.Fee} msg The message object to deserialize into. * @param {!jspb.BinaryReader} reader The BinaryReader to use. - * @return {!proto.aggregator.AutomationFee} + * @return {!proto.aggregator.Fee} */ -proto.aggregator.AutomationFee.deserializeBinaryFromReader = function(msg, reader) { +proto.aggregator.Fee.deserializeBinaryFromReader = function(msg, reader) { while (reader.nextField()) { if (reader.isEndGroup()) { break; @@ -30840,35 +30976,12 @@ proto.aggregator.AutomationFee.deserializeBinaryFromReader = function(msg, reade var field = reader.getFieldNumber(); switch (field) { case 1: - var value = new proto.aggregator.FeeAmount; - reader.readMessage(value,proto.aggregator.FeeAmount.deserializeBinaryFromReader); - msg.setBaseFee(value); - break; - case 2: - var value = new proto.aggregator.FeeAmount; - reader.readMessage(value,proto.aggregator.FeeAmount.deserializeBinaryFromReader); - msg.setMonitoringFee(value); - break; - case 3: - var value = new proto.aggregator.FeeAmount; - reader.readMessage(value,proto.aggregator.FeeAmount.deserializeBinaryFromReader); - msg.setExecutionFee(value); - break; - case 4: var value = /** @type {string} */ (reader.readString()); - msg.setTriggerType(value); - break; - case 5: - var value = /** @type {number} */ (reader.readInt64()); - msg.setEstimatedExecutions(value); - break; - case 6: - var value = /** @type {number} */ (reader.readInt64()); - msg.setDurationMinutes(value); + msg.setAmount(value); break; - case 7: + case 2: var value = /** @type {string} */ (reader.readString()); - msg.setFeeCalculationMethod(value); + msg.setUnit(value); break; default: reader.skipField(); @@ -30883,9 +30996,9 @@ proto.aggregator.AutomationFee.deserializeBinaryFromReader = function(msg, reade * Serializes the message to binary data (in protobuf wire format). * @return {!Uint8Array} */ -proto.aggregator.AutomationFee.prototype.serializeBinary = function() { +proto.aggregator.Fee.prototype.serializeBinary = function() { var writer = new jspb.BinaryWriter(); - proto.aggregator.AutomationFee.serializeBinaryToWriter(this, writer); + proto.aggregator.Fee.serializeBinaryToWriter(this, writer); return writer.getResultBuffer(); }; @@ -30893,61 +31006,23 @@ proto.aggregator.AutomationFee.prototype.serializeBinary = function() { /** * Serializes the given message to binary data (in protobuf wire * format), writing to the given BinaryWriter. - * @param {!proto.aggregator.AutomationFee} message + * @param {!proto.aggregator.Fee} message * @param {!jspb.BinaryWriter} writer * @suppress {unusedLocalVariables} f is only used for nested messages */ -proto.aggregator.AutomationFee.serializeBinaryToWriter = function(message, writer) { +proto.aggregator.Fee.serializeBinaryToWriter = function(message, writer) { var f = undefined; - f = message.getBaseFee(); - if (f != null) { - writer.writeMessage( - 1, - f, - proto.aggregator.FeeAmount.serializeBinaryToWriter - ); - } - f = message.getMonitoringFee(); - if (f != null) { - writer.writeMessage( - 2, - f, - proto.aggregator.FeeAmount.serializeBinaryToWriter - ); - } - f = message.getExecutionFee(); - if (f != null) { - writer.writeMessage( - 3, - f, - proto.aggregator.FeeAmount.serializeBinaryToWriter - ); - } - f = message.getTriggerType(); + f = message.getAmount(); if (f.length > 0) { writer.writeString( - 4, - f - ); - } - f = message.getEstimatedExecutions(); - if (f !== 0) { - writer.writeInt64( - 5, - f - ); - } - f = message.getDurationMinutes(); - if (f !== 0) { - writer.writeInt64( - 6, + 1, f ); } - f = message.getFeeCalculationMethod(); + f = message.getUnit(); if (f.length > 0) { writer.writeString( - 7, + 2, f ); } @@ -30955,104 +31030,641 @@ proto.aggregator.AutomationFee.serializeBinaryToWriter = function(message, write /** - * optional FeeAmount base_fee = 1; - * @return {?proto.aggregator.FeeAmount} + * optional string amount = 1; + * @return {string} */ -proto.aggregator.AutomationFee.prototype.getBaseFee = function() { - return /** @type{?proto.aggregator.FeeAmount} */ ( - jspb.Message.getWrapperField(this, proto.aggregator.FeeAmount, 1)); +proto.aggregator.Fee.prototype.getAmount = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, "")); }; /** - * @param {?proto.aggregator.FeeAmount|undefined} value - * @return {!proto.aggregator.AutomationFee} returns this -*/ -proto.aggregator.AutomationFee.prototype.setBaseFee = function(value) { - return jspb.Message.setWrapperField(this, 1, value); + * @param {string} value + * @return {!proto.aggregator.Fee} returns this + */ +proto.aggregator.Fee.prototype.setAmount = function(value) { + return jspb.Message.setProto3StringField(this, 1, value); }; /** - * Clears the message field making it undefined. - * @return {!proto.aggregator.AutomationFee} returns this + * optional string unit = 2; + * @return {string} */ -proto.aggregator.AutomationFee.prototype.clearBaseFee = function() { - return this.setBaseFee(undefined); +proto.aggregator.Fee.prototype.getUnit = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 2, "")); }; /** - * Returns whether this field is set. - * @return {boolean} + * @param {string} value + * @return {!proto.aggregator.Fee} returns this */ -proto.aggregator.AutomationFee.prototype.hasBaseFee = function() { - return jspb.Message.getField(this, 1) != null; +proto.aggregator.Fee.prototype.setUnit = function(value) { + return jspb.Message.setProto3StringField(this, 2, value); }; -/** - * optional FeeAmount monitoring_fee = 2; - * @return {?proto.aggregator.FeeAmount} - */ -proto.aggregator.AutomationFee.prototype.getMonitoringFee = function() { - return /** @type{?proto.aggregator.FeeAmount} */ ( - jspb.Message.getWrapperField(this, proto.aggregator.FeeAmount, 2)); -}; + +if (jspb.Message.GENERATE_TO_OBJECT) { /** - * @param {?proto.aggregator.FeeAmount|undefined} value - * @return {!proto.aggregator.AutomationFee} returns this -*/ -proto.aggregator.AutomationFee.prototype.setMonitoringFee = function(value) { - return jspb.Message.setWrapperField(this, 2, value); + * Creates an object representation of this proto. + * Field names that are reserved in JavaScript and will be renamed to pb_name. + * Optional fields that are not set will be set to undefined. + * To access a reserved field use, foo.pb_, eg, foo.pb_default. + * For the list of reserved names please see: + * net/proto2/compiler/js/internal/generator.cc#kKeyword. + * @param {boolean=} opt_includeInstance Deprecated. whether to include the + * JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @return {!Object} + */ +proto.aggregator.NativeToken.prototype.toObject = function(opt_includeInstance) { + return proto.aggregator.NativeToken.toObject(opt_includeInstance, this); }; /** - * Clears the message field making it undefined. - * @return {!proto.aggregator.AutomationFee} returns this + * Static version of the {@see toObject} method. + * @param {boolean|undefined} includeInstance Deprecated. Whether to include + * the JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @param {!proto.aggregator.NativeToken} msg The msg instance to transform. + * @return {!Object} + * @suppress {unusedLocalVariables} f is only used for nested messages */ -proto.aggregator.AutomationFee.prototype.clearMonitoringFee = function() { - return this.setMonitoringFee(undefined); +proto.aggregator.NativeToken.toObject = function(includeInstance, msg) { + var f, obj = { + symbol: jspb.Message.getFieldWithDefault(msg, 1, ""), + decimals: jspb.Message.getFieldWithDefault(msg, 2, 0) + }; + + if (includeInstance) { + obj.$jspbMessageInstance = msg; + } + return obj; }; +} /** - * Returns whether this field is set. - * @return {boolean} + * Deserializes binary data (in protobuf wire format). + * @param {jspb.ByteSource} bytes The bytes to deserialize. + * @return {!proto.aggregator.NativeToken} */ -proto.aggregator.AutomationFee.prototype.hasMonitoringFee = function() { - return jspb.Message.getField(this, 2) != null; +proto.aggregator.NativeToken.deserializeBinary = function(bytes) { + var reader = new jspb.BinaryReader(bytes); + var msg = new proto.aggregator.NativeToken; + return proto.aggregator.NativeToken.deserializeBinaryFromReader(msg, reader); }; /** - * optional FeeAmount execution_fee = 3; - * @return {?proto.aggregator.FeeAmount} - */ -proto.aggregator.AutomationFee.prototype.getExecutionFee = function() { - return /** @type{?proto.aggregator.FeeAmount} */ ( - jspb.Message.getWrapperField(this, proto.aggregator.FeeAmount, 3)); + * Deserializes binary data (in protobuf wire format) from the + * given reader into the given message object. + * @param {!proto.aggregator.NativeToken} msg The message object to deserialize into. + * @param {!jspb.BinaryReader} reader The BinaryReader to use. + * @return {!proto.aggregator.NativeToken} + */ +proto.aggregator.NativeToken.deserializeBinaryFromReader = function(msg, reader) { + while (reader.nextField()) { + if (reader.isEndGroup()) { + break; + } + var field = reader.getFieldNumber(); + switch (field) { + case 1: + var value = /** @type {string} */ (reader.readString()); + msg.setSymbol(value); + break; + case 2: + var value = /** @type {number} */ (reader.readInt32()); + msg.setDecimals(value); + break; + default: + reader.skipField(); + break; + } + } + return msg; +}; + + +/** + * Serializes the message to binary data (in protobuf wire format). + * @return {!Uint8Array} + */ +proto.aggregator.NativeToken.prototype.serializeBinary = function() { + var writer = new jspb.BinaryWriter(); + proto.aggregator.NativeToken.serializeBinaryToWriter(this, writer); + return writer.getResultBuffer(); +}; + + +/** + * Serializes the given message to binary data (in protobuf wire + * format), writing to the given BinaryWriter. + * @param {!proto.aggregator.NativeToken} message + * @param {!jspb.BinaryWriter} writer + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.aggregator.NativeToken.serializeBinaryToWriter = function(message, writer) { + var f = undefined; + f = message.getSymbol(); + if (f.length > 0) { + writer.writeString( + 1, + f + ); + } + f = message.getDecimals(); + if (f !== 0) { + writer.writeInt32( + 2, + f + ); + } +}; + + +/** + * optional string symbol = 1; + * @return {string} + */ +proto.aggregator.NativeToken.prototype.getSymbol = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, "")); +}; + + +/** + * @param {string} value + * @return {!proto.aggregator.NativeToken} returns this + */ +proto.aggregator.NativeToken.prototype.setSymbol = function(value) { + return jspb.Message.setProto3StringField(this, 1, value); +}; + + +/** + * optional int32 decimals = 2; + * @return {number} + */ +proto.aggregator.NativeToken.prototype.getDecimals = function() { + return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 2, 0)); +}; + + +/** + * @param {number} value + * @return {!proto.aggregator.NativeToken} returns this + */ +proto.aggregator.NativeToken.prototype.setDecimals = function(value) { + return jspb.Message.setProto3IntField(this, 2, value); +}; + + + + + +if (jspb.Message.GENERATE_TO_OBJECT) { +/** + * Creates an object representation of this proto. + * Field names that are reserved in JavaScript and will be renamed to pb_name. + * Optional fields that are not set will be set to undefined. + * To access a reserved field use, foo.pb_, eg, foo.pb_default. + * For the list of reserved names please see: + * net/proto2/compiler/js/internal/generator.cc#kKeyword. + * @param {boolean=} opt_includeInstance Deprecated. whether to include the + * JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @return {!Object} + */ +proto.aggregator.NodeCOGS.prototype.toObject = function(opt_includeInstance) { + return proto.aggregator.NodeCOGS.toObject(opt_includeInstance, this); +}; + + +/** + * Static version of the {@see toObject} method. + * @param {boolean|undefined} includeInstance Deprecated. Whether to include + * the JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @param {!proto.aggregator.NodeCOGS} msg The msg instance to transform. + * @return {!Object} + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.aggregator.NodeCOGS.toObject = function(includeInstance, msg) { + var f, obj = { + nodeId: jspb.Message.getFieldWithDefault(msg, 1, ""), + costType: jspb.Message.getFieldWithDefault(msg, 2, ""), + fee: (f = msg.getFee()) && proto.aggregator.Fee.toObject(includeInstance, f), + gasUnits: jspb.Message.getFieldWithDefault(msg, 4, "") + }; + + if (includeInstance) { + obj.$jspbMessageInstance = msg; + } + return obj; +}; +} + + +/** + * Deserializes binary data (in protobuf wire format). + * @param {jspb.ByteSource} bytes The bytes to deserialize. + * @return {!proto.aggregator.NodeCOGS} + */ +proto.aggregator.NodeCOGS.deserializeBinary = function(bytes) { + var reader = new jspb.BinaryReader(bytes); + var msg = new proto.aggregator.NodeCOGS; + return proto.aggregator.NodeCOGS.deserializeBinaryFromReader(msg, reader); +}; + + +/** + * Deserializes binary data (in protobuf wire format) from the + * given reader into the given message object. + * @param {!proto.aggregator.NodeCOGS} msg The message object to deserialize into. + * @param {!jspb.BinaryReader} reader The BinaryReader to use. + * @return {!proto.aggregator.NodeCOGS} + */ +proto.aggregator.NodeCOGS.deserializeBinaryFromReader = function(msg, reader) { + while (reader.nextField()) { + if (reader.isEndGroup()) { + break; + } + var field = reader.getFieldNumber(); + switch (field) { + case 1: + var value = /** @type {string} */ (reader.readString()); + msg.setNodeId(value); + break; + case 2: + var value = /** @type {string} */ (reader.readString()); + msg.setCostType(value); + break; + case 3: + var value = new proto.aggregator.Fee; + reader.readMessage(value,proto.aggregator.Fee.deserializeBinaryFromReader); + msg.setFee(value); + break; + case 4: + var value = /** @type {string} */ (reader.readString()); + msg.setGasUnits(value); + break; + default: + reader.skipField(); + break; + } + } + return msg; +}; + + +/** + * Serializes the message to binary data (in protobuf wire format). + * @return {!Uint8Array} + */ +proto.aggregator.NodeCOGS.prototype.serializeBinary = function() { + var writer = new jspb.BinaryWriter(); + proto.aggregator.NodeCOGS.serializeBinaryToWriter(this, writer); + return writer.getResultBuffer(); +}; + + +/** + * Serializes the given message to binary data (in protobuf wire + * format), writing to the given BinaryWriter. + * @param {!proto.aggregator.NodeCOGS} message + * @param {!jspb.BinaryWriter} writer + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.aggregator.NodeCOGS.serializeBinaryToWriter = function(message, writer) { + var f = undefined; + f = message.getNodeId(); + if (f.length > 0) { + writer.writeString( + 1, + f + ); + } + f = message.getCostType(); + if (f.length > 0) { + writer.writeString( + 2, + f + ); + } + f = message.getFee(); + if (f != null) { + writer.writeMessage( + 3, + f, + proto.aggregator.Fee.serializeBinaryToWriter + ); + } + f = message.getGasUnits(); + if (f.length > 0) { + writer.writeString( + 4, + f + ); + } +}; + + +/** + * optional string node_id = 1; + * @return {string} + */ +proto.aggregator.NodeCOGS.prototype.getNodeId = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, "")); +}; + + +/** + * @param {string} value + * @return {!proto.aggregator.NodeCOGS} returns this + */ +proto.aggregator.NodeCOGS.prototype.setNodeId = function(value) { + return jspb.Message.setProto3StringField(this, 1, value); +}; + + +/** + * optional string cost_type = 2; + * @return {string} + */ +proto.aggregator.NodeCOGS.prototype.getCostType = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 2, "")); +}; + + +/** + * @param {string} value + * @return {!proto.aggregator.NodeCOGS} returns this + */ +proto.aggregator.NodeCOGS.prototype.setCostType = function(value) { + return jspb.Message.setProto3StringField(this, 2, value); +}; + + +/** + * optional Fee fee = 3; + * @return {?proto.aggregator.Fee} + */ +proto.aggregator.NodeCOGS.prototype.getFee = function() { + return /** @type{?proto.aggregator.Fee} */ ( + jspb.Message.getWrapperField(this, proto.aggregator.Fee, 3)); +}; + + +/** + * @param {?proto.aggregator.Fee|undefined} value + * @return {!proto.aggregator.NodeCOGS} returns this +*/ +proto.aggregator.NodeCOGS.prototype.setFee = function(value) { + return jspb.Message.setWrapperField(this, 3, value); +}; + + +/** + * Clears the message field making it undefined. + * @return {!proto.aggregator.NodeCOGS} returns this + */ +proto.aggregator.NodeCOGS.prototype.clearFee = function() { + return this.setFee(undefined); +}; + + +/** + * Returns whether this field is set. + * @return {boolean} + */ +proto.aggregator.NodeCOGS.prototype.hasFee = function() { + return jspb.Message.getField(this, 3) != null; +}; + + +/** + * optional string gas_units = 4; + * @return {string} + */ +proto.aggregator.NodeCOGS.prototype.getGasUnits = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 4, "")); +}; + + +/** + * @param {string} value + * @return {!proto.aggregator.NodeCOGS} returns this + */ +proto.aggregator.NodeCOGS.prototype.setGasUnits = function(value) { + return jspb.Message.setProto3StringField(this, 4, value); +}; + + + + + +if (jspb.Message.GENERATE_TO_OBJECT) { +/** + * Creates an object representation of this proto. + * Field names that are reserved in JavaScript and will be renamed to pb_name. + * Optional fields that are not set will be set to undefined. + * To access a reserved field use, foo.pb_, eg, foo.pb_default. + * For the list of reserved names please see: + * net/proto2/compiler/js/internal/generator.cc#kKeyword. + * @param {boolean=} opt_includeInstance Deprecated. whether to include the + * JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @return {!Object} + */ +proto.aggregator.ValueFee.prototype.toObject = function(opt_includeInstance) { + return proto.aggregator.ValueFee.toObject(opt_includeInstance, this); +}; + + +/** + * Static version of the {@see toObject} method. + * @param {boolean|undefined} includeInstance Deprecated. Whether to include + * the JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @param {!proto.aggregator.ValueFee} msg The msg instance to transform. + * @return {!Object} + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.aggregator.ValueFee.toObject = function(includeInstance, msg) { + var f, obj = { + fee: (f = msg.getFee()) && proto.aggregator.Fee.toObject(includeInstance, f), + tier: jspb.Message.getFieldWithDefault(msg, 2, 0), + valueBase: jspb.Message.getFieldWithDefault(msg, 3, ""), + classificationMethod: jspb.Message.getFieldWithDefault(msg, 4, ""), + confidence: jspb.Message.getFloatingPointFieldWithDefault(msg, 5, 0.0), + reason: jspb.Message.getFieldWithDefault(msg, 6, "") + }; + + if (includeInstance) { + obj.$jspbMessageInstance = msg; + } + return obj; }; +} /** - * @param {?proto.aggregator.FeeAmount|undefined} value - * @return {!proto.aggregator.AutomationFee} returns this + * Deserializes binary data (in protobuf wire format). + * @param {jspb.ByteSource} bytes The bytes to deserialize. + * @return {!proto.aggregator.ValueFee} + */ +proto.aggregator.ValueFee.deserializeBinary = function(bytes) { + var reader = new jspb.BinaryReader(bytes); + var msg = new proto.aggregator.ValueFee; + return proto.aggregator.ValueFee.deserializeBinaryFromReader(msg, reader); +}; + + +/** + * Deserializes binary data (in protobuf wire format) from the + * given reader into the given message object. + * @param {!proto.aggregator.ValueFee} msg The message object to deserialize into. + * @param {!jspb.BinaryReader} reader The BinaryReader to use. + * @return {!proto.aggregator.ValueFee} + */ +proto.aggregator.ValueFee.deserializeBinaryFromReader = function(msg, reader) { + while (reader.nextField()) { + if (reader.isEndGroup()) { + break; + } + var field = reader.getFieldNumber(); + switch (field) { + case 1: + var value = new proto.aggregator.Fee; + reader.readMessage(value,proto.aggregator.Fee.deserializeBinaryFromReader); + msg.setFee(value); + break; + case 2: + var value = /** @type {!proto.aggregator.ExecutionTier} */ (reader.readEnum()); + msg.setTier(value); + break; + case 3: + var value = /** @type {string} */ (reader.readString()); + msg.setValueBase(value); + break; + case 4: + var value = /** @type {string} */ (reader.readString()); + msg.setClassificationMethod(value); + break; + case 5: + var value = /** @type {number} */ (reader.readFloat()); + msg.setConfidence(value); + break; + case 6: + var value = /** @type {string} */ (reader.readString()); + msg.setReason(value); + break; + default: + reader.skipField(); + break; + } + } + return msg; +}; + + +/** + * Serializes the message to binary data (in protobuf wire format). + * @return {!Uint8Array} + */ +proto.aggregator.ValueFee.prototype.serializeBinary = function() { + var writer = new jspb.BinaryWriter(); + proto.aggregator.ValueFee.serializeBinaryToWriter(this, writer); + return writer.getResultBuffer(); +}; + + +/** + * Serializes the given message to binary data (in protobuf wire + * format), writing to the given BinaryWriter. + * @param {!proto.aggregator.ValueFee} message + * @param {!jspb.BinaryWriter} writer + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.aggregator.ValueFee.serializeBinaryToWriter = function(message, writer) { + var f = undefined; + f = message.getFee(); + if (f != null) { + writer.writeMessage( + 1, + f, + proto.aggregator.Fee.serializeBinaryToWriter + ); + } + f = message.getTier(); + if (f !== 0.0) { + writer.writeEnum( + 2, + f + ); + } + f = message.getValueBase(); + if (f.length > 0) { + writer.writeString( + 3, + f + ); + } + f = message.getClassificationMethod(); + if (f.length > 0) { + writer.writeString( + 4, + f + ); + } + f = message.getConfidence(); + if (f !== 0.0) { + writer.writeFloat( + 5, + f + ); + } + f = message.getReason(); + if (f.length > 0) { + writer.writeString( + 6, + f + ); + } +}; + + +/** + * optional Fee fee = 1; + * @return {?proto.aggregator.Fee} + */ +proto.aggregator.ValueFee.prototype.getFee = function() { + return /** @type{?proto.aggregator.Fee} */ ( + jspb.Message.getWrapperField(this, proto.aggregator.Fee, 1)); +}; + + +/** + * @param {?proto.aggregator.Fee|undefined} value + * @return {!proto.aggregator.ValueFee} returns this */ -proto.aggregator.AutomationFee.prototype.setExecutionFee = function(value) { - return jspb.Message.setWrapperField(this, 3, value); +proto.aggregator.ValueFee.prototype.setFee = function(value) { + return jspb.Message.setWrapperField(this, 1, value); }; /** * Clears the message field making it undefined. - * @return {!proto.aggregator.AutomationFee} returns this + * @return {!proto.aggregator.ValueFee} returns this */ -proto.aggregator.AutomationFee.prototype.clearExecutionFee = function() { - return this.setExecutionFee(undefined); +proto.aggregator.ValueFee.prototype.clearFee = function() { + return this.setFee(undefined); }; @@ -31060,80 +31672,98 @@ proto.aggregator.AutomationFee.prototype.clearExecutionFee = function() { * Returns whether this field is set. * @return {boolean} */ -proto.aggregator.AutomationFee.prototype.hasExecutionFee = function() { - return jspb.Message.getField(this, 3) != null; +proto.aggregator.ValueFee.prototype.hasFee = function() { + return jspb.Message.getField(this, 1) != null; +}; + + +/** + * optional ExecutionTier tier = 2; + * @return {!proto.aggregator.ExecutionTier} + */ +proto.aggregator.ValueFee.prototype.getTier = function() { + return /** @type {!proto.aggregator.ExecutionTier} */ (jspb.Message.getFieldWithDefault(this, 2, 0)); +}; + + +/** + * @param {!proto.aggregator.ExecutionTier} value + * @return {!proto.aggregator.ValueFee} returns this + */ +proto.aggregator.ValueFee.prototype.setTier = function(value) { + return jspb.Message.setProto3EnumField(this, 2, value); }; /** - * optional string trigger_type = 4; + * optional string value_base = 3; * @return {string} */ -proto.aggregator.AutomationFee.prototype.getTriggerType = function() { - return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 4, "")); +proto.aggregator.ValueFee.prototype.getValueBase = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 3, "")); }; /** * @param {string} value - * @return {!proto.aggregator.AutomationFee} returns this + * @return {!proto.aggregator.ValueFee} returns this */ -proto.aggregator.AutomationFee.prototype.setTriggerType = function(value) { - return jspb.Message.setProto3StringField(this, 4, value); +proto.aggregator.ValueFee.prototype.setValueBase = function(value) { + return jspb.Message.setProto3StringField(this, 3, value); }; /** - * optional int64 estimated_executions = 5; - * @return {number} + * optional string classification_method = 4; + * @return {string} */ -proto.aggregator.AutomationFee.prototype.getEstimatedExecutions = function() { - return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 5, 0)); +proto.aggregator.ValueFee.prototype.getClassificationMethod = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 4, "")); }; /** - * @param {number} value - * @return {!proto.aggregator.AutomationFee} returns this + * @param {string} value + * @return {!proto.aggregator.ValueFee} returns this */ -proto.aggregator.AutomationFee.prototype.setEstimatedExecutions = function(value) { - return jspb.Message.setProto3IntField(this, 5, value); +proto.aggregator.ValueFee.prototype.setClassificationMethod = function(value) { + return jspb.Message.setProto3StringField(this, 4, value); }; /** - * optional int64 duration_minutes = 6; + * optional float confidence = 5; * @return {number} */ -proto.aggregator.AutomationFee.prototype.getDurationMinutes = function() { - return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 6, 0)); +proto.aggregator.ValueFee.prototype.getConfidence = function() { + return /** @type {number} */ (jspb.Message.getFloatingPointFieldWithDefault(this, 5, 0.0)); }; /** * @param {number} value - * @return {!proto.aggregator.AutomationFee} returns this + * @return {!proto.aggregator.ValueFee} returns this */ -proto.aggregator.AutomationFee.prototype.setDurationMinutes = function(value) { - return jspb.Message.setProto3IntField(this, 6, value); +proto.aggregator.ValueFee.prototype.setConfidence = function(value) { + return jspb.Message.setProto3FloatField(this, 5, value); }; /** - * optional string fee_calculation_method = 7; + * optional string reason = 6; * @return {string} */ -proto.aggregator.AutomationFee.prototype.getFeeCalculationMethod = function() { - return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 7, "")); +proto.aggregator.ValueFee.prototype.getReason = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 6, "")); }; /** * @param {string} value - * @return {!proto.aggregator.AutomationFee} returns this + * @return {!proto.aggregator.ValueFee} returns this */ -proto.aggregator.AutomationFee.prototype.setFeeCalculationMethod = function(value) { - return jspb.Message.setProto3StringField(this, 7, value); +proto.aggregator.ValueFee.prototype.setReason = function(value) { + return jspb.Message.setProto3StringField(this, 6, value); }; @@ -31171,11 +31801,9 @@ proto.aggregator.FeeDiscount.toObject = function(includeInstance, msg) { var f, obj = { discountType: jspb.Message.getFieldWithDefault(msg, 1, ""), discountName: jspb.Message.getFieldWithDefault(msg, 2, ""), - appliesTo: jspb.Message.getFieldWithDefault(msg, 3, ""), - discountPercentage: jspb.Message.getFloatingPointFieldWithDefault(msg, 4, 0.0), - discountAmount: (f = msg.getDiscountAmount()) && proto.aggregator.FeeAmount.toObject(includeInstance, f), - expiryDate: jspb.Message.getFieldWithDefault(msg, 6, ""), - terms: jspb.Message.getFieldWithDefault(msg, 7, "") + discount: (f = msg.getDiscount()) && proto.aggregator.Fee.toObject(includeInstance, f), + expiryDate: jspb.Message.getFieldWithDefault(msg, 4, ""), + terms: jspb.Message.getFieldWithDefault(msg, 5, "") }; if (includeInstance) { @@ -31221,23 +31849,15 @@ proto.aggregator.FeeDiscount.deserializeBinaryFromReader = function(msg, reader) msg.setDiscountName(value); break; case 3: - var value = /** @type {string} */ (reader.readString()); - msg.setAppliesTo(value); + var value = new proto.aggregator.Fee; + reader.readMessage(value,proto.aggregator.Fee.deserializeBinaryFromReader); + msg.setDiscount(value); break; case 4: - var value = /** @type {number} */ (reader.readFloat()); - msg.setDiscountPercentage(value); - break; - case 5: - var value = new proto.aggregator.FeeAmount; - reader.readMessage(value,proto.aggregator.FeeAmount.deserializeBinaryFromReader); - msg.setDiscountAmount(value); - break; - case 6: var value = /** @type {string} */ (reader.readString()); msg.setExpiryDate(value); break; - case 7: + case 5: var value = /** @type {string} */ (reader.readString()); msg.setTerms(value); break; @@ -31284,39 +31904,25 @@ proto.aggregator.FeeDiscount.serializeBinaryToWriter = function(message, writer) f ); } - f = message.getAppliesTo(); - if (f.length > 0) { - writer.writeString( - 3, - f - ); - } - f = message.getDiscountPercentage(); - if (f !== 0.0) { - writer.writeFloat( - 4, - f - ); - } - f = message.getDiscountAmount(); + f = message.getDiscount(); if (f != null) { writer.writeMessage( - 5, + 3, f, - proto.aggregator.FeeAmount.serializeBinaryToWriter + proto.aggregator.Fee.serializeBinaryToWriter ); } f = message.getExpiryDate(); if (f.length > 0) { writer.writeString( - 6, + 4, f ); } f = message.getTerms(); if (f.length > 0) { writer.writeString( - 7, + 5, f ); } @@ -31360,57 +31966,21 @@ proto.aggregator.FeeDiscount.prototype.setDiscountName = function(value) { /** - * optional string applies_to = 3; - * @return {string} - */ -proto.aggregator.FeeDiscount.prototype.getAppliesTo = function() { - return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 3, "")); -}; - - -/** - * @param {string} value - * @return {!proto.aggregator.FeeDiscount} returns this - */ -proto.aggregator.FeeDiscount.prototype.setAppliesTo = function(value) { - return jspb.Message.setProto3StringField(this, 3, value); -}; - - -/** - * optional float discount_percentage = 4; - * @return {number} - */ -proto.aggregator.FeeDiscount.prototype.getDiscountPercentage = function() { - return /** @type {number} */ (jspb.Message.getFloatingPointFieldWithDefault(this, 4, 0.0)); -}; - - -/** - * @param {number} value - * @return {!proto.aggregator.FeeDiscount} returns this - */ -proto.aggregator.FeeDiscount.prototype.setDiscountPercentage = function(value) { - return jspb.Message.setProto3FloatField(this, 4, value); -}; - - -/** - * optional FeeAmount discount_amount = 5; - * @return {?proto.aggregator.FeeAmount} + * optional Fee discount = 3; + * @return {?proto.aggregator.Fee} */ -proto.aggregator.FeeDiscount.prototype.getDiscountAmount = function() { - return /** @type{?proto.aggregator.FeeAmount} */ ( - jspb.Message.getWrapperField(this, proto.aggregator.FeeAmount, 5)); +proto.aggregator.FeeDiscount.prototype.getDiscount = function() { + return /** @type{?proto.aggregator.Fee} */ ( + jspb.Message.getWrapperField(this, proto.aggregator.Fee, 3)); }; /** - * @param {?proto.aggregator.FeeAmount|undefined} value + * @param {?proto.aggregator.Fee|undefined} value * @return {!proto.aggregator.FeeDiscount} returns this */ -proto.aggregator.FeeDiscount.prototype.setDiscountAmount = function(value) { - return jspb.Message.setWrapperField(this, 5, value); +proto.aggregator.FeeDiscount.prototype.setDiscount = function(value) { + return jspb.Message.setWrapperField(this, 3, value); }; @@ -31418,8 +31988,8 @@ proto.aggregator.FeeDiscount.prototype.setDiscountAmount = function(value) { * Clears the message field making it undefined. * @return {!proto.aggregator.FeeDiscount} returns this */ -proto.aggregator.FeeDiscount.prototype.clearDiscountAmount = function() { - return this.setDiscountAmount(undefined); +proto.aggregator.FeeDiscount.prototype.clearDiscount = function() { + return this.setDiscount(undefined); }; @@ -31427,17 +31997,17 @@ proto.aggregator.FeeDiscount.prototype.clearDiscountAmount = function() { * Returns whether this field is set. * @return {boolean} */ -proto.aggregator.FeeDiscount.prototype.hasDiscountAmount = function() { - return jspb.Message.getField(this, 5) != null; +proto.aggregator.FeeDiscount.prototype.hasDiscount = function() { + return jspb.Message.getField(this, 3) != null; }; /** - * optional string expiry_date = 6; + * optional string expiry_date = 4; * @return {string} */ proto.aggregator.FeeDiscount.prototype.getExpiryDate = function() { - return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 6, "")); + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 4, "")); }; @@ -31446,16 +32016,16 @@ proto.aggregator.FeeDiscount.prototype.getExpiryDate = function() { * @return {!proto.aggregator.FeeDiscount} returns this */ proto.aggregator.FeeDiscount.prototype.setExpiryDate = function(value) { - return jspb.Message.setProto3StringField(this, 6, value); + return jspb.Message.setProto3StringField(this, 4, value); }; /** - * optional string terms = 7; + * optional string terms = 5; * @return {string} */ proto.aggregator.FeeDiscount.prototype.getTerms = function() { - return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 7, "")); + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 5, "")); }; @@ -31464,7 +32034,7 @@ proto.aggregator.FeeDiscount.prototype.getTerms = function() { * @return {!proto.aggregator.FeeDiscount} returns this */ proto.aggregator.FeeDiscount.prototype.setTerms = function(value) { - return jspb.Message.setProto3StringField(this, 7, value); + return jspb.Message.setProto3StringField(this, 5, value); }; @@ -31474,7 +32044,7 @@ proto.aggregator.FeeDiscount.prototype.setTerms = function(value) { * @private {!Array} * @const */ -proto.aggregator.EstimateFeesResp.repeatedFields_ = [8,15,16]; +proto.aggregator.EstimateFeesResp.repeatedFields_ = [7,9,11]; @@ -31510,20 +32080,16 @@ proto.aggregator.EstimateFeesResp.toObject = function(includeInstance, msg) { success: jspb.Message.getBooleanFieldWithDefault(msg, 1, false), error: jspb.Message.getFieldWithDefault(msg, 2, ""), errorCode: jspb.Message.getFieldWithDefault(msg, 3, 0), - gasFees: (f = msg.getGasFees()) && proto.aggregator.GasFeeBreakdown.toObject(includeInstance, f), - automationFees: (f = msg.getAutomationFees()) && proto.aggregator.AutomationFee.toObject(includeInstance, f), - creationFees: (f = msg.getCreationFees()) && proto.aggregator.SmartWalletCreationFee.toObject(includeInstance, f), - totalFees: (f = msg.getTotalFees()) && proto.aggregator.FeeAmount.toObject(includeInstance, f), + chainId: jspb.Message.getFieldWithDefault(msg, 4, ""), + nativeToken: (f = msg.getNativeToken()) && proto.aggregator.NativeToken.toObject(includeInstance, f), + executionFee: (f = msg.getExecutionFee()) && proto.aggregator.Fee.toObject(includeInstance, f), + cogsList: jspb.Message.toObjectList(msg.getCogsList(), + proto.aggregator.NodeCOGS.toObject, includeInstance), + valueFee: (f = msg.getValueFee()) && proto.aggregator.ValueFee.toObject(includeInstance, f), discountsList: jspb.Message.toObjectList(msg.getDiscountsList(), proto.aggregator.FeeDiscount.toObject, includeInstance), - totalDiscounts: (f = msg.getTotalDiscounts()) && proto.aggregator.FeeAmount.toObject(includeInstance, f), - finalTotal: (f = msg.getFinalTotal()) && proto.aggregator.FeeAmount.toObject(includeInstance, f), - estimatedAt: jspb.Message.getFieldWithDefault(msg, 11, 0), - chainId: jspb.Message.getFieldWithDefault(msg, 12, ""), - priceDataSource: jspb.Message.getFieldWithDefault(msg, 13, ""), - priceDataAgeSeconds: jspb.Message.getFieldWithDefault(msg, 14, 0), - warningsList: (f = jspb.Message.getRepeatedField(msg, 15)) == null ? undefined : f, - recommendationsList: (f = jspb.Message.getRepeatedField(msg, 16)) == null ? undefined : f + pricingModel: jspb.Message.getFieldWithDefault(msg, 10, ""), + warningsList: (f = jspb.Message.getRepeatedField(msg, 11)) == null ? undefined : f }; if (includeInstance) { @@ -31573,63 +32139,41 @@ proto.aggregator.EstimateFeesResp.deserializeBinaryFromReader = function(msg, re msg.setErrorCode(value); break; case 4: - var value = new proto.aggregator.GasFeeBreakdown; - reader.readMessage(value,proto.aggregator.GasFeeBreakdown.deserializeBinaryFromReader); - msg.setGasFees(value); + var value = /** @type {string} */ (reader.readString()); + msg.setChainId(value); break; case 5: - var value = new proto.aggregator.AutomationFee; - reader.readMessage(value,proto.aggregator.AutomationFee.deserializeBinaryFromReader); - msg.setAutomationFees(value); - break; - case 6: - var value = new proto.aggregator.SmartWalletCreationFee; - reader.readMessage(value,proto.aggregator.SmartWalletCreationFee.deserializeBinaryFromReader); - msg.setCreationFees(value); - break; - case 7: - var value = new proto.aggregator.FeeAmount; - reader.readMessage(value,proto.aggregator.FeeAmount.deserializeBinaryFromReader); - msg.setTotalFees(value); - break; - case 8: - var value = new proto.aggregator.FeeDiscount; - reader.readMessage(value,proto.aggregator.FeeDiscount.deserializeBinaryFromReader); - msg.addDiscounts(value); - break; - case 9: - var value = new proto.aggregator.FeeAmount; - reader.readMessage(value,proto.aggregator.FeeAmount.deserializeBinaryFromReader); - msg.setTotalDiscounts(value); - break; - case 10: - var value = new proto.aggregator.FeeAmount; - reader.readMessage(value,proto.aggregator.FeeAmount.deserializeBinaryFromReader); - msg.setFinalTotal(value); + var value = new proto.aggregator.NativeToken; + reader.readMessage(value,proto.aggregator.NativeToken.deserializeBinaryFromReader); + msg.setNativeToken(value); break; - case 11: - var value = /** @type {number} */ (reader.readInt64()); - msg.setEstimatedAt(value); + case 6: + var value = new proto.aggregator.Fee; + reader.readMessage(value,proto.aggregator.Fee.deserializeBinaryFromReader); + msg.setExecutionFee(value); break; - case 12: - var value = /** @type {string} */ (reader.readString()); - msg.setChainId(value); + case 7: + var value = new proto.aggregator.NodeCOGS; + reader.readMessage(value,proto.aggregator.NodeCOGS.deserializeBinaryFromReader); + msg.addCogs(value); break; - case 13: - var value = /** @type {string} */ (reader.readString()); - msg.setPriceDataSource(value); + case 8: + var value = new proto.aggregator.ValueFee; + reader.readMessage(value,proto.aggregator.ValueFee.deserializeBinaryFromReader); + msg.setValueFee(value); break; - case 14: - var value = /** @type {number} */ (reader.readInt64()); - msg.setPriceDataAgeSeconds(value); + case 9: + var value = new proto.aggregator.FeeDiscount; + reader.readMessage(value,proto.aggregator.FeeDiscount.deserializeBinaryFromReader); + msg.addDiscounts(value); break; - case 15: + case 10: var value = /** @type {string} */ (reader.readString()); - msg.addWarnings(value); + msg.setPricingModel(value); break; - case 16: + case 11: var value = /** @type {string} */ (reader.readString()); - msg.addRecommendations(value); + msg.addWarnings(value); break; default: reader.skipField(); @@ -31681,101 +32225,64 @@ proto.aggregator.EstimateFeesResp.serializeBinaryToWriter = function(message, wr f ); } - f = message.getGasFees(); - if (f != null) { - writer.writeMessage( + f = message.getChainId(); + if (f.length > 0) { + writer.writeString( 4, - f, - proto.aggregator.GasFeeBreakdown.serializeBinaryToWriter + f ); } - f = message.getAutomationFees(); + f = message.getNativeToken(); if (f != null) { writer.writeMessage( 5, f, - proto.aggregator.AutomationFee.serializeBinaryToWriter + proto.aggregator.NativeToken.serializeBinaryToWriter ); } - f = message.getCreationFees(); + f = message.getExecutionFee(); if (f != null) { writer.writeMessage( 6, f, - proto.aggregator.SmartWalletCreationFee.serializeBinaryToWriter - ); - } - f = message.getTotalFees(); - if (f != null) { - writer.writeMessage( - 7, - f, - proto.aggregator.FeeAmount.serializeBinaryToWriter + proto.aggregator.Fee.serializeBinaryToWriter ); } - f = message.getDiscountsList(); + f = message.getCogsList(); if (f.length > 0) { writer.writeRepeatedMessage( - 8, - f, - proto.aggregator.FeeDiscount.serializeBinaryToWriter - ); - } - f = message.getTotalDiscounts(); - if (f != null) { - writer.writeMessage( - 9, + 7, f, - proto.aggregator.FeeAmount.serializeBinaryToWriter + proto.aggregator.NodeCOGS.serializeBinaryToWriter ); } - f = message.getFinalTotal(); + f = message.getValueFee(); if (f != null) { writer.writeMessage( - 10, + 8, f, - proto.aggregator.FeeAmount.serializeBinaryToWriter - ); - } - f = message.getEstimatedAt(); - if (f !== 0) { - writer.writeInt64( - 11, - f + proto.aggregator.ValueFee.serializeBinaryToWriter ); } - f = message.getChainId(); + f = message.getDiscountsList(); if (f.length > 0) { - writer.writeString( - 12, - f + writer.writeRepeatedMessage( + 9, + f, + proto.aggregator.FeeDiscount.serializeBinaryToWriter ); } - f = message.getPriceDataSource(); + f = message.getPricingModel(); if (f.length > 0) { writer.writeString( - 13, - f - ); - } - f = message.getPriceDataAgeSeconds(); - if (f !== 0) { - writer.writeInt64( - 14, + 10, f ); } f = message.getWarningsList(); if (f.length > 0) { writer.writeRepeatedString( - 15, - f - ); - } - f = message.getRecommendationsList(); - if (f.length > 0) { - writer.writeRepeatedString( - 16, + 11, f ); } @@ -31837,57 +32344,38 @@ proto.aggregator.EstimateFeesResp.prototype.setErrorCode = function(value) { /** - * optional GasFeeBreakdown gas_fees = 4; - * @return {?proto.aggregator.GasFeeBreakdown} + * optional string chain_id = 4; + * @return {string} */ -proto.aggregator.EstimateFeesResp.prototype.getGasFees = function() { - return /** @type{?proto.aggregator.GasFeeBreakdown} */ ( - jspb.Message.getWrapperField(this, proto.aggregator.GasFeeBreakdown, 4)); -}; - - -/** - * @param {?proto.aggregator.GasFeeBreakdown|undefined} value - * @return {!proto.aggregator.EstimateFeesResp} returns this -*/ -proto.aggregator.EstimateFeesResp.prototype.setGasFees = function(value) { - return jspb.Message.setWrapperField(this, 4, value); +proto.aggregator.EstimateFeesResp.prototype.getChainId = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 4, "")); }; /** - * Clears the message field making it undefined. + * @param {string} value * @return {!proto.aggregator.EstimateFeesResp} returns this */ -proto.aggregator.EstimateFeesResp.prototype.clearGasFees = function() { - return this.setGasFees(undefined); -}; - - -/** - * Returns whether this field is set. - * @return {boolean} - */ -proto.aggregator.EstimateFeesResp.prototype.hasGasFees = function() { - return jspb.Message.getField(this, 4) != null; +proto.aggregator.EstimateFeesResp.prototype.setChainId = function(value) { + return jspb.Message.setProto3StringField(this, 4, value); }; /** - * optional AutomationFee automation_fees = 5; - * @return {?proto.aggregator.AutomationFee} + * optional NativeToken native_token = 5; + * @return {?proto.aggregator.NativeToken} */ -proto.aggregator.EstimateFeesResp.prototype.getAutomationFees = function() { - return /** @type{?proto.aggregator.AutomationFee} */ ( - jspb.Message.getWrapperField(this, proto.aggregator.AutomationFee, 5)); +proto.aggregator.EstimateFeesResp.prototype.getNativeToken = function() { + return /** @type{?proto.aggregator.NativeToken} */ ( + jspb.Message.getWrapperField(this, proto.aggregator.NativeToken, 5)); }; /** - * @param {?proto.aggregator.AutomationFee|undefined} value + * @param {?proto.aggregator.NativeToken|undefined} value * @return {!proto.aggregator.EstimateFeesResp} returns this */ -proto.aggregator.EstimateFeesResp.prototype.setAutomationFees = function(value) { +proto.aggregator.EstimateFeesResp.prototype.setNativeToken = function(value) { return jspb.Message.setWrapperField(this, 5, value); }; @@ -31896,8 +32384,8 @@ proto.aggregator.EstimateFeesResp.prototype.setAutomationFees = function(value) * Clears the message field making it undefined. * @return {!proto.aggregator.EstimateFeesResp} returns this */ -proto.aggregator.EstimateFeesResp.prototype.clearAutomationFees = function() { - return this.setAutomationFees(undefined); +proto.aggregator.EstimateFeesResp.prototype.clearNativeToken = function() { + return this.setNativeToken(undefined); }; @@ -31905,26 +32393,26 @@ proto.aggregator.EstimateFeesResp.prototype.clearAutomationFees = function() { * Returns whether this field is set. * @return {boolean} */ -proto.aggregator.EstimateFeesResp.prototype.hasAutomationFees = function() { +proto.aggregator.EstimateFeesResp.prototype.hasNativeToken = function() { return jspb.Message.getField(this, 5) != null; }; /** - * optional SmartWalletCreationFee creation_fees = 6; - * @return {?proto.aggregator.SmartWalletCreationFee} + * optional Fee execution_fee = 6; + * @return {?proto.aggregator.Fee} */ -proto.aggregator.EstimateFeesResp.prototype.getCreationFees = function() { - return /** @type{?proto.aggregator.SmartWalletCreationFee} */ ( - jspb.Message.getWrapperField(this, proto.aggregator.SmartWalletCreationFee, 6)); +proto.aggregator.EstimateFeesResp.prototype.getExecutionFee = function() { + return /** @type{?proto.aggregator.Fee} */ ( + jspb.Message.getWrapperField(this, proto.aggregator.Fee, 6)); }; /** - * @param {?proto.aggregator.SmartWalletCreationFee|undefined} value + * @param {?proto.aggregator.Fee|undefined} value * @return {!proto.aggregator.EstimateFeesResp} returns this */ -proto.aggregator.EstimateFeesResp.prototype.setCreationFees = function(value) { +proto.aggregator.EstimateFeesResp.prototype.setExecutionFee = function(value) { return jspb.Message.setWrapperField(this, 6, value); }; @@ -31933,8 +32421,8 @@ proto.aggregator.EstimateFeesResp.prototype.setCreationFees = function(value) { * Clears the message field making it undefined. * @return {!proto.aggregator.EstimateFeesResp} returns this */ -proto.aggregator.EstimateFeesResp.prototype.clearCreationFees = function() { - return this.setCreationFees(undefined); +proto.aggregator.EstimateFeesResp.prototype.clearExecutionFee = function() { + return this.setExecutionFee(undefined); }; @@ -31942,74 +32430,37 @@ proto.aggregator.EstimateFeesResp.prototype.clearCreationFees = function() { * Returns whether this field is set. * @return {boolean} */ -proto.aggregator.EstimateFeesResp.prototype.hasCreationFees = function() { +proto.aggregator.EstimateFeesResp.prototype.hasExecutionFee = function() { return jspb.Message.getField(this, 6) != null; }; /** - * optional FeeAmount total_fees = 7; - * @return {?proto.aggregator.FeeAmount} - */ -proto.aggregator.EstimateFeesResp.prototype.getTotalFees = function() { - return /** @type{?proto.aggregator.FeeAmount} */ ( - jspb.Message.getWrapperField(this, proto.aggregator.FeeAmount, 7)); -}; - - -/** - * @param {?proto.aggregator.FeeAmount|undefined} value - * @return {!proto.aggregator.EstimateFeesResp} returns this -*/ -proto.aggregator.EstimateFeesResp.prototype.setTotalFees = function(value) { - return jspb.Message.setWrapperField(this, 7, value); -}; - - -/** - * Clears the message field making it undefined. - * @return {!proto.aggregator.EstimateFeesResp} returns this - */ -proto.aggregator.EstimateFeesResp.prototype.clearTotalFees = function() { - return this.setTotalFees(undefined); -}; - - -/** - * Returns whether this field is set. - * @return {boolean} - */ -proto.aggregator.EstimateFeesResp.prototype.hasTotalFees = function() { - return jspb.Message.getField(this, 7) != null; -}; - - -/** - * repeated FeeDiscount discounts = 8; - * @return {!Array} + * repeated NodeCOGS cogs = 7; + * @return {!Array} */ -proto.aggregator.EstimateFeesResp.prototype.getDiscountsList = function() { - return /** @type{!Array} */ ( - jspb.Message.getRepeatedWrapperField(this, proto.aggregator.FeeDiscount, 8)); +proto.aggregator.EstimateFeesResp.prototype.getCogsList = function() { + return /** @type{!Array} */ ( + jspb.Message.getRepeatedWrapperField(this, proto.aggregator.NodeCOGS, 7)); }; /** - * @param {!Array} value + * @param {!Array} value * @return {!proto.aggregator.EstimateFeesResp} returns this */ -proto.aggregator.EstimateFeesResp.prototype.setDiscountsList = function(value) { - return jspb.Message.setRepeatedWrapperField(this, 8, value); +proto.aggregator.EstimateFeesResp.prototype.setCogsList = function(value) { + return jspb.Message.setRepeatedWrapperField(this, 7, value); }; /** - * @param {!proto.aggregator.FeeDiscount=} opt_value + * @param {!proto.aggregator.NodeCOGS=} opt_value * @param {number=} opt_index - * @return {!proto.aggregator.FeeDiscount} + * @return {!proto.aggregator.NodeCOGS} */ -proto.aggregator.EstimateFeesResp.prototype.addDiscounts = function(opt_value, opt_index) { - return jspb.Message.addToRepeatedWrapperField(this, 8, opt_value, proto.aggregator.FeeDiscount, opt_index); +proto.aggregator.EstimateFeesResp.prototype.addCogs = function(opt_value, opt_index) { + return jspb.Message.addToRepeatedWrapperField(this, 7, opt_value, proto.aggregator.NodeCOGS, opt_index); }; @@ -32017,27 +32468,27 @@ proto.aggregator.EstimateFeesResp.prototype.addDiscounts = function(opt_value, o * Clears the list making it empty but non-null. * @return {!proto.aggregator.EstimateFeesResp} returns this */ -proto.aggregator.EstimateFeesResp.prototype.clearDiscountsList = function() { - return this.setDiscountsList([]); +proto.aggregator.EstimateFeesResp.prototype.clearCogsList = function() { + return this.setCogsList([]); }; /** - * optional FeeAmount total_discounts = 9; - * @return {?proto.aggregator.FeeAmount} + * optional ValueFee value_fee = 8; + * @return {?proto.aggregator.ValueFee} */ -proto.aggregator.EstimateFeesResp.prototype.getTotalDiscounts = function() { - return /** @type{?proto.aggregator.FeeAmount} */ ( - jspb.Message.getWrapperField(this, proto.aggregator.FeeAmount, 9)); +proto.aggregator.EstimateFeesResp.prototype.getValueFee = function() { + return /** @type{?proto.aggregator.ValueFee} */ ( + jspb.Message.getWrapperField(this, proto.aggregator.ValueFee, 8)); }; /** - * @param {?proto.aggregator.FeeAmount|undefined} value + * @param {?proto.aggregator.ValueFee|undefined} value * @return {!proto.aggregator.EstimateFeesResp} returns this */ -proto.aggregator.EstimateFeesResp.prototype.setTotalDiscounts = function(value) { - return jspb.Message.setWrapperField(this, 9, value); +proto.aggregator.EstimateFeesResp.prototype.setValueFee = function(value) { + return jspb.Message.setWrapperField(this, 8, value); }; @@ -32045,8 +32496,8 @@ proto.aggregator.EstimateFeesResp.prototype.setTotalDiscounts = function(value) * Clears the message field making it undefined. * @return {!proto.aggregator.EstimateFeesResp} returns this */ -proto.aggregator.EstimateFeesResp.prototype.clearTotalDiscounts = function() { - return this.setTotalDiscounts(undefined); +proto.aggregator.EstimateFeesResp.prototype.clearValueFee = function() { + return this.setValueFee(undefined); }; @@ -32054,90 +32505,55 @@ proto.aggregator.EstimateFeesResp.prototype.clearTotalDiscounts = function() { * Returns whether this field is set. * @return {boolean} */ -proto.aggregator.EstimateFeesResp.prototype.hasTotalDiscounts = function() { - return jspb.Message.getField(this, 9) != null; +proto.aggregator.EstimateFeesResp.prototype.hasValueFee = function() { + return jspb.Message.getField(this, 8) != null; }; /** - * optional FeeAmount final_total = 10; - * @return {?proto.aggregator.FeeAmount} + * repeated FeeDiscount discounts = 9; + * @return {!Array} */ -proto.aggregator.EstimateFeesResp.prototype.getFinalTotal = function() { - return /** @type{?proto.aggregator.FeeAmount} */ ( - jspb.Message.getWrapperField(this, proto.aggregator.FeeAmount, 10)); +proto.aggregator.EstimateFeesResp.prototype.getDiscountsList = function() { + return /** @type{!Array} */ ( + jspb.Message.getRepeatedWrapperField(this, proto.aggregator.FeeDiscount, 9)); }; /** - * @param {?proto.aggregator.FeeAmount|undefined} value + * @param {!Array} value * @return {!proto.aggregator.EstimateFeesResp} returns this */ -proto.aggregator.EstimateFeesResp.prototype.setFinalTotal = function(value) { - return jspb.Message.setWrapperField(this, 10, value); -}; - - -/** - * Clears the message field making it undefined. - * @return {!proto.aggregator.EstimateFeesResp} returns this - */ -proto.aggregator.EstimateFeesResp.prototype.clearFinalTotal = function() { - return this.setFinalTotal(undefined); -}; - - -/** - * Returns whether this field is set. - * @return {boolean} - */ -proto.aggregator.EstimateFeesResp.prototype.hasFinalTotal = function() { - return jspb.Message.getField(this, 10) != null; -}; - - -/** - * optional int64 estimated_at = 11; - * @return {number} - */ -proto.aggregator.EstimateFeesResp.prototype.getEstimatedAt = function() { - return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 11, 0)); -}; - - -/** - * @param {number} value - * @return {!proto.aggregator.EstimateFeesResp} returns this - */ -proto.aggregator.EstimateFeesResp.prototype.setEstimatedAt = function(value) { - return jspb.Message.setProto3IntField(this, 11, value); +proto.aggregator.EstimateFeesResp.prototype.setDiscountsList = function(value) { + return jspb.Message.setRepeatedWrapperField(this, 9, value); }; /** - * optional string chain_id = 12; - * @return {string} + * @param {!proto.aggregator.FeeDiscount=} opt_value + * @param {number=} opt_index + * @return {!proto.aggregator.FeeDiscount} */ -proto.aggregator.EstimateFeesResp.prototype.getChainId = function() { - return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 12, "")); +proto.aggregator.EstimateFeesResp.prototype.addDiscounts = function(opt_value, opt_index) { + return jspb.Message.addToRepeatedWrapperField(this, 9, opt_value, proto.aggregator.FeeDiscount, opt_index); }; /** - * @param {string} value + * Clears the list making it empty but non-null. * @return {!proto.aggregator.EstimateFeesResp} returns this */ -proto.aggregator.EstimateFeesResp.prototype.setChainId = function(value) { - return jspb.Message.setProto3StringField(this, 12, value); +proto.aggregator.EstimateFeesResp.prototype.clearDiscountsList = function() { + return this.setDiscountsList([]); }; /** - * optional string price_data_source = 13; + * optional string pricing_model = 10; * @return {string} */ -proto.aggregator.EstimateFeesResp.prototype.getPriceDataSource = function() { - return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 13, "")); +proto.aggregator.EstimateFeesResp.prototype.getPricingModel = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 10, "")); }; @@ -32145,35 +32561,17 @@ proto.aggregator.EstimateFeesResp.prototype.getPriceDataSource = function() { * @param {string} value * @return {!proto.aggregator.EstimateFeesResp} returns this */ -proto.aggregator.EstimateFeesResp.prototype.setPriceDataSource = function(value) { - return jspb.Message.setProto3StringField(this, 13, value); -}; - - -/** - * optional int64 price_data_age_seconds = 14; - * @return {number} - */ -proto.aggregator.EstimateFeesResp.prototype.getPriceDataAgeSeconds = function() { - return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 14, 0)); -}; - - -/** - * @param {number} value - * @return {!proto.aggregator.EstimateFeesResp} returns this - */ -proto.aggregator.EstimateFeesResp.prototype.setPriceDataAgeSeconds = function(value) { - return jspb.Message.setProto3IntField(this, 14, value); +proto.aggregator.EstimateFeesResp.prototype.setPricingModel = function(value) { + return jspb.Message.setProto3StringField(this, 10, value); }; /** - * repeated string warnings = 15; + * repeated string warnings = 11; * @return {!Array} */ proto.aggregator.EstimateFeesResp.prototype.getWarningsList = function() { - return /** @type {!Array} */ (jspb.Message.getRepeatedField(this, 15)); + return /** @type {!Array} */ (jspb.Message.getRepeatedField(this, 11)); }; @@ -32182,7 +32580,7 @@ proto.aggregator.EstimateFeesResp.prototype.getWarningsList = function() { * @return {!proto.aggregator.EstimateFeesResp} returns this */ proto.aggregator.EstimateFeesResp.prototype.setWarningsList = function(value) { - return jspb.Message.setField(this, 15, value || []); + return jspb.Message.setField(this, 11, value || []); }; @@ -32192,7 +32590,7 @@ proto.aggregator.EstimateFeesResp.prototype.setWarningsList = function(value) { * @return {!proto.aggregator.EstimateFeesResp} returns this */ proto.aggregator.EstimateFeesResp.prototype.addWarnings = function(value, opt_index) { - return jspb.Message.addToRepeatedField(this, 15, value, opt_index); + return jspb.Message.addToRepeatedField(this, 11, value, opt_index); }; @@ -32205,43 +32603,6 @@ proto.aggregator.EstimateFeesResp.prototype.clearWarningsList = function() { }; -/** - * repeated string recommendations = 16; - * @return {!Array} - */ -proto.aggregator.EstimateFeesResp.prototype.getRecommendationsList = function() { - return /** @type {!Array} */ (jspb.Message.getRepeatedField(this, 16)); -}; - - -/** - * @param {!Array} value - * @return {!proto.aggregator.EstimateFeesResp} returns this - */ -proto.aggregator.EstimateFeesResp.prototype.setRecommendationsList = function(value) { - return jspb.Message.setField(this, 16, value || []); -}; - - -/** - * @param {string} value - * @param {number=} opt_index - * @return {!proto.aggregator.EstimateFeesResp} returns this - */ -proto.aggregator.EstimateFeesResp.prototype.addRecommendations = function(value, opt_index) { - return jspb.Message.addToRepeatedField(this, 16, value, opt_index); -}; - - -/** - * Clears the list making it empty but non-null. - * @return {!proto.aggregator.EstimateFeesResp} returns this - */ -proto.aggregator.EstimateFeesResp.prototype.clearRecommendationsList = function() { - return this.setRecommendationsList([]); -}; - - @@ -32491,6 +32852,16 @@ proto.aggregator.NodeType = { NODE_TYPE_BALANCE: 10 }; +/** + * @enum {number} + */ +proto.aggregator.ExecutionTier = { + EXECUTION_TIER_UNSPECIFIED: 0, + EXECUTION_TIER_1: 1, + EXECUTION_TIER_2: 2, + EXECUTION_TIER_3: 3 +}; + /** * @enum {number} */ @@ -32552,7 +32923,8 @@ proto.aggregator.ErrorCode = { SMART_WALLET_RPC_ERROR: 8000, SMART_WALLET_NOT_FOUND: 8001, SMART_WALLET_DEPLOYMENT_ERROR: 8002, - INSUFFICIENT_BALANCE: 8003 + INSUFFICIENT_BALANCE: 8003, + INSUFFICIENT_CREDIT: 8004 }; /** diff --git a/packages/sdk-js/src/index.ts b/packages/sdk-js/src/index.ts index 026afe38..7ed42b61 100644 --- a/packages/sdk-js/src/index.ts +++ b/packages/sdk-js/src/index.ts @@ -52,10 +52,12 @@ import { type TriggerWorkflowResponse, type WithdrawFundsRequest, type WithdrawFundsResponse, - // Fee estimation types (only those used internally by SDK) + // Fee estimation types type EstimateFeesRequest, type EstimateFeesResponse, - type FeeAmount, + type Fee, + type NodeCOGS, + type ValueFee, } from "@avaprotocol/types"; import { ExecutionStatus as ProtobufExecutionStatus } from "@/grpc_codegen/avs_pb"; @@ -1565,163 +1567,74 @@ class Client extends BaseClient { private convertEstimateFeesResponse( result: avs_pb.EstimateFeesResp, ): EstimateFeesResponse { - const response: EstimateFeesResponse = { - success: result.getSuccess(), - error: result.getError() || undefined, - errorCode: result.getErrorCode().toString() || undefined, - }; - - // Convert gas fees if present - const gasFees = result.getGasFees(); - if (gasFees) { - response.gasFees = { - nodeGasFees: gasFees.getOperationsList().map((operation) => ({ - nodeId: operation.getNodeId(), - operationType: operation.getOperationType(), - methodName: operation.getMethodName() || undefined, - gasUnits: operation.getGasUnits(), - gasPrice: gasFees.getGasPriceGwei() || "", // Use parent gas price - totalCost: operation.getFee() - ? this.convertFeeAmount(operation.getFee()!) - : this.createZeroFeeAmount(), - success: operation.getFee() - ? parseFloat(operation.getFee()!.getNativeTokenAmount()) > 0 - : false, // Check if operation has valid gas cost - error: undefined, - })), - totalGasCost: this.convertFeeAmount(gasFees.getTotalGasFees()!), - estimationAccurate: gasFees.getEstimationAccurate(), - estimationMethod: gasFees.getEstimationMethod(), - averageGasPrice: gasFees.getGasPriceGwei(), - notes: [], // Not available in current protobuf + // Convert native token metadata + const nativeTokenPb = result.getNativeToken(); + const nativeToken = nativeTokenPb + ? { symbol: nativeTokenPb.getSymbol(), decimals: nativeTokenPb.getDecimals() } + : undefined; + + // Convert execution fee + const execFeePb = result.getExecutionFee(); + const executionFee: Fee | undefined = execFeePb + ? { amount: execFeePb.getAmount(), unit: execFeePb.getUnit() } + : undefined; + + // Convert COGS array + const cogs: NodeCOGS[] = result.getCogsList().map((cogsPb) => { + const feePb = cogsPb.getFee(); + return { + nodeId: cogsPb.getNodeId(), + costType: cogsPb.getCostType(), + fee: feePb + ? { amount: feePb.getAmount(), unit: feePb.getUnit() } + : { amount: "0", unit: "WEI" }, + gasUnits: cogsPb.getGasUnits() || undefined, }; - } + }); - // Convert automation fees if present - const automationFees = result.getAutomationFees(); - if (automationFees) { - // Calculate total fee from base + execution - const baseFee = automationFees.getBaseFee(); - const executionFee = automationFees.getExecutionFee(); - - // For now, use baseFee as totalFee since the exact calculation isn't available - // If baseFee is not available, create a mock fee amount with proper chain detection - const totalFee = baseFee || this.createMockFeeAmount(); - - response.automationFees = { - triggerType: automationFees.getTriggerType(), - durationMinutes: automationFees.getDurationMinutes(), - baseFee: baseFee - ? this.convertFeeAmount(baseFee) - : this.createZeroFeeAmount(), - executionFee: executionFee - ? this.convertFeeAmount(executionFee) - : this.createZeroFeeAmount(), - estimatedExecutions: automationFees.getEstimatedExecutions(), - totalFee: this.convertFeeAmount(totalFee), - breakdown: [], // Not available in current protobuf structure + // Convert value fee + const valueFeePb = result.getValueFee(); + let valueFee: ValueFee | undefined; + if (valueFeePb) { + const vfFeePb = valueFeePb.getFee(); + valueFee = { + fee: vfFeePb + ? { amount: vfFeePb.getAmount(), unit: vfFeePb.getUnit() } + : { amount: "0", unit: "PERCENTAGE" }, + tier: valueFeePb.getTier().toString(), + valueBase: valueFeePb.getValueBase() || undefined, + classificationMethod: valueFeePb.getClassificationMethod(), + confidence: valueFeePb.getConfidence(), + reason: valueFeePb.getReason(), }; } - // Convert creation fees if present - const creationFees = result.getCreationFees(); - if (creationFees) { - response.creationFees = { - creationRequired: creationFees.getCreationRequired(), - walletAddress: creationFees.getWalletAddress(), - creationFee: creationFees.getCreationFee() - ? this.convertFeeAmount(creationFees.getCreationFee()!) - : undefined, - initialFunding: creationFees.getInitialFunding() - ? this.convertFeeAmount(creationFees.getInitialFunding()!) - : undefined, + // Convert discounts + const discounts = result.getDiscountsList().map((discountPb) => { + const dFeePb = discountPb.getDiscount(); + return { + discountType: discountPb.getDiscountType(), + discountName: discountPb.getDiscountName(), + discount: dFeePb + ? { amount: dFeePb.getAmount(), unit: dFeePb.getUnit() } + : { amount: "0", unit: "USD" }, + expiryDate: discountPb.getExpiryDate() || undefined, + terms: discountPb.getTerms() || undefined, }; - } - - // Convert fee amounts - if (result.getTotalFees()) { - response.totalFees = this.convertFeeAmount(result.getTotalFees()!); - } - if (result.getTotalDiscounts()) { - response.totalDiscounts = this.convertFeeAmount( - result.getTotalDiscounts()!, - ); - } - if (result.getFinalTotal()) { - response.finalTotal = this.convertFeeAmount(result.getFinalTotal()!); - } - - // Convert discounts (using FeeDiscount type, not Discount) - response.discounts = result.getDiscountsList().map((discount, index) => ({ - discountId: `auto-${index}`, // Synthesized unique ID since not available in FeeDiscount - discountType: discount.getDiscountType(), - discountName: discount.getDiscountName(), - appliesTo: discount.getAppliesTo(), - discountPercentage: discount.getDiscountPercentage(), - discountAmount: this.convertFeeAmount(discount.getDiscountAmount()!), - expiryDate: discount.getExpiryDate() || undefined, - terms: discount.getTerms() || undefined, - })); - - // Add metadata - response.estimatedAt = result.getEstimatedAt() || undefined; - response.chainId = result.getChainId() || undefined; - response.priceDataSource = result.getPriceDataSource() || undefined; - response.priceDataAgeSeconds = result.getPriceDataAgeSeconds() || undefined; - response.warnings = result.getWarningsList(); - response.recommendations = result.getRecommendationsList(); - - return response; - } - - /** - * Create a mock fee amount object that mimics protobuf FeeAmount interface - * @private - */ - private createMockFeeAmount(): any { - const getNativeTokenSymbol = (): string => { - // All supported chains (Ethereum and Base) use ETH as native token - return "ETH"; // Ethereum, Base mainnet/testnet all use ETH - }; - - return { - getNativeTokenAmount: () => "0", - getNativeTokenSymbol: () => getNativeTokenSymbol(), - getUsdAmount: () => "0", - getApTokenAmount: () => "0", - }; - } - - /** - * Create a zero fee amount - * @private - */ - private createZeroFeeAmount(): FeeAmount { - // Determine native token symbol based on chain ID - const getNativeTokenSymbol = (): string => { - // All supported chains (Ethereum and Base) use ETH as native token - // But could be extended for other chains in the future - return "ETH"; // Ethereum, Base mainnet/testnet all use ETH - }; - - return { - nativeTokenAmount: "0", - nativeTokenSymbol: getNativeTokenSymbol(), - usdAmount: "0", - apTokenAmount: "0", - }; - } + }); - /** - * Convert protobuf FeeAmount to TypeScript FeeAmount - * @private - */ - private convertFeeAmount(feeAmount: avs_pb.FeeAmount): FeeAmount { return { - nativeTokenAmount: feeAmount.getNativeTokenAmount(), - nativeTokenSymbol: feeAmount.getNativeTokenSymbol(), - usdAmount: feeAmount.getUsdAmount(), - apTokenAmount: feeAmount.getApTokenAmount(), + success: result.getSuccess(), + error: result.getError() || undefined, + errorCode: result.getErrorCode().toString() || undefined, + chainId: result.getChainId() || undefined, + nativeToken, + executionFee, + cogs, + valueFee, + discounts, + pricingModel: result.getPricingModel() || undefined, + warnings: result.getWarningsList(), }; } } diff --git a/packages/sdk-js/src/models/execution.ts b/packages/sdk-js/src/models/execution.ts index 7d1c8519..32e6e56b 100644 --- a/packages/sdk-js/src/models/execution.ts +++ b/packages/sdk-js/src/models/execution.ts @@ -3,7 +3,9 @@ import { ExecutionProps, StepProps, ExecutionStatus, - type FeeAmount, + type Fee, + type NodeCOGS, + type ValueFee, } from "@avaprotocol/types"; import Step from "./step"; @@ -28,6 +30,35 @@ function convertProtobufExecutionStatusToTypes( } } +function convertFee(feePb: avs_pb.Fee | undefined): Fee | undefined { + if (!feePb) return undefined; + return { + amount: feePb.getAmount(), + unit: feePb.getUnit(), + }; +} + +function convertNodeCOGS(cogsPb: avs_pb.NodeCOGS): NodeCOGS { + return { + nodeId: cogsPb.getNodeId(), + costType: cogsPb.getCostType(), + fee: convertFee(cogsPb.getFee()) || { amount: "0", unit: "WEI" }, + gasUnits: cogsPb.getGasUnits() || undefined, + }; +} + +function convertValueFee(valuePb: avs_pb.ValueFee | undefined): ValueFee | undefined { + if (!valuePb) return undefined; + return { + fee: convertFee(valuePb.getFee()) || { amount: "0", unit: "PERCENTAGE" }, + tier: valuePb.getTier().toString(), + valueBase: valuePb.getValueBase() || undefined, + classificationMethod: valuePb.getClassificationMethod(), + confidence: valuePb.getConfidence(), + reason: valuePb.getReason(), + }; +} + class Execution implements ExecutionProps { id: string; startAt: number; @@ -36,8 +67,9 @@ class Execution implements ExecutionProps { error: string; index: number; steps: Step[]; - totalGasCost?: string; - automationFee?: FeeAmount; + executionFee?: Fee; + cogs: NodeCOGS[]; + valueFee?: ValueFee; constructor(props: ExecutionProps) { this.id = props.id; @@ -47,15 +79,11 @@ class Execution implements ExecutionProps { this.error = props.error; this.index = props.index; this.steps = props.steps.map(s => new Step(s)); - this.totalGasCost = props.totalGasCost; - this.automationFee = props.automationFee; + this.executionFee = props.executionFee; + this.cogs = props.cogs || []; + this.valueFee = props.valueFee; } - - /** - * Convert Execution instance to plain object (ExecutionProps) - * This is useful for serialization, especially with Next.js Server Components - */ toJson(): ExecutionProps { return { id: this.id, @@ -65,19 +93,13 @@ class Execution implements ExecutionProps { error: this.error, index: this.index, steps: this.steps.map(step => step.toJson()), - ...(this.totalGasCost && { totalGasCost: this.totalGasCost }), - ...(this.automationFee && { automationFee: this.automationFee }), + ...(this.executionFee && { executionFee: this.executionFee }), + cogs: this.cogs, + ...(this.valueFee && { valueFee: this.valueFee }), }; } static fromResponse(execution: avs_pb.Execution): Execution { - const automationFeePb = typeof execution.getAutomationFee === 'function' - ? execution.getAutomationFee() - : undefined; - const automationFee: FeeAmount | undefined = automationFeePb - ? (automationFeePb.toObject() as FeeAmount) - : undefined; - return new Execution({ id: execution.getId(), startAt: execution.getStartAt(), @@ -85,15 +107,14 @@ class Execution implements ExecutionProps { status: convertProtobufExecutionStatusToTypes(execution.getStatus()), error: execution.getError(), index: execution.getIndex(), - totalGasCost: execution.getTotalGasCost() || undefined, - automationFee, + executionFee: convertFee(execution.getExecutionFee()), + cogs: execution.getCogsList().map(convertNodeCOGS), + valueFee: convertValueFee(execution.getValueFee()), steps: execution .getStepsList() .map((step) => Step.fromResponse(step)) as StepProps[], }); } - - // Client side does not generate the execution, so there's no toRequest() method } export default Execution; diff --git a/packages/types/src/api.ts b/packages/types/src/api.ts index 2f3d1e80..5dc69edf 100644 --- a/packages/types/src/api.ts +++ b/packages/types/src/api.ts @@ -292,185 +292,129 @@ export interface WithdrawFundsResponse { // ============================================================================== /** - * Request for comprehensive fee estimation for workflow deployment + * Unit-safe fee value. Every monetary field is self-describing. + * Units: "USD" (fiat), "WEI" (native token smallest unit), "PERCENTAGE" (0.03 = 0.03%) */ -export interface EstimateFeesRequest { - /** Trigger configuration for the workflow */ - trigger: TriggerProps; - /** Array of workflow nodes */ - nodes: NodeProps[]; - /** Runner address (smart wallet address) - if not provided, will be extracted from inputVariables */ - runner?: string; - /** Input variables for the workflow context */ - inputVariables?: Record; - /** Workflow creation timestamp (milliseconds) */ - createdAt: number; - /** Workflow expiration timestamp (milliseconds) */ - expireAt: number; +export interface Fee { + /** Numeric value as string (precision-safe) */ + amount: string; + /** Unit: "USD", "WEI", or "PERCENTAGE" */ + unit: string; } /** - * Comprehensive fee estimation response with detailed breakdown + * Native token metadata for the chain */ -export interface EstimateFeesResponse { - /** Whether the fee estimation was successful */ - success: boolean; - /** Error message if estimation failed */ - error?: string; - /** Error code if estimation failed */ - errorCode?: string; - - /** Gas fees for blockchain operations */ - gasFees?: GasFeeBreakdown; - /** Automation/monitoring fees based on trigger type */ - automationFees?: AutomationFee; - /** Smart wallet creation fees (if needed) */ - creationFees?: SmartWalletCreationFee; - - /** Total fees before discounts */ - totalFees?: FeeAmount; - /** Applied discounts */ - discounts?: Discount[]; - /** Total discount amount */ - totalDiscounts?: FeeAmount; - /** Final total after discounts */ - finalTotal?: FeeAmount; - - /** When the estimation was performed (milliseconds) */ - estimatedAt?: number; - /** Chain ID where the workflow will be deployed */ - chainId?: string; - /** Source of price data ("moralis", "fallback") */ - priceDataSource?: string; - /** Age of price data in seconds */ - priceDataAgeSeconds?: number; - - /** Warnings about estimation accuracy */ - warnings?: string[]; - /** Recommendations for cost optimization */ - recommendations?: string[]; +export interface NativeToken { + /** Token symbol (e.g., "ETH") */ + symbol: string; + /** Token decimals (e.g., 18) */ + decimals: number; } /** - * Fee amount in multiple formats (native token + USD + AP token) + * Per-node cost of goods sold (gas, external API costs) */ -export interface FeeAmount { - /** Amount in native token wei (e.g., ETH wei) */ - nativeTokenAmount: string; - /** Native token symbol (ETH, etc.) */ - nativeTokenSymbol: string; - /** USD amount (formatted string with 6 decimals) */ - usdAmount: string; - /** AP token amount (future feature, currently "0") */ - apTokenAmount: string; +export interface NodeCOGS { + /** Node ID */ + nodeId: string; + /** Cost type: "gas", "external_api", "wallet_creation" */ + costType: string; + /** Cost amount */ + fee: Fee; + /** Gas units (for gas costs only) */ + gasUnits?: string; } /** - * Gas fee breakdown for blockchain operations + * Workflow-level value-capture fee */ -export interface GasFeeBreakdown { - /** Individual gas fees per node */ - nodeGasFees: NodeGasFee[]; - /** Total gas cost across all nodes */ - totalGasCost: FeeAmount; - /** Whether the estimation is accurate or fallback */ - estimationAccurate: boolean; - /** Method used for estimation ("rpc_estimate", "tenderly_simulation", "fallback") */ - estimationMethod: string; - /** Average gas price used (gwei) */ - averageGasPrice: string; - /** Notes about the estimation */ - notes?: string[]; +export interface ValueFee { + /** Fee as percentage of transaction value */ + fee: Fee; + /** Pricing tier */ + tier: string; + /** What the percentage applies to (e.g., "input_token_value") */ + valueBase?: string; + /** Classification method: "rule_based" or "llm" */ + classificationMethod: string; + /** Classification confidence (0.0–1.0) */ + confidence: number; + /** Why this tier was assigned */ + reason: string; } /** - * Gas fee for a single node/operation + * Applied discount */ -export interface NodeGasFee { - /** Node ID */ - nodeId: string; - /** Type of operation ("contract_write", "eth_transfer") */ - operationType: string; - /** Contract method name (for contract writes) */ - methodName?: string; - /** Estimated gas units */ - gasUnits: string; - /** Gas price in wei */ - gasPrice: string; - /** Total cost for this operation */ - totalCost: FeeAmount; - /** Whether the estimation was successful */ - success: boolean; - /** Error message if estimation failed */ - error?: string; +export interface FeeDiscount { + /** Discount type: "new_user", "volume", "promotional", "beta_program" */ + discountType: string; + /** Human-readable name */ + discountName: string; + /** Discount amount or percentage */ + discount: Fee; + /** Expiry date (ISO string) */ + expiryDate?: string; + /** Terms and conditions */ + terms?: string; } /** - * Automation fees based on trigger type and duration + * Request for fee estimation */ -export interface AutomationFee { - /** Type of trigger */ - triggerType: string; - /** Monitoring duration in minutes */ - durationMinutes: number; - /** Base monitoring fee */ - baseFee: FeeAmount; - /** Per-execution fee estimate */ - executionFee: FeeAmount; - /** Estimated number of executions */ - estimatedExecutions: number; - /** Total automation fee */ - totalFee: FeeAmount; - /** Fee calculation breakdown */ - breakdown: AutomationFeeComponent[]; +export interface EstimateFeesRequest { + /** Trigger configuration */ + trigger: TriggerProps; + /** Workflow nodes */ + nodes: NodeProps[]; + /** Runner address (smart wallet) */ + runner?: string; + /** Input variables */ + inputVariables?: Record; + /** Creation timestamp (ms) */ + createdAt: number; + /** Expiration timestamp (ms) */ + expireAt: number; } /** - * Individual component of automation fee calculation + * Fee estimation response. + * All fees are per-execution. No totals — client computes. + * Components: execution_fee (USD) + cogs[] (WEI) + value_fee (PERCENTAGE) */ -export interface AutomationFeeComponent { - /** Component type ("base", "monitoring", "execution", "address_scaling", "topic_scaling") */ - type: string; - /** Description of this fee component */ - description: string; - /** Fee amount for this component */ - amount: FeeAmount; - /** Calculation details */ - calculation?: string; -} +export interface EstimateFeesResponse { + /** Whether estimation succeeded */ + success: boolean; + /** Error message */ + error?: string; + /** Error code */ + errorCode?: string; -/** - * Smart wallet creation fees (if wallet doesn't exist) - */ -export interface SmartWalletCreationFee { - /** Whether wallet creation is required */ - creationRequired: boolean; - /** Smart wallet address */ - walletAddress: string; - /** Cost to create the wallet */ - creationFee?: FeeAmount; - /** Recommended initial funding amount */ - initialFunding?: FeeAmount; + /** Chain ID */ + chainId?: string; + /** Native token metadata */ + nativeToken?: NativeToken; + + /** Flat per-execution platform fee */ + executionFee?: Fee; + /** Per-node operational costs (gas, external API) */ + cogs: NodeCOGS[]; + /** Workflow-level value-capture fee */ + valueFee?: ValueFee; + /** Applied discounts */ + discounts: FeeDiscount[]; + + /** Pricing model version */ + pricingModel?: string; + /** Warnings */ + warnings: string[]; } -/** - * Applied discount information - */ -export interface Discount { - /** Unique discount ID */ - discountId: string; - /** Type of discount ("beta_program", "new_user", "volume") */ - discountType: string; - /** Human-readable discount name */ - discountName: string; - /** What the discount applies to ("automation_fees", "gas_fees", "total_fees") */ - appliesTo: string; - /** Discount percentage (0-100) */ - discountPercentage: number; - /** Discount amount */ - discountAmount: FeeAmount; - /** When the discount expires (ISO string) */ - expiryDate?: string; - /** Terms and conditions */ - terms?: string; +// Legacy type kept for backward compatibility with Execution.automationFee +export interface FeeAmount { + nativeTokenAmount: string; + nativeTokenSymbol: string; + usdAmount: string; + apTokenAmount: string; } diff --git a/packages/types/src/index.ts b/packages/types/src/index.ts index 8c90c234..a2baebb7 100644 --- a/packages/types/src/index.ts +++ b/packages/types/src/index.ts @@ -23,11 +23,10 @@ export type { // Fee estimation types EstimateFeesRequest, EstimateFeesResponse, + Fee, + NativeToken, + NodeCOGS, + ValueFee, + FeeDiscount, FeeAmount, - GasFeeBreakdown, - NodeGasFee, - AutomationFee, - AutomationFeeComponent, - SmartWalletCreationFee, - Discount } from "./api"; diff --git a/packages/types/src/workflow.ts b/packages/types/src/workflow.ts index 5b9e6745..863f7dd6 100644 --- a/packages/types/src/workflow.ts +++ b/packages/types/src/workflow.ts @@ -90,11 +90,12 @@ export type StepProps = Omit< }; // Execution Props -export type ExecutionProps = Omit & { +export type ExecutionProps = Omit & { steps: Array; status: ExecutionStatus; - // Total gas cost for the entire workflow execution (sum of all blockchain operations) - totalGasCost?: string; + executionFee?: import("./api").Fee; + cogs: import("./api").NodeCOGS[]; + valueFee?: import("./api").ValueFee; }; // Workflow Props - depends on other types so defined last From 0221c10f09803ace258bd5b449a5a6294615f95e Mon Sep 17 00:00:00 2001 From: Will Zimmerman Date: Mon, 6 Apr 2026 00:40:45 -0700 Subject: [PATCH 2/8] test: update fee assertions for new Fee/NodeCOGS/ValueFee structure - Replace expectAutomationFee with expectExecutionFees that checks: - executionFee: Fee{amount, unit: 'USD'} - cogs[]: NodeCOGS{fee: Fee{amount, unit: 'WEI'}} - valueFee: ValueFee{fee: Fee{amount, unit: 'PERCENTAGE'}} - Keep expectAutomationFee as deprecated alias for backward compat - Update execution test imports to use new name --- tests/executions/getExecution.test.ts | 10 +++--- tests/executions/getExecutions.test.ts | 16 +++++----- tests/utils/utils.ts | 43 +++++++++++++++++++++----- 3 files changed, 48 insertions(+), 21 deletions(-) diff --git a/tests/executions/getExecution.test.ts b/tests/executions/getExecution.test.ts index dc2eaecd..661366ca 100644 --- a/tests/executions/getExecution.test.ts +++ b/tests/executions/getExecution.test.ts @@ -12,7 +12,7 @@ import { TIMEOUT_DURATION, getSmartWallet, executionHasWriteFailure, - expectAutomationFee, + expectExecutionFees, getClient, authenticateClient, } from "../utils/utils"; @@ -64,7 +64,7 @@ describe("getExecution Tests", () => { expect(execution).toBeDefined(); expect(execution.id).toEqual(triggerResult.executionId); - expectAutomationFee(execution); + expectExecutionFees(execution); // Ensure status reflects step outcomes const hasWriteFailure = executionHasWriteFailure(execution as any); @@ -175,7 +175,7 @@ describe("getExecution Tests", () => { result.executionId ); expect(execution.id).toEqual(result.executionId); - expectAutomationFee(execution); + expectExecutionFees(execution); // The execution now contains both trigger and node steps // Step 0: Trigger step, Step 1: ETH transfer node @@ -255,7 +255,7 @@ describe("getExecution Tests", () => { expect(execution).toBeDefined(); expect(execution.id).toEqual(executionIdFromList); expect(execution.status).toBe(ExecutionStatus.Success); - expectAutomationFee(execution); + expectExecutionFees(execution); // The execution now contains both trigger and node steps // Step 0: Trigger step, Step 1: ETH transfer node @@ -392,7 +392,7 @@ describe("getExecution Tests", () => { expect(execution).toBeDefined(); expect(execution.id).toEqual(triggerResult.executionId); expect(execution.status).toBe(ExecutionStatus.Success); - expectAutomationFee(execution); + expectExecutionFees(execution); // Verify execution has both trigger and node steps expect(execution.steps).toBeDefined(); diff --git a/tests/executions/getExecutions.test.ts b/tests/executions/getExecutions.test.ts index 7c604bb0..9e3b9ecb 100644 --- a/tests/executions/getExecutions.test.ts +++ b/tests/executions/getExecutions.test.ts @@ -8,7 +8,7 @@ import { getSmartWallet, getClient, authenticateClient, - expectAutomationFee, + expectExecutionFees, } from "../utils/utils"; import { createFromTemplate, defaultTriggerId } from "../utils/templates"; @@ -71,7 +71,7 @@ describe("getExecutions Tests", () => { expect(Array.isArray(resultWithLimitOne.items)).toBe(true); expect(resultWithLimitOne.items.length).toBe(limitOne); - expectAutomationFee(resultWithLimitOne.items[0]); + expectExecutionFees(resultWithLimitOne.items[0]); expect(resultWithLimitOne).toHaveProperty("pageInfo"); expect(resultWithLimitOne.pageInfo.hasNextPage).toBeTruthy(); const firstCursor = resultWithLimitOne.pageInfo.endCursor; @@ -83,7 +83,7 @@ describe("getExecutions Tests", () => { }); expect(Array.isArray(resultWithLimitTwo.items)).toBe(true); expect(resultWithLimitTwo.items.length).toBe(limitTwo); - expectAutomationFee(resultWithLimitTwo.items[0]); + expectExecutionFees(resultWithLimitTwo.items[0]); expect(resultWithLimitTwo.pageInfo.hasNextPage).toBeTruthy(); // Make sure there's no overlap between the two lists @@ -105,7 +105,7 @@ describe("getExecutions Tests", () => { totalTriggerCount - limitTwo - limitOne ); if (resultWithExtraLimit.items.length > 0) { - expectAutomationFee(resultWithExtraLimit.items[0]); + expectExecutionFees(resultWithExtraLimit.items[0]); } expect(resultWithExtraLimit.pageInfo.hasNextPage).toBeFalsy(); @@ -322,7 +322,7 @@ describe("getExecutions Tests", () => { expect(firstPage.items.length).toBeLessThanOrEqual(pageSize); expect(firstPage.pageInfo.endCursor).toBeTruthy(); expect(firstPage.pageInfo.hasNextPage).toBeTruthy(); - firstPage.items.forEach((item) => expectAutomationFee(item)); + firstPage.items.forEach((item) => expectExecutionFees(item)); const secondPage = await client.getExecutions([workflowId], { after: firstPage.pageInfo.endCursor, @@ -330,7 +330,7 @@ describe("getExecutions Tests", () => { }); expect(secondPage.items.length).toBeLessThanOrEqual(pageSize); - secondPage.items.forEach((item) => expectAutomationFee(item)); + secondPage.items.forEach((item) => expectExecutionFees(item)); // Verify no overlap between pages const firstPageIds = firstPage.items.map((item: any) => item.id); @@ -391,7 +391,7 @@ describe("getExecutions Tests", () => { expect(firstPage.items.length).toBeLessThanOrEqual(pageSize); expect(firstPage.pageInfo.endCursor).toBeTruthy(); - firstPage.items.forEach((item) => expectAutomationFee(item)); + firstPage.items.forEach((item) => expectExecutionFees(item)); const previousPage = await client.getExecutions([workflowId], { before: firstPage.pageInfo.startCursor, @@ -401,7 +401,7 @@ describe("getExecutions Tests", () => { // Verify we got items in both pages expect(previousPage.items.length).toBeGreaterThan(0); expect(firstPage.items.length).toBeGreaterThan(0); - previousPage.items.forEach((item) => expectAutomationFee(item)); + previousPage.items.forEach((item) => expectExecutionFees(item)); // Verify the previous page has endCursor and hasPreviousPage fields expect(typeof previousPage.pageInfo.endCursor).toBe("string"); diff --git a/tests/utils/utils.ts b/tests/utils/utils.ts index 275f15e2..699fe5ee 100644 --- a/tests/utils/utils.ts +++ b/tests/utils/utils.ts @@ -725,20 +725,47 @@ export function executionHasWriteFailure( .some((s) => hasWriteFailureFromMetadata(s.metadata)); } -/** Assert execution has automationFee with expected FeeAmount shape when present */ -export function expectAutomationFee( +/** Assert execution has fee fields with expected shapes when present */ +export function expectExecutionFees( execution: { - automationFee?: { nativeTokenAmount?: string; usdAmount?: string }; + executionFee?: { amount?: string; unit?: string }; + cogs?: Array<{ nodeId?: string; costType?: string; fee?: { amount?: string; unit?: string } }>; + valueFee?: { fee?: { amount?: string; unit?: string }; tier?: string }; } ): void { - if (execution.automationFee) { - expect(execution.automationFee).toHaveProperty("nativeTokenAmount"); - expect(execution.automationFee).toHaveProperty("usdAmount"); - expect(typeof execution.automationFee.nativeTokenAmount).toBe("string"); - expect(typeof execution.automationFee.usdAmount).toBe("string"); + // executionFee is a Fee{amount, unit} — may be nil for pending executions + if (execution.executionFee) { + expect(execution.executionFee).toHaveProperty("amount"); + expect(execution.executionFee).toHaveProperty("unit"); + expect(typeof execution.executionFee.amount).toBe("string"); + expect(execution.executionFee.unit).toBe("USD"); + } + + // cogs is always an array (may be empty) + if (execution.cogs) { + expect(Array.isArray(execution.cogs)).toBe(true); + for (const cogsEntry of execution.cogs) { + expect(cogsEntry).toHaveProperty("nodeId"); + expect(cogsEntry).toHaveProperty("costType"); + expect(cogsEntry).toHaveProperty("fee"); + if (cogsEntry.fee) { + expect(cogsEntry.fee.unit).toBe("WEI"); + } + } + } + + // valueFee is a ValueFee — may be nil for pending executions + if (execution.valueFee) { + expect(execution.valueFee).toHaveProperty("fee"); + if (execution.valueFee.fee) { + expect(execution.valueFee.fee.unit).toBe("PERCENTAGE"); + } } } +/** @deprecated Use expectExecutionFees instead */ +export const expectAutomationFee = expectExecutionFees; + export const verifyExecutionStepResults = ( expected: StepProps, actual: Step From 1caadb576058a1d1e3cf0d901ffd9b6683a1a2d3 Mon Sep 17 00:00:00 2001 From: Will Zimmerman Date: Mon, 6 Apr 2026 01:27:55 -0700 Subject: [PATCH 3/8] =?UTF-8?q?fix:=20address=20Copilot=20review=20?= =?UTF-8?q?=E2=80=94=20FeeUnit=20type=20safety,=20tier=20enum=20mapping?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add FeeUnit string union type ('USD' | 'WEI' | 'PERCENTAGE') - Use enum name mapping for ExecutionTier (e.g., 'EXECUTION_TIER_1') instead of numeric string - Assert cogs is defined in expectExecutionFees test helper - Update FeeAmount legacy comment - Cast proto unit strings to FeeUnit in conversion functions --- packages/sdk-js/src/index.ts | 17 +++---- packages/sdk-js/src/models/execution.ts | 9 +++- packages/types/src/api.ts | 12 +++-- packages/types/src/index.ts | 1 + tests/core/secret.test.ts | 63 +++++++++++++++---------- tests/executions/getExecutions.test.ts | 32 +++++++++++-- tests/utils/utils.ts | 1 + tests/workflows/workflow.test.ts | 35 ++++++++++---- 8 files changed, 118 insertions(+), 52 deletions(-) diff --git a/packages/sdk-js/src/index.ts b/packages/sdk-js/src/index.ts index 7ed42b61..ddaa6089 100644 --- a/packages/sdk-js/src/index.ts +++ b/packages/sdk-js/src/index.ts @@ -56,6 +56,7 @@ import { type EstimateFeesRequest, type EstimateFeesResponse, type Fee, + type FeeUnit, type NodeCOGS, type ValueFee, } from "@avaprotocol/types"; @@ -1576,7 +1577,7 @@ class Client extends BaseClient { // Convert execution fee const execFeePb = result.getExecutionFee(); const executionFee: Fee | undefined = execFeePb - ? { amount: execFeePb.getAmount(), unit: execFeePb.getUnit() } + ? { amount: execFeePb.getAmount(), unit: execFeePb.getUnit() as FeeUnit } : undefined; // Convert COGS array @@ -1586,8 +1587,8 @@ class Client extends BaseClient { nodeId: cogsPb.getNodeId(), costType: cogsPb.getCostType(), fee: feePb - ? { amount: feePb.getAmount(), unit: feePb.getUnit() } - : { amount: "0", unit: "WEI" }, + ? { amount: feePb.getAmount(), unit: feePb.getUnit() as FeeUnit } + : { amount: "0", unit: "WEI" as FeeUnit }, gasUnits: cogsPb.getGasUnits() || undefined, }; }); @@ -1599,9 +1600,9 @@ class Client extends BaseClient { const vfFeePb = valueFeePb.getFee(); valueFee = { fee: vfFeePb - ? { amount: vfFeePb.getAmount(), unit: vfFeePb.getUnit() } - : { amount: "0", unit: "PERCENTAGE" }, - tier: valueFeePb.getTier().toString(), + ? { amount: vfFeePb.getAmount(), unit: vfFeePb.getUnit() as FeeUnit } + : { amount: "0", unit: "PERCENTAGE" as FeeUnit }, + tier: avs_pb.ExecutionTier[valueFeePb.getTier()] ?? valueFeePb.getTier().toString(), valueBase: valueFeePb.getValueBase() || undefined, classificationMethod: valueFeePb.getClassificationMethod(), confidence: valueFeePb.getConfidence(), @@ -1616,8 +1617,8 @@ class Client extends BaseClient { discountType: discountPb.getDiscountType(), discountName: discountPb.getDiscountName(), discount: dFeePb - ? { amount: dFeePb.getAmount(), unit: dFeePb.getUnit() } - : { amount: "0", unit: "USD" }, + ? { amount: dFeePb.getAmount(), unit: dFeePb.getUnit() as FeeUnit } + : { amount: "0", unit: "USD" as FeeUnit }, expiryDate: discountPb.getExpiryDate() || undefined, terms: discountPb.getTerms() || undefined, }; diff --git a/packages/sdk-js/src/models/execution.ts b/packages/sdk-js/src/models/execution.ts index 32e6e56b..17a96561 100644 --- a/packages/sdk-js/src/models/execution.ts +++ b/packages/sdk-js/src/models/execution.ts @@ -4,6 +4,7 @@ import { StepProps, ExecutionStatus, type Fee, + type FeeUnit, type NodeCOGS, type ValueFee, } from "@avaprotocol/types"; @@ -34,7 +35,7 @@ function convertFee(feePb: avs_pb.Fee | undefined): Fee | undefined { if (!feePb) return undefined; return { amount: feePb.getAmount(), - unit: feePb.getUnit(), + unit: feePb.getUnit() as FeeUnit, }; } @@ -47,11 +48,15 @@ function convertNodeCOGS(cogsPb: avs_pb.NodeCOGS): NodeCOGS { }; } +function convertExecutionTier(tier: number): string { + return avs_pb.ExecutionTier[tier] ?? tier.toString(); +} + function convertValueFee(valuePb: avs_pb.ValueFee | undefined): ValueFee | undefined { if (!valuePb) return undefined; return { fee: convertFee(valuePb.getFee()) || { amount: "0", unit: "PERCENTAGE" }, - tier: valuePb.getTier().toString(), + tier: convertExecutionTier(valuePb.getTier()), valueBase: valuePb.getValueBase() || undefined, classificationMethod: valuePb.getClassificationMethod(), confidence: valuePb.getConfidence(), diff --git a/packages/types/src/api.ts b/packages/types/src/api.ts index 5dc69edf..78d38c16 100644 --- a/packages/types/src/api.ts +++ b/packages/types/src/api.ts @@ -291,6 +291,11 @@ export interface WithdrawFundsResponse { // FEE ESTIMATION TYPES // ============================================================================== +/** + * Valid fee units + */ +export type FeeUnit = "USD" | "WEI" | "PERCENTAGE"; + /** * Unit-safe fee value. Every monetary field is self-describing. * Units: "USD" (fiat), "WEI" (native token smallest unit), "PERCENTAGE" (0.03 = 0.03%) @@ -298,8 +303,8 @@ export interface WithdrawFundsResponse { export interface Fee { /** Numeric value as string (precision-safe) */ amount: string; - /** Unit: "USD", "WEI", or "PERCENTAGE" */ - unit: string; + /** Unit */ + unit: FeeUnit; } /** @@ -411,7 +416,8 @@ export interface EstimateFeesResponse { warnings: string[]; } -// Legacy type kept for backward compatibility with Execution.automationFee +// Legacy type — kept for any third-party code that may reference it. +// New code should use Fee instead. export interface FeeAmount { nativeTokenAmount: string; nativeTokenSymbol: string; diff --git a/packages/types/src/index.ts b/packages/types/src/index.ts index a2baebb7..ff4e834c 100644 --- a/packages/types/src/index.ts +++ b/packages/types/src/index.ts @@ -24,6 +24,7 @@ export type { EstimateFeesRequest, EstimateFeesResponse, Fee, + FeeUnit, NativeToken, NodeCOGS, ValueFee, diff --git a/tests/core/secret.test.ts b/tests/core/secret.test.ts index d8d8d76f..8fb22acc 100644 --- a/tests/core/secret.test.ts +++ b/tests/core/secret.test.ts @@ -380,47 +380,60 @@ describe("secret Tests", () => { }); it("should support backward pagination with before parameter", async () => { - const middleOptions = { limit: 3 } as GetSecretsOptions; - const middlePage = await client.getSecrets(middleOptions); + const pageSize = 3; + const firstOptions = { limit: pageSize } as GetSecretsOptions; + const firstPage = await client.getSecrets(firstOptions); - if (Array.isArray(middlePage)) { + if (Array.isArray(firstPage)) { return; } // Skip test if no cursor or no more items - if (!middlePage.pageInfo.endCursor || !middlePage.pageInfo.hasNextPage) { + if (!firstPage.pageInfo.endCursor || !firstPage.pageInfo.hasNextPage) { console.log( "No cursor or no more items, skipping backward pagination test" ); return; } - const previousOptions = { - before: middlePage.pageInfo.endCursor, - limit: 3, + // Get the second page (forward) using after + const secondOptions = { + after: firstPage.pageInfo.endCursor, + limit: pageSize, } as GetSecretsOptions; + const secondPage = await client.getSecrets(secondOptions); - try { - const previousPage = await client.getSecrets(previousOptions); + if (Array.isArray(secondPage)) { + return; + } - // Verify that we got items in both pages - expect(previousPage.items.length).toBeGreaterThan(0); - expect(middlePage.items.length).toBeGreaterThan(0); + expect(secondPage.items.length).toBeGreaterThan(0); - // Verify that the previous page has the pagination fields - if (!Array.isArray(previousPage)) { - expect(typeof previousPage.pageInfo.startCursor).toBe("string"); - expect(typeof previousPage.pageInfo.endCursor).toBe("string"); - expect(typeof previousPage.pageInfo.hasPreviousPage).toBe("boolean"); - expect(typeof previousPage.pageInfo.hasNextPage).toBe("boolean"); - } - } catch (error) { - console.log( - "Backward pagination failed, this might be expected:", - error - ); - // Skip the test if backward pagination is not supported + // Now paginate backward from the second page using before + const previousOptions = { + before: secondPage.pageInfo.startCursor, + limit: pageSize, + } as GetSecretsOptions; + const previousPage = await client.getSecrets(previousOptions); + + // Verify that we got items going backward + expect(previousPage.items.length).toBeGreaterThan(0); + + // Verify that the previous page has the pagination fields + if (!Array.isArray(previousPage)) { + expect(typeof previousPage.pageInfo.startCursor).toBe("string"); + expect(typeof previousPage.pageInfo.endCursor).toBe("string"); + expect(typeof previousPage.pageInfo.hasPreviousPage).toBe("boolean"); + expect(typeof previousPage.pageInfo.hasNextPage).toBe("boolean"); } + + // Verify no overlap between second page and backward page + const previousNames = previousPage.items.map((item) => item.name); + const secondPageNames = secondPage.items.map((item) => item.name); + const overlap = previousNames.filter((name) => + secondPageNames.includes(name) + ); + expect(overlap.length).toBe(0); }); it("should respect the limit parameter", async () => { diff --git a/tests/executions/getExecutions.test.ts b/tests/executions/getExecutions.test.ts index 9e3b9ecb..36abc31d 100644 --- a/tests/executions/getExecutions.test.ts +++ b/tests/executions/getExecutions.test.ts @@ -385,33 +385,55 @@ describe("getExecutions Tests", () => { executionIds.push(result.executionId); } + // Get the first page (forward) const firstPage = await client.getExecutions([workflowId], { limit: pageSize, }); expect(firstPage.items.length).toBeLessThanOrEqual(pageSize); expect(firstPage.pageInfo.endCursor).toBeTruthy(); + expect(firstPage.pageInfo.hasNextPage).toBeTruthy(); firstPage.items.forEach((item) => expectExecutionFees(item)); + // Get the second page (forward) using after + const secondPage = await client.getExecutions([workflowId], { + after: firstPage.pageInfo.endCursor, + limit: pageSize, + }); + + expect(secondPage.items.length).toBeLessThanOrEqual(pageSize); + expect(secondPage.items.length).toBeGreaterThan(0); + secondPage.items.forEach((item) => expectExecutionFees(item)); + + // Now paginate backward from the second page using before const previousPage = await client.getExecutions([workflowId], { - before: firstPage.pageInfo.startCursor, + before: secondPage.pageInfo.startCursor, limit: pageSize, }); - // Verify we got items in both pages + // Verify we got items going backward expect(previousPage.items.length).toBeGreaterThan(0); - expect(firstPage.items.length).toBeGreaterThan(0); previousPage.items.forEach((item) => expectExecutionFees(item)); // Verify the previous page has endCursor and hasPreviousPage fields expect(typeof previousPage.pageInfo.endCursor).toBe("string"); expect(typeof previousPage.pageInfo.hasPreviousPage).toBe("boolean"); - // Verify all returned executions are in our created list + // Verify no overlap between second page and previous page + const secondPageIds = secondPage.items.map((item: any) => item.id); const previousPageIds = previousPage.items.map((item: any) => item.id); const firstPageIds = firstPage.items.map((item: any) => item.id); - [...previousPageIds, ...firstPageIds].forEach((id) => { + const overlap = previousPageIds.filter((id) => + secondPageIds.includes(id) + ); + expect(overlap.length).toBe(0); + + // The backward page should return the same items as the first page + expect(previousPageIds.sort()).toEqual(firstPageIds.sort()); + + // Verify all returned executions are in our created list + [...previousPageIds, ...secondPageIds].forEach((id) => { expect(id).toBeDefined(); expect(executionIds.includes(id)).toBe(true); }); diff --git a/tests/utils/utils.ts b/tests/utils/utils.ts index 699fe5ee..464bf666 100644 --- a/tests/utils/utils.ts +++ b/tests/utils/utils.ts @@ -742,6 +742,7 @@ export function expectExecutionFees( } // cogs is always an array (may be empty) + expect(execution).toHaveProperty("cogs"); if (execution.cogs) { expect(Array.isArray(execution.cogs)).toBe(true); for (const cogsEntry of execution.cogs) { diff --git a/tests/workflows/workflow.test.ts b/tests/workflows/workflow.test.ts index 86be540d..fa42f210 100644 --- a/tests/workflows/workflow.test.ts +++ b/tests/workflows/workflow.test.ts @@ -242,27 +242,44 @@ describe("Workflow Management Tests", () => { workflowIds.push(workflowId); } - // Get all workflows first to get cursor - const allWorkflows = await client.getWorkflows([wallet.address], { - limit: totalCount, + // Get the first page (forward) + const firstPage = await client.getWorkflows([wallet.address], { + limit: pageSize, }); - expect(allWorkflows.items.length).toBe(totalCount); + expect(firstPage.items.length).toBeLessThanOrEqual(pageSize); + expect(firstPage.pageInfo.endCursor).toBeTruthy(); + expect(firstPage.pageInfo.hasNextPage).toBeTruthy(); - // Use the second item's cursor as a reference point - const secondItemCursor = allWorkflows.pageInfo.endCursor; + // Get the second page (forward) using after + const secondPage = await client.getWorkflows([wallet.address], { + after: firstPage.pageInfo.endCursor, + limit: pageSize, + }); + + expect(secondPage.items.length).toBeGreaterThan(0); - // Get workflows before the cursor + // Now paginate backward from the second page using before const beforePage = await client.getWorkflows([wallet.address], { - before: secondItemCursor, + before: secondPage.pageInfo.startCursor, limit: pageSize, }); + expect(beforePage.items.length).toBeGreaterThan(0); expect(beforePage.items.length).toBeLessThanOrEqual(pageSize); expect(typeof beforePage.pageInfo.hasPreviousPage).toBe("boolean"); - // Verify that items in beforePage come before items in the original list + // Verify no overlap between second page and backward page const beforeIds = beforePage.items.map((item) => item.id); + const secondPageIds = secondPage.items.map((item) => item.id); + const overlap = beforeIds.filter((id) => secondPageIds.includes(id)); + expect(overlap.length).toBe(0); + + // The backward page should return the same items as the first page + const firstPageIds = firstPage.items.map((item) => item.id); + expect(beforeIds.sort()).toEqual(firstPageIds.sort()); + + // Verify all returned workflows are in our created list beforeIds.forEach((id) => { if (id) { expect(workflowIds.includes(id)).toBe(true); From 038d29ee403c7ef368a42eaa2967774c25b73ece Mon Sep 17 00:00:00 2001 From: Will Zimmerman Date: Mon, 6 Apr 2026 15:50:01 -0700 Subject: [PATCH 4/8] fix: remove legacy FeeAmount, fix test timeouts, add failure summary reporter - Remove deprecated FeeAmount type and expectAutomationFee alias - Migrate gasTracking tests from execution.totalGasCost to execution.cogs - Add TimeoutPresets.SLOW to gRPC calls for on-chain operations - Add Jest-level timeouts for multi-operation consistency tests - Replace fake contract address with Chainlink price feed in loopNode tests - Add null guard for ethTransfer step output - Rewrite fee-estimation-example.ts for new Fee/NodeCOGS/ValueFee API - Add custom Jest failure summary reporter - Add migration guide to docs/fee-proto-migration.md --- docs/fee-proto-migration.md | 240 +++++++++++++++++++++ examples/fee-estimation-example.ts | 204 +++++++----------- jest.config.cjs | 4 + packages/types/src/api.ts | 8 - packages/types/src/index.ts | 1 - tests/executions/gasTracking.test.ts | 157 +++++++------- tests/executions/runNodeWithInputs.test.ts | 6 +- tests/nodes/contractWrite.test.ts | 6 +- tests/nodes/ethTransfer.test.ts | 4 +- tests/nodes/loopNode.test.ts | 4 +- tests/utils/failureSummaryReporter.js | 50 +++++ tests/utils/utils.ts | 2 - 12 files changed, 458 insertions(+), 228 deletions(-) create mode 100644 docs/fee-proto-migration.md create mode 100644 tests/utils/failureSummaryReporter.js diff --git a/docs/fee-proto-migration.md b/docs/fee-proto-migration.md new file mode 100644 index 00000000..10aac44e --- /dev/null +++ b/docs/fee-proto-migration.md @@ -0,0 +1,240 @@ +# Fee Estimation Proto Migration + +Breaking changes to the fee estimation and execution fee interfaces, aligning the SDK with the updated aggregator protobuf schema. + +## Types Removed + +| Type | Package | Description | +|------|---------|-------------| +| `FeeAmount` | `@avaprotocol/types` | Multi-format fee (native + USD + AP token). Replaced by `Fee`. | +| `GasFeeBreakdown` | `@avaprotocol/types` | Gas fee breakdown with per-node fees, estimation method, gas price | +| `NodeGasFee` | `@avaprotocol/types` | Per-node gas fee (operationType, methodName, gasUnits, gasPrice, totalCost) | +| `AutomationFee` | `@avaprotocol/types` | Trigger-based monitoring/execution fees with duration and breakdown | +| `AutomationFeeComponent` | `@avaprotocol/types` | Individual automation fee component (base, monitoring, scaling) | +| `SmartWalletCreationFee` | `@avaprotocol/types` | Wallet creation fee (creationRequired, creationFee, initialFunding) | +| `Discount` | `@avaprotocol/types` | Discount with appliesTo, discountPercentage, discountAmount | + +## Types Added + +| Type | Package | Description | +|------|---------|-------------| +| `FeeUnit` | `@avaprotocol/types` | `"USD" \| "WEI" \| "PERCENTAGE"` | +| `Fee` | `@avaprotocol/types` | `{ amount: string, unit: FeeUnit }` — unit-safe fee value | +| `NativeToken` | `@avaprotocol/types` | `{ symbol: string, decimals: number }` — chain native token metadata | +| `NodeCOGS` | `@avaprotocol/types` | `{ nodeId, costType, fee: Fee, gasUnits? }` — per-node operational cost | +| `ValueFee` | `@avaprotocol/types` | `{ fee: Fee, tier, valueBase?, classificationMethod, confidence, reason }` — workflow-level value-capture fee | +| `FeeDiscount` | `@avaprotocol/types` | `{ discountType, discountName, discount: Fee, expiryDate?, terms? }` — applied discount | + +## Types Modified + +### `EstimateFeesResponse` + +| Removed Fields | Added Fields | +|----------------|-------------| +| `gasFees: GasFeeBreakdown` | `nativeToken: NativeToken` | +| `automationFees: AutomationFee` | `executionFee: Fee` | +| `creationFees: SmartWalletCreationFee` | `cogs: NodeCOGS[]` | +| `totalFees: FeeAmount` | `valueFee: ValueFee` | +| `totalDiscounts: FeeAmount` | `pricingModel: string` | +| `finalTotal: FeeAmount` | | +| `estimatedAt: number` | | +| `priceDataSource: string` | | +| `priceDataAgeSeconds: number` | | +| `recommendations: string[]` | | +| `discounts: Discount[]` | `discounts: FeeDiscount[]` (type changed) | + +All fees are now per-execution. No server-side totals — the client computes. +Components: `executionFee` (USD) + `cogs[]` (WEI) + `valueFee` (PERCENTAGE). + +### `ExecutionProps` + +| Removed Fields | Added Fields | +|----------------|-------------| +| `totalGasCost: string` | `executionFee: Fee` | +| | `cogs: NodeCOGS[]` | +| | `valueFee: ValueFee` | + +### SDK Internal Methods (`Client`) + +| Method | Change | +|--------|--------| +| `convertEstimateFeesResponse()` | Rewritten for new proto fields | +| `convertFeeAmount()` | Removed | +| `createZeroFeeAmount()` | Removed | +| `createMockFeeAmount()` | Removed | + +## Test Utilities + +| Change | File | +|--------|------| +| `expectAutomationFee` alias removed | `tests/utils/utils.ts` | +| `expectExecutionFees` updated for `Fee`/`NodeCOGS`/`ValueFee` | `tests/utils/utils.ts` | +| Backward pagination tests fixed (all 3 suites) | `getExecutions`, `workflow`, `secret` | +| `gasTracking.test.ts` migrated from `execution.totalGasCost` to `execution.cogs` | `tests/executions/gasTracking.test.ts` | + +--- + +## Migration Guide + +### 1. Import Changes + +```diff +- import type { +- FeeAmount, +- GasFeeBreakdown, +- NodeGasFee, +- AutomationFee, +- AutomationFeeComponent, +- SmartWalletCreationFee, +- Discount, +- } from "@avaprotocol/types"; + ++ import type { ++ Fee, ++ FeeUnit, ++ NativeToken, ++ NodeCOGS, ++ ValueFee, ++ FeeDiscount, ++ } from "@avaprotocol/types"; +``` + +### 2. Execution Object Migration + +Any code accessing `execution.totalGasCost` or `execution.automationFee` must switch to the new fields: + +```diff + // Before +- const gasCost = execution.totalGasCost; // string (wei) +- const fee = execution.automationFee; // FeeAmount +- const feeUsd = execution.automationFee?.usdAmount; + + // After ++ const platformFee = execution.executionFee; // Fee { amount: "0.020000", unit: "USD" } ++ const gasCosts = execution.cogs; // NodeCOGS[] — per-node gas/API costs ++ const valueFee = execution.valueFee; // ValueFee — percentage-based value capture +``` + +Example: summing total gas cost from COGS: + +```typescript +const totalGasWei = execution.cogs + .filter((c) => c.costType === "gas") + .reduce((sum, c) => sum + BigInt(c.fee.amount), BigInt(0)); +``` + +### 3. Fee Estimation Response Migration + +The response no longer has nested breakdown objects or server-computed totals: + +```diff + // Before +- const gasTotal = response.gasFees?.totalGasCost; +- const automationTotal = response.automationFees?.totalFee; +- const walletCreation = response.creationFees?.creationFee; +- const total = response.finalTotal; // FeeAmount +- const discountPct = response.discounts?.[0]?.discountPercentage; + + // After — flat per-execution structure ++ const platformFee = response.executionFee; // Fee { amount, unit: "USD" } ++ const nodeCosts = response.cogs; // NodeCOGS[] ++ const valueFee = response.valueFee; // ValueFee ++ const discounts = response.discounts; // FeeDiscount[] ++ const nativeToken = response.nativeToken; // { symbol: "ETH", decimals: 18 } +``` + +### 4. Fee Display Logic + +The old `FeeAmount` had `nativeTokenAmount`, `usdAmount`, and `nativeTokenSymbol` baked in. The new `Fee` is unit-tagged — the client must handle formatting per unit: + +```diff + // Before +- function formatFee(fee: FeeAmount): string { +- return `${fee.nativeTokenSymbol} ${fee.nativeTokenAmount} ($${fee.usdAmount})`; +- } + + // After ++ function formatFee(fee: Fee): string { ++ switch (fee.unit) { ++ case "USD": ++ return `$${fee.amount}`; ++ case "WEI": ++ return `${fee.amount} wei`; ++ case "PERCENTAGE": ++ return `${fee.amount}%`; ++ } ++ } +``` + +To convert WEI to a human-readable ETH amount, use `nativeToken.decimals` from the response: + +```typescript +function formatWei(amount: string, decimals: number, symbol: string): string { + const value = Number(BigInt(amount)) / 10 ** decimals; + return `${value.toFixed(6)} ${symbol}`; +} + +// Usage with estimation response +if (response.nativeToken) { + const { symbol, decimals } = response.nativeToken; + for (const cogs of response.cogs) { + console.log(formatWei(cogs.fee.amount, decimals, symbol)); + } +} +``` + +### 5. Client-Side Total Computation + +The server no longer returns `totalFees`, `totalDiscounts`, or `finalTotal`. The client computes totals from the components: + +```typescript +import type { EstimateFeesResponse } from "@avaprotocol/types"; + +function computeTotals(response: EstimateFeesResponse) { + // Platform fee (USD) + const executionFeeUsd = parseFloat(response.executionFee?.amount ?? "0"); + + // Sum gas COGS (WEI) — convert to ETH for display + const decimals = response.nativeToken?.decimals ?? 18; + const totalCogsWei = response.cogs.reduce( + (sum, c) => sum + BigInt(c.fee.amount), + BigInt(0) + ); + const totalCogsEth = Number(totalCogsWei) / 10 ** decimals; + + // Value fee (percentage of transaction value — applied by the client) + const valueFeePercent = parseFloat(response.valueFee?.fee.amount ?? "0"); + + // Sum discounts (check unit per discount) + const totalDiscountUsd = response.discounts + .filter((d) => d.discount.unit === "USD") + .reduce((sum, d) => sum + parseFloat(d.discount.amount), 0); + + return { + executionFeeUsd, + totalCogsWei: totalCogsWei.toString(), + totalCogsEth, + valueFeePercent, + totalDiscountUsd, + }; +} +``` + +### Quick Reference: Field Mapping + +| Old Field | New Field | Notes | +|-----------|-----------|-------| +| `execution.totalGasCost` | `execution.cogs` | Array of per-node costs | +| `execution.automationFee` | `execution.executionFee` | Now `Fee { amount, unit }` | +| `response.gasFees.totalGasCost` | `sum(response.cogs[].fee)` | Client computes total | +| `response.gasFees.nodeGasFees` | `response.cogs` | Renamed, simplified | +| `response.automationFees.totalFee` | `response.executionFee` | Flat platform fee | +| `response.creationFees` | _(removed)_ | No longer in response | +| `response.totalFees` | _(removed)_ | Client computes | +| `response.finalTotal` | _(removed)_ | Client computes | +| `response.totalDiscounts` | `sum(response.discounts[].discount)` | Client computes | +| `discount.discountPercentage` | `discount.discount` | Now `Fee { amount, unit }` | +| `discount.discountAmount` | `discount.discount` | Unified into one field | +| `discount.appliesTo` | _(removed)_ | | +| `fee.nativeTokenAmount` | `fee.amount` (when `unit === "WEI"`) | Unit-tagged | +| `fee.usdAmount` | `fee.amount` (when `unit === "USD"`) | Unit-tagged | diff --git a/examples/fee-estimation-example.ts b/examples/fee-estimation-example.ts index fd5f5c53..e6184d7c 100644 --- a/examples/fee-estimation-example.ts +++ b/examples/fee-estimation-example.ts @@ -2,18 +2,24 @@ /** * Fee Estimation Example - * - * This example demonstrates how to use the new fee estimation functionality - * to get comprehensive cost breakdowns before deploying workflows. + * + * Demonstrates how to use the fee estimation API to get per-execution + * cost breakdowns before deploying workflows. + * + * Response components (all per-execution): + * executionFee — flat platform fee (USD) + * cogs[] — per-node operational costs: gas, external API (WEI) + * valueFee — workflow-level value-capture fee (PERCENTAGE) */ import { Client } from '../packages/sdk-js/src/index'; -import type { +import type { TriggerType, EstimateFeesRequest, EstimateFeesResponse, + Fee, TriggerProps, - NodeProps + NodeProps, } from '@avaprotocol/types'; // Example configuration @@ -22,28 +28,26 @@ const TEST_API_KEY = process.env.TEST_API_KEY || ''; const SMART_WALLET_ADDRESS = process.env.SMART_WALLET_ADDRESS || '0x742d35Cc6634C0532925a3b8D965337c7FF18723'; async function demonstrateFeeEstimation() { - // Initialize the client const client = new Client({ endpoint: AGGREGATOR_ENDPOINT, }); - // Set auth key if available if (TEST_API_KEY) { client.setAuthKey(TEST_API_KEY); } - console.log('🔍 Fee Estimation Example'); + console.log('Fee Estimation Example'); console.log('========================\n'); try { // Example 1: Simple fixed-time trigger with REST API call - console.log('📊 Example 1: Simple workflow with fixed-time trigger'); + console.log('Example 1: Simple workflow with fixed-time trigger'); console.log('-----------------------------------------------------'); - + const simpleTrigger: TriggerProps = { type: TriggerType.FixedTime, config: { - datetime: Math.floor(Date.now() / 1000) + 3600, // 1 hour from now + datetime: Math.floor(Date.now() / 1000) + 3600, }, }; @@ -69,7 +73,7 @@ async function demonstrateFeeEstimation() { }, }, createdAt: Date.now(), - expireAt: Date.now() + (24 * 60 * 60 * 1000), // 24 hours from now + expireAt: Date.now() + (24 * 60 * 60 * 1000), }; const simpleEstimation = await client.estimateFees(simpleRequest); @@ -78,7 +82,7 @@ async function demonstrateFeeEstimation() { console.log('\n'); // Example 2: Complex workflow with event trigger and contract interaction - console.log('📊 Example 2: Complex workflow with event trigger and contract write'); + console.log('Example 2: Complex workflow with event trigger and contract write'); console.log('---------------------------------------------------------------------'); const complexTrigger: TriggerProps = { @@ -90,9 +94,9 @@ async function demonstrateFeeEstimation() { { type: 'topic', values: [ - '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef', // Transfer signature - '', // from (any) - '0x000000000000000000000000' + SMART_WALLET_ADDRESS.slice(2), // to (our wallet) + '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef', + '', + '0x000000000000000000000000' + SMART_WALLET_ADDRESS.slice(2), ], }, ], @@ -119,7 +123,7 @@ async function demonstrateFeeEstimation() { functionName: 'approve', args: [ '0x1234567890123456789012345678901234567890', - '1000000000000000000', // 1 token + '1000000000000000000', ], }, }, @@ -128,7 +132,7 @@ async function demonstrateFeeEstimation() { type: 'ethTransfer', config: { to: '0x1234567890123456789012345678901234567890', - amount: '100000000000000000', // 0.1 ETH + amount: '100000000000000000', }, }, ]; @@ -144,7 +148,7 @@ async function demonstrateFeeEstimation() { }, }, createdAt: Date.now(), - expireAt: Date.now() + (7 * 24 * 60 * 60 * 1000), // 7 days from now + expireAt: Date.now() + (7 * 24 * 60 * 60 * 1000), }; const complexEstimation = await client.estimateFees(complexRequest); @@ -153,13 +157,13 @@ async function demonstrateFeeEstimation() { console.log('\n'); // Example 3: Long-running cron workflow - console.log('📊 Example 3: Long-running cron workflow'); + console.log('Example 3: Long-running cron workflow'); console.log('----------------------------------------'); const cronTrigger: TriggerProps = { type: TriggerType.Cron, config: { - cron: '0 */6 * * *', // Every 6 hours + cron: '0 */6 * * *', }, }; @@ -177,7 +181,7 @@ async function demonstrateFeeEstimation() { type: 'ethTransfer', config: { to: '0x1234567890123456789012345678901234567890', - amount: '50000000000000000', // 0.05 ETH + amount: '50000000000000000', }, }, ]; @@ -193,152 +197,94 @@ async function demonstrateFeeEstimation() { }, }, createdAt: Date.now(), - expireAt: Date.now() + (30 * 24 * 60 * 60 * 1000), // 30 days from now + expireAt: Date.now() + (30 * 24 * 60 * 60 * 1000), }; const cronEstimation = await client.estimateFees(cronRequest); printFeeEstimation('Cron Workflow (30 days)', cronEstimation); } catch (error: any) { - console.error('❌ Error during fee estimation:', error.message); + console.error('Error during fee estimation:', error.message); if (error.details) { console.error('Details:', error.details); } } } -/** - * Print fee estimation results in a readable format - */ +function formatFee(fee: Fee): string { + return `${fee.amount} ${fee.unit}`; +} + function printFeeEstimation(title: string, estimation: EstimateFeesResponse) { - console.log(`💰 ${title} Fee Estimation:`); - + console.log(`${title} Fee Estimation:`); + if (!estimation.success) { - console.log(`❌ Error: ${estimation.error}`); + console.log(` Error: ${estimation.error}`); if (estimation.errorCode) { - console.log(` Code: ${estimation.errorCode}`); + console.log(` Code: ${estimation.errorCode}`); } return; } - console.log('✅ Estimation successful'); - + console.log(' Estimation successful'); + if (estimation.chainId) { - console.log(`🔗 Chain ID: ${estimation.chainId}`); + console.log(` Chain ID: ${estimation.chainId}`); } - - // Gas fees - if (estimation.gasFees) { - console.log('⛽ Gas Fees:'); - console.log(` Total: ${formatFeeAmount(estimation.gasFees.totalGasCost)}`); - console.log(` Method: ${estimation.gasFees.estimationMethod}`); - console.log(` Accurate: ${estimation.gasFees.estimationAccurate ? '✅' : '⚠️'}`); - console.log(` Avg Gas Price: ${estimation.gasFees.averageGasPrice} gwei`); - - if (estimation.gasFees.nodeGasFees.length > 0) { - console.log(' Operations:'); - estimation.gasFees.nodeGasFees.forEach((op, i) => { - console.log(` ${i + 1}. ${op.operationType} (${op.nodeId}): ${formatFeeAmount(op.totalCost)}`); - if (op.methodName) { - console.log(` Method: ${op.methodName}`); - } - console.log(` Gas Units: ${op.gasUnits}`); - }); - } + + if (estimation.nativeToken) { + console.log(` Native Token: ${estimation.nativeToken.symbol} (${estimation.nativeToken.decimals} decimals)`); } - // Automation fees - if (estimation.automationFees) { - console.log('🤖 Automation Fees:'); - console.log(` Trigger Type: ${estimation.automationFees.triggerType}`); - console.log(` Duration: ${estimation.automationFees.durationMinutes} minutes`); - console.log(` Base Fee: ${formatFeeAmount(estimation.automationFees.baseFee)}`); - console.log(` Execution Fee: ${formatFeeAmount(estimation.automationFees.executionFee)}`); - console.log(` Est. Executions: ${estimation.automationFees.estimatedExecutions}`); - console.log(` Total: ${formatFeeAmount(estimation.automationFees.totalFee)}`); + // Execution fee (flat platform fee) + if (estimation.executionFee) { + console.log(` Execution Fee: ${formatFee(estimation.executionFee)}`); } - // Smart wallet creation - if (estimation.creationFees) { - console.log('🏦 Smart Wallet:'); - console.log(` Creation Required: ${estimation.creationFees.creationRequired ? '✅' : '❌'}`); - console.log(` Wallet Address: ${estimation.creationFees.walletAddress}`); - if (estimation.creationFees.creationRequired && estimation.creationFees.creationFee) { - console.log(` Creation Fee: ${formatFeeAmount(estimation.creationFees.creationFee)}`); - if (estimation.creationFees.initialFunding) { - console.log(` Recommended Funding: ${formatFeeAmount(estimation.creationFees.initialFunding)}`); + // COGS (per-node operational costs) + if (estimation.cogs.length > 0) { + console.log(' Node COGS:'); + estimation.cogs.forEach((cogs, i) => { + console.log(` ${i + 1}. ${cogs.nodeId} [${cogs.costType}]: ${formatFee(cogs.fee)}`); + if (cogs.gasUnits) { + console.log(` Gas Units: ${cogs.gasUnits}`); } + }); + } + + // Value fee (workflow-level value-capture) + if (estimation.valueFee) { + console.log(' Value Fee:'); + console.log(` Fee: ${formatFee(estimation.valueFee.fee)}`); + console.log(` Tier: ${estimation.valueFee.tier}`); + console.log(` Classification: ${estimation.valueFee.classificationMethod} (confidence: ${estimation.valueFee.confidence})`); + console.log(` Reason: ${estimation.valueFee.reason}`); + if (estimation.valueFee.valueBase) { + console.log(` Value Base: ${estimation.valueFee.valueBase}`); } } // Discounts - if (estimation.discounts && estimation.discounts.length > 0) { - console.log('🎫 Discounts Applied:'); + if (estimation.discounts.length > 0) { + console.log(' Discounts:'); estimation.discounts.forEach((discount, i) => { - console.log(` ${i + 1}. ${discount.discountName} (${discount.discountPercentage}% off)`); - console.log(` Applies to: ${discount.appliesTo}`); - console.log(` Discount: ${formatFeeAmount(discount.discountAmount)}`); + console.log(` ${i + 1}. ${discount.discountName} (${discount.discountType}): ${formatFee(discount.discount)}`); if (discount.expiryDate) { - console.log(` Expires: ${discount.expiryDate}`); + console.log(` Expires: ${discount.expiryDate}`); } }); } - // Totals - console.log('💳 Total Costs:'); - if (estimation.totalFees) { - console.log(` Before Discounts: ${formatFeeAmount(estimation.totalFees)}`); - } - if (estimation.totalDiscounts) { - console.log(` Total Discounts: ${formatFeeAmount(estimation.totalDiscounts)}`); - } - if (estimation.finalTotal) { - console.log(` 🎯 Final Total: ${formatFeeAmount(estimation.finalTotal)}`); - } - - // Warnings and recommendations - if (estimation.warnings && estimation.warnings.length > 0) { - console.log('⚠️ Warnings:'); + // Warnings + if (estimation.warnings.length > 0) { + console.log(' Warnings:'); estimation.warnings.forEach((warning, i) => { - console.log(` ${i + 1}. ${warning}`); + console.log(` ${i + 1}. ${warning}`); }); } - if (estimation.recommendations && estimation.recommendations.length > 0) { - console.log('💡 Recommendations:'); - estimation.recommendations.forEach((rec, i) => { - console.log(` ${i + 1}. ${rec}`); - }); - } - - // Metadata - if (estimation.priceDataSource) { - console.log(`📊 Price Data: ${estimation.priceDataSource}${estimation.priceDataAgeSeconds ? ` (${estimation.priceDataAgeSeconds}s ago)` : ''}`); - } -} - -/** - * Format fee amount for display - */ -function formatFeeAmount(feeAmount: any): string { - return `${feeAmount.nativeTokenSymbol} ${formatWeiAmount(feeAmount.nativeTokenAmount)} ($${feeAmount.usdAmount})`; -} - -/** - * Format wei amount to human-readable format - */ -function formatWeiAmount(weiString: string): string { - const wei = BigInt(weiString); - const ethInt = wei / BigInt(1e18); - const ethFrac = wei % BigInt(1e18); - const eth = Number(ethInt) + Number(ethFrac) / 1e18; - - if (eth < 0.0001) { - return wei.toString() + ' wei'; - } else if (eth < 1) { - return eth.toFixed(6); - } else { - return eth.toFixed(4); + if (estimation.pricingModel) { + console.log(` Pricing Model: ${estimation.pricingModel}`); } } @@ -347,4 +293,4 @@ if (require.main === module) { demonstrateFeeEstimation().catch(console.error); } -export { demonstrateFeeEstimation }; \ No newline at end of file +export { demonstrateFeeEstimation }; diff --git a/jest.config.cjs b/jest.config.cjs index ec87c544..43566fdc 100644 --- a/jest.config.cjs +++ b/jest.config.cjs @@ -18,4 +18,8 @@ module.exports = { "^@/types/(.*)$": "/packages/types/$1", }, setupFilesAfterEnv: ["/tests/utils/mocks/api.ts"], + reporters: [ + "default", + "/tests/utils/failureSummaryReporter.js", + ], }; diff --git a/packages/types/src/api.ts b/packages/types/src/api.ts index 78d38c16..3c6b8a12 100644 --- a/packages/types/src/api.ts +++ b/packages/types/src/api.ts @@ -416,11 +416,3 @@ export interface EstimateFeesResponse { warnings: string[]; } -// Legacy type — kept for any third-party code that may reference it. -// New code should use Fee instead. -export interface FeeAmount { - nativeTokenAmount: string; - nativeTokenSymbol: string; - usdAmount: string; - apTokenAmount: string; -} diff --git a/packages/types/src/index.ts b/packages/types/src/index.ts index ff4e834c..47286bd5 100644 --- a/packages/types/src/index.ts +++ b/packages/types/src/index.ts @@ -29,5 +29,4 @@ export type { NodeCOGS, ValueFee, FeeDiscount, - FeeAmount, } from "./api"; diff --git a/tests/executions/gasTracking.test.ts b/tests/executions/gasTracking.test.ts index dee5763f..a89f2721 100644 --- a/tests/executions/gasTracking.test.ts +++ b/tests/executions/gasTracking.test.ts @@ -129,14 +129,17 @@ describeIfSepolia("Gas Tracking Tests", () => { createdIdMap.set(workflowId, true); // Trigger the workflow with blocking execution - const triggerResult = await client.triggerWorkflow({ - id: workflowId, - triggerData: { - type: TriggerType.Manual, - data: {}, + const triggerResult = await client.triggerWorkflow( + { + id: workflowId, + triggerData: { + type: TriggerType.Manual, + data: {}, + }, + isBlocking: true, }, - isBlocking: true, - }); + { timeout: TimeoutPresets.SLOW } + ); // Accept both success and partialSuccess (operational issues may cause partial failures) expect([ @@ -204,20 +207,22 @@ describeIfSepolia("Gas Tracking Tests", () => { ); expect(execution).toBeDefined(); - // Check for execution-level gas cost aggregation if any gas operations succeeded - if (execution.totalGasCost) { - expect(typeof execution.totalGasCost).toBe("string"); - // Accept 0 gas costs for operations that failed before gas consumption - expect(parseInt(execution.totalGasCost)).toBeGreaterThanOrEqual(0); - - // Log the gas cost for debugging + // Check for execution-level COGS if any gas operations succeeded + expect(Array.isArray(execution.cogs)).toBe(true); + if (execution.cogs.length > 0) { + execution.cogs.forEach((cogs) => { + expect(cogs.nodeId).toBeDefined(); + expect(cogs.costType).toBeDefined(); + expect(cogs.fee).toBeDefined(); + expect(cogs.fee.unit).toBe("WEI"); + }); console.log( - "✅ ETH Transfer gas tracking validated - execution gas cost:", - execution.totalGasCost + "✅ ETH Transfer gas tracking validated - execution COGS:", + JSON.stringify(execution.cogs) ); } else { console.log( - "✅ ETH Transfer gas tracking infrastructure validated - no gas cost recorded due to early failure" + "✅ ETH Transfer gas tracking infrastructure validated - no COGS recorded due to early failure" ); } } finally { @@ -335,40 +340,41 @@ describeIfSepolia("Gas Tracking Tests", () => { triggerResult.executionId ); expect(execution).toBeDefined(); - expect(execution.totalGasCost).toBeDefined(); - expect(typeof execution.totalGasCost).toBe("string"); - expect(parseInt(execution.totalGasCost!)).toBeGreaterThan(0); - - // Execution total gas cost should match step total for single contract write - expect(execution.totalGasCost).toBe(contractWriteStep.totalGasCost); + expect(Array.isArray(execution.cogs)).toBe(true); + expect(execution.cogs.length).toBeGreaterThan(0); + + // COGS should include the contract write node's gas cost + execution.cogs.forEach((cogs) => { + expect(cogs.nodeId).toBeDefined(); + expect(cogs.costType).toBeDefined(); + expect(cogs.fee).toBeDefined(); + expect(cogs.fee.unit).toBe("WEI"); + }); } else { console.log( "Contract write step not found - checking for successful operation in logs" ); - // Even if step not found in the main steps, check if any gas operations succeeded - // by looking at the execution total const execution = await client.getExecution( workflowId, triggerResult.executionId ); expect(execution).toBeDefined(); - if (execution.totalGasCost) { + if (execution.cogs.length > 0) { console.log( - "Found execution-level gas cost despite missing step:", - execution.totalGasCost + "Found execution-level COGS despite missing step:", + JSON.stringify(execution.cogs) ); - expect(typeof execution.totalGasCost).toBe("string"); - // Accept 0 gas costs for operations that failed before gas consumption - expect(parseInt(execution.totalGasCost)).toBeGreaterThanOrEqual(0); + execution.cogs.forEach((cogs) => { + expect(cogs.fee.unit).toBe("WEI"); + }); console.log( - "✅ Contract write gas tracking validated - execution gas cost:", - execution.totalGasCost + "✅ Contract write gas tracking validated via COGS" ); } else { console.log( - "✅ Contract write gas tracking infrastructure validated - no gas cost due to early failure" + "✅ Contract write gas tracking infrastructure validated - no COGS due to early failure" ); } } @@ -504,23 +510,22 @@ describeIfSepolia("Gas Tracking Tests", () => { ); expect(execution).toBeDefined(); - // Check for execution-level gas aggregation if any operations succeeded - if (execution.totalGasCost) { - expect(typeof execution.totalGasCost).toBe("string"); - // Accept 0 gas costs for operations that failed before gas consumption - expect(parseInt(execution.totalGasCost)).toBeGreaterThanOrEqual(0); + // Check for execution-level COGS if any operations succeeded + expect(Array.isArray(execution.cogs)).toBe(true); + if (execution.cogs.length > 0) { + execution.cogs.forEach((cogs) => { + expect(cogs.nodeId).toBeDefined(); + expect(cogs.costType).toBeDefined(); + expect(cogs.fee).toBeDefined(); + expect(cogs.fee.unit).toBe("WEI"); + }); console.log( - "✅ Loop ETH transfer gas tracking validated - execution gas cost:", - execution.totalGasCost + "✅ Loop ETH transfer gas tracking validated - execution COGS:", + JSON.stringify(execution.cogs) ); - - // If both loop step and execution have gas data, they should match - if (loopStep && loopStep.totalGasCost) { - expect(execution.totalGasCost).toBe(loopStep.totalGasCost); - } } else { console.log( - "✅ Loop ETH transfer gas tracking infrastructure validated - no gas cost due to setup failure" + "✅ Loop ETH transfer gas tracking infrastructure validated - no COGS due to setup failure" ); } } finally { @@ -661,23 +666,22 @@ describeIfSepolia("Gas Tracking Tests", () => { ); expect(execution).toBeDefined(); - // Check for execution-level gas aggregation if any operations succeeded - if (execution.totalGasCost) { - expect(typeof execution.totalGasCost).toBe("string"); - // Accept 0 gas costs for operations that failed before gas consumption - expect(parseInt(execution.totalGasCost)).toBeGreaterThanOrEqual(0); + // Check for execution-level COGS if any operations succeeded + expect(Array.isArray(execution.cogs)).toBe(true); + if (execution.cogs.length > 0) { + execution.cogs.forEach((cogs) => { + expect(cogs.nodeId).toBeDefined(); + expect(cogs.costType).toBeDefined(); + expect(cogs.fee).toBeDefined(); + expect(cogs.fee.unit).toBe("WEI"); + }); console.log( - "✅ Loop contract write gas tracking validated - execution gas cost:", - execution.totalGasCost + "✅ Loop contract write gas tracking validated - execution COGS:", + JSON.stringify(execution.cogs) ); - - // If both loop step and execution have gas data, they should match - if (loopStep && loopStep.totalGasCost) { - expect(execution.totalGasCost).toBe(loopStep.totalGasCost); - } } else { console.log( - "✅ Loop contract write gas tracking infrastructure validated - no gas cost due to setup failure" + "✅ Loop contract write gas tracking infrastructure validated - no COGS due to setup failure" ); } } finally { @@ -836,28 +840,21 @@ describeIfSepolia("Gas Tracking Tests", () => { ); expect(execution).toBeDefined(); - if (execution.totalGasCost && successfulSteps.length > 0) { - expect(typeof execution.totalGasCost).toBe("string"); - expect(parseInt(execution.totalGasCost)).toBeGreaterThan(0); + expect(Array.isArray(execution.cogs)).toBe(true); - // If we have multiple successful steps, validate aggregation + if (execution.cogs.length > 0 && successfulSteps.length > 0) { + // Validate COGS entries + execution.cogs.forEach((cogs) => { + expect(cogs.nodeId).toBeDefined(); + expect(cogs.costType).toBeDefined(); + expect(cogs.fee).toBeDefined(); + expect(cogs.fee.unit).toBe("WEI"); + }); + + // If we have multiple successful steps, COGS should have multiple entries if (successfulSteps.length > 1) { - const totalStepCosts = successfulSteps.reduce( - (sum, step) => sum + BigInt(step.totalGasCost!), - BigInt(0) - ); - expect(BigInt(execution.totalGasCost!)).toBe(totalStepCosts); - - // Execution total should be greater than any individual step - successfulSteps.forEach((step) => { - expect(parseInt(execution.totalGasCost!)).toBeGreaterThan( - parseInt(step.totalGasCost!) - ); - }); - } else if (successfulSteps.length === 1) { - // For single successful step, execution total should match step total - expect(execution.totalGasCost).toBe( - successfulSteps[0].totalGasCost + expect(execution.cogs.length).toBeGreaterThanOrEqual( + successfulSteps.length ); } } else { diff --git a/tests/executions/runNodeWithInputs.test.ts b/tests/executions/runNodeWithInputs.test.ts index 8e915b4a..1d4bfa52 100644 --- a/tests/executions/runNodeWithInputs.test.ts +++ b/tests/executions/runNodeWithInputs.test.ts @@ -1,6 +1,6 @@ import { describe, beforeAll, test, expect } from "@jest/globals"; import { Client } from "@avaprotocol/sdk-js"; -import { NodeType } from "@avaprotocol/types"; +import { NodeType, TimeoutPresets } from "@avaprotocol/types"; import { TIMEOUT_DURATION, getSettings, @@ -182,7 +182,9 @@ describe("RunNodeWithInputs", () => { util.inspect(params, { depth: null, colors: true }) ); - const result = await client.runNodeWithInputs(params); + const result = await client.runNodeWithInputs(params, { + timeout: TimeoutPresets.SLOW, + }); console.log( "🚀 ~ runNodeWithInputs ContractWrite with isSimulated=false ~ result:", diff --git a/tests/nodes/contractWrite.test.ts b/tests/nodes/contractWrite.test.ts index 08002cee..5863756b 100644 --- a/tests/nodes/contractWrite.test.ts +++ b/tests/nodes/contractWrite.test.ts @@ -888,7 +888,9 @@ describeIfSepolia("ContractWrite Node Tests", () => { isBlocking: true, }; - await client.triggerWorkflow(triggerParams); + await client.triggerWorkflow(triggerParams, { + timeout: TimeoutPresets.SLOW, + }); const executions = await client.getExecutions([workflowId], { limit: 1, @@ -1070,7 +1072,7 @@ describeIfSepolia("ContractWrite Node Tests", () => { createdIdMap.delete(workflowId); } } - }); + }, TIMEOUT_DURATION * 3); }); describe("Error Handling Tests", () => { diff --git a/tests/nodes/ethTransfer.test.ts b/tests/nodes/ethTransfer.test.ts index 4861eb90..e665e0c0 100644 --- a/tests/nodes/ethTransfer.test.ts +++ b/tests/nodes/ethTransfer.test.ts @@ -679,7 +679,7 @@ describeIfSepolia("ETHTransfer Node Tests", () => { ); const output = ethTransferStep.output as any; - expect(output).toBeDefined(); + expect(output).not.toBeNull(); expect(typeof output).toBe("object"); // Verify transfer object (matches ERC20 format) @@ -1061,7 +1061,7 @@ describeIfSepolia("ETHTransfer Node Tests", () => { createdIdMap.delete(workflowId); } } - }); + }, TIMEOUT_DURATION * 3); }); describe("Real Transaction Tests", () => { diff --git a/tests/nodes/loopNode.test.ts b/tests/nodes/loopNode.test.ts index dd69e670..65385428 100644 --- a/tests/nodes/loopNode.test.ts +++ b/tests/nodes/loopNode.test.ts @@ -394,7 +394,7 @@ describe("LoopNode Tests", () => { }, inputVariables: { contractAddresses: [ - "0x1234567890abcdef1234567890abcdef12345678", // Mock contract address (doesn't have name/symbol) + "0xB0C712f98daE15264c8E26132BCC91C40aD4d5F9", // Chainlink ETH/USD price feed (doesn't have name/symbol) USDC_SEPOLIA_ADDRESS, // USDC contract (has name/symbol) ], }, @@ -2391,7 +2391,7 @@ describe("LoopNode Tests", () => { inputVariables: { contractAddresses: [ - "0x1234567890abcdef1234567890abcdef12345678", // Mock contract address (doesn't have name/symbol) + "0xB0C712f98daE15264c8E26132BCC91C40aD4d5F9", // Chainlink ETH/USD price feed (doesn't have name/symbol) USDC_SEPOLIA_ADDRESS, // USDC contract (has name/symbol) ], }, diff --git a/tests/utils/failureSummaryReporter.js b/tests/utils/failureSummaryReporter.js new file mode 100644 index 00000000..5c4b6373 --- /dev/null +++ b/tests/utils/failureSummaryReporter.js @@ -0,0 +1,50 @@ +/** + * Custom Jest reporter that prints a clear summary of failed tests at the end. + * Works alongside --silent to keep output clean while surfacing failures. + */ +class FailureSummaryReporter { + constructor(globalConfig) { + this._globalConfig = globalConfig; + } + + onRunComplete(_contexts, results) { + const { testResults } = results; + const failures = []; + + for (const suite of testResults) { + for (const test of suite.testResults) { + if (test.status === "failed") { + failures.push({ + suitePath: suite.testFilePath.replace(process.cwd() + "/", ""), + testName: test.ancestorTitles.concat(test.title).join(" > "), + messages: test.failureMessages, + }); + } + } + } + + if (failures.length === 0) return; + + console.log("\n" + "=".repeat(80)); + console.log(`FAILURE SUMMARY: ${failures.length} test(s) failed`); + console.log("=".repeat(80)); + + failures.forEach((f, i) => { + console.log(`\n${i + 1}) ${f.suitePath}`); + console.log(` ${f.testName}`); + // Print first failure message, trimmed + if (f.messages.length > 0) { + const msg = f.messages[0] + .split("\n") + .slice(0, 10) + .map((line) => ` ${line}`) + .join("\n"); + console.log(msg); + } + }); + + console.log("\n" + "=".repeat(80) + "\n"); + } +} + +module.exports = FailureSummaryReporter; diff --git a/tests/utils/utils.ts b/tests/utils/utils.ts index 464bf666..d17d08d3 100644 --- a/tests/utils/utils.ts +++ b/tests/utils/utils.ts @@ -764,8 +764,6 @@ export function expectExecutionFees( } } -/** @deprecated Use expectExecutionFees instead */ -export const expectAutomationFee = expectExecutionFees; export const verifyExecutionStepResults = ( expected: StepProps, From a40932dc60e489477e7c53db58f7b82f26c0c5f9 Mon Sep 17 00:00:00 2001 From: Will Zimmerman Date: Mon, 6 Apr 2026 16:12:46 -0700 Subject: [PATCH 5/8] =?UTF-8?q?fix:=20address=20PR=20review=20=E2=80=94=20?= =?UTF-8?q?cogs=20type=20consistency,=20path=20portability,=20estimateFees?= =?UTF-8?q?=20test?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Make cogs required (not optional) in expectExecutionFees parameter type - Use path.relative() in failure summary reporter for cross-platform support - Add estimateFees test covering response shape validation (executionFee, cogs, valueFee, discounts, nativeToken, warnings) --- tests/executions/estimateFees.test.ts | 177 ++++++++++++++++++++++++++ tests/utils/failureSummaryReporter.js | 4 +- tests/utils/utils.ts | 20 ++- 3 files changed, 189 insertions(+), 12 deletions(-) create mode 100644 tests/executions/estimateFees.test.ts diff --git a/tests/executions/estimateFees.test.ts b/tests/executions/estimateFees.test.ts new file mode 100644 index 00000000..1cf433a5 --- /dev/null +++ b/tests/executions/estimateFees.test.ts @@ -0,0 +1,177 @@ +import { describe, beforeAll, test, expect } from "@jest/globals"; +import { Client } from "@avaprotocol/sdk-js"; +import { TriggerType, NodeType, Lang } from "@avaprotocol/types"; +import { + TIMEOUT_DURATION, + getNextId, + getSmartWallet, + getClient, + authenticateClient, +} from "../utils/utils"; + +jest.setTimeout(TIMEOUT_DURATION); + +describe("EstimateFees", () => { + let client: Client; + let smartWalletAddress: string; + + beforeAll(async () => { + client = getClient(); + await authenticateClient(client); + const wallet = await getSmartWallet(client); + smartWalletAddress = wallet.address; + }); + + test("should return fee estimation with correct structure for a simple workflow", async () => { + const triggerId = getNextId(); + const nodeId = getNextId(); + + const result = await client.estimateFees({ + trigger: { + id: triggerId, + name: "manualTrigger", + type: TriggerType.Manual, + data: {}, + }, + nodes: [ + { + id: nodeId, + name: "customCode", + type: NodeType.CustomCode, + data: { + lang: Lang.JavaScript, + source: "return { result: 1 };", + }, + }, + ], + runner: smartWalletAddress, + inputVariables: { + settings: { + name: "Fee Estimation Test", + runner: smartWalletAddress, + chain: "sepolia", + }, + }, + createdAt: Date.now(), + expireAt: Date.now() + 24 * 60 * 60 * 1000, + }); + + // Top-level response fields + expect(typeof result.success).toBe("boolean"); + expect(result).toHaveProperty("cogs"); + expect(Array.isArray(result.cogs)).toBe(true); + expect(result).toHaveProperty("discounts"); + expect(Array.isArray(result.discounts)).toBe(true); + expect(result).toHaveProperty("warnings"); + expect(Array.isArray(result.warnings)).toBe(true); + + if (!result.success) { + expect(typeof result.error).toBe("string"); + return; + } + + // executionFee should be a Fee with USD unit + expect(result.executionFee).toBeDefined(); + expect(typeof result.executionFee!.amount).toBe("string"); + expect(result.executionFee!.unit).toBe("USD"); + + // cogs entries should have correct shape + for (const cogs of result.cogs) { + expect(typeof cogs.nodeId).toBe("string"); + expect(typeof cogs.costType).toBe("string"); + expect(cogs.fee).toBeDefined(); + expect(typeof cogs.fee.amount).toBe("string"); + expect(cogs.fee.unit).toBe("WEI"); + } + + // valueFee when present + if (result.valueFee) { + expect(result.valueFee.fee).toBeDefined(); + expect(typeof result.valueFee.fee.amount).toBe("string"); + expect(result.valueFee.fee.unit).toBe("PERCENTAGE"); + expect(typeof result.valueFee.tier).toBe("string"); + expect(typeof result.valueFee.classificationMethod).toBe("string"); + expect(typeof result.valueFee.confidence).toBe("number"); + expect(typeof result.valueFee.reason).toBe("string"); + } + + // discounts entries when present + for (const discount of result.discounts) { + expect(typeof discount.discountType).toBe("string"); + expect(typeof discount.discountName).toBe("string"); + expect(discount.discount).toBeDefined(); + expect(typeof discount.discount.amount).toBe("string"); + expect(typeof discount.discount.unit).toBe("string"); + } + + // optional metadata fields + if (result.chainId) { + expect(typeof result.chainId).toBe("string"); + } + if (result.nativeToken) { + expect(typeof result.nativeToken.symbol).toBe("string"); + expect(typeof result.nativeToken.decimals).toBe("number"); + } + if (result.pricingModel) { + expect(typeof result.pricingModel).toBe("string"); + } + }); + + test("should return fee estimation for a workflow with ETH transfer node", async () => { + const triggerId = getNextId(); + const nodeId = getNextId(); + + const result = await client.estimateFees({ + trigger: { + id: triggerId, + name: "manualTrigger", + type: TriggerType.Manual, + data: {}, + }, + nodes: [ + { + id: nodeId, + name: "ethTransfer", + type: NodeType.ETHTransfer, + data: { + destination: smartWalletAddress, + amount: "1000000000000000", + }, + }, + ], + runner: smartWalletAddress, + inputVariables: { + settings: { + name: "ETH Transfer Fee Test", + runner: smartWalletAddress, + chain: "sepolia", + }, + }, + createdAt: Date.now(), + expireAt: Date.now() + 24 * 60 * 60 * 1000, + }); + + expect(typeof result.success).toBe("boolean"); + expect(Array.isArray(result.cogs)).toBe(true); + expect(Array.isArray(result.discounts)).toBe(true); + expect(Array.isArray(result.warnings)).toBe(true); + + if (result.success) { + // ETH transfer should produce gas COGS + if (result.cogs.length > 0) { + const gasCogs = result.cogs.filter((c) => c.costType === "gas"); + expect(gasCogs.length).toBeGreaterThan(0); + for (const cogs of gasCogs) { + expect(cogs.fee.unit).toBe("WEI"); + expect(BigInt(cogs.fee.amount)).toBeGreaterThanOrEqual(BigInt(0)); + } + } + + // valueFee should indicate on-chain execution + if (result.valueFee) { + expect(result.valueFee.fee.unit).toBe("PERCENTAGE"); + expect(typeof result.valueFee.tier).toBe("string"); + } + } + }); +}); diff --git a/tests/utils/failureSummaryReporter.js b/tests/utils/failureSummaryReporter.js index 5c4b6373..d6613a66 100644 --- a/tests/utils/failureSummaryReporter.js +++ b/tests/utils/failureSummaryReporter.js @@ -1,3 +1,5 @@ +const path = require("path"); + /** * Custom Jest reporter that prints a clear summary of failed tests at the end. * Works alongside --silent to keep output clean while surfacing failures. @@ -15,7 +17,7 @@ class FailureSummaryReporter { for (const test of suite.testResults) { if (test.status === "failed") { failures.push({ - suitePath: suite.testFilePath.replace(process.cwd() + "/", ""), + suitePath: path.relative(process.cwd(), suite.testFilePath), testName: test.ancestorTitles.concat(test.title).join(" > "), messages: test.failureMessages, }); diff --git a/tests/utils/utils.ts b/tests/utils/utils.ts index d17d08d3..2d5d7ca7 100644 --- a/tests/utils/utils.ts +++ b/tests/utils/utils.ts @@ -216,6 +216,7 @@ const fileToStartIndex: Record = { "inputVariables.test.ts": 220, // Shares with createWorkflow "partialSuccess.test.ts": 700, // Shares with execution "gasTracking.test.ts": 540, // Shares with contractWrite + "estimateFees.test.ts": 840, }; /** @@ -729,7 +730,7 @@ export function executionHasWriteFailure( export function expectExecutionFees( execution: { executionFee?: { amount?: string; unit?: string }; - cogs?: Array<{ nodeId?: string; costType?: string; fee?: { amount?: string; unit?: string } }>; + cogs: Array<{ nodeId?: string; costType?: string; fee?: { amount?: string; unit?: string } }>; valueFee?: { fee?: { amount?: string; unit?: string }; tier?: string }; } ): void { @@ -742,16 +743,13 @@ export function expectExecutionFees( } // cogs is always an array (may be empty) - expect(execution).toHaveProperty("cogs"); - if (execution.cogs) { - expect(Array.isArray(execution.cogs)).toBe(true); - for (const cogsEntry of execution.cogs) { - expect(cogsEntry).toHaveProperty("nodeId"); - expect(cogsEntry).toHaveProperty("costType"); - expect(cogsEntry).toHaveProperty("fee"); - if (cogsEntry.fee) { - expect(cogsEntry.fee.unit).toBe("WEI"); - } + expect(Array.isArray(execution.cogs)).toBe(true); + for (const cogsEntry of execution.cogs) { + expect(cogsEntry).toHaveProperty("nodeId"); + expect(cogsEntry).toHaveProperty("costType"); + expect(cogsEntry).toHaveProperty("fee"); + if (cogsEntry.fee) { + expect(cogsEntry.fee.unit).toBe("WEI"); } } From e789ff0739b69212571f76c04f932a1364b63dad Mon Sep 17 00:00:00 2001 From: Will Zimmerman Date: Mon, 6 Apr 2026 16:36:06 -0700 Subject: [PATCH 6/8] chore: disable auto-run on PR against production aggregator --- .github/workflows/prod-test-on-pr.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/prod-test-on-pr.yml b/.github/workflows/prod-test-on-pr.yml index 9c0f9ebd..895f2df3 100644 --- a/.github/workflows/prod-test-on-pr.yml +++ b/.github/workflows/prod-test-on-pr.yml @@ -1,7 +1,9 @@ -name: Run Production Tests on PR +name: Run Production Tests +# Production tests run against live deployed endpoints. Do NOT enable auto-run on +# pull_request — in-flight PR changes will break against the current production +# deployment. Trigger this workflow manually after a release is deployed. on: - # pull_request: # Disabled to prevent conflicts with dev-test-on-pr workflow workflow_dispatch: inputs: environment: From fb5e792c635fd6b1b873cd58fe3c16a25266a6b6 Mon Sep 17 00:00:00 2001 From: Will Zimmerman Date: Mon, 6 Apr 2026 16:38:51 -0700 Subject: [PATCH 7/8] ci: enable executions test suite in PR workflow --- .github/workflows/dev-test-on-pr.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/dev-test-on-pr.yml b/.github/workflows/dev-test-on-pr.yml index 6585c822..39886642 100644 --- a/.github/workflows/dev-test-on-pr.yml +++ b/.github/workflows/dev-test-on-pr.yml @@ -68,7 +68,7 @@ jobs: strategy: fail-fast: false matrix: - suite: [workflows, triggers] # Other suites (core, executions, nodes, templates) disabled — bundler not reachable from CI, run locally + suite: [workflows, triggers, executions] env: # Secrets From 5312428319a9822790b6dc18d3070f27eaa9eb5c Mon Sep 17 00:00:00 2001 From: Will Zimmerman Date: Mon, 6 Apr 2026 16:44:34 -0700 Subject: [PATCH 8/8] ci: enable all test suites in PR workflow --- .github/workflows/dev-test-on-pr.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/dev-test-on-pr.yml b/.github/workflows/dev-test-on-pr.yml index 39886642..2f5474e4 100644 --- a/.github/workflows/dev-test-on-pr.yml +++ b/.github/workflows/dev-test-on-pr.yml @@ -68,7 +68,7 @@ jobs: strategy: fail-fast: false matrix: - suite: [workflows, triggers, executions] + suite: [core, workflows, executions, triggers, nodes, templates] env: # Secrets