# omnia\_disperse

**Transfer (disperse) native or ERC-20 tokens to multiple addresses in a single RPC call.**

The workflow of the **omnia\_disperse** method is based on a two-stage process in which:

1. The first call is used to create and return an unsinged *disperse* transaction. This transaction will contain the addresses of the recipients, the amounts (values) to be sent to each recipient and the address of the token contract (ERC-20), in case of dispersing ERC-20 tokens, not native ones (Ether, Avax etc.);
2. The signing and starting the disperse. The caller should sign the unsigned *disperse* transaction returned by call in stage 1 and then make another *start disperse* call to launch the disperse aciton on-chain.

{% hint style="info" %}
**In case of dispersing ERC-20 tokens:** before sending the signed *disperse* transaction, make sure to give the *approve* allowance from the spending wallet to the ERC-20 token contract for the total amount (sum) spent. This is a requirement of the ERC-20 standard. [Follow step-by-step explanation here.](https://support.metamask.io/hc/en-us/articles/6174898326683-What-is-a-token-approval-)
{% endhint %}

{% hint style="info" %}
When dispersing the same amount (value) to all recipients, there's no need to send an array of values with the length of the recipients array. It is enough to send only one amount in the **values** array.
{% endhint %}

**Parameters**

1. `DATA, ["native" || "efficient" || "tracking"]` - disperseType. The type of disperse operation wanted.  <mark style="color:red;">REQUIRED</mark>
   * native - used for dispersing native tokens of the specific network. (Ether for Ethereum/Arbitrum/Optimism, BNB for Binance Smart Chain, Avax for Avalanche C-Chain etc.);
   * efficient - used when dispersing ERC-20 tokens in a more gas-efficient manner. This will generate less gas cost, but will be harder to track/audit for many recipients from the [Disperse smart contract](https://etherscan.io/address/0xd152f549545093347a162dce210e7293f1452150#code);
   * tracking - this allows tracking every transfer directly from the [Disperse smart contract](https://etherscan.io/address/0xd152f549545093347a162dce210e7293f1452150#code) but increases the gas consumed.
2. `DATA, ["createUnsignedDisperse" || "startDisperse"]` - disperseStage. As the disperse workflow uses two stages, the `createUnsignedDisperse` stage is used for creating the initial unsigned *disperse* transaction, while `startDisperse` stage is used for sending the signed *disperse* transaction.  <mark style="color:red;">REQUIRED</mark>
3. `DATA`, 20 Bytes - spendingAddress. Wallet addres from which the funds will be dispersed to recipients.  <mark style="color:red;">REQUIRED</mark>
4. `DATA`, Bytes - gasLimit. Hex value used overwrite the default gas limit when creating the unsigned *disperse* transaction. Default value: `0xC350` (50,000).
5. `Array of DATA`, 20 Bytes - recipients. The addresses of the wallets receiving the dispersed funds.  <mark style="color:red;">REQUIRED</mark>
6. `Array of DATA`, Bytes - values. The amounts (values) of dispersed funds received by each recipient. SHOULD be provided in Hex format. In case of same value for multiple recipients, see the note above.  <mark style="color:red;">REQUIRED</mark>
7. `DATA`, Bytes - signedTransaction. The signed *disperse* transaction RLP-encoded with 0x prefix. Required only in the `startDisperse` stage. <mark style="color:red;">REQUIRED</mark>

**Returns**

1. Unsigned *disperse* transaction serialised into JSON and ready to be signed.
2. Hash of *disperse* transaction.

## Example

#### Driver code (Node.js)

```javascript
const ethers = require('ethers');
const axios = require('axios');

async function main() {
  const omniaRpcUrl = '<INSERT YOUR OMNIA RPC ENDPOINT>';

  // #region Disperse createUnsignedDisperse
  const generateDisperseReq = {
    id: 1,
    
    jsonrpc: 2.0,
    method: "omnia_disperse",
    params: [{
        recipients: ["0xb3Be198329E658547381A2a823732122522D3566"],
        values: ["0x16345785d8a0000"],
        tokenAddress: "0x21F8246ECdE66A4F193f4a288371718484256d0a",
        spendingAddress: "0x6D8A32Fb9210dC8B903347204E105f4De08f0c34",
        disperseStage: "createUnsignedDisperse",
        disperseType: "tracking",
        gasLimit: "0x186A0"
    }]
  };
  const disperseRes = await axios.default.post(omniaRpcUrl, generateDisperseReq);
  const unsignedTransaction = JSON.parse(disperseRes.data.result);
  // #endregion Disperse createUnsignedDisperse

  // #region Disperse signDisperse
  const privateKey = '<INSERT YOUR WALLET PRIVATE KEY>';
  const rpcProvider = new ethers.providers.JsonRpcProvider(omniaRpcUrl);
  const wallet = new ethers.Wallet(privateKey, rpcProvider);
  
  const signedTransaction = await wallet.signTransaction(unsignedTransaction);
  console.log('signedTransaction: ', signedTransaction);


  const sendSignedDisperseReq = {
    id: 1,
    jsonrpc: 2.0,
    method: "omnia_disperse",
    params: [{
        disperseStage: "startDisperse",
        signedTransaction
    }]
  };


  const sendSignedTxRes = await axios.default.post(customRpcUrl, sendSignedDisperseReq, { headers })
  // #endregion Disperse signDisperse
}

main().catch((error) => {
  console.error(error);
  process.exitCode = 1;
});
```

#### Response

```json
{
  id: 1,
  jsonrpc: "2.0",
  result: '0xf335db1f9534a753180a53f1f82710c2703abfde4a97cc1208cb2b85340dc12b'
}
```
