Skip to content

Commit

Permalink
feat(ethereum): Read ERC20 informations (#122)
Browse files Browse the repository at this point in the history
* Include contract ABI as json

* Call erc 20 methods without parameters

* feat(ethereum): statements that reads erc 20 informations
  • Loading branch information
albertolerda committed Mar 3, 2022
1 parent 5648bb4 commit d4e769c
Show file tree
Hide file tree
Showing 10 changed files with 362 additions and 84 deletions.
1 change: 1 addition & 0 deletions packages/core/tests/utils_test.js
Expand Up @@ -120,6 +120,7 @@ test("getContracts works correctly", async (t) => {
"/database",
"/database_table",
"/empty",
"/ethereum_erc20",
"/ethereum_retrieve",
"/ethereum_retrieve_no_exist",
"/ethereum_store",
Expand Down
4 changes: 4 additions & 0 deletions packages/ethereum/src/actions.ts
Expand Up @@ -2,3 +2,7 @@ export const CONNECT = "have a ethereum endpoint named {}";
export const SET_SK = "use the ethereum private key {}";
export const STORE = "ask {} to store the data named {} into the tag {}";
export const RETRIEVE = "read from {} the data in tag {} and save the output into {}";
export const ERC20_0 = "have the {} for erc20 {}"
export const ERC20_0_NAMED = "have the {} for erc20 {} named {}"
export const ERC20_1 = "have the {} of {} for erc20 {}"
export const ERC20_1_NAMED = "have the {} of {} for erc20 {} named {}"
222 changes: 222 additions & 0 deletions packages/ethereum/src/erc20_abi.json
@@ -0,0 +1,222 @@
[
{
"constant": true,
"inputs": [],
"name": "name",
"outputs": [
{
"name": "",
"type": "string"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "_spender",
"type": "address"
},
{
"name": "_value",
"type": "uint256"
}
],
"name": "approve",
"outputs": [
{
"name": "",
"type": "bool"
}
],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "totalSupply",
"outputs": [
{
"name": "",
"type": "uint256"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "_from",
"type": "address"
},
{
"name": "_to",
"type": "address"
},
{
"name": "_value",
"type": "uint256"
}
],
"name": "transferFrom",
"outputs": [
{
"name": "",
"type": "bool"
}
],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "decimals",
"outputs": [
{
"name": "",
"type": "uint8"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "_owner",
"type": "address"
}
],
"name": "balanceOf",
"outputs": [
{
"name": "balance",
"type": "uint256"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "symbol",
"outputs": [
{
"name": "",
"type": "string"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "_to",
"type": "address"
},
{
"name": "_value",
"type": "uint256"
}
],
"name": "transfer",
"outputs": [
{
"name": "",
"type": "bool"
}
],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "_owner",
"type": "address"
},
{
"name": "_spender",
"type": "address"
}
],
"name": "allowance",
"outputs": [
{
"name": "",
"type": "uint256"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"payable": true,
"stateMutability": "payable",
"type": "fallback"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"name": "owner",
"type": "address"
},
{
"indexed": true,
"name": "spender",
"type": "address"
},
{
"indexed": false,
"name": "value",
"type": "uint256"
}
],
"name": "Approval",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"name": "from",
"type": "address"
},
{
"indexed": true,
"name": "to",
"type": "address"
},
{
"indexed": false,
"name": "value",
"type": "uint256"
}
],
"name": "Transfer",
"type": "event"
}
]
129 changes: 86 additions & 43 deletions packages/ethereum/src/index.ts
Expand Up @@ -7,52 +7,24 @@ import {
SET_SK,
STORE,
RETRIEVE,
ERC20_0,
ERC20_0_NAMED,
ERC20_1,
ERC20_1_NAMED,
} from "./actions";
import { zencodeNamedParamsOf } from '@restroom-mw/utils';
import Web3 from 'web3'
import { Account } from 'web3-core/types'
//import * as STORE_ABI from './store_abi.json'
const GAS_LIMIT = 100000
const STORE_ADDRESS = "0xf0562148463aD4D3A8aB59222E2e390332Fc4a0d"
const STORE_ABI = JSON.parse(`[
{
"inputs": [
{
"internaltype": "uint256",
"name": "_maxlen",
"type": "uint256"
}
],
"statemutability": "nonpayable",
"type": "constructor"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internaltype": "string",
"name": "",
"type": "string"
}
],
"name": "hashsaved",
"type": "event"
},
{
"inputs": [
{
"internaltype": "string",
"name": "message",
"type": "string"
}
],
"name": "store",
"outputs": [],
"statemutability": "nonpayable",
"type": "function"
}
]`)
// import * as STORE_ABI from './store_abi.json'
// import * as ERC20_ABI from './erc20_abi.json'

require("dotenv").config();

const STORE_ABI = require('./store_abi.json');
const ERC20_ABI = require('./erc20_abi.json');

const GAS_LIMIT = process.env.GAS_LIMIT || 100000;
const STORE_ADDRESS = process.env.STORE_ADDRESS || "0xf0562148463aD4D3A8aB59222E2e390332Fc4a0d";
let web3: Web3 = null;
let account: Account = null;
let input: ObjectLiteral = null;
Expand All @@ -73,6 +45,34 @@ export default async (req: Request, res: Response, next: NextFunction) => {
input = rr.combineDataKeys(data, keys);
const namedParamsOf = zencodeNamedParamsOf(zencode, input);

const call_erc20 = async (command: string, contractAddress: string,
variableName: string, args: string[]) => {
if(!web3.utils.isAddress(contractAddress)) {
throw new Error(`Not an ethereum address ${contractAddress}`);
}
const erc20 = new web3.eth.Contract(ERC20_ABI, contractAddress);

const fz = (() => {
switch(command) {
case "decimals": return erc20.methods.decimals;
case "name": return erc20.methods.name;
case "symbol": return erc20.methods.symbol;
case "total supply": return erc20.methods.totalSupply;
case "balance": return erc20.methods.balanceOf;
default: return null;
}
})();

if(!fz) {
throw new Error(`Unknown function name ${command}`);
}

const result = await fz(...args).call();


data[variableName] = result;
}

if(zencode.match(CONNECT)) {
const [ endpoint ] = namedParamsOf(CONNECT)
web3 = new Web3(endpoint);
Expand Down Expand Up @@ -104,6 +104,50 @@ export default async (req: Request, res: Response, next: NextFunction) => {
}
}
}

if(zencode.match(ERC20_0_NAMED)) {
validateWeb3();
const params = zencode.paramsOf(ERC20_0_NAMED);
for(var i = 0; i < params.length; i += 3) {
const command = params[i];
const contractAddress = input[params[i+1]] || params[i+1];
const variableName = params[i+2];
await call_erc20(command, contractAddress, variableName, []);
}
}

if(zencode.match(ERC20_0)) {
validateWeb3();
const params = zencode.paramsOf(ERC20_0);
for(var i = 0; i < params.length; i += 2) {
const command = params[i];
const contractAddress = input[params[i+1]] || params[i+1];
await call_erc20(command, contractAddress, command.replace(" ", "_"), []);
}
}

if(zencode.match(ERC20_1)) {
validateWeb3();
const params = zencode.paramsOf(ERC20_1);
for(var i = 0; i < params.length; i += 3) {
const command = params[i];
const arg = input[params[i+1]] || params[i+1];
const contractAddress = input[params[i+2]] || params[i+2];
await call_erc20(command, contractAddress, command.replace(" ", "_"), [ arg ]);
}
}

if(zencode.match(ERC20_1_NAMED)) {
validateWeb3();
const params = zencode.paramsOf(ERC20_1_NAMED);
for(var i = 0; i < params.length; i += 4) {
const command = params[i];
const arg = input[params[i+1]] || params[i+1];
const contractAddress = input[params[i+2]] || params[i+2];
const variableName = params[i+3];
await call_erc20(command, contractAddress, variableName, [ arg ]);
}
}
});

rr.onSuccess(async (params) => {
Expand All @@ -129,7 +173,6 @@ export default async (req: Request, res: Response, next: NextFunction) => {
if(receipt.status) {
result[tag] = receipt.transactionHash.substring(2); // Remove 0x
} else {
console.log(receipt);
throw new Error("Transaction failed");
}
}
Expand Down

0 comments on commit d4e769c

Please sign in to comment.