Get all transactions for an NFT on Solana - api

I want to collect all transactions for an NFT.
For example, you can display all transactions here:
https://explorer.solana.com/address/2Nzt8TYeAfgJDftKzkb7rgYShVvyXTR7cPVvpqaZ2a4V
or here:
https://solscan.io/token/2Nzt8TYeAfgJDftKzkb7rgYShVvyXTR7cPVvpqaZ2a4V#txs
But is there any way to do this with the API?
I checked
solana-py: https://michaelhly.github.io/solana-py/
and solscan api: https://public-api.solscan.io/docs/
But I could not find a way to do it.

You can use the getSignaturesForAddress RPC method on the mint address and walk backward to get all the transactions.
Here is an example in JS:
import {
Connection,
clusterApiUrl,
ConfirmedSignatureInfo,
PublicKey,
} from "#solana/web3.js";
const connection = new Connection(clusterApiUrl("mainnet-beta"));
export const getTxs = async (connection: Connection, pubkey: PublicKey) => {
const txs: ConfirmedSignatureInfo[] = [];
// Walk backward
let lastTransactions = await connection.getConfirmedSignaturesForAddress2(
pubkey
);
let before = lastTransactions[lastTransactions.length - 1].signature;
txs.push(...lastTransactions);
while (true) {
const newTransactions = await connection.getConfirmedSignaturesForAddress2(
pubkey,
{
before,
}
);
if (newTransactions.length === 0) break;
txs.push(...newTransactions);
before = newTransactions[newTransactions.length - 1].signature;
}
return txs;
};
getTxs(
connection,
new PublicKey("2Nzt8TYeAfgJDftKzkb7rgYShVvyXTR7cPVvpqaZ2a4V")
);
The equivalent method in Solana.py is this one https://michaelhly.github.io/solana-py/rpc/api/#solana.rpc.api.Client.get_signatures_for_address

Related

Write rows to BigQuery via nodejs BigQuery Storage Write API

It seems quite new, but just hoping someone here has been able to use nodejs to write directly to BigQuery storage using #google-cloud/bigquery-storage.
There is an explanation of how the overall backend API works and how to write a collection of rows atomically using BigQuery Write API but no such documentation for nodejs yet. A recent release 2.7.0 documents the addition of said feature but there is no documentation, and the code is not easily understood.
There is an open issue requesting an example but thought I'd try my luck to see if anyone has been able to use this API yet.
Suppose you have a BigQuery table called student with three columns id,name and age. Following steps will get you to load data into the table with nodejs storage write api.
Define student.proto file as follows
syntax = "proto2";
message Student {
required int64 id = 1;
optional string name = 2;
optional int64 age = 3;
}
Run the following at the command prompt
protoc --js_out=import_style=commonjs,binary:. student.proto
It should generate student_pb.js file in the current directory.
Write the following js code in the current directory and run it
const {BigQueryWriteClient} = require('#google-cloud/bigquery-storage').v1;
const st = require('./student_pb.js')
const type = require('#google-cloud/bigquery-storage').protos.google.protobuf.FieldDescriptorProto.Type
const mode = require('#google-cloud/bigquery-storage').protos.google.cloud.bigquery.storage.v1.WriteStream.Type
const storageClient = new BigQueryWriteClient();
const parent = `projects/${project}/datasets/${dataset}/tables/student`
var writeStream = {type: mode.PENDING}
var student = new st.Student()
var protoDescriptor = {}
protoDescriptor.name = 'student'
protoDescriptor.field = [{'name':'id','number':1,'type':type.TYPE_INT64},{'name':'name','number':2,'type':type.TYPE_STRING},{'name':'age','number':3,'type':type.TYPE_INT64}]
async function run() {
try {
var request = {
parent,
writeStream
}
var response = await storageClient.createWriteStream(request);
writeStream = response[0].name
var serializedRows = []
//Row 1
student.setId(1)
student.setName('st1')
student.setAge(15)
serializedRows.push(student.serializeBinary())
//Row 2
student.setId(2)
student.setName('st2')
student.setAge(15)
serializedRows.push(student.serializeBinary())
var protoRows = {
serializedRows
}
var proto_data = {
writerSchema: {protoDescriptor},
rows: protoRows
}
// Construct request
request = {
writeStream,
protoRows: proto_data
};
// Insert rows
const stream = await storageClient.appendRows();
stream.on('data', response => {
console.log(response);
});
stream.on('error', err => {
throw err;
});
stream.on('end', async () => {
/* API call completed */
try {
var response = await storageClient.finalizeWriteStream({name: writeStream})
response = await storageClient.batchCommitWriteStreams({parent,writeStreams: [writeStream]})
}
catch(err) {
console.log(err)
}
});
stream.write(request);
stream.end();
}
catch(err) {
console.log(err)
}
}
run();
Make sure your environment variables are set correctly to point to the file containing google cloud credentials.
Change project and dataset values accordingly.

