Seller
A seller can create offers and participate in exchanges. The seller is a complex role with admin, assistant and treasury. Initially, all roles must be the same Ethereum address; however, the admin can later change them to other addresses.
When a seller is created, a default collection is initialised and all rNFTs belonging to their offers are issued on that collection. If the seller wants to organise offers and issue rNFTs on different collections, the protocol enables them to create as many collections as needed.
The sellers manage royalty recipients on two levels - the admin defines a list of allowed recipients, and the assistant then decides which royalty recipients are added to which offer.
Seller's funds management is described in Deposit and withdraw.
TypeScript SDK
Creates a new seller. The assistant, admin and treasury must be the caller's address.
const sellerAddress = signerWallet.address;
await coreSDK.createSeller({
  assistant: sellerAddress,
  admin: sellerAddress,
  treasury: sellerAddress,
  contractUri: "http://contract.uri",
  royaltyPercentage: "0",
  authTokenId: "0",
  authTokenType: 0,
  metadataUri: "http://metadata.uri",
});Change the admin, the assistant, the treasury, or the authentication method. Except for the treasury, all other actions require confirmation from the new address.
const newAssistantWallet = Wallet.createRandom(ethereumProvider);
const sellerId = "12";
const seller = await coreSDK.getSellerById(sellerId);
// Start the update with the seller's wallet
await coreSDK.updateSellerAndOptIn({
   ...seller,
   {assistant: newAssistantWallet.address}
})
// Finalize the update with the assistant's wallet 
const assistantCoreSDK = CoreSDK.fromDefaultConfig({
   envName,
   configId,
   web3Lib: new EthersAdapter(provider, newAssistantWallet),
});
await assistantCoreSDK.optInToSellerUpdate({
   id: sellerId,
   fieldsToUpdate: {assistant: true}
})Create a new rNFT collection (ERC721 contract) which can be assigned to new offers.
await coreSDK.createNewCollection({
      contractUri: "http://newCollection.uri",
      collectionId: "customCollectionID"
});To get the new collection index, one can query
const collections = await coreSDK.getOfferCollections({
      offerCollectionsFilter: {
        sellerId: seller.id
      }
});
const latestCollectionId = collections[collections.length - 1].collectionIndexAdd, update or remove royalty recipients allowlist.
Add
const recipients = [
  "recipientAddress1",
  "recipientAddress2"
];
const recipientsPercentage = ["200", "300"];
    
await coreSDK.addRoyaltyRecipients(
      seller.id,
      recipients.map((wallet, index) => {
        return {
          wallet,
          minRoyaltyPercentage: recipientsPercentage[index]
        };
      })
);Update
const newRecipients = [
  "recipientAddress1", // address unchanged
  "recipientAddress3"
];
const recipientsPercentage = ["400", "100"];
const recipientIndices = [1,2];
await coreSDK.updateRoyaltyRecipients(
      seller.id,
      recipientIndices,
      recipients_2.map((wallet, index) => {
        return {
          wallet,
          minRoyaltyPercentage: recipientsPercentage_2[index]
        };
      })
);Remove
const recipient2Index = 2;
await coreSDK.removeRoyaltyRecipients(seller.id, [
      recipient2Index
]);Solidity
Creates a new seller. The assistant, admin and treasury must be the caller's address.
IBosonProtocol bosonProtocol = IBosonSellerHandler(_bosonProtocolAddress);
BosonTypes.Seller memory seller = BosonTypes.Seller({
     id: 0,
     assistant: address(this),
     admin: address(this),
     clerk: address(0),
     treasury: payable(address(this)),
     active: true,
     metadataUri: ""
});
BosonTypes.AuthToken memory authToken;
BosonTypes.VoucherInitValues memory voucherInitValues;
bosonProtocol.createSeller(seller, authToken, voucherInitValues);Change the admin, the assistant, the treasury, or the authentication method. Except for the treasury, all other actions require confirmation from the new address.
IBosonAccountHandler bosonProtocol = IBosonAccountHandler(_bosonProtocolAddress);
BosonTypes.Seller memory seller = BosonTypes.Seller({
    id: 1, // existing seller ID
    assistant: newAssistantAddress,
    admin: newAdminAddress, 
    clerk: address(0), // deprecated, always zero
    treasury: payable(newTreasuryAddress),
    active: true,
    metadataUri: "https://ipfs.io/ipfs/updated-metadata"
});
BosonTypes.AuthToken memory authToken = BosonTypes.AuthToken({
    tokenId: 0,
    tokenType: BosonTypes.AuthTokenType.None
});
bosonProtocol.updateSeller(seller, authToken);
// For admin/assistant updates, new addresses must opt in:
// bosonProtocol.optInToSellerUpdate(sellerId, fieldsToUpdate);Create a new rNFT collection (ERC721 contract) which can be assigned to new offers.
IBosonAccountHandler bosonProtocol = IBosonAccountHandler(_bosonProtocolAddress);
BosonTypes.VoucherInitValues memory voucherInitValues = BosonTypes.VoucherInitValues({
    contractURI: "https://ipfs.io/ipfs/collection-metadata",
    royaltyPercentage: 250, // 2.5%
    collectionSalt: keccak256(abi.encodePacked(block.timestamp, "unique-collection"))
});
bosonProtocol.createNewCollection("external-collection-id", voucherInitValues);In case of admin address being updated it is a good practice also the salt to be updated. If not there exists a possibility that the old admin will try to create the vouchers with matching addresses on other chains.
IBosonAccountHandler bosonProtocol = IBosonAccountHandler(_bosonProtocolAddress);
uint256 sellerId = 1;
bytes32 newSalt = keccak256(abi.encodePacked(block.timestamp, "new-unique-salt"));
bosonProtocol.updateSellerSalt(sellerId, newSalt);Add, update or remove royalty recipients allowlist.
IBosonAccountHandler bosonProtocol = IBosonAccountHandler(_bosonProtocolAddress);
uint256 sellerId = 1;
// Add royalty recipients
BosonTypes.RoyaltyRecipientInfo[] memory royaltyRecipients = new BosonTypes.RoyaltyRecipientInfo[](2);
royaltyRecipients[0] = BosonTypes.RoyaltyRecipientInfo({
    wallet: payable(recipientAddress1),
    minRoyaltyPercentage: 100 // 1%
});
royaltyRecipients[1] = BosonTypes.RoyaltyRecipientInfo({
    wallet: payable(recipientAddress2),
    minRoyaltyPercentage: 150 // 1.5%
});
bosonProtocol.addRoyaltyRecipients(sellerId, royaltyRecipients);
// Update royalty recipients
uint256[] memory recipientIds = new uint256[](1);
recipientIds[0] = 0; // first recipient
royaltyRecipients[0].minRoyaltyPercentage = 200; // update to 2%
bosonProtocol.updateRoyaltyRecipients(sellerId, recipientIds, royaltyRecipients);
// Remove royalty recipients
uint256[] memory idsToRemove = new uint256[](1);
idsToRemove[0] = 1; // second recipient
bosonProtocol.removeRoyaltyRecipients(sellerId, idsToRemove);Last updated
