Skip to content

Commit

Permalink
added xchain-avax
Browse files Browse the repository at this point in the history
  • Loading branch information
mikewyszinski committed Jul 29, 2022
1 parent 0c870fc commit da834f0
Show file tree
Hide file tree
Showing 40 changed files with 1,084 additions and 626 deletions.
6 changes: 6 additions & 0 deletions packages/xchain-avax/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
*.log
.DS_Store
node_modules
lerna-debug.log
npm-debug.log
packages/**/lib
6 changes: 6 additions & 0 deletions packages/xchain-avax/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# v.0.1.0-alpha (2022-07-28)

## Update

- initial release

21 changes: 21 additions & 0 deletions packages/xchain-avax/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2022 THORChain

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
40 changes: 40 additions & 0 deletions packages/xchain-avax/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# `@xchainjs/xchain-avax`

## Modules

- `client` - Custom client for communicating with avax by using [`ethers`](https://github.com/ethers-io/ethers.js)

## Installation

```
yarn add @xchainjs/xchain-avax
```

Following peer dependencies have to be installed into your project. These are not included in `@xchainjs/xchain-avax`.

```
yarn add @xchainjs/xchain-evm @xchainjs/xchain-client @xchainjs/xchain-crypto @xchainjs/xchain-util axios ethers
```

## Documentation

### [`xchain avax`](http://docs.xchainjs.org/xchain-client/xchain-avax/)

[`How xchain-avax works`](http://docs.xchainjs.org/xchain-client/xchain-avax/how-it-works.html)\
[`How to use xchain-avax`](http://docs.xchainjs.org/xchain-client/xchain-avax/how-to-use.html)

## Service Providers

This package uses the following service providers:

| Function | Service | Notes |
| ------------------------- | --------- | ------------------------------------------------------------------------------ |
| ETH balances | Etherscan | https://api.snowtrace.io/apis#accounts (module=`account`, action=`balance`) |
| Token balances | Etherscan | https://api.snowtrace.io/apis#tokens (module=`account`, action=`tokenbalance`) |
| ETH transaction history | Etherscan | https://api.snowtrace.io/apis#accounts (module=`account`, action=`txlistinternal`) |
| Token transaction history | Etherscan | https://api.snowtrace.io/apis#accounts (module=`account`, action=`tokentx`) |
| Explorer | Etherscan | https://snowtrace.io/ |

Etherscan API rate limits: https://snowtrace.io/apis

- This package uses `etherjs` library, by default it uses several providers. (`https://docs.ethers.io/v5/api-keys/`)
145 changes: 145 additions & 0 deletions packages/xchain-avax/__e2e__/avax-client.e2e.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
import { Network, TxType } from '@xchainjs/xchain-client'
import { ApproveParams, EstimateApproveParams, IsApprovedParams } from '@xchainjs/xchain-evm'
import { Asset, AssetAVAX, Chain, assetAmount, assetToBase, assetToString } from '@xchainjs/xchain-util'

import AvaxClient from '../src/client'
import { defaultAvaxParams } from '../src/const'

// import { ApproveParams, EstimateApproveParams, IsApprovedParams } from '../src/types'

// =====Erc-20 asset=====

const assetRIP: Asset = {
chain: Chain.Avalanche,
symbol: `RIP-0x224695Ba2a98E4a096a519B503336E06D9116E48`,
ticker: `RIP`,
synth: false,
}
defaultAvaxParams.network = Network.Testnet
const client = new AvaxClient(defaultAvaxParams)

function delay(ms: number) {
return new Promise((resolve) => setTimeout(resolve, ms))
}
describe('xchain-evm (Avax) Integration Tests', () => {
it('should fetch avax balances', async () => {
const address = client.getAddress(0)
console.log(address)
const balances = await client.getBalance(address)
balances.forEach((bal) => {
console.log(`${assetToString(bal.asset)} = ${bal.amount.amount()}`)
})
expect(balances.length).toBeGreaterThan(0)
})
it('should fetch avax txs', async () => {
const address = '0x55aEd0ce035883626e536254dda2F23a5b5D977f'
const txPage = await client.getTransactions({ address })
console.log(JSON.stringify(txPage, null, 2))
expect(txPage.total).toBeGreaterThan(0)
expect(txPage.txs.length).toBeGreaterThan(0)
})
it('should fetch single avax transfer tx', async () => {
const txId = '0x206d2300e57d0c23e48b8c4cc4af9c87abf33e2f406ac2265915b3d7b0e131e2'
const tx = await client.getTransactionData(txId)
console.log(JSON.stringify(tx, null, 2))
const amount = assetToBase(assetAmount('0.01', 18))
expect(tx.asset.chain).toBe(AssetAVAX.chain)
expect(tx.asset.ticker).toBe(AssetAVAX.ticker)
expect(tx.type).toBe(TxType.Transfer)
expect(tx.from[0].from).toBe(client.getAddress(0))
expect(tx.from[0].amount.amount().toFixed()).toBe(amount.amount().toFixed())
expect(tx.to[0].to).toBe(client.getAddress(1))
expect(tx.to[0].amount.amount().toFixed()).toBe(amount.amount().toFixed())
expect(tx.hash).toBe(txId)
})
it('should fetch single RIP token transfer tx', async () => {
const txId = '0x15fa3948bf5c980de8be74afec94b69e6aba1134ed6714aa20fdb6bddb7738f8'
const tx = await client.getTransactionData(txId)
console.log(JSON.stringify(tx, null, 2))
const amount = assetToBase(assetAmount('0.01', 18))
expect(tx.asset.chain).toBe(AssetAVAX.chain)
expect(tx.asset.ticker).toBe(AssetAVAX.ticker)
expect(tx.asset.symbol).toBe(AssetAVAX.symbol)
expect(tx.type).toBe(TxType.Transfer)
expect(tx.from[0].from).toBe(client.getAddress(0))
expect(tx.from[0].amount.amount().toFixed()).toBe(amount.amount().toFixed())
expect(tx.to[0].to).toBe(client.getAddress(1))
expect(tx.to[0].amount.amount().toFixed()).toBe(amount.amount().toFixed())
expect(tx.hash).toBe(txId)
})

it('should transfer 0.01 AVAX between wallet 0 and 1, with a memo', async () => {
const recipient = client.getAddress(1)
const amount = assetToBase(assetAmount('0.01', 18))
const memo = '=:BNB.BUSD-BD1:bnb1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx:100000000000'
const txHash = await client.transfer({ amount, recipient, memo })
console.log(txHash)
})
it('should transfer 0.01 RIP(ERC-20) between wallet 0 and 1, with a memo', async () => {
const recipient = client.getAddress(1)
const amount = assetToBase(assetAmount('0.01', 18))
//ERC20 address The Crypt (RIP)

const memo = '=:BNB.BUSD-BD1:bnb1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx:100000000000'
const txHash = await client.transfer({ amount, recipient, asset: assetRIP, memo })
console.log(txHash)
})
it('should test erc-20 approvals ', async () => {
let isApproved = false
// check if approved for 1 RIP, should be false
const params: IsApprovedParams = {
contractAddress: '0x224695Ba2a98E4a096a519B503336E06D9116E48', //ERC20 address The Crypt (RIP)
spenderAddress: '0x688d21b0b8dc35971af58cff1f7bf65639937860', //PangolinRouter contract on testnet
amount: assetToBase(assetAmount('1', 18)),
}
isApproved = await client.isApproved(params)
expect(isApproved).toBe(false)

// approve for 1 RIP
const approveParams: ApproveParams = {
contractAddress: '0x224695Ba2a98E4a096a519B503336E06D9116E48', //ERC20 address The Crypt (RIP)
spenderAddress: '0x688d21b0b8dc35971af58cff1f7bf65639937860', //PangolinRouter contract on testnet
amount: assetToBase(assetAmount('1', 18)),
walletIndex: 0,
}
await client.approve(approveParams)
await delay(10_000) //wait 10 secs for block to be mined

// check if approved for 1 RIP, should be true
isApproved = await client.isApproved(params)
expect(isApproved).toBe(true)

// set approve below 1 rip
approveParams.amount = assetToBase(assetAmount('0.1', 18))
await client.approve(approveParams)
await delay(10_000) //wait 10 secs for block to be mined

// check if approved for 1 RIP, should be false
isApproved = await client.isApproved(params)
expect(isApproved).toBe(false)
})
it('should test estimates ', async () => {
const estimateParams: EstimateApproveParams = {
fromAddress: client.getAddress(0),
contractAddress: '0x224695Ba2a98E4a096a519B503336E06D9116E48', //ERC20 address The Crypt (RIP)
spenderAddress: '0x688d21b0b8dc35971af58cff1f7bf65639937860', //PangolinRouter contract on testnet
amount: assetToBase(assetAmount('1', 18)),
}
const gasEstimate = await client.estimateApprove(estimateParams)
console.log(gasEstimate.toString())
expect(gasEstimate.gte(0)).toBe(true)

const recipient = client.getAddress(1)
const amount = assetToBase(assetAmount('0.01', 18))
const memo = '=:BNB.BUSD-BD1:bnb1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx:100000000000'
const gasEstimateWithMemo = await client.estimateFeesWithGasPricesAndLimits({ amount, recipient, memo })
const gasEstimateWithoutMemo = await client.estimateFeesWithGasPricesAndLimits({ amount, recipient })
expect(gasEstimateWithMemo.gasLimit.gte(gasEstimateWithoutMemo.gasLimit)).toBe(true)
expect(gasEstimateWithMemo.fees.average.gte(gasEstimateWithoutMemo.fees.average)).toBe(true)

const gasPrices = await client.estimateGasPrices()
expect(gasPrices.fast.gte(gasPrices.average)).toBe(true)
expect(gasPrices.fastest.gte(gasPrices.average)).toBe(true)
expect(gasPrices.fastest.gte(gasPrices.fast)).toBe(true)
})
})
54 changes: 54 additions & 0 deletions packages/xchain-avax/__e2e__/etherscan-provider.e2e.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
// import { Network, TxType } from '@xchainjs/xchain-client'
import { AssetAVAX, Chain, assetToString } from '@xchainjs/xchain-util'
import { ethers } from 'ethers'

import { EtherscanProvider } from '../src/providers/etherscan/etherscan-data-provider'
// =====Erc-20 asset=====

// const assetRIP: Asset = {
// chain: Chain.Avalanche,
// symbol: `RIP-0x224695Ba2a98E4a096a519B503336E06D9116E48`,
// ticker: `RIP`,
// synth: false,
// }

// =====Ethers providers=====
// const AVALANCHE_MAINNET_ETHERS_PROVIDER = new ethers.providers.JsonRpcProvider('https://api.avax.network/ext/bc/C/rpc')
const AVALANCHE_TESTNET_ETHERS_PROVIDER = new ethers.providers.JsonRpcProvider(
'https://api.avax-test.network/ext/bc/C/rpc',
)
const provider = new EtherscanProvider(
AVALANCHE_TESTNET_ETHERS_PROVIDER,
'https://api-testnet.snowtrace.io',
'fake',
Chain.Avalanche,
AssetAVAX,
18,
)

// function delay(ms: number) {
// return new Promise((resolve) => setTimeout(resolve, ms))
// }
describe('etherscan Integration Tests', () => {
it('should fetch all balances', async () => {
const balances = await provider.getBalance('0xf32DA51880374201852057009c4c4d1e75949e09')
balances.forEach((bal) => {
console.log(`${assetToString(bal.asset)} = ${bal.amount.amount()}`)
})
expect(balances.length).toBeGreaterThan(0)
})
it('should fetch all balances 2', async () => {
const balances = await provider.getBalance('0x55aEd0ce035883626e536254dda2F23a5b5D977f')
balances.forEach((bal) => {
console.log(`${assetToString(bal.asset)} = ${bal.amount.amount()}`)
})
expect(balances.length).toBeGreaterThan(10)
})
it('should fetch alltxs', async () => {
const txs = await provider.getTransactions({ address: '0x55aEd0ce035883626e536254dda2F23a5b5D977f' })
txs.txs.forEach((tx) => {
console.log(JSON.stringify(tx))
})
expect(txs.total).toBeGreaterThan(10)
})
})
7 changes: 7 additions & 0 deletions packages/xchain-avax/jest.config.e2e.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
module.exports = {
preset: 'ts-jest',
testEnvironment: 'node',
testPathIgnorePatterns: ['<rootDir>/node_modules', '<rootDir>/lib'],
testMatch: ['<rootDir>/__e2e__/**/*.[jt]s?(x)'],
setupFilesAfterEnv: ['./jest.setup.js'],
}
6 changes: 6 additions & 0 deletions packages/xchain-avax/jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
module.exports = {
preset: 'ts-jest',
testEnvironment: 'node',
testPathIgnorePatterns: ['<rootDir>/node_modules', '<rootDir>/lib'],
setupFilesAfterEnv: ['./jest.setup.js'],
}
1 change: 1 addition & 0 deletions packages/xchain-avax/jest.setup.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
jest.setTimeout(60000)
53 changes: 53 additions & 0 deletions packages/xchain-avax/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
{
"name": "@xchainjs/xchain-avax",
"version": "0.1.0-alpha",
"description": "Avax EVM client for XChainJS",
"keywords": [
"XChain",
"Ethereum Virtual Machine"
],
"author": "XChainJS",
"homepage": "https://github.com/xchainjs/xchainjs-lib",
"license": "MIT",
"main": "lib/index.js",
"module": "lib/index.esm.js",
"typings": "lib/index.d.ts",
"directories": {
"lib": "lib",
"test": "__tests__"
},
"files": [
"lib"
],
"repository": {
"type": "git",
"url": "git@github.com:xchainjs/xchainjs-lib.git"
},
"scripts": {
"clean": "rimraf lib/**",
"build": "yarn clean && rollup -c rollup.config.ts",
"test": "jest --passWithNoTests",
"e2e": "jest --config jest.config.e2e.js",
"lint": "eslint \"{src,__tests__, __mocks__}/**/*.ts\" --fix --max-warnings 0",
"prepublishOnly": "yarn build"
},
"publishConfig": {
"access": "public"
},
"devDependencies": {
"@xchainjs/xchain-client": "^0.12.0",
"@xchainjs/xchain-crypto": "^0.2.6",
"@xchainjs/xchain-evm": "^0.1.0-alpha",
"@xchainjs/xchain-util": "^0.8.0",
"axios": "^0.25.0",
"ethers": "^5.6.6"
},
"peerDependencies": {
"@xchainjs/xchain-client": "^0.12.0",
"@xchainjs/xchain-crypto": "^0.2.6",
"@xchainjs/xchain-evm": "^0.1.0-alpha",
"@xchainjs/xchain-util": "^0.8.0",
"axios": "^0.25.0",
"ethers": "^5.6.6"
}
}
Loading

0 comments on commit da834f0

Please sign in to comment.