Revert "Cleaning up"
This reverts commit 0db69bf72b0b090edc22d0e682f8f3bb4356dc3e.
This commit is contained in:
parent
2b12c99813
commit
a578978c95
179
Airdrop.fsx
Normal file
179
Airdrop.fsx
Normal file
@ -0,0 +1,179 @@
|
||||
#load "/home/joe/Development/DegenzGame/.paket/load/net6.0/main.group.fsx";;
|
||||
|
||||
open System
|
||||
open System.IO
|
||||
open Npgsql.FSharp
|
||||
open dotenv.net
|
||||
open Solnet.Rpc
|
||||
open Solnet.Rpc.Models
|
||||
open Solnet.Rpc.Builders
|
||||
open Solnet.Wallet
|
||||
open Solnet.Programs
|
||||
open Solnet.KeyStore
|
||||
|
||||
let devEnv = DotEnv.Read(DotEnvOptions(envFilePaths = [ "./.dev.env" ]))
|
||||
|
||||
let ( _ , devConnStr )= devEnv.TryGetValue("DATABASE_URL")
|
||||
|
||||
let keystore = SolanaKeyStoreService()
|
||||
let file = File.ReadAllText("/home/joe/.config/solana/devnet.json")
|
||||
let authority = keystore.RestoreKeystore(file)
|
||||
|
||||
//let rpcClient = ClientFactory.GetClient("https://still-empty-field.solana-mainnet.quiknode.pro/5b1b6b5c913ec79a20bef19d5ba5f63023e470d6/")
|
||||
let rpcClient = ClientFactory.GetClient(Cluster.DevNet)
|
||||
|
||||
let mintAccount = PublicKey("2iS6gcoB5VhiLC4eNB7NdcaLgEHjLrXHYpz7T2JMGBDw")
|
||||
//let associatedTokenAccountOwner = PublicKey("GutKESfJw8PDMbFVqByxTr4f5TUSHUVmkf5gtsWWWqrU")
|
||||
|
||||
type AirdropStatus =
|
||||
| Hold = 0
|
||||
| Ready = 1
|
||||
| Pending = 2
|
||||
| Error = 3
|
||||
| PendingError = 4
|
||||
| Completed = 5
|
||||
| Verified = 6
|
||||
|
||||
let updateError wallet msg =
|
||||
devConnStr
|
||||
|> Sql.connect
|
||||
|> Sql.parameters [ "wallet" , Sql.string wallet ; "msg" , Sql.string msg ]
|
||||
|> Sql.query """
|
||||
UPDATE crypto SET error_msg = @msg, status = 'Error' WHERE crypto.wallet_address = @wallet;
|
||||
"""
|
||||
|> Sql.executeNonQueryAsync
|
||||
|
||||
let updatePendingError wallet msg txId =
|
||||
devConnStr
|
||||
|> Sql.connect
|
||||
|> Sql.parameters [ "wallet" , Sql.string wallet ; "msg" , Sql.string msg ; "txId" , Sql.string txId ]
|
||||
|> Sql.query """
|
||||
UPDATE crypto SET error_msg = @msg, pending_tx = @txId, status = 'PendingError' WHERE crypto.wallet_address = @wallet;
|
||||
"""
|
||||
|> Sql.executeNonQueryAsync
|
||||
|
||||
let updatePending wallet txId =
|
||||
devConnStr
|
||||
|> Sql.connect
|
||||
|> Sql.parameters [ "wallet" , Sql.string wallet ; "txId" , Sql.string txId ]
|
||||
|> Sql.query """
|
||||
UPDATE crypto SET pending_tx = @txId, status = 'Pending' WHERE crypto.wallet_address = @wallet;
|
||||
"""
|
||||
|> Sql.executeNonQueryAsync
|
||||
|
||||
let updateCompleted wallet txId =
|
||||
devConnStr
|
||||
|> Sql.connect
|
||||
|> Sql.parameters [ "wallet" , Sql.string wallet ; "txId" , Sql.string txId ]
|
||||
|> Sql.query """
|
||||
UPDATE crypto SET successful_tx = pending_tx, status = 'Completed' WHERE crypto.wallet_address = @wallet;
|
||||
"""
|
||||
|> Sql.executeNonQueryAsync
|
||||
|
||||
let updateVerified wallet txId amount =
|
||||
devConnStr
|
||||
|> Sql.connect
|
||||
|> Sql.parameters [ "wallet" , Sql.string wallet ; "txId" , Sql.string txId ; "amount" , Sql.int amount ]
|
||||
|> Sql.query """
|
||||
UPDATE crypto SET pending_tx = @txId, status = 'Verified', total_dropped = @amount WHERE crypto.wallet_address = @wallet;
|
||||
"""
|
||||
|> Sql.executeNonQueryAsync
|
||||
|
||||
let getTokenCountToDrop wallet =
|
||||
task {
|
||||
let! wl =
|
||||
devConnStr
|
||||
|> Sql.connect
|
||||
|> Sql.parameters [ "wallet" , Sql.string wallet ]
|
||||
|> Sql.query """
|
||||
SELECT has_wl, has_og FROM crypto WHERE wallet_address = @wallet;
|
||||
"""
|
||||
|> Sql.executeRowAsync (fun reader -> {| HasWhitelist = reader.bool "has_wl" ; HasOg = reader.bool "has_og" |})
|
||||
return (if wl.HasWhitelist then 1uL else 0uL) + (if wl.HasOg then 2uL else 0uL)
|
||||
}
|
||||
|
||||
// TODO: Change was_successful to status and check if attempted, pending, errored, or completed
|
||||
let executeDrop (wallet : string) =
|
||||
let associatedTokenAccountOwner = PublicKey(wallet)
|
||||
let associatedTokenAccount = AssociatedTokenAccountProgram.DeriveAssociatedTokenAccount(associatedTokenAccountOwner, mintAccount)
|
||||
let log msg = printfn $"{wallet} || {msg}"
|
||||
|
||||
log $"ATA: {associatedTokenAccount.Key}"
|
||||
let buildTransaction (block : LatestBlockHash) amount (targetWallet : string) =
|
||||
TransactionBuilder()
|
||||
.SetRecentBlockHash(block.Blockhash)
|
||||
.SetFeePayer(authority.Account)
|
||||
.AddInstruction(AssociatedTokenAccountProgram.CreateAssociatedTokenAccount(
|
||||
authority.Account,
|
||||
PublicKey(targetWallet),
|
||||
mintAccount))
|
||||
.AddInstruction(TokenProgram.Transfer(
|
||||
PublicKey("CRa7GCMUaB4np32XoTD2sEyCXFVfYKKF4JRPkQTwV3EY"),
|
||||
associatedTokenAccount,
|
||||
amount,
|
||||
authority.Account))
|
||||
.Build(authority.Account);
|
||||
task {
|
||||
// let streamingClient = ClientFactory.GetStreamingClient("wss://still-empty-field.solana-mainnet.quiknode.pro/5b1b6b5c913ec79a20bef19d5ba5f63023e470d6/")
|
||||
let streamingClient = ClientFactory.GetStreamingClient(Cluster.DevNet)
|
||||
do! streamingClient.ConnectAsync()
|
||||
let blockHash = rpcClient.GetLatestBlockHash()
|
||||
let! amount = getTokenCountToDrop wallet
|
||||
log $"Dropping {amount} tokens"
|
||||
let tx = buildTransaction blockHash.Result.Value amount wallet
|
||||
let! tx = rpcClient.SendTransactionAsync(tx)
|
||||
if tx.ErrorData <> null then
|
||||
let! _ = updateError wallet (tx.ErrorData.Logs |> String.concat "\n")
|
||||
()
|
||||
log $"Transaction error: {wallet}"
|
||||
return ()
|
||||
elif String.IsNullOrWhiteSpace(tx.Result) then
|
||||
let msg = $"Transaction did not have an ID but the ErrorData was null: {tx.Reason}"
|
||||
let! _ = updateError wallet msg
|
||||
log $"Odd Transaction Error"
|
||||
return ()
|
||||
else
|
||||
log $"Successful, now waiting for RPC"
|
||||
let! _ = updatePending wallet tx.Result
|
||||
let! _ = streamingClient.SubscribeSignatureAsync(tx.Result, fun _ result ->
|
||||
if result.Value.Error = null then
|
||||
log "RPC Finished"
|
||||
task {
|
||||
let! _ = updateCompleted wallet tx.Result
|
||||
log "Getting Transaction and Token Balance"
|
||||
let! txInfo = rpcClient.GetTransactionAsync(tx.Result)
|
||||
let! tokenBalance = rpcClient.GetTokenAccountBalanceAsync(associatedTokenAccount)
|
||||
|
||||
|
||||
log $"Transaction Successful? {txInfo.WasSuccessful} - Token Balance {tokenBalance.Result.Value.AmountUlong}"
|
||||
if txInfo.WasSuccessful = true && tokenBalance.Result.Value.AmountUlong = amount then
|
||||
let! _ = updateVerified wallet tx.Result (int amount)
|
||||
()
|
||||
return ()
|
||||
} |> Async.AwaitTask |> Async.Start
|
||||
else
|
||||
let msg = $"Got an error, let's check it out {result.Value.Error}"
|
||||
updatePendingError wallet msg tx.Result |> Async.AwaitTask |> Async.Ignore |> Async.Start)
|
||||
return ()
|
||||
}
|
||||
|
||||
let targetWallets =
|
||||
devConnStr
|
||||
|> Sql.connect
|
||||
|> Sql.query """
|
||||
SELECT wallet_address FROM crypto WHERE status = 'Ready';
|
||||
"""
|
||||
|> Sql.execute (fun reader -> reader.string "wallet_address")
|
||||
|
||||
printfn $"Got target wallets: {targetWallets.Length}"
|
||||
|
||||
// "GK7rkZYrdAEpTm9n9TkHWK1T5nDXeRfVUVfcHQwSDyuJ"
|
||||
let asyncs =
|
||||
targetWallets
|
||||
|> List.map executeDrop
|
||||
|> List.map Async.AwaitTask
|
||||
|
||||
Async.Parallel ( asyncs , 16 ) |> Async.StartChild
|
||||
|
||||
|
||||
Console.ReadLine() |> ignore
|
188
Bot/Scripts/Airdrop.fsx
Normal file
188
Bot/Scripts/Airdrop.fsx
Normal file
@ -0,0 +1,188 @@
|
||||
#load "/home/joe/Development/DegenzGame/.paket/load/net6.0/main.group.fsx";;
|
||||
|
||||
open System
|
||||
open System.IO
|
||||
open Npgsql.FSharp
|
||||
open dotenv.net
|
||||
open Solnet.Rpc
|
||||
open Solnet.Rpc.Models
|
||||
open Solnet.Rpc.Builders
|
||||
open Solnet.Wallet
|
||||
open Solnet.Programs
|
||||
open Solnet.KeyStore
|
||||
|
||||
let devEnv = DotEnv.Read(DotEnvOptions(envFilePaths = [ "./.dev.env" ]))
|
||||
|
||||
let ( _ , devConnStr )= devEnv.TryGetValue("DATABASE_URL")
|
||||
let ( _ , rpcClientUrl )= devEnv.TryGetValue("RPC_CLIENT")
|
||||
let ( _ , wssClientUrl )= devEnv.TryGetValue("WSS_CLIENT")
|
||||
|
||||
let keystore = SolanaKeyStoreService()
|
||||
//let file = File.ReadAllText("/home/joe/.config/solana/devnet.json")
|
||||
let file = File.ReadAllText("/home/joe/.config/solana/DegenzW7kWzac5zEdTWEuqVasoVMPKd16T3za2j6S3qR.json")
|
||||
let authority = keystore.RestoreKeystore(file)
|
||||
|
||||
//let rpcClient = ClientFactory.GetClient(Cluster.DevNet)
|
||||
let rpcClient = ClientFactory.GetClient(rpcClientUrl)
|
||||
|
||||
//let mintAccount = PublicKey("2iS6gcoB5VhiLC4eNB7NdcaLgEHjLrXHYpz7T2JMGBDw")
|
||||
let mintAccount = PublicKey("4gN1u9LNBnvFERpDU3SrMusMJ1gKLbE9XB6EYraQkWTf")
|
||||
//let ataAccount = PublicKey("CRa7GCMUaB4np32XoTD2sEyCXFVfYKKF4JRPkQTwV3EY")
|
||||
let sourceAtaAccount = PublicKey("7CB459UJC3qtTYJzfC8bFNvdycQGXTPzKoEHxys8Ytfs")
|
||||
//let associatedTokenAccountOwner = PublicKey("GutKESfJw8PDMbFVqByxTr4f5TUSHUVmkf5gtsWWWqrU")
|
||||
|
||||
type AirdropStatus =
|
||||
| Hold = 0
|
||||
| Ready = 1
|
||||
| Pending = 2
|
||||
| Error = 3
|
||||
| PendingError = 4
|
||||
| Completed = 5
|
||||
| Verified = 6
|
||||
|
||||
let updateError wallet msg =
|
||||
devConnStr
|
||||
|> Sql.connect
|
||||
|> Sql.parameters [ "wallet" , Sql.string wallet ; "msg" , Sql.string msg ]
|
||||
|> Sql.query """
|
||||
UPDATE crypto SET error_msg = @msg, status = 'Error' WHERE crypto.wallet_address = @wallet;
|
||||
"""
|
||||
|> Sql.executeNonQueryAsync
|
||||
|
||||
let updatePendingError wallet msg txId =
|
||||
devConnStr
|
||||
|> Sql.connect
|
||||
|> Sql.parameters [ "wallet" , Sql.string wallet ; "msg" , Sql.string msg ; "txId" , Sql.string txId ]
|
||||
|> Sql.query """
|
||||
UPDATE crypto SET error_msg = @msg, pending_tx = @txId, status = 'PendingError' WHERE crypto.wallet_address = @wallet;
|
||||
"""
|
||||
|> Sql.executeNonQueryAsync
|
||||
|
||||
let updatePending wallet txId =
|
||||
devConnStr
|
||||
|> Sql.connect
|
||||
|> Sql.parameters [ "wallet" , Sql.string wallet ; "txId" , Sql.string txId ]
|
||||
|> Sql.query """
|
||||
UPDATE crypto SET pending_tx = @txId, status = 'Pending' WHERE crypto.wallet_address = @wallet;
|
||||
"""
|
||||
|> Sql.executeNonQueryAsync
|
||||
|
||||
let updateCompleted wallet txId =
|
||||
devConnStr
|
||||
|> Sql.connect
|
||||
|> Sql.parameters [ "wallet" , Sql.string wallet ; "txId" , Sql.string txId ]
|
||||
|> Sql.query """
|
||||
UPDATE crypto SET successful_tx = pending_tx, status = 'Completed' WHERE crypto.wallet_address = @wallet;
|
||||
"""
|
||||
|> Sql.executeNonQueryAsync
|
||||
|
||||
let updateVerified wallet txId amount =
|
||||
devConnStr
|
||||
|> Sql.connect
|
||||
|> Sql.parameters [ "wallet" , Sql.string wallet ; "txId" , Sql.string txId ; "amount" , Sql.int amount ]
|
||||
|> Sql.query """
|
||||
UPDATE crypto SET pending_tx = @txId, status = 'Verified', total_dropped = @amount WHERE crypto.wallet_address = @wallet;
|
||||
"""
|
||||
|> Sql.executeNonQueryAsync
|
||||
|
||||
|
||||
let getTokenCountToDrop wallet =
|
||||
task {
|
||||
let! wl =
|
||||
devConnStr
|
||||
|> Sql.connect
|
||||
|> Sql.parameters [ "wallet" , Sql.string wallet ]
|
||||
|> Sql.query """
|
||||
SELECT has_wl, has_og FROM crypto WHERE wallet_address = @wallet;
|
||||
"""
|
||||
|> Sql.executeRowAsync (fun reader -> {| HasWhitelist = reader.bool "has_wl" ; HasOg = reader.bool "has_og" |})
|
||||
return (if wl.HasWhitelist then 1uL else 0uL) + (if wl.HasOg then 2uL else 0uL)
|
||||
}
|
||||
|
||||
let executeDrop (wallet : string) =
|
||||
let associatedTokenAccountOwner = PublicKey(wallet)
|
||||
let associatedTokenAccount = AssociatedTokenAccountProgram.DeriveAssociatedTokenAccount(associatedTokenAccountOwner, mintAccount)
|
||||
let log msg = printfn $"{wallet} || {msg}"
|
||||
|
||||
log $"ATA: {associatedTokenAccount.Key}"
|
||||
let buildTransaction (block : LatestBlockHash) amount (targetWallet : string) =
|
||||
TransactionBuilder()
|
||||
.SetRecentBlockHash(block.Blockhash)
|
||||
.SetFeePayer(authority.Account)
|
||||
.AddInstruction(AssociatedTokenAccountProgram.CreateAssociatedTokenAccount(
|
||||
authority.Account,
|
||||
PublicKey(targetWallet),
|
||||
mintAccount))
|
||||
.AddInstruction(TokenProgram.Transfer(
|
||||
sourceAtaAccount,
|
||||
associatedTokenAccount,
|
||||
amount,
|
||||
authority.Account))
|
||||
.Build(authority.Account);
|
||||
async {
|
||||
// let streamingClient = ClientFactory.GetStreamingClient(Cluster.DevNet)
|
||||
let streamingClient = ClientFactory.GetStreamingClient(wssClientUrl)
|
||||
do! streamingClient.ConnectAsync() |> Async.AwaitTask
|
||||
let blockHash = rpcClient.GetLatestBlockHash()
|
||||
let! amount = getTokenCountToDrop wallet |> Async.AwaitTask
|
||||
log $"Dropping {amount} tokens"
|
||||
let tx = buildTransaction blockHash.Result.Value amount wallet
|
||||
let! tx = rpcClient.SendTransactionAsync(tx) |> Async.AwaitTask
|
||||
if tx.ErrorData <> null then
|
||||
let! _ = updateError wallet (tx.ErrorData.Logs |> String.concat "\n") |> Async.AwaitTask
|
||||
()
|
||||
log $"Transaction error: {wallet}"
|
||||
return ()
|
||||
elif String.IsNullOrWhiteSpace(tx.Result) then
|
||||
let msg = $"Transaction did not have an ID but the ErrorData was null: {tx.Reason}"
|
||||
let! _ = updateError wallet msg |> Async.AwaitTask
|
||||
log $"Odd Transaction Error"
|
||||
return ()
|
||||
else
|
||||
log $"Successful, now waiting for RPC"
|
||||
let! _ = updatePending wallet tx.Result |> Async.AwaitTask
|
||||
let! _ = streamingClient.SubscribeSignatureAsync(tx.Result, fun sub result ->
|
||||
if result.Value.Error = null then
|
||||
log "RPC Finished"
|
||||
task {
|
||||
let! _ = updateCompleted wallet tx.Result
|
||||
log "Getting Transaction and Token Balance"
|
||||
let! txInfo = rpcClient.GetTransactionAsync(tx.Result)
|
||||
let! tokenBalance = rpcClient.GetTokenAccountBalanceAsync(associatedTokenAccount)
|
||||
|
||||
log $"Transaction Successful? {txInfo.WasSuccessful} - Token Balance {tokenBalance.Result.Value.AmountUlong}"
|
||||
if txInfo.WasSuccessful = true && tokenBalance.Result.Value.AmountUlong = amount then
|
||||
let! _ = updateVerified wallet tx.Result (int amount)
|
||||
()
|
||||
return ()
|
||||
} |> Async.AwaitTask |> Async.Start
|
||||
else
|
||||
let msg = $"Got an error, check the tx id"
|
||||
updatePendingError wallet msg tx.Result |> Async.AwaitTask |> Async.Ignore |> Async.Start) |> Async.AwaitTask
|
||||
return ()
|
||||
}
|
||||
|
||||
let targetWallets =
|
||||
devConnStr
|
||||
|> Sql.connect
|
||||
|> Sql.query """
|
||||
SELECT wallet_address FROM crypto WHERE status = 'Ready' AND total_dropped = 0;
|
||||
"""
|
||||
|> Sql.execute (fun reader -> reader.string "wallet_address")
|
||||
|
||||
printfn $"Got target wallets: {targetWallets.Length}"
|
||||
|
||||
let asyncs =
|
||||
targetWallets
|
||||
|> List.map executeDrop
|
||||
|> List.chunkBySize 5
|
||||
|
||||
async {
|
||||
for a in asyncs do
|
||||
let! _ = Async.Parallel a
|
||||
do! Async.Sleep 500
|
||||
} |> Async.Start
|
||||
|
||||
|
||||
Console.ReadLine() |> ignore
|
||||
|
148
Bot/Scripts/GetWhitelisted.fsx
Normal file
148
Bot/Scripts/GetWhitelisted.fsx
Normal file
@ -0,0 +1,148 @@
|
||||
#load "/home/joe/Development/DegenzGame/.paket/load/net6.0/main.group.fsx";;
|
||||
|
||||
open Npgsql.FSharp
|
||||
open DSharpPlus
|
||||
open DSharpPlus.Entities
|
||||
open Solnet.Programs
|
||||
open dotenv.net
|
||||
|
||||
let prodEnv = DotEnv.Read(DotEnvOptions(envFilePaths = [ "./.prod.env" ]))
|
||||
let devEnv = DotEnv.Read(DotEnvOptions(envFilePaths = [ "./.dev.env" ]))
|
||||
|
||||
let ( _ , prodConnStr )= prodEnv.TryGetValue("DATABASE_URL")
|
||||
let ( _ , devConnStr )= devEnv.TryGetValue("DATABASE_URL")
|
||||
let ( _ , adminBotToken )= prodEnv.TryGetValue("TOKEN_ADMINBOT")
|
||||
|
||||
let botConfig = DiscordConfiguration()
|
||||
botConfig.TokenType <- TokenType.Bot
|
||||
botConfig.Intents <- DiscordIntents.All
|
||||
botConfig.Token <- adminBotToken
|
||||
|
||||
printfn "Connecting"
|
||||
let bot = new DiscordClient(botConfig)
|
||||
bot.ConnectAsync() |> Async.AwaitTask |> Async.RunSynchronously
|
||||
|
||||
printfn "Getting Guild"
|
||||
let prodGuild = 933888229776703559uL
|
||||
let guild = bot.GetGuildAsync(prodGuild) |> Async.AwaitTask |> Async.RunSynchronously
|
||||
printfn "Getting Members"
|
||||
let users = guild.GetAllMembersAsync() |> Async.AwaitTask |> Async.RunSynchronously
|
||||
printfn $"Total Members: {users.Count}"
|
||||
|
||||
let firstDrop =
|
||||
users
|
||||
|> Seq.filter (fun u -> u.Roles |> Seq.exists (fun role ->
|
||||
role.Id = 978229149569286174uL))
|
||||
|> Seq.distinct
|
||||
|> Seq.toList
|
||||
|
||||
printfn $"{firstDrop.Length}"
|
||||
|
||||
let changeStatus ids =
|
||||
devConnStr
|
||||
|> Sql.connect
|
||||
|> Sql.parameters [ "ids" , Sql.stringArray ids ]
|
||||
|> Sql.query """
|
||||
UPDATE crypto SET status = 'Ready' WHERE discord_id = ANY (ARRAY[@ids]::varchar[]) AND status = 'Nothing'
|
||||
"""
|
||||
|> Sql.executeNonQuery
|
||||
|
||||
changeStatus (firstDrop |> List.map (fun m -> string m.Id) |> List.toArray)
|
||||
|
||||
let whitelisted =
|
||||
users
|
||||
|> Seq.filter (fun u -> u.Roles |> Seq.exists (fun role -> role.Name.Contains("Confirmed")))
|
||||
|> Seq.toList
|
||||
|
||||
printfn $"Total Whitelist Confirmed: {whitelisted.Length}"
|
||||
|
||||
printfn "Getting Wallet Addresses:"
|
||||
let walletAddresses =
|
||||
prodConnStr
|
||||
|> Sql.connect
|
||||
|> Sql.query """
|
||||
SELECT DISTINCT discord_id, display_name, wallet_address FROM "user" WHERE wallet_address IS NOT NULL;
|
||||
"""
|
||||
|> Sql.execute (fun reader -> {| Id = reader.string "discord_id" |> uint64 ; Name = reader.string "display_name" ; Wallet = reader.string "wallet_address" |})
|
||||
|
||||
printfn $"Total Wallet Addresses: {walletAddresses.Length}"
|
||||
|
||||
let insert did name wallet wl og =
|
||||
devConnStr
|
||||
|> Sql.connect
|
||||
|> Sql.parameters [ "did" , Sql.string (string did) ; "name" , Sql.string name ; "wallet" , Sql.string wallet
|
||||
"wl" , Sql.bool wl ; "og" , Sql.bool og ]
|
||||
|> Sql.query """
|
||||
INSERT INTO crypto(discord_id, display_name, wallet_address, has_wl, has_og) VALUES (@did, @name, @wallet, @wl, @og)
|
||||
ON CONFLICT (discord_id) DO
|
||||
UPDATE SET wallet_address = @wallet, has_wl = @wl , has_og = @og WHERE crypto.discord_id = @did AND crypto.status = 'Nothing';
|
||||
"""
|
||||
|> Sql.executeNonQuery
|
||||
|
||||
let updateUserWithWallet wallet wl og =
|
||||
devConnStr
|
||||
|> Sql.connect
|
||||
|> Sql.parameters [ "wallet" , Sql.string wallet ; "wl" , Sql.bool wl ; "og" , Sql.bool og ]
|
||||
|> Sql.query """
|
||||
UPDATE crypto SET has_wl = @wl, has_og = @og WHERE crypto.wallet_address = @wallet AND crypto.status = 'Nothing';
|
||||
"""
|
||||
|> Sql.executeNonQuery
|
||||
|
||||
let prune ids =
|
||||
devConnStr
|
||||
|> Sql.connect
|
||||
|> Sql.parameters [ "ids" , Sql.stringArray ids ]
|
||||
|> Sql.query """
|
||||
DELETE FROM crypto WHERE discord_id = ANY (ARRAY[@ids]::varchar[]) AND status = 'Nothing'
|
||||
"""
|
||||
|> Sql.executeNonQuery
|
||||
|
||||
let getExisting () =
|
||||
devConnStr
|
||||
|> Sql.connect
|
||||
|> Sql.query """
|
||||
SELECT discord_id, display_name, wallet_address FROM crypto
|
||||
"""
|
||||
|> Sql.execute (fun reader -> {| Id = reader.string "discord_id" |> uint64 ; Name = reader.string "display_name" ; Wallet = reader.string "wallet_address" |})
|
||||
|
||||
let walletExists wallet =
|
||||
let list =
|
||||
devConnStr
|
||||
|> Sql.connect
|
||||
|> Sql.parameters [ "wallet" , Sql.string wallet ]
|
||||
|> Sql.query """
|
||||
SELECT wallet_address FROM crypto WHERE wallet_address = @wallet
|
||||
"""
|
||||
|> Sql.execute (fun reader -> reader.string "wallet_address")
|
||||
not list.IsEmpty
|
||||
|
||||
printfn "Inserting"
|
||||
async {
|
||||
for user in whitelisted do
|
||||
for wa in walletAddresses do
|
||||
if wa.Id = user.Id then
|
||||
let hasWL = user.Roles |> Seq.exists (fun role -> role.Name = "Whitelist Confirmed")
|
||||
let hasOG = user.Roles |> Seq.exists (fun role -> role.Name = "OG Whitelist Confirmed")
|
||||
try
|
||||
if walletExists wa.Wallet then
|
||||
let _ = updateUserWithWallet wa.Wallet hasWL hasOG
|
||||
()
|
||||
else
|
||||
let _ = insert wa.Id wa.Name wa.Wallet hasWL hasOG
|
||||
()
|
||||
with ex -> printfn $"Huh? {ex.Message}"
|
||||
()
|
||||
()
|
||||
let existing = getExisting ()
|
||||
let usersToFilter =
|
||||
existing |> List.filter (fun wa -> (whitelisted |> List.exists (fun wl -> wl.Id = wa.Id)) |> not)
|
||||
let toPrune = usersToFilter |> List.map (fun u -> u.Id |> string) |> List.toArray
|
||||
let _ = prune toPrune
|
||||
if toPrune.Length > 0 then
|
||||
printfn $"Pruning {toPrune.Length} users: {toPrune}"
|
||||
let existing = getExisting ()
|
||||
printfn $"Total Users: {existing.Length}"
|
||||
|
||||
} |> Async.RunSynchronously
|
||||
|
||||
bot.DisconnectAsync() |> Async.AwaitTask |> Async.RunSynchronously
|
96
Bot/Scripts/TransferNFT.fsx
Normal file
96
Bot/Scripts/TransferNFT.fsx
Normal file
@ -0,0 +1,96 @@
|
||||
#load "/home/joe/Development/DegenzGame/.paket/load/net6.0/main.group.fsx";;
|
||||
|
||||
open Npgsql.FSharp
|
||||
open dotenv.net
|
||||
open System.IO
|
||||
open System.Diagnostics
|
||||
open System.Threading.Tasks
|
||||
|
||||
let prodEnv = DotEnv.Read(DotEnvOptions(envFilePaths = [ "./.prod.env" ]))
|
||||
let ( _ , prodConnStr )= prodEnv.TryGetValue("DATABASE_URL")
|
||||
|
||||
type NftTransfer = {
|
||||
Id : uint64
|
||||
Name : string
|
||||
NftName : string
|
||||
NftAddress : string
|
||||
UserWallet : string
|
||||
}
|
||||
|
||||
printfn "Getting Wallet Addresses:"
|
||||
|
||||
let pending =
|
||||
prodConnStr
|
||||
|> Sql.connect
|
||||
|> Sql.query """
|
||||
SELECT u.id, u.display_name, token.name, token.address, mpa.tx_wallet FROM gen_one_token token
|
||||
JOIN mint_pass_assignment mpa on token.id = mpa.token_id
|
||||
JOIN "user" u on mpa.recipient_id = u.id
|
||||
WHERE mpa.fulfilled = false AND token.locked = false
|
||||
ORDER BY mpa.created_at;
|
||||
"""
|
||||
|> Sql.execute (fun reader ->
|
||||
{ Id = reader.string "id" |> uint64
|
||||
Name = reader.string "display_name"
|
||||
NftName = reader.string "name"
|
||||
NftAddress = reader.string "address"
|
||||
UserWallet = reader.string "tx_wallet" })
|
||||
|
||||
|
||||
let testSample = [ pending |> List.last ]
|
||||
|
||||
type CommandResult = {
|
||||
ExitCode: int;
|
||||
StandardOutput: string;
|
||||
StandardError: string
|
||||
}
|
||||
|
||||
let executeCommand executable args =
|
||||
async {
|
||||
let startInfo = ProcessStartInfo()
|
||||
startInfo.FileName <- executable
|
||||
|
||||
for a in args do
|
||||
startInfo.ArgumentList.Add(a)
|
||||
|
||||
startInfo.RedirectStandardOutput <- true
|
||||
startInfo.RedirectStandardError <- true
|
||||
startInfo.UseShellExecute <- false
|
||||
startInfo.CreateNoWindow <- true
|
||||
use p = new Process()
|
||||
p.StartInfo <- startInfo
|
||||
p.Start() |> ignore
|
||||
|
||||
let outTask =
|
||||
Task.WhenAll(
|
||||
[| p.StandardOutput.ReadToEndAsync()
|
||||
p.StandardError.ReadToEndAsync() |]
|
||||
)
|
||||
|
||||
do! p.WaitForExitAsync() |> Async.AwaitTask
|
||||
let! out = outTask |> Async.AwaitTask
|
||||
|
||||
return
|
||||
{ ExitCode = p.ExitCode
|
||||
StandardOutput = out.[0]
|
||||
StandardError = out.[1] }
|
||||
}
|
||||
let executeShellCommand command =
|
||||
executeCommand "/usr/bin/env" [ "-S"; "bash"; "-c"; command ]
|
||||
|
||||
|
||||
let transfer (nft : NftTransfer) =
|
||||
printfn $"Transferring {nft.NftName} to {nft.Name} "
|
||||
let result =
|
||||
$"spl-token transfer --allow-unfunded-recipient --fund-recipient {nft.NftAddress} 1 {nft.UserWallet}"
|
||||
|> executeShellCommand
|
||||
|> Async.RunSynchronously
|
||||
if result.ExitCode = 0 then
|
||||
let user = $"{nft.Id} - {nft.Name} - {nft.NftName}"
|
||||
let tx = result.StandardOutput
|
||||
File.AppendAllLines("/home/joe/Downloads/transactions", [ user ; tx ])
|
||||
else
|
||||
printfn $"{result.StandardError}"
|
||||
|
||||
for nft in pending do
|
||||
transfer nft
|
Loading…
x
Reference in New Issue
Block a user