Newer
Older
Kristify / src / libs / kristly.lua
@Erb3 Erb3 on 14 Nov 2022 15 KB Get ready to develop backend
local expect = require "cc.expect"
local expect, field = expect.expect, expect.field

local kristly = {}
local kristlyWS = { ws = nil }

----------------------------------------------------------------------------------
--                                 UTILS                                        --
----------------------------------------------------------------------------------

--- A basic JSON Post function to the krist api.
-- Decodes the response from json into a table.
-- @param endpoint The json endpoint. The first part of the url should not be included.
-- @param body A stringified body
-- @return table
local function basicJSONPOST(endpoint, body)
  expect(1, endpoint, "string")

  return textutils.unserializeJSON(http.post("https://krist.dev/" .. endpoint, body).readAll())
end

--- A basic Get function to the krist api.
-- Decodes the response from json into a table.
-- @param endpoint The GET endpoint. Do not include the first part of the url.
-- @return table
local function basicGET(endpoint)
  expect(1, endpoint, "string")

  return textutils.unserializeJSON(http.get("https://krist.dev/" .. endpoint).readAll())
end

----------------------------------------------------------------------------------
--                                ADDRESSES                                     --
----------------------------------------------------------------------------------

--- Gets information about the supplied krist address.
-- @param address The krist address
-- @return address table, with address, balance, totalin, totalout, and firstseen.
function kristly.getAddress(address)
  expect(1, address, "string")

  return basicGET("addresses/" .. address)
end

--- Lists initized krist addresses.
-- @param limit The amount of addresses to return. Between 1-1000. Default: 50
-- @param offset The amount of offset the results. Useful for pagination.
-- @return table with count, total, and a addresses table, which contains the same data you would get from getAddress()
function kristly.listAddresses(limit, offset)
  expect(1, limit, "nil", "number")
  expect(2, offset, "nil", "number")

  limit = limit or 50
  offset = offset or 0

  return basicGET("addresses?limit=" .. limit .. "&offset=" .. offset)
end

--- Lists the richest krist addresses
-- @param limit The amount of addresses to return. Between 1-1000. Default: 50
-- @param offset The amount of offset the results. Useful for pagination.
-- @return table with count, total, and a addresses table, which contains the same data you would get from getAddress()
function kristly.listRichestAddresses(limit, offset)
  expect(1, limit, "nil", "number")
  expect(2, offset, "nil", "number")

  limit = limit or 50
  offset = offset or 0

  return basicGET("addresses/rich?limit=" .. limit .. "&offset=" .. offset)
end

--- Lists the recent transactions for a address
-- @param address the address to get transactions from
-- @param excludeMined if we should exclude mined blocks from the transactions
-- @param limit The limit of transactions to return
-- @param offset The amount to offset the results, useful for pagination
-- @return table with count, total, and a table array with transactions
function kristly.getRecentTransactions(address, excludeMined, limit, offset)
  expect(1, address, "string")
  expect(2, excludeMined, "nil", "boolean")
  expect(3, limit, "nil", "number")
  expect(4, offset, "nil", "number")

  excludeMined = excludeMined or true
  limit = limit or 50
  offset = offset or 0

  return basicGET("addresses/" ..
    address .. "/transactions?limit=" .. limit .. "&offset=" .. offset .. "&excludeMined=" .. excludeMined)
end

--- Lists the names owned by a address
-- @param address the address to get names from
-- @param limit The limit of names to return
-- @param offset The amount to offset the results, useful for pagination
function kristly.getNamesOwnedBy(address, limit, offset)
  expect(1, address, "string")
  expect(2, limit, "nil", "number")
  expect(3, offset, "nil", "number")

  limit = limit or 50
  offset = offset or 0

  return basicGET("addresses/" .. address .. "/names")
end

----------------------------------------------------------------------------------
--                                 BLOCKS                                       --
----------------------------------------------------------------------------------

-- MINING IS DISABLED, BUT THIS PART WILL BE ADDED LATER

----------------------------------------------------------------------------------
--                                 LOOKUP API                                   --
----------------------------------------------------------------------------------

-- LOOKUP API IS IN BETA, MAY BE ADDED TO kristly IN THE FUTURE

----------------------------------------------------------------------------------
--                                  MISC                                        --
----------------------------------------------------------------------------------

--- Gets the current work
-- @return a table with if it is ok and work which contains the current work.
function kristly.getCurrentWork()
  return basicGET("work")
end

--- Gets the work over the past 24h
-- @return a table with if it is ok and a table of work
function kristly.getLast24hWork()
  return basicGET("work/day")
end

--- Gets detailed information about work/blocks
-- @return a table with lots of information
function kristly.getDetailedWorkInfo()
  return basicGET("work/detailed")
end

