# Erc20

## What is JellySwap?

JellySwap is a cross-chain atomic swap protocol that supports many different blockchains. The erc20 package is used to interact with the Ethereum Hash Time Locked Contracts and to handle blockchain events. The main components of the module are **Providers, Contract, Event, Adapter and Config.**

## Install package

Using **yarn**

```
$ yarn add @jelly-swap/erc20
```

Using **npm**

```bash
$ npm install @jelly-swap/erc20
```

## Importing

JavaScript (ES3)

```javascript
const jellyErc20 = require('@jelly-swap/erc20');
```

JavaScript (ES6) / TypeScript

```javascript
import * as jellyErc20 from '@jelly-swap/erc20';
```

## Config Module

This module contains the main configuration for the whole package.

```javascript
const config = jellyErc20.Config(token?, expiration?);

//Expected output
{
  explorer: 'https://ropsten.etherscan.io/tx/',
  providerUrl: 'https://ropsten.infura.io/v3/8fe4fc9626494d238879981936dbf144',
  contractAddress: '0x66ea49fd943544d59e14d1bd9107217c7503906a',
  receiverAddress: '0xc555d8bc1B47F53F2b28fd2B3301aD94F7add17C',
  blockTime: 15,
  expiration: 10800,
  unix: true,
  network: 'DAI',
  decimals: 18,
  address: '0x2d69ad895797c880abce92437788047ba0eb7ff6'
}
```

| parameter  | type   | description                                |
| ---------- | ------ | ------------------------------------------ |
| token      | string | Name of the token. Optional.               |
| expiration | number | The Time Lock of the transaction. Optional |

## Provider Module

A Provider abstracts a connection to the Ethereum blockchain, for issuing queries and sending signed state changing transactions.

**JsonRpcProvider** - allows you to connect to Ethereum nodes you control or have access to, including mainnet, testnets, proof-of-authority (PoA) nodes or Ganache by providing a URL to the node.

```javascript
const jsonProvider = new jellyErc20.Providers.JsonRpcProvider(providerUrl);
```

| parameter   | type   | description                                            |
| ----------- | ------ | ------------------------------------------------------ |
| providerUrl | string | Can be infura or other provider on testnet or mainnet. |

**Web3Provider** - used with Web3 application, or Web3-compatible Provider (e.g. MetaMask’s web3.currentProvider).

```javascript
const jsonRpcProvider = new jellyErc20.Providers.Web3Provider(web3);
```

| parameter | type   | description                                          |
| --------- | ------ | ---------------------------------------------------- |
| web3      | object | Can be any web3 provider like the one from Metamask. |

**WalletProvider** - manages a private/public key pair which is used to cryptographically sign transactions and prove ownership on the Ethereum network. Use when there is no **Web3Provider** available.

```javascript
const walletProvider = new jellyErc20.Providers.WalletProvider(privateKey)
```

| parameter  | type   | description           |
| ---------- | ------ | --------------------- |
| privateKey | string | Ethereum Private Key. |

## Contract Module

Contract module is used to interact with the Solidity Contract and get blockchain specific data (balance, blockNumber, subscribe to events, get past events).

Create **contract** instance:

```javascript
const erc20Contract = new jellyErc20.Contract(provider);
```

| parameter | type   | description                                                  |
| --------- | ------ | ------------------------------------------------------------ |
| provider  | object | Provider instance that will be used for transaction signing. |

### **subscribe**

```javascript
await erc20Contract.subscribe(onEvent, filter?);
```

| parameter | type     | description                                  |
| --------- | -------- | -------------------------------------------- |
| onEvent   | function | Called when an event is received.            |
| filter    | function | Used to filter any received event. Optional. |

### **getPastEvents**

Returns past blockchain events.

```javascript
const pastEvents = await erc20Contract.getPastEvents(eventType, filter?, currentBlock?);
```

| parameter    | type     | description                                                                                                                             |
| ------------ | -------- | --------------------------------------------------------------------------------------------------------------------------------------- |
| eventType    | string   | can be 'new', 'withdraw' or 'refund'                                                                                                    |
| filter       | function | <p>Filter the received events. </p><p>Optional. If not passed all events will be returned.</p>                                          |
| currentBlock | number   | <p>Read events up to the currentBlock. <br>Optional. If not passed the currentBlock will be <br>assigned to the latest mined block.</p> |

### **getCurrentBlock**&#x20;

Returns the latest block.

```javascript
const currentBlock = await erc20Contract.getCurrentBlock();
```

### **getBalance**&#x20;

Returns the balance of the given address.

```javascript
const balance = await erc20Contract.getBalance(address, token);
```

| parameter | type   | description              |
| --------- | ------ | ------------------------ |
| address   | string | Ethereum Public Address. |
| token     | string | Token symbol.            |

### **getStatus**

&#x20;Returns the swaps statuses by given ids.

```javascript
const statuses = await erc20Contract.getStatus(ids);
```

| parameter | type  | description  |
| --------- | ----- | ------------ |
| ids       | array | List of ids. |

### **newContract**

Creates and broadcasts a new swap transaction.

```javascript
const transactionHashSwap = await erc20Contract.newContract(swap, checkAllowance);
```

| parameter      | type              | description                            |
| -------------- | ----------------- | -------------------------------------- |
| swap           | Erc20ContractSwap | Input data for the swap.               |
| checkAllowance | bool              | Check ERC20 token allowance. Optional. |

### **withdraw**

Creates and broadcasts a withdraw transaction.

```javascript
const transactionHashWithdraw = await erc20Contract.withdraw(withdraw);
```

| parameter | type                  | description                  |
| --------- | --------------------- | ---------------------------- |
| withdraw  | Erc20ContractWithdraw | Input data for the withdraw. |

### **refund**&#x20;

Creates and broadcasts a refund transaction.

```javascript
const transactionHashRefund = await erc20Contract.refund(contractRefund);
```

| parameter      | type                | description                |
| -------------- | ------------------- | -------------------------- |
| contractRefund | Erc20ContractRefund | Input data for the refund. |

### getTokenContract

Returns new token contract instance.

```javascript
 const tokenContract = erc20Contract.getTokenContract(tokenAddress);
```

| parameter    | type   | description                        |
| ------------ | ------ | ---------------------------------- |
| tokenAddress | string | The address of desired ERC20 token |

## **Event module**

**Event module** is used to read **past blockchain events** and **subscribe for new ones.**

Initialize **event** module:

```javascript
const erc20Events = new jellyErc20.Event(erc20Contract);
```

| parameter     | type          | description              |
| ------------- | ------------- | ------------------------ |
| erc20Contract | Erc20Contract | Erc20 contract instance. |

### **getPast**

Returns past blockchain events.

```javascript
const pastEvents = await erc20Events.getPast(eventType, filter?, currentBlock?);
```

| parameter    | type     | description                                                                                                                             |
| ------------ | -------- | --------------------------------------------------------------------------------------------------------------------------------------- |
| eventType    | string   | can be 'new', 'withdraw' or 'refund'                                                                                                    |
| filter       | function | <p>Filter the received events. </p><p>Optional. If not passed all events will be returned.</p>                                          |
| currentBlock | number   | <p>Read events up to the currentBlock. <br>Optional. If not passed the currentBlock will be <br>assigned to the latest mined block.</p> |

### **subscribe**

```javascript
await erc20Events.subscribe(onEvent, filter?);
```

| parameter | type     | description                                  |
| --------- | -------- | -------------------------------------------- |
| onEvent   | function | Called when an event is received.            |
| filter    | function | Used to filter any received event. Optional. |

## Adapter module

The Adapter module is used to **format the client data and prepare the input** for the swaps.

Initialize **adapter** module:

```javascript
const erc20Adapter = new jellyErc20.Adapter();
```

###

### generateId

Generate swap id based on the input parameters. The same id will be generated by the Solidity Contract.

```javascript
const id = erc20Adapter.generateId(input);
```

| parameter | type              | description              |
| --------- | ----------------- | ------------------------ |
| input     | Erc20ContractSwap | Input data for the swap. |

###

### addressValid

Checks if the passed address is valid or not.

```javascript
const isAddressValid = erc20Adapter.addressValid(address);
```

