Sending erc20 tokens using Web3js - ethereum

I have tried to send erc20 (Bela) from one address to another got tx id in a result, but this transaction is not appearing in any tx check services and no funds sent from my address.
code at the moment looks like this:
web3 = new Web3(new Web3.providers.HttpProvider('https://mainnet.infura.io/PKEY'));
var myAddress = "0x4d0...";
var toAddress = "0xce6...";
var amount = web3.utils.toHex(5);
var count = web3.eth.getTransactionCount(myAddress).then(function(v){console.log(v); count = v});
var privateKey = new Buffer('pkey', 'hex');
//got from https://etherscan.io/address/0x2e98a6804e4b6c832ed0ca876a943abd3400b224#code
var abiArray = '';
var contractAddress = '0x2e98a6804e4b6c832ed0ca876a943abd3400b224';
var contract = new web3.eth.Contract(abiArray, contractAddress, {from: myAddress});
var rawTransaction = {
"from":myAddress,
"gasPrice":"0x098bca5a00",
"gasLimit":"0xcb05",
"to":contractAddress,
"value":"0x0",
"data":contract.methods.transfer(toAddress, amount).encodeABI(),
"nonce":web3.utils.toHex(count)
};
var transaction = new Tx(rawTransaction);
transaction.sign(privateKey);
web3.eth.sendSignedTransaction('0x' + transaction.serialize().toString('hex'), function (err, hash) {
console.log(err, hash);
});

Update the "to" address within the transaction object using contract._address

Related

How to run many triggers with LOCK without discarding one? [duplicate]