--- Authenticates a address with a private key
-- @param privatekey The privatekey of the address you want to authenticate
-- @return a table with ok and authed key/value pairs
function kristly.authenticate(privatekey)
  expect(1, privatekey, "string")

  return basicJSONPOST("https://krist.dev/login", "privatekey=" .. privatekey)
end

--- Gets information about the krist server (MOTD)
-- @return table with lots of information. Specifications are over at krist.dev/docs
function kristly.getMOTD()
  return basicGET("motd")
end

--- Gets the latest krist wallet version
-- @return a table with ok and walletVersion key/value pairs
function kristly.getKristWalletVersion()
  return basicGET("walletversion")
end

--- Gets the latests changes/commits to the krist project
-- @return a table with ok, commits and whatsNew
function kristly.getKristChanges()
  return basicGET("whatsnew")
end

--- Gets the current supply of krist
-- @return a table with ok and money_supply
function kristly.getKristSupply()
  return basicGET("supply")
end

--- Converts a private key into a krist address
-- @return a table with ok and address porperty
function kristly.addressFromKey(privateKey)
  expect(1, privatekey, "string")

  return basicJSONPOST("v2", "privatekey=" .. privateKey)
end

----------------------------------------------------------------------------------
--                                  NAMES                                       --
----------------------------------------------------------------------------------

--- Gets info about a krist name
-- @return a table with information
function kristly.getNameInfo(name)
  expect(1, name, "string")

  return basicGET("names/" .. name)
end

--- Lists currently registered krist names
-- @param limit number The limit of results
-- @param offset The amount to offset the results
-- @returns table with count, total, and a tablearray of names
function kristly.getKristNames(limit, offset)
  expect(1, limit, "nil", "number")
  expect(2, offset, "nil", "number")

  limit = limit or 50
  offset = offset or 0

  return basicGET("names?limit=" .. limit .. "&offset=" .. offset)
end

--- Lists currently registered krist names sorted by newest
-- @param limit number The limit of results
-- @param offset The amount to offset the results
-- @returns table with count, total, and a tablearray of names
function kristly.getNewestKristNames(limit, offset)
  expect(1, limit, "nil", "number")
  expect(2, offset, "nil", "number")

  limit = limit or 50
  offset = offset or 0

  return basicGET("names/new?limit=" .. limit .. "&offset=" .. offset)
end

---Gets the price of a krist name
-- @return a table with ok and name_cost properties
function kristly.getNamePrice()
  return basicGET("names/cost")
end

--- Gets the current name bonus. Simply: Amount of names bought in the latest 500 blocks
-- @return a table with ok and name_bonus
function kristly.getCurrentNameBonus()
  return basicGET("names/bonus")
end

--- Check if the supplied krist name is available
-- @param name The krist name
-- @return a table with ok and available properties
function kristly.isNameAvailable(name)
  expect(1, name, "string")

  return basicGET("names/check/" .. name)
end

--- Tries to register a krist name
-- @param name The krist name that should be registered
-- @param privatekey The krist privatekey. This should never be shared.
-- @return a table with a propery named ok. If ok is false it also contains a error property
function kristly.purchaseName(name, privatekey)
  expect(1, name, "string")
  expect(2, privatekey, "string")

  return basicJSONPOST("names/" .. name, "privatekey=" .. privatekey)
end

--- Tries to transfer a name from one krist address to another krist address
-- @param name The krist name that should be transferred
-- @param fromPrivatekey The krist privatekey of the krist address the name will be transferred from
-- @param addressTo The krist address that the name should be transferred to
-- @return A table with ok propery and a name property if ok was true, or else a error property
function kristly.transferName(name, addressTo, fromPrivatekey)
  expect(1, name, "string")
  expect(2, addressTo, "string")
  expect(3, fromPrivatekey, "string")

  return basicJSONPOST("names/" .. name .. "/transfer?name=", "address=" .. addressTo .. "&privatekey=" .. fromPrivatekey)
end

--- Updates the data of a name, also knows as a A record
-- @param name The krist name that should get A record changed
-- @param privatekey The krist private key that ownes the krist name
-- @param newData The new data of the krist private key
-- @return a table with a ok property
function kristly.updateDataOfName(name, privatekey, newData)
  expect(1, name, "string")
  expect(2, privatekey, "string")
  expect(3, newData, "nil", "string")

  newData = newData or "Powered by Kristly"

  return basicJSONPOST("names/" .. name .. "/update", "privatekey=" .. privatekey .. "&newData=" .. newData)
end

----------------------------------------------------------------------------------
--                                TRANSACTIONS                                  --
----------------------------------------------------------------------------------