| parameter | type   | description               |
| --------- | ------ | ------------------------- |
| address   | string | True if address is valid. |

###

### parseAddress

Returns the address in lower case.

```javascript
const addressParsed = erc20Adapter.parseAddress(address);
```

| parameter | type   | description            |
| --------- | ------ | ---------------------- |
| address   | string | Address in lower case. |

### **parseToNative**

Parse **token** amount to amount based on token decimals i.e. **0.1** to **100000000000000000**

```javascript
const result = erc20Adapter.parseToNative(amount);
```

| parameter | type   | description                              |
| --------- | ------ | ---------------------------------------- |
| amount    | number | String representation of the wei amount. |

###

### **parseFromNative**

Parse **amount** to **token** amount based on the token decimals i.e. **100000000000000000** to **0.1**

```javascript
const result = erc20Adapter.parseFromNative(amount);
```

| parameter | type         | description                                |
| --------- | ------------ | ------------------------------------------ |
| amount    | BigNumberish | String representation of the ether amount. |

###

### formatInput

Returns object of type UserInputSwap.

```javascript
const swapInput = erc20Adapter.formatInput(data, receiver);
```

| parameter | type               | description                                                                                   |
| --------- | ------------------ | --------------------------------------------------------------------------------------------- |
| data      | Erc20UserInputSwap | User input data.                                                                              |
| receiver  | string             | <p>Address of the receiver.<br>Optional. If not passed uses the receiver from the config.</p> |

## Example