I'm struggling to understand why this script is executing 2, 3, even 4 times simultaneously every time a form is submitted. I have added the LockService, but while it does sometimes keep multiple emails from being sent, it doesn't seem to prevent the simultaneous executions from occurring.
Everything else is working fine--I just don't want the failed executions every time, because these are also disrupting subsequent legitimate trigger executions due to script timeouts.
I have to execute from the sheet, because I am calling data that is retrieved to the sheet based on form responses. The sheet is not shared, and there are no "orphaned" triggers. I've removed/re-created the trigger, and even re-created the sheet and script but still getting extra executions.
Thanks in advance for any suggestions!
function zoneRepEmail(e) {
var lock = LockService.getScriptLock();
lock.waitLock(30000); // wait 30 seconds before conceding defeat.
// got the lock, you may now proceed
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName('SupervisorApprovals');
var lookupRow = e.range.getRow();
var rowRange = sheet.getRange(1,1,sheet.getLastRow(),37);
var appEmailSentLog = rowRange.getCell(lookupRow,36);
var repEmailSentLog = rowRange.getCell(lookupRow,37);
Logger.log(appEmailSentLog);
var form = FormApp.openById('1efkzyAgHf3PjEnPXSXP4P5mTCnII_BQaf5jf2Apr8gM');
var startRow = 3;
var headers = sheet.getRange(2, 1, 1, sheet.getLastColumn()).getValues()[0];
var timestampColumn = sheet.getRange('K'+lookupRow);
var dateColumns = sheet.getRangeList(['X'+lookupRow, 'Y'+lookupRow]);
var pctColumns = sheet.getRange('Z'+lookupRow);
var phoneColumns = sheet.getRangeList(['P'+lookupRow,'Q'+lookupRow,'U'+lookupRow]);
var dataRange = sheet.getRange(lookupRow,1,sheet.getLastRow(),37);
var data = dataRange.getValues();
for (var i = 0; i < data.length; ++i){
var row = data[i];
var timestamp = e.namedValues["Timestamp"];
var columnOfEditUrl = 46;
var email_address = "email#email.com";
var columnOfHomeUnit = 44;
var columnOfAppId = 45;
var columnOfZoneRep = 47;
var columnOfZoneRepEmail = 48;
var colEmplLName = 2;
var emplLName = sheet.getRange(lookupRow, 12).getValue();
var colEmplFName = 3;
var emplFName = sheet.getRange(lookupRow, 13).getValue();
var emplMName = sheet.getRange(lookupRow, 14).getValue();
var locDisp = sheet.getRange(lookupRow, 15).getValue();
var empPhone = row[15];
var emplAltPhone = row[16];
var emplEmail = row[17];
var emplClass = row[18];
var emplSup = row[19];
var supPhone = row[20];
var supEmail = row[21];
var trainPosition = row[22];
var firstAssign = row[23];
var lastAssign = row[24];
var tbPercent = row[25];
var trainIMT = row[26];
var imtName = row[27];
var reqTraining = row[28];
var trainNeeded = row[29];
var appComments = row[30];
var homeUnit = row[31];
var appId = row[1];
var zoneRep = row[33];
var zoneRepEmail = sheet.getRange(lookupRow, 35).getValue();
var appStatus = row[6];
var statusReason = row[7];
var statusComment = row[8];
timestampColumn.setNumberFormat("mm/dd/yyyy hh:mm:ss");
pctColumns.setNumberFormat("###%");
dateColumns.setNumberFormat("mm/dd/yyyy");
phoneColumns.setNumberFormat("###-###-####");
var emailTo = emplEmail;
var message = "The following application to the Rocky Mountain Area Priority Trainee Program has been "+appStatus+" for "+emplFName+" "+emplMName+" "+emplLName+". Please carefully review all details in the application and update your zone sheet accordingly."+"\n"+"If corrections are required, please contact the applicant directly."+"\n"+"A status email has been forwarded to the applicant and supervisor listed."+"\n"+"\n"+"--------------------------------------------------------------"+"\n"+"\n"+"Applicant Name: "+emplFName+" "+emplMName+" "+emplLName+"\n"+"Application Reference ID: "+appId+"\n"+"Dispatch: "+locDisp+"\n"+"Employee Phone: "+empPhone+"\n"+"Employee Alternate Phone: "+emplAltPhone+"\n"+"Employee Email: "+emplEmail+"\n"+"Home Unit ID: "+homeUnit+"\n"+"Employment Class: "+emplClass+"\n"+"\n"+"Supervisor Name: "+emplSup+"\n"+"Supervisor Phone: "+supPhone+"\n"+"Supervisor Email: "+supEmail+"\n"+"\n"+"Trainee Position: "+trainPosition+"\n"+"Taskbook Percentage Complete: "+tbPercent+"\n"+"Taskbook First Assignment: "+firstAssign+"\n"+"\n"+"IMT Trainee: "+trainIMT+"\n"+"Assigned to IMT: "+imtName+"\n"+"\n"+"All Required Training Completed?: "+reqTraining+"\n"+"Training Still Needed for Position: "+trainNeeded+"\n"+"\n"+"Comments: "+appComments+"\n"+"\n"+"Application Status: "+appStatus+"\n"+"Reason for Denial (if applicable): "+statusReason+"\n"+"Supervisor Comments: "+statusComment;
var appMessage = "The following application to the Rocky Mountain Area Priority Trainee Program has been "+appStatus+" for "+emplFName+" "+emplMName+" "+emplLName+". The application has been forwarded to the Zone Training Representative for processing."+"\n"+"\n"+"--------------------------------------------------------------"+"\n"+"\n"+"Applicant Name: "+emplFName+" "+emplMName+" "+emplLName+"\n"+"Application Reference ID: "+appId+"\n"+"Dispatch: "+locDisp+"\n"+"Employee Phone: "+empPhone+"\n"+"Employee Alternate Phone: "+emplAltPhone+"\n"+"Employee Email: "+emplEmail+"\n"+"Home Unit ID: "+homeUnit+"\n"+"Employment Class: "+emplClass+"\n"+"\n"+"Supervisor Name: "+emplSup+"\n"+"Supervisor Phone: "+supPhone+"\n"+"Supervisor Email: "+supEmail+"\n"+"\n"+"Trainee Position: "+trainPosition+"\n"+"Taskbook Percentage Complete: "+tbPercent+"\n"+"Taskbook First Assignment: "+firstAssign+"\n"+"\n"+"IMT Trainee: "+trainIMT+"\n"+"Assigned to IMT: "+imtName+"\n"+"\n"+"All Required Training Completed?: "+reqTraining+"\n"+"Training Still Needed for Position: "+trainNeeded+"\n"+"\n"+"Comments: "+appComments+"\n"+"\n"+"Application Status: "+appStatus+"\n"+"Reason for Denial (if applicable): "+statusReason+"\n"+"Supervisor Comments: "+statusComment;
var subject = appStatus+": PT App for "+emplFName+" "+emplMName+" "+emplLName+" // "+trainPosition+" // "+timestamp;
Utilities.sleep(5000);//allow all column formats to be applied, then proceed.
if (repEmailSentLog.isBlank()){
GmailApp.sendEmail(zoneRepEmail, subject, message,{noReply:true});
repEmailSentLog.setValue('EmailSent');
}
if (appEmailSentLog.isBlank()){
GmailApp.sendEmail(emplEmail, subject, appMessage,{cc:supEmail,noReply:true});
appEmailSentLog.setValue('EmailSent');
}
}
lock.releaseLock(); Utilities.sleep(10000);
}
I'd definitely remove the line:
Utilities.sleep(10000);
There's no reason to wait.
If you want to avoid rate limiting errors caused by Apps Script restrictions, then put calls to services inside a for loop, and only wait if there is an error. That way the code isn't waiting if it doesn't need to, and only waiting if it needs to.
And I'd increase the timeout time. Normally, the code will release the lock, so a long timeout doesn't affect that situation, but if the timeout ends before the code is done, that could cause a problem.
And if there is an error, then release the lock. So, the following code adds a try/catch block to handle that.
Also, you should test for an obtained lock before proceeding, and if the lock isn't obtained, then quit and notify someone that there was an error.
function zoneRepEmail(e) {
try{
var lock = LockService.getScriptLock();
lock.waitLock(60000); // wait 60 seconds before timing out
if (!lock.hasLock()) {//Failed to get lock
MailApp.sendEmail(Session.getEffectiveUser().getEmail(),
'Code Failed', 'The code for ABC failed');
//Logger.log('Could not obtain lock');
return;
}
for (i=1;i<4;i++) {//Try up to 3 times
try{
//Rate limited service call code here
break;
}catch(e){
if (i!==3){Utilities.sleep(i*2000);}
if (i>=3) {
MailApp.sendEmail(Session.getEffectiveUser().getEmail(),
'Code Failed', 'The code for ABC failed - ' + e.message + "\n\n" +
e.stack);
}
};
}
//Code here
lock.releaseLock();
} catch(e) {
lock.releaseLock();//Release the lock if there is an error
MailApp.sendEmail(Session.getEffectiveUser().getEmail(),
'Code Failed', 'The code for ABC failed - ' + e.message + "\n\n" +
e.stack);
//Logger.log('error: ' + e.message + ' stack: ' + e.stack);
}
}

