diff --git a/pages/docs/build-with-avail/Validium/reference.mdx b/pages/docs/build-with-avail/Validium/reference.mdx
index 52b5520b9..2a7400885 100644
--- a/pages/docs/build-with-avail/Validium/reference.mdx
+++ b/pages/docs/build-with-avail/Validium/reference.mdx
@@ -25,198 +25,11 @@ interpreted or executed in any way. The submission can be done using
`Polkadot-JS` which is a collection of tools for communication with
chains based on Substrate (which is now part of the Polkadot SDK).
-Complete example can be found on [github](https://github.com/availproject/avail/tree/develop/examples/validium).
+Complete example can be found on [github](https://github.com/availproject/avail/blob/main/examples/deno/validium.ts).
Example of sending data to Avail:
```typescript
-async function submitData(availApi, data, account) {
- let submit = await availApi.tx.dataAvailability.submitData(data);
- return await sendTx(availApi, account, submit);
-}
-```
-
-Function `submitData` receives `availApi` api instance, `data` that will be submitted,
-and the `account` which is sending the transaction. In order to create account
-it is necessary to create _keyring_ _pair_ for the account that wants to send the data.
-This can be done with `keyring.addFromUri(secret)` which creates keyring pair via suri
-(the secret can be a hex string, mnemonic phrase or a string).
-After creating keyring pair, it is possible to submit data in a transaction to the Avail network with
-`availApi.tx.dataAvailability.submitData(data);`. Once the transaction is included in an Avail block,
-it is possible to initiate the dispatch of the data root by creating a dispatch transaction
-`availApi.tx.daBridge.tryDispatchDataRoot(destinationDomain, bridgeRouterEthAddress, header);` with the parameters:
-
-`destinationDomain` Destination domain 1000.
-
-`bridgeRouterEthAddress` Address of the main data availability router contract deployed on Sepolia network for Goldberg (`0x305222c4DdB86FfA9fa9Aa0A479705577E3c4d33`),
-for Kate`0xbD824890A51ed8bda53F51F27303b14EFfEbC152`.
-
-`header` Provided from the block when data is submitted.
-
-```typescript
-async function dispatchDataRoot(availApi, blockHash, account) {
- const header = await availApi.rpc.chain.getHeader(blockHash);
- let tx = await availApi.tx.daBridge.tryDispatchDataRoot(
- process.env.DESTINATION_DOMAIN,
- process.env.DA_BRIDGE_ADDRESS,
- header,
- );
- return await sendTx(availApi, account, tx);
-}
-```
-
-
-Example of submitting data to Avail and dispatching the data root using `Polkadot-JS`.
-
-Environment variables:
-
-```dotenv
-AVAIL_RPC= # avail network websocket url
-SURI= # mnemonic
-DA_BRIDGE_ADDRESS= # main da bridge contract address deployed to Sepolia test network in format (Kate) 0x000000000000000000000000bD824890A51ed8bda53F51F27303b14EFfEbC152 (Goldberg) 0x000000000000000000000000305222c4DdB86FfA9fa9Aa0A479705577E3c4d33
-DESTINATION_DOMAIN= # destination domain is 1000
-DATA= # data sending to avail
-```
-
-
-
- Dispatch Data Root Javascript Example
-
-
-```typescript
-import { ApiPromise, Keyring, WsProvider } from '@polkadot/api';
-import * as dotenv from 'dotenv';
-
-dotenv.config();
-
-/**
- * Creates api instance.
- *
- * @param url websocket address
- */
-async function createApi(url) {
- const provider = new WsProvider(url);
- return ApiPromise.create({
- provider,
- rpc: {
- kate: {
- queryDataProof: {
- description: 'Generate the data proof for the given `index`',
- params: [
- {
- name: 'transaction_index',
- type: 'u32',
- },
- {
- name: 'at',
- type: 'Hash',
- isOptional: true,
- },
- ],
- type: 'DataProof',
- },
- },
- },
- types: {
- AppId: 'Compact',
- DataLookupIndexItem: {
- appId: 'AppId',
- start: 'Compact',
- },
- DataLookup: {
- size: 'Compact',
- index: 'Vec',
- },
- KateCommitment: {
- rows: 'Compact',
- cols: 'Compact',
- dataRoot: 'H256',
- commitment: 'Vec',
- },
- V1HeaderExtension: {
- commitment: 'KateCommitment',
- appLookup: 'DataLookup',
- },
- VTHeaderExtension: {
- newField: 'Vec',
- commitment: 'KateCommitment',
- appLookup: 'DataLookup',
- },
- HeaderExtension: {
- _enum: {
- V1: 'V1HeaderExtension',
- VTest: 'VTHeaderExtension',
- },
- },
- DaHeader: {
- parentHash: 'Hash',
- number: 'Compact',
- stateRoot: 'Hash',
- extrinsicsRoot: 'Hash',
- digest: 'Digest',
- extension: 'HeaderExtension',
- },
- Header: 'DaHeader',
- CheckAppIdExtra: {
- appId: 'AppId',
- },
- CheckAppIdTypes: {},
- CheckAppId: {
- extra: 'CheckAppIdExtra',
- types: 'CheckAppIdTypes',
- },
- DataProof: {
- root: 'H256',
- proof: 'Vec',
- numberOfLeaves: 'Compact',
- leafIndex: 'Compact',
- leaf: 'H256',
- },
- Cell: {
- row: 'u32',
- col: 'u32',
- },
- },
- signedExtensions: {
- CheckAppId: {
- extrinsic: {
- appId: 'AppId',
- },
- payload: {},
- },
- },
- });
-}
-
-/**
- * Sends transaction to Avail.
- *
- * @param api instance of the api
- * @param account sending the transaction
- * @param tx transaction
- */
-async function sendTx(api, account, tx) {
- return new Promise(async (resolve) => {
- try {
- const res = await tx.signAndSend(account, (result) => {
- if (result.status.isReady) {
- console.log(`Txn has been sent to the mempool`);
- }
- if (result.status.isInBlock) {
- console.log(
- `Tx hash: ${result.txHash} is in block ${result.status.asInBlock}`,
- );
- res();
- resolve(result);
- }
- });
- } catch (e) {
- console.log(e);
- process.exit(1);
- }
- });
-}
-
/**
* Submitting data to Avail as a transaction.
*
@@ -226,223 +39,118 @@ async function sendTx(api, account, tx) {
* @returns {Promise}
*/
async function submitData(availApi, data, account) {
- let submit = await availApi.tx.dataAvailability.submitData(data);
- return await sendTx(availApi, account, submit);
-}
-
-/**
- * Sending dispatch data root transaction.
- *
- * @param availApi api instance
- * @param blockHash hash of the block
- * @param account sending transaction
- * @returns {Promise}
- */
-async function dispatchDataRoot(availApi, blockHash, account) {
- const destinationDomain = process.env.DESTINATION_DOMAIN;
- const bridgeRouterEthAddress = process.env.DA_BRIDGE_ADDRESS;
- const header = await availApi.rpc.chain.getHeader(blockHash);
- console.log(`Block Number: ${header.number}`);
- console.log(`State Root: ${header.stateRoot}`);
- let tx = await availApi.tx.daBridge.tryDispatchDataRoot(
- destinationDomain,
- bridgeRouterEthAddress,
- header,
- );
- return await sendTx(availApi, account, tx);
-}
-
-/**
- * Returns data root for the particular block.
- *
- * @param availApi api instance
- * @param blockHash hash of the block
- * @returns {Promise<(*)[]>}
- */
-async function getDataRoot(availApi, blockHash) {
- const header = JSON.parse(await availApi.rpc.chain.getHeader(blockHash));
- return [header.extension.v1.commitment.dataRoot, header.number];
+ return await new Promise((res) => {
+ console.log("Sending transaction...")
+ availApi.tx.dataAvailability.submitData(data).signAndSend(account, {nonce: -1}, (result: ISubmittableResult) => {
+ console.log(`Tx status: ${result.status}`)
+ if (result.isError) {
+ console.log(`Tx failed!`);
+ res(result)
+ }
+ if (result.isInBlock) {
+ console.log("Transaction in block, waiting for block finalization...")
+ }
+ if (result.isFinalized) {
+ console.log(`Tx finalized.`)
+ res(result)
+ }
+ })
+ });
}
-
-(async function dataRootDispatch() {
- const availApi = await createApi(process.env.AVAIL_RPC);
- const keyring = new Keyring({ type: 'sr25519' });
- const account = keyring.addFromMnemonic(process.env.SURI);
- console.log('Submitting data to Avail...');
-
- let result = await submitData(availApi, process.env.DATA, account);
- const txIndex = JSON.parse(result.events[0].phase).applyExtrinsic;
- const blockHash = result.status.asInBlock;
- console.log(
- `Transaction: ${result.txHash}. Block hash: ${blockHash}. Transaction index: ${txIndex}.`,
- );
-
- console.log('Triggering Home...');
- result = await dispatchDataRoot(availApi, blockHash, account);
- console.log(`Sent txn on Avail. Txn Hash: ${result.txHash}.`);
- let [root, blockNum] = await getDataRoot(availApi, blockHash);
- console.log('Data Root:' + root + ' and Block number: ' + blockNum);
-
- await availApi.disconnect();
-})()
- .then(() => {
- console.log('Done');
- })
- .catch((err) => {
- console.error(err);
- process.exit(1);
- });
```
-
-
-Dispatching data root will trigger an optimistic bridge which will bridge the data root to the Ethereum network. Since the bridge
-is optimistic, it is necessary to wait for 30 minutes before the data root is available on Ethereum.
+Function `submitData` receives `availApi` api instance, `data` that will be submitted,
+and the `account` which is sending the transaction. In order to create account
+it is necessary to create _keyring_ _pair_ for the account that wants to send the data.
+This can be done with `keyring.addFromUri(secret)` which creates keyring pair via suri
+(the secret can be a hex string, mnemonic phrase or a string).
+After creating keyring pair, it is possible to submit data in a transaction to the Avail network with
+`availApi.tx.dataAvailability.submitData(data);`. Once the transaction is included in an Avail block, and bridged to the
+Ethereum network it is possible to query for the proof and check the data inclusion.
-After successfully bridging data root to the main data availability attestation contract on Ethereum,
+When DA transaction is included in the finalized Avail block, it will be bridged via VectorX bridge to the Ethereum network.
+VectorX is a Zero-Knowledge bridge that bridges a batches of data roots every 360 Avail blocks to the Ethereum network.
+After successfully bridging the data root to the Ethereum network,
it is possible to prove that data is available on the Avail network by submitting a Merkle proof to the verification contract.
-Fetching proof from Avail can be done via RPC call `kate_queryDataProof` for
-example `availApi.rpc.kate.queryDataProof(transactionIndex, hashBlock);`
-where `transactionIndex` is index of the transaction in the block and `hashBlock` which is a hash of the block in which
-the data is included. This RPC endpoint returns `DataProof` object that can be used to prove on Ethereum that data is available on the Avail network.
+Proof is available only when the block in which the transaction is included is committed to the VectorX contract,
+one such is deployed to the Sepolia network ([`0xe542db219a7e2b29c7aeaeace242c9a2cd528f96`](https://sepolia.etherscan.io/address/0xe542db219a7e2b29c7aeaeace242c9a2cd528f96)).
+ Once the range is committed to the VectorX contract, which
+can be checked by calling `https://turing-bridge-api.fra.avail.so/avl/head` that returns `start` and `end` block range that is available on the VectorX contract,
+fetching proof can be done via bridge api http call
+ `https://turing-bridge-api.fra.avail.so/eth/proof/?index=`
+where path param `blockHash` is a hash of the finalized block in which
+the data is included and a query param `index` is index of the transaction in the block.
+This http endpoint returns a json object that can be used to prove that data is available on the Avail network.
Example:
```typescript
-async function getProof(availApi, hashBlock, transactionIndex) {
- const dataProof = await availApi.rpc.kate.queryDataProof(
- transactionIndex,
- hashBlock,
- );
- return dataProof;
-}
+const proofResponse: ProofData = await fetch(BRIDGE_API_URL + "/eth/proof/" + result.finalized + "?index=" + result.txIndex);
```
Returned data:
-```
-DataProof: {
- root: 'H256',
- proof: 'Vec',
- numberOfLeaves: 'Compact',
- leafIndex: 'Compact',
- leaf: 'H256'
+``` typescript
+class ProofData {
+ dataRootProof: Array
+ leafProof: string
+ rangeHash: string
+ dataRootIndex: number
+ blobRoot: string
+ bridgeRoot: string
+ leaf: string
+ leafIndex: number
}
```
-`root` Root hash of generated merkle tree.
-
-`proof` Merkle proof items (does not contain the leaf hash, nor the root).
-
-`numberOfLeaves` Number of leaves in the original tree.
+- `dataRootProof` Merkle proof of batched data root items (does not contain the leaf hash, nor the root).
-`leafIndex` Index of the leaf the proof is for (starts from 0).
-
-`leaf` Leaf for which is the proof.
-
-
-EXAMPLE
-
-
- Example of Verification Contract
-
+- `leafProof` Merkle proof of items for the leaf (does not contain the leaf hash, nor the root).
-```solidity
-// SPDX-License-Identifier: Apache-2.0
-// Modified from https://github.com/QEDK/solidity-misc/blob/master/contracts/Merkle.sol
-pragma solidity ^0.8.21;
+- `rangeHash` Header rang hash of the items batch.
-import "@openzeppelin/contracts/access/Ownable.sol";
-// or for foundry:
-// import "openzeppelin-contracts/contracts/access/Ownable.sol";
+- `dataRootIndex` Index of the data root in the commitment tree.
-interface IDataAvailabilityRouter {
- function roots(uint32 blockNumber) external view returns (bytes32 root);
-}
+- `blobRoot` Root hash of generated blob merkle sub-tree.
-contract ValidiumContract is Ownable {
- IDataAvailabilityRouter private router;
+- `bridgeRoot` Root hash of generated bridge merkle sub-tree.
- function setRouter(
- IDataAvailabilityRouter _router
- ) public virtual onlyOwner {
- router = _router;
- }
+- `numberOfLeaves` Number of leaves in the original tree.
- function checkDataRootMembership(
- uint32 blockNumber,
- bytes32[] calldata proof,
- uint256 width, // number of leaves
- uint256 index,
- bytes32 leaf
- ) public view virtual returns (bool isMember) {
- bytes32 rootHash = router.roots(blockNumber);
- // if root hash is 0, block does not have a root (yet)
- require(rootHash != bytes32(0), "INVALID_ROOT");
- assembly ("memory-safe") {
- if proof.length {
- let end := add(proof.offset, shl(5, proof.length))
- let i := proof.offset
-
- for {} 1 {} {
- let leafSlot := shl(5, and(0x1, index))
- if eq(add(index, 1), width) {
- leafSlot := 0x20
- }
- mstore(leafSlot, leaf)
- mstore(xor(leafSlot, 32), calldataload(i))
- leaf := keccak256(0, 64)
- index := shr(1, index)
- i := add(i, 32)
- width := add(shr(1, sub(width, 1)), 1)
- if iszero(lt(i, end)) {
- break
- }
- }
- }
- // checks if the calculated root matches the expected root
- isMember := eq(leaf, rootHash)
- }
- }
-}
-```
+- `leaf` Leaf for which is the proof.
-
-
+- `leafIndex` Index of the leaf the proof is for (starts from 0).
By submitting proof to the verification contract it is possible to verify
that data is available on Avail. Merkle proof is a list of hashes that can be used to prove
that given leaf is a member of the Merkle tree. Example of submitting a proof to the verification contract
-deployed on Sepolia network for Kate (`0xA06386C65B1f56De57CE6aB9CeEB2552fa811529`) and Goldberg (`0x67044689F7e274a4aC7b818FDea64Cb4604c6875`) can be queried by calling data root membership function
-`async function checkProof(sepoliaApi, blockNumber, proof, numberOfLeaves, leafIndex, leafHash);` where
-
-`sepoliaApi` Sepolia network api instance.
-
-`blockNumber` Avail block number.
-
-`proof` Merkle proof for the leaf.
-
-`numberOfLeaves` Number of leaves in the original tree.
-
-`leafIndex` Index of the leaf in the Merkle tree.
-
-`leafHash` Hash of the leaf in the Merkle tree.
-
-This will call deployed contracts function `verificationContract.checkDataRootMembership(blockNumber, proof, numberOfLeaves, leafIndex, leafHash)`
+deployed on Sepolia network for Turing ([`0x967F7DdC4ec508462231849AE81eeaa68Ad01389`](https://sepolia.etherscan.io/address/0x967F7DdC4ec508462231849AE81eeaa68Ad01389)) can be done by calling `verifyBlobLeaf` function.
+This will call deployed contracts function `verificationContract.verifyBlobLeaf(merkleProofInput)`
and return `true` or `false` depending on the provided proof.
-
-EXAMPLE OF GETTING THE PROOF AND CHECKING IT WITH VERIFICATION CONTRACT USING `POLKADOT-JS` AND `ETHERS.JS`.
-Environment variables:
-
-```dotenv
-AVAIL_RPC= # avail websocket address
-INFURA_KEY= # rpc provider key if needed
-VALIDIUM_ADDRESS= # address of the verification contract, one such is deployed on Sepolia network for Kate 0xA06386C65B1f56De57CE6aB9CeEB2552fa811529 or Goldberg 0x67044689F7e274a4aC7b818FDea64Cb4604c6875
-VALIDIYM_ABI_PATH= # path to abi file e.g. abi/ValidiumContract.json
-BLOCK_NUMBER= # number of the block for which to get Merkle proof
-BLOCK_HASH= # hash of the block for which to get Merkle proof
-TRANSACTION_INDEX= # index of the transaction in the block
+Input params for the `verifyBlobLeaf` function:
+
+```
+struct MerkleProofInput {
+ // proof of inclusion for the data root
+ bytes32[] dataRootProof;
+ // proof of inclusion of leaf within blob/bridge root
+ bytes32[] leafProof;
+ // abi.encodePacked(startBlock, endBlock) of header range commitment on VectorX
+ bytes32 rangeHash;
+ // index of the data root in the commitment tree
+ uint256 dataRootIndex;
+ // blob root to check proof against, or reconstruct the data root
+ bytes32 blobRoot;
+ // bridge root to check proof against, or reconstruct the data root
+ bytes32 bridgeRoot;
+ // leaf being proven
+ bytes32 leaf;
+ // index of the leaf in the blob/bridge root tree
+ uint256 leafIndex;
+ }
```
+
+EXAMPLE OF GETTING THE PROOF AND CHECKING IT WITH VERIFICATION CONTRACT FUNCTION USING `POLKADOT-JS` AND `ETHERS.JS`.
@@ -450,155 +158,121 @@ TRANSACTION_INDEX= # index of the transaction in the block
```typescript
-import { ethers } from 'ethers';
-import * as dotenv from 'dotenv';
-import { hexlify } from 'ethers/lib/utils.js';
-import { readFileSync } from 'fs';
-import { ApiPromise, WsProvider } from '@polkadot/api';
-
-dotenv.config();
+import {ApiPromise, Keyring, WsProvider} from "https://deno.land/x/polkadot@0.2.45/api/mod.ts";
+import {API_EXTENSIONS, API_RPC, API_TYPES} from "./api_options.ts";
+import {ISubmittableResult} from "https://deno.land/x/polkadot@0.2.45/types/types/extrinsic.ts";
+import {ethers} from "npm:ethers@5.4";
+
+import ABI from './abi/availbridge.json' with {type: "json"};
+
+const AVAIL_RPC = "ws://127.0.0.1:9944";
+const SURI = "//Alice";
+const BRIDGE_ADDRESS = ""; // deployed bridge address
+const DATA = ""; // data to send
+const BRIDGE_API_URL = ""; // bridge api url
+const ETH_PROVIDER_URL = ""; // eth provider url
+const availApi = await ApiPromise.create({
+ provider: new WsProvider(AVAIL_RPC),
+ rpc: API_RPC,
+ types: API_TYPES,
+ signedExtensions: API_EXTENSIONS,
+});
+const account = new Keyring({type: "sr25519"}).addFromUri(SURI);
/**
- * Creates api instance.
- *
- * @param url websocket address
- * @returns {Promise}
+ * ProofData represents a response from the api that holds proof for
+ * the blob verification.
*/
-async function createApi(url) {
- const provider = new WsProvider(url);
-
- // Create the API and wait until ready
- return ApiPromise.create({
- provider,
- rpc: {
- kate: {
- queryDataProof: {
- description: 'Generate the data proof for the given `index`',
- params: [
- {
- name: 'data_index',
- type: 'u32',
- },
- {
- name: 'at',
- type: 'Hash',
- isOptional: true,
- },
- ],
- type: 'DataProof',
- },
- },
- },
- types: {
- DataProof: {
- root: 'H256',
- proof: 'Vec',
- numberOfLeaves: 'Compact',
- leafIndex: 'Compact',
- leaf: 'H256',
- },
- },
- });
+class ProofData {
+ dataRootProof: Array
+ leafProof: string
+ rangeHash: string
+ dataRootIndex: number
+ blobRoot: string
+ bridgeRoot: string
+ leaf: string
+ leafIndex: number
}
/**
- * Returns Merkle proof for the particular data.
+ * Submitting data to Avail as a transaction.
*
- * @param availApi Api instance
- * @param hashBlock Hash of the block
- * @param transactionIndex Index of the transaction in the block
- * @returns {Promise<*>}
+ * @param availApi api instance
+ * @param data payload to send
+ * @param account that is sending transaction
+ * @returns {Promise}
*/
-async function getProof(availApi, hashBlock, transactionIndex) {
- const daHeader = await availApi.rpc.kate.queryDataProof(
- transactionIndex,
- hashBlock,
- );
- console.log(
- `Fetched proof from Avail for txn index ${transactionIndex} inside block ${hashBlock}`,
- );
- return daHeader;
+async function submitData(availApi, data, account) {
+ return await new Promise((res) => {
+ console.log("Sending transaction...")
+ availApi.tx.dataAvailability.submitData(data).signAndSend(account, {nonce: -1}, (result: ISubmittableResult) => {
+ console.log(`Tx status: ${result.status}`)
+ if (result.isError) {
+ console.log(`Tx failed!`);
+ res(result)
+ }
+ if (result.isInBlock) {
+ console.log("Transaction in block, waiting for block finalization...")
+ }
+ if (result.isFinalized) {
+ console.log(`Tx finalized.`)
+ res(result)
+ }
+ })
+ });
}
-/**
- * Checks if the provided Merkle proof is valid by checking on Ethereum deployed validation contract.
- *
- * @param sepoliaApi Sepolia network api instance
- * @param blockNumber Avail block number
- * @param proof Merkle proof for the leaf
- * @param numberOfLeaves Number of leaves in the original tree
- * @param leafIndex Index of the leaf in the Merkle tree
- * @param leafHash Hash of the leaf in the Merkle tree
- * @returns {Promise<*>}
- */
-async function checkProof(
- sepoliaApi,
- blockNumber,
- proof,
- numberOfLeaves,
- leafIndex,
- leafHash,
-) {
- const abi = JSON.parse(
- readFileSync(process.env.VALIDIYM_ABI_PATH).toString(),
- );
- const verificationContract = new ethers.Contract(
- process.env.VALIDIUM_ADDRESS,
- abi,
- sepoliaApi,
- );
- return await verificationContract.checkDataRootMembership(
- BigInt(blockNumber),
- proof,
- BigInt(numberOfLeaves),
- BigInt(leafIndex),
- leafHash,
- );
+let result = await submitData(availApi, DATA, account);
+if (result.isFinalized) {
+ console.log(`DA transaction in finalized block: ${result.blockNumber}, transaction index: ${result.txIndex}`);
}
-(async function submitProof() {
- // connect to Sepolia through Infura but can be used any other available provider
- const sepoliaApi = new ethers.providers.InfuraProvider.getWebSocketProvider(
- 'sepolia',
- process.env.INFURA_KEY,
- );
- const availApi = await createApi(process.env.AVAIL_RPC);
-
- console.log(
- `Getting proof for transaction index ${process.env.TRANSACTION_INDEX} block number ${process.env.BLOCK_NUMBER} and block hash ${process.env.BLOCK_HASH}`,
- );
- const daHeader = await getProof(
- availApi,
- process.env.BLOCK_HASH,
- process.env.TRANSACTION_INDEX,
- );
-
- console.log(`Data Root: ${hexlify(daHeader.root)}`);
- console.log(`Proof: ${daHeader.proof}`);
- console.log(`Leaf to prove: ${hexlify(daHeader.leaf)}`);
- console.log(`Leaf index : ${daHeader.leafIndex}`);
- console.log(`Number of leaves: ${daHeader.numberOfLeaves}`);
-
- const isDataAccepted = await checkProof(
- sepoliaApi,
- process.env.BLOCK_NUMBER,
- daHeader.proof,
- daHeader.numberOfLeaves,
- daHeader.leafIndex,
- daHeader.leaf,
- );
- console.log('Data is: ' + (isDataAccepted ? 'available' : 'not available'));
- await availApi.disconnect();
- await sepoliaApi.destroy();
-})()
- .then(() => {
- console.log('Done');
- })
- .catch((err) => {
- console.error(err);
- process.exit(1);
- });
+// wait until the chain head on the Ethereum network is updated with the block range
+// in which the Avail DA transaction is included.
+while (true) {
+ let getHeadRsp = await fetch(BRIDGE_API_URL + "/avl/head");
+ if (getHeadRsp.status != 200) {
+ console.log("Something went wrong fetching the head.");
+ break;
+ }
+ let headRsp = await getHeadRsp.json();
+ let blockNumber: number = result.blockNumber.toNumber();
+ let lastCommittedBlock: number = headRsp.data.end;
+ if (lastCommittedBlock >= blockNumber) {
+ console.log("Fetching the blob proof.")
+ const proofResponse = await fetch(BRIDGE_API_URL + "/eth/proof/" + result.status.asFinalized + "?index=" + result.txIndex);
+ if (proofResponse.status != 200) {
+ console.log("Something went wrong fetching the proof.")
+ console.log(proofResponse)
+ break;
+ }
+ let proof: ProofData = await proofResponse.json();
+ console.log("Proof fetched:")
+ console.log(proof);
+ // call the deployed contract verification function with the inclusion proof.
+ const provider = new ethers.providers.JsonRpcProvider(ETH_PROVIDER_URL);
+ const contractInstance = new ethers.Contract(BRIDGE_ADDRESS, ABI, provider);
+ const isVerified = await contractInstance.verifyBlobLeaf([
+ proof.dataRootProof,
+ proof.leafProof,
+ proof.rangeHash,
+ proof.dataRootIndex,
+ proof.blobRoot,
+ proof.bridgeRoot,
+ proof.leaf,
+ proof.leafIndex]
+ );
+ console.log(`Blob validation is: ${isVerified}`)
+ break;
+ }
+
+ console.log("Waiting to bridge inclusion commitment. This can take a while...")
+ // wait for 1 minute to check again
+ await new Promise(f => setTimeout(f, 60*1000));
+}
+
+Deno.exit(0);
```
-
\ No newline at end of file
+