```javascript
const jellyErc20 = require('@jelly-swap/erc20');

const provider = new jellyErc20.Providers.WalletProvider('ETH_PRIVATE_KEY');

const erc20Contract = new jellyErc20.Contract(provider);

const adapter = new jellyErc20.Adapter();

async function start() {
    // Subscribe for contract events and pass handle function
    await erc20Contract.subscribe(e => {
        console.log(e);
    });


    // Get past blockchain events
    const swaps = await erc20Contract.getPastEvents('new', s => s);
    console.log(swaps);
    // [
    //  {
    //    network: 'DAI',
    //    eventName: 'NEW_CONTRACT',
    //    id: '0x87289065138d186900738561d2f80b84b0bed66e4e930f17ff84dae0caf69a6f',
    //    hashLock: '0x07d7feb413329c6a92fc30481b0144d874e4eccb189d8f351a932055f3f77edd',
    //    tokenAddress: '0x2d69ad895797c880abce92437788047ba0eb7ff6',
    //    sender: '0xc525d8bc1B47F53F2b28fd2B3301aD94F7add17C',
    //    receiver: '0xB7b4043Ad3e6986D39F344c551aA78266fb140e2',
    //    inputAmount: '10000000000000000000',
    //    outputAmount: '100000000000000000',
    //    expiration: '1578488152',
    //    outputNetwork: 'ETH',
    //    outputAddress: '0xF684C21Ec023E93da0B402ac0a274317eb51C2c7',
    //    transactionHash: '0x0b7292560788fed178383d371dd7457e0d8b9df9f9685b841bf883300db8fedf',
    //    status: 4
    //  },
    // ];

  
    const withdraws = await erc20Contract.getPastEvents('withdraw', w => w);
    console.log(withdraws);
    // [
    //  {
    //    network: 'DAI',
    //    eventName: 'WITHDRAW',
    //    id: '0x697842a3655cc64c917e6d2f5655895b9ece2cf9b57bfb70a270a0950d012dbe',
    //    secret: '0xb8504b8a996634a96294d6e631de9d8b2599d16ca5b85db4f776339690e2fa8a',
    //    hashLock: '0x6378b69129893558c5c6e86b99eddf9a875525a9f4268fdc1680451ada03326b',
    //    tokenAddress: '0x2d69ad895797c880abce92437788047ba0eb7ff6',
    //    sender: '0xc555d8bc1B47F53F2b28fd2B3301aD94F7add17C',
    //    receiver: '0xC9F5Eb95a4d32Af48ab07E2d6c160D82205c5298',
    //  }
    // ];


    const refunds = await erc20Contract.getPastEvents('refund', r => r);
    console.log(refunds);
    // [
    //  {
    //    network: 'DAI',
    //    eventName: 'REFUND',
    //    id: '0xad88986a6fd4e958683ae267929450caeaace7655cc98d74f69d85b9000cde46',
    //    hashLock: '0x07d7feb413329c6a92fc30481b0144d874e4eccb189d8f351a932055f3f77edd',
    //    tokenAddress: '0x2d69ad895797c880abce92437788047ba0eb7ff6',
    //    sender: '0xc555d8bc1B47F53F2b28fd2B3301aD94F7add17C',
    //    receiver: '0xB7b4043Ad3e6986D39F344c551aA78266fb140e2',
    //    transactionHash: '0xa9641add8e4c38f26f2cff92c9499557acb21364c6bf5adedd76c7688e18e6e9'
    //  }
    // ];


    const currentBlock = await erc20Contract.getCurrentBlock();
    console.log(currentBlock);
    // 7085825


    const balance = await erc20Contract.getBalance('0xB7B4043aD3E6986D39f344c551AA78266Fb140D4', 'DAI');
    console.log(balance);
    // 1000000000000000000


    const statuses = await erc20Contract.getStatus([
        '0x9ee52df91acbdd56079c885cf24f7d0fa74b8ca7ecdbe4385b28f566feb51896',
        '0xb8504b8a996634a96294d6e631de9d8b2599d16ca5b85db4f776339690e2fa8a',
    ]);
    console.log(statuses);
    // [1, 4]

    // ACTIVE: 1,
    // REFUNDED: 2,
    // WITHDRAWN: 3,
    // EXPIRED: 4




    // ================ SWAP ================
    const userInputSwap = {
        inputAmount: '0.01',
        network: 'DAI',
        outputAddress: '0x7bc272693510354a84e1632cca005253dbb08d18',
        outputAmount: '98917611',
        outputNetwork: 'TRX',
        secret: 'pond cram isolate chair float moon tongue firm spirit hand peace together',
        sender: '0xd9dabdeac2c54004bed2a3d0fee27b1c5d063cf2',
    };
    
    const swap = adapter.formatInput(userInputSwap);
    console.log(swap);
    //  {
    //    inputAmount: '10000000000000000',
    //    network: 'DAI',
    //    outputAddress: '0x7bc272693510354a84e1632cca005253dbb08d18',
    //    outputAmount: '98917611',
    //    outputNetwork: 'TRX',
    //    secret: 'pond cram isolate chair float moon tongue firm spirit hand peace together',
    //    sender: '0xd9dabdeac2c54004bed2a3d0fee27b1c5d063cf2',
    //    tokenAddress: '0x2d69ad895797c880abce92437788047ba0eb7ff6',
    //    expiration: 1578501147,
    //    hashLock: '0x4af116ee28ecde1d2b71e49fb964fe76a20c694c94f6895c1baa8ed1d1b06dda',
    //    receiver: '0xc555d8bc1B47F53F2b28fd2B3301aD94F7add17C'
    //  }

    //broadcast swap transaction
    const swapHash = await erc20Contract.newContract(swap, true);
    console.log(swapHash);
    // 0x9aaee4781efd92f214cfc625e385492241e4f252f9400cdf6b1706668137f905




    // ================ REFUND ================

    const refund = {
        id: '0xfa033fb78799f986cffba5e965db049d8da4f9764e6b791cb8aeb6df842c0e52',
    };

    const refundHash = await erc20Contract.refund(refund);
    console.log(refundHash);
    // 0x9aaee4781efd92f214cfc625e385492241e4f252f9400cdf6b1706668137f905

    
    
    
    // ================ WITHDRAW ================

    const withdraw = {
        id: '0xfa033fb78799f986cffba5e965db049d8da4f9764e6b791cb8aeb6df842c0e54',
        secret: '0x307afe7a1a9bc9f94b7bf5b091441bac10222f4c797ee4441cb213aae7ac18a2',
    };

    const withdrawHash = await erc20Contract.withdraw(withdraw);
    console.log(withdrawHash);
    // 0x9aaee4781efd92f214cfc625e385492241e4f252f9400cdf6b1706668137f905
}

```