JSON API Call: Pagination loop - unable to increment offset value

I am trying to make an API call which has a 50 records per call limit, the JSON response gives me "objects" and "total_objects".
I am running into an issue with the code that i managed to put together with help, the output does increment from the 50th record till the 95th record, post which it loops back to print from the 45th record and loops with the same set.
issue: stuck in a loop where the increment is one record at a time and a repeat of 49 old records
var client_id = 'xxxx';
var client_secret = 'xxx';
var email = 'xxx';
var password = 'abc';
var device = '1';
var app_version = '1';
var Token = 'abcde';
// call the API to get data for your list
function AP_Hyd() {
// URL and params for the API
var root = 'https://abcdef:443//v2/';
var endpoint = 'ghij/3241/objects?search=rtewq&limit=50&offset=';
var offset = '0'
// parameters for url fetch
var params = {
'method': 'GET',
'muteHttpExceptions': true,
'headers': {
'Authorization': 'Bearer ' + Token
}
};
// call the API for first offset
var json = getAssetData(root,endpoint, offset, params);
var totalObjects = json.objects;
//Adding data to ActiveGoogleSheet
var sheet = SpreadsheetApp.getActiveSheet();
sheet.clear()
//Adding Column Headings
var headerRow = ['erwf', 'gtre', 'poi', 'hgf', 'lkj', 'zyx'];
sheet.appendRow(headerRow);
//print first batch
printRows(totalObjects,sheet);
//check for any further data available
if (totalObjects) {
let totalPages = json.totals.objects;
//get total number of pages to be retrieved
var pageCount = parseInt(totalPages / 50)
//check for decimal
//if decimal is found increase the value of pageCount by 1
if(totalPages%50 !=0){
pageCount++;
}
Logger.log("pageCount:::" + pageCount +" for total objects:: " + totalPages);
for (i = 1; i < pageCount; i++) {
//invoke again and lets say the response is added in response
// call the API with incremented offset
var pageResponse = getAssetData(root,endpoint, i, params);
var jsonObjects = pageResponse.objects;
//print the rows
printRows(jsonObjects,sheet);
}
}
}
function getAssetData(root,endpoint,offset, params){
var response = UrlFetchApp.fetch(root + endpoint + offset, params);
var content = response.getContentText()
//return the parsed content
//TODO: add null check
return JSON.parse(content)
}
function printRows(jsonData, sheet) {
if (jsonData) {
for (var i = 0; i < jsonData.length; i++) {
var fieldObj = jsonData[i];
;
Logger.log(fieldObj)
// print out all the Columns
sheet.appendRow(row);
}
}
}

