{"id":27944062,"url":"https://github.com/ar-to/ethereum-api","last_synced_at":"2026-03-08T19:36:56.225Z","repository":{"id":65387516,"uuid":"132175610","full_name":"ar-to/ethereum-api","owner":"ar-to","description":"This project implements an ERC20 ethereum token and the web3 ethereum client into a REST API using an express/nodejs server","archived":false,"fork":false,"pushed_at":"2018-10-15T22:44:51.000Z","size":295,"stargazers_count":21,"open_issues_count":0,"forks_count":18,"subscribers_count":3,"default_branch":"master","last_synced_at":"2024-05-21T07:55:33.369Z","etag":null,"topics":["erc20-token","ethereum","ethereum-token","expressjs-api","ganache","nodemon","openzeppelin","truffle"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ar-to.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-05-04T18:29:19.000Z","updated_at":"2024-02-03T17:16:52.000Z","dependencies_parsed_at":"2023-01-20T22:15:21.236Z","dependency_job_id":null,"html_url":"https://github.com/ar-to/ethereum-api","commit_stats":null,"previous_names":[],"tags_count":9,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ar-to%2Fethereum-api","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ar-to%2Fethereum-api/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ar-to%2Fethereum-api/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ar-to%2Fethereum-api/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ar-to","download_url":"https://codeload.github.com/ar-to/ethereum-api/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252874205,"owners_count":21817780,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["erc20-token","ethereum","ethereum-token","expressjs-api","ganache","nodemon","openzeppelin","truffle"],"created_at":"2025-05-07T12:21:23.269Z","updated_at":"2026-03-08T19:36:56.188Z","avatar_url":"https://github.com/ar-to.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Ethereum/Token API\n\n## Table of Contents\n\n- [Quick Start](#quick-start)\n- Getting Started\n  - [Run Private Test Node](#run-private-test-node)\n  - [Config](#config)\n  - [Environment Variables](#environment-variablese)\n  - [Truffle Token Contract](#truffle-token-contract)\n  - [Development local node](#development-local-node)\n  - [Testnet node](#testnet-node)\n  - [Run truffle commands](#run-truffle-commands)\n  - [Server](#server)\n  - [Adding Networks](#adding-networks)\n- [Notes](#notes)\n    - [Token](#token)\n    - [Ethereum](#ethereum)\n- [Scripts](#scripts)\n- [Bash](#bash)\n- [Helpers](#helpers)\n- [Keystore](#keystore)\n- [Error Debugging](#error-debugging)\n- [Sample Contracts](#sample-contracts)\n- [Version Control]($version-control)\n- [Connections](#Connections)\n- [Bugs to Fix](#bugs-to-fix)\n- [Improvements](#improvements)\n- [ERC20 Token Endpoint Notes](#erc20-token-endpoint-notes)\n    - [Owner Token API](#owner-token-api)\n    - [ERC20 Multi-Token API](#erc20-multi-token-api)\n        - [Setup](#setup)\n        - [Get Balance](#get-balance)\n        - [Transfer](#transfer)\n    - [Token Transaction Verification](#token-transaction-verification)\n  - [Ethereum Endpoint Notes](#ethereum-endpoint-notes)\n      - [Get Block Info](#get-block-info)\n      - [Create address](#create-address)\n      - [Get Transaction Info](#get-transaction-info)\n      - [Send Transaction](#send-transaction)\n      - [Sign and Send Manually](#sign-and-send-manually)\n          - [Get Transaction Info](#get-transaction-info)\n          - [Sign Transaction](#sign-transaction)\n          - [Send Signed Transaction](#send-signed-transaction)\n- [Webhook](#webhook)\n- [Websockets](#websockets)\n- [List of All API Endpoints](#endpoints)\n\n## Quick Start\n\nInstall [Ganache](http://truffleframework.com/ganache/) to have a local blockchain and start it. You will see 10 address and a mnemonic phrase. Copy `RPC Server` URL, e.g `HTTP://127.0.0.1:7545`\n\n```\nbrew cask install ganache\n```\n\nCreate `.env` in root\n\n```\nNODE_URL=http://127.0.0.1:7545\n```\n\nClone repo and start server\n\n```\ngit clone git@github.com:ar-to/ethereum-api.git\ncd ethereum-api\nnpm install\nnpm start\n```\nin new terminal check if connected and what accounts you have on the node\n```\ncurl http://localhost:3000/api/eth/syncing\n{\"nodeSynced\":true}\nhttp://localhost:3000/api/eth/accounts\n{\"accounts\":[\"0xAb7faf7bDAE1B9D0F757e2a8aB120619b388C4c6\",\"0x451E62137891156215d9D58BeDdc6dE3f30218e7\",\"0x22B55D4cc5cE3E32Ee31B0684172E2BCE9F722e7\",\"0x71c9625B0005F20d264775cfF8fc9FB1BEf96525\",\"0x48E5A9807A1C862CeB00a9867c1b57dF02b8F1Fe\",\"0xb7B3FaD7d81C5D2e09Dc464Fec36AC6b4e1B04d3\",\"0x16e665134A1A3b048b2d9aFdB612Bd34CAc0F35C\",\"0xcCFf4FEa69126b9E2c7ce02d69d7c5205657e722\",\"0x032D0Fa0AD21aa5a50C6c6e13D9d14a9550457C5\",\"0x20032730927fB07C46e20FD3725C1f77b04cd4ee\"]}\n```\n\n\n## Getting Started\n\nPlease read [notes](#notes) for important information before developing.\n\n\n### Run Private Test Node\n\nThe easiest method to run a local private ethereum node that will also mine blocks to facilitate creating transactions and to tests this api is via [Ganache](http://truffleframework.com/ganache/) GUI application. \n\n```\nbrew cask install ganache\n```\nOpen application and it will automatically create 10 addresses. Save the mnemonic phrase if you want to use it again. It will be set the url to `http://127.0.0.1:7545`\n\n### Config\nAdd connections to `config/connections.json`, and set the name of the network you want to use for the API using `\"connectApi\": \"network-name\",`\n\n```\n{\n  \"networks\": {\n    \"connectApi\": \"ganache\",\n    \"ganache\":{\n      \"url\": \"http://127.0.0.1:7545\",\n      \"networkId\": \"5777\",\n      \"networkName\": \"ganache\",\n      \"networkType\": \"testrpc\",\n      \"token\": {\n        \"ownerAddress\": \"0x451E62137891156215d9D58BeDdc6dE3f30218e7\",\n        \"tokenContractAddress\": \"0x4c59b696552863429d25917b52263532af6e6078\",\n        \"migrateContractAddress\": \"0xcf068555df7eab0a9bad97829aa1a187bbffbdba\"\n      },\n      \"erc20Tokens\": []\n    },\n    \"ropsten\":{},\n    \"mainnet\":{}\n  }\n}\n```\n\nCopy the same parameters from ganache above to other networks.\n\n### Environment Variables\n\nYou can change the port for the server and overwrite the node url from the connections.json by adding it in a `.env` file at the root directory.\n\n```\nPORT=4000\nNODE_URL=http://127.0.0.1:7545\n```\n\n**Remember to restart your server after changing environment variables. If running nodemon run `npm run nodemon` again**\n\n### Truffle Token Contract\n\nThis requires familiarization with truffle framework and open-zeppelin for making ERC20 token contracts.\n\n#### Development local node\n\nFirst add the same OWNER_ACCOUNT address from the environment variable into the `truffle.js` file `from` parameter so the owner to the contract is set to this address when deployed.\n\n```\n  networks: {\n    development: {\n      host: \"127.0.0.1\",\n      port: 7545,\n      network_id: \"*\", // Match any network id\n      from: \"0x451E62137891156215d9D58BeDdc6dE3f30218e7\"\n    },\n  }\n```\n\n#### Testnet node \n\n(e.g. Ropsten, etc)\n\nSee section on adding new networks\n\n#### Run truffle commands\nMake sure you have truffle installed glabally before trying these commands.\n\nRun Compile when changes are made to the `token-contract/contracts` directory.\n```\nbash bin/truffle-compile\n```\n\nRun Migrate to deploy contract to node. Truffle will migrate new deployments inside `token-contract/migrations` directory but ignore those already sent.\n\n```\nbash bin/truffle-migrate\n```\n\nResetting to overwrite the existing contracts can be done with:\n```\nbash bin/truffle-migrate-reset\n```\nSee [scripts](#scripts) for all available scripts.\n\n**Remember to update the addresses in the `.env` file so the api will know which address to use for the token contract and owner.**\n\n### Server\n\nstart the server\n```\ngit clone url\ncd projectname\nnpm install\nnpm start\"\n```\nstart server with custom port and in debug mode\n```\nnpm run dev\n```\nTo run server and watch for changes and run debugger via `--inspect`\n```\nnpm run nodemon\n```\n\n## Adding Networks\n\nConfiguring testnets and mainnet is more complicated than with local nodes. You need to have a node that is connected to those blockchains and a url that is allowed to receive RPC calls. Then to connect it with this api, create a new JSON file for the network you are adding to `network-wallets/ropsten.config.json`\n\nThen copy the following configuration and change it with the appropriate keystore and password:\n```\n{\n  \"keystore\": {\n    \"address\": \"008aeeda4d805471df9b2a5b0f38a0c3bcba786b\"\n    \"crypto\" : {\n      \"cipher\" : \"aes-128-ctr\",\n      \"cipherparams\" : {\n          \"iv\" : \"83dbcc02d8ccb40e466191a123791e0e\"\n      },\n      \"ciphertext\" : \"d172bf743a674da9cdad04534d56926ef8358534d458fffccd4e6ad2fbde479c\",\n      \"kdf\" : \"scrypt\",\n      \"kdfparams\" : {\n          \"dklen\" : 32,\n          \"n\" : 262144,\n          \"r\" : 1,\n          \"p\" : 8,\n          \"salt\" : \"ab0c7876052600dd703518d6fc3fe8984592145b591fc8fb5c6d43190334ba19\"\n      },\n      \"mac\" : \"2103ac29920d71da29f15d75b4a16dbe95cfd7ff8faea1056c33131d846e3097\"\n    },\n    \"id\" : \"3198bc9c-6672-5ab3-d995-4942343ae5b6\",\n    \"version\" : 3\n  },\n  \"password\": \"password\",\n  \"url\": \"http://127.0.0.1:8545\"\n}\n```\nRead about what is a [keystore](#keystore)\n\nThen inside `truffle.js` add the following to the top\n\n```\n// ROPSTEN testnet\nconst ropstenConfig = require(\"../network-wallets/ropsten.config.json\");\nvar ropstenProvider;\nif(ropstenConfig){\n  const keystore = ropstenConfig.keystore;\n  const pass = ropstenConfig.password;\n  const url = ropstenConfig.url\n  console.log('keystore', url)\n  var wallet = require('ethereumjs-wallet').fromV3(keystore, pass);\n  ropstenProvider = new WalletProvider(wallet, url);\n}\n```\n\nstill inside `truffle.js` add a new network:\n\n```\nropsten: {\n  provider: ropstenProvider,\n  network_id: '3',\n  gas: 2249435,\n  gasPrice: 20000000000,\n},\n```\nGrab the gas and gas price from [helpers](#helpers) directory, using the `token-contract/helpers/gasEstimate.js ` file.\n\nMigrate/deploy with truffle. You can also add a script inside `bin/`\n\n```\nbash bin/truffle-migrate-ropsten\n```\n\n**Do same for mainnet using `network-wallets/mainnet.config.json`**\n\n## Production\n\n[PM2](http://pm2.keymetrics.io/) is used to handle starting the server, watching for changes in the directories and restarting the server if it crashes. \n\nDeploy your repo file to a remote server and install pm2 globally\n\n```\nnpm i -g pm2@latest\ncd ethereum-api\nnpm install\nnpm run prod\n```\nThis runs `pm2 start ecosystem.config.js` which start the server and watches for changes.\n\nPm2 helpful commands\n\n- `pm2 logs API` - this shows the logs for requests and errors. You can see these logs in `~/.pm2/logs/API-error-0.log`\n- `pm2 show API` - shows information about process\n- `pm2 stop API` - this stops process.\n- `pm2 delete API` - delete process after its stopped.  NOTE: may be necessary if the server does not restart after files are updated\n\n**To restart server when machine reboots**\n\n## Notes\n\n1. This api uses web3 for interacting with the node, but manual curl commands can be used via [RPC calls](https://github.com/ethereum/wiki/wiki/JSON-RPC). Test the `bash bin/rpc-call` to test an rpc call.\n\n2. Install a solidity extension into your choosen editor when developing contracts\n\n3. the contracts are compiled into the `token-contract/build/contracts` directory and it was added to `/gitignore` as a **comment** to facilitate migrating new contracts during development when using a local private node. But when coming back to the default contract simply compile and migrate or migrate with reset to overwrite existing contracts. \n\n4. Extra directories: \n- `deployed-contracts` directory that can store the artifact files (e.g.abi, Token.json) if you want to keep different deployments to interact with your contracts in the future. Read [here](#vc) for storing contracts in version control.\n\n### Token\n\n1. This API is meant ot be used with an ERC20 token. Future release may add other tokens or feel free to experiment and pull request a new token.\n2. To use a custom abi for interacting with the erc20 add `\"customAbi\": \"abi.js\"` to the `config/connections.json`. The value refers to the name of the file (requires the extension) and this file need to be added inside the `deployed-contracts` directory.\n\n```\n\"customAbi\": \"abi.js\"\n```\n\n\n### Ethereum\n\n1. This api implement web3 v1.0 instead of manual rpc calls to the node.\n\n## Scripts\n\nScripts are added for convenience to allow commands to be performs from the root and for testing.\n\n- rpc-call - a curl command via an rpc call to communicated to a node. Remember to change the url:port to connect to the correct node and address when using the `eth_getBalance` method or pass it as an argument:\n```\nsh bin/rpc-call http://127.0.0.1:7545\n```\n\n- bash bin/truffle-compile\n\n- bash bin/truffle-migrate\n\n- bash bin/truffle-migrate-reset\n\n- bash bin/truffle-migrate-ropsten\n\n- bash bin/truffle-gas-estimate\n\n## Bash\nThere are scripts that perform operations and follow this tips to create new ones.\n\nCreate a new bash or node script \n```\n#!/usr/bin/env bash\n#!/usr/bin/env node\n```\n```\nchmod +x ./bin/newscript\n```\nAdd it to package.json is optional\n```\n  \"scripts\": {\n    \"script\": \"./bin/newscript\"\n  }\n```\n\n## Helpers\n\nThe `token-contract/helpers` directory has files that can help with contract,truffle or web3.\n\n- gasEstimate.js - estimate the gas, gas price and total gas that a contract will consume. This information is needed for deploying to testnets and mainnet. \n\nrun\n```\nbash bin/truffle-gas-estimate\n```\n\noutput:\n\n```\nUsing network 'development'.\n\nGas Price is 20000000000 wei\nGas Price is = 20 gwei\ngas estimation = 2249435 units\ngas cost estimation = 44988700000000000 wei\ngas cost estimation = 0.0449887 ether\n```\n\n## Keystore\n\nRead about what is a [keystore](https://medium.com/@julien.m./what-is-an-ethereum-keystore-file-86c8c5917b97) file and how to make one. Above keystore taken from [here](https://github.com/hashcat/hashcat/issues/1228) If using the geth client for creating your node, you can run `geth account new`, enter your password and check the `keystore/` directory for the keystore file. This directory is next to the chaindata where you are storing the blockchain data.\n\n## Error Debugging\n\nSetting up can be somewhat complicated if not tedious. Maybe in future releases there will be much more efficient way to setup but for now fixing and understanding error is best to guarantee everything is running correctly. Below are a few warnings or error you may see and possible ways to solve them. More added as they are found. Keep in mind error do not necessarily mean bugs, but it does not mean a bug is not present. If an error turns out to be a bug file an issue and your solution. Thanks.\n\n- `Invalid JSON RPC response: \"\"` - This may show as a response from testing the api endpoint the first time you are connecting to a node. It is a failure to connect by web3 provider. Solution:\n    1. restart your server\n    2. Check you have the correct node url inside the `.env` file\n    3. Make an RPC call to the node using the `bin/rpc-call` script to test for connection. See [scripts section](#scripts) for details\n    4. wait until the connection is successful and try the endpoint you got the error again\n- {package} `was compiled against a different Node.js version using` - best solution is to rebuild packages by first updating npm and node and then `npm rebuild`\n\n\n\n## Sample Contracts\n\nSample constracts are used for reference and can be found in `token-contract/samples`. \n\n- advancedToken.sol - sample token code that has been fixed to meet solidity v0.4.23. This can be tested by adding it into Mist app. Deploy using TokenERC20 token name.\n\n## Version Control\nQuestion about storing artifact files (e.g. Token.json) after truffle compiles contracts with abi and contract addresses for different networks. Community in gitter (chat app) recommended to add to VC but optional not to.\n\n- [stackexchange](https://ethereum.stackexchange.com/questions/19486/storing-a-truffle-contract-interface-in-version-control) - recommendation to store outside\n- [artifact-updates](https://github.com/trufflesuite/artifact-updates) - community repo for updating some issues with doing this.\n\n## Connections\n\nFull example of `connections.json` and available parameters\n\n```\n{\n  \"networks\": {\n    \"connectApi\": \"ropsten\",\n    \"ganache\":{\n      \"url\": \"http://127.0.0.1:7545\",\n      \"websocketUrl\": \"'ws://localhost:7545\",\n      \"networkId\": \"5777\",\n      \"networkName\": \"ganache\",\n      \"networkType\": \"testrpc\",\n      \"token\": {\n        \"ownerAddress\": \"0x451E62137891156215d9D58BeDdc6dE3f30218e7\",\n        \"tokenContractAddress\": \"0x4c59b696552863429d25917b52263532af6e6078\",\n        \"migrateContractAddress\": \"0xcf068555df7eab0a9bad97829aa1a187bbffbdba\"\n      }\n    },\n    \"ropsten\":{\n      \"url\": \"http://10.10.0.163:8545\",\n      \"websocketUrl\": \"ws://10.10.0.163:8546\",\n      \"blockWebhookUrl\": \"http://4f5a64ba.ngrok.io/api/eth/webhook\",\n      \"syncingWebhookUrl\": \"http://4f5a64ba.ngrok.io/api/eth/webhook\",\n      \"testWebhookUrl\": \"http://4f5a64ba.ngrok.io/api/eth/webhook\",\n      \"networkId\": 3,\n      \"networkName\": \"ropsten\",\n      \"networkType\": \"testnet\",\n      \"token\": {\n        \"ownerAddress\": \"0x83634a8eaadc34b860b4553e0daf1fac1cb43b1e\",\n        \"tokenContractAddress\": \"0x3e672122bfd3d6548ee1cc4f1fa111174e8465fb\",\n        \"migrateContractAddress\": \"0xa8ebf36b0a34acf98395bc5163103efc37621052\",\n        \"customAbi\": \"abi.js\"\n      },\n      \"erc20Tokens\": [\n        {\n          \"name\": \"threshodl\",\n          \"contractAddress\": \"0x3e672122bfd3d6548ee1cc4f1fa111174e8465fb\"\n        },\n        {\n          \"name\": \"golem\",\n          \"contractAddress\": \"0x9a0027f3c0fc4fab7825fcf50dd55dfdcca07cd6\"\n        },\n        {\n          \"name\": \"bokky\",\n          \"contractAddress\": \"0x583cbBb8a8443B38aBcC0c956beCe47340ea1367\"\n        }\n      ]\n    },\n    \"mainnet\":{}\n  }\n}\n```\n\n## Bugs to Fix\n\ntransferOwnership \u0026 kill functions both catch an 'invalid address'. The response it 200 with `false` boolean indicating request failed. \n\n- `api/eth/tx-from-block/hashStringOrNumber` endpoint seems to fail when connected to Ropsten Testnet but not with ganache local node\n\n- subscription does not seem to work and or do\n\n## Improvements\n\nThere is always room for improvement, but below is a list of tasks to tackle first.\n\n- error handling needs to be better and standarized. Using combination of promises/catch and try/catch but only some error are sent as a response, most stop the server and the requests gets timedout.\n- add a way to calculate default gas when transferring tokens for multi-token and owner-token apis\n- Get `transferFrom` branch working and debugged, which also included payments to the contract. This branch is for the owner api but can be integrated into the multi-tokens api once it works correctly.\n- Add unit tests via mocha, jest\n- Add logging via [winston package](https://github.com/winstonjs/winston) and rotate daily\n- setup a quick one command program that will create a private Ethereum node and connect node to it. Possible adding flags for the type (testnet, main, or specific network like ropsten). Test [bitcore](https://bitcore.io/) does this so test and use as reference on how  a config is setup and everything is created.\n- setup a docker container to quickly run server\n\n## ERC20 Token Endpoint Notes\n\nThere is currently two ways to communicate to tokens, both requiring erc20 tokens. The first is for general requests and owner specific requests. The second, is meant to communicate to multiple tokens by simply adding a name for the endpoint and the token contract used for communication. \n\n### Owner Token API\nThis api is used for communications with the erc20 contract deployed within this repo and given in the `connections.json`:\n\n```\n      \"token\": {\n        \"ownerAddress\": \"0x83634a8eaadc34b860b4553e0daf1fac1cb43b1e\",\n        \"tokenContractAddress\": \"0x3e672122bfd3d6548ee1cc4f1fa111174e8465fb\",\n\t...\n      },\n```\n\nThe paths that can be used that are specific to this api are:\n\n```\nhttp://localhost:3000/api/token/:options\n/owner\n/node-accounts\n/balance\n/balance/:address\n/owner\n/add-tokens/:amount\n/transfer-tokens\n/transfer-owner\n/kill-token\n```\n\n### ERC20 Multi-Token API\n\nThis API supports multiple erc20 token connections. This means, you can communicate to different tokens by simply changing a path parameter in the url. See the instructions below Below you change the `tokenName` and `erc20Method` and\n\nThe paths that this api features are below:\n```\nhttp://localhost:3000/api/token/:tokenName/:erc20Method\n/:tokenName\n/:tokenName/getbalance/:address\n/:tokenName/transfer\n/:tokenName/request-transfer\n```\n\n#### Setup \n\nAdd the `erc20Tokens` array parameter to the `config/connections.json` to add new tokens. Then add each new token as an object with a name and contractAddress parameter.\n\n```\n{\n  \"networks\": {\n    \"connectApi\": \"ropsten\",\n    \"ganache\":{\n...\n    },\n    \"ropsten\":{\n...\n      \"token\": {\n...\n      },\n      \"erc20Tokens\": [\n        {\n          \"name\": \"threshodl\",\n          \"contractAddress\": \"0x3e672122bfd3d6548ee1cc4f1fa111174e8465fb\"\n        },\n        {\n          \"name\": \"golem\",\n          \"contractAddress\": \"0x9a0027f3c0fc4fab7825fcf50dd55dfdcca07cd6\"\n        },\n        {\n          \"name\": \"bokky\",\n          \"contractAddress\": \"0x583cbBb8a8443B38aBcC0c956beCe47340ea1367\"\n        }\n      ]\n    },\n    \"mainnet\":{}\n  }\n}\n```\n\nThen test is by adding it the name path param\n\nRequest (GET method):\n```\nhttp://localhost:3000/api/token/threshodl\n```\n\nResponse:\n```\n{\n    \"method\": \"test\",\n    \"params\": {\n        \"tokenName\": \"threshodl\"\n    },\n    \"erc20Available\": [\n        {\n            \"name\": \"threshodl\",\n            \"contractAddress\": \"0x3e672122bfd3d6548ee1cc4f1fa111174e8465fb\"\n        }\n    ],\n    \"success\": \"Token threshodl is available on this api!\"\n}\n```\n\nYou can now use the rest of the api endpoints.\n\n#### Get Balance\n\nGet the balance for an address with the token selected.\n\n**Sample**\nRequest (GET method):\n```\nhttp://localhost:3000/api/token/threshodl/getbalance/0x07CE1F5852f222cc261ca803a1DA4a4016154539\n```\n\nResponse:\n\n```\n{\n    \"method\": \"getbalance\",\n    \"params\": {\n        \"tokenName\": \"threshodl\",\n        \"address\": \"0x83634a8eaadc34b860b4553e0daf1fac1cb43b1e\"\n    },\n    \"erc20Available\": [\n        {\n            \"name\": \"threshodl\",\n            \"contractAddress\": \"0x3e672122bfd3d6548ee1cc4f1fa111174e8465fb\"\n        }\n    ],\n    \"tokenBalance\": \"11300\"\n}\n```\n\n#### Request Transfer\n\nThis endpoint transfers tokens from the owner to any address, hence the request of tokens. The caveat is to unlock the owner address provided in the `connections.json` because it takes this as the global owner. This endpoint could be part of the owner-token api but because it can be made by any token it is best left here.\n\n#### Transfer\n\nTransfer tokens between any two addresses. \n\nUrl:\n```\nhttp://localhost:3000/api/token/threshodl/transfer\n```\n\nOptions: \n\n- gas[optional] - Example: \"gas\": 41000. Defaults to gas from web3.eth.estimateGas()\n- fromAddres[required]\n- toAddress[required]\n- value[required] - number/string. Keep in mind the decimal spaces for the token contract. Usually is 18. Example below is 2, so 100 is actually 100 tokens.\n- privateKey[required] - sender(fromAddress) private key. \n- priority[required] - low, medium, high. Based on thi [api](https://ethgasstation.info/json/ethgasAPI.json) and fast, average and safelow are divided by 10.\n\nRequest:\n```\n{\n\t\"toAddress\": \"0x07CE1F5852f222cc261ca803a1DA4a4016154539\",\n\t\"value\": 100,\n\t\"gas\": 41000,\n\t\"privateKey\": \"0x7f74657374320000000000000000000000000000000000000000000000000057\"\n}\n```\n\nResponse:\n```\n{\n    \"method\": \"transfer\",\n    \"params\": {\n        \"tokenName\": \"threshodl\"\n    },\n    \"body\": {\n        \"toAddress\": \"0x07CE1F5852f222cc261ca803a1DA4a4016154539\",\n        \"value\": 100,\n        \"gas\": 41000,\n        \"privateKey\": \"0xa6b7d3fb531567b199d025ded92cb86c685dba5247d4455041319bb0108985e7\"\n    },\n    \"erc20Available\": [\n        {\n            \"name\": \"threshodl\",\n            \"contractAddress\": \"0x3e672122bfd3d6548ee1cc4f1fa111174e8465fb\"\n        }\n    ],\n    \"transferABI\": \"0xa9059cbb00000000000000000000000007ce1f5852f222cc261ca803a1da4a40161545390000000000000000000000000000000000000000000000000000000000000064\",\n    \"txSignature\": {\n        \"messageHash\": \"0x28f36a05a927a8d245119baef7a0f0333e441dca6256601b42fba8c827b87b6b\",\n        \"v\": \"0x2a\",\n        \"r\": \"0xac47468f77fa1c862e66a28e76672e1a9586bca5074df3c2af8d0c53b9dfff36\",\n        \"s\": \"0x1d8b87ff4d719103aff2a4384444a356f2d03bcbbeec6208acedfbcd0e6b569c\",\n        \"rawTransaction\": \"0xf8a841843b9aca0082a028943e672122bfd3d6548ee1cc4f1fa111174e8465fb80b844a9059cbb00000000000000000000000007ce1f5852f222cc261ca803a1da4a401615453900000000000000000000000000000000000000000000000000000000000000642aa0ac47468f77fa1c862e66a28e76672e1a9586bca5074df3c2af8d0c53b9dfff36a01d8b87ff4d719103aff2a4384444a356f2d03bcbbeec6208acedfbcd0e6b569c\"\n    },\n    \"sendTxHash\": {\n        \"txHash\": \"0x3d556ffdb7faa9577eec1251a84477d1ddaa5a12e64920d4f2bad2fc64d6cf9d\"\n    }\n}\n```\n\n### Token Transaction Verification\n\nVerifying a token transaction can be done fast by looking at [Ropsten Etherscan](https://ropsten.etherscan.io) for example. Go to your address and check the transaction was successful, then check the contract address and receiver address for the same transaction.\n\nTo do this with this api and potentially create a check using blocks and transactions you need to do the following:\n\n- perform the transfer\n- get the block and transactions for that block via a GET request to this endpoint `http://localhost:3000/api/eth/block/{block-number}?showTx=true` and replace the block number with the once you see in Etherscan or via a custom webhook that receives new blocks. The response will show all the details for each transaction. Then use the transaction hash you got from the transfer and search it the response.\n- Use the \"to\" address from that transaction and perform a contract check to verify that it is a contract. Send a GET request to `http://localhost:3000/api/token/check-for-contract/{address}`. The response will give you a ` \"isContract\": true,` and the contract bytecode if its a contract.\n- Check the \"from\" address in that transaction and you will see the address tokens would have been received at. This and the contract check is the way to verify a token transfer. \n\n## Ethereum Endpoint Notes\n\nThe ethereum endpoint for this API uses the [web3js](http://web3js.readthedocs.io/en/1.0/) so parameters for a web3 method is normally supported by the endpoint unless otherwise specified. \n\n### Get Block Info\n\nThe following endpoints can be used to get information about blocks and even transactions.\n\n- `/api/eth/tx:txHash` : get transaction details by the transaction hash\n- `api/eth/tx-from-block/hashStringOrNumber` : hashStringOrNumber can be same as in the [web3 docs](http://web3js.readthedocs.io/en/1.0/web3-eth.html#gettransactionfromblock), e.g. `/latest` or `0xa343d89bb0447c8a22c8ce73bf35504d9363e234b2a1a8229d40b69ce3439fc5`. See [bug](#bugs-to-fix) for problem when using it in Ropsten\n\n- `api/eth/block/2?showTx=true\u0026useString=latest` : 1 is the blocknumber, the query `showTx` will show the transaction object in the output when set to true, and the query `useString` will overwrite the block number and use one of the strings used in the [getBlock api](http://web3js.readthedocs.io/en/1.0/web3-eth.html#getblock) such as `latest` to get the most recent block.\n\n### Create address\n\nGET request\n```\nhttp://localhost:3000/api/eth/create-account\n```\n\n### Get public address from private key\n\nGET request\n```\nhttp://localhost:3000/api/eth/get-account/{privatekey}\n```\n\n### Get Transaction info\n\n\nYou can get information about the transaction you want to send before sending it. Information like gas, gas price, amount in wei and ether, etc.\n\nsend a POST request with transaction object below to the `api/eth/send-tx-info` endpoint\n```\n{\n  \"from\": \"0x451E62137891156215d9D58BeDdc6dE3f30218e7\",\n  \"to\": \"0xAb7faf7bDAE1B9D0F757e2a8aB120619b388C4c6\",\n  \"value\": \"0.1\",\n  \"gas\":\"41000\",\n  \"gasPrice\": \"high\"\n}\n```\noutput\n```\n{\n    \"amountToSendEther\": \"0.1\",\n    \"amountToSendWei\": \"100000000000000000\",\n    \"gasPrices\": {\n        \"low\": 7,\n        \"medium\": 9,\n        \"high\": 14\n    },\n    \"gasPriceTypeDefault\": \"low\",\n    \"gasPriceDefault\": 7000000000,\n    \"gasPriceTypeCustom\": \"high\",\n    \"gasPrice\": 14000000000,\n    \"estimatedGas\": 21000,\n    \"gas\": \"41000\",\n    \"params\": {\n        \"from\": \"0x451e62137891156215d9d58beddc6de3f30218e7\",\n        \"to\": \"0xab7faf7bdae1b9d0f757e2a8ab120619b388c4c6\",\n        \"gasPrice\": \"0x342770c00\",\n        \"value\": \"0x16345785d8a0000\"\n    },\n    \"paramsUpdated\": {\n        \"from\": \"0x451E62137891156215d9D58BeDdc6dE3f30218e7\",\n        \"to\": \"0xAb7faf7bDAE1B9D0F757e2a8aB120619b388C4c6\",\n        \"gas\": \"41000\",\n        \"gasPrice\": 14000000000,\n        \"value\": \"100000000000000000\"\n    }\n}\n```\n\nYou can change the following:\n\n- from - takes a valid ethereum address\n- to - takes a valid ethereum address\n- value - takes a string number in ether\n- gas - you can send it without gas to see the estimatedGas and then modify it from there\n- gasPrice - [\"low\", \"medium\", \"high\"] are the options and you can see that in the gasPrice{} object that is outputted. So if you don't pass `\"gasPrice\": \"high\"` from the above example the transaction will return `gasPriceDefault` value.\n\nThe rest of the parameters are for your information:\n\n- gasPrices{} - taken from `https://ethgasstation.info/json/ethgasAPI.json`\n- gasPriceTypeDefault - default gas using `gasPrices.low * 1000000000;`\n- estimatedGas - taken from `web3.eth.estimateGas(txObject)`, where `txObject` is created from the other parameters and is shown as `params`\n- params - transaction object that is used to calculate the estimated gas\n- paramsUpdated - is the final transaction object that will be used for sending the transaction\n\nNote: you may notice that `nonce` is not a parameter accepted for changing because it is optional for the `sendTransaction()` function. If required it needs to be updated in the api to accept it as a parameter.\n\n### Send Transaction\n\nSending a transaction uses the `paramsUpdated` object and passes it to `web3.eth.sendTransaction(paramsUpdated)` and **requires a the from address to be an unlocked keystore address from inside the node**\n\noutput \n\n```\n{\n    \"transactionHash\": \"0x7c948c9d17c80ae0e89074eddab614c2ce24d6185b21f9aa2d9fb03d393d3dec\",\n    \"transactionIndex\": 0,\n    \"blockHash\": \"0x5ea250d8c2a1e4e9cead27a457f79cce084a494f9f3009e9f806d7a81030296d\",\n    \"blockNumber\": 12,\n    \"gasUsed\": 21000,\n    \"cumulativeGasUsed\": 21000,\n    \"contractAddress\": null,\n    \"logs\": [],\n    \"status\": true,\n    \"logsBloom\": \"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\"\n}\n```\n\n### Sign and Send Manually\n\nTo sign with a private key and send the raw transaction follow these instructions for constructing your request:\n\n#### Get Transaction Info\n\n`http://localhost:3000/api/eth/send-tx-info` POST request with the following json to see your data:\n\n```\n{\n  \"from\": \"0xA8D26e47CD1CB6Fc0803cA7D64D395bb38bc33de\",\n  \"to\": \"0x87E426ff6Deb0dF15CD98CAae0F63cf027D711b3\",\n  \"value\": \"0.002\"\n}\n```\n\nIf you are sending transactions from the same `from` address consecutively, you will need to increase the nonce by one so add it to your request\n\n```\n  \"nonce\": 1\n```\nYou will see the a change in the nonce. You want to pay attention to the `paramsToSign` parameter because it will be used to sign the transaction next.\n\n#### Sign transaction\n\n`http://localhost:3000/api/eth/sign-tx` and pass the POST request json:\n\n```\n{\n  \"from\": \"0xA8D26e47CD1CB6Fc0803cA7D64D395bb38bc33de\",\n  \"to\": \"0x87E426ff6Deb0dF15CD98CAae0F63cf027D711b3\",\n  \"value\": \"0.002\",\n  \"privateKey\": \"0x7f74657374320000000000000000000000000000000000000000000000000057\"\n}\n```\nSee [web3 api](http://web3js.readthedocs.io/en/1.0/web3-eth-accounts.html#signtransaction) for details on the out put and grab the `rawTransaction` parameter hex encoded transaction\n\n\n#### Send Signed Transaction\n\n`http://localhost:3000/api/eth/send-signed-tx` POST request with json:\n\n```\n{\n\t\"rawTransaction\": \"0xf86b04850218711a008252089487e426ff6deb0df15cd98caae0f63cf027d711b387071afd498d00008029a063542de27e66ea4a92f1270cbef3cd6ed9ad0b8bafbdcd0cedfcc25e2d731da7a05a7fb9dec086a6b1e4c0c19410b1b2f10a76c9f6198351731e92096534b67624\"\n}\n```\n\n## Webhook\n\nWebhooks allow data to be sent as POST request to an external url specified in the `config/connections.json` inside the `blockWebhookUrl` paramater. \n\n**To use this webhook you need to have websockets connected see [websockets](#websockets) for more information**\n\n```\n\"ropsten\":{\n  ...\n  \"blockWebhookUrl\": \"http://4f5a64ba.ngrok.io/api/eth/webhook\",\n  \"testWebhookUrl\": \"http://4f5a64ba.ngrok.io/api/eth/webhook\",\n  ...\n},\n```\n\nThe `testWebhookUrl` parameter is used for testing but following these instructions:\n\nRun this api server and then run these\n\n```\nbrew cask install ngrok\nngrok http 3000\n```\ngrab the ngrok url and add it the `testWebhookUrl` parameter e.g.`http://4f5a64ba.ngrok.io/api/eth/webhook`.\n\nThen open the debug url for ngrok e.g. `http://127.0.0.1:4040`\n\nSend a post request to `http://localhost:3000/api/eth/post-to-webhook` and watch two request show, one for the request and the second that send another POST request to the `/api/eth/webhook` endpoint\n\n## Websockets\n\nA websocket connection to the node is used to subscribe to events (e.g. new blocks, transactions, see [web3 api](http://web3js.readthedocs.io/en/1.0/web3-eth-subscribe.html)) and required to use the webhook feature which sends these subscriptions to a specified url.\n\n**Setup**\n\nYou need to enable a websocket connection inside the node and add that url to the `connections.json`\n\n```\n\"ropsten\":{\n  ...\n  \"websocketUrl\": \"ws://10.10.0.163:8546\",\n  ...\n},\n```\n\nor `.env` files which will overwrite the connections.json parameter\n\n```\nWEBSOCKET_URL=ws://127.0.0.1:8546\n```\n\nWebsockets are an experimental feature, and the code can be found inside `server/app/helpers/web3-websocket.js`\nThere is one `subscriptionType` that is corrently tested and working:\n\n```\n  blockSubscription\n```\n\nAnother is to get status on the syncing of the node with the most current block. **Needs more testing so use with caution**\n \n```\n  syncingSubscription\n```\n\n**Create subscription**\nTo create a subscription to block headers so every new block will be emitted and POSTed to a webhook url.\n\n```\nhttp://localhost:3000/api/eth/subscribe-block\n```\n\n**Remove Subscription**\n\n```\nhttp://localhost:3000/api/eth/close-subscriptions/blockSubscription\nhttp://localhost:3000/api/eth/close-subscriptions/syncingSubscription\n```\n\n\n## Endpoints\n\nTo get this endpoints run:\n\nRequest (GET method):\n```\nhttp://localhost:3000/api-endpoints\n```\n\nResponse: \n```\n[\n    {\n        \"path\": \"/\",\n        \"methods\": [\n            \"GET\"\n        ]\n    },\n    {\n        \"path\": \"/api\",\n        \"methods\": [\n            \"GET\",\n            \"POST\"\n        ]\n    },\n    {\n        \"path\": \"/api/network\",\n        \"methods\": [\n            \"GET\"\n        ]\n    },\n    {\n        \"path\": \"/api/token\",\n        \"methods\": [\n            \"GET\"\n        ]\n    },\n    {\n        \"path\": \"/api/token/get-web3-provider\",\n        \"methods\": [\n            \"GET\"\n        ]\n    },\n    {\n        \"path\": \"/api/token/get-contract\",\n        \"methods\": [\n            \"GET\"\n        ]\n    },\n    {\n        \"path\": \"/api/token/get-contract-instance\",\n        \"methods\": [\n            \"GET\"\n        ]\n    },\n    {\n        \"path\": \"/api/token/check-for-contract/:address\",\n        \"methods\": [\n            \"GET\"\n        ]\n    },\n    {\n        \"path\": \"/api/token/node-accounts\",\n        \"methods\": [\n            \"GET\"\n        ]\n    },\n    {\n        \"path\": \"/api/token/balance\",\n        \"methods\": [\n            \"GET\"\n        ]\n    },\n    {\n        \"path\": \"/api/token/balance/:address\",\n        \"methods\": [\n            \"GET\"\n        ]\n    },\n    {\n        \"path\": \"/api/token/owner\",\n        \"methods\": [\n            \"GET\"\n        ]\n    },\n    {\n        \"path\": \"/api/token/add-tokens/:amount\",\n        \"methods\": [\n            \"POST\"\n        ]\n    },\n    {\n        \"path\": \"/api/token/transfer-tokens\",\n        \"methods\": [\n            \"POST\"\n        ]\n    },\n    {\n        \"path\": \"/api/token/transfer-owner\",\n        \"methods\": [\n            \"POST\"\n        ]\n    },\n    {\n        \"path\": \"/api/token/kill-token\",\n        \"methods\": [\n            \"GET\"\n        ]\n    },\n    {\n        \"path\": \"/api/token/transfer-from\",\n        \"methods\": [\n            \"POST\"\n        ]\n    },\n    {\n        \"path\": \"/api/token/:tokenName\",\n        \"methods\": [\n            \"GET\"\n        ]\n    },\n    {\n        \"path\": \"/api/token/:tokenName/getbalance/:address\",\n        \"methods\": [\n            \"GET\"\n        ]\n    },\n    {\n        \"path\": \"/api/token/:tokenName/transfer\",\n        \"methods\": [\n            \"POST\"\n        ]\n    },\n    {\n        \"path\": \"/api/token/:tokenName/request-transfer\",\n        \"methods\": [\n            \"POST\"\n        ]\n    },\n    {\n        \"path\": \"/api/token/:tokenName/decode-tx-input\",\n        \"methods\": [\n            \"POST\"\n        ]\n    },\n    {\n        \"path\": \"/api/eth\",\n        \"methods\": [\n            \"GET\"\n        ]\n    },\n    {\n        \"path\": \"/api/eth/syncing\",\n        \"methods\": [\n            \"GET\"\n        ]\n    },\n    {\n        \"path\": \"/api/eth/balance/:address\",\n        \"methods\": [\n            \"GET\"\n        ]\n    },\n    {\n        \"path\": \"/api/eth/block\",\n        \"methods\": [\n            \"GET\"\n        ]\n    },\n    {\n        \"path\": \"/api/eth/block/:blockNumber\",\n        \"methods\": [\n            \"GET\"\n        ]\n    },\n    {\n        \"path\": \"/api/eth/tx/:transactionHash\",\n        \"methods\": [\n            \"GET\"\n        ]\n    },\n    {\n        \"path\": \"/api/eth/tx-receipt/:transactionHash\",\n        \"methods\": [\n            \"GET\"\n        ]\n    },\n    {\n        \"path\": \"/api/eth/tx-from-block/:hashStringOrNumber\",\n        \"methods\": [\n            \"GET\"\n        ]\n    },\n    {\n        \"path\": \"/api/eth/create-account\",\n        \"methods\": [\n            \"GET\"\n        ]\n    },\n    {\n        \"path\": \"/api/eth/get-account/:privateKey\",\n        \"methods\": [\n            \"GET\"\n        ]\n    },\n    {\n        \"path\": \"/api/eth/accounts\",\n        \"methods\": [\n            \"GET\"\n        ]\n    },\n    {\n        \"path\": \"/api/eth/wallet\",\n        \"methods\": [\n            \"GET\"\n        ]\n    },\n    {\n        \"path\": \"/api/eth/wallet/create\",\n        \"methods\": [\n            \"GET\"\n        ]\n    },\n    {\n        \"path\": \"/api/eth/wallet/add/:privateKey\",\n        \"methods\": [\n            \"POST\"\n        ]\n    },\n    {\n        \"path\": \"/api/eth/wallet/remove/:publicKey\",\n        \"methods\": [\n            \"POST\"\n        ]\n    },\n    {\n        \"path\": \"/api/eth/wallet/clear\",\n        \"methods\": [\n            \"POST\"\n        ]\n    },\n    {\n        \"path\": \"/api/eth/send-tx-info\",\n        \"methods\": [\n            \"POST\"\n        ]\n    },\n    {\n        \"path\": \"/api/eth/sign-tx\",\n        \"methods\": [\n            \"POST\"\n        ]\n    },\n    {\n        \"path\": \"/api/eth/send-signed-tx\",\n        \"methods\": [\n            \"POST\"\n        ]\n    },\n    {\n        \"path\": \"/api/eth/send-tx\",\n        \"methods\": [\n            \"POST\"\n        ]\n    },\n    {\n        \"path\": \"/api/eth/subscribe-syncing\",\n        \"methods\": [\n            \"GET\"\n        ]\n    },\n    {\n        \"path\": \"/api/eth/subscribe-block\",\n        \"methods\": [\n            \"GET\"\n        ]\n    },\n    {\n        \"path\": \"/api/eth/close-subscriptions/:subscriptionType\",\n        \"methods\": [\n            \"POST\"\n        ]\n    },\n    {\n        \"path\": \"/api/eth/post-to-webhook\",\n        \"methods\": [\n            \"POST\"\n        ]\n    },\n    {\n        \"path\": \"/api/eth/webhook\",\n        \"methods\": [\n            \"POST\"\n        ]\n    },\n    {\n        \"path\": \"/api-endpoints\",\n        \"methods\": [\n            \"GET\"\n        ]\n    }\n]\n```","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Far-to%2Fethereum-api","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Far-to%2Fethereum-api","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Far-to%2Fethereum-api/lists"}