# Portfolio Management API

#### Overview <a href="#overview" id="overview"></a>

The Velvet Portfolio Management API enables you to manage and rebalance tokenized portfolios (vaults) programmatically. With this API, you can:

* Retrieve and inspect all portfolios (vaults) created by a given owner.
* Rebalance portfolios by selling one token and buying another.
* Execute trades using on-chain calls.
* Deposit and withdraw tokens from portfolios.
* Obtain helper information, such as the number of portfolio tokens a user holds.

This guide will walk you through key endpoints and illustrate how to integrate the provided data and call parameters into your applications.

***

#### Prerequisites <a href="#prerequisites" id="prerequisites"></a>

* A wallet with a private key to sign blockchain transactions.
* A JSON-RPC provider URL for your target chain (for instance, Base chain with chainId = 8453).
* Familiarity with Ethereum-compatible contracts, tokens, and basic web3 concepts.

***

#### Trade Flow Overview <a href="#trade-flow-overview" id="trade-flow-overview"></a>

To execute a trade withing a Velvet portfolio (vault), follow these steps:

1. **Fetch All Created Vaults**: Retrieve all portfolios (vaults) associated with a specific owner.
2. **Use the Rebalance API Endpoint**: Generate the necessary call data and parameters for the intended trade.
3. **Execute the Trade On-Chain**: Use the parameters from the Rebalance API to call the vault’s rebalance contract function.

***

#### Fetch All Created Vaults <a href="#fetch-all-created-vaults" id="fetch-all-created-vaults"></a>

**Endpoint**: `GET https://api.velvet.capital/api/v3/portfolio/owner/<OWNER_WALLET_ADDRESS>?chain=base`

**Description**: Retrieves all vaults created by a specified owner on the Velvet V3 platform.

**URL Parameters**:

* `OWNER_WALLET_ADDRESS` (string): The Ethereum address of the owner.

**Response**:

Copy

```
jsonCopy code{
  "data": [
    {
      "portfolioId": "string",
      "portfolio": "string",
      "name": "string",
      "symbol": "string",
      "public": true,
      "initialized": true,
      "confirmed": true,
      "tokenExclusionManager": "string",
      "rebalancing": "string",       // ← Use this address in next steps
      "owner": "string",
      "assetManagementConfig": "string",
      "accessController": "string",
      "feeModule": "string",
      "vaultAddress": "string",
      "gnosisModule": "string",
      "whitelistedUsers": [],
      "whitelistedTokens": [],
      "whitelistAccessGrantedUsers": [],
      "assetManagerAccessGrantedUsers": [],
      "chainID": 8453,
      "chainName": "base",
      "txnHash": "string",
      "createdAt": "Date",
      "updatedAt": "Date",
      "creatorName": "string",
      "description": "string",
      "avatar": "string"
    }
  ]
}
```

**Usage**: From the response, note the `rebalancing` address, which will be needed to prepare the trade in the next step.

***

#### Rebalance API Endpoint <a href="#rebalance-api-endpoint" id="rebalance-api-endpoint"></a>

**Endpoint**: `POST https://eventsapi.velvetdao.xyz/api/v3/rebalance`

**Description**: Generates the necessary parameters (call data, handler address, etc.) to execute a trade within a portfolio’s rebalance contract.

**Request Body**:

Copy

```
jsonCopy code{
  "rebalanceAddress": "string",
  "sellToken": "string",
  "buyToken": "string",
  "sellAmount": "string",
  "slippage": "string",
  "remainingTokens": ["string"],
  "owner": "string"
}
```

**Parameters**:

* `rebalanceAddress` (string, required): The rebalance contract address retrieved from the "Fetch All Created Vaults" response.
* `sellToken` (string, required): The token address you want to sell.
* `buyToken` (string, required): The token address you want to buy.
* `sellAmount` (string, required): The amount of `sellToken` to sell (in smallest unit, e.g., if USDC is 6 decimals, `1 USDC` = `1000000`).
* `slippage` (string, required): Allowed slippage in basis points. For example, `"100"` means 1%.
* `remainingTokens` (array, required): The list of tokens that will remain in the vault after the trade.
* `owner` (string, required): The vault owner’s Ethereum address.