Multiple executions of Google Script, even with Lock on form submit trigger

I'm struggling to understand why this script is executing 2, 3, even 4 times simultaneously every time a form is submitted. I have added the LockService, but while it does sometimes keep multiple emails from being sent, it doesn't seem to prevent the simultaneous executions from occurring.
Everything else is working fine--I just don't want the failed executions every time, because these are also disrupting subsequent legitimate trigger executions due to script timeouts.
I have to execute from the sheet, because I am calling data that is retrieved to the sheet based on form responses. The sheet is not shared, and there are no "orphaned" triggers. I've removed/re-created the trigger, and even re-created the sheet and script but still getting extra executions.
Thanks in advance for any suggestions!
function zoneRepEmail(e) {
var lock = LockService.getScriptLock();
lock.waitLock(30000); // wait 30 seconds before conceding defeat.
// got the lock, you may now proceed
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName('SupervisorApprovals');
var lookupRow = e.range.getRow();
var rowRange = sheet.getRange(1,1,sheet.getLastRow(),37);
var appEmailSentLog = rowRange.getCell(lookupRow,36);
var repEmailSentLog = rowRange.getCell(lookupRow,37);
Logger.log(appEmailSentLog);
var form = FormApp.openById('1efkzyAgHf3PjEnPXSXP4P5mTCnII_BQaf5jf2Apr8gM');
var startRow = 3;
var headers = sheet.getRange(2, 1, 1, sheet.getLastColumn()).getValues()[0];
var timestampColumn = sheet.getRange('K'+lookupRow);
var dateColumns = sheet.getRangeList(['X'+lookupRow, 'Y'+lookupRow]);
var pctColumns = sheet.getRange('Z'+lookupRow);
var phoneColumns = sheet.getRangeList(['P'+lookupRow,'Q'+lookupRow,'U'+lookupRow]);
var dataRange = sheet.getRange(lookupRow,1,sheet.getLastRow(),37);
var data = dataRange.getValues();
for (var i = 0; i < data.length; ++i){
var row = data[i];
var timestamp = e.namedValues["Timestamp"];
var columnOfEditUrl = 46;
var email_address = "email#email.com";
var columnOfHomeUnit = 44;
var columnOfAppId = 45;
var columnOfZoneRep = 47;
var columnOfZoneRepEmail = 48;
var colEmplLName = 2;
var emplLName = sheet.getRange(lookupRow, 12).getValue();
var colEmplFName = 3;
var emplFName = sheet.getRange(lookupRow, 13).getValue();
var emplMName = sheet.getRange(lookupRow, 14).getValue();
var locDisp = sheet.getRange(lookupRow, 15).getValue();
var empPhone = row[15];
var emplAltPhone = row[16];
var emplEmail = row[17];
var emplClass = row[18];
var emplSup = row[19];
var supPhone = row[20];
var supEmail = row[21];
var trainPosition = row[22];
var firstAssign = row[23];
var lastAssign = row[24];
var tbPercent = row[25];
var trainIMT = row[26];
var imtName = row[27];
var reqTraining = row[28];
var trainNeeded = row[29];
var appComments = row[30];
var homeUnit = row[31];
var appId = row[1];
var zoneRep = row[33];
var zoneRepEmail = sheet.getRange(lookupRow, 35).getValue();
var appStatus = row[6];
var statusReason = row[7];
var statusComment = row[8];
timestampColumn.setNumberFormat("mm/dd/yyyy hh:mm:ss");
pctColumns.setNumberFormat("###%");
dateColumns.setNumberFormat("mm/dd/yyyy");
phoneColumns.setNumberFormat("###-###-####");
var emailTo = emplEmail;
var message = "The following application to the Rocky Mountain Area Priority Trainee Program has been "+appStatus+" for "+emplFName+" "+emplMName+" "+emplLName+". Please carefully review all details in the application and update your zone sheet accordingly."+"\n"+"If corrections are required, please contact the applicant directly."+"\n"+"A status email has been forwarded to the applicant and supervisor listed."+"\n"+"\n"+"--------------------------------------------------------------"+"\n"+"\n"+"Applicant Name: "+emplFName+" "+emplMName+" "+emplLName+"\n"+"Application Reference ID: "+appId+"\n"+"Dispatch: "+locDisp+"\n"+"Employee Phone: "+empPhone+"\n"+"Employee Alternate Phone: "+emplAltPhone+"\n"+"Employee Email: "+emplEmail+"\n"+"Home Unit ID: "+homeUnit+"\n"+"Employment Class: "+emplClass+"\n"+"\n"+"Supervisor Name: "+emplSup+"\n"+"Supervisor Phone: "+supPhone+"\n"+"Supervisor Email: "+supEmail+"\n"+"\n"+"Trainee Position: "+trainPosition+"\n"+"Taskbook Percentage Complete: "+tbPercent+"\n"+"Taskbook First Assignment: "+firstAssign+"\n"+"\n"+"IMT Trainee: "+trainIMT+"\n"+"Assigned to IMT: "+imtName+"\n"+"\n"+"All Required Training Completed?: "+reqTraining+"\n"+"Training Still Needed for Position: "+trainNeeded+"\n"+"\n"+"Comments: "+appComments+"\n"+"\n"+"Application Status: "+appStatus+"\n"+"Reason for Denial (if applicable): "+statusReason+"\n"+"Supervisor Comments: "+statusComment;
var appMessage = "The following application to the Rocky Mountain Area Priority Trainee Program has been "+appStatus+" for "+emplFName+" "+emplMName+" "+emplLName+". The application has been forwarded to the Zone Training Representative for processing."+"\n"+"\n"+"--------------------------------------------------------------"+"\n"+"\n"+"Applicant Name: "+emplFName+" "+emplMName+" "+emplLName+"\n"+"Application Reference ID: "+appId+"\n"+"Dispatch: "+locDisp+"\n"+"Employee Phone: "+empPhone+"\n"+"Employee Alternate Phone: "+emplAltPhone+"\n"+"Employee Email: "+emplEmail+"\n"+"Home Unit ID: "+homeUnit+"\n"+"Employment Class: "+emplClass+"\n"+"\n"+"Supervisor Name: "+emplSup+"\n"+"Supervisor Phone: "+supPhone+"\n"+"Supervisor Email: "+supEmail+"\n"+"\n"+"Trainee Position: "+trainPosition+"\n"+"Taskbook Percentage Complete: "+tbPercent+"\n"+"Taskbook First Assignment: "+firstAssign+"\n"+"\n"+"IMT Trainee: "+trainIMT+"\n"+"Assigned to IMT: "+imtName+"\n"+"\n"+"All Required Training Completed?: "+reqTraining+"\n"+"Training Still Needed for Position: "+trainNeeded+"\n"+"\n"+"Comments: "+appComments+"\n"+"\n"+"Application Status: "+appStatus+"\n"+"Reason for Denial (if applicable): "+statusReason+"\n"+"Supervisor Comments: "+statusComment;
var subject = appStatus+": PT App for "+emplFName+" "+emplMName+" "+emplLName+" // "+trainPosition+" // "+timestamp;
Utilities.sleep(5000);//allow all column formats to be applied, then proceed.
if (repEmailSentLog.isBlank()){
GmailApp.sendEmail(zoneRepEmail, subject, message,{noReply:true});
repEmailSentLog.setValue('EmailSent');
}
if (appEmailSentLog.isBlank()){
GmailApp.sendEmail(emplEmail, subject, appMessage,{cc:supEmail,noReply:true});
appEmailSentLog.setValue('EmailSent');
}
}
lock.releaseLock(); Utilities.sleep(10000);
}
I'd definitely remove the line:
Utilities.sleep(10000);
There's no reason to wait.
If you want to avoid rate limiting errors caused by Apps Script restrictions, then put calls to services inside a for loop, and only wait if there is an error. That way the code isn't waiting if it doesn't need to, and only waiting if it needs to.
And I'd increase the timeout time. Normally, the code will release the lock, so a long timeout doesn't affect that situation, but if the timeout ends before the code is done, that could cause a problem.
And if there is an error, then release the lock. So, the following code adds a try/catch block to handle that.
Also, you should test for an obtained lock before proceeding, and if the lock isn't obtained, then quit and notify someone that there was an error.
function zoneRepEmail(e) {
try{
var lock = LockService.getScriptLock();
lock.waitLock(60000); // wait 60 seconds before timing out
if (!lock.hasLock()) {//Failed to get lock
MailApp.sendEmail(Session.getEffectiveUser().getEmail(),
'Code Failed', 'The code for ABC failed');
//Logger.log('Could not obtain lock');
return;
}
for (i=1;i<4;i++) {//Try up to 3 times
try{
//Rate limited service call code here
break;
}catch(e){
if (i!==3){Utilities.sleep(i*2000);}
if (i>=3) {
MailApp.sendEmail(Session.getEffectiveUser().getEmail(),
'Code Failed', 'The code for ABC failed - ' + e.message + "\n\n" +
e.stack);
}
};
}
//Code here
lock.releaseLock();
} catch(e) {
lock.releaseLock();//Release the lock if there is an error
MailApp.sendEmail(Session.getEffectiveUser().getEmail(),
'Code Failed', 'The code for ABC failed - ' + e.message + "\n\n" +
e.stack);
//Logger.log('error: ' + e.message + ' stack: ' + e.stack);
}
}

