We just opened a PR about XCQ RFC. Feedback is welcome!
PVQ Status Report
Summary
- Rename project from
XCQ
toPVQ
- Refactor PVQ extension system
- Refactor PVQ program macros
- XCM Intergration PoC
Example Usage
- PVQ Extensions Definitions: Example
- Use
pvq-program
macros to write a guest program. Example - PVQ Extensions Implementation: Example
Run Examples
Available PoC PVQ examples:
guest-sum-balance
: sum the balances of multiple accountsguest-total-supply
: get the total supply of an assetguest-sum-balance-percent
: sum the balances of multiple accounts and calculate the percentage of the total supply
- Build guest program:
make guests
- Run test runner:
cargo run -p pvq-test-runner -- --program output/<guest-program>
guest-examples
contains several guest programs to test the PVQ.
XCM Integration PoC
The test case of XCM integration is located in vendor/polkadot-sdk/polkadot/xcm/xcm-simulator/example/src/tests.rs
#[test]
fn test_report_query() {
...
}
We are happy to share the recent progress of PVQ:
PVQ Frontend SDK
We have created a TypeScript SDK for interacting with PolkaVM Query(PVQ) enabled chains.
In summary, the SDK supports the following use cases:
- Create a PVQ program instance by providing the guest program and corresponding metadata files.
- List queryable entrypoints by accessing the metadata.
- Check if the guest program is compatible with the chain’s supported extensions.
For more details, please refer to the github repo.
PVQ Frontend Demo
And we also created a demo to demonstrate the usage of PVQ-SDK.
In this demo, you can interact with a PoC runtime that implements the core
and fungibles
extensions.
- Clone the PVQ repository.
- Install bun.
- Run
make tools
to install the required tools. - Run
make run
to start the local PoC runtime. - Run
make guests
to build the PVQ programs and generate their metadata. - Open the demo in your browser.
- Enter the custom endpoint shown in Step 4 and connect to the chain.
- Upload a PVQ program, such as
guest-sum-balance
, along with the corresponding metadata JSON file,guest-sum-balance-metadata.json
.
- Select the program; the program bytecode and metadata should be displayed in the UI.
- Switch to the
Query
tab, input the query argument, and execute the query to get the result. In the following example, we query the sum of the balances of asset21
for two accounts:Alice
andBob
.
Ongoing Works
We are targeting to the first release of the PVQ as well as demonstrating a more decent Demo to show how PVQ works with different chains.
We’ve built a simple swap demo showcases how PVQ can facilitate the development of multi-chain Dapps. It has the following core functions:
-
List Liquidity Pools: Displays the available token pair pools on the selected chain.
-
Get Pool Reserves: Shows the current liquidity reserves for a selected pool.
-
Get Swap Price: Show price quote for swapping a specific amount of one token for another.
The main takeaway is that the demo works seamlessly with both Acala and AssetHub, using the exact same front-end logic despite the DEX implementations on these chains being entirely different:
-
Acala: Uses its own custom
module-dex
pallet. -
AssetHub: Uses the
AssetConversion
pallet.
How It Works
Front-end side
From the client’s perspective, the process is simple:
-
Check for Extension: The UI first checks if the connected chain (Acala or AssetHub) implements the
swap
extension. -
Construct PVQ program query arguments: If the extension is available, the UI constructs its query with the required arguments (e.g., token pair, amount to swap).
-
Call PVQ program Entrypoints: The UI sends the query to the entrypoints of the PVQ program.
The front-end code is completely agnostic of whether it’s talking to Acala’s DEX pallet or AssetHub’s AssetConversion pallet.
Runtime side
The heavy lifting is done at the runtime side, which is tailored for each chain. We implement swap extension on both Acala and AssetHub, which exposes five extension functions: quote_price_tokens_for_exact_tokens
, quote_price_exact_tokens_for_tokens
, get_liquidity_pool
, list_pools
, asset_info
, assets_info
.
PVQ Program
For the corresponding PVQ program, it only has four entrypoints. This is by design and demonstrates one of PVQ’s most powerful features: the ability to perform custom computations in PVQ program.
For example, the list_pools
entrypoint is actually a composition of extension functions list_pools
and assets_info
:
#[program::entrypoint]
fn entrypoint_list_pools() -> Vec<(AssetInfo, AssetInfo)> {
let pools = list_pools();
let mut result = Vec::new();
let assets_info = assets_info();
for pool in pools {
let asset1_info = assets_info.get(&pool.0).cloned();
let asset2_info = assets_info.get(&pool.1).cloned();
if let (Some(a1), Some(a2)) = (asset1_info, asset2_info) {
result.push((a1, a2));
}
}
result
}
Key Advancement
This demo is a concrete validation of the PVQ vision. We have successfully created a unified, high-level interface for a non-trivial operation (DEX interactions) across two parachains with fundamentally different runtime implementations.
For dApp developers:
-
Reduced Complexity: No need to learn the low-level details of every parachain’s pallets.
-
Faster Development: Write code once and deploy it across multiple chains.
-
Easy Extensibility: As more chains adopt the PVQ swap extension, they will instantly work with existing UIs without requiring any front-end updates.
This advancement is a crucial step toward a more cohesive and developer-friendly Polkadot ecosystem.
Next Steps
We are targeting the first release of the PVQ and integrating it into the polkadot-sdk
.
We welcome feedback, questions, and collaboration from the community. Please feel free to check out the demo and share your thoughts below.
Thank you!