SQLite3 Database is not a constructor

So in my project I am trying to gather simple Discord username and unique identifier from discord and store it in SQLite database file. I get the error:
` let userDB = new sqlite.Database('./disco.db', sqlite.OPEN_READWRITE);
^
TypeError: sqlite.Database is not a constructor`
Here is my code in my index.js
// Requirements
const Discord = require('discord.js');
const client = new Discord.Client();
const fs = require('fs');
const ServList = client.guilds.cache.size;
const sqlite = require('sqlite3').verbose();
require('dotenv').config()
//client login function
client.login(process.env.TOKEN);
// Start up Check list
client.once('ready', () => {
//Log and Set Status
console.log('Bot Online');
client.user.setActivity(`Proudly in ${client.guilds.cache.size} servers`, {
type: "WATCHING",
}, 60000);
//Database Initialization
let userDB = new sqlite.Database('./disco.db', sqlite.OPEN_READWRITE | sqlite.OPEN_CREATE);
});
Here is my code for the command that is creating the error:
const Discord = require('discord.js');
const sqlite = require('sqlite3').verbose();
module.exports = {
name: 'create',
description: "Create your account!",
use(message, args, client, sqlite){
// Data to Add
let userDB = new sqlite.Database('./disco.db', sqlite.OPEN_READWRITE);
userDB.run(`CREATE TABLE IF NOT EXIST usersInfo(userID INTEGER NOT NULL, uNameR TEXT NOT NULL)`);
let userID = message.author.id;
let uName = message.author.tag;
let uQuery = `SELECT * FROM usersInfo WHERE userID = ?`;
userDB.get(uQuery, [userID], (err, row) => {
if (err) {
console.log(err);
return;
}
if (row === undefined){
userDB.prepare(`INSERT INTO usersInfo VALUES(?,?)`);
insertdata.run('userID, uName');
insertdata.finalize();
userDB.close();
} else {
let userID2 = row.userID;
let yName = row.uNameR;
console.log(yName, userID);
}
});
message.channel.send('success');
}
}
Edit: Your question has been identified as a possible duplicate of another question. If the answers there do not address your problem, please edit to explain in detail the parts of your question that are unique.
The suggestion solution does not work for me as the suggested answer utilizes mySQL while I use SQLite3, Not only that but the suggested answer attempts to connect to a hosted database while mine is local.

Write query in BigQuery from Pubsub

