---
# System prepended metadata

title: Asset Listing Implementation Design

---

Asset Listing Implementation Design
=====

<style>.markdown-body { max-width: 1500px; }</style>

Sequence diagram
----

```mermaid
sequenceDiagram
    title: Asset Listing
    #-------
    actor MarketplaceOwner
    actor AssetProvider
    actor Sponsor
    # actor Buyer
    #-------
    participant Blockchain
    participant MKPContract
    participant ISaleStrategy
    # participant SDK
    participant TimeOracle

    note left of MKPContract: B2B
    MarketplaceOwner-)Blockchain: deploy ISaleStrategy contract
    MarketplaceOwner->>MKPContract: whitelist ISaleStrategy

    note left of MKPContract: B2C
    note over MKPContract: req: Asset is in Asset Registered state
    AssetProvider-)MKPContract: list asset for sale
    ## Asset check
    MKPContract->>MKPContract: get Asset
    MKPContract->>MKPContract: verify AssetState
    alt Asset not found
         MKPContract--)AssetProvider: reject
    end
    alt Asset not in AssetRegistered state
         MKPContract--)AssetProvider: reject
    end
    MKPContract->>MKPContract: verify asset owner
    alt Asset not owned by caller
         MKPContract--)AssetProvider: reject
    end
    
    
    alt Asset has sponsor
        MKPContract-)Sponsor: get sponsorship
        Sponsor--)MKPContract: fee %
    end
    
    ## Listing check
    MKPContract->>MKPContract: verify ListingState
    alt Listing not in InitialState state
         MKPContract-->>AssetProvider: reject
    end
        
    ## Sale Strategy check    
    MKPContract->>MKPContract: verify ISaleStrategy is whitelisted
    alt ISaleStrategy not whitelisted
         MKPContract-->>AssetProvider: reject
    end
    MKPContract->>ISaleStrategy: verify parameters (price, currency, etc.)
    alt Listing not compatible with ISaleStrategy
         ISaleStrategy-->>AssetProvider: reject
    end
    
    ## Asset Transfer
    MKPContract->>MKPContract: transfer token to MKPContract
    alt transfer not allowed
        MKPContract--)AssetProvider: reject
    end
    
    alt sponsorship request
        MKPContract-)Sponsor: request sponsorship
        alt approved
            Sponsor--)MKPContract: activateListing
            
                alt has pending activation
                MKPContract->>MKPContract: set state to PendingActivation
            end
        end

        alt rejected
            MKPContract->>MKPContract: set statet to ListingRegistered
        end
    end
    
    MKPContract->>MKPContract: calculate fee (marketplace + sponsor)
    
    ## State change
    MKPContract->>MKPContract: check startTime <= time now
    MKPContract->>MKPContract: activateListing (set state to ListingActive)
    
    alt timed activation (start time > time now)
        MKPContract-)TimeOracle: set execution of activateListing
        TimeOracle--)MKPContract: activateListing
        
        alt is in pending sponsorship state
            TimeOracle--)MKPContract: set isPreactevated = true
        end
    end
```

Class diagram
----

```mermaid
classDiagram
    
    class AssetState {
        <<enum>> 
        InitialState
        PendingValidation
        ReadyToRegister
        AssetInvalidated
        AssetRegistered
        PendingSponsorship
    }
    
    class ListingState {
        <<enum>>
        InitialState
        ListingCreated
        PendinActivation
        ListingActive
        PendingPurchase
    }
    
    class AssetValidationRecord{
        <<struct>>
        address validator
        address deletage
        bool approved
    }
    
    class Fee {
        <<struct>>
        uint8 percentage
        uint256 setAmount
    }
    
    class ISaleStrategy {
        <<interface>>
        +verifySaleParams(uiun256 price, bytes32 endBy)
    }
    
    class Listing {
        <<struct>>
        ISaleStrategy saleStrategy
        ListingState state
        bytes32 assetId
        addres->Fee fees
        address => uint256 currencyToPrice ?
        uint256 priceFiat ?
    }
    
    class Asset {
        <<struct>>
        AssetValidationRecord[] validatorHistory
        AssetState state
        bytes32 subdomain
        address assetContract
        uint256 assetId
        ISponsor sponsor
    }

    class AssetManagement {
        <<abstract>>
        -uint256 assetCount
        -address->uint256->bytes32 tokenToTokenIdToAssetId
        -bytes32->Asset assetById
        -uint256 listingCount
        -bytes32->Listing listingIdToListing
        +registerAsset(address tokenAddr, uint256 tokenId, bytes32 assetId)
        +listAsset(bytes32 assetId, uint256 price)
        +renewListing(uint256 listingId)
        +getAssetById(bytes32 assetId): Asset
        +getAssetByToken(address tokenAddr, uint256 tokenId): Asset
        +getLisingById()
        
    }
    
    AssetState --* Asset
    AssetValidationRecord --o Asset
    
    ListingState --* Listing
    
    Asset o--AssetManagement
    Listing o-- AssetManagement
    Listing *-- Fee
    Listing *-- ISaleStrategy
    
```



