当智能合约中发生智能合约想要与 dapp
和其他智能合约通信的有意义的事情时,智能合约会发出所谓的事件。 智能合约的开发人员决定何时发出这些事件。 例如 - 当有人发送 ERC20 代币时 - 代币合约将发出一个包含有关转账的所有数据的 Transferevent
。
当您构建 dapps
时,能够实时收听这些事件对您来说非常重要。 例如,如果您正在构建 NFT 市场,您的 dapp
需要知道何时有人创建了新的拍卖或有人对某项商品出价——智能合约将通过发出事件来传达这些事件。
幸运的是,Moralis Server 内置了此功能。
您可以实时收听智能合约事件,还可以获取特定事件的所有历史事件。
您可以从特定的智能合约主题中获取所有历史事件并实时收听新事件。 它需要以下信息:
_description
:_用于标识此同步作业的简短描述。_topic
: _你将要听的主题,这可以是定义或 sha3:bet(address,uint256,bool)
0x20d932006281d267f137cd3921b707c2097e1f041b1291181cc3d0e86f449ebb
abi
:如果您为此事件提供 abi,Moralis 将自动解析所有字段并相应地填充架构。address
:您将为此事件收听的地址。tableName
:将在 Moralis 数据库中创建的子类的名称。如果您不提供 _**abi **_,则将使用以下架构:
{
"objectId": String,
"block_hash": String,
"topic0": String,
"topic1": String,
"block_timestamp": Date,
"ACL": ACL,
"data": String,
"updatedAt": Date,
"transaction_hash": String,
"transaction_index": Number,
"address": String,
"log_index": Number,
"createdAt": Date,
"block_number": Number
}
这是一个有效 abi
的示例:
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "user",
"type": "address"
},
{
"indexed": true,
"internalType": "uint256",
"name": "bet",
"type": "uint256"
},
{
"indexed": true,
"internalType": "bool",
"name": "win",
"type": "bool"
},
{
"indexed": false,
"internalType": "uint8",
"name": "side",
"type": "uint8"
}
],
"name": "bet",
"type": "event"
}
如果提供的 abi
包含“id
”输入,则由于在 Moralis.Object 中保留字段“id
”,它将被解析为“uid
”
表名不允许包含数字字符(0 到 9)
以 _
开头的名称字段暂时不起作用,例如 "name": "_side"
将不起作用,您必须将其更改为 "name": "side"
才能使其起作用 .
如果创建的同步作业会导致检索更多历史事件,则Sync_historical
选项将被禁用并且不会保存历史数据。可以联系支持人员升级您的帐户以启用保存它,无论如何,但在这样做之前要仔细考虑是否真的有必要。可以实时处理事件而无需将数据保存到数据库中。
要编辑同步作业,请单击安装插件的服务器上的查看详细信息,然后转到sync
选项卡。 在那里,您将看到所有同步作业。 单击Edit
按钮。
由于进行任何更改都可能对事件架构造成重大更改,因此保存更改需要提供新的 tableName
。
如果未提供新表名,您将看到以下错误消息:
想象一下,您只想根据某些条件在数据库中获取事件。
Moralis 为您提供了一种基于 ABI 变量定义过滤器的简单方法。
例如,下面的过滤器将仅同步可变price
等于 80000000000000000 的事件实例:
{“eq”:[“price”,“80000000000000000”]}
下面是更多过滤器示例。 您可以为事件中的任何变量设置条件。
If sender
= 0x0
AND receiver
=0x0
{
"and": [
{ "eq": ["sender", "0x0"] },
{ "eq": ["receiver", "0x0"] }
]
}
If sender
= 0x0
OR receiver
= 0x0
{
"or": [
{ "eq": ["sender", "0x0"] },
{ "eq": ["receiver", "0x0"] }
]
}
If (sender
= 0x0
AND amount
= 1000
) OR (receiver
= 0x0
AND amount
= 100
)
{
"or": [
{
"and": [
{ "eq": ["sender", "0x0"] },
{ "eq": ["amount", "1000"]}
]
},
{
"and": [
{ "eq": ["receiver", "0x0"] },
{ "eq": ["amount", "1000"]}
]
}
]
}
如果一个事件有 wei
命名的值,你可以使用 <name>_decimals
字段来运行比较(比如大于/小于):
{
"and": [
{ "eq": ["sender", "0x0"] },
{ "gt": ["amount_decimals", "1000"]}
]
}
Moralis Server 有一个特殊的云功能,称为 watchContractEvent(options)
。 您可以使用主密钥调用它。
注意:limit
参数仅适用于 Nitro 服务器(具有 coreservices
插件的服务器)。 如果未提供限制参数,则默认值为 500000。
注意:目前通过代码创建的事件不会在管理界面中看到,您只能在数据库中看到它们,我们正在努力正确连接管理界面
// code example of creating a sync event from cloud code
let options = {
chainId: "0x1",
address: "0x5c69bee701ef814a2b6a3edd4b1652cb9cc5aa6f",
topic: "PairCreated(address, address, address, uint256)",
abi: {
anonymous: false,
inputs: [
{
indexed: true,
internalType: "address",
name: "token0",
type: "address",
},
{
indexed: true,
internalType: "address",
name: "token1",
type: "address",
},
{
indexed: false,
internalType: "address",
name: "pair",
type: "address",
},
{
indexed: false,
internalType: "uint256",
name: "test",
type: "uint256",
},
],
name: "PairCreated",
type: "event",
},
limit: 500000,
tableName: "UniPairCreated",
sync_historical: false,
};
Moralis.Cloud.run("watchContractEvent", options, { useMasterKey: true });
// unwatch event that has TABLE_NAME as table in the database
let options = { tableName: "TABLE_NAME" };
Moralis.Cloud.run("unwatchContractEvent", options, { useMasterKey: true });