I want to create a Rocket Chat client to subscribe to a channel through browser using Realtime API. Documentation here does not provide step by step procedure. Please let me know how to achieve it.
Links to any documentation would be very helpful.
I had less idea about websockets when I asked this question. For the benefit of all, mentioning the steps I followed.
Open websocket
var rocketChatSocket = new WebSocket("ws://locahost:3000/websocket");
Connect
var connectRequest = {
"msg": "connect",
"version": "1",
"support": ["1", "pre2", "pre1"]
}
rocketChatSocket.send(JSON.stringify(connectRequest));
After connecting, keep responding with {"msg":"pong"} for {"msg":"ping"} from server.
Login with authToken received by calling this API
var loginRequest = {
"msg": "method",
"method": "login",
"id": "42",
"params": [
{ "resume": "authToken" }
]
}
rocketChatSocket.send(JSON.stringify(loginRequest));
Subscribe to room
var subscribeRequest = {
"msg": "sub",
"id": "unique-id",
"name": "stream-notify-room",
"params":[
"room-id/event",
false
]
}
rocketChatSocket.send(JSON.stringify(subscribeRequest));
Send message
var request={
"msg": "method",
"method": "sendMessage",
"id": "42",
"params":
[
{
"_id": "message-id",
"rid": "room-id",
"msg": "Hello World!"
}
]
}
rocketChatSocket.send(JSON.stringify(request));
Thank you Mr Nandan,we were able to use your answer to build fully custom client to talk with the rocket chat real time api
here's the link for future people who will want the same thing
https://github.com/lalosh/rocketchat.realTimeAPI.customClient/blob/master/main.js
and here's the code in case you want to check immediately
/*
Rocket Chat Real Time API Custom Client
even though this code works great I don't know what exactly each event we listen for is doing
you can go back to rocket chat real time api for further declarations
we were able to write this code after we test real normal use case of livechat in a web page
and we listen for WebSocket connection inside the browser Network tab(by filtering ws(WebSocket) connections)
*/
let socket = new WebSocket('ws://[rocketChatIP]:[rocketChatPort]/websocket');
//note messageCount is incremented with every message
//but it can works even if you didn't change it
let messagesCount = 1;
// the variables chatToken and chatRoomId are very important
// and they are the identifier to the room(the whole chat) you are using
// if you want to get access to the chat again you need these two variables tokens
let chatToken = generateHash(17);
let chatRoomId = generateHash(17);
let subId = generateHash(17);
let roomSubId = generateHash(17);
let streamLivechatchatRoomId = generateHash(17);
let steamNotifyRoomSubId = generateHash(17);
let name = 'user28';
let email = 'user28#gmail.com';
let guestName = 'guest';
// listen to messages passed to this socket
socket.onmessage = function(e) {
let response = JSON.parse(e.data);
console.log('response', response);
// you have to pong back if you need to keep the connection alive
// each ping from server need a 'pong' back
if (response.msg == 'ping') {
console.log('pong!');
socket.send(JSON.stringify({
msg: 'pong'
}));
return;
}
// here you receive messages from server //notive the event name is: 'stream-room-messages'
if (response.msg === 'changed' && response.collection === 'stream-room-messages') {
console.log('msg received ', response.fields.args[0].msg, 'timestamp ', response.fields.args[0].ts.$date, 'from ' + response.fields.args[0].u.name);
return;
}
// receive all messages which will only succeed if you already have messages
// in the room (or in case you send the first message immediately you can listen for history correctly)
if (response.msg === 'result' && response.result) {
if (response.result.messages) {
let allMsgs = response.result.messages;
console.log('-----previous msgs---------------');
allMsgs.map(x => console.log(x))
console.log('---------------------------------')
}
}
}
//////////////////////////////////////////////
// steps to achieve the connection to the rocket chat real time api through WebSocket
//1 connect
let connectObject = {
msg: 'connect',
version: '1',
support: ['1', 'pre2', 'pre1']
}
setTimeout(() => {
socket.send(JSON.stringify(connectObject));
}, 1000)
//////////////////////////////////////////////
//2 getInitialData
let getInitialDataObject = {
msg: 'method',
method: 'livechat:getInitialData',
params: [String(chatToken), null],
id: String(messagesCount++),
}
setTimeout(() => {
socket.send(JSON.stringify(getInitialDataObject));
}, 2000)
//////////////////////////////////////////////
//3 loginByToken
let loginByToken = {
msg: 'method',
method: 'livechat:loginByToken',
params: [String(chatToken)],
id: String(messagesCount++),
}
setTimeout(() => {
socket.send(JSON.stringify(loginByToken));
}, 3000)
//////////////////////////////////////////////
//4 subscribtion
let subObj = {
msg: 'sub',
id: subId,
name: 'meteor.loginServiceConfiguration',
params: []
}
setTimeout(() => {
socket.send(JSON.stringify(subObj));
}, 4000)
//////////////////////////////////////////////
//5 register // you may skip this if you alredy registered
// or you can re use it even though you are registered.. no problems
// the crucial part is the `chatToken` and later on the `chatRoomId`
let registerObj = {
msg: 'method',
method: 'livechat:registerGuest',
params: [{
token: chatToken,
name: name,
email: email,
'department': null
}],
id: String(messagesCount++),
};
setTimeout(() => {
socket.send(JSON.stringify(registerObj));
}, 5000)
//////////////////////////////////////////////////
//6 stream-notify-room
let streamNotifyObj = {
msg: 'method',
method: 'stream-notify-room',
params: [
'null/typing',
guestName, true, {
token: String(chatToken)
}
],
id: String(messagesCount++)
};
setTimeout(() => {
socket.send(JSON.stringify(streamNotifyObj));
}, 6000)
//////////////////////////////////////////////////
//7 send a msg //use the same method to send your own messages again when you are all connected
let myMsg = {
msg: 'method',
method: 'sendMessageLivechat',
params: [{
_id: String(generateHash(17)),
rid: chatRoomId,
msg: 'first message',
token: String(chatToken),
}, null],
id: String(messagesCount++),
}
setTimeout(() => {
socket.send(JSON.stringify(myMsg));
}, 7000)
//////////////////////////////////////////////////
//8 send userPresence
let UserPresence = {
msg: 'method',
method: 'UserPresence:connect',
params: [
String(chatToken),
{
visitor: String(chatToken)
}
],
id: String(messagesCount++)
}
setTimeout(() => {
socket.send(JSON.stringify(UserPresence));
}, 8000)
/////////////////////////////////////////////////
//9 loadHistory of old messages
let loadHistory = {
msg: 'method',
method: 'livechat:loadHistory',
params: [{
token: String(chatToken),
rid: String(chatRoomId),
ts: {
$date: new Date().getTime()
}, //current point of time
limit: 50
}],
id: String(messagesCount++)
};
setTimeout(() => {
socket.send(JSON.stringify(loadHistory));
}, 9000)
/////////////////////////////////////////////////
// 10 stream-room-messages
// listen to all received messages
let roomMessagesSub = {
msg: 'sub',
id: String(roomSubId),
name: 'stream-room-messages',
params: [
String(chatRoomId),
{
useCollection: false,
args: [{
visitorToken: String(chatToken)
}]
}
]
};
setTimeout(() => {
socket.send(JSON.stringify(roomMessagesSub));
}, 10000)
/////////////////////////////////////////////////
// 11 getAgentData
let getAgentData = {
msg: 'method',
method: 'livechat:getAgentData',
params: [{
roomId: String(chatRoomId),
token: String(chatToken),
}],
id: String(messagesCount++)
}
setTimeout(() => {
socket.send(JSON.stringify(getAgentData));
}, 11000)
/////////////////////////////////////////////////
//12 stream-livechat-room
let streamLivechatRoom = {
msg: 'sub',
id: String(streamLivechatchatRoomId),
name: 'stream-livechat-room',
params: [
String(chatRoomId),
{
useCollection: false,
args: [{
'visitorToken': String(chatToken)
}]
}
]
}
setTimeout(() => {
socket.send(JSON.stringify(streamLivechatRoom));
}, 12000)
//////////////////////////////////////////
//13 stream-notify-room
let steamNotifyRoomSub = {
msg: 'sub',
id: String(steamNotifyRoomSubId),
name: 'stream-notify-room',
params: [
`${String(chatRoomId)}/typing`,
{
useCollection: false,
args: [{
token: String(chatToken)
}]
}
]
}
setTimeout(() => {
socket.send(JSON.stringify(steamNotifyRoomSub));
}, 13000)
//////////////////////////////////////
//14 userpresence 2
let UserPresence2 = {
msg: 'method',
method: 'UserPresence:online',
params: [String(chatToken)],
id: String(messagesCount++),
}
setTimeout(() => {
socket.send(JSON.stringify(UserPresence2));
}, 14000)
//////////////////////////////////////
//use it to send new messages
function sendNewMsg(msg, messagesCount) {
let myMsg = {
msg: 'method',
method: 'sendMessageLivechat',
params: [{
_id: String(generateHash(17)),
rid: chatRoomId,
msg: String(msg),
token: String(chatToken),
}, null],
id: String(messagesCount++),
}
setTimeout(() => {
socket.send(JSON.stringify(myMsg));
}, 500);
}
function generateHash(targetLength) {
var text = '';
var possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
for (var i = 0; i < targetLength; i++)
text += possible.charAt(Math.floor(Math.random() * possible.length));
return text;
}
If you like to use an open source library for this purpose, here is one https://github.com/inf3cti0n95/Rocket.Chat.RealTime.API.RxJS
Here is the sample code:
import { RealTimeAPI } from "rocket.chat.realtime.api.rxjs";
const realTimeAPI = new RealTimeAPI("wss://demo.rocket.chat/websocket");
realTimeAPI.keepAlive();
const auth = realTimeApi.login(USERNAME, PASSWORD);
//Subscribe to messages and errors
auth.subscribe(
(data) => console.log(data),
(err) => console.log(err),
() => console.log('completed'));
//Subscribe to a specific channel, identified by roomId
realtimeAPI.sendMessage({
msg: 'sub',
id: '<a unique Id for subscription>',
name: 'stream-room-messages',
params: [roomId, false],
});
Related
I'm currently following Patrick C. Web3 development tutorial. I would have cloned the github repo for lesson 9 and and changed what needed to be changed. After running yarn hardhat deploy --network goerli, the terminal would output: Error HH110: Invalid JSON-RPC response received: project id required in the url.
Code for 01-deploy-raffle.js:
const { network, ethers } = require("hardhat")
const {
networkConfig,
developmentChains,
VERIFICATION_BLOCK_CONFIRMATIONS,
} = require("../helper-hardhat-config")
const { verify } = require("../utils/verify")
const FUND_AMOUNT = ethers.utils.parseEther("1") // 1 Ether, or 1e18 (10^18) Wei
module.exports = async ({ getNamedAccounts, deployments }) => {
const { deploy, log } = deployments
const { deployer } = await getNamedAccounts()
const chainId = network.config.chainId
let vrfCoordinatorV2Address, subscriptionId, vrfCoordinatorV2Mock
if (chainId == 31337) {
// create VRFV2 Subscription
vrfCoordinatorV2Mock = await ethers.getContract("VRFCoordinatorV2Mock")
vrfCoordinatorV2Address = vrfCoordinatorV2Mock.address
const transactionResponse = await vrfCoordinatorV2Mock.createSubscription()
const transactionReceipt = await transactionResponse.wait()
subscriptionId = transactionReceipt.events[0].args.subId
// Fund the subscription
// Our mock makes it so we don't actually have to worry about sending fund
await vrfCoordinatorV2Mock.fundSubscription(subscriptionId, FUND_AMOUNT)
} else {
vrfCoordinatorV2Address = networkConfig[chainId]["vrfCoordinatorV2"]
subscriptionId = networkConfig[chainId]["subscriptionId"]
}
const waitBlockConfirmations = developmentChains.includes(network.name)
? 1
: VERIFICATION_BLOCK_CONFIRMATIONS
log("----------------------------------------------------")
const arguments = [
vrfCoordinatorV2Address,
subscriptionId,
networkConfig[chainId]["gasLane"],
networkConfig[chainId]["keepersUpdateInterval"],
networkConfig[chainId]["raffleEntranceFee"],
networkConfig[chainId]["callbackGasLimit"],
]
const raffle = await deploy("Raffle", {
from: deployer,
args: arguments,
log: true,
waitConfirmations: waitBlockConfirmations,
})
// Verify the deployment
if (!developmentChains.includes(network.name) && process.env.ETHERSCAN_API_KEY) {
log("Verifying...")
await verify(raffle.address, arguments)
}
log("Enter lottery with command:")
const networkName = network.name == "hardhat" ? "localhost" : network.name
log(`yarn hardhat run scripts/enterRaffle.js --network ${networkName}`)
log("----------------------------------------------------")
}
module.exports.tags = ["all", "raffle"]
Code for helper-hardhat-config.js:
const { ethers } = require("hardhat")
const networkConfig = {
default: {
name: "hardhat",
keepersUpdateInterval: "30",
},
31337: {
name: "localhost",
subscriptionId: "4640",
gasLane: "0xd89b2bf150e3b9e13446986e571fb9cab24b13cea0a43ea20a6049a85cc807cc", // 30 gwei
keepersUpdateInterval: "30",
raffleEntranceFee: ethers.utils.parseEther("0.01"), // 0.1 ETH
callbackGasLimit: "500000", // 500,000 gas
},
5: {
name: "goerli",
subscriptionId: "4640",
gasLane: "0x79d3d8832d904592c0bf9818b621522c988bb8b0c05cdc3b15aea1b6e8db0c15", // 30 gwei
keepersUpdateInterval: "30",
raffleEntranceFee: ethers.utils.parseEther("0.01"), // 0.1 ETH
callbackGasLimit: "500000", // 500,000 gas
vrfCoordinatorV2: "0x2Ca8E0C643bDe4C2E08ab1fA0da3401AdAD7734D",
},
1: {
name: "mainnet",
keepersUpdateInterval: "30",
},
}
const developmentChains = ["hardhat", "localhost"]
const VERIFICATION_BLOCK_CONFIRMATIONS = 6
const frontEndContractsFile = "../nextjs-smartcontract-lottery-fcc/constants/contractAddresses.json"
const frontEndAbiFile = "../nextjs-smartcontract-lottery-fcc/constants/abi.json"
module.exports = {
networkConfig,
developmentChains,
VERIFICATION_BLOCK_CONFIRMATIONS,
frontEndContractsFile,
frontEndAbiFile,
}
Code for hardhat.config.js:
require("#nomiclabs/hardhat-waffle")
require("#nomiclabs/hardhat-etherscan")
require("hardhat-deploy")
require("solidity-coverage")
require("hardhat-gas-reporter")
require("hardhat-contract-sizer")
require("dotenv").config()
/**
* #type import('hardhat/config').HardhatUserConfig
*/
const MAINNET_RPC_URL =
process.env.MAINNET_RPC_URL ||
process.env.ALCHEMY_MAINNET_RPC_URL ||
"https://eth-mainnet.alchemyapi.io/v2/your-api-key"
const GOERLI_RPC_URL =
process.env.GOERLI_RPC_URL || "https://eth-goerli.alchemyapi.io/v2/your-api-key"
const POLYGON_MAINNET_RPC_URL =
process.env.POLYGON_MAINNET_RPC_URL || "https://polygon-mainnet.alchemyapi.io/v2/your-api-key"
const PRIVATE_KEY = process.env.PRIVATE_KEY || "0x"
// optional
const MNEMONIC = process.env.MNEMONIC || "your mnemonic"
// Your API key for Etherscan, obtain one at https://etherscan.io/
const ETHERSCAN_API_KEY = process.env.ETHERSCAN_API_KEY || "Your etherscan API key"
const POLYGONSCAN_API_KEY = process.env.POLYGONSCAN_API_KEY || "Your polygonscan API key"
const REPORT_GAS = process.env.REPORT_GAS || false
module.exports = {
defaultNetwork: "hardhat",
networks: {
hardhat: {
// // If you want to do some forking, uncomment this
// forking: {
// url: MAINNET_RPC_URL
// }
chainId: 31337,
},
localhost: {
chainId: 31337,
},
goerli: {
url: GOERLI_RPC_URL,
accounts: PRIVATE_KEY !== undefined ? [PRIVATE_KEY] : [],
// accounts: {
// mnemonic: MNEMONIC,
// },
saveDeployments: true,
chainId: 5,
},
mainnet: {
url: MAINNET_RPC_URL,
accounts: PRIVATE_KEY !== undefined ? [PRIVATE_KEY] : [],
// accounts: {
// mnemonic: MNEMONIC,
// },
saveDeployments: true,
chainId: 1,
},
polygon: {
url: POLYGON_MAINNET_RPC_URL,
accounts: PRIVATE_KEY !== undefined ? [PRIVATE_KEY] : [],
saveDeployments: true,
chainId: 137,
},
},
etherscan: {
// yarn hardhat verify --network <NETWORK> <CONTRACT_ADDRESS> <CONSTRUCTOR_PARAMETERS>
apiKey: {
goerli: ETHERSCAN_API_KEY,
polygon: POLYGONSCAN_API_KEY,
},
},
gasReporter: {
enabled: REPORT_GAS,
currency: "USD",
outputFile: "gas-report.txt",
noColors: true,
// coinmarketcap: process.env.COINMARKETCAP_API_KEY,
},
contractSizer: {
runOnCompile: false,
only: ["Raffle"],
},
namedAccounts: {
deployer: {
default: 0, // here this will by default take the first account as deployer
1: 0, // similarly on mainnet it will take the first account as deployer. Note though that depending on how hardhat network are configured, the account 0 on one network can be different than on another
},
player: {
default: 1,
},
},
solidity: {
compilers: [
{
version: "0.8.7",
},
{
version: "0.4.24",
},
],
},
mocha: {
timeout: 500000, // 500 seconds max for running tests
},
}
trying to send buttons using whatsapp web js following the official documentation ,
note : number is user input
client.on('ready', async () => {
console.log('Client is ready!');
button = new Buttons('Button body',[{body:'bt1'},{body:'bt2'},{body:'bt3'}],'title','footer');
console.log(button)
chatId= number.substring(1) + "#c.us"
client.sendMessage(chatId,button);
}
client is ready is printed in terminal
but message not sent
Hi used this code to achieve buttons with multiple options:-
const { Client, LocalAuth, List } = require('whatsapp-web.js');
const client = new Client({
authStrategy: new LocalAuth({ clientId: "client-one" }),
puppeteer: {
headless: false,
args: ['--no-sandbox',
'--disable-setuid-sandbox',
'--disable-extensions',
'--disable-dev-shm-usage',
'--disable-accelerated-2d-canvas',
'--no-first-run',
'--no-zygote',
'--single-process', // <- this one doesn't works in Windows
'--disable-gpu']
}
});
client.on('ready', async () => {
const number = "9999999999";
const sanitized_number = number.toString().replace(/[- )(]/g, ""); // remove unnecessary chars from the number
const final_number = `91${sanitized_number.substring(sanitized_number.length - 10)}`; // add 91 before the number here 91 is country code of India
const number_details = await client.getNumberId(final_number); // get mobile number details
const productsList = new List(
"Amazing deal on these products",
"View products",
[
{
title: "Products list",
rows: [
{ id: "apple", title: "Apple" },
{ id: "mango", title: "Mango" },
{ id: "banana", title: "Banana" },
],
},
],
"Please select a product"
);
if (number_details) {
const sendMessageData = await client.sendMessage(number_details._serialized, productsList); // send message
console.log('msg sent now closing ', sendMessageData)
setTimeout(() => {
client.destroy()
}, 20000);
} else {
console.log(final_number, "Mobile number is not registered");
}
});
client.initialize()
Using this node-ews package, I can send email, but I haven't been able to find a good example of how to read mails from the Inbox folder and get the email's text and attachments.
I've read the Microsoft documentation, such as this one: https://learn.microsoft.com/en-us/exchange/client-developer/exchange-web-services/how-to-work-with-exchange-mailbox-items-by-using-ews-in-exchange#get-an-item-by-using-the-ews-managed-api, but the examples are in C#, C++, or VB.
However, I would like to use Nodejs for this.
**I have found a best way extract every content using mailparser. see bellow
// At first Read emails from Inbox
const EWS = require('node-ews');
const simpleParser = require('mailparser').simpleParser;
// exchange server connection info
const ewsConfig = {
username: 'username',
password: 'password',
host: 'hostname'
};
const options = {
rejectUnauthorized: false,
strictSSL: false
};
// initialize node-ews
const ews = new EWS(ewsConfig, options);
var ewsFunction = 'FindItem';
var ewsArgs = {
'attributes': {
'Traversal': 'Shallow'
},
'ItemShape': {
't:BaseShape': 'Default'
},
'ParentFolderIds' : {
'DistinguishedFolderId': {
'attributes': {
'Id': 'inbox'
}
}
}
};
// Itreate over all the emails and store Id and ChangeKey.
ews.run(ewsFunction, ewsArgs, ewsSoapHeader)
.then(result => {
// Iterate over the result and extract Id and ChangeKey of the messages and pass those to GetItem function to read messages
})
// For reading individual messages returned by FindItem (using Id and ChangeKey)
var ewsFunction = 'GetItem';
var ewsArgs = {
'ItemShape': {
'BaseShape': 'Default',
'AdditionalProperties': {
'FieldURI': [
{ 'attributes': { 'FieldURI': 'item:MimeContent'}}
]
}
},
'ItemIds': {
'ItemId': {
'attributes': {
'Id': Id,
'ChangeKey': ChangeKey
}
}
}
};
await ews.run(ewsFunction, ewsArgs, ewsSoapHeader)
.then(result => {
// Iterate over the result and extract meesage
const {Message} = result.ResponseMessages.GetItemResponseMessage.Items
let mimeContent = Buffer.from(Message.MimeContent['$value'], 'base64').toString('binary');// decode mime content
simpleParser(mimeContent).then(async function (mail) {
console.log("mail")
console.log(mail.attachments)
console.log(mail.headers.get('message-id'))
console.log(mail.headers.get('references'))
console.log(mail.headers.get('in-reply-to'))
console.log({
// text: mail.text,
// html: mail.html ? mail.html.replace(/<meta([^>]+)>/g, "") : "",
from: (mail.from) ? mail.from.value.map(item => item.address) : [],
to: (mail.to) ? mail.to.value.map(item => item.address) : [],
cc: (mail.cc) ? mail.cc.value.map(item => item.address) : [],
bcc: (mail.bcc) ? mail.bcc.value.map(item => item.address) : [],
messageId: mail.messageId,
subject: mail.subject
})
}).catch((err) => {
console.log("err")
console.log(err)
})
})
Here you will get the full parsed mail contents with attachments. Happy Coding!!!
For creating an action at hasura I'm using the following node.js code (still at an experimental stage) in glitch.com -
const execute = async (gql_query, variables) => {
const fetchResponse = await fetch(
"https://example.com/v1/graphql",
{
method: "POST",
body: JSON.stringify({
query: gql_query,
variables: variables
})
}
);
// console.log('DEBUG: ', fetchResponse);
const data = await fetchResponse.json();
console.log("DEBUG: ", data);
return data;
};
// paste the code from codegen here
const ACTION_INSERT_PAYSLIP_GET_DRIVER_PAYMENT_DATA = `
query getDriverPaymentData ($orders: [Int!]!) {
company_order (where: {company_order_id: {_in: $orders}}) {
company_order_details (distinct_on: stage_cost_driver_id) {
stage_cost_driver_id
company_user {
delivery_salary
}
}
}
}`
// Request Handler
app.post('/action_insert_payslip', async (req, res) => {
// get request input
const { order_list } = req.body.input
console.log('Input', order_list)
const orders = order_list.order_id
console.log('Item: ', orders)
const { data:driverPaymentData, errors:driverPaymentError} = await execute(ACTION_INSERT_PAYSLIP_GET_DRIVER_PAYMENT_DATA, orders)
console.log('Driver Payment Data: ', driverPaymentData)
// run some business logic
// success
return res.json({
// payslip_list: "<value>"
payslip_list: order_list
})
});
The query getDriverPaymentData produces an output like the following in hasura api explorer:
{
"data": {
"company_order": [
{
"company_order_details": [
{
"stage_cost_driver_id": 1,
"company_user": {
"delivery_salary": 20
}
},
{
"stage_cost_driver_id": 6,
"company_user": {
"delivery_salary": 10
}
}
]
},
{
"company_order_details": [
{
"stage_cost_driver_id": 6,
"company_user": {
"delivery_salary": 10
}
}
]
}
]
}
}
But in the log, I'm getting the following output:
Input { order_id: [ 247, 260, 253 ] }
Item: [ 247, 260, 253 ]
DEBUG: { errors:
[ { extensions: [Object],
message:
'parsing HashMap failed, expected Object, but encountered Array' } ] }
Driver Payment Data: undefined
It says that it expects object but encountered array. But from what I see, I'm already getting an object "data": {[....]} with array inside it from the output at hasura's API console.
What am I missing here? How can I get the data of stage_cost_driver_id and delivery_salary?
Shouldn't variables be an object?
body: JSON.stringify({
query: gql_query,
variables: {orders: variables}
})
const network = {
blockchain:'eos',
protocol:'https',
host:'jungle2.cryptolions.io',
port:443,
chainId: 'e70aaab8997e1dfce58fbfac80cbbb8fecec7b99cf982a9444273cbc64c41473',
sign: true,
broadcast: true,
debug: true,
verbose: false,
}
try {
const scatterInfo = await ScatterJS.scatter.connect('eosbetdice');
console.log({scatterInfo})
if ( scatterInfo ) {
const scatter = ScatterJS.scatter;
const requiredFields = { accounts:[network] };
const scatterVal = await scatter.getIdentity(requiredFields);
console.log({scatter,scatterVal})
if ( scatterVal ) {
const account = scatter.identity.accounts.find(x => x.blockchain === 'eos');
console.log("account",account)
const result = await api.transact({
actions: [{
account: 'eosio.token',
name: 'transfer',
authorization: [{
actor: account.name,
permission:'active',
signatures:[signature],
available_keys:[account.publicKey]
}],
data: {
from: 'abceristest2',
to: account.name,
quantity: betAsset,
memo: memo
},
}]
}, {
blocksBehind: 3,
expireSeconds: 30,
});
console.log({result})
return result;
}
} return false;
} catch ( exception ) {
console.log( exception )
}
I expect the transfer function will be work fine but It give me 401 unauthorized error. This transfer function hit the api of jungle testnet , "http://jungle.eosgen.io/v1/chain/get_required_keys"
How I can authenticate this function?
Error which I got, when this transfer function run
I don't check your codes in detail, but I think it is needed to set the data of "abceristest2" to authorization parameter.