Example code for creating new asset and new listing
----
```solidity=
class AssettManager {
    registerAsset(address tokenAddr, uint256 tokenId, assetId) {
        ...
        ...
        bytes32 existingId = assetId == 0x0
            ? tokenToTokenIdToAssetId[tokenAddr, tokenId]
            : assetId;
        
        bytes32 assetId = existingId == 0x0
            ? keccak256(abi.encodePacked(tokenAddr, tokenId))
            : existingId;
        Asset asset = assetById[assetId];
        asset.name = name;
        ...
    }
    
    listAsset(bytes32 assetId, uint256 price) {
        ...
        ...
        Asset asset = assetById[assetId];
        require(asset.state == AssetState.AssetRegistered);
        bytes32 listingId = keccak256(abi.encodePacked(asset, price)); // the asset might need unpacking first
        
        listing = listingIdToListing[listingId];
        listing.price = price;
        listing.assetId = assetId;
        listing.stategy = strategy;
        ...
        emit ListingCreated(...);
        ...
    }
}
```

State Flow Diagram
----

```mermaid
stateDiagram-v2
    direction LR
    [*] --> InitialState
    InitialState --> ListingCreated: listAsset
    ListingCreated --> PendingSponsorship: requestSponsorship
    ListingCreated --> ListingActive: activateListing
    PendingSponsorship --> ListingCreated: rejectSponsorship
    state timed_fork <<choice>>
    PendingSponsorship --> timed_fork: approveSponsorship
    PendingSponsorship --> PendingSponsorship: activateListing
    timed_fork --> ListingActive: isPreactivated
    timed_fork --> PendingActivation: !isPreactivated
    
    
    ListingCreated --> PendingActivation: setActivationTimeout
    PendingActivation --> ListingActive: activateListing
    PendingActivation --> PendingSponsorship: requestSponsorship
        
    ListingActive --> ListingCreated: deactivateListing
    ListingActive --> InitialState: removeListing
    
    ListingActive --> PendingPurchase: lockListingForPurchase
    PendingPurchase --> InitialState: removeListing
    
    ListingActive --> ListingActive: changeBasePrice
    ListingActive --> ListingActive: changeExpiration
    
```

```
Scene 1: Asset Registration with sponsorship
    1. @requestSponsorship { Asset:InitialState -> Asset:PendingSponsorship }
    2. @rejectSponsorship { Asset:PendingSponsorship -> Asset:SponsorshipRejected }
    2. @approveSponsorship { Asset:PendingSponsorship -> Asset:Active }
    no listing change
    
Scene 2: requesting sponsorship only when Asset::Active 
    1. @requestSponsorship { Asset::Active -> Asset:PendingSponsorship }
    2. @rejectSponsorship { Asset:PendingSponsorship -> Asset:SponsorshipRejected }
    2. @approveSponsorship { Asset:PendingSponsorship -> Asset:Active }
    no listing change
    
    
Scene 3: Listing Creation with sponsorship, instant
    1. @requestSponsorship { 
        Asset::InitialState -> Asset::PendingSponsorship,
        Listing::InitialState -> Listing::PendingActivation
    }
    2. @rejectSponsorship { 
        Asset::PendingSponsorship -> Asset::SponsorshipRejected,
        Listing::PendingActivation -> Listing::InitialState
    }
    3. @approveSponsorship { 
        Asset::PendingSponsorship -> Asset::Active,
        Listing::PendingActivation -> Listing::Active
    }

Scene 4: Listing Creation with sponsorship, timed
    1. @requestSponsorship { 
        Asset::InitialState -> Asset::PendingSponsorship,
        Listing::InitialState -> Listing::PendingActivation
    }
    a: response.time < activation.time
        2a. @rejectSponsorship { 
            Asset::PendingSponsorship -> Asset::SponsorshipRejected,
            Listing::PendingActivation -> Listing::InitialState
        }
        3a. @approveSponsorship { 
            Asset::PendingSponsorship -> Asset::Active,
            Listing::PendingActivation -> Listing::Active
        }
        
    b: response.time < activation.time
        2b. @rejectSponsorship { 
            Asset::PendingSponsorship -> Asset::SponsorshipRejected,
            Listing::PendingActivation -> Listing::InitialState
        }
        3b. @approveSponsorship { 
            Asset::PendingSponsorship -> Asset::Active,
            Listing::PendingActivation -> Listing::Active
        }
Scene 5: requesting sponsorship only when Lising::Active 
    1. @requestSponsorship  --> Scene 3
```

The feature/flow in question has two parts, but basically bois down to requesting a sponsorship after an asset has been registered.
That is, the ability to request sponsorship
1. when an asset has been registered
2. as a part of the process that creates a listing 
4. when listing is created, but pending activation
5. when listing is active 



```mermaid
 stateDiagram-v2
    direction LR
    [*] --> Asset
    [*] --> Listing
    state Asset {
        [*] --> AssetInitial
        AssetInitial --> PendingSponsorship: requestSponsorship
        PendingSponsorship --> AssetActive: approveSponsorship
        PendingSponsorship --> SponsorshipRejected: rejectSponsorship



 AssetActive --> PendingSponsorship: requestSponsorship
        SponsorshipRejected --> PendingSponsorship: requestSponsorship
    }
    
   state Listing {
        [*] --> ListingInitial
        
        
        ListingInitial --> PendingActivation: requestSponsorship
        AssetActive --> PendingSponsorship: requestSponsorship
        
       PendingActivation --> rejectSponsorship: rejectSponsorship
        PendingActivation --> rejectSponsorship: rejectSponsorship
        
        
 }
```