need some help.
I'm receiving messages with data in a PubSub topic, I need to insert the data I get from the message and query in BigQuery with a background cloud function(PUB/SUB)...
What I manage to do:
/**
* Triggered from a message on a Cloud Pub/Sub topic.
*
* #param {!Object} event Event payload.
* #param {!Object} context Metadata for the event.
*/
exports.insertBigQuery = (message, context) => {
extractQuery(message.data);
};
function extractQuery(pubSubMessage){
// Decide base64 the PubSub message
let logData = Buffer.from(pubSubMessage, 'base64').toString();
// Convert it in JSON
let logMessage= JSON.parse(logData);
console.log(logMessage.customerToken)
console.log(logMessage.fbclid)
console.log(logMessage.fbc)
console.log(logMessage.fbp)
console.log(logMessage.firstHitTS)
console.log(logMessage.consentFB)
main();
return logMessage
}
"use strict";
function main() {
const { BigQuery } = require("#google-cloud/bigquery");
const bigquery = new BigQuery();
async function query() {
const query = `INSERT INTO MYTABLE( customerToken, fbclid, fbc, fbp, firstHitTS, consentFB)
VALUES ("customerTokenSCRIPTCLOUD","fbclidSCRIPT"," fbcSCRIPTCLOUD"," fbpSCRIPTCLOUD","2021-01-05",TRUE )`;
const options = {
query: query,
location: "US",
};
const [job] = await bigquery.createQueryJob(options);
console.log(`Job ${job.id} started.`);
const [rows] = await job.getQueryResults();
console.log("Rows:");
rows.forEach((row) => console.log(row));
}
query();
}
Now every time I receive a message I query in bigQuery, but my VALUES is hard coded, as you can see here:
const query = `INSERT INTO devsensetestprojects.TestDataSet.fbSimpleData( customerToken, fbclid, fbc, fbp, firstHitTS, consentFB)
VALUES ("customerTokenSCRIPTCLOUD","fbclidSCRIPT"," fbcSCRIPTCLOUD"," fbpSCRIPTCLOUD","2021-01-05",TRUE )`;
What I'm not able to do is to get the values from function extractQuery(pubSubMessage) and use them in my query the same way I use in the function (logMessage.SOMEVALUE) to have the correct values I need.
Thanks in advance!
As you said, you are beginner in development. Here a more concise and efficient code. I didn't tested it but it is closer of what you want. Let me know is some part are mysterious for you!
// Make them global to load them only when the Cloud Function instance is created
// They will be reused in the subsequent processing and until the instance deletion
const { BigQuery } = require("#google-cloud/bigquery");
const bigquery = new BigQuery();
exports.insertBigQuery = async (message, context) => {
// Decode base64 the PubSub message
let logData = Buffer.from(message.data, 'base64').toString();
// Convert it in JSON
let logMessage= JSON.parse(logData);
const query = createQuery(logMessage)
const options = {
query: query,
location: "US",
};
const [job] = await bigquery.createQueryJob(options);
console.log(`Job ${job.id} started.`);
// Only wait the end of the job. Theere is no row as answer, it's only an insert
await job.getQueryResults();
}
function createQuery(logMessage) {
// You maybe have to format correctly the logMessage.firstHitTS to be accepted by BigQuery as a date.
return `INSERT INTO MYTABLE(customerToken, fbclid, fbc, fbp, firstHitTS, consentFB)
VALUES (logMessage.customerToken, logMessage.fbclid, logMessage.fbc, logMessage.fbp,
logMessage.firstHitTS, logMessage.consentFB)`;
}

TestCafe - Can You Pass ctx (Context) Variables to reporter?

I would like to know if I have a context variable like t.ctx.data, is there a way to get that to write the value of t.ctx.data to the TestCafe JSON reporter (or any reporter)?
My code:
// Called within Express.js by a request coming from req
const testMySite = (req, res) => {
process.env.PARAMS = JSON.stringify(req.body)
let testcafe = null;
console.log(`Running test on ports 1341 and 1342`)
createTestCafe('localhost', 1341, 1342, void 0, true)
.then(tc => {
testcafe = tc;
const runner = testcafe.createRunner()
return runner
.src(`${path.dirname(__filename)}/tests/gisTest.js`)
.browsers('firefox:headless')
.reporter('json', 'report.json')
.run()
})
.then(failedCount => {
testcafe.close()
})
res.json({message: `Success! Scraper has begun to process ${req.body}`});
}
My test code:
import { ClientFunction, Selector } from 'testcafe';
const doc = process.env.PARAMS
const newDoc = JSON.parse(process.env.PARAMS)
console.log(`newDoc (from test)`, newDoc)
// const _id = newDoc._id
let data = newDoc.mydata
fixture `My Fixture`
.page('https://www.mysite.co')
.afterEach(async t => {
await t
// how do I get t.ctx.myData into the reporter??
console.log(`t.ctx.myData: `, t.ctx.myData)
})
test(`My Test`, async t => {
const photoIcon = Selector('div#sbtc div.LM8x9c > span')
const photoFieldForPaste = Selector('input#Ycyxxc')
const searchByImageButton = Selector('td#aoghAf > input')
const targetElement = Selector('div#jHnbRc span:nth-child(2) > a')
await t
.wait(1000)
.click(photoIcon)
.typeText(photoFieldForPaste, data, {paste: true})
.click(searchByImageButton)
if(await targetElement.exists && await targetElement.visible) {
await t.ctx.finalData = targetElement.innerText;
}
await t.ctx.finalData = null;
})
Please see the part // how do I get t.ctx.myData into the reporter??.
I am assuming this is the only place where I could potentially get the data from the test into the reporter but I'm not sure exactly how.
If you know how to get the t.ctx.myData variable as shown in the above code to be written to the JSON reporter, I would highly appreciate it.
Even better would be to have a way to send the t.ctx.myData value into the response.
At present, you can add only static metadata to tests and fixtures. This metadata is available in reports. Please refer to the following article to get details: https://devexpress.github.io/testcafe/documentation/guides/basic-guides/organize-tests.html#specify-test-metadata
As for sending dynamic data to the reporter, we keep this feature in mind, however we cannot give any estimates on this. Please track the following issue: https://github.com/DevExpress/testcafe/issues/3584

How to send a message when a trello card is moved to a certain list

