Created
October 2, 2023 08:11
-
-
Save khaschuluu/8c5bf459729ae2b3b0f488302d3d0791 to your computer and use it in GitHub Desktop.
Interact web3 with Google Cloud Functions sample
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const https = require('https') | |
const fs = require('fs') | |
const agent = new https.Agent({keepAlive: true}) | |
const qs = require('querystring') | |
const Web3 = require('web3') | |
const web3 = new Web3() | |
const crypto = require('crypto') | |
const EthereumTx = require('ethereumjs-tx') | |
const Datastore = require('@google-cloud/datastore'); | |
const config = require('./config.json') | |
const privateKey = Buffer.from(config.contract_owner_private.replace(/^0x/, ''), 'hex') | |
const datastore = new Datastore({}); | |
const abi = [{"constant":true,"inputs":[],"name":"mintingFinished","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"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":false,"inputs":[{"name":"_to","type":"address"},{"name":"_amount","type":"uint256"}],"name":"mint","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_value","type":"uint256"}],"name":"burn","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_subtractedValue","type":"uint256"}],"name":"decreaseApproval","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"}],"name":"balanceOf","outputs":[{"name":"balance","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"finishMinting","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"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":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_addedValue","type":"uint256"}],"name":"increaseApproval","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"},{"constant":false,"inputs":[{"name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"inputs":[],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"name":"burner","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Burn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"to","type":"address"},{"indexed":false,"name":"amount","type":"uint256"}],"name":"Mint","type":"event"},{"anonymous":false,"inputs":[],"name":"MintFinished","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"previousOwner","type":"address"},{"indexed":true,"name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"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"}] | |
const contract_address = config.contract_address | |
const Contract = web3.eth.contract(abi) | |
const contract = Contract.at(contract_address) | |
let gnonce // Global Nonce for security | |
fs.readFile("./nonce", (err, data) => { | |
if (err) { | |
console.error('L24: ', err) | |
} else { | |
gnonce = parseInt(data) | |
} | |
}) | |
exports.mint = (req, res) => { | |
const ts = Date.now() | |
if (req.method === 'GET') { | |
const q = req.query | |
const address = q.address | |
const amount = q.amount | |
const signature = q.signature | |
res.set('Content-Type', 'text/plain') | |
if (address && amount && signature) { | |
var hmac = crypto.createHmac('sha256', config.hmac_secret) | |
hmac.on('readable', () => { | |
const data = hmac.read() | |
if (data) { | |
if (data.toString('hex').toLowerCase() === signature.toLowerCase()) { | |
var abidata = contract.mint.getData(address, amount) | |
var countReq = https.request({ | |
host: 'api.infura.io', | |
path: '/v1/jsonrpc/ropsten/eth_getTransactionCount?params=%5B%220x5B7Ece121303185Eea3c905fC6D72e6b811bD4F6%22%2C%22latest%22%5D', | |
headers: { | |
'Content-Type': 'application/json', | |
'Accept': 'application/json' | |
}, | |
agent: agent, | |
}, countRes => { | |
let countRawData = ''; | |
countRes.on('data', chunk => countRawData += chunk) | |
countRes.on('end', () => { | |
try { | |
var countData = JSON.parse(countRawData) | |
} catch (err) { | |
console.error(err) | |
res.status(500).send('internal server error') | |
} | |
var nonce = countData.result | |
const txParams = { | |
nonce: nonce, | |
gasLimit: '0x' + (4700000).toString(16), | |
gasPrice: '0x' + (100000000000).toString(16), | |
to: contract_address, | |
data: abidata | |
} | |
const tx = new EthereumTx(txParams) | |
tx.sign(privateKey) | |
const serializedTx = tx.serialize() | |
const postData = JSON.stringify({ | |
jsonrpc: '2.0', | |
id: 1, | |
method: "eth_sendRawTransaction", | |
token: 'hq9l5D1Moq7KjYPgyfNn', | |
params: ['0x' + serializedTx.toString('hex')] | |
}) | |
var reqst = https.request({ | |
host: 'api.infura.io', | |
path: '/v1/jsonrpc/ropsten', | |
method: 'POST', | |
headers: { | |
'Content-Type': 'application/json', | |
'Accept': 'application/json' | |
}, | |
agent: agent, | |
}, resp => { | |
resp.on('data', () => {}) | |
resp.on('end', () => { | |
increase_gnonce() | |
res.status(200).send('ok') | |
}) | |
}) | |
reqst.on('error', e => { | |
console.error(`Error: ${e.message}`) | |
res.status(500).send('internal server error') | |
}) | |
reqst.write(postData) | |
reqst.end() | |
}) | |
}) | |
countReq.on('error', e => { | |
console.error(`Error: ${e.message}`) | |
res.status(500).send('internal server error') | |
}) | |
countReq.end() | |
} else { | |
res.status(401).send('unauthorized') | |
} | |
} | |
}) | |
hmac.write(qs.stringify({ | |
address: address, | |
amount: amount, | |
nonce: gnonce | |
})) | |
hmac.end() | |
} else { | |
res.status(400).send('bad request') | |
} | |
} | |
} | |
exports.setnonce = (req, res) => { | |
// var increase_gnonce = function() { | |
fs.writeFile("./nonce", (gnonce + 1).toString(), err => { | |
// if (err) return console.error('L29: ', err) | |
// console.log('Global nonce successfuly increased') | |
if (err) { | |
res.status(500).send(err) | |
} else { | |
res.status(200).send(':)') | |
} | |
}) | |
// } | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment