Skip to content

Instantly share code, notes, and snippets.

@khaschuluu
Created October 2, 2023 08:11
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save khaschuluu/8c5bf459729ae2b3b0f488302d3d0791 to your computer and use it in GitHub Desktop.
Save khaschuluu/8c5bf459729ae2b3b0f488302d3d0791 to your computer and use it in GitHub Desktop.
Interact web3 with Google Cloud Functions sample
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