I’m currently making a bot that informs me when a card is moved to the list titled Passed Applications.
I have already made the code and it basically sends a message once a card is moved to the specific list, however, it will randomly send a message and pull a card minutes/hours after it has already been pulled and sent the message.
What I’ve done so far is:
trello.js
var Trello = require("node-trello"),
EventEmitter = require("events").EventEmitter,
extend = require("extend"),
config,
trello,
timer,
e;
module.exports = function(options) {
var defaults = {
pollFrequency: 1000 * 60,
minId: 0,
trello: {
key: "",
token: "",
boards: []
},
start: true
};
e = new EventEmitter();
config = extend(true, defaults, options);
trello = new Trello(
process.env.TRELLO_API_KEY,
process.env.TRELLO_OAUTH_TOKEN
);
if (config.start) {
process.nextTick(function() {
start(config.pollFrequency, true);
});
}
function start(frequency, immediate) {
if (timer) {
return;
}
frequency = frequency || config.pollFrequency;
timer = setInterval(poll, frequency);
if (immediate) {
poll();
}
}
function poll() {
config.trello.boards.forEach(function(boardId) {
getBoardActivity(boardId);
});
}
function getBoardActivity(boardId) {
trello.get("/1/boards/" + boardId + "/actions", function(err, resp) {
if (err) {
return e.emit("trelloError", err);
}
var boardActions = resp.reverse();
var actionId;
for (var ix in boardActions) {
actionId = parseInt(boardActions[ix].id, 16);
if (actionId <= config.minId) {
continue;
}
var eventType = boardActions[ix].type;
e.emit(eventType, boardActions[ix], boardId);
}
config.minId = Math.max(config.minId, actionId);
e.emit("maxId", config.minId);
});
}
index.js
const conf = JSON.parse(fs.readFileSync("trelloconfig.json"));
let latestActivityID = fs.existsSync("./latestActivityID") ?
fs.readFileSync("./latestActivityID") :
0;
const eventEnabled = type =>
conf.enabledEvents.length > 0 ? conf.enabledEvents.includes(type) : true;
const TrelloEvents = require("./trello.js");
const events = new TrelloEvents({
pollFrequency: 60000,
minId: latestActivityID,
start: false,
trello: {
boards: conf.boardIDs,
key: process.env.TRELLO_API_KEY,
token: process.env.TRELLO_OAUTH_TOKEN
}
});
client.on("ready", () => {
events.start();
console.log(`[STATUS CHANGE] ${client.user.username} is now online.`);
client.user.setActivity("Cookout Grill");
});
events.on("updateCard", (event, board) => {
if (event.data.old.hasOwnProperty("idList")) {
if (!eventEnabled(`cardListChanged`)) return;
if (event.data.listAfter.name === "Passed Applications") {
let robloxId = event.data.card.name.split(" | ")[0];
client.channels.get("730839109236424756").send(robloxId);
if (database.find(x => x.RobloxUser === robloxId)) {
let data = database.find(x => x.RobloxUser === robloxId);
const person = client.users.get(data.DiscordID);
let embed = new discord.RichEmbed()
.setThumbnail(
"https://www.roblox.com/bust-thumbnail/image?userId=" +
data.RobloxID +
"&width=420&height=420&format=png"
)
.setTitle("APPLICATION RESULTS | Passed")
.setColor("3ef72d")
.setFooter("Cookout Grill", client.user.avatarURL)
.setDescription(
"Greetings, **" +
data.RobloxUser +
"**!\n\nAfter extensive review by our Management Team, we have decided to accept your Trainee Application at Cookout Grill. We believe that your application showed that you’re ready to become a staff member at our establishment.\n\nWe would like to congratulate you on passing your Trainee Application. Your application met our critical expectations and requirements in order to pass.\n\nIn order to work your way up throughout the staff ranks, you must attend a training at [Cookout Grill’s Training Center](https://www.roblox.com/groups/5634772/Cookout-Grill#!/about) during the specific session times. If you’re unable to attend one of our designated sessions, feel free to schedule a private session with a member of our Management Team.\n\nWe wish you the best of luck in continuing throughout the staff ranks at Cookout Grill. If you have any further questions, please do not hesitate to create a ticket in our main Discord Server."
)
.addField("**NEW RANK**", "`Trainee`");
person.send(embed);
roblox.message(
event.data.card.name.split(" | ")[1],
"APPLICATION RESULTS | Passed",
"Greetings, **" +
data.RobloxUser +
"**!\n\nAfter extensive review by our Management Team, we have decided to accept your Trainee Application at Cookout Grill.\n\nWe would like to congratulate you on passing your Trainee Application. Your application met our critical expectations and requirements in order to pass.\n\nIn order to work your way up throughout the staff ranks, you must attend a training at Cookout Grill’s Training Center during the specific session times. If you’re unable to attend one of our designated sessions, feel free to schedule a private session with a member of our Management Team.\n\nWe wish you the best of luck in continuing throughout the staff ranks at Cookout Grill."
);
}
let embed2 = new discord.RichEmbed()
.setTitle(`Card list changed!`)
.setDescription(
`**CARD:** ${
event.data.card.name
} — **[CARD LINK](https://trello.com/c/${
event.data.card.shortLink
})**\n\n**EVENT:** Card moved to list __${
event.data.listAfter.name
}__ from list __${event.data.listBefore.name}__ by **[${
conf.realNames
? event.memberCreator.fullName
: event.memberCreator.username
}](https://trello.com/${event.memberCreator.username})**`
);
client.channels.get("730839109236424756").send(embed2);
Trello.addCommentToCard(
event.data.card.id,
"User has been ranked.",
function(error, trelloCard) {
console.log(error);
}
);
} else return;
} else return;
});