Skip to content

Instantly share code, notes, and snippets.

@gamalielhere
Last active April 26, 2018 20:46
Show Gist options
  • Save gamalielhere/0ed7aeaef9e8e8c17fed9dd6d3db2b62 to your computer and use it in GitHub Desktop.
Save gamalielhere/0ed7aeaef9e8e8c17fed9dd6d3db2b62 to your computer and use it in GitHub Desktop.
Figures out what tokens are missing from the MEW token contract
GET_TOKEN_DEFAULT_PARAM='' // Data object for getAllBAlance for the contract
CONTRACT_ADDRESS='' // Contract address
TOKEN_LIST_SRC='' // Token list source
PRIV='' // account private key
RPC='' // Node you're connecting to
GAS_PRICE = 0
GAS = 0
require("dotenv").config();
const fs = require("fs");
const Web3 = require("web3");
const fetch = require("node-fetch");
const BigNumber = require("bignumber.js");
const abi = require("./contractABI.js");
const ethUtil = require("ethereumjs-util");
const ethTx = require("ethereumjs-tx");
const privateKey = Buffer.from(process.env.PRIV, 'hex');
let web3 = new Web3();
web3.setProvider(new web3.providers.HttpProvider(process.env.RPC));
function getDataString(func, inputs) {
return web3.eth.abi.encodeFunctionCall(func, inputs);
}
function sizeHex(bytes) {
return bytes * 2;
}
function sortAlphabetically(a, b) {
const first = a.symbol.toUpperCase();
const second = b.symbol.toUpperCase();
return first < second ? -1 : first > second ? 1 : 0;
}
function trim(str) {
return str.replace(/\0[\s\S]*$/g, "");
}
function getAscii(hex) {
hex = hex.substring(0, 2) === "0x" ? hex : "0x" + hex;
return trim(web3.utils.hexToAscii(hex));
}
function parseContractToken(hex) {
let tokens = [];
hex = hex.substring(0, 2) === "0x" ? hex.substring(2) : hex;
hex = hex.substring(0, hex.lastIndexOf("1") - 1); //starting point
let offset = hex.length;
offset -= sizeHex(32);
let countTokens = hex.substr(offset, sizeHex(32));
offset -= sizeHex(1);
let isName = parseInt(hex.substr(offset, sizeHex(1)));
offset -= sizeHex(1);
let isWebSite = parseInt(hex.substr(offset, sizeHex(1)));
offset -= sizeHex(1);
let isEmail = parseInt(hex.substr(offset, sizeHex(1)));
let numTokens = new BigNumber("0x" + countTokens).toNumber();
for (var i = 0; i < parseInt(numTokens); i++) {
var token = {};
offset -= sizeHex(16);
token.symbol = getAscii(hex.substr(offset, sizeHex(16)));
offset -= sizeHex(20);
token.addr = "0x" + hex.substr(offset, sizeHex(20));
offset -= sizeHex(8);
token.decimals = new BigNumber(
"0x" + hex.substr(offset, sizeHex(8))
).toNumber();
offset -= sizeHex(32);
token.balance = new BigNumber(
"0x" + hex.substr(offset, sizeHex(32))
).toFixed();
if (isName) {
offset -= sizeHex(16);
token.name = getAscii(hex.substr(offset, sizeHex(16)));
}
if (isWebSite) {
offset -= sizeHex(32);
token.website = getAscii(hex.substr(offset, sizeHex(32)));
}
if (isEmail) {
offset -= sizeHex(32);
token.email = getAscii(hex.substr(offset, sizeHex(32)));
}
tokens.push(token);
}
return tokens;
}
async function getMEWTokens() {
const response = await fetch(process.env.TOKEN_LIST_SRC);
const mewTokens = await response.json();
return mewTokens;
}
async function getContractTokens() {
const newTokens = await web3.eth
.call({
to: process.env.CONTRACT_ADDRESS,
data: process.env.GET_TOKEN_DEFAULT_PARAM
})
.then(function(res) {
return parseContractToken(res);
})
.catch(function(err) {
throw err;
});
return newTokens;
}
var getHex = (str) => {
return '0x' + Buffer.from(str, 'utf8').toString('hex')
}
async function differenceTokenList(arr) {
if(arr.length > 0) {
this.tokensAbi = {};
for (var i in abi) this.tokensAbi[abi[i].name] = abi[i];
fs.writeFileSync('./notInContractTokens.json', JSON.stringify(arr));
const FROM =
"0x" + ethUtil.privateToAddress("0x"+process.env.PRIV).toString("hex");
for (let i = 0; i < arr.length; i++) {
let txCount = await web3.eth.getTransactionCount(FROM);
let name = getHex(arr[i].name);
let symbol = getHex(arr[i].symbol);
let address = arr[i].address;
let decimal = arr[i].decimals;
let website = getHex(arr[i].website);
let email = getHex(arr[i].support.email);
let dataStr = getDataString(this.tokensAbi.addSetToken, [name, symbol, address, decimal, website, email]);
const params = {
nonce: web3.utils.toHex(txCount + i),
gasPrice: web3.utils.toHex(process.env.GAS_PRICE),
gasLimit: web3.utils.toHex(process.env.GAS),
to: web3.utils.toHex(process.env.CONTRACT_ADDRESS),
value: '0x0',
data: dataStr,
chainId: 1
}
const tx = new ethTx(params);
tx.sign(privateKey);
const serializedTx = tx.serialize();
const actualTransactionParams = '0x' + serializedTx.toString('hex');
new Promise(function(resolve, reject) {
web3.eth.sendSignedTransaction(actualTransactionParams).on('transactionHash',function(hash){
console.log("Added token " + (arr[i].name, hash);
resolve();
}).catch(function(err) {
console.log(err.message);
resolve();
})
})
}
}
}
async function run() {
const mewTokens = await getMEWTokens();
const contractTokens = await getContractTokens();
let diffTokens = [];
mewTokens.forEach(function(mToken) {
if (
!contractTokens.find(function(cToken) {
return (
web3.utils.toChecksumAddress(cToken.addr) ===
web3.utils.toChecksumAddress(mToken.address)
);
})
) {
diffTokens.push(mToken);
}
});
diffTokens.sort(sortAlphabetically);
differenceTokenList(diffTokens);
}
run();
{
"name": "token-contract",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "node index.js"
},
"author": "",
"license": "ISC",
"devDependencies": {
"ethereumjs-tx": "^1.3.4",
"node-fetch": "^2.1.2",
"utf8": "^3.0.0",
"web3": "^1.0.0-beta.34"
},
"dependencies": {
"bignumber.js": "^4.0.2",
"dotenv": "^5.0.1",
"ethereumjs-util": "^5.1.5"
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment