sqrtPriceX96 is represented as token1 over token0 or rather how much token1 is needed for 1 token0.
Because solidity uses fixed point numbers there are no decimal places used.
This is a must read on the topic https://uniswap.org/blog/uniswap-v3-math-primer.
Token 1 is determined by which token contract address base16 value is greater.
For example WETH/USDC on Ethereum https://etherscan.io/address/0x8ad599c3a0ff1de082011efddc58f1908eb6e6d8
>>> 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2 > 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48
True
WETH has 18 decimals of precision, USDC has 6.
Price is reported in the slot0 call avaialble on all Uniswap V3 pools.
[ slot0 method Response ]
sqrtPriceX96 uint160 : 1837769053120899173775504701779545
In solidity to get price you would do
FullMath.mulDiv(
uint256(_sqrtRatioX96) * uint256(_sqrtRatioX96),
10 ** _decimal0,
1 << 192
);
In nodejs you would do
const returnPrice = async (poolContract, decimals0) => {
const sqrtPriceX96 = (await poolContract.slot0())[0];
return sqrtPriceX96
.pow(BigNumber.from("2"))
.mul(BigNumber.from("10").pow(decimals0))
.div(BigNumber.from("2").pow(BigNumber.from("192")));
};
In python you would do
one_token0 = round(decimal.Decimal(sqrtPriceX96 * sqrtPriceX96 * ((10**decimal_token0) / (10**decimal_token1)) / (2 ** 192)), decimal_token1)
Also there are some helpful documents in the Discord if you haven't met the wonderful Rachel.
Example
>>> one_token0 = round(decimal.Decimal(sqrtPriceX96 * sqrtPriceX96 * ((10**6) / (10**18)) / (2 ** 192)), 18)
>>> one_token0
Decimal('0.000538050080273366') # how much WETH for 1 USDC
>>> one_token1 = 1 / one_token0
>>> one_token1
Decimal('1858.563053260640816896359652') # how much USDC for 1 WETH
The first returned value is in 18 decimal precision. Gwei you would multiple by 1e9 and Wei you would multiply by 1e18.
I'm not sure your sqrtPrice is correct. Here I pull the WETH-DAI 5 bips pool (both tokens are 18 decimals of precision as you note). https://etherscan.io/address/0x60594a405d53811d3bc4766596efd80fd545a270#readContract.
[ slot0 method Response ]
sqrtPriceX96 uint160 : 1837867657081239291626318498
>>> one_token0 = round(decimal.Decimal(sqrtPriceX96 * sqrtPriceX96 * ((10**18) / (10**18))
/ (2 ** 192)), 18)
>>> one_token0
Decimal('0.000538107819075710')
>>> one_token1
Decimal('1858.363630020591262902910979')
If things still don't make sense let me know.