Repository: safe-global/safe-config-service

Issue:
Support for non-authenticated RPC urls
Currently the RPC url being used assumes that Infura is the provider. Under this assumption, the clients just append the Infura project ID to use that RPC url.

Given that there might be chains not available on Infura and that might not require authentication we can have two different types:

```javascript
GET /api/v1/chains/<chain-id>

{
  "rpcUri": {
    "type": <string>, // INFURA | OTHER
    "value": <url> 
  }
}
```

Other types can be added in the future.

cc/ @gnosis/safe-android @gnosis/safe-ios @gnosis/safe-web 

### Payload Update 1 https://github.com/gnosis/safe-config-service/issues/171#issuecomment-884099079


Discussion:
@mikheevm if the team is aligned on this, this might change your proposal on #169
So on clients, we agree that we try to use rpcUri as is (without appending `project id` or another secret key) for unknown types 

Resolving patch:
diff --git a/src/chains/migrations/0018_chain_rpc_authentication.py b/src/chains/migrations/0018_chain_rpc_authentication.py
new file mode 100644
--- /dev/null
+++ b/src/chains/migrations/0018_chain_rpc_authentication.py
@@ -0,0 +1,26 @@
+# Generated by Django 3.2.5 on 2021-07-21 12:24
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ("chains", "0017_alter_chain_block_explorer_uri"),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name="chain",
+            name="rpc_authentication",
+            field=models.CharField(
+                choices=[
+                    ("API_KEY_PATH", "Api Key Path"),
+                    ("NO_AUTHENTICATION", "No Authentication"),
+                ],
+                default="API_KEY_PATH",
+                max_length=255,
+            ),
+            preserve_default=False,
+        ),
+    ]
diff --git a/src/chains/models.py b/src/chains/models.py
--- a/src/chains/models.py
+++ b/src/chains/models.py
@@ -18,11 +18,18 @@
 
 
 class Chain(models.Model):
+    class RpcAuthentication(models.TextChoices):
+        API_KEY_PATH = "API_KEY_PATH"
+        NO_AUTHENTICATION = "NO_AUTHENTICATION"
+
     id = models.PositiveBigIntegerField(verbose_name="Chain Id", primary_key=True)
     relevance = models.SmallIntegerField(
         default=100
     )  # A lower number will indicate more relevance
     name = models.CharField(verbose_name="Chain name", max_length=255)
+    rpc_authentication = models.CharField(
+        max_length=255, choices=RpcAuthentication.choices
+    )
     rpc_uri = models.URLField()
     block_explorer_uri = models.URLField()
     currency_name = models.CharField(max_length=255)
diff --git a/src/chains/serializers.py b/src/chains/serializers.py
--- a/src/chains/serializers.py
+++ b/src/chains/serializers.py
@@ -32,9 +32,15 @@ class CurrencySerializer(serializers.Serializer):
     logo_uri = serializers.URLField(source="currency_logo_uri")
 
 
+class RpcUriSerializer(serializers.Serializer):
+    authentication = serializers.CharField(source="rpc_authentication")
+    value = serializers.URLField(source="rpc_uri")
+
+
 class ChainSerializer(serializers.ModelSerializer):
     chain_id = serializers.CharField(source="id")
     chain_name = serializers.CharField(source="name")
+    rpc_uri = serializers.SerializerMethodField()
     native_currency = serializers.SerializerMethodField()
     transaction_service = serializers.URLField(
         source="transaction_service_uri", default=None
@@ -68,6 +74,11 @@ def get_native_currency(obj):
     def get_theme(obj):
         return ThemeSerializer(obj).data
 
+    @staticmethod
+    @swagger_serializer_method(serializer_or_field=RpcUriSerializer)
+    def get_rpc_uri(obj):
+        return RpcUriSerializer(obj).data
+
     @staticmethod
     def get_gas_price(obj):
         if obj.gas_price_oracle_uri and obj.gas_price_fixed_wei is None:


Test patch:
diff --git a/src/chains/tests/factories.py b/src/chains/tests/factories.py
--- a/src/chains/tests/factories.py
+++ b/src/chains/tests/factories.py
@@ -1,3 +1,5 @@
+import random
+
 import factory
 import web3
 from factory.django import DjangoModelFactory
@@ -12,6 +14,9 @@ class Meta:
     id = factory.Sequence(lambda id: id)
     relevance = factory.Faker("pyint")
     name = factory.Faker("company")
+    rpc_authentication = factory.lazy_attribute(
+        lambda o: random.choice(list(Chain.RpcAuthentication))
+    )
     rpc_uri = factory.Faker("url")
     block_explorer_uri = factory.Faker("url")
     currency_name = factory.Faker("cryptocurrency_name")
diff --git a/src/chains/tests/test_views.py b/src/chains/tests/test_views.py
--- a/src/chains/tests/test_views.py
+++ b/src/chains/tests/test_views.py
@@ -27,7 +27,10 @@ def test_json_payload_format(self):
                 {
                     "chainId": str(chain.id),
                     "chainName": chain.name,
-                    "rpcUri": chain.rpc_uri,
+                    "rpcUri": {
+                        "authentication": chain.rpc_authentication,
+                        "value": chain.rpc_uri,
+                    },
                     "blockExplorerUri": chain.block_explorer_uri,
                     "nativeCurrency": {
                         "name": chain.currency_name,
@@ -118,7 +121,10 @@ def test_json_payload_format(self):
         json_response = {
             "chainId": str(chain.id),
             "chainName": chain.name,
-            "rpcUri": chain.rpc_uri,
+            "rpcUri": {
+                "authentication": chain.rpc_authentication,
+                "value": chain.rpc_uri,
+            },
             "blockExplorerUri": chain.block_explorer_uri,
             "nativeCurrency": {
                 "name": chain.currency_name,
@@ -158,7 +164,10 @@ def test_match(self):
         json_response = {
             "chain_id": str(chain.id),
             "chain_name": chain.name,
-            "rpc_uri": chain.rpc_uri,
+            "rpc_uri": {
+                "authentication": chain.rpc_authentication,
+                "value": chain.rpc_uri,
+            },
             "block_explorer_uri": chain.block_explorer_uri,
             "native_currency": {
                 "name": chain.currency_name,