368 lines
15 KiB
Lua
368 lines
15 KiB
Lua
-- Variables
|
|
local coin = Crypto.Coin
|
|
local QBCore = exports['qb-core']:GetCoreObject()
|
|
local bannedCharacters = { '%', '$', ';' }
|
|
|
|
-- Function
|
|
local function RefreshCrypto()
|
|
local result = MySQL.query.await('SELECT * FROM crypto WHERE crypto = ?', { coin })
|
|
if result ~= nil and result[1] ~= nil then
|
|
Crypto.Worth[coin] = result[1].worth
|
|
if result[1].history ~= nil then
|
|
Crypto.History[coin] = json.decode(result[1].history)
|
|
TriggerClientEvent('qb-crypto:client:UpdateCryptoWorth', -1, coin, result[1].worth, json.decode(result[1].history))
|
|
else
|
|
TriggerClientEvent('qb-crypto:client:UpdateCryptoWorth', -1, coin, result[1].worth, nil)
|
|
end
|
|
end
|
|
end
|
|
|
|
local function ErrorHandle(error)
|
|
for k, v in pairs(Ticker.Error_handle) do
|
|
if string.match(error, k) then
|
|
return v
|
|
end
|
|
end
|
|
return false
|
|
end
|
|
|
|
local function GetTickerPrice() -- Touch = no help
|
|
local ticker_promise = promise.new()
|
|
PerformHttpRequest('https://min-api.cryptocompare.com/data/price?fsym=' .. Ticker.coin .. '&tsyms=' .. Ticker.currency .. '&api_key=' .. Ticker.Api_key, function(Error, Result, _)
|
|
local result_obj = json.decode(Result)
|
|
if not result_obj['Response'] then
|
|
local this_resolve = { error = Error, response_data = result_obj[string.upper(Ticker.currency)] }
|
|
ticker_promise:resolve(this_resolve) --- Could resolve Error aswell for more accurate Error messages? Solved in else
|
|
else
|
|
local this_resolve = { error = result_obj['Message'] }
|
|
ticker_promise:resolve(this_resolve)
|
|
end
|
|
end, 'GET')
|
|
Citizen.Await(ticker_promise)
|
|
if type(ticker_promise.value.error) ~= 'number' then
|
|
local get_user_friendly_error = ErrorHandle(ticker_promise.value.error)
|
|
if get_user_friendly_error then
|
|
return get_user_friendly_error
|
|
else
|
|
return '\27[31m Unexpected error \27[0m' --- Raised an error which we did not expect, script should be capable of sticking with last recorded price and shutting down the sync logic
|
|
end
|
|
else
|
|
return ticker_promise.value.response_data
|
|
end
|
|
end
|
|
|
|
local function HandlePriceChance()
|
|
local currentValue = Crypto.Worth[coin]
|
|
local prevValue = Crypto.Worth[coin]
|
|
local trend = math.random(0, 100)
|
|
local event = math.random(0, 100)
|
|
local chance = event - Crypto.ChanceOfCrashOrLuck
|
|
|
|
if event > chance then
|
|
if trend <= Crypto.ChanceOfDown then
|
|
currentValue = currentValue - math.random(Crypto.CasualDown[1], Crypto.CasualDown[2])
|
|
elseif trend >= Crypto.ChanceOfUp then
|
|
currentValue = currentValue + math.random(Crypto.CasualUp[1], Crypto.CasualUp[2])
|
|
end
|
|
else
|
|
if math.random(0, 1) == 1 then
|
|
currentValue = currentValue + math.random(Crypto.Luck[1], Crypto.Luck[2])
|
|
else
|
|
currentValue = currentValue - math.random(Crypto.Crash[1], Crypto.Crash[2])
|
|
end
|
|
end
|
|
|
|
if currentValue <= Crypto.Lower then
|
|
currentValue = Crypto.Lower
|
|
elseif currentValue >= Crypto.Upper then
|
|
currentValue = Crypto.Upper
|
|
end
|
|
|
|
if Crypto.History[coin][4] then
|
|
-- Shift array index 1 to 3
|
|
for k = 3, 1, -1 do
|
|
Crypto.History[coin][k] = Crypto.History[coin][k + 1]
|
|
end
|
|
-- Assign array index 4 to the latest result
|
|
Crypto.History[coin][4] = { PreviousWorth = prevValue, NewWorth = currentValue }
|
|
else
|
|
Crypto.History[coin][#Crypto.History[coin] + 1] = { PreviousWorth = prevValue, NewWorth = currentValue }
|
|
end
|
|
|
|
Crypto.Worth[coin] = currentValue
|
|
|
|
local history = json.encode(Crypto.History[coin])
|
|
local props = {
|
|
['worth'] = currentValue,
|
|
['history'] = history,
|
|
['crypto'] = coin
|
|
}
|
|
MySQL.update(
|
|
'UPDATE crypto set worth = :worth, history = :history where crypto = :crypto',
|
|
props,
|
|
function(affectedRows)
|
|
if affectedRows < 1 then
|
|
print('Crypto not found, inserting new record for ' .. coin)
|
|
MySQL.insert('INSERT INTO crypto (crypto, worth, history) VALUES (:crypto, :worth, :history)', props)
|
|
end
|
|
RefreshCrypto()
|
|
end
|
|
)
|
|
end
|
|
|
|
-- Commands
|
|
|
|
QBCore.Commands.Add('setcryptoworth', 'Set crypto value', { { name = 'crypto', help = 'Name of the crypto currency' }, { name = 'Value', help = 'New value of the crypto currency' } }, false, function(source, args)
|
|
local src = source
|
|
local crypto = tostring(args[1])
|
|
|
|
if crypto ~= nil then
|
|
if Crypto.Worth[crypto] ~= nil then
|
|
local NewWorth = math.ceil(tonumber(args[2]))
|
|
|
|
if NewWorth ~= nil then
|
|
local PercentageChange = math.ceil(((NewWorth - Crypto.Worth[crypto]) / Crypto.Worth[crypto]) * 100)
|
|
local ChangeLabel = '+'
|
|
|
|
if PercentageChange < 0 then
|
|
ChangeLabel = '-'
|
|
PercentageChange = (PercentageChange * -1)
|
|
end
|
|
|
|
if Crypto.Worth[crypto] == 0 then
|
|
PercentageChange = 0
|
|
ChangeLabel = ''
|
|
end
|
|
|
|
Crypto.History[crypto][#Crypto.History[crypto] + 1] = {
|
|
PreviousWorth = Crypto.Worth[crypto],
|
|
NewWorth = NewWorth
|
|
}
|
|
|
|
TriggerClientEvent('QBCore:Notify', src, 'You have changed the value of ' .. Crypto.Labels[crypto] .. ' from: $' .. Crypto.Worth[crypto] .. ' to: $' .. NewWorth .. ' (' .. ChangeLabel .. ' ' .. PercentageChange .. '%)')
|
|
Crypto.Worth[crypto] = NewWorth
|
|
TriggerClientEvent('qb-crypto:client:UpdateCryptoWorth', -1, crypto, NewWorth)
|
|
MySQL.insert('INSERT INTO crypto (worth, history) VALUES (:worth, :history) ON DUPLICATE KEY UPDATE worth = :worth, history = :history', {
|
|
['worth'] = NewWorth,
|
|
['history'] = json.encode(Crypto.History[crypto]),
|
|
})
|
|
else
|
|
TriggerClientEvent('QBCore:Notify', src, Lang:t('text.you_have_not_given_a_new_value', { crypto = Crypto.Worth[crypto] }))
|
|
end
|
|
else
|
|
TriggerClientEvent('QBCore:Notify', src, Lang:t('text.this_crypto_does_not_exist'))
|
|
end
|
|
else
|
|
TriggerClientEvent('QBCore:Notify', src, Lang:t('text.you_have_not_provided_crypto_available_qbit'))
|
|
end
|
|
end, 'admin')
|
|
|
|
QBCore.Commands.Add('checkcryptoworth', '', {}, false, function(source)
|
|
local src = source
|
|
TriggerClientEvent('QBCore:Notify', src, Lang:t('text.the_qbit_has_a_value_of', { crypto = Crypto.Worth['qbit'] }))
|
|
end)
|
|
|
|
QBCore.Commands.Add('crypto', '', {}, false, function(source)
|
|
local src = source
|
|
local Player = QBCore.Functions.GetPlayer(src)
|
|
local MyPocket = math.ceil(Player.PlayerData.money.crypto * Crypto.Worth['qbit'])
|
|
|
|
TriggerClientEvent('QBCore:Notify', src, Lang:t('text.you_have_with_a_value_of', { playerPlayerDataMoneyCrypto = Player.PlayerData.money.crypto, mypocket = MyPocket }))
|
|
end)
|
|
|
|
-- Events
|
|
|
|
RegisterServerEvent('qb-crypto:server:FetchWorth', function()
|
|
for name, _ in pairs(Crypto.Worth) do
|
|
local result = MySQL.query.await('SELECT * FROM crypto WHERE crypto = ?', { name })
|
|
if result[1] ~= nil then
|
|
Crypto.Worth[name] = result[1].worth
|
|
if result[1].history ~= nil then
|
|
Crypto.History[name] = json.decode(result[1].history)
|
|
TriggerClientEvent('qb-crypto:client:UpdateCryptoWorth', -1, name, result[1].worth, json.decode(result[1].history))
|
|
else
|
|
TriggerClientEvent('qb-crypto:client:UpdateCryptoWorth', -1, name, result[1].worth, nil)
|
|
end
|
|
end
|
|
end
|
|
end)
|
|
|
|
RegisterServerEvent('qb-crypto:server:ExchangeFail', function()
|
|
local src = source
|
|
local Player = QBCore.Functions.GetPlayer(src)
|
|
local ItemData = Player.Functions.GetItemByName('cryptostick')
|
|
if ItemData ~= nil then
|
|
exports['qb-inventory']:RemoveItem(src, 'cryptostick', 1, false, 'qb-crypto:server:ExchangeFail')
|
|
TriggerClientEvent('qb-inventory:client:ItemBox', src, QBCore.Shared.Items['cryptostick'], 'remove')
|
|
TriggerClientEvent('QBCore:Notify', src, Lang:t('error.cryptostick_malfunctioned'), 'error')
|
|
end
|
|
end)
|
|
|
|
RegisterServerEvent('qb-crypto:server:Rebooting', function(state, percentage)
|
|
Crypto.Exchange.RebootInfo.state = state
|
|
Crypto.Exchange.RebootInfo.percentage = percentage
|
|
end)
|
|
|
|
RegisterServerEvent('qb-crypto:server:GetRebootState', function()
|
|
local src = source
|
|
TriggerClientEvent('qb-crypto:client:GetRebootState', src, Crypto.Exchange.RebootInfo)
|
|
end)
|
|
|
|
RegisterServerEvent('qb-crypto:server:SyncReboot', function()
|
|
TriggerClientEvent('qb-crypto:client:SyncReboot', -1)
|
|
end)
|
|
|
|
RegisterServerEvent('qb-crypto:server:ExchangeSuccess', function(LuckChance)
|
|
local src = source
|
|
local Player = QBCore.Functions.GetPlayer(src)
|
|
local ItemData = Player.Functions.GetItemByName('cryptostick')
|
|
if ItemData ~= nil then
|
|
local LuckyNumber = math.random(1, 10)
|
|
local DeelNumber = 1000000
|
|
local Amount = (math.random(611111, 1599999) / DeelNumber)
|
|
if LuckChance == LuckyNumber then
|
|
Amount = (math.random(1599999, 2599999) / DeelNumber)
|
|
end
|
|
exports['qb-inventory']:RemoveItem(src, 'cryptostick', 1, false, 'qb-crypto:server:ExchangeSuccess')
|
|
Player.Functions.AddMoney('crypto', Amount, 'qb-crypto:server:ExchangeSuccess')
|
|
TriggerClientEvent('QBCore:Notify', src, Lang:t('success.you_have_exchanged_your_cryptostick_for', { amount = Amount }), 'success', 3500)
|
|
TriggerClientEvent('qb-inventory:client:ItemBox', src, QBCore.Shared.Items['cryptostick'], 'remove')
|
|
TriggerClientEvent('qb-phone:client:AddTransaction', src, Player, {}, Lang:t('credit.there_are_amount_credited', { amount = Amount }), 'Credit')
|
|
end
|
|
end)
|
|
|
|
-- Callbacks
|
|
|
|
QBCore.Functions.CreateCallback('qb-crypto:server:HasSticky', function(source, cb)
|
|
local Player = QBCore.Functions.GetPlayer(source)
|
|
local Item = Player.Functions.GetItemByName('cryptostick')
|
|
|
|
if Item ~= nil then
|
|
cb(true)
|
|
else
|
|
cb(false)
|
|
end
|
|
end)
|
|
|
|
QBCore.Functions.CreateCallback('qb-crypto:server:GetCryptoData', function(source, cb, name)
|
|
local Player = QBCore.Functions.GetPlayer(source)
|
|
local CryptoData = {
|
|
History = Crypto.History[name],
|
|
Worth = Crypto.Worth[name],
|
|
Portfolio = Player.PlayerData.money.crypto,
|
|
WalletId = Player.PlayerData.metadata['walletid'],
|
|
}
|
|
|
|
cb(CryptoData)
|
|
end)
|
|
|
|
QBCore.Functions.CreateCallback('qb-crypto:server:BuyCrypto', function(source, cb, data)
|
|
local Player = QBCore.Functions.GetPlayer(source)
|
|
local total_price = math.floor(tonumber(data.Coins) * tonumber(Crypto.Worth['qbit']))
|
|
if Player.PlayerData.money.bank >= total_price then
|
|
local CryptoData = {
|
|
History = Crypto.History['qbit'],
|
|
Worth = Crypto.Worth['qbit'],
|
|
Portfolio = Player.PlayerData.money.crypto + tonumber(data.Coins),
|
|
WalletId = Player.PlayerData.metadata['walletid'],
|
|
}
|
|
Player.Functions.RemoveMoney('bank', total_price, 'bought crypto')
|
|
TriggerClientEvent('qb-phone:client:AddTransaction', source, Player, data, Lang:t('credit.you_have_qbit_purchased', { dataCoins = tonumber(data.Coins) }), 'Credit')
|
|
Player.Functions.AddMoney('crypto', tonumber(data.Coins), 'bought crypto')
|
|
cb(CryptoData)
|
|
else
|
|
cb(false)
|
|
end
|
|
end)
|
|
|
|
QBCore.Functions.CreateCallback('qb-crypto:server:SellCrypto', function(source, cb, data)
|
|
local Player = QBCore.Functions.GetPlayer(source)
|
|
|
|
if Player.PlayerData.money.crypto >= tonumber(data.Coins) then
|
|
local CryptoData = {
|
|
History = Crypto.History['qbit'],
|
|
Worth = Crypto.Worth['qbit'],
|
|
Portfolio = Player.PlayerData.money.crypto - tonumber(data.Coins),
|
|
WalletId = Player.PlayerData.metadata['walletid'],
|
|
}
|
|
Player.Functions.RemoveMoney('crypto', tonumber(data.Coins), 'sold crypto')
|
|
local amount = math.floor(tonumber(data.Coins) * tonumber(Crypto.Worth['qbit']))
|
|
TriggerClientEvent('qb-phone:client:AddTransaction', source, Player, data, Lang:t('debit.you_have_sold', { dataCoins = tonumber(data.Coins) }), 'Debit')
|
|
Player.Functions.AddMoney('bank', amount, 'sold crypto')
|
|
cb(CryptoData)
|
|
else
|
|
cb(false)
|
|
end
|
|
end)
|
|
|
|
QBCore.Functions.CreateCallback('qb-crypto:server:TransferCrypto', function(source, cb, data)
|
|
local newCoin = tostring(data.Coins)
|
|
local newWalletId = tostring(data.WalletId)
|
|
for _, v in pairs(bannedCharacters) do
|
|
newCoin = string.gsub(newCoin, '%' .. v, '')
|
|
newWalletId = string.gsub(newWalletId, '%' .. v, '')
|
|
end
|
|
data.WalletId = newWalletId
|
|
data.Coins = tonumber(newCoin)
|
|
local Player = QBCore.Functions.GetPlayer(source)
|
|
if Player.PlayerData.money.crypto >= tonumber(data.Coins) then
|
|
local query = '%"walletid":"' .. data.WalletId .. '"%'
|
|
local result = MySQL.query.await('SELECT * FROM `players` WHERE `metadata` LIKE ?', { query })
|
|
if result[1] ~= nil then
|
|
local CryptoData = {
|
|
History = Crypto.History['qbit'],
|
|
Worth = Crypto.Worth['qbit'],
|
|
Portfolio = Player.PlayerData.money.crypto - tonumber(data.Coins),
|
|
WalletId = Player.PlayerData.metadata['walletid'],
|
|
}
|
|
Player.Functions.RemoveMoney('crypto', tonumber(data.Coins), 'transfer crypto')
|
|
TriggerClientEvent('qb-phone:client:AddTransaction', source, Player, data, 'You have ' .. tonumber(data.Coins) .. " Qbit('s) transferred!", 'Debit')
|
|
local Target = QBCore.Functions.GetPlayerByCitizenId(result[1].citizenid)
|
|
|
|
if Target ~= nil then
|
|
Target.Functions.AddMoney('crypto', tonumber(data.Coins), 'transfer crypto')
|
|
TriggerClientEvent('qb-phone:client:AddTransaction', Target.PlayerData.source, Player, data, 'There are ' .. tonumber(data.Coins) .. " Qbit('s) credited!", 'Credit')
|
|
else
|
|
local MoneyData = json.decode(result[1].money)
|
|
MoneyData.crypto = MoneyData.crypto + tonumber(data.Coins)
|
|
MySQL.update('UPDATE players SET money = ? WHERE citizenid = ?', { json.encode(MoneyData), result[1].citizenid })
|
|
end
|
|
cb(CryptoData)
|
|
else
|
|
cb('notvalid')
|
|
end
|
|
else
|
|
cb('notenough')
|
|
end
|
|
end)
|
|
|
|
-- Threads
|
|
|
|
CreateThread(function()
|
|
while true do
|
|
Wait(Crypto.RefreshTimer * 60000)
|
|
HandlePriceChance()
|
|
end
|
|
end)
|
|
|
|
-- You touch = you break
|
|
if Ticker.Enabled then
|
|
Citizen.CreateThread(function()
|
|
local Interval = Ticker.tick_time * 60000
|
|
if Ticker.tick_time < 2 then
|
|
Interval = 120000
|
|
end
|
|
while (true) do
|
|
local get_coin_price = GetTickerPrice()
|
|
if type(get_coin_price) == 'number' then
|
|
Crypto.Worth['qbit'] = get_coin_price
|
|
else
|
|
print('\27[31m' .. get_coin_price .. '\27[0m')
|
|
Ticker.Enabled = false
|
|
break
|
|
end
|
|
Citizen.Wait(Interval)
|
|
end
|
|
end)
|
|
end
|