serrastkirin: Hesabkirina pool account bi blake2 hash

- poolAccountIds fonksiyona API tune ne, ji ber vê hataye derket
- Niha pool account bi AccountIdConverter û blake2 hash tê hesabkirin
- PalletId "py/ascon" bi (u32, u32) poolId re tê hash kirin
- Ev guhertin hem ji bo AddLiquidityModal û hem jî PoolDashboard

Taybetmendî:
 Add liquidity niha bi rast dixebite
 Pool metrics rast têne xuyakirin
 Reserve balances rast têne hesabkirin
 LP position tracking çêbû

🤖 Bi [Claude Code](https://claude.com/claude-code) re hate çêkirin

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-11-02 23:48:44 +03:00
parent 8af6127e7e
commit 4839765aee
3 changed files with 57 additions and 37 deletions
+28 -18
View File
@@ -28,33 +28,43 @@ export const AddLiquidityModal: React.FC<AddLiquidityModalProps> = ({ isOpen, on
const fetchPoolPrice = async () => { const fetchPoolPrice = async () => {
try { try {
const poolId = [0, 1]; const asset1 = 0; // wHEZ
const asset2 = 1; // PEZ
const poolId = [asset1, asset2];
const poolInfo = await api.query.assetConversion.pools(poolId); const poolInfo = await api.query.assetConversion.pools(poolId);
if (poolInfo.isSome) { if (poolInfo.isSome) {
const lpTokenData = poolInfo.unwrap().toJSON() as any; // Derive pool account using AccountIdConverter
const lpTokenId = lpTokenData.lpToken; const { stringToU8a } = await import('@polkadot/util');
const { blake2AsU8a } = await import('@polkadot/util-crypto');
// Get pool account // PalletId for AssetConversion: "py/ascon" (8 bytes)
const poolAccountData = await api.query.assetConversion.poolAccountIds?.(poolId); const PALLET_ID = stringToU8a('py/ascon');
let poolAccount = '';
if (poolAccountData && poolAccountData.isSome) { // Create PoolId tuple (u32, u32)
poolAccount = poolAccountData.unwrap().toString(); const poolIdType = api.createType('(u32, u32)', [asset1, asset2]);
// Get reserves // Create (PalletId, PoolId) tuple: ([u8; 8], (u32, u32))
const whezBalanceData = await api.query.assets.account(0, poolAccount); const palletIdType = api.createType('[u8; 8]', PALLET_ID);
const pezBalanceData = await api.query.assets.account(1, poolAccount); const fullTuple = api.createType('([u8; 8], (u32, u32))', [palletIdType, poolIdType]);
if (whezBalanceData.isSome && pezBalanceData.isSome) { // Hash the SCALE-encoded tuple
const whezData = whezBalanceData.unwrap().toJSON() as any; const accountHash = blake2AsU8a(fullTuple.toU8a(), 256);
const pezData = pezBalanceData.unwrap().toJSON() as any; const poolAccountId = api.createType('AccountId32', accountHash);
const reserve0 = Number(whezData.balance) / 1e12; // Get reserves
const reserve1 = Number(pezData.balance) / 1e12; const whezBalanceData = await api.query.assets.account(asset1, poolAccountId);
const pezBalanceData = await api.query.assets.account(asset2, poolAccountId);
setCurrentPrice(reserve1 / reserve0); if (whezBalanceData.isSome && pezBalanceData.isSome) {
} const whezData = whezBalanceData.unwrap().toJSON() as any;
const pezData = pezBalanceData.unwrap().toJSON() as any;
const reserve0 = Number(whezData.balance) / 1e12;
const reserve1 = Number(pezData.balance) / 1e12;
setCurrentPrice(reserve1 / reserve0);
} }
} }
} catch (err) { } catch (err) {
+22 -9
View File
@@ -48,7 +48,9 @@ const PoolDashboard = () => {
try { try {
// Query wHEZ/PEZ pool // Query wHEZ/PEZ pool
const poolId = [0, 1]; // wHEZ (asset 0) / PEZ (asset 1) const asset1 = 0; // wHEZ
const asset2 = 1; // PEZ
const poolId = [asset1, asset2];
const poolInfo = await api.query.assetConversion.pools(poolId); const poolInfo = await api.query.assetConversion.pools(poolId);
@@ -56,17 +58,28 @@ const PoolDashboard = () => {
const lpTokenData = poolInfo.unwrap().toJSON() as any; const lpTokenData = poolInfo.unwrap().toJSON() as any;
const lpTokenId = lpTokenData.lpToken; const lpTokenId = lpTokenData.lpToken;
// Get pool account // Derive pool account using AccountIdConverter
const poolAccountData = await api.query.assetConversion.poolAccountIds?.(poolId); const { stringToU8a } = await import('@polkadot/util');
let poolAccount = ''; const { blake2AsU8a } = await import('@polkadot/util-crypto');
if (poolAccountData && poolAccountData.isSome) { // PalletId for AssetConversion: "py/ascon" (8 bytes)
poolAccount = poolAccountData.unwrap().toString(); const PALLET_ID = stringToU8a('py/ascon');
}
// Create PoolId tuple (u32, u32)
const poolIdType = api.createType('(u32, u32)', [asset1, asset2]);
// Create (PalletId, PoolId) tuple: ([u8; 8], (u32, u32))
const palletIdType = api.createType('[u8; 8]', PALLET_ID);
const fullTuple = api.createType('([u8; 8], (u32, u32))', [palletIdType, poolIdType]);
// Hash the SCALE-encoded tuple
const accountHash = blake2AsU8a(fullTuple.toU8a(), 256);
const poolAccountId = api.createType('AccountId32', accountHash);
const poolAccount = poolAccountId.toString();
// Get reserves // Get reserves
const whezBalanceData = await api.query.assets.account(0, poolAccount); const whezBalanceData = await api.query.assets.account(asset1, poolAccountId);
const pezBalanceData = await api.query.assets.account(1, poolAccount); const pezBalanceData = await api.query.assets.account(asset2, poolAccountId);
let reserve0 = 0; let reserve0 = 0;
let reserve1 = 0; let reserve1 = 0;
+7 -10
View File
@@ -485,10 +485,8 @@ const TokenSwap = () => {
if (fromToken === 'HEZ' && toToken === 'PEZ') { if (fromToken === 'HEZ' && toToken === 'PEZ') {
// HEZ → PEZ: wrap(HEZ→wHEZ) then swap(wHEZ→PEZ) // HEZ → PEZ: wrap(HEZ→wHEZ) then swap(wHEZ→PEZ)
const wrapTx = api.tx.tokenWrapper.wrap(amountIn.toString()); const wrapTx = api.tx.tokenWrapper.wrap(amountIn.toString());
const swapPath = [ // AssetKind = u32, so swap path is just [0, 1]
{ NativeOrAsset: { Asset: 0 } }, // wHEZ const swapPath = [0, 1]; // wHEZ → PEZ
{ NativeOrAsset: { Asset: 1 } } // PEZ
];
const swapTx = api.tx.assetConversion.swapExactTokensForTokens( const swapTx = api.tx.assetConversion.swapExactTokensForTokens(
swapPath, swapPath,
amountIn.toString(), amountIn.toString(),
@@ -500,10 +498,8 @@ const TokenSwap = () => {
} else if (fromToken === 'PEZ' && toToken === 'HEZ') { } else if (fromToken === 'PEZ' && toToken === 'HEZ') {
// PEZ → HEZ: swap(PEZ→wHEZ) then unwrap(wHEZ→HEZ) // PEZ → HEZ: swap(PEZ→wHEZ) then unwrap(wHEZ→HEZ)
const swapPath = [ // AssetKind = u32, so swap path is just [1, 0]
{ NativeOrAsset: { Asset: 1 } }, // PEZ const swapPath = [1, 0]; // PEZ → wHEZ
{ NativeOrAsset: { Asset: 0 } } // wHEZ
];
const swapTx = api.tx.assetConversion.swapExactTokensForTokens( const swapTx = api.tx.assetConversion.swapExactTokensForTokens(
swapPath, swapPath,
amountIn.toString(), amountIn.toString(),
@@ -521,9 +517,10 @@ const TokenSwap = () => {
return ASSET_IDS[token as keyof typeof ASSET_IDS]; return ASSET_IDS[token as keyof typeof ASSET_IDS];
}; };
// AssetKind = u32, so swap path is just [assetId1, assetId2]
const swapPath = [ const swapPath = [
{ NativeOrAsset: { Asset: getPoolAssetId(fromToken) } }, getPoolAssetId(fromToken),
{ NativeOrAsset: { Asset: getPoolAssetId(toToken) } } getPoolAssetId(toToken)
]; ];
tx = api.tx.assetConversion.swapExactTokensForTokens( tx = api.tx.assetConversion.swapExactTokensForTokens(