Skip to content

Commit

Permalink
migrating javascript to typescript
Browse files Browse the repository at this point in the history
  • Loading branch information
kenryu42 committed Jul 30, 2022
1 parent 278722b commit 689401a
Show file tree
Hide file tree
Showing 33 changed files with 493 additions and 447 deletions.
3 changes: 2 additions & 1 deletion .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,6 @@
"linebreak-style": ["error", "unix"],
"quotes": ["error", "single"],
"semi": ["error", "always"]
}
},
"ignorePatterns": ["node_modules/", "dist/"]
}
1 change: 1 addition & 0 deletions .github/workflows/run-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ on:
push:
branches:
- main
- typescript
- 'releases/*'

jobs:
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
node_modules/
dist/
.env
.DS_Store
9 changes: 9 additions & 0 deletions .mocharc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"diff": true,
"retries": 1,
"recursive": true,
"extension": ["ts"],
"timeout": "180000",
"check-leaks": true,
"node-option": ["experimental-specifier-resolution=node", "loader=ts-node/esm", "no-warnings"]
}
1 change: 1 addition & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
dist
12 changes: 6 additions & 6 deletions .prettierrc
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
{
"semi": true,
"trailingComma": "none",
"singleQuote": true,
"printWidth": 100,
"tabWidth": 4,
"useTabs": false
"semi": true,
"trailingComma": "none",
"singleQuote": true,
"printWidth": 100,
"tabWidth": 4,
"useTabs": false
}
33 changes: 22 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,9 @@
<li><a href="#multi-monitoring">Multi Monitoring</a></li>
</ul>
</li>
<li><a href="#run-test">Run Test</a></li>
<li><a href="#usage">Usage</a></li>
<li><a href="#run-test">Run Test</a></li>
<li><a href="#run-fix">Run Fix</a></li>
<li>
<a href="#notify-method">Notify Method</a>
<ul>
Expand Down Expand Up @@ -165,30 +166,40 @@ If `CONTRACT_ADDRESS` and `CONTRACT_ADDRESSES` are both set, `CONTRACT_ADDRESSES

<p align="right">(<a href="#top">back to top</a>)</p>

## Run Test
## Usage

To ensure your configuration(`.env`) is correct, run the following command:
Run the following command to start the bot:

```bash
npm test
npm start
```

The test should take less than 2 minutes to run. If it fails, either APIs are down or your configuration is incorrect.
To test a certain transaction for debugging purposes, run the following command:

```
npm run debug -- <transaction-hash>
```

<p align="right">(<a href="#top">back to top</a>)</p>

## Usage
## Run Test

Run the following command to start the bot:
To ensure your configuration(`.env`) is correct, run the following command:

```bash
node app.js
npm test
```

To test a certain transaction for debugging purposes, run the following command:
The test should take less than 3 minutes to run. If it fails, either APIs are down or your configuration is incorrect.

```
node app.js -t <transaction-hash>
<p align="right">(<a href="#top">back to top</a>)</p>

## Run Fix

To format code and fix linting errors, run the following command:

```bash
npm run fix
```

<p align="right">(<a href="#top">back to top</a>)</p>
Expand Down
13 changes: 9 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,19 @@
"name": "ethereum-nft-sales-bot",
"version": "1.0.0",
"description": "An ethereum NFT sales monitoring bot.",
"main": "app.ts",
"main": "src/app.js",
"type": "module",
"scripts": {
"clean": "rm -rf dist",
"build": "npm run clean && npx tsc",
"start": "npm run build && node --no-warnings dist/app.js",
"debug": "node --no-warnings dist/app.js -t",
"format": "prettier --write '**/*.{js,jsx,ts,tsx}'",
"lint": "eslint '**/*.{js,jsx,ts,tsx}' --ext .ts",
"fix": "npm run format && npm run lint",
"unit": "npx mocha -r ts-node/register test/unit/* --timeout 120000",
"integration": "npx mocha -r ts-node/register test/integration/* --timeout 240000",
"test": "npx mocha -r ts-node/register test/unit/* test/integration/* --timeout 360000"
"unit": "npx mocha test/unit/*",
"integration": "npx mocha test/integration/*",
"test": "npm run unit && npm run integration"
},
"repository": {
"type": "git",
Expand Down
31 changes: 18 additions & 13 deletions app.ts → src/app.ts
Original file line number Diff line number Diff line change
@@ -1,33 +1,37 @@
import { runApp } from './controllers/runApp';
import { runApp } from './controllers/runApp.js';
import {
WEB3,
ABI,
TOKEN_TYPE,
ALCHEMY_API_KEY,
CONTRACT_ADDRESS,
CONTRACT_ADDRESSES,
DEFAULT_NFT_API
} from './config/setup';
} from './config/setup.js';
import { AbiItem } from 'web3-utils';
import { options } from './config/commander';
import { getContractData } from './utils/api';
import { options } from './config/commander.js';
import { getContractData } from './utils/api.js';
import { EventData } from 'web3-eth-contract';
import { ContractData } from './types/types';
import { HttpProvider } from 'web3-core';
import { createAlchemyWeb3 } from '@alch/alchemy-web3';

