diff --git a/automation/fluidity/website/mainnet.yml b/automation/fluidity/website/mainnet.yml
index f5be2dd74..c4ae27dce 100644
--- a/automation/fluidity/website/mainnet.yml
+++ b/automation/fluidity/website/mainnet.yml
@@ -18,6 +18,7 @@ SERVICES:
NEXT_PUBLIC_FLU_SPLIT_BROWSER_KEY: s7ovhvrpv77htn8aqlf2irirnll9ofvr07be
NEXT_PUBLIC_FLU_GTAG_ID: G-EF68MNJRJ7
NEXT_PUBLIC_FLU_GTM_ID: GTM-W7QJGR2
+ NEXT_PUBLIC_FLU_HASURA_URL: https://fluidity.hasura.app/v1/graphql
DOCKER_ARGS:
SECRET_FLU_SENTRY_DSN: /fluidity/frontend/sentryURL
diff --git a/cmd/connector-common-lootboxes-timescale/main.go b/cmd/connector-common-lootboxes-timescale/main.go
index ab05975c4..b7f0d2e10 100644
--- a/cmd/connector-common-lootboxes-timescale/main.go
+++ b/cmd/connector-common-lootboxes-timescale/main.go
@@ -6,7 +6,5 @@ import (
)
func main() {
- queue.LootboxesAll(func(lootbox lootboxes.Lootbox) {
- lootboxes.InsertLootbox(lootbox)
- })
+ queue.LootboxesAll(lootboxes.InsertLootbox)
}
diff --git a/cmd/connector-common-winners-timescale/README.md b/cmd/connector-common-winners-timescale/README.md
index 455a15be3..58683806b 100644
--- a/cmd/connector-common-winners-timescale/README.md
+++ b/cmd/connector-common-winners-timescale/README.md
@@ -1,7 +1,7 @@
# Winners to Timescale connector
-Write winners received via AMQP to Timescale.
+Write winners received via AMQP to Timescale. Also tracks epochs.
## Environment variables
diff --git a/cmd/connector-common-winners-timescale/main.go b/cmd/connector-common-winners-timescale/main.go
index 0e389ab18..cce0f97e1 100644
--- a/cmd/connector-common-winners-timescale/main.go
+++ b/cmd/connector-common-winners-timescale/main.go
@@ -5,17 +5,85 @@
package main
import (
+ "math"
+ "math/big"
+
"github.com/fluidity-money/fluidity-app/lib/databases/postgres/solana"
+ "github.com/fluidity-money/fluidity-app/lib/databases/timescale/lootboxes"
database "github.com/fluidity-money/fluidity-app/lib/databases/timescale/winners"
+ "github.com/fluidity-money/fluidity-app/lib/log"
queue "github.com/fluidity-money/fluidity-app/lib/queues/winners"
+ "github.com/fluidity-money/fluidity-app/lib/types/network"
)
+// lootboxUpdateTrackedRewardAmounts by destructuring the winner, and
+// upserting it into the database. queries the current epoch to get what
+// should be used.
+func lootboxUpdateTrackedRewardAmounts(winner queue.Winner) {
+ var (
+ network_ = winner.Network
+ tokenDetails = winner.TokenDetails
+ application = winner.Application
+ amountWon = &winner.WinningAmount.Int
+ )
+
+ _, lootboxHasBegun, lootboxCurrentEpoch, _ := lootboxes.GetLootboxConfig()
+
+ if !lootboxHasBegun {
+ log.Debug(func(k *log.Log) {
+ k.Message = "Lootbox not running! Ignoring a winner to be inserted in the lootbox tracked rewards!"
+ })
+
+ return
+ }
+
+ var (
+ tokenShortName = tokenDetails.TokenShortName
+ tokenDecimals = tokenDetails.TokenDecimals
+ )
+
+ winnerAddress := ""
+
+ // need to set it to the owner of the ATA if we're on solana!
+
+ switch network_ {
+ case network.NetworkSolana:
+ winnerAddress = winner.SolanaWinnerOwnerAddress
+
+ default:
+ winnerAddress = winner.WinnerAddress
+ }
+
+ // we can normalise this and store it in the database to avoid an
+ // extra check, as we can afford some loss in this calculation.
+
+ decimals := math.Pow10(tokenDecimals)
+
+ amountNormal := new(big.Rat).SetInt(amountWon)
+ amountNormal.Quo(amountNormal, new(big.Rat).SetInt64(int64(decimals)))
+
+ amountNormalFloat, _ := amountNormal.Float64()
+
+ lootboxes.UpdateOrInsertAmountsRewarded(
+ network_,
+ lootboxCurrentEpoch,
+ tokenShortName,
+ amountNormalFloat, // amount normal lossy
+ winnerAddress,
+ application,
+ )
+}
+
func main() {
- go queue.WinnersEthereum(database.InsertWinner)
+ go queue.WinnersEthereum(func(winner queue.Winner) {
+ lootboxUpdateTrackedRewardAmounts(winner)
+ database.InsertWinner(winner)
+ })
queue.WinnersSolana(func(winner queue.Winner) {
winningSignature := solana.GetIntermediateWinner(winner.TransactionHash)
winner.SendTransactionHash = winningSignature
+ lootboxUpdateTrackedRewardAmounts(winner)
database.InsertWinner(winner)
})
}
diff --git a/cmd/microservice-ethereum-create-transaction-lootboxes/main.go b/cmd/microservice-ethereum-create-transaction-lootboxes/main.go
index fb1973511..a523578a7 100644
--- a/cmd/microservice-ethereum-create-transaction-lootboxes/main.go
+++ b/cmd/microservice-ethereum-create-transaction-lootboxes/main.go
@@ -10,29 +10,31 @@ import (
"math/big"
"time"
- "github.com/ethereum/go-ethereum/accounts/abi/bind"
- "github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/ethclient"
- libEthereum "github.com/fluidity-money/fluidity-app/common/ethereum"
- ethereumApps "github.com/fluidity-money/fluidity-app/common/ethereum/applications"
database "github.com/fluidity-money/fluidity-app/lib/databases/timescale/lootboxes"
user_actions "github.com/fluidity-money/fluidity-app/lib/databases/timescale/user-actions"
"github.com/fluidity-money/fluidity-app/lib/log"
"github.com/fluidity-money/fluidity-app/lib/queue"
lootboxes_queue "github.com/fluidity-money/fluidity-app/lib/queues/lootboxes"
winners_queue "github.com/fluidity-money/fluidity-app/lib/queues/winners"
- "github.com/fluidity-money/fluidity-app/lib/types/applications"
"github.com/fluidity-money/fluidity-app/lib/types/ethereum"
"github.com/fluidity-money/fluidity-app/lib/types/lootboxes"
"github.com/fluidity-money/fluidity-app/lib/types/misc"
"github.com/fluidity-money/fluidity-app/lib/types/worker"
"github.com/fluidity-money/fluidity-app/lib/util"
+
+ libEthereum "github.com/fluidity-money/fluidity-app/common/ethereum"
+ "github.com/fluidity-money/fluidity-app/common/ethereum/applications"
+
+ "github.com/ethereum/go-ethereum/accounts/abi/bind"
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/ethclient"
)
const (
// EnvTokensList to relate the received token names to a contract address
// of the form ADDR1:TOKEN1:DECIMALS1,ADDR2:TOKEN2:DECIMALS2,...
EnvTokensList = "FLU_ETHEREUM_TOKENS_LIST"
+
// EnvGethHttpUrl to use when performing RPC requests
EnvGethHttpUrl = `FLU_ETHEREUM_HTTP_URL`
)
@@ -85,6 +87,32 @@ func main() {
tokenShortName = tokenDetails.TokenShortName
)
+ programFound, hasBegun, currentEpoch, _ := database.GetLootboxConfig()
+
+ // check that the lootbox is enabled, and that it's also
+ // running. logs separately if either fail. if the
+ // campaign has begun but isn't in progress, then we
+ // should die! that means that something was processed
+ // weirdly.
+
+ switch false {
+ case programFound:
+ log.App(func(k *log.Log) {
+ k.Message = "No lootbox epoch found, skipping a request to track a winner!"
+ })
+
+ return
+
+ case hasBegun:
+ log.Fatal(func(k *log.Log) {
+ k.Message = "Lootbox epoch that was found is not running! Terminating on request to track a winner!"
+ })
+
+ return
+ }
+
+ log.Debugf("Lootbox current epoch running is %v!", currentEpoch)
+
// don't track fluidification
if winner.RewardType != "send" {
log.Debug(func(k *log.Log) {
@@ -114,7 +142,11 @@ func main() {
// fetch parameters to call GetApplicationFee
// wait for transaction to be mined before fetching receipt
- transaction, isPending, err := ethClient.TransactionByHash(context.Background(), common.HexToHash(transactionHash))
+
+ transaction, isPending, err := ethClient.TransactionByHash(
+ context.Background(),
+ common.HexToHash(transactionHash),
+ )
if err != nil {
log.Fatal(func(k *log.Log) {
@@ -172,7 +204,14 @@ func main() {
inputData := transaction.Data()
- feeData, _, _, err := ethereumApps.GetApplicationFee(applicationTransfer, ethClient, fluidTokenContract, tokenDecimals, receipt, inputData)
+ feeData, _, _, err := applications.GetApplicationFee(
+ applicationTransfer,
+ ethClient,
+ fluidTokenContract,
+ tokenDecimals,
+ receipt,
+ inputData,
+ )
if err != nil {
log.Fatal(func(k *log.Log) {
@@ -288,22 +327,8 @@ func volumeLiquidityMultiplier(volume *big.Rat, tokenDecimals int, address strin
}
func protocolMultiplier(application applications.Application) *big.Rat {
- switch application.String() {
- case "uniswap_v2":
- fallthrough
- case "uniswap_v3":
- fallthrough
- case "saddle":
- fallthrough
- case "curve":
- fallthrough
- case "camelot":
- fallthrough
- case "chronos":
- fallthrough
- case "kyber_classic":
- fallthrough
- case "sushiswap":
+ switch application {
+ case applications.ApplicationJumper, applications.ApplicationUniswapV3, applications.ApplicationTraderJoe, applications.ApplicationCamelot, applications.ApplicationSushiswap, applications.ApplicationRamses:
return big.NewRat(2, 100)
}
diff --git a/cmd/microservice-ethereum-track-winners/main.go b/cmd/microservice-ethereum-track-winners/main.go
index 0bf358ce0..302042be9 100644
--- a/cmd/microservice-ethereum-track-winners/main.go
+++ b/cmd/microservice-ethereum-track-winners/main.go
@@ -11,13 +11,14 @@ import (
"strconv"
"strings"
- "github.com/fluidity-money/fluidity-app/common/ethereum/fluidity"
logging "github.com/fluidity-money/fluidity-app/lib/log"
"github.com/fluidity-money/fluidity-app/lib/queues/ethereum"
"github.com/fluidity-money/fluidity-app/lib/queues/winners"
"github.com/fluidity-money/fluidity-app/lib/types/network"
"github.com/fluidity-money/fluidity-app/lib/types/token-details"
"github.com/fluidity-money/fluidity-app/lib/util"
+
+ "github.com/fluidity-money/fluidity-app/common/ethereum/fluidity"
)
const (
@@ -81,7 +82,6 @@ func main() {
}
ethereum.Logs(func(log ethereum.Log) {
-
var (
logTopics = log.Topics
transactionHash = log.TxHash
diff --git a/cmd/microservice-ethereum-track-winners/processing.go b/cmd/microservice-ethereum-track-winners/processing.go
index 4d2a80158..d976b96af 100644
--- a/cmd/microservice-ethereum-track-winners/processing.go
+++ b/cmd/microservice-ethereum-track-winners/processing.go
@@ -3,7 +3,6 @@ package main
import (
"time"
- "github.com/fluidity-money/fluidity-app/common/ethereum/fluidity"
winnersDb "github.com/fluidity-money/fluidity-app/lib/databases/timescale/winners"
"github.com/fluidity-money/fluidity-app/lib/log"
"github.com/fluidity-money/fluidity-app/lib/queue"
@@ -12,17 +11,19 @@ import (
"github.com/fluidity-money/fluidity-app/lib/types/network"
token_details "github.com/fluidity-money/fluidity-app/lib/types/token-details"
"github.com/fluidity-money/fluidity-app/lib/types/winners"
+
+ "github.com/fluidity-money/fluidity-app/common/ethereum/fluidity"
)
func processReward(contractAddress ethereum.Address, transactionHash ethereum.Hash, data fluidity.RewardData, tokenDetails token_details.TokenDetails, network network.BlockchainNetwork) {
var (
- winnerString = data.Winner.String()
- winnerAddress = ethereum.AddressFromString(winnerString)
- startBlock = *data.StartBlock
- endBlock = *data.EndBlock
+ winnerString = data.Winner.String()
+ startBlock = *data.StartBlock
+ endBlock = *data.EndBlock
+ blocked = data.Blocked
)
- blocked := data.Blocked
+ winnerAddress := ethereum.AddressFromString(winnerString)
if blocked {
blockedWinner := convertBlockedWinner(
@@ -61,8 +62,9 @@ func processReward(contractAddress ethereum.Address, transactionHash ethereum.Ha
}
func processUnblockedReward(transactionHash ethereum.Hash, data fluidity.UnblockedRewardData, tokenDetails token_details.TokenDetails, network network.BlockchainNetwork) {
+ rewardData := data.RewardData
+
var (
- rewardData = data.RewardData
winnerString = rewardData.Winner.String()
startBlock = *rewardData.StartBlock
endBlock = *rewardData.EndBlock
diff --git a/cmd/microservice-lootbox-referral-activator/main.go b/cmd/microservice-lootbox-referral-activator/main.go
index a065abc4b..5b0c5dd28 100644
--- a/cmd/microservice-lootbox-referral-activator/main.go
+++ b/cmd/microservice-lootbox-referral-activator/main.go
@@ -26,9 +26,7 @@ const (
)
func main() {
- var (
- lootboxReferralAmount_ = util.GetEnvOrFatal(EnvLootboxReferralAmount)
- )
+ lootboxReferralAmount_ := util.GetEnvOrFatal(EnvLootboxReferralAmount)
lootboxReferralAmount, err := strconv.ParseUint(lootboxReferralAmount_, 10, 64)
@@ -45,6 +43,7 @@ func main() {
transactionHash = lootbox.TransactionHash
address = lootbox.Address
lootboxCount = lootbox.LootboxCount
+ epoch = lootbox.Epoch
)
// don't track non-transaction lootboxes
@@ -102,6 +101,7 @@ func main() {
RewardTier: 1,
LootboxCount: 5,
Application: applications.ApplicationNone,
+ Epoch: epoch,
}
queue.SendMessage(lootboxes_queue.TopicLootboxes, referralLootbox)
diff --git a/cmd/microservice-lootbox-referral-distributor/main.go b/cmd/microservice-lootbox-referral-distributor/main.go
index d960725a3..80abdecd8 100644
--- a/cmd/microservice-lootbox-referral-distributor/main.go
+++ b/cmd/microservice-lootbox-referral-distributor/main.go
@@ -5,7 +5,6 @@
package main
import (
- "github.com/fluidity-money/fluidity-app/common/ethereum/applications"
"github.com/fluidity-money/fluidity-app/lib/databases/timescale/referrals"
"github.com/fluidity-money/fluidity-app/lib/log"
"github.com/fluidity-money/fluidity-app/lib/queue"
@@ -13,6 +12,8 @@ import (
"github.com/fluidity-money/fluidity-app/lib/types/ethereum"
"github.com/fluidity-money/fluidity-app/lib/types/lootboxes"
"github.com/fluidity-money/fluidity-app/lib/types/misc"
+
+ "github.com/fluidity-money/fluidity-app/common/ethereum/applications"
)
func main() {
@@ -23,6 +24,7 @@ func main() {
address = lootbox.Address
lootboxCount = lootbox.LootboxCount
awardedTime = lootbox.AwardedTime
+ epoch = lootbox.Epoch
)
// don't track non-transaction lootboxes
@@ -62,9 +64,10 @@ func main() {
RewardTier: 1,
LootboxCount: referralLootboxCount,
Application: applications.ApplicationNone,
+ Epoch: epoch,
}
- go queue.SendMessage(lootboxes_queue.TopicLootboxes, referralLootbox)
+ queue.SendMessage(lootboxes_queue.TopicLootboxes, referralLootbox)
}
})
}
diff --git a/cmd/microservice-lootbox-reward-top-winners/main.go b/cmd/microservice-lootbox-reward-top-winners/main.go
index 12119feeb..eabe0fa9d 100644
--- a/cmd/microservice-lootbox-reward-top-winners/main.go
+++ b/cmd/microservice-lootbox-reward-top-winners/main.go
@@ -32,8 +32,48 @@ func main() {
// endTime is the beginning of the day after startTime (the start of the current date)
endTime := currentTime
- // fetch and log the top 10 users
- topUsers := lootboxes.GetTopApplicationUsersByLootboxCount(startTime, endTime, applications.ApplicationKyberClassic)
+ programFound, hasBegun, currentEpoch, currentApplication := lootboxes.GetLootboxConfig()
+
+ // if the lootbox isn't enabled, or it isn't running, then we skip. we
+ // treat the cases separately for logging reasons.
+
+ switch false {
+ case programFound:
+ log.App(func(k *log.Log) {
+ k.Message = "No lootbox epoch found! Skipping running."
+ })
+
+ return
+
+ case hasBegun:
+ log.App(func(k *log.Log) {
+ k.Message = "Current lootbox epoch has not yet started! Skipping running."
+ })
+
+ return
+ }
+
+ var topUsers []lootboxes.UserLootboxCount
+
+ // if there's a current application focus, then we want to reward only specific winners
+
+ switch currentApplication {
+ case applications.ApplicationNone:
+ topUsers = lootboxes.GetTopUsersByLootboxCount(
+ currentEpoch,
+ startTime,
+ endTime,
+ )
+ default:
+ // fetch and log the top 10 users for a specific application
+ topUsers = lootboxes.GetTopApplicationUsersByLootboxCount(
+ currentEpoch,
+ startTime,
+ endTime,
+ currentApplication,
+ )
+ }
+
for i, user := range topUsers {
log.App(func(k *log.Log) {
k.Format(
@@ -47,5 +87,5 @@ func main() {
}
// reward the top 10 users
- lootboxes.InsertTopUserReward(startTime, topUsers)
+ lootboxes.InsertTopUserReward(currentEpoch, startTime, topUsers)
}
diff --git a/cmd/microservice-redeem-testnet-lootboxes/README.md b/cmd/microservice-redeem-testnet-lootboxes/README.md
index 988ac37b6..8c9a2f45b 100644
--- a/cmd/microservice-redeem-testnet-lootboxes/README.md
+++ b/cmd/microservice-redeem-testnet-lootboxes/README.md
@@ -1,7 +1,11 @@
# microservice-redeem-testnet-lootboxes
-Watch for events indicating ownership of a testnet address and reward the owner.
+Watch for events indicating ownership of a testnet address and reward
+the owner.
+
+If an epoch is not currently running, then this should break as
+someone is using the contract improperly.
## Environment variables
diff --git a/cmd/microservice-redeem-testnet-lootboxes/main.go b/cmd/microservice-redeem-testnet-lootboxes/main.go
index 9ddf11e58..90ed02578 100644
--- a/cmd/microservice-redeem-testnet-lootboxes/main.go
+++ b/cmd/microservice-redeem-testnet-lootboxes/main.go
@@ -34,6 +34,27 @@ func main() {
)
logs.Logs(func(l logs.Log) {
+ programFound, hasBegun, currentEpoch, _ := lootboxes.GetLootboxConfig()
+
+ // if the lootbox isn't enabled, or it isn't running, then we alarm
+ // because someone has called the contract to manually reward themselves
+ // whem presumably the UI isn't enabled. treated separately for logging
+ // reasons.
+
+ switch false {
+ case programFound:
+ log.Fatal(func(k *log.Log) {
+ k.Message = "No lootbox program found, but a log was received for a testnet redemption!"
+ })
+
+ case hasBegun:
+ log.Fatal(func(k *log.Log) {
+ k.Message = "Lootbox program that was found is not running!"
+ })
+ }
+
+ log.Debugf("Lootbox current epoch running is %v!", currentEpoch)
+
if l.Address != addressConfirmerContractAddress {
log.Debug(func(k *log.Log) {
k.Format(
@@ -98,6 +119,7 @@ func main() {
AwardedTime: currentTime,
LootboxCount: LootboxCountCommon,
RewardTier: 1,
+ Epoch: currentEpoch,
},
{
Address: testnetOwnerString,
@@ -105,6 +127,7 @@ func main() {
AwardedTime: currentTime,
LootboxCount: LootboxCountUncommon,
RewardTier: 2,
+ Epoch: currentEpoch,
},
{
Address: testnetOwnerString,
@@ -112,6 +135,7 @@ func main() {
AwardedTime: currentTime,
LootboxCount: LootboxCountRare,
RewardTier: 3,
+ Epoch: currentEpoch,
},
{
Address: testnetOwnerString,
@@ -119,6 +143,7 @@ func main() {
AwardedTime: currentTime,
LootboxCount: LootboxCountUltraRare,
RewardTier: 4,
+ Epoch: currentEpoch,
},
}
diff --git a/common/ethereum/applications/applications.go b/common/ethereum/applications/applications.go
index fac0e3ec9..eaf96096e 100644
--- a/common/ethereum/applications/applications.go
+++ b/common/ethereum/applications/applications.go
@@ -39,6 +39,8 @@ import (
"github.com/ethereum/go-ethereum/ethclient"
)
+type Application = libApps.Application
+
const (
// ApplicationNone is the nil value representing a transfer.
ApplicationNone libApps.Application = iota
@@ -64,8 +66,15 @@ const (
ApplicationWombat
ApplicationSeawaterAmm
ApplicationTraderJoe
+ ApplicationRamses
+ ApplicationJumper
)
+// ParseApplicationName shadows the lib types definition
+func ParseApplicationName(name string) (Application, error) {
+ return libApps.ParseApplicationName(name)
+}
+
// GetApplicationFee to find the fee (in USD) paid by a user for the application interaction
// returns (feeData wiht Fee set to nil, ni) in the case where the application event is legitimate, but doesn't involve
// the fluid asset we're tracking, e.g. in a multi-token pool where two other tokens are swapped
@@ -383,7 +392,6 @@ func GetApplicationTransferParties(transaction ethereum.Transaction, transfer wo
// Gave the majority payout to the swap-maker (i.e. transaction sender)
// and rest to pool
return transaction.From, logAddress, nil
-
default:
return nilAddress, nilAddress, fmt.Errorf(
"Transfer #%v did not contain an application",
diff --git a/common/ethereum/applications/jumper/init.go b/common/ethereum/applications/jumper/init.go
new file mode 100644
index 000000000..872132a0c
--- /dev/null
+++ b/common/ethereum/applications/jumper/init.go
@@ -0,0 +1,7 @@
+// Copyright 2022 Fluidity Money. All rights reserved. Use of this
+// source code is governed by a GPL-style license that can be found in the
+// LICENSE.md file.
+
+package jumper
+
+func init() {}
diff --git a/database/102-up-timescale/20230323164105-airdrop_leaderboard.sql b/database/102-up-timescale/20230323164105-airdrop_leaderboard.sql
index fcf1e86ce..750fa4f29 100644
--- a/database/102-up-timescale/20230323164105-airdrop_leaderboard.sql
+++ b/database/102-up-timescale/20230323164105-airdrop_leaderboard.sql
@@ -14,18 +14,18 @@ LANGUAGE SQL
STABLE
AS
$$
-SELECT
+SELECT
address,
-- placeholder
ROW_NUMBER() OVER () AS rank,
- COUNT(DISTINCT referee) AS referral_count,
- SUM(lootbox_count) AS total_lootboxes,
- MAX(reward_tier) AS highest_reward_tier,
- COALESCE(liquidity.result, 1) AS liquidity_multiplier
-FROM lootbox
- LEFT JOIN lootbox_referrals
- ON lootbox.address = lootbox_referrals.referrer,
- LATERAL calculate_a_y(address, now()::TIMESTAMP) AS liquidity
+ COUNT(DISTINCT referee) AS referral_count,
+ SUM(lootbox_count) AS total_lootboxes,
+ MAX(reward_tier) AS highest_reward_tier,
+ COALESCE(liquidity.result, 1) AS liquidity_multiplier
+FROM lootbox
+ LEFT JOIN lootbox_referrals
+ ON lootbox.address = lootbox_referrals.referrer,
+ LATERAL calculate_a_y(address, now()::TIMESTAMP) AS liquidity
GROUP BY address, liquidity_multiplier
$$;
diff --git a/database/102-up-timescale/20230613063527_airdrop_leaderboard_add_24_hrs_application.sql b/database/102-up-timescale/20230613063527_airdrop_leaderboard_add_24_hrs_application.sql
index c9ed1a47a..c1c77eae7 100644
--- a/database/102-up-timescale/20230613063527_airdrop_leaderboard_add_24_hrs_application.sql
+++ b/database/102-up-timescale/20230613063527_airdrop_leaderboard_add_24_hrs_application.sql
@@ -5,25 +5,25 @@ LANGUAGE SQL
STABLE
AS
$$
-SELECT
+SELECT
address,
-- placeholder
ROW_NUMBER() OVER () AS rank,
- COUNT(DISTINCT referee) AS referral_count,
- lb_24_application.total_box_count,
+ COUNT(DISTINCT referee) AS referral_count,
+ lb_24_application.total_box_count,
lb_24_application.highest_reward_tier,
- COALESCE(liquidity.result, 1) AS liquidity_multiplier
+ COALESCE(liquidity.result, 1) AS liquidity_multiplier
FROM (
-- subquery to avoid re-summing lootbox_count for every referee
SELECT address, SUM(lootbox_count) as total_box_count, MAX(reward_tier) as highest_reward_tier
- FROM lootbox
+ FROM lootbox
WHERE awarded_time > now() - interval '1 day'
- AND application = application_
+ AND application = application_
GROUP BY address
) lb_24_application
- LEFT JOIN lootbox_referrals
- ON lb_24_application.address = lootbox_referrals.referrer,
- LATERAL calculate_a_y(address, now()::TIMESTAMP) AS liquidity
+ LEFT JOIN lootbox_referrals
+ ON lb_24_application.address = lootbox_referrals.referrer,
+ LATERAL calculate_a_y(address, now()::TIMESTAMP) AS liquidity
GROUP BY address, liquidity_multiplier, total_box_count, highest_reward_tier
$$;
diff --git a/database/102-up-timescale/20231219091930-lootbox_add_epoch.sql b/database/102-up-timescale/20231219091930-lootbox_add_epoch.sql
new file mode 100644
index 000000000..ba3523d0c
--- /dev/null
+++ b/database/102-up-timescale/20231219091930-lootbox_add_epoch.sql
@@ -0,0 +1,102 @@
+
+-- migrate:up
+
+CREATE TYPE lootbox_epoch AS ENUM (
+ 'epoch_1',
+ 'epoch_2',
+ 'epoch_testing'
+);
+
+ALTER TABLE lootbox
+ ADD COLUMN epoch lootbox_epoch NOT NULL DEFAULT 'epoch_1';
+
+ALTER TABLE lootbox_referral_codes
+ ADD COLUMN epoch lootbox_epoch NOT NULL DEFAULT 'epoch_1';
+
+ALTER TABLE lootbox_referrals
+ ADD COLUMN epoch lootbox_epoch NOT NULL DEFAULT 'epoch_1';
+
+DROP FUNCTION lootbox_referral_lootbottle_counts;
+
+CREATE FUNCTION lootbox_referral_lootbottle_counts(epoch_ lootbox_epoch)
+RETURNS SETOF lootbox_counts_return
+LANGUAGE SQL
+STABLE
+AS
+$$
+SELECT
+ address,
+ COALESCE(tier1, 0),
+ COALESCE(tier2, 0),
+ COALESCE(tier3, 0),
+ COALESCE(tier4, 0),
+ COALESCE(tier5, 0)
+FROM crosstab(
+ format(
+ 'SELECT
+ address,
+ reward_tier,
+ SUM(lootbox_count)
+ FROM lootbox
+ WHERE source=''referral'' AND epoch = %s
+ GROUP BY
+ address,
+ reward_tier
+ ORDER BY 1',
+ quote_literal(epoch_)
+ ),
+ 'VALUES (1),(2),(3),(4),(5)'
+) AS ct(
+ address VARCHAR,
+ tier1 NUMERIC,
+ tier2 NUMERIC,
+ tier3 NUMERIC,
+ tier4 NUMERIC,
+ tier5 NUMERIC
+);
+$$;
+
+-- migrate:down
+
+ALTER TABLE lootbox DROP COLUMN epoch;
+
+ALTER TABLE lootbox_referral_codes DROP COLUMN epoch;
+
+ALTER TABLE lootbox_referrals DROP COLUMN epoch;
+
+DROP FUNCTION lootbox_referral_lootbottle_counts;
+
+CREATE FUNCTION lootbox_referral_lootbottle_counts()
+RETURNS SETOF lootbox_counts_return
+LANGUAGE SQL
+STABLE
+AS
+$$
+SELECT
+ address,
+ COALESCE(tier1, 0),
+ COALESCE(tier2, 0),
+ COALESCE(tier3, 0),
+ COALESCE(tier4, 0),
+ COALESCE(tier5, 0)
+FROM crosstab(
+ 'SELECT
+ address,
+ reward_tier,
+ SUM(lootbox_count)
+ FROM lootbox
+ WHERE source=''referral''
+ GROUP BY
+ address,
+ reward_tier
+ ORDER BY 1',
+ 'VALUES (1),(2),(3),(4),(5)'
+) AS ct(
+ address VARCHAR,
+ tier1 NUMERIC,
+ tier2 NUMERIC,
+ tier3 NUMERIC,
+ tier4 NUMERIC,
+ tier5 NUMERIC
+);
+$$;
diff --git a/database/102-up-timescale/20231219094456-lootbox_config_add_prev_epoch.sql b/database/102-up-timescale/20231219094456-lootbox_config_add_prev_epoch.sql
new file mode 100644
index 000000000..fa75fd5a6
--- /dev/null
+++ b/database/102-up-timescale/20231219094456-lootbox_config_add_prev_epoch.sql
@@ -0,0 +1,39 @@
+
+-- migrate:up
+
+CREATE TABLE lootbox_config (
+ -- is_current_program if enabled, it's assumed that this is
+ -- the current epoch routine, and config is derived from this
+ is_current_program BOOLEAN NOT NULL DEFAULT FALSE,
+
+ -- program_begin_date to begin counting lootbottles from
+ -- this date onwards, in UTC
+ program_begin TIMESTAMP WITHOUT TIME ZONE NOT NULL,
+
+ -- program_end to use as the final date for the epoch, and
+ -- when to stop counting (also in UTC)
+ program_end TIMESTAMP WITHOUT TIME ZONE NOT NULL,
+
+ -- epoch_identifier to use as the identifier for the epoch with
+ -- the enum
+ epoch_identifier lootbox_epoch NOT NULL UNIQUE,
+
+ -- ethereum_application that should be the current focus of the lootbox
+ -- mini leaderboard competitions (and should be displayed in the UI
+ -- with the right query)
+ ethereum_application ethereum_application NOT NULL DEFAULT 'none'
+);
+
+INSERT INTO lootbox_config (
+ program_begin,
+ program_end,
+ epoch_identifier
+) VALUES (
+ '2023-05-01 12:00:00+02',
+ '2023-06-28 12:00:00+02',
+ 'epoch_1'
+);
+
+-- migrate:down
+
+DROP TABLE lootbox_config;
diff --git a/database/102-up-timescale/20231228172908-lootbox_amounts_earned_create.sql b/database/102-up-timescale/20231228172908-lootbox_amounts_earned_create.sql
new file mode 100644
index 000000000..839cf1e2a
--- /dev/null
+++ b/database/102-up-timescale/20231228172908-lootbox_amounts_earned_create.sql
@@ -0,0 +1,34 @@
+-- migrate:up
+
+-- lootbox_amounts_rewarded is an accumulation table that increases
+-- itself over time on a per-epoch basis. it does so so we can track
+-- cleanly in the UI the amounts earned for the lootbox presentation
+
+-- the winner field is converted from the solana winner owner
+-- address implicitly in the go code currently!
+
+-- we're okay with DECIMAL as we can store the floating amount with a
+-- level of loss since this is user-facing.
+
+CREATE TABLE lootbox_amounts_rewarded (
+ network network_blockchain NOT NULL,
+ epoch lootbox_epoch NOT NULL,
+ token_short_name VARCHAR NOT NULL,
+
+ -- the amount earned, normalised according to the underlying
+ -- decimals. can be lossy
+ amount_earned NUMERIC NOT NULL,
+
+ -- winner of the winning (the recipient of the winning payout)
+ winner VARCHAR NOT NULL,
+
+ application VARCHAR NOT NULL,
+ last_updated TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
+
+ -- id to prevent duplication during the upsert for updating amounts
+ CONSTRAINT id PRIMARY KEY(network, epoch, token_short_name, winner, application)
+);
+
+-- migrate:down
+
+DROP TABLE lootbox_amounts_rewarded;
diff --git a/database/102-up-timescale/20240102213320-airdrop_leaderboard_remove_chronos.sql b/database/102-up-timescale/20240102213320-airdrop_leaderboard_remove_chronos.sql
new file mode 100644
index 000000000..c74f30ea6
--- /dev/null
+++ b/database/102-up-timescale/20240102213320-airdrop_leaderboard_remove_chronos.sql
@@ -0,0 +1,31 @@
+-- migrate:up
+DROP FUNCTION airdrop_leaderboard_24_hours_chronos;
+
+-- migrate:down
+CREATE OR REPLACE FUNCTION airdrop_leaderboard_24_hours_chronos()
+RETURNS SETOF airdrop_leaderboard_return
+LANGUAGE SQL
+STABLE
+AS
+$$
+SELECT
+ address,
+ -- placeholder
+ ROW_NUMBER() OVER () AS rank,
+ COUNT(DISTINCT referee) AS referral_count,
+ lb_24_chronos.total_box_count,
+ lb_24_chronos.highest_reward_tier,
+ COALESCE(liquidity.result, 1) AS liquidity_multiplier
+FROM (
+ -- subquery to avoid re-summing lootbox_count for every referee
+ SELECT address, SUM(lootbox_count) as total_box_count, MAX(reward_tier) as highest_reward_tier
+ FROM lootbox
+ WHERE awarded_time > now() - interval '1 day'
+ AND application = 'chronos'
+ GROUP BY address
+) lb_24_chronos
+ LEFT JOIN lootbox_referrals
+ ON lb_24_chronos.address = lootbox_referrals.referrer,
+ LATERAL calculate_a_y(address, now()::TIMESTAMP) AS liquidity
+GROUP BY address, liquidity_multiplier, total_box_count, highest_reward_tier
+$$;
\ No newline at end of file
diff --git a/database/102-up-timescale/20240102213501-airdrop_leaderboard_24_hours_add_epoch_and_arb_fusdc.sql b/database/102-up-timescale/20240102213501-airdrop_leaderboard_24_hours_add_epoch_and_arb_fusdc.sql
new file mode 100644
index 000000000..6f8286e07
--- /dev/null
+++ b/database/102-up-timescale/20240102213501-airdrop_leaderboard_24_hours_add_epoch_and_arb_fusdc.sql
@@ -0,0 +1,89 @@
+-- migrate:up
+
+-- doesn't take the underlying network into account!
+
+DROP FUNCTION airdrop_leaderboard_24_hours;
+
+ALTER TABLE airdrop_leaderboard_return
+ ADD COLUMN fusdc_earned NUMERIC NOT NULL,
+ ADD COLUMN arb_earned NUMERIC NOT NULL;
+
+CREATE FUNCTION airdrop_leaderboard_24_hours(epoch_ lootbox_epoch)
+RETURNS SETOF airdrop_leaderboard_return
+LANGUAGE SQL
+STABLE
+AS
+$$
+SELECT
+ address,
+ -- placeholder
+ ROW_NUMBER() OVER () AS rank,
+ COUNT(DISTINCT referee) AS referral_count,
+ lb.total_box_count,
+ lb.highest_reward_tier,
+ COALESCE(liquidity.result, 1) AS liquidity_multiplier,
+ COALESCE(lootbox_amounts_rewarded_fusdc.amount_earned, 0),
+ COALESCE(lootbox_amounts_rewarded_arb.amount_earned, 0)
+FROM (
+ -- subquery to avoid re-summing lootbox_count for every referee
+ SELECT address, SUM(lootbox_count) as total_box_count, MAX(reward_tier) as highest_reward_tier
+ FROM lootbox
+ WHERE awarded_time > now() - interval '1 day' AND epoch = epoch_
+ GROUP BY address
+) lb
+ LEFT JOIN (
+ SELECT amount_earned, winner
+ FROM lootbox_amounts_rewarded
+ WHERE token_short_name = 'USDC'
+ ) AS lootbox_amounts_rewarded_fusdc ON lb.address = lootbox_amounts_rewarded_fusdc.winner
+ LEFT JOIN (
+ SELECT amount_earned, winner
+ FROM lootbox_amounts_rewarded
+ WHERE token_short_name = 'ARB'
+ ) AS lootbox_amounts_rewarded_arb ON lb.address = lootbox_amounts_rewarded_arb.winner
+ LEFT JOIN lootbox_referrals
+ ON lb.address = lootbox_referrals.referrer,
+ LATERAL calculate_a_y(address, now()::TIMESTAMP) AS liquidity
+GROUP BY
+ address,
+ liquidity_multiplier,
+ total_box_count,
+ highest_reward_tier,
+ lootbox_amounts_rewarded_fusdc.amount_earned,
+ lootbox_amounts_rewarded_arb.amount_earned
+$$;
+
+-- migrate:down
+
+DROP FUNCTION airdrop_leaderboard_24_hours;
+
+ALTER TABLE airdrop_leaderboard_return
+ DROP COLUMN fusdc_earned,
+ DROP COLUMN arb_earned;
+
+CREATE OR REPLACE FUNCTION airdrop_leaderboard_24_hours()
+RETURNS SETOF airdrop_leaderboard_return
+LANGUAGE SQL
+STABLE
+AS
+$$
+SELECT
+ address,
+ -- placeholder
+ ROW_NUMBER() OVER () AS rank,
+ COUNT(DISTINCT referee) AS referral_count,
+ lb.total_box_count,
+ lb.highest_reward_tier,
+ COALESCE(liquidity.result, 1) AS liquidity_multiplier
+FROM (
+ -- subquery to avoid re-summing lootbox_count for every referee
+ SELECT address, SUM(lootbox_count) as total_box_count, MAX(reward_tier) as highest_reward_tier
+ FROM lootbox
+ WHERE awarded_time > now() - interval '1 day'
+ GROUP BY address
+) lb
+ LEFT JOIN lootbox_referrals
+ ON lb.address = lootbox_referrals.referrer,
+ LATERAL calculate_a_y(address, now()::TIMESTAMP) AS liquidity
+GROUP BY address, liquidity_multiplier, total_box_count, highest_reward_tier
+$$;
diff --git a/database/102-up-timescale/20240103103945-airdrop_leaderboard_add_epoch_and_arb_fusdc.sql b/database/102-up-timescale/20240103103945-airdrop_leaderboard_add_epoch_and_arb_fusdc.sql
new file mode 100644
index 000000000..0da4d791a
--- /dev/null
+++ b/database/102-up-timescale/20240103103945-airdrop_leaderboard_add_epoch_and_arb_fusdc.sql
@@ -0,0 +1,79 @@
+-- migrate:up
+
+DROP FUNCTION airdrop_leaderboard_24_hours_by_application;
+
+CREATE FUNCTION airdrop_leaderboard_24_hours_by_application(epoch_ lootbox_epoch, application_ ethereum_application)
+RETURNS SETOF airdrop_leaderboard_return
+LANGUAGE SQL
+STABLE
+AS
+$$
+SELECT
+ address,
+ -- placeholder
+ ROW_NUMBER() OVER () AS rank,
+ COUNT(DISTINCT referee) AS referral_count,
+ lb_24_application.total_box_count,
+ lb_24_application.highest_reward_tier,
+ COALESCE(liquidity.result, 1) AS liquidity_multiplier,
+ COALESCE(lootbox_amounts_rewarded_fusdc.amount_earned, 0),
+ COALESCE(lootbox_amounts_rewarded_arb.amount_earned, 0)
+FROM (
+ -- subquery to avoid re-summing lootbox_count for every referee
+ SELECT address, SUM(lootbox_count) as total_box_count, MAX(reward_tier) as highest_reward_tier
+ FROM lootbox
+ WHERE awarded_time > now() - interval '1 day' AND epoch = epoch_
+ AND application = application_
+ GROUP BY address
+) lb_24_application
+ LEFT JOIN (
+ SELECT amount_earned, winner
+ FROM lootbox_amounts_rewarded
+ WHERE token_short_name = 'USDC'
+ ) AS lootbox_amounts_rewarded_fusdc ON lb_24_application.address = lootbox_amounts_rewarded_fusdc.winner
+ LEFT JOIN (
+ SELECT amount_earned, winner
+ FROM lootbox_amounts_rewarded
+ WHERE token_short_name = 'ARB'
+ ) AS lootbox_amounts_rewarded_arb ON lb_24_application.address = lootbox_amounts_rewarded_arb.winner
+ LEFT JOIN lootbox_referrals
+ ON lb_24_application.address = lootbox_referrals.referrer,
+ LATERAL calculate_a_y(address, now()::TIMESTAMP) AS liquidity
+GROUP BY
+ address,
+ liquidity_multiplier,
+ total_box_count,
+ highest_reward_tier,
+ lootbox_amounts_rewarded_fusdc.amount_earned,
+ lootbox_amounts_rewarded_arb.amount_earned
+$$;
+
+-- migrate:down
+
+CREATE OR REPLACE FUNCTION airdrop_leaderboard_24_hours_by_application(application_ ethereum_application)
+RETURNS SETOF airdrop_leaderboard_return
+LANGUAGE SQL
+STABLE
+AS
+$$
+SELECT
+ address,
+ -- placeholder
+ ROW_NUMBER() OVER () AS rank,
+ COUNT(DISTINCT referee) AS referral_count,
+ lb_24_application.total_box_count,
+ lb_24_application.highest_reward_tier,
+ COALESCE(liquidity.result, 1) AS liquidity_multiplier
+FROM (
+ -- subquery to avoid re-summing lootbox_count for every referee
+ SELECT address, SUM(lootbox_count) as total_box_count, MAX(reward_tier) as highest_reward_tier
+ FROM lootbox
+ WHERE awarded_time > now() - interval '1 day'
+ AND application = application_
+ GROUP BY address
+) lb_24_application
+ LEFT JOIN lootbox_referrals
+ ON lb_24_application.address = lootbox_referrals.referrer,
+ LATERAL calculate_a_y(address, now()::TIMESTAMP) AS liquidity
+GROUP BY address, liquidity_multiplier, total_box_count, highest_reward_tier
+$$;
\ No newline at end of file
diff --git a/database/102-up-timescale/20240104203505-lootbox_counts_add_epoch.sql b/database/102-up-timescale/20240104203505-lootbox_counts_add_epoch.sql
new file mode 100644
index 000000000..2d68b232c
--- /dev/null
+++ b/database/102-up-timescale/20240104203505-lootbox_counts_add_epoch.sql
@@ -0,0 +1,81 @@
+--migrate:up
+
+DROP FUNCTION lootbox_counts;
+
+-- epoch should be sanitised as an argument here
+
+CREATE FUNCTION lootbox_counts(epoch_ lootbox_epoch)
+RETURNS SETOF lootbox_counts_return
+LANGUAGE SQL
+STABLE
+AS
+$$
+SELECT
+ address,
+ COALESCE(tier1, 0),
+ COALESCE(tier2, 0),
+ COALESCE(tier3, 0),
+ COALESCE(tier4, 0),
+ COALESCE(tier5, 0)
+FROM crosstab(
+ format(
+ 'SELECT
+ address,
+ reward_tier,
+ SUM(lootbox_count)
+ FROM lootbox
+ WHERE epoch = %s
+ GROUP BY
+ address,
+ reward_tier
+ ORDER BY 1',
+ quote_literal(epoch_)
+ ),
+ 'VALUES (1),(2),(3),(4),(5)'
+) AS ct(
+ address VARCHAR,
+ tier1 NUMERIC,
+ tier2 NUMERIC,
+ tier3 NUMERIC,
+ tier4 NUMERIC,
+ tier5 NUMERIC
+);
+$$;
+
+--migrate:down
+
+DROP FUNCTION lootbox_counts;
+
+CREATE FUNCTION lootbox_counts()
+RETURNS SETOF lootbox_counts_return
+LANGUAGE SQL
+STABLE
+AS
+$$
+SELECT
+ address,
+ COALESCE(tier1, 0),
+ COALESCE(tier2, 0),
+ COALESCE(tier3, 0),
+ COALESCE(tier4, 0),
+ COALESCE(tier5, 0)
+FROM crosstab(
+ 'SELECT
+ address,
+ reward_tier,
+ SUM(lootbox_count)
+ FROM lootbox
+ GROUP BY
+ address,
+ reward_tier
+ ORDER BY 1',
+ 'VALUES (1),(2),(3),(4),(5)'
+) AS ct(
+ address VARCHAR,
+ tier1 NUMERIC,
+ tier2 NUMERIC,
+ tier3 NUMERIC,
+ tier4 NUMERIC,
+ tier5 NUMERIC
+);
+$$;
diff --git a/database/102-up-timescale/20240105003308-airdrop_leaderboard_add_epoch.sql b/database/102-up-timescale/20240105003308-airdrop_leaderboard_add_epoch.sql
new file mode 100644
index 000000000..2b1e21463
--- /dev/null
+++ b/database/102-up-timescale/20240105003308-airdrop_leaderboard_add_epoch.sql
@@ -0,0 +1,72 @@
+-- migrate:up
+
+DROP FUNCTION airdrop_leaderboard;
+
+CREATE FUNCTION airdrop_leaderboard(epoch_ lootbox_epoch)
+RETURNS SETOF airdrop_leaderboard_return
+LANGUAGE SQL
+STABLE
+AS
+$$
+SELECT
+ address,
+ -- placeholder
+ ROW_NUMBER() OVER () AS rank,
+ COUNT(DISTINCT referee) AS referral_count,
+ lb.total_box_count,
+ lb.highest_reward_tier,
+ COALESCE(liquidity.result, 1) AS liquidity_multiplier,
+ COALESCE(lootbox_amounts_rewarded_fusdc.amount_earned, 0),
+ COALESCE(lootbox_amounts_rewarded_arb.amount_earned, 0)
+FROM (
+ -- subquery to avoid re-summing lootbox_count for every referee
+ SELECT address, SUM(lootbox_count) as total_box_count, MAX(reward_tier) as highest_reward_tier
+ FROM lootbox
+ WHERE epoch = epoch_
+ GROUP BY address
+) lb
+ LEFT JOIN (
+ SELECT amount_earned, winner
+ FROM lootbox_amounts_rewarded
+ WHERE token_short_name = 'USDC'
+ ) AS lootbox_amounts_rewarded_fusdc ON lb.address = lootbox_amounts_rewarded_fusdc.winner
+ LEFT JOIN (
+ SELECT amount_earned, winner
+ FROM lootbox_amounts_rewarded
+ WHERE token_short_name = 'ARB'
+ ) AS lootbox_amounts_rewarded_arb ON lb.address = lootbox_amounts_rewarded_arb.winner
+ LEFT JOIN lootbox_referrals
+ ON lb.address = lootbox_referrals.referrer,
+ LATERAL calculate_a_y(address, now()::TIMESTAMP) AS liquidity
+GROUP BY address, liquidity_multiplier, total_box_count, highest_reward_tier, lootbox_amounts_rewarded_fusdc.amount_earned, lootbox_amounts_rewarded_arb.amount_earned
+$$;
+
+-- migrate:down
+
+DROP FUNCTION airdrop_leaderboard;
+
+CREATE FUNCTION airdrop_leaderboard()
+RETURNS SETOF airdrop_leaderboard_return
+LANGUAGE SQL
+STABLE
+AS
+$$
+SELECT
+ address,
+ -- placeholder
+ ROW_NUMBER() OVER () AS rank,
+ COUNT(DISTINCT referee) AS referral_count,
+ lb.total_box_count,
+ lb.highest_reward_tier,
+ COALESCE(liquidity.result, 1) AS liquidity_multiplier
+FROM (
+ -- subquery to avoid re-summing lootbox_count for every referee
+ SELECT address, SUM(lootbox_count) as total_box_count, MAX(reward_tier) as highest_reward_tier
+ FROM lootbox
+ GROUP BY address
+) lb
+ LEFT JOIN lootbox_referrals
+ ON lb.address = lootbox_referrals.referrer,
+ LATERAL calculate_a_y(address, now()::TIMESTAMP) AS liquidity
+GROUP BY address, liquidity_multiplier, total_box_count, highest_reward_tier
+$$;
\ No newline at end of file
diff --git a/database/102-up-timescale/20240108102606-user_actions_add_user_actions_lootbottles.sql b/database/102-up-timescale/20240108102606-user_actions_add_user_actions_lootbottles.sql
new file mode 100644
index 000000000..e60430912
--- /dev/null
+++ b/database/102-up-timescale/20240108102606-user_actions_add_user_actions_lootbottles.sql
@@ -0,0 +1,61 @@
+-- migrate:up
+
+-- this is a copy of aggregated_user_transactions
+
+CREATE TABLE aggregated_user_transactions_lootbottles_return (
+ token_short_name VARCHAR NOT NULL,
+ network network_blockchain NOT NULL,
+ time TIMESTAMP WITHOUT TIME ZONE NOT NULL,
+ transaction_hash VARCHAR NOT NULL,
+ sender_address VARCHAR NOT NULL,
+ recipient_address VARCHAR NOT NULL,
+ amount DOUBLE PRECISION NOT NULL,
+ application VARCHAR NOT NULL,
+ winning_amount DOUBLE PRECISION NOT NULL,
+ winning_address VARCHAR NOT NULL,
+ reward_hash VARCHAR NOT NULL,
+ type user_action NOT NULL,
+ swap_in BOOLEAN NOT NULL,
+ utility_amount DOUBLE PRECISION NOT NULL,
+ utility_name VARCHAR NOT NULL,
+
+ lootbox_count DECIMAL,
+ reward_tier INTEGER
+);
+
+CREATE FUNCTION aggregated_user_transactions_lootbottles()
+RETURNS SETOF aggregated_user_transactions_lootbottles_return
+LANGUAGE SQL
+STABLE
+AS
+$$
+SELECT
+ token_short_name,
+ network,
+ time,
+ transaction_hash,
+ sender_address,
+ recipient_address,
+ amount,
+ application,
+ winning_amount,
+ winning_address,
+ reward_hash,
+ type user_action,
+ swap_in,
+ utility_amount,
+ utility_name,
+ lootbox_count,
+ reward_tier
+FROM
+ aggregated_user_transactions
+LEFT JOIN (
+ SELECT reward_tier, lootbox_count FROM lootbox
+) AS lootbox_user_actions ON transaction_hash = aggregated_user_transactions.transaction_hash
+$$;
+
+-- migrate:down
+
+DROP TABLE user_actions_lootbottles_return;
+
+DROP FUNCTION user_actions_lootbottles;
diff --git a/lib/databases/timescale/lootboxes/config.go b/lib/databases/timescale/lootboxes/config.go
new file mode 100644
index 000000000..5f8e1f12e
--- /dev/null
+++ b/lib/databases/timescale/lootboxes/config.go
@@ -0,0 +1,101 @@
+// Copyright 2023 Fluidity Money. All rights reserved. Use of this
+// source code is governed by a GPL-style license that can be found in the
+// LICENSE.md file.
+
+package lootboxes
+
+import (
+ "database/sql"
+ "fmt"
+
+ "github.com/fluidity-money/fluidity-app/common/ethereum/applications"
+ "github.com/fluidity-money/fluidity-app/lib/log"
+ "github.com/fluidity-money/fluidity-app/lib/timescale"
+)
+
+const (
+ Epoch1 = "epoch_1"
+ Epoch2 = "epoch_2"
+ EpochTesting = "epoch_testing"
+)
+
+// GetConfig that's currently marked as enabled, also getting whether the
+// program has currently begun or not. Fatals if the number of rows returned
+// exceeds 1.
+func GetLootboxConfig() (programFound bool, hasBegun bool, curEpoch string, curApplication applications.Application) {
+ timescaleClient := timescale.Client()
+
+ statementText := fmt.Sprintf(
+ `WITH t AS (
+ SELECT CURRENT_TIMESTAMP AT TIME ZONE 'UTC' AS timestamp
+ )
+ SELECT
+ program_begin < (select timestamp from t) AND
+ program_end > (select timestamp from t),
+ epoch_identifier,
+ current_application
+ FROM %s
+ WHERE is_current_program;`,
+
+ TableLootboxConfig,
+ )
+
+ rows, err := timescaleClient.Query(statementText)
+
+ switch err {
+ case sql.ErrNoRows:
+ return false, false, "", applications.ApplicationNone
+
+ case nil:
+ // do nothing
+
+ default:
+ log.Fatal(func(k *log.Log) {
+ k.Context = Context
+ k.Message = "Failed to query for lootbox config!"
+ k.Payload = err
+ })
+ }
+
+ defer rows.Close()
+
+ if !rows.Next() {
+ return false, false, "", applications.ApplicationNone
+ }
+
+ var applicationString string
+
+ err = rows.Scan(&hasBegun, &curEpoch, &applicationString)
+
+ if err != nil {
+ log.Fatal(func(k *log.Log) {
+ k.Context = Context
+ k.Message = "Failed to query for lootbox config!"
+ k.Payload = err
+ })
+ }
+
+ curApplication, err = applications.ParseApplicationName(applicationString)
+
+ if err != nil {
+ log.Fatal(func(k *log.Log) {
+ k.Context = Context
+
+ k.Format(
+ "Failed to parse the Ethereum application name %#v!",
+ applicationString,
+ )
+
+ k.Payload = err
+ })
+ }
+
+ if rows.Next() {
+ log.Fatal(func(k *log.Log) {
+ k.Context = Context
+ k.Message = "Duplicate enabled row for the lootbox_config found!"
+ })
+ }
+
+ return true, hasBegun, curEpoch, curApplication
+}
diff --git a/lib/databases/timescale/lootboxes/lootboxes.go b/lib/databases/timescale/lootboxes/lootboxes.go
index 471c89e20..55e46c516 100644
--- a/lib/databases/timescale/lootboxes/lootboxes.go
+++ b/lib/databases/timescale/lootboxes/lootboxes.go
@@ -1,3 +1,7 @@
+// Copyright 2023 Fluidity Money. All rights reserved. Use of this
+// source code is governed by a GPL-style license that can be found in the
+// LICENSE.md file.
+
package lootboxes
import (
@@ -17,6 +21,14 @@ const (
// TableLootboxes to use when inserting
// derived lootboxes to database
TableLootboxes = `lootbox`
+
+ // TableLootboxConfig to use for setting configuration
+ // for the currently running epoch
+ TableLootboxConfig = `lootbox_config`
+
+ // TableLootboxAmountsRewarded to use for tracking cumulative
+ // amounts earned by users during a lootbox campaign
+ TableLootboxAmountsRewarded = `lootbox_amounts_rewarded`
)
type Lootbox = types.Lootbox
@@ -34,7 +46,8 @@ func InsertLootbox(lootbox Lootbox) {
volume,
reward_tier,
lootbox_count,
- application
+ application,
+ epoch
)
VALUES (
@@ -45,7 +58,8 @@ func InsertLootbox(lootbox Lootbox) {
$5,
$6,
$7,
- $8
+ $8,
+ $9
)`,
TableLootboxes,
@@ -61,6 +75,7 @@ func InsertLootbox(lootbox Lootbox) {
lootbox.RewardTier,
lootbox.LootboxCount,
lootbox.Application.String(),
+ lootbox.Epoch,
)
if err != nil {
@@ -73,7 +88,7 @@ func InsertLootbox(lootbox Lootbox) {
}
// GetLootboxes gets all Lootboxes earned by address, limited by a number
-func GetLootboxes(address ethereum.Address, limit int) []Lootbox {
+func GetLootboxes(currentEpoch string, address ethereum.Address, limit int) []Lootbox {
timescaleClient := timescale.Client()
statementText := fmt.Sprintf(
@@ -87,9 +102,9 @@ func GetLootboxes(address ethereum.Address, limit int) []Lootbox {
lootbox_count,
application
- FROM %s
- WHERE address = $1
- LIMIT $2
+ FROM %s
+ WHERE address = $1 AND epoch = $2
+ LIMIT $3
`,
TableLootboxes,
@@ -98,6 +113,7 @@ func GetLootboxes(address ethereum.Address, limit int) []Lootbox {
rows, err := timescaleClient.Query(
statementText,
address,
+ currentEpoch,
limit,
)
@@ -143,6 +159,8 @@ func GetLootboxes(address ethereum.Address, limit int) []Lootbox {
})
}
+ lootbox.Epoch = currentEpoch
+
application, err := applications.ParseApplicationName(application_)
if err != nil {
diff --git a/lib/databases/timescale/lootboxes/rewards.go b/lib/databases/timescale/lootboxes/rewards.go
index 430b7abd4..a0df54a3b 100644
--- a/lib/databases/timescale/lootboxes/rewards.go
+++ b/lib/databases/timescale/lootboxes/rewards.go
@@ -13,6 +13,7 @@ import (
"github.com/fluidity-money/fluidity-app/lib/log"
"github.com/fluidity-money/fluidity-app/lib/timescale"
"github.com/fluidity-money/fluidity-app/lib/types/applications"
+ "github.com/fluidity-money/fluidity-app/lib/types/network"
)
const ExpectedTopUsers = 10
@@ -33,32 +34,32 @@ func buildUserRewardValuesString(userCount int) (string, error) {
}
rewardStrings := []string{
- `($2, '', 'leaderboard_prize', $1, 0, 1, 30, 'none'),
-($2, '', 'leaderboard_prize', $1, 0, 2, 10, 'none'),
-($2, '', 'leaderboard_prize', $1, 0, 3, 5, 'none')`,
+ `($3, '', 'leaderboard_prize', $1, 0, 1, 30, 'none', $2),
+($3, '', 'leaderboard_prize', $1, 0, 2, 10, 'none', $2),
+($3, '', 'leaderboard_prize', $1, 0, 3, 5, 'none', $2)`,
- `($3, '', 'leaderboard_prize', $1, 0, 1, 20, 'none'),
-($3, '', 'leaderboard_prize', $1, 0, 2, 5, 'none'),
-($3, '', 'leaderboard_prize', $1, 0, 3, 2, 'none')`,
+ `($4, '', 'leaderboard_prize', $1, 0, 1, 20, 'none', $2),
+($4, '', 'leaderboard_prize', $1, 0, 2, 5, 'none', $2),
+($4, '', 'leaderboard_prize', $1, 0, 3, 2, 'none', $2)`,
- `($4, '', 'leaderboard_prize', $1, 0, 1, 15, 'none'),
-($4, '', 'leaderboard_prize', $1, 0, 2, 3, 'none'),
-($4, '', 'leaderboard_prize', $1, 0, 3, 1, 'none')`,
+ `($5, '', 'leaderboard_prize', $1, 0, 1, 15, 'none', $2),
+($5, '', 'leaderboard_prize', $1, 0, 2, 3, 'none', $2),
+($5, '', 'leaderboard_prize', $1, 0, 3, 1, 'none', $2)`,
- `($5, '', 'leaderboard_prize', $1, 0, 1, 12, 'none'),
-($5, '', 'leaderboard_prize', $1, 0, 2, 1, 'none')`,
+ `($6, '', 'leaderboard_prize', $1, 0, 1, 12, 'none', $2),
+($6, '', 'leaderboard_prize', $1, 0, 2, 1, 'none', $2)`,
- "($6, '', 'leaderboard_prize', $1, 0, 1, 10, 'none')",
+ "($7, '', 'leaderboard_prize', $1, 0, 1, 10, 'none', $2)",
- "($7, '', 'leaderboard_prize', $1, 0, 1, 10, 'none')",
+ "($8, '', 'leaderboard_prize', $1, 0, 1, 10, 'none', $2)",
- "($8, '', 'leaderboard_prize', $1, 0, 1, 10, 'none')",
+ "($9, '', 'leaderboard_prize', $1, 0, 1, 10, 'none', $2)",
- "($9, '', 'leaderboard_prize', $1, 0, 1, 10, 'none')",
+ "($10, '', 'leaderboard_prize', $1, 0, 1, 10, 'none', $2)",
- "($10, '', 'leaderboard_prize', $1, 0, 1, 10, 'none')",
+ "($11, '', 'leaderboard_prize', $1, 0, 1, 10, 'none', $2)",
- "($11, '', 'leaderboard_prize', $1, 0, 1, 10, 'none')",
+ "($12, '', 'leaderboard_prize', $1, 0, 1, 10, 'none', $2)",
}
var output strings.Builder
@@ -100,7 +101,7 @@ func buildUserRewardValuesString(userCount int) (string, error) {
// InsertTopUserReward to insert lootboxes for the given users for their activity during the airdrop.
// Expects 10 users to reward
-func InsertTopUserReward(currentTime time.Time, users []UserLootboxCount) {
+func InsertTopUserReward(currentEpoch string, currentTime time.Time, users []UserLootboxCount) {
valuesString, err := buildUserRewardValuesString(len(users))
if err != nil {
@@ -114,14 +115,15 @@ func InsertTopUserReward(currentTime time.Time, users []UserLootboxCount) {
statementText := fmt.Sprintf(
`INSERT INTO %s (
- address,
- transaction_hash,
- source,
- awarded_time,
- volume,
- reward_tier,
- lootbox_count,
- application
+ address,
+ transaction_hash,
+ source,
+ awarded_time,
+ volume,
+ reward_tier,
+ lootbox_count,
+ application,
+ epoch
) VALUES
%s`,
TableLootboxes,
@@ -129,8 +131,7 @@ func InsertTopUserReward(currentTime time.Time, users []UserLootboxCount) {
)
// build variadic arguments [time, users...]
- var args []interface{}
- args = append(args, currentTime)
+ args := []interface{}{currentTime, currentEpoch}
for _, user := range users {
args = append(args, user.Address)
@@ -151,21 +152,22 @@ func InsertTopUserReward(currentTime time.Time, users []UserLootboxCount) {
}
// fetch the 10 addresses with the highest lootboxes earned during the given period
-func GetTopUsersByLootboxCount(startTime, endTime time.Time) []UserLootboxCount {
+func GetTopUsersByLootboxCount(currentEpoch string, startTime, endTime time.Time) []UserLootboxCount {
timescaleClient := timescale.Client()
statementText := fmt.Sprintf(
- `SELECT
- address,
- SUM(lootbox_count) AS lootbox_count
+ `SELECT
+ address,
+ SUM(lootbox_count) AS lootbox_count
FROM %s
- WHERE
+ WHERE
awarded_time >= $1 AT TIME ZONE $3 AND
- awarded_time < $2 AT TIME ZONE $4 AND
- source != 'leaderboard_prize'
- GROUP BY address
+ awarded_time < $2 AT TIME ZONE $4 AND
+ source != 'leaderboard_prize' AND
+ epoch = $5
+ GROUP BY address
ORDER BY lootbox_count DESC
- LIMIT $5`,
+ LIMIT $6`,
TableLootboxes,
)
@@ -176,6 +178,7 @@ func GetTopUsersByLootboxCount(startTime, endTime time.Time) []UserLootboxCount
endTime,
LootboxRewardTimezone,
LootboxRewardTimezone,
+ currentEpoch,
10,
)
@@ -193,10 +196,8 @@ func GetTopUsersByLootboxCount(startTime, endTime time.Time) []UserLootboxCount
for rows.Next() {
var user UserLootboxCount
- err := rows.Scan(
- &user.Address,
- &user.LootboxCount,
- )
+
+ err := rows.Scan(&user.Address, &user.LootboxCount)
if err != nil {
log.Fatal(func(k *log.Log) {
@@ -215,20 +216,21 @@ func GetTopUsersByLootboxCount(startTime, endTime time.Time) []UserLootboxCount
const LootboxRewardTimezone = "Australia/Adelaide"
// fetch the 10 addresses with the highest lootboxes earned during the given period on the given application
-func GetTopApplicationUsersByLootboxCount(startTime, endTime time.Time, application applications.Application) []UserLootboxCount {
+func GetTopApplicationUsersByLootboxCount(currentEpoch string, startTime, endTime time.Time, application applications.Application) []UserLootboxCount {
timescaleClient := timescale.Client()
statementText := fmt.Sprintf(
- `SELECT
- address,
- SUM(lootbox_count) AS lootbox_count
+ `SELECT
+ address,
+ SUM(lootbox_count) AS lootbox_count
FROM %s
- WHERE
+ WHERE
awarded_time >= $1 AT TIME ZONE $3 AND
- awarded_time < $2 AT TIME ZONE $4 AND
+ awarded_time < $2 AT TIME ZONE $4 AND
source != 'leaderboard_prize' AND
- application = $6
- GROUP BY address
+ application = $6 AND
+ epoch = $7
+ GROUP BY address
ORDER BY lootbox_count DESC
LIMIT $5`,
@@ -243,6 +245,7 @@ func GetTopApplicationUsersByLootboxCount(startTime, endTime time.Time, applicat
LootboxRewardTimezone,
10,
application.String(),
+ currentEpoch,
)
if err != nil {
@@ -259,10 +262,8 @@ func GetTopApplicationUsersByLootboxCount(startTime, endTime time.Time, applicat
for rows.Next() {
var user UserLootboxCount
- err := rows.Scan(
- &user.Address,
- &user.LootboxCount,
- )
+
+ err := rows.Scan(&user.Address, &user.LootboxCount)
if err != nil {
log.Fatal(func(k *log.Log) {
@@ -277,3 +278,54 @@ func GetTopApplicationUsersByLootboxCount(startTime, endTime time.Time, applicat
return topUsers
}
+
+// UpdateOrInsertAmountsRewarded for the current user in the specific
+// epoch that's taking place.
+func UpdateOrInsertAmountsRewarded(network_ network.BlockchainNetwork, lootboxCurrentEpoch, tokenShortName string, amountNormalLossy float64, winnerAddress, application string) {
+ timescaleClient := timescale.Client()
+
+ statementText := fmt.Sprintf(
+ `INSERT INTO %s (
+ network,
+ epoch,
+ token_short_name,
+ amount_earned,
+ winner,
+ application,
+ last_updated
+ )
+ VALUES (
+ $1,
+ $2,
+ $3,
+ $4,
+ $5,
+ $6,
+ $7
+ )
+ ON CONFLICT (id)
+ DO UPDATE SET
+ amount_earned = amount_earned + $4,
+ last_updated = CURRENT_TIMESTAMP`,
+
+ TableLootboxAmountsRewarded,
+ )
+
+ _, err := timescaleClient.Exec(
+ statementText,
+ network_,
+ lootboxCurrentEpoch,
+ tokenShortName,
+ amountNormalLossy,
+ application,
+ winnerAddress,
+ )
+
+ if err != nil {
+ log.Fatal(func(k *log.Log) {
+ k.Context = Context
+ k.Message = "Failed to upsert a lootbox amount rewarded!"
+ k.Payload = err
+ })
+ }
+}
diff --git a/lib/databases/timescale/lootboxes/rewards_test.go b/lib/databases/timescale/lootboxes/rewards_test.go
index 7a74779d2..707382fa6 100644
--- a/lib/databases/timescale/lootboxes/rewards_test.go
+++ b/lib/databases/timescale/lootboxes/rewards_test.go
@@ -9,131 +9,131 @@ import (
func TestBuildUserRewardValuesString(t *testing.T) {
expectedRewardStrings := []string{
- `($2, '', 'leaderboard_prize', $1, 0, 1, 30, 'none'),
-($2, '', 'leaderboard_prize', $1, 0, 2, 10, 'none'),
-($2, '', 'leaderboard_prize', $1, 0, 3, 5, 'none')`,
-
- `($2, '', 'leaderboard_prize', $1, 0, 1, 30, 'none'),
-($2, '', 'leaderboard_prize', $1, 0, 2, 10, 'none'),
-($2, '', 'leaderboard_prize', $1, 0, 3, 5, 'none'),
-($3, '', 'leaderboard_prize', $1, 0, 1, 20, 'none'),
-($3, '', 'leaderboard_prize', $1, 0, 2, 5, 'none'),
-($3, '', 'leaderboard_prize', $1, 0, 3, 2, 'none')`,
-
- `($2, '', 'leaderboard_prize', $1, 0, 1, 30, 'none'),
-($2, '', 'leaderboard_prize', $1, 0, 2, 10, 'none'),
-($2, '', 'leaderboard_prize', $1, 0, 3, 5, 'none'),
-($3, '', 'leaderboard_prize', $1, 0, 1, 20, 'none'),
-($3, '', 'leaderboard_prize', $1, 0, 2, 5, 'none'),
-($3, '', 'leaderboard_prize', $1, 0, 3, 2, 'none'),
-($4, '', 'leaderboard_prize', $1, 0, 1, 15, 'none'),
-($4, '', 'leaderboard_prize', $1, 0, 2, 3, 'none'),
-($4, '', 'leaderboard_prize', $1, 0, 3, 1, 'none')`,
-
- `($2, '', 'leaderboard_prize', $1, 0, 1, 30, 'none'),
-($2, '', 'leaderboard_prize', $1, 0, 2, 10, 'none'),
-($2, '', 'leaderboard_prize', $1, 0, 3, 5, 'none'),
-($3, '', 'leaderboard_prize', $1, 0, 1, 20, 'none'),
-($3, '', 'leaderboard_prize', $1, 0, 2, 5, 'none'),
-($3, '', 'leaderboard_prize', $1, 0, 3, 2, 'none'),
-($4, '', 'leaderboard_prize', $1, 0, 1, 15, 'none'),
-($4, '', 'leaderboard_prize', $1, 0, 2, 3, 'none'),
-($4, '', 'leaderboard_prize', $1, 0, 3, 1, 'none'),
-($5, '', 'leaderboard_prize', $1, 0, 1, 12, 'none'),
-($5, '', 'leaderboard_prize', $1, 0, 2, 1, 'none')`,
-
- `($2, '', 'leaderboard_prize', $1, 0, 1, 30, 'none'),
-($2, '', 'leaderboard_prize', $1, 0, 2, 10, 'none'),
-($2, '', 'leaderboard_prize', $1, 0, 3, 5, 'none'),
-($3, '', 'leaderboard_prize', $1, 0, 1, 20, 'none'),
-($3, '', 'leaderboard_prize', $1, 0, 2, 5, 'none'),
-($3, '', 'leaderboard_prize', $1, 0, 3, 2, 'none'),
-($4, '', 'leaderboard_prize', $1, 0, 1, 15, 'none'),
-($4, '', 'leaderboard_prize', $1, 0, 2, 3, 'none'),
-($4, '', 'leaderboard_prize', $1, 0, 3, 1, 'none'),
-($5, '', 'leaderboard_prize', $1, 0, 1, 12, 'none'),
-($5, '', 'leaderboard_prize', $1, 0, 2, 1, 'none'),
-($6, '', 'leaderboard_prize', $1, 0, 1, 10, 'none')`,
-
- `($2, '', 'leaderboard_prize', $1, 0, 1, 30, 'none'),
-($2, '', 'leaderboard_prize', $1, 0, 2, 10, 'none'),
-($2, '', 'leaderboard_prize', $1, 0, 3, 5, 'none'),
-($3, '', 'leaderboard_prize', $1, 0, 1, 20, 'none'),
-($3, '', 'leaderboard_prize', $1, 0, 2, 5, 'none'),
-($3, '', 'leaderboard_prize', $1, 0, 3, 2, 'none'),
-($4, '', 'leaderboard_prize', $1, 0, 1, 15, 'none'),
-($4, '', 'leaderboard_prize', $1, 0, 2, 3, 'none'),
-($4, '', 'leaderboard_prize', $1, 0, 3, 1, 'none'),
-($5, '', 'leaderboard_prize', $1, 0, 1, 12, 'none'),
-($5, '', 'leaderboard_prize', $1, 0, 2, 1, 'none'),
-($6, '', 'leaderboard_prize', $1, 0, 1, 10, 'none'),
-($7, '', 'leaderboard_prize', $1, 0, 1, 10, 'none')`,
-
- `($2, '', 'leaderboard_prize', $1, 0, 1, 30, 'none'),
-($2, '', 'leaderboard_prize', $1, 0, 2, 10, 'none'),
-($2, '', 'leaderboard_prize', $1, 0, 3, 5, 'none'),
-($3, '', 'leaderboard_prize', $1, 0, 1, 20, 'none'),
-($3, '', 'leaderboard_prize', $1, 0, 2, 5, 'none'),
-($3, '', 'leaderboard_prize', $1, 0, 3, 2, 'none'),
-($4, '', 'leaderboard_prize', $1, 0, 1, 15, 'none'),
-($4, '', 'leaderboard_prize', $1, 0, 2, 3, 'none'),
-($4, '', 'leaderboard_prize', $1, 0, 3, 1, 'none'),
-($5, '', 'leaderboard_prize', $1, 0, 1, 12, 'none'),
-($5, '', 'leaderboard_prize', $1, 0, 2, 1, 'none'),
-($6, '', 'leaderboard_prize', $1, 0, 1, 10, 'none'),
-($7, '', 'leaderboard_prize', $1, 0, 1, 10, 'none'),
-($8, '', 'leaderboard_prize', $1, 0, 1, 10, 'none')`,
-
- `($2, '', 'leaderboard_prize', $1, 0, 1, 30, 'none'),
-($2, '', 'leaderboard_prize', $1, 0, 2, 10, 'none'),
-($2, '', 'leaderboard_prize', $1, 0, 3, 5, 'none'),
-($3, '', 'leaderboard_prize', $1, 0, 1, 20, 'none'),
-($3, '', 'leaderboard_prize', $1, 0, 2, 5, 'none'),
-($3, '', 'leaderboard_prize', $1, 0, 3, 2, 'none'),
-($4, '', 'leaderboard_prize', $1, 0, 1, 15, 'none'),
-($4, '', 'leaderboard_prize', $1, 0, 2, 3, 'none'),
-($4, '', 'leaderboard_prize', $1, 0, 3, 1, 'none'),
-($5, '', 'leaderboard_prize', $1, 0, 1, 12, 'none'),
-($5, '', 'leaderboard_prize', $1, 0, 2, 1, 'none'),
-($6, '', 'leaderboard_prize', $1, 0, 1, 10, 'none'),
-($7, '', 'leaderboard_prize', $1, 0, 1, 10, 'none'),
-($8, '', 'leaderboard_prize', $1, 0, 1, 10, 'none'),
-($9, '', 'leaderboard_prize', $1, 0, 1, 10, 'none')`,
-
- `($2, '', 'leaderboard_prize', $1, 0, 1, 30, 'none'),
-($2, '', 'leaderboard_prize', $1, 0, 2, 10, 'none'),
-($2, '', 'leaderboard_prize', $1, 0, 3, 5, 'none'),
-($3, '', 'leaderboard_prize', $1, 0, 1, 20, 'none'),
-($3, '', 'leaderboard_prize', $1, 0, 2, 5, 'none'),
-($3, '', 'leaderboard_prize', $1, 0, 3, 2, 'none'),
-($4, '', 'leaderboard_prize', $1, 0, 1, 15, 'none'),
-($4, '', 'leaderboard_prize', $1, 0, 2, 3, 'none'),
-($4, '', 'leaderboard_prize', $1, 0, 3, 1, 'none'),
-($5, '', 'leaderboard_prize', $1, 0, 1, 12, 'none'),
-($5, '', 'leaderboard_prize', $1, 0, 2, 1, 'none'),
-($6, '', 'leaderboard_prize', $1, 0, 1, 10, 'none'),
-($7, '', 'leaderboard_prize', $1, 0, 1, 10, 'none'),
-($8, '', 'leaderboard_prize', $1, 0, 1, 10, 'none'),
-($9, '', 'leaderboard_prize', $1, 0, 1, 10, 'none'),
-($10, '', 'leaderboard_prize', $1, 0, 1, 10, 'none')`,
-
- `($2, '', 'leaderboard_prize', $1, 0, 1, 30, 'none'),
-($2, '', 'leaderboard_prize', $1, 0, 2, 10, 'none'),
-($2, '', 'leaderboard_prize', $1, 0, 3, 5, 'none'),
-($3, '', 'leaderboard_prize', $1, 0, 1, 20, 'none'),
-($3, '', 'leaderboard_prize', $1, 0, 2, 5, 'none'),
-($3, '', 'leaderboard_prize', $1, 0, 3, 2, 'none'),
-($4, '', 'leaderboard_prize', $1, 0, 1, 15, 'none'),
-($4, '', 'leaderboard_prize', $1, 0, 2, 3, 'none'),
-($4, '', 'leaderboard_prize', $1, 0, 3, 1, 'none'),
-($5, '', 'leaderboard_prize', $1, 0, 1, 12, 'none'),
-($5, '', 'leaderboard_prize', $1, 0, 2, 1, 'none'),
-($6, '', 'leaderboard_prize', $1, 0, 1, 10, 'none'),
-($7, '', 'leaderboard_prize', $1, 0, 1, 10, 'none'),
-($8, '', 'leaderboard_prize', $1, 0, 1, 10, 'none'),
-($9, '', 'leaderboard_prize', $1, 0, 1, 10, 'none'),
-($10, '', 'leaderboard_prize', $1, 0, 1, 10, 'none'),
-($11, '', 'leaderboard_prize', $1, 0, 1, 10, 'none')`,
+ `($3, '', 'leaderboard_prize', $1, 0, 1, 30, 'none', $2),
+($3, '', 'leaderboard_prize', $1, 0, 2, 10, 'none', $2),
+($3, '', 'leaderboard_prize', $1, 0, 3, 5, 'none', $2)`,
+
+ `($3, '', 'leaderboard_prize', $1, 0, 1, 30, 'none', $2),
+($3, '', 'leaderboard_prize', $1, 0, 2, 10, 'none', $2),
+($3, '', 'leaderboard_prize', $1, 0, 3, 5, 'none', $2),
+($4, '', 'leaderboard_prize', $1, 0, 1, 20, 'none', $2),
+($4, '', 'leaderboard_prize', $1, 0, 2, 5, 'none', $2),
+($4, '', 'leaderboard_prize', $1, 0, 3, 2, 'none', $2)`,
+
+ `($3, '', 'leaderboard_prize', $1, 0, 1, 30, 'none', $2),
+($3, '', 'leaderboard_prize', $1, 0, 2, 10, 'none', $2),
+($3, '', 'leaderboard_prize', $1, 0, 3, 5, 'none', $2),
+($4, '', 'leaderboard_prize', $1, 0, 1, 20, 'none', $2),
+($4, '', 'leaderboard_prize', $1, 0, 2, 5, 'none', $2),
+($4, '', 'leaderboard_prize', $1, 0, 3, 2, 'none', $2),
+($5, '', 'leaderboard_prize', $1, 0, 1, 15, 'none', $2),
+($5, '', 'leaderboard_prize', $1, 0, 2, 3, 'none', $2),
+($5, '', 'leaderboard_prize', $1, 0, 3, 1, 'none', $2)`,
+
+ `($3, '', 'leaderboard_prize', $1, 0, 1, 30, 'none', $2),
+($3, '', 'leaderboard_prize', $1, 0, 2, 10, 'none', $2),
+($3, '', 'leaderboard_prize', $1, 0, 3, 5, 'none', $2),
+($4, '', 'leaderboard_prize', $1, 0, 1, 20, 'none', $2),
+($4, '', 'leaderboard_prize', $1, 0, 2, 5, 'none', $2),
+($4, '', 'leaderboard_prize', $1, 0, 3, 2, 'none', $2),
+($5, '', 'leaderboard_prize', $1, 0, 1, 15, 'none', $2),
+($5, '', 'leaderboard_prize', $1, 0, 2, 3, 'none', $2),
+($5, '', 'leaderboard_prize', $1, 0, 3, 1, 'none', $2),
+($6, '', 'leaderboard_prize', $1, 0, 1, 12, 'none', $2),
+($6, '', 'leaderboard_prize', $1, 0, 2, 1, 'none', $2)`,
+
+ `($3, '', 'leaderboard_prize', $1, 0, 1, 30, 'none', $2),
+($3, '', 'leaderboard_prize', $1, 0, 2, 10, 'none', $2),
+($3, '', 'leaderboard_prize', $1, 0, 3, 5, 'none', $2),
+($4, '', 'leaderboard_prize', $1, 0, 1, 20, 'none', $2),
+($4, '', 'leaderboard_prize', $1, 0, 2, 5, 'none', $2),
+($4, '', 'leaderboard_prize', $1, 0, 3, 2, 'none', $2),
+($5, '', 'leaderboard_prize', $1, 0, 1, 15, 'none', $2),
+($5, '', 'leaderboard_prize', $1, 0, 2, 3, 'none', $2),
+($5, '', 'leaderboard_prize', $1, 0, 3, 1, 'none', $2),
+($6, '', 'leaderboard_prize', $1, 0, 1, 12, 'none', $2),
+($6, '', 'leaderboard_prize', $1, 0, 2, 1, 'none', $2),
+($7, '', 'leaderboard_prize', $1, 0, 1, 10, 'none', $2)`,
+
+ `($3, '', 'leaderboard_prize', $1, 0, 1, 30, 'none', $2),
+($3, '', 'leaderboard_prize', $1, 0, 2, 10, 'none', $2),
+($3, '', 'leaderboard_prize', $1, 0, 3, 5, 'none', $2),
+($4, '', 'leaderboard_prize', $1, 0, 1, 20, 'none', $2),
+($4, '', 'leaderboard_prize', $1, 0, 2, 5, 'none', $2),
+($4, '', 'leaderboard_prize', $1, 0, 3, 2, 'none', $2),
+($5, '', 'leaderboard_prize', $1, 0, 1, 15, 'none', $2),
+($5, '', 'leaderboard_prize', $1, 0, 2, 3, 'none', $2),
+($5, '', 'leaderboard_prize', $1, 0, 3, 1, 'none', $2),
+($6, '', 'leaderboard_prize', $1, 0, 1, 12, 'none', $2),
+($6, '', 'leaderboard_prize', $1, 0, 2, 1, 'none', $2),
+($7, '', 'leaderboard_prize', $1, 0, 1, 10, 'none', $2),
+($8, '', 'leaderboard_prize', $1, 0, 1, 10, 'none', $2)`,
+
+ `($3, '', 'leaderboard_prize', $1, 0, 1, 30, 'none', $2),
+($3, '', 'leaderboard_prize', $1, 0, 2, 10, 'none', $2),
+($3, '', 'leaderboard_prize', $1, 0, 3, 5, 'none', $2),
+($4, '', 'leaderboard_prize', $1, 0, 1, 20, 'none', $2),
+($4, '', 'leaderboard_prize', $1, 0, 2, 5, 'none', $2),
+($4, '', 'leaderboard_prize', $1, 0, 3, 2, 'none', $2),
+($5, '', 'leaderboard_prize', $1, 0, 1, 15, 'none', $2),
+($5, '', 'leaderboard_prize', $1, 0, 2, 3, 'none', $2),
+($5, '', 'leaderboard_prize', $1, 0, 3, 1, 'none', $2),
+($6, '', 'leaderboard_prize', $1, 0, 1, 12, 'none', $2),
+($6, '', 'leaderboard_prize', $1, 0, 2, 1, 'none', $2),
+($7, '', 'leaderboard_prize', $1, 0, 1, 10, 'none', $2),
+($8, '', 'leaderboard_prize', $1, 0, 1, 10, 'none', $2),
+($9, '', 'leaderboard_prize', $1, 0, 1, 10, 'none', $2)`,
+
+ `($3, '', 'leaderboard_prize', $1, 0, 1, 30, 'none', $2),
+($3, '', 'leaderboard_prize', $1, 0, 2, 10, 'none', $2),
+($3, '', 'leaderboard_prize', $1, 0, 3, 5, 'none', $2),
+($4, '', 'leaderboard_prize', $1, 0, 1, 20, 'none', $2),
+($4, '', 'leaderboard_prize', $1, 0, 2, 5, 'none', $2),
+($4, '', 'leaderboard_prize', $1, 0, 3, 2, 'none', $2),
+($5, '', 'leaderboard_prize', $1, 0, 1, 15, 'none', $2),
+($5, '', 'leaderboard_prize', $1, 0, 2, 3, 'none', $2),
+($5, '', 'leaderboard_prize', $1, 0, 3, 1, 'none', $2),
+($6, '', 'leaderboard_prize', $1, 0, 1, 12, 'none', $2),
+($6, '', 'leaderboard_prize', $1, 0, 2, 1, 'none', $2),
+($7, '', 'leaderboard_prize', $1, 0, 1, 10, 'none', $2),
+($8, '', 'leaderboard_prize', $1, 0, 1, 10, 'none', $2),
+($9, '', 'leaderboard_prize', $1, 0, 1, 10, 'none', $2),
+($10, '', 'leaderboard_prize', $1, 0, 1, 10, 'none', $2)`,
+
+ `($3, '', 'leaderboard_prize', $1, 0, 1, 30, 'none', $2),
+($3, '', 'leaderboard_prize', $1, 0, 2, 10, 'none', $2),
+($3, '', 'leaderboard_prize', $1, 0, 3, 5, 'none', $2),
+($4, '', 'leaderboard_prize', $1, 0, 1, 20, 'none', $2),
+($4, '', 'leaderboard_prize', $1, 0, 2, 5, 'none', $2),
+($4, '', 'leaderboard_prize', $1, 0, 3, 2, 'none', $2),
+($5, '', 'leaderboard_prize', $1, 0, 1, 15, 'none', $2),
+($5, '', 'leaderboard_prize', $1, 0, 2, 3, 'none', $2),
+($5, '', 'leaderboard_prize', $1, 0, 3, 1, 'none', $2),
+($6, '', 'leaderboard_prize', $1, 0, 1, 12, 'none', $2),
+($6, '', 'leaderboard_prize', $1, 0, 2, 1, 'none', $2),
+($7, '', 'leaderboard_prize', $1, 0, 1, 10, 'none', $2),
+($8, '', 'leaderboard_prize', $1, 0, 1, 10, 'none', $2),
+($9, '', 'leaderboard_prize', $1, 0, 1, 10, 'none', $2),
+($10, '', 'leaderboard_prize', $1, 0, 1, 10, 'none', $2),
+($11, '', 'leaderboard_prize', $1, 0, 1, 10, 'none', $2)`,
+
+ `($3, '', 'leaderboard_prize', $1, 0, 1, 30, 'none', $2),
+($3, '', 'leaderboard_prize', $1, 0, 2, 10, 'none', $2),
+($3, '', 'leaderboard_prize', $1, 0, 3, 5, 'none', $2),
+($4, '', 'leaderboard_prize', $1, 0, 1, 20, 'none', $2),
+($4, '', 'leaderboard_prize', $1, 0, 2, 5, 'none', $2),
+($4, '', 'leaderboard_prize', $1, 0, 3, 2, 'none', $2),
+($5, '', 'leaderboard_prize', $1, 0, 1, 15, 'none', $2),
+($5, '', 'leaderboard_prize', $1, 0, 2, 3, 'none', $2),
+($5, '', 'leaderboard_prize', $1, 0, 3, 1, 'none', $2),
+($6, '', 'leaderboard_prize', $1, 0, 1, 12, 'none', $2),
+($6, '', 'leaderboard_prize', $1, 0, 2, 1, 'none', $2),
+($7, '', 'leaderboard_prize', $1, 0, 1, 10, 'none', $2),
+($8, '', 'leaderboard_prize', $1, 0, 1, 10, 'none', $2),
+($9, '', 'leaderboard_prize', $1, 0, 1, 10, 'none', $2),
+($10, '', 'leaderboard_prize', $1, 0, 1, 10, 'none', $2),
+($11, '', 'leaderboard_prize', $1, 0, 1, 10, 'none', $2),
+($12, '', 'leaderboard_prize', $1, 0, 1, 10, 'none', $2)`,
}
for i, expectedString := range expectedRewardStrings {
diff --git a/lib/queues/lootboxes/lootboxes.go b/lib/queues/lootboxes/lootboxes.go
index a0a886737..a6ec6d3aa 100644
--- a/lib/queues/lootboxes/lootboxes.go
+++ b/lib/queues/lootboxes/lootboxes.go
@@ -12,13 +12,9 @@ import (
types "github.com/fluidity-money/fluidity-app/lib/types/lootboxes"
)
-const (
- TopicLootboxes = `lootboxes`
-)
+const TopicLootboxes = `lootboxes`
-type (
- Lootbox = types.Lootbox
-)
+type Lootbox = types.Lootbox
func LootboxesAll(f func(Lootbox)) {
queue.GetMessages(TopicLootboxes, func(message queue.Message) {
diff --git a/lib/types/lootboxes/lootboxes.go b/lib/types/lootboxes/lootboxes.go
index 0b2998262..d13522184 100644
--- a/lib/types/lootboxes/lootboxes.go
+++ b/lib/types/lootboxes/lootboxes.go
@@ -38,4 +38,7 @@ type Lootbox struct {
// Application is the application involved in the source transfer
Application applications.Application `json:"application"`
+
+ // Epoch of the lootbox program thats taking place
+ Epoch string `json:"epoch"`
}
diff --git a/tests/pipeline/transaction_lootbox_test.go b/tests/pipeline/transaction_lootbox_test.go
index 16a42f7cc..fc854cedd 100644
--- a/tests/pipeline/transaction_lootbox_test.go
+++ b/tests/pipeline/transaction_lootbox_test.go
@@ -116,7 +116,7 @@ func TestTransactionLootboxes(t *testing.T) {
time.Sleep(time.Second)
- allLootboxes := lootboxes_db.GetLootboxes(senderAddress, 1)
+ allLootboxes := lootboxes_db.GetLootboxes("epoch_1", senderAddress, 1)
assert.Len(t, allLootboxes, 1)
expectedLootbox := lootboxes.Lootbox{
diff --git a/web/app.fluidity.money/app/components/JoeFarmlandsOrCamelotKingdom/index.tsx b/web/app.fluidity.money/app/components/JoeFarmlandsOrCamelotKingdom/index.tsx
new file mode 100644
index 000000000..1339df2c4
--- /dev/null
+++ b/web/app.fluidity.money/app/components/JoeFarmlandsOrCamelotKingdom/index.tsx
@@ -0,0 +1,26 @@
+import styles from "./styles.css";
+
+export const JoeFarmlandsOrCamelotKingdomLinks = () => [
+ { rel: "stylesheet", href: styles },
+];
+
+const JoeFarmlandsOrCamelotKingdom = () => {
+ return (
+
+ );
+};
+
+export default JoeFarmlandsOrCamelotKingdom;
diff --git a/web/app.fluidity.money/app/components/JoeFarmlandsOrCamelotKingdom/styles.css b/web/app.fluidity.money/app/components/JoeFarmlandsOrCamelotKingdom/styles.css
new file mode 100644
index 000000000..2ac505afc
--- /dev/null
+++ b/web/app.fluidity.money/app/components/JoeFarmlandsOrCamelotKingdom/styles.css
@@ -0,0 +1,35 @@
+.joe_farmlands_or_camelot_div {
+ display: grid;
+ padding-top: 20px;
+}
+
+.joe_farmlands_or_camelot_div a {
+ grid-area: 1/1;
+ --_p: calc(-1 * var(--g));
+}
+
+.joe_farmlands_or_camelot_div img {
+ width: 100%;
+ border-radius: 10px;
+}
+
+.joe_farmlands_or_camelot_img_joe {
+ clip-path: polygon(0% 0%, 0% 100%, 100% 10%);
+}
+
+.joe_farmlands_or_camelot_img_camelot {
+ padding-top: 12px;
+ clip-path: polygon(100% 0, 0% 100%, 100% 100%);
+}
+
+.joe_farmlands_or_camelot_div img:hover {
+ transform-origin: 50% 50% 0;
+ animation: joe_farmlands_or_camelot_img_scale 100ms ease-in-out forwards;
+ z-index: -999;
+}
+
+@keyframes joe_farmlands_or_camelot_img_scale {
+ to {
+ transform: scale(1.025);
+ }
+}
diff --git a/web/app.fluidity.money/app/components/UtilityToken.tsx b/web/app.fluidity.money/app/components/UtilityToken.tsx
index d9cee2329..b71f71e26 100644
--- a/web/app.fluidity.money/app/components/UtilityToken.tsx
+++ b/web/app.fluidity.money/app/components/UtilityToken.tsx
@@ -10,7 +10,12 @@ const UtilityToken = ({ utility, ...imgProps }: IUtilityToken) => {
return ;
case "sushi":
return ;
- case "trader":
+ case "trader_joe":
+ return ;
+ case "ramses":
+ return ;
+ case "jumper":
+ return ;
case "arb":
return ;
default:
diff --git a/web/app.fluidity.money/app/components/index.ts b/web/app.fluidity.money/app/components/index.ts
index df7ea69c4..268d18965 100644
--- a/web/app.fluidity.money/app/components/index.ts
+++ b/web/app.fluidity.money/app/components/index.ts
@@ -6,3 +6,4 @@ export {
ToolTipContent,
} from "./ToolTip";
export { UtilityToken } from "./UtilityToken";
+export { JoeFarmlandsOrCamelotKingdomLinks } from "./JoeFarmlandsOrCamelotKingdom";
diff --git a/web/app.fluidity.money/app/queries/addReferral.ts b/web/app.fluidity.money/app/queries/addReferral.ts
index aaf284901..2222c90c3 100644
--- a/web/app.fluidity.money/app/queries/addReferral.ts
+++ b/web/app.fluidity.money/app/queries/addReferral.ts
@@ -40,8 +40,10 @@ const addReferral = (referrer: string, referee: string) => {
variables,
};
+ const url = "https://fluidity.hasura.app/v1/graphql";
+
return jsonPost(
- "https://fluidity.hasura.app/v1/graphql",
+ url,
body,
process.env.FLU_HASURA_SECRET
? {
diff --git a/web/app.fluidity.money/app/queries/addReferralCode.ts b/web/app.fluidity.money/app/queries/addReferralCode.ts
index 0cccdca74..5aba12969 100644
--- a/web/app.fluidity.money/app/queries/addReferralCode.ts
+++ b/web/app.fluidity.money/app/queries/addReferralCode.ts
@@ -40,8 +40,10 @@ const addReferralCode = (address: string, code: string) => {
variables,
};
+ const url = "https://fluidity.hasura.app/v1/graphql";
+
return jsonPost(
- "https://fluidity.hasura.app/v1/graphql",
+ url,
body,
process.env.FLU_HASURA_SECRET
? {
diff --git a/web/app.fluidity.money/app/queries/index.ts b/web/app.fluidity.money/app/queries/index.ts
index f71e1a3ea..a959ac1e8 100644
--- a/web/app.fluidity.money/app/queries/index.ts
+++ b/web/app.fluidity.money/app/queries/index.ts
@@ -9,3 +9,4 @@ export * from "./useReferralCount";
export * from "./addReferral";
export * from "./useReferralCode";
export * from "./addReferralCode";
+export * from "./useLootboxConfig";
diff --git a/web/app.fluidity.money/app/queries/useAirdropLeaderboard.ts b/web/app.fluidity.money/app/queries/useAirdropLeaderboard.ts
index a5326094b..c85fc0391 100644
--- a/web/app.fluidity.money/app/queries/useAirdropLeaderboard.ts
+++ b/web/app.fluidity.money/app/queries/useAirdropLeaderboard.ts
@@ -1,7 +1,7 @@
import { jsonPost, gql, fetchInternalEndpoint } from "~/util";
const queryByUserAllTime = gql`
- query AirdropLeaderboard($address: String!) {
+ query AirdropLeaderboard($epoch: lootbox_epoch!, $address: String!) {
airdrop_leaderboard(where: { address: { _eq: $address } }, limit: 1) {
user: address
rank
@@ -14,21 +14,28 @@ const queryByUserAllTime = gql`
`;
const queryAllTime = gql`
- query AirdropLeaderboard {
- airdrop_leaderboard(limit: 16, order_by: { total_lootboxes: desc }) {
+ query AirdropLeaderboard($epoch: lootbox_epoch!) {
+ airdrop_leaderboard(
+ args: { epoch_: $epoch }
+ limit: 16
+ order_by: { total_lootboxes: desc }
+ ) {
user: address
rank
referralCount: referral_count
bottles: total_lootboxes
highestRewardTier: highest_reward_tier
liquidityMultiplier: liquidity_multiplier
+ fusdcEarned: fusdc_earned
+ arbEarned: arb_earned
}
}
`;
const queryByUser24Hours = gql`
- query AirdropLeaderboard($address: String!) {
+ query AirdropLeaderboard($epoch: lootbox_epoch!, $address: String!) {
airdrop_leaderboard: airdrop_leaderboard_24_hours(
+ args: { epoch_: $epoch, application_: $application }
where: { address: { _eq: $address } }
limit: 1
) {
@@ -38,6 +45,8 @@ const queryByUser24Hours = gql`
bottles: total_lootboxes
highestRewardTier: highest_reward_tier
liquidityMultiplier: liquidity_multiplier
+ fusdcEarned: fusdc_earned
+ arbEarned: arb_earned
}
}
`;
@@ -45,6 +54,7 @@ const queryByUser24Hours = gql`
const query24Hours = gql`
query AirdropLeaderboard {
airdrop_leaderboard: airdrop_leaderboard_24_hours(
+ args: { epoch_: $epoch }
limit: 16
order_by: { total_lootboxes: desc }
) {
@@ -54,17 +64,20 @@ const query24Hours = gql`
bottles: total_lootboxes
highestRewardTier: highest_reward_tier
liquidityMultiplier: liquidity_multiplier
+ fusdcEarned: fusdc_earned
+ arbEarned: arb_earned
}
}
`;
const query24HoursByUserByApplication = gql`
query AirdropLeaderboardApplication(
+ $epoch: lootbox_epoch!
$application: ethereum_application!
$address: String!
) {
airdrop_leaderboard: airdrop_leaderboard_24_hours_by_application(
- args: { application_: $application }
+ args: { epoch_: $epoch, application_: $application }
where: { address: { _eq: $address } }
limit: 1
) {
@@ -74,14 +87,19 @@ const query24HoursByUserByApplication = gql`
bottles: total_lootboxes
highestRewardTier: highest_reward_tier
liquidityMultiplier: liquidity_multiplier
+ fusdcEarned: fusdc_earned
+ arbEarned: arb_earned
}
}
`;
const query24HoursByApplication = gql`
- query AirdropLeaderboardByApplication($application: ethereum_application!) {
+ query AirdropLeaderboardByApplication(
+ $epoch: lootbox_epoch!
+ $application: ethereum_application!
+ ) {
airdrop_leaderboard: airdrop_leaderboard_24_hours_by_application(
- args: { application_: $application }
+ args: { epoch_: $epoch, application_: $application }
limit: 16
order_by: { total_lootboxes: desc }
) {
@@ -91,6 +109,8 @@ const query24HoursByApplication = gql`
bottles: total_lootboxes
highestRewardTier: highest_reward_tier
liquidityMultiplier: liquidity_multiplier
+ fusdcEarned: fusdc_earned
+ arbEarned: arb_earned
}
}
`;
@@ -125,6 +145,8 @@ export type AirdropLeaderboardEntry = {
bottles: number;
highestRewardTier: number;
liquidityMultiplier: number;
+ fusdcEarned: number;
+ arbEarned: number;
};
type AirdropLeaderboardResponse = {
@@ -134,10 +156,14 @@ type AirdropLeaderboardResponse = {
errors?: unknown;
};
-export const useAirdropLeaderboardByUserAllTime = (address: string) => {
+export const useAirdropLeaderboardByUserAllTime = (
+ epoch: string,
+ address: string
+) => {
const { url, headers } = fetchInternalEndpoint();
const variables = {
+ epoch,
address,
};
const body = {
@@ -152,10 +178,12 @@ export const useAirdropLeaderboardByUserAllTime = (address: string) => {
);
};
-export const useAirdropLeaderboardAllTime = () => {
+export const useAirdropLeaderboardAllTime = (epoch: string) => {
const { url, headers } = fetchInternalEndpoint();
+ const variables = { epoch };
const body = {
query: queryAllTime,
+ variables,
};
return jsonPost(
@@ -165,11 +193,15 @@ export const useAirdropLeaderboardAllTime = () => {
);
};
-export const useAirdropLeaderboardByUser24Hours = (address: string) => {
+export const useAirdropLeaderboardByUser24Hours = (
+ epoch: string,
+ address: string
+) => {
const { url, headers } = fetchInternalEndpoint();
const variables = {
address,
+ epoch,
};
const body = {
query: queryByUser24Hours,
@@ -183,9 +215,11 @@ export const useAirdropLeaderboardByUser24Hours = (address: string) => {
);
};
-export const useAirdropLeaderboard24Hours = () => {
+export const useAirdropLeaderboard24Hours = (epoch: string) => {
const { url, headers } = fetchInternalEndpoint();
+ const variables = { epoch };
const body = {
+ variables,
query: query24Hours,
};
@@ -197,12 +231,14 @@ export const useAirdropLeaderboard24Hours = () => {
};
export const useAirdropLeaderboardByUserByApplication24Hours = (
+ epoch: string,
address: string,
application: string
) => {
const { url, headers } = fetchInternalEndpoint();
const variables = {
+ epoch,
address,
application,
};
@@ -218,10 +254,12 @@ export const useAirdropLeaderboardByUserByApplication24Hours = (
};
export const useAirdropLeaderboardByApplication24Hours = (
+ epoch: string,
application: string
) => {
const { url, headers } = fetchInternalEndpoint();
const variables = {
+ epoch,
application,
};
const body = {
diff --git a/web/app.fluidity.money/app/queries/useAirdropStats.ts b/web/app.fluidity.money/app/queries/useAirdropStats.ts
index 25828ab32..f712c4d77 100644
--- a/web/app.fluidity.money/app/queries/useAirdropStats.ts
+++ b/web/app.fluidity.money/app/queries/useAirdropStats.ts
@@ -3,12 +3,15 @@ import { BottleTiers } from "~/routes/$network/query/dashboard/airdrop";
import { jsonPost, gql, fetchInternalEndpoint } from "~/util";
const queryAirdropStatsByAddress = gql`
- query AirdropStats($address: String!, $now: timestamp!) {
- lootboxCounts: lootbox_counts(where: { address: { _eq: $address } }) {
+ query AirdropStats($epoch: lootbox_epoch!, $address: String!, $now: timestamp!) {
+ lootboxCounts: lootbox_counts(
+ args: { epoch_: $epoch }
+ where: { address: { _eq: $address } }
+ ) {
${Rarity.Common}: tier1
${Rarity.Uncommon}: tier2
${Rarity.Rare}: tier3
- ${Rarity.UltraRare}: tier4
+ ${Rarity.UltraRare}: tier4
${Rarity.Legendary}: tier5
}
liquidityMultiplier: calculate_a_y(
@@ -26,11 +29,15 @@ const queryAirdropStatsByAddress = gql`
}
`;
-export const useAirdropStatsByAddress = async (address: string) => {
+export const useAirdropStatsByAddress = async (
+ address: string,
+ epoch: string
+) => {
const { url, headers } = fetchInternalEndpoint();
const variables = {
address,
+ epoch,
now: new Date().toISOString(),
};
const body = {
diff --git a/web/app.fluidity.money/app/queries/useApplicationRewardStatistics.ts b/web/app.fluidity.money/app/queries/useApplicationRewardStatistics.ts
index a5a5336b5..e6252aba7 100644
--- a/web/app.fluidity.money/app/queries/useApplicationRewardStatistics.ts
+++ b/web/app.fluidity.money/app/queries/useApplicationRewardStatistics.ts
@@ -41,7 +41,9 @@ const useApplicationRewardStatistics = async (
network: T | string
) => {
const variables = { network };
+
const url = "https://fluidity.hasura.app/v1/graphql";
+
const body = {
variables,
query: query,
diff --git a/web/app.fluidity.money/app/queries/useAssetStatistics.ts b/web/app.fluidity.money/app/queries/useAssetStatistics.ts
index 11bd89fe2..366fb6828 100644
--- a/web/app.fluidity.money/app/queries/useAssetStatistics.ts
+++ b/web/app.fluidity.money/app/queries/useAssetStatistics.ts
@@ -86,10 +86,10 @@ const useAssetStatistics = (
},
};
- const fluGqlEndpoint = "https://fluidity.hasura.app/v1/graphql";
+ const url = "https://fluidity.hasura.app/v1/graphql";
return jsonPost(
- fluGqlEndpoint,
+ url,
body,
process.env.FLU_HASURA_SECRET
? {
diff --git a/web/app.fluidity.money/app/queries/useLootBottles.ts b/web/app.fluidity.money/app/queries/useLootBottles.ts
index f48ec6542..6f5025298 100644
--- a/web/app.fluidity.money/app/queries/useLootBottles.ts
+++ b/web/app.fluidity.money/app/queries/useLootBottles.ts
@@ -41,8 +41,10 @@ const useLootboxesByTxHash = (filterHashes: string[]) => {
variables,
};
+ const url = "https://fluidity.hasura.app/v1/graphql";
+
return jsonPost(
- "https://fluidity.hasura.app/v1/graphql",
+ url,
body,
process.env.FLU_HASURA_SECRET
? {
diff --git a/web/app.fluidity.money/app/queries/useLootBottlesCount.ts b/web/app.fluidity.money/app/queries/useLootBottlesCount.ts
index 60f1927c4..34c28658f 100644
--- a/web/app.fluidity.money/app/queries/useLootBottlesCount.ts
+++ b/web/app.fluidity.money/app/queries/useLootBottlesCount.ts
@@ -3,8 +3,11 @@ import { BottleTiers } from "~/routes/$network/query/dashboard/airdrop";
import { jsonPost, gql, fetchInternalEndpoint } from "~/util";
const QUERY_REFERRALS_BY_ADDRESS = gql`
- query getReferralLootboxCountByAddress($address: String!) {
- referralLootboxCounts: lootbox_referral_lootbottle_counts(where: { address: { _eq: $address } }) {
+ query getReferralLootboxCountByAddress($epoch: String!, $address: String!) {
+ referralLootboxCounts: lootbox_referral_lootbottle_counts(
+ args: { epoch_: $epoch }
+ where: { address: { _eq: $address } }
+ ) {
${Rarity.Common}: tier1
${Rarity.Uncommon}: tier2
${Rarity.Rare}: tier3
@@ -18,6 +21,7 @@ type ReferralLootboxCountBody = {
query: string;
variables: {
address: string;
+ epoch: string;
};
};
@@ -28,10 +32,11 @@ type ReferralLootboxCountRes = {
errors?: unknown;
};
-const useReferralLootboxesByAddress = (address: string) => {
+const useReferralLootboxesByAddress = (epoch: string, address: string) => {
const { url, headers } = fetchInternalEndpoint();
const variables = {
+ epoch,
address,
};
diff --git a/web/app.fluidity.money/app/queries/useLootboxConfig.ts b/web/app.fluidity.money/app/queries/useLootboxConfig.ts
new file mode 100644
index 000000000..e2aed0dc1
--- /dev/null
+++ b/web/app.fluidity.money/app/queries/useLootboxConfig.ts
@@ -0,0 +1,72 @@
+import { jsonPost, gql, fetchInternalEndpoint } from "~/util";
+
+const queryGetConfigCurrentProgram = gql`
+ query getLootboxConfig {
+ lootboxConfig: lootbox_config(
+ where: { is_current_program: { _eq: true } }
+ limit: 1
+ ) {
+ programBegin: program_begin
+ programEnd: program_end
+ epochIdentifier: epoch_identifier
+ ethereumApplication: ethereum_application
+ }
+ }
+`;
+
+const queryGetConfigSpecific = gql`
+ query getLootboxConfig($identifier: lootbox_epoch!) {
+ lootboxConfig: lootbox_config(
+ where: { epoch_identifier: { _eq: $identifier } }
+ limit: 1
+ ) {
+ programBegin: program_begin
+ programEnd: program_end
+ epochIdentifier: epoch_identifier
+ ethereumApplication: ethereum_application
+ }
+ }
+`;
+
+type LootboxConfigBody = {
+ query: string;
+};
+
+export type LootboxConfig = {
+ programBegin: string;
+ programEnd: string;
+ epochIdentifier: string;
+ ethereumApplication: string;
+ found: boolean;
+};
+
+type LootboxConfigResponse = {
+ data?: {
+ lootboxConfig: Array;
+ };
+ errors?: unknown;
+};
+
+type IUseLootboxConfig = {
+ identifier: string | undefined;
+ shouldFind: boolean | undefined;
+};
+
+export const useLootboxConfig = ({
+ identifier,
+ shouldFind,
+}: IUseLootboxConfig) => {
+ const { url, headers } = fetchInternalEndpoint();
+
+ const body = (() =>
+ shouldFind
+ ? {
+ query: queryGetConfigCurrentProgram,
+ }
+ : {
+ query: queryGetConfigSpecific,
+ variables: { identifier },
+ })();
+
+ return jsonPost(url, body, headers);
+};
diff --git a/web/app.fluidity.money/app/queries/useReferralCode.ts b/web/app.fluidity.money/app/queries/useReferralCode.ts
index b6cd6c5d9..75db76633 100644
--- a/web/app.fluidity.money/app/queries/useReferralCode.ts
+++ b/web/app.fluidity.money/app/queries/useReferralCode.ts
@@ -54,8 +54,10 @@ const useReferralCodeByAddress = (address: string) => {
variables,
};
+ const url = "https://fluidity.hasura.app/v1/graphql";
+
return jsonPost(
- "https://fluidity.hasura.app/v1/graphql",
+ url,
body,
process.env.FLU_HASURA_SECRET
? {
@@ -75,8 +77,10 @@ const useReferralCodeByCode = (code: string) => {
variables,
};
+ const url = "https://fluidity.hasura.app/v1/graphql";
+
return jsonPost(
- "https://fluidity.hasura.app/v1/graphql",
+ url,
body,
process.env.FLU_HASURA_SECRET
? {
diff --git a/web/app.fluidity.money/app/queries/useReferralCount.ts b/web/app.fluidity.money/app/queries/useReferralCount.ts
index aabd612b2..0a6ed9fec 100644
--- a/web/app.fluidity.money/app/queries/useReferralCount.ts
+++ b/web/app.fluidity.money/app/queries/useReferralCount.ts
@@ -64,8 +64,10 @@ const useActiveReferralCountByReferrerAddress = (address: string) => {
variables,
};
+ const url = "https://fluidity.hasura.app/v1/graphql";
+
return jsonPost(
- "https://fluidity.hasura.app/v1/graphql",
+ url,
body,
process.env.FLU_HASURA_SECRET
? {
@@ -85,8 +87,10 @@ const useActiveReferralCountByRefereeAddress = (address: string) => {
variables,
};
+ const url = "https://fluidity.hasura.app/v1/graphql";
+
return jsonPost(
- "https://fluidity.hasura.app/v1/graphql",
+ url,
body,
process.env.FLU_HASURA_SECRET
? {
@@ -106,8 +110,10 @@ const useInactiveReferralCountByRefereeAddress = (address: string) => {
variables,
};
+ const url = "https://fluidity.hasura.app/v1/graphql";
+
return jsonPost(
- "https://fluidity.hasura.app/v1/graphql",
+ url,
body,
process.env.FLU_HASURA_SECRET
? {
diff --git a/web/app.fluidity.money/app/queries/useReferrals.ts b/web/app.fluidity.money/app/queries/useReferrals.ts
index 0da3ee93a..731f4b8af 100644
--- a/web/app.fluidity.money/app/queries/useReferrals.ts
+++ b/web/app.fluidity.money/app/queries/useReferrals.ts
@@ -71,8 +71,10 @@ const useReferralByAddress = (referrer: string, referee: string) => {
variables,
};
+ const url = "https://fluidity.hasura.app/v1/graphql";
+
return jsonPost(
- "https://fluidity.hasura.app/v1/graphql",
+ url,
body,
process.env.FLU_HASURA_SECRET
? {
@@ -92,8 +94,10 @@ const useInactiveReferralByAddress = (address: string) => {
variables,
};
+ const url = "https://fluidity.hasura.app/v1/graphql";
+
return jsonPost(
- "https://fluidity.hasura.app/v1/graphql",
+ url,
body,
process.env.FLU_HASURA_SECRET
? {
diff --git a/web/app.fluidity.money/app/queries/useStakingData.ts b/web/app.fluidity.money/app/queries/useStakingData.ts
index 9d43759f1..1d335af2f 100644
--- a/web/app.fluidity.money/app/queries/useStakingData.ts
+++ b/web/app.fluidity.money/app/queries/useStakingData.ts
@@ -24,7 +24,9 @@ export const useStakingDataByAddress = async (
address: `0x${"0".repeat(24)}${address.slice(2)}`,
days_elapsed: daysElapsed,
};
+
const url = "https://fluidity.hasura.app/v1/graphql";
+
const body = {
variables,
query: queryStakingDataByAddress,
diff --git a/web/app.fluidity.money/app/queries/useTokens.ts b/web/app.fluidity.money/app/queries/useTokens.ts
index 4dad1bd8f..7b16eb8a7 100644
--- a/web/app.fluidity.money/app/queries/useTokens.ts
+++ b/web/app.fluidity.money/app/queries/useTokens.ts
@@ -23,10 +23,12 @@ export type Asset = {
};
export const useTokens = async () => {
+ const url = "https://fluidity.hasura.app/v1/graphql";
+
const {
data: { asset },
} = await jsonPost(
- "https://fluidity.hasura.app/v1/graphql",
+ url,
{ query: tokenQuery },
process.env.FLU_HASURA_SECRET
? {
diff --git a/web/app.fluidity.money/app/queries/useUserActionsAggregate.ts b/web/app.fluidity.money/app/queries/useUserActionsAggregate.ts
index 546ddebb2..7f037e802 100644
--- a/web/app.fluidity.money/app/queries/useUserActionsAggregate.ts
+++ b/web/app.fluidity.money/app/queries/useUserActionsAggregate.ts
@@ -10,120 +10,149 @@ export type AggregatedTransaction = Omit<
swap_in: boolean;
type: "send" | "swap";
timestamp: string;
+ rewardTier: number;
+ lootboxCount: number;
};
const queryByAddress: Queryable = {
arbitrum: gql`
- query AggregatedUserTransactionsByAddress($offset: Int = 0, $limit: Int = 12, $address: String!, $token: String) {
- arbitrum: aggregated_user_transactions(
- order_by: {time: desc},
- limit: $limit,
- offset: $offset,
- where: {
- network: {_eq: "arbitrum"}
- token_short_name: {_eq: $token},
- type: {_is_null: false},
- _or: [
- {sender_address: {_eq: $address}},
- {recipient_address: {_eq: $address}}
- ]
- }
+ query AggregatedUserTransactionsByAddress(
+ $offset: Int = 0
+ $limit: Int = 12
+ $address: String!
+ $token: String
) {
- value: amount
- application
- network
- receiver: recipient_address
- rewardHash: reward_hash
- sender: sender_address
- swap_in
- timestamp: time
- currency: token_short_name
- hash: transaction_hash
- type
- utility_amount
- utility_name
- winner: winning_address
- reward: winning_amount
+ arbitrum: aggregated_user_transactions_lootbottles(
+ order_by: { time: desc }
+ limit: $limit
+ offset: $offset
+ where: {
+ network: { _eq: "arbitrum" }
+ token_short_name: { _eq: $token }
+ type: { _is_null: false }
+ _or: [
+ { sender_address: { _eq: $address } }
+ { recipient_address: { _eq: $address } }
+ ]
+ }
+ ) {
+ value: amount
+ application
+ network
+ receiver: recipient_address
+ rewardHash: reward_hash
+ sender: sender_address
+ swap_in
+ timestamp: time
+ currency: token_short_name
+ hash: transaction_hash
+ type
+ utility_amount
+ utility_name
+ winner: winning_address
+ reward: winning_amount
+ rewardTier: reward_tier
+ lootboxCount: lootbox_count
+ }
}
- }
`,
solana: gql`
- query AggregatedUserTransactionsByAddress($offset: Int = 0, $limit: Int = 12, $address: String!) {
- solana: aggregated_user_transactions(
- order_by: {time: desc},
- limit: $limit,
- offset: $offset,
- where: {
- network: {_eq: "solana"}
- type: {_is_null: false},
- _or: [
- {sender_address: {_eq: $address}},
- {recipient_address: {_eq: $address}}
- ]
- }
+ query AggregatedUserTransactionsByAddress(
+ $offset: Int = 0
+ $limit: Int = 12
+ $address: String!
) {
- value: amount
- application
- network
- receiver: recipient_address
- rewardHash: reward_hash
- sender: sender_address
- swap_in
- timestamp: time
- currency: token_short_name
- hash: transaction_hash
- type
- utility_amount
- utility_name
- winner: winning_address
- reward: winning_amount
+ solana: aggregated_user_transactions_lootbottles(
+ order_by: { time: desc }
+ limit: $limit
+ offset: $offset
+ where: {
+ network: { _eq: "solana" }
+ type: { _is_null: false }
+ _or: [
+ { sender_address: { _eq: $address } }
+ { recipient_address: { _eq: $address } }
+ ]
+ }
+ ) {
+ value: amount
+ application
+ network
+ receiver: recipient_address
+ rewardHash: reward_hash
+ sender: sender_address
+ swap_in
+ timestamp: time
+ currency: token_short_name
+ hash: transaction_hash
+ type
+ utility_amount
+ utility_name
+ winner: winning_address
+ reward: winning_amount
+ rewardTier: reward_tier
+ lootboxCount: lootbox_count
+ }
}
- }
`,
};
const queryAll: Queryable = {
arbitrum: gql`
- query aggregatedUserTransactionsAll ($offset: Int = 0, $limit: Int = 12) {
- arbitrum: aggregated_user_transactions(order_by: {time: desc}, limit: $limit, offset: $offset, where: {network: {_eq: "arbitrum"}, type: {_is_null: false}}) {
- value: amount
- application
- network
- receiver: recipient_address
- rewardHash: reward_hash
- sender: sender_address
- swap_in
- timestamp: time
- currency: token_short_name
- hash: transaction_hash
- type
- utility_amount
- utility_name
- winner: winning_address
- reward: winning_amount
+ query aggregatedUserTransactionsAll($offset: Int = 0, $limit: Int = 12) {
+ arbitrum: aggregated_user_transactions_lootbottles(
+ order_by: { time: desc }
+ limit: $limit
+ offset: $offset
+ where: { network: { _eq: "arbitrum" }, type: { _is_null: false } }
+ ) {
+ value: amount
+ application
+ network
+ receiver: recipient_address
+ rewardHash: reward_hash
+ sender: sender_address
+ swap_in
+ timestamp: time
+ currency: token_short_name
+ hash: transaction_hash
+ type
+ utility_amount
+ utility_name
+ winner: winning_address
+ reward: winning_amount
+ rewardTier: reward_tier
+ lootboxCount: lootbox_count
+ }
}
- }
`,
solana: gql`
- query aggregatedUserTransactionsAll ($offset: Int = 0, $limit: Int = 12) {
- solana: aggregated_user_transactions(order_by: {time: desc}, limit: $limit, offset: $offset, where: {network: {_eq: "solana"}, type: {_is_null: false}}) {
- value: amount
- application
- network
- receiver: recipient_address
- rewardHash: reward_hash
- sender: sender_address
- swap_in
- timestamp: time
- currency: token_short_name
- hash: transaction_hash
- type
- utility_amount
- utility_name
- winner: winning_address
- reward: winning_amount
+ query aggregatedUserTransactionsAll($offset: Int = 0, $limit: Int = 12) {
+ solana: aggregated_user_transactions_lootbottles(
+ order_by: { time: desc }
+ limit: $limit
+ offset: $offset
+ where: { network: { _eq: "solana" }, type: { _is_null: false } }
+ ) {
+ value: amount
+ application
+ network
+ receiver: recipient_address
+ rewardHash: reward_hash
+ sender: sender_address
+ swap_in
+ timestamp: time
+ currency: token_short_name
+ hash: transaction_hash
+ type
+ utility_amount
+ utility_name
+ winner: winning_address
+ reward: winning_amount
+ rewardTier: reward_tier
+ lootboxCount: lootbox_count
+ }
}
- }
`,
};
diff --git a/web/app.fluidity.money/app/queries/useUserRewards.ts b/web/app.fluidity.money/app/queries/useUserRewards.ts
index 06654c913..d494224b1 100644
--- a/web/app.fluidity.money/app/queries/useUserRewards.ts
+++ b/web/app.fluidity.money/app/queries/useUserRewards.ts
@@ -196,7 +196,9 @@ const useUserRewardsAll = async (network: string) => {
const useUserRewardsByAddress = async (network: string, address: string) => {
const variables = { network, address };
+
const url = "https://fluidity.hasura.app/v1/graphql";
+
const body = {
variables,
query: queryWinnersByAddress[network as Chain],
diff --git a/web/app.fluidity.money/app/queries/useUserTransactions.ts b/web/app.fluidity.money/app/queries/useUserTransactions.ts
index b7c8f0012..8db0ae4f9 100644
--- a/web/app.fluidity.money/app/queries/useUserTransactions.ts
+++ b/web/app.fluidity.money/app/queries/useUserTransactions.ts
@@ -21,7 +21,7 @@ const queryByAddress: Queryable = {
$limit: Int = 12
$tokens: [String!] = []
) {
- transfers: user_actions(
+ transfers: user_actions_lootbottles(
where: {
network: { _eq: "arbitrum" }
token_short_name: { _in: $tokens }
@@ -45,6 +45,8 @@ const queryByAddress: Queryable = {
type
swap_in
application
+ rewardTier: reward_tier
+ lootboxCount: lootbox_count
}
}
`,
@@ -57,7 +59,7 @@ const queryByAddress: Queryable = {
$limit: Int = 12
$tokens: [String!] = []
) {
- transfers: user_actions(
+ transfers: user_actions_lootbottles(
where: {
network: { _eq: "solana" }
token_short_name: { _in: $tokens }
@@ -81,6 +83,8 @@ const queryByAddress: Queryable = {
type
swap_in
application
+ rewardTier: reward_tier
+ lootboxCount: lootbox_count
}
}
`,
@@ -93,7 +97,7 @@ const queryByAddress: Queryable = {
$limit: Int = 12
$tokens: [String!] = []
) {
- transfers: user_actions(
+ transfers: user_actions_lootbottles(
where: {
network: { _eq: "polygon_zk" }
token_short_name: { _in: $tokens }
@@ -117,6 +121,8 @@ const queryByAddress: Queryable = {
type
swap_in
application
+ rewardTier: reward_tier
+ lootboxCount: lootbox_count
}
}
`,
@@ -129,7 +135,7 @@ const queryByTxHash: Queryable = {
$filterHashes: [String!] = []
$limit: Int = 12
) {
- transfers: user_actions(
+ transfers: user_actions_lootbottles(
where: {
network: { _eq: "arbitrum" }
_not: { transaction_hash: { _in: $filterHashes } }
@@ -148,6 +154,8 @@ const queryByTxHash: Queryable = {
type
swap_in
application
+ rewardTier: reward_tier
+ lootboxCount: lootbox_count
}
}
`,
@@ -157,7 +165,7 @@ const queryByTxHash: Queryable = {
$filterHashes: [String!] = []
$limit: Int = 12
) {
- transfers: user_actions(
+ transfers: user_actions_lootbottles(
where: {
network: { _eq: "solana" }
_not: { transaction_hash: { _in: $filterHashes } }
@@ -176,6 +184,8 @@ const queryByTxHash: Queryable = {
type
swap_in
application
+ rewardTier: reward_tier
+ lootboxCount: lootbox_count
}
}
`,
@@ -186,7 +196,7 @@ const queryByTxHash: Queryable = {
$filterHashes: [String!] = []
$limit: Int = 12
) {
- transfers: user_actions(
+ transfers: user_actions_lootbottles(
where: {
network: { _eq: "polygon_zk" }
_not: { transaction_hash: { _in: $filterHashes } }
@@ -205,6 +215,8 @@ const queryByTxHash: Queryable = {
type
swap_in
application
+ rewardTier: reward_tier
+ lootboxCount: lootbox_count
}
}
`,
@@ -218,7 +230,7 @@ const queryAll: Queryable = {
$limit: Int = 12
$tokens: [String!] = []
) {
- transfers: user_actions(
+ transfers: user_actions_lootbottles(
where: {
network: { _eq: "arbitrum" }
_not: { transaction_hash: { _in: $filterHashes } }
@@ -238,6 +250,8 @@ const queryAll: Queryable = {
type
swap_in
application
+ rewardTier: reward_tier
+ lootboxCount: lootbox_count
}
}
`,
@@ -249,7 +263,7 @@ const queryAll: Queryable = {
$limit: Int = 12
$tokens: [String!] = []
) {
- transfers: user_actions(
+ transfers: user_actions_lootbottles(
where: {
network: { _eq: "solana" }
_not: { transaction_hash: { _in: $filterHashes } }
@@ -269,6 +283,8 @@ const queryAll: Queryable = {
type
swap_in
application
+ rewardTier: reward_tier
+ lootboxCount: lootbox_count
}
}
`,
@@ -280,7 +296,7 @@ const queryAll: Queryable = {
$limit: Int = 12
$tokens: [String!] = []
) {
- transfers: user_actions(
+ transfers: user_actions_lootbottles(
where: {
network: { _eq: "polygon_zk" }
_not: { transaction_hash: { _in: $filterHashes } }
@@ -300,6 +316,8 @@ const queryAll: Queryable = {
type
swap_in
application
+ rewardTier: reward_tier
+ lootboxCount: lootbox_count
}
}
`,
@@ -349,6 +367,8 @@ export type UserTransaction = {
amount: number;
currency: { symbol: string };
application: string;
+ lootboxCount: number;
+ rewardTier: number;
};
type HasuraUserTransaction = {
@@ -362,6 +382,8 @@ type HasuraUserTransaction = {
type: "swap" | "send";
swap_in: boolean;
application: string;
+ rewardTier: number;
+ lootboxCount: number;
};
export type HasuraUserTransactionRes = {
@@ -542,6 +564,8 @@ const parseHasuraUserTransactions = (
timestamp: { unixtime: hasuraDateToUnix(transfer.time) },
},
application: transfer.application,
+ lootboxCount: transfer.lootboxCount,
+ rewardTier: transfer.rewardTier,
};
}),
},
diff --git a/web/app.fluidity.money/app/queries/useUserUnclaimedRewards.ts b/web/app.fluidity.money/app/queries/useUserUnclaimedRewards.ts
index d7152d5ce..7ce75f5de 100644
--- a/web/app.fluidity.money/app/queries/useUserUnclaimedRewards.ts
+++ b/web/app.fluidity.money/app/queries/useUserUnclaimedRewards.ts
@@ -82,10 +82,10 @@ const useUserUnclaimedRewards = async (network: string, address: string) => {
},
};
- const fluGqlEndpoint = "https://fluidity.hasura.app/v1/graphql";
+ const url = "https://fluidity.hasura.app/v1/graphql";
return jsonPost(
- fluGqlEndpoint,
+ url,
body,
process.env.FLU_HASURA_SECRET
? {
diff --git a/web/app.fluidity.money/app/root.tsx b/web/app.fluidity.money/app/root.tsx
index 819c7a8cd..226392f24 100644
--- a/web/app.fluidity.money/app/root.tsx
+++ b/web/app.fluidity.money/app/root.tsx
@@ -15,7 +15,7 @@ import { withSentry } from "@sentry/remix";
import globalStylesheetUrl from "./global-styles.css";
import surfingStylesheetUrl from "@fluidity-money/surfing/dist/style.css";
-import { ToolTipLinks } from "./components";
+import { JoeFarmlandsOrCamelotKingdomLinks, ToolTipLinks } from "./components";
import { ToolProvider } from "./components/ToolTip";
import { SplitContextProvider } from "contexts/SplitProvider";
import CacheProvider from "contexts/CacheProvider";
@@ -29,6 +29,7 @@ globalThis.Buffer = Buffer;
export const links = () => {
return [
...ToolTipLinks(),
+ ...JoeFarmlandsOrCamelotKingdomLinks(),
{ rel: "icon", href: "/favicon.ico" },
{ rel: "apple-touch-icon", sizes: "57x57", href: "/apple-icon-57x57.png" },
diff --git a/web/app.fluidity.money/app/routes/$network/dashboard.tsx b/web/app.fluidity.money/app/routes/$network/dashboard.tsx
index 80dec9167..eb585bbc9 100644
--- a/web/app.fluidity.money/app/routes/$network/dashboard.tsx
+++ b/web/app.fluidity.money/app/routes/$network/dashboard.tsx
@@ -461,53 +461,49 @@ export default function Dashboard() {
{/* Referral Modal */}
- {false && (
- setReferralModalVisibility(false)}
- cardPositionStyle={{
- position: "absolute",
- top: "1em",
- right: isTablet ? "20px" : "60px",
- width: 500,
+ setReferralModalVisibility(false)}
+ cardPositionStyle={{
+ position: "absolute",
+ top: "1em",
+ right: isTablet ? "20px" : "60px",
+ width: 500,
+ }}
+ color="holo"
+ style={{ padding: 0, width: "100%" }}
+ >
+ {
+ setReferralModalVisibility(false);
+ setWalletModalVisibility(true);
}}
- color="holo"
- style={{ padding: 0, width: "100%" }}
- >
- {
- setReferralModalVisibility(false);
- setWalletModalVisibility(true);
- }}
- referrerClaimed={numActiveReferrerReferrals}
- refereeClaimed={numActiveReferreeReferrals}
- refereeUnclaimed={numInactiveReferreeReferrals}
- progress={inactiveReferrals[0]?.progress || 0}
- progressReq={10}
- referralCode={referralCode}
- loaded={referralCountLoaded}
- closeModal={() => setReferralModalVisibility(false)}
- />
-
- )}
+ referrerClaimed={numActiveReferrerReferrals}
+ refereeClaimed={numActiveReferreeReferrals}
+ refereeUnclaimed={numInactiveReferreeReferrals}
+ progress={inactiveReferrals[0]?.progress || 0}
+ progressReq={10}
+ referralCode={referralCode}
+ loaded={referralCountLoaded}
+ closeModal={() => setReferralModalVisibility(false)}
+ />
+
{/* Accept Referral Modal */}
- {false && (
- setAcceptReferralModalVisibility(false)}
- >
-
-
- )}
+ setAcceptReferralModalVisibility(false)}
+ >
+
+
{/* Fluidify Money button, in a portal with z-index above tooltip if another modal isn't open */}
@@ -679,36 +675,32 @@ export default function Dashboard() {
{/* Referrals Button */}
- {false && (
- {
- width < airdropMobileBreakpoint
- ? navigate(`/${network}/dashboard/airdrop#referrals`)
- : setReferralModalVisibility(true);
- }}
- icon={}
- >
- {isMobile ? "" : "Referral"}
-
- )}
+ {
+ width < airdropMobileBreakpoint
+ ? navigate(`/${network}/dashboard/airdrop#referrals`)
+ : setReferralModalVisibility(true);
+ }}
+ icon={}
+ >
+ {isMobile ? "" : "Referral"}
+
{/* Fluidify button */}
- {otherModalOpen && showExperiment("Fluidify-Button-Placement") && (
- {
- client?.track("user", "click_fluidify");
- navigate(`/${network}/fluidify`);
- }}
- >
- Fluidify{isMobile ? "" : " Money"}
-
- )}
+ {
+ client?.track("user", "click_fluidify");
+ navigate(`/${network}/fluidify`);
+ }}
+ >
+ Fluidify{isMobile ? "" : " Money"}
+
{/* Prize Money */}
{
export const loader: LoaderFunction = async ({ params }) => {
const network = params.network ?? "";
- const epochDays = dayDifference(new Date(), EPOCH_START_DATE);
-
// Staking Tokens
const allowedTokenSymbols = new Set(["fUSDC", "USDC", "wETH"]);
const { tokens } = config.config[network];
@@ -98,16 +93,12 @@ export const loader: LoaderFunction = async ({ params }) => {
return json({
tokens: allowedTokens,
- epochDaysTotal: EPOCH_DAYS_TOTAL,
- epochDays,
network,
} satisfies LoaderData);
};
type LoaderData = {
tokens: Array;
- epochDaysTotal: number;
- epochDays: number;
network: string;
};
@@ -122,9 +113,15 @@ const SAFE_DEFAULT_AIRDROP: AirdropLoaderData = {
},
bottlesCount: 0,
liquidityMultiplier: 0,
- stakes: [],
wethPrice: 0,
usdcPrice: 0,
+ programBegin: new Date("2023-05-01T12:00:00+02:00"),
+ programEnd: new Date("2023-06-28 T12:00:00+02:00"),
+ epochDaysTotal: 30,
+ epochDaysElapsed: 30,
+ epochIdentifier: "epoch_1",
+ ethereumApplication: "none",
+ epochFound: false,
loaded: false,
};
@@ -163,12 +160,7 @@ const GLOBAL_AIRDROP_BOTTLE_TIERS = {
};
const Airdrop = () => {
- const {
- epochDaysTotal,
- epochDays,
- tokens: defaultTokens,
- network,
- } = useLoaderData();
+ const { tokens: defaultTokens, network } = useLoaderData();
if (network !== "arbitrum") {
return (
@@ -177,7 +169,8 @@ const Airdrop = () => {
Airdrop
- Wrap, Transact and Earn using $fUSDC, provide liquidity for even more rewards!
+ Wrap, Transact and Earn using $fUSDC, provide liquidity for even more
+ rewards!
);
@@ -207,42 +200,47 @@ const Airdrop = () => {
address,
balance,
stakeTokens,
- getStakingDeposits,
testStakeTokens,
getStakingRatios,
redeemableTokens: getRedeemableTokens,
redeemTokens,
} = useContext(FluidityFacadeContext);
+ const { width } = useViewport();
+
+ const navigate = useNavigate();
+
+ const mobileBreakpoint = 768;
+
+ const isMobile = width < mobileBreakpoint;
+
const { data: airdropData } = useCache(
- address ? `/${network}/query/dashboard/airdrop?address=${address}` : ""
+ address
+ ? `/${network}/query/dashboard/airdrop?address=${address}&epoch=${EPOCH_CURRENT_IDENTIFIER}`
+ : ""
);
const { data: airdropLeaderboardData } = useCache(
`/${network}/query/dashboard/airdropLeaderboard?period=${
leaderboardFilterIndex === 0 ? "24" : "all"
}&address=${address ?? ""}${
- leaderboardFilterIndex === 0 ? "&provider=kyber_classic" : ""
- }`
+ leaderboardFilterIndex === 0 ? "&provider=${currentApplication}" : ""
+ }&epoch=${EPOCH_CURRENT_IDENTIFIER}`
);
const { data: referralData } = useCache(
- address ? `/${network}/query/referrals?address=${address}` : ""
+ address
+ ? `/${network}/query/referrals?address=${address}&epoch=${EPOCH_CURRENT_IDENTIFIER}`
+ : ""
);
const { data: referralLootboxData } =
useCache(
- address ? `/${network}/query/referralBottles?address=${address}` : ""
+ address
+ ? `/${network}/query/referralBottles?address=${address}&epoch=${EPOCH_CURRENT_IDENTIFIER}`
+ : ""
);
- const { width } = useViewport();
-
- const navigate = useNavigate();
-
- const mobileBreakpoint = 768;
-
- const isMobile = width < mobileBreakpoint;
-
const data = {
airdrop: {
...SAFE_DEFAULT_AIRDROP,
@@ -269,6 +267,8 @@ const Airdrop = () => {
bottlesCount,
wethPrice,
usdcPrice,
+ epochDaysTotal,
+ epochDaysElapsed,
},
referrals: {
numActiveReferreeReferrals,
@@ -292,7 +292,7 @@ const Airdrop = () => {
const destModal = location.hash.replace("#", "");
const [currentModal, setCurrentModal] = useState(
- isAirdropModal(destModal) ? destModal : "recap"
+ isAirdropModal(destModal) ? destModal : null
);
useEffect(() => {
@@ -300,19 +300,12 @@ const Airdrop = () => {
setCurrentModal(isAirdropModal(destModal) ? destModal : null);
}, [location.hash]);
- const [stakes, setStakes] = useState<
- Array<{
- fluidAmount: BN;
- baseAmount: BN;
- durationDays: number;
- depositDate: Date;
- }>
- >([]);
-
- const fetchUserStakes = async (address: string) => {
- const stakingDeposits = (await getStakingDeposits?.(address)) ?? [];
- setStakes(stakingDeposits);
- };
+ const stakes: Array<{
+ fluidAmount: BN;
+ baseAmount: BN;
+ durationDays: number;
+ depositDate: Date;
+ }> = [];
const fetchUserTokenBalance = async () => {
const userTokenBalance = await Promise.all(
@@ -390,8 +383,6 @@ const Airdrop = () => {
fetchUserTokenBalance();
- fetchUserStakes(address);
-
fetchUserRedeemableTokens(address);
}, [address]);
@@ -402,7 +393,6 @@ const Airdrop = () => {
const res = await (await redeemTokens?.())?.confirmTx();
fetchUserTokenBalance();
- fetchUserStakes(address);
fetchUserRedeemableTokens(address);
return res;
@@ -416,10 +406,11 @@ const Airdrop = () => {
const [localShouldShowBottleNumbers, setLocalShouldShowBottleNumbers] =
useState(undefined);
- // const [localShouldShowTutorial, setLocalShouldShowTutorial] = useState<
- // boolean | undefined
- // >(undefined);
- const localShouldShowTutorial = false;
+
+ const [localShouldShowTutorial, setLocalShouldShowTutorial] = useState<
+ boolean | undefined
+ >(undefined);
+
const [localShouldShowRecapIntro, setLocalShouldShowRecapIntro] = useState<
boolean | undefined
>(undefined);
@@ -435,9 +426,11 @@ const Airdrop = () => {
setLocalCookieConsent(true);
}
- // const airdropHasVisited = window.localStorage.getItem("airdropHasVisited");
+ const airdropHasVisited = window.localStorage.getItem("airdropHasVisited");
+
const airdropBottleCount =
window.localStorage.getItem("airdropBottleCount");
+
const airdropShouldShowBottleNumbers = window.localStorage.getItem(
"airdropShouldShowBottleNumbers"
);
@@ -460,17 +453,8 @@ const Airdrop = () => {
"airdropShouldShowRecapIntro"
);
- if (airdropShouldShowRecapIntro) {
- setLocalShouldShowRecapIntro(false);
- } else {
- setLocalShouldShowRecapIntro(true);
- }
-
- // if (airdropHasVisited) {
- // setLocalShouldShowTutorial(false);
- // } else {
- // setLocalShouldShowTutorial(true);
- // }
+ setLocalShouldShowRecapIntro(!airdropShouldShowRecapIntro);
+ setLocalShouldShowTutorial(!airdropHasVisited);
}, []);
useEffect(() => {
@@ -519,7 +503,7 @@ const Airdrop = () => {
groupId="airdrop"
isSelected={currentModal === "recap"}
>
- Airdrop Recap
+ Epoch 1 Recap
{
>
Airdrop Dashboard
- {/* setCurrentModal("tutorial")}
groupId="airdrop"
isSelected={isMobile && currentModal === "tutorial"}
>
Airdrop Tutorial
- */}
+
{
@@ -561,7 +545,7 @@ const Airdrop = () => {
>
Leaderboard
- {/* setCurrentModal("referrals")}
groupId="airdrop"
@@ -569,15 +553,6 @@ const Airdrop = () => {
>
Referrals
- setCurrentModal("stake")}
- groupId="airdrop"
- isSelected={isMobile && currentModal === "stake"}
- disabled={true}
- >
- Stake
-
setCurrentModal("testnet-rewards")}
@@ -586,7 +561,16 @@ const Airdrop = () => {
disabled={true}
>
Testnet Rewards
- */}
+
+
+
+ Dune
+
+
);
};
@@ -621,7 +605,7 @@ const Airdrop = () => {
style={{ marginBottom: "0.5em" }}
className={"no-margin"}
>
- Welcome to Fluidity's Airdrop Event!
+ Airdrop V2: Arbitrum's Space Expedition.
Fluidify your assets, transact them, and boost your rewards by
@@ -673,7 +657,7 @@ const Airdrop = () => {
seeBottlesDetails={() => setCurrentModal("bottles-details")}
seeLeaderboardMobile={() => setCurrentModal("leaderboard")}
epochMax={epochDaysTotal}
- epochDays={epochDays}
+ epochDays={epochDaysElapsed}
activatedReferrals={numActiveReferrerReferrals}
totalBottles={bottlesCount}
network={network}
@@ -759,7 +743,6 @@ const Airdrop = () => {
wethPrice={wethPrice}
usdcPrice={usdcPrice}
stakeCallback={() => {
- fetchUserStakes(address ?? "");
fetchUserTokenBalance();
}}
/>
@@ -861,7 +844,6 @@ const Airdrop = () => {
usdcPrice={usdcPrice}
isMobile={isMobile}
stakeCallback={() => {
- fetchUserStakes(address ?? "");
fetchUserTokenBalance();
}}
/>
@@ -919,6 +901,19 @@ const Airdrop = () => {
) : (
<>
+
+
+
{
className={"no-margin"}
style={{ marginBottom: "0.5em" }}
>
- Welcome to Fluidity's Airdrop Event!
+ Airdrop V2: Arbitrum's Space Expedition.
Fluidify your assets, transact them, and boost your rewards
@@ -973,7 +968,7 @@ const Airdrop = () => {
seeBottlesDetails={() => setCurrentModal("bottles-details")}
seeLeaderboardMobile={() => setCurrentModal("leaderboard")}
epochMax={epochDaysTotal}
- epochDays={epochDays}
+ epochDays={epochDaysElapsed}
activatedReferrals={numActiveReferrerReferrals}
totalBottles={bottlesCount}
network={network}
@@ -1169,16 +1164,16 @@ const MultiplierTasks = () => {
const [tasks, setTasks] = useState<"1x" | "6x">("6x");
const providerLinks: { provider: Provider; link: string }[] = [
- { provider: "Uniswap", link: "https://app.uniswap.org/#/swap" },
+ { provider: "Jumper", link: "https://app.uniswap.org/#/swap" },
{
- provider: "Sushiswap",
- link: "https://www.sushi.com/swap?fromChainId=42161&fromCurrency=0x4CFA50B7Ce747e2D61724fcAc57f24B748FF2b2A&toChainId=42161&toCurrency=NATIVE&amount=",
+ provider: "Uniswap",
+ link: "https://app.uniswap.org/#/swap",
},
- { provider: "Camelot", link: "https://app.camelot.exchange/" },
- { provider: "Saddle", link: "https://saddle.exchange/#/" },
- { provider: "Chronos", link: "https://app.chronos.exchange/" },
+ { provider: "Trader Joe", link: "https://app.camelot.exchange/" },
+ { provider: "Camelot", link: "https://saddle.exchange/#/" },
+ { provider: "Sushiswap", link: "https://app.chronos.exchange/" },
{
- provider: "Kyber",
+ provider: "Ramses",
link: "https://kyberswap.com/swap/arbitrum/fusdc-to-usdc",
},
];
@@ -1190,7 +1185,7 @@ const MultiplierTasks = () => {
Multiplier Tasks
- Perform displayed tasks to earn the respective multipliers.
+ Transact fUSDC on listed platforms to earn more!
{
- const sumLiquidityMultiplier = stakes.reduce(
- (sum, { fluidAmount, baseAmount, durationDays, depositDate }) => {
- const fluidDecimals = 6;
- const fluidUsd = getUsdFromTokenAmount(
- fluidAmount,
- fluidDecimals,
- usdcPrice
- );
-
- const wethDecimals = 18;
- const usdcDecimals = 6;
-
- // If converting base amount by weth decimals (18) is smaller than $0.01,
- // then tentatively assume Token amount is USDC
- // A false hit would be a USDC deposit >= $100,000
- const baseUsd =
- getUsdFromTokenAmount(baseAmount, wethDecimals, wethPrice) < 0.01
- ? getUsdFromTokenAmount(baseAmount, usdcDecimals, usdcPrice)
- : getUsdFromTokenAmount(baseAmount, wethDecimals, wethPrice);
-
- const stakedDays = dayDifference(new Date(), new Date(depositDate));
-
- const multiplier = stakingLiquidityMultiplierEq(stakedDays, durationDays);
-
- return sum + (fluidUsd + baseUsd) * multiplier;
- },
- 0
- );
-
- // if there are no stakes, this renders an empty stake on the dashboard which is A PART OF THE DESIGN SPEC
- if (stakes.length === 0)
- stakes = [
- {
- fluidAmount: new BN(0),
- baseAmount: new BN(0),
- durationDays: 0,
- depositDate: new Date(),
- },
- ];
-
return (
)}
-
- MY TOTAL LIQUIDITY MULTIPLIER}
- >
-
- {toSignificantDecimals(sumLiquidityMultiplier, 1)}x
-
-
-
}
layout="after"
@@ -1357,112 +1297,16 @@ const MyMultiplier = ({
handleClick={seeMyStakingStats}
id="mx-see-my-staking-stats"
>
- MY STAKING STATS
+ MY EPOCH 1 STAKING STATS
- {!isMobile && (
-
- {stakes
- .map((stake) => {
- const { fluidAmount, baseAmount, durationDays, depositDate } =
- stake;
-
- const stakedDays = dayDifference(
- new Date(),
- new Date(depositDate)
- );
- const multiplier = stakingLiquidityMultiplierEq(
- stakedDays,
- durationDays
- );
-
- const fluidDecimals = 6;
- const fluidUsd = getUsdFromTokenAmount(
- fluidAmount,
- fluidDecimals,
- usdcPrice
- );
-
- const wethDecimals = 18;
- const usdcDecimals = 6;
-
- // If converting base amount by weth decimals (18) is smaller than $0.01,
- // then tentatively assume Token amount is USDC
- // A false hit would be a USDC deposit >= $100,000
- const baseUsd =
- getUsdFromTokenAmount(baseAmount, wethDecimals, wethPrice) <
- 0.01
- ? getUsdFromTokenAmount(baseAmount, usdcDecimals, usdcPrice)
- : getUsdFromTokenAmount(baseAmount, wethDecimals, wethPrice);
-
- return {
- stake,
- stakedDays,
- multiplier,
- fluidUsd,
- baseUsd,
- };
- })
- .sort((a, b) => {
- const stakeAVal = (a.fluidUsd + a.baseUsd) * a.multiplier;
- const stakeBVal = (b.fluidUsd + b.baseUsd) * b.multiplier;
-
- // Sort Descending
- return stakeBVal > stakeAVal
- ? 1
- : stakeBVal === stakeAVal
- ? 0
- : -1;
- })
- .slice(0, 3)
- .map(({ stake, multiplier, fluidUsd, baseUsd }) => {
- const { durationDays } = stake;
-
- return (
- <>
-
-
- {numberToMonetaryString(fluidUsd + baseUsd)} FOR{" "}
- {Math.floor(durationDays)} DAYS
-
-
-
-
-
- {toSignificantDecimals(multiplier, 1)}X
-
-
- >
- );
- })}
+
+
+
+ Provide $fUSDC Liquidity to earn $ARB and Multipliers!
+
- )}
-
: undefined}
- layout={"after"}
- buttontype="text"
- size="medium"
- version="primary"
- handleClick={seeStakeNow}
- id="mx-stake-now-button"
- disabled={true}
- >
- STAKE NOW
-
+
+
);
};
@@ -1472,7 +1316,7 @@ const airdropRankRow = (
isMobile = false
): IRow => {
const { address } = useContext(FluidityFacadeContext);
- const { user, rank, referralCount, liquidityMultiplier, bottles } = data;
+ const { user, rank, referralCount, fusdcEarned, arbEarned, bottles } = data;
return {
className: `airdrop-row ${isMobile ? "airdrop-mobile" : ""} ${
@@ -1538,7 +1382,24 @@ const airdropRankRow = (
);
- case "STAKING MULTIPLIER":
+ case "$fUSDC EARNED":
+ return (
+
+
+ {fusdcEarned}
+
+ |
+ );
+ case "$ARB EARNED":
return (
- {toSignificantDecimals(liquidityMultiplier, 1)}x
+ {arbEarned}
|
);
@@ -1609,6 +1470,8 @@ const Leaderboard = ({
liquidityMultiplier: 0,
bottles: 0,
highestRewardTier: 0,
+ fusdcEarned: 0,
+ arbEarned: 0,
};
data.push(userEntry);
@@ -1671,7 +1534,8 @@ const Leaderboard = ({
{ name: "RANK" },
{ name: "USER" },
{ name: "BOTTLES" },
- { name: "STAKING MULTIPLIER" },
+ { name: "$fUSDC EARNED" },
+ { name: "$ARB EARNED" },
{ name: "REFERRALS" },
]}
pagination={{
diff --git a/web/app.fluidity.money/app/routes/$network/dashboard/home.tsx b/web/app.fluidity.money/app/routes/$network/dashboard/home.tsx
index f4add9655..0539d1cba 100644
--- a/web/app.fluidity.money/app/routes/$network/dashboard/home.tsx
+++ b/web/app.fluidity.money/app/routes/$network/dashboard/home.tsx
@@ -21,6 +21,7 @@ import {
TabButton,
toDecimalPlaces,
ProviderIcon,
+ LootBottle,
TokenIcon,
} from "@fluidity-money/surfing";
import { useState, useContext, useEffect, useMemo } from "react";
@@ -262,6 +263,7 @@ export default function Home() {
{ name: "VALUE" },
{ name: "FLUID REWARDS", show: width >= 500 },
{ name: "$UTILITY REWARDS", show: width >= 500 },
+ { name: "BOTTLES EARNED", show: width >= 500 },
{ name: "ACCOUNT", show: width >= 375 },
{ name: "TIME", show: width >= 850, alignRight: true },
];
@@ -375,6 +377,8 @@ export default function Home() {
logo,
utilityTokens,
application,
+ rewardTier,
+ lootboxCount,
} = data;
const appProviderName = getProviderDisplayName(application);
@@ -454,12 +458,33 @@ export default function Home() {
)}
);
+ case "BOTTLES EARNED":
+ return (
+
+ {lootboxCount ? (
+
+
+
+ ) : (
+ -
+ )}{" "}
+ |
+ );
case "ACCOUNT":
return (
{sender === MintAddress
diff --git a/web/app.fluidity.money/app/routes/$network/dashboard/rewards/index.tsx b/web/app.fluidity.money/app/routes/$network/dashboard/rewards/index.tsx
index 64f00566d..a9d1ab7a5 100644
--- a/web/app.fluidity.money/app/routes/$network/dashboard/rewards/index.tsx
+++ b/web/app.fluidity.money/app/routes/$network/dashboard/rewards/index.tsx
@@ -38,6 +38,7 @@ import {
WalletIcon,
TabButton,
toDecimalPlaces,
+ LootBottle,
} from "@fluidity-money/surfing";
import { useContext, useEffect, useState, useMemo } from "react";
import { ToolTipContent, useToolTip, UtilityToken } from "~/components";
@@ -257,6 +258,7 @@ export default function Rewards() {
{ name: "VALUE" },
{ name: "FLUID REWARDS", show: width >= 500 },
{ name: "$UTILITY REWARDS", show: width >= 500 },
+ { name: "BOTTLES EARNED", show: width >= 500 },
{ name: "WINNER", show: width >= 850 },
{ name: "REWARDED TIME", show: width >= 850, alignRight: true },
];
@@ -432,6 +434,8 @@ export default function Rewards() {
currency,
utilityTokens,
application,
+ lootboxCount,
+ rewardTier,
} = data;
const toolTip = useToolTip();
@@ -537,6 +541,25 @@ export default function Rewards() {
)}
|
);
+ case "BOTTLES EARNED":
+ return (
+
+ {lootboxCount ? (
+
+
+
+ ) : (
+ -
+ )}{" "}
+ |
+ );
case "WINNER":
return (
@@ -628,23 +651,23 @@ export default function Rewards() {
Swap To Earn
{!isMobile && Swap Fluid Assets to generate yield.}
diff --git a/web/app.fluidity.money/app/routes/$network/query/dashboard/airdrop.tsx b/web/app.fluidity.money/app/routes/$network/query/dashboard/airdrop.tsx
index c46ae93df..5a0685b79 100644
--- a/web/app.fluidity.money/app/routes/$network/query/dashboard/airdrop.tsx
+++ b/web/app.fluidity.money/app/routes/$network/query/dashboard/airdrop.tsx
@@ -4,7 +4,7 @@ import { JsonRpcProvider } from "@ethersproject/providers";
import { LoaderFunction, json } from "@remix-run/node";
import { captureException } from "@sentry/react";
import { useAirdropStatsByAddress } from "~/queries/useAirdropStats";
-import { useStakingDataByAddress } from "~/queries/useStakingData";
+import { useLootboxConfig } from "~/queries";
import { getWethUsdPrice } from "~/util/chainUtils/ethereum/transaction";
import EACAggregatorProxyAbi from "~/util/chainUtils/ethereum/EACAggregatorProxy.json";
import config from "~/webapp.config.server";
@@ -29,17 +29,19 @@ export type AirdropLoaderData = {
bottleTiers: BottleTiers;
bottlesCount: number;
liquidityMultiplier: number;
- stakes: Array;
wethPrice: number;
usdcPrice: number;
- loaded: boolean;
referralCode?: string;
+ programBegin: Date;
+ programEnd: Date;
+ epochDaysTotal: number;
+ epochDaysElapsed: number;
+ epochIdentifier: string;
+ ethereumApplication: string;
+ epochFound: boolean;
+ loaded: boolean;
};
-const EPOCH_DAYS_TOTAL = 31;
-// temp: april 19th, 2023
-const EPOCH_START_DATE = new Date(2023, 3, 20);
-
const MAINNET_ID = 0;
const dayDifference = (date1: Date, date2: Date) =>
@@ -50,13 +52,57 @@ export const loader: LoaderFunction = async ({ params, request }) => {
const url = new URL(request.url);
const address_ = url.searchParams.get("address");
+ const epochIdentifier = url.searchParams.get("epoch") ?? "";
const address = address_?.toLowerCase();
- if (!address || !network) throw new Error("Invalid Request");
+ if (!address || !network || !epochIdentifier)
+ throw new Error("Invalid Request");
+
+ const { data, errors } = await useLootboxConfig({
+ identifier: epochIdentifier,
+ shouldFind: false,
+ });
+
+ if (errors) {
+ captureException(errors, {
+ tags: {
+ section: "airdrop",
+ },
+ });
+
+ return new Error("Server could not fulfill request");
+ }
+
+ if (!data) {
+ // return defaults
+ return null;
+ }
+
+ const { lootboxConfig: configs } = data;
+
+ // if we didn't find anything, then we need to return the defaults
+
+ if (configs.length != 1) {
+ return null;
+ }
- const daysElapsed =
- dayDifference(new Date(), EPOCH_START_DATE) % EPOCH_DAYS_TOTAL;
+ const {
+ programBegin: programBegin_,
+ programEnd: programEnd_,
+ ethereumApplication,
+ found: epochFound,
+ } = configs[0];
+
+ const programBegin = new Date(programBegin_);
+ const programEnd = new Date(programEnd_);
+
+ const epochDaysTotal = Math.round(
+ (programEnd.valueOf() - programBegin.valueOf()) / (1000 * 60 * 60 * 24)
+ );
+
+ const epochDaysElapsed =
+ dayDifference(new Date(), programBegin) % epochDaysTotal;
const infuraRpc = config.drivers[network][MAINNET_ID].rpc.http;
const provider = new JsonRpcProvider(infuraRpc);
@@ -65,18 +111,17 @@ export const loader: LoaderFunction = async ({ params, request }) => {
config.contract.eac_aggregator_proxy[network as Chain];
try {
- const [
- { data: airdropStatsData, errors: airdropStatsErrors },
- { data: stakingData, errors: stakingErrors },
- wethPrice,
- ] = await Promise.all([
- useAirdropStatsByAddress(address),
- useStakingDataByAddress(address, daysElapsed),
- getWethUsdPrice(provider, eacAggregatorProxyAddr, EACAggregatorProxyAbi),
- ]);
+ const [{ data: airdropStatsData, errors: airdropStatsErrors }, wethPrice] =
+ await Promise.all([
+ useAirdropStatsByAddress(address, epochIdentifier),
+ getWethUsdPrice(
+ provider,
+ eacAggregatorProxyAddr,
+ EACAggregatorProxyAbi
+ ),
+ ]);
if (airdropStatsErrors || !airdropStatsData) throw airdropStatsErrors;
- if (stakingErrors || !stakingData) throw stakingErrors;
const {
lootboxCounts: [bottleTiers_],
@@ -86,15 +131,6 @@ export const loader: LoaderFunction = async ({ params, request }) => {
},
} = airdropStatsData;
- const stakes = stakingData.stakes.map(
- ({ multiplier, durationSecs, amount, ...stake }) => ({
- ...stake,
- amountUsd: amount / 1e6,
- durationDays: durationSecs / 60 / 60 / 24,
- multiplier: multiplier[0].result,
- })
- );
-
const bottleTiers = bottleTiers_ || {
[Rarity.Common]: 0,
[Rarity.Uncommon]: 0,
@@ -111,10 +147,16 @@ export const loader: LoaderFunction = async ({ params, request }) => {
(sum: number, quantity: number) => sum + quantity,
0
),
- stakes,
wethPrice,
usdcPrice: 1,
loaded: true,
+ programBegin,
+ programEnd,
+ epochDaysTotal,
+ epochDaysElapsed,
+ epochIdentifier,
+ epochFound,
+ ethereumApplication,
} satisfies AirdropLoaderData);
} catch (err) {
captureException(new Error(`Could not fetch airdrop data: ${err}`), {
diff --git a/web/app.fluidity.money/app/routes/$network/query/dashboard/airdropLeaderboard.tsx b/web/app.fluidity.money/app/routes/$network/query/dashboard/airdropLeaderboard.tsx
index f7836405e..044c8fff0 100644
--- a/web/app.fluidity.money/app/routes/$network/query/dashboard/airdropLeaderboard.tsx
+++ b/web/app.fluidity.money/app/routes/$network/query/dashboard/airdropLeaderboard.tsx
@@ -22,6 +22,11 @@ export const loader: LoaderFunction = async ({ params, request }) => {
const { network } = params;
const url = new URL(request.url);
+
+ const epoch = url.searchParams.get("epoch");
+
+ if (!epoch) throw new Error("Invalid Request");
+
const address = url.searchParams.get("address") ?? "";
const period = url.searchParams.get("period") ?? "";
const provider_ = url.searchParams.get("provider") ?? "";
@@ -38,15 +43,17 @@ export const loader: LoaderFunction = async ({ params, request }) => {
switch (true) {
case useAll: {
return [
- useAirdropLeaderboardAllTime,
- useAirdropLeaderboardByUserAllTime,
+ () => useAirdropLeaderboardAllTime(epoch),
+ (address: string) =>
+ useAirdropLeaderboardByUserAllTime(epoch, address),
];
}
case use24Hours && !!provider: {
return [
- () => useAirdropLeaderboardByApplication24Hours(provider),
+ () => useAirdropLeaderboardByApplication24Hours(epoch, provider),
(address: string) =>
useAirdropLeaderboardByUserByApplication24Hours(
+ epoch,
address,
provider
),
@@ -55,8 +62,9 @@ export const loader: LoaderFunction = async ({ params, request }) => {
case use24Hours && !provider:
default: {
return [
- useAirdropLeaderboard24Hours,
- useAirdropLeaderboardByUser24Hours,
+ () => useAirdropLeaderboard24Hours(epoch),
+ (address: string) =>
+ useAirdropLeaderboardByUser24Hours(epoch, address),
];
}
}
@@ -105,6 +113,8 @@ export const loader: LoaderFunction = async ({ params, request }) => {
referralCount: 0,
bottles: 0,
highestRewardTier: 0,
+ fusdcEarned: 0,
+ arbEarned: 0,
} satisfies AirdropLeaderboardEntry,
]
).concat(leaderboard);
diff --git a/web/app.fluidity.money/app/routes/$network/query/dashboard/prizePool.tsx b/web/app.fluidity.money/app/routes/$network/query/dashboard/prizePool.tsx
index 182786e8d..30fcbda26 100644
--- a/web/app.fluidity.money/app/routes/$network/query/dashboard/prizePool.tsx
+++ b/web/app.fluidity.money/app/routes/$network/query/dashboard/prizePool.tsx
@@ -25,6 +25,7 @@ export async function loader() {
},
].map(({ network, abi, getPrizePool }) => {
const infuraRpc = config.drivers[network][mainnetId].rpc.http;
+ console.log("infura rpc", infuraRpc);
const provider = new JsonRpcProvider(infuraRpc);
const rewardPoolAddr = config.contract.prize_pool[network as Chain];
diff --git a/web/app.fluidity.money/app/routes/$network/query/referralBottles.tsx b/web/app.fluidity.money/app/routes/$network/query/referralBottles.tsx
index 07a50c3b0..d6c89b4c3 100644
--- a/web/app.fluidity.money/app/routes/$network/query/referralBottles.tsx
+++ b/web/app.fluidity.money/app/routes/$network/query/referralBottles.tsx
@@ -15,15 +15,14 @@ export const loader: LoaderFunction = async ({ request }) => {
const url = new URL(request.url);
const address_ = url.searchParams.get("address") ?? "";
+ const epoch = url.searchParams.get("epoch");
const address = address_.toLocaleLowerCase();
- if (!address) {
- throw new Error("Invalid Request");
- }
+ if (!address || !epoch) throw new Error("Invalid Request");
const { data: referralBottleCountData, errors: referralBottleCountErr } =
- await useReferralLootboxesByAddress(address);
+ await useReferralLootboxesByAddress(epoch, address);
if (referralBottleCountErr || !referralBottleCountData) {
throw new Error("Could not fetch Referral Bottles");
diff --git a/web/app.fluidity.money/app/routes/$network/query/userTransactions.tsx b/web/app.fluidity.money/app/routes/$network/query/userTransactions.tsx
index 4085cecbb..2000c80a1 100644
--- a/web/app.fluidity.money/app/routes/$network/query/userTransactions.tsx
+++ b/web/app.fluidity.money/app/routes/$network/query/userTransactions.tsx
@@ -38,6 +38,8 @@ type UserTransaction = {
value: number;
currency: string;
application: string;
+ rewardTier: number;
+ lootboxCount: number;
};
export type TransactionsLoaderData = {
@@ -117,6 +119,8 @@ export const loader: LoaderFunction = async ({ params, request }) => {
utility_amount,
type,
swap_in,
+ rewardTier,
+ lootboxCount,
}) => {
const utilityName = utility_name?.match(ALPHA_NUMERIC)?.[0];
@@ -142,14 +146,17 @@ export const loader: LoaderFunction = async ({ params, request }) => {
// convert to JS timestamp
timestamp: new Date(timestamp + "Z").getTime(),
value,
- currency: 'f' + currency,
+ currency: "f" + currency,
application,
swapType,
provider: application ?? "Fluidity",
logo: tokenLogoMap[currency] || defaultLogo,
- utilityTokens: utilityName && utility_amount > 0
- ? { [utilityName]: utility_amount }
- : undefined,
+ utilityTokens:
+ utilityName && utility_amount > 0
+ ? { [utilityName]: utility_amount }
+ : undefined,
+ rewardTier,
+ lootboxCount,
};
}
);
@@ -351,6 +358,8 @@ export const loader: LoaderFunction = async ({ params, request }) => {
amount: value,
currency: { symbol: currency },
application,
+ lootboxCount,
+ rewardTier,
} = transaction;
return {
@@ -367,6 +376,8 @@ export const loader: LoaderFunction = async ({ params, request }) => {
: value,
currency,
application,
+ lootboxCount,
+ rewardTier,
};
}
);
@@ -408,6 +419,8 @@ export const loader: LoaderFunction = async ({ params, request }) => {
swapType,
utilityTokens: winner?.utility,
application: tx.application,
+ rewardTier: tx.rewardTier,
+ lootboxCount: tx.lootboxCount,
};
});
diff --git a/web/app.fluidity.money/app/routes/$network/query/winningUserTransactions.tsx b/web/app.fluidity.money/app/routes/$network/query/winningUserTransactions.tsx
index 71520113b..7380b3d3e 100644
--- a/web/app.fluidity.money/app/routes/$network/query/winningUserTransactions.tsx
+++ b/web/app.fluidity.money/app/routes/$network/query/winningUserTransactions.tsx
@@ -26,6 +26,8 @@ type UserTransaction = {
value: number;
currency: string;
application: string;
+ lootboxCount: number;
+ rewardTier: number;
};
export type TransactionsLoaderData = {
@@ -206,6 +208,8 @@ export const loader: LoaderFunction = async ({ params, request }) => {
amount: value,
currency: { symbol: currency },
application,
+ lootboxCount,
+ rewardTier,
} = transaction;
return {
@@ -222,6 +226,8 @@ export const loader: LoaderFunction = async ({ params, request }) => {
: value,
currency,
application,
+ lootboxCount,
+ rewardTier,
};
}
);
@@ -286,6 +292,8 @@ export const loader: LoaderFunction = async ({ params, request }) => {
swapType,
utilityTokens: winner.utility,
application: tx.application,
+ lootboxCount: tx.lootboxCount,
+ rewardTier: tx.rewardTier,
};
});
diff --git a/web/app.fluidity.money/app/routes/arbitrum/index.tsx b/web/app.fluidity.money/app/routes/arbitrum/index.tsx
new file mode 100644
index 000000000..36f70df78
--- /dev/null
+++ b/web/app.fluidity.money/app/routes/arbitrum/index.tsx
@@ -0,0 +1,5 @@
+import { LoaderFunction, redirect } from "@remix-run/node";
+
+export const loader: LoaderFunction = async () => {
+ return redirect(`/arbitrum/dashboard/home`);
+};
diff --git a/web/app.fluidity.money/app/routes/arbitrum/query/dashboard/home.tsx b/web/app.fluidity.money/app/routes/arbitrum/query/dashboard/home.tsx
index f7e2b4375..6d7d10076 100644
--- a/web/app.fluidity.money/app/routes/arbitrum/query/dashboard/home.tsx
+++ b/web/app.fluidity.money/app/routes/arbitrum/query/dashboard/home.tsx
@@ -49,10 +49,12 @@ export const loader: LoaderFunction = async ({ request }) => {
}
if (rewardsErr || !rewardsData) {
- throw new Error("Could not fetch rewards data");
+ console.log("Could not fetch rewards data", rewardsErr);
+ throw new Error(`Could not fetch rewards data: ${rewardsErr}`);
}
if (graphErr || !graphData) {
+ console.log("Could not fetch graph data", graphErr);
throw new Error("Could not fetch graph data");
}
diff --git a/web/app.fluidity.money/app/routes/polygon_zk/index.tsx b/web/app.fluidity.money/app/routes/polygon_zk/index.tsx
new file mode 100644
index 000000000..b83703f40
--- /dev/null
+++ b/web/app.fluidity.money/app/routes/polygon_zk/index.tsx
@@ -0,0 +1,5 @@
+import { LoaderFunction, redirect } from "@remix-run/node";
+
+export const loader: LoaderFunction = async () => {
+ return redirect(`/polygon_zk/dashboard/home`);
+};
diff --git a/web/app.fluidity.money/app/routes/solana/index.tsx b/web/app.fluidity.money/app/routes/solana/index.tsx
new file mode 100644
index 000000000..8d02d7a2a
--- /dev/null
+++ b/web/app.fluidity.money/app/routes/solana/index.tsx
@@ -0,0 +1,5 @@
+import { LoaderFunction, redirect } from "@remix-run/node";
+
+export const loader: LoaderFunction = async () => {
+ return redirect(`/solana/dashboard/home`);
+};
diff --git a/web/app.fluidity.money/app/styles/dashboard.css b/web/app.fluidity.money/app/styles/dashboard.css
index f5c50dbf0..7d3166ba0 100644
--- a/web/app.fluidity.money/app/styles/dashboard.css
+++ b/web/app.fluidity.money/app/styles/dashboard.css
@@ -943,4 +943,9 @@ ul.sidebar-nav li div.active {
stroke: currentColor;
}
+.fluidify-button-dashboard {
+ background-color: white;
+ color: black;
+}
+
/*# sourceMappingURL=dashboard.css.map */
diff --git a/web/app.fluidity.money/app/styles/dashboard.scss b/web/app.fluidity.money/app/styles/dashboard.scss
index f143136b5..423e58c21 100644
--- a/web/app.fluidity.money/app/styles/dashboard.scss
+++ b/web/app.fluidity.money/app/styles/dashboard.scss
@@ -1007,3 +1007,8 @@ ul.sidebar-nav {
}
}
}
+
+.fluidify-button-dashboard {
+ background-color: white;
+ color: black;
+}
diff --git a/web/app.fluidity.money/app/styles/dashboard/airdrop.css b/web/app.fluidity.money/app/styles/dashboard/airdrop.css
index a75578573..4e0b8e444 100644
--- a/web/app.fluidity.money/app/styles/dashboard/airdrop.css
+++ b/web/app.fluidity.money/app/styles/dashboard/airdrop.css
@@ -391,9 +391,6 @@
.airdrop-my-multiplier {
position: relative;
- display: grid;
- grid-template-columns: 1fr 1fr;
- gap: 2em;
}
.airdrop-my-multiplier svg,
.airdrop-my-multiplier path {
@@ -426,9 +423,6 @@
}
.airdrop-my-multiplier #mx-see-my-staking-stats {
width: 100%;
- grid-area: 2/1;
- box-sizing: border-box;
- align-self: end;
}
.airdrop-my-multiplier #mx-my-stakes {
display: grid;
@@ -982,4 +976,21 @@
aspect-ratio: 1/1;
}
+#tutorial,
+#staking-stats,
+#bottles-details,
+#testnet-rewards {
+ position: fixed;
+}
+
+.airdrop-arb-multipliers-container {
+ display: flex;
+ padding-top: 20px;
+}
+
+.airdrop-arb-multipliers-container > * {
+ margin-left: auto;
+ margin-right: auto;
+}
+
/*# sourceMappingURL=airdrop.css.map */
diff --git a/web/app.fluidity.money/app/styles/dashboard/airdrop.scss b/web/app.fluidity.money/app/styles/dashboard/airdrop.scss
index bb43ffe2e..f76b7cfbf 100644
--- a/web/app.fluidity.money/app/styles/dashboard/airdrop.scss
+++ b/web/app.fluidity.money/app/styles/dashboard/airdrop.scss
@@ -400,9 +400,6 @@ $holo: linear-gradient(
.airdrop-my-multiplier {
position: relative;
- display: grid;
- grid-template-columns: 1fr 1fr;
- gap: 2em;
svg,
path {
@@ -442,9 +439,6 @@ $holo: linear-gradient(
#mx-see-my-staking-stats {
width: 100%;
- grid-area: 2 / 1;
- box-sizing: border-box;
- align-self: end;
}
#mx-my-stakes {
@@ -1066,3 +1060,20 @@ $holo: linear-gradient(
}
}
}
+
+#tutorial,
+#staking-stats,
+#bottles-details,
+#testnet-rewards {
+ position: fixed;
+}
+
+.airdrop-arb-multipliers-container {
+ display: flex;
+ padding-top: 20px;
+}
+
+.airdrop-arb-multipliers-container > * {
+ margin-left: auto;
+ margin-right: auto;
+}
diff --git a/web/app.fluidity.money/app/types/Transaction.ts b/web/app.fluidity.money/app/types/Transaction.ts
index 98583c11c..47597bc68 100644
--- a/web/app.fluidity.money/app/types/Transaction.ts
+++ b/web/app.fluidity.money/app/types/Transaction.ts
@@ -14,6 +14,8 @@ type Transaction = {
swapType?: "in" | "out";
utilityTokens?: { [tokens: string]: number };
application: string;
+ rewardTier: number;
+ lootboxCount: number;
};
export default Transaction;
diff --git a/web/app.fluidity.money/app/util/api/graphql.ts b/web/app.fluidity.money/app/util/api/graphql.ts
index 59a11e4ea..d112f9b87 100644
--- a/web/app.fluidity.money/app/util/api/graphql.ts
+++ b/web/app.fluidity.money/app/util/api/graphql.ts
@@ -11,6 +11,8 @@ type GqlEndpoint = {
type GqlBackend = "hasura";
+const HasuraUrl = "https://fluidity.hasura.app/v1/graphql";
+
export const networkGqlBackend = (network: string): GqlBackend | null => {
switch (network) {
case "solana":
@@ -26,7 +28,7 @@ export const fetchGqlEndpoint = (network: string): GqlEndpoint | null => {
switch (networkGqlBackend(network)) {
case "hasura":
return {
- url: "https://fluidity.hasura.app/v1/graphql",
+ url: HasuraUrl,
headers: {
"x-hasura-admin-secret": process.env.FLU_HASURA_SECRET ?? "",
},
@@ -37,7 +39,7 @@ export const fetchGqlEndpoint = (network: string): GqlEndpoint | null => {
};
export const fetchInternalEndpoint = (): GqlEndpoint => ({
- url: "https://fluidity.hasura.app/v1/graphql",
+ url: HasuraUrl,
headers:
typeof process.env.FLU_HASURA_SECRET === "string"
? {
diff --git a/web/app.fluidity.money/app/util/chainUtils/ethereum/transaction.ts b/web/app.fluidity.money/app/util/chainUtils/ethereum/transaction.ts
index 545721d1d..428a89178 100644
--- a/web/app.fluidity.money/app/util/chainUtils/ethereum/transaction.ts
+++ b/web/app.fluidity.money/app/util/chainUtils/ethereum/transaction.ts
@@ -628,10 +628,10 @@ export const handleContractErrors = async (
if (metaMaskError?.value.code === -32603) {
throw new Error(
- `Failed to make swap. Please reset your Metamask account (settings -> advanced -> reset account)`
+ `RPC error. Please reset your Metamask account (settings -> advanced -> reset account)`
);
} else if (metaMaskError?.value.code === -32000) {
- throw new Error(`Failed to make swap. Gas limit too low.`);
+ throw new Error(`RPC error. Gas limit too low.`);
}
// otherwise, check for a 'non intrinsic' gas error (gas exhausted)
@@ -640,12 +640,12 @@ export const handleContractErrors = async (
// found revert opcode, assume it's a gas error since we can't call this with an insufficient balance within the application
if (receipt?.status === 0) {
throw new Error(
- `Failed to make swap. Gas limit of ${receipt?.gasUsed?.toNumber()} exhausted!`
+ `RPC error. Gas limit of ${receipt?.gasUsed?.toNumber()} exhausted!`
);
}
} catch (e) {
// otherwise, use a generic error
- throw new Error(`Failed to make swap. ${msg}`);
+ throw new Error(`RPC error. ${msg}`);
}
};
diff --git a/web/app.fluidity.money/app/util/provider.ts b/web/app.fluidity.money/app/util/provider.ts
index 6f01ff400..cc92159f8 100644
--- a/web/app.fluidity.money/app/util/provider.ts
+++ b/web/app.fluidity.money/app/util/provider.ts
@@ -69,8 +69,12 @@ export const getProviderDisplayName = (name?: string): Provider => {
return "Lifinity";
case "mercurial":
return "Mercurial";
+ case "ramses":
+ return "Ramses";
case "trader_joe":
return "Trader Joe";
+ case "jumper":
+ return "Jumper";
case "meteora":
return "Meteora";
case "fluidity":
diff --git a/web/app.fluidity.money/public/images/epoch2AirdropBanner.png b/web/app.fluidity.money/public/images/epoch2AirdropBanner.png
new file mode 100644
index 000000000..eb7a4eb31
--- /dev/null
+++ b/web/app.fluidity.money/public/images/epoch2AirdropBanner.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:72209eaa5f613befc0b8fcc53d66b42693d48fa565404b028dcab5034a9fe1fc
+size 170872
diff --git a/web/app.fluidity.money/public/images/hero/common.png b/web/app.fluidity.money/public/images/hero/common.png
index afb7e2da1..9651b6b77 100644
--- a/web/app.fluidity.money/public/images/hero/common.png
+++ b/web/app.fluidity.money/public/images/hero/common.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:cf873fc5dbc6f6493a8729e240d33026022a45def8c53c5d847873b1bb01bd5c
-size 267816
+oid sha256:fbfdf8c12d6b02bad36eca229eadffb462b819d39b0a8385de3b864a85f83814
+size 167937
diff --git a/web/app.fluidity.money/public/images/hero/legendary.png b/web/app.fluidity.money/public/images/hero/legendary.png
index 06fb62a20..a38f1a1f6 100644
--- a/web/app.fluidity.money/public/images/hero/legendary.png
+++ b/web/app.fluidity.money/public/images/hero/legendary.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:252ea1e42636e41520a4e003056825f11e77ecf39f0766f93b6d2b6005eedfd3
-size 882592
+oid sha256:cfb9fdce40d47bd56d85f36f53f890113c97d48b52f35cf3a1772077c95132f4
+size 216190
diff --git a/web/app.fluidity.money/public/images/hero/rare.png b/web/app.fluidity.money/public/images/hero/rare.png
index 282a12a3c..8b80c9ea0 100644
--- a/web/app.fluidity.money/public/images/hero/rare.png
+++ b/web/app.fluidity.money/public/images/hero/rare.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:246725e96442ac0ac7e5aeafd33415937c1984eed2b83a6cb839dcf8e0dce6d6
-size 209084
+oid sha256:60677247e65f4ce979c7b4a709e51d310285f5bc6a971f753710e7cddc301439
+size 157634
diff --git a/web/app.fluidity.money/public/images/hero/ultra_rare.png b/web/app.fluidity.money/public/images/hero/ultra_rare.png
index c90a7c963..96c422d32 100644
--- a/web/app.fluidity.money/public/images/hero/ultra_rare.png
+++ b/web/app.fluidity.money/public/images/hero/ultra_rare.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:872c19d8fa54a4f59c7d11ba9dd3f84870f6955e817b8c8c91d1d866dbd49265
-size 241863
+oid sha256:576235a66a879f45a55773b95591a0a78c022b15aa82a41c7674471e6284bd76
+size 169854
diff --git a/web/app.fluidity.money/public/images/hero/uncommon.png b/web/app.fluidity.money/public/images/hero/uncommon.png
index ad5d7c2fa..0010e8234 100644
--- a/web/app.fluidity.money/public/images/hero/uncommon.png
+++ b/web/app.fluidity.money/public/images/hero/uncommon.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:238e51be54c715fbb00d8233d809cd6d4ff6e6a05fdd581d95c28a5c6344dabe
-size 259633
+oid sha256:c2e149ca67b2f012270d78c53bbf2f052de5cc41c799c73a5698cebd16bb8649
+size 177534
diff --git a/web/app.fluidity.money/public/images/joe-farmlands.png b/web/app.fluidity.money/public/images/joe-farmlands.png
new file mode 100644
index 000000000..4a1b50dbd
--- /dev/null
+++ b/web/app.fluidity.money/public/images/joe-farmlands.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:2395663fa922328621ea843e25ca3ad697d61c2414bb6a18b3bb57c2c577140d
+size 248359
diff --git a/web/app.fluidity.money/public/images/kingdom-of-camelot.png b/web/app.fluidity.money/public/images/kingdom-of-camelot.png
new file mode 100644
index 000000000..5e33cf3f3
--- /dev/null
+++ b/web/app.fluidity.money/public/images/kingdom-of-camelot.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:e623e4cabc261485889e786d0624b00466829912c28b43b8e2678b59df78ffb4
+size 131162
diff --git a/web/app.fluidity.money/public/images/providers/Jumper.svg b/web/app.fluidity.money/public/images/providers/Jumper.svg
new file mode 100644
index 000000000..d7f19b72e
--- /dev/null
+++ b/web/app.fluidity.money/public/images/providers/Jumper.svg
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:60185b2e2158d5c994f8665081a708e721849bc038e4decdc36bbb64bf171446
+size 1180
diff --git a/web/app.fluidity.money/public/images/providers/Ramses.svg b/web/app.fluidity.money/public/images/providers/Ramses.svg
new file mode 100644
index 000000000..492f06864
--- /dev/null
+++ b/web/app.fluidity.money/public/images/providers/Ramses.svg
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:3519ca5687a2779d0ad4af62ffbff2bf2eeb5ec2f5ff6ca53593254a3ec9e00e
+size 2668
diff --git a/web/fluidity.money/Dockerfile.frontend b/web/fluidity.money/Dockerfile.frontend
index 1706b1d9d..161cb8c98 100644
--- a/web/fluidity.money/Dockerfile.frontend
+++ b/web/fluidity.money/Dockerfile.frontend
@@ -11,6 +11,8 @@ ARG GITHUB_TOKEN
ARG NEXT_PUBLIC_FLU_ETH_RPC_HTTP
+ARG NEXT_PUBLIC_FLU_HASURA_URL
+
ENV CI $CI
ENV PATH /app/node_modules.bin:$PATH
diff --git a/web/surfing/src/types/provider.ts b/web/surfing/src/types/provider.ts
index f45511be6..ad579fe80 100644
--- a/web/surfing/src/types/provider.ts
+++ b/web/surfing/src/types/provider.ts
@@ -30,4 +30,6 @@ export type Provider =
| "Trader Joe"
| "Uniswap"
| "XY Finance"
+ | "Ramses"
+ | "Jumper"
| "Meteora";
diff --git a/web/surfing/src/util/liquidityProviders/providers.ts b/web/surfing/src/util/liquidityProviders/providers.ts
index dd553245f..0715ca022 100644
--- a/web/surfing/src/util/liquidityProviders/providers.ts
+++ b/web/surfing/src/util/liquidityProviders/providers.ts
@@ -17,6 +17,7 @@ const providerImgNames: { [K in Provider]: string } = {
Curve: "curve.png",
Dodo: "DODO.png",
Fluidity: "logoMetallic.png",
+ Jumper: "Jumper.svg",
Jupiter: "Jupiter.svg",
Kyber: "Kyber.svg",
Lemniscap: "Lemniscap.png",
@@ -29,6 +30,7 @@ const providerImgNames: { [K in Provider]: string } = {
Oneinch: "1inch.svg",
Orca: "Orca.svg",
Polygon: "Polygon.svg",
+ Ramses: "Ramses.svg",
Raydium: "raydium.png",
Saber: "Saber.svg",
Saddle: "Saddle.svg",
|