dao icon indicating copy to clipboard operation
dao copied to clipboard

Terminus webapp server side spec

Open peersky opened this issue 4 years ago • 2 comments

Terminus whitelist server side should allow us to

  1. Save up blockchain state space by indexing additional state information trough our nodes
  2. Allow our customers to enchase blockchain state with their additional information

Proposed specification:

data classes:

class TerminusContracts(BaseModel):
    resource_id: uuid 
    contract_address: str
    pools: List[uuid] #I suspect this is how foreign key should work, but how does it scales if this list is veeeery long?  

class TerminusContractsListResponse(BaseModel):
   contracts: List[TerminusContracts] = Field(default_factory=list)


class TerminusPool(BaseModel):
     resource_id: uuid
     identities: List[uuid]  #To paginate probably must migrate in to new /TerminusPoolIdentities/ paginated resource?

class TerminusIdentity(BaseModel):
     resource_id: uuid
     address: str

endpoints:

GET /terminus/${DiamondAddress} -> (TerminusContract)
GET /terminus/${DiamondAddress}/pools/${poolId} -> (TerminusPool)
GET /terminus/${DiamondAddress}/pools/${poolId}/refresh -> (TerminusPool)
GET /terminus/${DiamondAddress}/pools/${poolId}/${address} -> (TerminusIdentity)

API logic:

GET /terminus/${DiamondAddress} -> (TerminusContract):

 terminus_contract_resource_id: BugoutResource = bc.list_resources(
                params = { "contract_address": DiamondAddress }
            )[0]
 terminus_resource = bc.get_resource( resource_id = terminus_contract_resource_id)

1. Update resource from web3 provider
2. Return resource

Case if terminus_contract not found:
Check web3 -> if contract exists and payment service conditions are met - create resource and set up crawler
GET /terminus/${DiamondAddress}/pools/${poolId} -> (TerminusPool): 
terminus_pool: BugoutResource = bc.get_resource(
                resource_id=terminus_contract[poolId],
            )
1. Update resource from web3 provider
2. Return resource

Case if resource not found: 
If payment service conditions are met - create resource and set up crawler.
  For each address found in crawler:
     add TerminusIdentity. 
GET /terminus/${DiamondAddress}/pools/${poolId}/${address} -> (TerminusIdentity)
terminus_pool_resource: BugoutResource = bc.get_resource(
                resource_id=terminus_pool.identities[],
            )
if address in terminus_pool_resource.identities
    terminus_identity_resource: BugoutResource = bc.get_resource(
                resource_id=address,
            )
    terminus_identity_record_resource: BugoutResource = bc.get_pool_resource(
                resource_id=web3.sha(DiamondAddress + poolId + address),
            )

peersky avatar Feb 28 '22 15:02 peersky

@peersky: Wanted to put in writing what we discussed verbally in earlier meeting.

ID fields

Better for ID fields to have no semantic connection with the data they describe. If we used the hashing scheme that you were initially considering, for example, it could cause problems if we migrated from a contract at one address to another. This is just one reason to not put semantic information in ID.

There are situations in which we might want to put semantic information in primary key, but at this point it would bring more headaches than we need.

Simple data model

Better to make a simple, composable data model for now and we can add additional functionality (like KYC) later. Invariably, if we put too much stuff in the data model compared to the functionality we want to offer on day 1, most of it will become obsolete as soon as we release. Even worse, it might become an obstacle to rapid development of the data model when we do want to make the correct changes.

I suggest we create the following types of resources:

Customer

Contains the following information

  1. id - primary key we use to refer to customer in DB
  2. name - name of customer
  3. notes - human-readable/writeable notes about customer

This data should only be visible to Terminus admins (anyone who has appropriate token on the Moonstream Terminus contract).

Contract

Contains the following information:

  1. id - primary key we use to refer to contract in DB
  2. blockchain - chain which Terminus contract is deployed
  3. address - address of the contract on that blockchain
  4. customer_id - foreign key to Customer.id
  5. controller - address of Terminus controller
  6. name - human friendly name for contract
  7. notes - human friendly notes about contract

customer_id only visible to admins

name, notes only visible to admins and Terminus controller

Pool

Contains the following information:

  1. id - primary key
  2. contract_id - foreign key to Contract.id
  3. pool_number - ID of pool on Terminus contract (uint256)
  4. capacity - capacity of pool
  5. is_transferable - true/false depending on whether pool is transferable
  6. is_burnable - true/false depending on whether pool is burnable
  7. pool_controller - address of pool controller
  8. name - human friendly name for pool
  9. notes - notes about pool

name, notes only visible to admins and Terminus controller

PoolAuthorization

Contains the following information:

  1. id - primary key
  2. pool_id - foreign key into Pool.id
  3. address - authorized address for pool

PoolOwner

Contains the following information:

  1. id - primary key
  2. pool_id - foreign key into Pool.id
  3. address - address of token owner
  4. num_tokens - number of tokens they own

AddressAnnotation

Contains the following information:

  1. address
  2. annotator - address of account that created annotation
  3. name - name for address
  4. notes - notes for address

Each resource is only visible to its annotator.

zomglings avatar Mar 01 '22 07:03 zomglings

Better for ID fields to have no semantic connection with the data they describe. If we used the hashing scheme that you were initially considering, for example, it could cause problems if we migrated from a contract at one address to another. This is just one reason to not put semantic information in ID.

@zomglings
I like idea with Contract objects. I think we should treat Contract as blockchain specific object, not a Diamond/Terminus specific.
Assuming Contract is blockchain property - such hashing scheme would just represent blockchain state more precise: Contract.address is immutable property in it's blockchain nature.

This semantic connection would allow to avoid potential bugs that might occur if there occurs mismatch of env in frontend and address stored in Contract.address (failed migration, did not update field correctly, wrong branch etc).

I have feeling that the more we work with blockchain, the more it will make sense for us to use such scheme.

My concern is here that Im not aware how this can impact performance of db, I want to run benchmark after implementation to compare db access speed for approach when we hash on frontend and access by hash and selected for now approach when we do

  1. ListResources matching criteria
  2. Access resource[0] of ^^^

peersky avatar Mar 01 '22 12:03 peersky