**Response**:

Copy

```
jsonCopy code{
  "newTokens": ["string"],
  "sellTokens": ["string"],
  "sellAmounts": ["string"],
  "handler": "string",
  "callData": "string",
  "estimateGas": "string",
  "gasPrice": "string"
}
```

**Note**: Use the returned data (`newTokens`, `sellTokens`, `sellAmounts`, `handler`, and `callData`) to execute the trade in the next step.

***

#### Executing the Trade On-Chain <a href="#executing-the-trade-on-chain" id="executing-the-trade-on-chain"></a>

After obtaining the necessary parameters from the Rebalance API, you can execute the trade by interacting directly with the rebalance contract on-chain.

**Prerequisite**: Install Ethers.js:

Copy

```
bashCopy codenpm install ethers@5.5.4
```

**Example Code**:

Copy

```
javascriptCopy codeimport { ethers } from 'ethers'

const provider = new ethers.providers.JsonRpcProvider('<RPC_URL>')
const privateKey = '<OWNER_WALLET_PRIVATE_KEY>'
const wallet = new ethers.Wallet(privateKey, provider)

const RebalanceABI = [
  {
    inputs: [
      {
        components: [
          { internalType: 'address[]', name: '_newTokens', type: 'address[]' },
          { internalType: 'address[]', name: '_sellTokens', type: 'address[]' },
          { internalType: 'uint256[]', name: '_sellAmounts', type: 'uint256[]' },
          { internalType: 'address', name: '_handler', type: 'address' },
          { internalType: 'bytes', name: '_callData', type: 'bytes' }
        ],
        internalType: 'struct FunctionParameters.RebalanceIntent',
        name: 'rebalanceData',
        type: 'tuple'
      }
    ],
    name: 'updateTokens',
    outputs: [],
    stateMutability: 'nonpayable',
    type: 'function'
  }
]

const RebalanceInstance = new ethers.Contract(
  'VAULT_REBALANCING_ADDRESS',
  RebalanceABI,
  wallet
)

async function executeRebalance(newTokens, sellTokens, sellAmounts, handler, callData, estimateGas, gasPrice) {
  try {
    console.log('Executing Trade...')
    const tx = await RebalanceInstance.updateTokens(
      {
        _newTokens: newTokens,
        _sellTokens: sellTokens,
        _sellAmounts: sellAmounts,
        _handler: handler,
        _callData: callData
      },
      {
        gasLimit: ethers.BigNumber.from(estimateGas).add('1000000'),
        gasPrice: gasPrice
      }
    )

    console.log('Transaction successful:', tx)
  } catch (error) {
    console.error('Transaction failed:', error)
  }
}
```

***

#### Rebalance Transaction API <a href="#rebalance-transaction-api" id="rebalance-transaction-api"></a>

**Endpoint**: `POST https://eventsapi.velvetdao.xyz/api/v3/rebalance/txn`

**Description**: Initiates a rebalance transaction directly. Useful when you already know the parameters required to perform the rebalance.

**Request Body**:

Copy

```
jsonCopy code{
  "rebalanceAddress": "0x19bc26a8e42727a2567d244cca344ceddd0493ae",
  "sellToken": "0x833589fcd6edb6e08f4c7c32d4f71b54bda02913",
  "buyToken": "0xb6fe221fe9eef5aba221c348ba20a1bf5e73624c",
  "sellAmount": "883373",
  "slippage": "100",
  "remainingTokens": [
    "0xb6fe221fe9eef5aba221c348ba20a1bf5e73624c",
    "0xc1CBa3fCea344f92D9239c08C0568f6F2F0ee452"
  ],
  "owner": "0x86F91b660a5432CE4654D84B3AbAD38A6645425e"
}
```

**Parameters**:

* Similar to the Rebalance API Endpoint (above), but returns direct transaction data for immediate execution.

