---
# System prepended metadata

title: SDK Interfaces Design

---

# SDK Interfaces Design

## IMarketplace

### Administrator

*(notes): Consider using get/set nomenclature*

## Proposal 1

```typescript=


interface IAccessControl {
    addAdministrator(address: string) : Promise<boolean>;
    removeAdministrator(address: string) : Promise<boolean>;
    addAssetManager(address : string) : Promise<boolean>;
    removeAssetManager(address : string) : Promise<boolean>;
    addAssetValidatorManager(address: string) : Promise<boolean>;
    removeAssetValidatorManager(address : string) : Promise<boolean>;
    addAssetValidator(address: string) : Promise<boolean>;
    removeAssetValidator(address: string) : Promise<boolean>;
    addFinance(address: string) : Promise<boolean>;
    removeFinance(address: string) : Promise<boolean>;
    addFinanceManager(address: string) : Promise<boolean>;
    removeFinanceManager(address: string) : Promise<boolean>;
    addAssetProviderManager(address: string) : Promise<boolean>;
    removeAssetProviderManager(address: string) : Promise<boolean>;
    addAssetProvider(address: string) : Promise<boolean>;
    removeAssetProvider(address: string) : Promise<boolean>;
}

/* Probably we need to segregate interfaces here */
interface IMarketplace {
    changeRequireWhitelistedAsset(requireWhitelistedAsset: boolean) : Promise<boolean>;
    changeRequireWhitelistedAssetProvider(requireWhitelistedAssetProvider: boolean) : Promise<boolean>;
    changeRequireAssetValidation(requireAssetValidation: boolean) : Promise<boolean>;
    changeRequireSaleStrategyPerAsset(requireSaleStrategyPerAsset: boolean) : Promise<boolean>;
    changeRequireSameCurrencyPerAsset(requireSameCurrencyPerAsset: boolean) : Promise<boolean>;
    changeRequireAssetSubdomain(requireAssetSubdomain: boolean) : Promise<boolean>;
    changeSupportsStakingSlashing(supportStakingSlashing: boolean) : Promise<boolean>;

    whitelistAsset(address: string) : Promise<boolean>;
    removeAssetFromWhitelist(address: string) : Promise<boolean>;
    isWhitelistedAsset(address: string) : Promise<boolean>;

    addAcceptedCurrency(tokenERC20: string) : Promise<boolean>;
    removeAcceptedCurrency(tokenERC20: string) : Promise<boolean>;
    withdraw(to: string, amount: number) : Promise<boolean>;

    addAssetValidatorDelegate(account: string) : Promise<boolean>;
    removeAssetValidatorDelegate(account: string) : Promise<boolean>;

    assignRnsDomain(rnsDomainNode: string) : Promise<boolean>;
    assignRnsNameGenerationStrategy(strategy: string) : Promise<boolean>;

    //registerAsset(Asset _asset) external;
    validatorDelegateApprovesAsset(assetValidator: string, asset: string) : Promise<boolean>;
    validatorDelegateRejectAsset(assetValidator: string, asset: string): Promise<boolean>;
    assignOrderIdGeneratorStrategy(strategy: string) : Promise<boolean>;
    sellAsset(asset: string) : Promise<boolean>;
}

interface IWhitelist {
    add(address: string) : Promise<boolean>;
    remove(address: string) : Promise<boolean>;
    isWhitelisted(address: string) : Promise<boolean>;
}

class AssetWhitelist implements IWhitelist {
    add(address: string) : Promise<boolean> {
        // TODO: Implement method
        return Promise.resolve(true);
    }
    remove(address: string) : Promise<boolean> {
        // TODO: Implement method
        return Promise.resolve(true);
    }
    isWhitelisted(address: string) : Promise<boolean> {
        // TODO: Implement method
        return Promise.resolve(true);
    }
}

/* We need to work on the interfaces for the smart contract interaction
   Hint: Look into legacy marketplace-ui contract
     - https://github.com/rsksmart/rif-marketplace-ui/blob/develop/src/contracts/wrappers/contract-base.ts
 */

abstract class ContractWrapper { }

class MarketplaceContractWrapper extends ContractWrapper {
    constructor () {
        super();
    }
}

/* TODO : Add Asset Validator Delegate | RNS parts */
class Marketplace implements IMarketplace, IAccessControl {
    private requireWhitelistedAsset! : boolean;
    private requireWhitelistedAssetProvider! : boolean;
    private requireAssetValidation! : boolean;
    private requireSaleStrategyPerAsset! : boolean;
    private requireSameCurrencyPerAsset! : boolean;
    private requireAssetSubdomain! : boolean;
    private supportsStakingSlashing! : boolean;
    private assetWhitelist! : AssetWhitelist;
    private contractWrapper : MarketplaceContractWrapper; // library to interact with contract (ethers);

    [index: string] : any;

    constructor (config: any = { }) {
        Object.keys(config).forEach((key: string) => this[key] = config[key]);
        this.assetWhitelist = new AssetWhitelist();
        this.contractWrapper = new MarketplaceContractWrapper();
    }

    whitelistAsset(address: string) : Promise<boolean> {
        return this.assetWhitelist.add(address);
    }
    removeAssetFromWhitelist(address: string) : Promise<boolean> {
        return this.assetWhitelist.remove(address);
    }
    isWhitelistedAsset(address: string) : Promise<boolean> {
        return this.assetWhitelist.isWhitelisted(address);
    }

    changeRequireWhitelistedAsset(requireWhitelistedAsset: boolean): Promise<boolean> {
        // TODO: Implement method
        return Promise.resolve(true);
    }
    changeRequireWhitelistedAssetProvider(requireWhitelistedAssetProvider: boolean) : Promise<boolean> {
        // TODO: Implement method
        return Promise.resolve(true);
    }
    changeRequireAssetValidation(requireAssetValidation: boolean) : Promise<boolean> {
        // TODO: Implement method
        return Promise.resolve(true);
    }
    changeRequireSaleStrategyPerAsset(requireSaleStrategyPerAsset: boolean) : Promise<boolean> {
        // TODO: Implement method
        return Promise.resolve(true);
    }
    changeRequireSameCurrencyPerAsset(requireSameCurrencyPerAsset: boolean) : Promise<boolean> {
        // TODO: Implement method
        return Promise.resolve(true);
    }
    changeRequireAssetSubdomain(requireAssetSubdomain: boolean) : Promise<boolean> {
        // TODO: Implement method
        return Promise.resolve(true);
    }
    changeSupportsStakingSlashing(supportStakingSlashing: boolean) : Promise<boolean> {
        // TODO: Implement method
        return Promise.resolve(true);
    }

    addAdministrator(address: string) : Promise<boolean> {
        // TODO: Implement method
        return Promise.resolve(true);
    }
    removeAdministrator(address: string) : Promise<boolean> {
        // TODO: Implement method
        return Promise.resolve(true);
    }
    addAssetManager(address : string) : Promise<boolean> {
        // TODO: Implement method
        return Promise.resolve(true);
    }
    removeAssetManager(address : string) : Promise<boolean> {
        // TODO: Implement method
        return Promise.resolve(true);
    }
    addAssetValidatorManager(address: string) : Promise<boolean> {
        // TODO: Implement method
        return Promise.resolve(true);
    }
    removeAssetValidatorManager(address : string) : Promise<boolean> {
        // TODO: Implement method
        return Promise.resolve(true);
    }
    addAssetValidator(address: string) : Promise<boolean> {
        // TODO: Implement method
        return Promise.resolve(true);
    }
    removeAssetValidator(address: string) : Promise<boolean> {
        // TODO: Implement method
        return Promise.resolve(true);
    }
    addFinance(address: string) : Promise<boolean> {
        // TODO: Implement method
        return Promise.resolve(true);
    }
    removeFinance(address: string) : Promise<boolean> {
        // TODO: Implement method
        return Promise.resolve(true);
    }
    addFinanceManager(address: string) : Promise<boolean> {
        // TODO: Implement method
        return Promise.resolve(true);
    }
    removeFinanceManager(address: string) : Promise<boolean> {
        // TODO: Implement method
        return Promise.resolve(true);
    }
    addAssetProviderManager(address: string) : Promise<boolean> {
        // TODO: Implement method
        return Promise.resolve(true);
    }
    removeAssetProviderManager(address: string) : Promise<boolean> {
        // TODO: Implement method
        return Promise.resolve(true);
    }
    addAssetProvider(address: string) : Promise<boolean> {
        // TODO: Implement method
        return Promise.resolve(true);
    }
    removeAssetProvider(address: string) : Promise<boolean> {
        // TODO: Implement method
        return Promise.resolve(true);
    }

    addAcceptedCurrency(tokenERC20: string) : Promise<boolean> {
        // TODO: Implement method
        return Promise.resolve(true);
    }
    removeAcceptedCurrency(tokenERC20: string) : Promise<boolean> {
        // TODO: Implement method
        return Promise.resolve(true);
    }
    withdraw(to: string, amount: number) : Promise<boolean> {
        // TODO: Implement method
        return Promise.resolve(true);
    }
    addAssetValidatorDelegate(account: string) : Promise<boolean> {
        // TODO: Implement method
        return Promise.resolve(true);
    }
    removeAssetValidatorDelegate(account: string) : Promise<boolean> {
        // TODO: Implement method
        return Promise.resolve(true);
    }
    assignRnsDomain(rnsDomainNode: string) : Promise<boolean> {
        // TODO: Implement method
        return Promise.resolve(true);
    }
    assignRnsNameGenerationStrategy(strategy: string) : Promise<boolean> {
        // TODO: Implement method
        return Promise.resolve(true);
    }
    //registerAsset(Asset _asset) external;
    validatorDelegateApprovesAsset(assetValidator: string, asset: string) : Promise<boolean> {
        // TODO: Implement method
        return Promise.resolve(true);
    }
    validatorDelegateRejectAsset(assetValidator: string, asset: string): Promise<boolean> {
        // TODO: Implement method
        return Promise.resolve(true);
    }
    assignOrderIdGeneratorStrategy(strategy: string) : Promise<boolean> {
        // TODO: Implement method
        return Promise.resolve(true);
    }
    sellAsset(asset: string) : Promise<boolean> {
        // TODO: Implement method
        return Promise.resolve(true);
    }
}
```


