Updates to scripts, add log
This commit is contained in:
parent
d88c6be0ce
commit
dc84d2de4c
@ -507,7 +507,8 @@ Keep an eye on <#{GuildEnvironment.channelAnnouncements}> for updates."""
|
|||||||
else
|
else
|
||||||
do! Messaging.sendFollowUpMessage ctx "⚠️ That's not a valid Solana address, please try again"
|
do! Messaging.sendFollowUpMessage ctx "⚠️ That's not a valid Solana address, please try again"
|
||||||
do! Analytics.invalidWalletSubmit (ctx.GetDiscordMember())
|
do! Analytics.invalidWalletSubmit (ctx.GetDiscordMember())
|
||||||
with _ ->
|
with ex ->
|
||||||
|
printfn $"{ex.Message}"
|
||||||
do! Messaging.sendFollowUpMessage ctx "⚠️ That's not a valid Solana address, please try again"
|
do! Messaging.sendFollowUpMessage ctx "⚠️ That's not a valid Solana address, please try again"
|
||||||
do! Analytics.invalidWalletSubmit (ctx.GetDiscordMember())
|
do! Analytics.invalidWalletSubmit (ctx.GetDiscordMember())
|
||||||
})
|
})
|
||||||
|
@ -14,15 +14,21 @@ open Solnet.KeyStore
|
|||||||
let devEnv = DotEnv.Read(DotEnvOptions(envFilePaths = [ "./.dev.env" ]))
|
let devEnv = DotEnv.Read(DotEnvOptions(envFilePaths = [ "./.dev.env" ]))
|
||||||
|
|
||||||
let ( _ , devConnStr )= devEnv.TryGetValue("DATABASE_URL")
|
let ( _ , devConnStr )= devEnv.TryGetValue("DATABASE_URL")
|
||||||
|
let ( _ , rpcClientUrl )= devEnv.TryGetValue("RPC_CLIENT")
|
||||||
|
let ( _ , wssClientUrl )= devEnv.TryGetValue("WSS_CLIENT")
|
||||||
|
|
||||||
let keystore = SolanaKeyStoreService()
|
let keystore = SolanaKeyStoreService()
|
||||||
let file = File.ReadAllText("/home/joe/.config/solana/devnet.json")
|
//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 authority = keystore.RestoreKeystore(file)
|
||||||
|
|
||||||
//let rpcClient = ClientFactory.GetClient("https://still-empty-field.solana-mainnet.quiknode.pro/5b1b6b5c913ec79a20bef19d5ba5f63023e470d6/")
|
//let rpcClient = ClientFactory.GetClient(Cluster.DevNet)
|
||||||
let rpcClient = ClientFactory.GetClient(Cluster.DevNet)
|
let rpcClient = ClientFactory.GetClient(rpcClientUrl)
|
||||||
|
|
||||||
let mintAccount = PublicKey("2iS6gcoB5VhiLC4eNB7NdcaLgEHjLrXHYpz7T2JMGBDw")
|
//let mintAccount = PublicKey("2iS6gcoB5VhiLC4eNB7NdcaLgEHjLrXHYpz7T2JMGBDw")
|
||||||
|
let mintAccount = PublicKey("4gN1u9LNBnvFERpDU3SrMusMJ1gKLbE9XB6EYraQkWTf")
|
||||||
|
//let ataAccount = PublicKey("CRa7GCMUaB4np32XoTD2sEyCXFVfYKKF4JRPkQTwV3EY")
|
||||||
|
let sourceAtaAccount = PublicKey("7CB459UJC3qtTYJzfC8bFNvdycQGXTPzKoEHxys8Ytfs")
|
||||||
//let associatedTokenAccountOwner = PublicKey("GutKESfJw8PDMbFVqByxTr4f5TUSHUVmkf5gtsWWWqrU")
|
//let associatedTokenAccountOwner = PublicKey("GutKESfJw8PDMbFVqByxTr4f5TUSHUVmkf5gtsWWWqrU")
|
||||||
|
|
||||||
type AirdropStatus =
|
type AirdropStatus =
|
||||||
@ -93,7 +99,6 @@ let getTokenCountToDrop wallet =
|
|||||||
return (if wl.HasWhitelist then 1uL else 0uL) + (if wl.HasOg then 2uL else 0uL)
|
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 executeDrop (wallet : string) =
|
||||||
let associatedTokenAccountOwner = PublicKey(wallet)
|
let associatedTokenAccountOwner = PublicKey(wallet)
|
||||||
let associatedTokenAccount = AssociatedTokenAccountProgram.DeriveAssociatedTokenAccount(associatedTokenAccountOwner, mintAccount)
|
let associatedTokenAccount = AssociatedTokenAccountProgram.DeriveAssociatedTokenAccount(associatedTokenAccountOwner, mintAccount)
|
||||||
@ -109,33 +114,33 @@ let executeDrop (wallet : string) =
|
|||||||
PublicKey(targetWallet),
|
PublicKey(targetWallet),
|
||||||
mintAccount))
|
mintAccount))
|
||||||
.AddInstruction(TokenProgram.Transfer(
|
.AddInstruction(TokenProgram.Transfer(
|
||||||
PublicKey("CRa7GCMUaB4np32XoTD2sEyCXFVfYKKF4JRPkQTwV3EY"),
|
sourceAtaAccount,
|
||||||
associatedTokenAccount,
|
associatedTokenAccount,
|
||||||
amount,
|
amount,
|
||||||
authority.Account))
|
authority.Account))
|
||||||
.Build(authority.Account);
|
.Build(authority.Account);
|
||||||
task {
|
async {
|
||||||
// let streamingClient = ClientFactory.GetStreamingClient("wss://still-empty-field.solana-mainnet.quiknode.pro/5b1b6b5c913ec79a20bef19d5ba5f63023e470d6/")
|
// let streamingClient = ClientFactory.GetStreamingClient(Cluster.DevNet)
|
||||||
let streamingClient = ClientFactory.GetStreamingClient(Cluster.DevNet)
|
let streamingClient = ClientFactory.GetStreamingClient(wssClientUrl)
|
||||||
do! streamingClient.ConnectAsync()
|
do! streamingClient.ConnectAsync() |> Async.AwaitTask
|
||||||
let blockHash = rpcClient.GetLatestBlockHash()
|
let blockHash = rpcClient.GetLatestBlockHash()
|
||||||
let! amount = getTokenCountToDrop wallet
|
let! amount = getTokenCountToDrop wallet |> Async.AwaitTask
|
||||||
log $"Dropping {amount} tokens"
|
log $"Dropping {amount} tokens"
|
||||||
let tx = buildTransaction blockHash.Result.Value amount wallet
|
let tx = buildTransaction blockHash.Result.Value amount wallet
|
||||||
let! tx = rpcClient.SendTransactionAsync(tx)
|
let! tx = rpcClient.SendTransactionAsync(tx) |> Async.AwaitTask
|
||||||
if tx.ErrorData <> null then
|
if tx.ErrorData <> null then
|
||||||
let! _ = updateError wallet (tx.ErrorData.Logs |> String.concat "\n")
|
let! _ = updateError wallet (tx.ErrorData.Logs |> String.concat "\n") |> Async.AwaitTask
|
||||||
()
|
()
|
||||||
log $"Transaction error: {wallet}"
|
log $"Transaction error: {wallet}"
|
||||||
return ()
|
return ()
|
||||||
elif String.IsNullOrWhiteSpace(tx.Result) then
|
elif String.IsNullOrWhiteSpace(tx.Result) then
|
||||||
let msg = $"Transaction did not have an ID but the ErrorData was null: {tx.Reason}"
|
let msg = $"Transaction did not have an ID but the ErrorData was null: {tx.Reason}"
|
||||||
let! _ = updateError wallet msg
|
let! _ = updateError wallet msg |> Async.AwaitTask
|
||||||
log $"Odd Transaction Error"
|
log $"Odd Transaction Error"
|
||||||
return ()
|
return ()
|
||||||
else
|
else
|
||||||
log $"Successful, now waiting for RPC"
|
log $"Successful, now waiting for RPC"
|
||||||
let! _ = updatePending wallet tx.Result
|
let! _ = updatePending wallet tx.Result |> Async.AwaitTask
|
||||||
let! _ = streamingClient.SubscribeSignatureAsync(tx.Result, fun sub result ->
|
let! _ = streamingClient.SubscribeSignatureAsync(tx.Result, fun sub result ->
|
||||||
if result.Value.Error = null then
|
if result.Value.Error = null then
|
||||||
log "RPC Finished"
|
log "RPC Finished"
|
||||||
@ -152,8 +157,8 @@ let executeDrop (wallet : string) =
|
|||||||
return ()
|
return ()
|
||||||
} |> Async.AwaitTask |> Async.Start
|
} |> Async.AwaitTask |> Async.Start
|
||||||
else
|
else
|
||||||
let msg = $"Got an error, let's check it out {result.Value.Error}"
|
let msg = $"Got an error, check the tx id"
|
||||||
updatePendingError wallet msg tx.Result |> Async.AwaitTask |> Async.Ignore |> Async.Start)
|
updatePendingError wallet msg tx.Result |> Async.AwaitTask |> Async.Ignore |> Async.Start) |> Async.AwaitTask
|
||||||
return ()
|
return ()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -161,19 +166,22 @@ let targetWallets =
|
|||||||
devConnStr
|
devConnStr
|
||||||
|> Sql.connect
|
|> Sql.connect
|
||||||
|> Sql.query """
|
|> Sql.query """
|
||||||
SELECT wallet_address FROM crypto WHERE status = 'Ready';
|
SELECT wallet_address FROM crypto WHERE status = 'Ready' AND total_dropped = 0;
|
||||||
"""
|
"""
|
||||||
|> Sql.execute (fun reader -> reader.string "wallet_address")
|
|> Sql.execute (fun reader -> reader.string "wallet_address")
|
||||||
|
|
||||||
printfn $"Got target wallets: {targetWallets.Length}"
|
printfn $"Got target wallets: {targetWallets.Length}"
|
||||||
|
|
||||||
// "GK7rkZYrdAEpTm9n9TkHWK1T5nDXeRfVUVfcHQwSDyuJ"
|
|
||||||
let asyncs =
|
let asyncs =
|
||||||
targetWallets
|
targetWallets
|
||||||
|> List.map executeDrop
|
|> List.map executeDrop
|
||||||
|> List.map Async.AwaitTask
|
|> List.chunkBySize 5
|
||||||
|
|
||||||
Async.Parallel ( asyncs , 16 ) |> Async.StartChild
|
async {
|
||||||
|
for a in asyncs do
|
||||||
|
let! _ = Async.Parallel a
|
||||||
|
do! Async.Sleep 500
|
||||||
|
} |> Async.Start
|
||||||
|
|
||||||
|
|
||||||
Console.ReadLine() |> ignore
|
Console.ReadLine() |> ignore
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
open Npgsql.FSharp
|
open Npgsql.FSharp
|
||||||
open DSharpPlus
|
open DSharpPlus
|
||||||
|
open DSharpPlus.Entities
|
||||||
open dotenv.net
|
open dotenv.net
|
||||||
|
|
||||||
let prodEnv = DotEnv.Read(DotEnvOptions(envFilePaths = [ "./.prod.env" ]))
|
let prodEnv = DotEnv.Read(DotEnvOptions(envFilePaths = [ "./.prod.env" ]))
|
||||||
@ -27,6 +28,26 @@ printfn "Getting Members"
|
|||||||
let users = guild.GetAllMembersAsync() |> Async.AwaitTask |> Async.RunSynchronously
|
let users = guild.GetAllMembersAsync() |> Async.AwaitTask |> Async.RunSynchronously
|
||||||
printfn $"Total Members: {users.Count}"
|
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 =
|
let whitelisted =
|
||||||
users
|
users
|
||||||
|> Seq.filter (fun u -> u.Roles |> Seq.exists (fun role -> role.Name.Contains("Confirmed")))
|
|> Seq.filter (fun u -> u.Roles |> Seq.exists (fun role -> role.Name.Contains("Confirmed")))
|
||||||
@ -52,22 +73,75 @@ let insert did name wallet wl og =
|
|||||||
"wl" , Sql.bool wl ; "og" , Sql.bool og ]
|
"wl" , Sql.bool wl ; "og" , Sql.bool og ]
|
||||||
|> Sql.query """
|
|> Sql.query """
|
||||||
INSERT INTO crypto(discord_id, display_name, wallet_address, has_wl, has_og) VALUES (@did, @name, @wallet, @wl, @og)
|
INSERT INTO crypto(discord_id, display_name, wallet_address, has_wl, has_og) VALUES (@did, @name, @wallet, @wl, @og)
|
||||||
ON CONFLICT (wallet_address) DO
|
ON CONFLICT (discord_id) DO
|
||||||
UPDATE SET display_name = @name, discord_id = @did , has_wl = @wl , has_og = @og WHERE crypto.wallet_address = @wallet;
|
UPDATE SET wallet_address = @wallet, has_wl = @wl , has_og = @og WHERE crypto.discord_id = @did AND crypto.status = 'Nothing';
|
||||||
"""
|
"""
|
||||||
|> Sql.executeNonQuery
|
|> 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"
|
printfn "Inserting"
|
||||||
async {
|
async {
|
||||||
for user in whitelisted do
|
for user in whitelisted do
|
||||||
for wa in walletAddresses do
|
for wa in walletAddresses do
|
||||||
if wa.Id = user.Id then
|
if wa.Id = user.Id then
|
||||||
let hasWL = user.Roles |> Seq.exists (fun role -> role.Name = "Whitelist Confirmed")
|
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")
|
let hasOG = user.Roles |> Seq.exists (fun role -> role.Name = "OG Whitelist Confirmed")
|
||||||
try
|
try
|
||||||
let _ = insert wa.Id wa.Name wa.Wallet hasWL hasOG
|
if walletExists wa.Wallet then
|
||||||
()
|
let _ = updateUserWithWallet wa.Wallet hasWL hasOG
|
||||||
with ex -> printfn $"{ex.Message}"
|
()
|
||||||
|
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
|
} |> Async.RunSynchronously
|
||||||
|
|
||||||
bot.DisconnectAsync() |> Async.AwaitTask |> Async.RunSynchronously
|
bot.DisconnectAsync() |> Async.AwaitTask |> Async.RunSynchronously
|
Loading…
x
Reference in New Issue
Block a user