Call airdrop contract method keep report error "Error: Transaction ran out of gas. Please provide more gas"

I had deployed a ERC20 token on ropsten testnet MyToken
. Now I want to send my token to multiple addresses. After google and some research I found OMG Airdropper may work. So i deployed airdrop on ropsten with the same key as MyToken contract.
I use web3js invoke 'multisend' method on airdrop contract, but got error:
(node:70819) UnhandledPromiseRejectionWarning: Error: Transaction ran out of gas. Please provide more gas:
Checked transaction receipt "gasUsed" is not exceed gasLimit:
{
"blockHash":
"0xb14df1fda48c44adb75249b46921b0a2889325ccd5335fc4282206a6731d03ed",
"blockNumber": 3423377,
"contractAddress": null,
"cumulativeGasUsed": 1440969,
"from": "0x7b4d9ef0740f75dbc79222a323246a3659609896",
"gasUsed": 30479,
"logs": [],
"logsBloom": "0x...many 0",
"status": false,
"to": "0xcf3afc7e21da35559269f7503b843ac543392ae0",
"transactionHash":
"0x53c7b6842308dec6be5ced3fd1cbb53848c73161da1eb0cfb323c3eb847eebd7",
"transactionIndex": 15
}
test code:
var fs = require('fs');
var parse = require('csv-parse');
var Web3 = require('web3');
var abi = require('./abi.json');
var _ = require('lodash');
const Tx = require('ethereumjs-tx');
var web3 = new Web3(new Web3.providers.HttpProvider("https://ropsten.infura.io/secure_key"));
var inputFile = 'smalldata.csv';
const main = async (addrs, tokens) => {
console.log(`web3 version: ${web3.version}`)
var contractJson = abi.abi;
var tokenAddress = "0x57fdf8001d1c240d4cbfc82b2fede932960dc310";
var myAddress = "0x7b4d9ef0740f75dbc79222a323246a3659609896";
var privateKey = "81d4f6e4b9d628fa15a9ff98f610e87d2662348c5666a7bf0fc39edf74f27b38";
var abiArray = abi.abi;
var contractAddress = "0xCF3aFC7e21Da35559269F7503b843ac543392aE0";
var count = await web3.eth.getTransactionCount(myAddress);
console.log(`num transactions so far: ${count}`);
var contract = new web3.eth.Contract(abiArray, contractAddress, {
from: myAddress
});
var rawTransaction = {
"from": myAddress,
"nonce": "0x" + count.toString(16),
"gasPrice": "0x003B9ACA00",
"gasLimit": "0x200B20",
"to": contractAddress,
"value": "0x0",
"data": contract.methods.multisend(tokenAddress, addrs, tokens).encodeABI(),
"chainId": "0x03",
"gas": "0x30D40"
};
var privKey = new Buffer(privateKey, 'hex');
var tx = new Tx(rawTransaction);
tx.sign(privKey);
var serializedTx = tx.serialize();
console.log(`Attempting to send signed tx: ${serializedTx.toString('hex')}`);
var receipt = await web3.eth.sendSignedTransaction('0x' + serializedTx.toString('hex'));
console.log(`Receipt info: ${JSON.stringify(receipt, null, '\t')}`);
}
var parser = parse({
delimiter: ','
}, function (err, data) {
let addressList = [];
let tokensList = [];
for (let i = 0; i < data.length; i++) {
addressList.push(data[i][0]);
tokensList.push(data[i][1]);
}
let addrsList = _.chunk(addressList, 2);
let tokenList = _.chunk(tokensList, 2);
main(addrsList[0], tokenList[0]);
});
fs.createReadStream(inputFile).pipe(parser);
sorry for not proper format code. Format well code at code on gist
csv data is:
0x7710f02222Ae6B4b2C308d98526B1D719D6ff2D5,188
0x34dB0eaDFfFE6ed5C4458badCA042F79ECF2a2A7,128
0xb3d475eB29E4fa88D5dB40d29D1AEa6A3C5cB3C9,288
0x5875A89a2043F0eAA858a26610fF58B4f5514e52,188
Any suggestion or help will be helpful. Thanks.