## Proposal 2
```typescript=

interface AccessControlable {
    addAdministrator(_adminAddr: string);
    removeAdministrator(_adminAddr: string);
    addAssetManager(_assetManagerAddr: string);
    removeAssetManager(_assetManagerAddr: string);
    addAssetValidatorManager(_assetValidatorManagerAddr: string)
    removeAssetValidatorManager(_assetValidatorAddr: string) ;
    addAssetValidator(_assetValidatorManagerAddr: string);
    removeAssetValidator(_assetValidatorAddr: string);
    addFinance(_financeAddr: string);
    removeFinance(_financeAddr: string);
    addFinanceManager(_financeManagerAddr: string);
    removeFinanceManager(_financeManagerAddr: string);
    addAssetProviderManager(_assetProviderManagerAddr: string);
    removeAssetProviderManager(_assetProviderManagerAddr: string);
    addAssetProvider(_assetProviderAddr: string);
    removeAssetProvider(_assetProviderAddr: string);
}

interface Configurable {
    changeRequireWhitelistedAsset(boolean);
    changeRequireWhitelistedAssetProvider(boolean);
    changeRequireAssetValidation(boolean);
    changeRequireSaleStrategyPerAsset(boolean);
    changeRequireSameCurrencyPerAsset(boolean);
    changeRequireAssetSubdomain(boolean);
    changeSupportsStakingSlashing(boolean);
}

/**
 * Represents a user who interacts with the contract
 */
abstract class User {

  marketplace: MarketplaceContract; // web3/ethers contract instance
  address: string;

  constructor(marketplace: MarketplaceContract) {
      this.marketplace = marketplace;
  };

  abstract getAddress(): string;
   
}

/**
 *  Abstract Role access
 */
interface AccessController {
    add(): Promise<any>;
    remove(): Promise<any>;
}

/*
 * Concrete Roles Access in the marketplace 
 */
 class AssetManagerController extends User implements AccessController {
    constructor(address: string, contract: ContractWrapper) {
        super(contract);
        this.address = address;
    };

    async add() {
        this.marketplace.addAssetManager(this.getAddress());
    };
    async remove(){
        this.marketplace.addAssetManager(this.getAddress());
    };
    getAddress() { return this.address }
}


class FinanceManagerController extends User implements AccessController {
    constructor(address: string, contract: ContractWrapper) {
        super(contract);
        this.address = address;
    };

    async add() {
        // add administrator role into the marketplace
        this.marketplace.addFinanceManager(this.getAddress());
    };
    async remove(){
        this.marketplace.addFinanceManager(this.getAddress());
    };

    getAddress() { return this.address }
}


// This can be decoupled using a Factory method 
// that creates the role access // classes for us
class MarketplaceAccesControl implements AccessControlable {

    accessController: AccessController;
    marketplace: Contract; // web3/ethers contract instance

    addAssetManager(_assetManagerAddr: string) {
        this.accessController = new AssetManagerController(_assetManagerAddr, contract);
        this.accessController.add();
    }
    removeAssetManager(_assetManagerAddr: string) {
        this.accessController = new AssetManagerController(_assetManagerAddr, contract);
        this.accessController.remove();
    }
    // more methods...
}


class Marketplace implements IMarketplace {

    marketplace: Contract; //web3/ethers contract instance
    accessController: AccessControlable;
    configurer: Configurable;
    
    acceptedCurrencies: string[];
    assetValidators: Array<any>;
    
    // more properties...
    
    constructor (
        marketplace: Contract, //web3/ethers contract instance
        configurer: Configurable
    ) {
       this.marketplace = marketplace;
       this.configurer = configurer;
    }
    
    addAcceptedCurrency(_tokenERC20: string) {}
    removeAcceptedCurrency(_tokenERC20: string) {}
    withdraw(_to: string, amount: number) {}
    addAssetValidatorDelegate(_account: string) {}
    removeAssetValidatorDelegate(_account: string) {}
    assignRnsDomain(_rnsDomainNode: any) {}
    assignRnsNameGenerationStrategy(_strategy: string) {}
    registerAsset(_asset: string) {}
    validatorDelegateApprovesAsset(assetValidator: string, _asset: string){}
    validatorDelegateRejectAsset(assetValidator: string, _asset: any) {}
    assignOrderIdGeneratorStrategy(_strategy: string) {}
    sellAsset(_asset: string) {}
    
}

```

