> For the complete documentation index, see [llms.txt](https://v1.etherspot.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://v1.etherspot.io/use-cases/crosschain-streaming.md).

# Crosschain Streaming

Etherspot have teamed up with Superfluid to allow Crosschain Streaming. This allows you to stream assets to another Etherspot-supported blockchain.

{% hint style="success" %}
Before we continue, please ensure that you have had a look at our [Supported Ethereum Chains](broken://pages/-MeAyzR2e2VKsOneDqAi), followed the steps in [Install Etherspot SDK](/getting-started/install-sdk.md) and how to [Bootstrap Etherspot SDK](/getting-started/bootstrap-etherspot-sdk.md). We're assuming that you have completed these steps before going forward.
{% endhint %}

## Before we continue...

We're going to need a few things ready to go. For this example. we're going to use two testnets:

* Goerli (Ethereum testnet)
* Mumbai (Polygon tesnet)

... and we're going be using two tokens:

* ETH on Goerli: `0x0000000000000000000000000000000000000000`
* ERC-20 Test Token on Mumbai:  `0xA6FA4fB5f76172d178d61B04b0ecd319C5d1C0aa`

Let's set this up in our code.

```javascript
import {
  Sdk as EtherspotSdk,
  NetworkNames,
  randomPrivateKey,
} from 'etherspot';

// ...

// First, define the tokens
const fromToken = '0x0000000000000000000000000000000000000000';
const toToken = '0xA6FA4fB5f76172d178d61B04b0ecd319C5d1C0aa';

// Next, instantiate our SDKs for each network
const etherspotGoerliSdk = new EtherspotSdk({
  privateKey: randomPrivateKey(),
}, {
  networkName: NetworkNames.Goerli,
});

const etherspotMumbaiSdk = new EtherspotSdk({
  privateKey: randomPrivateKey(),
}, {
  networkName: NetworkNames.Mumbai,
});

// Finally, compute the contract account addresses ahead of time
// The responses will return the account details.
const goerliAccount = await etherspotGoerliSdk.computeContractAccount();
const mumbaiAccount = await etherspotMumbaiSdk.computeContractAccount();
```

Now we have two Etherspot accounts ready to go.

## Supported Chains

Not all chains are supported. We have created an SDK method that allows you to fetch the supported chains. This helps minimise wasted time testing what chains might be supported.

```javascript
import { CrossChainServiceProvider } from 'etherspot';

// Keep this for future use.
const supporteChains = await sdk.getCrossChainBridgeSupportedChains({
  serviceProvider: this.serviceProvider
});
```

{% hint style="info" %}
Be sure to check whatever chains you are working with against the list returned above!
{% endhint %}

## Supported Tokens

As with the Supported Chains above, we also provide a helper SDK method to return the supported list of tokens between two chains. This can save you alot of time and effort.

```javascript
import {
  SocketTokenDirection,
  CrossChainServiceProvider
} from 'etherspot';

const supportedTokens = await sdk.getCrossChainBridgeTokenList({
  fromChainId: 420,
  toChainId: 80001,
  direction: SocketTokenDirection.From,
  serviceProvider: CrossChainServiceProvider.LiFi,
});
```

## Create Superfluid Token Wrapper

We're now going to create a Superfluid Token Wrapper.

```javascript
import { ethers } from 'ethers';
import {
  SuperTokenFactoryContract,
  SuperTokenContract,
} from 'etherspot';

// Build the transaction to create the Superfluid
// ERC20 Super Token
const createSuperERC20Tx = await etherspotMumbaiSdk
  .createSuperERC20WrapperTransactionPayload(
    toToken
  );
  
// Add this to the Etherspot transaction batch
await etherspotMumbaiSdk.batchExecuteAccountTransaction(createSuperERC20Tx);

const txResponse = await this.toWallet.sendTransaction(
  await etherspotMumbaiSdk.encodeGatewayBatch()
);
const txReceipt = await txResponse.wait();
const factoryContract = new SuperTokenFactoryContract();
const factoryCreated = factoryContract
  .parseLogs(txReceipt.logs)
  .find(log => log && log.event === 'SuperTokenCreated');
  
const superTokenAddress = factoryCreated.args[0];
 
await sdk.clearGatewayBatch();

const superTokenContract = new SuperTokenContract(
  this.superTokenAddress
);
```

## Perform necessary transactions

In order to continue, we need to ensure that we can perform the necessary actions. The below code will ensure these are met.

```javascript
const approveReq = erc20TokenContract.encodeApprove(
  superTokenAddress,
  amountToStream // BigNumber
);

await etherspotMumbaiSdk.batchExecuteAccountTransaction(approveReq);

const upgradeReq = superTokenContract.encodeUpgrade(
  amountToStream
);

await etherspotMumbaiSdk.batchExecuteAccountTransaction(upgradeReq);
```

## Start Crosschain Streaming

We're now ready to start the Crosschain Streaming! Lets execute the final set of transactions.

```javascript
const txnData = await etherspotMumbaiSdk.createStreamTransactionPayload({
  tokenAddress: superTokenAddress,
  receiver: destinationAddress,
  amount: flowRate, // amount in wei
  skipBalanceCheck: true,
});
await etherspotMumbaiSdk.batchExecuteAccountTransaction(txnData);
```