let lastTransactionHash: string;
const web3 = createAlchemyWeb3(`wss://eth-mainnet.alchemyapi.io/v2/${ALCHEMY_API_KEY}`);

console.log(`Default NFT Api: ${DEFAULT_NFT_API}`);

async function main(contractAddress: string) {
const contractData: ContractData = await getContractData(contractAddress);
const tokenType = contractData!.tokenType === 'unknown' ? TOKEN_TYPE : contractData!.tokenType;
// if (!contractData) return;
const tokenType = contractData.tokenType === 'unknown' ? TOKEN_TYPE : contractData.tokenType;

if (tokenType !== 'ERC721' && tokenType !== 'ERC1155') {
console.log(contractData);
console.log('Alchemy getContractMetadata api cannot get the correct token type.');
console.log('Please enter the TOKEN_TYPE in (file:./.env)');
process.exit(1);
}
const contract = new WEB3.eth.Contract(ABI as AbiItem[], contractAddress);
const contract = new web3.eth.Contract(ABI as AbiItem[], contractAddress);

const transferEvents =
tokenType === 'ERC721'
Expand All @@ -40,9 +44,7 @@ async function main(contractAddress: string) {
.on('connected', (subscription_id: string) => {
console.log(`Subscription ID: ${subscription_id}`);
console.log(
`Listening to ${tokenType} ${eventType[i]} events on collection: ${
contractData!.name
}`
`Listening to ${tokenType} ${eventType[i]} events on collection: ${contractData.name}`
);
console.log(`Contract address: ${contractAddress}\n`);
})
Expand All @@ -52,7 +54,7 @@ async function main(contractAddress: string) {
if (transactionHash == lastTransactionHash) return;
lastTransactionHash = transactionHash;

await runApp(WEB3, transactionHash, contractAddress, contractData);
await runApp(web3, transactionHash, contractAddress, contractData);
})
.on('error', (error: Error) => {
console.error(error);
Expand All @@ -74,8 +76,11 @@ async function main(contractAddress: string) {
process.exit(1);
}
console.log(`Running test for tx: ${options.test}`);
await runApp(WEB3, options.test, CONTRACT_ADDRESS, contractData);
process.exit(0);
await runApp(web3, options.test, CONTRACT_ADDRESS, contractData);

const provider = web3.currentProvider as HttpProvider;

provider.disconnect();
} catch (error) {
console.error(error);
process.exit(1);
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
9 changes: 2 additions & 7 deletions config/setup.ts → src/config/setup.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import 'dotenv/config';
import { createAlchemyWeb3 } from '@alch/alchemy-web3';
import ABI from './abi.json';
import NFT_TRADER_ABI from './NFTTraderSwap.json';
import ABI from './abi.json' assert { type: 'json' };
import NFT_TRADER_ABI from './NFTTraderSwap.json' assert { type: 'json' };

// Required settings
const CONTRACT_ADDRESS = process.env.CONTRACT_ADDRESS
Expand Down Expand Up @@ -38,9 +37,6 @@ const DISCORD_ENABLED = process.env.DISCORD_ENABLED === '1';
const WEBHOOK_1 = process.env.WEBHOOK_URL || '';
const WEBHOOK_URLS = [WEBHOOK_1].filter((url) => url !== '');

// Alchemy provider settings
const WEB3 = createAlchemyWeb3(`wss://eth-mainnet.alchemyapi.io/v2/${ALCHEMY_API_KEY}`);

// Error handler for configuration
const checkConfig = (config: {
CONTRACT: [string, string];
Expand Down Expand Up @@ -85,7 +81,6 @@ checkConfig({

export {
ABI,
WEB3,
NFT_TRADER_ABI,
DEFAULT_NFT_API,
WEBHOOK_URLS,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,16 @@ import { AlchemyWeb3 } from '@alch/alchemy-web3';
import { Log } from 'web3-core';
import { AbiItem } from 'web3-utils';
import { ethers } from 'ethers';
import { NFT_TRADER_ABI } from '../config/setup';
import { TransactionData } from '../types/types';
import { getReadableName } from '../utils/api';
import { NFT_TRADER_ABI } from '../config/setup.js';
import { TransactionData, SwapEvent } from '../types/types';
import { getReadableName } from '../utils/api.js';

const parseNftTrader = async (
tx: TransactionData,
web3: AlchemyWeb3,
log: Log,
logAddress: string,
decodedLogData: any
decodedLogData: SwapEvent
) => {
const swapStatus = String(web3.eth.abi.decodeParameter('uint8', log.topics[3]));
// if tx.swap status is not 1 (closed), then skip parsing.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { transferEventTypes } from '../config/logEventTypes';
import { transferEventTypes } from '../config/logEventTypes.js';
import _ from 'lodash';
import { TransactionData } from '../types/types';
import { Log } from 'web3-core';
import { AlchemyWeb3 } from '@alch/alchemy-web3';

const parseSaleToken = (tx: TransactionData, web3: AlchemyWeb3, log: any, logAddress: string) => {
const parseSaleToken = (tx: TransactionData, web3: AlchemyWeb3, log: Log, logAddress: string) => {
if (
log.data === '0x' &&
transferEventTypes[tx.tokenType as keyof typeof transferEventTypes] === log.topics[0] &&
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { ethers } from 'ethers';
import { currencies } from '../config/currencies';
import { currencies } from '../config/currencies.js';
import {
Market,
TransactionData,
SeaportOrder,
OfferItem,
ConsiderationItem
} from '../types/types';
import { formatPrice } from '../utils/api';
import { formatPrice } from '../utils/api.js';

const parseSeaport = (tx: TransactionData, logMarket: Market, decodedLogData: SeaportOrder) => {
const offer = decodedLogData.offer;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { Log } from 'web3-core';
import { AlchemyWeb3 } from '@alch/alchemy-web3';
import { transferEventTypes } from '../config/logEventTypes';
import { TransactionData } from '../types/types';
import { transferEventTypes } from '../config/logEventTypes.js';

const parseSwapToken = (tx: TransactionData, web3: AlchemyWeb3, log: any, logAddress: string) => {
const parseSwapToken = (tx: TransactionData, web3: AlchemyWeb3, log: Log, logAddress: string) => {
if (tx.isSwap && transferEventTypes['ERC721'] === log.topics[0]) {
const receivedAddr = web3.eth.abi.decodeParameter('address', log.topics[2]).toLowerCase();

Expand Down Expand Up @@ -39,15 +40,15 @@ const parseSwapToken = (tx: TransactionData, web3: AlchemyWeb3, log: any, logAdd
? tx.swap[receivedAddr].receivedAssets.push({
tokenId: decodeData.ids[i],
tokenType: 'ERC1155',
quantity: decodeData.values[i],
quantity: Number(decodeData.values[i]),
contractAddress: logAddress
})
: (tx.swap[receivedAddr] = {
receivedAssets: [
{
tokenId: decodeData.ids[i],
tokenType: 'ERC1155',
quantity: decodeData.values[i],
quantity: Number(decodeData.values[i]),
contractAddress: logAddress
}
]
Expand Down
Loading

0 comments on commit 689401a

Please sign in to comment.