diff --git a/builders/.pages b/builders/.pages index 76f4501e5..f41feaa50 100644 --- a/builders/.pages +++ b/builders/.pages @@ -1,8 +1,8 @@ title: Builders hide: false nav: - - index.md - - get-started - - interact - - tools - - integrations + - index.md + - get-started + - interact + - tools + - integrations diff --git a/builders/get-started/.pages b/builders/get-started/.pages index 0c0935db0..1edd35c3d 100644 --- a/builders/get-started/.pages +++ b/builders/get-started/.pages @@ -1,6 +1,7 @@ title: Get Started nav: - - index.md - - moonbeam-dev.md - - moonbase.md - - moonriver.md \ No newline at end of file + - index.md + - eth-compare + - moonbeam-dev.md + - moonbase.md + - moonriver.md diff --git a/builders/get-started/eth-compare/.pages b/builders/get-started/eth-compare/.pages new file mode 100644 index 000000000..0dacd564c --- /dev/null +++ b/builders/get-started/eth-compare/.pages @@ -0,0 +1,7 @@ +title: Moonbeam vs Ethereum +nav: + - index.md + - balances.md + - transfers-api.md + - consensus-finality.md + - rpc-support.md diff --git a/builders/get-started/eth-compare/balances.md b/builders/get-started/eth-compare/balances.md new file mode 100644 index 000000000..3aee0dfb3 --- /dev/null +++ b/builders/get-started/eth-compare/balances.md @@ -0,0 +1,38 @@ +--- +title: Account Balances +description: A description of the main differences that Ethereum developers need to understand in terms of account balances on Moonbeam. +--- + +## Introduction + +While Moonbeam strives to be compatible with Ethereum's Web3 API and EVM, there are some important Moonbeam differences that developers should know and understand in terms of account balances. + +This guide will outline some of these main differences and what to expect when using Moonbeam for the first time. + +## Ethereum Account Balances + +An account on Ethereum is an entity with a token balance (Ether or ETH in this case). Account-holders can send Ether transactions on Ethereum and can be controlled by either users (with the private key for signing) or smart contracts. + +Therefore, Ethereum has two main types of accounts: user-owned and contract-owned. No matter the type, an Ethereum account has a single balance field that represents the number of Wei owned by this address, where Wei is a denomination of ETH (1 x 10^18 Wei per ETH). + +_An image will be here_ + +## Moonbeam Account Balances + +An account on Moonbeam is also an entity with a token balance (the token will depend on the network). Like on Ethereum, account holders can send token transactions on the Moonbeam Network they are connected to. In addition, accounts can be controlled by users (with the private key for signing) or smart contracts. + +As with Ethereum, there are two main types of accounts: user-owned and contract owned. Within both account types, there are also [proxy accounts](https://wiki.polkadot.network/docs/learn-proxies), which can perform a limited number of actions on behalf of another account. However, in terms of balances, all of Moonbeam account types have five (5) different [balance types](https://wiki.polkadot.network/docs/learn-accounts#balance-types): + + - **Free** — refers to the balance that can be used (not locked/frozen) inside the Substrate API. The concept of `free` balance depends on the action to be executed. For example, voting in democracy will not subtract the allocated balance to the vote from `free` balance, but token holders won't be able to transfers that balance + - **Redudicble** — refers to the balance that can be used (not locked/frozen) through the Ethereum API on Moonbeam. For example, this is the balance displayed by MetaMask. It is the real spendable balance, accounting for all democracy locks (displayed as transferable in Polkadot.js Apps) + - **Reserved** — refers to the balance held due to on-chain requirements and can be freed by performing some on-chain action. For example, funds that are being staked at a protocol level (parachain staking) are shown as `reserved balance`. These funds are **not** accessible via the Ethereum API until they are freed + - **Misc frozen** — represents a balance that the `free` balance may not drop below when withdrawing funds, except for transaction fee payment. For example, funds being used to vote on a governance proposal are shown as `misc frozen`. These funds are **not** accessible via the Ethereum API until they are freed + **Fee frozen** — represents a balance that the `free` balance may not drop below when specifically paying for transaction fees. These funds are **not** accessible via the Ethereum API until they are freed + +_An image will be here_ + +## Main Differences + +The main difference between account balances on Ethereum and Moonbeam lies in the concept of locked and reserved balance in Moonbeam. These are tokens that are still owned by that account, but they are not spendable (yet). + +From the Ethereum's API perspective, an account might show that it has a certain balance (called `reducible` balance). However, after an on-chain action, this value might increase (or decrease) without an actual balance transfer. \ No newline at end of file diff --git a/builders/get-started/eth-compare/consensus-finality.md b/builders/get-started/eth-compare/consensus-finality.md new file mode 100644 index 000000000..2d90f37fc --- /dev/null +++ b/builders/get-started/eth-compare/consensus-finality.md @@ -0,0 +1,91 @@ +--- +title: Consensus & Finality +description: A description of the main differences that Ethereum developers need to understand in terms of consensus and finality on Moonbeam. +--- + +## Introduction + +While Moonbeam strives to be compatible with Ethereum's Web3 API and EVM, there are some important Moonbeam differences that developers should know and understand in terms of consensus and finality. + +In short, consensus is a way for different parties to agree on a shared state. As blocks are created, nodes in the network must decide which block will represent the next valid state. Finality defines when that valid state cannot be altered or reversed. + +At the time of writing, Ethereum uses a consensus protocol based on [Proof-of-Work (PoW)](https://ethereum.org/en/developers/docs/consensus-mechanisms/pow/), which provides probabilistic finality. On the contrary, Moonbeam uses a hybrid consensus protocol based on [Nominated Proof-of-Stake (NPoS)](https://wiki.polkadot.network/docs/learn-consensus), which provides deterministic finality. + +This guide will outline some of these main differences around consensus and finality, and what to expect when using Moonbeam for the first time. + +## Ethereum Consensus and Finality + +As stated before, Ethereum is currently using a PoW consensus protocol and the longest chain rule, where finality is probabilistic. + +Probabilistic finality means that the probability that a block (and all its transactions) will not be reverted increases as more blocks are built on top of it. Therefore, the higher the number of blocks you wait, the higher the certainty that a transaction will not be re-organized, and consequently reverted. As suggested by [this blog on finality](https://blog.ethereum.org/2016/05/09/on-settlement-finality/) by Vitalik, _"you can wait 13 confirmations for a one-in-a-million chance of the attacker succeeding."_ + +## Moonbeam Consensus and Finality + +In Polkadot, there are collators and validators. [Collators](https://wiki.polkadot.network/docs/en/learn-collator) maintain parachains (in this case, Moonbeam) by collecting transactions from users and producing state transition proofs for the Relay Chain [validators](https://wiki.polkadot.network/docs/en/learn-validator). The collators set (nodes that produce blocks) are selected based on the [stake they have in the network](/learn/features/consensus/). + +For finality, Polkadot/Kusama rely on [GRANDPA](https://wiki.polkadot.network/docs/learn-consensus#finality-gadget-grandpa). GRANDPA provides deterministic finality for any given transaction (block). In other terms, when a block/transaction is marked as final, it can't be reverted except via on-chain governance or forking. Moonbeam follows this deterministic finality. + +## Main Differences + +In terms of consensus, Moonbeam is based on Nominated Proof-of-Stake, while Ethereum relies on Proof-of-Work, which are very different. Consequently, Proof of Work concepts, such as `difficulty`, `uncles`, `hashrate`, generally don’t have meaning within Moonbeam. + +For APIs that return values related to Ethereum’s Proof of Work, default values are returned. Existing Ethereum contracts that rely on Proof of Work internals (e.g., mining pool contracts) will almost certainly not work as expected on Moonbeam. + +In terms of finality, on Moonbeam, you can check when a transaction is finalized, meaning that it can't be reverted. The strategy is fairly simple: + 1. You ask the network the hash of the latest finalized block + 2. You retrieve the block number using the hash + 3. You compare it with the block number of your transaction. If your transaction was included in a previous block, it is finalized + 4. As as safety check, retrieve the block by number, and verify that the given transaction hash is in the block + +The following sections outline how you can check for transaction finality using both the Ethereum JSON-RPC (custom Web3 request) and the Substrate (Polkadot) JSON-RPC. + +## Checking Tx Finality with Ethereum Libraries + +You can make calls to the Substrate JSON-RPC using the `send` method of both [Web3.js](https://web3js.readthedocs.io/) and [Ethers.js](https://docs.ethers.io/). + +Custom RPC requests are also possible using [Web3.py](https://web3py.readthedocs.io/) with the `make_request` method. You can use the Web3.js example as a baseline. + +!!! note + The code snippets presented in the following sections are not meant for production environments. Please make sure you adapt it for each use-case. + +### Custom RPC Requests with Web3.js + +With [Web3.js](https://web3js.readthedocs.io/), you can make custom RPC requests with the `web3.currentProvider.send()` method. However, at the time of writing, this was not in the official Web3.js documentation. + +Given a transaction hash (`tx_hash`), the following code snippet uses Web3.js to fetch the current finalized block and compare it with the block number of the transaction you've provided. + +The code relies on two custom RPC requests from the Substrate JSON-RPC: `chain_getFinalizedHead` and `chain_getHeader`. The first request gets the block hash of the last finalized block. The second request gets the block header for a given block hash. It also uses the same custom RPC function for `eth_getTransactionReceipt`, but this can be modified to use the regular `web3.eth.getTransactionReceipt(hash)` method. The same is true for `eth_getBlockByNumber`, to check if the given transactio hash is included in the block. + +--8<-- 'code/vs-ethereum/web3.md' + +### Custom RPC Requests with Ethers.js + +With [Ethers.js](https://docs.ethers.io/), you can make custom RPC requests with the `JsonRpcProvider` web3 provider. This will enable the `web3Provider.send()` method, as detailed in their [documentation site](https://docs.ethers.io/v5/api/providers/jsonrpc-provider/#JsonRpcProvider-send). + +Given a transaction hash (`tx_hash`), the following code snippet uses Ethers.js to fetch the current finalized block and compare it with the block number of the transaction you've provided. + +The code relies on two custom RPC requests from the Substrate JSON-RPC: `chain_getFinalizedHead` and `chain_getHeader`. The first request gets the block hash of the last finalized block. The second request gets the block header for a given block hash. It also uses the same custom RPC function for `eth_getTransactionReceipt`, but this can be modified to use the regular `web3Provider.getTransactionReceipt(hash)` method. The same is true for `eth_getBlockByNumber`, to check if the given transactio hash is included in the block. + +--8<-- 'code/vs-ethereum/ethers.md' + + + +## Checking Tx Finality with Polkadot.js + +The [Polkadot.js API package](https://polkadot.js.org/docs/api/start) provides developers a way to interact with Substrate chains using Javascript. + +Given a transaction hash (`tx_hash`), the following code snippet uses Polkadot.js to fetch the current finalized block and compare it with the block number of the transaction you've provided. You can find all the available information about Polkadot.js and the Substrate JSON RPC in their [official documentation site](https://polkadot.js.org/docs/substrate/rpc). + +The code relies on three RPC requests from the Substrate JSON-RPC: `chain_getFinalizedHead`, `chain_getHeader` and `eth_getTransactionReceipt`. The first request gets the block hash of the last finalized block. The second request gets the block header for a given block hash. The third request is fairly similar to the Ethereum JSON-RPC method, but it is done directly via the Substrate metadata. + +--8<-- 'code/vs-ethereum/polkadotjs.md' diff --git a/builders/get-started/eth-compare/index.md b/builders/get-started/eth-compare/index.md new file mode 100644 index 000000000..f57bfff8d --- /dev/null +++ b/builders/get-started/eth-compare/index.md @@ -0,0 +1,6 @@ +--- +title: Moonbeam vs Ethereum +template: main.html +--- + +
\ No newline at end of file diff --git a/builders/get-started/eth-compare/rpc-support.md b/builders/get-started/eth-compare/rpc-support.md new file mode 100644 index 000000000..abc09884f --- /dev/null +++ b/builders/get-started/eth-compare/rpc-support.md @@ -0,0 +1,79 @@ +--- +title: RPC Support +description: A description of the main differences that Ethereum developers need to understand in terms of the Ethereum RPC support Moonbeam Provides. +--- + +## Introduction + +While Moonbeam strives to be compatible with Ethereum's Web3 API and EVM, there are some important Moonbeam differences that developers should know and understand in terms of the [Ethereum API JSON-RPC](https://eth.wiki/json-rpc/API#json-rpc-methods) support. + +The Moonbeam team has collaborated closely with [Parity](https://www.parity.io/) on developing [Frontier](https://github.com/paritytech/frontier). Frontier is the Ethereum compatibility layer for Substrate based chains, and it is what allows developers to run unmodified Ethereum dApps. + +Nevertheless, not all of the Ethereum JSON RPC methods are supported, and some of the supported ones return default values (those related to PoW). This guide will outline some of these main differences around Ethereum RPC support and what to expect when using Moonbeam for the first time. + +## Basic Ethereum JSON RPC Methods + +At the time of writing, the basic JSON RPC methods from the Ethereum API supported by Moonbeam are: + + - **[eth_protocolVersion](https://eth.wiki/json-rpc/API#eth_protocolversion)** — Returns `1` by default + - **[eth_syncing](https://eth.wiki/json-rpc/API#eth_syncing)** — Returns an object with data about the sync status or `false` + - **[eth_hashrate](https://eth.wiki/json-rpc/API#eth_hashrate)** — Returns `"0x0"` by default + - **[eth_coinbase](https://eth.wiki/json-rpc/API#eth_coinbase)** — Returns the latest block author. Not necessarily a finalized block + - **[eth_mining](https://eth.wiki/json-rpc/API#eth_mining)** — Returns `false` by default + - **[eth_chainId](https://eth.wiki/json-rpc/API#eth_chainid)** — Returns the chain ID used for signing at the current block + - **[eth_gasPrice](https://eth.wiki/json-rpc/API#eth_gasprice)** — Returns the current gas price + - **[eth_accounts](https://eth.wiki/json-rpc/API#eth_accounts)** — Returns a list of addresses owned by the client + - **[eth_blockNumber](https://eth.wiki/json-rpc/API#eth_blocknumber)** — Returns the highest available block number + - **[eth_getBalance](https://eth.wiki/json-rpc/API#eth_getbalance)** — Returns the balance of the given address + - **[eth_getStorageAt](https://eth.wiki/json-rpc/API#eth_getstorageat)** — Returns content of the storage at a given address + - **[eth_getBlockByHash](https://eth.wiki/json-rpc/API#eth_getblockbyhash)** — Returns the block of the given hash + - **[eth_getBlockByNumber](https://eth.wiki/json-rpc/API#eth_getblockbynumber)** — Returns the block of the given block number + - **[eth_getTransactionCount](https://eth.wiki/json-rpc/API#eth_gettransactioncount)** — Returns the number of transactions sent from the given address (nonce) + - **[eth_getBlockTransactionCountByHash](https://eth.wiki/json-rpc/API#eth_getblocktransactioncountbyhash)** — Returns the number of transactions in a block with a given block hash + - **[eth_getBlockTransactionCountByNumber](https://eth.wiki/json-rpc/API#eth_getblocktransactioncountbynumber)** — Returns the number of transactions in a block with a given block number + - **[eth_getUncleCountByBlockHash](https://eth.wiki/json-rpc/API#eth_getunclecountbyblockhash)** — Returns `"0x0"` by default + - **[eth_getUncleCountByBlockNumber](https://eth.wiki/json-rpc/API#eth_getunclecountbyblocknumber)** — Returns `"0x0"` by default + - **[eth_getCode](https://eth.wiki/json-rpc/API#eth_getcode)** — Returns the code at given address at given block number + - **[eth_sendTransaction](https://eth.wiki/json-rpc/API#eth_sendtransaction)** — Creates new message call transaction or a contract creation, if the data field contains code. Returns the transaction hash, or the zero hash if the transaction is not yet available + - **[eth_sendRawTransaction](https://eth.wiki/json-rpc/API#eth_sendrawtransaction)** — Creates new message call transaction or a contract creation for signed transactions. Returns the transaction hash, or the zero hash if the transaction is not yet available + - **[eth_call](https://eth.wiki/json-rpc/API#eth_call)** — Executes a new message call immediately without creating a transaction on the block chain, returning the value of the executed call + - **[eth_estimateGas](https://eth.wiki/json-rpc/API#eth_estimategas)** — Returns an estimate amount of how much gas is necessary for a given transaction to succeed + - **[eth_getTransactionByHash](https://eth.wiki/json-rpc/API#eth_gettransactionbyhash)** — Returns the information about a transation with a given hash + - **[eth_getTransactionByBlockHashAndIndex](https://eth.wiki/json-rpc/API#eth_gettransactionbyblockhashandindex)** — Returns information about a transaction at a given block hash, and a given index position + - **[eth_getTransactionByBlockNumberAndIndex](https://eth.wiki/json-rpc/API#eth_gettransactionbyblocknumberandindex)** — Returns information about a transaction at a given block number, and a given index position + - **[eth_getTransactionReceipt](https://eth.wiki/json-rpc/API#eth_gettransactionreceipt)** — Returns the transaction receipt of a given transaction hash + - **[eth_getUncleByBlockHashAndIndex](https://eth.wiki/json-rpc/API#eth_getunclebyblockhashandindex)** — Returns `"null"` by default + - **[eth_getUncleByBlockNumberAndIndex](https://eth.wiki/json-rpc/API#eth_getunclebyblocknumberandindex)** — Returns `null` by default + - **[eth_getLogs](https://eth.wiki/json-rpc/API#eth_getlogs)** — Returns the transaction receipt of a given transaction hash + - **[eth_getWork](https://eth.wiki/json-rpc/API#eth_getwork)** — Returns `["0x0","0x0","0x0"]` by default + - **[eth_submitWork](https://eth.wiki/json-rpc/API#eth_submitwork)** — Not supported in Moonbeam + - **[eth_submitHashrate](https://eth.wiki/json-rpc/API#eth_submithashrate)** — Not supported in Moonbeam + +## Filter-related Ethereum JSON RPC Methods + +At the time of writing, the filter-related JSON RPC methods from the Ethereum API supported by Moonbeam are: + +- **[eth_newFilter](https://eth.wiki/json-rpc/API#eth_newfilter)** — Creates a filter object based on the input provided. Returns a filter ID + - **[eth_newBlockFilter](https://eth.wiki/json-rpc/API#eth_newblockfilter)** — Creates a filter in the node to notify when a new block arrives. Returns a filter id + - **[eth_newPendingTransactionFilter](https://eth.wiki/json-rpc/API#eth_newpendingtransactionfilter)** — Creates a filter in the node to notify when a new pending transaction arrives. Returns a filter ID + - **[eth_getFilterChanges](https://eth.wiki/json-rpc/API#eth_getfilterchanges)** — Polling method for filters (see methods above). Returns an array of logs which occured since last poll + - **[eth_getFilterLogs](https://eth.wiki/json-rpc/API#eth_getfilterlogs)** — Returns an array of all the logs matching the filter with a given ID + - **[eth_uninstallFilter](https://eth.wiki/json-rpc/API#eth_uninstallfilter)** — Uninstall a filter with a given ID. Should be used when polling is not longer needed. Filters timeout when they are not requested using `eth_getFilterChanges` after a period of time + +## Event Subscription Ethereum JSON RPC Methods + +At the time of writing, the [event subscription JSON RPC methods](https://geth.ethereum.org/docs/rpc/pubsub) from the Ethereum API supported by Moonbeam are: + +- **[eth_subscribe](https://geth.ethereum.org/docs/rpc/pubsub#create-subscription)** — Creates a subscription for a given subscription name. If successful, returns the subscription ID +- **[eth_unsubscribe](https://geth.ethereum.org/docs/rpc/pubsub#cancel-subscription)** — Cancels the subscription given by its ID + +### Supported Subscription + +At the time of writing, the [supported subcriptions](https://geth.ethereum.org/docs/rpc/pubsub#supported-subscriptions) are: + + - **[newHeads](https://geth.ethereum.org/docs/rpc/pubsub#newheads)** — Triggers a notification each time a new header is appended to the chain + - **[logs](https://geth.ethereum.org/docs/rpc/pubsub#logs)** — Returns logs that are included in new imported blocks, and match a given filter criteria + - **[newPendingTransactions](https://geth.ethereum.org/docs/rpc/pubsub#newpendingtransactions)** — Returns the hash for all transactions that are added to the pending state + - **[syncing](https://geth.ethereum.org/docs/rpc/pubsub#syncing)** — Indicates when the node starts or stop synchronizing with the network + +For a dedicated tutorial for these subscriptions checkout the [Events Subscription](/builders/tools/pubsub/) guide. \ No newline at end of file diff --git a/builders/get-started/eth-compare/transfers-api.md b/builders/get-started/eth-compare/transfers-api.md new file mode 100644 index 000000000..ad3177129 --- /dev/null +++ b/builders/get-started/eth-compare/transfers-api.md @@ -0,0 +1,46 @@ +--- +title: Transfers API +description: A description of the main differences that developers need to understand in terms of the different balance transfers available on Moonbeam. +--- + +## Introduction + +While Moonbeam strives to be compatible with Ethereum's Web3 API and EVM, there are some important Moonbeam differences that developers should know and understand in terms of balance transfers. + +Token holders have two ways of initiating a balance transfer on Moonbeam. On one side, users can use the Ethereum API via apps like MetaMask, MathWallet, or any other tools that use the Ethereum JSON-RPC. On the other side, users can use the Substrate API, via the Polkadot.js Apps website. + +Developers need to be aware that token holders can leverage both APIs to transfer tokens. This guide will outline some of these main differences around both APIs for balance transfers and what to expect when using Moonbeam for the first time. + +## Ethereum Transfers + +A simple balance transfer using the Ethereum API relies on the `eth_sendRawTransaction` JSON RPC. This can be directly from one account to another or via a smart contract. + +There are different strategies to listen for transfers or balance changes on Ethereum, which are not covered in this documentation. But they are all focused on different strategies using the Ethereum JSON RPC. + +## Moonbeam Transfers + +As stated before, Moonbeam enables token holders to execute transfers via both the Ethereum and Substrate API. There are multiple scenarios to trigger token transfer on Moonbeam. Consequently, to monitor all transfers, **you should use the Polkadot.js SDK** (Substrate API). + +Before going over the different scenarios, there are two different elements associated with a block: + + - **Extrinsic** — refers to state changes that originated outside of the system itself. The most common form of extrinsic is a transaction. They are ordered by execution + - **Events** — refers to logs generated from the extrinsic. There can be multiple events per extrinsic. They are ordered by execution + +The different transfer scenarios are: + + - **Substrate transfer** — it will create an extrinsic, either `balances.transfer` or `balances.transferKeepAlive`. It will trigger **one** `balances.Transfer` event + - **Substrate feature** — some native Substrate features can create extrinsic that would send tokens to an address. For example, [Treasury](/learn/features/treasury/) can create an extrinsic such as `treasury.proposeSend`, which will trigger **one or multiple** `balances.Transfer` events + - **Ethereum transfer** — it will create an `ethereum.transact` extrinsic, with an empty input. It will trigger **one** `balances.Transfer` event + - **Ethereum transfers via smart contracts** — it will create an `ethereum.transact` extrinsic, with some data as input. It will trigger **one or multiple** `balances.Transfer` events + +All the scenarios described above will effectively transfer tokens. The easiest way to monitor them all is to rely on the `balances.Transfer` event. + +## Monitor All Balance Transfers with the Substrate API + +The [Polkadot.js API package](https://polkadot.js.org/docs/api/start) provides developers a way to interact with Substrate chains using Javascript. + +The following code snippet uses Polkadot.js to loop through each event fetched from the provider. Then, it checks it corresponds to a `balances.Transfer` event. If so, it will extract the `from`, `to` and `amount` of the transfer and display it on the console. Note that the `amount` is shown in the smallest unit (Wei). You can find all the available information about Polkadot.js and the Substrate JSON RPC in their [official documentation site](https://polkadot.js.org/docs/substrate/rpc). + +--8<-- 'code/vs-ethereum/balance-event.md' + +In addition, you can find more code snippets related to more specific cases around balance transfers in [this script](https://gist.github.com/crystalin/b2ce44a208af60d62b5ecd1bad513bce). diff --git a/snippets/code/vs-ethereum/balance-event.md b/snippets/code/vs-ethereum/balance-event.md new file mode 100644 index 000000000..e60689e2a --- /dev/null +++ b/snippets/code/vs-ethereum/balance-event.md @@ -0,0 +1,39 @@ +```js +import { typesBundle } from "moonbeam-types-bundle"; +import { ApiPromise, WsProvider } from "@polkadot/api"; + + +// This script will listen to all MOVRs transfers (Substrate & Ethereum) + +const main = async () => { + // Define the provider + const wsProvider = new WsProvider("wss://wss.moonriver.moonbeam.network"); + + // Create the provider using Moonbeam types + const polkadotApi = await ApiPromise.create({ + provider: wsProvider, + typesBundle: typesBundle, + }); + + + polkadotApi.query.system.events((events) => { + // Loop through the Vec + events.forEach(({ event }) => { + + // Check if the event is related to balances.Transfer + if (event.section == "balances" && event.method == "Transfer") { + + // Extract the relevant information + const from = event.data[0].toString(); + const to = event.data[1].toString(); + const balance = event.data[2].toBigInt(); + + // Balance is shown in the min unit + console.log(`Transfer from ${from} to ${to} of ${balance}`); + } + }); + }); +}; + +main(); +``` \ No newline at end of file diff --git a/snippets/code/vs-ethereum/ethers.md b/snippets/code/vs-ethereum/ethers.md new file mode 100644 index 000000000..c97e0880d --- /dev/null +++ b/snippets/code/vs-ethereum/ethers.md @@ -0,0 +1,76 @@ +```js +import ethers from 'ethers'; + +// Define the TxHash to Check Finality +const txHash = 'tx_hash'; + +// Define the RPC of the Provider +const providerRPC = { + moonriver: { + name: 'moonriver', + rpc: 'https://rpc.moonriver.moonbeam.network', + chainId: 1285, + }, +}; + +// Define the Web3 provider +const web3Provider = new ethers.providers.JsonRpcProvider(providerRPC.moonriver.rpc, { + chainId: providerRPC.moonriver.chainId, + name: providerRPC.moonriver.name, +}); + +// Define the function for the Custom Web3 Request +const customWeb3Request = async (web3Provider, method, params) => { + try { + return await web3Provider.send(method, params); + } catch (error) { + throw new Error(error.body); + } +}; + +const main = async () => { + // Get the latest finalized block of the Substrate chain + // Uses Polkadot JSON-RPC + const finalizedHeadHash = await customWeb3Request(web3Provider, 'chain_getFinalizedHead', []); + + // Get finalized block header to retrieve number + // Uses Polkadot JSON-RPC + const finalizedBlockHeader = await customWeb3Request(web3Provider, 'chain_getHeader', [ + finalizedHeadHash, + ]); + const finalizedBlockNumber = parseInt(finalizedBlockHeader.number, 16); + + // Get the transaction receipt of the given tx hash + // Uses Ethereum JSON-RPC + const txReceipt = await customWeb3Request(web3Provider, 'eth_getTransactionReceipt', [txHash]); + + // As a safety check, get given block to check if transaction is included + // Uses Ethereum JSON-RPC + const txBlock = await customWeb3Request(web3Provider, 'eth_getBlockByNumber', [ + txReceipt.blockNumber, + false, + ]); + + // If block number of receipt is not null, compare it against finalized head + if (txReceipt) { + // Convert to Number + const txBlockNumber = parseInt(txReceipt.blockNumber, 16); + + console.log(`Current finalized block number is ${finalizedBlockNumber}`); + console.log( + `Your transaction in block ${txBlockNumber} is finalized? ${ + finalizedBlockNumber >= txBlockNumber + }` + ); + console.log( + `Your transaction in indeed in block ${txBlockNumber}? ${txBlock.transactions.includes( + txHash + )}` + ); + } else { + console.log('Your transaction has not been included in the canonical chain'); + } +}; + +main(); +``` \ No newline at end of file diff --git a/snippets/code/vs-ethereum/polkadotjs.md b/snippets/code/vs-ethereum/polkadotjs.md new file mode 100644 index 000000000..f607a1e39 --- /dev/null +++ b/snippets/code/vs-ethereum/polkadotjs.md @@ -0,0 +1,45 @@ +```js +import { ApiPromise, WsProvider } from '@polkadot/api'; +import { typesBundle } from 'moonbeam-types-bundle'; + +// Define the TxHash to Check Finality +const txHash = 'tx_hash'; + +// Define the provider +const wsProvider = new WsProvider('wss://wss.moonriver.moonbeam.network'); + +const main = async () => { + // Create the provider using Moonbeam types + const polkadotApi = await ApiPromise.create({ + provider: wsProvider, + typesBundle: typesBundle, + }); + await polkadotApi.isReady; + + // Get the latest finalized block of the Substrate chain + const finalizedHeadHash = (await polkadotApi.rpc.chain.getFinalizedHead()).toJSON(); + + // Get finalized block header to retrieve number + const finalizedBlockHeader = (await polkadotApi.rpc.chain.getHeader(finalizedHeadHash)).toJSON(); + + // Get the transaction receipt of the given tx hash + const txReceipt = (await polkadotApi.rpc.eth.getTransactionReceipt(txHash)).toJSON(); + + // We can not verify if the tx is in block because polkadotApi.rpc.eth.getBlockByNumber + // does not return the list of tx hash + + // If block number of receipt is not null, compare it against finalized head + if (txReceipt) { + console.log(`Current finalized block number is ${finalizedBlockHeader.number}`); + console.log( + `Your transaction in block ${txReceipt.blockNumber} is finalized? ${ + finalizedBlockHeader.number >= txReceipt.blockNumber + }` + ); + } else { + console.log('Your transaction has not been included in the canonical chain'); + } +}; + +main(); +``` \ No newline at end of file diff --git a/snippets/code/vs-ethereum/web3.md b/snippets/code/vs-ethereum/web3.md new file mode 100644 index 000000000..0335e1076 --- /dev/null +++ b/snippets/code/vs-ethereum/web3.md @@ -0,0 +1,94 @@ +```js +import Web3 from 'web3'; + +// Define the TxHash to Check Finality +const txHash = 'tx_hash'; + +// Define the Web3 provider +const web3 = new Web3('https://rpc.moonriver.moonbeam.network'); + +// Define the function for the Custom Web3 Request +const customWeb3Request = async (web3Provider, method, params) => { + try { + return await requestPromise(web3Provider, method, params); + } catch (error) { + throw new Error(error); + } +}; + +// In Web3.js we need to return a promise +const requestPromise = async (web3Provider, method, params) => { + return new Promise((resolve, reject) => { + web3Provider.send( + { + jsonrpc: '2.0', + id: 1, + method, + params, + }, + (error, result) => { + if (error) { + reject(error.message); + } else { + if (result.error) { + reject(result.error.message); + } + resolve(result); + } + } + ); + }); +}; + +const main = async () => { + // Get the latest finalized block of the Substrate chain + // Uses Polkadot JSON-RPC + const finalizedHeadHash = await customWeb3Request( + web3.currentProvider, + 'chain_getFinalizedHead', + [] + ); + + // Get finalized block header to retrieve number + // Uses Polkadot JSON-RPC + const finalizedBlockHeader = await customWeb3Request(web3.currentProvider, 'chain_getHeader', [ + finalizedHeadHash.result, + ]); + const finalizedBlockNumber = parseInt(finalizedBlockHeader.result.number, 16); + + // Get the transaction receipt of the given tx hash + // Uses Ethereum JSON-RPC + const txReceipt = await customWeb3Request(web3.currentProvider, 'eth_getTransactionReceipt', [ + txHash, + ]); + + // As a safety check, get given block to check if transaction is included + // Uses Ethereum JSON-RPC + const txBlock = await customWeb3Request(web3.currentProvider, 'eth_getBlockByNumber', [ + txReceipt.result.blockNumber, + false, + ]); + + // If block number of receipt is not null, compare it against finalized head + if (txReceipt) { + // Convert to Number + const txBlockNumber = parseInt(txReceipt.result.blockNumber, 16); + + console.log(`Current finalized block number is ${finalizedBlockNumber}`); + console.log( + `Your transaction in block ${txBlockNumber} is finalized? ${ + finalizedBlockNumber >= txBlockNumber + }` + ); + console.log( + `Your transaction in indeed in block ${txBlockNumber}? ${txBlock.result.transactions.includes( + txHash + )}` + ); + } else { + console.log('Your transaction has not been included in the canonical chain'); + } +}; + +main(); +``` \ No newline at end of file diff --git a/snippets/code/vs-ethereum/web3py.md b/snippets/code/vs-ethereum/web3py.md new file mode 100644 index 000000000..10717c723 --- /dev/null +++ b/snippets/code/vs-ethereum/web3py.md @@ -0,0 +1,61 @@ +```python +import asyncio +from aiohttp import ClientSession +from web3.providers.base import JSONBaseProvider +from web3.providers import HTTPProvider +from web3 import Web3 + +# Define the TxHash to Check Finality +txHash = 'tx_hash' + +# Define the Web3 provider +RPC_address = 'https://rpc.moonriver.moonbeam.network' +web3 = Web3(HTTPProvider(RPC_address)) + + +# synchronously request receipts for given transaction +def sync_receipts(web3, transaction): + return web3.eth.getTransactionReceipt(transaction) + +# asynchronous JSON RPC API request +async def customWeb3Request(web3, method, params): + request_data = web3.encode_rpc_request(method, params) + async web3 + response = base_provider.decode_rpc_response(content) + return response + +async def run(node_address, method_header, params): + # Fetch all responses within one Client session, + # keep connection alive for all requests. + async with ClientSession() as session: + task = asyncio.ensure_future(async_make_request(session, node_address, + method_header, params)) + response = await task + return response + +if __name__ == "__main__": + + #Get the current event loop + loop = asyncio.get_event_loop() + + #Get the latest finalized block of the Substrate chain + finalizedHeadHash = loop.run_until_complete(run(RPC_address, 'chain_getFinalizedHead', []))['result'] + + #Get finalized block header to retrieve number + finalizedBlockHeader = loop.run_until_complete(run(RPC_address, 'chain_getHeader', [finalizedHeadHash]))['result'] + + #Parse the finalized block number + finalizedBlockNumber = int(finalizedBlockHeader["number"], 16) + + #Get the transaction receipt of the given tx hash + txReceipt = sync_receipts(web3, txHash) + + #If block number of receipt is not null, compare it against finalized head + if txReceipt is not None : + txBlockNumber = txReceipt["blockNumber"] + print('Current finalized block number is '+ str(finalizedBlockNumber)) + print('Your transaction in block '+str(txBlockNumber) + ' is finalized? ' + str(bool(finalizedBlockNumber >= txBlockNumber))) + + else: + print("Your transaction has not been included in the canonical chain") +``` \ No newline at end of file