How to use an Service Account Oauth token to make REST call in appscript

I am using the GAS_Service_Account library.
I was able to do all the .p12 key decoding. But now I have:
myJwt.generateJWT().requestToken();
var token=myJwt.getToken();
Now I would like to know a simple way to use it to make an API call with
the service account to an api like drive to get a specific user's files.
Service accounts are powerful tools. The library GersonLobos mentions is: MJ5317VIFJyKpi9HCkXOfS0MLm9v2IJHf
Lets give some back ground. See the first half of this video on how to set up a service account in your domain:
https://www.youtube.com/watch?v=EDmEzZEGSts
With the library enabled in your project you can generate the token with the following:
// If userEmail is null the service account's token is returned
function tokenService(userEmail){
var userEmail = userEmail || ""
var jsonKey = JSON.parse(PropertiesService.getScriptProperties().getProperty("jsonKey"));
var privateKey = jsonKey.private_key;
var serviceAccountEmail = jsonKey.client_email;
if(!userEmail){userEmail = serviceAccountEmail};
var sa = GSApp.init(privateKey, ['https://www.googleapis.com/auth/drive'], serviceAccountEmail).addUser(userEmail);
var tokenObj = JSON.parse(PropertiesService.getScriptProperties().getProperty(userEmail)) || {};
return function(){
var nowTime = parseInt((Date.now()/1000).toString().substr(0,10));
if(!("token" in tokenObj) || tokenObj.expire < nowTime){
var newToken = sa.requestToken().getToken(userEmail);
PropertiesService.getScriptProperties().setProperty(userEmail, JSON.stringify(newToken));
tokenObj.token = newToken.token;
tokenObj.expire = newToken.expire;
}
return tokenObj.token;
}
}
Good now you have your token. I even show how to cache it as the requests take several seconds. Now you can make some calls. As requested by Gerson here are some drive calls:
function transferFileToUser(fileId, transferToEmail, token){
var url = "https://www.googleapis.com/drive/v2/files/"+fileId+"/permissions?sendNotificationEmails=false";
var payload = {"role":"owner","value":transferToEmail,"type":"user"};
var params ={method:"POST",
contentType:'application/json',
headers:{Authorization: "Bearer " + token},
payload:JSON.stringify(payload),
muteHttpExceptions:true
};
var results = UrlFetchApp.fetch(url, params);
return JSON.parse(results.getContentText());
}
function getAllFolders(token){
var query = "mimeType = 'application/vnd.google-apps.folder'";
return driveList(query, token);
}
function getFilesInFolder(folderId, token){
var query = "'"+folderId+"' in parents and mimeType != 'application/vnd.google-apps.folder'";
return driveList(query, token);
}
// genereic call to drive just pass the query
function driveList(query, token){
var filesArray = [];
var pageToken = "";
var query = encodeURIComponent(query);
var params = {method:"GET",
contentType:'application/json',
headers:{Authorization:"Bearer "+token},
muteHttpExceptions:true
};
var url = "https://www.googleapis.com/drive/v2/files?q="+query;
do{
var results = UrlFetchApp.fetch(url,params);
if(results.getResponseCode() != 200){
Logger.log(results);
break;
}
var files = JSON.parse(results.getContentText());
url = "https://www.googleapis.com/drive/v2/files?q="+query;
for(var i in files.items){
filesArray.push({"name":files.items[i].title, "id":files.items[i].id})
}
pageToken = files.nextPageToken;
url += "&pageToken="+encodeURIComponent(pageToken);
}while(pageToken != undefined)
var filesObj = {};
filesObj["fileObjs"] = filesArray;
return filesObj;
}