--- Gets a list of transactions. This is not the latest transctions!
-- @param excludeMined If we should exclude transactions coming from mining
-- @param limit The max amount of transactions to return.
-- @param offset The amount to offset the transaction list. Useful for pagination.
-- @return a table with the following fields: count, total, transactions(tablearray of transactions).
function kristly.listAllTransactions(excludeMined, limit, offset)
  expect(1, excludeMined, "nil", "boolean")
  expect(2, limit, "nil", "number")
  expect(3, offset, "nil", "number")

  excludeMined = excludeMined or true
  limit = limit or 50
  offset = offset or 0

  return basicGET("transactions?excludeMined=" .. excludeMined .. "&limit=" .. limit .. "&offset=" .. offset)
end

--- Gets a list of the latesttransactions.
-- @param excludeMined If we should exclude transactions coming from mining
-- @param limit The max amount of transactions to return.
-- @param offset The amount to offset the transaction list. Useful for pagination.
-- @return a table with the following fields: count, total, transactions(tablearray of transactions).
function kristly.listLatestTransactions(excludeMined, limit, offset)
  expect(1, excludeMined, "nil", "boolean")
  expect(2, limit, "nil", "number")
  expect(3, offset, "nil", "number")

  excludeMined = excludeMined or true
  limit = limit or 50
  offset = offset or 0

  return basicGET("transactions/latest?excludeMined=" .. excludeMined .. "&limit=" .. limit .. "&offset=" .. offset)
end

--- Gets data about a specific transaction.
-- @param transactionID the ID of the transaction.
-- @return A table with one property: transaction
function kristly.getTransaction(transactionID)
  expect(1, transactionID, "number")

  return basicGET("transactions/" .. transactionID)
end

--- Transfer the specified amount from the specified privatekey's address
-- @param privatekey the krist privatekey of the address that the transaction should be from
-- @param to the krist address of the person recieveing the krist
-- @param amount the amount of krist to send
-- @param metadata option parameter that will contain metadata
function kristly.makeTransaction(privatekey, to, amount, metadata)
  expect(1, privatekey, "string")
  expect(2, to, "string")
  expect(3, amount, "number")
  expect(4, metadata, "nil", "string")

  metadata = metadata or "Powered by = Kristify"

  return basicJSONPOST("transactions",
    "privatekey=" .. privatekey .. "&to=" .. to .. "&amount=" .. amount .. "&metadata=" .. metadata)
end

----------------------------------------------------------------------------------
--                                WEBSOCKETS                                    --
----------------------------------------------------------------------------------

--- Generates a krist websocket url.
-- @param privatekey Optional: Privatekey of a wallet
-- @return A url to connect to with websocket
function kristly.generateWSUrl(privatekey)
  expect(1, privatekey, "nil", "string")

  privatekey = privatekey or ""
  return basicJSONPOST("ws/start", privatekey)
end

--- Creates a new Kristly Websocket.
-- @param privatekey Optional: the private key of the connection.
-- @return a kristly ws object. Have fun with it!
function kristly.websocket(privatekey)
  expect(1, privatekey, "nil", "string")

  local url = kristly.generateWSUrl(privatekey)
  local ws = http.websocket(url.url)
  local kws = kristlyWS:new { ws = ws }

  return kws
end

--- Creates a new Kristly websocket object.
-- @param o object with ws object inside.
-- @return a instance of Kristly WS
function kristlyWS:new(o)
  expect(1, o, "nil", "table")

  o = o or {}
  setmetatable(o, self)
  self.__index = self
  return o
end

--- Sends a simple websocket message to the krist server
-- @param type The action you would like to take
-- @param table Optional arguments
-- @return id The ID to listen after
function kristlyWS:simpleWSMessage(type, table)
  expect(1, type, "string")
  expect(2, table, "nil", "table")

  local id = os.clock() * os.getComputerID() * 2.5 + #shell.dir() -- Worlds best way to do it :troll: TODO:  make it more random possibly?

  table = table or {}
  table.id = id
  table.type = type

  self.ws.send(textutils.serialiseJSON(table))

  return id
end

--- Starts listening for events
-- You should run this function with the parallel API
function kristlyWS:start()
  -- Listen for events. If returns nil it is safe to say the ws is closed.
  -- Use os.queueEvent to send information back. Implement on and once later.

  while true do
    local res = self.ws.receive(10)
    local data = textutils.unserializeJSON(res)

    os.queueEvent("kristly", data)
  end
end

--- Downgrades the WS connection.
-- If you have a authed connection this will affectivly log you out.
function kristlyWS:downgradeConnection()
  return self:simpleWSMessage "logout"
end

--- Upgrade the WS connection.
-- This will make a unauthed connection into a authed one
-- @param privateKey The krist private key that you want to login to.
function kristlyWS:upgradeConnection(privateKey)
  expect(1, privateKey, "string")

  return self:simpleWSMessage("login", {
    privatekey = privateKey
  })
end

--- Subscribe to a krist event
-- This will make kristly recieve for example transaction events
-- @param event The event to subscribe to.
function kristlyWS:subscribe(event)
  expect(1, event, "string")

  return self:simpleWSMessage("subscribe", {
    event = event
  })
end

return kristly