让我们谈谈 Web3 集成!
Moralis 附带了一组插件,可帮助您专注于应用程序的开发,剩下的交给我们。
类似于 window.ethereum.enable()
但返回一个从 Ethers.js 解析为 web3Provider
实例的promise。 当您需要一个功能齐全的 web3Provider
实例时使用它,例如进行合约调用。
注意:确保安装了 v1.0.0 或更高版本的 SDK。 否则 Moralis.enableWeb3()
将返回 web3.js 的实例而不是 ethers.js
例如:
// Get a (ethers.js) web3Provider
const web3Provider = await Moralis.enableWeb3();
有关如何使用 Ethers.js 的更多信息,请参阅 Ethers.js 文档
您可能想要使用另一个库,例如 Web3.js。 为此,您需要将此库包含到您的代码中。
当您通过 html 导入 javascript 脚本时:
<script src="https://cdn.jsdelivr.net/npm/web3@latest/dist/web3.min.js" rel="external nofollow" ></script>
或者当您使用包管理器时:
npm install web3
然后在您的代码中,使用 Moralis.provider
来初始化 web3.js 库。 Moralis.provider
只会在调用 Moralis.authenticate
或 Moralis.enableWeb3
后设置。
import Web3 from "web3"; // Only when using npm/yarn
// Enable web3 and get the initialized web3 instance from Web3.js
await Moralis.enableWeb3();
const web3Js = new Web3(Moralis.provider);
有关如何使用 web3.js 的更多信息,请参阅 Web3.js 文档
注意:Ethers.js 包含在 Moralis SDK 中。 因此 Moralis.executeFunction
和 Moralis.transfer
的函数响应将始终由 Ethers.js 格式化(更多信息见下文)
您可以访问 Moralis 正在使用的 Ethers.js 库:
const ethers = Moralis.web3Library;
有了这个实例,你可以使用 Ethers.js 中的任何方法,例如:
const ethers = Moralis.web3Library;
const daiAddress = "dai.tokens.ethers.eth";
const daiAbi = [
"function name() view returns (string)",
"function symbol() view returns (string)",
"function balanceOf(address) view returns (uint)",
"function transfer(address to, uint amount)",
"event Transfer(address indexed from, address indexed to, uint amount)",
];
const daiContract = new ethers.Contract(daiAddress, daiAbi, provider);
const name = await daiContract.name();
console.log(name);
// 'Dai Stablecoin'
有关如何使用 Ethers.js 的更多信息,请参阅 Ethers.js 文档
您可以使用任何连接器(例如 WalletConnect
、Metamask
、Network
等)启用 web3,与使用 Moralis.authenticate
的方式相同),使用 provider
选项:
const web3 = await Moralis.enableWeb3({ provider: "walletconnect" });
在 nodejs 环境中使用moralis 时,您可以选择使用私钥选项来签署交易:
const web3 = await Moralis.enableWeb3({ privateKey: "your_private_key" });
也可以在云函数中获取 Web3 实例,但语法有点不同。
这个实例是一个 Web3.js 实例
通过 executeFunction
,您可以执行只读(查看)函数和编写方法。 他们都给出了略有不同的回应。 所以我们在下面分别处理它们。
选项:
contractAddress
(必填):智能合约地址 abi
(必填):合约或函数 ABI(应作为数组提供) functionName
(必需):函数名称 params
(必需):您的特定功能所需的参数 msgValue
(可选):数字|字符串|BN|BigNumber。 wei为交易转移的价值对于只读函数,您需要等待执行完成。 然后你直接得到结果。
const ABI = [
{
inputs: [],
name: "message",
outputs: [
{
internalType: "string",
name: "",
type: "string",
},
],
stateMutability: "view",
type: "function",
},
{
inputs: [
{
internalType: "string",
name: "_newMessage",
type: "string",
},
],
name: "setMessage",
outputs: [],
stateMutability: "nonpayable",
type: "function",
},
];
const readOptions = {
contractAddress: "0xe...56",
functionName: "message",
abi: ABI,
};
const message = await Moralis.executeFunction(readOptions);
console.log(message);
// -> "Hello World"
需要启用的 web3 提供程序。 在执行该功能之前,请确保在您的钱包中选择了正确的网络。
您可以使用我们的 Web3API 在没有活跃的 web3 提供者的情况下接收此信息: Moralis.Web3API.token.getAllowance()
通过 setMessage
函数调用设置消息的示例。
const ABI = [
{
inputs: [],
name: "message",
outputs: [
{
internalType: "string",
name: "",
type: "string",
},
],
stateMutability: "view",
type: "function",
},
{
inputs: [
{
internalType: "string",
name: "_newMessage",
type: "string",
},
],
name: "setMessage",
outputs: [],
stateMutability: "nonpayable",
type: "function",
},
];
const sendOptions = {
contractAddress: "0xe...56",
functionName: "setMessage",
abi: ABI,
params: {
_newMessage: "Hello Moralis",
},
};
const transaction = await Moralis.executeFunction(sendOptions);
console.log(transaction.hash);
// --> "0x39af55979f5b690fdce14eb23f91dfb0357cb1a27f387656e197636e597b5b7c"
// Wait until the transaction is confirmed
await transaction.wait();
// Read new value
const message = await Moralis.executeFunction(readOptions);
console.log(message);
// --> "Hello Moralis"
您将从 Ethers.js 获得交易响应,其中包括哈希和其他信息。
{
"hash": "0x39af55979f5b690fdce14eb23f91dfb0357cb1a27f387656e197636e597b5b7c",
"type": 2,
"accessList": null,
"blockHash": null,
"blockNumber": null,
"transactionIndex": null,
"confirmations": 0,
"from": "0xab5801a7d398351b8be11c439e05c5b3259aec9b",
"gasPrice": {
"type": "BigNumber",
"hex": "0x04cf1ef09a"
},
"maxPriorityFeePerGas": {
"type": "BigNumber",
"hex": "0x908a9040"
},
"maxFeePerGas": {
"type": "BigNumber",
"hex": "0x04cf1ef09a"
},
"gasLimit": {
"type": "BigNumber",
"hex": "0x75c0"
},
"to": "0x73bceb1cd57c711feac4224d062b0f6ff338501e",
"value": {
"type": "BigNumber",
"hex": "0x00"
},
"nonce": 13,
"data": "0x368b877200000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000004486f6c6100000000000000000000000000000000000000000000000000000000",
"r": "0x8b00442b141406a1b5d701c7ac6ab3b6adec13010fdc1218a42f8f9aa8e57718",
"s": "0x1abc60ae4de7af8bcba4d1b44e470f40a04c3c632fd4a75f87a553820a43ddef",
"v": 1,
"creates": null,
"chainId": 0
}
如果你想等到交易被链确认,那么你可以调用transaction.wait()。 这将解析为交易收据。 此收据还将包括交易中已触发的所有事件的日志。 例如,我们在这里等待 3 个确认:
const receipt = await transaction.wait(3);
收据示例
{
"to": "0x73bceb1cd57c711feac4224d062b0f6ff338501e",
"from": "0xab5801a7d398351b8be11c439e05c5b3259aec9b",
"contractAddress": null,
"transactionIndex": 72,
"gasUsed": {
"type": "BigNumber",
"hex": "0x75b2"
},
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"blockHash": "0x746d7d42e8022f560577dfdc0150e1e8b009e59c537a9053a82e9ad6d20f6d06",
"transactionHash": "0x39af55979f5b690fdce14eb23f91dfb0357cb1a27f387656e197636e597b5b7c",
"logs": [],
"blockNumber": 11847564,
"confirmations": 2,
"cumulativeGasUsed": {
"type": "BigNumber",
"hex": "0x6743ab"
},
"effectiveGasPrice": {
"type": "BigNumber",
"hex": "0x04623af60c"
},
"status": 1,
"type": 2,
"byzantium": true,
"events": []
}
例如,您想调用一个智能合约方法,将本机加密货币换成代币。 这种情况与您使用 ERC20
代币并指定要用作方法参数的代币数量的通常情况不同。 在智能合约中使用原生加密货币的操作假定您将随交易一起转移一些价值。 在solidity中,您可以将其称为 msg.value
const options = {
contractAddress: "0xe...56",
functionName: "swapNativeForTokens",
abi: ABI,
msgValue: Moralis.Units.ETH("0.1"),
};
const transaction = await Moralis.executeFunction(options);
const receipt = await transaction.wait();
console.log(receipt);
您可以使用此构造来创建可重用的选项来调用多个合约方法。
const options = {
contractAddress: "0xe...56",
abi: ABI,
};
const symbol = await Moralis.executeFunction({
functionName: "symbol",
...options,
});
const decimals = await Moralis.executeFunction({
functionName: "decimals",
...options,
});
const name = await Moralis.executeFunction({
functionName: "name",
...options,
});
Moralis.executeFunction()
返回:
您可以通过等待交易得到确认,将交易响应解析为收据。 例如,要等待 3 次确认:
const options = {
contractAddress: "0xe...56",
functionName: "swapNativeForTokens",
abi: ABI,
msgValue: Moralis.Units.ETH("0.1"),
};
const transaction = await Moralis.executeFunction(options);
const result = await transaction.wait();
您可以在 Moralis 上监听几个事件,以检查用户的 web3 连接:
当用户连接到链时监听事件(通过 Moralis.authenticate()
/ Moralis.enableWeb3()
):
// Subscribe to onWeb3Enabled events
const unsubscribe = Moralis.onWeb3Enabled((result) => {
console.log(result);
});
// Unsubscribe to onWeb3Enabled events
unsubscribe();
结果对象
{
account: '0x1a2b3c4d....',
chain: '0x1',
connector: {} // the connector instance
web3: {} // the Ethers.js web3 instance
provider: {} // the EIP1193-provider, used to connect
}
当用户断开连接时监听事件(通过 Moralis.deactivateWeb3()):
// Subscribe to onWeb3Deactivated events
const unsubscribe = Moralis.onWeb3Deactivated((result) => {
console.log(result);
});
// Unsubscribe to onWeb3Deactivated events
unsubscribe();
结果对象
{
connector: {
} // the connector instance
provider: {
} // the EIP1193-provider, used to connect
}
在启用 web3 后,当用户更改链时监听事件。
// Subscribe to onChainChanged events
const unsubscribe = Moralis.onChainChanged((chain) => {
console.log(chain);
// returns the new chain --> ex. "0x1"
});
// Unsubscribe to onChainChanged events
unsubscribe();
在启用 web3 后,在用户更改帐户时监听事件。
// Subscribe to onAccountChanged events
const unsubscribe = Moralis.onAccountChanged((chain) => {
console.log(chain);
// returns the new account --> ex. "0x1a2b3c4d..."
});
// Unsubscribe to onAccountChanged events
unsubscribe();
您可能想改用 Moralis.onWeb3Activated
,因为它更一致,并且由 Moralis 处理,而不是 EIP-1193 提供程序
当提供者触发连接事件时监听事件。
从规范:
Provider 在以下情况下发出连接:
// Subscribe to onConnect events
const unsubscribe = Moralis.onConnect((provider) => {
console.log(provider);
// returns the EIP-1193 provider
});
// Unsubscribe to onConnect events
unsubscribe();
您可能想改用 Moralis.onWeb3Deactivated
,因为它更一致,并且由 Moralis 处理,而不是 EIP-1193 提供程序
当提供者触发断开事件时监听事件。
从规范:
Provider 在与所有链断开连接时发出断开连接
// Subscribe to onDisconnect events
const unsubscribe = Moralis.onDisconnect((error) => {
console.log(error);
// returns a ProviderRpcError
});
// Unsubscribe to onDisconnect events
unsubscribe();
要监听这些事件,您只需调用 Moralis.onXXX
。 例如:
const unsubscribe = Moralis.onAccountChanged(function (account) {
console.log(account);
});
// "0x1a2b3c4d..."
如果您想在连接用户之前(在元掩码上)侦听事件,那么您可能希望直接从元掩码侦听事件
https://docs.metamask.io/guide/ethereum-provider.html#events
例如
window.ethereum.on('accountsChanged' (accounts) => {
console.log(accounts)
// --> [0x1a2b3c4d...]
})
其他钱包也有类似的实现,请查看各自钱包的文档。
将地址链接(取消链接)到当前用户。
用户可能有多个他们希望与他们的个人资料相关联的地址。 这可以在用户通过身份验证后使用链接功能完成。
Moralis.onAccountChanged(async function (account) {
const confirmed = confirm("Link this address to your account?");
if (confirmed) {
await Moralis.link(account);
alert("Address added!");
}
});
取消链接功能从用户的个人资料中删除给定的地址。
await Moralis.unlink(address);
可以通过提供signingMessage
选项来更改用户在将地址链接到当前用户时看到的消息:
await Moralis.link(accounts[0], { signingMessage: "Custom Linking Message" });
检测是否激活了 web3 提供程序。
返回: True or False
const isWeb3Active = Moralis.ensureWeb3IsInstalled();
if (isWeb3Active) {
console.log("Activated");
} else {
await Moralis.enable();
}
停用当前的 web3 连接
await Moralis.enableWeb3();
console.log("ENABLED", Moralis.isWeb3Enabled());
await Moralis.deactivateWeb3();
console.log("DISABLED", Moralis.isWeb3Enabled());
返回连接器或连接器类型的详细信息,用于验证或启用 web3:
const connectorType = Moralis.Web3.connectorType;
if (connectorType === "injected") {
console.log("Metamask or an injected provider is used");
}
const connector = Moralis.Web3.connector;
console.log(connector);
返回用于连接 web3 的当前链 ID
const chainId = await Moralis.chainId;
console.log(chainId); // 56
返回用于连接到 web3 的当前帐户
改变当前网络的功能
注意:此方法只能在 Metamask 用作连接器时使用
选项:
chain
(必填):要切换到的链 id。 接受数字或十六进制字符串中的值。 有效值列在交易和余额部分的介绍页面上。 示例:56、“0x38”const chainId = "0x1"; //Ethereum Mainnet
const chainIdHex = await Moralis.switchNetwork(chainId);
您只能切换到钱包中的网络。 如何添加新网络,您可以在下面找到。
注意:此方法只能在 Metamask 用作连接器时使用
将新网络添加到钱包的功能。 您可以在他们的文档站点中找到每个链的网络配置。
选项:
chainid
(必填):网络链 ID chainName
(必填):网络名称 currencyName
(必填):本币名称 currencySymbol
(必填):货币符号 rpcUrl
(必填):新的 RPC URL blockExplorerUrl
(必填):块浏览器 URLconst chainId = 43114;
const chainName = "Avalanche Mainnet";
const currencyName = "AVAX";
const currencySymbol = "AVAX";
const rpcUrl = "https://api.avax.network/ext/bc/C/rpc";
const blockExplorerUrl = "https://cchain.explorer.avax.network/";
await Moralis.addNetwork(
chainId,
chainName,
currencyName,
currencySymbol,
rpcUrl,
blockExplorerUrl
);