## Proposal #3 (Merge Proposal 1 & 2)

```typescript=

/* Probably we need to segregate interfaces here */
interface IMarketplace {
    changeRequireWhitelistedAsset(requireWhitelistedAsset: boolean) : Promise<boolean>;
    changeRequireWhitelistedAssetProvider(requireWhitelistedAssetProvider: boolean) : Promise<boolean>;
    changeRequireAssetValidation(requireAssetValidation: boolean) : Promise<boolean>;
    changeRequireSaleStrategyPerAsset(requireSaleStrategyPerAsset: boolean) : Promise<boolean>;
    changeRequireSameCurrencyPerAsset(requireSameCurrencyPerAsset: boolean) : Promise<boolean>;
    changeRequireAssetSubdomain(requireAssetSubdomain: boolean) : Promise<boolean>;
    changeSupportsStakingSlashing(supportStakingSlashing: boolean) : Promise<boolean>;

    whitelistAsset(address: string) : Promise<boolean>;
    removeAssetFromWhitelist(address: string) : Promise<boolean>;
    isWhitelistedAsset(address: string) : Promise<boolean>;

    addAcceptedCurrency(tokenERC20: string) : Promise<boolean>;
    removeAcceptedCurrency(tokenERC20: string) : Promise<boolean>;
    withdraw(to: string, amount: number) : Promise<boolean>;

    addAssetValidatorDelegate(account: string) : Promise<boolean>;
    removeAssetValidatorDelegate(account: string) : Promise<boolean>;

    assignRnsDomain(rnsDomainNode: string) : Promise<boolean>;
    assignRnsNameGenerationStrategy(strategy: string) : Promise<boolean>;

    //registerAsset(Asset _asset) external;
    validatorDelegateApprovesAsset(assetValidator: string, asset: string) : Promise<boolean>;
    validatorDelegateRejectAsset(assetValidator: string, asset: string): Promise<boolean>;
    assignOrderIdGeneratorStrategy(strategy: string) : Promise<boolean>;
    sellAsset(asset: string) : Promise<boolean>;
}

interface AccessControlable {
    addAdministrator(_adminAddr: string): Promise<void>;
    removeAdministrator(_adminAddr: string):Promise<void>;
    addAssetManager(_assetManagerAddr: string):Promise<void>;
    removeAssetManager(_assetManagerAddr: string): Promise<void>;
    addAssetValidatorManager(_assetValidatorManagerAddr: string): Promise<void>;
    removeAssetValidatorManager(_assetValidatorAddr: string): Promise<void>;
    addAssetValidator(_assetValidatorManagerAddr: string): Promise<void>;
    removeAssetValidator(_assetValidatorAddr: string);
    addFinance(_financeAddr: string): Promise<void>;
    removeFinance(_financeAddr: string): Promise<void>;
    addFinanceManager(_financeManagerAddr: string): Promise<void>;
    removeFinanceManager(_financeManagerAddr: string): Promise<void>;
    addAssetProviderManager(_assetProviderManagerAddr: string): Promise<void>;
    removeAssetProviderManager(_assetProviderManagerAddr: string): Promise<void>;
    addAssetProvider(_assetProviderAddr: string): Promise<void>;
    removeAssetProvider(_assetProviderAddr: string): Promise<boolvoidean>;
}

class Marketplace implements IMarketplace, AccessControlable {
    marketplace: IContract; //web3/ethers contract instance

    acceptedCurrencies: string[];
    assetValidators: Array;
    rnsNameGenerationStrategy: any;
    private assetWhitelist : AssetWhitelist;
    
    // more properties...
    
    constructor (
        marketplace: IContract //web3/ethers contract instance
        contractAddress: string,
    ) {
       this.marketplace = marketplace;
    }
    
    // implements AccessControlable interface
    addAssetManager(address: string) {
        const assetManagerController = AccessControllerFactory.getAccessController(
            AccessControllerType.ASSET_MANAGER,            
            contract,
        );
        assetManagerController.add(address);
    }
    removeAssetManager(address: string) {
        const assetManagerController = AccessControllerFactory.getAccessController(
            AccessControllerType.ASSET_MANAGER,            
            contract,
        );
        assetManagerController.remove(address);
    }
    
     addFinanceManager(address: string) {
        const financeManagerController = AccessControllerFactory.getAccessController(
            AccessControllerType.FINANCE_MANAGER,            
            contract,
        );
        financeManagerController.add(address);
    }
    removeFinanceManager(address: string) {
        const financeManagerController = AccessControllerFactory.getAccessController(
            AccessControllerType.FINANCE_MANAGER,            
            contract,
        );
        financeManagerController.remove(address);
    }
    // more methods...
    
    addAcceptedCurrency(_tokenERC20: string): Promise<void> {}
    removeAcceptedCurrency(_tokenERC20: string): Promise<void> {}
    withdraw(_to: string, amount: number): Promise<void> {}
    addAssetValidatorDelegate(_account: string): Promise<void> {}
    removeAssetValidatorDelegate(_account: string): Promise<void> {}
    assignRnsDomain(_rnsDomainNode: any): Promise<void> {}
    assignRnsNameGenerationStrategy(_strategy: string): Promise<void> {}
    registerAsset(_asset: string): Promise<void> {}
    validatorDelegateApprovesAsset(assetValidator: string, _asset: string): Promise<void>{}
    validatorDelegateRejectAsset(assetValidator: string, _asset: any): Promise<void> {}
    assignOrderIdGeneratorStrategy(_strategy: string) {}
    sellAsset(_asset: string): Promise<number> {}
        
    // implements configuration interface
    changeRequireWhitelistedAsset(requireWhitelistedAsset: boolean) : Promise<boolean>;
    changeRequireWhitelistedAssetProvider(requireWhitelistedAssetProvider: boolean) : Promise<boolean>;
    changeRequireAssetValidation(requireAssetValidation: boolean) : Promise<boolean>;
    changeRequireSaleStrategyPerAsset(requireSaleStrategyPerAsset: boolean) : Promise<boolean>;
    changeRequireSameCurrencyPerAsset(requireSameCurrencyPerAsset: boolean) : Promise<boolean>;
    changeRequireAssetSubdomain(requireAssetSubdomain: boolean) : Promise<boolean>;
    changeSupportsStakingSlashing(supportStakingSlashing: boolean) : Promise<boolean>;

}

interface IWhitelist {
    add(address: string) : Promise<boolean>;
    remove(address: string) : Promise<boolean>;
    isWhitelisted(address: string) : Promise<boolean>;
}

class AssetWhitelist implements IWhitelist {
    // TODO: implement
}

/* Suggestion
class CurrencyWhitelist implements IWhitelist { }
class AssetValidatorDelegateWhitelist implemts IWhitelist { }
*/


/**
 *  Abstract Role access
 */
interface AccessController {
    add(address, marketplace): Promise<void>;
    remove(address, marketplace): Promise<void>;
}

/*
 * Concrete Roles Access in the marketplace 
 */
 class AssetManagerController implements AccessController {
    private marketplace : Contract;

    constructor(marketplace: Contract) {
        this.marketplace = marketplace;
    };

    add(address) {
        return this.marketplace.addAssetManager(address);
    };
    remove(address){
        return this.marketplace.removeAssetManager(address);
    };
}


class FinanceManagerController implements AccessController {
    private marketplace : Contract;

    constructor(marketplace: Contract) {
        this.marketplace = marketplace;
        this.address = address;
    };

    add(address) {
        return this.marketplace.addFinanceManager(address);
    };
    remove(address){
        return this.marketplace.removeFinanceManager(address);
    };

}


enum AccessControllerType {
    ASSET_MANAGER;
    FINANCE_MANAGER;
    ASSET_VALIDATOR_MANAGER
    ASSET_PROVIDER_MANAGER;
    ADMINISTRATOR;
    OWNER;
}

class AccessControllerFactory {
    
    public static getAccessController(
        type: AccessControllerType, 
        marketplace: IContract,
    ): AccesController {
         switch(type){
    
             case AccessControllerType.ASSET_MANAGER:
                return new AssetManagerController(marketplace);
                
             case AccessControllerType.FINANCE_MANAGER:
                return new FinanceManagerController(marketplace);

             // more types...
             default:
                return null;
      } 
    }
}


// Contract interactor suggestion
class IContract {
    addAcceptedCurrency(address: string) : Promise<boolean>;
}

// Discuss: Basically a middleman
// - https://refactoring.guru/smells/middle-man
// Ideally, we would like to use the same interface used by Ethers (probs doesn't exist)
// Or use TypeChain ? 

class 
implements IContract {
  private ethers : any;
  
  constructor(ethers: any) {
      this.ethers = ethers;
  }
  
  addAcceptedCurrency(address: string) : Promise<boolean> {
      this.ethers.addAcceptedCurrency(address);
  }
}


```