***

#### Portfolio Deposit API <a href="#portfolio-deposit-api" id="portfolio-deposit-api"></a>

**Endpoint**: `POST https://eventsapi.velvetdao.xyz/api/v3/portfolio/deposit`

**Description**: Deposits a specified amount of tokens into a given portfolio.

**Request Body**:

Copy

```
jsonCopy code{
  "portfolio": "0x444ef5b66f3dc7f3d36fe607f84fcb2f3a666902",
  "depositAmount": "1000000",
  "depositToken": "0x50c5725949A6F0c72E6C4a641F24049A917DB0Cb",
  "user": "0x3C96e2Fc58332746fbBAB5eC44f01572F99033ed",
  "depositType": "batch",
  "tokenType": "erc20"
}
```

**Parameters**:

* `portfolio`: The portfolio contract address.
* `depositAmount`: The amount to deposit (in token’s smallest unit).
* `depositToken`: The token’s contract address being deposited.
* `user`: The depositor’s Ethereum address.
* `depositType`: The deposit mode (e.g., `batch`).
* `tokenType`: The type of token (e.g., `erc20`).

**Response**: Returns transaction data (`to`, `data`, `gasLimit`, `gasPrice`) needed to broadcast the transaction.

**Example Code**: After approval, send the returned transaction data via `wallet.sendTransaction(tx)`.

***

#### Portfolio Withdraw API <a href="#portfolio-withdraw-api" id="portfolio-withdraw-api"></a>

**Endpoint**: `POST https://eventsapi.velvetdao.xyz/api/v3/portfolio/withdraw`

**Description**: Initiates a withdrawal from a specified portfolio.

**Request Body**:

Copy

```
jsonCopy code{
  "portfolio": "0xc4dc922c90d44d07ea5d1aa8c08253ebc17e42c2",
  "withdrawAmount": "8999999999989636786",
  "withdrawToken": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
  "user": "0x86F91b660a5432CE4654D84B3AbAD38A6645425e",
  "withdrawType": "batch",
  "tokenType": "erc20"
}
```

**Parameters**:

* `portfolio`: The portfolio address.
* `withdrawAmount`: The withdrawal amount (in smallest unit).
* `withdrawToken`: The token address to withdraw.
* `user`: The user’s Ethereum address initiating the withdrawal.
* `withdrawType`: The withdrawal mode (e.g. `batch`).
* `tokenType`: The type of token (e.g., `erc20`).

**Response**: Returns transaction data needed to finalize the withdrawal transaction on-chain.

**Edge Case**: If the portfolio contains only one token and the user wishes to withdraw that same token, use the `multiTokenWithdrawal`function from the portfolio contract’s ABI.

***

#### Helper Functions <a href="#helper-functions" id="helper-functions"></a>

**Get Portfolio Token Amount**

**Function**: `getPortfolioTokenAmount(portfolioAddress, account, chainId=8453)`

**Description**: Returns the number of portfolio tokens a user holds.

**Example**:

Copy

```
javascriptCopy codeexport const getPortfolioTokenAmount = async (portfolioAddress, account, chainId = 8453) => {
  try {
    const web3 = getWeb3Provider(chainId);
    const ContractInstance = new web3.eth.Contract(
      portfolio_abi,
      portfolioAddress
    );
    const contractData = await ContractInstance.methods.balanceOf(account).call();
    return web3.utils.fromWei(contractData, 'ether');
  } catch (error) {
    console.log(error, 'error');
  }
};
```

***

#### Conclusion <a href="#conclusion" id="conclusion"></a>

With the endpoints and code samples provided, you should be able to:

* Discover and manage all your Velvet vaults.
* Programmatically prepare and execute trades through the Rebalance interface.
* Deposit and withdraw tokens from portfolios.
* Monitor and query token amounts within portfolios.

For a seamless integration, ensure you handle proper token approvals and confirm transactions on-chain. By following these guidelines and examples, you can fully leverage the Velvet Portfolio Management API.

Happy coding!
