- 函数(Functions): 您希望在外部事件发生时执行的自定义 JavaScript 或 TypeScript 代码。这是自动化的核心。
- 触发器(Triggers): 预定义的外部事件,您的 Web3 Action 会配置为监听它们。当事件发生时,触发器指示 Tenderly 执行您的自定义代码(函数)。
- 事件(Events,触发器类型): 预定义的外部事件,您可以通过设置触发器来监听。当事件发生时,触发器会调用您的自定义代码(函数)。
执行类型
Tenderly 中的 Web3 Actions 可以以两种模式执行: Sequential(顺序) 和 Parallel(并行)。
Web3 Action UI Builder 中的 Web3 Action Execution Type 步骤
Sequential 执行
在顺序执行模式下,actions 按其被调用的顺序逐一执行。这是默认的执行模式。在此模式下,每个 action 会等待前一个 action 完成后才开始执行。以下是顺序执行的 action 配置示例:example
Parallel 执行
在并行执行模式下,actions 并行执行,从而带来更高的吞吐量。在此模式下,执行顺序无法保证,并且可能与 action 存储 之间出现竞态条件。以下是并行执行的 action 配置示例:example
Action 函数
Web3 Action 函数指的是以标准 JavaScript 或 TypeScript 函数形式编写的自定义代码,但它们必须遵守一些规则。- 函数必须是异步的,返回
Promise<void> - 函数接受两个参数:
context和event - 函数必须是文件的具名导出
- 函数可以放在 actions root 目录下的任何文件中
context参数,包含对 Storage 和 Secrets 的访问。event参数,它是一个包含回答 “刚刚发生了什么?” 相关信息的对象。此参数包含特定于 Web3 Action 函数所监听触发器类型的数据。 外部事件的触发器规范 部分详细介绍了外部事件。
Web3 Action 函数的执行限制为 30 秒。如果您的函数执行时间超过
30 秒,将被终止。
event 参数可以是任意一种支持的触发器类型(事件)。
example.ts
Dashboard 版 actions 可用的库
Tenderly 运行时预先打包了若干 JavaScript 库,您可以在通过 Tenderly Dashboard 创建 Web3 Actions 时导入使用。可用的库包括: 要导入这些库中的任何一个,请像在标准基于 npm 的项目中一样使用require() 函数(不使用 ES6)。
Axios 的示例导入如下所示:
example.jsx
对基于 CLI 的 Web3 Actions 使用 npm 库
Tenderly CLI 创建的项目实际上是一个 npm 模块。您可以从 actions root 目录中安装任何 npm 包。外部事件和触发器类型
当外部事件发生时,它 触发您的自定义代码(函数)执行。您可以在四种要监听的外部事件之间选择:- Block 事件:在所选网络上有新区块被打包。
- Periodic 事件: 此触发器在一定时间间隔或基于 CRON 表达式的时间发生。
- Webhook 事件: HTTP 请求被发送到 webhook URL(Web3 Action 暴露 webhook)
- Transaction 事件: 在所选网络上执行了匹配给定过滤条件的事务。
您应为每种触发器类型编写单独的函数。不建议对不同的
触发器类型使用相同的函数。
将 Web3 Action 函数订阅到事件
除了在 JavaScript 中定义您的 action 函数之外,您还需要提供触发器配置,它告诉 Tenderly 是什么触发它,即您的函数订阅的外部事件。 通过 Tenderly Dashboard 创建 Web3 Actions 时,UI 中的创建流程将为您处理此部分。阅读 Dashboard 快速入门 指南。 在处理基于代码的 Web3 Actions 时,函数及其触发器必须在由 Tenderly CLI 生成的tenderly.yaml 文件中定义。阅读 CLI 快速入门 指南。
示例
在下面的示例中,我们声明了一个名为 bestActionEver 的 Web3 Action,并引用从 actions/myCoolTsFile.ts 文件导出的函数 awesomeActionFunction。这是当 Web3 Action 被触发时 Tenderly 将调用的函数。执行通过 execution_type 控制,在此示例中被设置为 parallel。
tenderly.yaml
为外部事件指定触发器
在本节中,我们将检查trigger 声明。有关编写 tenderly.yaml 文件的更多信息,请参考 本指南。
触发器类型和相应的配置在 tenderly.yaml 文件中定义。您必须首先定义 trigger 对象,它有两个必填属性:
type属性,指定触发器类型,可以是:periodic | webhook | block | transaction- 一个包含所选触发器类型特定配置的对象
Periodic 事件
当您希望 Web3 Action 在特定时间间隔被触发时,可以使用 periodic 事件。它携带 time:调用时间。example.ts
periodic。可以基于间隔或 cron:
trigger.yaml
interval 属性可以取以下任意值:5m | 10m | 15m | 30m | 1h | 3h | 6h | 12h | 1d
如果您需要对 Web3 Action 的执行时间进行更精细的控制,请使用基于 CRON 的 periodic 触发器:
trigger.yaml
cron 属性可以是任何有效的 CRON 字符串。
Webhook 事件
基于 Webhook 的 Web3 Actions 暴露一个自定义 webhook URL,使外部系统能够通过简单的 HTTP POST 请求触发它们。 对应的触发器类型包含两个属性: 调用的 time 和任意 payload(JSON 对象)。Tenderly 不会对您的负载执行任何验证或检查。example.ts
webhook-trigger.yaml
authenticated 设置为 true,您必须在请求中包含 Tenderly Access Token 作为 x-access-key 的值才能运行 Web3 Action。您可以在 Tenderly Dashboard 中的 Web3 Action 概览中找到所暴露 webhook 的 cURL。
example
Block 事件
当您希望监听一个或多个网络上的区块被打包时,可以使用 block 事件。您可以通过指定两次连续调用之间被打包的区块数量,让您的 Web3 Action “按块周期化”。example.ts
network:您感兴趣的 网络 ID 的单个值或列表blocks:Web3 Action 两次连续执行之间被打包的区块数量。例如,每 100 个被打包的区块执行一次 Web3 Action。
block-trigger.yaml
Transaction 事件
transaction 触发器类型允许您监听在链上执行的特定事务。要监听来自智能合约的事务,智能合约必须已经过验证并添加到
Tenderly Dashboard 中的您的项目。如果不是这样,CLI 会抛出警告。
event 参数被调用。
example.ts
- 事务打包状态:
mined(事务已被打包)或confirmed10(自包含该事务的区块以来已确认 10 个区块) - Filters: 使用
filters列表定义的一组涉及事务负载的条件。只有匹配 filters 的事务才会触发您的代码执行。
过滤事务
filters 列表允许您使用事务属性定义触发条件以匹配特定事务。
列表中的每个 filter 都是一个对象,其中 所有字段都是 AND 关系。filter 中的每个条件都必须为真时才能匹配。filters 列表本身是 OR 关系:只要事务满足列表中 任意一个 filter,就会匹配。
示例:在 Ethereum 主网或 Base 上发送到
0x236..fd62 的事务。
transaction-trigger.yaml
- Filter 1:network 1(Ethereum)AND status fail AND to
0x2364...fd62 - Filter 2:network 8453(Base)AND status fail AND to
0x2364...fd62
按事务字段过滤事务
在常见的事务字段中,您可以按以下具有特定值的属性进行过滤。from— 按特定发件人过滤。可以是单个地址或地址列表(OR 关系)。可选。to— 按特定接收者过滤。可以是单个地址或地址列表(OR 关系)。可选。status— 按事务状态过滤:success或fail。可以是单个值或列表(OR 关系)。可选。network— 按网络过滤。可以是单个链 ID 或链 ID 列表(OR 关系)。必填。contract.address— 仅过滤涉及此特定地址合约的事务。可选。
0xf63c48626f874bf5604D3Ba9f4A85d5cE58f8019)。
list-fields.yaml
valuegasUsedgasLimitfee
eq、gte、gt、lt、lte。您还可以使用 not 布尔标志对比较进行取反。
以下是一个展示使用事务负载中标量值的 filter 示例。
numeric-filters.yaml
not 标志取反比较:
negated-comparison.yaml
使用发出的 EVM 事件过滤事务
将 Web3 Actions 配置为监听由事务执行发出的 EVM 事件,允许您对这些事件记录的重要变化作出响应。您可以通过使用eventEmitted 运算符实现这一点,它支持以下嵌套属性:
contract(必填):指定事件的来源。contract.address:发出该事件的合约的地址。contract.invocation:控制合约如何被调用:direct、internal或any(默认)。有关详情,请参见 contract filter。
name:事件的名称(需要已验证的合约)。id:事件签名的 topic 哈希(作为name的替代方案)。对于 ABI 不可用的未验证合约很有用。例如,Transfer(address,address,uint256)事件的 topic 哈希是0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef。not:布尔值。设为true以对整个事件匹配(包括参数)取反(当未使用指定参数发出该事件时触发)。parameters:解码后事件参数值的条件列表。所有条件都是 AND 关系:每个条件都必须匹配。每个条目支持:name(必填):事件参数的名称。string:字符串比较。接受用于精确匹配的普通字符串,或包含exact和not字段的对象。有关详情,请参见 StringComparison。int:整数比较。支持与数值 filter 相同的运算符(eq、gt、gte、lt、lte)。单个int块内的所有运算符都是 AND 关系。使用not标志对组合条件取反。有关详情,请参见 IntComparison。
单个
eventEmitted 条目的 parameters 内没有 OR 关系。所有条件都是 AND 关系。
要对同一参数使用 OR 逻辑,请使用多个 eventEmitted 条目(它们在外层列表中是 OR 关系)。要将
eventEmitted filter 与 name 或 parameters 结合使用,合约必须已验证并添加到
Tenderly Dashboard 中的项目。对未验证的合约使用 id(topic 哈希)。0x418d..9d45 地址执行时发出 TxSubmission 或 TxConfirmation 事件之一时将被调用。
event-emitted-filter.yaml
event-parameters.yaml
negated-parameter.yaml
eventEmitted 条目:
event-parameter-or.yaml
not 以取反整个匹配:
negated-event.yaml
按发出的日志过滤事务
监听 EVM 事件的另一种方式是按日志 topic 查询。logEmitted filter 可以是单个对象或列表(条目是 OR 关系)。它支持以下属性:
startsWith(必填):与事务日志 topic 匹配的 topic 值列表。每个条目通过精确相等(不区分大小写)与相应的 topic 进行比较。实际上这些是完整的 32 字节 topic 哈希(以 0x 为前缀,64 个十六进制字符),但该字段接受任何有效的十六进制字符串。contract.address(可选):日志的来源。指定时,只匹配来自此合约的日志。matchAny:布尔值。当true时,匹配startsWith中 任意一个 topic 就足够了。当false(默认)时,所有 topic 都必须匹配。not:布尔值。设为true以取反整个日志匹配(当未发出该日志时触发)。
使用
logEmitted 使您能够以其原始形式使用事件 topic 前缀来过滤事件。
如果您在未验证的合约上设置 Web3 Action,这将非常有用。log-emitted-filter.yaml
过滤涉及特定合约的事务
要过滤在执行期间调用特定合约的事务,您可以使用可选的contract filter。
contract filter 支持以下属性:
address:合约的地址。invocation:控制合约如何被调用。可能的值:direct:合约被事务发送者(EOA)直接调用。仅关注对该合约的顶层调用时使用。internal:合约在执行过程中被另一个合约内部调用(例如通过CALL、DELEGATECALL或STATICCALLopcode)。用于检测您的合约作为多合约交互一部分被调用时的情况。any:匹配 direct 和 internal 两种调用。这是默认值。
invocation 字段在使用 contract 对象的任何位置都可用,包括 eventEmitted filter 内部。例如,您可以在 eventEmitted 合约上使用 invocation: internal,只匹配在内部调用期间发出的事件。有关 schema,请参见 Contract。
在下面的示例中,第一个 filter 匹配 Sepolia 上发送到 0x2364...fd62 的任何成功事务。第二个 filter 更严格:只有还涉及对合约 0xad88...80d6 的内部调用的事务才会触发 Web3 Action。
contract-filter.yaml
按函数调用过滤事务
要过滤直接调用特定函数的事务,您可以使用可选的function filter。它需要合约的地址 contract.address 以及函数的 name 或 signature。
function filter 支持以下属性:
contract(必填):指定目标合约。contract.address:被调用合约的地址。contract.invocation:控制函数必须如何被调用:any(默认,包括 direct 和 internal)、direct(仅由 EOA 发起)或internal(仅子调用)。有关详情,请参见 contract filter。
name:函数的名称(需要已验证的合约)。signature:4 字节函数选择器(例如0xa9059cbb)。对于 ABI 不可用的未验证合约很有用。not:布尔值。设为true以对整个函数匹配(包括参数)取反(当未使用指定参数调用该函数时触发)。parameters:解码后函数输入参数值的条件列表。所有条件都是 AND 关系:每个条件都必须匹配。每个条目支持:name(必填):函数参数的名称。string:字符串比较。接受用于精确匹配的普通字符串,或包含exact和not字段的对象。有关详情,请参见 StringComparison。int:整数比较。支持与数值 filter 相同的运算符(eq、gt、gte、lt、lte)。单个int块内的所有运算符都是 AND 关系。使用not标志对组合条件取反。有关详情,请参见 IntComparison。
单个
function 条目的 parameters 内没有 OR 关系。所有条件都是 AND 关系。
要对同一参数使用 OR 逻辑,请使用多个 function 条目(它们在外层列表中是 OR 关系)。要将
function filter 与 name 或 parameters 结合使用,合约必须已验证并添加到
Tenderly Dashboard 中的项目。对未验证的合约使用 signature(4 字节选择器)。function 指定为单个对象或列表。当提供列表时,条目是 OR 关系。如果列表中 任何一个 函数被调用,filter 就匹配。有关字段的完整参考,请参见 FunctionFilter。
以下是一个 Web3 Action 触发器示例,响应对部署在 0xad88...80d6 的合约 verySpecialFunction 的任何调用(direct 或 internal)。
function-filter.yaml
function-selector.yaml
function-parameters.yaml
function-negated-string.yaml
function-negated-parameter.yaml
function 条目:
function-parameter-or.yaml
transfer 而不是用户直接调用,设置 invocation: internal。此示例仅在另一个合约在 USDC 上内部调用 transfer 至少 1,000 USDC 时触发:
function-internal-with-params.yaml
按 ETH 余额过滤事务
ethBalance filter 在事务期间账户或合约的 ETH 余额满足数值条件时触发您的 Web3 Action。这对于监控大型鲸鱼动态、协议金库阈值或钱包充值事件很有用。
filter 支持以下属性:
address(必填):要监控的账户或合约地址。balanceCmp(必填):与事务时余额的数值比较。使用BigIntComparison运算符(eq、gt、gte、lt、lte)。值以 wei 为单位,可以以十进制字符串(例如"1000000000000000000")或0x前缀的十六进制(例如"0xde0b6b3a7640000")提供。not(可选):设为true以取反整个匹配。
ethBalance 对象或列表,条目是 OR 关系。
有关字段的完整参考,请参见 EthBalanceFilter。
示例:当钱包余额至少达到 1 ETH 时触发:
eth-balance-filter.yaml
eth-balance-multi.yaml
eth-balance-range.yaml
eth-balance-not.yaml
按合约状态变化过滤事务
stateChanged filter 在事务期间合约状态变量发生变化时触发您的 Web3 Action。您可以在以下任何组合上匹配:变量是否发生变化、特定的新值、百分比变化或原始存储槽键。
filter 支持以下属性:
address(除非matchAny: true,否则必填):要监视的合约地址。matchAny(可选):当true时,匹配事务中 任何 合约的状态变化,address可以省略。对协议范围的监控很有用。params(可选):状态变量条件列表。所有条目都是 AND 关系。省略时,filter 匹配指定地址上的任何状态变化。not(可选):设为true以取反整个匹配。
params 中的每个条目需要:
name(必填):状态变量的名称。- 至少一个条件:
change: true:当变量的值发生变化时匹配。valueCmp(BigIntComparison),当新值满足数值条件时匹配。percentageCmp(BigIntComparison),匹配按(newValue - oldValue) * 100 / oldValue计算的 带符号 百分比变化。正值表示增加,负值表示减少。例如,gte: "10"在增加 10%+ 时触发;lte: "-10"在减少 10%+ 时触发。注意:当oldValue为 0 时,百分比始终为 0,请改用change: true或valueCmp。storageSlotKey:按原始存储槽键匹配(对未验证的合约很有用)。
StateChangedFilter。
要使用基于
name 的状态变量匹配,合约必须已验证并添加到您在 Tenderly Dashboard 的项目中。totalSupply 发生任何变化时触发:
state-changed-basic.yaml
totalSupply 达到阈值时触发:
state-changed-value.yaml
totalSupply 增加 50% 或以上时触发:
state-changed-percentage-increase.yaml
totalSupply 减少 10% 或以上时触发:
state-changed-percentage-decrease.yaml
totalSupply 发生变化 AND 新值高于某个下限):
state-changed-multi-params.yaml
balances[bob]):
对于映射,没有按条目命名的变量,请对您关心的键使用 storageSlotKey 和 keccak256 派生的槽。对于 mapping(address => uint256) balances 在存储槽 N 和键 addr 上的槽是 keccak256(abi.encode(addr, N))。
state-changed-slot.yaml
storageSlotKey 方法适用于未验证的合约和任何存储布局,它不要求合约被验证或添加到您的 Tenderly 项目中。
示例:使用 matchAny 监视事务中的任何合约:
state-changed-match-any.yaml
stateChanged 和 ethBalance 可以在同一 filter 对象中与任何其他 filter 结合,所有字段都是 AND 关系。以下示例展示了常见的实际组合。
示例:mint() 被调用 AND totalSupply 发生变化(确认该调用产生了链上效果):
state-changed-with-function.yaml
Transfer 事件被发出 AND paused 状态发生变化(在转账期间所有权或暂停标志被切换):
state-changed-with-event.yaml
eth-balance-with-to.yaml
togglePause() 被调用但 balances 没有 变化时触发(即事务仅影响了 paused 标志):
state-changed-not.yaml
完整的 transaction 触发器参考
以下带注释的 YAML 块在一处展示了 transaction 触发器的每个可用字段。在构建您的触发器配置时,请将其用作快速参考。有关类型定义,请参见下面的 Trigger YAML schema 参考。complete-reference.yaml
Trigger YAML schema 参考
下面的 schema 描述了触发器配置接受的每个字段的结构和类型。在构建您的tenderly.yaml 时,请与上面的 带注释示例 一起使用。
约定:? = 可选,| = 之一,[] = 列表。标记为 “single or list” 的字段接受标量值或 YAML 列表。
所有触发器类型
schema.yaml
TransactionFilter
schema.yaml
顶层的
contract 字段充当 filter 的共享默认值。它会自动应用于任何未指定自身合约的 function 或 eventEmitted 条目,让您避免重复相同的地址。它 不适用 于 logEmitted。共享类型
schema.yaml
FunctionFilter
schema.yaml
EventFilter (eventEmitted)
schema.yaml
LogFilter (logEmitted)
schema.yaml
EthBalanceFilter (ethBalance)
schema.yaml
StateChangedFilter (stateChanged)
schema.yaml