-
Notifications
You must be signed in to change notification settings - Fork 11
/
Copy pathprepareAirdrop.ts
160 lines (124 loc) · 5.11 KB
/
prepareAirdrop.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
import * as web3 from '@solana/web3.js';
import * as anchor from "@project-serum/anchor";
import { assert } from 'console';
import * as splToken from "@solana/spl-token";
import { token } from '@project-serum/anchor/dist/cjs/utils';
const fs = require('fs');
const VERIFIED_CREATOR = "AHx6cQKhJQ6vV9zhb37B7gKtRRGDuLtTfNWgvMiLDJp7";
const TOKEN_TO_SEND = "toKPe7ENJiRBANPLnnp4dHs7ccFyHRg2oSEPdDfumg8";
const AMOUNT_TO_SEND = 42000000000; // including decimans
export const PROGRESS_FILE_PATH = "./progress.json";
export class TokenInfo {
metadataAccount: string;
nftTokenMint: string;
nftName: string | undefined;
owner: string | undefined;
sendableTokenMint: string | undefined;
sendableAmount: number | undefined;
txid: string | undefined;
constructor(metadataAccount: string, tokenMint: string) {
this.metadataAccount = metadataAccount;
this.nftTokenMint = tokenMint;
}
show(){
console.log(this.metadataAccount + " -> " + this.nftTokenMint +' -> '+ this.owner);
}
}
export function writeJson(data: TokenInfo[]){
let json = JSON.stringify(data);
fs.writeFileSync(PROGRESS_FILE_PATH, json);
}
export function readJson(): TokenInfo[] {
return JSON.parse(fs.readFileSync(PROGRESS_FILE_PATH).toString());
}
async function getOwnerForNFT(c: web3.Connection, tokenMintString: string) : Promise<web3.PublicKey>{
const tokenMint = new anchor.web3.PublicKey(tokenMintString);
//const accountInfo = await c.getAccountInfo(tokenMint);
const largestAccouts = await c.getTokenLargestAccounts(tokenMint);
const onlyHolder : web3.TokenAccountBalancePair[] = largestAccouts!.value.filter((tokenHolder: web3.TokenAccountBalancePair) => tokenHolder.uiAmount);
assert(onlyHolder.length == 1);
const NFTTokenAccount = onlyHolder[0].address;
//console.log(NFTTokenAccount.toBase58());
const tokenAccountInfo = await c.getAccountInfo(NFTTokenAccount);
const owner = new web3.PublicKey(tokenAccountInfo!.data.slice(32, 64));
//console.log(owner.toBase58());
return owner;
}
async function getAllNFTsForCreator(c: web3.Connection, verifiedCreator: string) : Promise<TokenInfo[]>{
const config : web3.GetProgramAccountsConfig = {
commitment: undefined,
encoding: "base64",
dataSlice: undefined,
filters: [
{
"memcmp": {
"offset": 1 + // key
32 + // update auth
32 + // mint
4 + // name string length
32 + //MAX_NAME_LENGTH + // name
4 + // uri string length
200 + // MAX_URI_LENGTH + // uri*
4 + // symbol string length
10 + // MAX_SYMBOL_LENGTH + // symbol
2 + // seller fee basis points
1 + // whether or not there is a creators vec
4, // creators
"bytes": verifiedCreator
}
}
]
}
const TOKEN_METADATA_PROGRAM_ID = new web3.PublicKey("metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s");
const accountList = await c.getProgramAccounts(TOKEN_METADATA_PROGRAM_ID, config);
//console.log(accountList);
const allInfo : TokenInfo[] = [];
for (let i =0; i<accountList.length; i++){
const metadataAccountPK = accountList[i].pubkey.toBase58()
const tokenMint = new web3.PublicKey(accountList[i].account.data.slice(1+32, 1+32+32)).toBase58();
allInfo[i] = new TokenInfo(metadataAccountPK, tokenMint);
//allInfo[i].show();
const nameLenght = accountList[i].account.data.readUInt32LE(1+32+32);
const nameBuffer = accountList[i].account.data.slice(1+32+32+4, 1+32+32+4+32);
//console.log(nameLenght);
let name = "";
for (let j = 0; j< nameLenght; j++){
if (nameBuffer.readUInt8(j)==0) break;
name += String.fromCharCode(nameBuffer.readUInt8(j));
}
allInfo[i].nftName = name;
//console.log(name);
}
return allInfo;
}
async function prepareSend(data: TokenInfo[]){
data.forEach(element => {
element.sendableAmount = AMOUNT_TO_SEND;
element.sendableTokenMint = TOKEN_TO_SEND;
});
}
async function main(){
const rpcHost = "https://ssc-dao.genesysgo.net/"
const c = new anchor.web3.Connection(rpcHost);
//const owner = await getOwnerForNFT(c, "AP7VntKBj4253RV6ktMrZJst5JFFmrQnHy29HC7rHvd");
//console.log(owner.toBase58());
if(!fs.existsSync(PROGRESS_FILE_PATH)){
const allInfo = await getAllNFTsForCreator(c, VERIFIED_CREATOR);
writeJson(allInfo);
console.log("file saved");
}
const allInfo = readJson();
console.log("finding owners...")
allInfo.forEach(async tokenInfo => {
if (!tokenInfo.owner) {
tokenInfo.owner = await (await getOwnerForNFT(c, tokenInfo.nftTokenMint)).toBase58();
writeJson(allInfo);
}
});
prepareSend(allInfo);
writeJson(allInfo);
console.log("DONE");
}
if (require.main === module) {
main();
}