From 1f672a6405ffd00005691d0d099a615b8fe9705a Mon Sep 17 00:00:00 2001 From: Ncookiez Date: Wed, 28 Feb 2024 14:34:12 -0500 Subject: [PATCH 001/161] updated contract ABIs --- shared/utilities/abis/chainlinkVrf.ts | 186 --------------- shared/utilities/abis/prizePool.ts | 203 +++++++++++----- shared/utilities/abis/rngAuction.ts | 283 ----------------------- shared/utilities/abis/rngRelay.ts | 198 ---------------- shared/utilities/abis/twabController.ts | 14 ++ shared/utilities/abis/vault.ts | 293 +++++++++++------------- shared/utilities/abis/vaultFactory.ts | 40 ++-- shared/utilities/index.ts | 3 - 8 files changed, 307 insertions(+), 913 deletions(-) delete mode 100644 shared/utilities/abis/chainlinkVrf.ts delete mode 100644 shared/utilities/abis/rngAuction.ts delete mode 100644 shared/utilities/abis/rngRelay.ts diff --git a/shared/utilities/abis/chainlinkVrf.ts b/shared/utilities/abis/chainlinkVrf.ts deleted file mode 100644 index 5f3606a3..00000000 --- a/shared/utilities/abis/chainlinkVrf.ts +++ /dev/null @@ -1,186 +0,0 @@ -export const chainlinkVrfABI = [ - { - inputs: [], - name: 'claimOwnership', - outputs: [], - stateMutability: 'nonpayable', - type: 'function' - }, - { - inputs: [{ internalType: 'uint32', name: 'requestId', type: 'uint32' }], - name: 'completedAt', - outputs: [{ internalType: 'uint64', name: 'completedAtTimestamp', type: 'uint64' }], - stateMutability: 'view', - type: 'function' - }, - { - inputs: [], - name: 'getCallbackGasLimit', - outputs: [{ internalType: 'uint32', name: '', type: 'uint32' }], - stateMutability: 'view', - type: 'function' - }, - { - inputs: [], - name: 'getLastRequestId', - outputs: [{ internalType: 'uint32', name: 'requestId', type: 'uint32' }], - stateMutability: 'view', - type: 'function' - }, - { - inputs: [], - name: 'getRequestConfirmations', - outputs: [{ internalType: 'uint16', name: '', type: 'uint16' }], - stateMutability: 'view', - type: 'function' - }, - { - inputs: [], - name: 'getRequestFee', - outputs: [ - { internalType: 'address', name: 'feeToken', type: 'address' }, - { internalType: 'uint256', name: 'requestFee', type: 'uint256' } - ], - stateMutability: 'view', - type: 'function' - }, - { - inputs: [{ internalType: 'uint32', name: '_internalRequestId', type: 'uint32' }], - name: 'isRequestComplete', - outputs: [{ internalType: 'bool', name: 'isCompleted', type: 'bool' }], - stateMutability: 'view', - type: 'function' - }, - { - inputs: [], - name: 'owner', - outputs: [{ internalType: 'address', name: '', type: 'address' }], - stateMutability: 'view', - type: 'function' - }, - { - inputs: [], - name: 'pendingOwner', - outputs: [{ internalType: 'address', name: '', type: 'address' }], - stateMutability: 'view', - type: 'function' - }, - { - inputs: [{ internalType: 'uint32', name: '_internalRequestId', type: 'uint32' }], - name: 'randomNumber', - outputs: [{ internalType: 'uint256', name: 'randomNum', type: 'uint256' }], - stateMutability: 'view', - type: 'function' - }, - { - inputs: [ - { internalType: 'uint256', name: '_requestId', type: 'uint256' }, - { internalType: 'uint256[]', name: '_randomWords', type: 'uint256[]' } - ], - name: 'rawFulfillRandomWords', - outputs: [], - stateMutability: 'nonpayable', - type: 'function' - }, - { - inputs: [], - name: 'renounceOwnership', - outputs: [], - stateMutability: 'nonpayable', - type: 'function' - }, - { - inputs: [], - name: 'requestRandomNumber', - outputs: [ - { internalType: 'uint32', name: 'requestId', type: 'uint32' }, - { internalType: 'uint32', name: 'lockBlock', type: 'uint32' } - ], - stateMutability: 'nonpayable', - type: 'function' - }, - { - inputs: [{ internalType: 'uint32', name: 'callbackGasLimit_', type: 'uint32' }], - name: 'setCallbackGasLimit', - outputs: [], - stateMutability: 'nonpayable', - type: 'function' - }, - { - inputs: [{ internalType: 'uint16', name: 'requestConfirmations_', type: 'uint16' }], - name: 'setRequestConfirmations', - outputs: [], - stateMutability: 'nonpayable', - type: 'function' - }, - { - inputs: [{ internalType: 'address', name: '_newOwner', type: 'address' }], - name: 'transferOwnership', - outputs: [], - stateMutability: 'nonpayable', - type: 'function' - }, - { - inputs: [], - name: 'vrfV2Wrapper', - outputs: [{ internalType: 'contract VRFV2Wrapper', name: '', type: 'address' }], - stateMutability: 'view', - type: 'function' - }, - { - anonymous: false, - inputs: [{ indexed: true, internalType: 'address', name: 'pendingOwner', type: 'address' }], - name: 'OwnershipOffered', - type: 'event' - }, - { - anonymous: false, - inputs: [ - { indexed: true, internalType: 'address', name: 'previousOwner', type: 'address' }, - { indexed: true, internalType: 'address', name: 'newOwner', type: 'address' } - ], - name: 'OwnershipTransferred', - type: 'event' - }, - { - anonymous: false, - inputs: [ - { indexed: true, internalType: 'uint32', name: 'requestId', type: 'uint32' }, - { indexed: false, internalType: 'uint256', name: 'randomNumber', type: 'uint256' } - ], - name: 'RandomNumberCompleted', - type: 'event' - }, - { - anonymous: false, - inputs: [ - { indexed: true, internalType: 'uint32', name: 'requestId', type: 'uint32' }, - { indexed: true, internalType: 'address', name: 'sender', type: 'address' } - ], - name: 'RandomNumberRequested', - type: 'event' - }, - { - anonymous: false, - inputs: [{ indexed: false, internalType: 'uint32', name: 'callbackGasLimit', type: 'uint32' }], - name: 'SetCallbackGasLimit', - type: 'event' - }, - { - anonymous: false, - inputs: [ - { indexed: false, internalType: 'uint16', name: 'requestConfirmations', type: 'uint16' } - ], - name: 'SetRequestConfirmations', - type: 'event' - }, - { inputs: [], name: 'CallbackGasLimitZero', type: 'error' }, - { - inputs: [{ internalType: 'uint256', name: 'vrfRequestId', type: 'uint256' }], - name: 'InvalidVrfRequestId', - type: 'error' - }, - { inputs: [], name: 'LinkTokenZeroAddress', type: 'error' }, - { inputs: [], name: 'RequestConfirmationsZero', type: 'error' }, - { inputs: [], name: 'VRFV2WrapperZeroAddress', type: 'error' } -] as const diff --git a/shared/utilities/abis/prizePool.ts b/shared/utilities/abis/prizePool.ts index 43bc73f9..8849df90 100644 --- a/shared/utilities/abis/prizePool.ts +++ b/shared/utilities/abis/prizePool.ts @@ -1,4 +1,11 @@ export const prizePoolABI = [ + { + inputs: [], + name: 'DONATOR', + outputs: [{ internalType: 'address', name: '', type: 'address' }], + stateMutability: 'view', + type: 'function' + }, { inputs: [], name: 'accountedBalance', @@ -23,10 +30,17 @@ export const prizePoolABI = [ stateMutability: 'nonpayable', type: 'function' }, + { + inputs: [], + name: 'canaryShares', + outputs: [{ internalType: 'uint8', name: '', type: 'uint8' }], + stateMutability: 'view', + type: 'function' + }, { inputs: [], name: 'claimCount', - outputs: [{ internalType: 'uint32', name: '', type: 'uint32' }], + outputs: [{ internalType: 'uint24', name: '', type: 'uint24' }], stateMutability: 'view', type: 'function' }, @@ -36,8 +50,8 @@ export const prizePoolABI = [ { internalType: 'uint8', name: '_tier', type: 'uint8' }, { internalType: 'uint32', name: '_prizeIndex', type: 'uint32' }, { internalType: 'address', name: '_prizeRecipient', type: 'address' }, - { internalType: 'uint96', name: '_fee', type: 'uint96' }, - { internalType: 'address', name: '_feeRecipient', type: 'address' } + { internalType: 'uint96', name: '_claimReward', type: 'uint96' }, + { internalType: 'address', name: '_claimRewardRecipient', type: 'address' } ], name: 'claimPrize', outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], @@ -51,6 +65,23 @@ export const prizePoolABI = [ stateMutability: 'view', type: 'function' }, + { + inputs: [ + { internalType: 'uint24', name: '_endDrawIdInclusive', type: 'uint24' }, + { internalType: 'uint24', name: '_rangeSize', type: 'uint24' } + ], + name: 'computeRangeStartDrawIdInclusive', + outputs: [{ internalType: 'uint24', name: '', type: 'uint24' }], + stateMutability: 'pure', + type: 'function' + }, + { + inputs: [{ internalType: 'uint8', name: '_numberOfTiers', type: 'uint8' }], + name: 'computeTotalShares', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function' + }, { inputs: [ { internalType: 'address', name: '_prizeVault', type: 'address' }, @@ -68,6 +99,13 @@ export const prizePoolABI = [ stateMutability: 'nonpayable', type: 'function' }, + { + inputs: [{ internalType: 'uint256', name: '_amount', type: 'uint256' }], + name: 'donatePrizeTokens', + outputs: [], + stateMutability: 'nonpayable', + type: 'function' + }, { inputs: [{ internalType: 'uint24', name: 'drawId', type: 'uint24' }], name: 'drawClosesAt', @@ -75,6 +113,13 @@ export const prizePoolABI = [ stateMutability: 'view', type: 'function' }, + { + inputs: [], + name: 'drawIdPriorToShutdown', + outputs: [{ internalType: 'uint24', name: '', type: 'uint24' }], + stateMutability: 'view', + type: 'function' + }, { inputs: [], name: 'drawManager', @@ -96,6 +141,20 @@ export const prizePoolABI = [ stateMutability: 'view', type: 'function' }, + { + inputs: [], + name: 'drawTimeout', + outputs: [{ internalType: 'uint24', name: '', type: 'uint24' }], + stateMutability: 'view', + type: 'function' + }, + { + inputs: [], + name: 'drawTimeoutAt', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function' + }, { inputs: [], name: 'estimateNextNumberOfTiers', @@ -135,6 +194,16 @@ export const prizePoolABI = [ stateMutability: 'view', type: 'function' }, + { + inputs: [ + { internalType: 'uint24', name: '_startDrawIdInclusive', type: 'uint24' }, + { internalType: 'uint24', name: '_endDrawIdInclusive', type: 'uint24' } + ], + name: 'getDonatedBetween', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function' + }, { inputs: [], name: 'getDrawIdToAward', @@ -177,7 +246,7 @@ export const prizePoolABI = [ inputs: [{ internalType: 'uint8', name: '_tier', type: 'uint8' }], name: 'getTierPrizeCount', outputs: [{ internalType: 'uint32', name: '', type: 'uint32' }], - stateMutability: 'view', + stateMutability: 'pure', type: 'function' }, { @@ -214,8 +283,8 @@ export const prizePoolABI = [ { inputs: [ { internalType: 'address', name: '_vault', type: 'address' }, - { internalType: 'uint24', name: '_startDrawId', type: 'uint24' }, - { internalType: 'uint24', name: '_endDrawId', type: 'uint24' } + { internalType: 'uint24', name: '_startDrawIdInclusive', type: 'uint24' }, + { internalType: 'uint24', name: '_endDrawIdInclusive', type: 'uint24' } ], name: 'getVaultPortion', outputs: [{ internalType: 'SD59x18', name: '', type: 'int256' }], @@ -226,12 +295,13 @@ export const prizePoolABI = [ inputs: [ { internalType: 'address', name: '_vault', type: 'address' }, { internalType: 'address', name: '_user', type: 'address' }, - { internalType: 'uint256', name: '_drawDuration', type: 'uint256' } + { internalType: 'uint24', name: '_startDrawIdInclusive', type: 'uint24' }, + { internalType: 'uint24', name: '_endDrawIdInclusive', type: 'uint24' } ], name: 'getVaultUserBalanceAndTotalSupplyTwab', outputs: [ - { internalType: 'uint256', name: '', type: 'uint256' }, - { internalType: 'uint256', name: '', type: 'uint256' } + { internalType: 'uint256', name: 'twab', type: 'uint256' }, + { internalType: 'uint256', name: 'twabTotalSupply', type: 'uint256' } ], stateMutability: 'view', type: 'function' @@ -250,6 +320,13 @@ export const prizePoolABI = [ stateMutability: 'view', type: 'function' }, + { + inputs: [{ internalType: 'uint8', name: '_tier', type: 'uint8' }], + name: 'isCanaryTier', + outputs: [{ internalType: 'bool', name: '', type: 'bool' }], + stateMutability: 'view', + type: 'function' + }, { inputs: [{ internalType: 'uint24', name: 'drawId', type: 'uint24' }], name: 'isDrawFinalized', @@ -257,6 +334,13 @@ export const prizePoolABI = [ stateMutability: 'view', type: 'function' }, + { + inputs: [], + name: 'isShutdown', + outputs: [{ internalType: 'bool', name: 'shutdown', type: 'bool' }], + stateMutability: 'view', + type: 'function' + }, { inputs: [ { internalType: 'address', name: '_vault', type: 'address' }, @@ -283,13 +367,6 @@ export const prizePoolABI = [ stateMutability: 'view', type: 'function' }, - { - inputs: [], - name: 'owner', - outputs: [{ internalType: 'address', name: '', type: 'address' }], - stateMutability: 'view', - type: 'function' - }, { inputs: [], name: 'pendingReserveContributions', @@ -311,13 +388,6 @@ export const prizePoolABI = [ stateMutability: 'view', type: 'function' }, - { - inputs: [], - name: 'renounceOwnership', - outputs: [], - stateMutability: 'nonpayable', - type: 'function' - }, { inputs: [], name: 'reserve', @@ -348,8 +418,25 @@ export const prizePoolABI = [ }, { inputs: [], - name: 'smoothing', - outputs: [{ internalType: 'SD1x18', name: '', type: 'int64' }], + name: 'shutdownAt', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function' + }, + { + inputs: [ + { internalType: 'address', name: '_vault', type: 'address' }, + { internalType: 'address', name: '_account', type: 'address' } + ], + name: 'shutdownBalanceOf', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function' + }, + { + inputs: [], + name: 'tierLiquidityUtilizationRate', + outputs: [{ internalType: 'UD60x18', name: '', type: 'uint256' }], stateMutability: 'view', type: 'function' }, @@ -367,13 +454,6 @@ export const prizePoolABI = [ stateMutability: 'view', type: 'function' }, - { - inputs: [{ internalType: 'address', name: 'newOwner', type: 'address' }], - name: 'transferOwnership', - outputs: [], - stateMutability: 'nonpayable', - type: 'function' - }, { inputs: [], name: 'twabController', @@ -403,6 +483,16 @@ export const prizePoolABI = [ stateMutability: 'nonpayable', type: 'function' }, + { + inputs: [ + { internalType: 'address', name: '_vault', type: 'address' }, + { internalType: 'address', name: '_recipient', type: 'address' } + ], + name: 'withdrawShutdownBalance', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'nonpayable', + type: 'function' + }, { anonymous: false, inputs: [ @@ -422,8 +512,8 @@ export const prizePoolABI = [ { indexed: false, internalType: 'uint8', name: 'tier', type: 'uint8' }, { indexed: false, internalType: 'uint32', name: 'prizeIndex', type: 'uint32' }, { indexed: false, internalType: 'uint152', name: 'payout', type: 'uint152' }, - { indexed: false, internalType: 'uint96', name: 'fee', type: 'uint96' }, - { indexed: false, internalType: 'address', name: 'feeRecipient', type: 'address' } + { indexed: false, internalType: 'uint96', name: 'claimReward', type: 'uint96' }, + { indexed: false, internalType: 'address', name: 'claimRewardRecipient', type: 'address' } ], name: 'ClaimedPrize', type: 'event' @@ -461,12 +551,6 @@ export const prizePoolABI = [ name: 'DrawAwarded', type: 'event' }, - { - anonymous: false, - inputs: [{ indexed: true, internalType: 'address', name: 'drawManager', type: 'address' }], - name: 'DrawManagerSet', - type: 'event' - }, { anonymous: false, inputs: [ @@ -478,17 +562,14 @@ export const prizePoolABI = [ }, { anonymous: false, - inputs: [ - { indexed: true, internalType: 'address', name: 'previousOwner', type: 'address' }, - { indexed: true, internalType: 'address', name: 'newOwner', type: 'address' } - ], - name: 'OwnershipTransferred', + inputs: [{ indexed: false, internalType: 'uint256', name: 'amount', type: 'uint256' }], + name: 'ReserveConsumed', type: 'event' }, { anonymous: false, - inputs: [{ indexed: false, internalType: 'uint256', name: 'amount', type: 'uint256' }], - name: 'ReserveConsumed', + inputs: [{ indexed: true, internalType: 'address', name: 'drawManager', type: 'address' }], + name: 'SetDrawManager', type: 'event' }, { @@ -525,6 +606,7 @@ export const prizePoolABI = [ name: 'ContributionGTDeltaBalance', type: 'error' }, + { inputs: [], name: 'CreatorIsZeroAddress', type: 'error' }, { inputs: [ { internalType: 'address', name: 'vault', type: 'address' }, @@ -543,16 +625,9 @@ export const prizePoolABI = [ name: 'DrawAwarded', type: 'error' }, - { inputs: [], name: 'DrawManagerIsZeroAddress', type: 'error' }, - { inputs: [], name: 'FeeRecipientZeroAddress', type: 'error' }, - { - inputs: [ - { internalType: 'uint256', name: 'fee', type: 'uint256' }, - { internalType: 'uint256', name: 'maxFee', type: 'uint256' } - ], - name: 'FeeTooLarge', - type: 'error' - }, + { inputs: [], name: 'DrawManagerAlreadySet', type: 'error' }, + { inputs: [], name: 'DrawTimeoutGTGrandPrizePeriodDraws', type: 'error' }, + { inputs: [], name: 'DrawTimeoutIsZero', type: 'error' }, { inputs: [], name: 'FirstDrawOpensInPast', type: 'error' }, { inputs: [], name: 'IncompatibleTwabPeriodLength', type: 'error' }, { inputs: [], name: 'IncompatibleTwabPeriodOffset', type: 'error' }, @@ -613,6 +688,7 @@ export const prizePoolABI = [ name: 'NumberOfTiersLessThanMinimum', type: 'error' }, + { inputs: [], name: 'OnlyCreator', type: 'error' }, { inputs: [ { internalType: 'uint256', name: 'x', type: 'uint256' }, @@ -684,11 +760,20 @@ export const prizePoolABI = [ type: 'error' }, { inputs: [], name: 'PrizeIsZero', type: 'error' }, + { inputs: [], name: 'PrizePoolNotShutdown', type: 'error' }, + { inputs: [], name: 'PrizePoolShutdown', type: 'error' }, { inputs: [], name: 'RandomNumberIsZero', type: 'error' }, + { inputs: [], name: 'RangeSizeZero', type: 'error' }, + { inputs: [], name: 'RewardRecipientZeroAddress', type: 'error' }, { - inputs: [{ internalType: 'int64', name: 'smoothing', type: 'int64' }], - name: 'SmoothingGTEOne', + inputs: [ + { internalType: 'uint256', name: 'reward', type: 'uint256' }, + { internalType: 'uint256', name: 'maxReward', type: 'uint256' } + ], + name: 'RewardTooLarge', type: 'error' }, + { inputs: [], name: 'TierLiquidityUtilizationRateCannotBeZero', type: 'error' }, + { inputs: [], name: 'TierLiquidityUtilizationRateGreaterThanOne', type: 'error' }, { inputs: [], name: 'UpperBoundGtZero', type: 'error' } ] as const diff --git a/shared/utilities/abis/rngAuction.ts b/shared/utilities/abis/rngAuction.ts deleted file mode 100644 index fb928691..00000000 --- a/shared/utilities/abis/rngAuction.ts +++ /dev/null @@ -1,283 +0,0 @@ -export const rngAuctionABI = [ - { - inputs: [], - name: 'auctionDuration', - outputs: [{ internalType: 'uint64', name: '', type: 'uint64' }], - stateMutability: 'view', - type: 'function' - }, - { - inputs: [], - name: 'auctionElapsedTime', - outputs: [{ internalType: 'uint64', name: '', type: 'uint64' }], - stateMutability: 'view', - type: 'function' - }, - { - inputs: [], - name: 'auctionTargetTime', - outputs: [{ internalType: 'uint64', name: '', type: 'uint64' }], - stateMutability: 'view', - type: 'function' - }, - { - inputs: [], - name: 'canStartNextSequence', - outputs: [{ internalType: 'bool', name: '', type: 'bool' }], - stateMutability: 'view', - type: 'function' - }, - { - inputs: [], - name: 'claimOwnership', - outputs: [], - stateMutability: 'nonpayable', - type: 'function' - }, - { - inputs: [{ internalType: 'uint64', name: '__auctionElapsedTime', type: 'uint64' }], - name: 'computeRewardFraction', - outputs: [{ internalType: 'UD2x18', name: '', type: 'uint64' }], - stateMutability: 'view', - type: 'function' - }, - { - inputs: [], - name: 'currentFractionalReward', - outputs: [{ internalType: 'UD2x18', name: '', type: 'uint64' }], - stateMutability: 'view', - type: 'function' - }, - { - inputs: [], - name: 'getLastAuction', - outputs: [ - { - components: [ - { internalType: 'address', name: 'recipient', type: 'address' }, - { internalType: 'UD2x18', name: 'rewardFraction', type: 'uint64' }, - { internalType: 'uint32', name: 'sequenceId', type: 'uint32' }, - { internalType: 'contract RNGInterface', name: 'rng', type: 'address' }, - { internalType: 'uint32', name: 'rngRequestId', type: 'uint32' } - ], - internalType: 'struct RngAuctionResult', - name: '', - type: 'tuple' - } - ], - stateMutability: 'view', - type: 'function' - }, - { - inputs: [], - name: 'getLastAuctionResult', - outputs: [ - { - components: [ - { internalType: 'address', name: 'recipient', type: 'address' }, - { internalType: 'UD2x18', name: 'rewardFraction', type: 'uint64' } - ], - internalType: 'struct AuctionResult', - name: '', - type: 'tuple' - } - ], - stateMutability: 'view', - type: 'function' - }, - { - inputs: [], - name: 'getLastRngService', - outputs: [{ internalType: 'contract RNGInterface', name: '', type: 'address' }], - stateMutability: 'view', - type: 'function' - }, - { - inputs: [], - name: 'getNextRngService', - outputs: [{ internalType: 'contract RNGInterface', name: '', type: 'address' }], - stateMutability: 'view', - type: 'function' - }, - { - inputs: [], - name: 'getRngResults', - outputs: [ - { internalType: 'uint256', name: 'randomNumber', type: 'uint256' }, - { internalType: 'uint64', name: 'rngCompletedAt', type: 'uint64' } - ], - stateMutability: 'nonpayable', - type: 'function' - }, - { - inputs: [], - name: 'isAuctionOpen', - outputs: [{ internalType: 'bool', name: '', type: 'bool' }], - stateMutability: 'view', - type: 'function' - }, - { - inputs: [], - name: 'isRngComplete', - outputs: [{ internalType: 'bool', name: '', type: 'bool' }], - stateMutability: 'view', - type: 'function' - }, - { - inputs: [], - name: 'lastSequenceId', - outputs: [{ internalType: 'uint32', name: '', type: 'uint32' }], - stateMutability: 'view', - type: 'function' - }, - { - inputs: [], - name: 'openSequenceId', - outputs: [{ internalType: 'uint32', name: '', type: 'uint32' }], - stateMutability: 'view', - type: 'function' - }, - { - inputs: [], - name: 'owner', - outputs: [{ internalType: 'address', name: '', type: 'address' }], - stateMutability: 'view', - type: 'function' - }, - { - inputs: [], - name: 'pendingOwner', - outputs: [{ internalType: 'address', name: '', type: 'address' }], - stateMutability: 'view', - type: 'function' - }, - { - inputs: [], - name: 'renounceOwnership', - outputs: [], - stateMutability: 'nonpayable', - type: 'function' - }, - { - inputs: [], - name: 'sequenceOffset', - outputs: [{ internalType: 'uint64', name: '', type: 'uint64' }], - stateMutability: 'view', - type: 'function' - }, - { - inputs: [], - name: 'sequencePeriod', - outputs: [{ internalType: 'uint64', name: '', type: 'uint64' }], - stateMutability: 'view', - type: 'function' - }, - { - inputs: [{ internalType: 'contract RNGInterface', name: '_rngService', type: 'address' }], - name: 'setNextRngService', - outputs: [], - stateMutability: 'nonpayable', - type: 'function' - }, - { - inputs: [{ internalType: 'address', name: '_rewardRecipient', type: 'address' }], - name: 'startRngRequest', - outputs: [], - stateMutability: 'nonpayable', - type: 'function' - }, - { - inputs: [{ internalType: 'address', name: '_newOwner', type: 'address' }], - name: 'transferOwnership', - outputs: [], - stateMutability: 'nonpayable', - type: 'function' - }, - { - anonymous: false, - inputs: [{ indexed: true, internalType: 'address', name: 'pendingOwner', type: 'address' }], - name: 'OwnershipOffered', - type: 'event' - }, - { - anonymous: false, - inputs: [ - { indexed: true, internalType: 'address', name: 'previousOwner', type: 'address' }, - { indexed: true, internalType: 'address', name: 'newOwner', type: 'address' } - ], - name: 'OwnershipTransferred', - type: 'event' - }, - { - anonymous: false, - inputs: [ - { indexed: true, internalType: 'address', name: 'sender', type: 'address' }, - { indexed: true, internalType: 'address', name: 'recipient', type: 'address' }, - { indexed: true, internalType: 'uint32', name: 'sequenceId', type: 'uint32' }, - { indexed: false, internalType: 'contract RNGInterface', name: 'rng', type: 'address' }, - { indexed: false, internalType: 'uint32', name: 'rngRequestId', type: 'uint32' }, - { indexed: false, internalType: 'uint64', name: 'elapsedTime', type: 'uint64' }, - { indexed: false, internalType: 'UD2x18', name: 'rewardFraction', type: 'uint64' } - ], - name: 'RngAuctionCompleted', - type: 'event' - }, - { - anonymous: false, - inputs: [ - { indexed: true, internalType: 'contract RNGInterface', name: 'rngService', type: 'address' } - ], - name: 'SetNextRngService', - type: 'event' - }, - { - inputs: [ - { internalType: 'uint64', name: 'auctionDuration', type: 'uint64' }, - { internalType: 'uint64', name: 'sequencePeriod', type: 'uint64' } - ], - name: 'AuctionDurationGTSequencePeriod', - type: 'error' - }, - { inputs: [], name: 'AuctionExpired', type: 'error' }, - { - inputs: [ - { internalType: 'uint64', name: 'auctionTargetTime', type: 'uint64' }, - { internalType: 'uint64', name: 'auctionDuration', type: 'uint64' } - ], - name: 'AuctionTargetTimeExceedsDuration', - type: 'error' - }, - { inputs: [], name: 'CannotStartNextSequence', type: 'error' }, - { inputs: [], name: 'OwnerZeroAddress', type: 'error' }, - { - inputs: [ - { internalType: 'uint256', name: 'x', type: 'uint256' }, - { internalType: 'uint256', name: 'y', type: 'uint256' } - ], - name: 'PRBMath_MulDiv18_Overflow', - type: 'error' - }, - { - inputs: [ - { internalType: 'uint256', name: 'x', type: 'uint256' }, - { internalType: 'uint256', name: 'y', type: 'uint256' }, - { internalType: 'uint256', name: 'denominator', type: 'uint256' } - ], - name: 'PRBMath_MulDiv_Overflow', - type: 'error' - }, - { - inputs: [{ internalType: 'uint256', name: 'x', type: 'uint256' }], - name: 'PRBMath_UD60x18_Convert_Overflow', - type: 'error' - }, - { - inputs: [{ internalType: 'UD60x18', name: 'x', type: 'uint256' }], - name: 'PRBMath_UD60x18_IntoUD2x18_Overflow', - type: 'error' - }, - { inputs: [], name: 'RewardRecipientIsZero', type: 'error' }, - { inputs: [], name: 'RngZeroAddress', type: 'error' }, - { inputs: [], name: 'SequencePeriodZero', type: 'error' }, - { inputs: [], name: 'TargetRewardFractionGTOne', type: 'error' } -] as const diff --git a/shared/utilities/abis/rngRelay.ts b/shared/utilities/abis/rngRelay.ts deleted file mode 100644 index e2ebe462..00000000 --- a/shared/utilities/abis/rngRelay.ts +++ /dev/null @@ -1,198 +0,0 @@ -export const rngRelayABI = [ - { - inputs: [], - name: 'auctionDuration', - outputs: [{ internalType: 'uint64', name: '', type: 'uint64' }], - stateMutability: 'view', - type: 'function' - }, - { - inputs: [{ internalType: 'uint64', name: '_auctionElapsedTime', type: 'uint64' }], - name: 'computeRewardFraction', - outputs: [{ internalType: 'UD2x18', name: '', type: 'uint64' }], - stateMutability: 'view', - type: 'function' - }, - { - inputs: [ - { - components: [ - { internalType: 'address', name: 'recipient', type: 'address' }, - { internalType: 'UD2x18', name: 'rewardFraction', type: 'uint64' } - ], - internalType: 'struct AuctionResult[]', - name: '__auctionResults', - type: 'tuple[]' - } - ], - name: 'computeRewards', - outputs: [{ internalType: 'uint256[]', name: '', type: 'uint256[]' }], - stateMutability: 'view', - type: 'function' - }, - { - inputs: [ - { - components: [ - { internalType: 'address', name: 'recipient', type: 'address' }, - { internalType: 'UD2x18', name: 'rewardFraction', type: 'uint64' } - ], - internalType: 'struct AuctionResult[]', - name: '__auctionResults', - type: 'tuple[]' - }, - { internalType: 'uint256', name: '_totalReserve', type: 'uint256' } - ], - name: 'computeRewardsWithTotal', - outputs: [{ internalType: 'uint256[]', name: '', type: 'uint256[]' }], - stateMutability: 'pure', - type: 'function' - }, - { - inputs: [], - name: 'getLastAuctionResult', - outputs: [ - { - components: [ - { internalType: 'address', name: 'recipient', type: 'address' }, - { internalType: 'UD2x18', name: 'rewardFraction', type: 'uint64' } - ], - internalType: 'struct AuctionResult', - name: '', - type: 'tuple' - } - ], - stateMutability: 'view', - type: 'function' - }, - { - inputs: [ - { internalType: 'uint32', name: '_sequenceId', type: 'uint32' }, - { internalType: 'uint256', name: '_rngCompletedAt', type: 'uint256' } - ], - name: 'isAuctionOpen', - outputs: [{ internalType: 'bool', name: '', type: 'bool' }], - stateMutability: 'view', - type: 'function' - }, - { - inputs: [{ internalType: 'uint32', name: '_sequenceId', type: 'uint32' }], - name: 'isSequenceCompleted', - outputs: [{ internalType: 'bool', name: '', type: 'bool' }], - stateMutability: 'view', - type: 'function' - }, - { - inputs: [], - name: 'lastSequenceId', - outputs: [{ internalType: 'uint32', name: '', type: 'uint32' }], - stateMutability: 'view', - type: 'function' - }, - { - inputs: [], - name: 'maxRewards', - outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], - stateMutability: 'view', - type: 'function' - }, - { - inputs: [], - name: 'prizePool', - outputs: [{ internalType: 'contract PrizePool', name: '', type: 'address' }], - stateMutability: 'view', - type: 'function' - }, - { - inputs: [], - name: 'rngAuctionRelayer', - outputs: [{ internalType: 'address', name: '', type: 'address' }], - stateMutability: 'view', - type: 'function' - }, - { - inputs: [ - { internalType: 'uint256', name: '_randomNumber', type: 'uint256' }, - { internalType: 'uint256', name: '_rngCompletedAt', type: 'uint256' }, - { internalType: 'address', name: '_rewardRecipient', type: 'address' }, - { internalType: 'uint32', name: '_sequenceId', type: 'uint32' }, - { - components: [ - { internalType: 'address', name: 'recipient', type: 'address' }, - { internalType: 'UD2x18', name: 'rewardFraction', type: 'uint64' } - ], - internalType: 'struct AuctionResult', - name: '_rngAuctionResult', - type: 'tuple' - } - ], - name: 'rngComplete', - outputs: [{ internalType: 'bytes32', name: '', type: 'bytes32' }], - stateMutability: 'nonpayable', - type: 'function' - }, - { - anonymous: false, - inputs: [ - { indexed: true, internalType: 'uint32', name: 'sequenceId', type: 'uint32' }, - { indexed: true, internalType: 'address', name: 'recipient', type: 'address' }, - { indexed: true, internalType: 'uint32', name: 'index', type: 'uint32' }, - { indexed: false, internalType: 'uint256', name: 'reward', type: 'uint256' } - ], - name: 'AuctionRewardAllocated', - type: 'event' - }, - { - anonymous: false, - inputs: [ - { indexed: true, internalType: 'uint32', name: 'sequenceId', type: 'uint32' }, - { indexed: true, internalType: 'uint32', name: 'drawId', type: 'uint32' } - ], - name: 'RngSequenceCompleted', - type: 'event' - }, - { inputs: [], name: 'AuctionDurationZero', type: 'error' }, - { inputs: [], name: 'AuctionExpired', type: 'error' }, - { - inputs: [ - { internalType: 'uint64', name: 'auctionDuration', type: 'uint64' }, - { internalType: 'uint64', name: 'auctionTargetTime', type: 'uint64' } - ], - name: 'AuctionTargetTimeExceedsDuration', - type: 'error' - }, - { inputs: [], name: 'AuctionTargetTimeZero', type: 'error' }, - { inputs: [], name: 'MaxRewardIsZero', type: 'error' }, - { - inputs: [ - { internalType: 'uint256', name: 'x', type: 'uint256' }, - { internalType: 'uint256', name: 'y', type: 'uint256' } - ], - name: 'PRBMath_MulDiv18_Overflow', - type: 'error' - }, - { - inputs: [ - { internalType: 'uint256', name: 'x', type: 'uint256' }, - { internalType: 'uint256', name: 'y', type: 'uint256' }, - { internalType: 'uint256', name: 'denominator', type: 'uint256' } - ], - name: 'PRBMath_MulDiv_Overflow', - type: 'error' - }, - { - inputs: [{ internalType: 'uint256', name: 'x', type: 'uint256' }], - name: 'PRBMath_UD60x18_Convert_Overflow', - type: 'error' - }, - { inputs: [], name: 'PrizePoolZeroAddress', type: 'error' }, - { inputs: [], name: 'RewardRecipientIsZeroAddress', type: 'error' }, - { inputs: [], name: 'RngRelayerZeroAddress', type: 'error' }, - { inputs: [], name: 'SequenceAlreadyCompleted', type: 'error' }, - { inputs: [], name: 'TargetRewardFractionGTOne', type: 'error' }, - { - inputs: [{ internalType: 'address', name: 'relayer', type: 'address' }], - name: 'UnauthorizedRelayer', - type: 'error' - } -] as const diff --git a/shared/utilities/abis/twabController.ts b/shared/utilities/abis/twabController.ts index 86bee37b..80c792df 100644 --- a/shared/utilities/abis/twabController.ts +++ b/shared/utilities/abis/twabController.ts @@ -285,6 +285,20 @@ export const twabControllerABI = [ stateMutability: 'view', type: 'function' }, + { + inputs: [{ internalType: 'uint256', name: 'timestamp', type: 'uint256' }], + name: 'isShutdownAt', + outputs: [{ internalType: 'bool', name: '', type: 'bool' }], + stateMutability: 'view', + type: 'function' + }, + { + inputs: [], + name: 'lastObservationAt', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function' + }, { inputs: [ { internalType: 'address', name: '_to', type: 'address' }, diff --git a/shared/utilities/abis/vault.ts b/shared/utilities/abis/vault.ts index 2bbfc585..599cf417 100644 --- a/shared/utilities/abis/vault.ts +++ b/shared/utilities/abis/vault.ts @@ -6,6 +6,27 @@ export const vaultABI = [ stateMutability: 'view', type: 'function' }, + { + inputs: [], + name: 'FEE_PRECISION', + outputs: [{ internalType: 'uint32', name: '', type: 'uint32' }], + stateMutability: 'view', + type: 'function' + }, + { + inputs: [], + name: 'HOOK_GAS', + outputs: [{ internalType: 'uint24', name: '', type: 'uint24' }], + stateMutability: 'view', + type: 'function' + }, + { + inputs: [], + name: 'MAX_YIELD_FEE', + outputs: [{ internalType: 'uint32', name: '', type: 'uint32' }], + stateMutability: 'view', + type: 'function' + }, { inputs: [ { internalType: 'address', name: 'owner', type: 'address' }, @@ -40,13 +61,6 @@ export const vaultABI = [ stateMutability: 'view', type: 'function' }, - { - inputs: [], - name: 'availableYieldFeeBalance', - outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], - stateMutability: 'view', - type: 'function' - }, { inputs: [{ internalType: 'address', name: '_account', type: 'address' }], name: 'balanceOf', @@ -74,6 +88,13 @@ export const vaultABI = [ stateMutability: 'nonpayable', type: 'function' }, + { + inputs: [{ internalType: 'uint256', name: '_shares', type: 'uint256' }], + name: 'claimYieldFeeShares', + outputs: [], + stateMutability: 'nonpayable', + type: 'function' + }, { inputs: [], name: 'claimer', @@ -92,6 +113,13 @@ export const vaultABI = [ inputs: [{ internalType: 'uint256', name: '_assets', type: 'uint256' }], name: 'convertToShares', outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'pure', + type: 'function' + }, + { + inputs: [], + name: 'currentYieldBuffer', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], stateMutability: 'view', type: 'function' }, @@ -152,7 +180,7 @@ export const vaultABI = [ type: 'function' }, { - inputs: [{ internalType: 'address', name: '_account', type: 'address' }], + inputs: [{ internalType: 'address', name: 'account', type: 'address' }], name: 'getHooks', outputs: [ { @@ -182,7 +210,7 @@ export const vaultABI = [ { inputs: [ { internalType: 'address', name: '_tokenOut', type: 'address' }, - { internalType: 'address', name: 'liquidationPair_', type: 'address' } + { internalType: 'address', name: '_liquidationPair', type: 'address' } ], name: 'isLiquidationPair', outputs: [{ internalType: 'bool', name: '', type: 'bool' }], @@ -190,14 +218,7 @@ export const vaultABI = [ type: 'function' }, { - inputs: [], - name: 'isVaultCollateralized', - outputs: [{ internalType: 'bool', name: '', type: 'bool' }], - stateMutability: 'view', - type: 'function' - }, - { - inputs: [{ internalType: 'address', name: '_token', type: 'address' }], + inputs: [{ internalType: 'address', name: '_tokenOut', type: 'address' }], name: 'liquidatableBalanceOf', outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], stateMutability: 'view', @@ -218,7 +239,7 @@ export const vaultABI = [ type: 'function' }, { - inputs: [{ internalType: 'address', name: '', type: 'address' }], + inputs: [{ internalType: 'address', name: '_owner', type: 'address' }], name: 'maxMint', outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], stateMutability: 'view', @@ -248,13 +269,6 @@ export const vaultABI = [ stateMutability: 'nonpayable', type: 'function' }, - { - inputs: [{ internalType: 'uint256', name: '_shares', type: 'uint256' }], - name: 'mintYieldFee', - outputs: [], - stateMutability: 'nonpayable', - type: 'function' - }, { inputs: [], name: 'name', @@ -302,14 +316,14 @@ export const vaultABI = [ inputs: [{ internalType: 'uint256', name: '_assets', type: 'uint256' }], name: 'previewDeposit', outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], - stateMutability: 'view', + stateMutability: 'pure', type: 'function' }, { inputs: [{ internalType: 'uint256', name: '_shares', type: 'uint256' }], name: 'previewMint', outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], - stateMutability: 'view', + stateMutability: 'pure', type: 'function' }, { @@ -329,7 +343,7 @@ export const vaultABI = [ { inputs: [], name: 'prizePool', - outputs: [{ internalType: 'address', name: '', type: 'address' }], + outputs: [{ internalType: 'contract PrizePool', name: '', type: 'address' }], stateMutability: 'view', type: 'function' }, @@ -352,9 +366,9 @@ export const vaultABI = [ type: 'function' }, { - inputs: [{ internalType: 'address', name: 'claimer_', type: 'address' }], + inputs: [{ internalType: 'address', name: '_claimer', type: 'address' }], name: 'setClaimer', - outputs: [{ internalType: 'address', name: '', type: 'address' }], + outputs: [], stateMutability: 'nonpayable', type: 'function' }, @@ -377,23 +391,23 @@ export const vaultABI = [ type: 'function' }, { - inputs: [{ internalType: 'address', name: 'liquidationPair_', type: 'address' }], + inputs: [{ internalType: 'address', name: '_liquidationPair', type: 'address' }], name: 'setLiquidationPair', - outputs: [{ internalType: 'address', name: '', type: 'address' }], + outputs: [], stateMutability: 'nonpayable', type: 'function' }, { - inputs: [{ internalType: 'uint32', name: 'yieldFeePercentage_', type: 'uint32' }], + inputs: [{ internalType: 'uint32', name: '_yieldFeePercentage', type: 'uint32' }], name: 'setYieldFeePercentage', - outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + outputs: [], stateMutability: 'nonpayable', type: 'function' }, { - inputs: [{ internalType: 'address', name: 'yieldFeeRecipient_', type: 'address' }], + inputs: [{ internalType: 'address', name: '_yieldFeeRecipient', type: 'address' }], name: 'setYieldFeeRecipient', - outputs: [{ internalType: 'address', name: '', type: 'address' }], + outputs: [], stateMutability: 'nonpayable', type: 'function' }, @@ -404,13 +418,6 @@ export const vaultABI = [ stateMutability: 'nonpayable', type: 'function' }, - { - inputs: [], - name: 'sweep', - outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], - stateMutability: 'nonpayable', - type: 'function' - }, { inputs: [], name: 'symbol', @@ -432,6 +439,13 @@ export const vaultABI = [ stateMutability: 'view', type: 'function' }, + { + inputs: [], + name: 'totalDebt', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function' + }, { inputs: [], name: 'totalSupply', @@ -439,6 +453,13 @@ export const vaultABI = [ stateMutability: 'view', type: 'function' }, + { + inputs: [], + name: 'totalYieldBalance', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function' + }, { inputs: [ { internalType: 'address', name: 'to', type: 'address' }, @@ -482,7 +503,7 @@ export const vaultABI = [ { inputs: [], name: 'twabController', - outputs: [{ internalType: 'address', name: '', type: 'address' }], + outputs: [{ internalType: 'contract TwabController', name: '', type: 'address' }], stateMutability: 'view', type: 'function' }, @@ -510,32 +531,39 @@ export const vaultABI = [ }, { inputs: [], - name: 'yieldFeePercentage', + name: 'yieldBuffer', outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], stateMutability: 'view', type: 'function' }, { inputs: [], - name: 'yieldFeeRecipient', - outputs: [{ internalType: 'address', name: '', type: 'address' }], + name: 'yieldFeeBalance', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], stateMutability: 'view', type: 'function' }, { inputs: [], - name: 'yieldFeeShares', - outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + name: 'yieldFeePercentage', + outputs: [{ internalType: 'uint32', name: '', type: 'uint32' }], stateMutability: 'view', type: 'function' }, { inputs: [], - name: 'yieldVault', + name: 'yieldFeeRecipient', outputs: [{ internalType: 'address', name: '', type: 'address' }], stateMutability: 'view', type: 'function' }, + { + inputs: [], + name: 'yieldVault', + outputs: [{ internalType: 'contract IERC4626', name: '', type: 'address' }], + stateMutability: 'view', + type: 'function' + }, { anonymous: false, inputs: [ @@ -546,6 +574,15 @@ export const vaultABI = [ name: 'Approval', type: 'event' }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: 'address', name: 'recipient', type: 'address' }, + { indexed: false, internalType: 'uint256', name: 'shares', type: 'uint256' } + ], + name: 'ClaimYieldFeeShares', + type: 'event' + }, { anonymous: false, inputs: [{ indexed: true, internalType: 'address', name: 'claimer', type: 'address' }], @@ -573,38 +610,6 @@ export const vaultABI = [ name: 'LiquidationPairSet', type: 'event' }, - { - anonymous: false, - inputs: [ - { indexed: true, internalType: 'address', name: 'caller', type: 'address' }, - { indexed: true, internalType: 'address', name: 'recipient', type: 'address' }, - { indexed: false, internalType: 'uint256', name: 'shares', type: 'uint256' } - ], - name: 'MintYieldFee', - type: 'event' - }, - { - anonymous: false, - inputs: [ - { indexed: true, internalType: 'contract IERC20', name: 'asset', type: 'address' }, - { indexed: false, internalType: 'string', name: 'name', type: 'string' }, - { indexed: false, internalType: 'string', name: 'symbol', type: 'string' }, - { - indexed: false, - internalType: 'contract TwabController', - name: 'twabController', - type: 'address' - }, - { indexed: true, internalType: 'contract IERC4626', name: 'yieldVault', type: 'address' }, - { indexed: true, internalType: 'contract PrizePool', name: 'prizePool', type: 'address' }, - { indexed: false, internalType: 'address', name: 'claimer', type: 'address' }, - { indexed: false, internalType: 'address', name: 'yieldFeeRecipient', type: 'address' }, - { indexed: false, internalType: 'uint256', name: 'yieldFeePercentage', type: 'uint256' }, - { indexed: false, internalType: 'address', name: 'owner', type: 'address' } - ], - name: 'NewVault', - type: 'event' - }, { anonymous: false, inputs: [{ indexed: true, internalType: 'address', name: 'pendingOwner', type: 'address' }], @@ -630,7 +635,7 @@ export const vaultABI = [ { internalType: 'bool', name: 'useAfterClaimPrize', type: 'bool' }, { internalType: 'contract IVaultHooks', name: 'implementation', type: 'address' } ], - indexed: true, + indexed: false, internalType: 'struct VaultHooks', name: 'hooks', type: 'tuple' @@ -652,20 +657,23 @@ export const vaultABI = [ { anonymous: false, inputs: [ - { indexed: true, internalType: 'address', name: 'caller', type: 'address' }, - { indexed: false, internalType: 'uint256', name: 'assets', type: 'uint256' } + { indexed: true, internalType: 'address', name: 'from', type: 'address' }, + { indexed: true, internalType: 'address', name: 'to', type: 'address' }, + { indexed: false, internalType: 'uint256', name: 'value', type: 'uint256' } ], - name: 'Sweep', + name: 'Transfer', type: 'event' }, { anonymous: false, inputs: [ - { indexed: true, internalType: 'address', name: 'from', type: 'address' }, - { indexed: true, internalType: 'address', name: 'to', type: 'address' }, - { indexed: false, internalType: 'uint256', name: 'value', type: 'uint256' } + { indexed: true, internalType: 'address', name: 'liquidationPair', type: 'address' }, + { indexed: true, internalType: 'address', name: 'tokenOut', type: 'address' }, + { indexed: true, internalType: 'address', name: 'recipient', type: 'address' }, + { indexed: false, internalType: 'uint256', name: 'amountOut', type: 'uint256' }, + { indexed: false, internalType: 'uint256', name: 'yieldFee', type: 'uint256' } ], - name: 'Transfer', + name: 'TransferYieldOut', type: 'event' }, { @@ -696,16 +704,7 @@ export const vaultABI = [ name: 'YieldFeeRecipientSet', type: 'event' }, - { - inputs: [{ internalType: 'bytes', name: 'reason', type: 'bytes' }], - name: 'AfterClaimPrizeFailed', - type: 'error' - }, - { - inputs: [{ internalType: 'bytes', name: 'reason', type: 'bytes' }], - name: 'BeforeClaimPrizeFailed', - type: 'error' - }, + { inputs: [], name: 'BurnZeroShares', type: 'error' }, { inputs: [ { internalType: 'address', name: 'caller', type: 'address' }, @@ -722,28 +721,28 @@ export const vaultABI = [ name: 'CallerNotLP', type: 'error' }, - { inputs: [], name: 'ClaimRecipientZeroAddress', type: 'error' }, - { inputs: [], name: 'ClaimerZeroAddress', type: 'error' }, { inputs: [ - { internalType: 'address', name: 'receiver', type: 'address' }, - { internalType: 'uint256', name: 'amount', type: 'uint256' }, - { internalType: 'uint256', name: 'max', type: 'uint256' } + { internalType: 'address', name: 'caller', type: 'address' }, + { internalType: 'address', name: 'yieldFeeRecipient', type: 'address' } ], - name: 'DepositMoreThanMax', + name: 'CallerNotYieldFeeRecipient', type: 'error' }, + { inputs: [], name: 'ClaimRecipientZeroAddress', type: 'error' }, + { inputs: [], name: 'ClaimerZeroAddress', type: 'error' }, + { inputs: [], name: 'DepositZeroAssets', type: 'error' }, { inputs: [], name: 'InvalidShortString', type: 'error' }, { inputs: [], name: 'LPZeroAddress', type: 'error' }, + { inputs: [], name: 'LiquidationAmountOutZero', type: 'error' }, { inputs: [ - { internalType: 'uint256', name: 'amountOut', type: 'uint256' }, + { internalType: 'uint256', name: 'totalToWithdraw', type: 'uint256' }, { internalType: 'uint256', name: 'availableYield', type: 'uint256' } ], - name: 'LiquidationAmountOutGTYield', + name: 'LiquidationExceedsAvailable', type: 'error' }, - { inputs: [], name: 'LiquidationAmountOutZero', type: 'error' }, { inputs: [ { internalType: 'address', name: 'tokenIn', type: 'address' }, @@ -753,95 +752,63 @@ export const vaultABI = [ type: 'error' }, { - inputs: [ - { internalType: 'address', name: 'tokenOut', type: 'address' }, - { internalType: 'address', name: 'vaultShare', type: 'address' } - ], - name: 'LiquidationTokenOutNotVaultShare', + inputs: [{ internalType: 'address', name: 'tokenOut', type: 'address' }], + name: 'LiquidationTokenOutNotSupported', type: 'error' }, { inputs: [ - { internalType: 'address', name: 'receiver', type: 'address' }, - { internalType: 'uint256', name: 'amount', type: 'uint256' }, - { internalType: 'uint256', name: 'max', type: 'uint256' } + { internalType: 'uint256', name: 'totalAssets', type: 'uint256' }, + { internalType: 'uint256', name: 'totalSupply', type: 'uint256' } ], - name: 'MintMoreThanMax', + name: 'LossyDeposit', type: 'error' }, { inputs: [], name: 'MintZeroShares', type: 'error' }, { inputs: [], name: 'OwnerZeroAddress', type: 'error' }, - { inputs: [], name: 'PrizePoolZeroAddress', type: 'error' }, { inputs: [ { internalType: 'address', name: 'owner', type: 'address' }, + { internalType: 'address', name: 'spender', type: 'address' }, { internalType: 'uint256', name: 'amount', type: 'uint256' }, - { internalType: 'uint256', name: 'max', type: 'uint256' } - ], - name: 'RedeemMoreThanMax', - type: 'error' - }, - { - inputs: [{ internalType: 'string', name: 'str', type: 'string' }], - name: 'StringTooLong', - type: 'error' - }, - { inputs: [], name: 'SweepZeroAssets', type: 'error' }, - { - inputs: [{ internalType: 'address', name: 'token', type: 'address' }], - name: 'TargetTokenNotSupported', - type: 'error' - }, - { - inputs: [ - { internalType: 'address', name: 'asset', type: 'address' }, - { internalType: 'address', name: 'yieldVaultAsset', type: 'address' } + { internalType: 'uint256', name: 'allowance', type: 'uint256' } ], - name: 'UnderlyingAssetMismatch', + name: 'PermitAllowanceNotSet', type: 'error' }, - { inputs: [], name: 'VaultUndercollateralized', type: 'error' }, { inputs: [ - { internalType: 'uint256', name: 'requestedAssets', type: 'uint256' }, - { internalType: 'uint256', name: 'withdrawnAssets', type: 'uint256' } - ], - name: 'WithdrawAssetsLTRequested', - type: 'error' - }, - { - inputs: [ - { internalType: 'address', name: 'owner', type: 'address' }, - { internalType: 'uint256', name: 'amount', type: 'uint256' }, - { internalType: 'uint256', name: 'max', type: 'uint256' } + { internalType: 'address', name: 'caller', type: 'address' }, + { internalType: 'address', name: 'owner', type: 'address' } ], - name: 'WithdrawMoreThanMax', + name: 'PermitCallerNotOwner', type: 'error' }, - { inputs: [], name: 'WithdrawZeroAssets', type: 'error' }, + { inputs: [], name: 'PrizePoolZeroAddress', type: 'error' }, { inputs: [ { internalType: 'uint256', name: 'shares', type: 'uint256' }, - { internalType: 'uint256', name: 'yieldFeeShares', type: 'uint256' } + { internalType: 'uint256', name: 'yieldFeeBalance', type: 'uint256' } ], - name: 'YieldFeeGTAvailableShares', + name: 'SharesExceedsYieldFeeBalance', type: 'error' }, { - inputs: [ - { internalType: 'uint256', name: 'shares', type: 'uint256' }, - { internalType: 'uint256', name: 'availableYield', type: 'uint256' } - ], - name: 'YieldFeeGTAvailableYield', + inputs: [{ internalType: 'string', name: 'str', type: 'string' }], + name: 'StringTooLong', type: 'error' }, + { inputs: [], name: 'SweepZeroAssets', type: 'error' }, + { inputs: [], name: 'TwabControllerZeroAddress', type: 'error' }, + { inputs: [], name: 'WithdrawZeroAssets', type: 'error' }, { inputs: [ { internalType: 'uint256', name: 'yieldFeePercentage', type: 'uint256' }, { internalType: 'uint256', name: 'maxYieldFeePercentage', type: 'uint256' } ], - name: 'YieldFeePercentageGtePrecision', + name: 'YieldFeePercentageExceedsMax', type: 'error' }, - { inputs: [], name: 'YieldVaultZeroAddress', type: 'error' } + { inputs: [], name: 'YieldVaultZeroAddress', type: 'error' }, + { inputs: [], name: 'ZeroTotalAssets', type: 'error' } ] as const diff --git a/shared/utilities/abis/vaultFactory.ts b/shared/utilities/abis/vaultFactory.ts index 4427e995..3de8d84a 100644 --- a/shared/utilities/abis/vaultFactory.ts +++ b/shared/utilities/abis/vaultFactory.ts @@ -1,28 +1,13 @@ export const vaultFactoryABI = [ - { - anonymous: false, - inputs: [ - { indexed: true, internalType: 'contract VaultV2', name: 'vault', type: 'address' }, - { - indexed: true, - internalType: 'contract VaultFactoryV2', - name: 'vaultFactory', - type: 'address' - } - ], - name: 'NewFactoryVault', - type: 'event' - }, { inputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], name: 'allVaults', - outputs: [{ internalType: 'contract VaultV2', name: '', type: 'address' }], + outputs: [{ internalType: 'contract PrizeVault', name: '', type: 'address' }], stateMutability: 'view', type: 'function' }, { inputs: [ - { internalType: 'contract IERC20', name: '_asset', type: 'address' }, { internalType: 'string', name: '_name', type: 'string' }, { internalType: 'string', name: '_symbol', type: 'string' }, { internalType: 'contract IERC4626', name: '_yieldVault', type: 'address' }, @@ -30,24 +15,25 @@ export const vaultFactoryABI = [ { internalType: 'address', name: '_claimer', type: 'address' }, { internalType: 'address', name: '_yieldFeeRecipient', type: 'address' }, { internalType: 'uint32', name: '_yieldFeePercentage', type: 'uint32' }, + { internalType: 'uint256', name: '_yieldBuffer', type: 'uint256' }, { internalType: 'address', name: '_owner', type: 'address' } ], name: 'deployVault', - outputs: [{ internalType: 'address', name: '', type: 'address' }], + outputs: [{ internalType: 'contract PrizeVault', name: '', type: 'address' }], stateMutability: 'nonpayable', type: 'function' }, { - inputs: [{ internalType: 'address', name: '', type: 'address' }], + inputs: [{ internalType: 'address', name: 'vault', type: 'address' }], name: 'deployedVaults', - outputs: [{ internalType: 'bool', name: '', type: 'bool' }], + outputs: [{ internalType: 'bool', name: 'deployedByFactory', type: 'bool' }], stateMutability: 'view', type: 'function' }, { - inputs: [{ internalType: 'address', name: '', type: 'address' }], + inputs: [{ internalType: 'address', name: 'deployer', type: 'address' }], name: 'deployerNonces', - outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + outputs: [{ internalType: 'uint256', name: 'nonce', type: 'uint256' }], stateMutability: 'view', type: 'function' }, @@ -57,5 +43,17 @@ export const vaultFactoryABI = [ outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], stateMutability: 'view', type: 'function' + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: 'contract PrizeVault', name: 'vault', type: 'address' }, + { indexed: true, internalType: 'contract IERC4626', name: 'yieldVault', type: 'address' }, + { indexed: true, internalType: 'contract PrizePool', name: 'prizePool', type: 'address' }, + { indexed: false, internalType: 'string', name: 'name', type: 'string' }, + { indexed: false, internalType: 'string', name: 'symbol', type: 'string' } + ], + name: 'NewPrizeVault', + type: 'event' } ] as const diff --git a/shared/utilities/index.ts b/shared/utilities/index.ts index e91a57aa..471c7498 100644 --- a/shared/utilities/index.ts +++ b/shared/utilities/index.ts @@ -1,7 +1,6 @@ /** * ABIs */ -export * from './abis/chainlinkVrf' export * from './abis/erc20-oldPermit' export * from './abis/erc20' export * from './abis/liquidationPair' @@ -9,8 +8,6 @@ export * from './abis/liquidationPairFactory' export * from './abis/liquidationRouter' export * from './abis/opGasOracle' export * from './abis/prizePool' -export * from './abis/rngAuction' -export * from './abis/rngRelay' export * from './abis/twabController' export * from './abis/twabRewards' export * from './abis/vault' From b0e8626c113a70e432b142e7e2baf0a037481875 Mon Sep 17 00:00:00 2001 From: Ncookiez Date: Wed, 28 Feb 2024 15:29:50 -0500 Subject: [PATCH 002/161] updated shared utils --- shared/utilities/constants.ts | 197 +++++--------------------- shared/utilities/index.ts | 1 - shared/utilities/utils/events.ts | 220 +---------------------------- shared/utilities/utils/metamask.ts | 49 ------- shared/utilities/utils/networks.ts | 14 +- 5 files changed, 41 insertions(+), 440 deletions(-) delete mode 100644 shared/utilities/utils/metamask.ts diff --git a/shared/utilities/constants.ts b/shared/utilities/constants.ts index a91efcda..eee42857 100644 --- a/shared/utilities/constants.ts +++ b/shared/utilities/constants.ts @@ -13,6 +13,7 @@ export enum NETWORK { mumbai = 80001, optimism = 10, optimism_sepolia = 11155420, + optimism_goerli = 420, avalanche = 43114, fuji = 43113, celo = 42220, @@ -30,9 +31,7 @@ export type NETWORK_NAME = keyof typeof NETWORK export const POOL_TOKEN_ADDRESSES = { [NETWORK.mainnet]: '0x0cEC1A9154Ff802e7934Fc916Ed7Ca50bDE6844e', [NETWORK.polygon]: '0x25788a1a171ec66Da6502f9975a15B609fF54CF6', - [NETWORK.optimism]: '0x395ae52bb17aef68c2888d941736a71dc6d4e125', - [NETWORK.optimism_sepolia]: '0xD675B9c8eea7f6Bd506d5FF66A10cF7B887CD293', - [NETWORK.arbitrum_sepolia]: '0xF401D1482DFAa89A050F111992A222e9ad123E14' + [NETWORK.optimism]: '0x395ae52bb17aef68c2888d941736a71dc6d4e125' } as const /** @@ -44,9 +43,8 @@ export const USDC_TOKEN_ADDRESSES: { [chainId: number]: Lowercase
} = { [NETWORK.mainnet]: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48', [NETWORK.polygon]: '0x2791bca1f2de4661ed88a30c99a7a9449aa84174', [NETWORK.optimism]: '0x7f5c764cbc14f9669b88837ca1490cca17c31607', - [NETWORK.optimism_sepolia]: '0x8067f3cb6eef936256108ff19a05574b8ad99cf3', - [NETWORK.arbitrum]: '0xff970a61a04b1ca14834a43f5de4533ebddb5cc8', - [NETWORK.arbitrum_sepolia]: '0x7a6dbc7ff4f1a2d864291db3aec105a8eee4a3d2' + [NETWORK.optimism_goerli]: '0x3e5bc94a341481f742f5f573d341fa2540bc0992', + [NETWORK.arbitrum]: '0xff970a61a04b1ca14834a43f5de4533ebddb5cc8' } /** @@ -89,33 +87,13 @@ export const PRIZE_POOLS: { } }[] = [ { - chainId: NETWORK.optimism, - address: '0xe32e5E1c5f0c80bD26Def2d0EA5008C107000d6A', + chainId: NETWORK.optimism_goerli, + address: '0x6cdd88A97801aD20F2dcfd14f1F9370e54757536', options: { - prizeTokenAddress: '0x395ae52bb17aef68c2888d941736a71dc6d4e125', - drawPeriodInSeconds: 86_400, + prizeTokenAddress: '0x0Ba5e0722797dcEa8Cec409a707cE495C33fB23D', + drawPeriodInSeconds: 7200, tierShares: 100, - reserveShares: 80 - } - }, - { - chainId: NETWORK.optimism_sepolia, - address: '0x46547a849f68178208490Cdd491Df15a5bEeA4B2', - options: { - prizeTokenAddress: '0xD675B9c8eea7f6Bd506d5FF66A10cF7B887CD293', - drawPeriodInSeconds: 21_600, - tierShares: 100, - reserveShares: 80 - } - }, - { - chainId: NETWORK.arbitrum_sepolia, - address: '0x6Fd1dF849DFC4F76F0B15ba0c8D3e99FF84817f1', - options: { - prizeTokenAddress: '0xF401D1482DFAa89A050F111992A222e9ad123E14', - drawPeriodInSeconds: 21_600, - tierShares: 100, - reserveShares: 80 + reserveShares: 20 } } ] @@ -124,11 +102,8 @@ export const PRIZE_POOLS: { * Subgraph API URLs */ export const SUBGRAPH_API_URLS = { - [NETWORK.optimism]: 'https://api.studio.thegraph.com/query/50959/pt-v5-op/version/latest', - [NETWORK.optimism_sepolia]: - 'https://api.studio.thegraph.com/query/63100/pt-v5-op-sepolia/version/latest', - [NETWORK.arbitrum_sepolia]: - 'https://api.thegraph.com/subgraphs/name/chuckbergeron/pt-v5-arb-sepolia' // TODO: switch to proper version once available + [NETWORK.optimism_goerli]: + 'https://api.studio.thegraph.com/query/63100/pt-v5-op-goerli-new/version/latest' } as const /** @@ -159,6 +134,7 @@ export const COINGECKO_NATIVE_TOKEN_IDS: Record = { [NETWORK.mumbai]: 'matic-network', [NETWORK.optimism]: 'ethereum', [NETWORK.optimism_sepolia]: 'ethereum', + [NETWORK.optimism_goerli]: 'ethereum', [NETWORK.avalanche]: 'avalanche-2', [NETWORK.fuji]: 'avalanche-2', [NETWORK.celo]: 'celo', @@ -181,10 +157,8 @@ export const BLOCK_EXPLORERS: Record = { [NETWORK.polygon]: { name: 'Polygonscan', url: 'https://polygonscan.com/' }, [NETWORK.mumbai]: { name: 'Polygonscan', url: 'https://mumbai.polygonscan.com/' }, [NETWORK.optimism]: { name: 'Etherscan', url: 'https://optimistic.etherscan.io/' }, - [NETWORK.optimism_sepolia]: { - name: 'Etherscan', - url: 'https://sepolia-optimism.etherscan.io/' - }, + [NETWORK.optimism_sepolia]: { name: 'Etherscan', url: 'https://sepolia-optimism.etherscan.io/' }, + [NETWORK.optimism_goerli]: { name: 'Etherscan', url: 'https://goerli-optimism.etherscan.io/' }, [NETWORK.avalanche]: { name: 'Snowtrace', url: 'https://snowtrace.io/' }, [NETWORK.fuji]: { name: 'Snowtrace', url: 'https://testnet.snowtrace.io/' }, [NETWORK.celo]: { name: 'Celoscan', url: 'https://celoscan.io/' }, @@ -192,7 +166,7 @@ export const BLOCK_EXPLORERS: Record = { [NETWORK.arbitrum]: { name: 'Arbiscan', url: 'https://arbiscan.io/' }, [NETWORK.arbitrum_sepolia]: { name: 'Arbiscan', url: 'https://sepolia.arbiscan.io/' }, [NETWORK.base]: { name: 'Basescan', url: 'https://basescan.org/' }, - [NETWORK.base_sepolia]: { name: 'Blockscout', url: 'https://base-sepolia.blockscout.com/' } // TODO: update to basescan when available + [NETWORK.base_sepolia]: { name: 'Blockscout', url: 'https://sepolia.basescan.org/' } } /** @@ -220,10 +194,11 @@ export const STABLECOINS: Record = { '0xda10009cbd5d07dd0cecc66161fc93d7c9000da1': 'usd', // DAI '0xc40f949f8a4e094d1b49a23ea9241d289b7b2819': 'usd' // LUSD }, - [NETWORK.optimism_sepolia]: { - '0x8067f3cb6eef936256108ff19a05574b8ad99cf3': 'usd', // USDC - '0xd590ec14364731b62265a5cc807164a17c6797d4': 'usd', // DAI - '0x1a188719711d62423abf1a4de7d8aa9014a39d73': 'usd' // GUSD + [NETWORK.optimism_sepolia]: {}, + [NETWORK.optimism_goerli]: { + '0x3e5bc94a341481f742f5f573d341fa2540bc0992': 'usd', // USDC + '0xf6cff71208ffcab13223b31b036f2801d5de6d17': 'usd', // DAI + '0xabddb2c18a5d02f26a5ad5f4a361e4814dbe2175': 'usd' // GUSD }, [NETWORK.avalanche]: { '0xa7d7079b0fead91f3e65f86e8915cb59c1a4c664': 'usd' // USDC.e @@ -232,11 +207,7 @@ export const STABLECOINS: Record = { [NETWORK.celo]: {}, [NETWORK.celo_testnet]: {}, [NETWORK.arbitrum]: {}, - [NETWORK.arbitrum_sepolia]: { - '0x7a6dbc7ff4f1a2d864291db3aec105a8eee4a3d2': 'usd', // USDC - '0x08c19fe57af150a1af975cb9a38769848c7df98e': 'usd', // DAI - '0xb84460d777133a4b86540d557db35952e4adfee7': 'usd' // GUSD - }, + [NETWORK.arbitrum_sepolia]: {}, [NETWORK.base]: {}, [NETWORK.base_sepolia]: {} } @@ -256,6 +227,7 @@ export const WRAPPED_NATIVE_ASSETS: Record = { [NETWORK.mumbai]: null, [NETWORK.optimism]: '0x4200000000000000000000000000000000000006', [NETWORK.optimism_sepolia]: null, + [NETWORK.optimism_goerli]: null, [NETWORK.avalanche]: '0xb31f66aa3c1e785363f0875a1b74e27b85fd66c7', [NETWORK.fuji]: null, [NETWORK.celo]: null, @@ -266,105 +238,46 @@ export const WRAPPED_NATIVE_ASSETS: Record = { [NETWORK.base_sepolia]: null } -/** - * RNG auction addresses - */ -export const RNG_AUCTION: { - [chainId: number]: { address: Address; sequenceOffset: number; sequencePeriod: number } -} = { - [NETWORK.mainnet]: { - address: '0x539A76507F18505cA696d618F8A684814c867F41', - sequenceOffset: 1_697_508_000, - sequencePeriod: 86_400 - }, - [NETWORK.sepolia]: { - address: '0x1A188719711d62423abF1A4de7D8aA9014A39D73', - sequenceOffset: 1_699_185_600, - sequencePeriod: 21_600 - } -} - -/** - * RNG relay addresses - */ -export const RNG_RELAY_ADDRESSES: { - [chainId: number]: { address: Address; from: { chainId: number; address: Address } } -} = { - [NETWORK.optimism]: { - address: '0x87d3D9afeD1702728B7F280ba5c4b4c55DEfa557', - from: { chainId: NETWORK.mainnet, address: '0xEC9460c59cCA1299b0242D6AF426c21223ccCD24' } - }, - [NETWORK.optimism_sepolia]: { - address: '0x80788dD1bCc906b25C879F6f04A108C4DCFDB78F', - from: { chainId: NETWORK.sepolia, address: '0x48cdb9fe4F71D9b6f17D8e4d72E4036931601BdE' } - }, - [NETWORK.arbitrum_sepolia]: { - address: '0x4A101c4703e8fa447859EF380048052b0cDB9893', - from: { chainId: NETWORK.sepolia, address: '0xAFD0a893845cb2c278D6629c78fFA7ad403077Bf' } - } -} - -/** - * Message executor addresses - */ -export const MSG_EXECUTOR_ADDRESSES: { [chainId: number]: Address } = { - [NETWORK.optimism]: '0x139f6dD114a9C45Ba43eE22C5e03c53de0c13225', - [NETWORK.optimism_sepolia]: '0x6A501383A61ebFBc143Fc4BD41A2356bA71A6964', - [NETWORK.arbitrum_sepolia]: '0x2B3E6b5c9a6Bdb0e595896C9093fce013490abbD' -} - /** * TWAB controller addresses */ export const TWAB_CONTROLLER_ADDRESSES: { [chainId: number]: Address } = { - [NETWORK.optimism]: '0x499a9F249ec4c8Ea190bebbFD96f9A83bf4F6E52', - [NETWORK.optimism_sepolia]: '0x8027117dAf575dc0668EB0876dC89e622F4d2733', - [NETWORK.arbitrum_sepolia]: '0xd57822B8846F36f0E1FC775C8214523db199a4C5' + [NETWORK.optimism_goerli]: '0x499a9F249ec4c8Ea190bebbFD96f9A83bf4F6E52' } /** * TWAB rewards addresses */ export const TWAB_REWARDS_ADDRESSES: { [chainId: number]: Address } = { - [NETWORK.optimism]: '0x27Ed5760Edc0128E3043F6cC0C3428E337396A66', - [NETWORK.optimism_sepolia]: '0x18354F158CdcB87e81299c15110A5D59293B57F8', - [NETWORK.arbitrum_sepolia]: '0x8cfFF0B59491835a2aCee98d9F9D9D2Ebe71a943' + [NETWORK.optimism_goerli]: '0x24cf54ecd8eC53Eda05394c839AAb3B67fF8aF19' } /** * Vault factory addresses */ export const VAULT_FACTORY_ADDRESSES: { [chainId: number]: Address } = { - [NETWORK.optimism]: '0x6B17EE3a95BcCd605340454c5919e693Ef8EfF0E', - [NETWORK.optimism_sepolia]: '0x47266c3447459793903Fe79589f43230fEAF3666', - [NETWORK.arbitrum_sepolia]: '0x443E475baABAEA1Ec6Bb503acAaa7Fd39945f38F' + [NETWORK.optimism_goerli]: '0x644Ba78d965e276C9617F18AfD5357564B59a1Ae' } /** * Liquidation pair factory addresses */ export const LIQUIDATION_PAIR_FACTORY_ADDRESSES: { [chainId: number]: Address } = { - [NETWORK.optimism]: '0x555BD8Fc65E57139C9F405980C7A9526A7De8093', - [NETWORK.optimism_sepolia]: '0xD72e8522824FCE34CCdC6E8872008465287304C1', - [NETWORK.arbitrum_sepolia]: '0xb87E4dC3eDC62977bD8d93554a4cbF6c52c9282a' + [NETWORK.optimism_goerli]: '0xA7923D5331d079F2fC300eDD3594E9bbF5fBb45B' } /** * Default claimer addresses */ export const DEFAULT_CLAIMER_ADDRESSES: { [chainId: number]: Address } = { - [NETWORK.optimism]: '0xdc6aB38f9590cB8e4357e0a391689a7C5Ef7681E', - [NETWORK.optimism_sepolia]: '0xB4B4bF1C75234f307BC1A2c7eFba9329e532caB9', - [NETWORK.arbitrum_sepolia]: '0xcCf2b2da02C6F19b85265190F274BeE997808243' + [NETWORK.optimism_goerli]: '0x23b832b1EDb3986d52bB19CAB90BC0501F508500' } /** * Liquidation router addresses */ export const LIQUIDATION_ROUTER_ADDRESSES: { [chainId: number]: Address } = { - [NETWORK.optimism]: '0xB9Fba7B2216167DCdd1A7AE0a564dD43E1b68b95', - [NETWORK.optimism_sepolia]: '0x4f03fF51019f56495422E73287B0e4A9C454d371', - [NETWORK.arbitrum_sepolia]: '0xeE79841CBCB6BF29989B8977952A58C4417D64A9' + [NETWORK.optimism_goerli]: '0xC238AA2E03EC39bF774Bb18Fb41997962c5AB0d3' } /** @@ -419,78 +332,36 @@ export const TOKEN_PRICE_REDIRECTS: { address: '0x0000000000000000000000000000000000001010' } }, - [NETWORK.optimism_sepolia]: { + [NETWORK.optimism_goerli]: { /* ETH */ [DOLPHIN_ADDRESS]: { chainId: NETWORK.mainnet, address: DOLPHIN_ADDRESS }, /* DAI */ - '0xd590ec14364731b62265a5cc807164a17c6797d4': { + '0xf6cff71208ffcab13223b31b036f2801d5de6d17': { chainId: NETWORK.optimism, address: '0xda10009cbd5d07dd0cecc66161fc93d7c9000da1' }, /* USDC */ - '0x8067f3cb6eef936256108ff19a05574b8ad99cf3': { + '0x3e5bc94a341481f742f5f573d341fa2540bc0992': { chainId: NETWORK.optimism, address: USDC_TOKEN_ADDRESSES[NETWORK.optimism] }, /* GUSD */ - '0x1a188719711d62423abf1a4de7d8aa9014a39d73': { + '0xabddb2c18a5d02f26a5ad5f4a361e4814dbe2175': { chainId: NETWORK.mainnet, address: '0x056fd409e1d7a124bd7017459dfea2f387b6d5cd' }, /* WBTC */ - '0x149e3b3bd69f1cfc1b42b6a6a152a42e38ceebf1': { + '0x3fa21c64666d1245dbc1836ded2e4b47979c6bee': { chainId: NETWORK.optimism, address: '0x68f180fcce6836688e9084f035309e29bf0a2095' }, /* WETH */ - '0xa416ed51158c5616b997b785fa6d18f02d0458a8': { + '0x0ba5e0722797dcea8cec409a707ce495c33fb23d': { chainId: NETWORK.optimism, address: WRAPPED_NATIVE_ASSETS[NETWORK.optimism] as Address - }, - /* POOL */ - '0xd675b9c8eea7f6bd506d5ff66a10cf7b887cd293': { - chainId: NETWORK.mainnet, - address: POOL_TOKEN_ADDRESSES[NETWORK.mainnet].toLowerCase() as Address - } - }, - [NETWORK.arbitrum_sepolia]: { - /* ETH */ - [DOLPHIN_ADDRESS]: { - chainId: NETWORK.mainnet, - address: DOLPHIN_ADDRESS - }, - /* DAI */ - '0x08c19fe57af150a1af975cb9a38769848c7df98e': { - chainId: NETWORK.arbitrum, - address: '0xda10009cbd5d07dd0cecc66161fc93d7c9000da1' - }, - /* USDC */ - '0x7a6dbc7ff4f1a2d864291db3aec105a8eee4a3d2': { - chainId: NETWORK.arbitrum, - address: USDC_TOKEN_ADDRESSES[NETWORK.arbitrum] - }, - /* GUSD */ - '0xb84460d777133a4b86540d557db35952e4adfee7': { - chainId: NETWORK.mainnet, - address: '0x056fd409e1d7a124bd7017459dfea2f387b6d5cd' - }, - /* WBTC */ - '0x1bc266e1f397517ece9e384c55c7a5414b683639': { - chainId: NETWORK.arbitrum, - address: '0x2f2a2543b76a4166549f7aab2e75bef0aefc5b0f' - }, - /* WETH */ - '0x779275fc1b987db24463801f3708f42f3c6f6ceb': { - chainId: NETWORK.arbitrum, - address: WRAPPED_NATIVE_ASSETS[NETWORK.arbitrum] as Address - }, - /* POOL */ - '0xf401d1482dfaa89a050f111992a222e9ad123e14': { - chainId: NETWORK.mainnet, - address: POOL_TOKEN_ADDRESSES[NETWORK.mainnet].toLowerCase() as Address } } } diff --git a/shared/utilities/index.ts b/shared/utilities/index.ts index 471c7498..1d422a1c 100644 --- a/shared/utilities/index.ts +++ b/shared/utilities/index.ts @@ -26,7 +26,6 @@ export * from './utils/events' export * from './utils/formatting' export * from './utils/liquidations' export * from './utils/math' -export * from './utils/metamask' export * from './utils/multicall' export * from './utils/networks' export * from './utils/odds' diff --git a/shared/utilities/utils/events.ts b/shared/utilities/utils/events.ts index c05ed67a..098c8967 100644 --- a/shared/utilities/utils/events.ts +++ b/shared/utilities/utils/events.ts @@ -1,11 +1,5 @@ import { Address, PublicClient } from 'viem' -import { - LIQUIDATION_ROUTER_ADDRESSES, - MSG_EXECUTOR_ADDRESSES, - RNG_AUCTION, - RNG_RELAY_ADDRESSES, - TWAB_REWARDS_ADDRESSES -} from '../constants' +import { LIQUIDATION_ROUTER_ADDRESSES, TWAB_REWARDS_ADDRESSES } from '../constants' import { getLiquidationPairAddresses } from './liquidations' /** @@ -69,102 +63,6 @@ export const getWithdrawEvents = async ( }) } -/** - * Returns `RelayedToDispatcher` events - * @param publicClient a public Viem client to query through - * @param destinationChainId the chain ID that the messages are to be relayed to - * @param options optional settings - * @returns - */ -export const getRngL1RelayMsgEvents = async ( - publicClient: PublicClient, - destinationChainId: number, - options?: { fromBlock?: bigint; toBlock?: bigint } -) => { - const chainId = await publicClient.getChainId() - - const rngRelayContractAddress = RNG_RELAY_ADDRESSES[destinationChainId]?.from.address - - if ( - !rngRelayContractAddress || - RNG_RELAY_ADDRESSES[destinationChainId].from.chainId !== chainId - ) { - console.warn( - `No relay auction addresses set from chain ID ${chainId} to chain ID ${destinationChainId}` - ) - return [] - } - - return await publicClient.getLogs({ - address: rngRelayContractAddress, - event: { - inputs: [ - { - indexed: false, - internalType: 'contract IMessageDispatcher', - name: 'messageDispatcher', - type: 'address' - }, - { indexed: true, internalType: 'uint256', name: 'remoteOwnerChainId', type: 'uint256' }, - { - indexed: false, - internalType: 'contract RemoteOwner', - name: 'remoteOwner', - type: 'address' - }, - { - indexed: false, - internalType: 'contract IRngAuctionRelayListener', - name: 'remoteRngAuctionRelayListener', - type: 'address' - }, - { indexed: true, internalType: 'address', name: 'rewardRecipient', type: 'address' }, - { indexed: true, internalType: 'bytes32', name: 'messageId', type: 'bytes32' } - ], - name: 'RelayedToDispatcher', - type: 'event' - }, - fromBlock: options?.fromBlock, - toBlock: options?.toBlock ?? 'latest', - strict: true - }) -} - -/** - * Returns `MessageIdExecuted` events - * @param publicClient a public Viem client to query through - * @param options optional settings - * @returns - */ -export const getRngL2RelayMsgEvents = async ( - publicClient: PublicClient, - options?: { fromBlock?: bigint; toBlock?: bigint } -) => { - const chainId = await publicClient.getChainId() - - const msgExecutorContractAddress = MSG_EXECUTOR_ADDRESSES[chainId] - - if (!msgExecutorContractAddress) { - console.warn(`No message executor contract set for chain ID ${chainId}`) - return [] - } - - return await publicClient.getLogs({ - address: msgExecutorContractAddress, - event: { - inputs: [ - { indexed: true, internalType: 'uint256', name: 'fromChainId', type: 'uint256' }, - { indexed: true, internalType: 'bytes32', name: 'messageId', type: 'bytes32' } - ], - name: 'MessageIdExecuted', - type: 'event' - }, - fromBlock: options?.fromBlock, - toBlock: options?.toBlock ?? 'latest', - strict: true - }) -} - /** * Returns `DrawAwarded` events * @param publicClient a public Viem client to query through @@ -182,21 +80,11 @@ export const getDrawAwardedEvents = async ( event: { inputs: [ { indexed: true, internalType: 'uint24', name: 'drawId', type: 'uint24' }, - { - indexed: false, - internalType: 'uint256', - name: 'winningRandomNumber', - type: 'uint256' - }, + { indexed: false, internalType: 'uint256', name: 'winningRandomNumber', type: 'uint256' }, { indexed: false, internalType: 'uint8', name: 'lastNumTiers', type: 'uint8' }, { indexed: false, internalType: 'uint8', name: 'numTiers', type: 'uint8' }, { indexed: false, internalType: 'uint104', name: 'reserve', type: 'uint104' }, - { - indexed: false, - internalType: 'UD34x4', - name: 'prizeTokensPerShare', - type: 'uint128' - }, + { indexed: false, internalType: 'UD34x4', name: 'prizeTokensPerShare', type: 'uint128' }, { indexed: false, internalType: 'uint48', name: 'drawOpenedAt', type: 'uint48' } ], name: 'DrawAwarded', @@ -331,108 +219,6 @@ export const getManualContributionEvents = async ( }) } -/** - * Returns `ReserveConsumed` events - * @param publicClient a public Viem client to query through - * @param prizePoolAddress the address of the prize pool to query events for - * @param options optional settings - * @returns - */ -export const getPrizeBackstopEvents = async ( - publicClient: PublicClient, - prizePoolAddress: Address, - options?: { fromBlock?: bigint; toBlock?: bigint } -) => { - return await publicClient.getLogs({ - address: prizePoolAddress, - event: { - inputs: [{ indexed: false, internalType: 'uint256', name: 'amount', type: 'uint256' }], - name: 'ReserveConsumed', - type: 'event' - }, - fromBlock: options?.fromBlock, - toBlock: options?.toBlock ?? 'latest', - strict: true - }) -} - -/** - * Returns `AuctionRewardAllocated` events - * @param publicClient a public Viem client to query through - * @param options optional settings - * @returns - */ -export const getRelayAuctionEvents = async ( - publicClient: PublicClient, - options?: { fromBlock?: bigint; toBlock?: bigint } -) => { - const chainId = await publicClient.getChainId() - - const rngRelayContractAddress = RNG_RELAY_ADDRESSES[chainId]?.address - - if (!rngRelayContractAddress) { - console.warn(`No relay auction contract set for chain ID ${chainId}`) - return [] - } - - return await publicClient.getLogs({ - address: rngRelayContractAddress, - event: { - inputs: [ - { indexed: true, internalType: 'uint32', name: 'sequenceId', type: 'uint32' }, - { indexed: true, internalType: 'address', name: 'recipient', type: 'address' }, - { indexed: true, internalType: 'uint32', name: 'index', type: 'uint32' }, - { indexed: false, internalType: 'uint256', name: 'reward', type: 'uint256' } - ], - name: 'AuctionRewardAllocated', - type: 'event' - }, - fromBlock: options?.fromBlock, - toBlock: options?.toBlock ?? 'latest', - strict: true - }) -} - -/** - * Returns `RngAuctionCompleted` events - * @param publicClient a public Viem client to query through - * @param options optional settings - * @returns - */ -export const getRngAuctionEvents = async ( - publicClient: PublicClient, - options?: { fromBlock?: bigint; toBlock?: bigint } -) => { - const chainId = await publicClient.getChainId() - - const rngAuctionContract = RNG_AUCTION[chainId] - - if (!rngAuctionContract) { - console.warn(`No RNG auction contract set for chain ID ${chainId}`) - return [] - } - - return await publicClient.getLogs({ - address: rngAuctionContract.address, - event: { - inputs: [ - { indexed: true, internalType: 'address', name: 'sender', type: 'address' }, - { indexed: true, internalType: 'address', name: 'recipient', type: 'address' }, - { indexed: true, internalType: 'uint32', name: 'sequenceId', type: 'uint32' }, - { indexed: false, internalType: 'contract RNGInterface', name: 'rng', type: 'address' }, - { indexed: false, internalType: 'uint32', name: 'rngRequestId', type: 'uint32' }, - { indexed: false, internalType: 'uint64', name: 'elapsedTime', type: 'uint64' }, - { indexed: false, internalType: 'UD2x18', name: 'rewardFraction', type: 'uint64' } - ], - name: 'RngAuctionCompleted', - type: 'event' - }, - fromBlock: options?.fromBlock, - toBlock: options?.toBlock ?? 'latest', - strict: true - }) -} - /** * Returns `Transfer` events for a given token * @param publicClient a public Viem client to query through diff --git a/shared/utilities/utils/metamask.ts b/shared/utilities/utils/metamask.ts deleted file mode 100644 index 046d05fd..00000000 --- a/shared/utilities/utils/metamask.ts +++ /dev/null @@ -1,49 +0,0 @@ -import { POOL_TOKEN_ADDRESSES } from '../constants' - -/** - * Adds any token to the currently connected MetaMask wallet - * @param token token to be added to MetaMask - * @returns - */ -export const addTokenToMetaMask = async (token: { - address: string - symbol: string - decimals: number - image: string -}) => { - try { - // @ts-ignore - if (!ethereum || !token || !token.address || !token.symbol || !token.decimals || !token.image) { - throw new Error() - } - - // @ts-ignore - return await ethereum.request({ - method: 'wallet_watchAsset', - params: { - type: 'ERC20', - options: token - } - }) - } catch (error) { - console.error(error) - } -} - -/** - * Adds the POOL token to the currently connected MetaMask wallet - * @param chainId chain ID to add the token to - * @returns - */ -export const addPoolTokenToMetaMask = async (chainId: number) => { - if (chainId in POOL_TOKEN_ADDRESSES) { - return addTokenToMetaMask({ - address: POOL_TOKEN_ADDRESSES[chainId as keyof typeof POOL_TOKEN_ADDRESSES], - symbol: 'POOL', - decimals: 18, - image: 'https://app.pooltogether.com/pooltogether-token-logo@2x.png' - }) - } else { - console.error(`No POOL token address found in chain ${chainId}`) - } -} diff --git a/shared/utilities/utils/networks.ts b/shared/utilities/utils/networks.ts index 8b616a4b..0da28c0e 100644 --- a/shared/utilities/utils/networks.ts +++ b/shared/utilities/utils/networks.ts @@ -1,15 +1,5 @@ import { NETWORK } from '../constants' -/** - * Returns the chain ID that maps to a provided network name - * @param networkName name that maps to a chain ID - * @returns - */ -export const getChainIdByName = (networkName: string): number | undefined => { - // @ts-ignore - return NETWORK[networkName] -} - /** * Returns the network name that maps to a provided chain ID * @param chainId chain ID that maps to a network name @@ -41,6 +31,9 @@ export const getNiceNetworkNameByChainId = (chainId: number): string => { case NETWORK.optimism_sepolia: { return 'Optimism Sepolia' } + case NETWORK.optimism_goerli: { + return 'Optimism Goerli' + } case NETWORK.arbitrum_sepolia: { return 'Arbitrum Sepolia' } @@ -73,6 +66,7 @@ export const isTestnet = (chainId: number) => { [NETWORK.mumbai]: true, [NETWORK.optimism]: false, [NETWORK.optimism_sepolia]: true, + [NETWORK.optimism_goerli]: true, [NETWORK.avalanche]: false, [NETWORK.fuji]: true, [NETWORK.celo]: false, From 7d8923cb3871a60c2b8fd3051e937bfe4634b353 Mon Sep 17 00:00:00 2001 From: Ncookiez Date: Wed, 28 Feb 2024 15:35:29 -0500 Subject: [PATCH 003/161] updated shared types --- shared/types/types/vaults.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shared/types/types/vaults.ts b/shared/types/types/vaults.ts index fb67ae04..2ceb720e 100644 --- a/shared/types/types/vaults.ts +++ b/shared/types/types/vaults.ts @@ -54,7 +54,6 @@ export interface VaultListTags { export interface VaultDeployInfo { chainId: number - token: `0x${string}` name: string symbol: string yieldSourceName: string @@ -63,5 +62,6 @@ export interface VaultDeployInfo { claimer: `0x${string}` feeRecipient: `0x${string}` feePercentage: number + yieldBuffer: bigint owner: `0x${string}` } From ffc0f75623b5589a91478e358c09d9784ce99811 Mon Sep 17 00:00:00 2001 From: Ncookiez Date: Wed, 28 Feb 2024 15:47:42 -0500 Subject: [PATCH 004/161] updated shared react components --- .../Modals/AaveCollateralizationError.tsx | 84 ------------------- .../Modals/CheckPrizesModal/Views/WinView.tsx | 16 +--- .../Modals/WithdrawModal/Views/MainView.tsx | 20 +---- .../Modals/WithdrawModal/WithdrawTxButton.tsx | 11 +-- .../components/Modals/WithdrawModal/index.tsx | 3 - .../components/PrizePool/PrizePoolCard.tsx | 11 +-- 6 files changed, 7 insertions(+), 138 deletions(-) delete mode 100644 shared/react-components/components/Modals/AaveCollateralizationError.tsx diff --git a/shared/react-components/components/Modals/AaveCollateralizationError.tsx b/shared/react-components/components/Modals/AaveCollateralizationError.tsx deleted file mode 100644 index eb486b8c..00000000 --- a/shared/react-components/components/Modals/AaveCollateralizationError.tsx +++ /dev/null @@ -1,84 +0,0 @@ -import { getNetworkNameByChainId, Vault } from '@generationsoftware/hyperstructure-client-js' -import { RichIntl } from '@shared/types' -import { ExternalLink, LINKS } from '@shared/ui' -import classNames from 'classnames' -import { ReactNode } from 'react' -import { AlertIcon } from '../Icons/AlertIcon' - -interface AaveCollateralizationErrorProps { - vault: Vault - intl?: { - warning?: string - error?: RichIntl< - | 'aaveCollateralizationError.issue' - | 'aaveCollateralizationError.recommendation' - | 'aaveCollateralizationError.moreInfo' - > - } - className?: string -} - -export const AaveCollateralizationError = (props: AaveCollateralizationErrorProps) => { - const { vault, intl, className } = props - - const govPostLink = 'https://gov.pooltogether.com/t/v5-vault-collateralization-issue/3170' - - const getLearnMoreLink = (chunks: ReactNode) => ( - - {chunks} - - ) - - const networkName = getNetworkNameByChainId(vault.chainId) - const uniswapHref = `https://app.uniswap.org/tokens/${networkName}/${vault.address}` - - const getUniswapLink = (chunks: ReactNode) => ( - - {chunks} - - ) - - const getDiscordLink = (chunks: ReactNode) => ( - - {chunks} - - ) - - return ( -
- - - {intl?.warning ?? 'Warning'} - - - {intl?.error?.rich('aaveCollateralizationError.issue', { link: getLearnMoreLink }) ?? ( - <> - This vault is experiencing issues due to using a high percentage of Aave's supply.{' '} - {getLearnMoreLink('Learn more')} - - )} - - - {intl?.error?.('aaveCollateralizationError.recommendation') ?? - 'It is not recommended to withdraw at this time'} - - - {intl?.error?.rich('aaveCollateralizationError.moreInfo', { - uniLink: getUniswapLink, - discordLink: getDiscordLink - }) ?? ( - <> - You may be able to swap out via {getUniswapLink('Uniswap')}, or wait for the vault to - normalize. For further updates, visit PoolTogether's {getDiscordLink(`Discord`)} - - )} - -
- ) -} diff --git a/shared/react-components/components/Modals/CheckPrizesModal/Views/WinView.tsx b/shared/react-components/components/Modals/CheckPrizesModal/Views/WinView.tsx index a7961002..7ee6c12c 100644 --- a/shared/react-components/components/Modals/CheckPrizesModal/Views/WinView.tsx +++ b/shared/react-components/components/Modals/CheckPrizesModal/Views/WinView.tsx @@ -7,12 +7,7 @@ import { useSelectedCurrency } from '@shared/generic-react-hooks' import { DrawWithTimestamps, SubgraphPrize, TokenWithAmount, Win } from '@shared/types' import { Intl } from '@shared/types' import { Button } from '@shared/ui' -import { - getSimpleDate, - NETWORK, - POOL_TOKEN_ADDRESSES, - WRAPPED_NATIVE_ASSETS -} from '@shared/utilities' +import { getSimpleDate, NETWORK, WRAPPED_NATIVE_ASSETS } from '@shared/utilities' import classNames from 'classnames' import Lottie from 'lottie-react' import { useMemo, useState } from 'react' @@ -129,10 +124,6 @@ const Header = (props: HeaderProps) => { const { selectedCurrency } = useSelectedCurrency() const isTokenEquivalentHidden = useMemo(() => { - const poolTokenAddress = POOL_TOKEN_ADDRESSES[ - token.chainId as keyof typeof POOL_TOKEN_ADDRESSES - ]?.toLowerCase() as Lowercase
| undefined - const wethTokenAddress = token.chainId === NETWORK.mainnet || token.chainId === NETWORK.optimism || @@ -141,10 +132,7 @@ const Header = (props: HeaderProps) => { ? (WRAPPED_NATIVE_ASSETS[token.chainId]?.toLowerCase() as Lowercase
) : undefined - return ( - (selectedCurrency === 'pool' && token.address.toLowerCase() === poolTokenAddress) || - (selectedCurrency === 'eth' && token.address.toLowerCase() === wethTokenAddress) - ) + return selectedCurrency === 'eth' && token.address.toLowerCase() === wethTokenAddress }, [token, selectedCurrency]) return ( diff --git a/shared/react-components/components/Modals/WithdrawModal/Views/MainView.tsx b/shared/react-components/components/Modals/WithdrawModal/Views/MainView.tsx index 3483f121..59c5124b 100644 --- a/shared/react-components/components/Modals/WithdrawModal/Views/MainView.tsx +++ b/shared/react-components/components/Modals/WithdrawModal/Views/MainView.tsx @@ -6,10 +6,8 @@ import { import { Intl, RichIntl } from '@shared/types' import { Spinner } from '@shared/ui' import { getNiceNetworkNameByChainId } from '@shared/utilities' -import { formatUnits } from 'viem' import { PrizePoolBadge } from '../../../Badges/PrizePoolBadge' import { WithdrawForm } from '../../../Form/WithdrawForm' -import { AaveCollateralizationError } from '../../AaveCollateralizationError' import { ExchangeRateError } from '../../ExchangeRateError' import { NetworkFees, NetworkFeesProps } from '../../NetworkFees' @@ -21,9 +19,6 @@ interface MainViewProps { fees?: NetworkFeesProps['intl'] errors?: RichIntl< | 'exchangeRateError' - | 'aaveCollateralizationError.issue' - | 'aaveCollateralizationError.recommendation' - | 'aaveCollateralizationError.moreInfo' | 'formErrors.notEnoughTokens' | 'formErrors.invalidNumber' | 'formErrors.negativeNumber' @@ -42,12 +37,6 @@ export const MainView = (props: MainViewProps) => { const vaultName = vault.name ?? `"${shareData?.name}"` const networkName = getNiceNetworkNameByChainId(vault.chainId) - const isAaveCollateralizationErrored = - vault.tags?.includes('aave') && - !!vaultExchangeRate && - vault.decimals !== undefined && - parseFloat(formatUnits(vaultExchangeRate, vault.decimals)) !== 1 - return (
@@ -73,14 +62,7 @@ export const MainView = (props: MainViewProps) => { {!!vaultExchangeRate ? ( <> - {isAaveCollateralizationErrored ? ( - - ) : ( - - )} + ) : ( diff --git a/shared/react-components/components/Modals/WithdrawModal/WithdrawTxButton.tsx b/shared/react-components/components/Modals/WithdrawModal/WithdrawTxButton.tsx index b09ccb94..81048658 100644 --- a/shared/react-components/components/Modals/WithdrawModal/WithdrawTxButton.tsx +++ b/shared/react-components/components/Modals/WithdrawModal/WithdrawTxButton.tsx @@ -13,7 +13,7 @@ import { Intl } from '@shared/types' import { Button } from '@shared/ui' import { useAtomValue } from 'jotai' import { useEffect } from 'react' -import { Address, formatUnits, parseUnits } from 'viem' +import { Address, parseUnits } from 'viem' import { useAccount } from 'wagmi' import { WithdrawModalView } from '.' import { isValidFormInput } from '../../Form/TxFormInput' @@ -130,12 +130,6 @@ export const WithdrawTxButton = (props: WithdrawTxButtonProps) => { } }, [withdrawTxHash, isConfirmingWithdrawal]) - const isAaveCollateralizationErrored = - vault.tags?.includes('aave') && - !!vaultExchangeRate && - vault.decimals !== undefined && - parseFloat(formatUnits(vaultExchangeRate, vault.decimals)) !== 1 - const withdrawEnabled = !isDisconnected && !!userAddress && @@ -145,8 +139,7 @@ export const WithdrawTxButton = (props: WithdrawTxButtonProps) => { isValidFormShareAmount && !!withdrawAmount && userVaultShareBalance.amount >= withdrawAmount && - !!sendRedeemTransaction && - !isAaveCollateralizationErrored + !!sendRedeemTransaction if (withdrawAmount === 0n) { return ( diff --git a/shared/react-components/components/Modals/WithdrawModal/index.tsx b/shared/react-components/components/Modals/WithdrawModal/index.tsx index ffaa0567..1f93c4a3 100644 --- a/shared/react-components/components/Modals/WithdrawModal/index.tsx +++ b/shared/react-components/components/Modals/WithdrawModal/index.tsx @@ -57,9 +57,6 @@ export interface WithdrawModalProps { txToast?: WithdrawTxToastProps['intl'] errors?: RichIntl< | 'exchangeRateError' - | 'aaveCollateralizationError.issue' - | 'aaveCollateralizationError.recommendation' - | 'aaveCollateralizationError.moreInfo' | 'formErrors.notEnoughTokens' | 'formErrors.invalidNumber' | 'formErrors.negativeNumber' diff --git a/shared/react-components/components/PrizePool/PrizePoolCard.tsx b/shared/react-components/components/PrizePool/PrizePoolCard.tsx index f836ea17..29420d44 100644 --- a/shared/react-components/components/PrizePool/PrizePoolCard.tsx +++ b/shared/react-components/components/PrizePool/PrizePoolCard.tsx @@ -3,7 +3,7 @@ import { useGrandPrize } from '@generationsoftware/hyperstructure-react-hooks' import { useSelectedCurrency } from '@shared/generic-react-hooks' import { Intl } from '@shared/types' import { Card, Spinner } from '@shared/ui' -import { NETWORK, POOL_TOKEN_ADDRESSES, WRAPPED_NATIVE_ASSETS } from '@shared/utilities' +import { NETWORK, WRAPPED_NATIVE_ASSETS } from '@shared/utilities' import { useMemo } from 'react' import { Address } from 'viem' import { PrizePoolBadge } from '../Badges/PrizePoolBadge' @@ -25,10 +25,6 @@ export const PrizePoolCard = (props: PrizePoolCardProps) => { const { selectedCurrency } = useSelectedCurrency() const isTokenEquivalentHidden = useMemo(() => { - const poolTokenAddress = POOL_TOKEN_ADDRESSES[ - prizePool.chainId as keyof typeof POOL_TOKEN_ADDRESSES - ]?.toLowerCase() as Lowercase
| undefined - const wethTokenAddress = prizePool.chainId === NETWORK.mainnet || prizePool.chainId === NETWORK.optimism || @@ -37,10 +33,7 @@ export const PrizePoolCard = (props: PrizePoolCardProps) => { ? (WRAPPED_NATIVE_ASSETS[prizePool.chainId]?.toLowerCase() as Lowercase
) : undefined - return ( - (selectedCurrency === 'pool' && grandPrize?.address.toLowerCase() === poolTokenAddress) || - (selectedCurrency === 'eth' && grandPrize?.address.toLowerCase() === wethTokenAddress) - ) + return selectedCurrency === 'eth' && grandPrize?.address.toLowerCase() === wethTokenAddress }, [prizePool, selectedCurrency]) return ( From 47111e6c140fa40092f77e8fd3a24175cc473443 Mon Sep 17 00:00:00 2001 From: Ncookiez Date: Wed, 28 Feb 2024 15:57:26 -0500 Subject: [PATCH 005/161] updated client pkg --- packages/hyperstructure-client-js/package.json | 2 +- packages/hyperstructure-client-js/src/Vault.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/hyperstructure-client-js/package.json b/packages/hyperstructure-client-js/package.json index 38d87bf7..a6343d96 100644 --- a/packages/hyperstructure-client-js/package.json +++ b/packages/hyperstructure-client-js/package.json @@ -1,6 +1,6 @@ { "name": "@generationsoftware/hyperstructure-client-js", - "version": "1.9.0", + "version": "1.10.0", "license": "MIT", "main": "./dist/index.mjs", "types": "./dist/index.d.ts", diff --git a/packages/hyperstructure-client-js/src/Vault.ts b/packages/hyperstructure-client-js/src/Vault.ts index 6bb794d4..c8645377 100644 --- a/packages/hyperstructure-client-js/src/Vault.ts +++ b/packages/hyperstructure-client-js/src/Vault.ts @@ -442,7 +442,7 @@ export class Vault { const feesAvailable = await this.publicClient.readContract({ address: this.address, abi: vaultABI, - functionName: 'availableYieldFeeBalance' + functionName: 'yieldFeeBalance' }) this.feesAvailable = feesAvailable @@ -724,7 +724,7 @@ export class Vault { account: this.walletClient.account, address: this.address, abi: vaultABI, - functionName: 'mintYieldFee', + functionName: 'claimYieldFeeShares', args: [amount], chain: this.walletClient.chain, ...overrides From af6f9f4521c58657932460d470c79f15abee6a7b Mon Sep 17 00:00:00 2001 From: Ncookiez Date: Wed, 28 Feb 2024 15:57:43 -0500 Subject: [PATCH 006/161] added canary deployment pkg versions to readme --- README.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 58294c3e..eb4b667f 100644 --- a/README.md +++ b/README.md @@ -52,10 +52,13 @@ All apps above are [Next.js](https://nextjs.org/) apps with [Tailwind CSS](https Prize pool and auxiliary contract addresses are included in the `hyperstructure-client-js` package. If you'd like to use older protocol deployments, refer to the versions below: -- Current Optimism Deployment: +- Current: - `hyperstructure-client-js@latest` - `hyperstructure-react-hooks@latest` -- Beta Optimism Deployment: +- Canary (Optimism): + - `hyperstructure-client-js@1.9.0` + - `hyperstructure-react-hooks@1.14.5` +- Beta (Optimism): - `hyperstructure-client-js@1.2.8` - `hyperstructure-react-hooks@1.4.10` From aeb00b80601673e4ece682b58231251c1c3ecc20 Mon Sep 17 00:00:00 2001 From: Ncookiez Date: Wed, 28 Feb 2024 16:07:44 -0500 Subject: [PATCH 007/161] updated hooks pkg --- packages/hyperstructure-react-hooks/README.md | 5 --- .../hyperstructure-react-hooks/package.json | 2 +- .../src/blockchain/useClients.ts | 2 + .../src/constants.ts | 5 --- .../src/events/usePrizeBackstopEvents.ts | 37 ------------------ .../src/events/useRelayAuctionEvents.ts | 36 ----------------- .../src/events/useRngAuctionEvents.ts | 36 ----------------- .../src/events/useRngL1RelayMsgEvents.ts | 39 ------------------- .../src/events/useRngL2RelayMsgEvents.ts | 36 ----------------- .../hyperstructure-react-hooks/src/index.ts | 5 --- .../useSendClaimVaultFeesTransaction.ts | 2 +- .../useSendDeployVaultTransaction.ts | 6 +-- 12 files changed, 7 insertions(+), 204 deletions(-) delete mode 100644 packages/hyperstructure-react-hooks/src/events/usePrizeBackstopEvents.ts delete mode 100644 packages/hyperstructure-react-hooks/src/events/useRelayAuctionEvents.ts delete mode 100644 packages/hyperstructure-react-hooks/src/events/useRngAuctionEvents.ts delete mode 100644 packages/hyperstructure-react-hooks/src/events/useRngL1RelayMsgEvents.ts delete mode 100644 packages/hyperstructure-react-hooks/src/events/useRngL2RelayMsgEvents.ts diff --git a/packages/hyperstructure-react-hooks/README.md b/packages/hyperstructure-react-hooks/README.md index c4e0ba2a..59c36841 100644 --- a/packages/hyperstructure-react-hooks/README.md +++ b/packages/hyperstructure-react-hooks/README.md @@ -74,13 +74,8 @@ yarn add @generationsoftware/hyperstructure-react-hooks - `useDrawAwardedEvents` - `useLiquidationEvents` - `useManualContributionEvents` -- `usePrizeBackstopEvents` - `usePromotionCreatedEvents` - `usePromotionRewardsClaimedEvents` -- `useRelayAuctionEvents` -- `useRngAuctionEvents` -- `useRngL1RelayMsgEvents` -- `useRngL2RelayMsgEvents` - `useTransferEvents` ### Prize Pool Hooks diff --git a/packages/hyperstructure-react-hooks/package.json b/packages/hyperstructure-react-hooks/package.json index fc0d134a..a4bdd457 100644 --- a/packages/hyperstructure-react-hooks/package.json +++ b/packages/hyperstructure-react-hooks/package.json @@ -1,6 +1,6 @@ { "name": "@generationsoftware/hyperstructure-react-hooks", - "version": "1.14.5", + "version": "1.15.0", "license": "MIT", "main": "./dist/index.mjs", "types": "./dist/index.d.ts", diff --git a/packages/hyperstructure-react-hooks/src/blockchain/useClients.ts b/packages/hyperstructure-react-hooks/src/blockchain/useClients.ts index 30e77ee3..0d775556 100644 --- a/packages/hyperstructure-react-hooks/src/blockchain/useClients.ts +++ b/packages/hyperstructure-react-hooks/src/blockchain/useClients.ts @@ -25,6 +25,7 @@ export const usePublicClients = (options?: { useAll?: boolean }): PublicClient[] ], testnets: [ usePublicClient({ chainId: NETWORK.optimism_sepolia }), + usePublicClient({ chainId: NETWORK.optimism_goerli }), usePublicClient({ chainId: NETWORK.arbitrum_sepolia }) ] } @@ -68,6 +69,7 @@ export const usePublicClientsByChain = (options?: { }, testnets: { [NETWORK.optimism_sepolia]: usePublicClient({ chainId: NETWORK.optimism_sepolia }), + [NETWORK.optimism_goerli]: usePublicClient({ chainId: NETWORK.optimism_goerli }), [NETWORK.arbitrum_sepolia]: usePublicClient({ chainId: NETWORK.arbitrum_sepolia }) } } diff --git a/packages/hyperstructure-react-hooks/src/constants.ts b/packages/hyperstructure-react-hooks/src/constants.ts index 3306d119..5d8ea2b4 100644 --- a/packages/hyperstructure-react-hooks/src/constants.ts +++ b/packages/hyperstructure-react-hooks/src/constants.ts @@ -21,17 +21,12 @@ export const QUERY_KEYS = { lastAwardedDrawTimestamps: 'lastAwardedDrawTimestamps', liquidationEvents: 'liquidationEvents', manualContributionEvents: 'manualContributionEvents', - prizeBackstopEvents: 'prizeBackstopEvents', prizeInfo: 'prizeInfo', prizeOdds: 'prizeOdds', prizeTokenData: 'prizeTokenData', promotionCreatedEvents: 'promotionCreatedEvents', promotionRewardsClaimedEvents: 'promotionRewardsClaimedEvents', promotionInfo: 'promotionInfo', - relayAuctionEvents: 'relayAuctionEvents', - rngAuctionEvents: 'rngAuctionEvents', - rngL1RelayMsgEvents: 'rngL1RelayMsgEvents', - rngL2RelayMsgEvents: 'rngL2RelayMsgEvents', selectedVaults: 'selectedVaults', tokenAllowances: 'tokenAllowances', tokenBalances: 'tokenBalances', diff --git a/packages/hyperstructure-react-hooks/src/events/usePrizeBackstopEvents.ts b/packages/hyperstructure-react-hooks/src/events/usePrizeBackstopEvents.ts deleted file mode 100644 index 10b93087..00000000 --- a/packages/hyperstructure-react-hooks/src/events/usePrizeBackstopEvents.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { PrizePool } from '@generationsoftware/hyperstructure-client-js' -import { NO_REFETCH } from '@shared/generic-react-hooks' -import { getPrizeBackstopEvents } from '@shared/utilities' -import { useQuery } from '@tanstack/react-query' -import { usePublicClient } from 'wagmi' -import { QUERY_KEYS } from '../constants' - -/** - * Returns `ReserveConsumed` events - * @param prizePool the prize pool to query events for - * @param options optional settings - * @returns - */ -export const usePrizeBackstopEvents = ( - prizePool: PrizePool, - options?: { fromBlock?: bigint; toBlock?: bigint } -) => { - const publicClient = usePublicClient({ chainId: prizePool?.chainId }) - - const queryKey = [ - QUERY_KEYS.prizeBackstopEvents, - prizePool?.id, - options?.fromBlock?.toString(), - options?.toBlock?.toString() ?? 'latest' - ] - - return useQuery({ - queryKey, - queryFn: async () => { - if (!!publicClient) { - return await getPrizeBackstopEvents(publicClient, prizePool.address, options) - } - }, - enabled: !!prizePool && !!publicClient, - ...NO_REFETCH - }) -} diff --git a/packages/hyperstructure-react-hooks/src/events/useRelayAuctionEvents.ts b/packages/hyperstructure-react-hooks/src/events/useRelayAuctionEvents.ts deleted file mode 100644 index 0cdad8f4..00000000 --- a/packages/hyperstructure-react-hooks/src/events/useRelayAuctionEvents.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { NO_REFETCH } from '@shared/generic-react-hooks' -import { getRelayAuctionEvents } from '@shared/utilities' -import { useQuery } from '@tanstack/react-query' -import { usePublicClient } from 'wagmi' -import { QUERY_KEYS } from '../constants' - -/** - * Returns `AuctionRewardAllocated` events - * @param chainId the chain ID the relay auction occurs in (L2) - * @param options optional settings - * @returns - */ -export const useRelayAuctionEvents = ( - chainId: number, - options?: { fromBlock?: bigint; toBlock?: bigint } -) => { - const publicClient = usePublicClient({ chainId }) - - const queryKey = [ - QUERY_KEYS.relayAuctionEvents, - chainId, - options?.fromBlock?.toString(), - options?.toBlock?.toString() ?? 'latest' - ] - - return useQuery({ - queryKey, - queryFn: async () => { - if (!!publicClient) { - return await getRelayAuctionEvents(publicClient, options) - } - }, - enabled: !!chainId && !!publicClient, - ...NO_REFETCH - }) -} diff --git a/packages/hyperstructure-react-hooks/src/events/useRngAuctionEvents.ts b/packages/hyperstructure-react-hooks/src/events/useRngAuctionEvents.ts deleted file mode 100644 index 13cbbed2..00000000 --- a/packages/hyperstructure-react-hooks/src/events/useRngAuctionEvents.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { NO_REFETCH } from '@shared/generic-react-hooks' -import { getRngAuctionEvents } from '@shared/utilities' -import { useQuery } from '@tanstack/react-query' -import { usePublicClient } from 'wagmi' -import { QUERY_KEYS } from '../constants' - -/** - * Returns `RngAuctionCompleted` events - * @param chainId the chain ID the RNG auction occurs in - * @param options optional settings - * @returns - */ -export const useRngAuctionEvents = ( - chainId: number, - options?: { fromBlock?: bigint; toBlock?: bigint } -) => { - const publicClient = usePublicClient({ chainId }) - - const queryKey = [ - QUERY_KEYS.rngAuctionEvents, - chainId, - options?.fromBlock?.toString(), - options?.toBlock?.toString() ?? 'latest' - ] - - return useQuery({ - queryKey, - queryFn: async () => { - if (!!publicClient) { - return await getRngAuctionEvents(publicClient, options) - } - }, - enabled: !!chainId && !!publicClient, - ...NO_REFETCH - }) -} diff --git a/packages/hyperstructure-react-hooks/src/events/useRngL1RelayMsgEvents.ts b/packages/hyperstructure-react-hooks/src/events/useRngL1RelayMsgEvents.ts deleted file mode 100644 index ec41adfa..00000000 --- a/packages/hyperstructure-react-hooks/src/events/useRngL1RelayMsgEvents.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { NO_REFETCH } from '@shared/generic-react-hooks' -import { getRngL1RelayMsgEvents } from '@shared/utilities' -import { useQuery } from '@tanstack/react-query' -import { usePublicClient } from 'wagmi' -import { QUERY_KEYS } from '../constants' - -/** - * Returns `RelayedToDispatcher` events - * @param chainId the chain ID the rng relay message is dispatched from (L1) - * @param destinationChainId the chain ID that the messages are to be relayed to (L2) - * @param options optional settings - * @returns - */ -export const useRngL1RelayMsgEvents = ( - chainId: number, - destinationChainId: number, - options?: { fromBlock?: bigint; toBlock?: bigint } -) => { - const publicClient = usePublicClient({ chainId }) - - const queryKey = [ - QUERY_KEYS.rngL1RelayMsgEvents, - chainId, - destinationChainId, - options?.fromBlock?.toString(), - options?.toBlock?.toString() ?? 'latest' - ] - - return useQuery({ - queryKey, - queryFn: async () => { - if (!!publicClient) { - return await getRngL1RelayMsgEvents(publicClient, destinationChainId, options) - } - }, - enabled: !!chainId && !!destinationChainId && !!publicClient, - ...NO_REFETCH - }) -} diff --git a/packages/hyperstructure-react-hooks/src/events/useRngL2RelayMsgEvents.ts b/packages/hyperstructure-react-hooks/src/events/useRngL2RelayMsgEvents.ts deleted file mode 100644 index 741a8974..00000000 --- a/packages/hyperstructure-react-hooks/src/events/useRngL2RelayMsgEvents.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { NO_REFETCH } from '@shared/generic-react-hooks' -import { getRngL2RelayMsgEvents } from '@shared/utilities' -import { useQuery } from '@tanstack/react-query' -import { usePublicClient } from 'wagmi' -import { QUERY_KEYS } from '../constants' - -/** - * Returns `MessageIdExecuted` events - * @param chainId the chain ID the rng relay message is received in (L2) - * @param options optional settings - * @returns - */ -export const useRngL2RelayMsgEvents = ( - chainId: number, - options?: { fromBlock?: bigint; toBlock?: bigint } -) => { - const publicClient = usePublicClient({ chainId }) - - const queryKey = [ - QUERY_KEYS.rngL2RelayMsgEvents, - chainId, - options?.fromBlock?.toString(), - options?.toBlock?.toString() ?? 'latest' - ] - - return useQuery({ - queryKey, - queryFn: async () => { - if (!!publicClient) { - return await getRngL2RelayMsgEvents(publicClient, options) - } - }, - enabled: !!chainId && !!publicClient, - ...NO_REFETCH - }) -} diff --git a/packages/hyperstructure-react-hooks/src/index.ts b/packages/hyperstructure-react-hooks/src/index.ts index 883e4ed8..25141be8 100644 --- a/packages/hyperstructure-react-hooks/src/index.ts +++ b/packages/hyperstructure-react-hooks/src/index.ts @@ -30,13 +30,8 @@ export * from './blockchain/useTxReceipts' export * from './events/useDrawAwardedEvents' export * from './events/useLiquidationEvents' export * from './events/useManualContributionEvents' -export * from './events/usePrizeBackstopEvents' export * from './events/usePromotionCreatedEvents' export * from './events/usePromotionRewardsClaimedEvents' -export * from './events/useRelayAuctionEvents' -export * from './events/useRngAuctionEvents' -export * from './events/useRngL1RelayMsgEvents' -export * from './events/useRngL2RelayMsgEvents' export * from './events/useTransferEvents' /** diff --git a/packages/hyperstructure-react-hooks/src/transactions/useSendClaimVaultFeesTransaction.ts b/packages/hyperstructure-react-hooks/src/transactions/useSendClaimVaultFeesTransaction.ts index 5692ade0..f2dd8c1e 100644 --- a/packages/hyperstructure-react-hooks/src/transactions/useSendClaimVaultFeesTransaction.ts +++ b/packages/hyperstructure-react-hooks/src/transactions/useSendClaimVaultFeesTransaction.ts @@ -42,7 +42,7 @@ export const useSendClaimVaultFeesTransaction = ( chainId: vault?.chainId, address: vault?.address, abi: vaultABI, - functionName: 'mintYieldFee', + functionName: 'claimYieldFeeShares', args: [amount], query: { enabled } }) diff --git a/packages/hyperstructure-react-hooks/src/transactions/useSendDeployVaultTransaction.ts b/packages/hyperstructure-react-hooks/src/transactions/useSendDeployVaultTransaction.ts index 850a544f..cb864bd4 100644 --- a/packages/hyperstructure-react-hooks/src/transactions/useSendDeployVaultTransaction.ts +++ b/packages/hyperstructure-react-hooks/src/transactions/useSendDeployVaultTransaction.ts @@ -35,7 +35,6 @@ export const useSendDeployVaultTransaction = ( const { chainId, - token, name, symbol, yieldSourceAddress, @@ -43,6 +42,7 @@ export const useSendDeployVaultTransaction = ( claimer, feeRecipient, feePercentage, + yieldBuffer, owner } = vaultDeployInfo @@ -55,7 +55,6 @@ export const useSendDeployVaultTransaction = ( const enabled = !!vaultDeployInfo && !!chainId && - !!token && !!name && !!symbol && !!yieldSourceAddress && @@ -63,6 +62,7 @@ export const useSendDeployVaultTransaction = ( !!claimer && !!feeRecipient && feePercentage !== undefined && + yieldBuffer !== undefined && !!owner && !!vaultFactoryAddress && chain?.id === chainId @@ -73,7 +73,6 @@ export const useSendDeployVaultTransaction = ( abi: vaultFactoryABI, functionName: 'deployVault', args: [ - token, name, symbol, yieldSourceAddress, @@ -81,6 +80,7 @@ export const useSendDeployVaultTransaction = ( claimer, feeRecipient, feePercentage, + yieldBuffer, owner ], query: { enabled } From 6847695aee9dcf22c2c6f818ecccd6ccdcb9b879 Mon Sep 17 00:00:00 2001 From: Ncookiez Date: Wed, 28 Feb 2024 16:42:35 -0500 Subject: [PATCH 008/161] readded prizebackstop fxs + hook --- packages/hyperstructure-react-hooks/README.md | 1 + .../src/constants.ts | 1 + .../src/events/usePrizeBackstopEvents.ts | 37 +++++++++++++++++++ .../hyperstructure-react-hooks/src/index.ts | 1 + shared/utilities/utils/events.ts | 25 +++++++++++++ 5 files changed, 65 insertions(+) create mode 100644 packages/hyperstructure-react-hooks/src/events/usePrizeBackstopEvents.ts diff --git a/packages/hyperstructure-react-hooks/README.md b/packages/hyperstructure-react-hooks/README.md index 59c36841..c27ef511 100644 --- a/packages/hyperstructure-react-hooks/README.md +++ b/packages/hyperstructure-react-hooks/README.md @@ -74,6 +74,7 @@ yarn add @generationsoftware/hyperstructure-react-hooks - `useDrawAwardedEvents` - `useLiquidationEvents` - `useManualContributionEvents` +- `usePrizeBackstopEvents` - `usePromotionCreatedEvents` - `usePromotionRewardsClaimedEvents` - `useTransferEvents` diff --git a/packages/hyperstructure-react-hooks/src/constants.ts b/packages/hyperstructure-react-hooks/src/constants.ts index 5d8ea2b4..cc377012 100644 --- a/packages/hyperstructure-react-hooks/src/constants.ts +++ b/packages/hyperstructure-react-hooks/src/constants.ts @@ -21,6 +21,7 @@ export const QUERY_KEYS = { lastAwardedDrawTimestamps: 'lastAwardedDrawTimestamps', liquidationEvents: 'liquidationEvents', manualContributionEvents: 'manualContributionEvents', + prizeBackstopEvents: 'prizeBackstopEvents', prizeInfo: 'prizeInfo', prizeOdds: 'prizeOdds', prizeTokenData: 'prizeTokenData', diff --git a/packages/hyperstructure-react-hooks/src/events/usePrizeBackstopEvents.ts b/packages/hyperstructure-react-hooks/src/events/usePrizeBackstopEvents.ts new file mode 100644 index 00000000..10b93087 --- /dev/null +++ b/packages/hyperstructure-react-hooks/src/events/usePrizeBackstopEvents.ts @@ -0,0 +1,37 @@ +import { PrizePool } from '@generationsoftware/hyperstructure-client-js' +import { NO_REFETCH } from '@shared/generic-react-hooks' +import { getPrizeBackstopEvents } from '@shared/utilities' +import { useQuery } from '@tanstack/react-query' +import { usePublicClient } from 'wagmi' +import { QUERY_KEYS } from '../constants' + +/** + * Returns `ReserveConsumed` events + * @param prizePool the prize pool to query events for + * @param options optional settings + * @returns + */ +export const usePrizeBackstopEvents = ( + prizePool: PrizePool, + options?: { fromBlock?: bigint; toBlock?: bigint } +) => { + const publicClient = usePublicClient({ chainId: prizePool?.chainId }) + + const queryKey = [ + QUERY_KEYS.prizeBackstopEvents, + prizePool?.id, + options?.fromBlock?.toString(), + options?.toBlock?.toString() ?? 'latest' + ] + + return useQuery({ + queryKey, + queryFn: async () => { + if (!!publicClient) { + return await getPrizeBackstopEvents(publicClient, prizePool.address, options) + } + }, + enabled: !!prizePool && !!publicClient, + ...NO_REFETCH + }) +} diff --git a/packages/hyperstructure-react-hooks/src/index.ts b/packages/hyperstructure-react-hooks/src/index.ts index 25141be8..1b7466ef 100644 --- a/packages/hyperstructure-react-hooks/src/index.ts +++ b/packages/hyperstructure-react-hooks/src/index.ts @@ -30,6 +30,7 @@ export * from './blockchain/useTxReceipts' export * from './events/useDrawAwardedEvents' export * from './events/useLiquidationEvents' export * from './events/useManualContributionEvents' +export * from './events/usePrizeBackstopEvents' export * from './events/usePromotionCreatedEvents' export * from './events/usePromotionRewardsClaimedEvents' export * from './events/useTransferEvents' diff --git a/shared/utilities/utils/events.ts b/shared/utilities/utils/events.ts index 098c8967..2330b62e 100644 --- a/shared/utilities/utils/events.ts +++ b/shared/utilities/utils/events.ts @@ -219,6 +219,31 @@ export const getManualContributionEvents = async ( }) } +/** + * Returns `ReserveConsumed` events + * @param publicClient a public Viem client to query through + * @param prizePoolAddress the address of the prize pool to query events for + * @param options optional settings + * @returns + */ +export const getPrizeBackstopEvents = async ( + publicClient: PublicClient, + prizePoolAddress: Address, + options?: { fromBlock?: bigint; toBlock?: bigint } +) => { + return await publicClient.getLogs({ + address: prizePoolAddress, + event: { + inputs: [{ indexed: false, internalType: 'uint256', name: 'amount', type: 'uint256' }], + name: 'ReserveConsumed', + type: 'event' + }, + fromBlock: options?.fromBlock, + toBlock: options?.toBlock ?? 'latest', + strict: true + }) +} + /** * Returns `Transfer` events for a given token * @param publicClient a public Viem client to query through From 327e87bd100a0bb1b4dad7caf68b428fac9b7b3b Mon Sep 17 00:00:00 2001 From: Ncookiez Date: Wed, 28 Feb 2024 17:25:19 -0500 Subject: [PATCH 009/161] refactored draw event queries --- .../hyperstructure-client-js/src/PrizePool.ts | 46 ++++ .../hyperstructure-client-js/src/Vaults.ts | 13 +- packages/hyperstructure-react-hooks/README.md | 1 + .../src/constants.ts | 1 + .../src/events/useDrawAwardedEvents.ts | 3 +- .../events/useRngAuctionCompletedEvents.ts | 38 ++++ .../hyperstructure-react-hooks/src/index.ts | 1 + shared/utilities/abis/drawManager.ts | 212 ++++++++++++++++++ shared/utilities/constants.ts | 11 +- shared/utilities/index.ts | 1 + shared/utilities/utils/events.ts | 48 +++- 11 files changed, 353 insertions(+), 22 deletions(-) create mode 100644 packages/hyperstructure-react-hooks/src/events/useRngAuctionCompletedEvents.ts create mode 100644 shared/utilities/abis/drawManager.ts diff --git a/packages/hyperstructure-client-js/src/PrizePool.ts b/packages/hyperstructure-client-js/src/PrizePool.ts index f83d5ada..69debca5 100644 --- a/packages/hyperstructure-client-js/src/PrizePool.ts +++ b/packages/hyperstructure-client-js/src/PrizePool.ts @@ -19,6 +19,8 @@ export class PrizePool { readonly id: string walletClient: WalletClient | undefined prizeTokenAddress: Address | undefined + drawManagerAddress: Address | undefined + twabControllerAddress: Address | undefined drawPeriodInSeconds: number | undefined tierShares: number | undefined reserveShares: number | undefined @@ -39,6 +41,8 @@ export class PrizePool { options?: { walletClient?: WalletClient prizeTokenAddress?: Address + drawManagerAddress?: Address + twabControllerAddress?: Address drawPeriodInSeconds?: number tierShares?: number reserveShares?: number @@ -48,6 +52,8 @@ export class PrizePool { this.walletClient = options?.walletClient this.prizeTokenAddress = options?.prizeTokenAddress + this.drawManagerAddress = options?.drawManagerAddress + this.twabControllerAddress = options?.twabControllerAddress this.drawPeriodInSeconds = options?.drawPeriodInSeconds this.tierShares = options?.tierShares this.reserveShares = options?.reserveShares @@ -75,6 +81,46 @@ export class PrizePool { return this.prizeTokenAddress } + /** + * Returns the address of prize pool's draw manager + * @returns + */ + async getDrawManagerAddress(): Promise
{ + if (this.drawManagerAddress !== undefined) return this.drawManagerAddress + + const source = 'Prize Pool [getDrawManagerAddress]' + await validateClientNetwork(this.chainId, this.publicClient, source) + + const drawManagerAddress = await this.publicClient.readContract({ + address: this.address, + abi: prizePoolABI, + functionName: 'drawManager' + }) + + this.drawManagerAddress = drawManagerAddress + return this.drawManagerAddress + } + + /** + * Returns the address of the prize pool's TWAB controller + * @returns + */ + async getTwabControllerAddress(): Promise
{ + if (this.twabControllerAddress !== undefined) return this.twabControllerAddress + + const source = 'Prize Pool [getTwabControllerAddress]' + await validateClientNetwork(this.chainId, this.publicClient, source) + + const twabControllerAddress = await this.publicClient.readContract({ + address: this.address, + abi: prizePoolABI, + functionName: 'twabController' + }) + + this.twabControllerAddress = twabControllerAddress + return this.twabControllerAddress + } + /** * Returns basic data about the token awarded by the prize pool * @returns diff --git a/packages/hyperstructure-client-js/src/Vaults.ts b/packages/hyperstructure-client-js/src/Vaults.ts index 5c9f4c7c..06d61a2c 100644 --- a/packages/hyperstructure-client-js/src/Vaults.ts +++ b/packages/hyperstructure-client-js/src/Vaults.ts @@ -10,7 +10,6 @@ import { getVaultId, getVaultsByChainId, getVaultUnderlyingTokenAddresses, - TWAB_CONTROLLER_ADDRESSES, validateAddress, validateClientNetwork } from '@shared/utilities' @@ -291,11 +290,13 @@ export class Vaults { networksToQuery.map((chainId) => (async () => { const vaultAddresses = this.vaultAddresses[chainId] - const twabControllerAddress = TWAB_CONTROLLER_ADDRESSES[chainId] - if (!!vaultAddresses && !!twabControllerAddress) { + if (!!vaultAddresses?.length) { const client = this.publicClients[chainId] if (!!client) { await validateClientNetwork(chainId, client, source + ` [${chainId}]`) + const twabControllerAddress = await this.vaults[ + getVaultId({ chainId, address: vaultAddresses[0] }) + ].getTWABController() const chainDelegateBalances = await getVaultDelegateBalances( client, userAddress as Address, @@ -333,11 +334,13 @@ export class Vaults { networksToQuery.map((chainId) => (async () => { const vaultAddresses = this.vaultAddresses[chainId] - const twabControllerAddress = TWAB_CONTROLLER_ADDRESSES[chainId] - if (!!vaultAddresses && !!twabControllerAddress) { + if (!!vaultAddresses?.length) { const client = this.publicClients[chainId] if (!!client) { await validateClientNetwork(chainId, client, source + ` [${chainId}]`) + const twabControllerAddress = await this.vaults[ + getVaultId({ chainId, address: vaultAddresses[0] }) + ].getTWABController() const chainDelegates = await getVaultDelegates( client, userAddress as Address, diff --git a/packages/hyperstructure-react-hooks/README.md b/packages/hyperstructure-react-hooks/README.md index c27ef511..a26e9311 100644 --- a/packages/hyperstructure-react-hooks/README.md +++ b/packages/hyperstructure-react-hooks/README.md @@ -77,6 +77,7 @@ yarn add @generationsoftware/hyperstructure-react-hooks - `usePrizeBackstopEvents` - `usePromotionCreatedEvents` - `usePromotionRewardsClaimedEvents` +- `useRngAuctionCompletedEvents` - `useTransferEvents` ### Prize Pool Hooks diff --git a/packages/hyperstructure-react-hooks/src/constants.ts b/packages/hyperstructure-react-hooks/src/constants.ts index cc377012..39a8b574 100644 --- a/packages/hyperstructure-react-hooks/src/constants.ts +++ b/packages/hyperstructure-react-hooks/src/constants.ts @@ -28,6 +28,7 @@ export const QUERY_KEYS = { promotionCreatedEvents: 'promotionCreatedEvents', promotionRewardsClaimedEvents: 'promotionRewardsClaimedEvents', promotionInfo: 'promotionInfo', + rngAuctionCompletedEvents: 'rngAuctionCompletedEvents', selectedVaults: 'selectedVaults', tokenAllowances: 'tokenAllowances', tokenBalances: 'tokenBalances', diff --git a/packages/hyperstructure-react-hooks/src/events/useDrawAwardedEvents.ts b/packages/hyperstructure-react-hooks/src/events/useDrawAwardedEvents.ts index 1fbcc8ef..138c6147 100644 --- a/packages/hyperstructure-react-hooks/src/events/useDrawAwardedEvents.ts +++ b/packages/hyperstructure-react-hooks/src/events/useDrawAwardedEvents.ts @@ -28,7 +28,8 @@ export const useDrawAwardedEvents = ( queryKey, queryFn: async () => { if (!!publicClient) { - return await getDrawAwardedEvents(publicClient, prizePool.address, options) + const drawManagerAddress = await prizePool.getDrawManagerAddress() + return await getDrawAwardedEvents(publicClient, drawManagerAddress, options) } }, enabled: !!prizePool && !!publicClient, diff --git a/packages/hyperstructure-react-hooks/src/events/useRngAuctionCompletedEvents.ts b/packages/hyperstructure-react-hooks/src/events/useRngAuctionCompletedEvents.ts new file mode 100644 index 00000000..c2dca698 --- /dev/null +++ b/packages/hyperstructure-react-hooks/src/events/useRngAuctionCompletedEvents.ts @@ -0,0 +1,38 @@ +import { PrizePool } from '@generationsoftware/hyperstructure-client-js' +import { NO_REFETCH } from '@shared/generic-react-hooks' +import { getRngAuctionCompletedEvents } from '@shared/utilities' +import { useQuery } from '@tanstack/react-query' +import { usePublicClient } from 'wagmi' +import { QUERY_KEYS } from '../constants' + +/** + * Returns `RngAuctionCompleted` events + * @param prizePool the prize pool to query events for + * @param options optional settings + * @returns + */ +export const useRngAuctionCompletedEvents = ( + prizePool: PrizePool, + options?: { fromBlock?: bigint; toBlock?: bigint } +) => { + const publicClient = usePublicClient({ chainId: prizePool?.chainId }) + + const queryKey = [ + QUERY_KEYS.rngAuctionCompletedEvents, + prizePool?.id, + options?.fromBlock?.toString(), + options?.toBlock?.toString() ?? 'latest' + ] + + return useQuery({ + queryKey, + queryFn: async () => { + if (!!publicClient) { + const drawManagerAddress = await prizePool.getDrawManagerAddress() + return await getRngAuctionCompletedEvents(publicClient, drawManagerAddress, options) + } + }, + enabled: !!prizePool && !!publicClient, + ...NO_REFETCH + }) +} diff --git a/packages/hyperstructure-react-hooks/src/index.ts b/packages/hyperstructure-react-hooks/src/index.ts index 1b7466ef..2bbd025a 100644 --- a/packages/hyperstructure-react-hooks/src/index.ts +++ b/packages/hyperstructure-react-hooks/src/index.ts @@ -33,6 +33,7 @@ export * from './events/useManualContributionEvents' export * from './events/usePrizeBackstopEvents' export * from './events/usePromotionCreatedEvents' export * from './events/usePromotionRewardsClaimedEvents' +export * from './events/useRngAuctionCompletedEvents' export * from './events/useTransferEvents' /** diff --git a/shared/utilities/abis/drawManager.ts b/shared/utilities/abis/drawManager.ts new file mode 100644 index 00000000..1e47d34c --- /dev/null +++ b/shared/utilities/abis/drawManager.ts @@ -0,0 +1,212 @@ +export const drawManagerABI = [ + { + inputs: [ + { internalType: 'uint256', name: '_timestamp', type: 'uint256' }, + { internalType: 'uint256', name: '_drawClosedAt', type: 'uint256' } + ], + name: '_elapsedTimeSinceDrawClosed', + outputs: [{ internalType: 'uint64', name: '', type: 'uint64' }], + stateMutability: 'view', + type: 'function' + }, + { + inputs: [], + name: 'auctionDuration', + outputs: [{ internalType: 'uint64', name: '', type: 'uint64' }], + stateMutability: 'view', + type: 'function' + }, + { + inputs: [], + name: 'auctionTargetTime', + outputs: [{ internalType: 'uint64', name: '', type: 'uint64' }], + stateMutability: 'view', + type: 'function' + }, + { + inputs: [{ internalType: 'address', name: '_rewardRecipient', type: 'address' }], + name: 'awardDraw', + outputs: [{ internalType: 'uint24', name: '', type: 'uint24' }], + stateMutability: 'nonpayable', + type: 'function' + }, + { + inputs: [], + name: 'awardDrawFee', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function' + }, + { + inputs: [], + name: 'canAwardDraw', + outputs: [{ internalType: 'bool', name: '', type: 'bool' }], + stateMutability: 'view', + type: 'function' + }, + { + inputs: [], + name: 'canStartDraw', + outputs: [{ internalType: 'bool', name: '', type: 'bool' }], + stateMutability: 'view', + type: 'function' + }, + { + inputs: [], + name: 'elapsedTimeSinceDrawClosed', + outputs: [{ internalType: 'uint64', name: '', type: 'uint64' }], + stateMutability: 'view', + type: 'function' + }, + { + inputs: [], + name: 'getLastAuction', + outputs: [ + { + components: [ + { internalType: 'address', name: 'recipient', type: 'address' }, + { internalType: 'uint40', name: 'startedAt', type: 'uint40' }, + { internalType: 'uint24', name: 'drawId', type: 'uint24' }, + { internalType: 'uint32', name: 'rngRequestId', type: 'uint32' } + ], + internalType: 'struct StartRngRequestAuction', + name: '', + type: 'tuple' + } + ], + stateMutability: 'view', + type: 'function' + }, + { + inputs: [], + name: 'lastAwardDrawFraction', + outputs: [{ internalType: 'UD2x18', name: '', type: 'uint64' }], + stateMutability: 'view', + type: 'function' + }, + { + inputs: [], + name: 'lastStartRngRequestFraction', + outputs: [{ internalType: 'UD2x18', name: '', type: 'uint64' }], + stateMutability: 'view', + type: 'function' + }, + { + inputs: [], + name: 'maxRewards', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function' + }, + { + inputs: [], + name: 'prizePool', + outputs: [{ internalType: 'contract PrizePool', name: '', type: 'address' }], + stateMutability: 'view', + type: 'function' + }, + { + inputs: [], + name: 'remainingRewardsRecipient', + outputs: [{ internalType: 'address', name: '', type: 'address' }], + stateMutability: 'view', + type: 'function' + }, + { + inputs: [], + name: 'rng', + outputs: [{ internalType: 'contract IRng', name: '', type: 'address' }], + stateMutability: 'view', + type: 'function' + }, + { + inputs: [ + { internalType: 'address', name: '_rewardRecipient', type: 'address' }, + { internalType: 'uint32', name: '_rngRequestId', type: 'uint32' } + ], + name: 'startDraw', + outputs: [], + stateMutability: 'nonpayable', + type: 'function' + }, + { + inputs: [], + name: 'startDrawFee', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function' + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: 'uint24', name: 'drawId', type: 'uint24' }, + { indexed: true, internalType: 'address', name: 'startRecipient', type: 'address' }, + { indexed: false, internalType: 'uint256', name: 'startReward', type: 'uint256' }, + { indexed: true, internalType: 'address', name: 'awardRecipient', type: 'address' }, + { indexed: false, internalType: 'uint256', name: 'awardReward', type: 'uint256' }, + { indexed: false, internalType: 'uint256', name: 'remainingReserve', type: 'uint256' } + ], + name: 'DrawAwarded', + type: 'event' + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: 'address', name: 'sender', type: 'address' }, + { indexed: true, internalType: 'address', name: 'recipient', type: 'address' }, + { indexed: false, internalType: 'uint24', name: 'drawId', type: 'uint24' }, + { indexed: false, internalType: 'uint32', name: 'rngRequestId', type: 'uint32' }, + { indexed: false, internalType: 'uint64', name: 'elapsedTime', type: 'uint64' } + ], + name: 'RngAuctionCompleted', + type: 'event' + }, + { + inputs: [{ internalType: 'uint64', name: 'auctionDuration', type: 'uint64' }], + name: 'AuctionDurationGTDrawPeriodSeconds', + type: 'error' + }, + { inputs: [], name: 'AuctionExpired', type: 'error' }, + { + inputs: [ + { internalType: 'uint64', name: 'auctionTargetTime', type: 'uint64' }, + { internalType: 'uint64', name: 'auctionDuration', type: 'uint64' } + ], + name: 'AuctionTargetTimeExceedsDuration', + type: 'error' + }, + { inputs: [], name: 'CannotStartRngRequest', type: 'error' }, + { inputs: [], name: 'DrawHasExpired', type: 'error' }, + { + inputs: [ + { internalType: 'uint256', name: 'x', type: 'uint256' }, + { internalType: 'uint256', name: 'y', type: 'uint256' } + ], + name: 'PRBMath_MulDiv18_Overflow', + type: 'error' + }, + { + inputs: [ + { internalType: 'uint256', name: 'x', type: 'uint256' }, + { internalType: 'uint256', name: 'y', type: 'uint256' }, + { internalType: 'uint256', name: 'denominator', type: 'uint256' } + ], + name: 'PRBMath_MulDiv_Overflow', + type: 'error' + }, + { + inputs: [{ internalType: 'uint256', name: 'x', type: 'uint256' }], + name: 'PRBMath_UD60x18_Convert_Overflow', + type: 'error' + }, + { + inputs: [{ internalType: 'UD60x18', name: 'x', type: 'uint256' }], + name: 'PRBMath_UD60x18_IntoUD2x18_Overflow', + type: 'error' + }, + { inputs: [], name: 'RewardRecipientIsZero', type: 'error' }, + { inputs: [], name: 'RewardRecipientIsZeroAddress', type: 'error' }, + { inputs: [], name: 'RngRequestNotComplete', type: 'error' }, + { inputs: [], name: 'RngRequestNotInSameBlock', type: 'error' }, + { inputs: [], name: 'TargetRewardFractionGTOne', type: 'error' } +] as const diff --git a/shared/utilities/constants.ts b/shared/utilities/constants.ts index eee42857..207ba44a 100644 --- a/shared/utilities/constants.ts +++ b/shared/utilities/constants.ts @@ -81,6 +81,8 @@ export const PRIZE_POOLS: { address: Address options: { prizeTokenAddress: Address + drawManagerAddress: Address + twabControllerAddress: Address drawPeriodInSeconds: number tierShares: number reserveShares: number @@ -91,6 +93,8 @@ export const PRIZE_POOLS: { address: '0x6cdd88A97801aD20F2dcfd14f1F9370e54757536', options: { prizeTokenAddress: '0x0Ba5e0722797dcEa8Cec409a707cE495C33fB23D', + drawManagerAddress: '0x512c1421D4f6f6c01A7508E060595ee08A652f69', + twabControllerAddress: '0x53f5545055f3804B7fD694081f9a13b3abceB38E', drawPeriodInSeconds: 7200, tierShares: 100, reserveShares: 20 @@ -238,13 +242,6 @@ export const WRAPPED_NATIVE_ASSETS: Record = { [NETWORK.base_sepolia]: null } -/** - * TWAB controller addresses - */ -export const TWAB_CONTROLLER_ADDRESSES: { [chainId: number]: Address } = { - [NETWORK.optimism_goerli]: '0x499a9F249ec4c8Ea190bebbFD96f9A83bf4F6E52' -} - /** * TWAB rewards addresses */ diff --git a/shared/utilities/index.ts b/shared/utilities/index.ts index 1d422a1c..0e63ab6a 100644 --- a/shared/utilities/index.ts +++ b/shared/utilities/index.ts @@ -1,6 +1,7 @@ /** * ABIs */ +export * from './abis/drawManager' export * from './abis/erc20-oldPermit' export * from './abis/erc20' export * from './abis/liquidationPair' diff --git a/shared/utilities/utils/events.ts b/shared/utilities/utils/events.ts index 2330b62e..37d6965a 100644 --- a/shared/utilities/utils/events.ts +++ b/shared/utilities/utils/events.ts @@ -63,29 +63,59 @@ export const getWithdrawEvents = async ( }) } +/** + * Returns `RngAuctionCompleted` events + * @param publicClient a public Viem client to query through + * @param drawManagerAddress the address of a prize pool's draw manager to query events for + * @param options optional settings + * @returns + */ +export const getRngAuctionCompletedEvents = async ( + publicClient: PublicClient, + drawManagerAddress: Address, + options?: { fromBlock?: bigint; toBlock?: bigint } +) => { + return await publicClient.getLogs({ + address: drawManagerAddress, + event: { + inputs: [ + { indexed: true, internalType: 'address', name: 'sender', type: 'address' }, + { indexed: true, internalType: 'address', name: 'recipient', type: 'address' }, + { indexed: false, internalType: 'uint24', name: 'drawId', type: 'uint24' }, + { indexed: false, internalType: 'uint32', name: 'rngRequestId', type: 'uint32' }, + { indexed: false, internalType: 'uint64', name: 'elapsedTime', type: 'uint64' } + ], + name: 'RngAuctionCompleted', + type: 'event' + }, + fromBlock: options?.fromBlock, + toBlock: options?.toBlock ?? 'latest', + strict: true + }) +} + /** * Returns `DrawAwarded` events * @param publicClient a public Viem client to query through - * @param prizePoolAddress the address of the prize pool to query events for + * @param drawManagerAddress the address of a prize pool's draw manager to query events for * @param options optional settings * @returns */ export const getDrawAwardedEvents = async ( publicClient: PublicClient, - prizePoolAddress: Address, + drawManagerAddress: Address, options?: { fromBlock?: bigint; toBlock?: bigint } ) => { return await publicClient.getLogs({ - address: prizePoolAddress, + address: drawManagerAddress, event: { inputs: [ { indexed: true, internalType: 'uint24', name: 'drawId', type: 'uint24' }, - { indexed: false, internalType: 'uint256', name: 'winningRandomNumber', type: 'uint256' }, - { indexed: false, internalType: 'uint8', name: 'lastNumTiers', type: 'uint8' }, - { indexed: false, internalType: 'uint8', name: 'numTiers', type: 'uint8' }, - { indexed: false, internalType: 'uint104', name: 'reserve', type: 'uint104' }, - { indexed: false, internalType: 'UD34x4', name: 'prizeTokensPerShare', type: 'uint128' }, - { indexed: false, internalType: 'uint48', name: 'drawOpenedAt', type: 'uint48' } + { indexed: true, internalType: 'address', name: 'startRecipient', type: 'address' }, + { indexed: false, internalType: 'uint256', name: 'startReward', type: 'uint256' }, + { indexed: true, internalType: 'address', name: 'awardRecipient', type: 'address' }, + { indexed: false, internalType: 'uint256', name: 'awardReward', type: 'uint256' }, + { indexed: false, internalType: 'uint256', name: 'remainingReserve', type: 'uint256' } ], name: 'DrawAwarded', type: 'event' From 4a0f8a3f0460aef57667fa6206e3f5c70e505ca7 Mon Sep 17 00:00:00 2001 From: Ncookiez Date: Wed, 28 Feb 2024 18:54:36 -0500 Subject: [PATCH 010/161] querying both `DrawAwarded` events --- packages/hyperstructure-react-hooks/README.md | 3 +- .../src/constants.ts | 3 +- ....ts => useDrawManagerDrawAwardedEvents.ts} | 14 ++++--- .../events/usePrizePoolDrawAwardedEvents.ts | 39 +++++++++++++++++++ .../hyperstructure-react-hooks/src/index.ts | 3 +- shared/utilities/utils/events.ts | 37 +++++++++++++++++- 6 files changed, 88 insertions(+), 11 deletions(-) rename packages/hyperstructure-react-hooks/src/events/{useDrawAwardedEvents.ts => useDrawManagerDrawAwardedEvents.ts} (69%) create mode 100644 packages/hyperstructure-react-hooks/src/events/usePrizePoolDrawAwardedEvents.ts diff --git a/packages/hyperstructure-react-hooks/README.md b/packages/hyperstructure-react-hooks/README.md index a26e9311..d64973a2 100644 --- a/packages/hyperstructure-react-hooks/README.md +++ b/packages/hyperstructure-react-hooks/README.md @@ -71,10 +71,11 @@ yarn add @generationsoftware/hyperstructure-react-hooks ### Event Hooks -- `useDrawAwardedEvents` +- `useDrawManagerDrawAwardedEvents` - `useLiquidationEvents` - `useManualContributionEvents` - `usePrizeBackstopEvents` +- `usePrizePoolDrawAwardedEvents` - `usePromotionCreatedEvents` - `usePromotionRewardsClaimedEvents` - `useRngAuctionCompletedEvents` diff --git a/packages/hyperstructure-react-hooks/src/constants.ts b/packages/hyperstructure-react-hooks/src/constants.ts index 39a8b574..125901bc 100644 --- a/packages/hyperstructure-react-hooks/src/constants.ts +++ b/packages/hyperstructure-react-hooks/src/constants.ts @@ -7,7 +7,7 @@ export const QUERY_KEYS = { block: 'block', blockAtTimestamp: 'blockAtTimestamp', clientChainId: 'clientChainId', - drawAwardedEvents: 'drawAwardedEvents', + drawManagerDrawAwardedEvents: 'drawManagerDrawAwardedEvents', drawPeriod: 'drawPeriod', drawTimestamps: 'drawTimestamps', drawWinners: 'drawWinners', @@ -24,6 +24,7 @@ export const QUERY_KEYS = { prizeBackstopEvents: 'prizeBackstopEvents', prizeInfo: 'prizeInfo', prizeOdds: 'prizeOdds', + prizePoolDrawAwardedEvents: 'prizePoolDrawAwardedEvents', prizeTokenData: 'prizeTokenData', promotionCreatedEvents: 'promotionCreatedEvents', promotionRewardsClaimedEvents: 'promotionRewardsClaimedEvents', diff --git a/packages/hyperstructure-react-hooks/src/events/useDrawAwardedEvents.ts b/packages/hyperstructure-react-hooks/src/events/useDrawManagerDrawAwardedEvents.ts similarity index 69% rename from packages/hyperstructure-react-hooks/src/events/useDrawAwardedEvents.ts rename to packages/hyperstructure-react-hooks/src/events/useDrawManagerDrawAwardedEvents.ts index 138c6147..7848c776 100644 --- a/packages/hyperstructure-react-hooks/src/events/useDrawAwardedEvents.ts +++ b/packages/hyperstructure-react-hooks/src/events/useDrawManagerDrawAwardedEvents.ts @@ -1,24 +1,26 @@ -import { PrizePool } from '@generationsoftware/hyperstructure-client-js' +import { + getDrawManagerDrawAwardedEvents, + PrizePool +} from '@generationsoftware/hyperstructure-client-js' import { NO_REFETCH } from '@shared/generic-react-hooks' -import { getDrawAwardedEvents } from '@shared/utilities' import { useQuery } from '@tanstack/react-query' import { usePublicClient } from 'wagmi' import { QUERY_KEYS } from '../constants' /** - * Returns `DrawAwarded` events + * Returns `DrawAwarded` events from a prize pool's draw manager * @param prizePool the prize pool to query events for * @param options optional settings * @returns */ -export const useDrawAwardedEvents = ( +export const useDrawManagerDrawAwardedEvents = ( prizePool: PrizePool, options?: { fromBlock?: bigint; toBlock?: bigint } ) => { const publicClient = usePublicClient({ chainId: prizePool?.chainId }) const queryKey = [ - QUERY_KEYS.drawAwardedEvents, + QUERY_KEYS.drawManagerDrawAwardedEvents, prizePool?.id, options?.fromBlock?.toString(), options?.toBlock?.toString() ?? 'latest' @@ -29,7 +31,7 @@ export const useDrawAwardedEvents = ( queryFn: async () => { if (!!publicClient) { const drawManagerAddress = await prizePool.getDrawManagerAddress() - return await getDrawAwardedEvents(publicClient, drawManagerAddress, options) + return await getDrawManagerDrawAwardedEvents(publicClient, drawManagerAddress, options) } }, enabled: !!prizePool && !!publicClient, diff --git a/packages/hyperstructure-react-hooks/src/events/usePrizePoolDrawAwardedEvents.ts b/packages/hyperstructure-react-hooks/src/events/usePrizePoolDrawAwardedEvents.ts new file mode 100644 index 00000000..e43740b0 --- /dev/null +++ b/packages/hyperstructure-react-hooks/src/events/usePrizePoolDrawAwardedEvents.ts @@ -0,0 +1,39 @@ +import { + getPrizePoolDrawAwardedEvents, + PrizePool +} from '@generationsoftware/hyperstructure-client-js' +import { NO_REFETCH } from '@shared/generic-react-hooks' +import { useQuery } from '@tanstack/react-query' +import { usePublicClient } from 'wagmi' +import { QUERY_KEYS } from '../constants' + +/** + * Returns `DrawAwarded` events from a prize pool + * @param prizePool the prize pool to query events for + * @param options optional settings + * @returns + */ +export const usePrizePoolDrawAwardedEvents = ( + prizePool: PrizePool, + options?: { fromBlock?: bigint; toBlock?: bigint } +) => { + const publicClient = usePublicClient({ chainId: prizePool?.chainId }) + + const queryKey = [ + QUERY_KEYS.prizePoolDrawAwardedEvents, + prizePool?.id, + options?.fromBlock?.toString(), + options?.toBlock?.toString() ?? 'latest' + ] + + return useQuery({ + queryKey, + queryFn: async () => { + if (!!publicClient) { + return await getPrizePoolDrawAwardedEvents(publicClient, prizePool.address, options) + } + }, + enabled: !!prizePool && !!publicClient, + ...NO_REFETCH + }) +} diff --git a/packages/hyperstructure-react-hooks/src/index.ts b/packages/hyperstructure-react-hooks/src/index.ts index 2bbd025a..29890800 100644 --- a/packages/hyperstructure-react-hooks/src/index.ts +++ b/packages/hyperstructure-react-hooks/src/index.ts @@ -27,10 +27,11 @@ export * from './blockchain/useTxReceipts' /** * Event Hooks */ -export * from './events/useDrawAwardedEvents' +export * from './events/useDrawManagerDrawAwardedEvents' export * from './events/useLiquidationEvents' export * from './events/useManualContributionEvents' export * from './events/usePrizeBackstopEvents' +export * from './events/usePrizePoolDrawAwardedEvents' export * from './events/usePromotionCreatedEvents' export * from './events/usePromotionRewardsClaimedEvents' export * from './events/useRngAuctionCompletedEvents' diff --git a/shared/utilities/utils/events.ts b/shared/utilities/utils/events.ts index 37d6965a..56e90173 100644 --- a/shared/utilities/utils/events.ts +++ b/shared/utilities/utils/events.ts @@ -95,13 +95,46 @@ export const getRngAuctionCompletedEvents = async ( } /** - * Returns `DrawAwarded` events + * Returns `DrawAwarded` events from a prize pool contract + * @param publicClient a public Viem client to query through + * @param prizePoolAddress the address of a prize pool to query events for + * @param options optional settings + * @returns + */ +export const getPrizePoolDrawAwardedEvents = async ( + publicClient: PublicClient, + prizePoolAddress: Address, + options?: { fromBlock?: bigint; toBlock?: bigint } +) => { + return await publicClient.getLogs({ + address: prizePoolAddress, + event: { + inputs: [ + { indexed: true, internalType: 'uint24', name: 'drawId', type: 'uint24' }, + { indexed: false, internalType: 'uint256', name: 'winningRandomNumber', type: 'uint256' }, + { indexed: false, internalType: 'uint8', name: 'lastNumTiers', type: 'uint8' }, + { indexed: false, internalType: 'uint8', name: 'numTiers', type: 'uint8' }, + { indexed: false, internalType: 'uint104', name: 'reserve', type: 'uint104' }, + { indexed: false, internalType: 'UD34x4', name: 'prizeTokensPerShare', type: 'uint128' }, + { indexed: false, internalType: 'uint48', name: 'drawOpenedAt', type: 'uint48' } + ], + name: 'DrawAwarded', + type: 'event' + }, + fromBlock: options?.fromBlock, + toBlock: options?.toBlock ?? 'latest', + strict: true + }) +} + +/** + * Returns `DrawAwarded` events from a draw manager contract * @param publicClient a public Viem client to query through * @param drawManagerAddress the address of a prize pool's draw manager to query events for * @param options optional settings * @returns */ -export const getDrawAwardedEvents = async ( +export const getDrawManagerDrawAwardedEvents = async ( publicClient: PublicClient, drawManagerAddress: Address, options?: { fromBlock?: bigint; toBlock?: bigint } From b639e46dfd1787d9f4614d5f21da1138440a5cdd Mon Sep 17 00:00:00 2001 From: Ncookiez Date: Wed, 28 Feb 2024 18:58:57 -0500 Subject: [PATCH 011/161] refactored `useRngTxs` --- apps/analytics/.env.example | 5 +- apps/analytics/package.json | 2 +- apps/analytics/src/components/ClaimFees.tsx | 19 +- apps/analytics/src/constants/config.ts | 41 +-- .../analytics/src/hooks/useAllDrawsStatus.tsx | 6 +- .../src/hooks/useCurrentDrawAwardReward.tsx | 32 +++ .../src/hooks/useCurrentRngAuctionReward.tsx | 32 +++ .../src/hooks/useDrawRelayFeePercentage.tsx | 34 --- .../src/hooks/useDrawRngFeePercentage.tsx | 44 ---- apps/analytics/src/hooks/useDrawStatus.tsx | 6 +- .../src/hooks/useRelayAuctionElapsedTime.tsx | 50 ---- apps/analytics/src/hooks/useRngTxs.tsx | 242 ++++++------------ apps/analytics/src/views/DrawsView.tsx | 51 ++-- apps/analytics/src/views/PrizesView.tsx | 39 +-- apps/analytics/src/views/ReserveView.tsx | 39 +-- 15 files changed, 220 insertions(+), 422 deletions(-) create mode 100644 apps/analytics/src/hooks/useCurrentDrawAwardReward.tsx create mode 100644 apps/analytics/src/hooks/useCurrentRngAuctionReward.tsx delete mode 100644 apps/analytics/src/hooks/useDrawRelayFeePercentage.tsx delete mode 100644 apps/analytics/src/hooks/useDrawRngFeePercentage.tsx delete mode 100644 apps/analytics/src/hooks/useRelayAuctionElapsedTime.tsx diff --git a/apps/analytics/.env.example b/apps/analytics/.env.example index 4f2c26a1..8fe8d023 100644 --- a/apps/analytics/.env.example +++ b/apps/analytics/.env.example @@ -1,9 +1,6 @@ # Mainnet RPC URLs NEXT_PUBLIC_MAINNET_RPC_URL="YOUR_MAINNET_RPC_HERE" NEXT_PUBLIC_OPTIMISM_RPC_URL="YOUR_OPTIMISM_RPC_HERE" -NEXT_PUBLIC_ARBITRUM_RPC_URL="YOUR_ARBITRUM_RPC_HERE" # Testnet RPC URLs -NEXT_PUBLIC_SEPOLIA_RPC_URL="YOUR_SEPOLIA_RPC_HERE" -NEXT_PUBLIC_OPTIMISM_SEPOLIA_RPC_URL="YOUR_OPTIMISM_SEPOLIA_RPC_HERE" -NEXT_PUBLIC_ARBITRUM_SEPOLIA_RPC_URL="YOUR_ARBITRUM_SEPOLIA_RPC_HERE" \ No newline at end of file +NEXT_PUBLIC_OPTIMISM_GOERLI_RPC_URL="YOUR_OPTIMISM_GOERLI_RPC_HERE" \ No newline at end of file diff --git a/apps/analytics/package.json b/apps/analytics/package.json index 9ed26131..6999e7f4 100644 --- a/apps/analytics/package.json +++ b/apps/analytics/package.json @@ -1,6 +1,6 @@ { "name": "analytics", - "version": "1.1.0", + "version": "1.2.0", "private": true, "scripts": { "dev": "next dev --port 3004", diff --git a/apps/analytics/src/components/ClaimFees.tsx b/apps/analytics/src/components/ClaimFees.tsx index 95513f9d..fc796d4c 100644 --- a/apps/analytics/src/components/ClaimFees.tsx +++ b/apps/analytics/src/components/ClaimFees.tsx @@ -1,7 +1,7 @@ import { PrizePool } from '@generationsoftware/hyperstructure-client-js' import { - useDrawAwardedEvents, - usePrizeDrawWinners + usePrizeDrawWinners, + usePrizePoolDrawAwardedEvents } from '@generationsoftware/hyperstructure-react-hooks' import { SubgraphDraw } from '@shared/types' import { ExternalLink, Spinner } from '@shared/ui' @@ -26,12 +26,15 @@ export const ClaimFees = (props: ClaimFeesProps) => { const { data: allDraws, isFetched: isFetchedAllDraws } = usePrizeDrawWinners(prizePool) const draw = allDraws?.find((d) => d.id === drawId) - const { data: drawAwardedEvents, isFetched: isFetchedDrawAwardedEvents } = useDrawAwardedEvents( - prizePool, - { fromBlock: !!prizePool ? QUERY_START_BLOCK[prizePool.chainId] : undefined } - ) - const drawAwardedEvent = drawAwardedEvents?.find((e) => e.args.drawId === drawId) - const numTiers = drawAwardedEvent?.args.numTiers + const { data: drawAwardedEvents, isFetched: isFetchedDrawAwardedEvents } = + usePrizePoolDrawAwardedEvents(prizePool, { + fromBlock: !!prizePool ? QUERY_START_BLOCK[prizePool.chainId] : undefined + }) + + const numTiers = useMemo(() => { + const drawAwardedEvent = drawAwardedEvents?.find((e) => e.args.drawId === drawId) + return drawAwardedEvent?.args.numTiers + }, [drawId, drawAwardedEvents]) const wins = useMemo(() => { const filteredWins: SubgraphDraw['prizeClaims'] = [] diff --git a/apps/analytics/src/constants/config.ts b/apps/analytics/src/constants/config.ts index a0d51df9..3ed2c050 100644 --- a/apps/analytics/src/constants/config.ts +++ b/apps/analytics/src/constants/config.ts @@ -1,13 +1,13 @@ import { NETWORK } from '@shared/utilities' import { Address } from 'viem' -import { arbitrum, arbitrumSepolia, mainnet, optimism, optimismSepolia, sepolia } from 'viem/chains' +import { mainnet, optimism, optimismGoerli } from 'viem/chains' /** * Supported networks */ export const SUPPORTED_NETWORKS = { - mainnets: [NETWORK.mainnet, NETWORK.optimism, NETWORK.arbitrum], - testnets: [NETWORK.sepolia, NETWORK.optimism_sepolia, NETWORK.arbitrum_sepolia] + mainnets: [NETWORK.mainnet, NETWORK.optimism], + testnets: [NETWORK.optimism_goerli] } as const /** @@ -16,10 +16,7 @@ export const SUPPORTED_NETWORKS = { export const WAGMI_CHAINS = { [NETWORK.mainnet]: mainnet, [NETWORK.optimism]: optimism, - [NETWORK.arbitrum]: arbitrum, - [NETWORK.sepolia]: sepolia, - [NETWORK.optimism_sepolia]: optimismSepolia, - [NETWORK.arbitrum_sepolia]: arbitrumSepolia + [NETWORK.optimism_goerli]: optimismGoerli } as const /** @@ -28,49 +25,33 @@ export const WAGMI_CHAINS = { export const RPC_URLS = { [NETWORK.mainnet]: process.env.NEXT_PUBLIC_MAINNET_RPC_URL, [NETWORK.optimism]: process.env.NEXT_PUBLIC_OPTIMISM_RPC_URL, - [NETWORK.arbitrum]: process.env.NEXT_PUBLIC_ARBITRUM_RPC_URL, - [NETWORK['sepolia']]: process.env.NEXT_PUBLIC_SEPOLIA_RPC_URL, - [NETWORK.optimism_sepolia]: process.env.NEXT_PUBLIC_OPTIMISM_SEPOLIA_RPC_URL, - [NETWORK.arbitrum_sepolia]: process.env.NEXT_PUBLIC_ARBITRUM_SEPOLIA_RPC_URL + [NETWORK.optimism_goerli]: process.env.NEXT_PUBLIC_OPTIMISM_GOERLI_RPC_URL } as const /** * Queries' start blocks */ export const QUERY_START_BLOCK: { [chainId: number]: bigint } = { - [NETWORK.mainnet]: 18_052_000n, - [NETWORK.optimism]: 108_927_000n, - [NETWORK.arbitrum]: 1n, - [NETWORK.sepolia]: 4_647_000n, - [NETWORK.optimism_sepolia]: 3_783_000n, - [NETWORK.arbitrum_sepolia]: 1_310_000n + [NETWORK.optimism]: 108_927_000n, // TODO: update once prizepool deployed to mainnet + [NETWORK.optimism_goerli]: 21_785_000n } /** * Draw results URL */ export const DRAW_RESULTS_URL: { [chainId: number]: string } = { - [NETWORK.optimism]: `https://raw.githubusercontent.com/GenerationSoftware/pt-v5-draw-results-mainnet/main/prizes/${NETWORK.optimism}`, - [NETWORK.arbitrum_sepolia]: `https://raw.githubusercontent.com/GenerationSoftware/pt-v5-draw-results-testnet/main/prizes/${NETWORK.arbitrum_sepolia}` + [NETWORK.optimism_goerli]: `https://raw.githubusercontent.com/GenerationSoftware/pt-v5-draw-results-testnet/main/prizes/${NETWORK.optimism_goerli}` } /** - * Vault LPs + * Extra POOL burn addresses */ -export const VAULT_LPS: { [chainId: number]: Lowercase
[] } = { +export const BURN_ADDRESSES: { [chainId: number]: Lowercase
[] } = { [NETWORK.optimism]: [ '0xb1b9dcb9f3a25e390fb37f597c2bf90b16889e41', '0xfbf4f89c7a9ecee48f65033097fecea257eb4049', '0xf9baa3cd7b8c1f205fd3a6861dca693fed683684', - '0x71409285d5b324a082e761e54ea0aa413da51db9' - ] -} - -/** - * Misc. POOL burn addresses - */ -export const BURN_ADDRESSES: { [chainId: number]: Lowercase
[] } = { - [NETWORK.optimism]: [ + '0x71409285d5b324a082e761e54ea0aa413da51db9', '0xf93329e78feff1145fce03a79d5b356588dea215', '0x3989cbc1fb0eb278601c018ed7627b07be9de4cb' ] diff --git a/apps/analytics/src/hooks/useAllDrawsStatus.tsx b/apps/analytics/src/hooks/useAllDrawsStatus.tsx index b918da96..5ab0b8c5 100644 --- a/apps/analytics/src/hooks/useAllDrawsStatus.tsx +++ b/apps/analytics/src/hooks/useAllDrawsStatus.tsx @@ -29,12 +29,12 @@ export const useAllDrawsStatus = (prizePool: PrizePool, drawIds: number[]) => { const currentTime = getSecondsSinceEpoch() drawIds.forEach((drawId) => { - const rngTxs = allRngTxs.find((txs) => txs.rng.drawId === drawId) + const rngTxs = allRngTxs.find((txs) => txs.rngAuction.drawId === drawId) const openedAt = firstDrawOpenedAt + drawPeriod * (drawId - 1) const closedAt = openedAt + drawPeriod - const rngCompletedAt = rngTxs?.rng?.timestamp - const awardedAt = rngTxs?.relay.l2?.timestamp + const rngCompletedAt = rngTxs?.rngAuction.timestamp + const awardedAt = rngTxs?.drawAward?.timestamp const finalizedAt = closedAt + drawPeriod const isClosed = currentTime >= closedAt diff --git a/apps/analytics/src/hooks/useCurrentDrawAwardReward.tsx b/apps/analytics/src/hooks/useCurrentDrawAwardReward.tsx new file mode 100644 index 00000000..be3c8b0d --- /dev/null +++ b/apps/analytics/src/hooks/useCurrentDrawAwardReward.tsx @@ -0,0 +1,32 @@ +import { PrizePool } from '@generationsoftware/hyperstructure-client-js' +import { NO_REFETCH } from '@shared/generic-react-hooks' +import { drawManagerABI } from '@shared/utilities' +import { useQuery } from '@tanstack/react-query' +import { formatUnits } from 'viem' +import { usePublicClient } from 'wagmi' + +export const useCurrentDrawAwardReward = ( + prizePool: PrizePool, + options?: { refetchInterval?: number } +) => { + const publicClient = usePublicClient({ chainId: prizePool?.chainId }) + + return useQuery({ + queryKey: ['currentDrawAwardReward'], + queryFn: async () => { + if (!!publicClient) { + const drawManagerAddress = await prizePool.getDrawManagerAddress() + const rewardFraction = await publicClient.readContract({ + address: drawManagerAddress, + abi: drawManagerABI, + functionName: 'awardDrawFee' + }) + + return parseFloat(formatUnits(rewardFraction, 18)) * 100 + } + }, + enabled: !!publicClient, + ...NO_REFETCH, + refetchInterval: options?.refetchInterval ?? false + }) +} diff --git a/apps/analytics/src/hooks/useCurrentRngAuctionReward.tsx b/apps/analytics/src/hooks/useCurrentRngAuctionReward.tsx new file mode 100644 index 00000000..718b6894 --- /dev/null +++ b/apps/analytics/src/hooks/useCurrentRngAuctionReward.tsx @@ -0,0 +1,32 @@ +import { PrizePool } from '@generationsoftware/hyperstructure-client-js' +import { NO_REFETCH } from '@shared/generic-react-hooks' +import { drawManagerABI } from '@shared/utilities' +import { useQuery } from '@tanstack/react-query' +import { formatUnits } from 'viem' +import { usePublicClient } from 'wagmi' + +export const useCurrentRngAuctionReward = ( + prizePool: PrizePool, + options?: { refetchInterval?: number } +) => { + const publicClient = usePublicClient({ chainId: prizePool?.chainId }) + + return useQuery({ + queryKey: ['currentRngAuctionReward'], + queryFn: async () => { + if (!!publicClient) { + const drawManagerAddress = await prizePool.getDrawManagerAddress() + const rewardFraction = await publicClient.readContract({ + address: drawManagerAddress, + abi: drawManagerABI, + functionName: 'startDrawFee' + }) + + return parseFloat(formatUnits(rewardFraction, 18)) * 100 + } + }, + enabled: !!publicClient, + ...NO_REFETCH, + refetchInterval: options?.refetchInterval ?? false + }) +} diff --git a/apps/analytics/src/hooks/useDrawRelayFeePercentage.tsx b/apps/analytics/src/hooks/useDrawRelayFeePercentage.tsx deleted file mode 100644 index ef86e35e..00000000 --- a/apps/analytics/src/hooks/useDrawRelayFeePercentage.tsx +++ /dev/null @@ -1,34 +0,0 @@ -import { PrizePool } from '@generationsoftware/hyperstructure-client-js' -import { NO_REFETCH } from '@shared/generic-react-hooks' -import { RNG_RELAY_ADDRESSES, rngRelayABI } from '@shared/utilities' -import { useQuery } from '@tanstack/react-query' -import { formatUnits } from 'viem' -import { usePublicClient } from 'wagmi' -import { useRelayAuctionElapsedTime } from './useRelayAuctionElapsedTime' - -export const useDrawRelayFeePercentage = (prizePool: PrizePool) => { - const publicClient = usePublicClient({ chainId: prizePool?.chainId }) - - const { data: elapsedTime } = useRelayAuctionElapsedTime(prizePool) - - const queryKey = ['drawRelayFeePercentage', prizePool?.chainId, elapsedTime?.toString()] - - return useQuery({ - queryKey, - queryFn: async () => { - if (!!publicClient) { - const rewardFraction = await publicClient.readContract({ - address: RNG_RELAY_ADDRESSES[prizePool.chainId].address, - abi: rngRelayABI, - functionName: 'computeRewardFraction', - args: [elapsedTime as bigint] - }) - - return parseFloat(formatUnits(rewardFraction, 18)) * 100 - } - }, - enabled: - !!prizePool && !!publicClient && !!elapsedTime && !!RNG_RELAY_ADDRESSES[prizePool.chainId], - ...NO_REFETCH - }) -} diff --git a/apps/analytics/src/hooks/useDrawRngFeePercentage.tsx b/apps/analytics/src/hooks/useDrawRngFeePercentage.tsx deleted file mode 100644 index 6d79752d..00000000 --- a/apps/analytics/src/hooks/useDrawRngFeePercentage.tsx +++ /dev/null @@ -1,44 +0,0 @@ -import { PrizePool } from '@generationsoftware/hyperstructure-client-js' -import { NO_REFETCH } from '@shared/generic-react-hooks' -import { RNG_AUCTION, RNG_RELAY_ADDRESSES, rngAuctionABI } from '@shared/utilities' -import { useQuery } from '@tanstack/react-query' -import { formatUnits } from 'viem' -import { usePublicClient } from 'wagmi' - -export const useDrawRngFeePercentage = ( - prizePool: PrizePool, - options?: { refetchInterval?: number } -) => { - const originChainId = !!prizePool - ? RNG_RELAY_ADDRESSES[prizePool.chainId].from.chainId - : undefined - const publicClient = usePublicClient({ chainId: originChainId }) - - return useQuery({ - queryKey: ['drawRngFeePercentage'], - queryFn: async () => { - if (!!publicClient) { - const isAuctionOpen = await publicClient.readContract({ - address: RNG_AUCTION[originChainId as number].address, - abi: rngAuctionABI, - functionName: 'isAuctionOpen' - }) - - if (isAuctionOpen) { - const rewardFraction = await publicClient.readContract({ - address: RNG_AUCTION[originChainId as number].address, - abi: rngAuctionABI, - functionName: 'currentFractionalReward' - }) - - return parseFloat(formatUnits(rewardFraction, 18)) * 100 - } - - return 0 - } - }, - enabled: !!originChainId && !!publicClient, - ...NO_REFETCH, - refetchInterval: options?.refetchInterval ?? false - }) -} diff --git a/apps/analytics/src/hooks/useDrawStatus.tsx b/apps/analytics/src/hooks/useDrawStatus.tsx index 6dda7ddb..7e47a16c 100644 --- a/apps/analytics/src/hooks/useDrawStatus.tsx +++ b/apps/analytics/src/hooks/useDrawStatus.tsx @@ -19,12 +19,12 @@ export const useDrawStatus = (prizePool: PrizePool, drawId: number) => { const data = useMemo(() => { if (isFetched && !!firstDrawOpenedAt && !!drawPeriod && !!allRngTxs) { - const rngTxs = allRngTxs.find((txs) => txs.rng.drawId === drawId) + const rngTxs = allRngTxs.find((txs) => txs.rngAuction.drawId === drawId) const openedAt = firstDrawOpenedAt + drawPeriod * (drawId - 1) const closedAt = openedAt + drawPeriod - const rngCompletedAt = rngTxs?.rng?.timestamp - const awardedAt = rngTxs?.relay.l2?.timestamp + const rngCompletedAt = rngTxs?.rngAuction.timestamp + const awardedAt = rngTxs?.drawAward?.timestamp const finalizedAt = closedAt + drawPeriod const currentTime = getSecondsSinceEpoch() diff --git a/apps/analytics/src/hooks/useRelayAuctionElapsedTime.tsx b/apps/analytics/src/hooks/useRelayAuctionElapsedTime.tsx deleted file mode 100644 index b75aac78..00000000 --- a/apps/analytics/src/hooks/useRelayAuctionElapsedTime.tsx +++ /dev/null @@ -1,50 +0,0 @@ -import { PrizePool } from '@generationsoftware/hyperstructure-client-js' -import { NO_REFETCH } from '@shared/generic-react-hooks' -import { - chainlinkVrfABI, - getSecondsSinceEpoch, - RNG_AUCTION, - RNG_RELAY_ADDRESSES, - rngAuctionABI -} from '@shared/utilities' -import { useQuery } from '@tanstack/react-query' -import { usePublicClient } from 'wagmi' - -export const useRelayAuctionElapsedTime = ( - prizePool: PrizePool, - options?: { refetchInterval?: number } -) => { - const originChainId = !!prizePool - ? RNG_RELAY_ADDRESSES[prizePool.chainId].from.chainId - : undefined - const publicClient = usePublicClient({ chainId: originChainId }) - - return useQuery({ - queryKey: ['relayAuctionElapsedTime'], - queryFn: async () => { - if (!!publicClient) { - const lastAuction = await publicClient.readContract({ - address: RNG_AUCTION[originChainId as number].address, - abi: rngAuctionABI, - functionName: 'getLastAuction' - }) - - if (!lastAuction.rngRequestId) { - return 0n - } - - const completedAt = await publicClient.readContract({ - address: lastAuction.rng, - abi: chainlinkVrfABI, - functionName: 'completedAt', - args: [lastAuction.rngRequestId] - }) - - return BigInt(getSecondsSinceEpoch()) - completedAt - } - }, - enabled: !!originChainId && !!publicClient, - ...NO_REFETCH, - refetchInterval: options?.refetchInterval ?? false - }) -} diff --git a/apps/analytics/src/hooks/useRngTxs.tsx b/apps/analytics/src/hooks/useRngTxs.tsx index 018ab109..6efbf3ec 100644 --- a/apps/analytics/src/hooks/useRngTxs.tsx +++ b/apps/analytics/src/hooks/useRngTxs.tsx @@ -1,217 +1,137 @@ import { PrizePool } from '@generationsoftware/hyperstructure-client-js' import { useBlocks, - useDrawAwardedEvents, - useFirstDrawOpenedAt, - useRelayAuctionEvents, - useRngAuctionEvents, - useRngL1RelayMsgEvents, - useRngL2RelayMsgEvents + useDrawManagerDrawAwardedEvents, + usePrizePoolDrawAwardedEvents, + useRngAuctionCompletedEvents } from '@generationsoftware/hyperstructure-react-hooks' -import { RNG_AUCTION, RNG_RELAY_ADDRESSES } from '@shared/utilities' import { useMemo } from 'react' import { Address } from 'viem' import { QUERY_START_BLOCK } from '@constants/config' -export interface RngTx { +export interface RngAuctionTx { drawId: number - fee?: bigint - feeFraction: bigint - feeRecipient: Address + reward?: bigint + rewardRecipient: Address hash: `0x${string}` blockNumber: bigint timestamp?: number } -export interface RelayTx { +export interface DrawAwardTx { drawId: number - fee: bigint - feeFraction?: bigint - feeRecipient: Address + reward: bigint + rewardRecipient: Address reserve: bigint - hash: `0x${string}` - closedAt: number - blockNumber: bigint - timestamp: number -} - -export interface RelayMsgTx { - drawId: number - msgId: `0x${string}` + lastNumTiers: number + numTiers: number hash: `0x${string}` blockNumber: bigint + timestamp?: number } export const useRngTxs = (prizePool: PrizePool) => { - const originChainId = !!prizePool - ? RNG_RELAY_ADDRESSES[prizePool.chainId].from.chainId - : undefined const fromBlock = !!prizePool ? QUERY_START_BLOCK[prizePool.chainId] : undefined - const originFromBlock = !!originChainId ? QUERY_START_BLOCK[originChainId] : undefined - - const { data: rngAuctionEvents, isFetched: isFetchedRngAuctionEvents } = useRngAuctionEvents( - originChainId as number, - { fromBlock: originFromBlock } - ) - const rngCompletedBlockNumbers = new Set( - rngAuctionEvents?.map((e) => e.blockNumber) ?? [] - ) - const { data: relayAuctionEvents, isFetched: isFetchedRelayAuctionEvents } = - useRelayAuctionEvents(prizePool?.chainId, { fromBlock }) + const { data: rngAuctionCompletedEvents, isFetched: isFetchedRngAuctionCompletedEvents } = + useRngAuctionCompletedEvents(prizePool, { fromBlock }) + const { data: prizePoolDrawAwardedEvents, isFetched: isFetchedPrizePoolDrawAwardedEvents } = + usePrizePoolDrawAwardedEvents(prizePool, { fromBlock }) + const { data: drawManagerDrawAwardedEvents, isFetched: isFetchedDrawManagerDrawAwardedEvents } = + useDrawManagerDrawAwardedEvents(prizePool, { fromBlock }) - const { data: drawAwardedEvents, isFetched: isFetchedDrawAwardedEvents } = useDrawAwardedEvents( - prizePool, - { fromBlock } + const rngAuctionCompletedBlockNumbers = new Set( + rngAuctionCompletedEvents?.map((e) => e.blockNumber) ?? [] ) const drawAwardedBlockNumbers = new Set( - drawAwardedEvents?.map((e) => e.blockNumber) ?? [] + prizePoolDrawAwardedEvents?.map((e) => e.blockNumber) ?? [] ) - const { data: rngCompletedBlocks, isFetched: isFetchedRngCompletedBlocks } = useBlocks( - originChainId as number, - [...rngCompletedBlockNumbers] - ) + const { data: rngAuctionCompletedBlocks, isFetched: isFetchedRngAuctionCompletedBlocks } = + useBlocks(prizePool?.chainId, [...rngAuctionCompletedBlockNumbers]) const { data: drawAwardedBlocks, isFetched: isFetchedDrawAwardedBlocks } = useBlocks( prizePool?.chainId, [...drawAwardedBlockNumbers] ) - const { data: rngL1RelayMsgEvents, isFetched: isFetchedRngL1RelayMsgEvents } = - useRngL1RelayMsgEvents(originChainId as number, prizePool?.chainId, { - fromBlock: originFromBlock - }) - const { data: rngL2RelayMsgEvents, isFetched: isFetchedRngL2RelayMsgEvents } = - useRngL2RelayMsgEvents(prizePool?.chainId, { fromBlock }) - - const { data: firstDrawOpenedAt, isFetched: isFetchedFirstDrawOpenedAt } = - useFirstDrawOpenedAt(prizePool) - - // TODO: this is assuming the drawPeriod is always the same as the sequencePeriod - not ideal const data = useMemo(() => { if ( - !!rngAuctionEvents && - !!relayAuctionEvents && - !!drawAwardedEvents && - !!rngCompletedBlocks && - !!drawAwardedBlocks && - !!rngL1RelayMsgEvents && - !!rngL2RelayMsgEvents && - !!firstDrawOpenedAt && - !!originChainId + !!rngAuctionCompletedEvents && + !!prizePoolDrawAwardedEvents && + !!drawManagerDrawAwardedEvents && + !!rngAuctionCompletedBlocks && + !!drawAwardedBlocks ) { - const rngTxs = rngAuctionEvents - .map((rngAuctionEvent) => { - const sequenceOffset = RNG_AUCTION[originChainId].sequenceOffset - const sequencePeriod = RNG_AUCTION[originChainId].sequencePeriod - const idDiff = (firstDrawOpenedAt - sequenceOffset) / sequencePeriod - - const sequenceId = rngAuctionEvent.args.sequenceId - const drawId = sequenceId - idDiff + const rngTxs = rngAuctionCompletedEvents + .map((rngAuctionCompletedEvent) => { + const drawId = rngAuctionCompletedEvent.args.drawId - const rngCompletedBlock = rngCompletedBlocks.find( - (e) => e.number === rngAuctionEvent.blockNumber + const rngAuctionCompletedBlock = rngAuctionCompletedBlocks.find( + (block) => block.number === rngAuctionCompletedEvent.blockNumber ) - if (drawId > 0) { - const drawAwardedEvent = drawAwardedEvents.find((e) => e.args.drawId === drawId) - - const periodStart = sequenceOffset + sequencePeriod * rngAuctionEvent.args.sequenceId - const periodEnd = periodStart + sequencePeriod - const drawAwardedBlock = drawAwardedBlocks.find( - (block) => block.timestamp > periodStart && block.timestamp < periodEnd - ) + const rngAuction: RngAuctionTx = { + drawId, + rewardRecipient: rngAuctionCompletedEvent.args.recipient, + hash: rngAuctionCompletedEvent.transactionHash, + blockNumber: rngAuctionCompletedEvent.blockNumber, + timestamp: !!rngAuctionCompletedBlock + ? Number(rngAuctionCompletedBlock.timestamp) + : undefined + } - const relevantRelayAuctionEvents = relayAuctionEvents.filter( - (event) => event.args.sequenceId === rngAuctionEvent.args.sequenceId - ) - const firstRelayEvent = relevantRelayAuctionEvents.find( - (event) => event.args.index === 0 - ) - const secondRelayEvent = relevantRelayAuctionEvents.find( - (event) => event.args.index === 1 - ) + let drawAward: DrawAwardTx | undefined = undefined - const relayMsgReceivedEvent = !!secondRelayEvent - ? rngL2RelayMsgEvents.find( - (event) => event.blockNumber === secondRelayEvent.blockNumber - ) - : undefined - const relayMsgEvent = !!relayMsgReceivedEvent - ? rngL1RelayMsgEvents.find( - (event) => - Number(event.args.remoteOwnerChainId) === prizePool.chainId && - event.args.messageId.toLowerCase() === - relayMsgReceivedEvent.args.messageId.toLowerCase() - ) - : undefined + const prizePoolDrawAwardedEvent = prizePoolDrawAwardedEvents.find( + (e) => e.args.drawId === drawId + ) - const rng: RngTx = { - drawId: drawId, - fee: firstRelayEvent?.args.reward, - feeFraction: rngAuctionEvent.args.rewardFraction, - feeRecipient: rngAuctionEvent.args.recipient, - hash: rngAuctionEvent.transactionHash, - blockNumber: rngAuctionEvent.blockNumber, - timestamp: !!rngCompletedBlock ? Number(rngCompletedBlock.timestamp) : undefined - } + if (!!prizePoolDrawAwardedEvent) { + const drawManagerDrawAwardedEvent = drawManagerDrawAwardedEvents.find( + (e) => e.args.drawId === drawId + ) - const relay: { l1?: RelayMsgTx; l2?: RelayTx } = { - l1: !!relayMsgEvent - ? { - drawId: drawId, - msgId: relayMsgEvent.args.messageId, - hash: relayMsgEvent.transactionHash, - blockNumber: relayMsgEvent.blockNumber - } - : undefined, - l2: - !!secondRelayEvent && !!drawAwardedEvent && !!drawAwardedBlock - ? { - drawId: drawId, - fee: secondRelayEvent.args.reward, - feeFraction: - !!rng.fee && !!rng.feeFraction - ? rng.fee / rng.feeFraction !== 0n - ? secondRelayEvent.args.reward / (rng.fee / rng.feeFraction) - : secondRelayEvent.args.reward - : undefined, - feeRecipient: secondRelayEvent.args.recipient, - reserve: drawAwardedEvent.args.reserve, - hash: secondRelayEvent.transactionHash, - closedAt: periodStart, - blockNumber: secondRelayEvent.blockNumber, - timestamp: Number(drawAwardedBlock.timestamp) - } - : undefined + if (!!drawManagerDrawAwardedEvent) { + const drawAwardedBlock = drawAwardedBlocks.find( + (block) => block.number === prizePoolDrawAwardedEvent.blockNumber + ) + + drawAward = { + drawId, + reward: drawManagerDrawAwardedEvent.args.awardReward, + rewardRecipient: drawManagerDrawAwardedEvent.args.awardRecipient, + reserve: prizePoolDrawAwardedEvent.args.reserve, + lastNumTiers: prizePoolDrawAwardedEvent.args.lastNumTiers, + numTiers: prizePoolDrawAwardedEvent.args.numTiers, + hash: prizePoolDrawAwardedEvent.transactionHash, + blockNumber: prizePoolDrawAwardedEvent.blockNumber, + timestamp: !!drawAwardedBlock ? Number(drawAwardedBlock.timestamp) : undefined + } + + rngAuction.reward = drawManagerDrawAwardedEvent.args.startReward } - - return { rng, relay } } + + return { rngAuction, drawAward } }) - .filter((tx) => !!tx) as { rng: RngTx; relay: { l1?: RelayMsgTx; l2?: RelayTx } }[] + .filter((tx) => !!tx) return rngTxs } }, [ - rngAuctionEvents, - relayAuctionEvents, - drawAwardedEvents, - drawAwardedBlocks, - rngL1RelayMsgEvents, - rngL2RelayMsgEvents, - firstDrawOpenedAt + rngAuctionCompletedEvents, + prizePoolDrawAwardedEvents, + drawManagerDrawAwardedEvents, + rngAuctionCompletedBlocks, + drawAwardedBlocks ]) const isFetched = - isFetchedRngAuctionEvents && - isFetchedRelayAuctionEvents && - isFetchedDrawAwardedEvents && - isFetchedRngCompletedBlocks && - isFetchedDrawAwardedBlocks && - isFetchedRngL1RelayMsgEvents && - isFetchedRngL2RelayMsgEvents && - isFetchedFirstDrawOpenedAt + isFetchedRngAuctionCompletedEvents && + isFetchedPrizePoolDrawAwardedEvents && + isFetchedDrawManagerDrawAwardedEvents && + isFetchedRngAuctionCompletedBlocks && + isFetchedDrawAwardedBlocks return { data, isFetched } } diff --git a/apps/analytics/src/views/DrawsView.tsx b/apps/analytics/src/views/DrawsView.tsx index 4dfac57a..17574f00 100644 --- a/apps/analytics/src/views/DrawsView.tsx +++ b/apps/analytics/src/views/DrawsView.tsx @@ -1,12 +1,10 @@ import { PrizePool } from '@generationsoftware/hyperstructure-client-js' import { - useDrawAwardedEvents, - useRelayAuctionEvents, - useRngAuctionEvents, - useRngL1RelayMsgEvents, - useRngL2RelayMsgEvents + useDrawManagerDrawAwardedEvents, + usePrizePoolDrawAwardedEvents, + useRngAuctionCompletedEvents } from '@generationsoftware/hyperstructure-react-hooks' -import { PRIZE_POOLS, RNG_RELAY_ADDRESSES, sToMs } from '@shared/utilities' +import { PRIZE_POOLS, sToMs } from '@shared/utilities' import classNames from 'classnames' import { useEffect, useMemo } from 'react' import { Address, PublicClient } from 'viem' @@ -15,8 +13,8 @@ import { DrawsAvgClaimFeesChart } from '@components/Charts/DrawsAvgClaimFeesChar import { DrawsAvgLiqEfficiencyChart } from '@components/Charts/DrawsAvgLiqEfficiencyChart' import { DrawCards } from '@components/Draws/DrawCards' import { QUERY_START_BLOCK } from '@constants/config' -import { useDrawRngFeePercentage } from '@hooks/useDrawRngFeePercentage' -import { useRelayAuctionElapsedTime } from '@hooks/useRelayAuctionElapsedTime' +import { useCurrentDrawAwardReward } from '@hooks/useCurrentDrawAwardReward' +import { useCurrentRngAuctionReward } from '@hooks/useCurrentRngAuctionReward' interface DrawsViewProps { chainId: number @@ -48,40 +46,29 @@ export const DrawsView = (props: DrawsViewProps) => { ) }, [chainId, publicClient]) - const originChainId = !!prizePool - ? RNG_RELAY_ADDRESSES[prizePool.chainId].from.chainId - : undefined const fromBlock = !!prizePool ? QUERY_START_BLOCK[prizePool.chainId] : undefined - const originFromBlock = !!originChainId ? QUERY_START_BLOCK[originChainId] : undefined - const { refetch: refetchDrawRngFeePercentage } = useDrawRngFeePercentage(prizePool) - const { refetch: refetchRngAuctionEvents } = useRngAuctionEvents(originChainId as number, { - fromBlock: originFromBlock - }) - const { refetch: refetchRngL1RelayMsgEvents } = useRngL1RelayMsgEvents( - originChainId as number, - prizePool?.chainId, - { fromBlock: originFromBlock } - ) - const { refetch: refetchRelayAuctionElapsedTime } = useRelayAuctionElapsedTime(prizePool) - const { refetch: refetchRelayAuctionEvents } = useRelayAuctionEvents(prizePool?.chainId, { + const { refetch: refetchCurrentRngAuctionReward } = useCurrentRngAuctionReward(prizePool) + const { refetch: refetchCurrentDrawAwardReward } = useCurrentDrawAwardReward(prizePool) + const { refetch: refetchRngAuctionCompletedEvents } = useRngAuctionCompletedEvents(prizePool, { fromBlock }) - const { refetch: refetchDrawAwardedEvents } = useDrawAwardedEvents(prizePool, { fromBlock }) - const { refetch: refetchRngL2RelayMsgEvents } = useRngL2RelayMsgEvents(prizePool?.chainId, { + const { refetch: refetchPrizePoolDrawAwardedEvents } = usePrizePoolDrawAwardedEvents(prizePool, { fromBlock }) + const { refetch: refetchDrawManagerDrawAwardedEvents } = useDrawManagerDrawAwardedEvents( + prizePool, + { fromBlock } + ) // Automatic data refetching useEffect(() => { const interval = setInterval(() => { - refetchDrawRngFeePercentage() - refetchRngAuctionEvents() - refetchRngL1RelayMsgEvents() - refetchRelayAuctionElapsedTime() - refetchRelayAuctionEvents() - refetchDrawAwardedEvents() - refetchRngL2RelayMsgEvents() + refetchCurrentRngAuctionReward() + refetchCurrentDrawAwardReward() + refetchRngAuctionCompletedEvents() + refetchPrizePoolDrawAwardedEvents() + refetchDrawManagerDrawAwardedEvents() }, sToMs(300)) return () => clearInterval(interval) diff --git a/apps/analytics/src/views/PrizesView.tsx b/apps/analytics/src/views/PrizesView.tsx index 9739760f..2666d8d9 100644 --- a/apps/analytics/src/views/PrizesView.tsx +++ b/apps/analytics/src/views/PrizesView.tsx @@ -1,12 +1,10 @@ import { PrizePool } from '@generationsoftware/hyperstructure-client-js' import { - useDrawAwardedEvents, - useRelayAuctionEvents, - useRngAuctionEvents, - useRngL1RelayMsgEvents, - useRngL2RelayMsgEvents + useDrawManagerDrawAwardedEvents, + usePrizePoolDrawAwardedEvents, + useRngAuctionCompletedEvents } from '@generationsoftware/hyperstructure-react-hooks' -import { PRIZE_POOLS, RNG_RELAY_ADDRESSES, sToMs } from '@shared/utilities' +import { PRIZE_POOLS, sToMs } from '@shared/utilities' import classNames from 'classnames' import { useAtomValue } from 'jotai' import { useEffect, useMemo } from 'react' @@ -49,36 +47,25 @@ export const PrizesView = (props: PrizesViewProps) => { ) }, [chainId, publicClient]) - const originChainId = !!prizePool - ? RNG_RELAY_ADDRESSES[prizePool.chainId].from.chainId - : undefined const fromBlock = !!prizePool ? QUERY_START_BLOCK[prizePool.chainId] : undefined - const originFromBlock = !!originChainId ? QUERY_START_BLOCK[originChainId] : undefined - const { refetch: refetchRngAuctionEvents } = useRngAuctionEvents(originChainId as number, { - fromBlock: originFromBlock - }) - const { refetch: refetchRngL1RelayMsgEvents } = useRngL1RelayMsgEvents( - originChainId as number, - prizePool?.chainId, - { fromBlock: originFromBlock } - ) - const { refetch: refetchRelayAuctionEvents } = useRelayAuctionEvents(prizePool?.chainId, { + const { refetch: refetchRngAuctionCompletedEvents } = useRngAuctionCompletedEvents(prizePool, { fromBlock }) - const { refetch: refetchDrawAwardedEvents } = useDrawAwardedEvents(prizePool, { fromBlock }) - const { refetch: refetchRngL2RelayMsgEvents } = useRngL2RelayMsgEvents(prizePool?.chainId, { + const { refetch: refetchPrizePoolDrawAwardedEvents } = usePrizePoolDrawAwardedEvents(prizePool, { fromBlock }) + const { refetch: refetchDrawManagerDrawAwardedEvents } = useDrawManagerDrawAwardedEvents( + prizePool, + { fromBlock } + ) // Automatic data refetching useEffect(() => { const interval = setInterval(() => { - refetchRngAuctionEvents() - refetchRngL1RelayMsgEvents() - refetchRelayAuctionEvents() - refetchDrawAwardedEvents() - refetchRngL2RelayMsgEvents() + refetchRngAuctionCompletedEvents() + refetchPrizePoolDrawAwardedEvents() + refetchDrawManagerDrawAwardedEvents() }, sToMs(300)) return () => clearInterval(interval) diff --git a/apps/analytics/src/views/ReserveView.tsx b/apps/analytics/src/views/ReserveView.tsx index 9fd55608..9f2c77ef 100644 --- a/apps/analytics/src/views/ReserveView.tsx +++ b/apps/analytics/src/views/ReserveView.tsx @@ -1,15 +1,13 @@ import { PrizePool } from '@generationsoftware/hyperstructure-client-js' import { - useDrawAwardedEvents, + useDrawManagerDrawAwardedEvents, useLiquidationEvents, useManualContributionEvents, usePrizeBackstopEvents, - useRelayAuctionEvents, - useRngAuctionEvents, - useRngL1RelayMsgEvents, - useRngL2RelayMsgEvents + usePrizePoolDrawAwardedEvents, + useRngAuctionCompletedEvents } from '@generationsoftware/hyperstructure-react-hooks' -import { getSecondsSinceEpoch, PRIZE_POOLS, RNG_RELAY_ADDRESSES, sToMs } from '@shared/utilities' +import { getSecondsSinceEpoch, PRIZE_POOLS, sToMs } from '@shared/utilities' import classNames from 'classnames' import { useSetAtom } from 'jotai' import { useEffect, useMemo } from 'react' @@ -53,11 +51,7 @@ export const ReserveView = (props: ReserveViewProps) => { ) }, [chainId, publicClient]) - const originChainId = !!prizePool - ? RNG_RELAY_ADDRESSES[prizePool.chainId].from.chainId - : undefined const fromBlock = !!prizePool ? QUERY_START_BLOCK[prizePool.chainId] : undefined - const originFromBlock = !!originChainId ? QUERY_START_BLOCK[originChainId] : undefined const { refetch: refetchReserve } = useReserve(prizePool) const { refetch: refetchLiquidationEvents } = useLiquidationEvents(prizePool?.chainId, { @@ -67,21 +61,16 @@ export const ReserveView = (props: ReserveViewProps) => { fromBlock }) const { refetch: refetchPrizeBackstopEvents } = usePrizeBackstopEvents(prizePool, { fromBlock }) - const { refetch: refetchRngAuctionEvents } = useRngAuctionEvents(originChainId as number, { - fromBlock: originFromBlock - }) - const { refetch: refetchRngL1RelayMsgEvents } = useRngL1RelayMsgEvents( - originChainId as number, - prizePool?.chainId, - { fromBlock: originFromBlock } - ) - const { refetch: refetchRelayAuctionEvents } = useRelayAuctionEvents(prizePool?.chainId, { + const { refetch: refetchRngAuctionCompletedEvents } = useRngAuctionCompletedEvents(prizePool, { fromBlock }) - const { refetch: refetchDrawAwardedEvents } = useDrawAwardedEvents(prizePool, { fromBlock }) - const { refetch: refetchRngL2RelayMsgEvents } = useRngL2RelayMsgEvents(prizePool?.chainId, { + const { refetch: refetchPrizePoolDrawAwardedEvents } = usePrizePoolDrawAwardedEvents(prizePool, { fromBlock }) + const { refetch: refetchDrawManagerDrawAwardedEvents } = useDrawManagerDrawAwardedEvents( + prizePool, + { fromBlock } + ) // Automatic data refetching useEffect(() => { @@ -90,11 +79,9 @@ export const ReserveView = (props: ReserveViewProps) => { refetchLiquidationEvents() refetchManualContributionEvents() refetchPrizeBackstopEvents() - refetchRngAuctionEvents() - refetchRngL1RelayMsgEvents() - refetchRelayAuctionEvents() - refetchDrawAwardedEvents() - refetchRngL2RelayMsgEvents() + refetchRngAuctionCompletedEvents() + refetchPrizePoolDrawAwardedEvents() + refetchDrawManagerDrawAwardedEvents() setCurrentTimestamp(getSecondsSinceEpoch()) }, sToMs(300)) From c13ca422034962907e30a70fcc382e1c3c442a0b Mon Sep 17 00:00:00 2001 From: Ncookiez Date: Wed, 28 Feb 2024 19:48:14 -0500 Subject: [PATCH 012/161] refactored components --- .../src/components/Burn/BurnCard.tsx | 17 +-- .../src/components/Burn/BurnHeader.tsx | 7 +- .../src/components/Burn/RecentBurnStats.tsx | 7 +- .../src/components/Charts/BurnChart.tsx | 59 ++++----- .../Charts/DrawAvgClaimFeesChart.tsx | 12 +- .../Charts/DrawsAvgClaimFeesChart.tsx | 7 +- .../Charts/DrawsAvgLiqEfficiencyChart.tsx | 8 +- .../src/components/Charts/ReserveChart.tsx | 40 +++--- .../src/components/Draws/DrawAwardReward.tsx | 84 +++++++++++++ .../src/components/Draws/DrawCard.tsx | 8 +- .../components/Draws/DrawLiqEfficiency.tsx | 8 +- .../src/components/Draws/DrawPrizes.tsx | 21 ++-- .../src/components/Draws/DrawRelayFee.tsx | 118 ------------------ .../{DrawRngFee.tsx => DrawRngReward.tsx} | 66 ++++------ .../src/components/Prizes/PrizesTable.tsx | 18 +-- .../src/components/Reserve/ReserveCard.tsx | 8 +- .../src/hooks/useCurrentDrawAwardReward.tsx | 6 +- .../src/hooks/useCurrentRngAuctionReward.tsx | 6 +- 18 files changed, 218 insertions(+), 282 deletions(-) create mode 100644 apps/analytics/src/components/Draws/DrawAwardReward.tsx delete mode 100644 apps/analytics/src/components/Draws/DrawRelayFee.tsx rename apps/analytics/src/components/Draws/{DrawRngFee.tsx => DrawRngReward.tsx} (52%) diff --git a/apps/analytics/src/components/Burn/BurnCard.tsx b/apps/analytics/src/components/Burn/BurnCard.tsx index 2430de6e..66a592da 100644 --- a/apps/analytics/src/components/Burn/BurnCard.tsx +++ b/apps/analytics/src/components/Burn/BurnCard.tsx @@ -4,15 +4,14 @@ import classNames from 'classnames' interface BurnCardProps { name: string - lp: { total: number; change: number } - manual: { total: number; change: number } + dead: { total: number; change: number } other: { total: number; change: number } prizeToken: Token className?: string } export const BurnCard = (props: BurnCardProps) => { - const { name, lp, manual, other, prizeToken, className } = props + const { name, dead, other, prizeToken, className } = props return (
{ )} > {name} - - +
{ const { prizeToken, className } = props - const lpAddresses = VAULT_LPS[prizeToken.chainId] ?? [] - const miscBurnAddresses = BURN_ADDRESSES[prizeToken.chainId] ?? [] + const burnAddresses = BURN_ADDRESSES[prizeToken.chainId] ?? [] const { data: burnTxs } = useTransferEvents(prizeToken.chainId, prizeToken.address, { - to: [...lpAddresses, ...miscBurnAddresses, DEAD_ADDRESS], + to: [DEAD_ADDRESS, ...burnAddresses], fromBlock: QUERY_START_BLOCK[prizeToken.chainId] }) diff --git a/apps/analytics/src/components/Burn/RecentBurnStats.tsx b/apps/analytics/src/components/Burn/RecentBurnStats.tsx index 679970ed..58431bf6 100644 --- a/apps/analytics/src/components/Burn/RecentBurnStats.tsx +++ b/apps/analytics/src/components/Burn/RecentBurnStats.tsx @@ -4,7 +4,7 @@ import { DEAD_ADDRESS, formatBigIntForDisplay } from '@shared/utilities' import classNames from 'classnames' import { useMemo } from 'react' import { Block } from 'viem' -import { BURN_ADDRESSES, QUERY_START_BLOCK, VAULT_LPS } from '@constants/config' +import { BURN_ADDRESSES, QUERY_START_BLOCK } from '@constants/config' interface RecentBurnStatsProps { prizeToken: Token @@ -16,11 +16,10 @@ interface RecentBurnStatsProps { export const RecentBurnStats = (props: RecentBurnStatsProps) => { const { prizeToken, minBlock, label, className } = props - const lpAddresses = VAULT_LPS[prizeToken.chainId] ?? [] - const miscBurnAddresses = BURN_ADDRESSES[prizeToken.chainId] ?? [] + const burnAddresses = BURN_ADDRESSES[prizeToken.chainId] ?? [] const { data: burnEvents } = useTransferEvents(prizeToken.chainId, prizeToken.address, { - to: [...lpAddresses, ...miscBurnAddresses, DEAD_ADDRESS], + to: [DEAD_ADDRESS, ...burnAddresses], fromBlock: QUERY_START_BLOCK[prizeToken.chainId] }) diff --git a/apps/analytics/src/components/Charts/BurnChart.tsx b/apps/analytics/src/components/Charts/BurnChart.tsx index 139d2a4f..d4ccdd46 100644 --- a/apps/analytics/src/components/Charts/BurnChart.tsx +++ b/apps/analytics/src/components/Charts/BurnChart.tsx @@ -16,14 +16,13 @@ import { useMemo } from 'react' import { currentTimestampAtom } from 'src/atoms' import { Address, formatUnits } from 'viem' import { BurnCard } from '@components/Burn/BurnCard' -import { BURN_ADDRESSES, QUERY_START_BLOCK, VAULT_LPS } from '@constants/config' -import { RelayMsgTx, RelayTx, RngTx, useRngTxs } from '@hooks/useRngTxs' +import { BURN_ADDRESSES, QUERY_START_BLOCK } from '@constants/config' +import { DrawAwardTx, RngAuctionTx, useRngTxs } from '@hooks/useRngTxs' import { AreaChart } from './AreaChart' interface DataPoint { name: string - lp: { total: number; change: number } - manual: { total: number; change: number } + dead: { total: number; change: number } other: { total: number; change: number } } @@ -36,11 +35,10 @@ interface BurnChartProps { export const BurnChart = (props: BurnChartProps) => { const { prizePool, prizeToken, className } = props - const lpAddresses = VAULT_LPS[prizeToken.chainId] ?? [] - const miscBurnAddresses = BURN_ADDRESSES[prizeToken.chainId] ?? [] + const burnAddresses = BURN_ADDRESSES[prizeToken.chainId] ?? [] const { data: burnEvents } = useTransferEvents(prizeToken.chainId, prizeToken.address, { - to: [...lpAddresses, ...miscBurnAddresses, DEAD_ADDRESS], + to: [DEAD_ADDRESS, ...burnAddresses], fromBlock: QUERY_START_BLOCK[prizeToken.chainId] }) @@ -58,17 +56,16 @@ export const BurnChart = (props: BurnChartProps) => { return parseFloat(formatUnits(val, prizeToken.decimals)) } - const validRngTxs = rngTxs.filter((txs) => !!txs.relay.l2) as { - rng: RngTx - relay: { l1?: RelayMsgTx; l2: RelayTx } + const validRngTxs = rngTxs.filter((txs) => !!txs.drawAward) as { + rngAuction: RngAuctionTx + drawAward: DrawAwardTx }[] - const firstRngBlockNumber = validRngTxs[0]?.relay.l2.blockNumber ?? MAX_UINT_256 + const firstRngBlockNumber = validRngTxs[0]?.drawAward.blockNumber ?? MAX_UINT_256 const lastRngBlockNumber = - validRngTxs[validRngTxs.length - 1]?.relay.l2.blockNumber ?? MAX_UINT_256 + validRngTxs[validRngTxs.length - 1]?.drawAward.blockNumber ?? MAX_UINT_256 - let lp = { total: 0, change: 0 } - let manual = { total: 0, change: 0 } + let dead = { total: 0, change: 0 } let other = { total: 0, change: 0 } const updateBurnAmounts = (entryName: string, minBlock: bigint, maxBlock: bigint) => { @@ -77,41 +74,36 @@ export const BurnChart = (props: BurnChartProps) => { const toAddress = burnEvent.args.to.toLowerCase() as Lowercase
const burnAmount = formatBurnNum(burnEvent.args.value) - if (lpAddresses.includes(toAddress)) { - lp.change += burnAmount - } else if (toAddress === DEAD_ADDRESS) { - manual.change += burnAmount + if (toAddress === DEAD_ADDRESS) { + dead.change += burnAmount } else { other.change += burnAmount } } }) - lp.total += lp.change - manual.total += manual.change + dead.total += dead.change other.total += other.change data.push({ name: entryName, - lp: { total: lp.total, change: lp.change }, - manual: { total: manual.total, change: manual.change }, + dead: { total: dead.total, change: dead.change }, other: { total: other.total, change: other.change } }) - lp.change = 0 - manual.change = 0 + dead.change = 0 other.change = 0 } updateBurnAmounts(`Start-${firstDrawOpenedAt}`, 0n, firstRngBlockNumber) validRngTxs.forEach((txs, i) => { - const drawId = txs.rng.drawId - const closedAt = txs.relay.l2.timestamp - const minBlock = validRngTxs[i].relay.l2.blockNumber - const maxBlock = validRngTxs[i + 1]?.relay.l2.blockNumber ?? 0n + const drawId = txs.drawAward.drawId + const awardedAt = txs.drawAward.timestamp + const minBlock = validRngTxs[i].drawAward.blockNumber + const maxBlock = validRngTxs[i + 1]?.drawAward.blockNumber ?? 0n - updateBurnAmounts(`${drawId}-${closedAt}`, minBlock, maxBlock) + updateBurnAmounts(`${drawId}-${awardedAt}`, minBlock, maxBlock) }) updateBurnAmounts(`Now-${currentTimestamp}`, lastRngBlockNumber, MAX_UINT_256) @@ -126,8 +118,7 @@ export const BurnChart = (props: BurnChartProps) => { { legend={{ show: true, formatter: (id) => { - if (id === 'lp.total') { - return 'Prizes to LPs' - } else if (id === 'manual.total') { - return 'Manual Burns' + if (id === 'dead.total') { + return 'Sent to 0xdead' } else if (id === 'other.total') { return 'Other' } else { diff --git a/apps/analytics/src/components/Charts/DrawAvgClaimFeesChart.tsx b/apps/analytics/src/components/Charts/DrawAvgClaimFeesChart.tsx index 6c312dd2..96645331 100644 --- a/apps/analytics/src/components/Charts/DrawAvgClaimFeesChart.tsx +++ b/apps/analytics/src/components/Charts/DrawAvgClaimFeesChart.tsx @@ -1,7 +1,7 @@ import { PrizePool } from '@generationsoftware/hyperstructure-client-js' import { - useDrawAwardedEvents, - usePrizeDrawWinners + usePrizeDrawWinners, + usePrizePoolDrawAwardedEvents } from '@generationsoftware/hyperstructure-react-hooks' import { divideBigInts, @@ -32,10 +32,14 @@ export const DrawAvgClaimFeesChart = (props: DrawAvgClaimFeesChartProps) => { const { closedAt, awardedAt, finalizedAt } = useDrawStatus(prizePool, drawId) - const { data: drawAwardedEvents } = useDrawAwardedEvents(prizePool, { + const { data: drawAwardedEvents } = usePrizePoolDrawAwardedEvents(prizePool, { fromBlock: !!prizePool ? QUERY_START_BLOCK[prizePool.chainId] : undefined }) - const numTiers = drawAwardedEvents?.find((e) => e.args.drawId === drawId)?.args.numTiers + + const numTiers = useMemo(() => { + const drawAwardedEvent = drawAwardedEvents?.find((e) => e.args.drawId === drawId) + return drawAwardedEvent?.args.numTiers + }, [drawId, drawAwardedEvents]) const currentTimestamp = useAtomValue(currentTimestampAtom) diff --git a/apps/analytics/src/components/Charts/DrawsAvgClaimFeesChart.tsx b/apps/analytics/src/components/Charts/DrawsAvgClaimFeesChart.tsx index e4070c6a..3e560f22 100644 --- a/apps/analytics/src/components/Charts/DrawsAvgClaimFeesChart.tsx +++ b/apps/analytics/src/components/Charts/DrawsAvgClaimFeesChart.tsx @@ -1,7 +1,7 @@ import { PrizePool } from '@generationsoftware/hyperstructure-client-js' import { - useDrawAwardedEvents, - usePrizeDrawWinners + usePrizeDrawWinners, + usePrizePoolDrawAwardedEvents } from '@generationsoftware/hyperstructure-react-hooks' import { divideBigInts, formatNumberForDisplay } from '@shared/utilities' import classNames from 'classnames' @@ -20,7 +20,7 @@ export const DrawsAvgClaimFeesChart = (props: DrawsAvgClaimFeesChartProps) => { const { data: allDraws } = usePrizeDrawWinners(prizePool) - const { data: drawAwardedEvents } = useDrawAwardedEvents(prizePool, { + const { data: drawAwardedEvents } = usePrizePoolDrawAwardedEvents(prizePool, { fromBlock: !!prizePool ? QUERY_START_BLOCK[prizePool.chainId] : undefined }) @@ -33,6 +33,7 @@ export const DrawsAvgClaimFeesChart = (props: DrawsAvgClaimFeesChartProps) => { allDraws.forEach((draw) => { const numTiers = drawAwardedEvents?.find((e) => e.args.drawId === draw.id)?.args.numTiers + if (!!numTiers) { const wins = draw.prizeClaims.filter( (win) => diff --git a/apps/analytics/src/components/Charts/DrawsAvgLiqEfficiencyChart.tsx b/apps/analytics/src/components/Charts/DrawsAvgLiqEfficiencyChart.tsx index bfdbb8bd..83c5c44d 100644 --- a/apps/analytics/src/components/Charts/DrawsAvgLiqEfficiencyChart.tsx +++ b/apps/analytics/src/components/Charts/DrawsAvgLiqEfficiencyChart.tsx @@ -6,7 +6,7 @@ import { useLiquidationEvents, usePrizeTokenData } from '@generationsoftware/hyperstructure-react-hooks' -import { formatNumberForDisplay, NETWORK, POOL_TOKEN_ADDRESSES } from '@shared/utilities' +import { formatNumberForDisplay, NETWORK, WRAPPED_NATIVE_ASSETS } from '@shared/utilities' import classNames from 'classnames' import { useAtomValue } from 'jotai' import { useMemo } from 'react' @@ -45,13 +45,13 @@ export const DrawsAvgLiqEfficiencyChart = (props: DrawsAvgLiqEfficiencyChartProp allDrawsStatus?.map((draw) => draw.closedAt) ?? [] ) - // TODO: this assumes the tokenIn is always POOL (and uses mainnet pricing) - not ideal + // TODO: this assumes the tokenIn is always WETH (and uses mainnet pricing) - this will fail for the burn mechanism from the reserve - need fix const { data: prizeToken } = usePrizeTokenData(prizePool) const { data: tokenInPrices } = useHistoricalTokenPrices(NETWORK.mainnet, [ - POOL_TOKEN_ADDRESSES[NETWORK.mainnet] + WRAPPED_NATIVE_ASSETS[NETWORK.mainnet] as Address ]) const prizeTokenPrices = - tokenInPrices[POOL_TOKEN_ADDRESSES[NETWORK.mainnet].toLowerCase() as Address] + tokenInPrices[WRAPPED_NATIVE_ASSETS[NETWORK.mainnet]?.toLowerCase() as Address] const lpAddresses = useMemo(() => { const addresses = new Set
() diff --git a/apps/analytics/src/components/Charts/ReserveChart.tsx b/apps/analytics/src/components/Charts/ReserveChart.tsx index f799b17e..ddd8484d 100644 --- a/apps/analytics/src/components/Charts/ReserveChart.tsx +++ b/apps/analytics/src/components/Charts/ReserveChart.tsx @@ -14,7 +14,7 @@ import { formatUnits, Log } from 'viem' import { ReserveCard } from '@components/Reserve/ReserveCard' import { QUERY_START_BLOCK } from '@constants/config' import { useReserve } from '@hooks/useReserve' -import { RelayMsgTx, RelayTx, RngTx, useRngTxs } from '@hooks/useRngTxs' +import { DrawAwardTx, RngAuctionTx, useRngTxs } from '@hooks/useRngTxs' import { LineChart } from './LineChart' interface DataPoint { @@ -22,7 +22,7 @@ interface DataPoint { reserve: number liquidations: number manual: number - rngFees: number + rewards: number prizeBackstops: number } @@ -68,13 +68,15 @@ export const ReserveChart = (props: ReserveChartProps) => { return parseFloat(formatUnits(val, prizeToken.decimals)) } - const validRngTxs = rngTxs.filter((txs) => txs.rng.fee !== undefined && !!txs.relay.l2) as { - rng: Required - relay: { l1?: RelayMsgTx; l2: RelayTx } + const validRngTxs = rngTxs.filter( + (txs) => txs.rngAuction.reward !== undefined && !!txs.drawAward + ) as { + rngAuction: RngAuctionTx & { reward: bigint } + drawAward: DrawAwardTx }[] let minBlock = 0n - let maxBlock = validRngTxs[0]?.relay.l2.blockNumber + let maxBlock = validRngTxs[0]?.drawAward.blockNumber let prevReserve = 0 const isValidEvent = (event: Log) => { @@ -86,37 +88,37 @@ export const ReserveChart = (props: ReserveChartProps) => { reserve: 0, liquidations: 0, manual: 0, - rngFees: 0, + rewards: 0, prizeBackstops: 0 }) validRngTxs.forEach((txs, i) => { - const drawId = txs.rng.drawId - const closedAt = txs.relay.l2.timestamp - const name = `${drawId}-${closedAt}` - const rngFees = formatPrizeNum(txs.rng.fee + txs.relay.l2.fee) - const reserve = formatPrizeNum(txs.relay.l2.reserve) - const reserveAfterFees = reserve - rngFees + const drawId = txs.drawAward.drawId + const awardedAt = txs.drawAward.timestamp + const name = `${drawId}-${awardedAt}` + const rewards = formatPrizeNum(txs.rngAuction.reward + txs.drawAward.reward) + const reserve = formatPrizeNum(txs.drawAward.reserve) + const reserveAfterRewards = reserve - rewards const manual = formatPrizeNum( manualContributionEvents.reduce((a, b) => a + (isValidEvent(b) ? b.args.amount : 0n), 0n) ) const prizeBackstops = formatPrizeNum( prizeBackstopEvents.reduce((a, b) => a + (isValidEvent(b) ? b.args.amount : 0n), 0n) ) - const liquidations = reserveAfterFees - prevReserve - manual + rngFees + prizeBackstops + const liquidations = reserveAfterRewards - prevReserve - manual + rewards + prizeBackstops data.push({ name, - reserve: reserveAfterFees, + reserve: reserveAfterRewards, liquidations, manual, - rngFees, + rewards, prizeBackstops }) minBlock = maxBlock - maxBlock = validRngTxs[i + 1]?.relay.l2.blockNumber ?? MAX_UINT_256 - prevReserve = reserveAfterFees + maxBlock = validRngTxs[i + 1]?.drawAward.blockNumber ?? MAX_UINT_256 + prevReserve = reserveAfterRewards }) const currentReserve = formatPrizeNum(reserve.current) @@ -134,7 +136,7 @@ export const ReserveChart = (props: ReserveChartProps) => { reserve: currentReserve, liquidations: currentLiquidations, manual: currentManual, - rngFees: 0, + rewards: 0, prizeBackstops: currentPrizeBackstops }) diff --git a/apps/analytics/src/components/Draws/DrawAwardReward.tsx b/apps/analytics/src/components/Draws/DrawAwardReward.tsx new file mode 100644 index 00000000..0c9bd452 --- /dev/null +++ b/apps/analytics/src/components/Draws/DrawAwardReward.tsx @@ -0,0 +1,84 @@ +import { PrizePool } from '@generationsoftware/hyperstructure-client-js' +import { usePrizeTokenData } from '@generationsoftware/hyperstructure-react-hooks' +import { ExternalLink, Spinner } from '@shared/ui' +import { formatBigIntForDisplay, getBlockExplorerUrl, shorten } from '@shared/utilities' +import classNames from 'classnames' +import { useCurrentDrawAwardReward } from '@hooks/useCurrentDrawAwardReward' +import { useDrawStatus } from '@hooks/useDrawStatus' +import { useRngTxs } from '@hooks/useRngTxs' +import { DrawCardItemTitle } from './DrawCardItemTitle' + +interface DrawAwardRewardProps { + prizePool: PrizePool + drawId: number + className?: string +} + +export const DrawAwardReward = (props: DrawAwardRewardProps) => { + const { prizePool, drawId, className } = props + + const { status, isSkipped } = useDrawStatus(prizePool, drawId) + + const { data: allRngTxs, isFetched: isFetchedAllRngTxs } = useRngTxs(prizePool) + const rngTxs = allRngTxs?.find((txs) => txs.rngAuction.drawId === drawId) + const drawAwardTx = rngTxs?.drawAward + + const { data: prizeToken } = usePrizeTokenData(prizePool) + + const { data: currentDrawAwardReward } = useCurrentDrawAwardReward(prizePool) + + const isAwardPossible = status === 'closed' && !!currentDrawAwardReward && !isSkipped + + return ( +
+ + {isAwardPossible ? 'Current ' : ''} + Award Reward + +
+ {isFetchedAllRngTxs && !!prizeToken ? ( + <> + + {!!drawAwardTx ? ( + <> + + {formatBigIntForDisplay(drawAwardTx.reward, prizeToken.decimals, { + minimumFractionDigits: 2, + maximumFractionDigits: 2 + })} + {' '} + {prizeToken.symbol} + + ) : isAwardPossible ? ( + <> + {/* TODO: reduce opacity on this number? make it look temporary */} + + {formatBigIntForDisplay(currentDrawAwardReward, prizeToken.decimals, { + minimumFractionDigits: 2, + maximumFractionDigits: 2 + })} + {' '} + {prizeToken.symbol} + + ) : ( + - + )} + + {!!drawAwardTx ? ( + + {shorten(drawAwardTx.hash, { short: true })} + + ) : ( + isAwardPossible && Not Yet Awarded + )} + + ) : ( + + )} +
+
+ ) +} diff --git a/apps/analytics/src/components/Draws/DrawCard.tsx b/apps/analytics/src/components/Draws/DrawCard.tsx index 7cb7ee9a..31947871 100644 --- a/apps/analytics/src/components/Draws/DrawCard.tsx +++ b/apps/analytics/src/components/Draws/DrawCard.tsx @@ -1,11 +1,11 @@ import { PrizePool } from '@generationsoftware/hyperstructure-client-js' import classNames from 'classnames' import { useDrawStatus } from '@hooks/useDrawStatus' +import { DrawAwardReward } from './DrawAwardReward' import { DrawClaimFees } from './DrawClaimFees' import { DrawLiqEfficiency } from './DrawLiqEfficiency' import { DrawPrizes } from './DrawPrizes' -import { DrawRelayFee } from './DrawRelayFee' -import { DrawRngFee } from './DrawRngFee' +import { DrawRngReward } from './DrawRngReward' import { DrawStatus } from './DrawStatus' import { DrawTimer } from './DrawTimer' @@ -51,8 +51,8 @@ export const DrawCard = (props: DrawCardProps) => { /> - - + +
) } diff --git a/apps/analytics/src/components/Draws/DrawLiqEfficiency.tsx b/apps/analytics/src/components/Draws/DrawLiqEfficiency.tsx index c48a3afb..3a5f99b6 100644 --- a/apps/analytics/src/components/Draws/DrawLiqEfficiency.tsx +++ b/apps/analytics/src/components/Draws/DrawLiqEfficiency.tsx @@ -6,7 +6,7 @@ import { usePrizeTokenData } from '@generationsoftware/hyperstructure-react-hooks' import { ExternalLink, Spinner } from '@shared/ui' -import { getBlockExplorerUrl, NETWORK, POOL_TOKEN_ADDRESSES } from '@shared/utilities' +import { getBlockExplorerUrl, NETWORK, WRAPPED_NATIVE_ASSETS } from '@shared/utilities' import classNames from 'classnames' import { useAtomValue } from 'jotai' import { useMemo } from 'react' @@ -38,14 +38,14 @@ export const DrawLiqEfficiency = (props: DrawLiqEfficiencyProps) => { const { data: openedAtBlock } = useBlockAtTimestamp(prizePool?.chainId, openedAt as number) const { data: closedAtBlock } = useBlockAtTimestamp(prizePool?.chainId, closedAt as number) - // TODO: this assumes the tokenIn is always POOL (and uses mainnet pricing) - not ideal + // TODO: this assumes the tokenIn is always WETH (and uses mainnet pricing) - will break with burn mechanism from reserve - need fix const { data: prizeToken } = usePrizeTokenData(prizePool) const { data: tokenInPrices, isFetched: isFetchedTokenInPrices } = useHistoricalTokenPrices( NETWORK.mainnet, - [POOL_TOKEN_ADDRESSES[NETWORK.mainnet]] + [WRAPPED_NATIVE_ASSETS[NETWORK.mainnet] as Address] ) const prizeTokenPrices = - tokenInPrices[POOL_TOKEN_ADDRESSES[NETWORK.mainnet].toLowerCase() as Address] + tokenInPrices[WRAPPED_NATIVE_ASSETS[NETWORK.mainnet]?.toLowerCase() as Address] const drawLiquidationEvents = useMemo(() => { if (!!liquidationEvents?.length && isFetchedDrawStatus && !!openedAtBlock && !!closedAtBlock) { diff --git a/apps/analytics/src/components/Draws/DrawPrizes.tsx b/apps/analytics/src/components/Draws/DrawPrizes.tsx index 4a07c3e1..c6e67d2f 100644 --- a/apps/analytics/src/components/Draws/DrawPrizes.tsx +++ b/apps/analytics/src/components/Draws/DrawPrizes.tsx @@ -1,12 +1,12 @@ import { PrizePool } from '@generationsoftware/hyperstructure-client-js' import { - useDrawAwardedEvents, - usePrizeDrawWinners + usePrizeDrawWinners, + usePrizePoolDrawAwardedEvents } from '@generationsoftware/hyperstructure-react-hooks' import { Spinner } from '@shared/ui' import { formatNumberForDisplay, sToMs } from '@shared/utilities' import classNames from 'classnames' -import { ReactNode } from 'react' +import { ReactNode, useMemo } from 'react' import { QUERY_START_BLOCK } from '@constants/config' import { useDrawResults } from '@hooks/useDrawResults' import { DrawCardItemTitle } from './DrawCardItemTitle' @@ -20,12 +20,15 @@ interface DrawPrizesProps { export const DrawPrizes = (props: DrawPrizesProps) => { const { prizePool, drawId, className } = props - const { data: drawAwardedEvents, isFetched: isFetchedDrawAwardedEvents } = useDrawAwardedEvents( - prizePool, - { fromBlock: !!prizePool ? QUERY_START_BLOCK[prizePool.chainId] : undefined } - ) - const drawAwardedEvent = drawAwardedEvents?.find((e) => e.args.drawId === drawId) - const numTiers = drawAwardedEvent?.args.numTiers + const { data: drawAwardedEvents, isFetched: isFetchedDrawAwardedEvents } = + usePrizePoolDrawAwardedEvents(prizePool, { + fromBlock: !!prizePool ? QUERY_START_BLOCK[prizePool.chainId] : undefined + }) + + const numTiers = useMemo(() => { + const drawAwardedEvent = drawAwardedEvents?.find((e) => e.args.drawId === drawId) + return drawAwardedEvent?.args.numTiers + }, [drawId, drawAwardedEvents]) const { data: prizesAvailable } = useDrawResults(prizePool, drawId, { refetchInterval: sToMs(300) diff --git a/apps/analytics/src/components/Draws/DrawRelayFee.tsx b/apps/analytics/src/components/Draws/DrawRelayFee.tsx deleted file mode 100644 index 767dee1f..00000000 --- a/apps/analytics/src/components/Draws/DrawRelayFee.tsx +++ /dev/null @@ -1,118 +0,0 @@ -import { PrizePool } from '@generationsoftware/hyperstructure-client-js' -import { usePrizeTokenData } from '@generationsoftware/hyperstructure-react-hooks' -import { ExternalLink, Spinner } from '@shared/ui' -import { - formatBigIntForDisplay, - getBlockExplorerUrl, - RNG_RELAY_ADDRESSES, - shorten -} from '@shared/utilities' -import classNames from 'classnames' -import { formatUnits } from 'viem' -import { useDrawRelayFeePercentage } from '@hooks/useDrawRelayFeePercentage' -import { useDrawStatus } from '@hooks/useDrawStatus' -import { useRngTxs } from '@hooks/useRngTxs' -import { DrawCardItemTitle } from './DrawCardItemTitle' - -interface DrawRelayFeeProps { - prizePool: PrizePool - drawId: number - className?: string -} - -export const DrawRelayFee = (props: DrawRelayFeeProps) => { - const { prizePool, drawId, className } = props - - const { status, isSkipped } = useDrawStatus(prizePool, drawId) - - const { data: allRngTxs, isFetched: isFetchedAllRngTxs } = useRngTxs(prizePool) - const rngTxs = allRngTxs?.find((txs) => txs.rng.drawId === drawId) - const relayMsgTx = rngTxs?.relay.l1 - const relayTx = rngTxs?.relay.l2 - - const rngTxFeeFraction = !!rngTxs - ? parseFloat(formatUnits(rngTxs.rng.feeFraction, 18)) - : undefined - - const { data: prizeToken } = usePrizeTokenData(prizePool) - - const { data: currentFeePercentage } = useDrawRelayFeePercentage(prizePool) - - const canBeRelayed = - status === 'closed' && !!currentFeePercentage && !!rngTxFeeFraction && !isSkipped - - return ( -
- - {canBeRelayed ? 'Current ' : ''} - Relay Fee - -
- {isFetchedAllRngTxs && !!prizeToken ? ( - <> - - {!!relayTx ? ( - <> - - {formatBigIntForDisplay(relayTx.fee, prizeToken.decimals, { - minimumFractionDigits: 2, - maximumFractionDigits: 2 - })} - {' '} - {prizeToken.symbol}{' '} - {!!relayTx.feeFraction && ( - <> - ( - {formatBigIntForDisplay(relayTx.feeFraction, 16, { - maximumSignificantDigits: 2 - })} - %) - - )} - - ) : canBeRelayed ? ( - <> - - {((1 - rngTxFeeFraction) * currentFeePercentage).toLocaleString(undefined, { - minimumFractionDigits: 2, - maximumFractionDigits: 2 - })} - - % - - ) : ( - - - )} - - {!!relayTx ? ( - <> - {!!relayMsgTx && ( - - {shorten(relayMsgTx.hash, { short: true })} - - )} - - {shorten(relayTx.hash, { short: true })} - - - ) : ( - canBeRelayed && Not Yet Awarded - )} - - ) : ( - - )} -
-
- ) -} diff --git a/apps/analytics/src/components/Draws/DrawRngFee.tsx b/apps/analytics/src/components/Draws/DrawRngReward.tsx similarity index 52% rename from apps/analytics/src/components/Draws/DrawRngFee.tsx rename to apps/analytics/src/components/Draws/DrawRngReward.tsx index 5ad4c587..28b8d27d 100644 --- a/apps/analytics/src/components/Draws/DrawRngFee.tsx +++ b/apps/analytics/src/components/Draws/DrawRngReward.tsx @@ -1,103 +1,83 @@ import { PrizePool } from '@generationsoftware/hyperstructure-client-js' import { usePrizeTokenData } from '@generationsoftware/hyperstructure-react-hooks' import { ExternalLink, Spinner } from '@shared/ui' -import { - formatBigIntForDisplay, - getBlockExplorerUrl, - RNG_RELAY_ADDRESSES, - shorten, - sToMs -} from '@shared/utilities' +import { formatBigIntForDisplay, getBlockExplorerUrl, shorten } from '@shared/utilities' import classNames from 'classnames' -import { useDrawRngFeePercentage } from '@hooks/useDrawRngFeePercentage' +import { useCurrentRngAuctionReward } from '@hooks/useCurrentRngAuctionReward' import { useDrawStatus } from '@hooks/useDrawStatus' import { useRngTxs } from '@hooks/useRngTxs' import { DrawCardItemTitle } from './DrawCardItemTitle' -interface DrawRngFeeProps { +interface DrawRngRewardProps { prizePool: PrizePool drawId: number className?: string } -export const DrawRngFee = (props: DrawRngFeeProps) => { +export const DrawRngReward = (props: DrawRngRewardProps) => { const { prizePool, drawId, className } = props const { status, isSkipped } = useDrawStatus(prizePool, drawId) const { data: allRngTxs, isFetched: isFetchedAllRngTxs } = useRngTxs(prizePool) - const rngTx = allRngTxs?.find((txs) => txs.rng.drawId === drawId)?.rng + const rngAuctionTx = allRngTxs?.find((txs) => txs.rngAuction.drawId === drawId)?.rngAuction const { data: prizeToken } = usePrizeTokenData(prizePool) - const { data: currentFeePercentage } = useDrawRngFeePercentage(prizePool, { - refetchInterval: sToMs(60) - }) + const { data: currentRngAuctionReward } = useCurrentRngAuctionReward(prizePool) - const canBeAwarded = status === 'closed' && !!currentFeePercentage && !isSkipped + const isRngCompletionPossible = status === 'closed' && !!currentRngAuctionReward && !isSkipped return (
- {canBeAwarded ? 'Current ' : ''}RNG Fee + {isRngCompletionPossible ? 'Current ' : ''}RNG Reward
{isFetchedAllRngTxs && !!prizeToken ? ( <> - {!!rngTx ? ( + {!!rngAuctionTx ? ( <> - {!!rngTx.fee ? ( + {!!rngAuctionTx.reward ? ( <> - {formatBigIntForDisplay(rngTx.fee, prizeToken.decimals, { + {formatBigIntForDisplay(rngAuctionTx.reward, prizeToken.decimals, { minimumFractionDigits: 2, maximumFractionDigits: 2 })} {' '} - {prizeToken.symbol} ( - {formatBigIntForDisplay(rngTx.feeFraction, 16, { - maximumSignificantDigits: 2 - })} - %) + {prizeToken.symbol} ) : ( <> - - {formatBigIntForDisplay(rngTx.feeFraction, 16, { - minimumFractionDigits: 2, - maximumFractionDigits: 2 - })} - - % + {/* TODO: get last rng auction reward from draw manager to display here */} + ? )} - ) : canBeAwarded ? ( + ) : isRngCompletionPossible ? ( <> + {/* TODO: reduce opacity on this number? make it look temporary */} - {currentFeePercentage.toLocaleString(undefined, { + {formatBigIntForDisplay(currentRngAuctionReward, prizeToken.decimals, { minimumFractionDigits: 2, maximumFractionDigits: 2 })} - - % + {' '} + {prizeToken.symbol} ) : ( - )} - {!!rngTx ? ( + {!!rngAuctionTx ? ( - {shorten(rngTx.hash, { short: true })} + {shorten(rngAuctionTx.hash, { short: true })} ) : ( - canBeAwarded && Not Yet Awarded + isRngCompletionPossible && Not Yet Awarded )} ) : ( diff --git a/apps/analytics/src/components/Prizes/PrizesTable.tsx b/apps/analytics/src/components/Prizes/PrizesTable.tsx index d5a15864..93c24e28 100644 --- a/apps/analytics/src/components/Prizes/PrizesTable.tsx +++ b/apps/analytics/src/components/Prizes/PrizesTable.tsx @@ -1,13 +1,14 @@ import { PrizePool } from '@generationsoftware/hyperstructure-client-js' import { - useDrawAwardedEvents, usePrizeDrawWinners, + usePrizePoolDrawAwardedEvents, usePrizeTokenData } from '@generationsoftware/hyperstructure-react-hooks' import { Spinner } from '@shared/ui' import { sToMs } from '@shared/utilities' import classNames from 'classnames' import Image from 'next/image' +import { useMemo } from 'react' import { QUERY_START_BLOCK } from '@constants/config' import { useDrawResults } from '@hooks/useDrawResults' import { useDrawStatus } from '@hooks/useDrawStatus' @@ -39,12 +40,15 @@ export const PrizesTable = (props: PrizesTableProps) => { refetchInterval: sToMs(300) }) - const { data: drawAwardedEvents, isFetched: isFetchedDrawAwardedEvents } = useDrawAwardedEvents( - prizePool, - { fromBlock: !!prizePool ? QUERY_START_BLOCK[prizePool.chainId] : undefined } - ) - const drawAwardedEvent = drawAwardedEvents?.find((e) => e.args.drawId === drawId) - const numTiers = drawAwardedEvent?.args.numTiers ?? 0 + const { data: drawAwardedEvents, isFetched: isFetchedDrawAwardedEvents } = + usePrizePoolDrawAwardedEvents(prizePool, { + fromBlock: !!prizePool ? QUERY_START_BLOCK[prizePool.chainId] : undefined + }) + + const numTiers = useMemo(() => { + const drawAwardedEvent = drawAwardedEvents?.find((e) => e.args.drawId === drawId) + return drawAwardedEvent?.args.numTiers ?? 0 + }, [drawId, drawAwardedEvents]) const { data: prizeToken } = usePrizeTokenData(prizePool) diff --git a/apps/analytics/src/components/Reserve/ReserveCard.tsx b/apps/analytics/src/components/Reserve/ReserveCard.tsx index 212eecda..1d0ad96b 100644 --- a/apps/analytics/src/components/Reserve/ReserveCard.tsx +++ b/apps/analytics/src/components/Reserve/ReserveCard.tsx @@ -7,14 +7,14 @@ interface ReserveCardProps { reserve: number liquidations: number manual: number - rngFees: number + rewards: number prizeBackstops: number prizeToken: Token className?: string } export const ReserveCard = (props: ReserveCardProps) => { - const { name, reserve, liquidations, manual, rngFees, prizeBackstops, prizeToken, className } = + const { name, reserve, liquidations, manual, rewards, prizeBackstops, prizeToken, className } = props return ( @@ -31,12 +31,12 @@ export const ReserveCard = (props: ReserveCardProps) => { token={prizeToken} /> - +
diff --git a/apps/analytics/src/hooks/useCurrentDrawAwardReward.tsx b/apps/analytics/src/hooks/useCurrentDrawAwardReward.tsx index be3c8b0d..26739244 100644 --- a/apps/analytics/src/hooks/useCurrentDrawAwardReward.tsx +++ b/apps/analytics/src/hooks/useCurrentDrawAwardReward.tsx @@ -2,7 +2,6 @@ import { PrizePool } from '@generationsoftware/hyperstructure-client-js' import { NO_REFETCH } from '@shared/generic-react-hooks' import { drawManagerABI } from '@shared/utilities' import { useQuery } from '@tanstack/react-query' -import { formatUnits } from 'viem' import { usePublicClient } from 'wagmi' export const useCurrentDrawAwardReward = ( @@ -16,13 +15,12 @@ export const useCurrentDrawAwardReward = ( queryFn: async () => { if (!!publicClient) { const drawManagerAddress = await prizePool.getDrawManagerAddress() - const rewardFraction = await publicClient.readContract({ + + return await publicClient.readContract({ address: drawManagerAddress, abi: drawManagerABI, functionName: 'awardDrawFee' }) - - return parseFloat(formatUnits(rewardFraction, 18)) * 100 } }, enabled: !!publicClient, diff --git a/apps/analytics/src/hooks/useCurrentRngAuctionReward.tsx b/apps/analytics/src/hooks/useCurrentRngAuctionReward.tsx index 718b6894..6092fd4d 100644 --- a/apps/analytics/src/hooks/useCurrentRngAuctionReward.tsx +++ b/apps/analytics/src/hooks/useCurrentRngAuctionReward.tsx @@ -2,7 +2,6 @@ import { PrizePool } from '@generationsoftware/hyperstructure-client-js' import { NO_REFETCH } from '@shared/generic-react-hooks' import { drawManagerABI } from '@shared/utilities' import { useQuery } from '@tanstack/react-query' -import { formatUnits } from 'viem' import { usePublicClient } from 'wagmi' export const useCurrentRngAuctionReward = ( @@ -16,13 +15,12 @@ export const useCurrentRngAuctionReward = ( queryFn: async () => { if (!!publicClient) { const drawManagerAddress = await prizePool.getDrawManagerAddress() - const rewardFraction = await publicClient.readContract({ + + return await publicClient.readContract({ address: drawManagerAddress, abi: drawManagerABI, functionName: 'startDrawFee' }) - - return parseFloat(formatUnits(rewardFraction, 18)) * 100 } }, enabled: !!publicClient, From f07203121d87026fc028b3ec4859ba8f419938c6 Mon Sep 17 00:00:00 2001 From: Ncookiez Date: Wed, 28 Feb 2024 19:54:47 -0500 Subject: [PATCH 013/161] fixed shared component constants --- shared/react-components/constants.ts | 23 ++++++++--------------- 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/shared/react-components/constants.ts b/shared/react-components/constants.ts index 509af70b..dc9e00b3 100644 --- a/shared/react-components/constants.ts +++ b/shared/react-components/constants.ts @@ -53,13 +53,13 @@ export const TOKEN_LOGO_OVERRIDES: Record '0x9485aca5bbbe1667ad97c7fe7c4531a624c8b1ed': tokenLogoUrls.ageur, '0x4200000000000000000000000000000000000042': tokenLogoUrls.op }, - [NETWORK.optimism_sepolia]: { - [POOL_TOKEN_ADDRESSES[NETWORK.optimism_sepolia].toLowerCase()]: tokenLogoUrls.pool, - '0x8067f3cb6eef936256108ff19a05574b8ad99cf3': tokenLogoUrls.usdc, - '0xd590ec14364731b62265a5cc807164a17c6797d4': tokenLogoUrls.dai, - '0x1a188719711d62423abf1a4de7d8aa9014a39d73': tokenLogoUrls.gusd, - '0xa416ed51158c5616b997b785fa6d18f02d0458a8': tokenLogoUrls.weth, - '0x149e3b3bd69f1cfc1b42b6a6a152a42e38ceebf1': tokenLogoUrls.wbtc + [NETWORK.optimism_sepolia]: {}, + [NETWORK.optimism_goerli]: { + '0x3e5bc94a341481f742f5f573d341fa2540bc0992': tokenLogoUrls.usdc, + '0xf6cff71208ffcab13223b31b036f2801d5de6d17': tokenLogoUrls.dai, + '0xabddb2c18a5d02f26a5ad5f4a361e4814dbe2175': tokenLogoUrls.gusd, + '0x0ba5e0722797dcea8cec409a707ce495c33fb23d': tokenLogoUrls.weth, + '0x3fa21c64666d1245dbc1836ded2e4b47979c6bee': tokenLogoUrls.wbtc }, [NETWORK.avalanche]: { '0x2f2a2543b76a4166549f7aab2e75bef0aefc5b0f': tokenLogoUrls.wbtc @@ -68,14 +68,7 @@ export const TOKEN_LOGO_OVERRIDES: Record [NETWORK.celo]: {}, [NETWORK.celo_testnet]: {}, [NETWORK.arbitrum]: {}, - [NETWORK.arbitrum_sepolia]: { - [POOL_TOKEN_ADDRESSES[NETWORK.arbitrum_sepolia].toLowerCase()]: tokenLogoUrls.pool, - '0x7a6dbc7ff4f1a2d864291db3aec105a8eee4a3d2': tokenLogoUrls.usdc, - '0x08c19fe57af150a1af975cb9a38769848c7df98e': tokenLogoUrls.dai, - '0xb84460d777133a4b86540d557db35952e4adfee7': tokenLogoUrls.gusd, - '0x779275fc1b987db24463801f3708f42f3c6f6ceb': tokenLogoUrls.weth, - '0x1bc266e1f397517ece9e384c55c7a5414b683639': tokenLogoUrls.wbtc - }, + [NETWORK.arbitrum_sepolia]: {}, [NETWORK.base]: {}, [NETWORK.base_sepolia]: {} } From 9400c6cfd66ed1a07c94aac53ad5f2131cf8b4c3 Mon Sep 17 00:00:00 2001 From: Ncookiez Date: Wed, 28 Feb 2024 20:00:54 -0500 Subject: [PATCH 014/161] added op goerli icon --- shared/react-components/components/Icons/NetworkIcon.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/shared/react-components/components/Icons/NetworkIcon.tsx b/shared/react-components/components/Icons/NetworkIcon.tsx index 3a6d9309..a0477bf4 100644 --- a/shared/react-components/components/Icons/NetworkIcon.tsx +++ b/shared/react-components/components/Icons/NetworkIcon.tsx @@ -170,6 +170,7 @@ const icons = { [NETWORK.mumbai]: { svgIcon: PolygonIcon, iconBgColor: '#9f71ec' }, [NETWORK.optimism]: { svgIcon: OptimismIcon, iconBgColor: '#ff5a57' }, [NETWORK.optimism_sepolia]: { svgIcon: OptimismIcon, iconBgColor: '#ff5a57' }, + [NETWORK.optimism_goerli]: { svgIcon: OptimismIcon, iconBgColor: '#ff5a57' }, [NETWORK.arbitrum]: { svgIcon: ArbitrumIcon, iconBgColor: '#96bedc' }, [NETWORK.arbitrum_sepolia]: { svgIcon: ArbitrumIcon, iconBgColor: '#96bedc' } } From 3d918eeb48b9c6f976a1766183a9bdc06c7da589 Mon Sep 17 00:00:00 2001 From: Ncookiez Date: Thu, 29 Feb 2024 16:07:00 -0500 Subject: [PATCH 015/161] fixed subgraph queries --- shared/types/types/subgraph.ts | 8 ++++---- shared/utilities/utils/subgraph.ts | 24 ++++++++++++------------ 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/shared/types/types/subgraph.ts b/shared/types/types/subgraph.ts index 3df66da5..4d2a385f 100644 --- a/shared/types/types/subgraph.ts +++ b/shared/types/types/subgraph.ts @@ -7,8 +7,8 @@ export interface SubgraphDraw { tier: number prizeIndex: number payout: bigint - fee: bigint - feeRecipient: `0x${string}` + claimReward: bigint + claimRewardRecipient: `0x${string}` timestamp: number txHash: `0x${string}` }[] @@ -20,8 +20,8 @@ export interface SubgraphPrize { tier: number prizeIndex: number payout: bigint - fee: bigint - feeRecipient: `0x${string}` + claimReward: bigint + claimRewardRecipient: `0x${string}` timestamp: number txHash: `0x${string}` } diff --git a/shared/utilities/utils/subgraph.ts b/shared/utilities/utils/subgraph.ts index 6d1752de..a1cdbd3c 100644 --- a/shared/utilities/utils/subgraph.ts +++ b/shared/utilities/utils/subgraph.ts @@ -36,8 +36,8 @@ export const getSubgraphDraws = async ( tier prizeIndex payout - fee - feeRecipient + claimReward + claimRewardRecipient timestamp txHash } @@ -66,8 +66,8 @@ export const getSubgraphDraws = async ( tier: number prizeIndex: string payout: string - fee: string - feeRecipient: string + claimReward: string + claimRewardRecipient: string timestamp: string txHash: string }[] @@ -82,8 +82,8 @@ export const getSubgraphDraws = async ( tier: claim.tier, prizeIndex: parseInt(claim.prizeIndex), payout: BigInt(claim.payout), - fee: BigInt(claim.fee), - feeRecipient: claim.feeRecipient as Address, + claimReward: BigInt(claim.claimReward), + claimRewardRecipient: claim.claimRewardRecipient as Address, timestamp: parseInt(claim.timestamp), txHash: claim.txHash as `0x${string}` })) @@ -191,8 +191,8 @@ export const getUserSubgraphPrizes = async ( tier prizeIndex payout - fee - feeRecipient + claimReward + claimRewardRecipient timestamp txHash } @@ -214,8 +214,8 @@ export const getUserSubgraphPrizes = async ( tier: number prizeIndex: string payout: string - fee: string - feeRecipient: string + claimReward: string + claimRewardRecipient: string timestamp: string txHash: string }[] = jsonData?.data?.prizeClaims ?? [] @@ -226,8 +226,8 @@ export const getUserSubgraphPrizes = async ( tier: win.tier, prizeIndex: parseInt(win.prizeIndex), payout: BigInt(win.payout), - fee: BigInt(win.fee), - feeRecipient: win.feeRecipient as Address, + claimReward: BigInt(win.claimReward), + claimRewardRecipient: win.claimRewardRecipient as Address, timestamp: parseInt(win.timestamp), txHash: win.txHash as `0x${string}` })) From 78cef250f82fac2b2485a1b434839f8d5fcd6912 Mon Sep 17 00:00:00 2001 From: Ncookiez Date: Thu, 29 Feb 2024 16:07:21 -0500 Subject: [PATCH 016/161] added pool token on op goerli --- shared/utilities/constants.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/shared/utilities/constants.ts b/shared/utilities/constants.ts index 207ba44a..ce056284 100644 --- a/shared/utilities/constants.ts +++ b/shared/utilities/constants.ts @@ -31,7 +31,8 @@ export type NETWORK_NAME = keyof typeof NETWORK export const POOL_TOKEN_ADDRESSES = { [NETWORK.mainnet]: '0x0cEC1A9154Ff802e7934Fc916Ed7Ca50bDE6844e', [NETWORK.polygon]: '0x25788a1a171ec66Da6502f9975a15B609fF54CF6', - [NETWORK.optimism]: '0x395ae52bb17aef68c2888d941736a71dc6d4e125' + [NETWORK.optimism]: '0x395ae52bb17aef68c2888d941736a71dc6d4e125', + [NETWORK.optimism_goerli]: '0x80D4D92731ae0239c536E53001FF30D07D05f65B' } as const /** @@ -359,6 +360,11 @@ export const TOKEN_PRICE_REDIRECTS: { '0x0ba5e0722797dcea8cec409a707ce495c33fb23d': { chainId: NETWORK.optimism, address: WRAPPED_NATIVE_ASSETS[NETWORK.optimism] as Address + }, + /* POOL */ + '0x80d4d92731ae0239c536e53001ff30d07d05f65b': { + chainId: NETWORK.optimism, + address: POOL_TOKEN_ADDRESSES[NETWORK.optimism] } } } From 524692d787d1fa1631984cb0276e0c66a8ff2ec4 Mon Sep 17 00:00:00 2001 From: Ncookiez Date: Thu, 29 Feb 2024 16:09:01 -0500 Subject: [PATCH 017/161] canary and burn token fixes --- .../src/components/Burn/BurnCard.tsx | 14 +++---- .../src/components/Burn/BurnHeader.tsx | 16 ++++---- .../src/components/Burn/RecentBurnStats.tsx | 14 +++---- .../src/components/Charts/BurnChart.tsx | 16 ++++---- .../Charts/DrawAvgClaimFeesChart.tsx | 11 +++--- .../Charts/DrawsAvgClaimFeesChart.tsx | 9 +++-- apps/analytics/src/components/ClaimFees.tsx | 25 ++++++------ .../src/components/Draws/DrawAwardReward.tsx | 7 +--- .../src/components/Draws/DrawPrizes.tsx | 16 +++++--- .../src/components/Draws/DrawRngReward.tsx | 9 ++--- .../src/components/Prizes/PrizesTableRow.tsx | 30 +++++++++----- apps/analytics/src/utils.ts | 10 +++++ apps/analytics/src/views/BurnView.tsx | 39 ++++++++----------- apps/analytics/src/views/DrawsView.tsx | 17 +++----- apps/analytics/src/views/LiquidationsView.tsx | 15 ++----- apps/analytics/src/views/PrizesView.tsx | 16 +++----- apps/analytics/src/views/ReserveView.tsx | 15 ++----- .../hyperstructure-client-js/src/PrizePool.ts | 4 +- 18 files changed, 138 insertions(+), 145 deletions(-) diff --git a/apps/analytics/src/components/Burn/BurnCard.tsx b/apps/analytics/src/components/Burn/BurnCard.tsx index 66a592da..942123fd 100644 --- a/apps/analytics/src/components/Burn/BurnCard.tsx +++ b/apps/analytics/src/components/Burn/BurnCard.tsx @@ -6,12 +6,12 @@ interface BurnCardProps { name: string dead: { total: number; change: number } other: { total: number; change: number } - prizeToken: Token + burnToken: Token className?: string } export const BurnCard = (props: BurnCardProps) => { - const { name, dead, other, prizeToken, className } = props + const { name, dead, other, burnToken, className } = props return (
{ )} > {name} - - + +
@@ -50,8 +50,8 @@ interface BurnCardItemProps { const BurnCardItem = (props: BurnCardItemProps) => { const { name, total, change, token, alwaysShow, className, nameClassName, valueClassName } = props - const formattedTotal = formatNumberForDisplay(total, { maximumFractionDigits: 0 }) - const formattedChange = formatNumberForDisplay(change, { maximumFractionDigits: 0 }) + const formattedTotal = formatNumberForDisplay(total, { maximumFractionDigits: 2 }) + const formattedChange = formatNumberForDisplay(change, { maximumFractionDigits: 2 }) if (!!total || alwaysShow) { return ( diff --git a/apps/analytics/src/components/Burn/BurnHeader.tsx b/apps/analytics/src/components/Burn/BurnHeader.tsx index f2c0b27f..0dbb7e0a 100644 --- a/apps/analytics/src/components/Burn/BurnHeader.tsx +++ b/apps/analytics/src/components/Burn/BurnHeader.tsx @@ -7,18 +7,18 @@ import { useMemo } from 'react' import { BURN_ADDRESSES, QUERY_START_BLOCK } from '@constants/config' interface BurnHeaderProps { - prizeToken: Token + burnToken: Token className?: string } export const BurnHeader = (props: BurnHeaderProps) => { - const { prizeToken, className } = props + const { burnToken, className } = props - const burnAddresses = BURN_ADDRESSES[prizeToken.chainId] ?? [] + const burnAddresses = BURN_ADDRESSES[burnToken.chainId] ?? [] - const { data: burnTxs } = useTransferEvents(prizeToken.chainId, prizeToken.address, { + const { data: burnTxs } = useTransferEvents(burnToken.chainId, burnToken.address, { to: [DEAD_ADDRESS, ...burnAddresses], - fromBlock: QUERY_START_BLOCK[prizeToken.chainId] + fromBlock: QUERY_START_BLOCK[burnToken.chainId] }) const totalBurned = useMemo(() => { @@ -27,17 +27,17 @@ export const BurnHeader = (props: BurnHeaderProps) => { return (
- Total {prizeToken.symbol} Burned: + {burnToken.symbol} Burned: {totalBurned !== undefined ? ( <> 🔥 - {formatBigIntForDisplay(totalBurned, prizeToken.decimals, { + {formatBigIntForDisplay(totalBurned, burnToken.decimals, { hideZeroes: true })} - {prizeToken.symbol} + {burnToken.symbol} 🔥 ) : ( diff --git a/apps/analytics/src/components/Burn/RecentBurnStats.tsx b/apps/analytics/src/components/Burn/RecentBurnStats.tsx index 58431bf6..82ae47e5 100644 --- a/apps/analytics/src/components/Burn/RecentBurnStats.tsx +++ b/apps/analytics/src/components/Burn/RecentBurnStats.tsx @@ -7,20 +7,20 @@ import { Block } from 'viem' import { BURN_ADDRESSES, QUERY_START_BLOCK } from '@constants/config' interface RecentBurnStatsProps { - prizeToken: Token + burnToken: Token minBlock: Block label: string className?: string } export const RecentBurnStats = (props: RecentBurnStatsProps) => { - const { prizeToken, minBlock, label, className } = props + const { burnToken, minBlock, label, className } = props - const burnAddresses = BURN_ADDRESSES[prizeToken.chainId] ?? [] + const burnAddresses = BURN_ADDRESSES[burnToken.chainId] ?? [] - const { data: burnEvents } = useTransferEvents(prizeToken.chainId, prizeToken.address, { + const { data: burnEvents } = useTransferEvents(burnToken.chainId, burnToken.address, { to: [DEAD_ADDRESS, ...burnAddresses], - fromBlock: QUERY_START_BLOCK[prizeToken.chainId] + fromBlock: QUERY_START_BLOCK[burnToken.chainId] }) const burned = useMemo(() => { @@ -31,7 +31,7 @@ export const RecentBurnStats = (props: RecentBurnStatsProps) => { }, [burnEvents, minBlock]) if (!!burned) { - const formattedBurnedAmount = formatBigIntForDisplay(burned, prizeToken.decimals, { + const formattedBurnedAmount = formatBigIntForDisplay(burned, burnToken.decimals, { hideZeroes: true }) @@ -40,7 +40,7 @@ export const RecentBurnStats = (props: RecentBurnStatsProps) => { {label}: {formattedBurnedAmount} - {prizeToken.symbol} + {burnToken.symbol}
) diff --git a/apps/analytics/src/components/Charts/BurnChart.tsx b/apps/analytics/src/components/Charts/BurnChart.tsx index d4ccdd46..f4f275a9 100644 --- a/apps/analytics/src/components/Charts/BurnChart.tsx +++ b/apps/analytics/src/components/Charts/BurnChart.tsx @@ -28,18 +28,18 @@ interface DataPoint { interface BurnChartProps { prizePool: PrizePool - prizeToken: Token + burnToken: Token className?: string } export const BurnChart = (props: BurnChartProps) => { - const { prizePool, prizeToken, className } = props + const { prizePool, burnToken, className } = props - const burnAddresses = BURN_ADDRESSES[prizeToken.chainId] ?? [] + const burnAddresses = BURN_ADDRESSES[burnToken.chainId] ?? [] - const { data: burnEvents } = useTransferEvents(prizeToken.chainId, prizeToken.address, { + const { data: burnEvents } = useTransferEvents(burnToken.chainId, burnToken.address, { to: [DEAD_ADDRESS, ...burnAddresses], - fromBlock: QUERY_START_BLOCK[prizeToken.chainId] + fromBlock: QUERY_START_BLOCK[burnToken.chainId] }) const { data: rngTxs, isFetched: isFetchedRngTxs } = useRngTxs(prizePool) @@ -53,7 +53,7 @@ export const BurnChart = (props: BurnChartProps) => { const data: DataPoint[] = [] const formatBurnNum = (val: bigint) => { - return parseFloat(formatUnits(val, prizeToken.decimals)) + return parseFloat(formatUnits(val, burnToken.decimals)) } const validRngTxs = rngTxs.filter((txs) => !!txs.drawAward) as { @@ -129,7 +129,7 @@ export const BurnChart = (props: BurnChartProps) => { ) } else { @@ -141,7 +141,7 @@ export const BurnChart = (props: BurnChartProps) => { show: true, formatter: (id) => { if (id === 'dead.total') { - return 'Sent to 0xdead' + return 'Sent to 0xdEaD' } else if (id === 'other.total') { return 'Other' } else { diff --git a/apps/analytics/src/components/Charts/DrawAvgClaimFeesChart.tsx b/apps/analytics/src/components/Charts/DrawAvgClaimFeesChart.tsx index 96645331..80e5a0e7 100644 --- a/apps/analytics/src/components/Charts/DrawAvgClaimFeesChart.tsx +++ b/apps/analytics/src/components/Charts/DrawAvgClaimFeesChart.tsx @@ -13,6 +13,7 @@ import classNames from 'classnames' import { useAtomValue } from 'jotai' import { useMemo } from 'react' import { currentTimestampAtom } from 'src/atoms' +import { isCanaryTier } from 'src/utils' import { QUERY_START_BLOCK } from '@constants/config' import { useDrawStatus } from '@hooks/useDrawStatus' import { LineChart, LineChartProps } from './LineChart' @@ -69,9 +70,9 @@ export const DrawAvgClaimFeesChart = (props: DrawAvgClaimFeesChartProps) => { const filteredWins = drawWins.filter( (win) => - win.fee > 0n && - win.feeRecipient !== win.recipient && - (!hideCanary || win.tier !== numTiers - 1) + win.claimReward > 0n && + win.claimRewardRecipient !== win.recipient && + (!hideCanary || !isCanaryTier(win.tier, numTiers)) ) const tiers = new Set(filteredWins.map((win) => win.tier)) @@ -98,7 +99,7 @@ export const DrawAvgClaimFeesChart = (props: DrawAvgClaimFeesChartProps) => { ) checkpointWins.forEach((win) => { - cumTierValues[win.tier].sumClaimFeeAmount += win.fee + cumTierValues[win.tier].sumClaimFeeAmount += win.claimReward cumTierValues[win.tier].sumPrizeAmount += win.payout }) @@ -136,7 +137,7 @@ export const DrawAvgClaimFeesChart = (props: DrawAvgClaimFeesChartProps) => { show: true, formatter: (value, tier) => [ `${formatNumberForDisplay(value, { maximumFractionDigits: 2 })}%`, - tier === 0 ? 'GP' : tier === numTiers - 1 ? 'Canary' : `Tier ${tier}` + tier === 0 ? 'GP' : isCanaryTier(Number(tier), numTiers) ? 'Canary' : `Tier ${tier}` ], labelFormatter: (label) => getSimpleTime(Number(label)) }} diff --git a/apps/analytics/src/components/Charts/DrawsAvgClaimFeesChart.tsx b/apps/analytics/src/components/Charts/DrawsAvgClaimFeesChart.tsx index 3e560f22..54669bbd 100644 --- a/apps/analytics/src/components/Charts/DrawsAvgClaimFeesChart.tsx +++ b/apps/analytics/src/components/Charts/DrawsAvgClaimFeesChart.tsx @@ -6,6 +6,7 @@ import { import { divideBigInts, formatNumberForDisplay } from '@shared/utilities' import classNames from 'classnames' import { useMemo } from 'react' +import { isCanaryTier } from 'src/utils' import { QUERY_START_BLOCK } from '@constants/config' import { LineChart } from './LineChart' @@ -37,13 +38,13 @@ export const DrawsAvgClaimFeesChart = (props: DrawsAvgClaimFeesChartProps) => { if (!!numTiers) { const wins = draw.prizeClaims.filter( (win) => - win.fee > 0n && - win.feeRecipient !== win.recipient && - (!hideCanary || win.tier !== numTiers - 1) + win.claimReward > 0n && + win.claimRewardRecipient !== win.recipient && + (!hideCanary || !isCanaryTier(win.tier, numTiers)) ) if (!!wins.length) { - const sumClaimFeeAmount = wins.reduce((a, b) => a + b.fee, 0n) + const sumClaimFeeAmount = wins.reduce((a, b) => a + b.claimReward, 0n) const sumPrizeAmount = wins.reduce((a, b) => a + b.payout, 0n) const percentage = divideBigInts(sumClaimFeeAmount, sumPrizeAmount + sumClaimFeeAmount) * 100 diff --git a/apps/analytics/src/components/ClaimFees.tsx b/apps/analytics/src/components/ClaimFees.tsx index fc796d4c..9b001507 100644 --- a/apps/analytics/src/components/ClaimFees.tsx +++ b/apps/analytics/src/components/ClaimFees.tsx @@ -8,6 +8,7 @@ import { ExternalLink, Spinner } from '@shared/ui' import { divideBigInts, getBlockExplorerUrl, MAX_UINT_256 } from '@shared/utilities' import classNames from 'classnames' import { useMemo } from 'react' +import { isCanaryTier } from 'src/utils' import { QUERY_START_BLOCK } from '@constants/config' type Stat = { amount: bigint; percentage: number; txHash?: `0x${string}` } @@ -40,13 +41,11 @@ export const ClaimFees = (props: ClaimFeesProps) => { const filteredWins: SubgraphDraw['prizeClaims'] = [] if (!!draw) { draw.prizeClaims.forEach((prize) => { - const isValidTier = tier === undefined || prize.tier === tier - const isCanaryTier = !!numTiers ? prize.tier === numTiers - 1 : false if ( - prize.fee > 0n && - prize.feeRecipient !== prize.recipient && - isValidTier && - (!hideCanary || !isCanaryTier) + prize.claimReward > 0n && + prize.claimRewardRecipient !== prize.recipient && + (tier === undefined || prize.tier === tier) && + (!hideCanary || (!!numTiers && !isCanaryTier(prize.tier, numTiers))) ) { filteredWins.push(prize) } @@ -57,21 +56,25 @@ export const ClaimFees = (props: ClaimFeesProps) => { const claimFeeStats = useMemo(() => { if (wins.length > 0) { - const sumClaimFeeAmount = wins.reduce((a, b) => a + b.fee, 0n) + const sumClaimFeeAmount = wins.reduce((a, b) => a + b.claimReward, 0n) const sumPrizeAmount = wins.reduce((a, b) => a + b.payout, 0n) const high: Stat = wins.reduce( (a, b) => { - const percentage = divideBigInts(b.fee, b.payout + b.fee) * 100 - return a.percentage < percentage ? { amount: b.fee, percentage, txHash: b.txHash } : a + const percentage = divideBigInts(b.claimReward, b.payout + b.claimReward) * 100 + return a.percentage < percentage + ? { amount: b.claimReward, percentage, txHash: b.txHash } + : a }, { amount: 0n, percentage: 0 } ) const low: Stat = wins.reduce( (a, b) => { - const percentage = divideBigInts(b.fee, b.payout + b.fee) * 100 - return a.percentage > percentage ? { amount: b.fee, percentage, txHash: b.txHash } : a + const percentage = divideBigInts(b.claimReward, b.payout + b.claimReward) * 100 + return a.percentage > percentage + ? { amount: b.claimReward, percentage, txHash: b.txHash } + : a }, { amount: MAX_UINT_256, percentage: 100 } ) diff --git a/apps/analytics/src/components/Draws/DrawAwardReward.tsx b/apps/analytics/src/components/Draws/DrawAwardReward.tsx index 0c9bd452..bc30ba17 100644 --- a/apps/analytics/src/components/Draws/DrawAwardReward.tsx +++ b/apps/analytics/src/components/Draws/DrawAwardReward.tsx @@ -43,19 +43,16 @@ export const DrawAwardReward = (props: DrawAwardRewardProps) => { <> {formatBigIntForDisplay(drawAwardTx.reward, prizeToken.decimals, { - minimumFractionDigits: 2, - maximumFractionDigits: 2 + maximumFractionDigits: 5 })} {' '} {prizeToken.symbol} ) : isAwardPossible ? ( <> - {/* TODO: reduce opacity on this number? make it look temporary */} {formatBigIntForDisplay(currentDrawAwardReward, prizeToken.decimals, { - minimumFractionDigits: 2, - maximumFractionDigits: 2 + maximumFractionDigits: 5 })} {' '} {prizeToken.symbol} diff --git a/apps/analytics/src/components/Draws/DrawPrizes.tsx b/apps/analytics/src/components/Draws/DrawPrizes.tsx index c6e67d2f..658c10b0 100644 --- a/apps/analytics/src/components/Draws/DrawPrizes.tsx +++ b/apps/analytics/src/components/Draws/DrawPrizes.tsx @@ -7,6 +7,7 @@ import { Spinner } from '@shared/ui' import { formatNumberForDisplay, sToMs } from '@shared/utilities' import classNames from 'classnames' import { ReactNode, useMemo } from 'react' +import { isCanaryTier } from 'src/utils' import { QUERY_START_BLOCK } from '@constants/config' import { useDrawResults } from '@hooks/useDrawResults' import { DrawCardItemTitle } from './DrawCardItemTitle' @@ -35,19 +36,23 @@ export const DrawPrizes = (props: DrawPrizesProps) => { }) const nonCanaryPrizesAvailable = !!prizesAvailable && !!numTiers - ? prizesAvailable.filter((prize) => prize.tier !== numTiers - 1) + ? prizesAvailable.filter((prize) => !isCanaryTier(prize.tier, numTiers)) : [] const canaryPrizesAvailable = !!prizesAvailable && !!numTiers - ? prizesAvailable.filter((prize) => prize.tier === numTiers - 1) + ? prizesAvailable.filter((prize) => isCanaryTier(prize.tier, numTiers)) : [] const { data: allDraws, isFetched: isFetchedPrizeDrawWinners } = usePrizeDrawWinners(prizePool) const draw = allDraws?.find((d) => d.id === drawId) const nonCanaryPrizeClaims = - !!draw && !!numTiers ? draw.prizeClaims.filter((prize) => prize.tier !== numTiers - 1) : [] + !!draw && !!numTiers + ? draw.prizeClaims.filter((prize) => !isCanaryTier(prize.tier, numTiers)) + : [] const canaryPrizeClaims = - !!draw && !!numTiers ? draw.prizeClaims.filter((prize) => prize.tier === numTiers - 1) : [] + !!draw && !!numTiers + ? draw.prizeClaims.filter((prize) => isCanaryTier(prize.tier, numTiers)) + : [] const formattedCanaryPercentage = !!canaryPrizeClaims.length && !!canaryPrizesAvailable.length @@ -71,7 +76,8 @@ export const DrawPrizes = (props: DrawPrizesProps) => { )} {!!nonCanaryPrizesAvailable.length && ( - {nonCanaryPrizesAvailable.length} prizes + {nonCanaryPrizesAvailable.length} prize + {nonCanaryPrizesAvailable.length > 1 && 's'} )} {!!nonCanaryPrizeClaims.length && ( diff --git a/apps/analytics/src/components/Draws/DrawRngReward.tsx b/apps/analytics/src/components/Draws/DrawRngReward.tsx index 28b8d27d..9376bd0f 100644 --- a/apps/analytics/src/components/Draws/DrawRngReward.tsx +++ b/apps/analytics/src/components/Draws/DrawRngReward.tsx @@ -37,12 +37,11 @@ export const DrawRngReward = (props: DrawRngRewardProps) => { {!!rngAuctionTx ? ( <> - {!!rngAuctionTx.reward ? ( + {rngAuctionTx.reward !== undefined ? ( <> {formatBigIntForDisplay(rngAuctionTx.reward, prizeToken.decimals, { - minimumFractionDigits: 2, - maximumFractionDigits: 2 + maximumFractionDigits: 5 })} {' '} {prizeToken.symbol} @@ -56,11 +55,9 @@ export const DrawRngReward = (props: DrawRngRewardProps) => { ) : isRngCompletionPossible ? ( <> - {/* TODO: reduce opacity on this number? make it look temporary */} {formatBigIntForDisplay(currentRngAuctionReward, prizeToken.decimals, { - minimumFractionDigits: 2, - maximumFractionDigits: 2 + maximumFractionDigits: 5 })} {' '} {prizeToken.symbol} diff --git a/apps/analytics/src/components/Prizes/PrizesTableRow.tsx b/apps/analytics/src/components/Prizes/PrizesTableRow.tsx index 9109d6bd..51ab42a9 100644 --- a/apps/analytics/src/components/Prizes/PrizesTableRow.tsx +++ b/apps/analytics/src/components/Prizes/PrizesTableRow.tsx @@ -3,6 +3,7 @@ import { SubgraphDraw, Token } from '@shared/types' import { formatBigIntForDisplay, getTimeBreakdown } from '@shared/utilities' import classNames from 'classnames' import { useMemo } from 'react' +import { isCanaryTier } from 'src/utils' import { ClaimFees } from '@components/ClaimFees' import { prizesHeaders } from './PrizesTable' @@ -38,7 +39,13 @@ export const PrizesTableRow = (props: PrizesTableRowProps) => { - +
) @@ -57,7 +64,7 @@ const PrizeTier = (props: PrizeTierProps) => { {tier === 0 ? ( 'GP' - ) : tier === numTiers - 1 ? ( + ) : tier >= numTiers - 2 ? ( 'Canary' ) : ( <> @@ -150,21 +157,26 @@ interface PrizeFeesProps { prizePool: PrizePool drawId: number tier: number + numTiers: number className?: string } const PrizeFees = (props: PrizeFeesProps) => { - const { prizePool, drawId, tier, className } = props + const { prizePool, drawId, tier, numTiers, className } = props return (
{prizesHeaders.fees} - + {isCanaryTier(tier, numTiers) ? ( + - + ) : ( + + )}
) } diff --git a/apps/analytics/src/utils.ts b/apps/analytics/src/utils.ts index fa14a9f2..4712638d 100644 --- a/apps/analytics/src/utils.ts +++ b/apps/analytics/src/utils.ts @@ -66,3 +66,13 @@ const isL2TransactionReceipt = ( let receipt = txReceipt as L2TransactionReceipt return !!receipt.l1GasUsed && !!receipt.l1GasPrice && !!receipt.l1FeeScalar } + +/** + * Returns true if the tier is a canary tier + * @param tier the tier to check + * @param numTiers the total number of tiers in a given draw + * @returns + */ +export const isCanaryTier = (tier: number, numTiers: number) => { + return tier >= numTiers - 2 +} diff --git a/apps/analytics/src/views/BurnView.tsx b/apps/analytics/src/views/BurnView.tsx index 98a3425e..fdb99d20 100644 --- a/apps/analytics/src/views/BurnView.tsx +++ b/apps/analytics/src/views/BurnView.tsx @@ -1,14 +1,11 @@ import { PrizePool } from '@generationsoftware/hyperstructure-client-js' -import { - useBlockAtTimestamp, - usePrizeTokenData -} from '@generationsoftware/hyperstructure-react-hooks' -import { PRIZE_POOLS, SECONDS_PER_DAY } from '@shared/utilities' +import { useBlockAtTimestamp, useToken } from '@generationsoftware/hyperstructure-react-hooks' +import { POOL_TOKEN_ADDRESSES, PRIZE_POOLS, SECONDS_PER_DAY } from '@shared/utilities' import classNames from 'classnames' import { useAtomValue } from 'jotai' import { useMemo } from 'react' import { currentTimestampAtom } from 'src/atoms' -import { Address, PublicClient } from 'viem' +import { PublicClient } from 'viem' import { usePublicClient } from 'wagmi' import { BurnHeader } from '@components/Burn/BurnHeader' import { RecentBurnStats } from '@components/Burn/RecentBurnStats' @@ -27,16 +24,9 @@ export const BurnView = (props: BurnViewProps) => { const currentTimestamp = useAtomValue(currentTimestampAtom) const prizePool = useMemo(() => { - const prizePoolInfo = PRIZE_POOLS.find((pool) => pool.chainId === chainId) as { - chainId: number - address: Address - options: { - prizeTokenAddress: Address - drawPeriodInSeconds: number - tierShares: number - reserveShares: number - } - } + const prizePoolInfo = PRIZE_POOLS.find( + (pool) => pool.chainId === chainId + ) as (typeof PRIZE_POOLS)[number] return new PrizePool( prizePoolInfo.chainId, @@ -46,8 +36,6 @@ export const BurnView = (props: BurnViewProps) => { ) }, [chainId, publicClient]) - const { data: prizeToken } = usePrizeTokenData(prizePool) - const { data: minBlockDay } = useBlockAtTimestamp( prizePool.chainId, currentTimestamp - SECONDS_PER_DAY @@ -58,19 +46,24 @@ export const BurnView = (props: BurnViewProps) => { currentTimestamp - SECONDS_PER_DAY * 7 ) - if (!!prizeToken) { + const { data: burnToken } = useToken( + chainId, + POOL_TOKEN_ADDRESSES[prizePool.chainId as keyof typeof POOL_TOKEN_ADDRESSES] + ) + + if (!!prizePool && !!burnToken) { return (
- + {!!minBlockDay && ( - + )} {!!minBlockWeek && ( - + )}
- +
) } diff --git a/apps/analytics/src/views/DrawsView.tsx b/apps/analytics/src/views/DrawsView.tsx index 17574f00..63d224c3 100644 --- a/apps/analytics/src/views/DrawsView.tsx +++ b/apps/analytics/src/views/DrawsView.tsx @@ -7,7 +7,7 @@ import { import { PRIZE_POOLS, sToMs } from '@shared/utilities' import classNames from 'classnames' import { useEffect, useMemo } from 'react' -import { Address, PublicClient } from 'viem' +import { PublicClient } from 'viem' import { usePublicClient } from 'wagmi' import { DrawsAvgClaimFeesChart } from '@components/Charts/DrawsAvgClaimFeesChart' import { DrawsAvgLiqEfficiencyChart } from '@components/Charts/DrawsAvgLiqEfficiencyChart' @@ -27,16 +27,9 @@ export const DrawsView = (props: DrawsViewProps) => { const publicClient = usePublicClient({ chainId }) const prizePool = useMemo(() => { - const prizePoolInfo = PRIZE_POOLS.find((pool) => pool.chainId === chainId) as { - chainId: number - address: Address - options: { - prizeTokenAddress: Address - drawPeriodInSeconds: number - tierShares: number - reserveShares: number - } - } + const prizePoolInfo = PRIZE_POOLS.find( + (pool) => pool.chainId === chainId + ) as (typeof PRIZE_POOLS)[number] return new PrizePool( prizePoolInfo.chainId, @@ -77,7 +70,7 @@ export const DrawsView = (props: DrawsViewProps) => { return (
- +
diff --git a/apps/analytics/src/views/LiquidationsView.tsx b/apps/analytics/src/views/LiquidationsView.tsx index 91379e7a..ce64f1e1 100644 --- a/apps/analytics/src/views/LiquidationsView.tsx +++ b/apps/analytics/src/views/LiquidationsView.tsx @@ -8,7 +8,7 @@ import classNames from 'classnames' import { useAtom } from 'jotai' import { useEffect, useMemo } from 'react' import { currentTimestampAtom } from 'src/atoms' -import { Address, PublicClient } from 'viem' +import { PublicClient } from 'viem' import { usePublicClient } from 'wagmi' import { LiquidationsTable } from '@components/Liquidations/LiquidationsTable' import { QUERY_START_BLOCK } from '@constants/config' @@ -26,16 +26,9 @@ export const LiquidationsView = (props: LiquidationsViewProps) => { const [currentTimestamp, setCurrentTimestamp] = useAtom(currentTimestampAtom) const prizePool = useMemo(() => { - const prizePoolInfo = PRIZE_POOLS.find((pool) => pool.chainId === chainId) as { - chainId: number - address: Address - options: { - prizeTokenAddress: Address - drawPeriodInSeconds: number - tierShares: number - reserveShares: number - } - } + const prizePoolInfo = PRIZE_POOLS.find( + (pool) => pool.chainId === chainId + ) as (typeof PRIZE_POOLS)[number] return new PrizePool( prizePoolInfo.chainId, diff --git a/apps/analytics/src/views/PrizesView.tsx b/apps/analytics/src/views/PrizesView.tsx index 2666d8d9..d88923f8 100644 --- a/apps/analytics/src/views/PrizesView.tsx +++ b/apps/analytics/src/views/PrizesView.tsx @@ -9,7 +9,7 @@ import classNames from 'classnames' import { useAtomValue } from 'jotai' import { useEffect, useMemo } from 'react' import { selectedDrawIdAtom } from 'src/atoms' -import { Address, PublicClient } from 'viem' +import { PublicClient } from 'viem' import { usePublicClient } from 'wagmi' import { DrawAvgClaimFeesChart } from '@components/Charts/DrawAvgClaimFeesChart' import { DrawSelector } from '@components/Draws/DrawSelector' @@ -28,16 +28,9 @@ export const PrizesView = (props: PrizesViewProps) => { const publicClient = usePublicClient({ chainId }) const prizePool = useMemo(() => { - const prizePoolInfo = PRIZE_POOLS.find((pool) => pool.chainId === chainId) as { - chainId: number - address: Address - options: { - prizeTokenAddress: Address - drawPeriodInSeconds: number - tierShares: number - reserveShares: number - } - } + const prizePoolInfo = PRIZE_POOLS.find( + (pool) => pool.chainId === chainId + ) as (typeof PRIZE_POOLS)[number] return new PrizePool( prizePoolInfo.chainId, @@ -81,6 +74,7 @@ export const PrizesView = (props: PrizesViewProps) => { diff --git a/apps/analytics/src/views/ReserveView.tsx b/apps/analytics/src/views/ReserveView.tsx index 9f2c77ef..e4848eb2 100644 --- a/apps/analytics/src/views/ReserveView.tsx +++ b/apps/analytics/src/views/ReserveView.tsx @@ -12,7 +12,7 @@ import classNames from 'classnames' import { useSetAtom } from 'jotai' import { useEffect, useMemo } from 'react' import { currentTimestampAtom } from 'src/atoms' -import { Address, PublicClient } from 'viem' +import { PublicClient } from 'viem' import { usePublicClient } from 'wagmi' import { ReserveChart } from '@components/Charts/ReserveChart' import { ReserveHeader } from '@components/Reserve/ReserveHeader' @@ -32,16 +32,9 @@ export const ReserveView = (props: ReserveViewProps) => { const setCurrentTimestamp = useSetAtom(currentTimestampAtom) const prizePool = useMemo(() => { - const prizePoolInfo = PRIZE_POOLS.find((pool) => pool.chainId === chainId) as { - chainId: number - address: Address - options: { - prizeTokenAddress: Address - drawPeriodInSeconds: number - tierShares: number - reserveShares: number - } - } + const prizePoolInfo = PRIZE_POOLS.find( + (pool) => pool.chainId === chainId + ) as (typeof PRIZE_POOLS)[number] return new PrizePool( prizePoolInfo.chainId, diff --git a/packages/hyperstructure-client-js/src/PrizePool.ts b/packages/hyperstructure-client-js/src/PrizePool.ts index 69debca5..0f58225f 100644 --- a/packages/hyperstructure-client-js/src/PrizePool.ts +++ b/packages/hyperstructure-client-js/src/PrizePool.ts @@ -199,7 +199,7 @@ export class PrizePool { /** * Returns the number of prize tiers in the prize pool * - * NOTE: Includes the canary tier + * NOTE: Includes the canary tiers * @returns */ async getNumberOfTiers(): Promise { @@ -461,7 +461,7 @@ export class PrizePool { address: this.address, abi: prizePoolABI, functionName: 'estimatedPrizeCount', - args: [!!options?.includeCanary ? numberOfTiers : numberOfTiers - 1] + args: [!!options?.includeCanary ? numberOfTiers : numberOfTiers - 2] }) return estimatedPrizeCount From a429ca069c6fc57dcc2518b96e51d6aac7af25ec Mon Sep 17 00:00:00 2001 From: Ncookiez Date: Thu, 29 Feb 2024 16:09:25 -0500 Subject: [PATCH 018/161] draw status fixes (WIP) --- .../src/components/Draws/DrawStatusBadge.tsx | 4 ++-- .../src/components/Draws/DrawTimer.tsx | 15 +++++---------- apps/analytics/src/hooks/useAllDrawsStatus.tsx | 18 +++++++++++------- apps/analytics/src/hooks/useDrawResults.tsx | 11 ++++------- apps/analytics/src/hooks/useDrawStatus.tsx | 18 +++++++++++------- 5 files changed, 33 insertions(+), 33 deletions(-) diff --git a/apps/analytics/src/components/Draws/DrawStatusBadge.tsx b/apps/analytics/src/components/Draws/DrawStatusBadge.tsx index 3890e389..0546a096 100644 --- a/apps/analytics/src/components/Draws/DrawStatusBadge.tsx +++ b/apps/analytics/src/components/Draws/DrawStatusBadge.tsx @@ -23,11 +23,11 @@ export const DrawStatusBadge = (props: DrawStatusBadgeProps) => { className={classNames( 'w-full px-2 py-1 text-center text-xl rounded whitespace-nowrap', { + 'bg-pt-warning-light text-pt-warning-dark': isSkipped, 'bg-blue-100 text-blue-600': status === 'open', 'bg-yellow-100 text-yellow-500': status === 'closed' && !isSkipped, - 'bg-pt-warning-light text-pt-warning-dark': isSkipped, 'bg-pt-purple-200 text-pt-purple-600': status === 'awarded', - 'bg-green-100 text-green-600': status === 'finalized' + 'bg-green-100 text-green-600': status === 'finalized' && !isSkipped }, className )} diff --git a/apps/analytics/src/components/Draws/DrawTimer.tsx b/apps/analytics/src/components/Draws/DrawTimer.tsx index 759483fe..33707bdf 100644 --- a/apps/analytics/src/components/Draws/DrawTimer.tsx +++ b/apps/analytics/src/components/Draws/DrawTimer.tsx @@ -14,17 +14,12 @@ interface DrawTimerProps { export const DrawTimer = (props: DrawTimerProps) => { const { prizePool, drawId, className } = props - const { status, openedAt, closedAt, awardedAt, finalizedAt, isSkipped, isFetched } = - useDrawStatus(prizePool, drawId) + const { status, openedAt, closedAt, awardedAt, isSkipped, isFetched } = useDrawStatus( + prizePool, + drawId + ) - const timestamp = - status === 'finalized' - ? finalizedAt - : status === 'awarded' - ? awardedAt - : status === 'closed' - ? closedAt - : openedAt + const timestamp = status === 'awarded' ? awardedAt : status === 'closed' ? closedAt : openedAt const { days, hours, minutes } = useCountup(timestamp ?? 0) const _hours = days * 24 + hours diff --git a/apps/analytics/src/hooks/useAllDrawsStatus.tsx b/apps/analytics/src/hooks/useAllDrawsStatus.tsx index 5ab0b8c5..77ae5bdc 100644 --- a/apps/analytics/src/hooks/useAllDrawsStatus.tsx +++ b/apps/analytics/src/hooks/useAllDrawsStatus.tsx @@ -1,7 +1,7 @@ import { PrizePool } from '@generationsoftware/hyperstructure-client-js' import { useDrawPeriod, useFirstDrawOpenedAt } from '@generationsoftware/hyperstructure-react-hooks' import { DrawStatus } from '@shared/types' -import { getSecondsSinceEpoch, SECONDS_PER_HOUR } from '@shared/utilities' +import { getSecondsSinceEpoch } from '@shared/utilities' import { useMemo } from 'react' import { useRngTxs } from './useRngTxs' @@ -33,13 +33,13 @@ export const useAllDrawsStatus = (prizePool: PrizePool, drawIds: number[]) => { const openedAt = firstDrawOpenedAt + drawPeriod * (drawId - 1) const closedAt = openedAt + drawPeriod - const rngCompletedAt = rngTxs?.rngAuction.timestamp + // const rngCompletedAt = rngTxs?.rngAuction.timestamp const awardedAt = rngTxs?.drawAward?.timestamp const finalizedAt = closedAt + drawPeriod const isClosed = currentTime >= closedAt const isAwarded = !!awardedAt - const isFinalized = isAwarded && currentTime >= finalizedAt + const isFinalized = currentTime >= finalizedAt const status: DrawStatus = isFinalized ? 'finalized' @@ -49,10 +49,14 @@ export const useAllDrawsStatus = (prizePool: PrizePool, drawIds: number[]) => { ? 'closed' : 'open' - const relayAuctionClosesAt = !!rngCompletedAt - ? rngCompletedAt + SECONDS_PER_HOUR * 6 - : finalizedAt - const isSkipped = status === 'closed' && currentTime >= relayAuctionClosesAt + // TODO: check if old deployment logic still applies, and determine auction time after rng was completed + const relayAuctionClosesAt = finalizedAt + // const relayAuctionClosesAt = !!rngCompletedAt + // ? rngCompletedAt + SECONDS_PER_HOUR * 6 + // : finalizedAt + const isSkipped = + (status === 'finalized' && !isAwarded) || + (status === 'closed' && currentTime >= relayAuctionClosesAt) allDrawsStatus.push({ id: drawId, diff --git a/apps/analytics/src/hooks/useDrawResults.tsx b/apps/analytics/src/hooks/useDrawResults.tsx index f56869f5..aa23b9ad 100644 --- a/apps/analytics/src/hooks/useDrawResults.tsx +++ b/apps/analytics/src/hooks/useDrawResults.tsx @@ -12,11 +12,12 @@ export const useDrawResults = ( ) => { const queryKey = ['drawResults', prizePool?.chainId, drawId] - const { status, isFetched: isFetchedStatus } = useDrawStatus(prizePool, drawId) + const { status, isSkipped, isFetched: isFetchedStatus } = useDrawStatus(prizePool, drawId) - const isValidStatus = !!status && (status === 'awarded' || status === 'finalized') + const isValidStatus = + isFetchedStatus && !!status && !isSkipped && (status === 'awarded' || status === 'finalized') - const { data, isFetched: isFetchedDrawResults } = useQuery({ + return useQuery({ queryKey, queryFn: async () => { try { @@ -47,8 +48,4 @@ export const useDrawResults = ( ...NO_REFETCH, refetchInterval: !!status && status !== 'finalized' ? options?.refetchInterval ?? false : false }) - - const isFetched = isFetchedStatus && (status === 'open' || isFetchedDrawResults) - - return { data, isFetched } } diff --git a/apps/analytics/src/hooks/useDrawStatus.tsx b/apps/analytics/src/hooks/useDrawStatus.tsx index 7e47a16c..cf9c3f6c 100644 --- a/apps/analytics/src/hooks/useDrawStatus.tsx +++ b/apps/analytics/src/hooks/useDrawStatus.tsx @@ -1,7 +1,7 @@ import { PrizePool } from '@generationsoftware/hyperstructure-client-js' import { useDrawPeriod, useFirstDrawOpenedAt } from '@generationsoftware/hyperstructure-react-hooks' import { DrawStatus } from '@shared/types' -import { getSecondsSinceEpoch, SECONDS_PER_HOUR } from '@shared/utilities' +import { getSecondsSinceEpoch } from '@shared/utilities' import { useMemo } from 'react' import { useRngTxs } from './useRngTxs' @@ -23,14 +23,14 @@ export const useDrawStatus = (prizePool: PrizePool, drawId: number) => { const openedAt = firstDrawOpenedAt + drawPeriod * (drawId - 1) const closedAt = openedAt + drawPeriod - const rngCompletedAt = rngTxs?.rngAuction.timestamp + // const rngCompletedAt = rngTxs?.rngAuction.timestamp const awardedAt = rngTxs?.drawAward?.timestamp const finalizedAt = closedAt + drawPeriod const currentTime = getSecondsSinceEpoch() const isClosed = currentTime >= closedAt const isAwarded = !!awardedAt - const isFinalized = isAwarded && currentTime >= finalizedAt + const isFinalized = currentTime >= finalizedAt const status: DrawStatus = isFinalized ? 'finalized' @@ -40,10 +40,14 @@ export const useDrawStatus = (prizePool: PrizePool, drawId: number) => { ? 'closed' : 'open' - const relayAuctionClosesAt = !!rngCompletedAt - ? rngCompletedAt + SECONDS_PER_HOUR * 6 - : finalizedAt - const isSkipped = status === 'closed' && currentTime >= relayAuctionClosesAt + // TODO: check if old deployment logic still applies, and determine auction time after rng was completed + const relayAuctionClosesAt = finalizedAt + // const relayAuctionClosesAt = !!rngCompletedAt + // ? rngCompletedAt + SECONDS_PER_HOUR * 6 + // : finalizedAt + const isSkipped = + (status === 'finalized' && !isAwarded) || + (status === 'closed' && currentTime >= relayAuctionClosesAt) return { status, From a5f8b668ea78134be3ae7d4ec50e4372c3a9a731 Mon Sep 17 00:00:00 2001 From: Ncookiez Date: Thu, 29 Feb 2024 17:01:01 -0500 Subject: [PATCH 019/161] fixed reserve page --- .../src/components/Burn/BurnCard.tsx | 2 +- .../src/components/Charts/ReserveChart.tsx | 43 +++++++++++-------- .../src/components/Reserve/ReserveCard.tsx | 35 +++++++++------ .../src/components/Reserve/ReserveTooltip.tsx | 8 +--- apps/analytics/src/hooks/useRngTxs.tsx | 2 + apps/analytics/src/views/ReserveView.tsx | 12 ++++-- 6 files changed, 62 insertions(+), 40 deletions(-) diff --git a/apps/analytics/src/components/Burn/BurnCard.tsx b/apps/analytics/src/components/Burn/BurnCard.tsx index 942123fd..ee78e341 100644 --- a/apps/analytics/src/components/Burn/BurnCard.tsx +++ b/apps/analytics/src/components/Burn/BurnCard.tsx @@ -16,7 +16,7 @@ export const BurnCard = (props: BurnCardProps) => { return (
diff --git a/apps/analytics/src/components/Charts/ReserveChart.tsx b/apps/analytics/src/components/Charts/ReserveChart.tsx index ddd8484d..eb959de7 100644 --- a/apps/analytics/src/components/Charts/ReserveChart.tsx +++ b/apps/analytics/src/components/Charts/ReserveChart.tsx @@ -5,6 +5,7 @@ import { usePrizeBackstopEvents, usePrizeTokenData } from '@generationsoftware/hyperstructure-react-hooks' +import { Token } from '@shared/types' import { formatNumberForDisplay, getSimpleDate, MAX_UINT_256 } from '@shared/utilities' import classNames from 'classnames' import { useAtomValue } from 'jotai' @@ -24,15 +25,18 @@ interface DataPoint { manual: number rewards: number prizeBackstops: number + buyback: number } +// TODO: `burnToken` should be optional, and all logic within should function appropriately interface ReserveChartProps { prizePool: PrizePool + burnToken: Token className?: string } export const ReserveChart = (props: ReserveChartProps) => { - const { prizePool, className } = props + const { prizePool, burnToken, className } = props const { data: reserve } = useReserve(prizePool) @@ -77,7 +81,6 @@ export const ReserveChart = (props: ReserveChartProps) => { let minBlock = 0n let maxBlock = validRngTxs[0]?.drawAward.blockNumber - let prevReserve = 0 const isValidEvent = (event: Log) => { return event.blockNumber >= minBlock && event.blockNumber < maxBlock @@ -89,55 +92,58 @@ export const ReserveChart = (props: ReserveChartProps) => { liquidations: 0, manual: 0, rewards: 0, - prizeBackstops: 0 + prizeBackstops: 0, + buyback: 0 }) validRngTxs.forEach((txs, i) => { const drawId = txs.drawAward.drawId const awardedAt = txs.drawAward.timestamp const name = `${drawId}-${awardedAt}` - const rewards = formatPrizeNum(txs.rngAuction.reward + txs.drawAward.reward) - const reserve = formatPrizeNum(txs.drawAward.reserve) - const reserveAfterRewards = reserve - rewards + + // Inbound tokens const manual = formatPrizeNum( manualContributionEvents.reduce((a, b) => a + (isValidEvent(b) ? b.args.amount : 0n), 0n) ) + + // Outbound tokens + const rewards = formatPrizeNum(txs.rngAuction.reward + txs.drawAward.reward) const prizeBackstops = formatPrizeNum( prizeBackstopEvents.reduce((a, b) => a + (isValidEvent(b) ? b.args.amount : 0n), 0n) ) - const liquidations = reserveAfterRewards - prevReserve - manual + rewards + prizeBackstops + const buyback = formatPrizeNum(txs.drawAward.remainingReserve) + + // Calculated liquidation contributions + const liquidations = rewards + prizeBackstops + buyback - manual data.push({ name, - reserve: reserveAfterRewards, + reserve: 0, liquidations, manual, rewards, - prizeBackstops + prizeBackstops, + buyback }) minBlock = maxBlock maxBlock = validRngTxs[i + 1]?.drawAward.blockNumber ?? MAX_UINT_256 - prevReserve = reserveAfterRewards }) - const currentReserve = formatPrizeNum(reserve.current) + const currentPendingReserve = formatPrizeNum(reserve.pending) const currentManual = formatPrizeNum( manualContributionEvents.reduce((a, b) => a + (isValidEvent(b) ? b.args.amount : 0n), 0n) ) - const currentPrizeBackstops = formatPrizeNum( - prizeBackstopEvents.reduce((a, b) => a + (isValidEvent(b) ? b.args.amount : 0n), 0n) - ) - const currentLiquidations = - currentReserve - prevReserve - currentManual + currentPrizeBackstops + const currentLiquidations = currentPendingReserve - currentManual data.push({ name: `Now-${currentTimestamp}`, - reserve: currentReserve, + reserve: currentPendingReserve, liquidations: currentLiquidations, manual: currentManual, rewards: 0, - prizeBackstops: currentPrizeBackstops + prizeBackstops: 0, + buyback: 0 }) return data @@ -159,6 +165,7 @@ export const ReserveChart = (props: ReserveChartProps) => { {...(payload[0].payload as DataPoint)} name={formatTooltipLabel(label)} prizeToken={prizeToken} + burnToken={burnToken} /> ) } else { diff --git a/apps/analytics/src/components/Reserve/ReserveCard.tsx b/apps/analytics/src/components/Reserve/ReserveCard.tsx index 1d0ad96b..fb4a7ca8 100644 --- a/apps/analytics/src/components/Reserve/ReserveCard.tsx +++ b/apps/analytics/src/components/Reserve/ReserveCard.tsx @@ -9,34 +9,47 @@ interface ReserveCardProps { manual: number rewards: number prizeBackstops: number + buyback: number prizeToken: Token + burnToken: Token className?: string } export const ReserveCard = (props: ReserveCardProps) => { - const { name, reserve, liquidations, manual, rewards, prizeBackstops, prizeToken, className } = - props + const { + name, + reserve, + liquidations, + manual, + rewards, + prizeBackstops, + buyback, + prizeToken, + burnToken, + className + } = props return (
{name} + + + + 0 ? liquidations : 0} + name={`${burnToken.symbol} Buyback & Burn`} + amount={0 - buyback} token={prizeToken} /> - - -
@@ -75,9 +88,7 @@ const ReserveCardItem = (props: ReserveCardItemProps) => { amountClassName } = props - const formattedAmount = formatNumberForDisplay(amount, { - maximumFractionDigits: 2 - }) + const formattedAmount = formatNumberForDisplay(amount, { maximumFractionDigits: 5 }) if (!!amount || alwaysShow) { return ( diff --git a/apps/analytics/src/components/Reserve/ReserveTooltip.tsx b/apps/analytics/src/components/Reserve/ReserveTooltip.tsx index e6d5e9d5..a5986e0f 100644 --- a/apps/analytics/src/components/Reserve/ReserveTooltip.tsx +++ b/apps/analytics/src/components/Reserve/ReserveTooltip.tsx @@ -21,16 +21,12 @@ export const ReserveTooltip = (props: ReserveTooltipProps) => {
Current:{' '} - {formatBigIntForDisplay(reserve.current, token.decimals, { - maximumFractionDigits: 1 - })}{' '} + {formatBigIntForDisplay(reserve.current, token.decimals, { maximumFractionDigits: 5 })}{' '} {token.symbol} Open Draw:{' '} - {formatBigIntForDisplay(reserve.pending, token.decimals, { - maximumFractionDigits: 1 - })}{' '} + {formatBigIntForDisplay(reserve.pending, token.decimals, { maximumFractionDigits: 5 })}{' '} {token.symbol}
diff --git a/apps/analytics/src/hooks/useRngTxs.tsx b/apps/analytics/src/hooks/useRngTxs.tsx index 6efbf3ec..14e8149c 100644 --- a/apps/analytics/src/hooks/useRngTxs.tsx +++ b/apps/analytics/src/hooks/useRngTxs.tsx @@ -23,6 +23,7 @@ export interface DrawAwardTx { reward: bigint rewardRecipient: Address reserve: bigint + remainingReserve: bigint lastNumTiers: number numTiers: number hash: `0x${string}` @@ -101,6 +102,7 @@ export const useRngTxs = (prizePool: PrizePool) => { reward: drawManagerDrawAwardedEvent.args.awardReward, rewardRecipient: drawManagerDrawAwardedEvent.args.awardRecipient, reserve: prizePoolDrawAwardedEvent.args.reserve, + remainingReserve: drawManagerDrawAwardedEvent.args.remainingReserve, lastNumTiers: prizePoolDrawAwardedEvent.args.lastNumTiers, numTiers: prizePoolDrawAwardedEvent.args.numTiers, hash: prizePoolDrawAwardedEvent.transactionHash, diff --git a/apps/analytics/src/views/ReserveView.tsx b/apps/analytics/src/views/ReserveView.tsx index e4848eb2..4b5f589c 100644 --- a/apps/analytics/src/views/ReserveView.tsx +++ b/apps/analytics/src/views/ReserveView.tsx @@ -5,9 +5,10 @@ import { useManualContributionEvents, usePrizeBackstopEvents, usePrizePoolDrawAwardedEvents, - useRngAuctionCompletedEvents + useRngAuctionCompletedEvents, + useToken } from '@generationsoftware/hyperstructure-react-hooks' -import { getSecondsSinceEpoch, PRIZE_POOLS, sToMs } from '@shared/utilities' +import { getSecondsSinceEpoch, POOL_TOKEN_ADDRESSES, PRIZE_POOLS, sToMs } from '@shared/utilities' import classNames from 'classnames' import { useSetAtom } from 'jotai' import { useEffect, useMemo } from 'react' @@ -44,6 +45,11 @@ export const ReserveView = (props: ReserveViewProps) => { ) }, [chainId, publicClient]) + const { data: burnToken } = useToken( + chainId, + POOL_TOKEN_ADDRESSES[prizePool.chainId as keyof typeof POOL_TOKEN_ADDRESSES] + ) + const fromBlock = !!prizePool ? QUERY_START_BLOCK[prizePool.chainId] : undefined const { refetch: refetchReserve } = useReserve(prizePool) @@ -84,7 +90,7 @@ export const ReserveView = (props: ReserveViewProps) => { return (
- + {!!burnToken && }
) } From 8c8cddf0688dd0e73ea0bbca375b90fa2b89d108 Mon Sep 17 00:00:00 2001 From: Ncookiez Date: Fri, 1 Mar 2024 12:03:43 -0500 Subject: [PATCH 020/161] improved chainId selection redirects --- .../src/components/NetworkDropdown.tsx | 18 ++++-------------- apps/analytics/src/hooks/useValidNetworks.tsx | 17 +++++++++++++++++ apps/analytics/src/pages/[network]/burn.tsx | 19 +++++++++++-------- apps/analytics/src/pages/[network]/index.tsx | 19 +++++++++++-------- .../src/pages/[network]/liquidations.tsx | 19 +++++++++++-------- apps/analytics/src/pages/[network]/prizes.tsx | 19 +++++++++++-------- .../analytics/src/pages/[network]/reserve.tsx | 19 +++++++++++-------- 7 files changed, 76 insertions(+), 54 deletions(-) create mode 100644 apps/analytics/src/hooks/useValidNetworks.tsx diff --git a/apps/analytics/src/components/NetworkDropdown.tsx b/apps/analytics/src/components/NetworkDropdown.tsx index 661689b4..ab8dd42c 100644 --- a/apps/analytics/src/components/NetworkDropdown.tsx +++ b/apps/analytics/src/components/NetworkDropdown.tsx @@ -1,10 +1,10 @@ import { NetworkBadge } from '@shared/react-components' import { Dropdown, DropdownItem, Spinner } from '@shared/ui' -import { getNetworkNameByChainId, NETWORK, PRIZE_POOLS } from '@shared/utilities' +import { getNetworkNameByChainId, NETWORK } from '@shared/utilities' import { useRouter } from 'next/router' import { useMemo } from 'react' -import { SUPPORTED_NETWORKS } from '@constants/config' import { useSelectedChainId } from '@hooks/useSelectedChainId' +import { useValidNetworks } from '@hooks/useValidNetworks' export interface NetworkDropdownProps { className?: string @@ -15,6 +15,8 @@ export const NetworkDropdown = (props: NetworkDropdownProps) => { const router = useRouter() + const validNetworks = useValidNetworks() + const onChangeNetwork = (newNetwork: NETWORK) => { const currentPage = router.pathname.split('/')[2] ?? '' router.replace( @@ -22,18 +24,6 @@ export const NetworkDropdown = (props: NetworkDropdownProps) => { ) } - const validNetworks = useMemo(() => { - const networks = new Set() - const allSupportedNetworks = [...SUPPORTED_NETWORKS.mainnets, ...SUPPORTED_NETWORKS.testnets] - - allSupportedNetworks.forEach((network) => { - const prizePool = PRIZE_POOLS.find((prizePool) => prizePool.chainId === network) - !!prizePool && networks.add(network) - }) - - return [...networks] - }, []) - const dropdownItems: DropdownItem[] = useMemo(() => { return validNetworks.map((network) => ({ id: network.toString(), diff --git a/apps/analytics/src/hooks/useValidNetworks.tsx b/apps/analytics/src/hooks/useValidNetworks.tsx new file mode 100644 index 00000000..d445c0ec --- /dev/null +++ b/apps/analytics/src/hooks/useValidNetworks.tsx @@ -0,0 +1,17 @@ +import { NETWORK, PRIZE_POOLS } from '@shared/utilities' +import { useMemo } from 'react' +import { SUPPORTED_NETWORKS } from '@constants/config' + +export const useValidNetworks = () => { + return useMemo(() => { + const networks = new Set() + const allSupportedNetworks = [...SUPPORTED_NETWORKS.mainnets, ...SUPPORTED_NETWORKS.testnets] + + allSupportedNetworks.forEach((network) => { + const prizePool = PRIZE_POOLS.find((prizePool) => prizePool.chainId === network) + !!prizePool && networks.add(network) + }) + + return [...networks] + }, []) +} diff --git a/apps/analytics/src/pages/[network]/burn.tsx b/apps/analytics/src/pages/[network]/burn.tsx index 1f1224f6..c602db0d 100644 --- a/apps/analytics/src/pages/[network]/burn.tsx +++ b/apps/analytics/src/pages/[network]/burn.tsx @@ -1,16 +1,19 @@ -import { Spinner } from '@shared/ui' +import { useRouter } from 'next/router' +import { useEffect } from 'react' import { BurnView } from 'src/views/BurnView' import { Layout } from '@components/Layout' import { useSelectedChainId } from '@hooks/useSelectedChainId' export default function BurnPage() { + const router = useRouter() + const { chainId, isReady } = useSelectedChainId() - return ( - - {!isReady && } - {/* TODO: show some error message if invalid chainId */} - {isReady && (!!chainId ? : <>)} - - ) + useEffect(() => { + if (isReady && !chainId) { + router.replace('/burn') + } + }, [chainId, isReady]) + + return {!!chainId && } } diff --git a/apps/analytics/src/pages/[network]/index.tsx b/apps/analytics/src/pages/[network]/index.tsx index f79b83df..8c56dcfb 100644 --- a/apps/analytics/src/pages/[network]/index.tsx +++ b/apps/analytics/src/pages/[network]/index.tsx @@ -1,16 +1,19 @@ -import { Spinner } from '@shared/ui' +import { useRouter } from 'next/router' +import { useEffect } from 'react' import { DrawsView } from 'src/views/DrawsView' import { Layout } from '@components/Layout' import { useSelectedChainId } from '@hooks/useSelectedChainId' export default function DrawsPage() { + const router = useRouter() + const { chainId, isReady } = useSelectedChainId() - return ( - - {!isReady && } - {/* TODO: show some error message if invalid chainId */} - {isReady && (!!chainId ? : <>)} - - ) + useEffect(() => { + if (isReady && !chainId) { + router.replace('/') + } + }, [chainId, isReady]) + + return {!!chainId && } } diff --git a/apps/analytics/src/pages/[network]/liquidations.tsx b/apps/analytics/src/pages/[network]/liquidations.tsx index 62a3b31c..1fa856ca 100644 --- a/apps/analytics/src/pages/[network]/liquidations.tsx +++ b/apps/analytics/src/pages/[network]/liquidations.tsx @@ -1,16 +1,19 @@ -import { Spinner } from '@shared/ui' +import { useRouter } from 'next/router' +import { useEffect } from 'react' import { LiquidationsView } from 'src/views/LiquidationsView' import { Layout } from '@components/Layout' import { useSelectedChainId } from '@hooks/useSelectedChainId' export default function LiquidationsPage() { + const router = useRouter() + const { chainId, isReady } = useSelectedChainId() - return ( - - {!isReady && } - {/* TODO: show some error message if invalid chainId */} - {isReady && (!!chainId ? : <>)} - - ) + useEffect(() => { + if (isReady && !chainId) { + router.replace('/liquidations') + } + }, [chainId, isReady]) + + return {!!chainId && } } diff --git a/apps/analytics/src/pages/[network]/prizes.tsx b/apps/analytics/src/pages/[network]/prizes.tsx index 030d8f9f..febc8d0e 100644 --- a/apps/analytics/src/pages/[network]/prizes.tsx +++ b/apps/analytics/src/pages/[network]/prizes.tsx @@ -1,16 +1,19 @@ -import { Spinner } from '@shared/ui' +import { useRouter } from 'next/router' +import { useEffect } from 'react' import { PrizesView } from 'src/views/PrizesView' import { Layout } from '@components/Layout' import { useSelectedChainId } from '@hooks/useSelectedChainId' export default function PrizesPage() { + const router = useRouter() + const { chainId, isReady } = useSelectedChainId() - return ( - - {!isReady && } - {/* TODO: show some error message if invalid chainId */} - {isReady && (!!chainId ? : <>)} - - ) + useEffect(() => { + if (isReady && !chainId) { + router.replace('/prizes') + } + }, [chainId, isReady]) + + return {!!chainId && } } diff --git a/apps/analytics/src/pages/[network]/reserve.tsx b/apps/analytics/src/pages/[network]/reserve.tsx index 928b5935..d5c2f466 100644 --- a/apps/analytics/src/pages/[network]/reserve.tsx +++ b/apps/analytics/src/pages/[network]/reserve.tsx @@ -1,16 +1,19 @@ -import { Spinner } from '@shared/ui' +import { useRouter } from 'next/router' +import { useEffect } from 'react' import { ReserveView } from 'src/views/ReserveView' import { Layout } from '@components/Layout' import { useSelectedChainId } from '@hooks/useSelectedChainId' export default function ReservePage() { + const router = useRouter() + const { chainId, isReady } = useSelectedChainId() - return ( - - {!isReady && } - {/* TODO: show some error message if invalid chainId */} - {isReady && (!!chainId ? : <>)} - - ) + useEffect(() => { + if (isReady && !chainId) { + router.replace('/reserve') + } + }, [chainId, isReady]) + + return {!!chainId && } } From f00ca7cc8866c773ea01754ac463d420d21b57a3 Mon Sep 17 00:00:00 2001 From: Ncookiez Date: Fri, 1 Mar 2024 12:25:05 -0500 Subject: [PATCH 021/161] improved reservechart logic --- .../src/components/Charts/ReserveChart.tsx | 28 +++++++++++++------ .../src/components/Reserve/ReserveCard.tsx | 4 +-- 2 files changed, 21 insertions(+), 11 deletions(-) diff --git a/apps/analytics/src/components/Charts/ReserveChart.tsx b/apps/analytics/src/components/Charts/ReserveChart.tsx index eb959de7..23feccd7 100644 --- a/apps/analytics/src/components/Charts/ReserveChart.tsx +++ b/apps/analytics/src/components/Charts/ReserveChart.tsx @@ -28,10 +28,9 @@ interface DataPoint { buyback: number } -// TODO: `burnToken` should be optional, and all logic within should function appropriately interface ReserveChartProps { prizePool: PrizePool - burnToken: Token + burnToken?: Token className?: string } @@ -81,6 +80,7 @@ export const ReserveChart = (props: ReserveChartProps) => { let minBlock = 0n let maxBlock = validRngTxs[0]?.drawAward.blockNumber + let prevReserve = 0 const isValidEvent = (event: Log) => { return event.blockNumber >= minBlock && event.blockNumber < maxBlock @@ -101,6 +101,8 @@ export const ReserveChart = (props: ReserveChartProps) => { const awardedAt = txs.drawAward.timestamp const name = `${drawId}-${awardedAt}` + const remainingReserve = formatPrizeNum(txs.drawAward.remainingReserve) + // Inbound tokens const manual = formatPrizeNum( manualContributionEvents.reduce((a, b) => a + (isValidEvent(b) ? b.args.amount : 0n), 0n) @@ -111,14 +113,17 @@ export const ReserveChart = (props: ReserveChartProps) => { const prizeBackstops = formatPrizeNum( prizeBackstopEvents.reduce((a, b) => a + (isValidEvent(b) ? b.args.amount : 0n), 0n) ) - const buyback = formatPrizeNum(txs.drawAward.remainingReserve) + const buyback = !!burnToken ? remainingReserve : 0 // Calculated liquidation contributions - const liquidations = rewards + prizeBackstops + buyback - manual + const liquidations = rewards + prizeBackstops + buyback - manual - prevReserve + + // Resulting reserve balance + const reserve = remainingReserve - buyback data.push({ name, - reserve: 0, + reserve, liquidations, manual, rewards, @@ -128,21 +133,26 @@ export const ReserveChart = (props: ReserveChartProps) => { minBlock = maxBlock maxBlock = validRngTxs[i + 1]?.drawAward.blockNumber ?? MAX_UINT_256 + prevReserve = reserve }) - const currentPendingReserve = formatPrizeNum(reserve.pending) + const currentReserve = formatPrizeNum(reserve.current + reserve.pending) const currentManual = formatPrizeNum( manualContributionEvents.reduce((a, b) => a + (isValidEvent(b) ? b.args.amount : 0n), 0n) ) - const currentLiquidations = currentPendingReserve - currentManual + const currentPrizeBackstops = formatPrizeNum( + prizeBackstopEvents.reduce((a, b) => a + (isValidEvent(b) ? b.args.amount : 0n), 0n) + ) + const currentLiquidations = + currentReserve - prevReserve - currentManual + currentPrizeBackstops data.push({ name: `Now-${currentTimestamp}`, - reserve: currentPendingReserve, + reserve: currentReserve, liquidations: currentLiquidations, manual: currentManual, rewards: 0, - prizeBackstops: 0, + prizeBackstops: currentPrizeBackstops, buyback: 0 }) diff --git a/apps/analytics/src/components/Reserve/ReserveCard.tsx b/apps/analytics/src/components/Reserve/ReserveCard.tsx index fb4a7ca8..95652abf 100644 --- a/apps/analytics/src/components/Reserve/ReserveCard.tsx +++ b/apps/analytics/src/components/Reserve/ReserveCard.tsx @@ -11,7 +11,7 @@ interface ReserveCardProps { prizeBackstops: number buyback: number prizeToken: Token - burnToken: Token + burnToken?: Token className?: string } @@ -42,7 +42,7 @@ export const ReserveCard = (props: ReserveCardProps) => { From cee3cc411cee12c98dd48670d34c309c9ba06ac4 Mon Sep 17 00:00:00 2001 From: Ncookiez Date: Fri, 1 Mar 2024 14:35:24 -0500 Subject: [PATCH 022/161] added draw auction duration queries + drawstatus hook cleanup --- .../src/components/Draws/DrawRngReward.tsx | 2 +- .../analytics/src/hooks/useAllDrawsStatus.tsx | 38 +++++++++++-------- apps/analytics/src/hooks/useDrawStatus.tsx | 36 ++++++++++-------- apps/analytics/src/hooks/useRngTxs.tsx | 29 ++++++++++---- .../hyperstructure-client-js/src/PrizePool.ts | 28 ++++++++++++++ packages/hyperstructure-react-hooks/README.md | 1 + .../src/constants.ts | 1 + .../hyperstructure-react-hooks/src/index.ts | 1 + .../src/prizes/useDrawAuctionDuration.ts | 20 ++++++++++ shared/utilities/constants.ts | 4 +- 10 files changed, 120 insertions(+), 40 deletions(-) create mode 100644 packages/hyperstructure-react-hooks/src/prizes/useDrawAuctionDuration.ts diff --git a/apps/analytics/src/components/Draws/DrawRngReward.tsx b/apps/analytics/src/components/Draws/DrawRngReward.tsx index 9376bd0f..c7a5c288 100644 --- a/apps/analytics/src/components/Draws/DrawRngReward.tsx +++ b/apps/analytics/src/components/Draws/DrawRngReward.tsx @@ -48,7 +48,7 @@ export const DrawRngReward = (props: DrawRngRewardProps) => { ) : ( <> - {/* TODO: get last rng auction reward from draw manager to display here */} + {/* TODO: get last rng auction reward from draw manager to display here - crossed out? */} ? )} diff --git a/apps/analytics/src/hooks/useAllDrawsStatus.tsx b/apps/analytics/src/hooks/useAllDrawsStatus.tsx index 77ae5bdc..dbb4759f 100644 --- a/apps/analytics/src/hooks/useAllDrawsStatus.tsx +++ b/apps/analytics/src/hooks/useAllDrawsStatus.tsx @@ -1,21 +1,31 @@ import { PrizePool } from '@generationsoftware/hyperstructure-client-js' -import { useDrawPeriod, useFirstDrawOpenedAt } from '@generationsoftware/hyperstructure-react-hooks' +import { + useDrawAuctionDuration, + useDrawPeriod, + useFirstDrawOpenedAt +} from '@generationsoftware/hyperstructure-react-hooks' import { DrawStatus } from '@shared/types' import { getSecondsSinceEpoch } from '@shared/utilities' import { useMemo } from 'react' import { useRngTxs } from './useRngTxs' -// TODO: need to be able to set refetch interval or manual refetch export const useAllDrawsStatus = (prizePool: PrizePool, drawIds: number[]) => { const { data: firstDrawOpenedAt, isFetched: isFetchedFirstDrawOpenedAt } = useFirstDrawOpenedAt(prizePool) - const { data: drawPeriod, isFetched: isFetchedDrawPeriod } = useDrawPeriod(prizePool) + const { data: drawAuctionDuration, isFetched: isFetchedDrawAuctionDuration } = + useDrawAuctionDuration(prizePool) + + const { data: allRngTxs, isFetched: isFetchedAllRngTxs, refetch } = useRngTxs(prizePool) - const { data: allRngTxs, isFetched: isFetchedAllRngTxs } = useRngTxs(prizePool) + const isFetched = + isFetchedFirstDrawOpenedAt && + isFetchedDrawPeriod && + isFetchedDrawAuctionDuration && + isFetchedAllRngTxs const data = useMemo(() => { - if (!!firstDrawOpenedAt && !!drawPeriod && !!allRngTxs) { + if (isFetched && !!firstDrawOpenedAt && !!drawPeriod && !!drawAuctionDuration && !!allRngTxs) { const allDrawsStatus: { id: number status: DrawStatus @@ -33,7 +43,7 @@ export const useAllDrawsStatus = (prizePool: PrizePool, drawIds: number[]) => { const openedAt = firstDrawOpenedAt + drawPeriod * (drawId - 1) const closedAt = openedAt + drawPeriod - // const rngCompletedAt = rngTxs?.rngAuction.timestamp + const rngCompletedAt = rngTxs?.rngAuction.timestamp const awardedAt = rngTxs?.drawAward?.timestamp const finalizedAt = closedAt + drawPeriod @@ -49,14 +59,12 @@ export const useAllDrawsStatus = (prizePool: PrizePool, drawIds: number[]) => { ? 'closed' : 'open' - // TODO: check if old deployment logic still applies, and determine auction time after rng was completed - const relayAuctionClosesAt = finalizedAt - // const relayAuctionClosesAt = !!rngCompletedAt - // ? rngCompletedAt + SECONDS_PER_HOUR * 6 - // : finalizedAt + const currentAuctionClosesAt = !!rngCompletedAt + ? rngCompletedAt + drawAuctionDuration + : closedAt + drawAuctionDuration const isSkipped = (status === 'finalized' && !isAwarded) || - (status === 'closed' && currentTime >= relayAuctionClosesAt) + (status === 'closed' && currentTime >= currentAuctionClosesAt) allDrawsStatus.push({ id: drawId, @@ -71,9 +79,7 @@ export const useAllDrawsStatus = (prizePool: PrizePool, drawIds: number[]) => { return allDrawsStatus } - }, [drawIds, firstDrawOpenedAt, allRngTxs]) - - const isFetched = isFetchedFirstDrawOpenedAt && isFetchedDrawPeriod && isFetchedAllRngTxs + }, [drawIds, firstDrawOpenedAt, drawPeriod, drawAuctionDuration, allRngTxs, isFetched]) - return { data, isFetched } + return { data, isFetched, refetch } } diff --git a/apps/analytics/src/hooks/useDrawStatus.tsx b/apps/analytics/src/hooks/useDrawStatus.tsx index cf9c3f6c..b74491ff 100644 --- a/apps/analytics/src/hooks/useDrawStatus.tsx +++ b/apps/analytics/src/hooks/useDrawStatus.tsx @@ -1,29 +1,37 @@ import { PrizePool } from '@generationsoftware/hyperstructure-client-js' -import { useDrawPeriod, useFirstDrawOpenedAt } from '@generationsoftware/hyperstructure-react-hooks' +import { + useDrawAuctionDuration, + useDrawPeriod, + useFirstDrawOpenedAt +} from '@generationsoftware/hyperstructure-react-hooks' import { DrawStatus } from '@shared/types' import { getSecondsSinceEpoch } from '@shared/utilities' import { useMemo } from 'react' import { useRngTxs } from './useRngTxs' -// TODO: need to be able to set refetch interval or manual refetch export const useDrawStatus = (prizePool: PrizePool, drawId: number) => { const { data: firstDrawOpenedAt, isFetched: isFetchedFirstDrawOpenedAt } = useFirstDrawOpenedAt(prizePool) - const { data: drawPeriod, isFetched: isFetchedDrawPeriod } = useDrawPeriod(prizePool) + const { data: drawAuctionDuration, isFetched: isFetchedDrawAuctionDuration } = + useDrawAuctionDuration(prizePool) - const { data: allRngTxs, isFetched: isFetchedAllRngTxs } = useRngTxs(prizePool) + const { data: allRngTxs, isFetched: isFetchedAllRngTxs, refetch } = useRngTxs(prizePool) const isFetched = - !!drawId && isFetchedFirstDrawOpenedAt && isFetchedDrawPeriod && isFetchedAllRngTxs + !!drawId && + isFetchedFirstDrawOpenedAt && + isFetchedDrawPeriod && + isFetchedDrawAuctionDuration && + isFetchedAllRngTxs const data = useMemo(() => { - if (isFetched && !!firstDrawOpenedAt && !!drawPeriod && !!allRngTxs) { + if (isFetched && !!firstDrawOpenedAt && !!drawPeriod && !!drawAuctionDuration && !!allRngTxs) { const rngTxs = allRngTxs.find((txs) => txs.rngAuction.drawId === drawId) const openedAt = firstDrawOpenedAt + drawPeriod * (drawId - 1) const closedAt = openedAt + drawPeriod - // const rngCompletedAt = rngTxs?.rngAuction.timestamp + const rngCompletedAt = rngTxs?.rngAuction.timestamp const awardedAt = rngTxs?.drawAward?.timestamp const finalizedAt = closedAt + drawPeriod @@ -40,14 +48,12 @@ export const useDrawStatus = (prizePool: PrizePool, drawId: number) => { ? 'closed' : 'open' - // TODO: check if old deployment logic still applies, and determine auction time after rng was completed - const relayAuctionClosesAt = finalizedAt - // const relayAuctionClosesAt = !!rngCompletedAt - // ? rngCompletedAt + SECONDS_PER_HOUR * 6 - // : finalizedAt + const currentAuctionClosesAt = !!rngCompletedAt + ? rngCompletedAt + drawAuctionDuration + : closedAt + drawAuctionDuration const isSkipped = (status === 'finalized' && !isAwarded) || - (status === 'closed' && currentTime >= relayAuctionClosesAt) + (status === 'closed' && currentTime >= currentAuctionClosesAt) return { status, @@ -58,7 +64,7 @@ export const useDrawStatus = (prizePool: PrizePool, drawId: number) => { isSkipped } } - }, [drawId, firstDrawOpenedAt, drawPeriod, allRngTxs, isFetched]) + }, [drawId, firstDrawOpenedAt, drawPeriod, drawAuctionDuration, allRngTxs, isFetched]) - return { ...data, isFetched } + return { ...data, isFetched, refetch } } diff --git a/apps/analytics/src/hooks/useRngTxs.tsx b/apps/analytics/src/hooks/useRngTxs.tsx index 14e8149c..a0c6015a 100644 --- a/apps/analytics/src/hooks/useRngTxs.tsx +++ b/apps/analytics/src/hooks/useRngTxs.tsx @@ -34,12 +34,21 @@ export interface DrawAwardTx { export const useRngTxs = (prizePool: PrizePool) => { const fromBlock = !!prizePool ? QUERY_START_BLOCK[prizePool.chainId] : undefined - const { data: rngAuctionCompletedEvents, isFetched: isFetchedRngAuctionCompletedEvents } = - useRngAuctionCompletedEvents(prizePool, { fromBlock }) - const { data: prizePoolDrawAwardedEvents, isFetched: isFetchedPrizePoolDrawAwardedEvents } = - usePrizePoolDrawAwardedEvents(prizePool, { fromBlock }) - const { data: drawManagerDrawAwardedEvents, isFetched: isFetchedDrawManagerDrawAwardedEvents } = - useDrawManagerDrawAwardedEvents(prizePool, { fromBlock }) + const { + data: rngAuctionCompletedEvents, + isFetched: isFetchedRngAuctionCompletedEvents, + refetch: refetchRngAuctionCompletedEvents + } = useRngAuctionCompletedEvents(prizePool, { fromBlock }) + const { + data: prizePoolDrawAwardedEvents, + isFetched: isFetchedPrizePoolDrawAwardedEvents, + refetch: refetchPrizePoolDrawAwardedEvents + } = usePrizePoolDrawAwardedEvents(prizePool, { fromBlock }) + const { + data: drawManagerDrawAwardedEvents, + isFetched: isFetchedDrawManagerDrawAwardedEvents, + refetch: refetchDrawManagerDrawAwardedEvents + } = useDrawManagerDrawAwardedEvents(prizePool, { fromBlock }) const rngAuctionCompletedBlockNumbers = new Set( rngAuctionCompletedEvents?.map((e) => e.blockNumber) ?? [] @@ -135,5 +144,11 @@ export const useRngTxs = (prizePool: PrizePool) => { isFetchedRngAuctionCompletedBlocks && isFetchedDrawAwardedBlocks - return { data, isFetched } + const refetch = () => { + refetchRngAuctionCompletedEvents() + refetchPrizePoolDrawAwardedEvents() + refetchDrawManagerDrawAwardedEvents() + } + + return { data, isFetched, refetch } } diff --git a/packages/hyperstructure-client-js/src/PrizePool.ts b/packages/hyperstructure-client-js/src/PrizePool.ts index 0f58225f..5070ceca 100644 --- a/packages/hyperstructure-client-js/src/PrizePool.ts +++ b/packages/hyperstructure-client-js/src/PrizePool.ts @@ -1,5 +1,6 @@ import { PrizeInfo, TokenWithSupply, TxOverrides } from '@shared/types' import { + drawManagerABI, getPrizePoolAllPrizeInfo, getPrizePoolContributionAmounts, getPrizePoolContributionPercentages, @@ -22,6 +23,7 @@ export class PrizePool { drawManagerAddress: Address | undefined twabControllerAddress: Address | undefined drawPeriodInSeconds: number | undefined + drawAuctionDurationInSeconds: number | undefined tierShares: number | undefined reserveShares: number | undefined @@ -44,6 +46,7 @@ export class PrizePool { drawManagerAddress?: Address twabControllerAddress?: Address drawPeriodInSeconds?: number + drawAuctionDurationInSeconds?: number tierShares?: number reserveShares?: number } @@ -55,6 +58,7 @@ export class PrizePool { this.drawManagerAddress = options?.drawManagerAddress this.twabControllerAddress = options?.twabControllerAddress this.drawPeriodInSeconds = options?.drawPeriodInSeconds + this.drawAuctionDurationInSeconds = options?.drawAuctionDurationInSeconds this.tierShares = options?.tierShares this.reserveShares = options?.reserveShares } @@ -156,6 +160,30 @@ export class PrizePool { return drawPeriodInSeconds } + /** + * Returns the duration of a draw auction in seconds + * @returns + */ + async getDrawAuctionDurationInSeconds(): Promise { + if (this.drawAuctionDurationInSeconds !== undefined) return this.drawAuctionDurationInSeconds + + const source = 'Prize Pool [getDrawAuctionDurationInSeconds]' + await validateClientNetwork(this.chainId, this.publicClient, source) + + const drawManagerAddress = await this.getDrawManagerAddress() + + const drawAuctionDurationInSeconds = Number( + await this.publicClient.readContract({ + address: drawManagerAddress, + abi: drawManagerABI, + functionName: 'auctionDuration' + }) + ) + + this.drawAuctionDurationInSeconds = drawAuctionDurationInSeconds + return drawAuctionDurationInSeconds + } + /** * Returns the number of shares allocated to each prize tier * @returns diff --git a/packages/hyperstructure-react-hooks/README.md b/packages/hyperstructure-react-hooks/README.md index d64973a2..c79d6296 100644 --- a/packages/hyperstructure-react-hooks/README.md +++ b/packages/hyperstructure-react-hooks/README.md @@ -92,6 +92,7 @@ yarn add @generationsoftware/hyperstructure-react-hooks - `useAllUserEligibleDraws` - `useAllUserPrizeOdds` - `useAllUserPrizePoolWins` +- `useDrawAuctionDuration` - `useDrawIds` - `useDrawPeriod` - `useDrawsToCheckForPrizes` diff --git a/packages/hyperstructure-react-hooks/src/constants.ts b/packages/hyperstructure-react-hooks/src/constants.ts index 125901bc..29ea3522 100644 --- a/packages/hyperstructure-react-hooks/src/constants.ts +++ b/packages/hyperstructure-react-hooks/src/constants.ts @@ -7,6 +7,7 @@ export const QUERY_KEYS = { block: 'block', blockAtTimestamp: 'blockAtTimestamp', clientChainId: 'clientChainId', + drawAuctionDuration: 'drawAuctionDuration', drawManagerDrawAwardedEvents: 'drawManagerDrawAwardedEvents', drawPeriod: 'drawPeriod', drawTimestamps: 'drawTimestamps', diff --git a/packages/hyperstructure-react-hooks/src/index.ts b/packages/hyperstructure-react-hooks/src/index.ts index 29890800..b5dfa1e5 100644 --- a/packages/hyperstructure-react-hooks/src/index.ts +++ b/packages/hyperstructure-react-hooks/src/index.ts @@ -49,6 +49,7 @@ export * from './prizes/useAllUserBalanceUpdates' export * from './prizes/useAllUserEligibleDraws' export * from './prizes/useAllUserPrizeOdds' export * from './prizes/useAllUserPrizePoolWins' +export * from './prizes/useDrawAuctionDuration' export * from './prizes/useDrawIds' export * from './prizes/useDrawPeriod' export * from './prizes/useDrawsToCheckForPrizes' diff --git a/packages/hyperstructure-react-hooks/src/prizes/useDrawAuctionDuration.ts b/packages/hyperstructure-react-hooks/src/prizes/useDrawAuctionDuration.ts new file mode 100644 index 00000000..69c70947 --- /dev/null +++ b/packages/hyperstructure-react-hooks/src/prizes/useDrawAuctionDuration.ts @@ -0,0 +1,20 @@ +import { PrizePool } from '@generationsoftware/hyperstructure-client-js' +import { NO_REFETCH } from '@shared/generic-react-hooks' +import { useQuery, UseQueryResult } from '@tanstack/react-query' +import { QUERY_KEYS } from '../constants' + +/** + * Returns a prize pool's draw auction duration (in seconds) + * @param prizePool instance of the `PrizePool` class + * @returns + */ +export const useDrawAuctionDuration = (prizePool: PrizePool): UseQueryResult => { + const queryKey = [QUERY_KEYS.drawAuctionDuration, prizePool?.id] + + return useQuery({ + queryKey, + queryFn: async () => await prizePool.getDrawAuctionDurationInSeconds(), + enabled: !!prizePool, + ...NO_REFETCH + }) +} diff --git a/shared/utilities/constants.ts b/shared/utilities/constants.ts index ce056284..8d2eab8c 100644 --- a/shared/utilities/constants.ts +++ b/shared/utilities/constants.ts @@ -85,6 +85,7 @@ export const PRIZE_POOLS: { drawManagerAddress: Address twabControllerAddress: Address drawPeriodInSeconds: number + drawActionDurationInSeconds: number tierShares: number reserveShares: number } @@ -96,7 +97,8 @@ export const PRIZE_POOLS: { prizeTokenAddress: '0x0Ba5e0722797dcEa8Cec409a707cE495C33fB23D', drawManagerAddress: '0x512c1421D4f6f6c01A7508E060595ee08A652f69', twabControllerAddress: '0x53f5545055f3804B7fD694081f9a13b3abceB38E', - drawPeriodInSeconds: 7200, + drawPeriodInSeconds: 7_200, + drawActionDurationInSeconds: 2_400, tierShares: 100, reserveShares: 20 } From 383017fa84037e5a5208ef53db9c31605b3626af Mon Sep 17 00:00:00 2001 From: Ncookiez Date: Fri, 1 Mar 2024 14:43:16 -0500 Subject: [PATCH 023/161] refetching cleanup --- apps/analytics/src/views/DrawsView.tsx | 24 +++--------------------- apps/analytics/src/views/PrizesView.tsx | 24 +++--------------------- apps/analytics/src/views/ReserveView.tsx | 19 +++---------------- 3 files changed, 9 insertions(+), 58 deletions(-) diff --git a/apps/analytics/src/views/DrawsView.tsx b/apps/analytics/src/views/DrawsView.tsx index 63d224c3..d833b898 100644 --- a/apps/analytics/src/views/DrawsView.tsx +++ b/apps/analytics/src/views/DrawsView.tsx @@ -1,9 +1,4 @@ import { PrizePool } from '@generationsoftware/hyperstructure-client-js' -import { - useDrawManagerDrawAwardedEvents, - usePrizePoolDrawAwardedEvents, - useRngAuctionCompletedEvents -} from '@generationsoftware/hyperstructure-react-hooks' import { PRIZE_POOLS, sToMs } from '@shared/utilities' import classNames from 'classnames' import { useEffect, useMemo } from 'react' @@ -12,9 +7,9 @@ import { usePublicClient } from 'wagmi' import { DrawsAvgClaimFeesChart } from '@components/Charts/DrawsAvgClaimFeesChart' import { DrawsAvgLiqEfficiencyChart } from '@components/Charts/DrawsAvgLiqEfficiencyChart' import { DrawCards } from '@components/Draws/DrawCards' -import { QUERY_START_BLOCK } from '@constants/config' import { useCurrentDrawAwardReward } from '@hooks/useCurrentDrawAwardReward' import { useCurrentRngAuctionReward } from '@hooks/useCurrentRngAuctionReward' +import { useRngTxs } from '@hooks/useRngTxs' interface DrawsViewProps { chainId: number @@ -39,29 +34,16 @@ export const DrawsView = (props: DrawsViewProps) => { ) }, [chainId, publicClient]) - const fromBlock = !!prizePool ? QUERY_START_BLOCK[prizePool.chainId] : undefined - const { refetch: refetchCurrentRngAuctionReward } = useCurrentRngAuctionReward(prizePool) const { refetch: refetchCurrentDrawAwardReward } = useCurrentDrawAwardReward(prizePool) - const { refetch: refetchRngAuctionCompletedEvents } = useRngAuctionCompletedEvents(prizePool, { - fromBlock - }) - const { refetch: refetchPrizePoolDrawAwardedEvents } = usePrizePoolDrawAwardedEvents(prizePool, { - fromBlock - }) - const { refetch: refetchDrawManagerDrawAwardedEvents } = useDrawManagerDrawAwardedEvents( - prizePool, - { fromBlock } - ) + const { refetch: refetchRngTxs } = useRngTxs(prizePool) // Automatic data refetching useEffect(() => { const interval = setInterval(() => { refetchCurrentRngAuctionReward() refetchCurrentDrawAwardReward() - refetchRngAuctionCompletedEvents() - refetchPrizePoolDrawAwardedEvents() - refetchDrawManagerDrawAwardedEvents() + refetchRngTxs() }, sToMs(300)) return () => clearInterval(interval) diff --git a/apps/analytics/src/views/PrizesView.tsx b/apps/analytics/src/views/PrizesView.tsx index d88923f8..1bff74b5 100644 --- a/apps/analytics/src/views/PrizesView.tsx +++ b/apps/analytics/src/views/PrizesView.tsx @@ -1,9 +1,4 @@ import { PrizePool } from '@generationsoftware/hyperstructure-client-js' -import { - useDrawManagerDrawAwardedEvents, - usePrizePoolDrawAwardedEvents, - useRngAuctionCompletedEvents -} from '@generationsoftware/hyperstructure-react-hooks' import { PRIZE_POOLS, sToMs } from '@shared/utilities' import classNames from 'classnames' import { useAtomValue } from 'jotai' @@ -15,7 +10,7 @@ import { DrawAvgClaimFeesChart } from '@components/Charts/DrawAvgClaimFeesChart' import { DrawSelector } from '@components/Draws/DrawSelector' import { DrawStatusBadge } from '@components/Draws/DrawStatusBadge' import { PrizesTable } from '@components/Prizes/PrizesTable' -import { QUERY_START_BLOCK } from '@constants/config' +import { useRngTxs } from '@hooks/useRngTxs' interface PrizesViewProps { chainId: number @@ -40,25 +35,12 @@ export const PrizesView = (props: PrizesViewProps) => { ) }, [chainId, publicClient]) - const fromBlock = !!prizePool ? QUERY_START_BLOCK[prizePool.chainId] : undefined - - const { refetch: refetchRngAuctionCompletedEvents } = useRngAuctionCompletedEvents(prizePool, { - fromBlock - }) - const { refetch: refetchPrizePoolDrawAwardedEvents } = usePrizePoolDrawAwardedEvents(prizePool, { - fromBlock - }) - const { refetch: refetchDrawManagerDrawAwardedEvents } = useDrawManagerDrawAwardedEvents( - prizePool, - { fromBlock } - ) + const { refetch: refetchRngTxs } = useRngTxs(prizePool) // Automatic data refetching useEffect(() => { const interval = setInterval(() => { - refetchRngAuctionCompletedEvents() - refetchPrizePoolDrawAwardedEvents() - refetchDrawManagerDrawAwardedEvents() + refetchRngTxs() }, sToMs(300)) return () => clearInterval(interval) diff --git a/apps/analytics/src/views/ReserveView.tsx b/apps/analytics/src/views/ReserveView.tsx index 4b5f589c..cfdbb080 100644 --- a/apps/analytics/src/views/ReserveView.tsx +++ b/apps/analytics/src/views/ReserveView.tsx @@ -1,11 +1,8 @@ import { PrizePool } from '@generationsoftware/hyperstructure-client-js' import { - useDrawManagerDrawAwardedEvents, useLiquidationEvents, useManualContributionEvents, usePrizeBackstopEvents, - usePrizePoolDrawAwardedEvents, - useRngAuctionCompletedEvents, useToken } from '@generationsoftware/hyperstructure-react-hooks' import { getSecondsSinceEpoch, POOL_TOKEN_ADDRESSES, PRIZE_POOLS, sToMs } from '@shared/utilities' @@ -19,6 +16,7 @@ import { ReserveChart } from '@components/Charts/ReserveChart' import { ReserveHeader } from '@components/Reserve/ReserveHeader' import { QUERY_START_BLOCK } from '@constants/config' import { useReserve } from '@hooks/useReserve' +import { useRngTxs } from '@hooks/useRngTxs' interface ReserveViewProps { chainId: number @@ -60,16 +58,7 @@ export const ReserveView = (props: ReserveViewProps) => { fromBlock }) const { refetch: refetchPrizeBackstopEvents } = usePrizeBackstopEvents(prizePool, { fromBlock }) - const { refetch: refetchRngAuctionCompletedEvents } = useRngAuctionCompletedEvents(prizePool, { - fromBlock - }) - const { refetch: refetchPrizePoolDrawAwardedEvents } = usePrizePoolDrawAwardedEvents(prizePool, { - fromBlock - }) - const { refetch: refetchDrawManagerDrawAwardedEvents } = useDrawManagerDrawAwardedEvents( - prizePool, - { fromBlock } - ) + const { refetch: refetchRngTxs } = useRngTxs(prizePool) // Automatic data refetching useEffect(() => { @@ -78,9 +67,7 @@ export const ReserveView = (props: ReserveViewProps) => { refetchLiquidationEvents() refetchManualContributionEvents() refetchPrizeBackstopEvents() - refetchRngAuctionCompletedEvents() - refetchPrizePoolDrawAwardedEvents() - refetchDrawManagerDrawAwardedEvents() + refetchRngTxs() setCurrentTimestamp(getSecondsSinceEpoch()) }, sToMs(300)) From 2f9e50d926275987da0f940f6d03ddcd73053f7c Mon Sep 17 00:00:00 2001 From: Ncookiez Date: Fri, 1 Mar 2024 15:43:08 -0500 Subject: [PATCH 024/161] refactored handling of tokenIn for liquidation pairs --- .../Charts/DrawsAvgLiqEfficiencyChart.tsx | 72 ++++++++++--------- .../components/Draws/DrawLiqEfficiency.tsx | 72 +++++++++---------- ...HistoricalLiquidationPairTokenInPrices.tsx | 44 ++++++++++++ ...istoricalLiquidationPairTokenOutPrices.tsx | 20 +++--- .../useIsLiquidationPairTokenOutAVault.tsx | 2 +- .../useLiquidationPairLiquidatableBalance.tsx | 2 +- .../useLiquidationPairTokenInAddresses.tsx | 52 ++++++++++++++ .../useLiquidationPairTokenOutAddress.tsx | 26 ------- .../useLiquidationPairTokenOutAddresses.tsx | 9 +++ .../hooks/useLiquidationPairTokenOutData.tsx | 21 ++---- .../hooks/useLiquidationPairTokenOutPrice.tsx | 13 ++-- 11 files changed, 202 insertions(+), 131 deletions(-) create mode 100644 apps/analytics/src/hooks/useHistoricalLiquidationPairTokenInPrices.tsx create mode 100644 apps/analytics/src/hooks/useLiquidationPairTokenInAddresses.tsx delete mode 100644 apps/analytics/src/hooks/useLiquidationPairTokenOutAddress.tsx diff --git a/apps/analytics/src/components/Charts/DrawsAvgLiqEfficiencyChart.tsx b/apps/analytics/src/components/Charts/DrawsAvgLiqEfficiencyChart.tsx index 83c5c44d..8e710e52 100644 --- a/apps/analytics/src/components/Charts/DrawsAvgLiqEfficiencyChart.tsx +++ b/apps/analytics/src/components/Charts/DrawsAvgLiqEfficiencyChart.tsx @@ -2,11 +2,9 @@ import { PrizePool } from '@generationsoftware/hyperstructure-client-js' import { useBlocksAtTimestamps, useDrawIds, - useHistoricalTokenPrices, - useLiquidationEvents, - usePrizeTokenData + useLiquidationEvents } from '@generationsoftware/hyperstructure-react-hooks' -import { formatNumberForDisplay, NETWORK, WRAPPED_NATIVE_ASSETS } from '@shared/utilities' +import { formatNumberForDisplay } from '@shared/utilities' import classNames from 'classnames' import { useAtomValue } from 'jotai' import { useMemo } from 'react' @@ -14,6 +12,7 @@ import { currentTimestampAtom } from 'src/atoms' import { Address, formatUnits } from 'viem' import { QUERY_START_BLOCK } from '@constants/config' import { useAllDrawsStatus } from '@hooks/useAllDrawsStatus' +import { useHistoricalLiquidationPairTokenInPrices } from '@hooks/useHistoricalLiquidationPairTokenInPrices' import { useHistoricalLiquidationPairTokenOutPrices } from '@hooks/useHistoricalLiquidationPairTokenOutPrices' import { LineChart } from './LineChart' @@ -45,14 +44,6 @@ export const DrawsAvgLiqEfficiencyChart = (props: DrawsAvgLiqEfficiencyChartProp allDrawsStatus?.map((draw) => draw.closedAt) ?? [] ) - // TODO: this assumes the tokenIn is always WETH (and uses mainnet pricing) - this will fail for the burn mechanism from the reserve - need fix - const { data: prizeToken } = usePrizeTokenData(prizePool) - const { data: tokenInPrices } = useHistoricalTokenPrices(NETWORK.mainnet, [ - WRAPPED_NATIVE_ASSETS[NETWORK.mainnet] as Address - ]) - const prizeTokenPrices = - tokenInPrices[WRAPPED_NATIVE_ASSETS[NETWORK.mainnet]?.toLowerCase() as Address] - const lpAddresses = useMemo(() => { const addresses = new Set
() liquidationEvents?.forEach((e) => @@ -61,6 +52,11 @@ export const DrawsAvgLiqEfficiencyChart = (props: DrawsAvgLiqEfficiencyChartProp return [...addresses] }, [liquidationEvents]) + const { data: tokenInPrices } = useHistoricalLiquidationPairTokenInPrices( + prizePool?.chainId, + lpAddresses + ) + const { data: tokenOutPrices } = useHistoricalLiquidationPairTokenOutPrices( prizePool?.chainId, lpAddresses @@ -72,8 +68,7 @@ export const DrawsAvgLiqEfficiencyChart = (props: DrawsAvgLiqEfficiencyChartProp !!allDrawsStatus && !!openedAtBlocksByTimestamp && !!closedAtBlocksByTimestamp && - !!prizeToken && - !!prizeTokenPrices && + !!Object.keys(tokenInPrices).length && !!Object.keys(tokenOutPrices).length ) { const data: { name: string; percentage: number; cumAvg: number }[] = [] @@ -81,40 +76,52 @@ export const DrawsAvgLiqEfficiencyChart = (props: DrawsAvgLiqEfficiencyChartProp let numValues = 0 let sumValues = 0 - allDrawsStatus.forEach((draw) => { - const targetTimestamp = - draw.closedAt < currentTimestamp - ? draw.closedAt - (draw.closedAt - draw.openedAt) / 2 - : draw.openedAt - const targetDate = new Date(targetTimestamp * 1_000).toISOString().split('T')[0] - const prizeTokenPrice = prizeTokenPrices.find((entry) => entry.date === targetDate)?.price + const getDate = (timestampInSeconds: number) => { + return new Date(timestampInSeconds * 1_000).toISOString().split('T')[0] + } + allDrawsStatus.forEach((draw) => { const openedAtBlock = openedAtBlocksByTimestamp[draw.openedAt] const closedAtBlock = !!draw.closedAt ? closedAtBlocksByTimestamp[draw.closedAt] : undefined - if (!!prizeTokenPrice && !!openedAtBlock && !!closedAtBlock) { + if (!!openedAtBlock && !!closedAtBlock) { let totalValueIn = 0 let totalValueOut = 0 + const targetDate = getDate( + draw.closedAt < currentTimestamp + ? draw.closedAt - (draw.closedAt - draw.openedAt) / 2 + : draw.openedAt + ) + const drawLiquidationEvents = liquidationEvents.filter( (e) => e.blockNumber > openedAtBlock.number && e.blockNumber <= closedAtBlock.number ) drawLiquidationEvents.forEach((event) => { - const tokenOut = tokenOutPrices[event.args.liquidationPair.toLowerCase() as Address] - const tokenOutPrice = tokenOut?.priceHistory.find( + const liquidationPair = event.args.liquidationPair.toLowerCase() as Address + + const tokenIn = tokenInPrices[liquidationPair] + const tokenInPrice = tokenIn?.priceHistory.find( (entry) => entry.date === targetDate )?.price - if (!!tokenOutPrice) { - const amountIn = parseFloat(formatUnits(event.args.amountIn, prizeToken.decimals)) - const amountOut = parseFloat(formatUnits(event.args.amountOut, tokenOut.decimals)) + if (!!tokenInPrice) { + const tokenOut = tokenOutPrices[liquidationPair] + const tokenOutPrice = tokenOut?.priceHistory.find( + (entry) => entry.date === targetDate + )?.price + + if (!!tokenOutPrice) { + const amountIn = parseFloat(formatUnits(event.args.amountIn, tokenIn.decimals)) + const amountOut = parseFloat(formatUnits(event.args.amountOut, tokenOut.decimals)) - const valueIn = amountIn * prizeTokenPrice - const valueOut = amountOut * tokenOutPrice + const valueIn = amountIn * tokenInPrice + const valueOut = amountOut * tokenOutPrice - totalValueIn += valueIn - totalValueOut += valueOut + totalValueIn += valueIn + totalValueOut += valueOut + } } }) @@ -135,8 +142,7 @@ export const DrawsAvgLiqEfficiencyChart = (props: DrawsAvgLiqEfficiencyChartProp allDrawsStatus, openedAtBlocksByTimestamp, closedAtBlocksByTimestamp, - prizeToken, - prizeTokenPrices, + tokenInPrices, tokenOutPrices ]) diff --git a/apps/analytics/src/components/Draws/DrawLiqEfficiency.tsx b/apps/analytics/src/components/Draws/DrawLiqEfficiency.tsx index 3a5f99b6..e234a11e 100644 --- a/apps/analytics/src/components/Draws/DrawLiqEfficiency.tsx +++ b/apps/analytics/src/components/Draws/DrawLiqEfficiency.tsx @@ -1,12 +1,10 @@ import { PrizePool } from '@generationsoftware/hyperstructure-client-js' import { useBlockAtTimestamp, - useHistoricalTokenPrices, - useLiquidationEvents, - usePrizeTokenData + useLiquidationEvents } from '@generationsoftware/hyperstructure-react-hooks' import { ExternalLink, Spinner } from '@shared/ui' -import { getBlockExplorerUrl, NETWORK, WRAPPED_NATIVE_ASSETS } from '@shared/utilities' +import { getBlockExplorerUrl } from '@shared/utilities' import classNames from 'classnames' import { useAtomValue } from 'jotai' import { useMemo } from 'react' @@ -14,6 +12,7 @@ import { currentTimestampAtom } from 'src/atoms' import { Address, formatUnits } from 'viem' import { QUERY_START_BLOCK } from '@constants/config' import { useDrawStatus } from '@hooks/useDrawStatus' +import { useHistoricalLiquidationPairTokenInPrices } from '@hooks/useHistoricalLiquidationPairTokenInPrices' import { useHistoricalLiquidationPairTokenOutPrices } from '@hooks/useHistoricalLiquidationPairTokenOutPrices' import { DrawCardItemTitle } from './DrawCardItemTitle' @@ -38,23 +37,15 @@ export const DrawLiqEfficiency = (props: DrawLiqEfficiencyProps) => { const { data: openedAtBlock } = useBlockAtTimestamp(prizePool?.chainId, openedAt as number) const { data: closedAtBlock } = useBlockAtTimestamp(prizePool?.chainId, closedAt as number) - // TODO: this assumes the tokenIn is always WETH (and uses mainnet pricing) - will break with burn mechanism from reserve - need fix - const { data: prizeToken } = usePrizeTokenData(prizePool) - const { data: tokenInPrices, isFetched: isFetchedTokenInPrices } = useHistoricalTokenPrices( - NETWORK.mainnet, - [WRAPPED_NATIVE_ASSETS[NETWORK.mainnet] as Address] - ) - const prizeTokenPrices = - tokenInPrices[WRAPPED_NATIVE_ASSETS[NETWORK.mainnet]?.toLowerCase() as Address] - const drawLiquidationEvents = useMemo(() => { - if (!!liquidationEvents?.length && isFetchedDrawStatus && !!openedAtBlock && !!closedAtBlock) { + if (!!liquidationEvents && isFetchedDrawStatus && !!openedAtBlock && !!closedAtBlock) { return liquidationEvents.filter( (event) => event.blockNumber > openedAtBlock.number && event.blockNumber <= closedAtBlock.number ) + } else { + return [] } - return [] }, [liquidationEvents, isFetchedDrawStatus, openedAtBlock, closedAtBlock]) const lpAddresses = useMemo(() => { @@ -65,43 +56,49 @@ export const DrawLiqEfficiency = (props: DrawLiqEfficiencyProps) => { return [...addresses] }, [drawLiquidationEvents]) + const { data: tokenInPrices, isFetched: isFetchedTokenInPrices } = + useHistoricalLiquidationPairTokenInPrices(prizePool?.chainId, lpAddresses) + const { data: tokenOutPrices, isFetched: isFetchedTokenOutPrices } = useHistoricalLiquidationPairTokenOutPrices(prizePool?.chainId, lpAddresses) const liqEfficiencyStats = useMemo(() => { if ( !!drawLiquidationEvents.length && - !!prizeToken && - !!prizeTokenPrices && - !!Object.keys(tokenOutPrices).length && !!openedAt && - !!closedAt + !!closedAt && + !!Object.keys(tokenInPrices).length && + !!Object.keys(tokenOutPrices).length ) { const targetTimestamp = closedAt < currentTimestamp ? closedAt - (closedAt - openedAt) / 2 : openedAt const targetDate = new Date(targetTimestamp * 1_000).toISOString().split('T')[0] - const prizeTokenPrice = prizeTokenPrices.find((entry) => entry.date === targetDate)?.price - if (!!prizeTokenPrice) { - type Stat = { efficiency: number; hash?: `0x${string}` } + type Stat = { efficiency: number; hash?: `0x${string}` } + + let high: Stat = { efficiency: -Number.MAX_SAFE_INTEGER } + let low: Stat = { efficiency: Number.MAX_SAFE_INTEGER } - let high: Stat = { efficiency: -Number.MAX_SAFE_INTEGER } - let low: Stat = { efficiency: Number.MAX_SAFE_INTEGER } + let totalValueIn = 0 + let totalValueOut = 0 - let totalValueIn = 0 - let totalValueOut = 0 + drawLiquidationEvents.forEach((event) => { + const liquidationPair = event.args.liquidationPair.toLowerCase() as Address - drawLiquidationEvents.forEach((event) => { - const tokenOut = tokenOutPrices[event.args.liquidationPair.toLowerCase() as Address] + const tokenIn = tokenInPrices[liquidationPair] + const tokenInPrice = tokenIn?.priceHistory.find((entry) => entry.date === targetDate)?.price + + if (!!tokenInPrice) { + const tokenOut = tokenOutPrices[liquidationPair] const tokenOutPrice = tokenOut?.priceHistory.find( (entry) => entry.date === targetDate )?.price if (!!tokenOutPrice) { - const amountIn = parseFloat(formatUnits(event.args.amountIn, prizeToken.decimals)) + const amountIn = parseFloat(formatUnits(event.args.amountIn, tokenIn.decimals)) const amountOut = parseFloat(formatUnits(event.args.amountOut, tokenOut.decimals)) - const valueIn = amountIn * prizeTokenPrice + const valueIn = amountIn * tokenInPrice const valueOut = amountOut * tokenOutPrice const efficiency = (valueIn / valueOut) * 100 @@ -116,22 +113,21 @@ export const DrawLiqEfficiency = (props: DrawLiqEfficiencyProps) => { totalValueIn += valueIn totalValueOut += valueOut } - }) + } + }) - if (!!high.hash && !!low.hash && !!totalValueIn && !!totalValueOut) { - const avg = (totalValueIn / totalValueOut) * 100 + if (!!high.hash && !!low.hash && !!totalValueIn && !!totalValueOut) { + const avg = (totalValueIn / totalValueOut) * 100 - return { avg, high, low } - } + return { avg, high, low } } } - }, [drawLiquidationEvents, prizeToken, prizeTokenPrices, tokenOutPrices, openedAt, closedAt]) + }, [drawLiquidationEvents, openedAt, closedAt, tokenInPrices, tokenOutPrices]) const isFetched = isFetchedLiquidationEvents && isFetchedDrawStatus && - isFetchedTokenInPrices && - (!lpAddresses.length || isFetchedTokenOutPrices) + (!lpAddresses.length || (isFetchedTokenInPrices && isFetchedTokenOutPrices)) return (
diff --git a/apps/analytics/src/hooks/useHistoricalLiquidationPairTokenInPrices.tsx b/apps/analytics/src/hooks/useHistoricalLiquidationPairTokenInPrices.tsx new file mode 100644 index 00000000..6228324d --- /dev/null +++ b/apps/analytics/src/hooks/useHistoricalLiquidationPairTokenInPrices.tsx @@ -0,0 +1,44 @@ +import { useHistoricalTokenPrices, useTokens } from '@generationsoftware/hyperstructure-react-hooks' +import { TokenWithSupply } from '@shared/types' +import { useMemo } from 'react' +import { Address } from 'viem' +import { useLiquidationPairTokenInAddresses } from './useLiquidationPairTokenInAddresses' + +export const useHistoricalLiquidationPairTokenInPrices = ( + chainId: number, + lpAddresses: Address[] +) => { + const { data: tokenInAddresses, isFetched: isFetchedTokenInAddresses } = + useLiquidationPairTokenInAddresses(chainId, lpAddresses) + + const { data: tokens, isFetched: isFetchedTokens } = useTokens( + chainId, + Object.values(tokenInAddresses) + ) + + const { data: historicalTokenPrices, isFetched: isFetchedHistoricalTokenPrices } = + useHistoricalTokenPrices(chainId, Object.values(tokenInAddresses)) + + const isFetched = isFetchedTokenInAddresses && isFetchedTokens && isFetchedHistoricalTokenPrices + + const data = useMemo(() => { + const results: { + [lpAddress: Address]: TokenWithSupply & { priceHistory: { date: string; price: number }[] } + } = {} + + if (!!tokenInAddresses) { + Object.entries(tokenInAddresses).forEach(([lpAddress, tokenInAddress]) => { + const token = tokens?.[tokenInAddress] + const tokenPrices = historicalTokenPrices?.[tokenInAddress.toLowerCase() as Address] + + if (!!token && !!tokenPrices?.length) { + results[lpAddress as Address] = { ...token, priceHistory: tokenPrices } + } + }) + } + + return results + }, [chainId, tokenInAddresses, tokens, historicalTokenPrices]) + + return { data, isFetched } +} diff --git a/apps/analytics/src/hooks/useHistoricalLiquidationPairTokenOutPrices.tsx b/apps/analytics/src/hooks/useHistoricalLiquidationPairTokenOutPrices.tsx index e7acb9bd..f8bd50bd 100644 --- a/apps/analytics/src/hooks/useHistoricalLiquidationPairTokenOutPrices.tsx +++ b/apps/analytics/src/hooks/useHistoricalLiquidationPairTokenOutPrices.tsx @@ -21,9 +21,9 @@ export const useHistoricalLiquidationPairTokenOutPrices = ( const { data: tokenOutAddresses, isFetched: isFetchedTokenOutAddresses } = useLiquidationPairTokenOutAddresses(chainId, lpAddresses) - const { data: shareTokens, isFetched: isFetchedShareTokens } = useTokens( + const { data: tokens, isFetched: isFetchedTokens } = useTokens( chainId, - !!tokenOutAddresses ? Object.values(tokenOutAddresses) : [] + Object.values(tokenOutAddresses) ) const { data: isValidVaults, isFetched: isFetchedIsValidVaults } = @@ -31,12 +31,15 @@ export const useHistoricalLiquidationPairTokenOutPrices = ( const vaults = useMemo(() => { const allValidVaultInfo: VaultInfo[] = [] + Object.entries(tokenOutAddresses).forEach(([lpAddress, tokenOutAddress]) => { const isValid = !!isValidVaults?.[lpAddress as Address] + if (isValid) { allValidVaultInfo.push({ chainId, address: tokenOutAddress }) } }) + return !!allValidVaultInfo.length && !!publicClient ? new Vaults(allValidVaultInfo, { [chainId]: publicClient }) : undefined @@ -48,6 +51,7 @@ export const useHistoricalLiquidationPairTokenOutPrices = ( const nonVaultTokenAddresses = useMemo(() => { const vaultAddresses = vaults?.vaultAddresses?.[chainId]?.map((address) => address.toLowerCase()) ?? [] + return Object.values(tokenOutAddresses).filter( (address) => !vaultAddresses.includes(address.toLowerCase()) ) @@ -58,7 +62,7 @@ export const useHistoricalLiquidationPairTokenOutPrices = ( const isFetched = isFetchedTokenOutAddresses && - isFetchedShareTokens && + isFetchedTokens && (vaults === undefined || isFetchedShareTokensWithPriceHistory) && (nonVaultTokenAddresses.length === 0 || isFetchedHistoricalTokenPrices) @@ -70,21 +74,21 @@ export const useHistoricalLiquidationPairTokenOutPrices = ( if (!!tokenOutAddresses) { Object.entries(tokenOutAddresses).forEach(([lpAddress, tokenOutAddress]) => { const vaultId = getVaultId({ chainId, address: tokenOutAddress }) - const shareToken = shareTokens?.[tokenOutAddress] - const shareTokenPrices = shareTokensWithPriceHistory?.[vaultId] + + const token = tokens?.[tokenOutAddress] const tokenPrices = historicalTokenPrices?.[tokenOutAddress.toLowerCase() as Address] if (!!shareTokenPrices?.priceHistory.length) { results[lpAddress as Address] = shareTokenPrices - } else if (!!shareToken && !!tokenPrices?.length) { - results[lpAddress as Address] = { ...shareToken, priceHistory: tokenPrices } + } else if (!!token && !!tokenPrices?.length) { + results[lpAddress as Address] = { ...token, priceHistory: tokenPrices } } }) } return results - }, [chainId, tokenOutAddresses, shareTokens, shareTokensWithPriceHistory, historicalTokenPrices]) + }, [chainId, tokenOutAddresses, tokens, shareTokensWithPriceHistory, historicalTokenPrices]) return { data, isFetched } } diff --git a/apps/analytics/src/hooks/useIsLiquidationPairTokenOutAVault.tsx b/apps/analytics/src/hooks/useIsLiquidationPairTokenOutAVault.tsx index 8bfbc1b1..6929985d 100644 --- a/apps/analytics/src/hooks/useIsLiquidationPairTokenOutAVault.tsx +++ b/apps/analytics/src/hooks/useIsLiquidationPairTokenOutAVault.tsx @@ -3,7 +3,7 @@ import { vaultABI } from '@shared/utilities' import { useQuery } from '@tanstack/react-query' import { Address, isAddress } from 'viem' import { usePublicClient } from 'wagmi' -import { useLiquidationPairTokenOutAddress } from './useLiquidationPairTokenOutAddress' +import { useLiquidationPairTokenOutAddress } from './useLiquidationPairTokenOutAddresses' export const useIsLiquidationPairTokenOutAVault = (chainId: number, lpAddress: Address) => { const publicClient = usePublicClient({ chainId }) diff --git a/apps/analytics/src/hooks/useLiquidationPairLiquidatableBalance.tsx b/apps/analytics/src/hooks/useLiquidationPairLiquidatableBalance.tsx index d6b59439..2e9a251d 100644 --- a/apps/analytics/src/hooks/useLiquidationPairLiquidatableBalance.tsx +++ b/apps/analytics/src/hooks/useLiquidationPairLiquidatableBalance.tsx @@ -3,7 +3,7 @@ import { liquidationPairABI, vaultABI } from '@shared/utilities' import { useQuery } from '@tanstack/react-query' import { Address } from 'viem' import { usePublicClient } from 'wagmi' -import { useLiquidationPairTokenOutAddress } from './useLiquidationPairTokenOutAddress' +import { useLiquidationPairTokenOutAddress } from './useLiquidationPairTokenOutAddresses' export const useLiquidationPairLiquidatableBalance = (chainId: number, lpAddress: Address) => { const publicClient = usePublicClient({ chainId }) diff --git a/apps/analytics/src/hooks/useLiquidationPairTokenInAddresses.tsx b/apps/analytics/src/hooks/useLiquidationPairTokenInAddresses.tsx new file mode 100644 index 00000000..dc0a9a01 --- /dev/null +++ b/apps/analytics/src/hooks/useLiquidationPairTokenInAddresses.tsx @@ -0,0 +1,52 @@ +import { NO_REFETCH } from '@shared/generic-react-hooks' +import { liquidationPairABI } from '@shared/utilities' +import { useQueries } from '@tanstack/react-query' +import { useMemo } from 'react' +import { Address } from 'viem' +import { usePublicClient } from 'wagmi' + +export const useLiquidationPairTokenInAddresses = (chainId: number, lpAddresses: Address[]) => { + const publicClient = usePublicClient({ chainId }) + + const results = useQueries({ + queries: lpAddresses.map((lpAddress) => { + return { + queryKey: ['lpTokenInAddress', chainId, lpAddress], + queryFn: async () => { + if (!!publicClient) { + return await publicClient.readContract({ + address: lpAddress, + abi: liquidationPairABI, + functionName: 'tokenIn' + }) + } + }, + enabled: !!publicClient && !!lpAddress, + ...NO_REFETCH + } + }) + }) + + return useMemo(() => { + const isFetched = results?.every((result) => result.isFetched) + + const data: { [lpAddress: Address]: Address } = {} + lpAddresses.forEach((lpAddress, i) => { + const tokenIn = results[i]?.data + if (!!tokenIn) { + data[lpAddress] = tokenIn + } + }) + + return { isFetched, data } + }, [results]) +} + +export const useLiquidationPairTokenInAddress = ( + chainId: number, + lpAddress: Address +): { data?: Address; isFetched: boolean } => { + const tokenInAddresses = useLiquidationPairTokenInAddresses(chainId, [lpAddress]) + + return { ...tokenInAddresses, data: tokenInAddresses.data[lpAddress] } +} diff --git a/apps/analytics/src/hooks/useLiquidationPairTokenOutAddress.tsx b/apps/analytics/src/hooks/useLiquidationPairTokenOutAddress.tsx deleted file mode 100644 index c3285987..00000000 --- a/apps/analytics/src/hooks/useLiquidationPairTokenOutAddress.tsx +++ /dev/null @@ -1,26 +0,0 @@ -import { NO_REFETCH } from '@shared/generic-react-hooks' -import { liquidationPairABI } from '@shared/utilities' -import { useQuery } from '@tanstack/react-query' -import { Address } from 'viem' -import { usePublicClient } from 'wagmi' - -export const useLiquidationPairTokenOutAddress = (chainId: number, lpAddress: Address) => { - const publicClient = usePublicClient({ chainId }) - - const queryKey = ['lpTokenOutAddress', chainId, lpAddress] - - return useQuery({ - queryKey, - queryFn: async () => { - if (!!publicClient) { - return await publicClient.readContract({ - address: lpAddress, - abi: liquidationPairABI, - functionName: 'tokenOut' - }) - } - }, - enabled: !!publicClient && !!lpAddress, - ...NO_REFETCH - }) -} diff --git a/apps/analytics/src/hooks/useLiquidationPairTokenOutAddresses.tsx b/apps/analytics/src/hooks/useLiquidationPairTokenOutAddresses.tsx index ff094283..56b8f82e 100644 --- a/apps/analytics/src/hooks/useLiquidationPairTokenOutAddresses.tsx +++ b/apps/analytics/src/hooks/useLiquidationPairTokenOutAddresses.tsx @@ -41,3 +41,12 @@ export const useLiquidationPairTokenOutAddresses = (chainId: number, lpAddresses return { isFetched, data } }, [results]) } + +export const useLiquidationPairTokenOutAddress = ( + chainId: number, + lpAddress: Address +): { data?: Address; isFetched: boolean } => { + const tokenOutAddresses = useLiquidationPairTokenOutAddresses(chainId, [lpAddress]) + + return { ...tokenOutAddresses, data: tokenOutAddresses.data[lpAddress] } +} diff --git a/apps/analytics/src/hooks/useLiquidationPairTokenOutData.tsx b/apps/analytics/src/hooks/useLiquidationPairTokenOutData.tsx index fee09ebb..09f33cd9 100644 --- a/apps/analytics/src/hooks/useLiquidationPairTokenOutData.tsx +++ b/apps/analytics/src/hooks/useLiquidationPairTokenOutData.tsx @@ -1,29 +1,18 @@ -import { Vault } from '@generationsoftware/hyperstructure-client-js' -import { useVaultShareData } from '@generationsoftware/hyperstructure-react-hooks' +import { useToken } from '@generationsoftware/hyperstructure-react-hooks' import { TokenWithSupply } from '@shared/types' -import { useMemo } from 'react' import { Address } from 'viem' -import { usePublicClient } from 'wagmi' -import { useLiquidationPairTokenOutAddress } from './useLiquidationPairTokenOutAddress' +import { useLiquidationPairTokenOutAddress } from './useLiquidationPairTokenOutAddresses' export const useLiquidationPairTokenOutData = ( chainId: number, lpAddress: Address ): { data?: TokenWithSupply; isFetched: boolean } => { - const publicClient = usePublicClient({ chainId }) - const { data: tokenOutAddress, isFetched: isFetchedTokenOutAddress } = useLiquidationPairTokenOutAddress(chainId, lpAddress) - const vault = useMemo(() => { - if (!!tokenOutAddress && !!publicClient) { - return new Vault(chainId, tokenOutAddress, publicClient) - } - }, [chainId, publicClient, tokenOutAddress]) - - const { data: shareToken, isFetched: isFetchedShareToken } = useVaultShareData(vault as Vault) + const { data: token, isFetched: isFetchedToken } = useToken(chainId, tokenOutAddress as Address) - const isFetched = isFetchedTokenOutAddress && isFetchedShareToken + const isFetched = isFetchedTokenOutAddress && isFetchedToken - return { data: shareToken, isFetched } + return { data: token, isFetched } } diff --git a/apps/analytics/src/hooks/useLiquidationPairTokenOutPrice.tsx b/apps/analytics/src/hooks/useLiquidationPairTokenOutPrice.tsx index 3554b3a4..54c25549 100644 --- a/apps/analytics/src/hooks/useLiquidationPairTokenOutPrice.tsx +++ b/apps/analytics/src/hooks/useLiquidationPairTokenOutPrice.tsx @@ -9,7 +9,7 @@ import { useMemo } from 'react' import { Address } from 'viem' import { usePublicClient } from 'wagmi' import { useIsLiquidationPairTokenOutAVault } from './useIsLiquidationPairTokenOutAVault' -import { useLiquidationPairTokenOutAddress } from './useLiquidationPairTokenOutAddress' +import { useLiquidationPairTokenOutAddress } from './useLiquidationPairTokenOutAddresses' export const useLiquidationPairTokenOutPrice = ( chainId: number, @@ -20,10 +20,7 @@ export const useLiquidationPairTokenOutPrice = ( const { data: tokenOutAddress, isFetched: isFetchedTokenOutAddress } = useLiquidationPairTokenOutAddress(chainId, lpAddress) - const { data: shareToken, isFetched: isFetchedShareToken } = useToken( - chainId, - tokenOutAddress as Address - ) + const { data: token, isFetched: isFetchedToken } = useToken(chainId, tokenOutAddress as Address) const { data: isValidVault, isFetched: isFetchedIsValidVault } = useIsLiquidationPairTokenOutAVault(chainId, lpAddress) @@ -40,14 +37,14 @@ export const useLiquidationPairTokenOutPrice = ( !!tokenOutAddress ? [tokenOutAddress] : [] ) - const isFetched = isFetchedTokenOutAddress && isFetchedShareToken && isFetchedTokenPrices + const isFetched = isFetchedTokenOutAddress && isFetchedToken && isFetchedTokenPrices - if (!!shareToken) { + if (!!token) { if (!!shareTokenWithPrice?.price) { return { data: shareTokenWithPrice, isFetched } } else if (!!tokenPrices && !!tokenOutAddress) { return { - data: { ...shareToken, price: tokenPrices[tokenOutAddress.toLowerCase() as Address] }, + data: { ...token, price: tokenPrices[tokenOutAddress.toLowerCase() as Address] }, isFetched } } From 8982c3069b6bd32ef5289ec0627204e1fc2ed954 Mon Sep 17 00:00:00 2001 From: Ncookiez Date: Mon, 4 Mar 2024 12:50:56 -0500 Subject: [PATCH 025/161] op goerli -> sepolia deployment --- apps/analytics/.env.example | 2 +- apps/analytics/src/constants/config.ts | 13 ++- .../src/blockchain/useClients.ts | 4 +- .../components/Icons/NetworkIcon.tsx | 1 - shared/react-components/constants.ts | 16 ++-- shared/utilities/constants.ts | 82 +++++++++---------- shared/utilities/utils/networks.ts | 4 - 7 files changed, 55 insertions(+), 67 deletions(-) diff --git a/apps/analytics/.env.example b/apps/analytics/.env.example index 8fe8d023..3710c75b 100644 --- a/apps/analytics/.env.example +++ b/apps/analytics/.env.example @@ -3,4 +3,4 @@ NEXT_PUBLIC_MAINNET_RPC_URL="YOUR_MAINNET_RPC_HERE" NEXT_PUBLIC_OPTIMISM_RPC_URL="YOUR_OPTIMISM_RPC_HERE" # Testnet RPC URLs -NEXT_PUBLIC_OPTIMISM_GOERLI_RPC_URL="YOUR_OPTIMISM_GOERLI_RPC_HERE" \ No newline at end of file +NEXT_PUBLIC_SEPOLIA_RPC_URL="YOUR_SEPOLIA_RPC_HERE" \ No newline at end of file diff --git a/apps/analytics/src/constants/config.ts b/apps/analytics/src/constants/config.ts index 3ed2c050..e7f1fa06 100644 --- a/apps/analytics/src/constants/config.ts +++ b/apps/analytics/src/constants/config.ts @@ -1,13 +1,13 @@ import { NETWORK } from '@shared/utilities' import { Address } from 'viem' -import { mainnet, optimism, optimismGoerli } from 'viem/chains' +import { mainnet, optimism, sepolia } from 'viem/chains' /** * Supported networks */ export const SUPPORTED_NETWORKS = { mainnets: [NETWORK.mainnet, NETWORK.optimism], - testnets: [NETWORK.optimism_goerli] + testnets: [NETWORK.sepolia] } as const /** @@ -16,7 +16,7 @@ export const SUPPORTED_NETWORKS = { export const WAGMI_CHAINS = { [NETWORK.mainnet]: mainnet, [NETWORK.optimism]: optimism, - [NETWORK.optimism_goerli]: optimismGoerli + [NETWORK.sepolia]: sepolia } as const /** @@ -25,22 +25,21 @@ export const WAGMI_CHAINS = { export const RPC_URLS = { [NETWORK.mainnet]: process.env.NEXT_PUBLIC_MAINNET_RPC_URL, [NETWORK.optimism]: process.env.NEXT_PUBLIC_OPTIMISM_RPC_URL, - [NETWORK.optimism_goerli]: process.env.NEXT_PUBLIC_OPTIMISM_GOERLI_RPC_URL + [NETWORK.sepolia]: process.env.NEXT_PUBLIC_SEPOLIA_RPC_URL } as const /** * Queries' start blocks */ export const QUERY_START_BLOCK: { [chainId: number]: bigint } = { - [NETWORK.optimism]: 108_927_000n, // TODO: update once prizepool deployed to mainnet - [NETWORK.optimism_goerli]: 21_785_000n + [NETWORK.sepolia]: 5_397_600n } /** * Draw results URL */ export const DRAW_RESULTS_URL: { [chainId: number]: string } = { - [NETWORK.optimism_goerli]: `https://raw.githubusercontent.com/GenerationSoftware/pt-v5-draw-results-testnet/main/prizes/${NETWORK.optimism_goerli}` + // [NETWORK.sepolia]: `https://raw.githubusercontent.com/GenerationSoftware/pt-v5-draw-results-testnet/main/prizes/${NETWORK.sepolia}` // TODO: uncomment once actions are setup } /** diff --git a/packages/hyperstructure-react-hooks/src/blockchain/useClients.ts b/packages/hyperstructure-react-hooks/src/blockchain/useClients.ts index 0d775556..e5ff9875 100644 --- a/packages/hyperstructure-react-hooks/src/blockchain/useClients.ts +++ b/packages/hyperstructure-react-hooks/src/blockchain/useClients.ts @@ -24,8 +24,8 @@ export const usePublicClients = (options?: { useAll?: boolean }): PublicClient[] usePublicClient({ chainId: NETWORK.celo }) ], testnets: [ + usePublicClient({ chainId: NETWORK.sepolia }), usePublicClient({ chainId: NETWORK.optimism_sepolia }), - usePublicClient({ chainId: NETWORK.optimism_goerli }), usePublicClient({ chainId: NETWORK.arbitrum_sepolia }) ] } @@ -68,8 +68,8 @@ export const usePublicClientsByChain = (options?: { [NETWORK.celo]: usePublicClient({ chainId: NETWORK.celo }) }, testnets: { + [NETWORK.sepolia]: usePublicClient({ chainId: NETWORK.sepolia }), [NETWORK.optimism_sepolia]: usePublicClient({ chainId: NETWORK.optimism_sepolia }), - [NETWORK.optimism_goerli]: usePublicClient({ chainId: NETWORK.optimism_goerli }), [NETWORK.arbitrum_sepolia]: usePublicClient({ chainId: NETWORK.arbitrum_sepolia }) } } diff --git a/shared/react-components/components/Icons/NetworkIcon.tsx b/shared/react-components/components/Icons/NetworkIcon.tsx index a0477bf4..3a6d9309 100644 --- a/shared/react-components/components/Icons/NetworkIcon.tsx +++ b/shared/react-components/components/Icons/NetworkIcon.tsx @@ -170,7 +170,6 @@ const icons = { [NETWORK.mumbai]: { svgIcon: PolygonIcon, iconBgColor: '#9f71ec' }, [NETWORK.optimism]: { svgIcon: OptimismIcon, iconBgColor: '#ff5a57' }, [NETWORK.optimism_sepolia]: { svgIcon: OptimismIcon, iconBgColor: '#ff5a57' }, - [NETWORK.optimism_goerli]: { svgIcon: OptimismIcon, iconBgColor: '#ff5a57' }, [NETWORK.arbitrum]: { svgIcon: ArbitrumIcon, iconBgColor: '#96bedc' }, [NETWORK.arbitrum_sepolia]: { svgIcon: ArbitrumIcon, iconBgColor: '#96bedc' } } diff --git a/shared/react-components/constants.ts b/shared/react-components/constants.ts index dc9e00b3..141c9cd7 100644 --- a/shared/react-components/constants.ts +++ b/shared/react-components/constants.ts @@ -30,7 +30,14 @@ export const TOKEN_LOGO_OVERRIDES: Record '0x2260fac5e5542a773aa44fbcfedf7c193bc2c599': tokenLogoUrls.wbtc, '0x5f98805a4e8be255a32880fdec7f6728c6568ba0': tokenLogoUrls.lusd }, - [NETWORK.sepolia]: {}, + [NETWORK.sepolia]: { + '0x196eef5231bc8806ddfdbaaf7b5ac206bd316f45': tokenLogoUrls.pool, + '0xd09eb8de85d547cfbf09f972edcc6f871b192b70': tokenLogoUrls.usdc, + '0x50088bf4dba58145c0b873643d285626f87837c3': tokenLogoUrls.dai, + '0x2b8919310d8e2576e19e22794a6d3ec961cd812a': tokenLogoUrls.gusd, + '0x00a66c161e4c7a9daefd3df8cbbb08a3de5b5f73': tokenLogoUrls.weth, + '0x0364994c88f97a18740ec791a336b2d63407f8d5': tokenLogoUrls.wbtc + }, [NETWORK.bsc]: {}, [NETWORK.bsc_testnet]: {}, [NETWORK.xdai]: {}, @@ -54,13 +61,6 @@ export const TOKEN_LOGO_OVERRIDES: Record '0x4200000000000000000000000000000000000042': tokenLogoUrls.op }, [NETWORK.optimism_sepolia]: {}, - [NETWORK.optimism_goerli]: { - '0x3e5bc94a341481f742f5f573d341fa2540bc0992': tokenLogoUrls.usdc, - '0xf6cff71208ffcab13223b31b036f2801d5de6d17': tokenLogoUrls.dai, - '0xabddb2c18a5d02f26a5ad5f4a361e4814dbe2175': tokenLogoUrls.gusd, - '0x0ba5e0722797dcea8cec409a707ce495c33fb23d': tokenLogoUrls.weth, - '0x3fa21c64666d1245dbc1836ded2e4b47979c6bee': tokenLogoUrls.wbtc - }, [NETWORK.avalanche]: { '0x2f2a2543b76a4166549f7aab2e75bef0aefc5b0f': tokenLogoUrls.wbtc }, diff --git a/shared/utilities/constants.ts b/shared/utilities/constants.ts index 8d2eab8c..74484083 100644 --- a/shared/utilities/constants.ts +++ b/shared/utilities/constants.ts @@ -13,7 +13,6 @@ export enum NETWORK { mumbai = 80001, optimism = 10, optimism_sepolia = 11155420, - optimism_goerli = 420, avalanche = 43114, fuji = 43113, celo = 42220, @@ -32,7 +31,7 @@ export const POOL_TOKEN_ADDRESSES = { [NETWORK.mainnet]: '0x0cEC1A9154Ff802e7934Fc916Ed7Ca50bDE6844e', [NETWORK.polygon]: '0x25788a1a171ec66Da6502f9975a15B609fF54CF6', [NETWORK.optimism]: '0x395ae52bb17aef68c2888d941736a71dc6d4e125', - [NETWORK.optimism_goerli]: '0x80D4D92731ae0239c536E53001FF30D07D05f65B' + [NETWORK.sepolia]: '0x196EEF5231Bc8806ddFdBAaF7b5aC206Bd316f45' } as const /** @@ -44,8 +43,8 @@ export const USDC_TOKEN_ADDRESSES: { [chainId: number]: Lowercase
} = { [NETWORK.mainnet]: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48', [NETWORK.polygon]: '0x2791bca1f2de4661ed88a30c99a7a9449aa84174', [NETWORK.optimism]: '0x7f5c764cbc14f9669b88837ca1490cca17c31607', - [NETWORK.optimism_goerli]: '0x3e5bc94a341481f742f5f573d341fa2540bc0992', - [NETWORK.arbitrum]: '0xff970a61a04b1ca14834a43f5de4533ebddb5cc8' + [NETWORK.arbitrum]: '0xff970a61a04b1ca14834a43f5de4533ebddb5cc8', + [NETWORK.sepolia]: '0xd09eb8de85d547cfbf09f972edcc6f871b192b70' } /** @@ -85,20 +84,20 @@ export const PRIZE_POOLS: { drawManagerAddress: Address twabControllerAddress: Address drawPeriodInSeconds: number - drawActionDurationInSeconds: number + drawAuctionDurationInSeconds: number tierShares: number reserveShares: number } }[] = [ { - chainId: NETWORK.optimism_goerli, - address: '0x6cdd88A97801aD20F2dcfd14f1F9370e54757536', + chainId: NETWORK.sepolia, + address: '0x934F03f3132d3B818d7c07F25818ea3961eF18aD', options: { - prizeTokenAddress: '0x0Ba5e0722797dcEa8Cec409a707cE495C33fB23D', - drawManagerAddress: '0x512c1421D4f6f6c01A7508E060595ee08A652f69', - twabControllerAddress: '0x53f5545055f3804B7fD694081f9a13b3abceB38E', + prizeTokenAddress: '0x00a66C161e4C7A9dAEFd3dF8Cbbb08a3DE5b5F73', + drawManagerAddress: '0xF21086aef81Eb3F5535B4bC8BA172bcFB5f1f3b4', + twabControllerAddress: '0x1F834baC8e84A4a4367025CE9e9BdCE85302dFdE', drawPeriodInSeconds: 7_200, - drawActionDurationInSeconds: 2_400, + drawAuctionDurationInSeconds: 2_400, tierShares: 100, reserveShares: 20 } @@ -109,8 +108,7 @@ export const PRIZE_POOLS: { * Subgraph API URLs */ export const SUBGRAPH_API_URLS = { - [NETWORK.optimism_goerli]: - 'https://api.studio.thegraph.com/query/63100/pt-v5-op-goerli-new/version/latest' + // TODO: add subgraph apis when available } as const /** @@ -141,7 +139,6 @@ export const COINGECKO_NATIVE_TOKEN_IDS: Record = { [NETWORK.mumbai]: 'matic-network', [NETWORK.optimism]: 'ethereum', [NETWORK.optimism_sepolia]: 'ethereum', - [NETWORK.optimism_goerli]: 'ethereum', [NETWORK.avalanche]: 'avalanche-2', [NETWORK.fuji]: 'avalanche-2', [NETWORK.celo]: 'celo', @@ -165,7 +162,6 @@ export const BLOCK_EXPLORERS: Record = { [NETWORK.mumbai]: { name: 'Polygonscan', url: 'https://mumbai.polygonscan.com/' }, [NETWORK.optimism]: { name: 'Etherscan', url: 'https://optimistic.etherscan.io/' }, [NETWORK.optimism_sepolia]: { name: 'Etherscan', url: 'https://sepolia-optimism.etherscan.io/' }, - [NETWORK.optimism_goerli]: { name: 'Etherscan', url: 'https://goerli-optimism.etherscan.io/' }, [NETWORK.avalanche]: { name: 'Snowtrace', url: 'https://snowtrace.io/' }, [NETWORK.fuji]: { name: 'Snowtrace', url: 'https://testnet.snowtrace.io/' }, [NETWORK.celo]: { name: 'Celoscan', url: 'https://celoscan.io/' }, @@ -187,7 +183,11 @@ export const STABLECOINS: Record = { '0x6b175474e89094c44da98b954eedeac495271d0f': 'usd', // DAI '0x056fd409e1d7a124bd7017459dfea2f387b6d5cd': 'usd' // GUSD }, - [NETWORK.sepolia]: {}, + [NETWORK.sepolia]: { + '0xd09eb8de85d547cfbf09f972edcc6f871b192b70': 'usd', // USDC + '0x50088bf4dba58145c0b873643d285626f87837c3': 'usd', // DAI + '0x2b8919310d8e2576e19e22794a6d3ec961cd812a': 'usd' // GUSD + }, [NETWORK.bsc]: {}, [NETWORK.bsc_testnet]: {}, [NETWORK.xdai]: {}, @@ -202,11 +202,6 @@ export const STABLECOINS: Record = { '0xc40f949f8a4e094d1b49a23ea9241d289b7b2819': 'usd' // LUSD }, [NETWORK.optimism_sepolia]: {}, - [NETWORK.optimism_goerli]: { - '0x3e5bc94a341481f742f5f573d341fa2540bc0992': 'usd', // USDC - '0xf6cff71208ffcab13223b31b036f2801d5de6d17': 'usd', // DAI - '0xabddb2c18a5d02f26a5ad5f4a361e4814dbe2175': 'usd' // GUSD - }, [NETWORK.avalanche]: { '0xa7d7079b0fead91f3e65f86e8915cb59c1a4c664': 'usd' // USDC.e }, @@ -234,7 +229,6 @@ export const WRAPPED_NATIVE_ASSETS: Record = { [NETWORK.mumbai]: null, [NETWORK.optimism]: '0x4200000000000000000000000000000000000006', [NETWORK.optimism_sepolia]: null, - [NETWORK.optimism_goerli]: null, [NETWORK.avalanche]: '0xb31f66aa3c1e785363f0875a1b74e27b85fd66c7', [NETWORK.fuji]: null, [NETWORK.celo]: null, @@ -249,35 +243,35 @@ export const WRAPPED_NATIVE_ASSETS: Record = { * TWAB rewards addresses */ export const TWAB_REWARDS_ADDRESSES: { [chainId: number]: Address } = { - [NETWORK.optimism_goerli]: '0x24cf54ecd8eC53Eda05394c839AAb3B67fF8aF19' + [NETWORK.sepolia]: '0x3668d73fe09244b6F66B601285076715A09eD07F' } /** * Vault factory addresses */ export const VAULT_FACTORY_ADDRESSES: { [chainId: number]: Address } = { - [NETWORK.optimism_goerli]: '0x644Ba78d965e276C9617F18AfD5357564B59a1Ae' + [NETWORK.sepolia]: '0x3874f4fD4b089e1a013b18870b2B1b83eCe57349' } /** * Liquidation pair factory addresses */ export const LIQUIDATION_PAIR_FACTORY_ADDRESSES: { [chainId: number]: Address } = { - [NETWORK.optimism_goerli]: '0xA7923D5331d079F2fC300eDD3594E9bbF5fBb45B' + [NETWORK.sepolia]: '0x4FeaaefBb5767d577547d8B1eB61Bfec172A7525' } /** * Default claimer addresses */ export const DEFAULT_CLAIMER_ADDRESSES: { [chainId: number]: Address } = { - [NETWORK.optimism_goerli]: '0x23b832b1EDb3986d52bB19CAB90BC0501F508500' + [NETWORK.sepolia]: '0xd6d4668AE64FF24fFF82b0DF7d12e7A5Ec936555' } /** * Liquidation router addresses */ export const LIQUIDATION_ROUTER_ADDRESSES: { [chainId: number]: Address } = { - [NETWORK.optimism_goerli]: '0xC238AA2E03EC39bF774Bb18Fb41997962c5AB0d3' + [NETWORK.sepolia]: '0xB0A9467863837D09e2C7A7a78F6A68F8857999Af' } /** @@ -332,41 +326,41 @@ export const TOKEN_PRICE_REDIRECTS: { address: '0x0000000000000000000000000000000000001010' } }, - [NETWORK.optimism_goerli]: { + [NETWORK.sepolia]: { /* ETH */ [DOLPHIN_ADDRESS]: { chainId: NETWORK.mainnet, address: DOLPHIN_ADDRESS }, /* DAI */ - '0xf6cff71208ffcab13223b31b036f2801d5de6d17': { - chainId: NETWORK.optimism, - address: '0xda10009cbd5d07dd0cecc66161fc93d7c9000da1' + '0x50088bf4dba58145c0b873643d285626f87837c3': { + chainId: NETWORK.mainnet, + address: '0x6b175474e89094c44da98b954eedeac495271d0f' }, /* USDC */ - '0x3e5bc94a341481f742f5f573d341fa2540bc0992': { - chainId: NETWORK.optimism, - address: USDC_TOKEN_ADDRESSES[NETWORK.optimism] + [USDC_TOKEN_ADDRESSES[NETWORK.sepolia]]: { + chainId: NETWORK.mainnet, + address: USDC_TOKEN_ADDRESSES[NETWORK.mainnet] }, /* GUSD */ - '0xabddb2c18a5d02f26a5ad5f4a361e4814dbe2175': { + '0x2b8919310d8e2576e19e22794a6d3ec961cd812a': { chainId: NETWORK.mainnet, address: '0x056fd409e1d7a124bd7017459dfea2f387b6d5cd' }, /* WBTC */ - '0x3fa21c64666d1245dbc1836ded2e4b47979c6bee': { - chainId: NETWORK.optimism, - address: '0x68f180fcce6836688e9084f035309e29bf0a2095' + '0x0364994c88f97a18740ec791a336b2d63407f8d5': { + chainId: NETWORK.mainnet, + address: '0x2260fac5e5542a773aa44fbcfedf7c193bc2c599' }, /* WETH */ - '0x0ba5e0722797dcea8cec409a707ce495c33fb23d': { - chainId: NETWORK.optimism, - address: WRAPPED_NATIVE_ASSETS[NETWORK.optimism] as Address + '0x00a66c161e4c7a9daefd3df8cbbb08a3de5b5f73': { + chainId: NETWORK.mainnet, + address: WRAPPED_NATIVE_ASSETS[NETWORK.mainnet] as Address }, /* POOL */ - '0x80d4d92731ae0239c536e53001ff30d07d05f65b': { - chainId: NETWORK.optimism, - address: POOL_TOKEN_ADDRESSES[NETWORK.optimism] + [POOL_TOKEN_ADDRESSES[NETWORK.sepolia]]: { + chainId: NETWORK.mainnet, + address: POOL_TOKEN_ADDRESSES[NETWORK.mainnet] } } } diff --git a/shared/utilities/utils/networks.ts b/shared/utilities/utils/networks.ts index 0da28c0e..639d32a9 100644 --- a/shared/utilities/utils/networks.ts +++ b/shared/utilities/utils/networks.ts @@ -31,9 +31,6 @@ export const getNiceNetworkNameByChainId = (chainId: number): string => { case NETWORK.optimism_sepolia: { return 'Optimism Sepolia' } - case NETWORK.optimism_goerli: { - return 'Optimism Goerli' - } case NETWORK.arbitrum_sepolia: { return 'Arbitrum Sepolia' } @@ -66,7 +63,6 @@ export const isTestnet = (chainId: number) => { [NETWORK.mumbai]: true, [NETWORK.optimism]: false, [NETWORK.optimism_sepolia]: true, - [NETWORK.optimism_goerli]: true, [NETWORK.avalanche]: false, [NETWORK.fuji]: true, [NETWORK.celo]: false, From fed68cca07adf91bc1d54ca58bc6b118cd965c61 Mon Sep 17 00:00:00 2001 From: Ncookiez Date: Mon, 4 Mar 2024 12:54:17 -0500 Subject: [PATCH 026/161] abi updates --- shared/utilities/abis/drawManager.ts | 116 ++++++++++++++++---------- shared/utilities/abis/vault.ts | 16 +--- shared/utilities/abis/vaultFactory.ts | 8 +- 3 files changed, 84 insertions(+), 56 deletions(-) diff --git a/shared/utilities/abis/drawManager.ts b/shared/utilities/abis/drawManager.ts index 1e47d34c..320f880b 100644 --- a/shared/utilities/abis/drawManager.ts +++ b/shared/utilities/abis/drawManager.ts @@ -1,66 +1,97 @@ export const drawManagerABI = [ { - inputs: [ - { internalType: 'uint256', name: '_timestamp', type: 'uint256' }, - { internalType: 'uint256', name: '_drawClosedAt', type: 'uint256' } - ], - name: '_elapsedTimeSinceDrawClosed', - outputs: [{ internalType: 'uint64', name: '', type: 'uint64' }], + inputs: [], + name: 'auctionDuration', + outputs: [{ internalType: 'uint48', name: '', type: 'uint48' }], stateMutability: 'view', type: 'function' }, { inputs: [], - name: 'auctionDuration', - outputs: [{ internalType: 'uint64', name: '', type: 'uint64' }], + name: 'auctionTargetTime', + outputs: [{ internalType: 'uint48', name: '', type: 'uint48' }], stateMutability: 'view', type: 'function' }, { inputs: [], - name: 'auctionTargetTime', - outputs: [{ internalType: 'uint64', name: '', type: 'uint64' }], + name: 'canFinishDraw', + outputs: [{ internalType: 'bool', name: '', type: 'bool' }], stateMutability: 'view', type: 'function' }, { - inputs: [{ internalType: 'address', name: '_rewardRecipient', type: 'address' }], - name: 'awardDraw', - outputs: [{ internalType: 'uint24', name: '', type: 'uint24' }], - stateMutability: 'nonpayable', + inputs: [], + name: 'canStartDraw', + outputs: [{ internalType: 'bool', name: '', type: 'bool' }], + stateMutability: 'view', type: 'function' }, { - inputs: [], - name: 'awardDrawFee', - outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + inputs: [{ internalType: 'uint48', name: '_elapsedTime', type: 'uint48' }], + name: 'computeFinishDrawRewardFraction', + outputs: [{ internalType: 'UD2x18', name: '', type: 'uint64' }], stateMutability: 'view', type: 'function' }, { - inputs: [], - name: 'canAwardDraw', - outputs: [{ internalType: 'bool', name: '', type: 'bool' }], + inputs: [ + { internalType: 'UD2x18[]', name: '_rewardFractions', type: 'uint64[]' }, + { internalType: 'uint256', name: '_reserve', type: 'uint256' } + ], + name: 'computeRewards', + outputs: [{ internalType: 'uint256[]', name: 'rewardAmounts', type: 'uint256[]' }], + stateMutability: 'pure', + type: 'function' + }, + { + inputs: [ + { internalType: 'uint48', name: '_startDrawElapsedTime', type: 'uint48' }, + { internalType: 'uint48', name: '_finishDrawElapsedTime', type: 'uint48' }, + { internalType: 'uint256', name: '_totalReserve', type: 'uint256' } + ], + name: 'computeRewards', + outputs: [ + { internalType: 'uint256[]', name: 'rewards', type: 'uint256[]' }, + { internalType: 'uint256', name: 'remainingReserve', type: 'uint256' } + ], stateMutability: 'view', type: 'function' }, { - inputs: [], - name: 'canStartDraw', - outputs: [{ internalType: 'bool', name: '', type: 'bool' }], + inputs: [ + { internalType: 'uint48', name: '_startDrawElapsedTime', type: 'uint48' }, + { internalType: 'uint256', name: '_totalReserve', type: 'uint256' } + ], + name: 'computeStartDrawReward', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function' + }, + { + inputs: [{ internalType: 'uint48', name: '_elapsedTime', type: 'uint48' }], + name: 'computeStartDrawRewardFraction', + outputs: [{ internalType: 'UD2x18', name: '', type: 'uint64' }], stateMutability: 'view', type: 'function' }, + { + inputs: [{ internalType: 'address', name: '_rewardRecipient', type: 'address' }], + name: 'finishDraw', + outputs: [{ internalType: 'uint24', name: '', type: 'uint24' }], + stateMutability: 'nonpayable', + type: 'function' + }, { inputs: [], - name: 'elapsedTimeSinceDrawClosed', - outputs: [{ internalType: 'uint64', name: '', type: 'uint64' }], + name: 'finishDrawReward', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], stateMutability: 'view', type: 'function' }, { inputs: [], - name: 'getLastAuction', + name: 'getLastStartDrawAuction', outputs: [ { components: [ @@ -69,7 +100,7 @@ export const drawManagerABI = [ { internalType: 'uint24', name: 'drawId', type: 'uint24' }, { internalType: 'uint32', name: 'rngRequestId', type: 'uint32' } ], - internalType: 'struct StartRngRequestAuction', + internalType: 'struct StartDrawAuction', name: '', type: 'tuple' } @@ -79,14 +110,14 @@ export const drawManagerABI = [ }, { inputs: [], - name: 'lastAwardDrawFraction', + name: 'lastFinishDrawFraction', outputs: [{ internalType: 'UD2x18', name: '', type: 'uint64' }], stateMutability: 'view', type: 'function' }, { inputs: [], - name: 'lastStartRngRequestFraction', + name: 'lastStartDrawFraction', outputs: [{ internalType: 'UD2x18', name: '', type: 'uint64' }], stateMutability: 'view', type: 'function' @@ -125,13 +156,13 @@ export const drawManagerABI = [ { internalType: 'uint32', name: '_rngRequestId', type: 'uint32' } ], name: 'startDraw', - outputs: [], + outputs: [{ internalType: 'uint24', name: '', type: 'uint24' }], stateMutability: 'nonpayable', type: 'function' }, { inputs: [], - name: 'startDrawFee', + name: 'startDrawReward', outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], stateMutability: 'view', type: 'function' @@ -140,13 +171,14 @@ export const drawManagerABI = [ anonymous: false, inputs: [ { indexed: true, internalType: 'uint24', name: 'drawId', type: 'uint24' }, + { indexed: false, internalType: 'uint256', name: 'elapsedTime', type: 'uint256' }, { indexed: true, internalType: 'address', name: 'startRecipient', type: 'address' }, { indexed: false, internalType: 'uint256', name: 'startReward', type: 'uint256' }, - { indexed: true, internalType: 'address', name: 'awardRecipient', type: 'address' }, - { indexed: false, internalType: 'uint256', name: 'awardReward', type: 'uint256' }, + { indexed: true, internalType: 'address', name: 'finishRecipient', type: 'address' }, + { indexed: false, internalType: 'uint256', name: 'finishReward', type: 'uint256' }, { indexed: false, internalType: 'uint256', name: 'remainingReserve', type: 'uint256' } ], - name: 'DrawAwarded', + name: 'DrawFinished', type: 'event' }, { @@ -156,27 +188,28 @@ export const drawManagerABI = [ { indexed: true, internalType: 'address', name: 'recipient', type: 'address' }, { indexed: false, internalType: 'uint24', name: 'drawId', type: 'uint24' }, { indexed: false, internalType: 'uint32', name: 'rngRequestId', type: 'uint32' }, - { indexed: false, internalType: 'uint64', name: 'elapsedTime', type: 'uint64' } + { indexed: false, internalType: 'uint48', name: 'elapsedTime', type: 'uint48' } ], - name: 'RngAuctionCompleted', + name: 'DrawStarted', type: 'event' }, + { inputs: [], name: 'AlreadyStartedDraw', type: 'error' }, { - inputs: [{ internalType: 'uint64', name: 'auctionDuration', type: 'uint64' }], + inputs: [{ internalType: 'uint48', name: 'auctionDuration', type: 'uint48' }], name: 'AuctionDurationGTDrawPeriodSeconds', type: 'error' }, { inputs: [], name: 'AuctionExpired', type: 'error' }, { inputs: [ - { internalType: 'uint64', name: 'auctionTargetTime', type: 'uint64' }, - { internalType: 'uint64', name: 'auctionDuration', type: 'uint64' } + { internalType: 'uint48', name: 'auctionTargetTime', type: 'uint48' }, + { internalType: 'uint48', name: 'auctionDuration', type: 'uint48' } ], name: 'AuctionTargetTimeExceedsDuration', type: 'error' }, - { inputs: [], name: 'CannotStartRngRequest', type: 'error' }, - { inputs: [], name: 'DrawHasExpired', type: 'error' }, + { inputs: [], name: 'DrawHasFinalized', type: 'error' }, + { inputs: [], name: 'DrawHasNotClosed', type: 'error' }, { inputs: [ { internalType: 'uint256', name: 'x', type: 'uint256' }, @@ -205,7 +238,6 @@ export const drawManagerABI = [ type: 'error' }, { inputs: [], name: 'RewardRecipientIsZero', type: 'error' }, - { inputs: [], name: 'RewardRecipientIsZeroAddress', type: 'error' }, { inputs: [], name: 'RngRequestNotComplete', type: 'error' }, { inputs: [], name: 'RngRequestNotInSameBlock', type: 'error' }, { inputs: [], name: 'TargetRewardFractionGTOne', type: 'error' } diff --git a/shared/utilities/abis/vault.ts b/shared/utilities/abis/vault.ts index 599cf417..d027632e 100644 --- a/shared/utilities/abis/vault.ts +++ b/shared/utilities/abis/vault.ts @@ -80,8 +80,8 @@ export const vaultABI = [ { internalType: 'address', name: '_winner', type: 'address' }, { internalType: 'uint8', name: '_tier', type: 'uint8' }, { internalType: 'uint32', name: '_prizeIndex', type: 'uint32' }, - { internalType: 'uint96', name: '_fee', type: 'uint96' }, - { internalType: 'address', name: '_feeRecipient', type: 'address' } + { internalType: 'uint96', name: '_reward', type: 'uint96' }, + { internalType: 'address', name: '_rewardRecipient', type: 'address' } ], name: 'claimPrize', outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], @@ -113,7 +113,7 @@ export const vaultABI = [ inputs: [{ internalType: 'uint256', name: '_assets', type: 'uint256' }], name: 'convertToShares', outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], - stateMutability: 'pure', + stateMutability: 'view', type: 'function' }, { @@ -766,16 +766,6 @@ export const vaultABI = [ }, { inputs: [], name: 'MintZeroShares', type: 'error' }, { inputs: [], name: 'OwnerZeroAddress', type: 'error' }, - { - inputs: [ - { internalType: 'address', name: 'owner', type: 'address' }, - { internalType: 'address', name: 'spender', type: 'address' }, - { internalType: 'uint256', name: 'amount', type: 'uint256' }, - { internalType: 'uint256', name: 'allowance', type: 'uint256' } - ], - name: 'PermitAllowanceNotSet', - type: 'error' - }, { inputs: [ { internalType: 'address', name: 'caller', type: 'address' }, diff --git a/shared/utilities/abis/vaultFactory.ts b/shared/utilities/abis/vaultFactory.ts index 3de8d84a..16e26148 100644 --- a/shared/utilities/abis/vaultFactory.ts +++ b/shared/utilities/abis/vaultFactory.ts @@ -1,4 +1,11 @@ export const vaultFactoryABI = [ + { + inputs: [], + name: 'YIELD_BUFFER', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function' + }, { inputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], name: 'allVaults', @@ -15,7 +22,6 @@ export const vaultFactoryABI = [ { internalType: 'address', name: '_claimer', type: 'address' }, { internalType: 'address', name: '_yieldFeeRecipient', type: 'address' }, { internalType: 'uint32', name: '_yieldFeePercentage', type: 'uint32' }, - { internalType: 'uint256', name: '_yieldBuffer', type: 'uint256' }, { internalType: 'address', name: '_owner', type: 'address' } ], name: 'deployVault', From 77922de576edb54bba735a28d3c16b894d72e5b9 Mon Sep 17 00:00:00 2001 From: Ncookiez Date: Mon, 4 Mar 2024 12:59:28 -0500 Subject: [PATCH 027/161] vaultfactory + drawmanager abi change fixes --- .../src/hooks/useCurrentDrawAwardReward.tsx | 2 +- .../src/hooks/useCurrentRngAuctionReward.tsx | 2 +- packages/hyperstructure-client-js/src/PrizePool.ts | 12 +++++------- .../transactions/useSendDeployVaultTransaction.ts | 3 --- shared/types/types/vaults.ts | 1 - 5 files changed, 7 insertions(+), 13 deletions(-) diff --git a/apps/analytics/src/hooks/useCurrentDrawAwardReward.tsx b/apps/analytics/src/hooks/useCurrentDrawAwardReward.tsx index 26739244..651fb0a9 100644 --- a/apps/analytics/src/hooks/useCurrentDrawAwardReward.tsx +++ b/apps/analytics/src/hooks/useCurrentDrawAwardReward.tsx @@ -19,7 +19,7 @@ export const useCurrentDrawAwardReward = ( return await publicClient.readContract({ address: drawManagerAddress, abi: drawManagerABI, - functionName: 'awardDrawFee' + functionName: 'finishDrawReward' }) } }, diff --git a/apps/analytics/src/hooks/useCurrentRngAuctionReward.tsx b/apps/analytics/src/hooks/useCurrentRngAuctionReward.tsx index 6092fd4d..d11c5509 100644 --- a/apps/analytics/src/hooks/useCurrentRngAuctionReward.tsx +++ b/apps/analytics/src/hooks/useCurrentRngAuctionReward.tsx @@ -19,7 +19,7 @@ export const useCurrentRngAuctionReward = ( return await publicClient.readContract({ address: drawManagerAddress, abi: drawManagerABI, - functionName: 'startDrawFee' + functionName: 'startDrawReward' }) } }, diff --git a/packages/hyperstructure-client-js/src/PrizePool.ts b/packages/hyperstructure-client-js/src/PrizePool.ts index 5070ceca..c1749a2b 100644 --- a/packages/hyperstructure-client-js/src/PrizePool.ts +++ b/packages/hyperstructure-client-js/src/PrizePool.ts @@ -172,13 +172,11 @@ export class PrizePool { const drawManagerAddress = await this.getDrawManagerAddress() - const drawAuctionDurationInSeconds = Number( - await this.publicClient.readContract({ - address: drawManagerAddress, - abi: drawManagerABI, - functionName: 'auctionDuration' - }) - ) + const drawAuctionDurationInSeconds = await this.publicClient.readContract({ + address: drawManagerAddress, + abi: drawManagerABI, + functionName: 'auctionDuration' + }) this.drawAuctionDurationInSeconds = drawAuctionDurationInSeconds return drawAuctionDurationInSeconds diff --git a/packages/hyperstructure-react-hooks/src/transactions/useSendDeployVaultTransaction.ts b/packages/hyperstructure-react-hooks/src/transactions/useSendDeployVaultTransaction.ts index cb864bd4..17735af9 100644 --- a/packages/hyperstructure-react-hooks/src/transactions/useSendDeployVaultTransaction.ts +++ b/packages/hyperstructure-react-hooks/src/transactions/useSendDeployVaultTransaction.ts @@ -42,7 +42,6 @@ export const useSendDeployVaultTransaction = ( claimer, feeRecipient, feePercentage, - yieldBuffer, owner } = vaultDeployInfo @@ -62,7 +61,6 @@ export const useSendDeployVaultTransaction = ( !!claimer && !!feeRecipient && feePercentage !== undefined && - yieldBuffer !== undefined && !!owner && !!vaultFactoryAddress && chain?.id === chainId @@ -80,7 +78,6 @@ export const useSendDeployVaultTransaction = ( claimer, feeRecipient, feePercentage, - yieldBuffer, owner ], query: { enabled } diff --git a/shared/types/types/vaults.ts b/shared/types/types/vaults.ts index 2ceb720e..799a6d43 100644 --- a/shared/types/types/vaults.ts +++ b/shared/types/types/vaults.ts @@ -62,6 +62,5 @@ export interface VaultDeployInfo { claimer: `0x${string}` feeRecipient: `0x${string}` feePercentage: number - yieldBuffer: bigint owner: `0x${string}` } From 678a3cd95466234c23616c8f10016bdc7b4d0635 Mon Sep 17 00:00:00 2001 From: Ncookiez Date: Mon, 4 Mar 2024 15:10:35 -0500 Subject: [PATCH 028/161] fixed event query functions for new ABIs --- .../src/components/Charts/BurnChart.tsx | 20 +-- .../Charts/DrawAvgClaimFeesChart.tsx | 6 +- .../Charts/DrawsAvgClaimFeesChart.tsx | 6 +- .../src/components/Charts/ReserveChart.tsx | 20 +-- apps/analytics/src/components/ClaimFees.tsx | 12 +- .../src/components/Draws/DrawAwardReward.tsx | 14 +- .../src/components/Draws/DrawPrizes.tsx | 12 +- .../src/components/Draws/DrawRngReward.tsx | 14 +- .../src/components/Prizes/PrizesTable.tsx | 10 +- .../analytics/src/hooks/useAllDrawsStatus.tsx | 6 +- apps/analytics/src/hooks/useDrawStatus.tsx | 6 +- apps/analytics/src/hooks/useRngTxs.tsx | 140 +++++++++--------- packages/hyperstructure-react-hooks/README.md | 6 +- .../src/constants.ts | 4 +- ...ardedEvents.ts => useDrawAwardedEvents.ts} | 13 +- ...rdedEvents.ts => useDrawFinishedEvents.ts} | 13 +- ...letedEvents.ts => useDrawStartedEvents.ts} | 10 +- .../hyperstructure-react-hooks/src/index.ts | 6 +- shared/utilities/utils/events.ts | 21 +-- 19 files changed, 168 insertions(+), 171 deletions(-) rename packages/hyperstructure-react-hooks/src/events/{usePrizePoolDrawAwardedEvents.ts => useDrawAwardedEvents.ts} (68%) rename packages/hyperstructure-react-hooks/src/events/{useDrawManagerDrawAwardedEvents.ts => useDrawFinishedEvents.ts} (69%) rename packages/hyperstructure-react-hooks/src/events/{useRngAuctionCompletedEvents.ts => useDrawStartedEvents.ts} (75%) diff --git a/apps/analytics/src/components/Charts/BurnChart.tsx b/apps/analytics/src/components/Charts/BurnChart.tsx index f4f275a9..81335b87 100644 --- a/apps/analytics/src/components/Charts/BurnChart.tsx +++ b/apps/analytics/src/components/Charts/BurnChart.tsx @@ -17,7 +17,7 @@ import { currentTimestampAtom } from 'src/atoms' import { Address, formatUnits } from 'viem' import { BurnCard } from '@components/Burn/BurnCard' import { BURN_ADDRESSES, QUERY_START_BLOCK } from '@constants/config' -import { DrawAwardTx, RngAuctionTx, useRngTxs } from '@hooks/useRngTxs' +import { DrawFinishTx, DrawStartTx, useRngTxs } from '@hooks/useRngTxs' import { AreaChart } from './AreaChart' interface DataPoint { @@ -56,14 +56,14 @@ export const BurnChart = (props: BurnChartProps) => { return parseFloat(formatUnits(val, burnToken.decimals)) } - const validRngTxs = rngTxs.filter((txs) => !!txs.drawAward) as { - rngAuction: RngAuctionTx - drawAward: DrawAwardTx + const validRngTxs = rngTxs.filter((txs) => !!txs.drawFinish) as { + drawStart: DrawStartTx + drawFinish: DrawFinishTx }[] - const firstRngBlockNumber = validRngTxs[0]?.drawAward.blockNumber ?? MAX_UINT_256 + const firstRngBlockNumber = validRngTxs[0]?.drawFinish.blockNumber ?? MAX_UINT_256 const lastRngBlockNumber = - validRngTxs[validRngTxs.length - 1]?.drawAward.blockNumber ?? MAX_UINT_256 + validRngTxs[validRngTxs.length - 1]?.drawFinish.blockNumber ?? MAX_UINT_256 let dead = { total: 0, change: 0 } let other = { total: 0, change: 0 } @@ -98,10 +98,10 @@ export const BurnChart = (props: BurnChartProps) => { updateBurnAmounts(`Start-${firstDrawOpenedAt}`, 0n, firstRngBlockNumber) validRngTxs.forEach((txs, i) => { - const drawId = txs.drawAward.drawId - const awardedAt = txs.drawAward.timestamp - const minBlock = validRngTxs[i].drawAward.blockNumber - const maxBlock = validRngTxs[i + 1]?.drawAward.blockNumber ?? 0n + const drawId = txs.drawFinish.drawId + const awardedAt = txs.drawFinish.timestamp + const minBlock = validRngTxs[i].drawFinish.blockNumber + const maxBlock = validRngTxs[i + 1]?.drawFinish.blockNumber ?? 0n updateBurnAmounts(`${drawId}-${awardedAt}`, minBlock, maxBlock) }) diff --git a/apps/analytics/src/components/Charts/DrawAvgClaimFeesChart.tsx b/apps/analytics/src/components/Charts/DrawAvgClaimFeesChart.tsx index 80e5a0e7..f558e505 100644 --- a/apps/analytics/src/components/Charts/DrawAvgClaimFeesChart.tsx +++ b/apps/analytics/src/components/Charts/DrawAvgClaimFeesChart.tsx @@ -1,7 +1,7 @@ import { PrizePool } from '@generationsoftware/hyperstructure-client-js' import { - usePrizeDrawWinners, - usePrizePoolDrawAwardedEvents + useDrawAwardedEvents, + usePrizeDrawWinners } from '@generationsoftware/hyperstructure-react-hooks' import { divideBigInts, @@ -33,7 +33,7 @@ export const DrawAvgClaimFeesChart = (props: DrawAvgClaimFeesChartProps) => { const { closedAt, awardedAt, finalizedAt } = useDrawStatus(prizePool, drawId) - const { data: drawAwardedEvents } = usePrizePoolDrawAwardedEvents(prizePool, { + const { data: drawAwardedEvents } = useDrawAwardedEvents(prizePool, { fromBlock: !!prizePool ? QUERY_START_BLOCK[prizePool.chainId] : undefined }) diff --git a/apps/analytics/src/components/Charts/DrawsAvgClaimFeesChart.tsx b/apps/analytics/src/components/Charts/DrawsAvgClaimFeesChart.tsx index 54669bbd..5c224401 100644 --- a/apps/analytics/src/components/Charts/DrawsAvgClaimFeesChart.tsx +++ b/apps/analytics/src/components/Charts/DrawsAvgClaimFeesChart.tsx @@ -1,7 +1,7 @@ import { PrizePool } from '@generationsoftware/hyperstructure-client-js' import { - usePrizeDrawWinners, - usePrizePoolDrawAwardedEvents + useDrawAwardedEvents, + usePrizeDrawWinners } from '@generationsoftware/hyperstructure-react-hooks' import { divideBigInts, formatNumberForDisplay } from '@shared/utilities' import classNames from 'classnames' @@ -21,7 +21,7 @@ export const DrawsAvgClaimFeesChart = (props: DrawsAvgClaimFeesChartProps) => { const { data: allDraws } = usePrizeDrawWinners(prizePool) - const { data: drawAwardedEvents } = usePrizePoolDrawAwardedEvents(prizePool, { + const { data: drawAwardedEvents } = useDrawAwardedEvents(prizePool, { fromBlock: !!prizePool ? QUERY_START_BLOCK[prizePool.chainId] : undefined }) diff --git a/apps/analytics/src/components/Charts/ReserveChart.tsx b/apps/analytics/src/components/Charts/ReserveChart.tsx index 23feccd7..e1dbc9c3 100644 --- a/apps/analytics/src/components/Charts/ReserveChart.tsx +++ b/apps/analytics/src/components/Charts/ReserveChart.tsx @@ -15,7 +15,7 @@ import { formatUnits, Log } from 'viem' import { ReserveCard } from '@components/Reserve/ReserveCard' import { QUERY_START_BLOCK } from '@constants/config' import { useReserve } from '@hooks/useReserve' -import { DrawAwardTx, RngAuctionTx, useRngTxs } from '@hooks/useRngTxs' +import { DrawFinishTx, DrawStartTx, useRngTxs } from '@hooks/useRngTxs' import { LineChart } from './LineChart' interface DataPoint { @@ -72,14 +72,14 @@ export const ReserveChart = (props: ReserveChartProps) => { } const validRngTxs = rngTxs.filter( - (txs) => txs.rngAuction.reward !== undefined && !!txs.drawAward + (txs) => txs.drawStart.reward !== undefined && !!txs.drawFinish ) as { - rngAuction: RngAuctionTx & { reward: bigint } - drawAward: DrawAwardTx + drawStart: DrawStartTx & { reward: bigint } + drawFinish: DrawFinishTx }[] let minBlock = 0n - let maxBlock = validRngTxs[0]?.drawAward.blockNumber + let maxBlock = validRngTxs[0]?.drawFinish.blockNumber let prevReserve = 0 const isValidEvent = (event: Log) => { @@ -97,11 +97,11 @@ export const ReserveChart = (props: ReserveChartProps) => { }) validRngTxs.forEach((txs, i) => { - const drawId = txs.drawAward.drawId - const awardedAt = txs.drawAward.timestamp + const drawId = txs.drawFinish.drawId + const awardedAt = txs.drawFinish.timestamp const name = `${drawId}-${awardedAt}` - const remainingReserve = formatPrizeNum(txs.drawAward.remainingReserve) + const remainingReserve = formatPrizeNum(txs.drawFinish.remainingReserve) // Inbound tokens const manual = formatPrizeNum( @@ -109,7 +109,7 @@ export const ReserveChart = (props: ReserveChartProps) => { ) // Outbound tokens - const rewards = formatPrizeNum(txs.rngAuction.reward + txs.drawAward.reward) + const rewards = formatPrizeNum(txs.drawStart.reward + txs.drawFinish.reward) const prizeBackstops = formatPrizeNum( prizeBackstopEvents.reduce((a, b) => a + (isValidEvent(b) ? b.args.amount : 0n), 0n) ) @@ -132,7 +132,7 @@ export const ReserveChart = (props: ReserveChartProps) => { }) minBlock = maxBlock - maxBlock = validRngTxs[i + 1]?.drawAward.blockNumber ?? MAX_UINT_256 + maxBlock = validRngTxs[i + 1]?.drawFinish.blockNumber ?? MAX_UINT_256 prevReserve = reserve }) diff --git a/apps/analytics/src/components/ClaimFees.tsx b/apps/analytics/src/components/ClaimFees.tsx index 9b001507..0c87fab4 100644 --- a/apps/analytics/src/components/ClaimFees.tsx +++ b/apps/analytics/src/components/ClaimFees.tsx @@ -1,7 +1,7 @@ import { PrizePool } from '@generationsoftware/hyperstructure-client-js' import { - usePrizeDrawWinners, - usePrizePoolDrawAwardedEvents + useDrawAwardedEvents, + usePrizeDrawWinners } from '@generationsoftware/hyperstructure-react-hooks' import { SubgraphDraw } from '@shared/types' import { ExternalLink, Spinner } from '@shared/ui' @@ -27,10 +27,10 @@ export const ClaimFees = (props: ClaimFeesProps) => { const { data: allDraws, isFetched: isFetchedAllDraws } = usePrizeDrawWinners(prizePool) const draw = allDraws?.find((d) => d.id === drawId) - const { data: drawAwardedEvents, isFetched: isFetchedDrawAwardedEvents } = - usePrizePoolDrawAwardedEvents(prizePool, { - fromBlock: !!prizePool ? QUERY_START_BLOCK[prizePool.chainId] : undefined - }) + const { data: drawAwardedEvents, isFetched: isFetchedDrawAwardedEvents } = useDrawAwardedEvents( + prizePool, + { fromBlock: !!prizePool ? QUERY_START_BLOCK[prizePool.chainId] : undefined } + ) const numTiers = useMemo(() => { const drawAwardedEvent = drawAwardedEvents?.find((e) => e.args.drawId === drawId) diff --git a/apps/analytics/src/components/Draws/DrawAwardReward.tsx b/apps/analytics/src/components/Draws/DrawAwardReward.tsx index bc30ba17..7ccea475 100644 --- a/apps/analytics/src/components/Draws/DrawAwardReward.tsx +++ b/apps/analytics/src/components/Draws/DrawAwardReward.tsx @@ -20,8 +20,8 @@ export const DrawAwardReward = (props: DrawAwardRewardProps) => { const { status, isSkipped } = useDrawStatus(prizePool, drawId) const { data: allRngTxs, isFetched: isFetchedAllRngTxs } = useRngTxs(prizePool) - const rngTxs = allRngTxs?.find((txs) => txs.rngAuction.drawId === drawId) - const drawAwardTx = rngTxs?.drawAward + const rngTxs = allRngTxs?.find((txs) => txs.drawStart.drawId === drawId) + const drawFinishTx = rngTxs?.drawFinish const { data: prizeToken } = usePrizeTokenData(prizePool) @@ -39,10 +39,10 @@ export const DrawAwardReward = (props: DrawAwardRewardProps) => { {isFetchedAllRngTxs && !!prizeToken ? ( <> - {!!drawAwardTx ? ( + {!!drawFinishTx ? ( <> - {formatBigIntForDisplay(drawAwardTx.reward, prizeToken.decimals, { + {formatBigIntForDisplay(drawFinishTx.reward, prizeToken.decimals, { maximumFractionDigits: 5 })} {' '} @@ -61,12 +61,12 @@ export const DrawAwardReward = (props: DrawAwardRewardProps) => { - )} - {!!drawAwardTx ? ( + {!!drawFinishTx ? ( - {shorten(drawAwardTx.hash, { short: true })} + {shorten(drawFinishTx.hash, { short: true })} ) : ( isAwardPossible && Not Yet Awarded diff --git a/apps/analytics/src/components/Draws/DrawPrizes.tsx b/apps/analytics/src/components/Draws/DrawPrizes.tsx index 658c10b0..a38da88c 100644 --- a/apps/analytics/src/components/Draws/DrawPrizes.tsx +++ b/apps/analytics/src/components/Draws/DrawPrizes.tsx @@ -1,7 +1,7 @@ import { PrizePool } from '@generationsoftware/hyperstructure-client-js' import { - usePrizeDrawWinners, - usePrizePoolDrawAwardedEvents + useDrawAwardedEvents, + usePrizeDrawWinners } from '@generationsoftware/hyperstructure-react-hooks' import { Spinner } from '@shared/ui' import { formatNumberForDisplay, sToMs } from '@shared/utilities' @@ -21,10 +21,10 @@ interface DrawPrizesProps { export const DrawPrizes = (props: DrawPrizesProps) => { const { prizePool, drawId, className } = props - const { data: drawAwardedEvents, isFetched: isFetchedDrawAwardedEvents } = - usePrizePoolDrawAwardedEvents(prizePool, { - fromBlock: !!prizePool ? QUERY_START_BLOCK[prizePool.chainId] : undefined - }) + const { data: drawAwardedEvents, isFetched: isFetchedDrawAwardedEvents } = useDrawAwardedEvents( + prizePool, + { fromBlock: !!prizePool ? QUERY_START_BLOCK[prizePool.chainId] : undefined } + ) const numTiers = useMemo(() => { const drawAwardedEvent = drawAwardedEvents?.find((e) => e.args.drawId === drawId) diff --git a/apps/analytics/src/components/Draws/DrawRngReward.tsx b/apps/analytics/src/components/Draws/DrawRngReward.tsx index c7a5c288..77c90f2d 100644 --- a/apps/analytics/src/components/Draws/DrawRngReward.tsx +++ b/apps/analytics/src/components/Draws/DrawRngReward.tsx @@ -20,7 +20,7 @@ export const DrawRngReward = (props: DrawRngRewardProps) => { const { status, isSkipped } = useDrawStatus(prizePool, drawId) const { data: allRngTxs, isFetched: isFetchedAllRngTxs } = useRngTxs(prizePool) - const rngAuctionTx = allRngTxs?.find((txs) => txs.rngAuction.drawId === drawId)?.rngAuction + const drawStartTx = allRngTxs?.find((txs) => txs.drawStart.drawId === drawId)?.drawStart const { data: prizeToken } = usePrizeTokenData(prizePool) @@ -35,12 +35,12 @@ export const DrawRngReward = (props: DrawRngRewardProps) => { {isFetchedAllRngTxs && !!prizeToken ? ( <> - {!!rngAuctionTx ? ( + {!!drawStartTx ? ( <> - {rngAuctionTx.reward !== undefined ? ( + {drawStartTx.reward !== undefined ? ( <> - {formatBigIntForDisplay(rngAuctionTx.reward, prizeToken.decimals, { + {formatBigIntForDisplay(drawStartTx.reward, prizeToken.decimals, { maximumFractionDigits: 5 })} {' '} @@ -66,12 +66,12 @@ export const DrawRngReward = (props: DrawRngRewardProps) => { - )} - {!!rngAuctionTx ? ( + {!!drawStartTx ? ( - {shorten(rngAuctionTx.hash, { short: true })} + {shorten(drawStartTx.hash, { short: true })} ) : ( isRngCompletionPossible && Not Yet Awarded diff --git a/apps/analytics/src/components/Prizes/PrizesTable.tsx b/apps/analytics/src/components/Prizes/PrizesTable.tsx index 93c24e28..b804efbf 100644 --- a/apps/analytics/src/components/Prizes/PrizesTable.tsx +++ b/apps/analytics/src/components/Prizes/PrizesTable.tsx @@ -1,7 +1,7 @@ import { PrizePool } from '@generationsoftware/hyperstructure-client-js' import { + useDrawAwardedEvents, usePrizeDrawWinners, - usePrizePoolDrawAwardedEvents, usePrizeTokenData } from '@generationsoftware/hyperstructure-react-hooks' import { Spinner } from '@shared/ui' @@ -40,10 +40,10 @@ export const PrizesTable = (props: PrizesTableProps) => { refetchInterval: sToMs(300) }) - const { data: drawAwardedEvents, isFetched: isFetchedDrawAwardedEvents } = - usePrizePoolDrawAwardedEvents(prizePool, { - fromBlock: !!prizePool ? QUERY_START_BLOCK[prizePool.chainId] : undefined - }) + const { data: drawAwardedEvents, isFetched: isFetchedDrawAwardedEvents } = useDrawAwardedEvents( + prizePool, + { fromBlock: !!prizePool ? QUERY_START_BLOCK[prizePool.chainId] : undefined } + ) const numTiers = useMemo(() => { const drawAwardedEvent = drawAwardedEvents?.find((e) => e.args.drawId === drawId) diff --git a/apps/analytics/src/hooks/useAllDrawsStatus.tsx b/apps/analytics/src/hooks/useAllDrawsStatus.tsx index dbb4759f..69b026da 100644 --- a/apps/analytics/src/hooks/useAllDrawsStatus.tsx +++ b/apps/analytics/src/hooks/useAllDrawsStatus.tsx @@ -39,12 +39,12 @@ export const useAllDrawsStatus = (prizePool: PrizePool, drawIds: number[]) => { const currentTime = getSecondsSinceEpoch() drawIds.forEach((drawId) => { - const rngTxs = allRngTxs.find((txs) => txs.rngAuction.drawId === drawId) + const rngTxs = allRngTxs.find((txs) => txs.drawStart.drawId === drawId) const openedAt = firstDrawOpenedAt + drawPeriod * (drawId - 1) const closedAt = openedAt + drawPeriod - const rngCompletedAt = rngTxs?.rngAuction.timestamp - const awardedAt = rngTxs?.drawAward?.timestamp + const rngCompletedAt = rngTxs?.drawStart.timestamp + const awardedAt = rngTxs?.drawFinish?.timestamp const finalizedAt = closedAt + drawPeriod const isClosed = currentTime >= closedAt diff --git a/apps/analytics/src/hooks/useDrawStatus.tsx b/apps/analytics/src/hooks/useDrawStatus.tsx index b74491ff..ee7433dd 100644 --- a/apps/analytics/src/hooks/useDrawStatus.tsx +++ b/apps/analytics/src/hooks/useDrawStatus.tsx @@ -27,12 +27,12 @@ export const useDrawStatus = (prizePool: PrizePool, drawId: number) => { const data = useMemo(() => { if (isFetched && !!firstDrawOpenedAt && !!drawPeriod && !!drawAuctionDuration && !!allRngTxs) { - const rngTxs = allRngTxs.find((txs) => txs.rngAuction.drawId === drawId) + const rngTxs = allRngTxs.find((txs) => txs.drawStart.drawId === drawId) const openedAt = firstDrawOpenedAt + drawPeriod * (drawId - 1) const closedAt = openedAt + drawPeriod - const rngCompletedAt = rngTxs?.rngAuction.timestamp - const awardedAt = rngTxs?.drawAward?.timestamp + const rngCompletedAt = rngTxs?.drawStart.timestamp + const awardedAt = rngTxs?.drawFinish?.timestamp const finalizedAt = closedAt + drawPeriod const currentTime = getSecondsSinceEpoch() diff --git a/apps/analytics/src/hooks/useRngTxs.tsx b/apps/analytics/src/hooks/useRngTxs.tsx index a0c6015a..98a89ad8 100644 --- a/apps/analytics/src/hooks/useRngTxs.tsx +++ b/apps/analytics/src/hooks/useRngTxs.tsx @@ -1,24 +1,25 @@ import { PrizePool } from '@generationsoftware/hyperstructure-client-js' import { useBlocks, - useDrawManagerDrawAwardedEvents, - usePrizePoolDrawAwardedEvents, - useRngAuctionCompletedEvents + useDrawAwardedEvents, + useDrawFinishedEvents, + useDrawStartedEvents } from '@generationsoftware/hyperstructure-react-hooks' import { useMemo } from 'react' import { Address } from 'viem' import { QUERY_START_BLOCK } from '@constants/config' -export interface RngAuctionTx { +export interface DrawStartTx { drawId: number reward?: bigint rewardRecipient: Address + elapsedTime: number hash: `0x${string}` blockNumber: bigint timestamp?: number } -export interface DrawAwardTx { +export interface DrawFinishTx { drawId: number reward: bigint rewardRecipient: Address @@ -26,6 +27,7 @@ export interface DrawAwardTx { remainingReserve: bigint lastNumTiers: number numTiers: number + elapsedTime: number hash: `0x${string}` blockNumber: bigint timestamp?: number @@ -35,30 +37,32 @@ export const useRngTxs = (prizePool: PrizePool) => { const fromBlock = !!prizePool ? QUERY_START_BLOCK[prizePool.chainId] : undefined const { - data: rngAuctionCompletedEvents, - isFetched: isFetchedRngAuctionCompletedEvents, - refetch: refetchRngAuctionCompletedEvents - } = useRngAuctionCompletedEvents(prizePool, { fromBlock }) + data: drawStartedEvents, + isFetched: isFetchedDrawStartedEvents, + refetch: refetchDrawStartedEvents + } = useDrawStartedEvents(prizePool, { fromBlock }) const { - data: prizePoolDrawAwardedEvents, - isFetched: isFetchedPrizePoolDrawAwardedEvents, - refetch: refetchPrizePoolDrawAwardedEvents - } = usePrizePoolDrawAwardedEvents(prizePool, { fromBlock }) + data: drawFinishedEvents, + isFetched: isFetchedDrawFinishedEvents, + refetch: refetchDrawFinishedEvents + } = useDrawFinishedEvents(prizePool, { fromBlock }) const { - data: drawManagerDrawAwardedEvents, - isFetched: isFetchedDrawManagerDrawAwardedEvents, - refetch: refetchDrawManagerDrawAwardedEvents - } = useDrawManagerDrawAwardedEvents(prizePool, { fromBlock }) + data: drawAwardedEvents, + isFetched: isFetchedDrawAwardedEvents, + refetch: refetchDrawAwardedEvents + } = useDrawAwardedEvents(prizePool, { fromBlock }) - const rngAuctionCompletedBlockNumbers = new Set( - rngAuctionCompletedEvents?.map((e) => e.blockNumber) ?? [] + const drawStartedBlockNumbers = new Set( + drawStartedEvents?.map((e) => e.blockNumber) ?? [] ) const drawAwardedBlockNumbers = new Set( - prizePoolDrawAwardedEvents?.map((e) => e.blockNumber) ?? [] + drawAwardedEvents?.map((e) => e.blockNumber) ?? [] ) - const { data: rngAuctionCompletedBlocks, isFetched: isFetchedRngAuctionCompletedBlocks } = - useBlocks(prizePool?.chainId, [...rngAuctionCompletedBlockNumbers]) + const { data: drawStartedBlocks, isFetched: isFetchedDrawStartedBlocks } = useBlocks( + prizePool?.chainId, + [...drawStartedBlockNumbers] + ) const { data: drawAwardedBlocks, isFetched: isFetchedDrawAwardedBlocks } = useBlocks( prizePool?.chainId, [...drawAwardedBlockNumbers] @@ -66,88 +70,84 @@ export const useRngTxs = (prizePool: PrizePool) => { const data = useMemo(() => { if ( - !!rngAuctionCompletedEvents && - !!prizePoolDrawAwardedEvents && - !!drawManagerDrawAwardedEvents && - !!rngAuctionCompletedBlocks && + !!drawStartedEvents && + !!drawFinishedEvents && + !!drawAwardedEvents && + !!drawStartedBlocks && !!drawAwardedBlocks ) { - const rngTxs = rngAuctionCompletedEvents - .map((rngAuctionCompletedEvent) => { - const drawId = rngAuctionCompletedEvent.args.drawId + const rngTxs = drawStartedEvents + .map((drawStartedEvent) => { + const drawId = drawStartedEvent.args.drawId - const rngAuctionCompletedBlock = rngAuctionCompletedBlocks.find( - (block) => block.number === rngAuctionCompletedEvent.blockNumber + const drawStartedBlock = drawStartedBlocks.find( + (block) => block.number === drawStartedEvent.blockNumber ) - const rngAuction: RngAuctionTx = { + const drawStart: DrawStartTx = { drawId, - rewardRecipient: rngAuctionCompletedEvent.args.recipient, - hash: rngAuctionCompletedEvent.transactionHash, - blockNumber: rngAuctionCompletedEvent.blockNumber, - timestamp: !!rngAuctionCompletedBlock - ? Number(rngAuctionCompletedBlock.timestamp) - : undefined + rewardRecipient: drawStartedEvent.args.recipient, + elapsedTime: drawStartedEvent.args.elapsedTime, + hash: drawStartedEvent.transactionHash, + blockNumber: drawStartedEvent.blockNumber, + timestamp: !!drawStartedBlock ? Number(drawStartedBlock.timestamp) : undefined } - let drawAward: DrawAwardTx | undefined = undefined + let drawFinish: DrawFinishTx | undefined = undefined - const prizePoolDrawAwardedEvent = prizePoolDrawAwardedEvents.find( - (e) => e.args.drawId === drawId - ) + const drawAwardedEvent = drawAwardedEvents.find((e) => e.args.drawId === drawId) - if (!!prizePoolDrawAwardedEvent) { - const drawManagerDrawAwardedEvent = drawManagerDrawAwardedEvents.find( - (e) => e.args.drawId === drawId - ) + if (!!drawAwardedEvent) { + const drawFinishedEvent = drawFinishedEvents.find((e) => e.args.drawId === drawId) - if (!!drawManagerDrawAwardedEvent) { + if (!!drawFinishedEvent) { const drawAwardedBlock = drawAwardedBlocks.find( - (block) => block.number === prizePoolDrawAwardedEvent.blockNumber + (block) => block.number === drawAwardedEvent.blockNumber ) - drawAward = { + drawFinish = { drawId, - reward: drawManagerDrawAwardedEvent.args.awardReward, - rewardRecipient: drawManagerDrawAwardedEvent.args.awardRecipient, - reserve: prizePoolDrawAwardedEvent.args.reserve, - remainingReserve: drawManagerDrawAwardedEvent.args.remainingReserve, - lastNumTiers: prizePoolDrawAwardedEvent.args.lastNumTiers, - numTiers: prizePoolDrawAwardedEvent.args.numTiers, - hash: prizePoolDrawAwardedEvent.transactionHash, - blockNumber: prizePoolDrawAwardedEvent.blockNumber, + reward: drawFinishedEvent.args.finishReward, + rewardRecipient: drawFinishedEvent.args.finishRecipient, + reserve: drawAwardedEvent.args.reserve, + remainingReserve: drawFinishedEvent.args.remainingReserve, + lastNumTiers: drawAwardedEvent.args.lastNumTiers, + numTiers: drawAwardedEvent.args.numTiers, + elapsedTime: Number(drawFinishedEvent.args.elapsedTime), // TODO: remove number cast once contract is fixed + hash: drawAwardedEvent.transactionHash, + blockNumber: drawAwardedEvent.blockNumber, timestamp: !!drawAwardedBlock ? Number(drawAwardedBlock.timestamp) : undefined } - rngAuction.reward = drawManagerDrawAwardedEvent.args.startReward + drawStart.reward = drawFinishedEvent.args.startReward } } - return { rngAuction, drawAward } + return { drawStart, drawFinish } }) .filter((tx) => !!tx) return rngTxs } }, [ - rngAuctionCompletedEvents, - prizePoolDrawAwardedEvents, - drawManagerDrawAwardedEvents, - rngAuctionCompletedBlocks, + drawStartedEvents, + drawFinishedEvents, + drawAwardedEvents, + drawStartedBlocks, drawAwardedBlocks ]) const isFetched = - isFetchedRngAuctionCompletedEvents && - isFetchedPrizePoolDrawAwardedEvents && - isFetchedDrawManagerDrawAwardedEvents && - isFetchedRngAuctionCompletedBlocks && + isFetchedDrawStartedEvents && + isFetchedDrawFinishedEvents && + isFetchedDrawAwardedEvents && + isFetchedDrawStartedBlocks && isFetchedDrawAwardedBlocks const refetch = () => { - refetchRngAuctionCompletedEvents() - refetchPrizePoolDrawAwardedEvents() - refetchDrawManagerDrawAwardedEvents() + refetchDrawStartedEvents() + refetchDrawFinishedEvents() + refetchDrawAwardedEvents() } return { data, isFetched, refetch } diff --git a/packages/hyperstructure-react-hooks/README.md b/packages/hyperstructure-react-hooks/README.md index c79d6296..8a64c27d 100644 --- a/packages/hyperstructure-react-hooks/README.md +++ b/packages/hyperstructure-react-hooks/README.md @@ -71,14 +71,14 @@ yarn add @generationsoftware/hyperstructure-react-hooks ### Event Hooks -- `useDrawManagerDrawAwardedEvents` +- `useDrawAwardedEvents` +- `useDrawFinishedEvents` +- `useDrawStartedEvents` - `useLiquidationEvents` - `useManualContributionEvents` - `usePrizeBackstopEvents` -- `usePrizePoolDrawAwardedEvents` - `usePromotionCreatedEvents` - `usePromotionRewardsClaimedEvents` -- `useRngAuctionCompletedEvents` - `useTransferEvents` ### Prize Pool Hooks diff --git a/packages/hyperstructure-react-hooks/src/constants.ts b/packages/hyperstructure-react-hooks/src/constants.ts index 29ea3522..8ecba858 100644 --- a/packages/hyperstructure-react-hooks/src/constants.ts +++ b/packages/hyperstructure-react-hooks/src/constants.ts @@ -8,8 +8,11 @@ export const QUERY_KEYS = { blockAtTimestamp: 'blockAtTimestamp', clientChainId: 'clientChainId', drawAuctionDuration: 'drawAuctionDuration', + drawAwardedEvents: 'drawAwardedEvents', + drawFinishedEvents: 'drawFinishedEvents', drawManagerDrawAwardedEvents: 'drawManagerDrawAwardedEvents', drawPeriod: 'drawPeriod', + drawStartedEvents: 'drawStartedEvents', drawTimestamps: 'drawTimestamps', drawWinners: 'drawWinners', estimatedPrizeCount: 'estimatedPrizeCount', @@ -30,7 +33,6 @@ export const QUERY_KEYS = { promotionCreatedEvents: 'promotionCreatedEvents', promotionRewardsClaimedEvents: 'promotionRewardsClaimedEvents', promotionInfo: 'promotionInfo', - rngAuctionCompletedEvents: 'rngAuctionCompletedEvents', selectedVaults: 'selectedVaults', tokenAllowances: 'tokenAllowances', tokenBalances: 'tokenBalances', diff --git a/packages/hyperstructure-react-hooks/src/events/usePrizePoolDrawAwardedEvents.ts b/packages/hyperstructure-react-hooks/src/events/useDrawAwardedEvents.ts similarity index 68% rename from packages/hyperstructure-react-hooks/src/events/usePrizePoolDrawAwardedEvents.ts rename to packages/hyperstructure-react-hooks/src/events/useDrawAwardedEvents.ts index e43740b0..a1aa4681 100644 --- a/packages/hyperstructure-react-hooks/src/events/usePrizePoolDrawAwardedEvents.ts +++ b/packages/hyperstructure-react-hooks/src/events/useDrawAwardedEvents.ts @@ -1,26 +1,23 @@ -import { - getPrizePoolDrawAwardedEvents, - PrizePool -} from '@generationsoftware/hyperstructure-client-js' +import { getDrawAwardedEvents, PrizePool } from '@generationsoftware/hyperstructure-client-js' import { NO_REFETCH } from '@shared/generic-react-hooks' import { useQuery } from '@tanstack/react-query' import { usePublicClient } from 'wagmi' import { QUERY_KEYS } from '../constants' /** - * Returns `DrawAwarded` events from a prize pool + * Returns `DrawAwarded` events from a prize pool contract * @param prizePool the prize pool to query events for * @param options optional settings * @returns */ -export const usePrizePoolDrawAwardedEvents = ( +export const useDrawAwardedEvents = ( prizePool: PrizePool, options?: { fromBlock?: bigint; toBlock?: bigint } ) => { const publicClient = usePublicClient({ chainId: prizePool?.chainId }) const queryKey = [ - QUERY_KEYS.prizePoolDrawAwardedEvents, + QUERY_KEYS.drawAwardedEvents, prizePool?.id, options?.fromBlock?.toString(), options?.toBlock?.toString() ?? 'latest' @@ -30,7 +27,7 @@ export const usePrizePoolDrawAwardedEvents = ( queryKey, queryFn: async () => { if (!!publicClient) { - return await getPrizePoolDrawAwardedEvents(publicClient, prizePool.address, options) + return await getDrawAwardedEvents(publicClient, prizePool.address, options) } }, enabled: !!prizePool && !!publicClient, diff --git a/packages/hyperstructure-react-hooks/src/events/useDrawManagerDrawAwardedEvents.ts b/packages/hyperstructure-react-hooks/src/events/useDrawFinishedEvents.ts similarity index 69% rename from packages/hyperstructure-react-hooks/src/events/useDrawManagerDrawAwardedEvents.ts rename to packages/hyperstructure-react-hooks/src/events/useDrawFinishedEvents.ts index 7848c776..7d975d37 100644 --- a/packages/hyperstructure-react-hooks/src/events/useDrawManagerDrawAwardedEvents.ts +++ b/packages/hyperstructure-react-hooks/src/events/useDrawFinishedEvents.ts @@ -1,26 +1,23 @@ -import { - getDrawManagerDrawAwardedEvents, - PrizePool -} from '@generationsoftware/hyperstructure-client-js' +import { getDrawFinishedEvents, PrizePool } from '@generationsoftware/hyperstructure-client-js' import { NO_REFETCH } from '@shared/generic-react-hooks' import { useQuery } from '@tanstack/react-query' import { usePublicClient } from 'wagmi' import { QUERY_KEYS } from '../constants' /** - * Returns `DrawAwarded` events from a prize pool's draw manager + * Returns `DrawFinished` events from a prize pool's draw manager contract * @param prizePool the prize pool to query events for * @param options optional settings * @returns */ -export const useDrawManagerDrawAwardedEvents = ( +export const useDrawFinishedEvents = ( prizePool: PrizePool, options?: { fromBlock?: bigint; toBlock?: bigint } ) => { const publicClient = usePublicClient({ chainId: prizePool?.chainId }) const queryKey = [ - QUERY_KEYS.drawManagerDrawAwardedEvents, + QUERY_KEYS.drawFinishedEvents, prizePool?.id, options?.fromBlock?.toString(), options?.toBlock?.toString() ?? 'latest' @@ -31,7 +28,7 @@ export const useDrawManagerDrawAwardedEvents = ( queryFn: async () => { if (!!publicClient) { const drawManagerAddress = await prizePool.getDrawManagerAddress() - return await getDrawManagerDrawAwardedEvents(publicClient, drawManagerAddress, options) + return await getDrawFinishedEvents(publicClient, drawManagerAddress, options) } }, enabled: !!prizePool && !!publicClient, diff --git a/packages/hyperstructure-react-hooks/src/events/useRngAuctionCompletedEvents.ts b/packages/hyperstructure-react-hooks/src/events/useDrawStartedEvents.ts similarity index 75% rename from packages/hyperstructure-react-hooks/src/events/useRngAuctionCompletedEvents.ts rename to packages/hyperstructure-react-hooks/src/events/useDrawStartedEvents.ts index c2dca698..271fba52 100644 --- a/packages/hyperstructure-react-hooks/src/events/useRngAuctionCompletedEvents.ts +++ b/packages/hyperstructure-react-hooks/src/events/useDrawStartedEvents.ts @@ -1,24 +1,24 @@ import { PrizePool } from '@generationsoftware/hyperstructure-client-js' import { NO_REFETCH } from '@shared/generic-react-hooks' -import { getRngAuctionCompletedEvents } from '@shared/utilities' +import { getDrawStartedEvents } from '@shared/utilities' import { useQuery } from '@tanstack/react-query' import { usePublicClient } from 'wagmi' import { QUERY_KEYS } from '../constants' /** - * Returns `RngAuctionCompleted` events + * Returns `DrawStarted` events * @param prizePool the prize pool to query events for * @param options optional settings * @returns */ -export const useRngAuctionCompletedEvents = ( +export const useDrawStartedEvents = ( prizePool: PrizePool, options?: { fromBlock?: bigint; toBlock?: bigint } ) => { const publicClient = usePublicClient({ chainId: prizePool?.chainId }) const queryKey = [ - QUERY_KEYS.rngAuctionCompletedEvents, + QUERY_KEYS.drawStartedEvents, prizePool?.id, options?.fromBlock?.toString(), options?.toBlock?.toString() ?? 'latest' @@ -29,7 +29,7 @@ export const useRngAuctionCompletedEvents = ( queryFn: async () => { if (!!publicClient) { const drawManagerAddress = await prizePool.getDrawManagerAddress() - return await getRngAuctionCompletedEvents(publicClient, drawManagerAddress, options) + return await getDrawStartedEvents(publicClient, drawManagerAddress, options) } }, enabled: !!prizePool && !!publicClient, diff --git a/packages/hyperstructure-react-hooks/src/index.ts b/packages/hyperstructure-react-hooks/src/index.ts index b5dfa1e5..7f4ce7d7 100644 --- a/packages/hyperstructure-react-hooks/src/index.ts +++ b/packages/hyperstructure-react-hooks/src/index.ts @@ -27,14 +27,14 @@ export * from './blockchain/useTxReceipts' /** * Event Hooks */ -export * from './events/useDrawManagerDrawAwardedEvents' +export * from './events/useDrawAwardedEvents' +export * from './events/useDrawFinishedEvents' +export * from './events/useDrawStartedEvents' export * from './events/useLiquidationEvents' export * from './events/useManualContributionEvents' export * from './events/usePrizeBackstopEvents' -export * from './events/usePrizePoolDrawAwardedEvents' export * from './events/usePromotionCreatedEvents' export * from './events/usePromotionRewardsClaimedEvents' -export * from './events/useRngAuctionCompletedEvents' export * from './events/useTransferEvents' /** diff --git a/shared/utilities/utils/events.ts b/shared/utilities/utils/events.ts index 56e90173..7aad4d0b 100644 --- a/shared/utilities/utils/events.ts +++ b/shared/utilities/utils/events.ts @@ -64,13 +64,13 @@ export const getWithdrawEvents = async ( } /** - * Returns `RngAuctionCompleted` events + * Returns `DrawStarted` events from a draw manager contract * @param publicClient a public Viem client to query through * @param drawManagerAddress the address of a prize pool's draw manager to query events for * @param options optional settings * @returns */ -export const getRngAuctionCompletedEvents = async ( +export const getDrawStartedEvents = async ( publicClient: PublicClient, drawManagerAddress: Address, options?: { fromBlock?: bigint; toBlock?: bigint } @@ -83,9 +83,9 @@ export const getRngAuctionCompletedEvents = async ( { indexed: true, internalType: 'address', name: 'recipient', type: 'address' }, { indexed: false, internalType: 'uint24', name: 'drawId', type: 'uint24' }, { indexed: false, internalType: 'uint32', name: 'rngRequestId', type: 'uint32' }, - { indexed: false, internalType: 'uint64', name: 'elapsedTime', type: 'uint64' } + { indexed: false, internalType: 'uint48', name: 'elapsedTime', type: 'uint48' } ], - name: 'RngAuctionCompleted', + name: 'DrawStarted', type: 'event' }, fromBlock: options?.fromBlock, @@ -101,7 +101,7 @@ export const getRngAuctionCompletedEvents = async ( * @param options optional settings * @returns */ -export const getPrizePoolDrawAwardedEvents = async ( +export const getDrawAwardedEvents = async ( publicClient: PublicClient, prizePoolAddress: Address, options?: { fromBlock?: bigint; toBlock?: bigint } @@ -128,13 +128,13 @@ export const getPrizePoolDrawAwardedEvents = async ( } /** - * Returns `DrawAwarded` events from a draw manager contract + * Returns `DrawFinished` events from a draw manager contract * @param publicClient a public Viem client to query through * @param drawManagerAddress the address of a prize pool's draw manager to query events for * @param options optional settings * @returns */ -export const getDrawManagerDrawAwardedEvents = async ( +export const getDrawFinishedEvents = async ( publicClient: PublicClient, drawManagerAddress: Address, options?: { fromBlock?: bigint; toBlock?: bigint } @@ -144,13 +144,14 @@ export const getDrawManagerDrawAwardedEvents = async ( event: { inputs: [ { indexed: true, internalType: 'uint24', name: 'drawId', type: 'uint24' }, + { indexed: false, internalType: 'uint256', name: 'elapsedTime', type: 'uint256' }, { indexed: true, internalType: 'address', name: 'startRecipient', type: 'address' }, { indexed: false, internalType: 'uint256', name: 'startReward', type: 'uint256' }, - { indexed: true, internalType: 'address', name: 'awardRecipient', type: 'address' }, - { indexed: false, internalType: 'uint256', name: 'awardReward', type: 'uint256' }, + { indexed: true, internalType: 'address', name: 'finishRecipient', type: 'address' }, + { indexed: false, internalType: 'uint256', name: 'finishReward', type: 'uint256' }, { indexed: false, internalType: 'uint256', name: 'remainingReserve', type: 'uint256' } ], - name: 'DrawAwarded', + name: 'DrawFinished', type: 'event' }, fromBlock: options?.fromBlock, From 4bcaaf8589b113216a892aba3d2b67ef062af0aa Mon Sep 17 00:00:00 2001 From: Ncookiez Date: Mon, 4 Mar 2024 15:36:01 -0500 Subject: [PATCH 029/161] WIP expected start reward on unfinished draw --- .../src/components/Draws/DrawRngReward.tsx | 21 +++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/apps/analytics/src/components/Draws/DrawRngReward.tsx b/apps/analytics/src/components/Draws/DrawRngReward.tsx index 77c90f2d..04dfbcd6 100644 --- a/apps/analytics/src/components/Draws/DrawRngReward.tsx +++ b/apps/analytics/src/components/Draws/DrawRngReward.tsx @@ -26,6 +26,9 @@ export const DrawRngReward = (props: DrawRngRewardProps) => { const { data: currentRngAuctionReward } = useCurrentRngAuctionReward(prizePool) + // TODO: query expected reward from draw manager if drawStartTx?.reward === undefined using `drawStartTx.elapsedTime` (not possible with current contract deployment) + const expectedDrawStartReward: bigint | undefined = undefined + const isRngCompletionPossible = status === 'closed' && !!currentRngAuctionReward && !isSkipped return ( @@ -48,8 +51,22 @@ export const DrawRngReward = (props: DrawRngRewardProps) => { ) : ( <> - {/* TODO: get last rng auction reward from draw manager to display here - crossed out? */} - ? + {expectedDrawStartReward !== undefined ? ( + <> + + {formatBigIntForDisplay(expectedDrawStartReward, prizeToken.decimals, { + maximumFractionDigits: 5 + })} + {' '} + {prizeToken.symbol} + + ) : ( + + )} )} From 12496743ece6c5d7b82d1f39a58a0bb2a0be350a Mon Sep 17 00:00:00 2001 From: Ncookiez Date: Mon, 4 Mar 2024 15:56:38 -0500 Subject: [PATCH 030/161] app update to new testnet --- apps/app/.env.example | 4 +- .../Account/AccountVaultButtons.tsx | 1 - apps/app/src/constants/config.ts | 31 +-- apps/app/src/vaultLists/default.ts | 184 +++++++++--------- apps/app/src/vaultLists/testnet.ts | 178 ++--------------- 5 files changed, 122 insertions(+), 276 deletions(-) diff --git a/apps/app/.env.example b/apps/app/.env.example index 41c5ebd6..20835ed9 100644 --- a/apps/app/.env.example +++ b/apps/app/.env.example @@ -1,11 +1,9 @@ # Mainnet RPC URLs NEXT_PUBLIC_MAINNET_RPC_URL="YOUR_MAINNET_RPC_HERE" NEXT_PUBLIC_OPTIMISM_RPC_URL="YOUR_OPTIMISM_RPC_HERE" -NEXT_PUBLIC_ARBITRUM_RPC_URL="YOUR_ARBITRUM_RPC_HERE" # Testnet RPC URLs -NEXT_PUBLIC_OPTIMISM_SEPOLIA_RPC_URL="YOUR_OPTIMISM_SEPOLIA_RPC_HERE" -NEXT_PUBLIC_ARBITRUM_SEPOLIA_RPC_URL="YOUR_ARBITRUM_SEPOLIA_RPC_HERE" +NEXT_PUBLIC_SEPOLIA_RPC_URL="YOUR_SEPOLIA_RPC_HERE" # Fathom Analytics NEXT_PUBLIC_FATHOM_SITE_ID="YOUR_FATHOM_ID_HERE" diff --git a/apps/app/src/components/Account/AccountVaultButtons.tsx b/apps/app/src/components/Account/AccountVaultButtons.tsx index 2227f814..2e665d3d 100644 --- a/apps/app/src/components/Account/AccountVaultButtons.tsx +++ b/apps/app/src/components/Account/AccountVaultButtons.tsx @@ -7,7 +7,6 @@ import { WithdrawButton } from '@shared/react-components' import { useTranslations } from 'next-intl' -import Image from 'next/image' interface AccountVaultButtonsProps { vault: Vault diff --git a/apps/app/src/constants/config.ts b/apps/app/src/constants/config.ts index ccfb936d..66014634 100644 --- a/apps/app/src/constants/config.ts +++ b/apps/app/src/constants/config.ts @@ -20,14 +20,14 @@ import { import { NETWORK, POOL_TOKEN_ADDRESSES, USDC_TOKEN_ADDRESSES } from '@shared/utilities' import defaultVaultList from '@vaultLists/default' import { Address } from 'viem' -import { arbitrum, arbitrumSepolia, mainnet, optimism, optimismSepolia } from 'viem/chains' +import { mainnet, optimism, sepolia } from 'viem/chains' /** * Supported networks */ export const SUPPORTED_NETWORKS = { - mainnets: [NETWORK.mainnet, NETWORK.optimism, NETWORK.arbitrum], - testnets: [NETWORK.optimism_sepolia, NETWORK.arbitrum_sepolia] + mainnets: [NETWORK.mainnet, NETWORK.optimism], + testnets: [NETWORK.sepolia] } as const /** @@ -36,9 +36,7 @@ export const SUPPORTED_NETWORKS = { export const WAGMI_CHAINS = { [NETWORK.mainnet]: mainnet, [NETWORK.optimism]: optimism, - [NETWORK.arbitrum]: arbitrum, - [NETWORK.optimism_sepolia]: optimismSepolia, - [NETWORK.arbitrum_sepolia]: arbitrumSepolia + [NETWORK.sepolia]: sepolia } as const /** @@ -69,9 +67,7 @@ export const WALLETS: { [wallet: string]: CreateWalletFn } = { export const RPC_URLS = { [NETWORK.mainnet]: process.env.NEXT_PUBLIC_MAINNET_RPC_URL, [NETWORK.optimism]: process.env.NEXT_PUBLIC_OPTIMISM_RPC_URL, - [NETWORK.arbitrum]: process.env.NEXT_PUBLIC_ARBITRUM_RPC_URL, - [NETWORK.optimism_sepolia]: process.env.NEXT_PUBLIC_OPTIMISM_SEPOLIA_RPC_URL, - [NETWORK.arbitrum_sepolia]: process.env.NEXT_PUBLIC_ARBITRUM_SEPOLIA_RPC_URL + [NETWORK.sepolia]: process.env.NEXT_PUBLIC_SEPOLIA_RPC_URL } as const /** @@ -99,20 +95,9 @@ export const TWAB_REWARDS_SETTINGS: { ], fromBlock: 112_933_000n }, - [NETWORK.arbitrum]: { tokenAddresses: [], fromBlock: 1n }, - [NETWORK.optimism_sepolia]: { - tokenAddresses: [ - USDC_TOKEN_ADDRESSES[NETWORK.optimism_sepolia], - POOL_TOKEN_ADDRESSES[NETWORK.optimism_sepolia] - ], - fromBlock: 4_400_000n - }, - [NETWORK.arbitrum_sepolia]: { - tokenAddresses: [ - USDC_TOKEN_ADDRESSES[NETWORK.arbitrum_sepolia], - POOL_TOKEN_ADDRESSES[NETWORK.arbitrum_sepolia] - ], - fromBlock: 1_490_000n + [NETWORK.sepolia]: { + tokenAddresses: [USDC_TOKEN_ADDRESSES[NETWORK.sepolia], POOL_TOKEN_ADDRESSES[NETWORK.sepolia]], + fromBlock: 5_397_600n } } diff --git a/apps/app/src/vaultLists/default.ts b/apps/app/src/vaultLists/default.ts index 28ae7735..46022ef5 100644 --- a/apps/app/src/vaultLists/default.ts +++ b/apps/app/src/vaultLists/default.ts @@ -6,100 +6,100 @@ import { testnetVaults } from './testnet' const defaultVaultList: VaultList = { name: 'Cabana Vault List', keywords: ['pooltogether', 'cabana', 'g9', 'optimism'], - version: { major: 1, minor: 16, patch: 2 }, - timestamp: '2024-01-02T20:55:09Z', + version: { major: 2, minor: 0, patch: 0 }, + timestamp: '2024-03-04T20:40:34Z', logoURI: `${LINKS.app}/pooltogether-token-logo.svg`, tokens: [ - { - chainId: NETWORK.optimism, - address: '0xE3B3a464ee575E8E25D2508918383b89c832f275', - name: 'Prize USDC.e - Aave', - decimals: 6, - symbol: 'pUSDC.e', - logoURI: `${LINKS.app}/icons/pUSDC.e.svg`, - tags: ['aave', 'vault_v1'], - yieldSourceURI: - 'https://app.aave.com/reserve-overview/?underlyingAsset=0x7f5c764cbc14f9669b88837ca1490cca17c31607&marketName=proto_optimism_v3', - extensions: { - underlyingAsset: { - address: '0x7F5c764cBc14f9669B88837ca1490cCa17c31607', - symbol: 'USDC.e', - name: 'USDC (Bridged from Ethereum)' - } - } - }, - { - chainId: NETWORK.optimism, - address: '0x29Cb69D4780B53c1e5CD4D2B817142D2e9890715', - name: 'Prize WETH - Aave', - decimals: 18, - symbol: 'pWETH', - logoURI: `${LINKS.app}/icons/pWETH.svg`, - tags: ['aave', 'vault_v1', 'deprecated'], - yieldSourceURI: - 'https://app.aave.com/reserve-overview/?underlyingAsset=0x4200000000000000000000000000000000000006&marketName=proto_optimism_v3', - extensions: { - underlyingAsset: { - address: '0x4200000000000000000000000000000000000006', - symbol: 'WETH', - name: 'Wrapped Ether' - } - } - }, - { - chainId: NETWORK.optimism, - address: '0xCe8293f586091d48A0cE761bBf85D5bCAa1B8d2b', - name: 'Prize DAI - Aave', - decimals: 18, - symbol: 'pDAI', - logoURI: `${LINKS.app}/icons/pDAI.svg`, - tags: ['aave', 'vault_v1', 'deprecated'], - yieldSourceURI: - 'https://app.aave.com/reserve-overview/?underlyingAsset=0xda10009cbd5d07dd0cecc66161fc93d7c9000da1&marketName=proto_optimism_v3', - extensions: { - underlyingAsset: { - address: '0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1', - symbol: 'DAI', - name: 'Dai Stablecoin' - } - } - }, - { - chainId: NETWORK.optimism, - address: '0x77935f2c72b5eb814753a05921ae495aa283906b', - name: 'Prize USDC - Aave', - decimals: 6, - symbol: 'pUSDC', - logoURI: `${LINKS.app}/icons/pUSDC.svg`, - tags: ['aave', 'vault_v2', 'deprecated'], - yieldSourceURI: - 'https://app.aave.com/reserve-overview/?underlyingAsset=0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85&marketName=proto_optimism_v3', - extensions: { - underlyingAsset: { - address: '0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85', - symbol: 'USDC', - name: 'USD Coin' - } - } - }, - { - chainId: NETWORK.optimism, - address: '0xf0b19f02c63d51b69563a2b675e0160e1c34397c', - name: 'Prize WETH - Aave', - decimals: 18, - symbol: 'pWETH', - logoURI: `${LINKS.app}/icons/pWETH.svg`, - tags: ['aave', 'vault_v2'], - yieldSourceURI: - 'https://app.aave.com/reserve-overview/?underlyingAsset=0x4200000000000000000000000000000000000006&marketName=proto_optimism_v3', - extensions: { - underlyingAsset: { - address: '0x4200000000000000000000000000000000000006', - symbol: 'WETH', - name: 'Wrapped Ether' - } - } - }, + // { + // chainId: NETWORK.optimism, + // address: '0xE3B3a464ee575E8E25D2508918383b89c832f275', + // name: 'Prize USDC.e - Aave', + // decimals: 6, + // symbol: 'pUSDC.e', + // logoURI: `${LINKS.app}/icons/pUSDC.e.svg`, + // tags: ['aave', 'vault_v1'], + // yieldSourceURI: + // 'https://app.aave.com/reserve-overview/?underlyingAsset=0x7f5c764cbc14f9669b88837ca1490cca17c31607&marketName=proto_optimism_v3', + // extensions: { + // underlyingAsset: { + // address: '0x7F5c764cBc14f9669B88837ca1490cCa17c31607', + // symbol: 'USDC.e', + // name: 'USDC (Bridged from Ethereum)' + // } + // } + // }, + // { + // chainId: NETWORK.optimism, + // address: '0x29Cb69D4780B53c1e5CD4D2B817142D2e9890715', + // name: 'Prize WETH - Aave', + // decimals: 18, + // symbol: 'pWETH', + // logoURI: `${LINKS.app}/icons/pWETH.svg`, + // tags: ['aave', 'vault_v1', 'deprecated'], + // yieldSourceURI: + // 'https://app.aave.com/reserve-overview/?underlyingAsset=0x4200000000000000000000000000000000000006&marketName=proto_optimism_v3', + // extensions: { + // underlyingAsset: { + // address: '0x4200000000000000000000000000000000000006', + // symbol: 'WETH', + // name: 'Wrapped Ether' + // } + // } + // }, + // { + // chainId: NETWORK.optimism, + // address: '0xCe8293f586091d48A0cE761bBf85D5bCAa1B8d2b', + // name: 'Prize DAI - Aave', + // decimals: 18, + // symbol: 'pDAI', + // logoURI: `${LINKS.app}/icons/pDAI.svg`, + // tags: ['aave', 'vault_v1', 'deprecated'], + // yieldSourceURI: + // 'https://app.aave.com/reserve-overview/?underlyingAsset=0xda10009cbd5d07dd0cecc66161fc93d7c9000da1&marketName=proto_optimism_v3', + // extensions: { + // underlyingAsset: { + // address: '0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1', + // symbol: 'DAI', + // name: 'Dai Stablecoin' + // } + // } + // }, + // { + // chainId: NETWORK.optimism, + // address: '0x77935f2c72b5eb814753a05921ae495aa283906b', + // name: 'Prize USDC - Aave', + // decimals: 6, + // symbol: 'pUSDC', + // logoURI: `${LINKS.app}/icons/pUSDC.svg`, + // tags: ['aave', 'vault_v2', 'deprecated'], + // yieldSourceURI: + // 'https://app.aave.com/reserve-overview/?underlyingAsset=0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85&marketName=proto_optimism_v3', + // extensions: { + // underlyingAsset: { + // address: '0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85', + // symbol: 'USDC', + // name: 'USD Coin' + // } + // } + // }, + // { + // chainId: NETWORK.optimism, + // address: '0xf0b19f02c63d51b69563a2b675e0160e1c34397c', + // name: 'Prize WETH - Aave', + // decimals: 18, + // symbol: 'pWETH', + // logoURI: `${LINKS.app}/icons/pWETH.svg`, + // tags: ['aave', 'vault_v2'], + // yieldSourceURI: + // 'https://app.aave.com/reserve-overview/?underlyingAsset=0x4200000000000000000000000000000000000006&marketName=proto_optimism_v3', + // extensions: { + // underlyingAsset: { + // address: '0x4200000000000000000000000000000000000006', + // symbol: 'WETH', + // name: 'Wrapped Ether' + // } + // } + // }, ...testnetVaults ] } diff --git a/apps/app/src/vaultLists/testnet.ts b/apps/app/src/vaultLists/testnet.ts index 6ee89a12..6da2f7d3 100644 --- a/apps/app/src/vaultLists/testnet.ts +++ b/apps/app/src/vaultLists/testnet.ts @@ -3,68 +3,68 @@ import { NETWORK } from '@shared/utilities' export const testnetVaults: VaultList['tokens'] = [ { - chainId: NETWORK.optimism_sepolia, - address: '0x22c6258ea5b1E742d18C27D846E2AaBd4505EDC2', + chainId: NETWORK.sepolia, + address: '0x7DE52AcB8cEBc9713A804F5fdBd443e95234A31a', name: 'Prize DAI - LY', decimals: 18, symbol: 'PDAI-LY', logoURI: 'https://assets.coingecko.com/coins/images/9956/small/4943.png?1636636734', extensions: { underlyingAsset: { - address: '0xD590EC14364731B62265A5cc807164a17C6797D4', + address: '0x50088bF4dba58145c0B873643d285626f87837c3', symbol: 'DAI', name: 'Dai Stablecoin' } } }, { - chainId: NETWORK.optimism_sepolia, - address: '0x15E5b4813942fa51835ceb7Aff13F771C398d062', + chainId: NETWORK.sepolia, + address: '0x17daE8454c24049E1Ec94a642014Fa3abf17ceDa', name: 'Prize DAI - HY', decimals: 18, symbol: 'PDAI-HY', logoURI: 'https://assets.coingecko.com/coins/images/9956/small/4943.png?1636636734', extensions: { underlyingAsset: { - address: '0xD590EC14364731B62265A5cc807164a17C6797D4', + address: '0x50088bF4dba58145c0B873643d285626f87837c3', symbol: 'DAI', name: 'Dai Stablecoin' } } }, { - chainId: NETWORK.optimism_sepolia, - address: '0x2891d69786650260B9F99A7b333058FCC5418Df0', + chainId: NETWORK.sepolia, + address: '0xa1dD041B4A0f2d01c43F0aCE522f968cCA9F747C', name: 'Prize USDC - LY', decimals: 6, symbol: 'PUSDC-LY', logoURI: 'https://etherscan.io/token/images/centre-usdc_28.png', extensions: { underlyingAsset: { - address: '0x8067F3Cb6Eef936256108FF19a05574b8aD99Cf3', + address: '0xd09eb8dE85D547cfBF09f972edCc6F871B192B70', symbol: 'USDC', name: 'USD Coin' } } }, { - chainId: NETWORK.optimism_sepolia, - address: '0xa3976b09b9695DFABc39a2E042F5bD5B7399Ac60', + chainId: NETWORK.sepolia, + address: '0x8d8d5e80DaEC5C917d1b1E7A331dAE2Fa0a789F5', name: 'Prize USDC - HY', decimals: 6, symbol: 'PUSDC-HY', logoURI: 'https://etherscan.io/token/images/centre-usdc_28.png', extensions: { underlyingAsset: { - address: '0x8067F3Cb6Eef936256108FF19a05574b8aD99Cf3', + address: '0xd09eb8dE85D547cfBF09f972edCc6F871B192B70', symbol: 'USDC', name: 'USD Coin' } } }, { - chainId: NETWORK.optimism_sepolia, - address: '0xD04756fe8b7A33741e1fA3A4dDD7e0075A0063aC', + chainId: NETWORK.sepolia, + address: '0xcA7042D10a36eB0F795476e529354D18ba204EDC', name: 'Prize GUSD', decimals: 2, symbol: 'PGUSD', @@ -72,173 +72,37 @@ export const testnetVaults: VaultList['tokens'] = [ 'https://assets.coingecko.com/coins/images/5992/small/gemini-dollar-gusd.png?1536745278', extensions: { underlyingAsset: { - address: '0x1A188719711d62423abF1A4de7D8aA9014A39D73', + address: '0x2B8919310D8E2576E19e22794a6d3EC961cD812a', symbol: 'GUSD', name: 'Gemini dollar' } } }, { - chainId: NETWORK.optimism_sepolia, - address: '0xbE4E7D33a1144e977C3A2f51798cc451E1a76B2f', + chainId: NETWORK.sepolia, + address: '0xad132763D325EFDa39E2ccBbc8E0eFA36fC6b4b8', name: 'Prize WBTC', decimals: 8, symbol: 'PWBTC', logoURI: 'https://etherscan.io/token/images/wbtc_28.png?v=1', extensions: { underlyingAsset: { - address: '0x149e3B3Bd69f1Cfc1B42b6A6a152a42E38cEeBf1', + address: '0x0364994c88F97a18740Ec791A336b2d63407F8d5', symbol: 'WBTC', name: 'Wrapped BTC' } } }, { - chainId: NETWORK.optimism_sepolia, - address: '0xaf25FfB53699AeDba3dAf97Bb2adc1B5054053EA', + chainId: NETWORK.sepolia, + address: '0xc30151c7F49d2056E7C8197F189EFb5b54c0De0b', name: 'Prize WETH', decimals: 18, symbol: 'PWETH', logoURI: 'https://etherscan.io/token/images/weth_28.png', extensions: { underlyingAsset: { - address: '0xA416eD51158c5616b997B785FA6d18f02D0458A8', - symbol: 'WETH', - name: 'Wrapped Ether' - } - } - }, - { - chainId: NETWORK.optimism_sepolia, - address: '0x51d439F705911634263DFE265097645Eb1A3C42a', - name: 'Prize WETH - Test WETH', - decimals: 18, - symbol: 'pWETH', - logoURI: 'https://etherscan.io/token/images/weth_28.png', - extensions: { - underlyingAsset: { - address: '0xA416eD51158c5616b997B785FA6d18f02D0458A8', - symbol: 'WETH', - name: 'Wrapped Ether' - } - } - }, - { - chainId: NETWORK.arbitrum_sepolia, - address: '0x3adaa1D4F23C82130e1681c2cA9b38f5Fb9a0892', - name: 'Prize DAI - LY', - decimals: 18, - symbol: 'PDAI-LY', - logoURI: 'https://assets.coingecko.com/coins/images/9956/small/4943.png?1636636734', - extensions: { - underlyingAsset: { - address: '0x08C19FE57af150a1AF975CB9a38769848c7DF98e', - symbol: 'DAI', - name: 'Dai Stablecoin' - } - } - }, - { - chainId: NETWORK.arbitrum_sepolia, - address: '0x4DBF73fe0D23A6d275aeFebC7C00600045aB8B9E', - name: 'Prize DAI - HY', - decimals: 18, - symbol: 'PDAI-HY', - logoURI: 'https://assets.coingecko.com/coins/images/9956/small/4943.png?1636636734', - extensions: { - underlyingAsset: { - address: '0x08C19FE57af150a1AF975CB9a38769848c7DF98e', - symbol: 'DAI', - name: 'Dai Stablecoin' - } - } - }, - { - chainId: NETWORK.arbitrum_sepolia, - address: '0xA723Cf5D90c1A472c7de7285e5bD314AeA107EDe', - name: 'Prize USDC - LY', - decimals: 6, - symbol: 'PUSDC-LY', - logoURI: 'https://etherscan.io/token/images/centre-usdc_28.png', - extensions: { - underlyingAsset: { - address: '0x7A6DBc7fF4f1a2D864291DB3AeC105A8EeE4A3D2', - symbol: 'USDC', - name: 'USD Coin' - } - } - }, - { - chainId: NETWORK.arbitrum_sepolia, - address: '0xb81b725b16e99c840Ac17B396590da9c93c5bc3B', - name: 'Prize USDC - HY', - decimals: 6, - symbol: 'PUSDC-HY', - logoURI: 'https://etherscan.io/token/images/centre-usdc_28.png', - extensions: { - underlyingAsset: { - address: '0x7A6DBc7fF4f1a2D864291DB3AeC105A8EeE4A3D2', - symbol: 'USDC', - name: 'USD Coin' - } - } - }, - { - chainId: NETWORK.arbitrum_sepolia, - address: '0xf028016D98eBA8fB9d56e9dee04e4639C724E6ae', - name: 'Prize GUSD', - decimals: 2, - symbol: 'PGUSD', - logoURI: - 'https://assets.coingecko.com/coins/images/5992/small/gemini-dollar-gusd.png?1536745278', - extensions: { - underlyingAsset: { - address: '0xB84460D777133a4B86540D557dB35952e4ADFeE7', - symbol: 'GUSD', - name: 'Gemini dollar' - } - } - }, - { - chainId: NETWORK.arbitrum_sepolia, - address: '0xF79C5f53399492308195b1417B8DfaE47e4efD75', - name: 'Prize WBTC', - decimals: 8, - symbol: 'PWBTC', - logoURI: 'https://etherscan.io/token/images/wbtc_28.png?v=1', - extensions: { - underlyingAsset: { - address: '0x1Bc266E1F397517ECe9e384c55C7A5414b683639', - symbol: 'WBTC', - name: 'Wrapped BTC' - } - } - }, - { - chainId: NETWORK.arbitrum_sepolia, - address: '0x5e733FC64179B18986ffa6D840023c99707984ad', - name: 'Prize WETH', - decimals: 18, - symbol: 'PWETH', - logoURI: 'https://etherscan.io/token/images/weth_28.png', - extensions: { - underlyingAsset: { - address: '0x779275Fc1b987dB24463801f3708f42f3c6f6Ceb', - symbol: 'WETH', - name: 'Wrapped Ether' - } - } - }, - { - chainId: NETWORK.arbitrum_sepolia, - address: '0xa5905161eAb67b6A13104537a09A949EF043366E', - name: 'Prize WETH - Test WETH', - decimals: 18, - symbol: 'PWETH', - logoURI: 'https://etherscan.io/token/images/weth_28.png', - extensions: { - underlyingAsset: { - address: '0x779275Fc1b987dB24463801f3708f42f3c6f6Ceb', + address: '0x00a66C161e4C7A9dAEFd3dF8Cbbb08a3DE5b5F73', symbol: 'WETH', name: 'Wrapped Ether' } From 8f7992764290ea98d1ae9c46b32c5b7c92de4535 Mon Sep 17 00:00:00 2001 From: Ncookiez Date: Mon, 4 Mar 2024 16:01:11 -0500 Subject: [PATCH 031/161] reverted aave issue temp fixes --- .../Account/AccountVaultBalance.tsx | 20 ++----------------- .../components/Vault/VaultTotalDeposits.tsx | 13 ------------ 2 files changed, 2 insertions(+), 31 deletions(-) diff --git a/apps/app/src/components/Account/AccountVaultBalance.tsx b/apps/app/src/components/Account/AccountVaultBalance.tsx index 0b5d1402..94fb0615 100644 --- a/apps/app/src/components/Account/AccountVaultBalance.tsx +++ b/apps/app/src/components/Account/AccountVaultBalance.tsx @@ -48,27 +48,11 @@ export const AccountVaultBalance = (props: AccountVaultBalanceProps) => { } if (tokenBalance.amount > 0n) { - // const shiftedAmount = parseFloat(formatUnits(tokenBalance.amount, tokenBalance.decimals)) + const shiftedAmount = parseFloat(formatUnits(tokenBalance.amount, tokenBalance.decimals)) - // return ( - // 1e3 ? { hideZeroes: true } : { maximumFractionDigits: 2 }} - // /> - // ) - - // TODO: revert back to using token balances once exchange rate issue is fixed - const _tokenBalance = !!shareBalance - ? { ...tokenBalance, amount: shareBalance.amount } - : tokenBalance - const shiftedAmount = parseFloat(formatUnits(_tokenBalance.amount, _tokenBalance.decimals)) return ( { return } - // TODO: remove this block entirely once exchange rate issue is fixed - if (!!shareData) { - const token = { ...totalDeposits, amount: shareData.totalSupply } - - return ( - } - /> - ) - } - return ( Date: Mon, 4 Mar 2024 16:14:17 -0500 Subject: [PATCH 032/161] incentives updates to draw bots page --- apps/incentives/src/pages/draw-bots.tsx | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/apps/incentives/src/pages/draw-bots.tsx b/apps/incentives/src/pages/draw-bots.tsx index aaa840e0..6e70ea77 100644 --- a/apps/incentives/src/pages/draw-bots.tsx +++ b/apps/incentives/src/pages/draw-bots.tsx @@ -14,17 +14,12 @@ export default function DrawBotsPage() { content={ <>

- Every draw a random number must be generated, bridged* and supplied to the prize - pool so that prizes may be awarded. + Every draw a random number must be generated and supplied to the prize pool so that + prizes may be awarded.

- The reward for doing so is a percentage of the prize pool's reserve, kept separate - for this purpose. This percentage climbs non-linearly throughout the span of a draw - period after it is closed. -

-

- *While the current RNG implementation requires bridging from Ethereum mainnet to - L2s, this system is currently being refactored. Check back soon! + The reward for doing so is a percentage of the prize pool's reserve. This percentage + climbs non-linearly throughout the span of a draw auction period after it is closed.

} @@ -51,9 +46,6 @@ export default function DrawBotsPage() { Dev Docs: Completing Draw Auctions Guide - - Tutorial: Building a draw auctioning bot - Example: G9 Bots Monorepo From 065129e6ccf471c346ce3365b210f84a3de2b3cb Mon Sep 17 00:00:00 2001 From: Ncookiez Date: Mon, 4 Mar 2024 16:16:43 -0500 Subject: [PATCH 033/161] minor landing page updates --- apps/landing-page/src/components/Home/FaqSection.tsx | 2 +- apps/landing-page/src/components/Tools/StartBuildingSection.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/landing-page/src/components/Home/FaqSection.tsx b/apps/landing-page/src/components/Home/FaqSection.tsx index 19178d4b..13ae32f6 100644 --- a/apps/landing-page/src/components/Home/FaqSection.tsx +++ b/apps/landing-page/src/components/Home/FaqSection.tsx @@ -29,7 +29,7 @@ export const FaqSection = (props: FaqSectionProps) => { Cabana offers a suite of open-source tools for interacting with PoolTogether V5.{' '} app.cabana.fi allows anyone to deposit and withdraw from the protocol. factory.cabana.fi allows - anyone to deploy their own prize vaults using any ERC-4626 compatible yield source.{' '} + anyone to deploy their own prize vaults using ERC-4626 compatible yield sources.{' '} lists.cabana.fi makes it easy for anyone to curate their own prize vault lists that can be shared and accessed via the main app. diff --git a/apps/landing-page/src/components/Tools/StartBuildingSection.tsx b/apps/landing-page/src/components/Tools/StartBuildingSection.tsx index 4dbd7407..cdd5f5dc 100644 --- a/apps/landing-page/src/components/Tools/StartBuildingSection.tsx +++ b/apps/landing-page/src/components/Tools/StartBuildingSection.tsx @@ -18,7 +18,7 @@ export const StartBuildingSection = (props: StartBuildingSectionProps) => { href={LINKS.vaultFactory} imgSrc='/factoryScreenshot.png' title='Cabana Factory' - description='Launch your own prize vaults using the PoolTogether protocol alongside any ERC-4626 compatible yield source.' + description='Launch your own prize vaults using the PoolTogether protocol alongside ERC-4626 compatible yield sources.' /> Date: Mon, 4 Mar 2024 16:49:38 -0500 Subject: [PATCH 034/161] updated rewards builder network config --- apps/rewards-builder/.env.example | 4 +--- apps/rewards-builder/src/constants/config.ts | 20 +++++--------------- 2 files changed, 6 insertions(+), 18 deletions(-) diff --git a/apps/rewards-builder/.env.example b/apps/rewards-builder/.env.example index c53e9e4c..c33bc6a0 100644 --- a/apps/rewards-builder/.env.example +++ b/apps/rewards-builder/.env.example @@ -1,8 +1,6 @@ # Mainnet RPC URLs NEXT_PUBLIC_MAINNET_RPC_URL="YOUR_MAINNET_RPC_HERE" NEXT_PUBLIC_OPTIMISM_RPC_URL="YOUR_OPTIMISM_RPC_HERE" -NEXT_PUBLIC_ARBITRUM_RPC_URL="YOUR_ARBITRUM_RPC_HERE" # Testnet RPC URLs -NEXT_PUBLIC_OPTIMISM_SEPOLIA_RPC_URL="YOUR_OPTIMISM_SEPOLIA_RPC_HERE" -NEXT_PUBLIC_ARBITRUM_SEPOLIA_RPC_URL="YOUR_ARBITRUM_SEPOLIA_RPC_HERE" +NEXT_PUBLIC_SEPOLIA_RPC_URL="YOUR_SEPOLIA_RPC_HERE" diff --git a/apps/rewards-builder/src/constants/config.ts b/apps/rewards-builder/src/constants/config.ts index f13b15a8..abbbf878 100644 --- a/apps/rewards-builder/src/constants/config.ts +++ b/apps/rewards-builder/src/constants/config.ts @@ -19,16 +19,12 @@ import { } from '@rainbow-me/rainbowkit/wallets' import { NETWORK } from '@shared/utilities' import { Address } from 'viem' -import { arbitrum, arbitrumSepolia, mainnet, optimism, optimismSepolia } from 'viem/chains' +import { mainnet, optimism, sepolia } from 'viem/chains' /** * Supported networks */ -export const SUPPORTED_NETWORKS = [ - NETWORK.optimism, - NETWORK.optimism_sepolia, - NETWORK.arbitrum_sepolia -] as const +export const SUPPORTED_NETWORKS = [NETWORK.optimism, NETWORK.sepolia] as const /** * Wagmi networks @@ -36,9 +32,7 @@ export const SUPPORTED_NETWORKS = [ export const WAGMI_CHAINS = { [NETWORK.mainnet]: mainnet, [NETWORK.optimism]: optimism, - [NETWORK.optimism_sepolia]: optimismSepolia, - [NETWORK.arbitrum]: arbitrum, - [NETWORK.arbitrum_sepolia]: arbitrumSepolia + [NETWORK.sepolia]: sepolia } as const /** @@ -69,9 +63,7 @@ export const WALLETS: { [wallet: string]: CreateWalletFn } = { export const RPC_URLS = { [NETWORK.mainnet]: process.env.NEXT_PUBLIC_MAINNET_RPC_URL, [NETWORK.optimism]: process.env.NEXT_PUBLIC_OPTIMISM_RPC_URL, - [NETWORK.optimism_sepolia]: process.env.NEXT_PUBLIC_OPTIMISM_SEPOLIA_RPC_URL, - [NETWORK.arbitrum]: process.env.NEXT_PUBLIC_ARBITRUM_RPC_URL, - [NETWORK.arbitrum_sepolia]: process.env.NEXT_PUBLIC_ARBITRUM_SEPOLIA_RPC_URL + [NETWORK.sepolia]: process.env.NEXT_PUBLIC_SEPOLIA_RPC_URL } as const /** @@ -82,7 +74,5 @@ export const PROMOTION_FILTERS: { } = { [NETWORK.mainnet]: {}, [NETWORK.optimism]: { fromBlock: 112_933_000n }, - [NETWORK.optimism_sepolia]: { fromBlock: 4_400_000n }, - [NETWORK.arbitrum]: {}, - [NETWORK.arbitrum_sepolia]: { fromBlock: 1_490_000n } + [NETWORK.sepolia]: { fromBlock: 5_397_600n } } From e1f45ef7fe15a9409e9cd9ed474d4f65426129d5 Mon Sep 17 00:00:00 2001 From: Ncookiez Date: Mon, 4 Mar 2024 17:02:28 -0500 Subject: [PATCH 035/161] minor updates to cabana swaps --- apps/swaps/src/components/Faq.tsx | 3 +-- apps/swaps/src/components/GrandPrize.tsx | 15 ++++--------- apps/swaps/src/components/RecentWinners.tsx | 21 ++++--------------- apps/swaps/src/components/VaultCards.tsx | 15 ++++--------- apps/swaps/src/constants/config.ts | 19 +++++++---------- apps/swaps/src/utils.ts | 4 +--- .../src/hooks/useLiquidationPairInfo.ts | 13 +++--------- 7 files changed, 24 insertions(+), 66 deletions(-) diff --git a/apps/swaps/src/components/Faq.tsx b/apps/swaps/src/components/Faq.tsx index d39a6e78..0d61fb59 100644 --- a/apps/swaps/src/components/Faq.tsx +++ b/apps/swaps/src/components/Faq.tsx @@ -29,8 +29,7 @@ export const Faq = (props: FaqProps) => { The tokens displayed here are prize vaults built using the ERC-4626 standard, and have been thoroughly audited. Their underlying yield - source (Aave) and ERC-4626 wrappers have also - undergone several audits. + sources and ERC-4626 wrappers have also had their respective audits. ) }, diff --git a/apps/swaps/src/components/GrandPrize.tsx b/apps/swaps/src/components/GrandPrize.tsx index 02049f15..ea5d9b29 100644 --- a/apps/swaps/src/components/GrandPrize.tsx +++ b/apps/swaps/src/components/GrandPrize.tsx @@ -5,7 +5,7 @@ import { } from '@generationsoftware/hyperstructure-react-hooks' import { CurrencyValue } from '@shared/react-components' import { ExternalLink, LINKS, Spinner } from '@shared/ui' -import { NETWORK, PRIZE_POOLS } from '@shared/utilities' +import { PRIZE_POOLS } from '@shared/utilities' import classNames from 'classnames' import { formatUnits } from 'viem' @@ -17,16 +17,9 @@ interface GrandPrizeProps { export const GrandPrize = (props: GrandPrizeProps) => { const { chainId, className } = props - const prizePoolInfo = PRIZE_POOLS.find((pool) => pool.chainId === chainId) as { - chainId: NETWORK - address: `0x${string}` - options: { - prizeTokenAddress: `0x${string}` - drawPeriodInSeconds: number - tierShares: number - reserveShares: number - } - } + const prizePoolInfo = PRIZE_POOLS.find( + (pool) => pool.chainId === chainId + ) as (typeof PRIZE_POOLS)[number] const prizePool = usePrizePool(chainId, prizePoolInfo.address, prizePoolInfo.options) const { data: grandPrize } = useGrandPrize(prizePool, { useCurrentPrizeSizes: true }) const { data: prizeToken } = usePrizeTokenPrice(prizePool) diff --git a/apps/swaps/src/components/RecentWinners.tsx b/apps/swaps/src/components/RecentWinners.tsx index 1a86ea26..3b336e4d 100644 --- a/apps/swaps/src/components/RecentWinners.tsx +++ b/apps/swaps/src/components/RecentWinners.tsx @@ -6,13 +6,7 @@ import { import { CurrencyValue } from '@shared/react-components' import { SubgraphDraw, TokenWithPrice } from '@shared/types' import { ExternalLink, LINKS, Spinner } from '@shared/ui' -import { - getSecondsSinceEpoch, - NETWORK, - PRIZE_POOLS, - SECONDS_PER_DAY, - shorten -} from '@shared/utilities' +import { getSecondsSinceEpoch, PRIZE_POOLS, SECONDS_PER_DAY, shorten } from '@shared/utilities' import classNames from 'classnames' import { useMemo } from 'react' import { formatUnits } from 'viem' @@ -26,16 +20,9 @@ interface RecentWinnersProps { export const RecentWinners = (props: RecentWinnersProps) => { const { chainId, className } = props - const prizePoolInfo = PRIZE_POOLS.find((pool) => pool.chainId === chainId) as { - chainId: NETWORK - address: `0x${string}` - options: { - prizeTokenAddress: `0x${string}` - drawPeriodInSeconds: number - tierShares: number - reserveShares: number - } - } + const prizePoolInfo = PRIZE_POOLS.find( + (pool) => pool.chainId === chainId + ) as (typeof PRIZE_POOLS)[number] const prizePool = usePrizePool(chainId, prizePoolInfo.address, prizePoolInfo.options) const { data: winners } = usePrizeDrawWinners(prizePool) const { data: prizeToken } = usePrizeTokenPrice(prizePool) diff --git a/apps/swaps/src/components/VaultCards.tsx b/apps/swaps/src/components/VaultCards.tsx index db15df53..0cd1a3eb 100644 --- a/apps/swaps/src/components/VaultCards.tsx +++ b/apps/swaps/src/components/VaultCards.tsx @@ -4,7 +4,7 @@ import { useVaults } from '@generationsoftware/hyperstructure-react-hooks' import { Spinner } from '@shared/ui' -import { NETWORK, PRIZE_POOLS } from '@shared/utilities' +import { PRIZE_POOLS } from '@shared/utilities' import classNames from 'classnames' import { VAULT_ADDRESSES } from '@constants/config' import { VaultCard } from './VaultCard' @@ -20,16 +20,9 @@ export const VaultCards = (props: VaultCardsProps) => { const vaultInfoArray = VAULT_ADDRESSES[chainId].map((address) => ({ chainId, address })) const vaults = useVaults(vaultInfoArray, { useAllChains: true }) - const prizePoolInfo = PRIZE_POOLS.find((pool) => pool.chainId === chainId) as { - chainId: NETWORK - address: `0x${string}` - options: { - prizeTokenAddress: `0x${string}` - drawPeriodInSeconds: number - tierShares: number - reserveShares: number - } - } + const prizePoolInfo = PRIZE_POOLS.find( + (pool) => pool.chainId === chainId + ) as (typeof PRIZE_POOLS)[number] const prizePool = usePrizePool(chainId, prizePoolInfo.address, prizePoolInfo.options) const { data: prizeToken } = usePrizeTokenData(prizePool) diff --git a/apps/swaps/src/constants/config.ts b/apps/swaps/src/constants/config.ts index e2de4763..a740b330 100644 --- a/apps/swaps/src/constants/config.ts +++ b/apps/swaps/src/constants/config.ts @@ -5,10 +5,7 @@ import { mainnet, optimism } from 'viem/chains' /** * Supported networks */ -export const SUPPORTED_NETWORKS = { - mainnets: [NETWORK.mainnet, NETWORK.optimism], - testnets: [] -} as const +export const SUPPORTED_NETWORKS = [NETWORK.mainnet, NETWORK.optimism] as const /** * Wagmi networks @@ -29,20 +26,18 @@ export const RPC_URLS = { /** * Vaults to display */ -export const VAULT_ADDRESSES = { - [NETWORK.optimism]: ['0x29Cb69D4780B53c1e5CD4D2B817142D2e9890715'] -} as const +export const VAULT_ADDRESSES: { [chainId: number]: Address[] } = { + // TODO: add vault addresses once deployed +} /** * Curve pools * * NOTE: All vault addresses are lowercase */ -export const CURVE_POOLS: { [chainId: number]: { [vaultAddress: Address]: string } } = { - [NETWORK.optimism]: { '0x31515cfc4550d9c83e2d86e8a352886d1364e2d9': 'factory-v2-76' } -} +export const CURVE_POOLS: { [chainId: number]: { [vaultAddress: Address]: string } } = {} /** - * Minimum "big win" POOL amount + * Minimum "big win" WETH amount */ -export const MIN_BIG_WIN = parseEther('100') +export const MIN_BIG_WIN = parseEther('0.01') diff --git a/apps/swaps/src/utils.ts b/apps/swaps/src/utils.ts index 6d391682..31cfe2cc 100644 --- a/apps/swaps/src/utils.ts +++ b/apps/swaps/src/utils.ts @@ -7,10 +7,8 @@ import { RPC_URLS, SUPPORTED_NETWORKS, WAGMI_CHAINS } from '@constants/config' * @returns */ export const createCustomWagmiConfig = () => { - const networks = [...SUPPORTED_NETWORKS.mainnets, ...SUPPORTED_NETWORKS.testnets] - const supportedNetworks = Object.values(WAGMI_CHAINS).filter( - (chain) => networks.includes(chain.id) && !!RPC_URLS[chain.id] + (chain) => SUPPORTED_NETWORKS.includes(chain.id) && !!RPC_URLS[chain.id] ) as any as [Chain, ...Chain[]] return createConfig({ diff --git a/apps/vault-factory/src/hooks/useLiquidationPairInfo.ts b/apps/vault-factory/src/hooks/useLiquidationPairInfo.ts index 2dd28452..7d3240cc 100644 --- a/apps/vault-factory/src/hooks/useLiquidationPairInfo.ts +++ b/apps/vault-factory/src/hooks/useLiquidationPairInfo.ts @@ -31,16 +31,9 @@ export const useLiquidationPairInfo = ( const vault = useVault({ chainId, address: vaultAddress }) const { data: shareToken } = useVaultShareData(vault) - const prizePoolInfo = PRIZE_POOLS.find((pool) => pool.chainId === chainId) as { - chainId: SupportedNetwork - address: Address - options: { - prizeTokenAddress: Address - drawPeriodInSeconds: number - tierShares: number - reserveShares: number - } - } + const prizePoolInfo = PRIZE_POOLS.find( + (pool) => pool.chainId === chainId + ) as (typeof PRIZE_POOLS)[number] const prizePool = usePrizePool(chainId, prizePoolInfo.address) const { data: periodOffset } = useFirstDrawOpenedAt(prizePool) From 1b692acd26ed817d85ef3cbfbfdd6c371c657025 Mon Sep 17 00:00:00 2001 From: Ncookiez Date: Mon, 4 Mar 2024 17:07:04 -0500 Subject: [PATCH 036/161] minor updates to vaultlist app --- apps/vaultlist-creator/.env.example | 4 +--- apps/vaultlist-creator/src/constants/config.ts | 14 +++++--------- 2 files changed, 6 insertions(+), 12 deletions(-) diff --git a/apps/vaultlist-creator/.env.example b/apps/vaultlist-creator/.env.example index 22115bc3..3710c75b 100644 --- a/apps/vaultlist-creator/.env.example +++ b/apps/vaultlist-creator/.env.example @@ -1,8 +1,6 @@ # Mainnet RPC URLs NEXT_PUBLIC_MAINNET_RPC_URL="YOUR_MAINNET_RPC_HERE" NEXT_PUBLIC_OPTIMISM_RPC_URL="YOUR_OPTIMISM_RPC_HERE" -NEXT_PUBLIC_ARBITRUM_RPC_URL="YOUR_ARBITRUM_RPC_HERE" # Testnet RPC URLs -NEXT_PUBLIC_OPTIMISM_SEPOLIA_RPC_URL="YOUR_OPTIMISM_SEPOLIA_RPC_HERE" -NEXT_PUBLIC_ARBITRUM_SEPOLIA_RPC_URL="YOUR_ARBITRUM_SEPOLIA_RPC_HERE" \ No newline at end of file +NEXT_PUBLIC_SEPOLIA_RPC_URL="YOUR_SEPOLIA_RPC_HERE" \ No newline at end of file diff --git a/apps/vaultlist-creator/src/constants/config.ts b/apps/vaultlist-creator/src/constants/config.ts index 6172a20c..8cbb01ad 100644 --- a/apps/vaultlist-creator/src/constants/config.ts +++ b/apps/vaultlist-creator/src/constants/config.ts @@ -1,12 +1,12 @@ import { NETWORK } from '@shared/utilities' -import { arbitrum, arbitrumSepolia, mainnet, optimism, optimismSepolia } from 'viem/chains' +import { mainnet, optimism, sepolia } from 'viem/chains' /** * Supported networks */ export const SUPPORTED_NETWORKS = { - mainnets: [NETWORK.mainnet, NETWORK.optimism, NETWORK.arbitrum], - testnets: [NETWORK.optimism_sepolia, NETWORK.arbitrum_sepolia] + mainnets: [NETWORK.mainnet, NETWORK.optimism], + testnets: [NETWORK.sepolia] } as const /** @@ -15,9 +15,7 @@ export const SUPPORTED_NETWORKS = { export const WAGMI_CHAINS = { [NETWORK.mainnet]: mainnet, [NETWORK.optimism]: optimism, - [NETWORK.optimism_sepolia]: optimismSepolia, - [NETWORK.arbitrum]: arbitrum, - [NETWORK.arbitrum_sepolia]: arbitrumSepolia + [NETWORK.sepolia]: sepolia } as const /** @@ -26,7 +24,5 @@ export const WAGMI_CHAINS = { export const RPC_URLS = { [NETWORK.mainnet]: process.env.NEXT_PUBLIC_MAINNET_RPC_URL, [NETWORK.optimism]: process.env.NEXT_PUBLIC_OPTIMISM_RPC_URL, - [NETWORK.optimism_sepolia]: process.env.NEXT_PUBLIC_OPTIMISM_SEPOLIA_RPC_URL, - [NETWORK.arbitrum]: process.env.NEXT_PUBLIC_ARBITRUM_RPC_URL, - [NETWORK.arbitrum_sepolia]: process.env.NEXT_PUBLIC_ARBITRUM_SEPOLIA_RPC_URL + [NETWORK.sepolia]: process.env.NEXT_PUBLIC_SEPOLIA_RPC_URL } as const From e02fe7469f3905b73a0c6859b12e27f86f6fe9d8 Mon Sep 17 00:00:00 2001 From: Ncookiez Date: Mon, 4 Mar 2024 17:16:08 -0500 Subject: [PATCH 037/161] minor updates to migrations app (WIP) --- apps/migrations/src/components/V5/V5MigrationsTable.tsx | 2 +- apps/migrations/src/constants/config.ts | 9 ++++++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/apps/migrations/src/components/V5/V5MigrationsTable.tsx b/apps/migrations/src/components/V5/V5MigrationsTable.tsx index 8c0e35b5..4a6bc9ba 100644 --- a/apps/migrations/src/components/V5/V5MigrationsTable.tsx +++ b/apps/migrations/src/components/V5/V5MigrationsTable.tsx @@ -279,7 +279,7 @@ const StatusItem = (props: StatusItemProps) => { return 'Beta Ended' } else if (tags.includes('replaced')) { return 'Better Vault Available' - } else if (tags.includes('old-prize-pool')) { + } else if (tags.includes('canary')) { return 'Old Prize Pool Deployment' } } diff --git a/apps/migrations/src/constants/config.ts b/apps/migrations/src/constants/config.ts index aff6ed32..f03a5111 100644 --- a/apps/migrations/src/constants/config.ts +++ b/apps/migrations/src/constants/config.ts @@ -17,7 +17,7 @@ import { xdefiWallet, zerionWallet } from '@rainbow-me/rainbowkit/wallets' -import { TokenWithLogo, VaultInfo } from '@shared/types' +import { TokenWithLogo } from '@shared/types' import { NETWORK } from '@shared/utilities' import { Address } from 'viem' import { arbitrum, avalanche, celo, mainnet, optimism, polygon } from 'viem/chains' @@ -80,6 +80,7 @@ export const RPC_URLS = { [NETWORK.celo]: process.env.NEXT_PUBLIC_CELO_RPC_URL } as const +// TODO: update addresses to toucan deployment /** * Migration Destinations */ @@ -91,8 +92,9 @@ export const MIGRATION_DESTINATIONS = { /** * V5 Vault Tags */ -export type V5_TAG = 'beta' | 'replaced' | 'old-prize-pool' +export type V5_TAG = 'beta' | 'canary' | 'replaced' +// TODO: add all current canary deployment vault addresses here /** * Deprecated V5 Vaults */ @@ -142,7 +144,7 @@ export const OLD_V5_VAULTS: { name: 'Prize WETH', decimals: 18, symbol: 'pWETH', - tags: ['replaced'], + tags: ['canary'], logoURI: 'https://etherscan.io/token/images/weth_28.png' }, migrateTo: MIGRATION_DESTINATIONS.wethVault @@ -150,6 +152,7 @@ export const OLD_V5_VAULTS: { ] } +// TODO: need to setup promotion settings for old and current deployments (pair of network and twabRewardsAddress) /** * V5 TWAB Promotion Settings */ From a53fb5b6841d3990939fa56a44ed30ca9ce2fe75 Mon Sep 17 00:00:00 2001 From: Ncookiez Date: Tue, 5 Mar 2024 10:42:33 -0500 Subject: [PATCH 038/161] updated vault factory to new testnet --- apps/vault-factory/.env.example | 4 +- .../src/components/HomePageContent.tsx | 4 +- .../src/components/VaultPreview.tsx | 6 +-- .../components/buttons/DeployVaultButton.tsx | 5 ++- apps/vault-factory/src/constants/config.ts | 45 +++++-------------- apps/vault-factory/src/hooks/useVaultInfo.ts | 4 +- shared/types/types/vaults.ts | 3 +- 7 files changed, 23 insertions(+), 48 deletions(-) diff --git a/apps/vault-factory/.env.example b/apps/vault-factory/.env.example index c53e9e4c..e07fb92c 100644 --- a/apps/vault-factory/.env.example +++ b/apps/vault-factory/.env.example @@ -1,8 +1,6 @@ # Mainnet RPC URLs NEXT_PUBLIC_MAINNET_RPC_URL="YOUR_MAINNET_RPC_HERE" NEXT_PUBLIC_OPTIMISM_RPC_URL="YOUR_OPTIMISM_RPC_HERE" -NEXT_PUBLIC_ARBITRUM_RPC_URL="YOUR_ARBITRUM_RPC_HERE" # Testnet RPC URLs -NEXT_PUBLIC_OPTIMISM_SEPOLIA_RPC_URL="YOUR_OPTIMISM_SEPOLIA_RPC_HERE" -NEXT_PUBLIC_ARBITRUM_SEPOLIA_RPC_URL="YOUR_ARBITRUM_SEPOLIA_RPC_HERE" +NEXT_PUBLIC_SEPOLIA_RPC_URL="YOUR_OPTIMISM_SEPOLIA_RPC_HERE" diff --git a/apps/vault-factory/src/components/HomePageContent.tsx b/apps/vault-factory/src/components/HomePageContent.tsx index 9934ce2c..965f9b5a 100644 --- a/apps/vault-factory/src/components/HomePageContent.tsx +++ b/apps/vault-factory/src/components/HomePageContent.tsx @@ -32,7 +32,6 @@ export const HomePageContent = () => { return (
- {/* TODO: add video tutorial once available */}
+ ) : ( @@ -428,7 +430,7 @@ const ManageItem = (props: ManageItemProps) => { chainId={migration.token.chainId} vaultAddress={migration.vaultInfo.address} userAddress={userAddress} - txOptions={{ onSuccess: () => refetchUserV5ClaimableRewards() }} + txOptions={{ onSuccess: () => refetchUserV5ClaimablePromotions() }} fullSized={fullSized} className='md:min-w-[6rem]' /> diff --git a/apps/migrations/src/constants/config.ts b/apps/migrations/src/constants/config.ts index b19ccf0d..6ab44f3b 100644 --- a/apps/migrations/src/constants/config.ts +++ b/apps/migrations/src/constants/config.ts @@ -223,28 +223,27 @@ export const OLD_V5_VAULTS: { ] } -// TODO: need to setup promotion settings for old and current deployments (pair of network and twabRewardsAddress) /** * V5 TWAB Promotion Settings */ export const V5_PROMOTION_SETTINGS: { [network: number]: { - tokenAddresses?: `0x${string}`[] - fromBlock?: bigint - toBlock?: bigint - twabRewardsAddress?: Lowercase
+ twabRewards: { address: Lowercase
; fromBlock?: bigint; toBlock?: bigint }[] + tokenAddresses?: Lowercase
[] } } = { [NETWORK.optimism]: { + twabRewards: [ + { address: '0x27ed5760edc0128e3043f6cc0c3428e337396a66', fromBlock: 112_933_000n } + ], tokenAddresses: [ '0x4200000000000000000000000000000000000042', // OP - '0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85', // USDC - '0x7F5c764cBc14f9669B88837ca1490cCa17c31607', // USDC.e + '0x0b2c639c533813f4aa9d7837caf62653d097ff85', // USDC + '0x7f5c764cbc14f9669b88837ca1490cca17c31607', // USDC.e '0x4200000000000000000000000000000000000006', // WETH - '0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1', // DAI - '0x395Ae52bB17aef68C2888d941736A71dC6d4e125' // POOL - ], - fromBlock: 112_933_000n + '0xda10009cbd5d07dd0cecc66161fc93d7c9000da1', // DAI + '0x395ae52bb17aef68c2888d941736a71dc6d4e125' // POOL + ] } } diff --git a/apps/migrations/src/hooks/useUserV5ClaimablePromotions.ts b/apps/migrations/src/hooks/useUserV5ClaimablePromotions.ts new file mode 100644 index 00000000..58ba2caa --- /dev/null +++ b/apps/migrations/src/hooks/useUserV5ClaimablePromotions.ts @@ -0,0 +1,108 @@ +import { PartialPromotionInfo } from '@shared/types' +import { useMemo } from 'react' +import { Address } from 'viem' +import { useUserV5ClaimableRewards } from './useUserV5ClaimableRewards' +import { useV5AllPromotions } from './useV5AllPromotions' + +export const useAllUserV5ClaimablePromotions = (userAddress: Address) => { + const { + data: allPromotions, + isFetched: isFetchedAllPromotions, + isFetching: isFetchingAllPromotions + } = useV5AllPromotions() + + const { + data: allClaimableRewards, + isFetched: isFetchedAllClaimableRewards, + isFetching: isFetchingAllClaimableRewards, + refetch: refetchAllClaimableRewards + } = useUserV5ClaimableRewards(userAddress, allPromotions) + + const isFetched = isFetchedAllPromotions && isFetchedAllClaimableRewards + const isFetching = isFetchingAllPromotions || isFetchingAllClaimableRewards + const refetch = refetchAllClaimableRewards + + const claimablePromotions = useMemo(() => { + const promotions: ({ + chainId: number + twabRewardsAddress: Lowercase
+ promotionId: bigint + epochRewards: { [epochId: number]: bigint } + } & PartialPromotionInfo)[] = [] + + Object.entries(allClaimableRewards).forEach(([strChainId, contracts]) => { + const chainId = parseInt(strChainId) + + Object.entries(contracts).forEach(([address, entries]) => { + const twabRewardsAddress = address as Lowercase
+ + Object.entries(entries).forEach(([promotionId, epochRewards]) => { + const promotionInfo = allPromotions[chainId]?.[twabRewardsAddress]?.[promotionId] + + if (!!promotionInfo) { + const filteredEpochRewards: { [epochId: number]: bigint } = {} + + const epochIds = Object.keys(epochRewards).map((k) => parseInt(k)) + epochIds.forEach((epochId) => { + if (epochRewards[epochId] > 0n) { + filteredEpochRewards[epochId] = epochRewards[epochId] + } + }) + + promotions.push({ + chainId, + twabRewardsAddress, + promotionId: BigInt(promotionId), + epochRewards: filteredEpochRewards, + ...promotionInfo + }) + } + }) + }) + }) + + return promotions + }, [isFetched, allPromotions, allClaimableRewards]) + + const data = useMemo(() => { + const entries: { + chainId: number + twabRewardsAddress: Lowercase
+ promotionId: bigint + tokenAddress: Lowercase
+ vaultAddress: Lowercase
+ rewards: { [epochId: number]: bigint } + total: bigint + }[] = [] + + claimablePromotions.forEach((promotion) => { + entries.push({ + chainId: promotion.chainId, + twabRewardsAddress: promotion.twabRewardsAddress, + promotionId: promotion.promotionId, + tokenAddress: promotion.token.toLowerCase() as Lowercase
, + vaultAddress: promotion.vault.toLowerCase() as Lowercase
, + rewards: promotion.epochRewards, + total: Object.values(promotion.epochRewards).reduce((a, b) => a + b, 0n) + }) + }) + + return entries + }, [claimablePromotions]) + + return { data, isFetched, isFetching, refetch } +} + +export const useUserV5ClaimablePromotions = ( + chainId: number, + vaultAddress: Address, + userAddress: Address +) => { + const allUserV5ClaimablePromotions = useAllUserV5ClaimablePromotions(userAddress) + + const vaultPromotions = allUserV5ClaimablePromotions.data.filter( + (entry) => entry.chainId === chainId && entry.vaultAddress === vaultAddress.toLowerCase() + ) + + return { ...allUserV5ClaimablePromotions, data: vaultPromotions } +} diff --git a/apps/migrations/src/hooks/useUserV5ClaimableRewards.ts b/apps/migrations/src/hooks/useUserV5ClaimableRewards.ts index 1d5df707..9f659dc3 100644 --- a/apps/migrations/src/hooks/useUserV5ClaimableRewards.ts +++ b/apps/migrations/src/hooks/useUserV5ClaimableRewards.ts @@ -1,122 +1,88 @@ -import { - useAllUserClaimableRewards, - useAllVaultPromotions, - useVaults -} from '@generationsoftware/hyperstructure-react-hooks' -import { PartialPromotionInfo, VaultInfo } from '@shared/types' -import { TWAB_REWARDS_ADDRESSES } from '@shared/utilities' +import { QUERY_KEYS, usePublicClientsByChain } from '@generationsoftware/hyperstructure-react-hooks' +import { NO_REFETCH } from '@shared/generic-react-hooks' +import { PartialPromotionInfo } from '@shared/types' +import { getClaimableRewards } from '@shared/utilities' +import { useQueries } from '@tanstack/react-query' import { useMemo } from 'react' import { Address } from 'viem' -import { OLD_V5_VAULTS, SUPPORTED_NETWORKS, V5_PROMOTION_SETTINGS } from '@constants/config' -export const useAllUserV5ClaimableRewards = (userAddress: Address) => { - const allVaultInfo = useMemo(() => { - const info: VaultInfo[] = [] - - SUPPORTED_NETWORKS.forEach((network) => { - const vaultInfoArray = OLD_V5_VAULTS[network]?.map((entry) => entry.vault) ?? [] - info.push(...vaultInfoArray) - }) - - return info - }, []) - - const vaults = useVaults(allVaultInfo) - - const { - data: allPromotions, - isFetched: isFetchedAllPromotions, - isFetching: isFetchingAllPromotions - } = useAllVaultPromotions(vaults, V5_PROMOTION_SETTINGS) - - const { - data: allClaimableRewards, - isFetched: isFetchedAllClaimableRewards, - isFetching: isFetchingAllClaimableRewards, - refetch: refetchAllClaimableRewards - } = useAllUserClaimableRewards(userAddress, allPromotions) - - const isFetched = isFetchedAllPromotions && isFetchedAllClaimableRewards - const isFetching = isFetchingAllPromotions || isFetchingAllClaimableRewards - const refetch = refetchAllClaimableRewards +export const useUserV5ClaimableRewards = ( + userAddress: Address, + allPromotions: { + [chainId: number]: { + [twabRewardsAddress: `0x${Lowercase}`]: { + [id: string]: PartialPromotionInfo + } + } + } +) => { + const publicClients = usePublicClientsByChain({ useAll: true }) - const claimablePromotions = useMemo(() => { - const claimablePromotions: ({ + const allQueryData = useMemo(() => { + const queries: { chainId: number - promotionId: bigint - epochRewards: { [epochId: number]: bigint } - } & PartialPromotionInfo)[] = [] - - const chainIds = Object.keys(allClaimableRewards).map((k) => parseInt(k)) - - chainIds.forEach((chainId) => { - Object.entries(allClaimableRewards[chainId]).forEach(([id, epochRewards]) => { - const promotionInfo = allPromotions[chainId]?.[id] + twabRewardsAddress: Lowercase
+ promotions: { [id: string]: PartialPromotionInfo } + }[] = [] - if (!!promotionInfo) { - const filteredEpochRewards: { [epochId: number]: bigint } = {} + Object.entries(allPromotions).forEach(([strChainId, contracts]) => { + const chainId = parseInt(strChainId) - const epochIds = Object.keys(epochRewards).map((k) => parseInt(k)) - epochIds.forEach((epochId) => { - if (epochRewards[epochId] > 0n) { - filteredEpochRewards[epochId] = epochRewards[epochId] - } - }) + Object.entries(contracts).forEach(([address, promotions]) => { + const twabRewardsAddress = address as Lowercase
- claimablePromotions.push({ - chainId, - promotionId: BigInt(id), - epochRewards: filteredEpochRewards, - ...promotionInfo - }) - } + queries.push({ chainId, twabRewardsAddress, promotions }) }) }) - return claimablePromotions - }, [isFetched, allPromotions, allClaimableRewards]) - - const data = useMemo(() => { - const entries: { - promotionId: bigint - chainId: number - tokenAddress: Lowercase
- vaultAddress: Lowercase
- twabRewardsAddress: Lowercase
- rewards: { [epochId: number]: bigint } - total: bigint - }[] = [] - - claimablePromotions.forEach((promotion) => { - entries.push({ - promotionId: promotion.promotionId, - chainId: promotion.chainId, - tokenAddress: promotion.token.toLowerCase() as Lowercase
, - vaultAddress: promotion.vault.toLowerCase() as Lowercase
, - twabRewardsAddress: - V5_PROMOTION_SETTINGS[promotion.chainId]?.twabRewardsAddress ?? - (TWAB_REWARDS_ADDRESSES[promotion.chainId].toLowerCase() as Lowercase
), - rewards: promotion.epochRewards, - total: Object.values(promotion.epochRewards).reduce((a, b) => a + b, 0n) - }) + return queries + }, [allPromotions]) + + const results = useQueries({ + queries: allQueryData.map(({ chainId, twabRewardsAddress, promotions }) => { + const publicClient = publicClients[chainId] + const promotionIds = Object.keys(promotions) + + const queryKey = [ + QUERY_KEYS.userClaimableRewards, + chainId, + userAddress, + promotionIds, + twabRewardsAddress + ] + + return { + queryKey, + queryFn: async () => + await getClaimableRewards(publicClient, userAddress, promotions, { twabRewardsAddress }), + enabled: !!chainId && !!publicClient && !!userAddress, + ...NO_REFETCH + } }) + }) + + return useMemo(() => { + const isFetched = results?.every((result) => result.isFetched) + const isFetching = results?.some((result) => result.isFetching) + const refetch = () => results?.forEach((result) => result.refetch()) + + const data: { + [chainId: number]: { + [twabRewardsAddress: Lowercase
]: { [id: string]: { [epochId: number]: bigint } } + } + } = {} + results.forEach((result, i) => { + if (!!result.data) { + const { chainId, twabRewardsAddress } = allQueryData[i] + + if (data[chainId] === undefined) { + data[chainId] = {} + } - return entries - }, [claimablePromotions]) - - return { data, isFetched, isFetching, refetch } -} - -export const useUserV5ClaimableRewards = ( - chainId: number, - vaultAddress: Address, - userAddress: Address -) => { - const allUserV5ClaimableRewards = useAllUserV5ClaimableRewards(userAddress) - - const vaultRewards = allUserV5ClaimableRewards.data.filter( - (entry) => entry.chainId === chainId && entry.vaultAddress === vaultAddress.toLowerCase() - ) + data[chainId][twabRewardsAddress] = result.data + } + }) - return { ...allUserV5ClaimableRewards, data: vaultRewards } + return { isFetched, isFetching, refetch, data } + }, [results]) } diff --git a/apps/migrations/src/hooks/useV5AllPromotionCreatedEvents.ts b/apps/migrations/src/hooks/useV5AllPromotionCreatedEvents.ts new file mode 100644 index 00000000..f82031f0 --- /dev/null +++ b/apps/migrations/src/hooks/useV5AllPromotionCreatedEvents.ts @@ -0,0 +1,96 @@ +import { QUERY_KEYS, usePublicClientsByChain } from '@generationsoftware/hyperstructure-react-hooks' +import { NO_REFETCH } from '@shared/generic-react-hooks' +import { getPromotionCreatedEvents } from '@shared/utilities' +import { useQueries } from '@tanstack/react-query' +import { useMemo } from 'react' +import { Address } from 'viem' +import { OLD_V5_VAULTS, V5_PROMOTION_SETTINGS } from '@constants/config' + +export const useV5AllPromotionCreatedEvents = () => { + const publicClients = usePublicClientsByChain({ useAll: true }) + + const allQueryData = useMemo(() => { + const queries: { + chainId: number + twabRewardsAddress: Lowercase
+ vaultAddresses: Lowercase
[] + tokenAddresses?: Lowercase
[] + fromBlock?: bigint + toBlock?: bigint + }[] = [] + + Object.entries(V5_PROMOTION_SETTINGS).forEach( + ([strChainId, { twabRewards, tokenAddresses }]) => { + const chainId = parseInt(strChainId) + const chainVaultInfo = OLD_V5_VAULTS[chainId] + + if (!!chainVaultInfo) { + const vaultAddresses = chainVaultInfo.map((entry) => entry.vault.address) + + twabRewards.forEach((entry) => { + queries.push({ + chainId, + twabRewardsAddress: entry.address, + vaultAddresses, + tokenAddresses, + fromBlock: entry.fromBlock, + toBlock: entry.toBlock + }) + }) + } + } + ) + + return queries + }, [V5_PROMOTION_SETTINGS]) + + const results = useQueries({ + queries: allQueryData.map((queryData) => { + const publicClient = publicClients[queryData.chainId] + + const queryKey = [ + QUERY_KEYS.promotionCreatedEvents, + queryData.chainId, + undefined, + queryData.vaultAddresses, + queryData.tokenAddresses, + queryData.fromBlock?.toString(), + queryData.toBlock?.toString() ?? 'latest', + queryData.twabRewardsAddress + ] + + return { + queryKey, + queryFn: async () => await getPromotionCreatedEvents(publicClient, queryData), + enabled: !!publicClient && !!allQueryData.length, + ...NO_REFETCH + } + }) + }) + + return useMemo(() => { + const isFetched = results?.every((result) => result.isFetched) + const refetch = () => results?.forEach((result) => result.refetch()) + + const data: { + [chainId: number]: { + [twabRewardsAddress: Lowercase
]: Awaited< + ReturnType + > + } + } = {} + results.forEach((result, i) => { + if (!!result.data) { + const { chainId, twabRewardsAddress } = allQueryData[i] + + if (data[chainId] === undefined) { + data[chainId] = {} + } + + data[chainId][twabRewardsAddress] = result.data + } + }) + + return { isFetched, refetch, data } + }, [results]) +} diff --git a/apps/migrations/src/hooks/useV5AllPromotions.ts b/apps/migrations/src/hooks/useV5AllPromotions.ts new file mode 100644 index 00000000..e66875c5 --- /dev/null +++ b/apps/migrations/src/hooks/useV5AllPromotions.ts @@ -0,0 +1,103 @@ +import { QUERY_KEYS, usePublicClientsByChain } from '@generationsoftware/hyperstructure-react-hooks' +import { NO_REFETCH } from '@shared/generic-react-hooks' +import { PartialPromotionInfo } from '@shared/types' +import { getPromotions } from '@shared/utilities' +import { useQueries } from '@tanstack/react-query' +import { useMemo } from 'react' +import { Address } from 'viem' +import { useV5AllPromotionCreatedEvents } from './useV5AllPromotionCreatedEvents' + +export const useV5AllPromotions = () => { + const publicClients = usePublicClientsByChain({ useAll: true }) + + const { data: allPromotionCreatedEvents } = useV5AllPromotionCreatedEvents() + + const allQueryData = useMemo(() => { + const queries: { + chainId: number + twabRewardsAddress: Lowercase
+ promotionIds: bigint[] + }[] = [] + + Object.entries(allPromotionCreatedEvents).forEach(([strChainId, contracts]) => { + const chainId = parseInt(strChainId) + + Object.entries(contracts).forEach(([address, events]) => { + const twabRewardsAddress = address as Lowercase
+ const promotionIds = events.map((event) => event.args.promotionId) + + queries.push({ chainId, twabRewardsAddress, promotionIds }) + }) + }) + + return queries + }, [allPromotionCreatedEvents]) + + const results = useQueries({ + queries: allQueryData.map(({ chainId, twabRewardsAddress, promotionIds }) => { + const publicClient = publicClients[chainId] + const promotionCreatedEvents = allPromotionCreatedEvents[chainId][twabRewardsAddress] + + const queryKey = [ + QUERY_KEYS.promotionInfo, + chainId, + promotionIds.map(String), + twabRewardsAddress + ] + + return { + queryKey, + queryFn: async () => { + const promotions: { [id: string]: PartialPromotionInfo } = {} + + const allPromotionInfo = await getPromotions(publicClient, promotionIds, { + twabRewardsAddress + }) + + promotionCreatedEvents.forEach((promotionCreatedEvent) => { + const id = promotionCreatedEvent.args.promotionId.toString() + + promotions[id] = { + startTimestamp: promotionCreatedEvent.args.startTimestamp, + vault: promotionCreatedEvent.args.vault, + epochDuration: promotionCreatedEvent.args.epochDuration, + createdAtBlockNumber: promotionCreatedEvent.blockNumber, + token: promotionCreatedEvent.args.token, + tokensPerEpoch: promotionCreatedEvent.args.tokensPerEpoch, + ...allPromotionInfo[id] + } + }) + + return promotions + }, + enabled: !!chainId && !!publicClient && !!promotionCreatedEvents, + ...NO_REFETCH + } + }) + }) + + return useMemo(() => { + const isFetched = results?.every((result) => result.isFetched) + const isFetching = results?.some((result) => result.isFetching) + const refetch = () => results?.forEach((result) => result.refetch()) + + const data: { + [chainId: number]: { + [twabRewardsAddress: Lowercase
]: { [id: string]: PartialPromotionInfo } + } + } = {} + results.forEach((result, i) => { + if (!!result.data) { + const { chainId, twabRewardsAddress } = allQueryData[i] + + if (data[chainId] === undefined) { + data[chainId] = {} + } + + data[chainId][twabRewardsAddress] = result.data + } + }) + + return { isFetched, isFetching, refetch, data } + }, [results]) +} diff --git a/apps/migrations/src/hooks/useV5ClaimRewardsGasEstimate.ts b/apps/migrations/src/hooks/useV5ClaimRewardsGasEstimate.ts index 48846eee..a9116879 100644 --- a/apps/migrations/src/hooks/useV5ClaimRewardsGasEstimate.ts +++ b/apps/migrations/src/hooks/useV5ClaimRewardsGasEstimate.ts @@ -6,7 +6,7 @@ import { GasCostEstimates } from '@shared/types' import { sToMs, TWAB_REWARDS_ADDRESSES, twabRewardsABI } from '@shared/utilities' import { useMemo } from 'react' import { Address, encodeFunctionData } from 'viem' -import { useUserV5ClaimableRewards } from './useUserV5ClaimableRewards' +import { useUserV5ClaimablePromotions } from './useUserV5ClaimablePromotions' export const useV5ClaimRewardsGasEstimate = ( chainId: number, @@ -16,7 +16,7 @@ export const useV5ClaimRewardsGasEstimate = ( ): { data?: GasCostEstimates; isFetched: boolean } => { const twabRewardsAddress = options?.twabRewardsAddress ?? TWAB_REWARDS_ADDRESSES[chainId] - const { data: claimable, isFetched: isFetchedClaimable } = useUserV5ClaimableRewards( + const { data: claimable, isFetched: isFetchedClaimable } = useUserV5ClaimablePromotions( chainId, vaultAddress, userAddress From ef1fa5408b7ca39a35c9f916fd34d91b7d9b50dc Mon Sep 17 00:00:00 2001 From: Ncookiez Date: Mon, 11 Mar 2024 11:35:32 -0400 Subject: [PATCH 044/161] bumped pkg version --- packages/hyperstructure-client-js/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/hyperstructure-client-js/package.json b/packages/hyperstructure-client-js/package.json index a6343d96..3537967a 100644 --- a/packages/hyperstructure-client-js/package.json +++ b/packages/hyperstructure-client-js/package.json @@ -1,6 +1,6 @@ { "name": "@generationsoftware/hyperstructure-client-js", - "version": "1.10.0", + "version": "1.12.0", "license": "MIT", "main": "./dist/index.mjs", "types": "./dist/index.d.ts", From bc7325864a6409e5e2623d311642639bb9d9bb92 Mon Sep 17 00:00:00 2001 From: Ncookiez Date: Mon, 11 Mar 2024 11:44:19 -0400 Subject: [PATCH 045/161] removed prepare script from workers --- workers/protocol-stats-worker/package.json | 1 - workers/token-prices-worker/package.json | 1 - 2 files changed, 2 deletions(-) diff --git a/workers/protocol-stats-worker/package.json b/workers/protocol-stats-worker/package.json index 499e4775..5f3b0dd3 100644 --- a/workers/protocol-stats-worker/package.json +++ b/workers/protocol-stats-worker/package.json @@ -11,7 +11,6 @@ ], "scripts": { "build": "tsup", - "prepare": "pnpm build", "dev": "wrangler dev", "deploy": "wrangler deploy", "clean": "rm -rf dist" diff --git a/workers/token-prices-worker/package.json b/workers/token-prices-worker/package.json index 4cf6dcc8..37d1b766 100644 --- a/workers/token-prices-worker/package.json +++ b/workers/token-prices-worker/package.json @@ -11,7 +11,6 @@ ], "scripts": { "build": "tsup", - "prepare": "pnpm build", "dev": "wrangler dev", "deploy": "wrangler deploy", "clean": "rm -rf dist" From b399b2aa983e341a8b9c22b37e888492d1c11f57 Mon Sep 17 00:00:00 2001 From: Ncookiez Date: Mon, 11 Mar 2024 17:58:38 -0400 Subject: [PATCH 046/161] specific yield source/token listing MVP --- apps/vault-factory/src/atoms.ts | 10 ++ .../src/components/CreateVaultStepContent.tsx | 6 +- .../src/components/CreateVaultStepInfo.tsx | 32 ++++++- .../components/LiquidationPairStepInfo.tsx | 4 +- .../src/components/YieldSourceView.tsx | 20 ++++ .../src/components/buttons/PrevButton.tsx | 6 +- .../src/components/forms/ClaimerForm.tsx | 6 +- .../forms/CustomYieldSourceForm.tsx | 88 +++++++++++++++++ .../forms/DeployLiquidationPairForm.tsx | 4 +- .../src/components/forms/NetworkInput.tsx | 10 +- .../src/components/forms/OwnerAndFeesForm.tsx | 8 +- .../src/components/forms/YieldSourceForm.tsx | 78 +++++++-------- .../src/components/forms/YieldSourceInput.tsx | 70 ++++++++++++++ .../src/components/forms/YieldVaultForm.tsx | 83 ++++++++++++++++ .../src/components/forms/YieldVaultInput.tsx | 96 +++++++++++++++++++ apps/vault-factory/src/constants/config.ts | 83 +++++++++++----- .../src/hooks/useLiquidationPairInfo.ts | 4 +- .../useLiquidationPairMinimumAuctionAmount.ts | 4 +- apps/vault-factory/src/hooks/useVaultInfo.ts | 4 +- .../claimer/[chainId]/[vaultAddress].tsx | 2 +- apps/vault-factory/src/types.ts | 2 + 21 files changed, 518 insertions(+), 102 deletions(-) create mode 100644 apps/vault-factory/src/components/YieldSourceView.tsx create mode 100644 apps/vault-factory/src/components/forms/CustomYieldSourceForm.tsx create mode 100644 apps/vault-factory/src/components/forms/YieldSourceInput.tsx create mode 100644 apps/vault-factory/src/components/forms/YieldVaultForm.tsx create mode 100644 apps/vault-factory/src/components/forms/YieldVaultInput.tsx diff --git a/apps/vault-factory/src/atoms.ts b/apps/vault-factory/src/atoms.ts index 0e69457b..a50c938b 100644 --- a/apps/vault-factory/src/atoms.ts +++ b/apps/vault-factory/src/atoms.ts @@ -8,6 +8,11 @@ import { SupportedNetwork } from './types' */ export const vaultChainIdAtom = atom(undefined) +/** + * Vault Yield Source ID + */ +export const vaultYieldSourceIdAtom = atom('') + /** * Vault Yield Source Name */ @@ -18,6 +23,11 @@ export const vaultYieldSourceNameAtom = atom('') */ export const vaultYieldSourceAddressAtom = atom
(undefined) +/** + * Custom Vault Yield Source State + */ +export const isUsingCustomYieldSourceAtom = atom(false) + /** * Vault Fee Percentage */ diff --git a/apps/vault-factory/src/components/CreateVaultStepContent.tsx b/apps/vault-factory/src/components/CreateVaultStepContent.tsx index ed45eaab..a0d693e0 100644 --- a/apps/vault-factory/src/components/CreateVaultStepContent.tsx +++ b/apps/vault-factory/src/components/CreateVaultStepContent.tsx @@ -8,11 +8,13 @@ import { NameAndSymbolForm } from './forms/NameAndSymbolForm' import { NetworkForm } from './forms/NetworkForm' import { OwnerAndFeesForm } from './forms/OwnerAndFeesForm' import { SetLiquidationPairForm } from './forms/SetLiquidationPairForm' -import { YieldSourceForm } from './forms/YieldSourceForm' +import { YieldVaultForm } from './forms/YieldVaultForm' +import { YieldSourceView } from './YieldSourceView' const allVaultStepContent: ReactNode[] = [ , - , + , + , , , , diff --git a/apps/vault-factory/src/components/CreateVaultStepInfo.tsx b/apps/vault-factory/src/components/CreateVaultStepInfo.tsx index 7c9f629a..e582b577 100644 --- a/apps/vault-factory/src/components/CreateVaultStepInfo.tsx +++ b/apps/vault-factory/src/components/CreateVaultStepInfo.tsx @@ -1,6 +1,9 @@ import { LINKS } from '@shared/ui' -import { ReactNode, useMemo } from 'react' +import { useAtomValue } from 'jotai' +import { ReactNode, useEffect, useMemo } from 'react' +import { isUsingCustomYieldSourceAtom } from 'src/atoms' import { useVaultCreationSteps } from '@hooks/useVaultCreationSteps' +import { useVaultInfo } from '@hooks/useVaultInfo' import { StepInfo } from './StepInfo' export const allVaultStepInfo: { title: string; info: ReactNode }[] = [ @@ -10,7 +13,11 @@ export const allVaultStepInfo: { title: string; info: ReactNode }[] = [ }, { title: 'Choose a yield source', - info: `Any ERC-4626 compatible yield source can be used to generate yield for your prize vault.` + info: `Choose from a list of audited and compatible ERC-4626 yield sources to provide yield for your prize vault, or use your own.` + }, + { + title: 'Choose a token', + info: `Choose the deposit token to use with ???` }, { title: 'Configure ownership and vault fees', @@ -56,12 +63,27 @@ export const CreateVaultStepInfo = (props: CreateVaultStepInfoProps) => { const { step, setStep } = useVaultCreationSteps() + const { yieldSourceName } = useVaultInfo() + + const isUsingCustomYieldSource = useAtomValue(isUsingCustomYieldSourceAtom) + + useEffect(() => { + allVaultStepInfo[2].info = `Choose the deposit token to use with ${yieldSourceName ?? '???'}` + }, [yieldSourceName]) + const blockedSteps = useMemo(() => { + const blocked: number[] = [] + + if (step >= 3 && isUsingCustomYieldSource) { + blocked.push(2) + } + if (step >= 6) { - return [...Array(6).keys()] + blocked.push(...[...Array(6).keys()]) } - return [] - }, [step]) + + return blocked + }, [step, isUsingCustomYieldSource]) return ( { + const { className } = props + + const isUsingCustomYieldSource = useAtomValue(isUsingCustomYieldSourceAtom) + + if (isUsingCustomYieldSource) { + return + } + + return +} diff --git a/apps/vault-factory/src/components/buttons/PrevButton.tsx b/apps/vault-factory/src/components/buttons/PrevButton.tsx index 8a4b7a9e..22af01fa 100644 --- a/apps/vault-factory/src/components/buttons/PrevButton.tsx +++ b/apps/vault-factory/src/components/buttons/PrevButton.tsx @@ -3,16 +3,16 @@ import classNames from 'classnames' import { useVaultCreationSteps } from '@hooks/useVaultCreationSteps' import { PurpleButton, PurpleButtonProps } from './PurpleButton' -interface PrevButtonProps extends Omit {} +interface PrevButtonProps extends Omit {} export const PrevButton = (props: PrevButtonProps) => { - const { className, innerClassName, ...rest } = props + const { onClick, className, innerClassName, ...rest } = props const { prevStep } = useVaultCreationSteps() return ( { useEffect(() => { !!vaultChainId && - formMethods.setValue('vaultClaimer', vaultClaimer ?? CONTRACTS[vaultChainId].claimer, { + formMethods.setValue('vaultClaimer', vaultClaimer ?? NETWORK_CONFIG[vaultChainId].claimer, { shouldValidate: true }) }, []) @@ -58,7 +58,7 @@ export const ClaimerForm = (props: ClaimerFormProps) => { validate={{ isValidAddress: (v: string) => isAddress(v?.trim()) || 'Enter a valid contract address.' }} - defaultValue={!!vaultChainId ? CONTRACTS[vaultChainId].claimer : undefined} + defaultValue={!!vaultChainId ? NETWORK_CONFIG[vaultChainId].claimer : undefined} label='Claimer Contract' needsOverride={true} className='w-full max-w-md' diff --git a/apps/vault-factory/src/components/forms/CustomYieldSourceForm.tsx b/apps/vault-factory/src/components/forms/CustomYieldSourceForm.tsx new file mode 100644 index 00000000..0e0e7ab2 --- /dev/null +++ b/apps/vault-factory/src/components/forms/CustomYieldSourceForm.tsx @@ -0,0 +1,88 @@ +import { ExternalLink } from '@shared/ui' +import classNames from 'classnames' +import { useAtom } from 'jotai' +import { useEffect } from 'react' +import { FormProvider, useForm } from 'react-hook-form' +import { vaultYieldSourceAddressAtom, vaultYieldSourceNameAtom } from 'src/atoms' +import { isValidChars } from 'src/utils' +import { Address, isAddress } from 'viem' +import { NextButton } from '@components/buttons/NextButton' +import { PrevButton } from '@components/buttons/PrevButton' +import { useVaultCreationSteps } from '@hooks/useVaultCreationSteps' +import { SimpleInput } from './SimpleInput' + +export interface CustomYieldSourceFormValues { + vaultYieldSourceName: string + vaultYieldSourceAddress: string +} + +interface CustomYieldSourceFormProps { + className?: string +} + +export const CustomYieldSourceForm = (props: CustomYieldSourceFormProps) => { + const { className } = props + + const formMethods = useForm({ mode: 'onChange' }) + + const [vaultYieldSourceName, setVaultYieldSourceName] = useAtom(vaultYieldSourceNameAtom) + const [vaultYieldSourceAddress, setVaultYieldSourceAddress] = useAtom(vaultYieldSourceAddressAtom) + + const { step, setStep } = useVaultCreationSteps() + + useEffect(() => { + !!vaultYieldSourceName && + formMethods.setValue('vaultYieldSourceName', vaultYieldSourceName, { shouldValidate: true }) + !!vaultYieldSourceAddress && + formMethods.setValue('vaultYieldSourceAddress', vaultYieldSourceAddress, { + shouldValidate: true + }) + }, []) + + const onSubmit = (data: CustomYieldSourceFormValues) => { + setVaultYieldSourceName(data.vaultYieldSourceName.trim()) + setVaultYieldSourceAddress(data.vaultYieldSourceAddress.trim() as Address) + setStep(step + 2) + } + + // TODO: add option to return to audited/compatible yield sources + return ( + +
+ + What is ERC-4626? + + !!v || 'Enter a valid name.', + isValidString: (v: string) => + isValidChars(v, { allowSpaces: true }) || 'Invalid characters in name.' + }} + placeholder='Aave, Yearn, etc.' + label='Yield Source Name' + className='w-full max-w-sm' + /> + isAddress(v?.trim()) || 'Enter a valid contract address.' + }} + placeholder='0x0000...' + label='Yield Source Address' + className='w-full max-w-sm' + /> +
+ + +
+ +
+ ) +} diff --git a/apps/vault-factory/src/components/forms/DeployLiquidationPairForm.tsx b/apps/vault-factory/src/components/forms/DeployLiquidationPairForm.tsx index ead18fed..ce9fea41 100644 --- a/apps/vault-factory/src/components/forms/DeployLiquidationPairForm.tsx +++ b/apps/vault-factory/src/components/forms/DeployLiquidationPairForm.tsx @@ -11,7 +11,7 @@ import { vaultAddressAtom, vaultChainIdAtom } from 'src/atoms' import { SupportedNetwork } from 'src/types' import { Address } from 'viem' import { DeployLiquidationPairButton } from '@components/buttons/DeployLiquidationPairButton' -import { CONTRACTS } from '@constants/config' +import { NETWORK_CONFIG } from '@constants/config' import { useLiquidationPairInitialAmountIn } from '@hooks/useLiquidationPairInitialAmountIn' import { useLiquidationPairMinimumAuctionAmount } from '@hooks/useLiquidationPairMinimumAuctionAmount' import { useLiquidationPairSteps } from '@hooks/useLiquidationPairSteps' @@ -39,7 +39,7 @@ export const DeployLiquidationPairForm = (props: DeployLiquidationPairFormProps) const chainId = useAtomValue(vaultChainIdAtom) as SupportedNetwork const vaultAddress = useAtomValue(vaultAddressAtom) as Address - const prizePool = usePrizePool(chainId, CONTRACTS[chainId].prizePool) + const prizePool = usePrizePool(chainId, NETWORK_CONFIG[chainId].prizePool) const { data: prizeToken } = usePrizeTokenPrice(prizePool) const { data: shareToken } = useToken(chainId, vaultAddress) diff --git a/apps/vault-factory/src/components/forms/NetworkInput.tsx b/apps/vault-factory/src/components/forms/NetworkInput.tsx index ba60edf3..1b72a7b5 100644 --- a/apps/vault-factory/src/components/forms/NetworkInput.tsx +++ b/apps/vault-factory/src/components/forms/NetworkInput.tsx @@ -5,7 +5,7 @@ import { getNiceNetworkNameByChainId } from '@shared/utilities' import classNames from 'classnames' import { useFormContext, useWatch } from 'react-hook-form' import { SupportedNetwork } from 'src/types' -import { CONTRACTS, NETWORK_DESCRIPTIONS } from '@constants/config' +import { NETWORK_CONFIG } from '@constants/config' interface NetworkInputFormValues { vaultChainId: string @@ -48,7 +48,7 @@ interface NetworkCardProps { const NetworkCard = (props: NetworkCardProps) => { const { chainId } = props - const prizePoolAddress = CONTRACTS[chainId].prizePool + const prizePoolAddress = NETWORK_CONFIG[chainId].prizePool const prizePool = usePrizePool(chainId, prizePoolAddress) const { data: grandPrize } = useGrandPrize(prizePool, { useCurrentPrizeSizes: true }) @@ -67,10 +67,10 @@ const NetworkCard = (props: NetworkCardProps) => { )} className='gap-3' > - + {getNiceNetworkNameByChainId(chainId)} - + Grand Prize:{' '} {!!grandPrize ? ( { )} - {NETWORK_DESCRIPTIONS[chainId]} + {NETWORK_CONFIG[chainId].description} ) } diff --git a/apps/vault-factory/src/components/forms/OwnerAndFeesForm.tsx b/apps/vault-factory/src/components/forms/OwnerAndFeesForm.tsx index 68e00944..49617909 100644 --- a/apps/vault-factory/src/components/forms/OwnerAndFeesForm.tsx +++ b/apps/vault-factory/src/components/forms/OwnerAndFeesForm.tsx @@ -1,8 +1,9 @@ import classNames from 'classnames' -import { useAtom } from 'jotai' +import { useAtom, useAtomValue } from 'jotai' import { useEffect } from 'react' import { FormProvider, useForm } from 'react-hook-form' import { + isUsingCustomYieldSourceAtom, vaultFeePercentageAtom, vaultFeeRecipientAddressAtom, vaultOwnerAddressAtom @@ -34,8 +35,9 @@ export const OwnerAndFeesForm = (props: OwnerAndFeesFormProps) => { const [vaultOwner, setVaultOwner] = useAtom(vaultOwnerAddressAtom) const [vaultFeePercentage, setVaultFeePercentage] = useAtom(vaultFeePercentageAtom) const [vaultFeeRecipient, setVaultFeeRecipient] = useAtom(vaultFeeRecipientAddressAtom) + const isUsingCustomYieldSource = useAtomValue(isUsingCustomYieldSourceAtom) - const { nextStep } = useVaultCreationSteps() + const { step, setStep, nextStep } = useVaultCreationSteps() useEffect(() => { formMethods.setValue('vaultOwner', vaultOwner ?? userAddress ?? '', { @@ -99,7 +101,7 @@ export const OwnerAndFeesForm = (props: OwnerAndFeesFormProps) => { className='w-full max-w-md' />
- + setStep(step - 2) : undefined} />
diff --git a/apps/vault-factory/src/components/forms/YieldSourceForm.tsx b/apps/vault-factory/src/components/forms/YieldSourceForm.tsx index 99ca2a91..82f5580f 100644 --- a/apps/vault-factory/src/components/forms/YieldSourceForm.tsx +++ b/apps/vault-factory/src/components/forms/YieldSourceForm.tsx @@ -1,19 +1,17 @@ -import { ExternalLink } from '@shared/ui' +import { Spinner } from '@shared/ui' import classNames from 'classnames' -import { useAtom } from 'jotai' +import { useAtom, useAtomValue, useSetAtom } from 'jotai' import { useEffect } from 'react' import { FormProvider, useForm } from 'react-hook-form' -import { vaultYieldSourceAddressAtom, vaultYieldSourceNameAtom } from 'src/atoms' -import { isValidChars } from 'src/utils' -import { Address, isAddress } from 'viem' +import { vaultChainIdAtom, vaultYieldSourceIdAtom, vaultYieldSourceNameAtom } from 'src/atoms' import { NextButton } from '@components/buttons/NextButton' import { PrevButton } from '@components/buttons/PrevButton' +import { NETWORK_CONFIG } from '@constants/config' import { useVaultCreationSteps } from '@hooks/useVaultCreationSteps' -import { SimpleInput } from './SimpleInput' +import { YieldSourceInput } from './YieldSourceInput' export interface YieldSourceFormValues { - vaultYieldSourceName: string - vaultYieldSourceAddress: string + vaultYieldSourceId: string } interface YieldSourceFormProps { @@ -25,58 +23,50 @@ export const YieldSourceForm = (props: YieldSourceFormProps) => { const formMethods = useForm({ mode: 'onChange' }) - const [vaultYieldSourceName, setVaultYieldSourceName] = useAtom(vaultYieldSourceNameAtom) - const [vaultYieldSourceAddress, setVaultYieldSourceAddress] = useAtom(vaultYieldSourceAddressAtom) + const chainId = useAtomValue(vaultChainIdAtom) + const [vaultYieldSourceId, setVaultYieldSourceId] = useAtom(vaultYieldSourceIdAtom) + const setVaultYieldSourceName = useSetAtom(vaultYieldSourceNameAtom) const { nextStep } = useVaultCreationSteps() useEffect(() => { - !!vaultYieldSourceName && - formMethods.setValue('vaultYieldSourceName', vaultYieldSourceName, { shouldValidate: true }) - !!vaultYieldSourceAddress && - formMethods.setValue('vaultYieldSourceAddress', vaultYieldSourceAddress, { - shouldValidate: true - }) + !!vaultYieldSourceId && + formMethods.setValue('vaultYieldSourceId', vaultYieldSourceId, { shouldValidate: true }) }, []) const onSubmit = (data: YieldSourceFormValues) => { - setVaultYieldSourceName(data.vaultYieldSourceName.trim()) - setVaultYieldSourceAddress(data.vaultYieldSourceAddress.trim() as Address) + setVaultYieldSourceId(data.vaultYieldSourceId) + + if (!!chainId) { + setVaultYieldSourceName( + NETWORK_CONFIG[chainId].yieldSources.find( + (yieldSource) => yieldSource.id === data.vaultYieldSourceId + )?.name ?? '' + ) + } + nextStep() } + if (!chainId) { + return + } + + // TODO: add option to use a custom yield source return (
- - What is ERC-4626? - - !!v || 'Enter a valid name.', - isValidString: (v: string) => - isValidChars(v, { allowSpaces: true }) || 'Invalid characters in name.' - }} - placeholder='Aave, Yearn, etc.' - label='Yield Source Name' - className='w-full max-w-sm' - /> - isAddress(v?.trim()) || 'Enter a valid contract address.' - }} - placeholder='0x0000...' - label='Yield Source Address' - className='w-full max-w-sm' - /> +
+ Select Yield Source +
+ {NETWORK_CONFIG[chainId].yieldSources.map((yieldSource) => ( + + ))} +
+
diff --git a/apps/vault-factory/src/components/forms/YieldSourceInput.tsx b/apps/vault-factory/src/components/forms/YieldSourceInput.tsx new file mode 100644 index 00000000..c18b8370 --- /dev/null +++ b/apps/vault-factory/src/components/forms/YieldSourceInput.tsx @@ -0,0 +1,70 @@ +import { Card, ExternalLink } from '@shared/ui' +import classNames from 'classnames' +import { useFormContext, useWatch } from 'react-hook-form' +import { SupportedNetwork } from 'src/types' +import { NETWORK_CONFIG } from '@constants/config' + +interface YieldSourceInputFormValues { + vaultYieldSourceId: string +} + +interface YieldSourceInputProps { + yieldSource: (typeof NETWORK_CONFIG)[SupportedNetwork]['yieldSources'][number] + className?: string +} + +export const YieldSourceInput = (props: YieldSourceInputProps) => { + const { yieldSource, className } = props + + const { register } = useFormContext() + + const id = `yieldSource-${yieldSource.id}` + + return ( +
+ !!v || 'Select a yield source!' } + })} + type='radio' + value={yieldSource.id} + className='hidden' + /> + +
+ ) +} + +interface YieldSourceCardProps { + yieldSource: (typeof NETWORK_CONFIG)[SupportedNetwork]['yieldSources'][number] +} + +const YieldSourceCard = (props: YieldSourceCardProps) => { + const { yieldSource } = props + + const { vaultYieldSourceId } = useWatch() + + const isSelected = !!vaultYieldSourceId && vaultYieldSourceId === yieldSource.id + + return ( + + {yieldSource.name} + + {yieldSource.href} + + {yieldSource.description} + + ) +} diff --git a/apps/vault-factory/src/components/forms/YieldVaultForm.tsx b/apps/vault-factory/src/components/forms/YieldVaultForm.tsx new file mode 100644 index 00000000..9dff9509 --- /dev/null +++ b/apps/vault-factory/src/components/forms/YieldVaultForm.tsx @@ -0,0 +1,83 @@ +import { Spinner } from '@shared/ui' +import classNames from 'classnames' +import { useAtom, useAtomValue } from 'jotai' +import { useEffect, useMemo } from 'react' +import { FormProvider, useForm } from 'react-hook-form' +import { vaultChainIdAtom, vaultYieldSourceAddressAtom, vaultYieldSourceIdAtom } from 'src/atoms' +import { Address } from 'viem' +import { NextButton } from '@components/buttons/NextButton' +import { PrevButton } from '@components/buttons/PrevButton' +import { NETWORK_CONFIG } from '@constants/config' +import { useVaultCreationSteps } from '@hooks/useVaultCreationSteps' +import { YieldVaultInput } from './YieldVaultInput' + +export interface YieldVaultFormValues { + vaultYieldSourceAddress: string +} + +interface YieldVaultFormProps { + className?: string +} + +export const YieldVaultForm = (props: YieldVaultFormProps) => { + const { className } = props + + const formMethods = useForm({ mode: 'onChange' }) + + const chainId = useAtomValue(vaultChainIdAtom) + const vaultYieldSourceId = useAtomValue(vaultYieldSourceIdAtom) + const [vaultYieldSourceAddress, setVaultYieldSourceAddress] = useAtom(vaultYieldSourceAddressAtom) + + const { nextStep } = useVaultCreationSteps() + + useEffect(() => { + !!vaultYieldSourceAddress && + formMethods.setValue('vaultYieldSourceAddress', vaultYieldSourceAddress, { + shouldValidate: true + }) + }, []) + + const onSubmit = (data: YieldVaultFormValues) => { + setVaultYieldSourceAddress(data.vaultYieldSourceAddress.trim() as Address) + nextStep() + } + + const yieldSource = useMemo(() => { + if (!!chainId) { + return NETWORK_CONFIG[chainId].yieldSources.find( + (yieldSource) => yieldSource.id === vaultYieldSourceId + ) + } + }, [chainId, vaultYieldSourceId]) + + if (!chainId || !yieldSource) { + return + } + + // TODO: add option to return to audited/compatible yield sources + // TODO: add filtering options by tag + return ( + + +
+ Select Deposit Token +
+ {yieldSource.vaults.map((yieldVault) => ( + + ))} +
+
+
+ + +
+ +
+ ) +} diff --git a/apps/vault-factory/src/components/forms/YieldVaultInput.tsx b/apps/vault-factory/src/components/forms/YieldVaultInput.tsx new file mode 100644 index 00000000..433a4926 --- /dev/null +++ b/apps/vault-factory/src/components/forms/YieldVaultInput.tsx @@ -0,0 +1,96 @@ +import { useToken } from '@generationsoftware/hyperstructure-react-hooks' +import { Card, ExternalLink, Spinner } from '@shared/ui' +import { getBlockExplorerUrl, shorten } from '@shared/utilities' +import classNames from 'classnames' +import { useAtomValue } from 'jotai' +import { useFormContext, useWatch } from 'react-hook-form' +import { vaultChainIdAtom } from 'src/atoms' +import { SupportedNetwork } from 'src/types' +import { Address } from 'viem' +import { NETWORK_CONFIG } from '@constants/config' +import { useYieldSourceTokenAddress } from '@hooks/useYieldSourceTokenAddress' + +interface YieldVaultInputFormValues { + vaultYieldSourceAddress: string +} + +interface YieldVaultInputProps { + yieldVault: (typeof NETWORK_CONFIG)[SupportedNetwork]['yieldSources'][number]['vaults'][number] + className?: string +} + +export const YieldVaultInput = (props: YieldVaultInputProps) => { + const { yieldVault, className } = props + + const chainId = useAtomValue(vaultChainIdAtom) + + const { register } = useFormContext() + + if (!chainId) { + return + } + + const id = `yieldVault-${yieldVault.address}` + + return ( +
+ !!v || 'Select a deposit token!' } + })} + type='radio' + value={yieldVault.address} + className='hidden' + /> + +
+ ) +} + +interface YieldVaultCardProps { + chainId: SupportedNetwork + yieldVault: (typeof NETWORK_CONFIG)[SupportedNetwork]['yieldSources'][number]['vaults'][number] +} + +// TODO: add token logos +// TODO: add tags +// TODO: add existing vaults # notice +const YieldVaultCard = (props: YieldVaultCardProps) => { + const { chainId, yieldVault } = props + + const { data: tokenAddress } = useYieldSourceTokenAddress(chainId, yieldVault.address) + const { data: tokenData } = useToken(chainId, tokenAddress as Address) + + const { vaultYieldSourceAddress } = useWatch() + + const isSelected = + !!vaultYieldSourceAddress && + vaultYieldSourceAddress.toLowerCase() === yieldVault.address.toLowerCase() + + return ( + + + {tokenData?.symbol ?? } + + + {shorten(yieldVault.address)} + + + ) +} diff --git a/apps/vault-factory/src/constants/config.ts b/apps/vault-factory/src/constants/config.ts index 8bc02add..5f7e888a 100644 --- a/apps/vault-factory/src/constants/config.ts +++ b/apps/vault-factory/src/constants/config.ts @@ -18,7 +18,7 @@ import { zerionWallet } from '@rainbow-me/rainbowkit/wallets' import { DEFAULT_CLAIMER_ADDRESSES, NETWORK } from '@shared/utilities' -import { SupportedNetwork } from 'src/types' +import { SupportedNetwork, YieldSourceVaultTag } from 'src/types' import { Address } from 'viem' import { mainnet, optimism, sepolia } from 'viem/chains' @@ -68,12 +68,65 @@ export const RPC_URLS = { } as const /** - * Contract addresses + * Network config */ -export const CONTRACTS: Record = { +export const NETWORK_CONFIG: Record< + SupportedNetwork, + { + description: string + prizePool: Address + claimer: Address + lp: { + targetFirstSaleTimeFraction: number + liquidationGasAmount: bigint + minAuctionAmountEth: number + } + yieldSources: { + id: string + name: string + href: string + description: string + vaults: { address: Address; tags?: YieldSourceVaultTag[] }[] + }[] + } +> = { + // [NETWORK.optimism]: { + // description: 'The OG optimistic rollup on Ethereum.', + // prizePool: '', + // claimer: DEFAULT_CLAIMER_ADDRESSES[NETWORK.optimism], + // lp: { + // targetFirstSaleTimeFraction: 0.5, + // liquidationGasAmount: 300_000n, + // minAuctionAmountEth: 0.001 + // }, + // yieldSources: [] + // }, [NETWORK.sepolia]: { + description: 'Sepolia testnet for the Ethereum network.', prizePool: '0x934F03f3132d3B818d7c07F25818ea3961eF18aD', - claimer: DEFAULT_CLAIMER_ADDRESSES[NETWORK.sepolia] + claimer: DEFAULT_CLAIMER_ADDRESSES[NETWORK.sepolia], + lp: { + targetFirstSaleTimeFraction: 0.5, + liquidationGasAmount: 300_000n, + minAuctionAmountEth: 0.001 + }, + yieldSources: [ + { + id: 'aave', + name: 'Aave', + href: 'https://aave.com/', + description: 'Lending and borrowing protocol', + vaults: [ + { address: '0x541D2a84928b7cFFe8455315c63b7F48f2f89cf8', tags: ['stablecoin'] }, + { address: '0x26542531d946E365f23e940aE0977Fd8efD9EFd7', tags: ['stablecoin'] }, + { address: '0x96A4624E73Ff5A305eD04c4895295Fe4E432E2b9', tags: ['stablecoin'] }, + { address: '0xe54D68f333826D334c08194Fa018519bB4Cec4F2', tags: ['stablecoin'] }, + { address: '0xC253890b75D75168202333F83302f9e76c5A1904', tags: ['stablecoin'] }, + { address: '0x7590DECC35A6C43E906721d44Ebc7D4B4662D583' }, + { address: '0xf86811C10b6f596684EE42cB6421a811e7B0527F' } + ] + } + ] } } @@ -83,25 +136,3 @@ export const CONTRACTS: Record = { - [NETWORK.sepolia]: { - targetFirstSaleTimeFraction: 0.5, - liquidationGasAmount: 300_000n, - minAuctionAmountEth: 0.001 - } -} - -/** - * Network descriptions - */ -export const NETWORK_DESCRIPTIONS: Record = { - // [NETWORK.optimism]: 'The OG optimistic rollup on Ethereum.', - [NETWORK.sepolia]: 'Sepolia testnet for the Ethereum network.' -} diff --git a/apps/vault-factory/src/hooks/useLiquidationPairInfo.ts b/apps/vault-factory/src/hooks/useLiquidationPairInfo.ts index 7d3240cc..287b22af 100644 --- a/apps/vault-factory/src/hooks/useLiquidationPairInfo.ts +++ b/apps/vault-factory/src/hooks/useLiquidationPairInfo.ts @@ -13,7 +13,7 @@ import { } from 'src/atoms' import { SupportedNetwork } from 'src/types' import { Address, parseEther, parseUnits } from 'viem' -import { LP_CONFIG } from '@constants/config' +import { NETWORK_CONFIG } from '@constants/config' /** * Returns all info required to deploy a new liquidation pair @@ -39,7 +39,7 @@ export const useLiquidationPairInfo = ( const { data: periodOffset } = useFirstDrawOpenedAt(prizePool) const periodLength = prizePoolInfo.options.drawPeriodInSeconds - const targetFirstSaleTime = LP_CONFIG[chainId].targetFirstSaleTimeFraction * periodLength + const targetFirstSaleTime = NETWORK_CONFIG[chainId].lp.targetFirstSaleTimeFraction * periodLength const decayConstant = parseEther('130') / BigInt(periodLength * 50) diff --git a/apps/vault-factory/src/hooks/useLiquidationPairMinimumAuctionAmount.ts b/apps/vault-factory/src/hooks/useLiquidationPairMinimumAuctionAmount.ts index 92d2551e..9f124776 100644 --- a/apps/vault-factory/src/hooks/useLiquidationPairMinimumAuctionAmount.ts +++ b/apps/vault-factory/src/hooks/useLiquidationPairMinimumAuctionAmount.ts @@ -2,7 +2,7 @@ import { useVault, useVaultSharePrice } from '@generationsoftware/hyperstructure import { useMemo } from 'react' import { SupportedNetwork } from 'src/types' import { Address, parseUnits } from 'viem' -import { LP_CONFIG } from '@constants/config' +import { NETWORK_CONFIG } from '@constants/config' /** * Returns a minimum share amount for a liquidation auction to begin @@ -20,7 +20,7 @@ export const useLiquidationPairMinimumAuctionAmount = ( const data = useMemo(() => { if (!!shareToken?.price) { - const numTokens = LP_CONFIG[chainId].minAuctionAmountEth / shareToken.price + const numTokens = NETWORK_CONFIG[chainId].lp.minAuctionAmountEth / shareToken.price return parseUnits(`${numTokens}`, shareToken.decimals) } else if (isFetched) { return 0n diff --git a/apps/vault-factory/src/hooks/useVaultInfo.ts b/apps/vault-factory/src/hooks/useVaultInfo.ts index a196f0ea..bc5b3353 100644 --- a/apps/vault-factory/src/hooks/useVaultInfo.ts +++ b/apps/vault-factory/src/hooks/useVaultInfo.ts @@ -12,7 +12,7 @@ import { vaultYieldSourceNameAtom } from 'src/atoms' import { Address } from 'viem' -import { CONTRACTS } from '@constants/config' +import { NETWORK_CONFIG } from '@constants/config' import { useYieldSourceTokenAddress } from './useYieldSourceTokenAddress' /** @@ -35,7 +35,7 @@ export const useVaultInfo = (): Partial => { yieldSourceAddress as Address ) - const prizePool = !!chainId ? CONTRACTS[chainId].prizePool : undefined + const prizePool = !!chainId ? NETWORK_CONFIG[chainId].prizePool : undefined return { chainId, diff --git a/apps/vault-factory/src/pages/claimer/[chainId]/[vaultAddress].tsx b/apps/vault-factory/src/pages/claimer/[chainId]/[vaultAddress].tsx index 5d01487a..e44a56e6 100644 --- a/apps/vault-factory/src/pages/claimer/[chainId]/[vaultAddress].tsx +++ b/apps/vault-factory/src/pages/claimer/[chainId]/[vaultAddress].tsx @@ -56,7 +56,7 @@ const ClaimerStepInfo = () => { return ( {}} className='grow items-center justify-center lg:items-start' /> diff --git a/apps/vault-factory/src/types.ts b/apps/vault-factory/src/types.ts index af58bd22..1082c8d4 100644 --- a/apps/vault-factory/src/types.ts +++ b/apps/vault-factory/src/types.ts @@ -19,3 +19,5 @@ export type FormKey = | 'lpAddress' export type VaultState = 'active' | 'invalid' | 'missingLiquidationPair' | 'missingClaimer' + +export type YieldSourceVaultTag = 'stablecoin' | 'lp' | 'lst' From 23cb4712d72edec1ed672bb5025fad3eee7100cf Mon Sep 17 00:00:00 2001 From: Ncookiez Date: Mon, 11 Mar 2024 17:58:51 -0400 Subject: [PATCH 047/161] fixed twab controller address reference --- .../components/Modals/NetworkFees.tsx | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/shared/react-components/components/Modals/NetworkFees.tsx b/shared/react-components/components/Modals/NetworkFees.tsx index 17147904..046240ac 100644 --- a/shared/react-components/components/Modals/NetworkFees.tsx +++ b/shared/react-components/components/Modals/NetworkFees.tsx @@ -8,11 +8,12 @@ import { Spinner } from '@shared/ui' import { erc20ABI, getSecondsSinceEpoch, + PRIZE_POOLS, sToMs, - TWAB_CONTROLLER_ADDRESSES, twabControllerABI, vaultABI } from '@shared/utilities' +import { useMemo } from 'react' import { useAccount } from 'wagmi' import { TX_GAS_ESTIMATES } from '../../constants' import { CurrencyValue } from '../Currency/CurrencyValue' @@ -30,6 +31,11 @@ export const NetworkFees = (props: NetworkFeesProps) => { const { data: tokenAddress } = useVaultTokenAddress(vault) + const twabControllerAddress = useMemo(() => { + return PRIZE_POOLS.find((prizePool) => prizePool.chainId === vault.chainId)?.options + .twabControllerAddress + }, [vault]) + return (
@@ -99,12 +105,12 @@ export const NetworkFees = (props: NetworkFeesProps) => { gasAmount={TX_GAS_ESTIMATES.withdraw} /> )} - {(!show || show.includes('delegation')) && ( + {(!show || show.includes('delegation')) && !!twabControllerAddress && ( Date: Tue, 12 Mar 2024 11:56:31 -0400 Subject: [PATCH 048/161] minor css fix --- apps/vault-factory/src/components/CreatePageContent.tsx | 2 +- apps/vault-factory/src/pages/lp/[chainId]/[vaultAddress].tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/vault-factory/src/components/CreatePageContent.tsx b/apps/vault-factory/src/components/CreatePageContent.tsx index 5907d99c..3395b3fa 100644 --- a/apps/vault-factory/src/components/CreatePageContent.tsx +++ b/apps/vault-factory/src/components/CreatePageContent.tsx @@ -13,7 +13,7 @@ export const CreatePageContent = () => { return (
- + {showPreview.includes(step) && } {showDeployment.includes(step) && }
diff --git a/apps/vault-factory/src/pages/lp/[chainId]/[vaultAddress].tsx b/apps/vault-factory/src/pages/lp/[chainId]/[vaultAddress].tsx index 4bcf6c0a..c591bc64 100644 --- a/apps/vault-factory/src/pages/lp/[chainId]/[vaultAddress].tsx +++ b/apps/vault-factory/src/pages/lp/[chainId]/[vaultAddress].tsx @@ -38,7 +38,7 @@ export default function LiquidationPairPage() {
- +
From d5bb5a5967814e2958c49579ec8f41432c9b7e28 Mon Sep 17 00:00:00 2001 From: Ncookiez Date: Tue, 12 Mar 2024 12:07:43 -0400 Subject: [PATCH 049/161] added links between suggested and custom yield source forms --- .../components/forms/CustomYieldSourceForm.tsx | 16 +++++++++++++--- .../src/components/forms/YieldSourceForm.tsx | 18 ++++++++++++++++-- 2 files changed, 29 insertions(+), 5 deletions(-) diff --git a/apps/vault-factory/src/components/forms/CustomYieldSourceForm.tsx b/apps/vault-factory/src/components/forms/CustomYieldSourceForm.tsx index 0e0e7ab2..3bfefd26 100644 --- a/apps/vault-factory/src/components/forms/CustomYieldSourceForm.tsx +++ b/apps/vault-factory/src/components/forms/CustomYieldSourceForm.tsx @@ -1,9 +1,13 @@ import { ExternalLink } from '@shared/ui' import classNames from 'classnames' -import { useAtom } from 'jotai' +import { useAtom, useSetAtom } from 'jotai' import { useEffect } from 'react' import { FormProvider, useForm } from 'react-hook-form' -import { vaultYieldSourceAddressAtom, vaultYieldSourceNameAtom } from 'src/atoms' +import { + isUsingCustomYieldSourceAtom, + vaultYieldSourceAddressAtom, + vaultYieldSourceNameAtom +} from 'src/atoms' import { isValidChars } from 'src/utils' import { Address, isAddress } from 'viem' import { NextButton } from '@components/buttons/NextButton' @@ -27,6 +31,7 @@ export const CustomYieldSourceForm = (props: CustomYieldSourceFormProps) => { const [vaultYieldSourceName, setVaultYieldSourceName] = useAtom(vaultYieldSourceNameAtom) const [vaultYieldSourceAddress, setVaultYieldSourceAddress] = useAtom(vaultYieldSourceAddressAtom) + const setIsUsingCustomYieldSource = useSetAtom(isUsingCustomYieldSourceAtom) const { step, setStep } = useVaultCreationSteps() @@ -45,7 +50,6 @@ export const CustomYieldSourceForm = (props: CustomYieldSourceFormProps) => { setStep(step + 2) } - // TODO: add option to return to audited/compatible yield sources return (
{ label='Yield Source Address' className='w-full max-w-sm' /> +
diff --git a/apps/vault-factory/src/components/forms/YieldSourceForm.tsx b/apps/vault-factory/src/components/forms/YieldSourceForm.tsx index 82f5580f..1880aed5 100644 --- a/apps/vault-factory/src/components/forms/YieldSourceForm.tsx +++ b/apps/vault-factory/src/components/forms/YieldSourceForm.tsx @@ -3,7 +3,12 @@ import classNames from 'classnames' import { useAtom, useAtomValue, useSetAtom } from 'jotai' import { useEffect } from 'react' import { FormProvider, useForm } from 'react-hook-form' -import { vaultChainIdAtom, vaultYieldSourceIdAtom, vaultYieldSourceNameAtom } from 'src/atoms' +import { + isUsingCustomYieldSourceAtom, + vaultChainIdAtom, + vaultYieldSourceIdAtom, + vaultYieldSourceNameAtom +} from 'src/atoms' import { NextButton } from '@components/buttons/NextButton' import { PrevButton } from '@components/buttons/PrevButton' import { NETWORK_CONFIG } from '@constants/config' @@ -26,6 +31,7 @@ export const YieldSourceForm = (props: YieldSourceFormProps) => { const chainId = useAtomValue(vaultChainIdAtom) const [vaultYieldSourceId, setVaultYieldSourceId] = useAtom(vaultYieldSourceIdAtom) const setVaultYieldSourceName = useSetAtom(vaultYieldSourceNameAtom) + const setIsUsingCustomYieldSource = useSetAtom(isUsingCustomYieldSourceAtom) const { nextStep } = useVaultCreationSteps() @@ -52,7 +58,6 @@ export const YieldSourceForm = (props: YieldSourceFormProps) => { return } - // TODO: add option to use a custom yield source return ( { ))}
+
+ Or... + +
From 37eb1d8826f590c541eea4935c67056f2d8003d0 Mon Sep 17 00:00:00 2001 From: Ncookiez Date: Tue, 12 Mar 2024 12:40:26 -0400 Subject: [PATCH 050/161] improved wrapping on yield vault cards --- apps/vault-factory/src/components/forms/YieldSourceInput.tsx | 5 +---- apps/vault-factory/src/components/forms/YieldVaultForm.tsx | 2 +- apps/vault-factory/src/components/forms/YieldVaultInput.tsx | 5 +---- shared/ui/components/ExternalLink.tsx | 2 +- 4 files changed, 4 insertions(+), 10 deletions(-) diff --git a/apps/vault-factory/src/components/forms/YieldSourceInput.tsx b/apps/vault-factory/src/components/forms/YieldSourceInput.tsx index c18b8370..ba5ae2c4 100644 --- a/apps/vault-factory/src/components/forms/YieldSourceInput.tsx +++ b/apps/vault-factory/src/components/forms/YieldSourceInput.tsx @@ -53,10 +53,7 @@ const YieldSourceCard = (props: YieldSourceCardProps) => { diff --git a/apps/vault-factory/src/components/forms/YieldVaultForm.tsx b/apps/vault-factory/src/components/forms/YieldVaultForm.tsx index 9dff9509..38041866 100644 --- a/apps/vault-factory/src/components/forms/YieldVaultForm.tsx +++ b/apps/vault-factory/src/components/forms/YieldVaultForm.tsx @@ -64,7 +64,7 @@ export const YieldVaultForm = (props: YieldVaultFormProps) => { >
Select Deposit Token -
+
{yieldSource.vaults.map((yieldVault) => ( { diff --git a/shared/ui/components/ExternalLink.tsx b/shared/ui/components/ExternalLink.tsx index e571aa37..d25e3f25 100644 --- a/shared/ui/components/ExternalLink.tsx +++ b/shared/ui/components/ExternalLink.tsx @@ -39,7 +39,7 @@ export const ExternalLink = (props: ExternalLinkProps) => { {children} Date: Tue, 12 Mar 2024 12:56:20 -0400 Subject: [PATCH 051/161] added tags --- .../src/components/forms/YieldVaultForm.tsx | 1 - .../src/components/forms/YieldVaultInput.tsx | 34 ++++++++++++++++--- apps/vault-factory/src/constants/config.ts | 9 +++++ 3 files changed, 39 insertions(+), 5 deletions(-) diff --git a/apps/vault-factory/src/components/forms/YieldVaultForm.tsx b/apps/vault-factory/src/components/forms/YieldVaultForm.tsx index 38041866..22bc4cd3 100644 --- a/apps/vault-factory/src/components/forms/YieldVaultForm.tsx +++ b/apps/vault-factory/src/components/forms/YieldVaultForm.tsx @@ -54,7 +54,6 @@ export const YieldVaultForm = (props: YieldVaultFormProps) => { return } - // TODO: add option to return to audited/compatible yield sources // TODO: add filtering options by tag return ( diff --git a/apps/vault-factory/src/components/forms/YieldVaultInput.tsx b/apps/vault-factory/src/components/forms/YieldVaultInput.tsx index d3fd4d3e..f65ddc23 100644 --- a/apps/vault-factory/src/components/forms/YieldVaultInput.tsx +++ b/apps/vault-factory/src/components/forms/YieldVaultInput.tsx @@ -5,9 +5,9 @@ import classNames from 'classnames' import { useAtomValue } from 'jotai' import { useFormContext, useWatch } from 'react-hook-form' import { vaultChainIdAtom } from 'src/atoms' -import { SupportedNetwork } from 'src/types' +import { SupportedNetwork, YieldSourceVaultTag } from 'src/types' import { Address } from 'viem' -import { NETWORK_CONFIG } from '@constants/config' +import { NETWORK_CONFIG, VAULT_TAGS } from '@constants/config' import { useYieldSourceTokenAddress } from '@hooks/useYieldSourceTokenAddress' interface YieldVaultInputFormValues { @@ -56,7 +56,6 @@ interface YieldVaultCardProps { } // TODO: add token logos -// TODO: add tags // TODO: add existing vaults # notice const YieldVaultCard = (props: YieldVaultCardProps) => { const { chainId, yieldVault } = props @@ -76,7 +75,7 @@ const YieldVaultCard = (props: YieldVaultCardProps) => { 'w-full h-full border cursor-pointer overflow-hidden hover:bg-pt-purple-50/20', { 'border-pt-teal-dark': isSelected, 'border-transparent': !isSelected } )} - className='gap-3' + className='gap-3 !justify-start !p-6' > {tokenData?.symbol ?? } @@ -88,6 +87,33 @@ const YieldVaultCard = (props: YieldVaultCardProps) => { > {shorten(yieldVault.address)} + ) } + +interface YieldVaultCardTagsProps { + tags?: YieldSourceVaultTag[] + className?: string +} + +const YieldVaultCardTags = (props: YieldVaultCardTagsProps) => { + const { tags, className } = props + + if (!tags?.length) { + return <> + } + + return ( +
+ {tags.map((tag) => ( + + {VAULT_TAGS[tag]} + + ))} +
+ ) +} diff --git a/apps/vault-factory/src/constants/config.ts b/apps/vault-factory/src/constants/config.ts index 5f7e888a..f1a9ab84 100644 --- a/apps/vault-factory/src/constants/config.ts +++ b/apps/vault-factory/src/constants/config.ts @@ -130,6 +130,15 @@ export const NETWORK_CONFIG: Record< } } +/** + * Vault tag display names + */ +export const VAULT_TAGS: Record = { + stablecoin: 'Stablecoin', + lp: 'LP Token', + lst: 'Liquid Staking' +} + /** * Local storage keys */ From 96902c122c7783a92b7e7514cc4740a76a222bbf Mon Sep 17 00:00:00 2001 From: Ncookiez Date: Tue, 12 Mar 2024 14:39:07 -0400 Subject: [PATCH 052/161] added token icons --- .../src/components/forms/YieldVaultInput.tsx | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/apps/vault-factory/src/components/forms/YieldVaultInput.tsx b/apps/vault-factory/src/components/forms/YieldVaultInput.tsx index f65ddc23..c5cca94c 100644 --- a/apps/vault-factory/src/components/forms/YieldVaultInput.tsx +++ b/apps/vault-factory/src/components/forms/YieldVaultInput.tsx @@ -1,4 +1,5 @@ import { useToken } from '@generationsoftware/hyperstructure-react-hooks' +import { TokenIcon } from '@shared/react-components' import { Card, ExternalLink, Spinner } from '@shared/ui' import { getBlockExplorerUrl, shorten } from '@shared/utilities' import classNames from 'classnames' @@ -55,13 +56,12 @@ interface YieldVaultCardProps { yieldVault: (typeof NETWORK_CONFIG)[SupportedNetwork]['yieldSources'][number]['vaults'][number] } -// TODO: add token logos // TODO: add existing vaults # notice const YieldVaultCard = (props: YieldVaultCardProps) => { const { chainId, yieldVault } = props const { data: tokenAddress } = useYieldSourceTokenAddress(chainId, yieldVault.address) - const { data: tokenData } = useToken(chainId, tokenAddress as Address) + const { data: token } = useToken(chainId, tokenAddress as Address) const { vaultYieldSourceAddress } = useWatch() @@ -77,9 +77,16 @@ const YieldVaultCard = (props: YieldVaultCardProps) => { )} className='gap-3 !justify-start !p-6' > - - {tokenData?.symbol ?? } - +
+ {!!token ? ( + <> + + {token.symbol} + + ) : ( + + )} +
Date: Tue, 12 Mar 2024 18:53:30 -0400 Subject: [PATCH 053/161] added hooks to query all vaults deployed with factory --- .../src/components/CreatePageContent.tsx | 4 +- .../src/components/DeployedVaultCard.tsx | 4 +- .../src/components/DeployedVaultsTable.tsx | 6 +-- .../components/buttons/DeployVaultButton.tsx | 4 +- .../components/forms/AddDeployedVaultForm.tsx | 4 +- .../src/hooks/useAllDeployedVaultAddresses.ts | 43 ++++++++++++++++ .../useDeployedVaultYieldSourceAddresses.ts | 51 +++++++++++++++++++ ...oyedVaults.ts => useUserDeployedVaults.ts} | 2 +- shared/utilities/utils/vaults.ts | 44 ++++++++++++++++ 9 files changed, 150 insertions(+), 12 deletions(-) create mode 100644 apps/vault-factory/src/hooks/useAllDeployedVaultAddresses.ts create mode 100644 apps/vault-factory/src/hooks/useDeployedVaultYieldSourceAddresses.ts rename apps/vault-factory/src/hooks/{useDeployedVaults.ts => useUserDeployedVaults.ts} (96%) diff --git a/apps/vault-factory/src/components/CreatePageContent.tsx b/apps/vault-factory/src/components/CreatePageContent.tsx index 3395b3fa..34a54c13 100644 --- a/apps/vault-factory/src/components/CreatePageContent.tsx +++ b/apps/vault-factory/src/components/CreatePageContent.tsx @@ -7,8 +7,8 @@ import { VaultPreview } from './VaultPreview' export const CreatePageContent = () => { const { step } = useVaultCreationSteps() - const showPreview: number[] = [1, 2, 3, 4] - const showDeployment: number[] = [6, 7] + const showPreview: number[] = [1, 2, 3, 4, 5] + const showDeployment: number[] = [7, 8] return (
diff --git a/apps/vault-factory/src/components/DeployedVaultCard.tsx b/apps/vault-factory/src/components/DeployedVaultCard.tsx index c007df84..ed6289eb 100644 --- a/apps/vault-factory/src/components/DeployedVaultCard.tsx +++ b/apps/vault-factory/src/components/DeployedVaultCard.tsx @@ -14,9 +14,9 @@ import { useRouter } from 'next/router' import { ReactNode } from 'react' import { zeroAddress } from 'viem' import { useAccount } from 'wagmi' -import { useDeployedVaults } from '@hooks/useDeployedVaults' import { useDeployedVaultState } from '@hooks/useDeployedVaultState' import { useLiquidationPairSteps } from '@hooks/useLiquidationPairSteps' +import { useUserDeployedVaults } from '@hooks/useUserDeployedVaults' interface DeployedVaultCardProps { vault: Vault @@ -157,7 +157,7 @@ const VaultActionsItem = (props: ItemProps) => { const { setStep: setLpStep } = useLiquidationPairSteps() - const { removeVault } = useDeployedVaults() + const { removeVault } = useUserDeployedVaults() const onClickDeployLp = () => { setLpStep(0) diff --git a/apps/vault-factory/src/components/DeployedVaultsTable.tsx b/apps/vault-factory/src/components/DeployedVaultsTable.tsx index 685e7589..89b6231b 100644 --- a/apps/vault-factory/src/components/DeployedVaultsTable.tsx +++ b/apps/vault-factory/src/components/DeployedVaultsTable.tsx @@ -16,9 +16,9 @@ import { useRouter } from 'next/router' import { zeroAddress } from 'viem' import { useAccount } from 'wagmi' import { SUPPORTED_NETWORKS } from '@constants/config' -import { useDeployedVaults } from '@hooks/useDeployedVaults' import { useDeployedVaultState } from '@hooks/useDeployedVaultState' import { useLiquidationPairSteps } from '@hooks/useLiquidationPairSteps' +import { useUserDeployedVaults } from '@hooks/useUserDeployedVaults' import { DeployedVaultCard } from './DeployedVaultCard' interface DeployedVaultsTableProps { @@ -28,7 +28,7 @@ interface DeployedVaultsTableProps { export const DeployedVaultsTable = (props: DeployedVaultsTableProps) => { const { className } = props - const { vaultInfoArray } = useDeployedVaults() + const { vaultInfoArray } = useUserDeployedVaults() const vaults = useVaults(vaultInfoArray, { useAllChains: true }) const vaultsArray = Object.values(vaults.vaults).filter((vault) => SUPPORTED_NETWORKS.includes(vault.chainId) @@ -211,7 +211,7 @@ const VaultActionsItem = (props: ItemProps) => { const { setStep: setLpStep } = useLiquidationPairSteps() - const { removeVault } = useDeployedVaults() + const { removeVault } = useUserDeployedVaults() const onClickDeployLp = () => { setLpStep(0) diff --git a/apps/vault-factory/src/components/buttons/DeployVaultButton.tsx b/apps/vault-factory/src/components/buttons/DeployVaultButton.tsx index ad28b67d..4715e86c 100644 --- a/apps/vault-factory/src/components/buttons/DeployVaultButton.tsx +++ b/apps/vault-factory/src/components/buttons/DeployVaultButton.tsx @@ -11,7 +11,7 @@ import { useSetAtom } from 'jotai' import { vaultAddressAtom } from 'src/atoms' import { SupportedNetwork } from 'src/types' import { Address } from 'viem' -import { useDeployedVaults } from '@hooks/useDeployedVaults' +import { useUserDeployedVaults } from '@hooks/useUserDeployedVaults' import { useVaultInfo } from '@hooks/useVaultInfo' interface DeployVaultButtonProps { @@ -36,7 +36,7 @@ export const DeployVaultButton = (props: DeployVaultButtonProps) => { const setVaultAddress = useSetAtom(vaultAddressAtom) - const { addVault } = useDeployedVaults() + const { addVault } = useUserDeployedVaults() const { isWaiting: isWaitingDeploy, diff --git a/apps/vault-factory/src/components/forms/AddDeployedVaultForm.tsx b/apps/vault-factory/src/components/forms/AddDeployedVaultForm.tsx index 86be30ab..a926f4c7 100644 --- a/apps/vault-factory/src/components/forms/AddDeployedVaultForm.tsx +++ b/apps/vault-factory/src/components/forms/AddDeployedVaultForm.tsx @@ -7,7 +7,7 @@ import { FormProvider, useForm, useFormContext, useWatch } from 'react-hook-form import { Address, isAddress } from 'viem' import { PurpleButton } from '@components/buttons/PurpleButton' import { SUPPORTED_NETWORKS } from '@constants/config' -import { useDeployedVaults } from '@hooks/useDeployedVaults' +import { useUserDeployedVaults } from '@hooks/useUserDeployedVaults' import { SimpleInput } from './SimpleInput' interface AddDeployedVaultFormValues { @@ -26,7 +26,7 @@ export const AddDeployedVaultForm = (props: AddDeployedVaultFormProps) => { const formMethods = useForm({ mode: 'onChange' }) - const { addVault } = useDeployedVaults() + const { addVault } = useUserDeployedVaults() const onSubmit = (data: AddDeployedVaultFormValues) => { addVault({ diff --git a/apps/vault-factory/src/hooks/useAllDeployedVaultAddresses.ts b/apps/vault-factory/src/hooks/useAllDeployedVaultAddresses.ts new file mode 100644 index 00000000..b1f66ccd --- /dev/null +++ b/apps/vault-factory/src/hooks/useAllDeployedVaultAddresses.ts @@ -0,0 +1,43 @@ +import { usePublicClientsByChain } from '@generationsoftware/hyperstructure-react-hooks' +import { NO_REFETCH } from '@shared/generic-react-hooks' +import { getVaultAddressesFromFactory } from '@shared/utilities' +import { useQueries } from '@tanstack/react-query' +import { useMemo } from 'react' +import { Address } from 'viem' +import { SUPPORTED_NETWORKS } from '@constants/config' + +/** + * Returns the addresses of vaults deployed through the factory + * @returns + */ +export const useAllDeployedVaultAddresses = () => { + const publicClients = usePublicClientsByChain({ useAll: true }) + + const results = useQueries({ + queries: SUPPORTED_NETWORKS.map((chainId) => { + const publicClient = publicClients[chainId] + + return { + queryKey: ['vaultAddressesFromFactory', chainId], + queryFn: async () => await getVaultAddressesFromFactory(publicClient), + enabled: !!chainId && !!publicClient, + ...NO_REFETCH + } + }) + }) + + return useMemo(() => { + const isFetched = results?.every((result) => result.isFetched) + const isFetching = results?.some((result) => result.isFetching) + const refetch = () => results?.forEach((result) => result.refetch()) + + const data: { [chainId: number]: Lowercase
[] } = {} + results.forEach((result, i) => { + if (result.status === 'success') { + data[SUPPORTED_NETWORKS[i]] = result.data + } + }) + + return { isFetched, isFetching, refetch, data } + }, [results]) +} diff --git a/apps/vault-factory/src/hooks/useDeployedVaultYieldSourceAddresses.ts b/apps/vault-factory/src/hooks/useDeployedVaultYieldSourceAddresses.ts new file mode 100644 index 00000000..6c550c2d --- /dev/null +++ b/apps/vault-factory/src/hooks/useDeployedVaultYieldSourceAddresses.ts @@ -0,0 +1,51 @@ +import { Vault } from '@generationsoftware/hyperstructure-client-js' +import { QUERY_KEYS, usePublicClientsByChain } from '@generationsoftware/hyperstructure-react-hooks' +import { NO_REFETCH } from '@shared/generic-react-hooks' +import { useQueries } from '@tanstack/react-query' +import { useMemo } from 'react' +import { SupportedNetwork } from 'src/types' +import { Address } from 'viem' +import { useAllDeployedVaultAddresses } from './useAllDeployedVaultAddresses' + +/** + * Returns the yield source addresses of all deployed vaults from a network's factory + * @returns + */ +export const useDeployedVaultYieldSourceAddresses = (chainId: SupportedNetwork) => { + const publicClients = usePublicClientsByChain({ useAll: true }) + + const { data: allDeployedVaultAddresses, isFetched: isFetchedAllDeployedVaultAddresses } = + useAllDeployedVaultAddresses() + + const deployedVaultAddresses = allDeployedVaultAddresses[chainId] ?? [] + + const results = useQueries({ + queries: deployedVaultAddresses.map((vaultAddress) => { + const publicClient = publicClients[chainId] + + const vault = new Vault(chainId, vaultAddress, publicClient) + + return { + queryKey: [QUERY_KEYS.vaultYieldSources, [vault.id]], + queryFn: async () => await vault.getYieldSource(), + enabled: !!chainId && !!publicClient && !!vault && isFetchedAllDeployedVaultAddresses, + ...NO_REFETCH + } + }) + }) + + return useMemo(() => { + const isFetched = results?.every((result) => result.isFetched) + const isFetching = results?.some((result) => result.isFetching) + const refetch = () => results?.forEach((result) => result.refetch()) + + const data: { [vaultAddress: Lowercase
]: Lowercase
} = {} + results.forEach((result, i) => { + if (result.status === 'success') { + data[deployedVaultAddresses[i]] = result.data.toLowerCase() as Lowercase
+ } + }) + + return { isFetched, isFetching, refetch, data } + }, [results]) +} diff --git a/apps/vault-factory/src/hooks/useDeployedVaults.ts b/apps/vault-factory/src/hooks/useUserDeployedVaults.ts similarity index 96% rename from apps/vault-factory/src/hooks/useDeployedVaults.ts rename to apps/vault-factory/src/hooks/useUserDeployedVaults.ts index ee7d7166..a573c3c1 100644 --- a/apps/vault-factory/src/hooks/useDeployedVaults.ts +++ b/apps/vault-factory/src/hooks/useUserDeployedVaults.ts @@ -9,7 +9,7 @@ import { LOCAL_STORAGE_KEYS } from '@constants/config' /** * Returns a record of a user's deployed vaults and methods to update them */ -export const useDeployedVaults = () => { +export const useUserDeployedVaults = () => { const [vaultIds, setVaultIds] = useAtom(vaultIdsAtom) const addVault = (vaultInfo: VaultInfo) => { diff --git a/shared/utilities/utils/vaults.ts b/shared/utilities/utils/vaults.ts index f821d766..64777d3b 100644 --- a/shared/utilities/utils/vaults.ts +++ b/shared/utilities/utils/vaults.ts @@ -2,6 +2,8 @@ import { VaultInfo } from '@shared/types' import { Address, formatUnits, isAddress, parseUnits, PublicClient } from 'viem' import { twabControllerABI } from '../abis/twabController' import { vaultABI } from '../abis/vault' +import { vaultFactoryABI } from '../abis/vaultFactory' +import { VAULT_FACTORY_ADDRESSES } from '../constants' import { formatStringWithPrecision } from './formatting' import { getComplexMulticallResults, @@ -224,6 +226,48 @@ export const getVaultAddresses = (vaults: VaultInfo[]): { [chainId: number]: Add return vaultAddresses } +/** + * Returns all vault addresses from the vault factory + * @param publicClient a public Viem client to query through + * @returns + */ +export const getVaultAddressesFromFactory = async (publicClient: PublicClient) => { + const vaultAddresses = new Set>() + + const chainId = await publicClient.getChainId() + + const vaultFactoryAddress = VAULT_FACTORY_ADDRESSES[chainId] + + if (!vaultFactoryAddress) throw new Error(`No vault factory address set for chain ID ${chainId}`) + + const totalVaults = await publicClient.readContract({ + address: vaultFactoryAddress, + abi: vaultFactoryABI, + functionName: 'totalVaults' + }) + + const vaultIndexes = [...Array(Number(totalVaults)).keys()] + const calls = vaultIndexes.map((vaultIndex) => ({ + functionName: 'allVaults', + args: [vaultIndex] + })) + + const multicallResults: (string | undefined)[] = await getSimpleMulticallResults( + publicClient, + vaultFactoryAddress, + vaultFactoryABI, + calls + ) + + multicallResults.forEach((address) => { + if (!!address && isAddress(address)) { + vaultAddresses.add(address.toLowerCase() as Lowercase
) + } + }) + + return [...vaultAddresses] +} + /** * Returns the underlying token addresses for each vault from a given chain * @param publicClient a public Viem client for the chain that should be queried From a4638c18dcfc7a4d6bf73b984f2082e51b23a87c Mon Sep 17 00:00:00 2001 From: Ncookiez Date: Wed, 13 Mar 2024 11:36:58 -0400 Subject: [PATCH 054/161] added yield buffer approvals before vault deployment --- .../components/buttons/DeployVaultButton.tsx | 123 +++++++++++++++--- .../useSendApproveYieldBufferTransaction.ts | 97 ++++++++++++++ apps/vault-factory/src/hooks/useVaultInfo.ts | 6 +- .../vault-factory/src/hooks/useYieldBuffer.ts | 31 +++++ .../useSendDeployVaultTransaction.ts | 20 ++- shared/types/types/vaults.ts | 1 + 6 files changed, 253 insertions(+), 25 deletions(-) create mode 100644 apps/vault-factory/src/hooks/useSendApproveYieldBufferTransaction.ts create mode 100644 apps/vault-factory/src/hooks/useYieldBuffer.ts diff --git a/apps/vault-factory/src/components/buttons/DeployVaultButton.tsx b/apps/vault-factory/src/components/buttons/DeployVaultButton.tsx index 4715e86c..0f669591 100644 --- a/apps/vault-factory/src/components/buttons/DeployVaultButton.tsx +++ b/apps/vault-factory/src/components/buttons/DeployVaultButton.tsx @@ -1,16 +1,21 @@ import { useSendDeployVaultTransaction, - useToken + useTokenAllowance, + useTokenBalance } from '@generationsoftware/hyperstructure-react-hooks' -import { ArrowRightIcon } from '@heroicons/react/24/outline' +import { ArrowRightIcon, InformationCircleIcon } from '@heroicons/react/24/outline' import { useAddRecentTransaction, useChainModal, useConnectModal } from '@rainbow-me/rainbowkit' import { createDeployVaultTxToast, TransactionButton } from '@shared/react-components' import { VaultDeployInfo } from '@shared/types' +import { Tooltip } from '@shared/ui' +import { VAULT_FACTORY_ADDRESSES } from '@shared/utilities' import classNames from 'classnames' import { useSetAtom } from 'jotai' import { vaultAddressAtom } from 'src/atoms' import { SupportedNetwork } from 'src/types' import { Address } from 'viem' +import { useAccount } from 'wagmi' +import { useSendApproveYieldBufferTransaction } from '@hooks/useSendApproveYieldBufferTransaction' import { useUserDeployedVaults } from '@hooks/useUserDeployedVaults' import { useVaultInfo } from '@hooks/useVaultInfo' @@ -23,11 +28,33 @@ interface DeployVaultButtonProps { export const DeployVaultButton = (props: DeployVaultButtonProps) => { const { onSuccess, className, innerClassName } = props - const vault = useVaultInfo() + const { address: userAddress } = useAccount() - const { data: tokenData } = useToken( - vault.chainId as SupportedNetwork, - vault.tokenAddress as Address + const vaultInfo = useVaultInfo() + const { chainId, tokenAddress, yieldBuffer } = vaultInfo + + const { + data: token, + isFetched: isFetchedToken, + refetch: refetchUserTokenBalance + } = useTokenBalance( + chainId as SupportedNetwork, + userAddress as Address, + tokenAddress as Address, + { refetchOnWindowFocus: true } + ) + + const vaultFactoryAddress = !!chainId ? VAULT_FACTORY_ADDRESSES[chainId] : undefined + + const { + data: allowance, + isFetched: isFetchedAllowance, + refetch: refetchAllowance + } = useTokenAllowance( + chainId as SupportedNetwork, + userAddress as Address, + vaultFactoryAddress as Address, + token?.address as Address ) const { openConnectModal } = useConnectModal() @@ -38,52 +65,106 @@ export const DeployVaultButton = (props: DeployVaultButtonProps) => { const { addVault } = useUserDeployedVaults() + const { + isWaiting: isWaitingApproval, + isConfirming: isConfirmingApproval, + isSuccess: isSuccessfulApproval, + txHash: approvalTxHash, + sendApproveYieldBufferTransaction: sendApproveYieldBufferTransaction + } = useSendApproveYieldBufferTransaction({ + onSuccess: () => { + refetchAllowance() + } + }) + const { isWaiting: isWaitingDeploy, isConfirming: isConfirmingDeploy, isSuccess: isSuccessfulDeploy, txHash: deployTxHash, sendDeployVaultTransaction - } = useSendDeployVaultTransaction(vault as VaultDeployInfo, { + } = useSendDeployVaultTransaction(vaultInfo as VaultDeployInfo, { onSend: (txHash) => { - if (!!vault.chainId) { - createDeployVaultTxToast({ chainId: vault.chainId, txHash, addRecentTransaction }) + if (!!chainId) { + createDeployVaultTxToast({ chainId: chainId, txHash, addRecentTransaction }) } }, onSuccess: (txReceipt) => { - if (!!vault.chainId) { + if (!!chainId) { const vaultAddress = txReceipt.logs[0].address setVaultAddress(vaultAddress) - addVault({ chainId: vault.chainId, address: vaultAddress }) + addVault({ chainId: chainId, address: vaultAddress }) + refetchUserTokenBalance() } onSuccess?.() } }) - const deployVaultEnabled = !!vault.chainId && !!tokenData && !!sendDeployVaultTransaction + const isDataFetched = + !!userAddress && + !!chainId && + !!token && + isFetchedToken && + allowance !== undefined && + isFetchedAllowance && + !!yieldBuffer - if (!vault.chainId) { + const buttonClassName = classNames( + 'min-w-[9rem] !bg-pt-purple-600 !border-pt-purple-600 hover:!bg-pt-purple-700 focus:outline-transparent', + className + ) + const buttonInnerClassName = classNames( + 'flex gap-2 items-center text-pt-purple-50', + innerClassName + ) + + if (!chainId) { return <> } + if (isDataFetched && allowance < yieldBuffer) { + return ( + + Approve Yield Buffer + + + + + ) + } + return ( Deploy Vault diff --git a/apps/vault-factory/src/hooks/useSendApproveYieldBufferTransaction.ts b/apps/vault-factory/src/hooks/useSendApproveYieldBufferTransaction.ts new file mode 100644 index 00000000..c79e13df --- /dev/null +++ b/apps/vault-factory/src/hooks/useSendApproveYieldBufferTransaction.ts @@ -0,0 +1,97 @@ +import { erc20ABI, VAULT_FACTORY_ADDRESSES } from '@shared/utilities' +import { useEffect } from 'react' +import { Address, TransactionReceipt } from 'viem' +import { + useAccount, + useSimulateContract, + useWaitForTransactionReceipt, + useWriteContract +} from 'wagmi' +import { useVaultInfo } from './useVaultInfo' + +/** + * Prepares and submits an `approve` transaction for the initial yield buffer amount to the vault factory contract + * @param options optional callbacks + * @returns + */ +export const useSendApproveYieldBufferTransaction = (options?: { + onSend?: (txHash: `0x${string}`) => void + onSuccess?: (txReceipt: TransactionReceipt) => void + onError?: () => void +}): { + isWaiting: boolean + isConfirming: boolean + isSuccess: boolean + isError: boolean + txHash?: Address + txReceipt?: TransactionReceipt + sendApproveYieldBufferTransaction?: () => void +} => { + const { chain } = useAccount() + + const { chainId, tokenAddress, yieldBuffer } = useVaultInfo() + + const vaultFactoryAddress = !!chainId ? VAULT_FACTORY_ADDRESSES[chainId] : undefined + + const enabled = + !!chainId && chain?.id === chainId && !!tokenAddress && !!yieldBuffer && !!vaultFactoryAddress + + const { data } = useSimulateContract({ + chainId, + address: tokenAddress, + abi: erc20ABI, + functionName: 'approve', + args: [vaultFactoryAddress as Address, yieldBuffer as bigint], + query: { enabled } + }) + + const { + data: txHash, + isPending: isWaiting, + isError: isSendingError, + isSuccess: isSendingSuccess, + writeContract: _sendApproveYieldBufferTransaction + } = useWriteContract() + + const sendApproveYieldBufferTransaction = + !!data && !!_sendApproveYieldBufferTransaction + ? () => _sendApproveYieldBufferTransaction(data.request) + : undefined + + useEffect(() => { + if (!!txHash && isSendingSuccess) { + options?.onSend?.(txHash) + } + }, [isSendingSuccess]) + + const { + data: txReceipt, + isFetching: isConfirming, + isSuccess, + isError: isConfirmingError + } = useWaitForTransactionReceipt({ chainId, hash: txHash }) + + useEffect(() => { + if (!!txReceipt && isSuccess) { + options?.onSuccess?.(txReceipt) + } + }, [isSuccess]) + + const isError = isSendingError || isConfirmingError + + useEffect(() => { + if (isError) { + options?.onError?.() + } + }, [isError]) + + return { + isWaiting, + isConfirming, + isSuccess, + isError, + txHash, + txReceipt, + sendApproveYieldBufferTransaction + } +} diff --git a/apps/vault-factory/src/hooks/useVaultInfo.ts b/apps/vault-factory/src/hooks/useVaultInfo.ts index bc5b3353..6d3c5505 100644 --- a/apps/vault-factory/src/hooks/useVaultInfo.ts +++ b/apps/vault-factory/src/hooks/useVaultInfo.ts @@ -13,6 +13,7 @@ import { } from 'src/atoms' import { Address } from 'viem' import { NETWORK_CONFIG } from '@constants/config' +import { useYieldBuffer } from './useYieldBuffer' import { useYieldSourceTokenAddress } from './useYieldSourceTokenAddress' /** @@ -35,6 +36,8 @@ export const useVaultInfo = (): Partial => { yieldSourceAddress as Address ) + const { data: yieldBuffer } = useYieldBuffer(chainId as number) + const prizePool = !!chainId ? NETWORK_CONFIG[chainId].prizePool : undefined return { @@ -48,6 +51,7 @@ export const useVaultInfo = (): Partial => { claimer, feeRecipient, feePercentage, - owner + owner, + yieldBuffer } } diff --git a/apps/vault-factory/src/hooks/useYieldBuffer.ts b/apps/vault-factory/src/hooks/useYieldBuffer.ts new file mode 100644 index 00000000..832b2733 --- /dev/null +++ b/apps/vault-factory/src/hooks/useYieldBuffer.ts @@ -0,0 +1,31 @@ +import { NO_REFETCH } from '@generationsoftware/hyperstructure-react-hooks' +import { VAULT_FACTORY_ADDRESSES, vaultFactoryABI } from '@shared/utilities' +import { useQuery } from '@tanstack/react-query' +import { Address } from 'viem' +import { usePublicClient } from 'wagmi' + +/** + * Returns the vault factory's yield buffer amount + * @param chainId the vault factory's chain ID + * @returns + */ +export const useYieldBuffer = (chainId: number) => { + const publicClient = usePublicClient({ chainId }) + + const vaultFactoryAddress = !!chainId ? VAULT_FACTORY_ADDRESSES[chainId] : undefined + + return useQuery({ + queryKey: ['yieldBuffer', chainId], + queryFn: async () => { + if (!!publicClient) { + return publicClient.readContract({ + address: vaultFactoryAddress as Address, + abi: vaultFactoryABI, + functionName: 'YIELD_BUFFER' + }) + } + }, + enabled: !!chainId && !!publicClient && !!vaultFactoryAddress, + ...NO_REFETCH + }) +} diff --git a/packages/hyperstructure-react-hooks/src/transactions/useSendDeployVaultTransaction.ts b/packages/hyperstructure-react-hooks/src/transactions/useSendDeployVaultTransaction.ts index 17735af9..ed941303 100644 --- a/packages/hyperstructure-react-hooks/src/transactions/useSendDeployVaultTransaction.ts +++ b/packages/hyperstructure-react-hooks/src/transactions/useSendDeployVaultTransaction.ts @@ -8,6 +8,7 @@ import { useWaitForTransactionReceipt, useWriteContract } from 'wagmi' +import { useTokenAllowance } from '../tokens/useTokenAllowances' /** * Prepares and submits a `deployVault` transaction to the vault factory @@ -31,10 +32,11 @@ export const useSendDeployVaultTransaction = ( txReceipt?: TransactionReceipt sendDeployVaultTransaction?: () => void } => { - const { chain } = useAccount() + const { address: userAdddress, chain } = useAccount() const { chainId, + tokenAddress, name, symbol, yieldSourceAddress, @@ -42,7 +44,8 @@ export const useSendDeployVaultTransaction = ( claimer, feeRecipient, feePercentage, - owner + owner, + yieldBuffer } = vaultDeployInfo const vaultFactoryAddress = !!chainId ? VAULT_FACTORY_ADDRESSES[chainId] : undefined @@ -51,6 +54,13 @@ export const useSendDeployVaultTransaction = ( console.warn(`No vault factory address found for chain ID ${chainId}.`) } + const { data: allowance, isFetched: isFetchedAllowance } = useTokenAllowance( + chainId, + userAdddress as Address, + vaultFactoryAddress as Address, + tokenAddress as Address + ) + const enabled = !!vaultDeployInfo && !!chainId && @@ -62,8 +72,12 @@ export const useSendDeployVaultTransaction = ( !!feeRecipient && feePercentage !== undefined && !!owner && + !!yieldBuffer && !!vaultFactoryAddress && - chain?.id === chainId + chain?.id === chainId && + isFetchedAllowance && + !!allowance && + allowance >= yieldBuffer const { data } = useSimulateContract({ chainId, diff --git a/shared/types/types/vaults.ts b/shared/types/types/vaults.ts index 5eed0df0..bae943ed 100644 --- a/shared/types/types/vaults.ts +++ b/shared/types/types/vaults.ts @@ -64,4 +64,5 @@ export interface VaultDeployInfo { feeRecipient: `0x${string}` feePercentage: number owner: `0x${string}` + yieldBuffer: bigint } From 6b6229384cd750c064d8ae9fffc698a76144676d Mon Sep 17 00:00:00 2001 From: Ncookiez Date: Wed, 13 Mar 2024 12:34:52 -0400 Subject: [PATCH 055/161] added token balance warning --- .../src/components/DeployVaultView.tsx | 63 ++++++++++++++++++- .../components/buttons/DeployVaultButton.tsx | 9 +-- .../useSendApproveYieldBufferTransaction.ts | 10 ++- apps/vault-factory/src/hooks/useVaultInfo.ts | 3 + shared/types/types/vaults.ts | 1 + 5 files changed, 73 insertions(+), 13 deletions(-) diff --git a/apps/vault-factory/src/components/DeployVaultView.tsx b/apps/vault-factory/src/components/DeployVaultView.tsx index e861ff73..29d15371 100644 --- a/apps/vault-factory/src/components/DeployVaultView.tsx +++ b/apps/vault-factory/src/components/DeployVaultView.tsx @@ -1,5 +1,12 @@ +import { useTokenBalance } from '@generationsoftware/hyperstructure-react-hooks' +import { getNiceNetworkNameByChainId } from '@shared/utilities' import classNames from 'classnames' +import { useMemo } from 'react' +import { SupportedNetwork } from 'src/types' +import { Address, formatUnits } from 'viem' +import { useAccount } from 'wagmi' import { useVaultCreationSteps } from '@hooks/useVaultCreationSteps' +import { useVaultInfo } from '@hooks/useVaultInfo' import { DeployVaultButton } from './buttons/DeployVaultButton' import { PrevButton } from './buttons/PrevButton' import { VaultPreview } from './VaultPreview' @@ -14,8 +21,9 @@ export const DeployVaultView = (props: DeployVaultViewProps) => { const { nextStep } = useVaultCreationSteps() return ( -
+
+
@@ -23,3 +31,56 @@ export const DeployVaultView = (props: DeployVaultViewProps) => {
) } + +// TODO: add invalid yield source warning +// TODO: add precision per dollar check warning +const DeployVaultViewWarnings = (props: { className?: string }) => { + const { className } = props + + const { address: userAddress } = useAccount() + + const { chainId, tokenAddress, yieldBuffer } = useVaultInfo() + + const { data: token } = useTokenBalance( + chainId as SupportedNetwork, + userAddress as Address, + tokenAddress as Address, + { refetchOnWindowFocus: true } + ) + + const warning = useMemo((): + | { text: string; fix?: { text: string; onClick: () => void } } + | undefined => { + if (!!token && !!yieldBuffer && token.amount < yieldBuffer) { + return { + text: `You need at least ${formatUnits(yieldBuffer, token.decimals)} ${ + token.symbol + } on ${getNiceNetworkNameByChainId( + token.chainId + )} to deploy this prize vault. These tokens are donated to your new prize vault to prevent potential rounding errors.` + } + } + }, [token, yieldBuffer]) + + if (!warning) { + return <> + } + + return ( +
+ Warning + {warning.text} + {!!warning.fix && ( + + )} +
+ ) +} diff --git a/apps/vault-factory/src/components/buttons/DeployVaultButton.tsx b/apps/vault-factory/src/components/buttons/DeployVaultButton.tsx index 0f669591..b4c211c1 100644 --- a/apps/vault-factory/src/components/buttons/DeployVaultButton.tsx +++ b/apps/vault-factory/src/components/buttons/DeployVaultButton.tsx @@ -8,7 +8,6 @@ import { useAddRecentTransaction, useChainModal, useConnectModal } from '@rainbo import { createDeployVaultTxToast, TransactionButton } from '@shared/react-components' import { VaultDeployInfo } from '@shared/types' import { Tooltip } from '@shared/ui' -import { VAULT_FACTORY_ADDRESSES } from '@shared/utilities' import classNames from 'classnames' import { useSetAtom } from 'jotai' import { vaultAddressAtom } from 'src/atoms' @@ -31,7 +30,7 @@ export const DeployVaultButton = (props: DeployVaultButtonProps) => { const { address: userAddress } = useAccount() const vaultInfo = useVaultInfo() - const { chainId, tokenAddress, yieldBuffer } = vaultInfo + const { chainId, tokenAddress, vaultFactory, yieldBuffer } = vaultInfo const { data: token, @@ -44,8 +43,6 @@ export const DeployVaultButton = (props: DeployVaultButtonProps) => { { refetchOnWindowFocus: true } ) - const vaultFactoryAddress = !!chainId ? VAULT_FACTORY_ADDRESSES[chainId] : undefined - const { data: allowance, isFetched: isFetchedAllowance, @@ -53,7 +50,7 @@ export const DeployVaultButton = (props: DeployVaultButtonProps) => { } = useTokenAllowance( chainId as SupportedNetwork, userAddress as Address, - vaultFactoryAddress as Address, + vaultFactory as Address, token?.address as Address ) @@ -141,7 +138,7 @@ export const DeployVaultButton = (props: DeployVaultButtonProps) => { > Approve Yield Buffer diff --git a/apps/vault-factory/src/hooks/useSendApproveYieldBufferTransaction.ts b/apps/vault-factory/src/hooks/useSendApproveYieldBufferTransaction.ts index c79e13df..85bcad34 100644 --- a/apps/vault-factory/src/hooks/useSendApproveYieldBufferTransaction.ts +++ b/apps/vault-factory/src/hooks/useSendApproveYieldBufferTransaction.ts @@ -1,4 +1,4 @@ -import { erc20ABI, VAULT_FACTORY_ADDRESSES } from '@shared/utilities' +import { erc20ABI } from '@shared/utilities' import { useEffect } from 'react' import { Address, TransactionReceipt } from 'viem' import { @@ -29,19 +29,17 @@ export const useSendApproveYieldBufferTransaction = (options?: { } => { const { chain } = useAccount() - const { chainId, tokenAddress, yieldBuffer } = useVaultInfo() - - const vaultFactoryAddress = !!chainId ? VAULT_FACTORY_ADDRESSES[chainId] : undefined + const { chainId, tokenAddress, vaultFactory, yieldBuffer } = useVaultInfo() const enabled = - !!chainId && chain?.id === chainId && !!tokenAddress && !!yieldBuffer && !!vaultFactoryAddress + !!chainId && chain?.id === chainId && !!tokenAddress && !!vaultFactory && !!yieldBuffer const { data } = useSimulateContract({ chainId, address: tokenAddress, abi: erc20ABI, functionName: 'approve', - args: [vaultFactoryAddress as Address, yieldBuffer as bigint], + args: [vaultFactory as Address, yieldBuffer as bigint], query: { enabled } }) diff --git a/apps/vault-factory/src/hooks/useVaultInfo.ts b/apps/vault-factory/src/hooks/useVaultInfo.ts index 6d3c5505..0449eaef 100644 --- a/apps/vault-factory/src/hooks/useVaultInfo.ts +++ b/apps/vault-factory/src/hooks/useVaultInfo.ts @@ -1,4 +1,5 @@ import { VaultDeployInfo } from '@shared/types' +import { VAULT_FACTORY_ADDRESSES } from '@shared/utilities' import { useAtomValue } from 'jotai' import { vaultChainIdAtom, @@ -39,6 +40,7 @@ export const useVaultInfo = (): Partial => { const { data: yieldBuffer } = useYieldBuffer(chainId as number) const prizePool = !!chainId ? NETWORK_CONFIG[chainId].prizePool : undefined + const vaultFactory = !!chainId ? VAULT_FACTORY_ADDRESSES[chainId] : undefined return { chainId, @@ -48,6 +50,7 @@ export const useVaultInfo = (): Partial => { yieldSourceName, yieldSourceAddress, prizePool, + vaultFactory, claimer, feeRecipient, feePercentage, diff --git a/shared/types/types/vaults.ts b/shared/types/types/vaults.ts index bae943ed..0cc5b579 100644 --- a/shared/types/types/vaults.ts +++ b/shared/types/types/vaults.ts @@ -60,6 +60,7 @@ export interface VaultDeployInfo { yieldSourceName?: string yieldSourceAddress: `0x${string}` prizePool: `0x${string}` + vaultFactory?: `0x${string}` claimer: `0x${string}` feeRecipient: `0x${string}` feePercentage: number From 7b13507ddca9f827bb1964da8cb1b480c7386e9c Mon Sep 17 00:00:00 2001 From: Ncookiez Date: Wed, 13 Mar 2024 12:50:56 -0400 Subject: [PATCH 056/161] added existing vaults notice (WIP) --- .../src/components/forms/YieldVaultInput.tsx | 25 +++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/apps/vault-factory/src/components/forms/YieldVaultInput.tsx b/apps/vault-factory/src/components/forms/YieldVaultInput.tsx index c5cca94c..69e630ea 100644 --- a/apps/vault-factory/src/components/forms/YieldVaultInput.tsx +++ b/apps/vault-factory/src/components/forms/YieldVaultInput.tsx @@ -1,14 +1,17 @@ import { useToken } from '@generationsoftware/hyperstructure-react-hooks' +import { InformationCircleIcon } from '@heroicons/react/24/outline' import { TokenIcon } from '@shared/react-components' -import { Card, ExternalLink, Spinner } from '@shared/ui' +import { Card, ExternalLink, Spinner, Tooltip } from '@shared/ui' import { getBlockExplorerUrl, shorten } from '@shared/utilities' import classNames from 'classnames' import { useAtomValue } from 'jotai' +import { useMemo } from 'react' import { useFormContext, useWatch } from 'react-hook-form' import { vaultChainIdAtom } from 'src/atoms' import { SupportedNetwork, YieldSourceVaultTag } from 'src/types' import { Address } from 'viem' import { NETWORK_CONFIG, VAULT_TAGS } from '@constants/config' +import { useDeployedVaultYieldSourceAddresses } from '@hooks/useDeployedVaultYieldSourceAddresses' import { useYieldSourceTokenAddress } from '@hooks/useYieldSourceTokenAddress' interface YieldVaultInputFormValues { @@ -56,13 +59,20 @@ interface YieldVaultCardProps { yieldVault: (typeof NETWORK_CONFIG)[SupportedNetwork]['yieldSources'][number]['vaults'][number] } -// TODO: add existing vaults # notice const YieldVaultCard = (props: YieldVaultCardProps) => { const { chainId, yieldVault } = props const { data: tokenAddress } = useYieldSourceTokenAddress(chainId, yieldVault.address) const { data: token } = useToken(chainId, tokenAddress as Address) + const { data: deployedVaultYieldSourceAddresses } = useDeployedVaultYieldSourceAddresses(chainId) + + const existingVaultAddresses = useMemo(() => { + return Object.entries(deployedVaultYieldSourceAddresses) + .filter((entry) => entry[1] === yieldVault.address.toLowerCase()) + .map((entry) => entry[0] as Lowercase
) + }, [yieldVault, deployedVaultYieldSourceAddresses]) + const { vaultYieldSourceAddress } = useWatch() const isSelected = @@ -94,6 +104,17 @@ const YieldVaultCard = (props: YieldVaultCardProps) => { > {shorten(yieldVault.address)} + {!!existingVaultAddresses.length && ( +
+ + {existingVaultAddresses.length} existing prize vaults + + {/* TODO: add actual content */} + + + +
+ )} ) From e64e9576fa829de9caaed653b197fd8a8234d81e Mon Sep 17 00:00:00 2001 From: Ncookiez Date: Wed, 13 Mar 2024 15:22:41 -0400 Subject: [PATCH 057/161] sepolia -> op sepolia testnet --- apps/analytics/.env.example | 2 +- apps/analytics/src/constants/config.ts | 18 +++---- apps/app/.env.example | 2 +- apps/app/src/constants/config.ts | 17 ++++--- apps/app/src/vaultLists/default.ts | 2 +- apps/app/src/vaultLists/testnet.ts | 42 ++++++++-------- apps/rewards-builder/.env.example | 2 +- apps/rewards-builder/src/constants/config.ts | 10 ++-- apps/vault-factory/.env.example | 2 +- apps/vault-factory/src/constants/config.ts | 30 +++++------ apps/vaultlist-creator/.env.example | 2 +- .../vaultlist-creator/src/constants/config.ts | 8 +-- shared/react-components/constants.ts | 18 +++---- shared/utilities/constants.ts | 50 +++++++++---------- 14 files changed, 104 insertions(+), 101 deletions(-) diff --git a/apps/analytics/.env.example b/apps/analytics/.env.example index 3710c75b..c3766cc4 100644 --- a/apps/analytics/.env.example +++ b/apps/analytics/.env.example @@ -3,4 +3,4 @@ NEXT_PUBLIC_MAINNET_RPC_URL="YOUR_MAINNET_RPC_HERE" NEXT_PUBLIC_OPTIMISM_RPC_URL="YOUR_OPTIMISM_RPC_HERE" # Testnet RPC URLs -NEXT_PUBLIC_SEPOLIA_RPC_URL="YOUR_SEPOLIA_RPC_HERE" \ No newline at end of file +NEXT_PUBLIC_OPTIMISM_SEPOLIA_RPC_URL="YOUR_OPTIMISM_SEPOLIA_RPC_HERE" \ No newline at end of file diff --git a/apps/analytics/src/constants/config.ts b/apps/analytics/src/constants/config.ts index 66062ac6..c21cfa51 100644 --- a/apps/analytics/src/constants/config.ts +++ b/apps/analytics/src/constants/config.ts @@ -1,13 +1,13 @@ import { DEAD_ADDRESS, NETWORK, POOL_TOKEN_ADDRESSES } from '@shared/utilities' import { Address } from 'viem' -import { mainnet, optimism, sepolia } from 'viem/chains' +import { mainnet, optimism, optimismSepolia } from 'viem/chains' /** * Supported networks */ export const SUPPORTED_NETWORKS = { mainnets: [NETWORK.mainnet, NETWORK.optimism], - testnets: [NETWORK.sepolia] + testnets: [NETWORK.optimism_sepolia] } as const /** @@ -16,7 +16,7 @@ export const SUPPORTED_NETWORKS = { export const WAGMI_CHAINS = { [NETWORK.mainnet]: mainnet, [NETWORK.optimism]: optimism, - [NETWORK.sepolia]: sepolia + [NETWORK.optimism_sepolia]: optimismSepolia } as const /** @@ -25,21 +25,21 @@ export const WAGMI_CHAINS = { export const RPC_URLS = { [NETWORK.mainnet]: process.env.NEXT_PUBLIC_MAINNET_RPC_URL, [NETWORK.optimism]: process.env.NEXT_PUBLIC_OPTIMISM_RPC_URL, - [NETWORK.sepolia]: process.env.NEXT_PUBLIC_SEPOLIA_RPC_URL + [NETWORK.optimism_sepolia]: process.env.NEXT_PUBLIC_OPTIMISM_SEPOLIA_RPC_URL } as const /** * Queries' start blocks */ export const QUERY_START_BLOCK: { [chainId: number]: bigint } = { - [NETWORK.sepolia]: 5_397_600n + [NETWORK.optimism_sepolia]: 9_270_700n } /** * Draw results URL */ export const DRAW_RESULTS_URL: { [chainId: number]: string } = { - // [NETWORK.sepolia]: `https://raw.githubusercontent.com/GenerationSoftware/pt-v5-draw-results-testnet/main/prizes/${NETWORK.sepolia}` // TODO: uncomment once actions are setup + [NETWORK.optimism_sepolia]: `https://raw.githubusercontent.com/GenerationSoftware/pt-v5-draw-results-testnet/main/prizes/${NETWORK.sepolia}` } /** @@ -64,9 +64,9 @@ export const BURN_SETTINGS: { '0x3989cbc1fb0eb278601c018ed7627b07be9de4cb' ] }, - [NETWORK.sepolia]: { - burnTokenAddress: POOL_TOKEN_ADDRESSES[NETWORK.sepolia], - liquidationPairAddress: '0xda8652c939643e9175a1f52d0c211b8dc55ff613', + [NETWORK.optimism_sepolia]: { + burnTokenAddress: POOL_TOKEN_ADDRESSES[NETWORK.optimism_sepolia], + liquidationPairAddress: '0xd20777642ba9441d0b7a3f9f53b2ef0255ec7c31', burnAddresses: [DEAD_ADDRESS] } } diff --git a/apps/app/.env.example b/apps/app/.env.example index 20835ed9..e462fae8 100644 --- a/apps/app/.env.example +++ b/apps/app/.env.example @@ -3,7 +3,7 @@ NEXT_PUBLIC_MAINNET_RPC_URL="YOUR_MAINNET_RPC_HERE" NEXT_PUBLIC_OPTIMISM_RPC_URL="YOUR_OPTIMISM_RPC_HERE" # Testnet RPC URLs -NEXT_PUBLIC_SEPOLIA_RPC_URL="YOUR_SEPOLIA_RPC_HERE" +NEXT_PUBLIC_OPTIMISM_SEPOLIA_RPC_URL="YOUR_OPTIMISM_SEPOLIA_RPC_HERE" # Fathom Analytics NEXT_PUBLIC_FATHOM_SITE_ID="YOUR_FATHOM_ID_HERE" diff --git a/apps/app/src/constants/config.ts b/apps/app/src/constants/config.ts index 66014634..9c32f19f 100644 --- a/apps/app/src/constants/config.ts +++ b/apps/app/src/constants/config.ts @@ -20,14 +20,14 @@ import { import { NETWORK, POOL_TOKEN_ADDRESSES, USDC_TOKEN_ADDRESSES } from '@shared/utilities' import defaultVaultList from '@vaultLists/default' import { Address } from 'viem' -import { mainnet, optimism, sepolia } from 'viem/chains' +import { mainnet, optimism, optimismSepolia } from 'viem/chains' /** * Supported networks */ export const SUPPORTED_NETWORKS = { mainnets: [NETWORK.mainnet, NETWORK.optimism], - testnets: [NETWORK.sepolia] + testnets: [NETWORK.optimism_sepolia] } as const /** @@ -36,7 +36,7 @@ export const SUPPORTED_NETWORKS = { export const WAGMI_CHAINS = { [NETWORK.mainnet]: mainnet, [NETWORK.optimism]: optimism, - [NETWORK.sepolia]: sepolia + [NETWORK.optimism_sepolia]: optimismSepolia } as const /** @@ -67,7 +67,7 @@ export const WALLETS: { [wallet: string]: CreateWalletFn } = { export const RPC_URLS = { [NETWORK.mainnet]: process.env.NEXT_PUBLIC_MAINNET_RPC_URL, [NETWORK.optimism]: process.env.NEXT_PUBLIC_OPTIMISM_RPC_URL, - [NETWORK.sepolia]: process.env.NEXT_PUBLIC_SEPOLIA_RPC_URL + [NETWORK.optimism_sepolia]: process.env.NEXT_PUBLIC_OPTIMISM_SEPOLIA_RPC_URL } as const /** @@ -95,9 +95,12 @@ export const TWAB_REWARDS_SETTINGS: { ], fromBlock: 112_933_000n }, - [NETWORK.sepolia]: { - tokenAddresses: [USDC_TOKEN_ADDRESSES[NETWORK.sepolia], POOL_TOKEN_ADDRESSES[NETWORK.sepolia]], - fromBlock: 5_397_600n + [NETWORK.optimism_sepolia]: { + tokenAddresses: [ + USDC_TOKEN_ADDRESSES[NETWORK.optimism_sepolia], + POOL_TOKEN_ADDRESSES[NETWORK.optimism_sepolia] + ], + fromBlock: 9_270_700n } } diff --git a/apps/app/src/vaultLists/default.ts b/apps/app/src/vaultLists/default.ts index 46022ef5..daf7bb87 100644 --- a/apps/app/src/vaultLists/default.ts +++ b/apps/app/src/vaultLists/default.ts @@ -7,7 +7,7 @@ const defaultVaultList: VaultList = { name: 'Cabana Vault List', keywords: ['pooltogether', 'cabana', 'g9', 'optimism'], version: { major: 2, minor: 0, patch: 0 }, - timestamp: '2024-03-04T20:40:34Z', + timestamp: '2024-03-13T19:04:47Z', logoURI: `${LINKS.app}/pooltogether-token-logo.svg`, tokens: [ // { diff --git a/apps/app/src/vaultLists/testnet.ts b/apps/app/src/vaultLists/testnet.ts index 6da2f7d3..d09dfcca 100644 --- a/apps/app/src/vaultLists/testnet.ts +++ b/apps/app/src/vaultLists/testnet.ts @@ -3,68 +3,68 @@ import { NETWORK } from '@shared/utilities' export const testnetVaults: VaultList['tokens'] = [ { - chainId: NETWORK.sepolia, - address: '0x7DE52AcB8cEBc9713A804F5fdBd443e95234A31a', + chainId: NETWORK.optimism_sepolia, + address: '0x332b1EB2Cc4046954725EbDFB8143fB8354ea9a7', name: 'Prize DAI - LY', decimals: 18, symbol: 'PDAI-LY', logoURI: 'https://assets.coingecko.com/coins/images/9956/small/4943.png?1636636734', extensions: { underlyingAsset: { - address: '0x50088bF4dba58145c0B873643d285626f87837c3', + address: '0x34F166839C655F2DcD56638F2CE779fd9B5987a6', symbol: 'DAI', name: 'Dai Stablecoin' } } }, { - chainId: NETWORK.sepolia, - address: '0x17daE8454c24049E1Ec94a642014Fa3abf17ceDa', + chainId: NETWORK.optimism_sepolia, + address: '0x13E37b0Ca8b48fc2818C177c24635F90C1495C5c', name: 'Prize DAI - HY', decimals: 18, symbol: 'PDAI-HY', logoURI: 'https://assets.coingecko.com/coins/images/9956/small/4943.png?1636636734', extensions: { underlyingAsset: { - address: '0x50088bF4dba58145c0B873643d285626f87837c3', + address: '0x34F166839C655F2DcD56638F2CE779fd9B5987a6', symbol: 'DAI', name: 'Dai Stablecoin' } } }, { - chainId: NETWORK.sepolia, - address: '0xa1dD041B4A0f2d01c43F0aCE522f968cCA9F747C', + chainId: NETWORK.optimism_sepolia, + address: '0x602d77e900eCD48ac9b51151936Dcc5Efe2e7FaE', name: 'Prize USDC - LY', decimals: 6, symbol: 'PUSDC-LY', logoURI: 'https://etherscan.io/token/images/centre-usdc_28.png', extensions: { underlyingAsset: { - address: '0xd09eb8dE85D547cfBF09f972edCc6F871B192B70', + address: '0xE9CB1A8c3C1b5bcE7c6C0FB15F31A3A56209207F', symbol: 'USDC', name: 'USD Coin' } } }, { - chainId: NETWORK.sepolia, - address: '0x8d8d5e80DaEC5C917d1b1E7A331dAE2Fa0a789F5', + chainId: NETWORK.optimism_sepolia, + address: '0xA2B0321B671A83a98Ff1F5a680b700864f57c6e7', name: 'Prize USDC - HY', decimals: 6, symbol: 'PUSDC-HY', logoURI: 'https://etherscan.io/token/images/centre-usdc_28.png', extensions: { underlyingAsset: { - address: '0xd09eb8dE85D547cfBF09f972edCc6F871B192B70', + address: '0xE9CB1A8c3C1b5bcE7c6C0FB15F31A3A56209207F', symbol: 'USDC', name: 'USD Coin' } } }, { - chainId: NETWORK.sepolia, - address: '0xcA7042D10a36eB0F795476e529354D18ba204EDC', + chainId: NETWORK.optimism_sepolia, + address: '0xd96702995B2bBD78a9A39eF86f4fA5f9704fdC7D', name: 'Prize GUSD', decimals: 2, symbol: 'PGUSD', @@ -72,37 +72,37 @@ export const testnetVaults: VaultList['tokens'] = [ 'https://assets.coingecko.com/coins/images/5992/small/gemini-dollar-gusd.png?1536745278', extensions: { underlyingAsset: { - address: '0x2B8919310D8E2576E19e22794a6d3EC961cD812a', + address: '0xCe1fe3170d4ACEFBc3d06595EeF3A918F65000c2', symbol: 'GUSD', name: 'Gemini dollar' } } }, { - chainId: NETWORK.sepolia, - address: '0xad132763D325EFDa39E2ccBbc8E0eFA36fC6b4b8', + chainId: NETWORK.optimism_sepolia, + address: '0xE77Db9f8b68BC47A82D4F47E68FB57535dF0086e', name: 'Prize WBTC', decimals: 8, symbol: 'PWBTC', logoURI: 'https://etherscan.io/token/images/wbtc_28.png?v=1', extensions: { underlyingAsset: { - address: '0x0364994c88F97a18740Ec791A336b2d63407F8d5', + address: '0x42fd018A6ac84478f28b3f7e322271C83064d737', symbol: 'WBTC', name: 'Wrapped BTC' } } }, { - chainId: NETWORK.sepolia, - address: '0xc30151c7F49d2056E7C8197F189EFb5b54c0De0b', + chainId: NETWORK.optimism_sepolia, + address: '0x98CED5d595e8981756f063db8D3c44a6Be9A8F86', name: 'Prize WETH', decimals: 18, symbol: 'PWETH', logoURI: 'https://etherscan.io/token/images/weth_28.png', extensions: { underlyingAsset: { - address: '0x00a66C161e4C7A9dAEFd3dF8Cbbb08a3DE5b5F73', + address: '0x1bcd630e1303cef37F19743fbFE84b1b14e7750c', symbol: 'WETH', name: 'Wrapped Ether' } diff --git a/apps/rewards-builder/.env.example b/apps/rewards-builder/.env.example index c33bc6a0..977e89c9 100644 --- a/apps/rewards-builder/.env.example +++ b/apps/rewards-builder/.env.example @@ -3,4 +3,4 @@ NEXT_PUBLIC_MAINNET_RPC_URL="YOUR_MAINNET_RPC_HERE" NEXT_PUBLIC_OPTIMISM_RPC_URL="YOUR_OPTIMISM_RPC_HERE" # Testnet RPC URLs -NEXT_PUBLIC_SEPOLIA_RPC_URL="YOUR_SEPOLIA_RPC_HERE" +NEXT_PUBLIC_OPTIMISM_SEPOLIA_RPC_URL="YOUR_OPTIMISM_SEPOLIA_RPC_HERE" diff --git a/apps/rewards-builder/src/constants/config.ts b/apps/rewards-builder/src/constants/config.ts index abbbf878..a9c8469a 100644 --- a/apps/rewards-builder/src/constants/config.ts +++ b/apps/rewards-builder/src/constants/config.ts @@ -19,12 +19,12 @@ import { } from '@rainbow-me/rainbowkit/wallets' import { NETWORK } from '@shared/utilities' import { Address } from 'viem' -import { mainnet, optimism, sepolia } from 'viem/chains' +import { mainnet, optimism, optimismSepolia } from 'viem/chains' /** * Supported networks */ -export const SUPPORTED_NETWORKS = [NETWORK.optimism, NETWORK.sepolia] as const +export const SUPPORTED_NETWORKS = [NETWORK.optimism, NETWORK.optimism_sepolia] as const /** * Wagmi networks @@ -32,7 +32,7 @@ export const SUPPORTED_NETWORKS = [NETWORK.optimism, NETWORK.sepolia] as const export const WAGMI_CHAINS = { [NETWORK.mainnet]: mainnet, [NETWORK.optimism]: optimism, - [NETWORK.sepolia]: sepolia + [NETWORK.optimism_sepolia]: optimismSepolia } as const /** @@ -63,7 +63,7 @@ export const WALLETS: { [wallet: string]: CreateWalletFn } = { export const RPC_URLS = { [NETWORK.mainnet]: process.env.NEXT_PUBLIC_MAINNET_RPC_URL, [NETWORK.optimism]: process.env.NEXT_PUBLIC_OPTIMISM_RPC_URL, - [NETWORK.sepolia]: process.env.NEXT_PUBLIC_SEPOLIA_RPC_URL + [NETWORK.optimism_sepolia]: process.env.NEXT_PUBLIC_OPTIMISM_SEPOLIA_RPC_URL } as const /** @@ -74,5 +74,5 @@ export const PROMOTION_FILTERS: { } = { [NETWORK.mainnet]: {}, [NETWORK.optimism]: { fromBlock: 112_933_000n }, - [NETWORK.sepolia]: { fromBlock: 5_397_600n } + [NETWORK.optimism_sepolia]: { fromBlock: 9_270_700n } } diff --git a/apps/vault-factory/.env.example b/apps/vault-factory/.env.example index e07fb92c..977e89c9 100644 --- a/apps/vault-factory/.env.example +++ b/apps/vault-factory/.env.example @@ -3,4 +3,4 @@ NEXT_PUBLIC_MAINNET_RPC_URL="YOUR_MAINNET_RPC_HERE" NEXT_PUBLIC_OPTIMISM_RPC_URL="YOUR_OPTIMISM_RPC_HERE" # Testnet RPC URLs -NEXT_PUBLIC_SEPOLIA_RPC_URL="YOUR_OPTIMISM_SEPOLIA_RPC_HERE" +NEXT_PUBLIC_OPTIMISM_SEPOLIA_RPC_URL="YOUR_OPTIMISM_SEPOLIA_RPC_HERE" diff --git a/apps/vault-factory/src/constants/config.ts b/apps/vault-factory/src/constants/config.ts index f1a9ab84..56240e95 100644 --- a/apps/vault-factory/src/constants/config.ts +++ b/apps/vault-factory/src/constants/config.ts @@ -20,12 +20,12 @@ import { import { DEFAULT_CLAIMER_ADDRESSES, NETWORK } from '@shared/utilities' import { SupportedNetwork, YieldSourceVaultTag } from 'src/types' import { Address } from 'viem' -import { mainnet, optimism, sepolia } from 'viem/chains' +import { mainnet, optimism, optimismSepolia } from 'viem/chains' /** * Supported networks */ -export const SUPPORTED_NETWORKS = [NETWORK.sepolia] as const +export const SUPPORTED_NETWORKS = [NETWORK.optimism_sepolia] as const /** * Wagmi networks @@ -33,7 +33,7 @@ export const SUPPORTED_NETWORKS = [NETWORK.sepolia] as const export const WAGMI_CHAINS = { [NETWORK.mainnet]: mainnet, [NETWORK.optimism]: optimism, - [NETWORK.sepolia]: sepolia + [NETWORK.optimism_sepolia]: optimismSepolia } as const /** @@ -64,7 +64,7 @@ export const WALLETS: { [wallet: string]: CreateWalletFn } = { export const RPC_URLS = { [NETWORK.mainnet]: process.env.NEXT_PUBLIC_MAINNET_RPC_URL, [NETWORK.optimism]: process.env.NEXT_PUBLIC_OPTIMISM_RPC_URL, - [NETWORK.sepolia]: process.env.NEXT_PUBLIC_SEPOLIA_RPC_URL + [NETWORK.optimism_sepolia]: process.env.NEXT_PUBLIC_OPTIMISM_SEPOLIA_RPC_URL } as const /** @@ -101,10 +101,10 @@ export const NETWORK_CONFIG: Record< // }, // yieldSources: [] // }, - [NETWORK.sepolia]: { - description: 'Sepolia testnet for the Ethereum network.', - prizePool: '0x934F03f3132d3B818d7c07F25818ea3961eF18aD', - claimer: DEFAULT_CLAIMER_ADDRESSES[NETWORK.sepolia], + [NETWORK.optimism_sepolia]: { + description: 'Sepolia testnet for the Optimism network.', + prizePool: '0x5e1b40e4249644a7d7589d1197AD0F1628e79FB1', + claimer: DEFAULT_CLAIMER_ADDRESSES[NETWORK.optimism_sepolia], lp: { targetFirstSaleTimeFraction: 0.5, liquidationGasAmount: 300_000n, @@ -117,13 +117,13 @@ export const NETWORK_CONFIG: Record< href: 'https://aave.com/', description: 'Lending and borrowing protocol', vaults: [ - { address: '0x541D2a84928b7cFFe8455315c63b7F48f2f89cf8', tags: ['stablecoin'] }, - { address: '0x26542531d946E365f23e940aE0977Fd8efD9EFd7', tags: ['stablecoin'] }, - { address: '0x96A4624E73Ff5A305eD04c4895295Fe4E432E2b9', tags: ['stablecoin'] }, - { address: '0xe54D68f333826D334c08194Fa018519bB4Cec4F2', tags: ['stablecoin'] }, - { address: '0xC253890b75D75168202333F83302f9e76c5A1904', tags: ['stablecoin'] }, - { address: '0x7590DECC35A6C43E906721d44Ebc7D4B4662D583' }, - { address: '0xf86811C10b6f596684EE42cB6421a811e7B0527F' } + { address: '0x332b1EB2Cc4046954725EbDFB8143fB8354ea9a7', tags: ['stablecoin'] }, + { address: '0x13E37b0Ca8b48fc2818C177c24635F90C1495C5c', tags: ['stablecoin'] }, + { address: '0x602d77e900eCD48ac9b51151936Dcc5Efe2e7FaE', tags: ['stablecoin'] }, + { address: '0xA2B0321B671A83a98Ff1F5a680b700864f57c6e7', tags: ['stablecoin'] }, + { address: '0xd96702995B2bBD78a9A39eF86f4fA5f9704fdC7D', tags: ['stablecoin'] }, + { address: '0xE77Db9f8b68BC47A82D4F47E68FB57535dF0086e' }, + { address: '0x98CED5d595e8981756f063db8D3c44a6Be9A8F86' } ] } ] diff --git a/apps/vaultlist-creator/.env.example b/apps/vaultlist-creator/.env.example index 3710c75b..c3766cc4 100644 --- a/apps/vaultlist-creator/.env.example +++ b/apps/vaultlist-creator/.env.example @@ -3,4 +3,4 @@ NEXT_PUBLIC_MAINNET_RPC_URL="YOUR_MAINNET_RPC_HERE" NEXT_PUBLIC_OPTIMISM_RPC_URL="YOUR_OPTIMISM_RPC_HERE" # Testnet RPC URLs -NEXT_PUBLIC_SEPOLIA_RPC_URL="YOUR_SEPOLIA_RPC_HERE" \ No newline at end of file +NEXT_PUBLIC_OPTIMISM_SEPOLIA_RPC_URL="YOUR_OPTIMISM_SEPOLIA_RPC_HERE" \ No newline at end of file diff --git a/apps/vaultlist-creator/src/constants/config.ts b/apps/vaultlist-creator/src/constants/config.ts index 8cbb01ad..1219e9a4 100644 --- a/apps/vaultlist-creator/src/constants/config.ts +++ b/apps/vaultlist-creator/src/constants/config.ts @@ -1,12 +1,12 @@ import { NETWORK } from '@shared/utilities' -import { mainnet, optimism, sepolia } from 'viem/chains' +import { mainnet, optimism, optimismSepolia } from 'viem/chains' /** * Supported networks */ export const SUPPORTED_NETWORKS = { mainnets: [NETWORK.mainnet, NETWORK.optimism], - testnets: [NETWORK.sepolia] + testnets: [NETWORK.optimism_sepolia] } as const /** @@ -15,7 +15,7 @@ export const SUPPORTED_NETWORKS = { export const WAGMI_CHAINS = { [NETWORK.mainnet]: mainnet, [NETWORK.optimism]: optimism, - [NETWORK.sepolia]: sepolia + [NETWORK.optimism_sepolia]: optimismSepolia } as const /** @@ -24,5 +24,5 @@ export const WAGMI_CHAINS = { export const RPC_URLS = { [NETWORK.mainnet]: process.env.NEXT_PUBLIC_MAINNET_RPC_URL, [NETWORK.optimism]: process.env.NEXT_PUBLIC_OPTIMISM_RPC_URL, - [NETWORK.sepolia]: process.env.NEXT_PUBLIC_SEPOLIA_RPC_URL + [NETWORK.optimism_sepolia]: process.env.NEXT_PUBLIC_OPTIMISM_SEPOLIA_RPC_URL } as const diff --git a/shared/react-components/constants.ts b/shared/react-components/constants.ts index e178613f..56f1cbb7 100644 --- a/shared/react-components/constants.ts +++ b/shared/react-components/constants.ts @@ -30,14 +30,7 @@ export const TOKEN_LOGO_OVERRIDES: Record '0x2260fac5e5542a773aa44fbcfedf7c193bc2c599': tokenLogoUrls.wbtc, '0x5f98805a4e8be255a32880fdec7f6728c6568ba0': tokenLogoUrls.lusd }, - [NETWORK.sepolia]: { - '0x196eef5231bc8806ddfdbaaf7b5ac206bd316f45': tokenLogoUrls.pool, - '0xd09eb8de85d547cfbf09f972edcc6f871b192b70': tokenLogoUrls.usdc, - '0x50088bf4dba58145c0b873643d285626f87837c3': tokenLogoUrls.dai, - '0x2b8919310d8e2576e19e22794a6d3ec961cd812a': tokenLogoUrls.gusd, - '0x00a66c161e4c7a9daefd3df8cbbb08a3de5b5f73': tokenLogoUrls.weth, - '0x0364994c88f97a18740ec791a336b2d63407f8d5': tokenLogoUrls.wbtc - }, + [NETWORK.sepolia]: {}, [NETWORK.bsc]: {}, [NETWORK.bsc_testnet]: {}, [NETWORK.xdai]: {}, @@ -60,7 +53,14 @@ export const TOKEN_LOGO_OVERRIDES: Record '0x9485aca5bbbe1667ad97c7fe7c4531a624c8b1ed': tokenLogoUrls.ageur, '0x4200000000000000000000000000000000000042': tokenLogoUrls.op }, - [NETWORK.optimism_sepolia]: {}, + [NETWORK.optimism_sepolia]: { + '0x264954576da8496cc0d2216df81a7d7a38857329': tokenLogoUrls.pool, + '0xe9cb1a8c3c1b5bce7c6c0fb15f31a3a56209207f': tokenLogoUrls.usdc, + '0x34f166839c655f2dcd56638f2ce779fd9b5987a6': tokenLogoUrls.dai, + '0xce1fe3170d4acefbc3d06595eef3a918f65000c2': tokenLogoUrls.gusd, + '0x1bcd630e1303cef37f19743fbfe84b1b14e7750c': tokenLogoUrls.weth, + '0x42fd018a6ac84478f28b3f7e322271c83064d737': tokenLogoUrls.wbtc + }, [NETWORK.avalanche]: { '0x2f2a2543b76a4166549f7aab2e75bef0aefc5b0f': tokenLogoUrls.wbtc }, diff --git a/shared/utilities/constants.ts b/shared/utilities/constants.ts index 74484083..fc15ef70 100644 --- a/shared/utilities/constants.ts +++ b/shared/utilities/constants.ts @@ -31,7 +31,7 @@ export const POOL_TOKEN_ADDRESSES = { [NETWORK.mainnet]: '0x0cEC1A9154Ff802e7934Fc916Ed7Ca50bDE6844e', [NETWORK.polygon]: '0x25788a1a171ec66Da6502f9975a15B609fF54CF6', [NETWORK.optimism]: '0x395ae52bb17aef68c2888d941736a71dc6d4e125', - [NETWORK.sepolia]: '0x196EEF5231Bc8806ddFdBAaF7b5aC206Bd316f45' + [NETWORK.optimism_sepolia]: '0x264954576Da8496cc0d2216Df81a7D7A38857329' } as const /** @@ -44,7 +44,7 @@ export const USDC_TOKEN_ADDRESSES: { [chainId: number]: Lowercase
} = { [NETWORK.polygon]: '0x2791bca1f2de4661ed88a30c99a7a9449aa84174', [NETWORK.optimism]: '0x7f5c764cbc14f9669b88837ca1490cca17c31607', [NETWORK.arbitrum]: '0xff970a61a04b1ca14834a43f5de4533ebddb5cc8', - [NETWORK.sepolia]: '0xd09eb8de85d547cfbf09f972edcc6f871b192b70' + [NETWORK.optimism_sepolia]: '0xe9cb1a8c3c1b5bce7c6c0fb15f31a3a56209207f' } /** @@ -90,12 +90,12 @@ export const PRIZE_POOLS: { } }[] = [ { - chainId: NETWORK.sepolia, - address: '0x934F03f3132d3B818d7c07F25818ea3961eF18aD', + chainId: NETWORK.optimism_sepolia, + address: '0x5e1b40e4249644a7d7589d1197AD0F1628e79FB1', options: { - prizeTokenAddress: '0x00a66C161e4C7A9dAEFd3dF8Cbbb08a3DE5b5F73', - drawManagerAddress: '0xF21086aef81Eb3F5535B4bC8BA172bcFB5f1f3b4', - twabControllerAddress: '0x1F834baC8e84A4a4367025CE9e9BdCE85302dFdE', + prizeTokenAddress: '0x1bcd630e1303cef37F19743fbFE84b1b14e7750c', + drawManagerAddress: '0x07DBA6DB0b4c2B65B340C93e751f3694277A5a89', + twabControllerAddress: '0xd7a754FCFf13007C8E35aE5c40417432C1918616', drawPeriodInSeconds: 7_200, drawAuctionDurationInSeconds: 2_400, tierShares: 100, @@ -183,11 +183,7 @@ export const STABLECOINS: Record = { '0x6b175474e89094c44da98b954eedeac495271d0f': 'usd', // DAI '0x056fd409e1d7a124bd7017459dfea2f387b6d5cd': 'usd' // GUSD }, - [NETWORK.sepolia]: { - '0xd09eb8de85d547cfbf09f972edcc6f871b192b70': 'usd', // USDC - '0x50088bf4dba58145c0b873643d285626f87837c3': 'usd', // DAI - '0x2b8919310d8e2576e19e22794a6d3ec961cd812a': 'usd' // GUSD - }, + [NETWORK.sepolia]: {}, [NETWORK.bsc]: {}, [NETWORK.bsc_testnet]: {}, [NETWORK.xdai]: {}, @@ -201,7 +197,11 @@ export const STABLECOINS: Record = { '0xda10009cbd5d07dd0cecc66161fc93d7c9000da1': 'usd', // DAI '0xc40f949f8a4e094d1b49a23ea9241d289b7b2819': 'usd' // LUSD }, - [NETWORK.optimism_sepolia]: {}, + [NETWORK.optimism_sepolia]: { + '0xe9cb1a8c3c1b5bce7c6c0fb15f31a3a56209207f': 'usd', // USDC + '0x34f166839c655f2dcd56638f2ce779fd9b5987a6': 'usd', // DAI + '0xce1fe3170d4acefbc3d06595eef3a918f65000c2': 'usd' // GUSD + }, [NETWORK.avalanche]: { '0xa7d7079b0fead91f3e65f86e8915cb59c1a4c664': 'usd' // USDC.e }, @@ -243,35 +243,35 @@ export const WRAPPED_NATIVE_ASSETS: Record = { * TWAB rewards addresses */ export const TWAB_REWARDS_ADDRESSES: { [chainId: number]: Address } = { - [NETWORK.sepolia]: '0x3668d73fe09244b6F66B601285076715A09eD07F' + [NETWORK.optimism_sepolia]: '0xB1231d0bdf134b09D92f6d33C651280D3B96F6e3' } /** * Vault factory addresses */ export const VAULT_FACTORY_ADDRESSES: { [chainId: number]: Address } = { - [NETWORK.sepolia]: '0x3874f4fD4b089e1a013b18870b2B1b83eCe57349' + [NETWORK.optimism_sepolia]: '0x2031fc356feec120eFba3BAfA7997d1dfB377Ed4' } /** * Liquidation pair factory addresses */ export const LIQUIDATION_PAIR_FACTORY_ADDRESSES: { [chainId: number]: Address } = { - [NETWORK.sepolia]: '0x4FeaaefBb5767d577547d8B1eB61Bfec172A7525' + [NETWORK.optimism_sepolia]: '0x5114de3c33458815BaD56B28D32261695490DBf3' } /** * Default claimer addresses */ export const DEFAULT_CLAIMER_ADDRESSES: { [chainId: number]: Address } = { - [NETWORK.sepolia]: '0xd6d4668AE64FF24fFF82b0DF7d12e7A5Ec936555' + [NETWORK.optimism_sepolia]: '0x239d1befb50fcFF353804C6df1579ED0Bbb9dA07' } /** * Liquidation router addresses */ export const LIQUIDATION_ROUTER_ADDRESSES: { [chainId: number]: Address } = { - [NETWORK.sepolia]: '0xB0A9467863837D09e2C7A7a78F6A68F8857999Af' + [NETWORK.optimism_sepolia]: '0xDfCF0c47C5697CDDFADEB7b5CbD29BC6b20c8DD1' } /** @@ -326,39 +326,39 @@ export const TOKEN_PRICE_REDIRECTS: { address: '0x0000000000000000000000000000000000001010' } }, - [NETWORK.sepolia]: { + [NETWORK.optimism_sepolia]: { /* ETH */ [DOLPHIN_ADDRESS]: { chainId: NETWORK.mainnet, address: DOLPHIN_ADDRESS }, /* DAI */ - '0x50088bf4dba58145c0b873643d285626f87837c3': { + '0x34f166839c655f2dcd56638f2ce779fd9b5987a6': { chainId: NETWORK.mainnet, address: '0x6b175474e89094c44da98b954eedeac495271d0f' }, /* USDC */ - [USDC_TOKEN_ADDRESSES[NETWORK.sepolia]]: { + [USDC_TOKEN_ADDRESSES[NETWORK.optimism_sepolia]]: { chainId: NETWORK.mainnet, address: USDC_TOKEN_ADDRESSES[NETWORK.mainnet] }, /* GUSD */ - '0x2b8919310d8e2576e19e22794a6d3ec961cd812a': { + '0xce1fe3170d4acefbc3d06595eef3a918f65000c2': { chainId: NETWORK.mainnet, address: '0x056fd409e1d7a124bd7017459dfea2f387b6d5cd' }, /* WBTC */ - '0x0364994c88f97a18740ec791a336b2d63407f8d5': { + '0x42fd018a6ac84478f28b3f7e322271c83064d737': { chainId: NETWORK.mainnet, address: '0x2260fac5e5542a773aa44fbcfedf7c193bc2c599' }, /* WETH */ - '0x00a66c161e4c7a9daefd3df8cbbb08a3de5b5f73': { + '0x1bcd630e1303cef37f19743fbfe84b1b14e7750c': { chainId: NETWORK.mainnet, address: WRAPPED_NATIVE_ASSETS[NETWORK.mainnet] as Address }, /* POOL */ - [POOL_TOKEN_ADDRESSES[NETWORK.sepolia]]: { + [POOL_TOKEN_ADDRESSES[NETWORK.optimism_sepolia]]: { chainId: NETWORK.mainnet, address: POOL_TOKEN_ADDRESSES[NETWORK.mainnet] } From 15e8f1f2a088207e152d56733f52e077bc55097a Mon Sep 17 00:00:00 2001 From: Ncookiez Date: Wed, 13 Mar 2024 16:00:15 -0400 Subject: [PATCH 058/161] fixed bad lp tokenIn assumptions --- .../Liquidations/LiquidationTxsDropdown.tsx | 26 ++++--- .../Liquidations/LiquidationsTable.tsx | 10 +-- .../Liquidations/LiquidationsTableRow.tsx | 71 +++++++++---------- .../hooks/useLiquidationPairTokenInData.tsx | 18 +++++ .../hooks/useLiquidationPairTokenInPrice.tsx | 28 ++++++++ shared/utilities/constants.ts | 4 +- 6 files changed, 95 insertions(+), 62 deletions(-) create mode 100644 apps/analytics/src/hooks/useLiquidationPairTokenInData.tsx create mode 100644 apps/analytics/src/hooks/useLiquidationPairTokenInPrice.tsx diff --git a/apps/analytics/src/components/Liquidations/LiquidationTxsDropdown.tsx b/apps/analytics/src/components/Liquidations/LiquidationTxsDropdown.tsx index ed59f0e7..7eefc2d2 100644 --- a/apps/analytics/src/components/Liquidations/LiquidationTxsDropdown.tsx +++ b/apps/analytics/src/components/Liquidations/LiquidationTxsDropdown.tsx @@ -4,7 +4,6 @@ import { useTokenPrices, useTxReceipt } from '@generationsoftware/hyperstructure-react-hooks' -import { TokenWithPrice } from '@shared/types' import { Button, ExternalLink, Spinner } from '@shared/ui' import { DOLPHIN_ADDRESS, @@ -16,18 +15,18 @@ import classNames from 'classnames' import { ReactNode, useState } from 'react' import { getTxGasSpent } from 'src/utils' import { Address, formatEther, formatUnits } from 'viem' +import { useLiquidationPairTokenInPrice } from '@hooks/useLiquidationPairTokenInPrice' import { useLiquidationPairTokenOutPrice } from '@hooks/useLiquidationPairTokenOutPrice' interface LiquidationTxsDropdownProps { prizePool: PrizePool lpAddress: Address liquidations: NonNullable['data']> - prizeToken: TokenWithPrice className?: string } export const LiquidationTxsDropdown = (props: LiquidationTxsDropdownProps) => { - const { prizePool, lpAddress, liquidations, prizeToken, className } = props + const { prizePool, lpAddress, liquidations, className } = props const [isOpen, setIsOpen] = useState(false) @@ -49,7 +48,6 @@ export const LiquidationTxsDropdown = (props: LiquidationTxsDropdownProps) => { chainId={prizePool.chainId} lpAddress={lpAddress} liquidation={liquidation} - prizeToken={prizeToken} key={`liqTx-${liquidation.transactionHash}-${liquidation.logIndex}`} /> ))} @@ -61,28 +59,28 @@ interface LiquidationTxProps { chainId: number lpAddress: Address liquidation: NonNullable['data']>[0] - prizeToken: TokenWithPrice className?: string } const LiquidationTx = (props: LiquidationTxProps) => { - const { chainId, lpAddress, liquidation, prizeToken, className } = props + const { chainId, lpAddress, liquidation, className } = props - const { data: lpToken } = useLiquidationPairTokenOutPrice(chainId, lpAddress) + const { data: tokenIn } = useLiquidationPairTokenInPrice(chainId, lpAddress) + const { data: tokenOut } = useLiquidationPairTokenOutPrice(chainId, lpAddress) const { data: txReceipt } = useTxReceipt(chainId, liquidation.transactionHash) const { data: tokenPrices } = useTokenPrices(chainId, [DOLPHIN_ADDRESS]) - if (!lpToken || !txReceipt || !tokenPrices) { + if (!tokenIn || !tokenOut || !txReceipt || !tokenPrices) { return } - const tokenInAmount = parseFloat(formatUnits(liquidation.args.amountIn, prizeToken.decimals)) - const tokenOutAmount = parseFloat(formatUnits(liquidation.args.amountOut, lpToken.decimals)) + const tokenInAmount = parseFloat(formatUnits(liquidation.args.amountIn, tokenIn.decimals)) + const tokenOutAmount = parseFloat(formatUnits(liquidation.args.amountOut, tokenOut.decimals)) - const tokenInValue = !!prizeToken.price ? tokenInAmount * prizeToken.price : undefined - const tokenOutValue = !!lpToken.price ? tokenOutAmount * lpToken.price : undefined + const tokenInValue = !!tokenIn.price ? tokenInAmount * tokenIn.price : undefined + const tokenOutValue = !!tokenOut.price ? tokenOutAmount * tokenOut.price : undefined const gasValue = parseFloat(formatEther(getTxGasSpent(txReceipt))) * tokenPrices[DOLPHIN_ADDRESS] const profit = !!tokenInValue && !!tokenOutValue @@ -115,11 +113,11 @@ const LiquidationTx = (props: LiquidationTxProps) => { {' '} liquidated{' '} - {formattedTokenOutAmount} {lpToken.symbol} + {formattedTokenOutAmount} {tokenOut.symbol} {' '} for{' '} - {formattedTokenInAmount} {prizeToken.symbol} + {formattedTokenInAmount} {tokenIn.symbol} {' '} {profit !== undefined && ( ({formatNumberForDisplay(profit, { maximumFractionDigits: 1 })}% profit) diff --git a/apps/analytics/src/components/Liquidations/LiquidationsTable.tsx b/apps/analytics/src/components/Liquidations/LiquidationsTable.tsx index 4490997b..561f19b0 100644 --- a/apps/analytics/src/components/Liquidations/LiquidationsTable.tsx +++ b/apps/analytics/src/components/Liquidations/LiquidationsTable.tsx @@ -1,8 +1,5 @@ import { PrizePool } from '@generationsoftware/hyperstructure-client-js' -import { - useLiquidationEvents, - usePrizeTokenPrice -} from '@generationsoftware/hyperstructure-react-hooks' +import { useLiquidationEvents } from '@generationsoftware/hyperstructure-react-hooks' import { Spinner } from '@shared/ui' import { MAX_UINT_256, SECONDS_PER_HOUR } from '@shared/utilities' import classNames from 'classnames' @@ -39,8 +36,6 @@ export const LiquidationsTable = (props: LiquidationsTableProps) => { { fromBlock: !!prizePool ? QUERY_START_BLOCK[prizePool.chainId] : undefined } ) - const { data: prizeToken } = usePrizeTokenPrice(prizePool) - const validLiquidationEvents = useMemo(() => { return ( liquidationEvents?.filter( @@ -59,7 +54,7 @@ export const LiquidationsTable = (props: LiquidationsTableProps) => { return [...addresses] }, [validLiquidationEvents]) - if (!isFetchedLiquidationEvents || !prizeToken) { + if (!isFetchedLiquidationEvents) { return } @@ -92,7 +87,6 @@ export const LiquidationsTable = (props: LiquidationsTableProps) => { prizePool={prizePool} lpAddress={lpAddress} liquidations={validLiquidationEvents} - prizeToken={prizeToken} className='py-3 px-4' gridClassName={classNames('flex flex-wrap', gridClassName)} /> diff --git a/apps/analytics/src/components/Liquidations/LiquidationsTableRow.tsx b/apps/analytics/src/components/Liquidations/LiquidationsTableRow.tsx index 52f45c4d..f805a8b3 100644 --- a/apps/analytics/src/components/Liquidations/LiquidationsTableRow.tsx +++ b/apps/analytics/src/components/Liquidations/LiquidationsTableRow.tsx @@ -5,7 +5,6 @@ import { useTxReceipts } from '@generationsoftware/hyperstructure-react-hooks' import { ArrowRightIcon } from '@heroicons/react/24/outline' -import { Token, TokenWithPrice } from '@shared/types' import { ExternalLink, Spinner } from '@shared/ui' import { DOLPHIN_ADDRESS, @@ -18,6 +17,8 @@ import { ReactNode, useMemo } from 'react' import { getTxGasSpent } from 'src/utils' import { Address, formatEther, formatUnits } from 'viem' import { useLiquidationPairLiquidatableBalance } from '@hooks/useLiquidationPairLiquidatableBalance' +import { useLiquidationPairTokenInData } from '@hooks/useLiquidationPairTokenInData' +import { useLiquidationPairTokenInPrice } from '@hooks/useLiquidationPairTokenInPrice' import { useLiquidationPairTokenOutData } from '@hooks/useLiquidationPairTokenOutData' import { useLiquidationPairTokenOutPrice } from '@hooks/useLiquidationPairTokenOutPrice' import { liquidationHeaders } from './LiquidationsTable' @@ -27,13 +28,12 @@ interface LiquidationsTableRowProps { prizePool: PrizePool lpAddress: Address liquidations: NonNullable['data']> - prizeToken: TokenWithPrice className?: string gridClassName?: string } export const LiquidationsTableRow = (props: LiquidationsTableRowProps) => { - const { prizePool, lpAddress, liquidations, prizeToken, className, gridClassName } = props + const { prizePool, lpAddress, liquidations, className, gridClassName } = props const lpLiquidations = liquidations.filter( (liq) => liq.args.liquidationPair.toLowerCase() === lpAddress.toLowerCase() @@ -50,7 +50,6 @@ export const LiquidationsTableRow = (props: LiquidationsTableRowProps) => { { chainId={prizePool.chainId} lpAddress={lpAddress} liquidations={lpLiquidations} - prizeToken={prizeToken} className='w-1/2 md:w-auto' /> { chainId={prizePool.chainId} lpAddress={lpAddress} liquidations={lpLiquidations} - prizeToken={prizeToken} className='w-1/2 md:w-auto' />
@@ -83,7 +80,6 @@ export const LiquidationsTableRow = (props: LiquidationsTableRowProps) => { prizePool={prizePool} lpAddress={lpAddress} liquidations={lpLiquidations} - prizeToken={prizeToken} />
) @@ -92,16 +88,16 @@ export const LiquidationsTableRow = (props: LiquidationsTableRowProps) => { interface LiquidationPairLinkProps { chainId: number lpAddress: Address - prizeToken: Token className?: string } const LiquidationPairLink = (props: LiquidationPairLinkProps) => { - const { chainId, lpAddress, prizeToken, className } = props + const { chainId, lpAddress, className } = props - const { data: lpToken } = useLiquidationPairTokenOutData(chainId, lpAddress) + const { data: tokenIn } = useLiquidationPairTokenInData(chainId, lpAddress) + const { data: tokenOut } = useLiquidationPairTokenOutData(chainId, lpAddress) - if (!lpToken) { + if (!tokenIn || !tokenOut) { return } @@ -111,7 +107,7 @@ const LiquidationPairLink = (props: LiquidationPairLinkProps) => { className={classNames('text-pt-purple-200 h-min text-xl font-semibold', className)} iconClassName='text-blue-300 hover:text-blue-200 transition' > - {lpToken.symbol ?? '?'}/{prizeToken.symbol} + {tokenOut.symbol ?? '?'}/{tokenIn.symbol} ) } @@ -126,9 +122,9 @@ interface YieldAuctionedProps { const YieldAuctioned = (props: YieldAuctionedProps) => { const { chainId, lpAddress, liquidations, className } = props - const { data: lpToken } = useLiquidationPairTokenOutData(chainId, lpAddress) + const { data: tokenOut } = useLiquidationPairTokenOutData(chainId, lpAddress) - if (!lpToken) { + if (!tokenOut) { return } @@ -139,9 +135,9 @@ const YieldAuctioned = (props: YieldAuctionedProps) => { {liquidationHeaders.auctioned} - {formatBigIntForDisplay(totalYieldAuctioned, lpToken.decimals, { hideZeroes: true })} + {formatBigIntForDisplay(totalYieldAuctioned, tokenOut.decimals, { hideZeroes: true })} {' '} - {lpToken.symbol} + {tokenOut.symbol}
) @@ -151,50 +147,50 @@ interface AvgLiquidationPriceProps { chainId: number lpAddress: Address liquidations: LiquidationsTableRowProps['liquidations'] - prizeToken: Token className?: string } const AvgLiquidationPrice = (props: AvgLiquidationPriceProps) => { - const { chainId, lpAddress, liquidations, prizeToken, className } = props + const { chainId, lpAddress, liquidations, className } = props - const { data: lpToken } = useLiquidationPairTokenOutData(chainId, lpAddress) + const { data: tokenIn } = useLiquidationPairTokenInData(chainId, lpAddress) + const { data: tokenOut } = useLiquidationPairTokenOutData(chainId, lpAddress) const avgPrice = useMemo(() => { - if (!!lpToken) { + if (!!tokenIn && !!tokenOut) { if (!liquidations.length) return 0 const avgAmountIn = parseFloat( formatUnits( liquidations.reduce((a, b) => a + b.args.amountIn, 0n), - prizeToken.decimals + tokenIn.decimals ) ) / liquidations.length const avgAmountOut = parseFloat( formatUnits( liquidations.reduce((a, b) => a + b.args.amountOut, 0n), - lpToken.decimals + tokenOut.decimals ) ) / liquidations.length return avgAmountIn / avgAmountOut } - }, [liquidations, lpToken]) + }, [liquidations, tokenIn, tokenOut]) return (
{liquidationHeaders.price} - {!!lpToken && !!avgPrice ? ( + {!!tokenIn && !!tokenOut && !!avgPrice ? ( <> - 1 {lpToken.symbol} ={' '} + 1 {tokenOut.symbol} ={' '} {formatNumberForDisplay( avgPrice, avgPrice > 100 ? { hideZeroes: true } : { maximumFractionDigits: 2 } )} {' '} - {prizeToken.symbol} + {tokenIn.symbol} ) : ( @@ -215,9 +211,9 @@ const CurrentAvailableYield = (props: CurrentAvailableYieldProps) => { const { data: liquidatableBalance } = useLiquidationPairLiquidatableBalance(chainId, lpAddress) - const { data: lpToken } = useLiquidationPairTokenOutData(chainId, lpAddress) + const { data: tokenOut } = useLiquidationPairTokenOutData(chainId, lpAddress) - if (liquidatableBalance === undefined || !lpToken) { + if (liquidatableBalance === undefined || !tokenOut) { return } @@ -226,9 +222,9 @@ const CurrentAvailableYield = (props: CurrentAvailableYieldProps) => { {liquidationHeaders.available} - {formatBigIntForDisplay(liquidatableBalance, lpToken.decimals, { hideZeroes: true })} + {formatBigIntForDisplay(liquidatableBalance, tokenOut.decimals, { hideZeroes: true })} {' '} - {lpToken.symbol} + {tokenOut.symbol}
) @@ -244,14 +240,14 @@ interface AvgEfficiencyProps { chainId: number lpAddress: Address liquidations: LiquidationsTableRowProps['liquidations'] - prizeToken: TokenWithPrice className?: string } const AvgEfficiency = (props: AvgEfficiencyProps) => { - const { chainId, lpAddress, liquidations, prizeToken, className } = props + const { chainId, lpAddress, liquidations, className } = props - const { data: lpToken } = useLiquidationPairTokenOutPrice(chainId, lpAddress) + const { data: tokenIn } = useLiquidationPairTokenInPrice(chainId, lpAddress) + const { data: tokenOut } = useLiquidationPairTokenOutPrice(chainId, lpAddress) const uniqueTxHashes = new Set(liquidations.map((liq) => liq.transactionHash)) const { data: liquidationTxReceipts } = useTxReceipts(chainId, [...uniqueTxHashes]) @@ -260,14 +256,13 @@ const AvgEfficiency = (props: AvgEfficiencyProps) => { const nativeTokenPrice = nativeTokenPrices?.[DOLPHIN_ADDRESS] const efficiency = useMemo(() => { - if (!!prizeToken?.price && !!lpToken?.price && !!liquidationTxReceipts && !!nativeTokenPrice) { + if (!!tokenIn?.price && !!tokenOut?.price && !!liquidationTxReceipts && !!nativeTokenPrice) { const totalAmountIn = liquidations.reduce((a, b) => a + b.args.amountIn, 0n) const totalAmountOut = liquidations.reduce((a, b) => a + b.args.amountOut, 0n) - const totalValueIn = - parseFloat(formatUnits(totalAmountIn, prizeToken.decimals)) * prizeToken.price + const totalValueIn = parseFloat(formatUnits(totalAmountIn, tokenIn.decimals)) * tokenIn.price const totalValueOut = - parseFloat(formatUnits(totalAmountOut, lpToken.decimals)) * lpToken.price + parseFloat(formatUnits(totalAmountOut, tokenOut.decimals)) * tokenOut.price const totalGasSpent = liquidationTxReceipts.reduce((a, b) => a + getTxGasSpent(b), 0n) const totalGasValueSpent = parseFloat(formatEther(totalGasSpent)) * nativeTokenPrice @@ -278,7 +273,7 @@ const AvgEfficiency = (props: AvgEfficiencyProps) => { return { prizes, gas, bots } } - }, [liquidations, prizeToken, lpToken, liquidationTxReceipts, nativeTokenPrice]) + }, [liquidations, tokenIn, tokenOut, liquidationTxReceipts, nativeTokenPrice]) if (!efficiency) { return diff --git a/apps/analytics/src/hooks/useLiquidationPairTokenInData.tsx b/apps/analytics/src/hooks/useLiquidationPairTokenInData.tsx new file mode 100644 index 00000000..62248daa --- /dev/null +++ b/apps/analytics/src/hooks/useLiquidationPairTokenInData.tsx @@ -0,0 +1,18 @@ +import { useToken } from '@generationsoftware/hyperstructure-react-hooks' +import { TokenWithSupply } from '@shared/types' +import { Address } from 'viem' +import { useLiquidationPairTokenInAddress } from './useLiquidationPairTokenInAddresses' + +export const useLiquidationPairTokenInData = ( + chainId: number, + lpAddress: Address +): { data?: TokenWithSupply; isFetched: boolean } => { + const { data: tokenInAddress, isFetched: isFetchedTokenInAddress } = + useLiquidationPairTokenInAddress(chainId, lpAddress) + + const { data: token, isFetched: isFetchedToken } = useToken(chainId, tokenInAddress as Address) + + const isFetched = isFetchedTokenInAddress && isFetchedToken + + return { data: token, isFetched } +} diff --git a/apps/analytics/src/hooks/useLiquidationPairTokenInPrice.tsx b/apps/analytics/src/hooks/useLiquidationPairTokenInPrice.tsx new file mode 100644 index 00000000..a360e5b2 --- /dev/null +++ b/apps/analytics/src/hooks/useLiquidationPairTokenInPrice.tsx @@ -0,0 +1,28 @@ +import { useToken, useTokenPrices } from '@generationsoftware/hyperstructure-react-hooks' +import { TokenWithPrice } from '@shared/types' +import { Address } from 'viem' +import { useLiquidationPairTokenInAddress } from './useLiquidationPairTokenInAddresses' + +export const useLiquidationPairTokenInPrice = ( + chainId: number, + lpAddress: Address +): { data?: TokenWithPrice; isFetched: boolean } => { + const { data: tokenInAddress, isFetched: isFetchedTokenInAddress } = + useLiquidationPairTokenInAddress(chainId, lpAddress) + + const { data: token, isFetched: isFetchedToken } = useToken(chainId, tokenInAddress as Address) + + const { data: tokenPrices, isFetched: isFetchedTokenPrices } = useTokenPrices( + chainId, + !!tokenInAddress ? [tokenInAddress] : [] + ) + + const data = + !!token && !!tokenPrices && !!tokenInAddress + ? { ...token, price: tokenPrices[tokenInAddress.toLowerCase() as Address] } + : undefined + + const isFetched = isFetchedTokenInAddress && isFetchedToken && isFetchedTokenPrices + + return { data, isFetched } +} diff --git a/shared/utilities/constants.ts b/shared/utilities/constants.ts index fc15ef70..0ab49d3d 100644 --- a/shared/utilities/constants.ts +++ b/shared/utilities/constants.ts @@ -358,9 +358,9 @@ export const TOKEN_PRICE_REDIRECTS: { address: WRAPPED_NATIVE_ASSETS[NETWORK.mainnet] as Address }, /* POOL */ - [POOL_TOKEN_ADDRESSES[NETWORK.optimism_sepolia]]: { + [POOL_TOKEN_ADDRESSES[NETWORK.optimism_sepolia].toLowerCase()]: { chainId: NETWORK.mainnet, - address: POOL_TOKEN_ADDRESSES[NETWORK.mainnet] + address: POOL_TOKEN_ADDRESSES[NETWORK.mainnet].toLowerCase() as Address } } } From f9b3b8efe2bdf39a109afb6022c3bd101e5714f2 Mon Sep 17 00:00:00 2001 From: Ncookiez Date: Wed, 13 Mar 2024 17:06:26 -0400 Subject: [PATCH 059/161] added op sepolia subgraph url --- shared/utilities/constants.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/shared/utilities/constants.ts b/shared/utilities/constants.ts index 0ab49d3d..70efe07c 100644 --- a/shared/utilities/constants.ts +++ b/shared/utilities/constants.ts @@ -108,7 +108,8 @@ export const PRIZE_POOLS: { * Subgraph API URLs */ export const SUBGRAPH_API_URLS = { - // TODO: add subgraph apis when available + [NETWORK.optimism_sepolia]: + 'https://api.studio.thegraph.com/query/63100/pt-v5-op-sepolia/version/latest' } as const /** From 7c677c0355d23b67edad631853ade2ca6563a869 Mon Sep 17 00:00:00 2001 From: Ncookiez Date: Wed, 13 Mar 2024 17:14:12 -0400 Subject: [PATCH 060/161] fixed draw results url --- apps/analytics/src/constants/config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/analytics/src/constants/config.ts b/apps/analytics/src/constants/config.ts index c21cfa51..508cd2cb 100644 --- a/apps/analytics/src/constants/config.ts +++ b/apps/analytics/src/constants/config.ts @@ -39,7 +39,7 @@ export const QUERY_START_BLOCK: { [chainId: number]: bigint } = { * Draw results URL */ export const DRAW_RESULTS_URL: { [chainId: number]: string } = { - [NETWORK.optimism_sepolia]: `https://raw.githubusercontent.com/GenerationSoftware/pt-v5-draw-results-testnet/main/prizes/${NETWORK.sepolia}` + [NETWORK.optimism_sepolia]: `https://raw.githubusercontent.com/GenerationSoftware/pt-v5-draw-results-testnet/main/prizes/${NETWORK.optimism_sepolia}` } /** From cd748aeb14030094c6dd2c9b937f8cf56be44917 Mon Sep 17 00:00:00 2001 From: Ncookiez Date: Wed, 13 Mar 2024 17:29:36 -0400 Subject: [PATCH 061/161] added tooltip content --- .../src/components/forms/YieldVaultInput.tsx | 35 ++++++++++++++----- 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/apps/vault-factory/src/components/forms/YieldVaultInput.tsx b/apps/vault-factory/src/components/forms/YieldVaultInput.tsx index 69e630ea..3d4f9ea3 100644 --- a/apps/vault-factory/src/components/forms/YieldVaultInput.tsx +++ b/apps/vault-factory/src/components/forms/YieldVaultInput.tsx @@ -1,8 +1,8 @@ import { useToken } from '@generationsoftware/hyperstructure-react-hooks' import { InformationCircleIcon } from '@heroicons/react/24/outline' import { TokenIcon } from '@shared/react-components' -import { Card, ExternalLink, Spinner, Tooltip } from '@shared/ui' -import { getBlockExplorerUrl, shorten } from '@shared/utilities' +import { Card, ExternalLink, LINKS, Spinner, Tooltip } from '@shared/ui' +import { getBlockExplorerUrl, getVaultId, shorten } from '@shared/utilities' import classNames from 'classnames' import { useAtomValue } from 'jotai' import { useMemo } from 'react' @@ -100,18 +100,35 @@ const YieldVaultCard = (props: YieldVaultCardProps) => { {shorten(yieldVault.address)} {!!existingVaultAddresses.length && (
- - {existingVaultAddresses.length} existing prize vaults - - {/* TODO: add actual content */} - - + + {existingVaultAddresses.map((existingVaultAddress) => ( + + {shorten(existingVaultAddress)} + + ))} +
+ } + > +
+ + {existingVaultAddresses.length} existing prize vault + {existingVaultAddresses.length > 1 ? 's' : ''} + + +
)} From b6db39c6f2b6de9edf56b8e45827dbb496bba069 Mon Sep 17 00:00:00 2001 From: Ncookiez Date: Wed, 13 Mar 2024 17:33:55 -0400 Subject: [PATCH 062/161] fixed mobile yield vault input style --- apps/vault-factory/src/components/forms/YieldVaultForm.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/vault-factory/src/components/forms/YieldVaultForm.tsx b/apps/vault-factory/src/components/forms/YieldVaultForm.tsx index 22bc4cd3..a609bb93 100644 --- a/apps/vault-factory/src/components/forms/YieldVaultForm.tsx +++ b/apps/vault-factory/src/components/forms/YieldVaultForm.tsx @@ -68,6 +68,7 @@ export const YieldVaultForm = (props: YieldVaultFormProps) => { ))}
From d79317951b5c5847f6e3464a5ee0d9f0df714c08 Mon Sep 17 00:00:00 2001 From: Ncookiez Date: Wed, 13 Mar 2024 17:51:04 -0400 Subject: [PATCH 063/161] fixed tailwind being monkebrain --- shared/ui/components/Tooltip.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/shared/ui/components/Tooltip.tsx b/shared/ui/components/Tooltip.tsx index e2aed3b0..a7b5d2f1 100644 --- a/shared/ui/components/Tooltip.tsx +++ b/shared/ui/components/Tooltip.tsx @@ -15,6 +15,7 @@ export const Tooltip = (props: TooltipProps) => { dark: 'bg-pt-purple-100 text-gray-600 text-center' }, arrow: { + base: 'absolute z-10 h-2 w-2 rotate-45', style: { dark: 'bg-pt-purple-100' } From dd70ef6cdfa14cead22af1a36ed6df57f8503d9a Mon Sep 17 00:00:00 2001 From: Ncookiez Date: Thu, 14 Mar 2024 11:41:18 -0400 Subject: [PATCH 064/161] hiding all canary tiers from /prizes page --- .../src/components/Prizes/PrizePoolWinners.tsx | 12 +++++++++--- apps/app/src/components/Prizes/PrizesTable.tsx | 2 +- .../Modals/DrawModal/Views/MainView.tsx | 16 ++++++++++++---- 3 files changed, 22 insertions(+), 8 deletions(-) diff --git a/apps/app/src/components/Prizes/PrizePoolWinners.tsx b/apps/app/src/components/Prizes/PrizePoolWinners.tsx index 3ebfb06f..541e27c2 100644 --- a/apps/app/src/components/Prizes/PrizePoolWinners.tsx +++ b/apps/app/src/components/Prizes/PrizePoolWinners.tsx @@ -104,14 +104,20 @@ const DrawRow = (props: DrawRowProps) => { const setSelectedDrawId = useSetAtom(drawIdAtom) + const { uniqueWallets, totalPrizeAmount } = useMemo(() => { + const validPrizeClaims = draw.prizeClaims.filter((claim) => !!claim.payout) + + return { + uniqueWallets: new Set
(validPrizeClaims.map((claim) => claim.winner)), + totalPrizeAmount: validPrizeClaims.reduce((a, b) => a + b.payout, 0n) + } + }, [draw]) + const handleClick = () => { setSelectedDrawId(draw.id) setIsModalOpen(true) } - const uniqueWallets = new Set
(draw.prizeClaims.map((claim) => claim.winner)) - const totalPrizeAmount = draw.prizeClaims.reduce((a, b) => a + b.payout, 0n) - const firstPrizeTimestamp = draw.prizeClaims[0].timestamp const currentTime = getSecondsSinceEpoch() const timeTextType = diff --git a/apps/app/src/components/Prizes/PrizesTable.tsx b/apps/app/src/components/Prizes/PrizesTable.tsx index e1979da7..6530eb55 100644 --- a/apps/app/src/components/Prizes/PrizesTable.tsx +++ b/apps/app/src/components/Prizes/PrizesTable.tsx @@ -27,7 +27,7 @@ export const PrizesTable = (props: PrizesTableProps) => { {isFetchedAllPrizeInfo && isFetchedTokenData && !!tokenData ? (
{Object.values(allPrizeInfo)[0] - .slice(0, -1) + .slice(0, -2) .map((prize, i) => { const frequency = formatDailyCountToFrequency(prize.dailyFrequency) diff --git a/shared/react-components/components/Modals/DrawModal/Views/MainView.tsx b/shared/react-components/components/Modals/DrawModal/Views/MainView.tsx index 4e43d08f..f582a1f9 100644 --- a/shared/react-components/components/Modals/DrawModal/Views/MainView.tsx +++ b/shared/react-components/components/Modals/DrawModal/Views/MainView.tsx @@ -135,13 +135,19 @@ const DrawTotals = (props: DrawTotalsProps) => { } }, [lastDrawId, lastDrawTimestamps]) + const { uniqueWallets, totalPrizeAmount } = useMemo(() => { + const validPrizeClaims = draw.prizeClaims.filter((claim) => !!claim.payout) + + return { + uniqueWallets: new Set
(validPrizeClaims.map((claim) => claim.winner)), + totalPrizeAmount: validPrizeClaims.reduce((a, b) => a + b.payout, 0n) + } + }, [draw]) + if (prizeToken === undefined) { return } - const uniqueWallets = new Set
(draw.prizeClaims.map((claim) => claim.winner)) - const totalPrizeAmount = draw.prizeClaims.reduce((a, b) => a + b.payout, 0n) - return ( {intl?.('drawTotal.beforeValue', { numWallets: uniqueWallets.size }) ?? @@ -169,7 +175,9 @@ const DrawWinnersTable = (props: DrawWinnersTableProps) => { const wins = useMemo(() => { const groupedWins: { [winner: Address]: bigint } = {} - draw.prizeClaims.forEach((win) => { + const validPrizeClaims = draw.prizeClaims.filter((claim) => !!claim.payout) + + validPrizeClaims.forEach((win) => { if (groupedWins[win.winner] !== undefined) { groupedWins[win.winner] += win.payout } else { From 3606e288d68f1cfe9bfd9253db173a85a46c76f1 Mon Sep 17 00:00:00 2001 From: Ncookiez Date: Thu, 14 Mar 2024 12:42:39 -0400 Subject: [PATCH 065/161] added yield source warning + style fixes --- .../src/components/CreateVaultStepInfo.tsx | 4 ++-- .../src/components/DeployVaultView.tsx | 16 +++++++++++----- apps/vault-factory/src/components/StepInfo.tsx | 9 ++++++--- 3 files changed, 19 insertions(+), 10 deletions(-) diff --git a/apps/vault-factory/src/components/CreateVaultStepInfo.tsx b/apps/vault-factory/src/components/CreateVaultStepInfo.tsx index e582b577..c85841de 100644 --- a/apps/vault-factory/src/components/CreateVaultStepInfo.tsx +++ b/apps/vault-factory/src/components/CreateVaultStepInfo.tsx @@ -74,11 +74,11 @@ export const CreateVaultStepInfo = (props: CreateVaultStepInfoProps) => { const blockedSteps = useMemo(() => { const blocked: number[] = [] - if (step >= 3 && isUsingCustomYieldSource) { + if (step > 2 && isUsingCustomYieldSource) { blocked.push(2) } - if (step >= 6) { + if (step > 6) { blocked.push(...[...Array(6).keys()]) } diff --git a/apps/vault-factory/src/components/DeployVaultView.tsx b/apps/vault-factory/src/components/DeployVaultView.tsx index 29d15371..90662d84 100644 --- a/apps/vault-factory/src/components/DeployVaultView.tsx +++ b/apps/vault-factory/src/components/DeployVaultView.tsx @@ -3,7 +3,7 @@ import { getNiceNetworkNameByChainId } from '@shared/utilities' import classNames from 'classnames' import { useMemo } from 'react' import { SupportedNetwork } from 'src/types' -import { Address, formatUnits } from 'viem' +import { Address, formatUnits, zeroAddress } from 'viem' import { useAccount } from 'wagmi' import { useVaultCreationSteps } from '@hooks/useVaultCreationSteps' import { useVaultInfo } from '@hooks/useVaultInfo' @@ -32,7 +32,6 @@ export const DeployVaultView = (props: DeployVaultViewProps) => { ) } -// TODO: add invalid yield source warning // TODO: add precision per dollar check warning const DeployVaultViewWarnings = (props: { className?: string }) => { const { className } = props @@ -48,10 +47,17 @@ const DeployVaultViewWarnings = (props: { className?: string }) => { { refetchOnWindowFocus: true } ) + const { setStep } = useVaultCreationSteps() + const warning = useMemo((): | { text: string; fix?: { text: string; onClick: () => void } } | undefined => { - if (!!token && !!yieldBuffer && token.amount < yieldBuffer) { + if (token?.address === zeroAddress) { + return { + text: `The yield source you have selected doesn't seem valid.`, + fix: { text: 'Select a valid yield source', onClick: () => setStep(1) } + } + } else if (!!token && !!yieldBuffer && token.amount < yieldBuffer) { return { text: `You need at least ${formatUnits(yieldBuffer, token.decimals)} ${ token.symbol @@ -69,7 +75,7 @@ const DeployVaultViewWarnings = (props: { className?: string }) => { return (
{ Warning {warning.text} {!!warning.fix && ( - )} diff --git a/apps/vault-factory/src/components/StepInfo.tsx b/apps/vault-factory/src/components/StepInfo.tsx index 003f8bac..fb13689d 100644 --- a/apps/vault-factory/src/components/StepInfo.tsx +++ b/apps/vault-factory/src/components/StepInfo.tsx @@ -49,6 +49,8 @@ const VaultStepGraphic = (props: VaultStepGraphicProps) => { const completedSteps = [...Array(step).keys()] const futureSteps = step < maxSteps ? [...Array(maxSteps - step - 1).keys()] : [] + const stepClassName = 'w-3 h-3 rounded-full' + return (
{completedSteps.map((i) => { @@ -61,15 +63,16 @@ const VaultStepGraphic = (props: VaultStepGraphicProps) => { setStep(i) } }} - className={classNames('w-3 h-3 bg-pt-teal-dark rounded-full', { - 'cursor-pointer': !isBlocked + className={classNames(stepClassName, { + 'bg-pt-teal-dark cursor-pointer': !isBlocked, + 'bg-pt-purple-50/50': isBlocked })} /> ) })}
{futureSteps.map((i) => ( -
+
))}
) From 28812142348419b096cdd5feb98ebdd1673d8b81 Mon Sep 17 00:00:00 2001 From: Ncookiez Date: Thu, 14 Mar 2024 16:07:02 -0400 Subject: [PATCH 066/161] added precision checks to factory --- .../src/components/Charts/BurnChart.tsx | 2 +- .../src/components/DeployVaultView.tsx | 30 +++++++++++++++++-- 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/apps/analytics/src/components/Charts/BurnChart.tsx b/apps/analytics/src/components/Charts/BurnChart.tsx index 732be24e..db26e507 100644 --- a/apps/analytics/src/components/Charts/BurnChart.tsx +++ b/apps/analytics/src/components/Charts/BurnChart.tsx @@ -93,7 +93,7 @@ export const BurnChart = (props: BurnChartProps) => { const burnAmount = formatBurnNum(burnEvent.args.value) if (toAddress === DEAD_ADDRESS) { - // TODO: it is possible to have multiple events in one tx - this could cause issues + // TODO: it is possible to have multiple events in one tx - this could cause issues (use amount to match?) if (buybackTxHashes.includes(burnEvent.transactionHash)) { buyback.change += burnAmount } else { diff --git a/apps/vault-factory/src/components/DeployVaultView.tsx b/apps/vault-factory/src/components/DeployVaultView.tsx index 90662d84..8e39b6f3 100644 --- a/apps/vault-factory/src/components/DeployVaultView.tsx +++ b/apps/vault-factory/src/components/DeployVaultView.tsx @@ -1,5 +1,5 @@ -import { useTokenBalance } from '@generationsoftware/hyperstructure-react-hooks' -import { getNiceNetworkNameByChainId } from '@shared/utilities' +import { useTokenBalance, useTokenPrices } from '@generationsoftware/hyperstructure-react-hooks' +import { getNiceNetworkNameByChainId, USDC_TOKEN_ADDRESSES } from '@shared/utilities' import classNames from 'classnames' import { useMemo } from 'react' import { SupportedNetwork } from 'src/types' @@ -32,7 +32,6 @@ export const DeployVaultView = (props: DeployVaultViewProps) => { ) } -// TODO: add precision per dollar check warning const DeployVaultViewWarnings = (props: { className?: string }) => { const { className } = props @@ -47,8 +46,29 @@ const DeployVaultViewWarnings = (props: { className?: string }) => { { refetchOnWindowFocus: true } ) + const { data: tokenPrices } = useTokenPrices( + chainId as SupportedNetwork, + !!chainId && !!tokenAddress ? [tokenAddress, USDC_TOKEN_ADDRESSES[chainId]] : [] + ) + const { setStep } = useVaultCreationSteps() + const isBadTokenPrecision = useMemo(() => { + if (!!token && !isNaN(token.decimals) && !!tokenPrices) { + const tokenPrice = tokenPrices[token.address.toLowerCase() as Lowercase
] + const usdcPrice = tokenPrices[USDC_TOKEN_ADDRESSES[token.chainId]] + + if (!!tokenPrice && !!usdcPrice) { + const precision = 10 ** token.decimals / tokenPrice + const usdcPrecision = 10 ** 6 / usdcPrice // TODO: this assumes all USDC tokens have 6 decimals + + return precision < usdcPrecision + } + } + + return false + }, [token, tokenPrices]) + const warning = useMemo((): | { text: string; fix?: { text: string; onClick: () => void } } | undefined => { @@ -57,6 +77,10 @@ const DeployVaultViewWarnings = (props: { className?: string }) => { text: `The yield source you have selected doesn't seem valid.`, fix: { text: 'Select a valid yield source', onClick: () => setStep(1) } } + } else if (!!token && isBadTokenPrecision) { + return { + text: `Using ${token.symbol} is likely to cause rounding error issues in the long run because of its high value to decimals ratio.` + } } else if (!!token && !!yieldBuffer && token.amount < yieldBuffer) { return { text: `You need at least ${formatUnits(yieldBuffer, token.decimals)} ${ From ba71f94127bfabc89ae5da11d2b5bbd6a8e56e40 Mon Sep 17 00:00:00 2001 From: Ncookiez Date: Thu, 14 Mar 2024 16:27:59 -0400 Subject: [PATCH 067/161] added dai polygon v3 pool and fixed v3 withdrawal gas estimates --- apps/migrations/src/components/V3/V3Migration.tsx | 3 ++- apps/migrations/src/constants/config.ts | 6 ++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/apps/migrations/src/components/V3/V3Migration.tsx b/apps/migrations/src/components/V3/V3Migration.tsx index 79251c9a..3fe4741c 100644 --- a/apps/migrations/src/components/V3/V3Migration.tsx +++ b/apps/migrations/src/components/V3/V3Migration.tsx @@ -98,7 +98,8 @@ const WithdrawContent = (props: WithdrawContentProps) => { args: migration?.type === 'pool' ? [userAddress, migration?.token.amount, migration?.token.address, 0n] - : [migration?.token.amount, 0n] + : [migration?.token.amount, 0n], + account: userAddress }, { refetchInterval: sToMs(10) } ) diff --git a/apps/migrations/src/constants/config.ts b/apps/migrations/src/constants/config.ts index 6ab44f3b..b0aa0d3f 100644 --- a/apps/migrations/src/constants/config.ts +++ b/apps/migrations/src/constants/config.ts @@ -422,6 +422,12 @@ export const V3_POOLS: Record< ticketAddress: '0x9ecb26631098973834925eb453de1908ea4bdd4e', tokenAddress: '0xc2132d05d31c914a87c6611c10748aeb04b58e8f', migrateTo: MIGRATION_DESTINATIONS.usdcVault + }, + { + address: '0x60764c6be24ddab70d9ae1dbf7436533cc073c21', + ticketAddress: '0x0bc114a3163a0bc72abf0ab964eef0dc52495703', + tokenAddress: '0x8f3cf7ad23cd3cadbd9735aff958023239c6a063', + migrateTo: MIGRATION_DESTINATIONS.usdcVault } ], [NETWORK.avalanche]: [], From cb8278ef4d7f8cae03cde931ddb2195dfed6ae99 Mon Sep 17 00:00:00 2001 From: Ncookiez Date: Thu, 14 Mar 2024 16:51:43 -0400 Subject: [PATCH 068/161] more accurate burn lookups --- .../src/components/Charts/BurnChart.tsx | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/apps/analytics/src/components/Charts/BurnChart.tsx b/apps/analytics/src/components/Charts/BurnChart.tsx index db26e507..95810a2a 100644 --- a/apps/analytics/src/components/Charts/BurnChart.tsx +++ b/apps/analytics/src/components/Charts/BurnChart.tsx @@ -76,10 +76,10 @@ export const BurnChart = (props: BurnChartProps) => { validRngTxs[validRngTxs.length - 1]?.drawFinish.blockNumber ?? MAX_UINT_256 const buybackLpAddress = BURN_SETTINGS[burnToken.chainId].liquidationPairAddress - const buybackTxHashes = !!buybackLpAddress - ? liquidationEvents - .filter((event) => event.args.liquidationPair.toLowerCase() === buybackLpAddress) - .map((e) => e.transactionHash) + const buybackEvents = !!buybackLpAddress + ? liquidationEvents.filter( + (event) => event.args.liquidationPair.toLowerCase() === buybackLpAddress + ) : [] let buyback = { total: 0, change: 0 } @@ -93,8 +93,13 @@ export const BurnChart = (props: BurnChartProps) => { const burnAmount = formatBurnNum(burnEvent.args.value) if (toAddress === DEAD_ADDRESS) { - // TODO: it is possible to have multiple events in one tx - this could cause issues (use amount to match?) - if (buybackTxHashes.includes(burnEvent.transactionHash)) { + const matchingBuybackEvent = buybackEvents.find( + (buybackEvent) => + buybackEvent.transactionHash === burnEvent.transactionHash && + buybackEvent.args.amountIn === burnEvent.args.value + ) + + if (!!matchingBuybackEvent) { buyback.change += burnAmount } else { manual.change += burnAmount From 361d144c40921b093954e8fec8223e648d379eb6 Mon Sep 17 00:00:00 2001 From: Ncookiez Date: Fri, 15 Mar 2024 16:03:22 -0400 Subject: [PATCH 069/161] filtering yield vaults by tag --- .../src/components/forms/YieldVaultForm.tsx | 104 ++++++++++++++++-- 1 file changed, 92 insertions(+), 12 deletions(-) diff --git a/apps/vault-factory/src/components/forms/YieldVaultForm.tsx b/apps/vault-factory/src/components/forms/YieldVaultForm.tsx index a609bb93..fe3799ec 100644 --- a/apps/vault-factory/src/components/forms/YieldVaultForm.tsx +++ b/apps/vault-factory/src/components/forms/YieldVaultForm.tsx @@ -1,9 +1,10 @@ -import { Spinner } from '@shared/ui' +import { Selection, SelectionItem, Spinner } from '@shared/ui' import classNames from 'classnames' import { useAtom, useAtomValue } from 'jotai' -import { useEffect, useMemo } from 'react' +import { useEffect, useMemo, useState } from 'react' import { FormProvider, useForm } from 'react-hook-form' import { vaultChainIdAtom, vaultYieldSourceAddressAtom, vaultYieldSourceIdAtom } from 'src/atoms' +import { YieldSourceVaultTag } from 'src/types' import { Address } from 'viem' import { NextButton } from '@components/buttons/NextButton' import { PrevButton } from '@components/buttons/PrevButton' @@ -30,6 +31,8 @@ export const YieldVaultForm = (props: YieldVaultFormProps) => { const { nextStep } = useVaultCreationSteps() + const [filterId, setFilterId] = useState<'all' | YieldSourceVaultTag>('all') + useEffect(() => { !!vaultYieldSourceAddress && formMethods.setValue('vaultYieldSourceAddress', vaultYieldSourceAddress, { @@ -50,11 +53,18 @@ export const YieldVaultForm = (props: YieldVaultFormProps) => { } }, [chainId, vaultYieldSourceId]) - if (!chainId || !yieldSource) { + const yieldVaults = useMemo(() => { + if (!!yieldSource) { + return filterId === 'all' + ? yieldSource.vaults + : yieldSource.vaults.filter((yieldVault) => yieldVault.tags?.includes(filterId)) + } + }, [yieldSource, filterId]) + + if (!chainId || !yieldSource || !yieldVaults) { return } - // TODO: add filtering options by tag return ( { >
Select Deposit Token -
- {yieldSource.vaults.map((yieldVault) => ( - - ))} + +
+
+ {yieldVaults.map((yieldVault) => ( + + ))} +
@@ -81,3 +98,66 @@ export const YieldVaultForm = (props: YieldVaultFormProps) => { ) } + +interface YieldVaultFilterSelectionProps { + allYieldVaults: { tags?: YieldSourceVaultTag[] }[] + selectedFilterId: 'all' | YieldSourceVaultTag + onSelectFilter: (id: 'all' | YieldSourceVaultTag) => void + className?: string +} + +const YieldVaultFilterSelection = (props: YieldVaultFilterSelectionProps) => { + const { allYieldVaults, selectedFilterId, onSelectFilter, className } = props + + const isTagPresent = (vaults: { tags?: YieldSourceVaultTag[] }[], tag: YieldSourceVaultTag) => { + return !!vaults.find((vault) => vault.tags?.includes(tag)) + } + + const filterItems = useMemo(() => { + const items: SelectionItem[] = [ + { + id: 'all', + content: 'Show All', + onClick: () => onSelectFilter('all'), + className: 'whitespace-nowrap' + } + ] + + if (isTagPresent(allYieldVaults, 'stablecoin')) { + items.push({ + id: 'stablecoin', + content: 'Stablecoins', + onClick: () => onSelectFilter('stablecoin') + }) + } + + if (isTagPresent(allYieldVaults, 'lp')) { + items.push({ + id: 'lp', + content: 'LP Tokens', + onClick: () => onSelectFilter('lp'), + className: 'whitespace-nowrap' + }) + } + + if (isTagPresent(allYieldVaults, 'lst')) { + items.push({ + id: 'lst', + content: 'Liquid Staking', + onClick: () => onSelectFilter('lst'), + className: 'whitespace-nowrap' + }) + } + + return items + }, [allYieldVaults]) + + return ( + + ) +} From 6860a3833a23a2d06eb21f07435fb7b514fbaa5c Mon Sep 17 00:00:00 2001 From: Ncookiez Date: Mon, 18 Mar 2024 11:41:38 -0400 Subject: [PATCH 070/161] ignoring canary tiers on claim fee % charts --- .../Charts/DrawAvgClaimFeesChart.tsx | 32 +++--------- .../Charts/DrawsAvgClaimFeesChart.tsx | 49 ++++++------------- apps/analytics/src/views/DrawsView.tsx | 2 +- apps/analytics/src/views/PrizesView.tsx | 1 - 4 files changed, 24 insertions(+), 60 deletions(-) diff --git a/apps/analytics/src/components/Charts/DrawAvgClaimFeesChart.tsx b/apps/analytics/src/components/Charts/DrawAvgClaimFeesChart.tsx index f558e505..f78387df 100644 --- a/apps/analytics/src/components/Charts/DrawAvgClaimFeesChart.tsx +++ b/apps/analytics/src/components/Charts/DrawAvgClaimFeesChart.tsx @@ -1,8 +1,5 @@ import { PrizePool } from '@generationsoftware/hyperstructure-client-js' -import { - useDrawAwardedEvents, - usePrizeDrawWinners -} from '@generationsoftware/hyperstructure-react-hooks' +import { usePrizeDrawWinners } from '@generationsoftware/hyperstructure-react-hooks' import { divideBigInts, formatNumberForDisplay, @@ -13,35 +10,23 @@ import classNames from 'classnames' import { useAtomValue } from 'jotai' import { useMemo } from 'react' import { currentTimestampAtom } from 'src/atoms' -import { isCanaryTier } from 'src/utils' -import { QUERY_START_BLOCK } from '@constants/config' import { useDrawStatus } from '@hooks/useDrawStatus' import { LineChart, LineChartProps } from './LineChart' interface DrawAvgClaimFeesChartProps { prizePool: PrizePool drawId: number - hideCanary?: boolean className?: string } export const DrawAvgClaimFeesChart = (props: DrawAvgClaimFeesChartProps) => { - const { prizePool, drawId, hideCanary, className } = props + const { prizePool, drawId, className } = props const { data: wins } = usePrizeDrawWinners(prizePool) const drawWins = wins?.find((draw) => draw.id === drawId)?.prizeClaims const { closedAt, awardedAt, finalizedAt } = useDrawStatus(prizePool, drawId) - const { data: drawAwardedEvents } = useDrawAwardedEvents(prizePool, { - fromBlock: !!prizePool ? QUERY_START_BLOCK[prizePool.chainId] : undefined - }) - - const numTiers = useMemo(() => { - const drawAwardedEvent = drawAwardedEvents?.find((e) => e.args.drawId === drawId) - return drawAwardedEvent?.args.numTiers - }, [drawId, drawAwardedEvents]) - const currentTimestamp = useAtomValue(currentTimestampAtom) const chartTimestamps = useMemo(() => { @@ -61,7 +46,7 @@ export const DrawAvgClaimFeesChart = (props: DrawAvgClaimFeesChartProps) => { }, [closedAt, currentTimestamp]) const chartData = useMemo(() => { - if (!!drawWins?.length && !!numTiers) { + if (!!drawWins?.length) { const data: { name: number; [tier: number]: number }[] = [] const cumTierValues: { @@ -69,10 +54,7 @@ export const DrawAvgClaimFeesChart = (props: DrawAvgClaimFeesChartProps) => { } = {} const filteredWins = drawWins.filter( - (win) => - win.claimReward > 0n && - win.claimRewardRecipient !== win.recipient && - (!hideCanary || !isCanaryTier(win.tier, numTiers)) + (win) => !!win.payout && !!win.claimReward && win.claimRewardRecipient !== win.recipient ) const tiers = new Set(filteredWins.map((win) => win.tier)) @@ -108,9 +90,9 @@ export const DrawAvgClaimFeesChart = (props: DrawAvgClaimFeesChartProps) => { return data } - }, [drawWins, numTiers, chartTimestamps]) + }, [drawWins, chartTimestamps]) - if (!!chartData?.length && !!numTiers) { + if (!!chartData?.length) { const lines: LineChartProps['lines'] = Object.keys(chartData[0]) .filter((key) => key !== 'name') .map((key) => ({ id: parseInt(key) })) @@ -137,7 +119,7 @@ export const DrawAvgClaimFeesChart = (props: DrawAvgClaimFeesChartProps) => { show: true, formatter: (value, tier) => [ `${formatNumberForDisplay(value, { maximumFractionDigits: 2 })}%`, - tier === 0 ? 'GP' : isCanaryTier(Number(tier), numTiers) ? 'Canary' : `Tier ${tier}` + tier === 0 ? 'GP' : `Tier ${tier}` ], labelFormatter: (label) => getSimpleTime(Number(label)) }} diff --git a/apps/analytics/src/components/Charts/DrawsAvgClaimFeesChart.tsx b/apps/analytics/src/components/Charts/DrawsAvgClaimFeesChart.tsx index 5c224401..94521bd3 100644 --- a/apps/analytics/src/components/Charts/DrawsAvgClaimFeesChart.tsx +++ b/apps/analytics/src/components/Charts/DrawsAvgClaimFeesChart.tsx @@ -1,66 +1,49 @@ import { PrizePool } from '@generationsoftware/hyperstructure-client-js' -import { - useDrawAwardedEvents, - usePrizeDrawWinners -} from '@generationsoftware/hyperstructure-react-hooks' +import { usePrizeDrawWinners } from '@generationsoftware/hyperstructure-react-hooks' import { divideBigInts, formatNumberForDisplay } from '@shared/utilities' import classNames from 'classnames' import { useMemo } from 'react' -import { isCanaryTier } from 'src/utils' -import { QUERY_START_BLOCK } from '@constants/config' import { LineChart } from './LineChart' interface DrawsAvgClaimFeesChartProps { prizePool: PrizePool - hideCanary?: boolean className?: string } export const DrawsAvgClaimFeesChart = (props: DrawsAvgClaimFeesChartProps) => { - const { prizePool, hideCanary, className } = props + const { prizePool, className } = props const { data: allDraws } = usePrizeDrawWinners(prizePool) - const { data: drawAwardedEvents } = useDrawAwardedEvents(prizePool, { - fromBlock: !!prizePool ? QUERY_START_BLOCK[prizePool.chainId] : undefined - }) - const chartData = useMemo(() => { - if (!!allDraws && !!drawAwardedEvents) { + if (!!allDraws) { const data: { name: string; percentage: number; cumAvg: number }[] = [] let numValues = 0 let sumValues = 0 allDraws.forEach((draw) => { - const numTiers = drawAwardedEvents?.find((e) => e.args.drawId === draw.id)?.args.numTiers - - if (!!numTiers) { - const wins = draw.prizeClaims.filter( - (win) => - win.claimReward > 0n && - win.claimRewardRecipient !== win.recipient && - (!hideCanary || !isCanaryTier(win.tier, numTiers)) - ) + const wins = draw.prizeClaims.filter( + (win) => !!win.payout && !!win.claimReward && win.claimRewardRecipient !== win.recipient + ) - if (!!wins.length) { - const sumClaimFeeAmount = wins.reduce((a, b) => a + b.claimReward, 0n) - const sumPrizeAmount = wins.reduce((a, b) => a + b.payout, 0n) - const percentage = - divideBigInts(sumClaimFeeAmount, sumPrizeAmount + sumClaimFeeAmount) * 100 + if (!!wins.length) { + const sumClaimFeeAmount = wins.reduce((a, b) => a + b.claimReward, 0n) + const sumPrizeAmount = wins.reduce((a, b) => a + b.payout, 0n) + const percentage = + divideBigInts(sumClaimFeeAmount, sumPrizeAmount + sumClaimFeeAmount) * 100 - numValues++ - sumValues += percentage - const cumAvg = sumValues / numValues + numValues++ + sumValues += percentage + const cumAvg = sumValues / numValues - data.push({ name: `#${draw.id}`, percentage, cumAvg }) - } + data.push({ name: `#${draw.id}`, percentage, cumAvg }) } }) return data } - }, [allDraws, drawAwardedEvents]) + }, [allDraws]) if (!!chartData?.length) { return ( diff --git a/apps/analytics/src/views/DrawsView.tsx b/apps/analytics/src/views/DrawsView.tsx index d833b898..ce63a706 100644 --- a/apps/analytics/src/views/DrawsView.tsx +++ b/apps/analytics/src/views/DrawsView.tsx @@ -52,7 +52,7 @@ export const DrawsView = (props: DrawsViewProps) => { return (
- +
diff --git a/apps/analytics/src/views/PrizesView.tsx b/apps/analytics/src/views/PrizesView.tsx index 1bff74b5..a6b637f8 100644 --- a/apps/analytics/src/views/PrizesView.tsx +++ b/apps/analytics/src/views/PrizesView.tsx @@ -56,7 +56,6 @@ export const PrizesView = (props: PrizesViewProps) => { From febb714163c48f4111cbf910742a88098a47958d Mon Sep 17 00:00:00 2001 From: Ncookiez Date: Mon, 18 Mar 2024 12:25:42 -0400 Subject: [PATCH 071/161] displaying multiple warnings --- .../src/components/DeployVaultView.tsx | 109 +++++++++++------- shared/utilities/constants.ts | 5 + 2 files changed, 73 insertions(+), 41 deletions(-) diff --git a/apps/vault-factory/src/components/DeployVaultView.tsx b/apps/vault-factory/src/components/DeployVaultView.tsx index 8e39b6f3..e50c8dd4 100644 --- a/apps/vault-factory/src/components/DeployVaultView.tsx +++ b/apps/vault-factory/src/components/DeployVaultView.tsx @@ -1,5 +1,9 @@ -import { useTokenBalance, useTokenPrices } from '@generationsoftware/hyperstructure-react-hooks' -import { getNiceNetworkNameByChainId, USDC_TOKEN_ADDRESSES } from '@shared/utilities' +import { + useToken, + useTokenBalance, + useTokenPrices +} from '@generationsoftware/hyperstructure-react-hooks' +import { getNiceNetworkNameByChainId, MAX_UINT_96, USDC_TOKEN_ADDRESSES } from '@shared/utilities' import classNames from 'classnames' import { useMemo } from 'react' import { SupportedNetwork } from 'src/types' @@ -46,6 +50,8 @@ const DeployVaultViewWarnings = (props: { className?: string }) => { { refetchOnWindowFocus: true } ) + const { data: tokenWithSupply } = useToken(chainId as SupportedNetwork, tokenAddress as Address) + const { data: tokenPrices } = useTokenPrices( chainId as SupportedNetwork, !!chainId && !!tokenAddress ? [tokenAddress, USDC_TOKEN_ADDRESSES[chainId]] : [] @@ -53,46 +59,63 @@ const DeployVaultViewWarnings = (props: { className?: string }) => { const { setStep } = useVaultCreationSteps() - const isBadTokenPrecision = useMemo(() => { - if (!!token && !isNaN(token.decimals) && !!tokenPrices) { - const tokenPrice = tokenPrices[token.address.toLowerCase() as Lowercase
] - const usdcPrice = tokenPrices[USDC_TOKEN_ADDRESSES[token.chainId]] - - if (!!tokenPrice && !!usdcPrice) { - const precision = 10 ** token.decimals / tokenPrice - const usdcPrecision = 10 ** 6 / usdcPrice // TODO: this assumes all USDC tokens have 6 decimals + const warnings = useMemo(() => { + const warnings: { id: string; text: string; fix?: { text: string; onClick: () => void } }[] = [] + + if (!!token) { + // Invalid yield source + if (token.address === zeroAddress) { + warnings.push({ + id: 'invalidYieldSource', + text: `The yield source you have selected doesn't seem valid.`, + fix: { text: 'Select a valid yield source', onClick: () => setStep(1) } + }) + } - return precision < usdcPrecision + // Bad precision per dollar + if (!isNaN(token.decimals) && !!tokenPrices) { + const tokenPrice = tokenPrices[token.address.toLowerCase() as Lowercase
] + const usdcPrice = tokenPrices[USDC_TOKEN_ADDRESSES[token.chainId]] + + if (!!tokenPrice && !!usdcPrice) { + const precision = 10 ** token.decimals / tokenPrice + const usdcPrecision = 10 ** 6 / usdcPrice // TODO: this assumes all USDC tokens have 6 decimals + + if (precision < usdcPrecision) { + warnings.push({ + id: 'badPrecisionPerDollar', + text: `Using ${token.symbol} is likely to cause rounding error issues in the long run because of its high value to decimals ratio.` + }) + } + } } - } - return false - }, [token, tokenPrices]) + // Total supply too large + if (!!tokenWithSupply && tokenWithSupply.totalSupply > MAX_UINT_96) { + const numTokens = formatUnits(MAX_UINT_96, token.decimals) - const warning = useMemo((): - | { text: string; fix?: { text: string; onClick: () => void } } - | undefined => { - if (token?.address === zeroAddress) { - return { - text: `The yield source you have selected doesn't seem valid.`, - fix: { text: 'Select a valid yield source', onClick: () => setStep(1) } - } - } else if (!!token && isBadTokenPrecision) { - return { - text: `Using ${token.symbol} is likely to cause rounding error issues in the long run because of its high value to decimals ratio.` + warnings.push({ + id: 'largeTotalSupply', + text: `A maximum of ${numTokens} ${token.symbol} can be deposited into this prize vault (less than its total supply).` + }) } - } else if (!!token && !!yieldBuffer && token.amount < yieldBuffer) { - return { - text: `You need at least ${formatUnits(yieldBuffer, token.decimals)} ${ - token.symbol - } on ${getNiceNetworkNameByChainId( - token.chainId - )} to deploy this prize vault. These tokens are donated to your new prize vault to prevent potential rounding errors.` + + // Not enough tokens in wallet + if (!!yieldBuffer && token.amount < yieldBuffer) { + const numTokens = formatUnits(yieldBuffer, token.decimals) + const networkName = getNiceNetworkNameByChainId(token.chainId) + + warnings.push({ + id: 'missingTokensInWallet', + text: `You need at least ${numTokens} ${token.symbol} on ${networkName} to deploy this prize vault. These tokens are donated to your new prize vault to prevent potential rounding errors.` + }) } } - }, [token, yieldBuffer]) - if (!warning) { + return warnings + }, [token, yieldBuffer, tokenPrices]) + + if (!warnings.length) { return <> } @@ -104,13 +127,17 @@ const DeployVaultViewWarnings = (props: { className?: string }) => { className )} > - Warning - {warning.text} - {!!warning.fix && ( - - )} + Warning{warnings.length > 1 ? 's' : ''} + {warnings.map((warning) => ( +
+ {warning.text} + {!!warning.fix && ( + + )} +
+ ))}
) } diff --git a/shared/utilities/constants.ts b/shared/utilities/constants.ts index 70efe07c..c2a2a4df 100644 --- a/shared/utilities/constants.ts +++ b/shared/utilities/constants.ts @@ -393,6 +393,11 @@ export const TOKEN_DATA_REDIRECTS: { */ export const MAX_UINT_256 = 2n ** 256n - 1n +/** + * Max uint96 value + */ +export const MAX_UINT_96 = 2n ** 96n - 1n + /** * EIP2612 Permit Types */ From 6b4cfa8f7837e6c56ca9c045ebe24655b1255e2d Mon Sep 17 00:00:00 2001 From: Ncookiez Date: Mon, 18 Mar 2024 12:30:06 -0400 Subject: [PATCH 072/161] improved total supply error message --- apps/vault-factory/src/components/DeployVaultView.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/vault-factory/src/components/DeployVaultView.tsx b/apps/vault-factory/src/components/DeployVaultView.tsx index e50c8dd4..954266dc 100644 --- a/apps/vault-factory/src/components/DeployVaultView.tsx +++ b/apps/vault-factory/src/components/DeployVaultView.tsx @@ -96,7 +96,7 @@ const DeployVaultViewWarnings = (props: { className?: string }) => { warnings.push({ id: 'largeTotalSupply', - text: `A maximum of ${numTokens} ${token.symbol} can be deposited into this prize vault (less than its total supply).` + text: `A maximum of ${numTokens} ${token.symbol} can be deposited into this prize vault (less than its total supply). If this limit is exceeded, deposits or yield liquidations may not function.` }) } From 945b15186783b1eaa3b81a2007c1f9449de473a4 Mon Sep 17 00:00:00 2001 From: Ncookiez Date: Mon, 18 Mar 2024 15:06:13 -0400 Subject: [PATCH 073/161] improved vault button logic + added tooltips --- apps/app/messages/en.json | 1 + .../Account/AccountDepositsCard.tsx | 2 +- .../Account/AccountDepositsTable.tsx | 4 +- .../Account/AccountVaultButtons.tsx | 41 ---------- .../app/src/components/Vault/VaultButtons.tsx | 53 +++++-------- apps/app/src/components/Vault/VaultCard.tsx | 4 +- .../src/components/Vault/VaultPageButtons.tsx | 31 -------- .../src/components/Vault/VaultPageContent.tsx | 8 +- apps/app/src/components/Vault/VaultsTable.tsx | 2 +- shared/react-components/README.md | 1 + .../components/Buttons/DepositButton.tsx | 74 ++++++++++++++++--- .../Tooltips/BadPrecisionPerDollarTooltip.tsx | 29 ++++++++ shared/react-components/index.tsx | 1 + 13 files changed, 124 insertions(+), 127 deletions(-) delete mode 100644 apps/app/src/components/Account/AccountVaultButtons.tsx delete mode 100644 apps/app/src/components/Vault/VaultPageButtons.tsx create mode 100644 shared/react-components/components/Tooltips/BadPrecisionPerDollarTooltip.tsx diff --git a/apps/app/messages/en.json b/apps/app/messages/en.json index ec4066b4..a8179c3e 100644 --- a/apps/app/messages/en.json +++ b/apps/app/messages/en.json @@ -283,6 +283,7 @@ "importedVault": "This vault is from the following imported list(s):", "vaultContribution": "The amount of {symbol} contributed to the prize pool over the last {days} days", "deprecatedVault": "This vault has been deprecated. It may still be eligible to win prizes, but we encourage users to migrate to other vaults.", + "badPrecisionPerDollar": "This vault is likely to have rounding errors which may lead to lossy withdrawals.", "delegateDescription": "By default the prize token holder is the delegated address. That can be overridden with delegation." }, "Toasts": { diff --git a/apps/app/src/components/Account/AccountDepositsCard.tsx b/apps/app/src/components/Account/AccountDepositsCard.tsx index 89edd1f5..ab1fff7e 100644 --- a/apps/app/src/components/Account/AccountDepositsCard.tsx +++ b/apps/app/src/components/Account/AccountDepositsCard.tsx @@ -56,7 +56,7 @@ export const AccountDepositsCard = (props: AccountDepositsCardProps) => {
{!isExternalUser && ( - + )}
) diff --git a/apps/app/src/components/Account/AccountDepositsTable.tsx b/apps/app/src/components/Account/AccountDepositsTable.tsx index ec1d0bfc..c3d9d80c 100644 --- a/apps/app/src/components/Account/AccountDepositsTable.tsx +++ b/apps/app/src/components/Account/AccountDepositsTable.tsx @@ -14,8 +14,8 @@ import Link from 'next/link' import { useMemo } from 'react' import { Address } from 'viem' import { useAccount } from 'wagmi' +import { VaultButtons } from '@components/Vault/VaultButtons' import { AccountVaultBalance } from './AccountVaultBalance' -import { AccountVaultButtons } from './AccountVaultButtons' import { AccountVaultOdds } from './AccountVaultOdds' interface AccountDepositsTableProps extends Omit { @@ -129,7 +129,7 @@ export const AccountDepositsTable = (props: AccountDepositsTableProps) => { position: 'center' }, manage: { - content: , + content: , position: 'right' } } diff --git a/apps/app/src/components/Account/AccountVaultButtons.tsx b/apps/app/src/components/Account/AccountVaultButtons.tsx deleted file mode 100644 index 2e665d3d..00000000 --- a/apps/app/src/components/Account/AccountVaultButtons.tsx +++ /dev/null @@ -1,41 +0,0 @@ -import { Vault } from '@generationsoftware/hyperstructure-client-js' -import { GiftIcon } from '@heroicons/react/24/solid' -import { - DelegateButton, - DepositButton, - DeprecatedVaultTooltip, - WithdrawButton -} from '@shared/react-components' -import { useTranslations } from 'next-intl' - -interface AccountVaultButtonsProps { - vault: Vault -} - -export const AccountVaultButtons = (props: AccountVaultButtonsProps) => { - const { vault } = props - - const t_common = useTranslations('Common') - const t_tooltips = useTranslations('Tooltips') - - const isDeprecated = vault.tags?.includes('deprecated') - - return ( -
- - - - - {t_common('withdraw')} - - - {isDeprecated ? ( - - {t_common('deposit')} - - ) : ( - {t_common('deposit')} - )} -
- ) -} diff --git a/apps/app/src/components/Vault/VaultButtons.tsx b/apps/app/src/components/Vault/VaultButtons.tsx index 547e6c69..38a1ba90 100644 --- a/apps/app/src/components/Vault/VaultButtons.tsx +++ b/apps/app/src/components/Vault/VaultButtons.tsx @@ -1,12 +1,7 @@ import { Vault } from '@generationsoftware/hyperstructure-client-js' import { useUserVaultShareBalance } from '@generationsoftware/hyperstructure-react-hooks' import { GiftIcon } from '@heroicons/react/24/solid' -import { - DelegateButton, - DepositButton, - DeprecatedVaultTooltip, - WithdrawButton -} from '@shared/react-components' +import { DelegateButton, DepositButton, WithdrawButton } from '@shared/react-components' import classNames from 'classnames' import { useTranslations } from 'next-intl' import { Address } from 'viem' @@ -14,14 +9,14 @@ import { useAccount } from 'wagmi' interface VaultButtonsProps { vault: Vault - hideDelegateButton?: boolean + forceShow?: ('delegate' | 'withdraw')[] + forceHide?: ('delegate' | 'withdraw')[] fullSized?: boolean - inverseOrder?: boolean className?: string } export const VaultButtons = (props: VaultButtonsProps) => { - const { vault, hideDelegateButton, fullSized, inverseOrder, className } = props + const { vault, forceShow, forceHide, fullSized, className } = props const t_common = useTranslations('Common') const t_tooltips = useTranslations('Tooltips') @@ -31,42 +26,28 @@ export const VaultButtons = (props: VaultButtonsProps) => { const { data: vaultBalance } = useUserVaultShareBalance(vault, userAddress as Address) const shareBalance = vaultBalance?.amount ?? 0n - const isDeprecated = vault.tags?.includes('deprecated') + const isDelegateButtonShown = + (shareBalance > 0n || forceShow?.includes('delegate')) && !forceHide?.includes('delegate') + const isWithdrawButtonShown = + (shareBalance > 0n || forceShow?.includes('withdraw')) && !forceHide?.includes('withdraw') return (
- {shareBalance > 0n && !hideDelegateButton && ( - + {isDelegateButtonShown && ( + )} - {isDeprecated ? ( -
- - - {t_common('deposit')} - - -
- ) : ( - - {t_common('deposit')} - - )} - {shareBalance > 0n && ( - + {isWithdrawButtonShown && ( + {t_common('withdraw')} )} +
) } diff --git a/apps/app/src/components/Vault/VaultCard.tsx b/apps/app/src/components/Vault/VaultCard.tsx index 09a82043..0029a99d 100644 --- a/apps/app/src/components/Vault/VaultCard.tsx +++ b/apps/app/src/components/Vault/VaultCard.tsx @@ -90,8 +90,8 @@ export const VaultCard = (props: VaultCardProps) => {
) diff --git a/apps/app/src/components/Vault/VaultPageButtons.tsx b/apps/app/src/components/Vault/VaultPageButtons.tsx deleted file mode 100644 index 9187b5c6..00000000 --- a/apps/app/src/components/Vault/VaultPageButtons.tsx +++ /dev/null @@ -1,31 +0,0 @@ -import { Vault } from '@generationsoftware/hyperstructure-client-js' -import { GiftIcon } from '@heroicons/react/24/solid' -import { DelegateButton, DepositButton, WithdrawButton } from '@shared/react-components' -import classNames from 'classnames' -import { useTranslations } from 'next-intl' - -interface VaultPageButtonsProps { - vault: Vault - className?: string -} - -export const VaultPageButtons = (props: VaultPageButtonsProps) => { - const { vault, className } = props - - const t = useTranslations('Common') - - return ( -
- - {t('withdraw')} - - {t('deposit')} - - <> - {' '} - {t('delegate') ?? `Delegate`} - - -
- ) -} diff --git a/apps/app/src/components/Vault/VaultPageContent.tsx b/apps/app/src/components/Vault/VaultPageContent.tsx index 11b61fce..b5c2d77a 100644 --- a/apps/app/src/components/Vault/VaultPageContent.tsx +++ b/apps/app/src/components/Vault/VaultPageContent.tsx @@ -14,7 +14,7 @@ import { useMemo } from 'react' import { Address, isAddress } from 'viem' import { SUPPORTED_NETWORKS } from '@constants/config' import { useNetworks } from '@hooks/useNetworks' -import { VaultPageButtons } from './VaultPageButtons' +import { VaultButtons } from './VaultButtons' import { VaultPageExtraInfo } from './VaultPageExtraInfo' import { VaultPageHeader } from './VaultPageHeader' import { VaultPageInfo } from './VaultPageInfo' @@ -72,7 +72,11 @@ export const VaultPageContent = (props: VaultPageContentProps) => { {!!vault && !!vaultTokenAddress ? ( <> - + ) : ( diff --git a/apps/app/src/components/Vault/VaultsTable.tsx b/apps/app/src/components/Vault/VaultsTable.tsx index fdc51e3a..99ca574a 100644 --- a/apps/app/src/components/Vault/VaultsTable.tsx +++ b/apps/app/src/components/Vault/VaultsTable.tsx @@ -210,7 +210,7 @@ export const VaultsTable = (props: VaultsTableProps) => { position: 'center' }, manage: { - content: , + content: , position: 'right' } } diff --git a/shared/react-components/README.md b/shared/react-components/README.md index 283938b2..ce80ef96 100644 --- a/shared/react-components/README.md +++ b/shared/react-components/README.md @@ -84,6 +84,7 @@ A React componponent library utilizing some simpler components from the internal ### Tooltip Components - `ApprovalTooltip` +- `BadPrecisionPerDollarTooltip` - `BonusRewardsTooltip` - `DeprecatedVaultTooltip` - `ImportedVaultTooltip` diff --git a/shared/react-components/components/Buttons/DepositButton.tsx b/shared/react-components/components/Buttons/DepositButton.tsx index 6f1304d6..af7068ae 100644 --- a/shared/react-components/components/Buttons/DepositButton.tsx +++ b/shared/react-components/components/Buttons/DepositButton.tsx @@ -1,20 +1,54 @@ -import { Vault } from '@generationsoftware/hyperstructure-client-js' -import { useSelectedVault } from '@generationsoftware/hyperstructure-react-hooks' +import { USDC_TOKEN_ADDRESSES, Vault } from '@generationsoftware/hyperstructure-client-js' +import { + useSelectedVault, + useTokenPrices, + useVaultTokenData +} from '@generationsoftware/hyperstructure-react-hooks' import { MODAL_KEYS, useIsModalOpen } from '@shared/generic-react-hooks' +import { Intl } from '@shared/types' import { Button, ButtonProps } from '@shared/ui' import classNames from 'classnames' +import { useMemo } from 'react' +import { Address } from 'viem' +import { BadPrecisionPerDollarTooltip } from '../Tooltips/BadPrecisionPerDollarTooltip' +import { DeprecatedVaultTooltip } from '../Tooltips/DeprecatedVaultTooltip' -interface DepositButtonProps extends Omit { +interface DepositButtonProps extends Omit { vault: Vault + intl?: { + base: Intl<'deposit'> + tooltips: Intl<'deprecatedVault' | 'badPrecisionPerDollar'> + } } export const DepositButton = (props: DepositButtonProps) => { - const { vault, children, className, disabled, ...rest } = props + const { vault, className, intl, ...rest } = props const { setIsModalOpen } = useIsModalOpen(MODAL_KEYS.deposit) const { setSelectedVaultById } = useSelectedVault() + const { data: token } = useVaultTokenData(vault) + + const { data: tokenPrices } = useTokenPrices( + vault.chainId, + !!token?.address ? [token.address, USDC_TOKEN_ADDRESSES[vault.chainId]] : [] + ) + + const isBadPrecisionPerDollar = useMemo(() => { + if (!!token && !!tokenPrices) { + const tokenPrice = tokenPrices[token.address.toLowerCase() as Lowercase
] + const usdcPrice = tokenPrices[USDC_TOKEN_ADDRESSES[token.chainId]] + + if (!!tokenPrice && !!usdcPrice) { + const precision = 10 ** token.decimals / tokenPrice + const usdcPrecision = 10 ** 6 / usdcPrice // TODO: this assumes all USDC tokens have 6 decimals + + return precision < usdcPrecision + } + } + }, [token, tokenPrices]) + const handleClick = () => { setSelectedVaultById(vault.id) setIsModalOpen(true) @@ -22,14 +56,32 @@ export const DepositButton = (props: DepositButtonProps) => { const isDeprecated = vault.tags?.includes('deprecated') + const buttonContent = intl?.base('deposit') ?? 'Deposit' + const buttonClassName = classNames('w-fit', className) + + if (isDeprecated) { + return ( + + + + ) + } + + if (isBadPrecisionPerDollar) { + return ( + + + + ) + } + return ( - ) } diff --git a/shared/react-components/components/Tooltips/BadPrecisionPerDollarTooltip.tsx b/shared/react-components/components/Tooltips/BadPrecisionPerDollarTooltip.tsx new file mode 100644 index 00000000..a2857018 --- /dev/null +++ b/shared/react-components/components/Tooltips/BadPrecisionPerDollarTooltip.tsx @@ -0,0 +1,29 @@ +import { Tooltip } from '@shared/ui' +import classNames from 'classnames' +import { ReactNode } from 'react' + +export interface BadPrecisionPerDollarTooltipProps { + children: ReactNode + intl?: string + className?: string +} + +export const BadPrecisionPerDollarTooltip = (props: BadPrecisionPerDollarTooltipProps) => { + const { children, intl, className } = props + + return ( + + + {intl ?? + 'This vault is likely to have rounding errors which may lead to lossy withdrawals.'} + +
+ } + fullSized={true} + > + {children} + + ) +} diff --git a/shared/react-components/index.tsx b/shared/react-components/index.tsx index eb5c3a5e..6e76f668 100644 --- a/shared/react-components/index.tsx +++ b/shared/react-components/index.tsx @@ -77,6 +77,7 @@ export * from './components/Toasts/WithdrawTxToast' * Tooltips */ export * from './components/Tooltips/ApprovalTooltip' +export * from './components/Tooltips/BadPrecisionPerDollarTooltip' export * from './components/Tooltips/BonusRewardsTooltip' export * from './components/Tooltips/DeprecatedVaultTooltip' export * from './components/Tooltips/ImportedVaultTooltip' From d080428f61f12ffe7928d3895f28f72c1cde51c1 Mon Sep 17 00:00:00 2001 From: Ncookiez Date: Mon, 18 Mar 2024 16:24:42 -0400 Subject: [PATCH 074/161] hiding reserve page when burning reserve --- .../src/components/Charts/ReserveChart.tsx | 19 ++++++++++++------- apps/analytics/src/components/Navbar.tsx | 10 +++++++++- apps/analytics/src/views/ReserveView.tsx | 12 +++--------- 3 files changed, 24 insertions(+), 17 deletions(-) diff --git a/apps/analytics/src/components/Charts/ReserveChart.tsx b/apps/analytics/src/components/Charts/ReserveChart.tsx index e1dbc9c3..928e506f 100644 --- a/apps/analytics/src/components/Charts/ReserveChart.tsx +++ b/apps/analytics/src/components/Charts/ReserveChart.tsx @@ -3,17 +3,17 @@ import { useFirstDrawOpenedAt, useManualContributionEvents, usePrizeBackstopEvents, - usePrizeTokenData + usePrizeTokenData, + useToken } from '@generationsoftware/hyperstructure-react-hooks' -import { Token } from '@shared/types' import { formatNumberForDisplay, getSimpleDate, MAX_UINT_256 } from '@shared/utilities' import classNames from 'classnames' import { useAtomValue } from 'jotai' import { useMemo } from 'react' import { currentTimestampAtom } from 'src/atoms' -import { formatUnits, Log } from 'viem' +import { Address, formatUnits, Log } from 'viem' import { ReserveCard } from '@components/Reserve/ReserveCard' -import { QUERY_START_BLOCK } from '@constants/config' +import { BURN_SETTINGS, QUERY_START_BLOCK } from '@constants/config' import { useReserve } from '@hooks/useReserve' import { DrawFinishTx, DrawStartTx, useRngTxs } from '@hooks/useRngTxs' import { LineChart } from './LineChart' @@ -30,12 +30,11 @@ interface DataPoint { interface ReserveChartProps { prizePool: PrizePool - burnToken?: Token className?: string } export const ReserveChart = (props: ReserveChartProps) => { - const { prizePool, burnToken, className } = props + const { prizePool, className } = props const { data: reserve } = useReserve(prizePool) @@ -53,6 +52,11 @@ export const ReserveChart = (props: ReserveChartProps) => { const { data: prizeToken } = usePrizeTokenData(prizePool) + const burnTokenAddress = !!prizePool + ? BURN_SETTINGS[prizePool.chainId]?.burnTokenAddress + : undefined + const { data: burnToken } = useToken(prizePool?.chainId, burnTokenAddress as Address) + const currentTimestamp = useAtomValue(currentTimestampAtom) const chartData = useMemo(() => { @@ -63,7 +67,8 @@ export const ReserveChart = (props: ReserveChartProps) => { !!firstDrawOpenedAt && !!manualContributionEvents && !!prizeBackstopEvents && - !!prizeToken + !!prizeToken && + (!!burnToken || !burnTokenAddress) ) { const data: DataPoint[] = [] diff --git a/apps/analytics/src/components/Navbar.tsx b/apps/analytics/src/components/Navbar.tsx index ec4ca503..22d40e9a 100644 --- a/apps/analytics/src/components/Navbar.tsx +++ b/apps/analytics/src/components/Navbar.tsx @@ -5,6 +5,7 @@ import Image from 'next/image' import Link from 'next/link' import { useRouter } from 'next/router' import { ReactNode } from 'react' +import { BURN_SETTINGS } from '@constants/config' import { useSelectedChainId } from '@hooks/useSelectedChainId' import { NetworkDropdown } from './NetworkDropdown' @@ -89,6 +90,11 @@ const NavbarActions = (props: NavbarActionsProps) => { const { chainId } = useSelectedChainId() const networkName = getNetworkNameByChainId(chainId ?? PRIZE_POOLS[0].chainId) + const isNotBurningReserve = + !!chainId && + !!BURN_SETTINGS[chainId] && + BURN_SETTINGS[chainId].liquidationPairAddress === undefined + return ( <> @@ -98,7 +104,9 @@ const NavbarActions = (props: NavbarActionsProps) => { className={linkClassName} /> - + {isNotBurningReserve && ( + + )} ) diff --git a/apps/analytics/src/views/ReserveView.tsx b/apps/analytics/src/views/ReserveView.tsx index cfdbb080..1f4bb2c7 100644 --- a/apps/analytics/src/views/ReserveView.tsx +++ b/apps/analytics/src/views/ReserveView.tsx @@ -2,10 +2,9 @@ import { PrizePool } from '@generationsoftware/hyperstructure-client-js' import { useLiquidationEvents, useManualContributionEvents, - usePrizeBackstopEvents, - useToken + usePrizeBackstopEvents } from '@generationsoftware/hyperstructure-react-hooks' -import { getSecondsSinceEpoch, POOL_TOKEN_ADDRESSES, PRIZE_POOLS, sToMs } from '@shared/utilities' +import { getSecondsSinceEpoch, PRIZE_POOLS, sToMs } from '@shared/utilities' import classNames from 'classnames' import { useSetAtom } from 'jotai' import { useEffect, useMemo } from 'react' @@ -43,11 +42,6 @@ export const ReserveView = (props: ReserveViewProps) => { ) }, [chainId, publicClient]) - const { data: burnToken } = useToken( - chainId, - POOL_TOKEN_ADDRESSES[prizePool.chainId as keyof typeof POOL_TOKEN_ADDRESSES] - ) - const fromBlock = !!prizePool ? QUERY_START_BLOCK[prizePool.chainId] : undefined const { refetch: refetchReserve } = useReserve(prizePool) @@ -77,7 +71,7 @@ export const ReserveView = (props: ReserveViewProps) => { return (
- {!!burnToken && } +
) } From ee1fd8fbb3d22f15a733b66b1dfcbedb79805706 Mon Sep 17 00:00:00 2001 From: Ncookiez Date: Thu, 21 Mar 2024 15:24:17 -0400 Subject: [PATCH 075/161] added `useIsValidYieldSourceConversionMath` + warnings --- .../src/components/DeployVaultView.tsx | 17 +++- .../useIsValidYieldSourceConversionMath.ts | 85 +++++++++++++++++++ 2 files changed, 101 insertions(+), 1 deletion(-) create mode 100644 apps/vault-factory/src/hooks/useIsValidYieldSourceConversionMath.ts diff --git a/apps/vault-factory/src/components/DeployVaultView.tsx b/apps/vault-factory/src/components/DeployVaultView.tsx index 954266dc..1d3a5935 100644 --- a/apps/vault-factory/src/components/DeployVaultView.tsx +++ b/apps/vault-factory/src/components/DeployVaultView.tsx @@ -9,6 +9,7 @@ import { useMemo } from 'react' import { SupportedNetwork } from 'src/types' import { Address, formatUnits, zeroAddress } from 'viem' import { useAccount } from 'wagmi' +import { useIsValidYieldSourceConversionMath } from '@hooks/useIsValidYieldSourceConversionMath' import { useVaultCreationSteps } from '@hooks/useVaultCreationSteps' import { useVaultInfo } from '@hooks/useVaultInfo' import { DeployVaultButton } from './buttons/DeployVaultButton' @@ -41,7 +42,7 @@ const DeployVaultViewWarnings = (props: { className?: string }) => { const { address: userAddress } = useAccount() - const { chainId, tokenAddress, yieldBuffer } = useVaultInfo() + const { chainId, yieldSourceAddress, tokenAddress, yieldBuffer } = useVaultInfo() const { data: token } = useTokenBalance( chainId as SupportedNetwork, @@ -57,6 +58,11 @@ const DeployVaultViewWarnings = (props: { className?: string }) => { !!chainId && !!tokenAddress ? [tokenAddress, USDC_TOKEN_ADDRESSES[chainId]] : [] ) + const { data: isValidYieldSourceConversionMath } = useIsValidYieldSourceConversionMath( + chainId as SupportedNetwork, + yieldSourceAddress as Address + ) + const { setStep } = useVaultCreationSteps() const warnings = useMemo(() => { @@ -72,6 +78,15 @@ const DeployVaultViewWarnings = (props: { className?: string }) => { }) } + // Inconsistent yield source conversion math + if (isValidYieldSourceConversionMath === false) { + warnings.push({ + id: 'inconsistentYieldSourceConversionMath', + text: `The yield source you have selected seems to have inconsistent math between "withdraw" and "redeem". This will likely mean your prize vault will not work as intended.`, + fix: { text: 'Select a valid yield source', onClick: () => setStep(1) } + }) + } + // Bad precision per dollar if (!isNaN(token.decimals) && !!tokenPrices) { const tokenPrice = tokenPrices[token.address.toLowerCase() as Lowercase
] diff --git a/apps/vault-factory/src/hooks/useIsValidYieldSourceConversionMath.ts b/apps/vault-factory/src/hooks/useIsValidYieldSourceConversionMath.ts new file mode 100644 index 00000000..377e2d47 --- /dev/null +++ b/apps/vault-factory/src/hooks/useIsValidYieldSourceConversionMath.ts @@ -0,0 +1,85 @@ +import { NO_REFETCH } from '@generationsoftware/hyperstructure-react-hooks' +import { vaultABI } from '@shared/utilities' +import { useQuery } from '@tanstack/react-query' +import { Address } from 'viem' +import { usePublicClient } from 'wagmi' + +/** + * Returns true or false depending on whether the conversion on withdraw/redeem amounts is accurate on a yield source + * @param chainId the yield source's chain ID + * @param address the yield source's address + * @returns + */ +export const useIsValidYieldSourceConversionMath = (chainId: number, address: Address) => { + const publicClient = usePublicClient({ chainId }) + + return useQuery({ + queryKey: ['yieldSourceConversionChecks', chainId, address], + queryFn: async () => { + if (!!publicClient) { + const valuesToCheck = Array.from(Array(19).keys()).map((i) => 10n ** BigInt(i)) + + const initialMulticallResults = await publicClient.multicall({ + contracts: [ + ...valuesToCheck.map((v) => ({ + address, + abi: vaultABI, + functionName: 'previewWithdraw', + args: [v] + })), + ...valuesToCheck.map((v) => ({ + address, + abi: vaultABI, + functionName: 'previewRedeem', + args: [v] + })) + ] + }) + + const withdrawResults = initialMulticallResults + .slice(0, valuesToCheck.length) + .map((r) => r.result as bigint) + const redeemResults = initialMulticallResults + .slice(valuesToCheck.length) + .map((r) => r.result as bigint) + + const testMulticallResults = await publicClient.multicall({ + contracts: [ + ...withdrawResults.map((v) => ({ + address, + abi: vaultABI, + functionName: 'previewRedeem', + args: [v] + })), + ...redeemResults.map((v) => ({ + address, + abi: vaultABI, + functionName: 'previewWithdraw', + args: [v] + })) + ] + }) + + const foundInconsistency = valuesToCheck.find((v, i) => { + if (testMulticallResults[i].status === 'success') { + const result = testMulticallResults[i].result as bigint + if (result < v) { + return true + } + } + + if (testMulticallResults[valuesToCheck.length + i].status === 'success') { + const result = testMulticallResults[valuesToCheck.length + i].result as bigint + if (result > v) { + return true + } + } + }) + + return !foundInconsistency + } + }, + enabled: !!chainId && !!address && !!publicClient, + ...NO_REFETCH + }) +} From 5a779ddd401f4acca51e426f2459affcb6fe0a43 Mon Sep 17 00:00:00 2001 From: Ncookiez Date: Thu, 21 Mar 2024 15:24:50 -0400 Subject: [PATCH 076/161] fixed faux yield vault addresses on testnet --- apps/vault-factory/src/constants/config.ts | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/apps/vault-factory/src/constants/config.ts b/apps/vault-factory/src/constants/config.ts index 56240e95..60f33e06 100644 --- a/apps/vault-factory/src/constants/config.ts +++ b/apps/vault-factory/src/constants/config.ts @@ -117,13 +117,13 @@ export const NETWORK_CONFIG: Record< href: 'https://aave.com/', description: 'Lending and borrowing protocol', vaults: [ - { address: '0x332b1EB2Cc4046954725EbDFB8143fB8354ea9a7', tags: ['stablecoin'] }, - { address: '0x13E37b0Ca8b48fc2818C177c24635F90C1495C5c', tags: ['stablecoin'] }, - { address: '0x602d77e900eCD48ac9b51151936Dcc5Efe2e7FaE', tags: ['stablecoin'] }, - { address: '0xA2B0321B671A83a98Ff1F5a680b700864f57c6e7', tags: ['stablecoin'] }, - { address: '0xd96702995B2bBD78a9A39eF86f4fA5f9704fdC7D', tags: ['stablecoin'] }, - { address: '0xE77Db9f8b68BC47A82D4F47E68FB57535dF0086e' }, - { address: '0x98CED5d595e8981756f063db8D3c44a6Be9A8F86' } + { address: '0x4Cf96b676a347E8647eEb6AAeA99F40cA76ed342', tags: ['stablecoin'] }, + { address: '0xBfF0113396fed91700A088F993b96B5473EB1497', tags: ['stablecoin'] }, + { address: '0xe661730EC120D78961542bc77f197792b01E7AFC', tags: ['stablecoin'] }, + { address: '0x5323ad247241A38e7169D694C58c8d84DE4b43B2', tags: ['stablecoin'] }, + { address: '0xbe2ca778890B9297d3Db17ae86f548B0E298224e', tags: ['stablecoin'] }, + { address: '0x7887F1e815847d896D52fFB10dEdf6eB09e967E9' }, + { address: '0xcC6b662bdf918583d2a5EcF4db1787C438e699dC' } ] } ] From d8acd66eb3a653b03a4a430d477dee8cdc1cd1fa Mon Sep 17 00:00:00 2001 From: Ncookiez Date: Thu, 21 Mar 2024 16:02:01 -0400 Subject: [PATCH 077/161] added error when yield fee != 0 and there is no recipient address --- .../src/components/forms/OwnerAndFeesForm.tsx | 15 +++++++++++++-- .../src/components/forms/YieldSourceInput.tsx | 2 +- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/apps/vault-factory/src/components/forms/OwnerAndFeesForm.tsx b/apps/vault-factory/src/components/forms/OwnerAndFeesForm.tsx index 49617909..9f3d01f5 100644 --- a/apps/vault-factory/src/components/forms/OwnerAndFeesForm.tsx +++ b/apps/vault-factory/src/components/forms/OwnerAndFeesForm.tsx @@ -37,6 +37,8 @@ export const OwnerAndFeesForm = (props: OwnerAndFeesFormProps) => { const [vaultFeeRecipient, setVaultFeeRecipient] = useAtom(vaultFeeRecipientAddressAtom) const isUsingCustomYieldSource = useAtomValue(isUsingCustomYieldSourceAtom) + const formVaultFee = formMethods.watch('vaultFee') + const { step, setStep, nextStep } = useVaultCreationSteps() useEffect(() => { @@ -51,6 +53,10 @@ export const OwnerAndFeesForm = (props: OwnerAndFeesFormProps) => { }) }, []) + useEffect(() => { + formMethods.trigger('vaultFeeRecipient') + }, [formVaultFee]) + const onSubmit = (data: OwnerAndFeesFormValues) => { setVaultOwner(data.vaultOwner.trim() as Address) setVaultFeePercentage(parseFloat(data.vaultFee) * 1e7) @@ -93,10 +99,15 @@ export const OwnerAndFeesForm = (props: OwnerAndFeesFormProps) => { isAddress(v?.trim()) || 'Enter a valid wallet address.' + isValidAddress: (v: string) => isAddress(v?.trim()) || 'Enter a valid wallet address.', + isNotZeroAddress: (v: string) => + !formVaultFee || + parseFloat(formVaultFee) === 0 || + v !== zeroAddress || + 'Enter a wallet address to receive yield fees.' }} defaultValue={zeroAddress} - label='Fee Recipient' + label='Yield Fee Recipient' needsOverride={true} className='w-full max-w-md' /> diff --git a/apps/vault-factory/src/components/forms/YieldSourceInput.tsx b/apps/vault-factory/src/components/forms/YieldSourceInput.tsx index ba5ae2c4..6f51838d 100644 --- a/apps/vault-factory/src/components/forms/YieldSourceInput.tsx +++ b/apps/vault-factory/src/components/forms/YieldSourceInput.tsx @@ -58,7 +58,7 @@ const YieldSourceCard = (props: YieldSourceCardProps) => { className='gap-3' > {yieldSource.name} - + {yieldSource.href} {yieldSource.description} From b4fd79299cfe23bce16efac2e5d6b2f63757d449 Mon Sep 17 00:00:00 2001 From: Ncookiez Date: Mon, 25 Mar 2024 14:48:02 -0400 Subject: [PATCH 078/161] ensured same block number for conversion math checks' queries --- .../src/hooks/useIsValidYieldSourceConversionMath.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/apps/vault-factory/src/hooks/useIsValidYieldSourceConversionMath.ts b/apps/vault-factory/src/hooks/useIsValidYieldSourceConversionMath.ts index 377e2d47..1dc33aac 100644 --- a/apps/vault-factory/src/hooks/useIsValidYieldSourceConversionMath.ts +++ b/apps/vault-factory/src/hooks/useIsValidYieldSourceConversionMath.ts @@ -19,6 +19,8 @@ export const useIsValidYieldSourceConversionMath = (chainId: number, address: Ad if (!!publicClient) { const valuesToCheck = Array.from(Array(19).keys()).map((i) => 10n ** BigInt(i)) + const blockNumber = await publicClient.getBlockNumber() + const initialMulticallResults = await publicClient.multicall({ contracts: [ ...valuesToCheck.map((v) => ({ @@ -33,7 +35,8 @@ export const useIsValidYieldSourceConversionMath = (chainId: number, address: Ad functionName: 'previewRedeem', args: [v] })) - ] + ], + blockNumber }) const withdrawResults = initialMulticallResults @@ -57,7 +60,8 @@ export const useIsValidYieldSourceConversionMath = (chainId: number, address: Ad functionName: 'previewWithdraw', args: [v] })) - ] + ], + blockNumber }) const foundInconsistency = valuesToCheck.find((v, i) => { From 9de4d39d481a17e6262e01290dc1a66cb3f3fdc8 Mon Sep 17 00:00:00 2001 From: Ncookiez Date: Mon, 25 Mar 2024 14:50:34 -0400 Subject: [PATCH 079/161] added migration meta images --- .../public/facebook-share-image-1200-630.png | Bin 0 -> 45625 bytes .../public/twitter-share-image-1200-675.png | Bin 0 -> 45900 bytes apps/migrations/src/pages/_document.tsx | 11 ++++++----- 3 files changed, 6 insertions(+), 5 deletions(-) create mode 100644 apps/migrations/public/facebook-share-image-1200-630.png create mode 100644 apps/migrations/public/twitter-share-image-1200-675.png diff --git a/apps/migrations/public/facebook-share-image-1200-630.png b/apps/migrations/public/facebook-share-image-1200-630.png new file mode 100644 index 0000000000000000000000000000000000000000..49eb9203972dd77fb8e651bbc184f9572afa2b20 GIT binary patch literal 45625 zcmeFZhc}#E^e8-t1R*3!ifAcBmuNwhkdP217`=;Lqqi{-M`>l>#p@ZYvHN;?6dbiyB`r6YDzRzH>e;G2+i|nPc$Krb7c?+ zsTak0a7SIv-w6DnbbY4p4uM>xC;pH?l2fmNn!J8}K;+)N6)yEJ>dGy6& zb8_%^@cEO++CC)fvlml8d#5eq*@nfB+F2T&zp#~Om%9~mO(gMUY?3NNYTE6|V$0O$ z6%B(QHXPEf+w}U3`#N=|V(NNs=ScaP#8z5+#Pz>;uzJ4de&#EYsvGY}DCx-Vkc^~# z86IFc3e1ui!W9J~kO*W05|L4`T7(#qLMdOJ^=y5VxV4KvJ&B9jX!iI95Clh1OtRyD zXL9c@n~|KIvX4=K*%A*r`*V8#ol%IA^8I%fa)X5Fzccxdkc5dAK*#?3Y8dbTu=z_#qe8fSuP z&C(!r!35_&XgRv?>@MJMI%+_6CII)mw9W2LG%WgxYftUYa7=HczTKWwclHXtHyd5W zD(##i?(}-oAM*txH5n-2CvAN2^MvVte|b*tJ_ALXqbxJQd-njgBtC1s4(p7hspjii zc)vfgi<)>+&FbXNHoBP>KD&E18pOPVuKn7;P}4QsR)S^EtlYOD^N@jQrAkQuguSJx8|jJa+t95#J|fahO(po zfo%_>D!vxMsAiJM@Od(Lx1=1NG*Fy=-91D4x#0Bc?2b#UKGK`sH#ENt2+2eJ2pipS zWdq9m`41URQ!hmSTPGAWq{ZeD9T%hrhSsYy_f=UbOArnPoX!1nFr~N?nfqfmqA^Om z;~%~)>WJF?&dL1g97pf^Q8e}P83ydS6lGy|FR|^}7S3v5f)1aO#1=T)hT*l|{O~zg zSDw?58Ko+o*jCO$!x45>vM58x)8(qXgExrt?_sG@HLbS)&Ert#fpnR+>KHo7BzTXu z1?S{{w4C^~blJ#etL1jh&(%Y2lvHhC*x^&C8Q1iJi+VJNm*SKC0l&NlR|JYkRia_e z3OhX-T85064hP)er|HA5V~68ctyw{43&__P0&IZ>gI4SoHS^nwAf<&g|V+QPRcqy0(2+$w}#OnXBsRc2~g| zI21j61&h1&W=4TFz@fj7H>3e&SK=>IGv&~oyYn*9DOJ-6&v(Tv?NQ+Pf79D3xf4cr zvYxaT-ae2qYN=A%WL7)tdTV2?kcvnDwD^?;S#G3?mXoc4H7s9%S?|wzQx!kmJXl(Z zq1V$PT})JnHKIm&%&nZ)uZ8oetiT!2AS0d#s$whN8w+7SKQ4M>@iln&S$}K=S76iE zsEix3o%&_AEoqKYE-9_YFb4_08J5yQbN{V|6CV6F7uLmn?RF(K=RpJF8X}U~A=S?A zrR)CSTyIPZ%@fjvo)yGfV~Rw zxrQ+aM9y5|pKxVSwe>|8A)sQj@2^bEsU#Mkt73JkRAtV%2IbzLr%kPio;$4YZ>jMc zUPUZ0*Z7l+|Bchy$WkhGhj(i}%q`=2ZQZKpjrDKzAF=%BI4YjqdODFbG`UhChHtC- ztpJ(*ideR;U5?j&cpAmxRmc%S=;)xp3czQ*#vR{Z;@z|TW9G=lyWgjL)2&cOuQ@TS zc;i>ECmN&DajSWo1_BAmXh$xf6bDT`$vA-E-(%G}SyvZxuDT**sZ&zY;+bT~lE?mS zcjuG++8=>RZ+;d&2Llx)a!Al$F;}fYlz3%16xcxG-M#^Ry+c3-fLZ zn%Wp@@N2-UkbSi~eY(W*d%dlK7tL1VdSt!ViDLnN>wVn$G&4jOr|N@73$wq4>H1cK z@S|De;67XjkJ?iJI!P>}f5VcYD6XK`nEJtHS;3Uv!-dHj^w1PCFde0&S|H&2u(d z4Yz8&e-EdK4N=A)Y)Sk&@n7nasA+PkX4WX;Xf!&Ak~qi6$tLw1w`3>9WcLYpubj zoP9y(7EO^>%>Hngi&8j)ec?}s5>Ky=3gOp@u#Jxme|%{eoA52uISM->HwC?(S*&4= zR>JgH(@eK9E_KW5H5rvGL+kHPN}TUq5%7G$THk^ZG47zj%+&L2{2+@T=7{2^% zM^5y4riz`78q27c&eB0B{2gXxv$0-efS)-vvi7GPa`QKZEzw?@zJSFiNPW-{d7p_W zZOSZY@XF2dKa6;ji@Tqts(*OXEWYcU9;L#GhiSUQQK@%FDVwT)yPCR$v!{aa zdP1pZjjLHwvxuke@0|-K(St!05J;q9!+gBW)~NNCiHlhEAkZ#UYTtCs?4FrA3geD^ zwbp4*r}>?I?%J=P42z>Gdsf~oltC&x!356DuzyHNs7W>1=E}>03dWc!^%QHf)n9J0IrCs2K&x?K9{+^RW zX*z2~gr9eZjE{y*dpPcy0x8?^PEVS~s(`=iXwOU%Brc-46j25=itTr~=WpUp0xO*E z3@1y^obq`6`?{GZwS0={XtZWI680Qa}cgiEKwJS0U-W+hCQs$5dd2&i2R zy<-a0BbOFOuWU4tfr`)1>wQC{i1=d@Sx>a99yhk%g6hsTrx3n|%LI`{23WyzHh zA9ngnOT11Arzahz6C+5$=!?xv2ZHYK7UTzvcA8JW)_H=P~1#KktBhq>ldr3jrxq$6}%nyPv!jp5{O*gxyvRI$@Ogi#4B;d z;$S5W^L~RkY#56h_H9##;KX6<2I$X`h_sfIe>Us>z-essW{otQm-sO&5c!-Wd^$HYORxt087YW22%mA78NRk;^uICCY&WgfS@|j$3&u=kbfe z7aWP6>-LY@891_4+ro!IWgd-nKIZBh<2QD2db%~RS^Rbg?dT4#{fRj5?eo)zAq-~T zQL995?Xao0_-OohxH_YW^xoH6MS_XK?V@&42z%4pODK!k?Z=g8hJn3Gxq_7U6HlT? zWFAkRIu;Mb_kCnz5e-m>YD7EDG2t4cO>3rf(8kWX>S>mqR`KKaCv24b)F!>vZk!N$Xc9hEX8Abu03BiLN5`?Q>vMx9cXpxPq(@D@MR} zI_0~QozglL+dSh-syX2loMKN;jTT&_NX8pyAu99ne+o_r2AFSu7DWQeoNeQBO^Sivsx=A6zouep9-^OeMEN$ue0%|jp%b|W_yljknsljWw@!OFFb z_aN7?@DYWpMN9uvYOT@57FME8EORvxjg^=U@x=kPKgL6q&V!oEReUQO@U@LuuO|2_ zzYK??Tg{awMUkjT&8HZf6tU@M+)31I%Zc=J7v7p!XZn?v~T~F7X zZ{zgr#n_nr(wc0dpr;MfoZd9`rzh>EfqnM&1qM8;j0p(eM-a%isZ2ZXP>Nv6fYYmc z91sXaK`c#KY^ZLEZ0$6`7ud1`^&umh4X*REtxx4M6>$L;cgOr~jNF}hGF z583Yb5^wW(*L=|_{MQdC$R(&TR81&We5X)GzEm|mPfzIBGT}KvKz&`-h6z3 zdtbJ#&)xEmGxYw-XtnFjq25iX4jJ!P4trS7t2Pt-#%!)bY^k+QQL_DJT!AAW72;^E zZ*~`U5m{_mcN*W0!Uk-z=p6dxo}xdOa-{r?bN^u;%IdzE4 zP~98tz0{!~;UefbAHQ6^JmCB<6QnXi6u+I*8<@sfF`9H;VtaA(I~SrZ_Ud5m)N-`6 zCCgQOHeAamZ@x@2>gY z5>+L_7or@yM%IB8HvocoIH$Zs}U(jwxYM}}nxH{a{RL>CIcn0~2#{iahh z43w1?{k}V6g;cyr1eDFMK$J2{Q2Lm=ofpUed;fgAQuOOGEHFg!S$BBKu5=X08o)(z zwv}s~CzJMS;DMW8{3AV8a0Z4y+;{8d<4KXVr;aVmCf`1nzSlX$as3Lr;AeqES)|l* zo!2?4O-9KcZP)yPQKLT$atn^Xh)6eeg$9c{>A3*e_6emkiNFlQ=4pTyit)bt@=di3 zChN~3(S>IV*fQKaEPx048u>tt4H+qe>aZXFgRUO7H>*E8Qpbu&5JBNIDO=zeK+A`_9Vhjye`sdZWC&Hcj~gR zmIcQ3p%{j;rS$L*a}oxC3`?5yAkRV?D^TOc<^WE%h%`3W4Q zT;93Li}RWu>I!w5-75A%Ez{i9*2{;}O5hft)+@eSftxYFKK*1c@VQHc(hdcAvKW`U z_e07W-E+m!R_-H65ly<>tZ-m3y~tRHdIbG(+e7Gs72UbWlaukyY8`Qr(MuTd>8Q4h z&e?HEuI*S%!)>${Ri22{&*Q5{j@_;45hiMtq+*XooSiZXYj0zXUWvAD)?C~wsw|4* zoSvEg&OJ2M=&WV{tLEZ(H?nc};Oodn)581K2>fgt8LANma(zLkRQH>93aQp2*HS-r z6QiNtl-Q)u;oXBG#2;T#H;hnwbGVJZl5SG-k>YG&Ur(5>8^Luko~O)1liu66)H-F_ zfA!-WWbA^y5&TH1yS{2>Unsn+nUeZ27C%fN_@RBd~jZSs#;2(PX zbk}M2D1|?1Vm|l^v&o9z9A9Vz!`Lhq?SK}A0%1GW>Yb1Gf$B{jv?o6rGmjJW4*QV?J#G! z6=Im!MNo~`-sM#itFS<=qOua$;|j}7SsPKp>yol%SRrtSYH1yjGgwj4jXSgBsO4E>bHs-K*vvFxJf)eR!V%Pa<8_>7K>7Pcnf z0W0NyTG7RXHB7+0%?E-e*H+>e2TpVeBhU8Z5mg?|C<%`7+UQm@LwcSXhIcTZIVvu* z2Y8fHO?|7@5TcW(cw&<2DG7$4>Yzk(QM+(|zem;*>wm0|`~71BFe!pJA4D2F#a8dr zYm%HVDv}m2z*usebrq=469hw-)}JSa@j6&P|5~Z0VLa~d z7pjuEQ0V4%+eFyJ{^&UN=lxx z1`x(;9emrdW$IYuWoi%>w6A%ZTt@~Gdfj!+B*M=;P39kB!1PPXHqUi(8xx;#iTz;b zFL@dufzQwyYyYcMMninAqQ3^vYBMCutNeiV24$56GBFTX5?EbeS79G-v1Z|Kauupd zCfy;gw?)YHXSipAyrMQ+hI)3Ra6g%&#wqT2=X>$b81=t(9?U8iw`-btPP!S5;#1?)BDmtdwf(G>nMOX^#tEM{(d}&H z;s}|Mp`{JMsD|UcBKs3o$|?p8Pm^_bg@PxDAz$kTd(wzo>Bc9u^A0?GI7FGt#Ap9(&5IHRfqeO5L5upm zcX-$9c#lR5?sbAFyJGilerA_;vVYKJYH~{URxc?e^I5!65F>95{BwKpD-srOV-7Zb!kJ zAHqOZ$LF(05F@e?$>nDv%-|>DU|zgcwdEatnG@Nrc`YxAs`X$=a0cGkjIuZ~-8a&8 z(rOTBkSEG+u|Qq$W+$5%@fOTFG`A!t|@T_WYqIpiHTzx@jHe~>GY@hs*Z48? z0b8l*_2w7ZZOPoP=i_s4$QS-puAQf0d|}o7+s)yNrWG_U{|VgNxezNsQ&*t($vhT6 zGm6Ka3gBmD1K1veTp_)NJ@DHwJu(*Je24j=lU18sB@L*_lJ4vuz>x}#hB)Z0m4AUa zY(5J@PeNr@D-i7?{cnoGPVIE$pEFs2oEozH*KI|v=R-)m@ywiC|Uscm8xJQy; zt2civtm;*IK<^AE=F#dv3cmX0b;_~?qwAFZW2dWV@z}&P_}~4EiCPqakgGs>SO1+S zI-}K@Y*&#KI0VRy3~6gq$HSGvthZD}&WJBg7~OtX-qKv$NKCcSx*M`&Dz$H|z^3~* z71s>HLrp7f?S;2GRi)QnS{012oSmrk6a;yOGZ|DBU`_ZbOEkp_iMg}&eHc`l$qL=; z1`_Fd*-XM9x~5+EvY)e_UpL{-KkJZH2VA`4Y3q*y%tmwwtzv6)qP}pL~{C0l&)TK2lU6%~UobZ&iSQ=#{v9vGJ zFE}aGrbksiCdjLwH_pHn6Z>jD{w)$zCM;^91JyNICU{e0{sXw_Lq{n;^(cCiF0Dm$ z%gOG6tfWch7VgQB9e3}My6DFr_5wd%gr&%wh5!K_qd+M(9i@2c*ox$C?~LLMx*#sM zfM|qK@%0F|`f&T5z_uhWOP}saqZdpt7t>_|Cs#iwzO=;Q2J5~P!=O(|l;P5^f8CXu zapx?3*(jd}<~vi8Y~MKHAiL_sEMC^|H^FMWu8`x%1^T)Aj&^*+TfQ`g$f7GM9OH4b zE_DiYPdO5J%0;w50QxR*Xd8iQ?K5#AkpdYKI1fguTD}~@%?Oy?RoIyZv!=3X0P7Of`C>0 z;cC-F#*Wvm$78vlh3S=z_45oPL|ZMASyp63R}aP(lsm{p9e(b@Y<`{OPZNY`o_aXn z7TYs$U)~?&J{%hswnk5_8YWDx8Yb$iI>oa*8ooj>T+VyE94P4+wcEsCy?=?;#t5Y3 z4Sg3ZfFpYOkODO|)Z~1+Gpg$B0n;Ra}7$NTdND=E?8dO;dz5wh654{<0m^_-+nInC$T+cCuCa^d0#C zv!Y(_>JWiZnn-TQUE??V6CKmP5GdB;h2F4Vqq40tMDOk{`s&pZ_i%`bp`pvP8XN1b z7%mOgm+Wu2k-y428;R8B;Y_TDLLF=bD@(Iv)^4t==+C3!E58a`xj#>p{bePVMREjA zCzhO?ttQh!fwWIlAo39d5Xm3Y1G=J2GPn)}B5~s5_i5 zp+_|^>SF}_Q1PloWtn5pTE=xD`6Q1bECQcVyNM7L6Om{>xD0|q97rMC&$SG-;Qmzt z;&!n$S*S2Qxlw$I#+FnJZuV|J4t-(YF0jj6ps&y+f+-m*?aQhG70l%9MiY{y_PvMkV52t8L8j%=j?ChkC!=@1< z4i}HS+K7RYPaRgK0ad1pJ6@KehCqG`HjTtQmbKHHUvY0OUsQX?n0r_EkyEJSPM%td zX`9#+<9KbVYz7hTPUXdkH{*3-8_D__ z<~qMTK^CkOBuME5+2-Rh#nKeORF!q2F@$vT#|jkq3v0#M#T``oz=0I2+`TL%y&()- z>h^*=WW}8^%WbkZR_^~D;D4XJjBb+F-_E5&mKL|4EbV7>51jwf|M%n)o|$W16JAV< zF?GRUjIG}zm+Rnb*VZf9(gM2zy*BlXED!Yhboo5+x_MHf2gMEpE(j3E+Ne7u zUl4iD{-->K?maw)Wrb}I%KexBup0ZPOT7pphkSjw!)U_dvtQu6u+P4K;5|v3ayoeO zGZ=39*w(4BE z&WcK9>As8?2-WGqOKOJc;>1g;@iO&d3){*xE0(-{kLHAcX^$~#Y3DsWe6Ox2V5`$1 z!_`aGzH;$>iQWs=)w23!wg-S)0(sZX&_nMohL7P^w=!-RYo4YZ5DrRey`y~%smfcL zk8v9di6vsP_iU${?A{ae2zO|5y4_q)pZyfGbgPG|-thJJmi6w1K)%`@QlqBSTUmYf zp~YmVlg_t4_uF`wpalO}dXN-~j=d>gIEm9P`Fv@=H1;nkPwh+my468_j^Rf2rk2=C zzYnxd|7xV`RxE!^o=5wbw5l)uJW2R-*j;f$N_@nxqrQhNTOwH@ikI^nq}t)>_tCA?`ib7cxj@3}7ZB^WMAU>S%P2GDm`Z5ix+A z0lH*Q+<2*#buyu%zA?E1)nZiy!?C4TZw`JkhY_RAjjn3kHXk0H^~@}<%zihqbt{aR zQ0p2Es|fupQ`}lQVqI*(tU~55RGC0~5r26|f)Ii>j2rBxzJq2I4wN@Xq*?&#;mN zl+hnCONGsC-+bz+il$y_G``BcF^XyvN|mym^BE*@AHzNW(NnOX)Kvv?H#^@n)a46j>zTEA2-Z@E{_saWQ)} zVLshug8TfZCBItRlmwzI4IfrMn*$pX{ElP??zK99%slEsSEC$$i~`Pqn4Yu7RC8sb8n$=0U7i+4CX;+wxC z1!n2dT;Aenb{mv0)KK!syU2f4)KBsbZLrL1{fRJ80vl}52vJLmFu1k!_`(E}x$xOND z6qY`sIbP|DQ+o|RH!E`*|J877heD@!tAMX`%mXsWUjNeM5uGMFn_J=G^wu{lpe6`6 zb=Lj5sj9yju?Hwkdfe(%ua#6oU-8O&q|;WGzH>}ohUzKoRks548Nc2boi~i2#%OZm zV0kubeNEN{e|`|8q?YmON-6d4!-N|!r@yD_vOWUQMV9H9s1Cgjg39`5kw5=9^Zuo( zY2_IjNgN>&mD@$(P@ZZno>W(dB;XaC)^$)a8Z@^q0rZ(L+<|MMH{P?&0nk z_H(Q%S#g2OnUg1I?{9gkH#2r&mVva&zkI-`mwYHVzVDeB-Oyie7ktp0 zBz-WS$m-2p%@w9=qIIBG>rwI%q~|Pg8(yl|-tCs)3kH1G$+bZ6GI@oV5dJdAQ5!$?rjwRnJH)^nMQ)SAvxGDdq zXfuzvVgh)QK*P~|@Y)jJM=_Vgt5S1rq{!LLp;u$KS8Jq7YelzA7sK=nGo}~`)9YtsjeA9^S6~hPI>R8yW&kE z!Y<9}h+>?6Z_?a$473&$zC;R%G~p0&L?H^x$#+qe;|r}dnMFACuOPBYVHTjt(fcw^ zHuyaZ) z3a50+3z5^19HKFRZ{1xMd6l*dbfD43Uat^t>bh2H96aT2sL1qBf0w!*gNzf0i&J== zSh`ah-J6m>JjJkZbOyr2U|Aw%%{Cp%RKL_xGd7pk8wl4=Co*;xaOwo z-jLT5XGr4S-q=Y1D{IDQO;aU&lXp~(`?X$fJ7Qw`y%RedUOd!=Uumik)G1$lkw*wS z5xi<(UkSe5hm)c=O{^@f73%5j<0tu+Z3u6bmu*6!+N$6Gh*5Dj#qutj+VCbEM*&;R z#l!$LZFc|WVmKUGeIX&77(g6zA3=D_l~;V=;nS(opAaP?Qkmi}T=@{+{rgE!N8vT&3xbn}QS?k9 zvd2HMdZiv7rq-Tl7sLC>Q>VOAHW{ESALIX&&8+L7MVT`$Q0vFq!$h>Fh08RH*aSVi z9-lHUX+HAeqI^$8RGryi&iDJ$VuB%OZ2>(=*Sze!I)Se+4uL!iZ|4bBR>FB(85_s* z3yw+d^{Lg~Sc}X<*VsPYFBC#*bnw0u zoHqpp!5B7x%Ep|p?bz1HbKCo`q?DI8@UQld0HgC&E+e0a-4uH$lZ^KbJAkKv}}6lO7fOx)qe_Zzsq?l;`z zpoYTmfV=Z(t`+v9R+%qU7m32-5>!~EcbyKZNa4bo8f?XpZ*)sq10sOpn&AN~tTBy8 zl#EMep{v!(ek+l=hw1@Odhz^Yex+!ot=m@>cC{xLMdL6qG3o8B`^e_;lGaJe+Js33 z(9U<>nW_fiz)J%OdO{U(iBQoYz1T3tL!Y)RFm^IpRUCsJGWipx zce=f2s(!Cia|j7PZIN}yJ1iQ&FN?cfg_;xFfn)rMy~hl5{90^v(q#v=b#GM5_X9@U zwSwa97}3OF1@l&)f&@}db+_(@O8Ghcoe`vLbw=~QCyI}CtgJpZ@w~HE*JtXfT{m2iY$r=Mn0*o_S7*nHWYb0&Ra5M=rD~c zLAiLq`9gJQDw(EY$;FAma9Zup@9rJ3N~xpbC3>FFl5%?C6E+Zg)=V3F=# zu$h_n>B_CF?C|qza59+nK$e!)$RDV2eI9wP{n4|t|}U_e(Ad;b}!9<2I4^@*1u_OAtPpG~iq&ctf)V!42E z!>cb}xZ{Cu_fv}4j2_v$$(E60?w`P5ktPHCE_8p9*e3Bm&pNYAy&AY)p-`t&mp0t#Nlf#vAVhIcg?_4=m-)f4d?QiG;}BJ#f| zA~Q&9TMr+pPQ%1RL|)kpr2#pEgpd(okr$WbMYrgZyp%026)>58p;`iJk`V0K^uKzY z1o33C8~>^Ms?kn;KZFicsNbAHt8P6cRk%QwpB1t!IDAvqnAoVse(#L_?Bu%Pfs^JG zCh9KH`}_OXyL+}Dg8+qrIAf~elMG{58@4CT9v((QAEE&)$hpunh&ijs9DDiHM>&Iy2E z=fchqdhG$Pc53Y{&d7^!JBjVp?XcKO^>Mn)j%?6yRDhZq@NeEj?x z%_R*+uDw=Luu$ZPX!fSraowZLIU(U$cy)4xNVl6rJUEodaIOtLe{X%9VG(8qc?Wja zGa!2Ktr+)PcPNqXgM)Rx+uNi-(ZpVwpTv1l+#is8x4p{yS4L07Ywbdl#8ECmfF^#4`jh?K;Ce8?F!4LUGi1E@h{~|4V(RU| zfkPPIXI1V2)uKZc;tUGTkSym-(5WwAXE{#N-=ZcP(bRbiTpXaUi2{-t!rdf!f*`R2 z?GkiA`1LYGx3?QA4qR8c!83V(OM!}^Nvgkape|=g`FEfIS<;EkyUrJp?G!$hDk}(Mf?4 zdPxkLf`r%sRWhGlHff{%zpg3%&vn_^bD%uh1kaxTcm3}FTnnAy_zYaDZy6BF$ysL% zxD1-TGPHg3sQ7>a`tO^s0H!)s=^q%7;`aZfThWKS)%Z348KMDah-!rBZl}CO@}htz z5Hx%S8*R}_AN5>>@5!BE*iNv?BK2M zJl7>b<7hi^i3gF&`GjWj8FdX46+z&cz}=i@eER@?zY=)HLG5P}`wk3t57E#N*#d}{ zDM!@PbeaHq?2*ZR51@G%sECVJ{@pg!V}k(tc}Ae{`OZL515ml_(T5_DS&4T z5Mut^E#hl(XRnm=Q@z6b}hS z@F{nbfln}TP#WS4+=>z7L0{=ifCN}*TLVHCl-{^>)dcGhgkr+J@>=u+HbBGU3>h+c zzJIDT(<{CJl}JV+Jl||OWK;V(dYPuzKtFFX5^f{r-a-V;PXxX5CvvSHvD$x0EQRKP zIp#9VO9!+QpQ+7z_9Cw@K-hBIK$0WpNI z633wGM-HVlA37*p&Rzu*VwX6(Nr%?!3P*sY392uExA)BUx_JV$jR9t7mM4g`fQOG< zzsFRV;R|mn*mMBx7Xl(HbOtdpgcLlZ=B1XUxoYI2@S6(^)vXi+#QPIRFO}eat!4)A zTO#QGGlwF#$vpI&{-II^@m9py;(5p2(8pu$6bKy5VkW|7TO>8mrw(eYRmzO?m#kw%+79S53+i<7wg`B!&Fg_ z^=20(mNNa!6_D#c%c`6j#*prm!^5jZg=8?`Zpv;Y%4!*L-g4Rn^k&Tj`&?6|<_bkE zTTx3H)k#1Ex3k@Eck(#GxC|*On}+R|0*IAd$nT3pNxPOvBmh+vgCnCbRA<1^RW0%U zBftuFzB8DLmqb&Vjh}qPGHRd)BKIm0X;0&cBVLOq+KuyrRr+n3dZN|ij*7wbIs^Ap z7LSV&K(RnV&dgBnb@FGyFs6s0ng|3B>fJdgwE7dAUI!q>z)56XjPP!$h+z%qh?YYc z*72*vzDKh0IvZt8x5G8rF3P;`;do8xr3>KWk)qT2}#@2sfaA(b?-hgL0k{7FTZm`FXbaX#n?Q5&&q z#4oaV?Mu~6SyjTVc9++yBjZ@O1(8BX5chaOOUpOE<1X6*dVD1+UI^(+UD!;i@xNUD z`d@a)duz|uBoW_7iW+JsX;8p3MhpveOr;mh zj@D19*FFBf-Wgc8LrtmCD~pF7cW$bX?-NFz_(vQ0jvL6d}EZYqMaN0 z?eDYrW4OIf9qRznz@Sb9$s;;#AY5-p;!2KNM>aj<`Du7l;rZWI{Q_;l^Ls4BS(?c+ zjfpqTLj?v_|FP-Z-$sB5Wr`4`Ij9)4Q>LKsh{a@{a!^u=$AjE5r0dKfe6<1NWuq!y zM*ED>J8Xu|=mdh#*k#YePKT*=!7fEss+9(f^iQ!{y#$aY{qM<~=YTjrwY68+!fODE z{oxszEfFo>F~e<75MQ%F>IafpN3_8~9{?G{nK(VA=lvdmcek$+sn+}Ksjt$Uzv*4X zCO(OXsLy}z_Gd7*%=^WKOI}k1+Cii9Kk*m1sJ|ayVDS?QgiY@CEux5BFDkjDw0rO* zKA1Q(q$`q0qF1?~T+(hklBf26zle0M6iR+T^d})2#hfhD{wuLyMB>5ml$^*UaQr{L zITdIDb_cHMp~*G^|G3|Jou}u4LEjItHLt*QN7P2VXD| z&vmn#p=kx>f@IUGEW2^rpp2$rWht)5aI9f8tGD{V^lfHUVh@rIwn8K(O&-$KGvsNX zZxD5p_LYA1G-c=x=tRpSq~7XtK4mTN@}VpXI(|4AIEUG)yi`GNMnX?CFWiLu?*KV*W*>7coVzR z+~fU9Bw`TslOOE&oVEiGCyb8to&=)qXq~I|r8a0j=Fpi)874bycdeRv=#$xXEO*MA zxmWm>9-;}1w}vKz32{foY}S)5Ws>o6{zhuKM_wP?7Jdf8-^!CJWmXkRwp^nXAl;@V zVG4@9yyCn6>Seett7yKB4a>ExEZg;Ki(z3Whkp$!smYWtVtpYCM5tFH%ZW;Dt$?9j zlAVQGsgGaQ>j@$K2c29U=y~Xcm=XP1<@O~(7w-Dii=kdv{||wBL1mVo4e41<3L+(- zZY1|uk_N9_%-jQfzvs6~2}Lw(k6nBp8}M~~k+7%rJugDQ`_fJz$=y)%ImieI2Qmxm zq0jEh@M1x^Lpbv@_lvA#uG*^gv|hTUV8QBZK_icCY1oOnIx_jlBwli$X`+enluQ|9 zvZ&em!)J%AP8)`Qf&T0XDLrJh=uh^wtzb~gu`dmIPS zkkt2{0%|F(m9NX+gSs&O(#Qtge^ax#WEbKd3hohnYY(NYVd{{2pQ~UM4fEFX2DPWJ zhy7V=bZ9>gE^mN3k$7vr(-&t5XB5QYEtRKL!`I0+la`7fK^A!*vz9jSd{=Kt@z)mY zrzIQ8-rjVZqf?@JP30D@DizxRwh`YGHMlgadso(EE^+pfUFlmGD4TtMAm;C%nyG)m zFqZtfF*S*Ry}9FlChU>C7CSLiV#qVnHnqB9l$R}swCgyU|GLp7C;rQ08niQhA<4@f z^Z&UR_tt&CP1Dn!^NUY*)gQuve=Z4CcrAepvI1f{4G*{S`yODMIdQA;?)$fVq2@>z zeQU5nF878tMcLa_3R5y5z{;{LcsMlH$1@sZ+R?3XTqQGgyjXDUmtp(f^-Nvvpciyz zS+DFGOa^?iSud`t2yLot?&5#mPW+vlKj$BK z-sSO+%f95!Q=ib@XuR_(zMxFK`HnV80gmG;_W5irrt$@r3nlpeP9SRU-`;F8(CEg_ z{m6`$t{rqUfpv?8>JY@o42|Hu{~2>y?gjlJhi>_)jQ2hVC~;DmbH`4T+UoBolEpH zp2^DXSSw&(k#@s;>WP|;n78uy<@ekoadfWXdC8L-X*m9jHBRZd%u5p-?S_fb``5V- zU~fI{w&=_~81_%2@@y@;cG)Z|*S14}z&NrJ@#~~n+RcQSry<=o=M|`hh9fv?a7|5V zCmsS@&N1DOWTSOnO%?ud?}tA8S?i=O?eduNLDP=yZ7q&*o0OKzv%}kcZDjn{FX&CD z4(aG7%0^o@ee{Eg*E&zeS6ooLqw%^W|@N8{|kHp$IFWl83VIULVH z#hhEm8q8~fzt3r(UxnY%!uz|3yODSDRxQq`IU}Nvtr_dr0yb8Q*gVcLaZhW29rasF zo%=Dg)Owid`GyUZC3RCMxO<8Iy38MpRr-orXuuCB+90{x5Mqju)=ZMpiQ|w^SIb z^?dIU%cw0`#kd(vb4~IU?4NwtpZjM#fTFB=D^nOZ(D29+f3ALJY0t7%qpulk?6b(u zy?N`a{PXQy+os00<_nAE8*iw-VLQwZUZzNw5~N*aJ?+ z;cpi!+qau{J$r?LW;V#>UhGgu$ir+moYjS{&yxdL`{X zK#&`$s0_j8n#bgNk4yUKW!Z>+f;7dA-!-lRH4=nJ6M0t2Ez9N;f_#kU^zQj7@3gM* zX&;-I`!RDG6fXNIiS&LemeAcm%jr~5h;3g{HfbPybjhaJcXp8La!$+f#J|4$aSr7J(_q4hWfE1h%aHN_JF-vKj1ZqY`^*CCpSWIlO1 zCkW5)z&~$X7Wa48ohXi^jYK91wi0>vwL<^2rZqNjD^rZ>4grs&x-0#^ZssL*0xy|{EPZK<+TlxcW0>G$un&2q#0Tgh{o{HAOvENMwLeC%zeQ>?|P4M=_X zBoP@~BYzfoVWnRsf0?@PIC8J=Yk6*rRSB+zat4ao;oh^xVc)1tDBRlmTmI>)TA+52 zy@E{I5cY{RyY?yX6R$DODXp^4Ps0WeYX_ilOAXI)MZxjr#+U48_x_0gGg^$pm~t04 z1-qK#sr_N?JCCQuvHy0Mf?EN0+D-Xchq>f+Y*LXXK8)RIj?rGq?b^4PpLj-u(JrNQ z53A?)Xl0iU9y=T53LC%9w;u_BQDyz=8L}UgFLHIu*j>&L3W+vl%v=f4qL-lfguHIi z@uGvgqbb;sV(0IXZ{?TJ|Ha;0wng>6Z@i#lAf<##hXT@)0@4!FHIy)Pmvo0niBck6 z(lEm?#Lx_bAfO=KHHb(I-2*ekUVMN5W50&|VDpsYU>0lcb+7BbuJinyx$M85M;2Ih ztK=ujJH+m;@f3yr!uqKdDX@FKyInN$gF#V|dva&+oL^Wh>=h=>!Js`4HyCE&ziM-t~&nRt>>`}ksGsp9{hSLT@yzO zQ#!3cQB?DBxR^Xj@Rb%JB5es*$@U6CuS31@T1GiAtT(%ydF}&6DE1!DYm@em=x`oA(JLPyac(YhEtSt2(3#_xU=|sWDYVpgj$-Tv znpTR>u8o^)rpipUq~3`4+IN>yd!czh*ZR0(smCLrwDNVy20V2Hjy*_bG;}}OaUE~u zfK2lqcVm5@fcp~(14>^+vR^i(=kRAqQ$&}AsO9?ca68yg>(2g}e(@73q{q zg0Hi(*Jj!pYs$Ev(7dcqD^n-jE z{z@)W1_Iai%dY4(H*}Zg-4*e+%bN3i5XFRFyx|Kdh~+U{CSy?}!0S!EGsE_vJ`3Xn zb}N)GW9D_T)FRGeTg~i&|6U1Azd^+=)h(TZfU8EcID0e0@6wYPwzrD7TJL>x(E=AsC&DmK=Zjhg7pWRVHl!2MknSTC^Sh z&1QQIg!wqY0YEC97jMT{oukW4WH8M%8*;ZT?Oz#LVitsTaA2910BC`Ky2n`u1waQg z(S|h(A>%_~mFMWY6Vb?o9DeiW;Z@Pk^b`6j*F>XSou1uzPQS-XW@2mScbyDluD&yA zsNU}~+SQ{-Rl$KPp44+auu{+rfggp8VyAZro~PXYCg;M8!MEWiZ9RqzyIh66#bV=K zqI|7E6XW9s31{v2vkW7$*QXXWZK6d*NS3R*c`XFTTWC zqVuVq%L90+@rHa#QwcScI%(TYq5**u_?#jKcY}7DaJB>g$oor=K$12Cr5FHaT_t>oO(X@ zwiXr)&UDj^2r8%lF2o1w}FthXYqbv;< z$Ltv0v9I{%nyTAf`F`z&7z3J(pc3g9*{HVeMz(E?K8HiVsy&+(FI`V|hFq9o>>eOe z6GS=m-d*}Tr7cBt_A!6i1$w(4&2?Nf!`pi?XT+?1l8-lT|~r?>x7g%R30WL4&+nc1;hu(@G(xG-bODm9s(?QekNR>z8PlLVnh4g`>G>taNhsFczSHY{xE0l4qME zw$pYbl+ur_m2|XP=9*L%^9UgD(R*+!48dCTP}ul+8l172(JyRwsnnwpe#Hl*7_0H`bjltDQJNz{8M*(*{gMir9KE@%(K!Q@77DhdvU=Kc85qS)c ziC>(L|KWQ$0rYK-P`_BBesZ~*|JnN5V!J?^oXh5ZX8^`0;X4oZmCu@v`(?A6oDYi6 z++u!uki~%4$^EK1^gxFD%~TcYc~L*S**X<&*%nw#HRfW|{l{cYQeuP{^<$|3XKEjm zU4p*ix|?}K1gYYU-?ew4BR(ecv{&`cYn5&_>$1fEYN&Hl)U`72u-QzY$xj=Dr1c+l ze0TLTbx*{3UzyR{?B(V!l{%o9vmZQ|9UMMBubl4hT_@2hEz*0P2-=Owe{V%0RGQ8T z6s{#MzAx)v6e1ReqI@LoL!_iNpU8|*e*k}&%gNQ2!CA&nb@jN5h+vpRl$t(ISwFwz zygJ^wLUN(>7Y$LRr;{OCh}xe+cD>6)UA)qyOrO>5^JfJ06Z_{X4sQ~Ao&wtvw}=1w zYw0?D3*)EjG8XNaK@0h>R*O$QA&iXHG%b?!L(XNU(9{*vkKyS+51?&oAvGW>mi>7D zzU1=dVbJvK>y!Hkt$%CZW#Qd&(m1#s%G^Ii3OMr|rhv5?T-kwHsG>cqWKIh>Nhs{; z^3(_o!^cDG_vJl5ff;P`j-?)Dhl^lxs&5g?W8%tdzKlU?VDj$S@y_!Z?YaeNqOMTT zgAL!{d(}PnqJ1KD5CxClGW@xuchlXtkZh>sJ@B$&^En>ChS{XZbUu|2_~IxuZ4GasF$YJl=#%`AX^>*UQ(1 z4C5G_Pv35#T>6LoTsT7?8&_gm>DD!L!AkmQ$R`}AM>=;eyXst~A_0X!+~Dg3QU5xf ze~>#LB%l5)Tlz2s-W}2rL1oqYlDo&QI9UtF7ASq~y`#LF9{AvN|4b!#_hRd2Nk#s} zpD8TYg2nX0n~KIt2j%B;x%6i6>A-1=NIKdxZH>pRlquWTi6PZ5@}-up1FKA8FW=P7 z)GlgF`7ra5=+FG?b&0h`M&q(IXLy{E)!f;eX?@j0^8c_~exWX?Qz^k`Oz~G7p5GJ} zAAxYU#f4Y|mBXV7g+|zFTS5;{=C{Jn0*(Z0m)D1Sip^Q_eAOrCGqVYx?BN8P`VR(U zsc3+sO_0S>X+9lomRw)rE~s8h!4$c=Dt8jyXH&*GieJfT<*{AB!Jd&gV zF4(nx=YTr?_F?_=MrBH+;<^-!{g9*%`H$dFxi$QiZF}5iANw66^`JvSaX6iV4Gr|t zRP|J_@MXS3(ps+s`6X~T*BOcMEtKpQ5qF{8vhP|^7IXK~vi#CdT*}<{H*-hyaUeY6 z)s3|^r9VJ-!_u;dAvyRcY4~9NLx#h+sIDqt^ zevC4RkwPZAD^THg9ZdcNa)V+CE5H=8ivrGozUFa^nz+`*JHHVr{>!j4((3aJ1lyy# zkhm0cmSlbW^rOjL0*-Vc68sCE=9aWKh1UWJMO(Kn@9c6@Q3}#RLZ^&>p4MEkmQ=I9 zbg60LBQB_qHfKy8E<%+KKln!a%J@w$+zT|8OQpQ@8N-uW??K7aB6LWf{l0wx|NFc{ z7nGBKC*C`VBj?-3Whwa&*GHI;IlzLkyNMMbnY+K)0)Ag$SLr4`*+Uq`x`HKKRAR#a zItvMZ30%_DDTVaJxB+b^Fl|#T87_Ucy|MA)R6#lRoKcAds4Q7K4wA)m6hT$K2}2;Cpk-rLsMs!t%9E3pP6>Uol{4P+{jyzsrKMHld#pSAN7x ziZou{{Q8T6nrDT_9`^nKreFc%zi$W->JQK!L z_ke|UJt;GjO;2wq3#PTris+0y8@Z!K{cOgGL}!?S24XS09o&1d1;cpwy`19}pc6$~ zTmDg|i~FekvfLJ-so!bEdcL(r_xe+UX@%vfxz6<(v<&<+TB`aS>_9nK8%(SS2A;f#|oSnaOTg-nAd?p17G=WOGIO}zVwRMMe&As1b2t|Q8lk7 zaHMAy;VD<0JqWienFZ*bA7qGKGu&Cm5|VuFm;(R21!OL%ozP$ql&2|c1FBE8bL~|j zs>=cSQ%9o>^MduA%dK|Cu%Q#A)qtQwDNBIhE+rr*ql#xPrF;bPacue=_}NA+5$4!s zCi-Bu<5{e%1VRttxSSFUrpUOyNMP%$2>|8`+%>{oORpy@<}iKIQ#g zm!szr{t=iMYU{hTT2Dj<)jciRa{xMhb<(vAj=DieTWA1Yx-(X|+LG!Xy#3Es+iGB$ zie%VUY-)l^Hx#AOb^QtZjvm~Ih034qZT!=W8Xa`a*mLD zDfzn|jYE{0ps{pfN?_XfFWJB-H0mLpXsEEaHS%!ebR==L^H({<`Pvx6I5Q~1@CG1b zxUn4gtTL=Mhz4I4(TK(ymhD^>4aIT6BhYd>Nl4BpjKD z=0}~}(>yhLzk>CQ1ea$3zA5I!`S7*yvj|c=faZG;=lh#!t_>gpCvnd{m;nl32wd>b znvz8U=-#atzx5@vA%QwXg;~7ZvTF4=XIBoBO(N5$?r^8Sx2-VTE>;kF;3P$z<`bPp z-G~fJg_(s>N>T87Cds8Zooc`j0sCfiYBKtJlubV-SiLR$NPo%zCpu@p`QXZq%~fjE zE4oujC>!i!$R`hImuZP4_s zWjqu2Im%lj!=owcwf*LgBsd+2H&lw;@GCcY8!VTVZ%BTjdP011YY9ZNI(X>5z5&o? zi8(tC+3`J}`ipxM21tFZ*ATie;_0^w3qU z-ZpIHTaiqOOiPp){&NS}j+MMK3d~`-iZ*oy7{Hi2j1(7;loXZ=yp~-l$5}?BJlV$GX(Z!z-6}~Z5Gr#hgy@m*}=GaLwz+*6<&oMV>k{()G zKKXIs_G9NJ+P}}W_qb)R*%Lx!@Yi!6yGx-e4XNj3>)B!FeHlHAX4JVD z3^bFge{nAjot!;1J?kBM=o1p!K!!qv4%>Iny&oA`A5_m;w;#mBgZ}UjfgVBxI(-Kfk>@=R|0_Z^nP(RBo7{xlhEAPo+0$gx5k>xI z^~0l4JhdmpFSTL0?w-UmUzra6ez^Tz7IwEg05Y!$e{QV9SI z>@W}!%u45x%c5=xq5 zao_-t34!Z^UZ0AL3(s+-GmCn6buuLU#tJ?=7VjepEc=|cO;UdZR56sUm$xYIR}H$A zXGZhWY*KVuWme2UV~_fa$nC`nx?Z2$)NS6MwAFX&e54P&XiC}GLaY3dbA1hQotsGE zk@%by?n6{v0Ri_Eoy(5)V5C#z4_R3$pJ^7dw8epvtLs^EJid-pky^lY_Vi!mB37TS zF;vSdx58>BKt)LzEApCqA9=I} z0b$XBIyHGH85is*eryAwP6d#xyifleC022Be6(7B6D# zLm1>CONGRRi0|3IqQ6BmH;klT9r09bl_vBrTqNw*%hnn!KEJ?R_ z_>=%-{x|_%f6my?D&_;;Jdsc4g4UPTw|V_T35$CqZ;|7dk1qa_^&j)sn47UWofD5j z4UiT5=A{vLpU(IG9aHxU-J4V-eos{yl)stcx;8(BI-d3rYjW~PTVtDRUNX_dFPOYO znm-Pil5lKWij*KIg7Bg^C`Q{g8x)?r2P8|fcO6O&hHqY;P)3ff1# z91>@0O@_o9f!rKQ+LwFzaR$^>rPLGgSv~j!P`g;+>n4oX4mMd`=O;8pOfh&%sg`3j zQK8FW&IRig6O0FAr1iErz5Pxy%>^-MB~xPMML3{#A)C1EZj3Zno zhtA)iUmC@Q9On7YwI^4WzmtOTf)9 z|4jd*PWZ|RKk+xgr!(3k-(YXUQdS~F-ysPEsJCBXJmuPN2j$5A$R!e7@^Hv3?MngR zp4qQ&G#6!-M37V)EVliofNSH8DryzVq`D@o(S-cb!ghARu*C(KtxCwf-gsx&?-)fR z=Y}t)O@QDH1inC&8T&Eg5onH|$J)9O_#ZLgP53n8<=-#-mXf1|x%<~0UjA2mupD)4 z!n?Z=Vs0h`VfpRy3gDHMRiEwNHY0M38*t3PFjmAfL?lD^27~Bl#YYE+->h-ga1r-p z7qhIhxW+#69_k{}x1i>AkD1+6)~`&Z4ZR~8xF9`uMA`~;jYgbAdD-gc4_hIjJS{RB z7R#WcAADuhE+r(@w0Em}3U9&#!#)vC81B&#(oj5<`1=?1nW|PDcXQ=Sf-d^%m(Pxl z+Si0&;REu{5RJ{A^Pr--!{H4tHf%LX_we#h#B4F(9TbNraod`--=?M=z2a)lV%_3c zITq+EUh-xc@j3`HD^_iglKcP-RW~e^N?9dqMEsFe@H8oP3Thc9?|A;B7)KnM?Lr{W zR=K3rf{=T-%EoJw?8Gkql?;xnN{aWPnj7<{rsk@leY79=Z?>KgWN8)@a%qnsE!v?s(Z3gkSBko+C_P| zBP@89gLC}mT-5pW12^Eg`RT8)K&-(6O2pKNx;FI_k1Sw4gt_UWXiZC73Cq8!X_y~s zBwALY^~Hne2NQH&7?edCYqM;4a#ib&lC*ZKvP=R#rrZ>1&E~=aeM=)gSnKAhb|rsj zb=6%-*xdd74&SlpV%R zwGcjzUYi6+rSf_gKL&N&0;F8ei!TlJb4ynT3=AsUjK6;B_OEMQjWC>$L{}e~4sYuG z&NoM`cbu%D&i5nk)gZRz7rAeJB)EU~IT245tN0dorF@=<3LO#ciP2r<< ze;slbr3*hpXC6ZYx@z@c42seG|I!u-B`@GTeqqU2pYb1}-TG0fyDML&Hsm(b1$daU z8I82+U1-}VxPNa7Gq?Z}az3D+&*EF;70L4(B)`F}zg`fRpcLxprS~&?2<|CH{D<8A zuH$2r;VeP$@QliU?@evVn`i#ukKZjG`>J|h1-pCp@BX^A9wyQ*zq6lCM*3{N=0cI1 z=FF526N)_kz^MGVQ;RmFY)EpQw#W4mGBMwek#33F6Y#g(73a6OH}>wa6#KT#qcI8w zSJ{w@ebn8BKCy=l)s#D8pqEYx?|fpj@}W)`HF7bH@){U^;rIS+w_1p(RD!_K!I*O< zJU0k=yQF7V+UN+SnmF0rO>eawuv1M<$(!!Ez|LxH`Symv==X$J&_ z0H5KO^Y4My%krGe15fpi+T;hnJ_#QlOBQs^sq!&+c-`&N0pirgBo%D5W-kD?^= z@vrO^HUMI6_SBRy-3@G*CvV-+EtOrYdFUmhGXS^Y-a1alQq7RKBSV|2@S@Ds=Sgx7q>9T)y~ zLO&M4TP3RtH}uNmqB^GC@Tks>GX>TvacrY?;JYw2&6_maujfxLK@Gka8qY@bl(?7g z7%G9+R_(#RF+J}MHMO4j?l>sRmzmx%#(|%ckg-ynB#dsH-KtUeMrtVH!sH(CZOF5T zvIp0kQaZ&wRy5Q+-AsOP!SmE4RMb8H)Op_D$8yJLHRWy1#k-Wb(^rOavV0DY3)&mI z8!ifnIf*#sA}KO?5~-{(vK8j}nJ(mg{vlK!Ov&*f9h~`A9=vTwQBVMWyZx_DF3B96 zv_h1Qd-6jG(QXJSZJP{$f4Bs9GnVA8AMQtN(Yb@uM%Km?bA{dQ)pxZTBx}IsYkt~q z-cf7iyUY0Y9E&Rij{j>r>*be_td2P}5vMPnWOG#vAQ-sMf~Y)U``PCk@K0GW5zWL~ z#8JyLeq0~AZ=Fl6*8gmwVfHrFoagME!STtx>plh6HQilY<+%Kz!0^*x#gnW_!90_D)cnqeJU3T;>EZ8w#lXOjo@^$ zov?)f)Z4AdLx%pNAZk1~=>0qCMduJ-?3TpWNqe!_p^Ck%-yj@u-np!*>%A~G zlbpDy06#)IYZ!s15th>{WRBvGE^^VkKd>!*(7j(IUE5!&lgdb>;?pLULS7Dbk&pQ zqk6H%e1rs1F^t#pV%hiFVc%T3xZMRaOpj7VfBS|GT#7dqoN@rL&d=_(*K*>!QlwXz zKV3YsWLXUdh8JdJLLgbX`Okn~0ImSQmGjMRl5*s6NA>p_o+hWi-&1HKZxS&7r(KpM z{OP;?jUy#<{#;9w31zz*G~Ih%?^0xc5kzXi8= zN~;0ajHTPk6`VO68=rHiOo64d`PPD3EpZ7DumO$(tN&dTk;Pe`632Wd22au9;B|U4 z%@1;W4!}oX0|0j2r~kX7O@PQ2X7s!bcV3!!X5x4o$bk6Y?RX!1RK?Yvc}8Utf>~k* zEQGSE{}~Snh<^gqMYe%4@;0|_S&(hFsqt-sz20K$AbvA|%0fUuv;yqRn|Z_&0H+;> zc~3sFOH7bNb8T?|EKUsbi&g;Hbst$1ltg7(@mEy?Lr9?VpBSA$`%hNmu9qf%w69SC zq;eePykI8QdhMP0Np&q&C(wR6PUj3f5-!-mt^m?HDqRu2tX%_RSi5Z|K#Z^ewE6#8 zW(c$+TUrBQD=OLbj8Z$1#=O3r_Zl@Da(%*fIif&bbaoQ&0ZcA<;?LmIX@8%asRjfD z=KuFC{l8*{{KX!|J_HxitzuZQT?~zfo1XkrRc3|r%v2#a{8RhRi4;Z`QhQwFU_|#I92=y zt&21kq1?6G3;7qw^qjGziNTD&m#x0Hv-N;~LC*RU;NN2P>A45J+^0iTPv!g}&UAFf z)YWa@^eu%g&YIw1&M(_kZ2@e>geHGobdPGbvH8v=uezfXz(n+$)ps$#m`W`QKlAFzoUHj-0ns(UjA9+*MdD%?I3~YRhY9pyD4` zno#sV->cIc2Ar*bi~(22#%`+(bT`M%awNcQ7^c6u%iwusrXw;Vu2DPt#6<$Ik)B&{ z-y+cV)Q1&=b!rNRDx2#?oxw1C9fgk{mQG3UCDrO)pV#^s8MHjdh8y6mn(ApE_i#(O znO8MThHiRxLIL7qIl`E9#kX5T4^~h!N}Ot!AAFd)Pj|L?Mssio_=t_J{TA;t<`+aHLVz1qFZ`FBoraWohd%~jA>STx|*5i`}@49&)Xk8o+Zc)&#<|9k)AWP=>X&qn%|BB#W|JbrI()<8xbXM#K_3nAoF0AJvG)jc^Ta(3VL(h3X_ zNwEsC2FVRV{2M};VM8(Uir0(i;M$WV@8&cY)(A<-R*urcXm?QKg)-mIF4kTeGu5{n zhgrx;9C&8C;?eC09Ke$^u5)Wft~Edh$nWI**{HZWmNyYP!U*zjz5JVp-kwL9%cZ$t zjX7S8Z6`bu#az1K|9Aq=U0($3ZogQR5UoT88Ik5;RfbbKKg6SpJMl(YV}j32^2Krt z{rxoY?`v@wkEur5x|Yn99oPQ1%B|Z!-yd4vHV*s^j?&YnGT3&P-c_^B0^g@FO}o5FAFOgVUi6;Q*`Y z^KQDPKWPB>2b*ayY%G3<$nS~!)4yJY)rK(dK1o11*$~3DjYpj)-+YuK0OelUuK0rSyK4HrExyv& zkS0C1pR4zN;756H=vv4jaUt#I`lVaYj(N{6gR;OK0@;`9XLT|&O(TG5S6_PEu8w0D zQ5)x!y|o3>$`bxHQ!%Nz`@>I~+9VaE?&I53_V)O9|H2*w@ExAL0U4U(I} zSt2n<9iwZNOj4f^CzBsafkgYGgfpk|6AO zKn2`5W34>hrQ1d|x66Ku$=K>X5M~4ke1s&A7C_2?ty9ND;kHl!2_#n4&!}i;4&M9C zGKRSP^5~GMxstYi#!iYI1#1HBztQYd&n}RiWzTIvZsj1bu`{(^*<0J~oUa@gW*lY)Q)(pe z^U^+UR44FUJ>~yNJ9HI#L}cE@J)}3d-7{#K5tk3>jIsCu4H=Qou2)04F~S=jKK*y- z3IXY7#-B4vyRt>$&F#k_3?N;Nd`fYYg(K`Oa>Y1snFMP;@cVRcqq8D;Pxbr6{W&c= zDsai6sbEVkJ&@+b|AW}6oE3QaNda#h3M(*?0drq&?rDV{o6G=;m?ui~>W>$YToLYL zlLIzE(Ytjp-h!7+`ct8a9(=V%U`9iUB1|2i#PET z6Q5MOHmF`byI)JC+03yfsvq@?xJ!RPq?t!>ez<6E_*mrAlG;$N58ljHZOFDw8oc}j z&dRH@6LQ5Pg9YrYae$4BAkqjz%ws;TDF)4U3!U4DRF{hsVbH?L-uw>LN6emSD@K1c4ZxjLNl zxZxql^4H2IR)s)ky+}hRT-6g2j*Ve{Nf%aqqExMzyxn(ny+HM>P9;?h9I*h}?(|C8 zZao0L;k7R%!Im~ZuGnk(`!7bxtQZws!;s%BzRj%hT~&KRs|H)ZRcv!nO~tsvIXv(+AzW@c~I__$SZ~ie7)oLOc1;NL4zv3{Pq^kGEIcRzkfTz55rq83bYD@U^8mf zqDv@IUXXOHRl?Gs)0D`e#T`^IG8__Vm(nj>37GAoK*Ys;)`4#;B2)qF(JF7<>(_yNu6p!7P61BsgcfE$1rU87Ogq=%~z`}f%=!ooTa|btQDdBe%?#O3FQ$DF=%F5 z4kNat>YsPj0yV=9rmsXVw_n|hyLB`KIS0hD5vWfAzy-4fO^2hI(g8P%;=R(5dr^Ql zbo`nKdFyrN0EyI2h&YQ*f3oOY-Dc8u=+0hwk`vF4?Ht=0`E@F%J8^B5*^Gl2y6tzs ze0*93U}kdx#t8G_TZiVCO}j&_!`J1=T~2S^)D-zLfS1V#^M^e4p8)*SAa*g^HK@$r z%bbP%iSb7V5cuuef2*d<+kZ&O1eA|8UmDIIUf6!(HRIn7?edgc(y$6IUbGeRc0Xw| zu`enK`)&F07ya~MPdNd%Az@ZA@xJN=9o)tsq~5|9#@p)g&!GweWfwR9R6zLYeqAvT zV>J`hobqS`+!hXTayobU@b~0LmZ)x~$TXabCpY^q+Pt39fnnBbP_TfRYm5N8a4%l) z-Vv25<}29%&uMFz>29PE$ASeH1My>_d(~}D{84`Pvv+c)`~|95f(JeeLUX0Nkps9M zE@va{Oi-#xgD{WouG(8?6zLK8vvfn|;BrMSc=dJ&#OlzRMrq-MZg8`VSOH0cYXp-g z=3##ag8DTEaiKohfw0~pyh-Evc9b=e=97WJ+-r>QaaPQ+5Mf7{nI;es@P;^p ziYx$#k*lS;yWrpN$uSM_gMO>^co+6bMCP!N(u5(-K;o?8c-;ewIIb{ryW0qK%o>raiI?K^LN2;cICcZGe`~2;8G{VF$&jwLy|O_$smvx zO@Q{fYAph()8fi!?vI6#eY7+dC7iWd+c!tQ-&t?nk3qFxP9eisKYylHM z1_h{OgUg*pjtCU8K&;JbnWiiU0(Bb7y*HeyNDd21H36~!sv(nS!8u}^FDdU0j%$OF zjibk_+?np$_M?&j!z~K|6l4*f=cHfthMvmIjRGkC?+Oyw0t*!dChCrO#ic0CmiYp6 zrFOATRepKB_|mh7wDHHMz#Cb;@7-P{~x*jT72(XA&WY| zGhhGu#@39zHh?z|pDwhs_Hv=OXebgKqaM@Qb0AIGqD7iar0q`&B)h^|Af5(Ipuv$M zFNLBhkD64?+TiX^oi0-3AJsA!D6CDDAHJ3<&;CpJ?$|LvOSA&AM`pgtr9rx^p8p)% zt$h+_bj=K5ev0d7?ZQ$qcHdS-SGVtb8^US^E0{iCzHLmd4TQS*?}xn*Bq@O&G&IR@ zzxHx3dWA$A9vC>|-p55`|5)-PPQ0wfG>(!dJ&dSQhoE#xkz>}nibfJcCHDT)1%}^! zBtD=GA+OYeNm_DcyyffTuU3K_r5>3nv1EZ8b*Fqn1z`OZxL=#*BH%wyMTA&keBl5)TM>6)?uo_Bylw@J2MAlrdPu8v+b{YI({EO&!i}PH=BX z_3T^RR$NJuxpx#@=FvFqr%q|2XE=<#MS&eI^Ok5$+giG2Y{}IAOqg`)NYG1~-52;L zR<^X@XJ9`&g(x!s(rYe_lA$E-jHI~F`HHwe38$)2d!2ji`X~stV$}$QJT#Y~)r#=V z>~wDa@4}pCn0K%FI_vibTx&R&)FSM|y z-Xe52iH2Vb9j;6G&%}Kc(A#P37~|2R#oy6a9Dom+e477VyRqKt z7|2CAMeLZv#Zy{KK(58@An*`3=`m1Y&dWLpcpfx-I2O^F&|j$h$C4J*I>r`K6`0!? z_Riv83;MY1t8eI;;jvGvq2$U*C4ttJ0_hUcfMTGIg9e#k-! zXwU~*Gtb-)8{R-Pe6r?mq>=!p)OOgf8V(|iAlGXk1(xdGD44zun|4X_guO{%N3^XV zu0;BC(sgg)_50*bwp=T2xOaO?qd3NgO7J5aK7);@hR0s@=sh>QWpffJOKD!6^ zo8#w=fyC)DLEe*?m_L1znUtJ2_{q(vq>mep>$~4g z!vm{NQ(#y&u(YjJSWI2D1?B$h<#8phW)&KYCrO09y8+#Io7;Rq{k36ITFfZhp*ud` zGVTV~F{#?gY&njLlQ@1{T`CrBF{5n`0n&2{g4qfFO#&GZiZNphj7kf#0{W$82pO98~4aNfXV=vQ82-NI)&P~3lFQ> zo%InJ5A{9vyvMKS@j)l*|WABo5G zf5Q>q6@u@kMwCyNZf(d+T-qhlG4dikqEih&M-r#>=cZ5!l9F~0DP_d*nM=P?*TxDB zGld~@WnBE^D+M`JvN!VD@LceW9A9dK7F^KSebYW}j%=p!spr|!Knc>XH(fMbW~Y=% z`HHMLRUHF1?Akvk<394YBQvZz#*)m;kZ_@OK};1muH0|xSYYmezJRiFEld@{N~W*` zP`f7nIoaKA1n!$6)2GAsr_LL@1BEa1szcZbZmB8Y+hpzA;vlbua;T4vsmHbhvvy` z(%_b&`8HgEQ=QPtOQ^d!d8w3GPoJPKg>m0)x6Y&E)bMSHb1GGge$qomH@??-$f0NG z3VNB@ftXnZ%cMbIgSoLJ)TTaj^o@(DH|hk}+Be|kz8^#`co(=Ty=@;p{ii2k85L1u zGcZJLQ7kmimooEsEP$u+99^li6f?ERwSZSO2su*9`W_GdG~Et1lzjg+Fl77u`)LUN zd<$06`))Z`=r8yafWvgfp42&pT?+Gv)+ifGu;^z#UGH`JH4Z zK=J{QbP2Yc$2anM#gIt@L5K)Gc)zdD36*X5%20tAK{&r~q;}VdFlE6F&P4f&@6Xdq z+VY|)HVzDP&XWeV&P#)Ud@AIQOT@-|YLJMCU~n~jh?jRn;QKV%xCT3?MMM)9ZWvPH z1bx(yk5~(xc2g!Zjg3|$hEuVoisP5+_<<88wv!vA>ysxcdAzFPUxI3$FkXSw#?32* z`TY~jG81S>PYVPOwDWix!xvN6+ZQEfZ3o^a%&AEZwOpNC8gSuapmsfV2O(oA27V=y zQ1py%816?v!JFDXh6{~>nK9VLJ|xj9SEFdZoeTa&qy&Y-Z6NH*kDNJeAX8S!hcDgm z7vheKnpRrEGSZY7l8?umLWInItU?3{Bp=7#b-0xC8&n39){P}~T*nRL#QaXWsPD(n z_3_sMInE1W!^+ z8=5_@Zh6^gWDUnIi_NG+wTywBay(DEpRhcmvcMLhnrfAvF$D;*R z1ILoy61@v*y#an=p;1Si^sw0XRWRkZnfu7wo3znWi+;aaqM7O#TRTZEcH&C(^uRI; zYnT}Qf;T)Md#U64nld%4L+Q_Hg7pUSA&ZZ$#6uT?6i6hhT4?O8`MaZ{u zOSuw!BT(724EEk}!i2JK=-rBH35}98mURQ)A!sh)s)W7uZC;z`S0$Yjs)vUaCj!&s z8gIYjSpXFvu6<{jcN9L1gO8w=OGlgIxIhWe!x+)ZL=v&L#FNlY~WvjzqqnrJRjoJ zSJaC&QZFx_(^>z@bv|mXJ&ic)e_MC~8{gb;7rWF$%mfLxknh&-aqa=krm8}E(Z`?u zyRlvy64^7y8jZD1c57_DfwT7Wi`*`w0-d#=+&Pfwtps>W`hHe3chUi*rf?j~HH+s8 zJ+*L|7BMio9jO6vO4^rafy+a=N~;w$(5=yL^$_$Mh_0YPQgTDOpby$Yq)sZ|qItkb zPZNZ38=x>^RjVVP9N^NTwTS0PVaH$$mYY(g23JO(go@G}yQ`L=zJPnZV`jReg=h^* z!wWY}L%E#oCJl>2jE{>{IXYD7rNz=zWQAUyn;a>de+oX5P_tj{i|ezH`1&K1-D>D2 zCu#h>t`$v9hFb2xF>|p?i_u@}0U)kt_fyGs+&#Dp+XS9Z0=oD_Itz@TN8-r6BH_7j zZbBg2uZ;cIA;DlJj>JKZpd29Bpo^Qx0I*%*n-XFF&31kQBRNfEL{ z4Avk2=xaUcPKceOI)vkv;^8-_?XuNO|mov+as z0ZXI(YlG9&pkqffKjp!@2`jM0j&O_j8QJXI{6na6#(fj ztVwkuzYjW&J3^X2Ih1Da<{>`L3I>FABPXq@*ZfpKMR-R9`prQ~k{0)V zYQA5qR&8J5PRj7&!XF40v%byMbkJGLoGU)#SO?h99d~wq^T}qJns|OWsSuu4lX;v;j^g4^+=@*Pa9tWqj5Oqz@|#3Ur1iKs zJdft%`a%1+$)?{eXD8Z7uk;6Ys!vHHn%W4XD#`|CA5VI6)}4^1bafrPQ++yh8fo3x=sKo?O8 z8cvy0LOb|K4GE=+=*A*w3oeZ$Fb$L9=^FGqQ-Q*vb0PJ1Ox}#?hMDz%G;QZ|B-$l1 z%XQCYF5tSI5L!X3rZEFjEcy0Jvc$TQ7*@kqwx^2C{Imfz-+5`}e6_rezDeAGcGBPn z)FO$3_fmXcg$x^1wtJ5IG=%u&;~$T{s4r#R#D{HLWCQcEe-F|+>%9lE#A^C7t(Hig z`-qwZh3OYJId8V2AsZ>kAX2y3=Y1g4Q-aPDFXva0t zZBSZ1Opo&9$E8sXwMAgnwYP#L7QMX%gau2^3p6~`konZ?7zEg82>_+&8~4GB_P07K zAZw!UbhVG?1f(4#8yFFO!h^Mb5-eYozmH6bUUF{FW#m$z*H1=Q7SiPr-TichiEqlh zpP?7GNN!X<$|2CgWnjMP_^I+8q@2jcKNLo|h~%z8uV0Hiv= zP+t++I?m0lcl<=O!N3UNU>grikpuHfa<4pl>@GY)dX^&HP*MX^uV%b{3b*MBof;q8 z?gYUgtx|JCYc{J$AlSjt{6sx#V4O0B){Yh&0FQFBFFg!g_Zb&xl{e%BdQoQu-;}ym z^#h*9+>zYE9Xxr%54HRtIhd#qe*XD7#H`WejmC_ad!W;AyejBfDj8h7RUR_kZcx*9 zX%zShOi(`;U|JJ4Ro(StGZ=@4_eilHZ`TIFY_2=HKXaiMkwK#*?`c_Ip6SL+9EnJ- znb*4RV6wj}xJ@qQl;`#;0{R>Bt>e znL%_dLt*DV{5)@KmfqI(3NbD;a@C+~m_3o{CvBF%>^<$|SO|$S`Z!_T{U^@3)Q-v` zK!}ozba#`>NVm%u#V{Sv<91;Yf;e!pU_NxpHI%-<1ag$D zMxUifHPic<^c~U%Y8>U-E18`yb022Ma992$645ZU9rhmp)QAOPHFc^^8Kx3TspxFm z-3l-1O;FK|YO8W1uHvCv;pff1EAovG-w4xLT7{SNRqkTjRxSsMI@S(>Et`yqO6=&3 z+=PY(d9Xug*MWZg3dksc+VGdKOr4mZ@MwTKSb(Df()hH&NuAoL#jQgBI<7(X{qXN_ z^j5eNBJ>Os)VuvLRRxeP2({B^v2PQ*2;OtGf;GL6meu7f(q2k-#2)p|nEc2b)L2>>=$h z>WF!C*!)Om)WpX1Vh_5mW_AXt$^`^KNhNcVNAmVcAi)-x;*??U#m+E)uemQK5QXnO ze$M1x#pO!1huK%MD^l0!dNEXN45OZF1g3AJ_u)OnkB1tl|DX2G{2%J}3;3#AY9!r7 zN+FeP6rmx6Zj`dejIpmFhLkta(40f-)kSz)c-|S&t=M>Kz#`kqU9M=GjLeGW@$ILU#2F6fQ#eAC~}UbemSy zi~&PdK*diFc}w3dnAU{dhZrD5L)}xG{kmjoRP?ksD}`iIWr#(F@7+r~){Om92uGwX zAfs#-UL}ErU7R(kt#+F|lb_xsJvrd>pau#RJ#aA(58L3sBIIrm3#kB{FTyb=2Y5c( zGR^ECXD81$45$&>lQbc)tshZxxXRby(Y8aX^XXB^GQq``UuN3x*p=pxTZs?K3KI1p z=H;yxDqstCZ!HJ6m{#A|(_c-_P3v6BAxM^cOA*uNOh85nC+hUPic{@cNx4sF{Xt+Y8tk29n=CPK6!$;%7nf8fhQ;n(J0X--?VGNxnY7kK|Ip> znLmtYARae9QdZG|OL`d@lLXOKe1D6VPg~g~t=fZ*^WldJr_ANeULp6*0JxjWW#@`_ zDMTrkm1NdaRs&TpY~u*`8%-42^aN?}h9(;pe?B;o=AGqKy}r$2ZL(`+QEQD`+n)`r zuYS68xVLxdrQU6?1&XLv60@TWDz_PEt&Dk%y8yMmO z+8~e%bO$22ma?F(rJZa1LUs0=h;>EH{*K32QEeTDT_yML^^1@s=gNGi+hL>inmLCe zcjv(GQ@ZpOAQmONlG_%GTQ4SL(<=aBL)cqhJ1Y?{&MIkEkY0Oe#A>n(ITp{a4nx1Q zEk%f)9=%tl;~{6V$YpqNUq-_tmnns^Bn)Qc3#G*A^awV~l3&OW2dgr5tS3M@&a$2_ z*0G`5z#ZVVgFWXBDCaXQLEH!}V<0P3tpkw`ROHXr;ebLl9OZJfxkj)ufoxJDb$hTk znk@M#sAxYCgy?Oih@I)8mGqz^P-up%{}|W-vAdll0Nj{dSz@a8Is371|254w-(?UJ zH(#KwE9U0idi3|Ww4a7QSE(oQ^da8T>;q|FE5l)hP^*H+m5S zdRXU)#3xs!`hOPxk!3xtgl(A`e}E;z-92C1S_4S$IMA-E$L%D|7plGgxZG4$^TB zHQDAbhC_x$I}dkJIx;iEgD^XN!5goEnZC_v6iyR^*~&Q&O>5?jwg)sv2*%$mBs!EI zfMxEyzF&RCfrXa9fF)miFAQ321qIB57H{8geJDNyS>Jug&&gZ97u?}zfIpcMv;p^8 zh3dGh^X}>g{B=#6+d(m@=N+&;9Z(*W2hrV{f^4LY&-}*k&Cqb^=M~%%ukY(RxO|lw zio-Q0jd5;QnxS3FW6gKEgV(Mz?ja9Js(trgjLW_P$3Q8H0p|_;|?9*!nzBK;N zcNE6|3CRn2ke;inP3k*iHIfu<`Q`C&{+bWKZv8g?%>0?FZua#N`5qISzD?Xs_ZI9{ z`D~=WQKX`wEiLngOV@|u!NvVE_l)6&0bo71o?zBf{npQN*@r*KhRn{t9f77M_XQ8Z z9;>I0kPU+nuNAl!m}w<>GLT{@e4$i9}+txSv(zPP1EIB`o}Xai?`K;`aD?&>E1yPC-FvHcs)`?f`ap$H0~OoeiRoyc;Ha zzPFr4q6z)WSE7N@InyYoo@WnSZNc_N6Yl5vAQMeFcQ-u<4tbfWvqCCdixyg2uuH4%D3!7Ni=9ay-r{aF;&T z_yzQOEAcMGw4(YSBAtRqPr};cE`D#a(!3sJsd_&f^2>OO_BG^+T)Pm5Zu_TA-qZ2? zFz(z4>7Jm@M^g}SzJ1B|hx`NvT^Qe_nlN5|KN(+L^~D-Wjy4-~M|-pmxN(M2$y4=$ zw9u6r8x~TtHJNq(k<|`z!Ehx@A(*DE#8nCoxY!-F?+`{Cg1-$A>rRPr6G-xhE@3If zfdF=g*~Ja@{hZ;G)F;ofA&Pr8r-x6b>M_zaw5=O3*Hl)1MWEw734kd2>(W1{)tA+00D%>&JF=p5{>NGdCLHrETE#bz9 z;eko_=a{CTXe+1>HY@aJbgB>8t?-rwdeZx3JXoN4Y^7k0SZ_;M1&isuRAU5GoW zqU_<_AJ1g(s4yP*+|)MdHzljN^kj^B=Em7-@mmDFvYiMEX>tjOQ3E8eKUNv^h;2Lt zqsQlu1eNzNmq{6IsN>1^=GV`6Z)PblW$Ci_yBwt+I(MZ&d(BOq{ActV=Zz-L#OMoD zMBL@SqSrjW=9vIE0sfL7+ZIvyRZ-v(nW>oFA}lP)N3QLYm)>f|p@hL@X?md>`c9vn zl?tqJ)IOm>S6iBzc+iY3iZGZR*`~|+Hy|Z_ve%c8x25XX&9MdA-$}3gK%Eo|u?+}* znWiqy!l$c5wp6?fnPkSV*h&+bh4~a!wSkbckmSyRleY=3C4G5v-cq}+WDUFQyA>L$ zcscdGUw=ve#hGsd$@CK=k&b_#V}GUF+DU)i-ic9Ig&PZIVu`GRNro-lpcRGN1{V3E ziog~j)2?i&I&M;#4l9JAd5qa;;G#WaebwuRzefm+E$RN79kvbPN2!6Z7PVzgZ{z`N zK{p(T>BPQBeQKSXGH-9QbOFn1E2R`_LT=6FH)x?B@qu?7%tVQ=woFd!0T7x|=C5G_ z?CeSaZb-#1pCv~uKQn1h2z`E~*1|a1JDYQkW_Kvj&x_l|sL`xBJ392^`a)p-{xxo7 zYN!MUUsi;04;o++o@~U(DUQ&C8)Yay37CNc3-*XCz8h*A%SxWi`s~_Hv~vJyUNcW0 zV~+3OG_;FC>K=iIUws zv|^<%UxXNpGkA{dl)@WUs|3Hq!O=btzP6pB8f}y=;dfhiFePR0e`XOPgkDTp19J3Cv|4^T6tJ8J14YXfW` zjx*ljFSu#?tTx<${m?kGY8A`O$2)&i5>VL3d~ zxT@T_E5xmAd?ucIYW63RTW$;PK^q|tW?M?JyOxAsE~x&r>MGK?Xvt~Kk7@Dc#h+Gu zyRX#n{_Ds4;m9$Ibh}|9eSs;YL)5=U3J_tGPe9}dh`)nX!%l6bKn(+wFR657XP=QJ z%*@5L$jj%?OmT3mo4vpC8qORxHQ_Sfu<~!XBpF&)O)7FO|uIOsF`8BIPzFZ({*{Fup**tf|g?>%5Fwln-G9#`kmcTUFgN*~x*m*LsW zXr4N2uR4>Jjc5g-rtJmbevXbM_w02m3mEc_)+h<1@hCxK!+A+YaC1N3HO#Y*Ihg;$ zN#>R+Q9m3WJ8kI7Ak|Gro7xze-siV>OZ6?R#78t_{g7u<;(|~)Zx(p166y>O^;cdv z6Cs^_xH$ePtOnEQ^-2aFI8rq#)X3@AuM;beti3ycD%~w8WoofO(Y&mk9c*$O zXICLydnNA_*<34mOCV2CKz`>4*>4YliJhcHxWiAF8FKcK70gd5wTCRpZi!{8o^|uK zi^Pd?ZGpzK5IV&8=*n6DYeRSy5o;Z|309WGfr&G6r*VGq`ouj`#tEm*wYyvZzz9)J$u}<&o3UV<8`)Ckz8^Fxdv-NPHx$ zJF9sp8p@Th|5YtwNF{J{?*Tj0)IIrI*bni93}YCONk9y8#R6;wfSc+SQ(N5AuY2?vtNbZ7l9R{xar6V!(s5dYeqcIzs4S z!WV3V2%G*#O;n0NX9GnCM|v2OJ1w~2!DjqsKz{Dvhyi0##a(u2gG4SpJP4y?YF-zD zCT>iptJ-`SA+e?nGH7fYt~x%r_1qydE{N0h9m+A;96^_&%O5>SsshWCCGBreU}{YI zOL%AMgCj(lr-1LruxwU{;hsm)wuRYuOU4r+P^)l8{U?|8k}3!2(b3iBp6ac2x!{@h z2LB3-lmCbDCEJpT%!gtr{+e%jOMFE_(K)sn<~wtC*>32ch3_WvNJi(>K7R$9N$}tz zEM@J=LUgJp;G2pB_rPZ4_sbGfHB$%mAN^PMzg=0=E2J9C^a1J2zpRcyY@BWHmD6PD z0S+lJmK6&ope=R7#D1<1JD|*I38?Y4c1S*q(xqo=N<=%VY)w;CiGD`UVMm!S12Djf zDy*ggMlSGv8h4qmhNWwBfWE30#Ycc>8c?lzR+ZC&-zR1iOwTRTbr|`mo~IiAl*rVDB^CS`V7p4_u9j?n{gh&=M_I7cw3iu2_!H!`wu4a_ z0?Q|*ZSwS2&05J%ea}c#p-OO}lM7sAdWRYg$dL(J@I$nT+m(sk5NdhT+0!maEcbtk zxWsAQp?{da{GNYsju6?b|F5Kw<}@fY||fJIUyn47lUcDtfw0EQU6c! zX;DbC&ksz$1&Kn?+>PP}P3j-PBn{J=uhh_D*!=Y@w={s+10Laqp3IwP^!iHH+i;NwdP?%ycv@K^U+Uwd$(9Qdk>B**wJG<&clWdR+oFAg`ZDY$ zsFu4xoq#Bd{XMiBqOvH zcVMCU_r5ZA?&;><>mMt+nAhwgBIMOu0q&dauN7&QF069jxt<#BBc&emkn1*CLGfr8 zN9Tq$d-1)LPn8Qs+6g^b&D~h*ri+z~9L;Mzy%e5j03U(3ZtGB?5=&)X8DeXUd~Uva zbUgu6n;;Ts2mG^mz8i@1`(f9Y_f8clJ$%LAQu%Z5D#Qe^d9&XJZl>UlUUrpjSwa;= zs2-wNS13EI;>wq^#;b5eH>8_?8-&TM4T8PcwPjH@sMcSEqjOW8cDC=w8d0>IO|72M z-wUoGzCS~h5<}Wjtxg}Uj%!2j+ZywicIb)?DqDYv$z>ET9I`$N9ayJltX?(`q|BQG{8oE-_#vvL{@Hh+2LI0q2VGSz=_nxop&)j~=j z2^su82w^th!UWx{f z9&YJ28yxqsM`WCJQ61d{Qp#34#ccN9{M87AD|(GSd4EMn^*GAeNNW;Z6#pG1_UsGl zZuQ274HmGZ8=TR^+;16ev)Hnvez>dX^pk3PWB3;e%g&my3}!e7sNY(&QRR2vYBP1c zBDWNe5`6N<)@6Tg98tO(AAoVBFj?p0B%ZVME3I{e5xw5R+@1 zitqAV$;qwWvJYw7d9?Of_t1Z4I>rx?lNw#+s)_TzJk%F@tAHZ5s&!47?b-%iosET# zMd_8$s54&Qs*fvPeB#URkoN{vzj1;6G>w)wmTZ*-mZpD@u7d3h(oMd|MEzMihuYoG zgY&LZB{8qB?A+JszR{xTyD@$x&!tpF8a|+t@vjaN+zrE>l0# zqc$52E>ycVcG)#fUkWTCRj4j;zy^kfJcF>Bl+TzH+$P%7e|3Np)->q>9hY@o&wTC{ z(O`1Ge>xCNH?mEQ*irKfH3tWpx1gDDi`lP^?;rSWN{XY)gF4N(Zd0{Kr!nQTm?K#D z3VUA(sWNl@B=C2|(HvGm1nQsE_k)q{NDfa~Qh`}FCpwE#+N@D!L-OZD_8wzG8ZmKqhZOtCZ)WKpl;s@AF^seAt@YnCJ#yc?OWNLe ziL6scn>Cg=y4aDhR{~h-awdAN>!!8oxjAUGLAr`!A&+q`d_Mdgs$Ob7M18;C?rLc= zOwU>FfXjFwxybVn4Q7LqV@%zGNi@HQ$i@CJd*AAzcu%h7_t(ac`7zmV_*v(g`)b#E zGiAi#yGc2QGU4CDlVEynHaFjYRI8Hu%jpcW>c^r7(VSpmh?7}`)qwDb@L{*H(XYcp-W@*fXj;swnEGrfOW3|r#(vU) zo40PZVI>kU;-|-uX4yQ}d z^nz}Se2?jr=8MBs43x7yaxrUk_17tr5HWT<=Rk5KOE)8~vTus(%-S|CEbqsrjD1E! zuijo@d!mZLyCzm_70{6HQpdJMZU$lfJM(&H1IGG)cP`ooWc#bUV7rHtCtpVMk<`tH z=|N8m-KDeJ&_#siMVA+xQn!~3hM@xs9l_aQPyS5Cao2vK`bf3#v>wDpgJRwb$F{WttGtH95`b+)$Yjr(tNo02s584Il`~!!($etp(dF0+ zn3!tf^*ID|S4yA|o$BmKRl#v3v6A!agDKwcG-qyI6jm zwa>>Pb1yA!(StcSBz5-_*R~N1?Z{q!dzu9_#W3pp7Zj<-A4s~FGaBVx(EV$L&3nsMwUmcnU zmuUx>pr_%R)lsvNTqp5t-S$K17-VLBr3PxA+qg-&K>ND@h1Tgp=MO{wVNKB+nf2tr z?(!E4-hXaC4;E=WB+pYWpL_O`fZ|>nzexqdG-H}@G$F2zc89^qh)qdwig#A&LJ!HY zk+%oJ2f`EFw(I>xmpcdMYR0%Pu)1ksi+T_G&~r~oS+Dq$X!NxDVL5(q`M;;ReGc{ZS*3A zYQ0;dplG+nAQSS&+jj8=JP4 z$Ah&}_Vyvlgr}VhB%BI}wqSYs<1p;#cAC7Z6p$S-TQ45p}AAh0Soe-}B zzT$xdy<=Mem8cGi44`l%l>Rbx^A7Q&@M;yz(aY<~)&HCkP4VM<6g$#fOx;$Mujk8p z*`9g8Q4d&l(5Lyc_A*d8_66~u!J1MmIrs&sqtzNqV-WINL4`JU)QSwmgzi!dfTG$sQv~&;4L;S@MBebJ{=6~04r{loOJCI9%@T3R7 zPPzX_p>iAp{l_-=f2#e)|6kp|w$1-F&g(w6y031vyXK>jgU{u`T|;fGrhUZ!0m63< AdH?_b literal 0 HcmV?d00001 diff --git a/apps/migrations/public/twitter-share-image-1200-675.png b/apps/migrations/public/twitter-share-image-1200-675.png new file mode 100644 index 0000000000000000000000000000000000000000..dbcd602b5f7a2a1c661c507d3fcc050dd044ab3a GIT binary patch literal 45900 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�@z#Dc6o=0tY_I3C2D~+hSy>FK~ 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 - {/* TODO: add meta image */} - {/* */} + @@ -47,11 +49,10 @@ class MyDocument extends Document { - {/* TODO: add meta image */} - {/* */} + /> From 632b2ece94706bea47ac65add8b5b4ada558c02d Mon Sep 17 00:00:00 2001 From: Ncookiez Date: Mon, 25 Mar 2024 15:03:47 -0400 Subject: [PATCH 080/161] added package descriptions --- packages/hyperstructure-client-js/package.json | 1 + packages/hyperstructure-react-hooks/package.json | 1 + 2 files changed, 2 insertions(+) diff --git a/packages/hyperstructure-client-js/package.json b/packages/hyperstructure-client-js/package.json index 3537967a..54529640 100644 --- a/packages/hyperstructure-client-js/package.json +++ b/packages/hyperstructure-client-js/package.json @@ -1,5 +1,6 @@ { "name": "@generationsoftware/hyperstructure-client-js", + "description": "Lightweight library for interacting with PoolTogether contracts", "version": "1.12.0", "license": "MIT", "main": "./dist/index.mjs", diff --git a/packages/hyperstructure-react-hooks/package.json b/packages/hyperstructure-react-hooks/package.json index a4bdd457..41ee0a13 100644 --- a/packages/hyperstructure-react-hooks/package.json +++ b/packages/hyperstructure-react-hooks/package.json @@ -1,5 +1,6 @@ { "name": "@generationsoftware/hyperstructure-react-hooks", + "description": "React hooks library for interacting with PoolTogether contracts", "version": "1.15.0", "license": "MIT", "main": "./dist/index.mjs", From 3de944e85d862292f6a62822759fd41ce4a39099 Mon Sep 17 00:00:00 2001 From: Ncookiez Date: Mon, 25 Mar 2024 15:24:11 -0400 Subject: [PATCH 081/161] all apps nextjs13 -> nextjs14 --- apps/analytics/package.json | 2 +- apps/app/package.json | 2 +- apps/flash-liquidator/package.json | 2 +- apps/incentives/package.json | 2 +- apps/landing-page/package.json | 2 +- apps/rewards-builder/package.json | 2 +- apps/swaps/package.json | 2 +- apps/vault-factory/package.json | 2 +- apps/vaultlist-creator/package.json | 2 +- pnpm-lock.yaml | 77 +++++++++++++++++------------ 10 files changed, 55 insertions(+), 40 deletions(-) diff --git a/apps/analytics/package.json b/apps/analytics/package.json index 6999e7f4..4dc83287 100644 --- a/apps/analytics/package.json +++ b/apps/analytics/package.json @@ -19,7 +19,7 @@ "framer-motion": "^10.12.16", "jotai": "^1.13.1", "lottie-react": "^2.4.0", - "next": "13.3.0", + "next": "14.1.0", "react": "^18.2.0", "react-dom": "^18.2.0", "react-hook-form": "^7.43.2", diff --git a/apps/app/package.json b/apps/app/package.json index 82cc5ad7..1e6286d9 100644 --- a/apps/app/package.json +++ b/apps/app/package.json @@ -22,7 +22,7 @@ "framer-motion": "^10.12.16", "jotai": "^1.13.1", "lottie-react": "^2.4.0", - "next": "13.3.0", + "next": "14.1.0", "next-intl": "^2.15.1", "react": "^18.2.0", "react-dom": "^18.2.0", diff --git a/apps/flash-liquidator/package.json b/apps/flash-liquidator/package.json index b204730b..564dad91 100644 --- a/apps/flash-liquidator/package.json +++ b/apps/flash-liquidator/package.json @@ -20,7 +20,7 @@ "framer-motion": "^10.12.16", "jotai": "^1.13.1", "lottie-react": "^2.4.0", - "next": "13.3.0", + "next": "14.1.0", "react": "^18.2.0", "react-dom": "^18.2.0", "react-hook-form": "^7.43.2", diff --git a/apps/incentives/package.json b/apps/incentives/package.json index d87ba225..70312cae 100644 --- a/apps/incentives/package.json +++ b/apps/incentives/package.json @@ -16,7 +16,7 @@ "flowbite-react": "0.7.2", "framer-motion": "^10.12.16", "jotai": "^1.13.1", - "next": "13.3.0", + "next": "14.1.0", "react": "^18.2.0", "react-dom": "^18.2.0", "react-hook-form": "^7.43.2", diff --git a/apps/landing-page/package.json b/apps/landing-page/package.json index 452532f5..55fdf2e2 100644 --- a/apps/landing-page/package.json +++ b/apps/landing-page/package.json @@ -16,7 +16,7 @@ "flowbite-react": "0.7.2", "framer-motion": "^10.12.16", "jotai": "^1.13.1", - "next": "13.3.0", + "next": "14.1.0", "react": "^18.2.0", "react-dom": "^18.2.0", "react-hook-form": "^7.43.2", diff --git a/apps/rewards-builder/package.json b/apps/rewards-builder/package.json index cb62882c..e53fcabb 100644 --- a/apps/rewards-builder/package.json +++ b/apps/rewards-builder/package.json @@ -20,7 +20,7 @@ "framer-motion": "^10.12.16", "jotai": "^1.13.1", "lottie-react": "^2.4.0", - "next": "13.3.0", + "next": "14.1.0", "react": "^18.2.0", "react-dom": "^18.2.0", "react-hook-form": "^7.43.2", diff --git a/apps/swaps/package.json b/apps/swaps/package.json index 4a4a574b..1a5ac8d2 100644 --- a/apps/swaps/package.json +++ b/apps/swaps/package.json @@ -19,7 +19,7 @@ "framer-motion": "^10.12.16", "jotai": "^1.13.1", "lottie-react": "^2.4.0", - "next": "13.3.0", + "next": "14.1.0", "react": "^18.2.0", "react-dom": "^18.2.0", "react-hook-form": "^7.43.2", diff --git a/apps/vault-factory/package.json b/apps/vault-factory/package.json index fd09531f..72f7a870 100644 --- a/apps/vault-factory/package.json +++ b/apps/vault-factory/package.json @@ -20,7 +20,7 @@ "framer-motion": "^10.12.16", "jotai": "^1.13.1", "lottie-react": "^2.4.0", - "next": "13.3.0", + "next": "14.1.0", "react": "^18.2.0", "react-dom": "^18.2.0", "react-hook-form": "^7.43.2", diff --git a/apps/vaultlist-creator/package.json b/apps/vaultlist-creator/package.json index 11efe2d5..759f9e66 100644 --- a/apps/vaultlist-creator/package.json +++ b/apps/vaultlist-creator/package.json @@ -19,7 +19,7 @@ "framer-motion": "^10.12.16", "jotai": "^1.13.1", "lottie-react": "^2.4.0", - "next": "13.3.0", + "next": "14.1.0", "react": "^18.2.0", "react-dom": "^18.2.0", "react-hook-form": "^7.43.2", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 40c2a547..ab38db00 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -117,7 +117,7 @@ importers: version: 2.2.1 flowbite-react: specifier: 0.7.2 - version: 0.7.2(@types/react@18.2.8)(esbuild@0.17.18)(next@13.3.0)(react-dom@18.2.0)(react@18.2.0)(tailwindcss@3.3.1) + version: 0.7.2(@types/react@18.2.8)(esbuild@0.17.18)(next@14.1.0)(react-dom@18.2.0)(react@18.2.0)(tailwindcss@3.3.1) framer-motion: specifier: ^10.12.16 version: 10.12.16(react-dom@18.2.0)(react@18.2.0) @@ -128,8 +128,8 @@ importers: specifier: ^2.4.0 version: 2.4.0(react-dom@18.2.0)(react@18.2.0) next: - specifier: 13.3.0 - version: 13.3.0(@babel/core@7.23.9)(@opentelemetry/api@1.7.0)(react-dom@18.2.0)(react@18.2.0) + specifier: 14.1.0 + version: 14.1.0(@babel/core@7.23.9)(@opentelemetry/api@1.7.0)(react-dom@18.2.0)(react@18.2.0) react: specifier: ^18.2.0 version: 18.2.0 @@ -211,7 +211,7 @@ importers: version: 2.2.1 flowbite-react: specifier: 0.7.2 - version: 0.7.2(@types/react@18.2.8)(esbuild@0.17.18)(next@13.3.0)(react-dom@18.2.0)(react@18.2.0)(tailwindcss@3.3.1) + version: 0.7.2(@types/react@18.2.8)(esbuild@0.17.18)(next@14.1.0)(react-dom@18.2.0)(react@18.2.0)(tailwindcss@3.3.1) framer-motion: specifier: ^10.12.16 version: 10.12.16(react-dom@18.2.0)(react@18.2.0) @@ -222,11 +222,11 @@ importers: specifier: ^2.4.0 version: 2.4.0(react-dom@18.2.0)(react@18.2.0) next: - specifier: 13.3.0 - version: 13.3.0(@babel/core@7.23.9)(@opentelemetry/api@1.7.0)(react-dom@18.2.0)(react@18.2.0) + specifier: 14.1.0 + version: 14.1.0(@babel/core@7.23.9)(@opentelemetry/api@1.7.0)(react-dom@18.2.0)(react@18.2.0) next-intl: specifier: ^2.15.1 - version: 2.17.5(next@13.3.0)(react@18.2.0) + version: 2.17.5(next@14.1.0)(react@18.2.0) react: specifier: ^18.2.0 version: 18.2.0 @@ -299,7 +299,7 @@ importers: version: 2.2.1 flowbite-react: specifier: 0.7.2 - version: 0.7.2(@types/react@18.2.8)(esbuild@0.17.18)(next@13.3.0)(react-dom@18.2.0)(react@18.2.0)(tailwindcss@3.3.1) + version: 0.7.2(@types/react@18.2.8)(esbuild@0.17.18)(next@14.1.0)(react-dom@18.2.0)(react@18.2.0)(tailwindcss@3.3.1) framer-motion: specifier: ^10.12.16 version: 10.12.16(react-dom@18.2.0)(react@18.2.0) @@ -310,8 +310,8 @@ importers: specifier: ^2.4.0 version: 2.4.0(react-dom@18.2.0)(react@18.2.0) next: - specifier: 13.3.0 - version: 13.3.0(@babel/core@7.23.9)(@opentelemetry/api@1.7.0)(react-dom@18.2.0)(react@18.2.0) + specifier: 14.1.0 + version: 14.1.0(@babel/core@7.23.9)(@opentelemetry/api@1.7.0)(react-dom@18.2.0)(react@18.2.0) react: specifier: ^18.2.0 version: 18.2.0 @@ -375,7 +375,7 @@ importers: version: 2.2.1 flowbite-react: specifier: 0.7.2 - version: 0.7.2(@types/react@18.2.8)(esbuild@0.17.18)(next@13.3.0)(react-dom@18.2.0)(react@18.2.0)(tailwindcss@3.3.1) + version: 0.7.2(@types/react@18.2.8)(esbuild@0.17.18)(next@14.1.0)(react-dom@18.2.0)(react@18.2.0)(tailwindcss@3.3.1) framer-motion: specifier: ^10.12.16 version: 10.12.16(react-dom@18.2.0)(react@18.2.0) @@ -383,8 +383,8 @@ importers: specifier: ^1.13.1 version: 1.13.1(@babel/core@7.23.9)(react@18.2.0) next: - specifier: 13.3.0 - version: 13.3.0(@babel/core@7.23.9)(@opentelemetry/api@1.7.0)(react-dom@18.2.0)(react@18.2.0) + specifier: 14.1.0 + version: 14.1.0(@babel/core@7.23.9)(@opentelemetry/api@1.7.0)(react-dom@18.2.0)(react@18.2.0) react: specifier: ^18.2.0 version: 18.2.0 @@ -445,7 +445,7 @@ importers: version: 2.2.1 flowbite-react: specifier: 0.7.2 - version: 0.7.2(@types/react@18.2.8)(esbuild@0.17.18)(next@13.3.0)(react-dom@18.2.0)(react@18.2.0)(tailwindcss@3.3.1) + version: 0.7.2(@types/react@18.2.8)(esbuild@0.17.18)(next@14.1.0)(react-dom@18.2.0)(react@18.2.0)(tailwindcss@3.3.1) framer-motion: specifier: ^10.12.16 version: 10.12.16(react-dom@18.2.0)(react@18.2.0) @@ -453,8 +453,8 @@ importers: specifier: ^1.13.1 version: 1.13.1(@babel/core@7.23.9)(react@18.2.0) next: - specifier: 13.3.0 - version: 13.3.0(@babel/core@7.23.9)(@opentelemetry/api@1.7.0)(react-dom@18.2.0)(react@18.2.0) + specifier: 14.1.0 + version: 14.1.0(@babel/core@7.23.9)(@opentelemetry/api@1.7.0)(react-dom@18.2.0)(react@18.2.0) react: specifier: ^18.2.0 version: 18.2.0 @@ -615,7 +615,7 @@ importers: version: 2.2.1 flowbite-react: specifier: 0.7.2 - version: 0.7.2(@types/react@18.2.8)(esbuild@0.17.18)(next@13.3.0)(react-dom@18.2.0)(react@18.2.0)(tailwindcss@3.3.1) + version: 0.7.2(@types/react@18.2.8)(esbuild@0.17.18)(next@14.1.0)(react-dom@18.2.0)(react@18.2.0)(tailwindcss@3.3.1) framer-motion: specifier: ^10.12.16 version: 10.12.16(react-dom@18.2.0)(react@18.2.0) @@ -626,8 +626,8 @@ importers: specifier: ^2.4.0 version: 2.4.0(react-dom@18.2.0)(react@18.2.0) next: - specifier: 13.3.0 - version: 13.3.0(@babel/core@7.23.9)(@opentelemetry/api@1.7.0)(react-dom@18.2.0)(react@18.2.0) + specifier: 14.1.0 + version: 14.1.0(@babel/core@7.23.9)(@opentelemetry/api@1.7.0)(react-dom@18.2.0)(react@18.2.0) react: specifier: ^18.2.0 version: 18.2.0 @@ -697,7 +697,7 @@ importers: version: 2.2.1 flowbite-react: specifier: 0.7.2 - version: 0.7.2(@types/react@18.2.8)(esbuild@0.17.18)(next@13.3.0)(react-dom@18.2.0)(react@18.2.0)(tailwindcss@3.3.1) + version: 0.7.2(@types/react@18.2.8)(esbuild@0.17.18)(next@14.1.0)(react-dom@18.2.0)(react@18.2.0)(tailwindcss@3.3.1) framer-motion: specifier: ^10.12.16 version: 10.12.16(react-dom@18.2.0)(react@18.2.0) @@ -708,8 +708,8 @@ importers: specifier: ^2.4.0 version: 2.4.0(react-dom@18.2.0)(react@18.2.0) next: - specifier: 13.3.0 - version: 13.3.0(@babel/core@7.23.9)(@opentelemetry/api@1.7.0)(react-dom@18.2.0)(react@18.2.0) + specifier: 14.1.0 + version: 14.1.0(@babel/core@7.23.9)(@opentelemetry/api@1.7.0)(react-dom@18.2.0)(react@18.2.0) react: specifier: ^18.2.0 version: 18.2.0 @@ -782,7 +782,7 @@ importers: version: 2.2.1 flowbite-react: specifier: 0.7.2 - version: 0.7.2(@types/react@18.2.8)(esbuild@0.17.18)(next@13.3.0)(react-dom@18.2.0)(react@18.2.0)(tailwindcss@3.3.1) + version: 0.7.2(@types/react@18.2.8)(esbuild@0.17.18)(next@14.1.0)(react-dom@18.2.0)(react@18.2.0)(tailwindcss@3.3.1) framer-motion: specifier: ^10.12.16 version: 10.12.16(react-dom@18.2.0)(react@18.2.0) @@ -793,8 +793,8 @@ importers: specifier: ^2.4.0 version: 2.4.0(react-dom@18.2.0)(react@18.2.0) next: - specifier: 13.3.0 - version: 13.3.0(@babel/core@7.23.9)(@opentelemetry/api@1.7.0)(react-dom@18.2.0)(react@18.2.0) + specifier: 14.1.0 + version: 14.1.0(@babel/core@7.23.9)(@opentelemetry/api@1.7.0)(react-dom@18.2.0)(react@18.2.0) react: specifier: ^18.2.0 version: 18.2.0 @@ -864,7 +864,7 @@ importers: version: 2.2.1 flowbite-react: specifier: 0.7.2 - version: 0.7.2(@types/react@18.2.8)(esbuild@0.17.18)(next@13.3.0)(react-dom@18.2.0)(react@18.2.0)(tailwindcss@3.3.1) + version: 0.7.2(@types/react@18.2.8)(esbuild@0.17.18)(next@14.1.0)(react-dom@18.2.0)(react@18.2.0)(tailwindcss@3.3.1) framer-motion: specifier: ^10.12.16 version: 10.12.16(react-dom@18.2.0)(react@18.2.0) @@ -875,8 +875,8 @@ importers: specifier: ^2.4.0 version: 2.4.0(react-dom@18.2.0)(react@18.2.0) next: - specifier: 13.3.0 - version: 13.3.0(@babel/core@7.23.9)(@opentelemetry/api@1.7.0)(react-dom@18.2.0)(react@18.2.0) + specifier: 14.1.0 + version: 14.1.0(@babel/core@7.23.9)(@opentelemetry/api@1.7.0)(react-dom@18.2.0)(react@18.2.0) react: specifier: ^18.2.0 version: 18.2.0 @@ -4939,6 +4939,7 @@ packages: { integrity: sha512-AjppRV4uG3No7L1plinoTQETH+j2F10TEnrMfzbTUYwze5sBUPveeeBAPZPm8OkJZ1epq9OyYKhZrvbD6/9HCQ== } + dev: true /@next/env@14.1.0: resolution: @@ -4956,6 +4957,7 @@ packages: cpu: [arm64] os: [darwin] requiresBuild: true + dev: true optional: true /@next/swc-darwin-arm64@14.1.0: @@ -4979,6 +4981,7 @@ packages: cpu: [x64] os: [darwin] requiresBuild: true + dev: true optional: true /@next/swc-darwin-x64@14.1.0: @@ -5002,6 +5005,7 @@ packages: cpu: [arm64] os: [linux] requiresBuild: true + dev: true optional: true /@next/swc-linux-arm64-gnu@14.1.0: @@ -5025,6 +5029,7 @@ packages: cpu: [arm64] os: [linux] requiresBuild: true + dev: true optional: true /@next/swc-linux-arm64-musl@14.1.0: @@ -5048,6 +5053,7 @@ packages: cpu: [x64] os: [linux] requiresBuild: true + dev: true optional: true /@next/swc-linux-x64-gnu@14.1.0: @@ -5071,6 +5077,7 @@ packages: cpu: [x64] os: [linux] requiresBuild: true + dev: true optional: true /@next/swc-linux-x64-musl@14.1.0: @@ -5094,6 +5101,7 @@ packages: cpu: [arm64] os: [win32] requiresBuild: true + dev: true optional: true /@next/swc-win32-arm64-msvc@14.1.0: @@ -5117,6 +5125,7 @@ packages: cpu: [ia32] os: [win32] requiresBuild: true + dev: true optional: true /@next/swc-win32-ia32-msvc@14.1.0: @@ -5140,6 +5149,7 @@ packages: cpu: [x64] os: [win32] requiresBuild: true + dev: true optional: true /@next/swc-win32-x64-msvc@14.1.0: @@ -7449,6 +7459,7 @@ packages: } dependencies: tslib: 2.6.2 + dev: true /@swc/helpers@0.5.2: resolution: @@ -12117,7 +12128,7 @@ packages: react-markdown: 9.0.1(@types/react@18.2.8)(react@18.2.0) sharp: 0.32.6 tailwind-merge: 2.2.1 - tailwindcss: 3.3.1(postcss@8.4.23) + tailwindcss: 3.3.1(postcss@8.4.31) transitivePeerDependencies: - '@effect-ts/otel-node' - '@types/react' @@ -12125,6 +12136,7 @@ packages: - markdown-wasm - next - supports-color + dev: true /flowbite-react@0.7.2(@types/react@18.2.8)(esbuild@0.17.18)(next@14.1.0)(react-dom@18.2.0)(react@18.2.0)(tailwindcss@3.3.1): resolution: @@ -15815,6 +15827,7 @@ packages: - esbuild - markdown-wasm - supports-color + dev: true /next-contentlayer@0.3.4(contentlayer@0.3.4)(esbuild@0.17.18)(next@14.1.0)(react-dom@18.2.0)(react@18.2.0): resolution: @@ -15840,7 +15853,7 @@ packages: - supports-color dev: false - /next-intl@2.17.5(next@13.3.0)(react@18.2.0): + /next-intl@2.17.5(next@14.1.0)(react@18.2.0): resolution: { integrity: sha512-p/tit4/FN0eHLw6Mjwsx4ktiFZWq9VMcuY9hhkAlYWXCQgKq09PB0lZcMNw5xLvV9eor818BzXxdA+3bSvFMmw== @@ -15852,7 +15865,7 @@ packages: dependencies: '@formatjs/intl-localematcher': 0.2.32 negotiator: 0.6.3 - next: 13.3.0(@babel/core@7.23.9)(@opentelemetry/api@1.7.0)(react-dom@18.2.0)(react@18.2.0) + next: 14.1.0(@babel/core@7.23.9)(@opentelemetry/api@1.7.0)(react-dom@18.2.0)(react@18.2.0) react: 18.2.0 use-intl: 2.17.5(react@18.2.0) dev: false @@ -15903,6 +15916,7 @@ packages: transitivePeerDependencies: - '@babel/core' - babel-plugin-macros + dev: true /next@14.1.0(@babel/core@7.23.9)(@opentelemetry/api@1.7.0)(react-dom@18.2.0)(react@18.2.0): resolution: @@ -16855,6 +16869,7 @@ packages: nanoid: 3.3.6 picocolors: 1.0.0 source-map-js: 1.0.2 + dev: true /postcss@8.4.23: resolution: From 902cad1e78db03bdcc85087bdc9a6983c10972e7 Mon Sep 17 00:00:00 2001 From: Ncookiez Date: Tue, 26 Mar 2024 15:57:12 -0400 Subject: [PATCH 082/161] updated toucan testnet --- apps/analytics/src/constants/config.ts | 4 +- apps/app/src/constants/config.ts | 2 +- apps/app/src/vaultLists/default.ts | 4 +- apps/app/src/vaultLists/testnet.ts | 28 +-- apps/rewards-builder/src/constants/config.ts | 2 +- apps/vault-factory/src/atoms.ts | 8 +- .../src/components/CreateVaultStepInfo.tsx | 2 +- .../forms/DeployLiquidationPairForm.tsx | 26 +- .../components/forms/ExchangeRateInput.tsx | 103 -------- .../forms/MinimumAuctionAmountInput.tsx | 7 +- .../components/forms/SmoothingFactorInput.tsx | 60 +++++ apps/vault-factory/src/constants/config.ts | 34 +-- .../src/hooks/useLiquidationPairInfo.ts | 39 +-- .../useLiquidationPairInitialAmountIn.ts | 38 --- .../src/hooks/useUserDeployedVaults.ts | 4 +- apps/vault-factory/src/types.ts | 2 +- ...useSendDeployLiquidationPairTransaction.ts | 32 +-- shared/react-components/constants.ts | 16 +- shared/types/types/liquidations.ts | 8 +- shared/utilities/abis/liquidationPair.ts | 220 ++--------------- .../utilities/abis/liquidationPairFactory.ts | 37 ++- shared/utilities/abis/liquidationRouter.ts | 12 +- shared/utilities/abis/opGasOracle.ts | 29 +++ shared/utilities/constants.ts | 227 +++++++++--------- shared/utilities/utils/events.ts | 2 +- 25 files changed, 318 insertions(+), 628 deletions(-) delete mode 100644 apps/vault-factory/src/components/forms/ExchangeRateInput.tsx create mode 100644 apps/vault-factory/src/components/forms/SmoothingFactorInput.tsx delete mode 100644 apps/vault-factory/src/hooks/useLiquidationPairInitialAmountIn.ts diff --git a/apps/analytics/src/constants/config.ts b/apps/analytics/src/constants/config.ts index 508cd2cb..3eab913e 100644 --- a/apps/analytics/src/constants/config.ts +++ b/apps/analytics/src/constants/config.ts @@ -32,7 +32,7 @@ export const RPC_URLS = { * Queries' start blocks */ export const QUERY_START_BLOCK: { [chainId: number]: bigint } = { - [NETWORK.optimism_sepolia]: 9_270_700n + [NETWORK.optimism_sepolia]: 9_801_300n } /** @@ -66,7 +66,7 @@ export const BURN_SETTINGS: { }, [NETWORK.optimism_sepolia]: { burnTokenAddress: POOL_TOKEN_ADDRESSES[NETWORK.optimism_sepolia], - liquidationPairAddress: '0xd20777642ba9441d0b7a3f9f53b2ef0255ec7c31', + liquidationPairAddress: '0xd781b45644fb5b5d8c76a991da2365b8272e932d', burnAddresses: [DEAD_ADDRESS] } } diff --git a/apps/app/src/constants/config.ts b/apps/app/src/constants/config.ts index 9c32f19f..ee600d5f 100644 --- a/apps/app/src/constants/config.ts +++ b/apps/app/src/constants/config.ts @@ -100,7 +100,7 @@ export const TWAB_REWARDS_SETTINGS: { USDC_TOKEN_ADDRESSES[NETWORK.optimism_sepolia], POOL_TOKEN_ADDRESSES[NETWORK.optimism_sepolia] ], - fromBlock: 9_270_700n + fromBlock: 9_801_300n } } diff --git a/apps/app/src/vaultLists/default.ts b/apps/app/src/vaultLists/default.ts index daf7bb87..f6b0900f 100644 --- a/apps/app/src/vaultLists/default.ts +++ b/apps/app/src/vaultLists/default.ts @@ -6,8 +6,8 @@ import { testnetVaults } from './testnet' const defaultVaultList: VaultList = { name: 'Cabana Vault List', keywords: ['pooltogether', 'cabana', 'g9', 'optimism'], - version: { major: 2, minor: 0, patch: 0 }, - timestamp: '2024-03-13T19:04:47Z', + version: { major: 2, minor: 0, patch: 1 }, + timestamp: '2024-03-26T19:36:50Z', logoURI: `${LINKS.app}/pooltogether-token-logo.svg`, tokens: [ // { diff --git a/apps/app/src/vaultLists/testnet.ts b/apps/app/src/vaultLists/testnet.ts index d09dfcca..47e5586e 100644 --- a/apps/app/src/vaultLists/testnet.ts +++ b/apps/app/src/vaultLists/testnet.ts @@ -4,14 +4,14 @@ import { NETWORK } from '@shared/utilities' export const testnetVaults: VaultList['tokens'] = [ { chainId: NETWORK.optimism_sepolia, - address: '0x332b1EB2Cc4046954725EbDFB8143fB8354ea9a7', + address: '0x8f8484f30F7A72c8059E6BD709f898606e38DedA', name: 'Prize DAI - LY', decimals: 18, symbol: 'PDAI-LY', logoURI: 'https://assets.coingecko.com/coins/images/9956/small/4943.png?1636636734', extensions: { underlyingAsset: { - address: '0x34F166839C655F2DcD56638F2CE779fd9B5987a6', + address: '0x8261Cb9519DD1D80B5ce66B0887C6fCEeA8a64eE', symbol: 'DAI', name: 'Dai Stablecoin' } @@ -19,14 +19,14 @@ export const testnetVaults: VaultList['tokens'] = [ }, { chainId: NETWORK.optimism_sepolia, - address: '0x13E37b0Ca8b48fc2818C177c24635F90C1495C5c', + address: '0x5B0182E62Baee8Be36AC15696E5C78A0c89b465F', name: 'Prize DAI - HY', decimals: 18, symbol: 'PDAI-HY', logoURI: 'https://assets.coingecko.com/coins/images/9956/small/4943.png?1636636734', extensions: { underlyingAsset: { - address: '0x34F166839C655F2DcD56638F2CE779fd9B5987a6', + address: '0x8261Cb9519DD1D80B5ce66B0887C6fCEeA8a64eE', symbol: 'DAI', name: 'Dai Stablecoin' } @@ -34,14 +34,14 @@ export const testnetVaults: VaultList['tokens'] = [ }, { chainId: NETWORK.optimism_sepolia, - address: '0x602d77e900eCD48ac9b51151936Dcc5Efe2e7FaE', + address: '0x383E8D88De4E3999b43C51cA1819516617260e99', name: 'Prize USDC - LY', decimals: 6, symbol: 'PUSDC-LY', logoURI: 'https://etherscan.io/token/images/centre-usdc_28.png', extensions: { underlyingAsset: { - address: '0xE9CB1A8c3C1b5bcE7c6C0FB15F31A3A56209207F', + address: '0x0E13bF42f927575475894f2d5076a7Ac77060eA0', symbol: 'USDC', name: 'USD Coin' } @@ -49,14 +49,14 @@ export const testnetVaults: VaultList['tokens'] = [ }, { chainId: NETWORK.optimism_sepolia, - address: '0xA2B0321B671A83a98Ff1F5a680b700864f57c6e7', + address: '0xe8AD34CB77b8DCE62DEd796DCB10b8f574d6A619', name: 'Prize USDC - HY', decimals: 6, symbol: 'PUSDC-HY', logoURI: 'https://etherscan.io/token/images/centre-usdc_28.png', extensions: { underlyingAsset: { - address: '0xE9CB1A8c3C1b5bcE7c6C0FB15F31A3A56209207F', + address: '0x0E13bF42f927575475894f2d5076a7Ac77060eA0', symbol: 'USDC', name: 'USD Coin' } @@ -64,7 +64,7 @@ export const testnetVaults: VaultList['tokens'] = [ }, { chainId: NETWORK.optimism_sepolia, - address: '0xd96702995B2bBD78a9A39eF86f4fA5f9704fdC7D', + address: '0x7eb63F62f2E1E4646793D3dA9C1A232A5f5710B5', name: 'Prize GUSD', decimals: 2, symbol: 'PGUSD', @@ -72,7 +72,7 @@ export const testnetVaults: VaultList['tokens'] = [ 'https://assets.coingecko.com/coins/images/5992/small/gemini-dollar-gusd.png?1536745278', extensions: { underlyingAsset: { - address: '0xCe1fe3170d4ACEFBc3d06595EeF3A918F65000c2', + address: '0x493c7081FAab6e5B2d6b18d9311918580e88c6bF', symbol: 'GUSD', name: 'Gemini dollar' } @@ -80,14 +80,14 @@ export const testnetVaults: VaultList['tokens'] = [ }, { chainId: NETWORK.optimism_sepolia, - address: '0xE77Db9f8b68BC47A82D4F47E68FB57535dF0086e', + address: '0x1B751A1F3b558173DF9832d4564E6B38db7552c6', name: 'Prize WBTC', decimals: 8, symbol: 'PWBTC', logoURI: 'https://etherscan.io/token/images/wbtc_28.png?v=1', extensions: { underlyingAsset: { - address: '0x42fd018A6ac84478f28b3f7e322271C83064d737', + address: '0x45bbc6B553D2Afc4d3e376B22f70A67d9a26f819', symbol: 'WBTC', name: 'Wrapped BTC' } @@ -95,14 +95,14 @@ export const testnetVaults: VaultList['tokens'] = [ }, { chainId: NETWORK.optimism_sepolia, - address: '0x98CED5d595e8981756f063db8D3c44a6Be9A8F86', + address: '0xf04Aa80EaC0043C8F8328Dd35385aaf2C0ed8E9a', name: 'Prize WETH', decimals: 18, symbol: 'PWETH', logoURI: 'https://etherscan.io/token/images/weth_28.png', extensions: { underlyingAsset: { - address: '0x1bcd630e1303cef37F19743fbFE84b1b14e7750c', + address: '0xD5C2a983D320a881F21Dc68fd89f905Ff1517B2C', symbol: 'WETH', name: 'Wrapped Ether' } diff --git a/apps/rewards-builder/src/constants/config.ts b/apps/rewards-builder/src/constants/config.ts index a9c8469a..30060cdb 100644 --- a/apps/rewards-builder/src/constants/config.ts +++ b/apps/rewards-builder/src/constants/config.ts @@ -74,5 +74,5 @@ export const PROMOTION_FILTERS: { } = { [NETWORK.mainnet]: {}, [NETWORK.optimism]: { fromBlock: 112_933_000n }, - [NETWORK.optimism_sepolia]: { fromBlock: 9_270_700n } + [NETWORK.optimism_sepolia]: { fromBlock: 9_801_300n } } diff --git a/apps/vault-factory/src/atoms.ts b/apps/vault-factory/src/atoms.ts index a50c938b..368c11d3 100644 --- a/apps/vault-factory/src/atoms.ts +++ b/apps/vault-factory/src/atoms.ts @@ -88,14 +88,14 @@ export const vaultIdsAtom = atom(getInitialVaultIds()) export const liquidationPairStepCounterAtom = atom(0) /** - * Liquidation Pair Initial POOL Exchange Rate + * Liquidation Pair Minimum Auction Share Amount */ -export const liquidationPairInitialAmountInAtom = atom(undefined) +export const liquidationPairMinimumAuctionAmountAtom = atom(undefined) /** - * Liquidation Pair Minimum Auction Share Amount + * Liquidation Pair Smoothing Factor */ -export const liquidationPairMinimumAuctionAmountAtom = atom(undefined) +export const liquidationPairSmoothingFactorAtom = atom(0) /** * Liquidation Pair Address diff --git a/apps/vault-factory/src/components/CreateVaultStepInfo.tsx b/apps/vault-factory/src/components/CreateVaultStepInfo.tsx index c85841de..130b9883 100644 --- a/apps/vault-factory/src/components/CreateVaultStepInfo.tsx +++ b/apps/vault-factory/src/components/CreateVaultStepInfo.tsx @@ -46,7 +46,7 @@ export const allVaultStepInfo: { title: string; info: ReactNode }[] = [ }, { title: 'Deploy your liquidation pair', - info: `This is the contract that enables your prize vault's yield to be liquidated for POOL prizes. We've set some initial settings automatically, but feel free to customize these.` + info: `This is the contract that enables your prize vault's yield to be liquidated and sent to the prize pool. We've set some initial settings automatically, but feel free to customize these.` }, { title: 'Set the liquidation pair to your prize vault', diff --git a/apps/vault-factory/src/components/forms/DeployLiquidationPairForm.tsx b/apps/vault-factory/src/components/forms/DeployLiquidationPairForm.tsx index ce9fea41..6e36c4bc 100644 --- a/apps/vault-factory/src/components/forms/DeployLiquidationPairForm.tsx +++ b/apps/vault-factory/src/components/forms/DeployLiquidationPairForm.tsx @@ -1,8 +1,4 @@ -import { - usePrizePool, - usePrizeTokenPrice, - useToken -} from '@generationsoftware/hyperstructure-react-hooks' +import { useToken } from '@generationsoftware/hyperstructure-react-hooks' import { Spinner } from '@shared/ui' import classNames from 'classnames' import { useAtomValue } from 'jotai' @@ -11,17 +7,15 @@ import { vaultAddressAtom, vaultChainIdAtom } from 'src/atoms' import { SupportedNetwork } from 'src/types' import { Address } from 'viem' import { DeployLiquidationPairButton } from '@components/buttons/DeployLiquidationPairButton' -import { NETWORK_CONFIG } from '@constants/config' -import { useLiquidationPairInitialAmountIn } from '@hooks/useLiquidationPairInitialAmountIn' import { useLiquidationPairMinimumAuctionAmount } from '@hooks/useLiquidationPairMinimumAuctionAmount' import { useLiquidationPairSteps } from '@hooks/useLiquidationPairSteps' import { useVaultCreationSteps } from '@hooks/useVaultCreationSteps' -import { ExchangeRateInput } from './ExchangeRateInput' import { MinimumAuctionAmountInput } from './MinimumAuctionAmountInput' +import { SmoothingFactorInput } from './SmoothingFactorInput' export interface DeployLiquidationPairFormValues { - initialExchangeRate: string minimumAuctionAmount: string + smoothingFactor: string } interface DeployLiquidationPairFormProps { @@ -39,18 +33,14 @@ export const DeployLiquidationPairForm = (props: DeployLiquidationPairFormProps) const chainId = useAtomValue(vaultChainIdAtom) as SupportedNetwork const vaultAddress = useAtomValue(vaultAddressAtom) as Address - const prizePool = usePrizePool(chainId, NETWORK_CONFIG[chainId].prizePool) - const { data: prizeToken } = usePrizeTokenPrice(prizePool) - const { data: shareToken } = useToken(chainId, vaultAddress) - const { data: defaultInitialAmountIn } = useLiquidationPairInitialAmountIn(chainId, vaultAddress) const { data: defaultMinimumAuctionAmount } = useLiquidationPairMinimumAuctionAmount( chainId, vaultAddress ) - if (!prizeToken || !shareToken || !defaultInitialAmountIn || !defaultMinimumAuctionAmount) { + if (!shareToken || !defaultMinimumAuctionAmount) { return } @@ -65,12 +55,12 @@ export const DeployLiquidationPairForm = (props: DeployLiquidationPairFormProps) onSubmit={formMethods.handleSubmit(() => {})} className={classNames('flex flex-col grow gap-12 items-center', className)} > - - + { - const { prizeToken, vaultAddress, shareSymbol, className, inputClassName } = props - - const [initialAmountIn, setInitialAmountIn] = useAtom(liquidationPairInitialAmountInAtom) - - const { initialExchangeRate } = useWatch() - - const { setValue } = useFormContext() - - const { data: defaultInitialAmountIn } = useLiquidationPairInitialAmountIn( - prizeToken.chainId, - vaultAddress - ) - - useEffect(() => { - setValue( - 'initialExchangeRate', - formatUnits(initialAmountIn ?? defaultInitialAmountIn ?? 0n, prizeToken.decimals), - { shouldValidate: true } - ) - if (!initialAmountIn) { - setInitialAmountIn(defaultInitialAmountIn) - } - }, []) - - useEffect(() => { - if (!!initialExchangeRate && isValidExchangeRate(initialExchangeRate, prizeToken.decimals)) { - const parsedExchangeRate = parseUnits(initialExchangeRate, prizeToken.decimals) - setInitialAmountIn(parsedExchangeRate) - } - }, [initialExchangeRate]) - - return ( -
- 1 {shareSymbol} = -
- /^-?\d+\.?\d*$/.test(v) || 'Enter a valid number.', - isPositiveNumber: (v: string) => parseFloat(v) > 0 || 'Enter a number larger than 0.', - isNotTooPrecise: (v) => - v.split('.').length < 2 || - v.split('.')[1].length <= prizeToken.decimals || - 'Too many decimals' - }} - defaultValue={ - !!defaultInitialAmountIn - ? formatUnits(defaultInitialAmountIn, prizeToken.decimals) - : undefined - } - className={classNames('w-full', inputClassName)} - /> - - {prizeToken.symbol} - - - ≈{' '} - - -
-
- ) -} - -const isValidExchangeRate = (val: string, maxDecimals: number) => { - return ( - !!val && - /^-?\d+\.?\d*$/.test(val) && - parseFloat(val) > 0 && - (val.split('.').length < 2 || val.split('.')[1].length <= maxDecimals) - ) -} diff --git a/apps/vault-factory/src/components/forms/MinimumAuctionAmountInput.tsx b/apps/vault-factory/src/components/forms/MinimumAuctionAmountInput.tsx index a0013461..fd10d29e 100644 --- a/apps/vault-factory/src/components/forms/MinimumAuctionAmountInput.tsx +++ b/apps/vault-factory/src/components/forms/MinimumAuctionAmountInput.tsx @@ -57,12 +57,7 @@ export const MinimumAuctionAmountInput = (props: MinimumAuctionAmountInputProps) }, [_minimumAuctionAmount]) return ( -
+
{ + const { className } = props + + const [smoothingFactor, setSmoothingFactor] = useAtom(liquidationPairSmoothingFactorAtom) + + const { smoothingFactor: _smoothingFactor } = useWatch() + + const { setValue } = useFormContext() + + useEffect(() => { + setValue('smoothingFactor', smoothingFactor.toString(), { shouldValidate: true }) + }, []) + + useEffect(() => { + if (!!_smoothingFactor && isValidSmoothingFactor(_smoothingFactor)) { + setSmoothingFactor(parseFloat(_smoothingFactor)) + } + }, [_smoothingFactor]) + + return ( + /^-?\d+\.?\d*$/.test(v) || 'Enter a valid number.', + isValidRange: (v: string) => + (parseFloat(v) >= 0 && parseFloat(v) < 1) || + 'Enter a number between 0 (inclusive) and 1 (exclusive).', + isNotTooPrecise: (v) => + v.split('.').length < 2 || v.split('.')[1].length <= 18 || 'Too many decimals' + }} + label='Smoothing Factor' + defaultValue={'0'} + needsOverride={true} + keepValueOnOverride={true} + className={className} + /> + ) +} + +const isValidSmoothingFactor = (val: string) => { + return ( + !!val && + /^-?\d+\.?\d*$/.test(val) && + parseFloat(val) >= 0 && + parseFloat(val) < 1 && + (val.split('.').length < 2 || val.split('.')[1].length <= 18) + ) +} diff --git a/apps/vault-factory/src/constants/config.ts b/apps/vault-factory/src/constants/config.ts index 60f33e06..569258bf 100644 --- a/apps/vault-factory/src/constants/config.ts +++ b/apps/vault-factory/src/constants/config.ts @@ -76,11 +76,7 @@ export const NETWORK_CONFIG: Record< description: string prizePool: Address claimer: Address - lp: { - targetFirstSaleTimeFraction: number - liquidationGasAmount: bigint - minAuctionAmountEth: number - } + lp: { targetAuctionPeriodFraction: number; minAuctionAmountEth: number } yieldSources: { id: string name: string @@ -94,22 +90,14 @@ export const NETWORK_CONFIG: Record< // description: 'The OG optimistic rollup on Ethereum.', // prizePool: '', // claimer: DEFAULT_CLAIMER_ADDRESSES[NETWORK.optimism], - // lp: { - // targetFirstSaleTimeFraction: 0.5, - // liquidationGasAmount: 300_000n, - // minAuctionAmountEth: 0.001 - // }, + // lp: { targetAuctionPeriodFraction: 0.5, minAuctionAmountEth: 0.001 }, // yieldSources: [] // }, [NETWORK.optimism_sepolia]: { description: 'Sepolia testnet for the Optimism network.', - prizePool: '0x5e1b40e4249644a7d7589d1197AD0F1628e79FB1', + prizePool: '0x31547D3c38F2F8dC92421C54B173F3B27Ab26EbB', claimer: DEFAULT_CLAIMER_ADDRESSES[NETWORK.optimism_sepolia], - lp: { - targetFirstSaleTimeFraction: 0.5, - liquidationGasAmount: 300_000n, - minAuctionAmountEth: 0.001 - }, + lp: { targetAuctionPeriodFraction: 0.5, minAuctionAmountEth: 0.001 }, yieldSources: [ { id: 'aave', @@ -117,13 +105,13 @@ export const NETWORK_CONFIG: Record< href: 'https://aave.com/', description: 'Lending and borrowing protocol', vaults: [ - { address: '0x4Cf96b676a347E8647eEb6AAeA99F40cA76ed342', tags: ['stablecoin'] }, - { address: '0xBfF0113396fed91700A088F993b96B5473EB1497', tags: ['stablecoin'] }, - { address: '0xe661730EC120D78961542bc77f197792b01E7AFC', tags: ['stablecoin'] }, - { address: '0x5323ad247241A38e7169D694C58c8d84DE4b43B2', tags: ['stablecoin'] }, - { address: '0xbe2ca778890B9297d3Db17ae86f548B0E298224e', tags: ['stablecoin'] }, - { address: '0x7887F1e815847d896D52fFB10dEdf6eB09e967E9' }, - { address: '0xcC6b662bdf918583d2a5EcF4db1787C438e699dC' } + { address: '0xeE71a7CdE1bA4896D5Bd7D33DEDEd67D0e8bA534', tags: ['stablecoin'] }, + { address: '0x6F626779fb5AB0F1Bba6EeE45F5D556A796e9341', tags: ['stablecoin'] }, + { address: '0x2332B17419a9F6BA122572Aa820Ba8f8E3D08c20', tags: ['stablecoin'] }, + { address: '0x8c2cbfeCd13344E48464c91bF7eA705aDD74D9D8', tags: ['stablecoin'] }, + { address: '0xB1126119dD12Bc11afB35A25D33c19ac60A64d1f', tags: ['stablecoin'] }, + { address: '0x5C28E1b31E88344606015479a4f2cfF4cB7bfAa1' }, + { address: '0x9CfC71e201fD7E9F2C758D1cF34D33c9Bd4c32E9' } ] } ] diff --git a/apps/vault-factory/src/hooks/useLiquidationPairInfo.ts b/apps/vault-factory/src/hooks/useLiquidationPairInfo.ts index 287b22af..671755aa 100644 --- a/apps/vault-factory/src/hooks/useLiquidationPairInfo.ts +++ b/apps/vault-factory/src/hooks/useLiquidationPairInfo.ts @@ -1,18 +1,12 @@ -import { - useFirstDrawOpenedAt, - usePrizePool, - useVault, - useVaultShareData -} from '@generationsoftware/hyperstructure-react-hooks' import { PairCreateInfo } from '@shared/types' import { POOL_TOKEN_ADDRESSES, PRIZE_POOLS } from '@shared/utilities' import { useAtomValue } from 'jotai' import { - liquidationPairInitialAmountInAtom, - liquidationPairMinimumAuctionAmountAtom + liquidationPairMinimumAuctionAmountAtom, + liquidationPairSmoothingFactorAtom } from 'src/atoms' import { SupportedNetwork } from 'src/types' -import { Address, parseEther, parseUnits } from 'viem' +import { Address } from 'viem' import { NETWORK_CONFIG } from '@constants/config' /** @@ -25,37 +19,24 @@ export const useLiquidationPairInfo = ( chainId: SupportedNetwork, vaultAddress: Address ): Partial => { - const initialAmountIn = useAtomValue(liquidationPairInitialAmountInAtom) const minimumAuctionAmount = useAtomValue(liquidationPairMinimumAuctionAmountAtom) - - const vault = useVault({ chainId, address: vaultAddress }) - const { data: shareToken } = useVaultShareData(vault) + const smoothingFactor = useAtomValue(liquidationPairSmoothingFactorAtom) const prizePoolInfo = PRIZE_POOLS.find( (pool) => pool.chainId === chainId ) as (typeof PRIZE_POOLS)[number] - const prizePool = usePrizePool(chainId, prizePoolInfo.address) - const { data: periodOffset } = useFirstDrawOpenedAt(prizePool) - - const periodLength = prizePoolInfo.options.drawPeriodInSeconds - const targetFirstSaleTime = NETWORK_CONFIG[chainId].lp.targetFirstSaleTimeFraction * periodLength - - const decayConstant = parseEther('130') / BigInt(periodLength * 50) - - const initialAmountOut = !!shareToken ? parseUnits('1', shareToken.decimals) : undefined + const drawPeriodLength = prizePoolInfo.options.drawPeriodInSeconds + const targetAuctionPeriod = + NETWORK_CONFIG[chainId].lp.targetAuctionPeriodFraction * drawPeriodLength return { chainId, source: vaultAddress, tokenIn: POOL_TOKEN_ADDRESSES[chainId], tokenOut: vaultAddress, - periodLength, - periodOffset, - targetFirstSaleTime, - decayConstant, - initialAmountIn, - initialAmountOut, - minimumAuctionAmount + targetAuctionPeriod, + minimumAuctionAmount, + smoothingFactor } } diff --git a/apps/vault-factory/src/hooks/useLiquidationPairInitialAmountIn.ts b/apps/vault-factory/src/hooks/useLiquidationPairInitialAmountIn.ts deleted file mode 100644 index 8037ed29..00000000 --- a/apps/vault-factory/src/hooks/useLiquidationPairInitialAmountIn.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { - usePrizePool, - usePrizeTokenPrice, - useVault, - useVaultSharePrice -} from '@generationsoftware/hyperstructure-react-hooks' -import { PRIZE_POOLS } from '@shared/utilities' -import { SupportedNetwork } from 'src/types' -import { Address, parseUnits } from 'viem' - -/** - * Returns an initial exchange rate for POOL on the liquidation pair - * @param chainId chain ID of the liquidation pair - * @param vaultAddress vault address to configure for - * @returns - */ -export const useLiquidationPairInitialAmountIn = ( - chainId: SupportedNetwork, - vaultAddress: Address -) => { - const vault = useVault({ chainId, address: vaultAddress }) - const { data: shareToken, isFetched: isFetchedShareToken } = useVaultSharePrice(vault) - - const prizePoolAddress = PRIZE_POOLS.find((pool) => pool.chainId === chainId)?.address as Address - - const prizePool = usePrizePool(chainId, prizePoolAddress) - const { data: prizeToken, isFetched: isFetchedPrizeToken } = usePrizeTokenPrice(prizePool) - - const isFetched = isFetchedShareToken && isFetchedPrizeToken - - const initialAmountIn = isFetched - ? !!shareToken?.price && !!prizeToken?.price - ? parseUnits(`${shareToken.price / prizeToken.price}`, prizeToken.decimals) - : parseUnits('1', prizeToken?.decimals ?? 18) - : undefined - - return { data: initialAmountIn, isFetched } -} diff --git a/apps/vault-factory/src/hooks/useUserDeployedVaults.ts b/apps/vault-factory/src/hooks/useUserDeployedVaults.ts index a573c3c1..2a9c645a 100644 --- a/apps/vault-factory/src/hooks/useUserDeployedVaults.ts +++ b/apps/vault-factory/src/hooks/useUserDeployedVaults.ts @@ -13,12 +13,12 @@ export const useUserDeployedVaults = () => { const [vaultIds, setVaultIds] = useAtom(vaultIdsAtom) const addVault = (vaultInfo: VaultInfo) => { - const vaultId = getVaultId(vaultInfo).toLowerCase() + const vaultId = getVaultId(vaultInfo) setVaultIds((prev) => Array.from(new Set([...prev, vaultId]))) } const removeVault = (vaultInfo: VaultInfo) => { - const vaultId = getVaultId(vaultInfo).toLowerCase() + const vaultId = getVaultId(vaultInfo) setVaultIds((prev) => prev.filter((id) => id !== vaultId)) } diff --git a/apps/vault-factory/src/types.ts b/apps/vault-factory/src/types.ts index 1082c8d4..a6dbea7e 100644 --- a/apps/vault-factory/src/types.ts +++ b/apps/vault-factory/src/types.ts @@ -12,8 +12,8 @@ export type FormKey = | 'vaultName' | 'vaultSymbol' | 'vaultClaimer' - | 'initialExchangeRate' | 'minimumAuctionAmount' + | 'smoothingFactor' | 'deployedVaultChainId' | 'deployedVaultAddress' | 'lpAddress' diff --git a/packages/hyperstructure-react-hooks/src/transactions/useSendDeployLiquidationPairTransaction.ts b/packages/hyperstructure-react-hooks/src/transactions/useSendDeployLiquidationPairTransaction.ts index 13584be6..83aeefb8 100644 --- a/packages/hyperstructure-react-hooks/src/transactions/useSendDeployLiquidationPairTransaction.ts +++ b/packages/hyperstructure-react-hooks/src/transactions/useSendDeployLiquidationPairTransaction.ts @@ -1,7 +1,7 @@ import { PairCreateInfo } from '@shared/types' import { LIQUIDATION_PAIR_FACTORY_ADDRESSES, liquidationPairFactoryABI } from '@shared/utilities' import { useEffect } from 'react' -import { Address, TransactionReceipt } from 'viem' +import { Address, parseEther, TransactionReceipt } from 'viem' import { useAccount, useSimulateContract, @@ -38,13 +38,9 @@ export const useSendDeployLiquidationPairTransaction = ( source, tokenIn, tokenOut, - periodLength, - periodOffset, - targetFirstSaleTime, - decayConstant, - initialAmountIn, - initialAmountOut, - minimumAuctionAmount + targetAuctionPeriod, + minimumAuctionAmount, + smoothingFactor } = pairCreateInfo const liquidationPairFactoryAddress = !!chainId @@ -60,13 +56,9 @@ export const useSendDeployLiquidationPairTransaction = ( !!chainId && !!tokenIn && !!tokenOut && - periodLength !== undefined && - periodOffset !== undefined && - targetFirstSaleTime !== undefined && - decayConstant !== undefined && - initialAmountIn !== undefined && - initialAmountOut !== undefined && - minimumAuctionAmount !== undefined && + !!targetAuctionPeriod && + !!minimumAuctionAmount && + smoothingFactor !== undefined && chain?.id === chainId const { data } = useSimulateContract({ @@ -78,13 +70,9 @@ export const useSendDeployLiquidationPairTransaction = ( source, tokenIn, tokenOut, - periodLength, - periodOffset, - targetFirstSaleTime, - decayConstant, - initialAmountIn, - initialAmountOut, - minimumAuctionAmount + BigInt(targetAuctionPeriod), + minimumAuctionAmount, + parseEther(`${smoothingFactor}`) ], query: { enabled } }) diff --git a/shared/react-components/constants.ts b/shared/react-components/constants.ts index 56f1cbb7..08b286e5 100644 --- a/shared/react-components/constants.ts +++ b/shared/react-components/constants.ts @@ -1,4 +1,4 @@ -import { NETWORK, POOL_TOKEN_ADDRESSES } from '@shared/utilities' +import { NETWORK, POOL_TOKEN_ADDRESSES, USDC_TOKEN_ADDRESSES } from '@shared/utilities' /** * Token Logo URLs @@ -37,6 +37,7 @@ export const TOKEN_LOGO_OVERRIDES: Record [NETWORK.polygon]: { [POOL_TOKEN_ADDRESSES[NETWORK.polygon].toLowerCase()]: tokenLogoUrls.pool, '0x2791bca1f2de4661ed88a30c99a7a9449aa84174': tokenLogoUrls.usdc, + '0x3c499c542cef5e3811e1192ce70d8cc03d5c3359': tokenLogoUrls.usdc, '0x8f3cf7ad23cd3cadbd9735aff958023239c6a063': tokenLogoUrls.dai, '0xc8a94a3d3d2dabc3c1caffffdca6a7543c3e3e65': tokenLogoUrls.gusd, '0x7ceb23fd6bc0add59e62ac25578270cff1b9f619': tokenLogoUrls.weth, @@ -46,6 +47,7 @@ export const TOKEN_LOGO_OVERRIDES: Record [NETWORK.optimism]: { [POOL_TOKEN_ADDRESSES[NETWORK.optimism].toLowerCase()]: tokenLogoUrls.pool, '0x7f5c764cbc14f9669b88837ca1490cca17c31607': tokenLogoUrls.usdc, + '0x0b2c639c533813f4aa9d7837caf62653d097ff85': tokenLogoUrls.usdc, '0xda10009cbd5d07dd0cecc66161fc93d7c9000da1': tokenLogoUrls.dai, '0x4200000000000000000000000000000000000006': tokenLogoUrls.weth, '0x68f180fcce6836688e9084f035309e29bf0a2095': tokenLogoUrls.wbtc, @@ -54,12 +56,12 @@ export const TOKEN_LOGO_OVERRIDES: Record '0x4200000000000000000000000000000000000042': tokenLogoUrls.op }, [NETWORK.optimism_sepolia]: { - '0x264954576da8496cc0d2216df81a7d7a38857329': tokenLogoUrls.pool, - '0xe9cb1a8c3c1b5bce7c6c0fb15f31a3a56209207f': tokenLogoUrls.usdc, - '0x34f166839c655f2dcd56638f2ce779fd9b5987a6': tokenLogoUrls.dai, - '0xce1fe3170d4acefbc3d06595eef3a918f65000c2': tokenLogoUrls.gusd, - '0x1bcd630e1303cef37f19743fbfe84b1b14e7750c': tokenLogoUrls.weth, - '0x42fd018a6ac84478f28b3f7e322271c83064d737': tokenLogoUrls.wbtc + [POOL_TOKEN_ADDRESSES[NETWORK.optimism_sepolia].toLowerCase()]: tokenLogoUrls.pool, + [USDC_TOKEN_ADDRESSES[NETWORK.optimism_sepolia]]: tokenLogoUrls.usdc, + '0x8261cb9519dd1d80b5ce66b0887c6fceea8a64ee': tokenLogoUrls.dai, + '0x493c7081faab6e5b2d6b18d9311918580e88c6bf': tokenLogoUrls.gusd, + '0xd5c2a983d320a881f21dc68fd89f905ff1517b2c': tokenLogoUrls.weth, + '0x45bbc6b553d2afc4d3e376b22f70a67d9a26f819': tokenLogoUrls.wbtc }, [NETWORK.avalanche]: { '0x2f2a2543b76a4166549f7aab2e75bef0aefc5b0f': tokenLogoUrls.wbtc diff --git a/shared/types/types/liquidations.ts b/shared/types/types/liquidations.ts index 4bcc97e8..7da61263 100644 --- a/shared/types/types/liquidations.ts +++ b/shared/types/types/liquidations.ts @@ -3,11 +3,7 @@ export interface PairCreateInfo { source: `0x${string}` tokenIn: `0x${string}` tokenOut: `0x${string}` - periodLength: number - periodOffset: number - targetFirstSaleTime: number - decayConstant: bigint - initialAmountIn: bigint - initialAmountOut: bigint + targetAuctionPeriod: number minimumAuctionAmount: bigint + smoothingFactor: number } diff --git a/shared/utilities/abis/liquidationPair.ts b/shared/utilities/abis/liquidationPair.ts index 0c41272b..89682955 100644 --- a/shared/utilities/abis/liquidationPair.ts +++ b/shared/utilities/abis/liquidationPair.ts @@ -1,100 +1,30 @@ export const liquidationPairABI = [ { - inputs: [], - name: 'amountInForPeriod', - outputs: [{ internalType: 'uint104', name: '', type: 'uint104' }], - stateMutability: 'nonpayable', - type: 'function' - }, - { - inputs: [], - name: 'amountOutForPeriod', - outputs: [{ internalType: 'uint104', name: '', type: 'uint104' }], - stateMutability: 'nonpayable', - type: 'function' - }, - { - inputs: [{ internalType: 'uint256', name: '_amountOut', type: 'uint256' }], + inputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], name: 'computeExactAmountIn', outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], - stateMutability: 'nonpayable', - type: 'function' - }, - { - inputs: [], - name: 'decayConstant', - outputs: [{ internalType: 'SD59x18', name: '', type: 'int256' }], stateMutability: 'view', type: 'function' }, { - inputs: [], - name: 'emissionRate', - outputs: [{ internalType: 'SD59x18', name: '', type: 'int256' }], - stateMutability: 'nonpayable', - type: 'function' - }, - { - inputs: [], - name: 'firstPeriodStartsAt', + inputs: [{ internalType: 'uint256', name: 'price', type: 'uint256' }], + name: 'computeTimeForPrice', outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], stateMutability: 'view', type: 'function' }, { inputs: [], - name: 'getElapsedTime', - outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], - stateMutability: 'nonpayable', - type: 'function' - }, - { - inputs: [], - name: 'getPeriodEnd', - outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], - stateMutability: 'nonpayable', - type: 'function' - }, - { - inputs: [], - name: 'getPeriodStart', - outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], - stateMutability: 'nonpayable', - type: 'function' - }, - { - inputs: [], - name: 'initialPrice', - outputs: [{ internalType: 'SD59x18', name: '', type: 'int256' }], - stateMutability: 'nonpayable', - type: 'function' - }, - { - inputs: [], - name: 'lastAuctionTime', - outputs: [{ internalType: 'uint48', name: '', type: 'uint48' }], - stateMutability: 'nonpayable', - type: 'function' - }, - { - inputs: [], - name: 'lastNonZeroAmountIn', - outputs: [{ internalType: 'uint112', name: '', type: 'uint112' }], - stateMutability: 'nonpayable', - type: 'function' - }, - { - inputs: [], - name: 'lastNonZeroAmountOut', - outputs: [{ internalType: 'uint112', name: '', type: 'uint112' }], - stateMutability: 'nonpayable', + name: 'lastAuctionAt', + outputs: [{ internalType: 'uint64', name: '', type: 'uint64' }], + stateMutability: 'view', type: 'function' }, { inputs: [], - name: 'maxAmountIn', - outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], - stateMutability: 'nonpayable', + name: 'lastAuctionPrice', + outputs: [{ internalType: 'uint192', name: '', type: 'uint192' }], + stateMutability: 'view', type: 'function' }, { @@ -113,7 +43,7 @@ export const liquidationPairABI = [ }, { inputs: [], - name: 'periodLength', + name: 'smoothingFactor', outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], stateMutability: 'view', type: 'function' @@ -128,7 +58,7 @@ export const liquidationPairABI = [ { inputs: [ { internalType: 'address', name: '_receiver', type: 'address' }, - { internalType: 'uint256', name: '_amountOut', type: 'uint256' }, + { internalType: 'uint256', name: '', type: 'uint256' }, { internalType: 'uint256', name: '_amountInMax', type: 'uint256' }, { internalType: 'bytes', name: '_flashSwapData', type: 'bytes' } ], @@ -146,8 +76,8 @@ export const liquidationPairABI = [ }, { inputs: [], - name: 'targetFirstSaleTime', - outputs: [{ internalType: 'uint32', name: '', type: 'uint32' }], + name: 'targetAuctionPeriod', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], stateMutability: 'view', type: 'function' }, @@ -165,118 +95,6 @@ export const liquidationPairABI = [ stateMutability: 'view', type: 'function' }, - { - anonymous: false, - inputs: [ - { indexed: false, internalType: 'uint104', name: 'lastNonZeroAmountIn', type: 'uint104' }, - { indexed: false, internalType: 'uint104', name: 'lastNonZeroAmountOut', type: 'uint104' }, - { indexed: false, internalType: 'uint48', name: 'lastAuctionTime', type: 'uint48' }, - { indexed: true, internalType: 'uint48', name: 'period', type: 'uint48' }, - { indexed: false, internalType: 'SD59x18', name: 'emissionRate', type: 'int256' }, - { indexed: false, internalType: 'SD59x18', name: 'initialPrice', type: 'int256' } - ], - name: 'StartedAuction', - type: 'event' - }, - { - anonymous: false, - inputs: [ - { indexed: true, internalType: 'address', name: 'sender', type: 'address' }, - { indexed: true, internalType: 'address', name: 'receiver', type: 'address' }, - { indexed: false, internalType: 'uint256', name: 'amountOut', type: 'uint256' }, - { indexed: false, internalType: 'uint256', name: 'amountInMax', type: 'uint256' }, - { indexed: false, internalType: 'uint256', name: 'amountIn', type: 'uint256' }, - { indexed: false, internalType: 'bytes', name: 'flashSwapData', type: 'bytes' } - ], - name: 'SwappedExactAmountOut', - type: 'event' - }, - { inputs: [], name: 'AmountInZero', type: 'error' }, - { inputs: [], name: 'AmountOutZero', type: 'error' }, - { - inputs: [ - { internalType: 'SD59x18', name: 'maxDecayConstant', type: 'int256' }, - { internalType: 'SD59x18', name: 'decayConstant', type: 'int256' } - ], - name: 'DecayConstantTooLarge', - type: 'error' - }, - { inputs: [], name: 'EmissionRateIsZero', type: 'error' }, - { inputs: [], name: 'LiquidationSourceZeroAddress', type: 'error' }, - { - inputs: [ - { internalType: 'uint256', name: 'x', type: 'uint256' }, - { internalType: 'uint256', name: 'y', type: 'uint256' } - ], - name: 'PRBMath_MulDiv18_Overflow', - type: 'error' - }, - { - inputs: [ - { internalType: 'uint256', name: 'x', type: 'uint256' }, - { internalType: 'uint256', name: 'y', type: 'uint256' }, - { internalType: 'uint256', name: 'denominator', type: 'uint256' } - ], - name: 'PRBMath_MulDiv_Overflow', - type: 'error' - }, - { - inputs: [{ internalType: 'SD59x18', name: 'x', type: 'int256' }], - name: 'PRBMath_SD59x18_Ceil_Overflow', - type: 'error' - }, - { - inputs: [{ internalType: 'int256', name: 'x', type: 'int256' }], - name: 'PRBMath_SD59x18_Convert_Overflow', - type: 'error' - }, - { - inputs: [{ internalType: 'int256', name: 'x', type: 'int256' }], - name: 'PRBMath_SD59x18_Convert_Underflow', - type: 'error' - }, - { inputs: [], name: 'PRBMath_SD59x18_Div_InputTooSmall', type: 'error' }, - { - inputs: [ - { internalType: 'SD59x18', name: 'x', type: 'int256' }, - { internalType: 'SD59x18', name: 'y', type: 'int256' } - ], - name: 'PRBMath_SD59x18_Div_Overflow', - type: 'error' - }, - { - inputs: [{ internalType: 'SD59x18', name: 'x', type: 'int256' }], - name: 'PRBMath_SD59x18_Exp2_InputTooBig', - type: 'error' - }, - { - inputs: [{ internalType: 'SD59x18', name: 'x', type: 'int256' }], - name: 'PRBMath_SD59x18_Exp_InputTooBig', - type: 'error' - }, - { inputs: [], name: 'PRBMath_SD59x18_Mul_InputTooSmall', type: 'error' }, - { - inputs: [ - { internalType: 'SD59x18', name: 'x', type: 'int256' }, - { internalType: 'SD59x18', name: 'y', type: 'int256' } - ], - name: 'PRBMath_SD59x18_Mul_Overflow', - type: 'error' - }, - { - inputs: [{ internalType: 'uint256', name: 'amountOut', type: 'uint256' }], - name: 'PurchasePriceIsZero', - type: 'error' - }, - { inputs: [], name: 'ReceiverIsZero', type: 'error' }, - { - inputs: [ - { internalType: 'uint256', name: 'amountOut', type: 'uint256' }, - { internalType: 'uint256', name: 'available', type: 'uint256' } - ], - name: 'SwapExceedsAvailable', - type: 'error' - }, { inputs: [ { internalType: 'uint256', name: 'amountInMax', type: 'uint256' }, @@ -284,15 +102,5 @@ export const liquidationPairABI = [ ], name: 'SwapExceedsMax', type: 'error' - }, - { - inputs: [ - { internalType: 'uint256', name: 'passedTargetSaleTime', type: 'uint256' }, - { internalType: 'uint256', name: 'periodLength', type: 'uint256' } - ], - name: 'TargetFirstSaleTimeGePeriodLength', - type: 'error' - }, - { inputs: [], name: 'TokenInZeroAddress', type: 'error' }, - { inputs: [], name: 'TokenOutZeroAddress', type: 'error' } + } ] as const diff --git a/shared/utilities/abis/liquidationPairFactory.ts b/shared/utilities/abis/liquidationPairFactory.ts index e8781e92..9c1f961d 100644 --- a/shared/utilities/abis/liquidationPairFactory.ts +++ b/shared/utilities/abis/liquidationPairFactory.ts @@ -2,7 +2,7 @@ export const liquidationPairFactoryABI = [ { inputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], name: 'allPairs', - outputs: [{ internalType: 'contract LiquidationPair', name: '', type: 'address' }], + outputs: [{ internalType: 'contract TpdaLiquidationPair', name: '', type: 'address' }], stateMutability: 'view', type: 'function' }, @@ -11,21 +11,17 @@ export const liquidationPairFactoryABI = [ { internalType: 'contract ILiquidationSource', name: '_source', type: 'address' }, { internalType: 'address', name: '_tokenIn', type: 'address' }, { internalType: 'address', name: '_tokenOut', type: 'address' }, - { internalType: 'uint32', name: '_periodLength', type: 'uint32' }, - { internalType: 'uint32', name: '_firstPeriodStartsAt', type: 'uint32' }, - { internalType: 'uint32', name: '_targetFirstSaleTime', type: 'uint32' }, - { internalType: 'SD59x18', name: '_decayConstant', type: 'int256' }, - { internalType: 'uint104', name: '_initialAmountIn', type: 'uint104' }, - { internalType: 'uint104', name: '_initialAmountOut', type: 'uint104' }, - { internalType: 'uint256', name: '_minimumAuctionAmount', type: 'uint256' } + { internalType: 'uint256', name: '_targetAuctionPeriod', type: 'uint256' }, + { internalType: 'uint192', name: '_minimumAuctionAmount', type: 'uint192' }, + { internalType: 'uint256', name: '_smoothingFactor', type: 'uint256' } ], name: 'createPair', - outputs: [{ internalType: 'contract LiquidationPair', name: '', type: 'address' }], + outputs: [{ internalType: 'contract TpdaLiquidationPair', name: '', type: 'address' }], stateMutability: 'nonpayable', type: 'function' }, { - inputs: [{ internalType: 'contract LiquidationPair', name: '', type: 'address' }], + inputs: [{ internalType: 'contract TpdaLiquidationPair', name: '', type: 'address' }], name: 'deployedPairs', outputs: [{ internalType: 'bool', name: '', type: 'bool' }], stateMutability: 'view', @@ -41,22 +37,23 @@ export const liquidationPairFactoryABI = [ { anonymous: false, inputs: [ - { indexed: true, internalType: 'contract LiquidationPair', name: 'pair', type: 'address' }, - { indexed: true, internalType: 'address', name: 'tokenIn', type: 'address' }, - { indexed: true, internalType: 'address', name: 'tokenOut', type: 'address' }, + { + indexed: true, + internalType: 'contract TpdaLiquidationPair', + name: 'pair', + type: 'address' + }, { indexed: false, internalType: 'contract ILiquidationSource', name: 'source', type: 'address' }, - { indexed: false, internalType: 'uint32', name: 'periodLength', type: 'uint32' }, - { indexed: false, internalType: 'uint32', name: 'firstPeriodStartsAt', type: 'uint32' }, - { indexed: false, internalType: 'uint32', name: 'targetFirstSaleTime', type: 'uint32' }, - { indexed: false, internalType: 'SD59x18', name: 'decayConstant', type: 'int256' }, - { indexed: false, internalType: 'uint104', name: 'initialAmountIn', type: 'uint104' }, - { indexed: false, internalType: 'uint104', name: 'initialAmountOut', type: 'uint104' }, - { indexed: false, internalType: 'uint256', name: 'minimumAuctionAmount', type: 'uint256' } + { indexed: true, internalType: 'address', name: 'tokenIn', type: 'address' }, + { indexed: true, internalType: 'address', name: 'tokenOut', type: 'address' }, + { indexed: false, internalType: 'uint256', name: 'targetAuctionPeriod', type: 'uint256' }, + { indexed: false, internalType: 'uint192', name: 'minimumAuctionAmount', type: 'uint192' }, + { indexed: false, internalType: 'uint256', name: 'smoothingFactor', type: 'uint256' } ], name: 'PairCreated', type: 'event' diff --git a/shared/utilities/abis/liquidationRouter.ts b/shared/utilities/abis/liquidationRouter.ts index 8d95029d..595c7704 100644 --- a/shared/utilities/abis/liquidationRouter.ts +++ b/shared/utilities/abis/liquidationRouter.ts @@ -13,7 +13,7 @@ export const liquidationRouterABI = [ }, { inputs: [ - { internalType: 'contract LiquidationPair', name: '_liquidationPair', type: 'address' }, + { internalType: 'contract TpdaLiquidationPair', name: '_liquidationPair', type: 'address' }, { internalType: 'address', name: '_receiver', type: 'address' }, { internalType: 'uint256', name: '_amountOut', type: 'uint256' }, { internalType: 'uint256', name: '_amountInMax', type: 'uint256' }, @@ -29,7 +29,7 @@ export const liquidationRouterABI = [ inputs: [ { indexed: true, - internalType: 'contract LiquidationPairFactory', + internalType: 'contract TpdaLiquidationPairFactory', name: 'liquidationPairFactory', type: 'address' } @@ -42,7 +42,7 @@ export const liquidationRouterABI = [ inputs: [ { indexed: true, - internalType: 'contract LiquidationPair', + internalType: 'contract TpdaLiquidationPair', name: 'liquidationPair', type: 'address' }, @@ -66,12 +66,12 @@ export const liquidationRouterABI = [ name: 'SwapExpired', type: 'error' }, - { inputs: [], name: 'UndefinedLiquidationPairFactory', type: 'error' }, + { inputs: [], name: 'UndefinedTpdaLiquidationPairFactory', type: 'error' }, { inputs: [ - { internalType: 'contract LiquidationPair', name: 'liquidationPair', type: 'address' } + { internalType: 'contract TpdaLiquidationPair', name: 'liquidationPair', type: 'address' } ], - name: 'UnknownLiquidationPair', + name: 'UnknownTpdaLiquidationPair', type: 'error' } ] as const diff --git a/shared/utilities/abis/opGasOracle.ts b/shared/utilities/abis/opGasOracle.ts index 51427699..b373e251 100644 --- a/shared/utilities/abis/opGasOracle.ts +++ b/shared/utilities/abis/opGasOracle.ts @@ -13,6 +13,27 @@ export const opGasOracleABI = [ stateMutability: 'view', type: 'function' }, + { + inputs: [], + name: 'baseFeeScalar', + outputs: [{ internalType: 'uint32', name: '', type: 'uint32' }], + stateMutability: 'view', + type: 'function' + }, + { + inputs: [], + name: 'blobBaseFee', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function' + }, + { + inputs: [], + name: 'blobBaseFeeScalar', + outputs: [{ internalType: 'uint32', name: '', type: 'uint32' }], + stateMutability: 'view', + type: 'function' + }, { inputs: [], name: 'decimals', @@ -41,6 +62,13 @@ export const opGasOracleABI = [ stateMutability: 'view', type: 'function' }, + { + inputs: [], + name: 'isEcotone', + outputs: [{ internalType: 'bool', name: '', type: 'bool' }], + stateMutability: 'view', + type: 'function' + }, { inputs: [], name: 'l1BaseFee', @@ -62,6 +90,7 @@ export const opGasOracleABI = [ stateMutability: 'view', type: 'function' }, + { inputs: [], name: 'setEcotone', outputs: [], stateMutability: 'nonpayable', type: 'function' }, { inputs: [], name: 'version', diff --git a/shared/utilities/constants.ts b/shared/utilities/constants.ts index c2a2a4df..e86c3ff0 100644 --- a/shared/utilities/constants.ts +++ b/shared/utilities/constants.ts @@ -31,48 +31,20 @@ export const POOL_TOKEN_ADDRESSES = { [NETWORK.mainnet]: '0x0cEC1A9154Ff802e7934Fc916Ed7Ca50bDE6844e', [NETWORK.polygon]: '0x25788a1a171ec66Da6502f9975a15B609fF54CF6', [NETWORK.optimism]: '0x395ae52bb17aef68c2888d941736a71dc6d4e125', - [NETWORK.optimism_sepolia]: '0x264954576Da8496cc0d2216Df81a7D7A38857329' + [NETWORK.optimism_sepolia]: '0x1e62Cf8A2C981B0AE39E0A52A06EA5679186938C' } as const /** * USDC token addresses - * - * NOTE: All addresses are lowercase */ export const USDC_TOKEN_ADDRESSES: { [chainId: number]: Lowercase
} = { [NETWORK.mainnet]: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48', [NETWORK.polygon]: '0x2791bca1f2de4661ed88a30c99a7a9449aa84174', [NETWORK.optimism]: '0x7f5c764cbc14f9669b88837ca1490cca17c31607', [NETWORK.arbitrum]: '0xff970a61a04b1ca14834a43f5de4533ebddb5cc8', - [NETWORK.optimism_sepolia]: '0xe9cb1a8c3c1b5bce7c6c0fb15f31a3a56209207f' + [NETWORK.optimism_sepolia]: '0x0e13bf42f927575475894f2d5076a7ac77060ea0' } -/** - * Second constants - */ -export const SECONDS_PER_MINUTE = 60 -export const SECONDS_PER_HOUR = 3_600 -export const SECONDS_PER_DAY = 86_400 -export const SECONDS_PER_WEEK = 604_800 -export const SECONDS_PER_MONTH = 2_628_000 -export const SECONDS_PER_YEAR = 31_536_000 - -/** - * Minute constants - */ -export const MINUTES_PER_HOUR = 60 -export const MINUTES_PER_DAY = 1_440 - -/** - * CoinGecko API URL - */ -export const COINGECKO_API_URL = 'https://api.coingecko.com/api/v3' - -/** - * Token Prices API URL - */ -export const TOKEN_PRICES_API_URL = 'https://token-prices.api.cabana.fi' - /** * Prize Pools */ @@ -91,11 +63,11 @@ export const PRIZE_POOLS: { }[] = [ { chainId: NETWORK.optimism_sepolia, - address: '0x5e1b40e4249644a7d7589d1197AD0F1628e79FB1', + address: '0x31547D3c38F2F8dC92421C54B173F3B27Ab26EbB', options: { - prizeTokenAddress: '0x1bcd630e1303cef37F19743fbFE84b1b14e7750c', - drawManagerAddress: '0x07DBA6DB0b4c2B65B340C93e751f3694277A5a89', - twabControllerAddress: '0xd7a754FCFf13007C8E35aE5c40417432C1918616', + prizeTokenAddress: '0xD5C2a983D320a881F21Dc68fd89f905Ff1517B2C', + drawManagerAddress: '0x1bEbF92C4502341785DDDe63d2f770954CA38e33', + twabControllerAddress: '0xB2549f4e7b919004b31925FD4271459273DE8A89', drawPeriodInSeconds: 7_200, drawAuctionDurationInSeconds: 2_400, tierShares: 100, @@ -104,75 +76,6 @@ export const PRIZE_POOLS: { } ] -/** - * Subgraph API URLs - */ -export const SUBGRAPH_API_URLS = { - [NETWORK.optimism_sepolia]: - 'https://api.studio.thegraph.com/query/63100/pt-v5-op-sepolia/version/latest' -} as const - -/** - * CoinGecko platform IDs - */ -export const COINGECKO_PLATFORMS = { - [NETWORK.mainnet]: 'ethereum', - [NETWORK.bsc]: 'binance-smart-chain', - [NETWORK.xdai]: 'xdai', - [NETWORK.polygon]: 'polygon-pos', - [NETWORK.optimism]: 'optimistic-ethereum', - [NETWORK.avalanche]: 'avalanche', - [NETWORK.celo]: 'celo', - [NETWORK.arbitrum]: 'arbitrum-one' -} as const -export type COINGECKO_PLATFORM = keyof typeof COINGECKO_PLATFORMS - -/** - * CoinGecko native token IDs - */ -export const COINGECKO_NATIVE_TOKEN_IDS: Record = { - [NETWORK.mainnet]: 'ethereum', - [NETWORK.sepolia]: 'ethereum', - [NETWORK.bsc]: 'binancecoin', - [NETWORK.bsc_testnet]: 'binancecoin', - [NETWORK.xdai]: 'xdai', - [NETWORK.polygon]: 'matic-network', - [NETWORK.mumbai]: 'matic-network', - [NETWORK.optimism]: 'ethereum', - [NETWORK.optimism_sepolia]: 'ethereum', - [NETWORK.avalanche]: 'avalanche-2', - [NETWORK.fuji]: 'avalanche-2', - [NETWORK.celo]: 'celo', - [NETWORK.celo_testnet]: 'celo', - [NETWORK.arbitrum]: 'ethereum', - [NETWORK.arbitrum_sepolia]: 'ethereum', - [NETWORK.base]: 'ethereum', - [NETWORK.base_sepolia]: 'ethereum' -} - -/** - * Block explorer mapping - */ -export const BLOCK_EXPLORERS: Record = { - [NETWORK.mainnet]: { name: 'Etherscan', url: 'https://etherscan.io/' }, - [NETWORK.sepolia]: { name: 'Etherscan', url: 'https://sepolia.etherscan.io/' }, - [NETWORK.bsc]: { name: 'Bscscan', url: 'https://bscscan.com/' }, - [NETWORK.bsc_testnet]: { name: 'Bscscan', url: 'https://testnet.bscscan.com/' }, - [NETWORK.xdai]: { name: 'Gnosisscan', url: 'https://gnosisscan.io/' }, - [NETWORK.polygon]: { name: 'Polygonscan', url: 'https://polygonscan.com/' }, - [NETWORK.mumbai]: { name: 'Polygonscan', url: 'https://mumbai.polygonscan.com/' }, - [NETWORK.optimism]: { name: 'Etherscan', url: 'https://optimistic.etherscan.io/' }, - [NETWORK.optimism_sepolia]: { name: 'Etherscan', url: 'https://sepolia-optimism.etherscan.io/' }, - [NETWORK.avalanche]: { name: 'Snowtrace', url: 'https://snowtrace.io/' }, - [NETWORK.fuji]: { name: 'Snowtrace', url: 'https://testnet.snowtrace.io/' }, - [NETWORK.celo]: { name: 'Celoscan', url: 'https://celoscan.io/' }, - [NETWORK.celo_testnet]: { name: 'Celoscan', url: 'https://alfajores.celoscan.io/' }, - [NETWORK.arbitrum]: { name: 'Arbiscan', url: 'https://arbiscan.io/' }, - [NETWORK.arbitrum_sepolia]: { name: 'Arbiscan', url: 'https://sepolia.arbiscan.io/' }, - [NETWORK.base]: { name: 'Basescan', url: 'https://basescan.org/' }, - [NETWORK.base_sepolia]: { name: 'Blockscout', url: 'https://sepolia.basescan.org/' } -} - /** * Stablecoin addresses and their corresponding fiat currency * @@ -199,9 +102,9 @@ export const STABLECOINS: Record = { '0xc40f949f8a4e094d1b49a23ea9241d289b7b2819': 'usd' // LUSD }, [NETWORK.optimism_sepolia]: { - '0xe9cb1a8c3c1b5bce7c6c0fb15f31a3a56209207f': 'usd', // USDC - '0x34f166839c655f2dcd56638f2ce779fd9b5987a6': 'usd', // DAI - '0xce1fe3170d4acefbc3d06595eef3a918f65000c2': 'usd' // GUSD + '0x0e13bf42f927575475894f2d5076a7ac77060ea0': 'usd', // USDC + '0x8261cb9519dd1d80b5ce66b0887c6fceea8a64ee': 'usd', // DAI + '0x493c7081faab6e5b2d6b18d9311918580e88c6bf': 'usd' // GUSD }, [NETWORK.avalanche]: { '0xa7d7079b0fead91f3e65f86e8915cb59c1a4c664': 'usd' // USDC.e @@ -244,35 +147,35 @@ export const WRAPPED_NATIVE_ASSETS: Record = { * TWAB rewards addresses */ export const TWAB_REWARDS_ADDRESSES: { [chainId: number]: Address } = { - [NETWORK.optimism_sepolia]: '0xB1231d0bdf134b09D92f6d33C651280D3B96F6e3' + [NETWORK.optimism_sepolia]: '0xC5c208DFAE3bA24132070E63aE964bA0D4A81a03' } /** * Vault factory addresses */ export const VAULT_FACTORY_ADDRESSES: { [chainId: number]: Address } = { - [NETWORK.optimism_sepolia]: '0x2031fc356feec120eFba3BAfA7997d1dfB377Ed4' + [NETWORK.optimism_sepolia]: '0x65741e6C8fbCcD3d4BEC7E2179417236FbD33d3A' } /** * Liquidation pair factory addresses */ export const LIQUIDATION_PAIR_FACTORY_ADDRESSES: { [chainId: number]: Address } = { - [NETWORK.optimism_sepolia]: '0x5114de3c33458815BaD56B28D32261695490DBf3' + [NETWORK.optimism_sepolia]: '0x0d2AD8f32E94605a9a7E797Ff494D27C691B16Dc' } /** * Default claimer addresses */ export const DEFAULT_CLAIMER_ADDRESSES: { [chainId: number]: Address } = { - [NETWORK.optimism_sepolia]: '0x239d1befb50fcFF353804C6df1579ED0Bbb9dA07' + [NETWORK.optimism_sepolia]: '0x189231eBe184a40A8AFb1659985C6D976729780D' } /** * Liquidation router addresses */ export const LIQUIDATION_ROUTER_ADDRESSES: { [chainId: number]: Address } = { - [NETWORK.optimism_sepolia]: '0xDfCF0c47C5697CDDFADEB7b5CbD29BC6b20c8DD1' + [NETWORK.optimism_sepolia]: '0xB485D92896944D3f8Dd73A1a61371CDaDb1021f5' } /** @@ -290,6 +193,18 @@ export const DEAD_ADDRESS = '0x000000000000000000000000000000000000dead' */ export const OP_GAS_ORACLE_ADDRESS = '0x420000000000000000000000000000000000000f' +/** + * Subgraph API URLs + */ +export const SUBGRAPH_API_URLS = { + // [NETWORK.optimism_sepolia]: 'https://api.studio.thegraph.com/query/63100/pt-v5-op-sepolia/version/latest' +} as const + +/** + * Token Prices API URL + */ +export const TOKEN_PRICES_API_URL = 'https://token-prices.api.cabana.fi' + /** * Networks supported by the price caching API */ @@ -334,7 +249,7 @@ export const TOKEN_PRICE_REDIRECTS: { address: DOLPHIN_ADDRESS }, /* DAI */ - '0x34f166839c655f2dcd56638f2ce779fd9b5987a6': { + '0x8261cb9519dd1d80b5ce66b0887c6fceea8a64ee': { chainId: NETWORK.mainnet, address: '0x6b175474e89094c44da98b954eedeac495271d0f' }, @@ -344,17 +259,17 @@ export const TOKEN_PRICE_REDIRECTS: { address: USDC_TOKEN_ADDRESSES[NETWORK.mainnet] }, /* GUSD */ - '0xce1fe3170d4acefbc3d06595eef3a918f65000c2': { + '0x493c7081faab6e5b2d6b18d9311918580e88c6bf': { chainId: NETWORK.mainnet, address: '0x056fd409e1d7a124bd7017459dfea2f387b6d5cd' }, /* WBTC */ - '0x42fd018a6ac84478f28b3f7e322271c83064d737': { + '0x45bbc6b553d2afc4d3e376b22f70a67d9a26f819': { chainId: NETWORK.mainnet, address: '0x2260fac5e5542a773aa44fbcfedf7c193bc2c599' }, /* WETH */ - '0x1bcd630e1303cef37f19743fbfe84b1b14e7750c': { + '0xd5c2a983d320a881f21dc68fd89f905ff1517b2c': { chainId: NETWORK.mainnet, address: WRAPPED_NATIVE_ASSETS[NETWORK.mainnet] as Address }, @@ -388,6 +303,88 @@ export const TOKEN_DATA_REDIRECTS: { } } +/** + * Block explorer mapping + */ +export const BLOCK_EXPLORERS: Record = { + [NETWORK.mainnet]: { name: 'Etherscan', url: 'https://etherscan.io/' }, + [NETWORK.sepolia]: { name: 'Etherscan', url: 'https://sepolia.etherscan.io/' }, + [NETWORK.bsc]: { name: 'Bscscan', url: 'https://bscscan.com/' }, + [NETWORK.bsc_testnet]: { name: 'Bscscan', url: 'https://testnet.bscscan.com/' }, + [NETWORK.xdai]: { name: 'Gnosisscan', url: 'https://gnosisscan.io/' }, + [NETWORK.polygon]: { name: 'Polygonscan', url: 'https://polygonscan.com/' }, + [NETWORK.mumbai]: { name: 'Polygonscan', url: 'https://mumbai.polygonscan.com/' }, + [NETWORK.optimism]: { name: 'Etherscan', url: 'https://optimistic.etherscan.io/' }, + [NETWORK.optimism_sepolia]: { name: 'Etherscan', url: 'https://sepolia-optimism.etherscan.io/' }, + [NETWORK.avalanche]: { name: 'Snowtrace', url: 'https://snowtrace.io/' }, + [NETWORK.fuji]: { name: 'Snowtrace', url: 'https://testnet.snowtrace.io/' }, + [NETWORK.celo]: { name: 'Celoscan', url: 'https://celoscan.io/' }, + [NETWORK.celo_testnet]: { name: 'Celoscan', url: 'https://alfajores.celoscan.io/' }, + [NETWORK.arbitrum]: { name: 'Arbiscan', url: 'https://arbiscan.io/' }, + [NETWORK.arbitrum_sepolia]: { name: 'Arbiscan', url: 'https://sepolia.arbiscan.io/' }, + [NETWORK.base]: { name: 'Basescan', url: 'https://basescan.org/' }, + [NETWORK.base_sepolia]: { name: 'Blockscout', url: 'https://sepolia.basescan.org/' } +} + +/** + * CoinGecko API URL + */ +export const COINGECKO_API_URL = 'https://api.coingecko.com/api/v3' + +/** + * CoinGecko platform IDs + */ +export const COINGECKO_PLATFORMS = { + [NETWORK.mainnet]: 'ethereum', + [NETWORK.bsc]: 'binance-smart-chain', + [NETWORK.xdai]: 'xdai', + [NETWORK.polygon]: 'polygon-pos', + [NETWORK.optimism]: 'optimistic-ethereum', + [NETWORK.avalanche]: 'avalanche', + [NETWORK.celo]: 'celo', + [NETWORK.arbitrum]: 'arbitrum-one' +} as const +export type COINGECKO_PLATFORM = keyof typeof COINGECKO_PLATFORMS + +/** + * CoinGecko native token IDs + */ +export const COINGECKO_NATIVE_TOKEN_IDS: Record = { + [NETWORK.mainnet]: 'ethereum', + [NETWORK.sepolia]: 'ethereum', + [NETWORK.bsc]: 'binancecoin', + [NETWORK.bsc_testnet]: 'binancecoin', + [NETWORK.xdai]: 'xdai', + [NETWORK.polygon]: 'matic-network', + [NETWORK.mumbai]: 'matic-network', + [NETWORK.optimism]: 'ethereum', + [NETWORK.optimism_sepolia]: 'ethereum', + [NETWORK.avalanche]: 'avalanche-2', + [NETWORK.fuji]: 'avalanche-2', + [NETWORK.celo]: 'celo', + [NETWORK.celo_testnet]: 'celo', + [NETWORK.arbitrum]: 'ethereum', + [NETWORK.arbitrum_sepolia]: 'ethereum', + [NETWORK.base]: 'ethereum', + [NETWORK.base_sepolia]: 'ethereum' +} + +/** + * Second constants + */ +export const SECONDS_PER_MINUTE = 60 +export const SECONDS_PER_HOUR = 3_600 +export const SECONDS_PER_DAY = 86_400 +export const SECONDS_PER_WEEK = 604_800 +export const SECONDS_PER_MONTH = 2_628_000 +export const SECONDS_PER_YEAR = 31_536_000 + +/** + * Minute constants + */ +export const MINUTES_PER_HOUR = 60 +export const MINUTES_PER_DAY = 1_440 + /** * Max uint256 value */ diff --git a/shared/utilities/utils/events.ts b/shared/utilities/utils/events.ts index 7aad4d0b..624a19b1 100644 --- a/shared/utilities/utils/events.ts +++ b/shared/utilities/utils/events.ts @@ -231,7 +231,7 @@ export const getLiquidationEvents = async ( inputs: [ { indexed: true, - internalType: 'contract LiquidationPair', + internalType: 'contract TpdaLiquidationPair', name: 'liquidationPair', type: 'address' }, From 6c2eadfd6a6a1fcae1efd92c8fa68358f5fc4348 Mon Sep 17 00:00:00 2001 From: Ncookiez Date: Tue, 26 Mar 2024 16:20:49 -0400 Subject: [PATCH 083/161] added smoothing factor tooltip --- .../components/forms/SmoothingFactorInput.tsx | 27 ++++++++++- .../src/components/forms/YieldVaultInput.tsx | 48 +++++++++---------- 2 files changed, 48 insertions(+), 27 deletions(-) diff --git a/apps/vault-factory/src/components/forms/SmoothingFactorInput.tsx b/apps/vault-factory/src/components/forms/SmoothingFactorInput.tsx index 695530d4..bdcf7944 100644 --- a/apps/vault-factory/src/components/forms/SmoothingFactorInput.tsx +++ b/apps/vault-factory/src/components/forms/SmoothingFactorInput.tsx @@ -1,3 +1,5 @@ +import { InformationCircleIcon } from '@heroicons/react/24/outline' +import { Tooltip } from '@shared/ui' import { useAtom } from 'jotai' import { useEffect } from 'react' import { useFormContext, useWatch } from 'react-hook-form' @@ -9,7 +11,6 @@ interface SmoothingFactorInputProps { className?: string } -// TODO: add tooltip explaining this value (0.8 = 20% of yield liquidated per auction, etc.) export const SmoothingFactorInput = (props: SmoothingFactorInputProps) => { const { className } = props @@ -40,7 +41,7 @@ export const SmoothingFactorInput = (props: SmoothingFactorInputProps) => { isNotTooPrecise: (v) => v.split('.').length < 2 || v.split('.')[1].length <= 18 || 'Too many decimals' }} - label='Smoothing Factor' + label={} defaultValue={'0'} needsOverride={true} keepValueOnOverride={true} @@ -49,6 +50,28 @@ export const SmoothingFactorInput = (props: SmoothingFactorInputProps) => { ) } +const SmoothingFactorInputLabel = () => { + return ( +
+ Smoothing Factor + + + The higher the smoothing factor, the lesser % of the available yield will be + liquidated every auction. + + Example: At 0.1, 90% of yield is liquidated. + Higher smoothing is recommended for prize vaults with infrequent yield. +
+ } + > + + +
+ ) +} + const isValidSmoothingFactor = (val: string) => { return ( !!val && diff --git a/apps/vault-factory/src/components/forms/YieldVaultInput.tsx b/apps/vault-factory/src/components/forms/YieldVaultInput.tsx index 3d4f9ea3..7cad1916 100644 --- a/apps/vault-factory/src/components/forms/YieldVaultInput.tsx +++ b/apps/vault-factory/src/components/forms/YieldVaultInput.tsx @@ -105,32 +105,30 @@ const YieldVaultCard = (props: YieldVaultCardProps) => { {shorten(yieldVault.address)} {!!existingVaultAddresses.length && ( -
- - {existingVaultAddresses.map((existingVaultAddress) => ( - - {shorten(existingVaultAddress)} - - ))} -
- } - > -
- - {existingVaultAddresses.length} existing prize vault - {existingVaultAddresses.length > 1 ? 's' : ''} - - + + {existingVaultAddresses.map((existingVaultAddress) => ( + + {shorten(existingVaultAddress)} + + ))}
- -
+ } + > +
+ + {existingVaultAddresses.length} existing prize vault + {existingVaultAddresses.length > 1 ? 's' : ''} + + +
+ )} From f6c514e7177d00e5c508775305fcf7adb7a60a72 Mon Sep 17 00:00:00 2001 From: Ncookiez Date: Tue, 26 Mar 2024 17:04:36 -0400 Subject: [PATCH 084/161] reformatted abis --- shared/utilities/abis/drawManager.ts | 164 +-- shared/utilities/abis/liquidationPair.ts | 28 +- .../utilities/abis/liquidationPairFactory.ts | 48 +- shared/utilities/abis/liquidationRouter.ts | 67 +- shared/utilities/abis/prizePool.ts | 1017 +++++++++-------- shared/utilities/abis/twabController.ts | 314 ++--- shared/utilities/abis/twabRewards.ts | 277 ++--- shared/utilities/abis/vault.ts | 490 ++++---- shared/utilities/abis/vaultFactory.ts | 24 +- 9 files changed, 1259 insertions(+), 1170 deletions(-) diff --git a/shared/utilities/abis/drawManager.ts b/shared/utilities/abis/drawManager.ts index 320f880b..770e9147 100644 --- a/shared/utilities/abis/drawManager.ts +++ b/shared/utilities/abis/drawManager.ts @@ -1,4 +1,92 @@ export const drawManagerABI = [ + { + inputs: [ + { internalType: 'contract PrizePool', name: '_prizePool', type: 'address' }, + { internalType: 'contract IRng', name: '_rng', type: 'address' }, + { internalType: 'uint48', name: '_auctionDuration', type: 'uint48' }, + { internalType: 'uint48', name: '_auctionTargetTime', type: 'uint48' }, + { internalType: 'UD2x18', name: '_firstStartDrawTargetFraction', type: 'uint64' }, + { internalType: 'UD2x18', name: '_firstFinishDrawTargetFraction', type: 'uint64' }, + { internalType: 'uint256', name: '_maxRewards', type: 'uint256' }, + { internalType: 'address', name: '_remainingRewardsRecipient', type: 'address' } + ], + stateMutability: 'nonpayable', + type: 'constructor' + }, + { inputs: [], name: 'AlreadyStartedDraw', type: 'error' }, + { + inputs: [{ internalType: 'uint48', name: 'auctionDuration', type: 'uint48' }], + name: 'AuctionDurationGTDrawPeriodSeconds', + type: 'error' + }, + { inputs: [], name: 'AuctionExpired', type: 'error' }, + { + inputs: [ + { internalType: 'uint48', name: 'auctionTargetTime', type: 'uint48' }, + { internalType: 'uint48', name: 'auctionDuration', type: 'uint48' } + ], + name: 'AuctionTargetTimeExceedsDuration', + type: 'error' + }, + { inputs: [], name: 'DrawHasFinalized', type: 'error' }, + { inputs: [], name: 'DrawHasNotClosed', type: 'error' }, + { + inputs: [ + { internalType: 'uint256', name: 'x', type: 'uint256' }, + { internalType: 'uint256', name: 'y', type: 'uint256' } + ], + name: 'PRBMath_MulDiv18_Overflow', + type: 'error' + }, + { + inputs: [ + { internalType: 'uint256', name: 'x', type: 'uint256' }, + { internalType: 'uint256', name: 'y', type: 'uint256' }, + { internalType: 'uint256', name: 'denominator', type: 'uint256' } + ], + name: 'PRBMath_MulDiv_Overflow', + type: 'error' + }, + { + inputs: [{ internalType: 'uint256', name: 'x', type: 'uint256' }], + name: 'PRBMath_UD60x18_Convert_Overflow', + type: 'error' + }, + { + inputs: [{ internalType: 'UD60x18', name: 'x', type: 'uint256' }], + name: 'PRBMath_UD60x18_IntoUD2x18_Overflow', + type: 'error' + }, + { inputs: [], name: 'RewardRecipientIsZero', type: 'error' }, + { inputs: [], name: 'RngRequestNotComplete', type: 'error' }, + { inputs: [], name: 'RngRequestNotInSameBlock', type: 'error' }, + { inputs: [], name: 'TargetRewardFractionGTOne', type: 'error' }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: 'uint24', name: 'drawId', type: 'uint24' }, + { indexed: false, internalType: 'uint256', name: 'elapsedTime', type: 'uint256' }, + { indexed: true, internalType: 'address', name: 'startRecipient', type: 'address' }, + { indexed: false, internalType: 'uint256', name: 'startReward', type: 'uint256' }, + { indexed: true, internalType: 'address', name: 'finishRecipient', type: 'address' }, + { indexed: false, internalType: 'uint256', name: 'finishReward', type: 'uint256' }, + { indexed: false, internalType: 'uint256', name: 'remainingReserve', type: 'uint256' } + ], + name: 'DrawFinished', + type: 'event' + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: 'address', name: 'sender', type: 'address' }, + { indexed: true, internalType: 'address', name: 'recipient', type: 'address' }, + { indexed: false, internalType: 'uint24', name: 'drawId', type: 'uint24' }, + { indexed: false, internalType: 'uint32', name: 'rngRequestId', type: 'uint32' }, + { indexed: false, internalType: 'uint48', name: 'elapsedTime', type: 'uint48' } + ], + name: 'DrawStarted', + type: 'event' + }, { inputs: [], name: 'auctionDuration', @@ -166,79 +254,5 @@ export const drawManagerABI = [ outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], stateMutability: 'view', type: 'function' - }, - { - anonymous: false, - inputs: [ - { indexed: true, internalType: 'uint24', name: 'drawId', type: 'uint24' }, - { indexed: false, internalType: 'uint256', name: 'elapsedTime', type: 'uint256' }, - { indexed: true, internalType: 'address', name: 'startRecipient', type: 'address' }, - { indexed: false, internalType: 'uint256', name: 'startReward', type: 'uint256' }, - { indexed: true, internalType: 'address', name: 'finishRecipient', type: 'address' }, - { indexed: false, internalType: 'uint256', name: 'finishReward', type: 'uint256' }, - { indexed: false, internalType: 'uint256', name: 'remainingReserve', type: 'uint256' } - ], - name: 'DrawFinished', - type: 'event' - }, - { - anonymous: false, - inputs: [ - { indexed: true, internalType: 'address', name: 'sender', type: 'address' }, - { indexed: true, internalType: 'address', name: 'recipient', type: 'address' }, - { indexed: false, internalType: 'uint24', name: 'drawId', type: 'uint24' }, - { indexed: false, internalType: 'uint32', name: 'rngRequestId', type: 'uint32' }, - { indexed: false, internalType: 'uint48', name: 'elapsedTime', type: 'uint48' } - ], - name: 'DrawStarted', - type: 'event' - }, - { inputs: [], name: 'AlreadyStartedDraw', type: 'error' }, - { - inputs: [{ internalType: 'uint48', name: 'auctionDuration', type: 'uint48' }], - name: 'AuctionDurationGTDrawPeriodSeconds', - type: 'error' - }, - { inputs: [], name: 'AuctionExpired', type: 'error' }, - { - inputs: [ - { internalType: 'uint48', name: 'auctionTargetTime', type: 'uint48' }, - { internalType: 'uint48', name: 'auctionDuration', type: 'uint48' } - ], - name: 'AuctionTargetTimeExceedsDuration', - type: 'error' - }, - { inputs: [], name: 'DrawHasFinalized', type: 'error' }, - { inputs: [], name: 'DrawHasNotClosed', type: 'error' }, - { - inputs: [ - { internalType: 'uint256', name: 'x', type: 'uint256' }, - { internalType: 'uint256', name: 'y', type: 'uint256' } - ], - name: 'PRBMath_MulDiv18_Overflow', - type: 'error' - }, - { - inputs: [ - { internalType: 'uint256', name: 'x', type: 'uint256' }, - { internalType: 'uint256', name: 'y', type: 'uint256' }, - { internalType: 'uint256', name: 'denominator', type: 'uint256' } - ], - name: 'PRBMath_MulDiv_Overflow', - type: 'error' - }, - { - inputs: [{ internalType: 'uint256', name: 'x', type: 'uint256' }], - name: 'PRBMath_UD60x18_Convert_Overflow', - type: 'error' - }, - { - inputs: [{ internalType: 'UD60x18', name: 'x', type: 'uint256' }], - name: 'PRBMath_UD60x18_IntoUD2x18_Overflow', - type: 'error' - }, - { inputs: [], name: 'RewardRecipientIsZero', type: 'error' }, - { inputs: [], name: 'RngRequestNotComplete', type: 'error' }, - { inputs: [], name: 'RngRequestNotInSameBlock', type: 'error' }, - { inputs: [], name: 'TargetRewardFractionGTOne', type: 'error' } + } ] as const diff --git a/shared/utilities/abis/liquidationPair.ts b/shared/utilities/abis/liquidationPair.ts index 89682955..bf96450a 100644 --- a/shared/utilities/abis/liquidationPair.ts +++ b/shared/utilities/abis/liquidationPair.ts @@ -1,4 +1,24 @@ export const liquidationPairABI = [ + { + inputs: [ + { internalType: 'contract ILiquidationSource', name: '_source', type: 'address' }, + { internalType: 'address', name: '__tokenIn', type: 'address' }, + { internalType: 'address', name: '__tokenOut', type: 'address' }, + { internalType: 'uint256', name: '_targetAuctionPeriod', type: 'uint256' }, + { internalType: 'uint192', name: '_minimumAuctionAmount', type: 'uint192' }, + { internalType: 'uint256', name: '_smoothingFactor', type: 'uint256' } + ], + stateMutability: 'nonpayable', + type: 'constructor' + }, + { + inputs: [ + { internalType: 'uint256', name: 'amountInMax', type: 'uint256' }, + { internalType: 'uint256', name: 'amountIn', type: 'uint256' } + ], + name: 'SwapExceedsMax', + type: 'error' + }, { inputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], name: 'computeExactAmountIn', @@ -94,13 +114,5 @@ export const liquidationPairABI = [ outputs: [{ internalType: 'address', name: '', type: 'address' }], stateMutability: 'view', type: 'function' - }, - { - inputs: [ - { internalType: 'uint256', name: 'amountInMax', type: 'uint256' }, - { internalType: 'uint256', name: 'amountIn', type: 'uint256' } - ], - name: 'SwapExceedsMax', - type: 'error' } ] as const diff --git a/shared/utilities/abis/liquidationPairFactory.ts b/shared/utilities/abis/liquidationPairFactory.ts index 9c1f961d..3ccb3393 100644 --- a/shared/utilities/abis/liquidationPairFactory.ts +++ b/shared/utilities/abis/liquidationPairFactory.ts @@ -1,4 +1,28 @@ export const liquidationPairFactoryABI = [ + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'contract TpdaLiquidationPair', + name: 'pair', + type: 'address' + }, + { + indexed: false, + internalType: 'contract ILiquidationSource', + name: 'source', + type: 'address' + }, + { indexed: true, internalType: 'address', name: 'tokenIn', type: 'address' }, + { indexed: true, internalType: 'address', name: 'tokenOut', type: 'address' }, + { indexed: false, internalType: 'uint256', name: 'targetAuctionPeriod', type: 'uint256' }, + { indexed: false, internalType: 'uint192', name: 'minimumAuctionAmount', type: 'uint192' }, + { indexed: false, internalType: 'uint256', name: 'smoothingFactor', type: 'uint256' } + ], + name: 'PairCreated', + type: 'event' + }, { inputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], name: 'allPairs', @@ -33,29 +57,5 @@ export const liquidationPairFactoryABI = [ outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], stateMutability: 'view', type: 'function' - }, - { - anonymous: false, - inputs: [ - { - indexed: true, - internalType: 'contract TpdaLiquidationPair', - name: 'pair', - type: 'address' - }, - { - indexed: false, - internalType: 'contract ILiquidationSource', - name: 'source', - type: 'address' - }, - { indexed: true, internalType: 'address', name: 'tokenIn', type: 'address' }, - { indexed: true, internalType: 'address', name: 'tokenOut', type: 'address' }, - { indexed: false, internalType: 'uint256', name: 'targetAuctionPeriod', type: 'uint256' }, - { indexed: false, internalType: 'uint192', name: 'minimumAuctionAmount', type: 'uint192' }, - { indexed: false, internalType: 'uint256', name: 'smoothingFactor', type: 'uint256' } - ], - name: 'PairCreated', - type: 'event' } ] as const diff --git a/shared/utilities/abis/liquidationRouter.ts b/shared/utilities/abis/liquidationRouter.ts index 595c7704..1ffa743c 100644 --- a/shared/utilities/abis/liquidationRouter.ts +++ b/shared/utilities/abis/liquidationRouter.ts @@ -1,28 +1,32 @@ export const liquidationRouterABI = [ { inputs: [ - { internalType: 'address', name: '_sender', type: 'address' }, - { internalType: 'uint256', name: '_amountIn', type: 'uint256' }, - { internalType: 'uint256', name: '', type: 'uint256' }, - { internalType: 'bytes', name: '_flashSwapData', type: 'bytes' } + { + internalType: 'contract TpdaLiquidationPairFactory', + name: 'liquidationPairFactory_', + type: 'address' + } ], - name: 'flashSwapCallback', - outputs: [], stateMutability: 'nonpayable', - type: 'function' + type: 'constructor' + }, + { + inputs: [{ internalType: 'address', name: 'sender', type: 'address' }], + name: 'InvalidSender', + type: 'error' }, + { + inputs: [{ internalType: 'uint256', name: 'deadline', type: 'uint256' }], + name: 'SwapExpired', + type: 'error' + }, + { inputs: [], name: 'UndefinedTpdaLiquidationPairFactory', type: 'error' }, { inputs: [ - { internalType: 'contract TpdaLiquidationPair', name: '_liquidationPair', type: 'address' }, - { internalType: 'address', name: '_receiver', type: 'address' }, - { internalType: 'uint256', name: '_amountOut', type: 'uint256' }, - { internalType: 'uint256', name: '_amountInMax', type: 'uint256' }, - { internalType: 'uint256', name: '_deadline', type: 'uint256' } + { internalType: 'contract TpdaLiquidationPair', name: 'liquidationPair', type: 'address' } ], - name: 'swapExactAmountOut', - outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], - stateMutability: 'nonpayable', - type: 'function' + name: 'UnknownTpdaLiquidationPair', + type: 'error' }, { anonymous: false, @@ -57,21 +61,28 @@ export const liquidationRouterABI = [ type: 'event' }, { - inputs: [{ internalType: 'address', name: 'sender', type: 'address' }], - name: 'InvalidSender', - type: 'error' - }, - { - inputs: [{ internalType: 'uint256', name: 'deadline', type: 'uint256' }], - name: 'SwapExpired', - type: 'error' + inputs: [ + { internalType: 'address', name: '_sender', type: 'address' }, + { internalType: 'uint256', name: '_amountIn', type: 'uint256' }, + { internalType: 'uint256', name: '', type: 'uint256' }, + { internalType: 'bytes', name: '_flashSwapData', type: 'bytes' } + ], + name: 'flashSwapCallback', + outputs: [], + stateMutability: 'nonpayable', + type: 'function' }, - { inputs: [], name: 'UndefinedTpdaLiquidationPairFactory', type: 'error' }, { inputs: [ - { internalType: 'contract TpdaLiquidationPair', name: 'liquidationPair', type: 'address' } + { internalType: 'contract TpdaLiquidationPair', name: '_liquidationPair', type: 'address' }, + { internalType: 'address', name: '_receiver', type: 'address' }, + { internalType: 'uint256', name: '_amountOut', type: 'uint256' }, + { internalType: 'uint256', name: '_amountInMax', type: 'uint256' }, + { internalType: 'uint256', name: '_deadline', type: 'uint256' } ], - name: 'UnknownTpdaLiquidationPair', - type: 'error' + name: 'swapExactAmountOut', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'nonpayable', + type: 'function' } ] as const diff --git a/shared/utilities/abis/prizePool.ts b/shared/utilities/abis/prizePool.ts index 8849df90..e762fbd2 100644 --- a/shared/utilities/abis/prizePool.ts +++ b/shared/utilities/abis/prizePool.ts @@ -1,779 +1,804 @@ export const prizePoolABI = [ { - inputs: [], - name: 'DONATOR', - outputs: [{ internalType: 'address', name: '', type: 'address' }], - stateMutability: 'view', - type: 'function' + inputs: [ + { + components: [ + { internalType: 'contract IERC20', name: 'prizeToken', type: 'address' }, + { internalType: 'contract TwabController', name: 'twabController', type: 'address' }, + { internalType: 'address', name: 'creator', type: 'address' }, + { internalType: 'uint256', name: 'tierLiquidityUtilizationRate', type: 'uint256' }, + { internalType: 'uint48', name: 'drawPeriodSeconds', type: 'uint48' }, + { internalType: 'uint48', name: 'firstDrawOpensAt', type: 'uint48' }, + { internalType: 'uint24', name: 'grandPrizePeriodDraws', type: 'uint24' }, + { internalType: 'uint8', name: 'numberOfTiers', type: 'uint8' }, + { internalType: 'uint8', name: 'tierShares', type: 'uint8' }, + { internalType: 'uint8', name: 'canaryShares', type: 'uint8' }, + { internalType: 'uint8', name: 'reserveShares', type: 'uint8' }, + { internalType: 'uint24', name: 'drawTimeout', type: 'uint24' } + ], + internalType: 'struct ConstructorParams', + name: 'params', + type: 'tuple' + } + ], + stateMutability: 'nonpayable', + type: 'constructor' }, + { inputs: [], name: 'AddToDrawZero', type: 'error' }, { - inputs: [], - name: 'accountedBalance', - outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], - stateMutability: 'view', - type: 'function' + inputs: [{ internalType: 'uint48', name: 'drawClosesAt', type: 'uint48' }], + name: 'AwardingDrawNotClosed', + type: 'error' }, { inputs: [ - { internalType: 'address', name: '_to', type: 'address' }, - { internalType: 'uint96', name: '_amount', type: 'uint96' } + { internalType: 'address', name: 'caller', type: 'address' }, + { internalType: 'address', name: 'drawManager', type: 'address' } ], - name: 'allocateRewardFromReserve', - outputs: [], - stateMutability: 'nonpayable', - type: 'function' - }, - { - inputs: [{ internalType: 'uint256', name: 'winningRandomNumber_', type: 'uint256' }], - name: 'awardDraw', - outputs: [{ internalType: 'uint24', name: '', type: 'uint24' }], - stateMutability: 'nonpayable', - type: 'function' + name: 'CallerNotDrawManager', + type: 'error' }, + { inputs: [], name: 'ClaimPeriodExpired', type: 'error' }, { - inputs: [], - name: 'canaryShares', - outputs: [{ internalType: 'uint8', name: '', type: 'uint8' }], - stateMutability: 'view', - type: 'function' + inputs: [ + { internalType: 'uint256', name: 'amount', type: 'uint256' }, + { internalType: 'uint256', name: 'available', type: 'uint256' } + ], + name: 'ContributionGTDeltaBalance', + type: 'error' }, + { inputs: [], name: 'CreatorIsZeroAddress', type: 'error' }, { - inputs: [], - name: 'claimCount', - outputs: [{ internalType: 'uint24', name: '', type: 'uint24' }], - stateMutability: 'view', - type: 'function' + inputs: [ + { internalType: 'address', name: 'vault', type: 'address' }, + { internalType: 'address', name: 'winner', type: 'address' }, + { internalType: 'uint8', name: 'tier', type: 'uint8' }, + { internalType: 'uint32', name: 'prizeIndex', type: 'uint32' } + ], + name: 'DidNotWin', + type: 'error' }, { inputs: [ - { internalType: 'address', name: '_winner', type: 'address' }, - { internalType: 'uint8', name: '_tier', type: 'uint8' }, - { internalType: 'uint32', name: '_prizeIndex', type: 'uint32' }, - { internalType: 'address', name: '_prizeRecipient', type: 'address' }, - { internalType: 'uint96', name: '_claimReward', type: 'uint96' }, - { internalType: 'address', name: '_claimRewardRecipient', type: 'address' } + { internalType: 'uint24', name: 'drawId', type: 'uint24' }, + { internalType: 'uint24', name: 'newestDrawId', type: 'uint24' } ], - name: 'claimPrize', - outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], - stateMutability: 'nonpayable', - type: 'function' + name: 'DrawAwarded', + type: 'error' }, + { inputs: [], name: 'DrawManagerAlreadySet', type: 'error' }, + { inputs: [], name: 'DrawTimeoutGTGrandPrizePeriodDraws', type: 'error' }, + { inputs: [], name: 'DrawTimeoutIsZero', type: 'error' }, + { inputs: [], name: 'FirstDrawOpensInPast', type: 'error' }, + { inputs: [], name: 'IncompatibleTwabPeriodLength', type: 'error' }, + { inputs: [], name: 'IncompatibleTwabPeriodOffset', type: 'error' }, { - inputs: [{ internalType: 'uint32', name: '_claimCount', type: 'uint32' }], - name: 'computeNextNumberOfTiers', - outputs: [{ internalType: 'uint8', name: '', type: 'uint8' }], - stateMutability: 'view', - type: 'function' + inputs: [{ internalType: 'uint104', name: 'requestedLiquidity', type: 'uint104' }], + name: 'InsufficientLiquidity', + type: 'error' }, { inputs: [ - { internalType: 'uint24', name: '_endDrawIdInclusive', type: 'uint24' }, - { internalType: 'uint24', name: '_rangeSize', type: 'uint24' } + { internalType: 'uint104', name: 'amount', type: 'uint104' }, + { internalType: 'uint104', name: 'reserve', type: 'uint104' } ], - name: 'computeRangeStartDrawIdInclusive', - outputs: [{ internalType: 'uint24', name: '', type: 'uint24' }], - stateMutability: 'pure', - type: 'function' - }, - { - inputs: [{ internalType: 'uint8', name: '_numberOfTiers', type: 'uint8' }], - name: 'computeTotalShares', - outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], - stateMutability: 'view', - type: 'function' + name: 'InsufficientReserve', + type: 'error' }, { inputs: [ - { internalType: 'address', name: '_prizeVault', type: 'address' }, - { internalType: 'uint256', name: '_amount', type: 'uint256' } + { internalType: 'uint256', name: 'requested', type: 'uint256' }, + { internalType: 'uint256', name: 'available', type: 'uint256' } ], - name: 'contributePrizeTokens', - outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], - stateMutability: 'nonpayable', - type: 'function' + name: 'InsufficientRewardsError', + type: 'error' }, { - inputs: [{ internalType: 'uint96', name: '_amount', type: 'uint96' }], - name: 'contributeReserve', - outputs: [], - stateMutability: 'nonpayable', - type: 'function' + inputs: [ + { internalType: 'uint24', name: 'startDrawId', type: 'uint24' }, + { internalType: 'uint24', name: 'endDrawId', type: 'uint24' } + ], + name: 'InvalidDrawRange', + type: 'error' }, { - inputs: [{ internalType: 'uint256', name: '_amount', type: 'uint256' }], - name: 'donatePrizeTokens', - outputs: [], - stateMutability: 'nonpayable', - type: 'function' + inputs: [ + { internalType: 'uint32', name: 'invalidPrizeIndex', type: 'uint32' }, + { internalType: 'uint32', name: 'prizeCount', type: 'uint32' }, + { internalType: 'uint8', name: 'tier', type: 'uint8' } + ], + name: 'InvalidPrizeIndex', + type: 'error' }, { - inputs: [{ internalType: 'uint24', name: 'drawId', type: 'uint24' }], - name: 'drawClosesAt', - outputs: [{ internalType: 'uint48', name: '', type: 'uint48' }], - stateMutability: 'view', - type: 'function' + inputs: [ + { internalType: 'uint8', name: 'tier', type: 'uint8' }, + { internalType: 'uint8', name: 'numberOfTiers', type: 'uint8' } + ], + name: 'InvalidTier', + type: 'error' }, + { inputs: [], name: 'NoDrawsAwarded', type: 'error' }, { - inputs: [], - name: 'drawIdPriorToShutdown', - outputs: [{ internalType: 'uint24', name: '', type: 'uint24' }], - stateMutability: 'view', - type: 'function' + inputs: [{ internalType: 'uint8', name: 'numTiers', type: 'uint8' }], + name: 'NumberOfTiersGreaterThanMaximum', + type: 'error' }, { - inputs: [], - name: 'drawManager', - outputs: [{ internalType: 'address', name: '', type: 'address' }], - stateMutability: 'view', - type: 'function' + inputs: [{ internalType: 'uint8', name: 'numTiers', type: 'uint8' }], + name: 'NumberOfTiersLessThanMinimum', + type: 'error' }, + { inputs: [], name: 'OnlyCreator', type: 'error' }, { - inputs: [{ internalType: 'uint24', name: 'drawId', type: 'uint24' }], - name: 'drawOpensAt', - outputs: [{ internalType: 'uint48', name: '', type: 'uint48' }], - stateMutability: 'view', - type: 'function' + inputs: [ + { internalType: 'uint256', name: 'x', type: 'uint256' }, + { internalType: 'uint256', name: 'y', type: 'uint256' } + ], + name: 'PRBMath_MulDiv18_Overflow', + type: 'error' }, { - inputs: [], - name: 'drawPeriodSeconds', - outputs: [{ internalType: 'uint48', name: '', type: 'uint48' }], - stateMutability: 'view', - type: 'function' + inputs: [ + { internalType: 'uint256', name: 'x', type: 'uint256' }, + { internalType: 'uint256', name: 'y', type: 'uint256' }, + { internalType: 'uint256', name: 'denominator', type: 'uint256' } + ], + name: 'PRBMath_MulDiv_Overflow', + type: 'error' }, { - inputs: [], - name: 'drawTimeout', - outputs: [{ internalType: 'uint24', name: '', type: 'uint24' }], - stateMutability: 'view', - type: 'function' + inputs: [{ internalType: 'SD59x18', name: 'x', type: 'int256' }], + name: 'PRBMath_SD59x18_Ceil_Overflow', + type: 'error' }, { - inputs: [], - name: 'drawTimeoutAt', - outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], - stateMutability: 'view', - type: 'function' + inputs: [{ internalType: 'int256', name: 'x', type: 'int256' }], + name: 'PRBMath_SD59x18_Convert_Overflow', + type: 'error' }, { - inputs: [], - name: 'estimateNextNumberOfTiers', - outputs: [{ internalType: 'uint8', name: '', type: 'uint8' }], - stateMutability: 'view', - type: 'function' + inputs: [{ internalType: 'int256', name: 'x', type: 'int256' }], + name: 'PRBMath_SD59x18_Convert_Underflow', + type: 'error' }, + { inputs: [], name: 'PRBMath_SD59x18_Div_InputTooSmall', type: 'error' }, { - inputs: [{ internalType: 'uint8', name: 'numTiers', type: 'uint8' }], - name: 'estimatedPrizeCount', - outputs: [{ internalType: 'uint32', name: '', type: 'uint32' }], - stateMutability: 'view', - type: 'function' + inputs: [ + { internalType: 'SD59x18', name: 'x', type: 'int256' }, + { internalType: 'SD59x18', name: 'y', type: 'int256' } + ], + name: 'PRBMath_SD59x18_Div_Overflow', + type: 'error' }, { - inputs: [], - name: 'estimatedPrizeCount', - outputs: [{ internalType: 'uint32', name: '', type: 'uint32' }], - stateMutability: 'view', - type: 'function' + inputs: [{ internalType: 'SD59x18', name: 'x', type: 'int256' }], + name: 'PRBMath_SD59x18_Exp2_InputTooBig', + type: 'error' }, { - inputs: [], - name: 'firstDrawOpensAt', - outputs: [{ internalType: 'uint48', name: '', type: 'uint48' }], - stateMutability: 'view', - type: 'function' + inputs: [{ internalType: 'SD59x18', name: 'x', type: 'int256' }], + name: 'PRBMath_SD59x18_Log_InputTooSmall', + type: 'error' }, + { inputs: [], name: 'PRBMath_SD59x18_Mul_InputTooSmall', type: 'error' }, { inputs: [ - { internalType: 'address', name: '_vault', type: 'address' }, - { internalType: 'uint24', name: '_startDrawIdInclusive', type: 'uint24' }, - { internalType: 'uint24', name: '_endDrawIdInclusive', type: 'uint24' } + { internalType: 'SD59x18', name: 'x', type: 'int256' }, + { internalType: 'SD59x18', name: 'y', type: 'int256' } ], - name: 'getContributedBetween', - outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], - stateMutability: 'view', - type: 'function' + name: 'PRBMath_SD59x18_Mul_Overflow', + type: 'error' }, { - inputs: [ - { internalType: 'uint24', name: '_startDrawIdInclusive', type: 'uint24' }, - { internalType: 'uint24', name: '_endDrawIdInclusive', type: 'uint24' } + inputs: [{ internalType: 'uint256', name: 'x', type: 'uint256' }], + name: 'PRBMath_UD34x4_fromUD60x18_Convert_Overflow', + type: 'error' + }, + { + inputs: [{ internalType: 'uint256', name: 'x', type: 'uint256' }], + name: 'PRBMath_UD60x18_Convert_Overflow', + type: 'error' + }, + { inputs: [], name: 'PrizeIsZero', type: 'error' }, + { inputs: [], name: 'PrizePoolNotShutdown', type: 'error' }, + { inputs: [], name: 'PrizePoolShutdown', type: 'error' }, + { inputs: [], name: 'RandomNumberIsZero', type: 'error' }, + { inputs: [], name: 'RangeSizeZero', type: 'error' }, + { inputs: [], name: 'RewardRecipientZeroAddress', type: 'error' }, + { + inputs: [ + { internalType: 'uint256', name: 'reward', type: 'uint256' }, + { internalType: 'uint256', name: 'maxReward', type: 'uint256' } ], - name: 'getDonatedBetween', - outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], - stateMutability: 'view', - type: 'function' + name: 'RewardTooLarge', + type: 'error' }, + { inputs: [], name: 'TierLiquidityUtilizationRateCannotBeZero', type: 'error' }, + { inputs: [], name: 'TierLiquidityUtilizationRateGreaterThanOne', type: 'error' }, + { inputs: [], name: 'UpperBoundGtZero', type: 'error' }, { - inputs: [], - name: 'getDrawIdToAward', - outputs: [{ internalType: 'uint24', name: '', type: 'uint24' }], - stateMutability: 'view', - type: 'function' + anonymous: false, + inputs: [ + { indexed: true, internalType: 'address', name: 'to', type: 'address' }, + { indexed: false, internalType: 'uint256', name: 'amount', type: 'uint256' } + ], + name: 'AllocateRewardFromReserve', + type: 'event' }, { - inputs: [], - name: 'getLastAwardedDrawId', - outputs: [{ internalType: 'uint24', name: '', type: 'uint24' }], - stateMutability: 'view', - type: 'function' + anonymous: false, + inputs: [ + { indexed: true, internalType: 'address', name: 'vault', type: 'address' }, + { indexed: true, internalType: 'address', name: 'winner', type: 'address' }, + { indexed: true, internalType: 'address', name: 'recipient', type: 'address' }, + { indexed: false, internalType: 'uint24', name: 'drawId', type: 'uint24' }, + { indexed: false, internalType: 'uint8', name: 'tier', type: 'uint8' }, + { indexed: false, internalType: 'uint32', name: 'prizeIndex', type: 'uint32' }, + { indexed: false, internalType: 'uint152', name: 'payout', type: 'uint152' }, + { indexed: false, internalType: 'uint96', name: 'claimReward', type: 'uint96' }, + { indexed: false, internalType: 'address', name: 'claimRewardRecipient', type: 'address' } + ], + name: 'ClaimedPrize', + type: 'event' }, { - inputs: [], - name: 'getOpenDrawId', - outputs: [{ internalType: 'uint24', name: '', type: 'uint24' }], - stateMutability: 'view', - type: 'function' + anonymous: false, + inputs: [ + { indexed: true, internalType: 'address', name: 'vault', type: 'address' }, + { indexed: true, internalType: 'uint24', name: 'drawId', type: 'uint24' }, + { indexed: false, internalType: 'uint256', name: 'amount', type: 'uint256' } + ], + name: 'ContributePrizeTokens', + type: 'event' }, { - inputs: [{ internalType: 'uint8', name: '_tier', type: 'uint8' }], - name: 'getTierAccrualDurationInDraws', - outputs: [{ internalType: 'uint24', name: '', type: 'uint24' }], - stateMutability: 'view', - type: 'function' + anonymous: false, + inputs: [ + { indexed: true, internalType: 'address', name: 'user', type: 'address' }, + { indexed: false, internalType: 'uint256', name: 'amount', type: 'uint256' } + ], + name: 'ContributedReserve', + type: 'event' }, { + anonymous: false, inputs: [ - { internalType: 'uint8', name: '_tier', type: 'uint8' }, - { internalType: 'uint8', name: '_numTiers', type: 'uint8' } + { indexed: true, internalType: 'uint24', name: 'drawId', type: 'uint24' }, + { indexed: false, internalType: 'uint256', name: 'winningRandomNumber', type: 'uint256' }, + { indexed: false, internalType: 'uint8', name: 'lastNumTiers', type: 'uint8' }, + { indexed: false, internalType: 'uint8', name: 'numTiers', type: 'uint8' }, + { indexed: false, internalType: 'uint104', name: 'reserve', type: 'uint104' }, + { indexed: false, internalType: 'UD34x4', name: 'prizeTokensPerShare', type: 'uint128' }, + { indexed: false, internalType: 'uint48', name: 'drawOpenedAt', type: 'uint48' } ], - name: 'getTierOdds', - outputs: [{ internalType: 'SD59x18', name: '', type: 'int256' }], - stateMutability: 'view', - type: 'function' + name: 'DrawAwarded', + type: 'event' }, { - inputs: [{ internalType: 'uint8', name: '_tier', type: 'uint8' }], - name: 'getTierPrizeCount', - outputs: [{ internalType: 'uint32', name: '', type: 'uint32' }], - stateMutability: 'pure', - type: 'function' + anonymous: false, + inputs: [ + { indexed: true, internalType: 'address', name: 'to', type: 'address' }, + { indexed: false, internalType: 'uint256', name: 'amount', type: 'uint256' } + ], + name: 'IncreaseClaimRewards', + type: 'event' }, { - inputs: [{ internalType: 'uint8', name: '_tier', type: 'uint8' }], - name: 'getTierPrizeSize', - outputs: [{ internalType: 'uint104', name: '', type: 'uint104' }], - stateMutability: 'view', - type: 'function' + anonymous: false, + inputs: [{ indexed: false, internalType: 'uint256', name: 'amount', type: 'uint256' }], + name: 'ReserveConsumed', + type: 'event' }, { - inputs: [{ internalType: 'uint8', name: '_tier', type: 'uint8' }], - name: 'getTierRemainingLiquidity', - outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], - stateMutability: 'view', - type: 'function' + anonymous: false, + inputs: [{ indexed: true, internalType: 'address', name: 'drawManager', type: 'address' }], + name: 'SetDrawManager', + type: 'event' }, { + anonymous: false, inputs: [ - { internalType: 'uint24', name: '_startDrawIdInclusive', type: 'uint24' }, - { internalType: 'uint24', name: '_endDrawIdInclusive', type: 'uint24' } + { indexed: true, internalType: 'address', name: 'account', type: 'address' }, + { indexed: true, internalType: 'address', name: 'to', type: 'address' }, + { indexed: false, internalType: 'uint256', name: 'amount', type: 'uint256' }, + { indexed: false, internalType: 'uint256', name: 'available', type: 'uint256' } ], - name: 'getTotalContributedBetween', - outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + name: 'WithdrawRewards', + type: 'event' + }, + { + inputs: [], + name: 'DONATOR', + outputs: [{ internalType: 'address', name: '', type: 'address' }], stateMutability: 'view', type: 'function' }, { inputs: [], - name: 'getTotalShares', + name: 'accountedBalance', outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], stateMutability: 'view', type: 'function' }, { inputs: [ - { internalType: 'address', name: '_vault', type: 'address' }, - { internalType: 'uint24', name: '_startDrawIdInclusive', type: 'uint24' }, - { internalType: 'uint24', name: '_endDrawIdInclusive', type: 'uint24' } + { internalType: 'address', name: '_to', type: 'address' }, + { internalType: 'uint96', name: '_amount', type: 'uint96' } ], - name: 'getVaultPortion', - outputs: [{ internalType: 'SD59x18', name: '', type: 'int256' }], - stateMutability: 'view', + name: 'allocateRewardFromReserve', + outputs: [], + stateMutability: 'nonpayable', type: 'function' }, { - inputs: [ - { internalType: 'address', name: '_vault', type: 'address' }, - { internalType: 'address', name: '_user', type: 'address' }, - { internalType: 'uint24', name: '_startDrawIdInclusive', type: 'uint24' }, - { internalType: 'uint24', name: '_endDrawIdInclusive', type: 'uint24' } - ], - name: 'getVaultUserBalanceAndTotalSupplyTwab', - outputs: [ - { internalType: 'uint256', name: 'twab', type: 'uint256' }, - { internalType: 'uint256', name: 'twabTotalSupply', type: 'uint256' } - ], - stateMutability: 'view', + inputs: [{ internalType: 'uint256', name: 'winningRandomNumber_', type: 'uint256' }], + name: 'awardDraw', + outputs: [{ internalType: 'uint24', name: '', type: 'uint24' }], + stateMutability: 'nonpayable', type: 'function' }, { inputs: [], - name: 'getWinningRandomNumber', - outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + name: 'canaryShares', + outputs: [{ internalType: 'uint8', name: '', type: 'uint8' }], stateMutability: 'view', type: 'function' }, { inputs: [], - name: 'grandPrizePeriodDraws', + name: 'claimCount', outputs: [{ internalType: 'uint24', name: '', type: 'uint24' }], stateMutability: 'view', type: 'function' }, { - inputs: [{ internalType: 'uint8', name: '_tier', type: 'uint8' }], - name: 'isCanaryTier', - outputs: [{ internalType: 'bool', name: '', type: 'bool' }], - stateMutability: 'view', + inputs: [ + { internalType: 'address', name: '_winner', type: 'address' }, + { internalType: 'uint8', name: '_tier', type: 'uint8' }, + { internalType: 'uint32', name: '_prizeIndex', type: 'uint32' }, + { internalType: 'address', name: '_prizeRecipient', type: 'address' }, + { internalType: 'uint96', name: '_claimReward', type: 'uint96' }, + { internalType: 'address', name: '_claimRewardRecipient', type: 'address' } + ], + name: 'claimPrize', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'nonpayable', type: 'function' }, { - inputs: [{ internalType: 'uint24', name: 'drawId', type: 'uint24' }], - name: 'isDrawFinalized', - outputs: [{ internalType: 'bool', name: '', type: 'bool' }], + inputs: [{ internalType: 'uint32', name: '_claimCount', type: 'uint32' }], + name: 'computeNextNumberOfTiers', + outputs: [{ internalType: 'uint8', name: '', type: 'uint8' }], stateMutability: 'view', type: 'function' }, { - inputs: [], - name: 'isShutdown', - outputs: [{ internalType: 'bool', name: 'shutdown', type: 'bool' }], + inputs: [ + { internalType: 'uint24', name: '_endDrawIdInclusive', type: 'uint24' }, + { internalType: 'uint24', name: '_rangeSize', type: 'uint24' } + ], + name: 'computeRangeStartDrawIdInclusive', + outputs: [{ internalType: 'uint24', name: '', type: 'uint24' }], + stateMutability: 'pure', + type: 'function' + }, + { + inputs: [{ internalType: 'uint8', name: '_numberOfTiers', type: 'uint8' }], + name: 'computeTotalShares', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], stateMutability: 'view', type: 'function' }, { inputs: [ - { internalType: 'address', name: '_vault', type: 'address' }, - { internalType: 'address', name: '_user', type: 'address' }, - { internalType: 'uint8', name: '_tier', type: 'uint8' }, - { internalType: 'uint32', name: '_prizeIndex', type: 'uint32' } + { internalType: 'address', name: '_prizeVault', type: 'address' }, + { internalType: 'uint256', name: '_amount', type: 'uint256' } ], - name: 'isWinner', - outputs: [{ internalType: 'bool', name: '', type: 'bool' }], - stateMutability: 'view', + name: 'contributePrizeTokens', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'nonpayable', type: 'function' }, { - inputs: [], - name: 'lastAwardedDrawAwardedAt', - outputs: [{ internalType: 'uint48', name: '', type: 'uint48' }], - stateMutability: 'view', + inputs: [{ internalType: 'uint96', name: '_amount', type: 'uint96' }], + name: 'contributeReserve', + outputs: [], + stateMutability: 'nonpayable', type: 'function' }, { - inputs: [], - name: 'numberOfTiers', - outputs: [{ internalType: 'uint8', name: '', type: 'uint8' }], - stateMutability: 'view', + inputs: [{ internalType: 'uint256', name: '_amount', type: 'uint256' }], + name: 'donatePrizeTokens', + outputs: [], + stateMutability: 'nonpayable', type: 'function' }, { - inputs: [], - name: 'pendingReserveContributions', - outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + inputs: [{ internalType: 'uint24', name: 'drawId', type: 'uint24' }], + name: 'drawClosesAt', + outputs: [{ internalType: 'uint48', name: '', type: 'uint48' }], stateMutability: 'view', type: 'function' }, { inputs: [], - name: 'prizeToken', - outputs: [{ internalType: 'contract IERC20', name: '', type: 'address' }], + name: 'drawIdPriorToShutdown', + outputs: [{ internalType: 'uint24', name: '', type: 'uint24' }], stateMutability: 'view', type: 'function' }, { inputs: [], - name: 'prizeTokenPerShare', - outputs: [{ internalType: 'UD34x4', name: '', type: 'uint128' }], + name: 'drawManager', + outputs: [{ internalType: 'address', name: '', type: 'address' }], + stateMutability: 'view', + type: 'function' + }, + { + inputs: [{ internalType: 'uint24', name: 'drawId', type: 'uint24' }], + name: 'drawOpensAt', + outputs: [{ internalType: 'uint48', name: '', type: 'uint48' }], stateMutability: 'view', type: 'function' }, { inputs: [], - name: 'reserve', - outputs: [{ internalType: 'uint96', name: '', type: 'uint96' }], + name: 'drawPeriodSeconds', + outputs: [{ internalType: 'uint48', name: '', type: 'uint48' }], stateMutability: 'view', type: 'function' }, { inputs: [], - name: 'reserveShares', - outputs: [{ internalType: 'uint8', name: '', type: 'uint8' }], + name: 'drawTimeout', + outputs: [{ internalType: 'uint24', name: '', type: 'uint24' }], stateMutability: 'view', type: 'function' }, { - inputs: [{ internalType: 'address', name: '_recipient', type: 'address' }], - name: 'rewardBalance', + inputs: [], + name: 'drawTimeoutAt', outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], stateMutability: 'view', type: 'function' }, { - inputs: [{ internalType: 'address', name: '_drawManager', type: 'address' }], - name: 'setDrawManager', - outputs: [], - stateMutability: 'nonpayable', + inputs: [], + name: 'estimateNextNumberOfTiers', + outputs: [{ internalType: 'uint8', name: '', type: 'uint8' }], + stateMutability: 'view', + type: 'function' + }, + { + inputs: [{ internalType: 'uint8', name: 'numTiers', type: 'uint8' }], + name: 'estimatedPrizeCount', + outputs: [{ internalType: 'uint32', name: '', type: 'uint32' }], + stateMutability: 'view', type: 'function' }, { inputs: [], - name: 'shutdownAt', - outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + name: 'estimatedPrizeCount', + outputs: [{ internalType: 'uint32', name: '', type: 'uint32' }], + stateMutability: 'view', + type: 'function' + }, + { + inputs: [], + name: 'firstDrawOpensAt', + outputs: [{ internalType: 'uint48', name: '', type: 'uint48' }], stateMutability: 'view', type: 'function' }, { inputs: [ { internalType: 'address', name: '_vault', type: 'address' }, - { internalType: 'address', name: '_account', type: 'address' } + { internalType: 'uint24', name: '_startDrawIdInclusive', type: 'uint24' }, + { internalType: 'uint24', name: '_endDrawIdInclusive', type: 'uint24' } ], - name: 'shutdownBalanceOf', + name: 'getContributedBetween', outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], stateMutability: 'view', type: 'function' }, { - inputs: [], - name: 'tierLiquidityUtilizationRate', - outputs: [{ internalType: 'UD60x18', name: '', type: 'uint256' }], + inputs: [ + { internalType: 'uint24', name: '_startDrawIdInclusive', type: 'uint24' }, + { internalType: 'uint24', name: '_endDrawIdInclusive', type: 'uint24' } + ], + name: 'getDonatedBetween', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], stateMutability: 'view', type: 'function' }, { inputs: [], - name: 'tierShares', - outputs: [{ internalType: 'uint8', name: '', type: 'uint8' }], + name: 'getDrawIdToAward', + outputs: [{ internalType: 'uint24', name: '', type: 'uint24' }], stateMutability: 'view', type: 'function' }, { inputs: [], - name: 'totalWithdrawn', - outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + name: 'getLastAwardedDrawId', + outputs: [{ internalType: 'uint24', name: '', type: 'uint24' }], stateMutability: 'view', type: 'function' }, { inputs: [], - name: 'twabController', - outputs: [{ internalType: 'contract TwabController', name: '', type: 'address' }], + name: 'getOpenDrawId', + outputs: [{ internalType: 'uint24', name: '', type: 'uint24' }], stateMutability: 'view', type: 'function' }, { - inputs: [ - { internalType: 'address', name: '_vault', type: 'address' }, - { internalType: 'address', name: '_winner', type: 'address' }, - { internalType: 'uint8', name: '_tier', type: 'uint8' }, - { internalType: 'uint32', name: '_prizeIndex', type: 'uint32' } - ], - name: 'wasClaimed', - outputs: [{ internalType: 'bool', name: '', type: 'bool' }], + inputs: [{ internalType: 'uint8', name: '_tier', type: 'uint8' }], + name: 'getTierAccrualDurationInDraws', + outputs: [{ internalType: 'uint24', name: '', type: 'uint24' }], stateMutability: 'view', type: 'function' }, { inputs: [ - { internalType: 'address', name: '_to', type: 'address' }, - { internalType: 'uint256', name: '_amount', type: 'uint256' } + { internalType: 'uint8', name: '_tier', type: 'uint8' }, + { internalType: 'uint8', name: '_numTiers', type: 'uint8' } ], - name: 'withdrawRewards', - outputs: [], - stateMutability: 'nonpayable', + name: 'getTierOdds', + outputs: [{ internalType: 'SD59x18', name: '', type: 'int256' }], + stateMutability: 'view', type: 'function' }, { - inputs: [ - { internalType: 'address', name: '_vault', type: 'address' }, - { internalType: 'address', name: '_recipient', type: 'address' } - ], - name: 'withdrawShutdownBalance', - outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], - stateMutability: 'nonpayable', + inputs: [{ internalType: 'uint8', name: '_tier', type: 'uint8' }], + name: 'getTierPrizeCount', + outputs: [{ internalType: 'uint32', name: '', type: 'uint32' }], + stateMutability: 'pure', type: 'function' }, { - anonymous: false, - inputs: [ - { indexed: true, internalType: 'address', name: 'to', type: 'address' }, - { indexed: false, internalType: 'uint256', name: 'amount', type: 'uint256' } - ], - name: 'AllocateRewardFromReserve', - type: 'event' + inputs: [{ internalType: 'uint8', name: '_tier', type: 'uint8' }], + name: 'getTierPrizeSize', + outputs: [{ internalType: 'uint104', name: '', type: 'uint104' }], + stateMutability: 'view', + type: 'function' }, { - anonymous: false, - inputs: [ - { indexed: true, internalType: 'address', name: 'vault', type: 'address' }, - { indexed: true, internalType: 'address', name: 'winner', type: 'address' }, - { indexed: true, internalType: 'address', name: 'recipient', type: 'address' }, - { indexed: false, internalType: 'uint24', name: 'drawId', type: 'uint24' }, - { indexed: false, internalType: 'uint8', name: 'tier', type: 'uint8' }, - { indexed: false, internalType: 'uint32', name: 'prizeIndex', type: 'uint32' }, - { indexed: false, internalType: 'uint152', name: 'payout', type: 'uint152' }, - { indexed: false, internalType: 'uint96', name: 'claimReward', type: 'uint96' }, - { indexed: false, internalType: 'address', name: 'claimRewardRecipient', type: 'address' } - ], - name: 'ClaimedPrize', - type: 'event' + inputs: [{ internalType: 'uint8', name: '_tier', type: 'uint8' }], + name: 'getTierRemainingLiquidity', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function' }, { - anonymous: false, inputs: [ - { indexed: true, internalType: 'address', name: 'vault', type: 'address' }, - { indexed: true, internalType: 'uint24', name: 'drawId', type: 'uint24' }, - { indexed: false, internalType: 'uint256', name: 'amount', type: 'uint256' } + { internalType: 'uint24', name: '_startDrawIdInclusive', type: 'uint24' }, + { internalType: 'uint24', name: '_endDrawIdInclusive', type: 'uint24' } ], - name: 'ContributePrizeTokens', - type: 'event' + name: 'getTotalContributedBetween', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function' }, { - anonymous: false, - inputs: [ - { indexed: true, internalType: 'address', name: 'user', type: 'address' }, - { indexed: false, internalType: 'uint256', name: 'amount', type: 'uint256' } - ], - name: 'ContributedReserve', - type: 'event' + inputs: [], + name: 'getTotalShares', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function' }, { - anonymous: false, inputs: [ - { indexed: true, internalType: 'uint24', name: 'drawId', type: 'uint24' }, - { indexed: false, internalType: 'uint256', name: 'winningRandomNumber', type: 'uint256' }, - { indexed: false, internalType: 'uint8', name: 'lastNumTiers', type: 'uint8' }, - { indexed: false, internalType: 'uint8', name: 'numTiers', type: 'uint8' }, - { indexed: false, internalType: 'uint104', name: 'reserve', type: 'uint104' }, - { indexed: false, internalType: 'UD34x4', name: 'prizeTokensPerShare', type: 'uint128' }, - { indexed: false, internalType: 'uint48', name: 'drawOpenedAt', type: 'uint48' } + { internalType: 'address', name: '_vault', type: 'address' }, + { internalType: 'uint24', name: '_startDrawIdInclusive', type: 'uint24' }, + { internalType: 'uint24', name: '_endDrawIdInclusive', type: 'uint24' } ], - name: 'DrawAwarded', - type: 'event' + name: 'getVaultPortion', + outputs: [{ internalType: 'SD59x18', name: '', type: 'int256' }], + stateMutability: 'view', + type: 'function' }, { - anonymous: false, inputs: [ - { indexed: true, internalType: 'address', name: 'to', type: 'address' }, - { indexed: false, internalType: 'uint256', name: 'amount', type: 'uint256' } + { internalType: 'address', name: '_vault', type: 'address' }, + { internalType: 'address', name: '_user', type: 'address' }, + { internalType: 'uint24', name: '_startDrawIdInclusive', type: 'uint24' }, + { internalType: 'uint24', name: '_endDrawIdInclusive', type: 'uint24' } ], - name: 'IncreaseClaimRewards', - type: 'event' + name: 'getVaultUserBalanceAndTotalSupplyTwab', + outputs: [ + { internalType: 'uint256', name: 'twab', type: 'uint256' }, + { internalType: 'uint256', name: 'twabTotalSupply', type: 'uint256' } + ], + stateMutability: 'view', + type: 'function' }, { - anonymous: false, - inputs: [{ indexed: false, internalType: 'uint256', name: 'amount', type: 'uint256' }], - name: 'ReserveConsumed', - type: 'event' + inputs: [], + name: 'getWinningRandomNumber', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function' }, { - anonymous: false, - inputs: [{ indexed: true, internalType: 'address', name: 'drawManager', type: 'address' }], - name: 'SetDrawManager', - type: 'event' + inputs: [], + name: 'grandPrizePeriodDraws', + outputs: [{ internalType: 'uint24', name: '', type: 'uint24' }], + stateMutability: 'view', + type: 'function' }, { - anonymous: false, - inputs: [ - { indexed: true, internalType: 'address', name: 'account', type: 'address' }, - { indexed: true, internalType: 'address', name: 'to', type: 'address' }, - { indexed: false, internalType: 'uint256', name: 'amount', type: 'uint256' }, - { indexed: false, internalType: 'uint256', name: 'available', type: 'uint256' } - ], - name: 'WithdrawRewards', - type: 'event' + inputs: [{ internalType: 'uint8', name: '_tier', type: 'uint8' }], + name: 'isCanaryTier', + outputs: [{ internalType: 'bool', name: '', type: 'bool' }], + stateMutability: 'view', + type: 'function' }, - { inputs: [], name: 'AddToDrawZero', type: 'error' }, { - inputs: [{ internalType: 'uint48', name: 'drawClosesAt', type: 'uint48' }], - name: 'AwardingDrawNotClosed', - type: 'error' + inputs: [{ internalType: 'uint24', name: 'drawId', type: 'uint24' }], + name: 'isDrawFinalized', + outputs: [{ internalType: 'bool', name: '', type: 'bool' }], + stateMutability: 'view', + type: 'function' }, { - inputs: [ - { internalType: 'address', name: 'caller', type: 'address' }, - { internalType: 'address', name: 'drawManager', type: 'address' } - ], - name: 'CallerNotDrawManager', - type: 'error' + inputs: [], + name: 'isShutdown', + outputs: [{ internalType: 'bool', name: 'shutdown', type: 'bool' }], + stateMutability: 'view', + type: 'function' }, - { inputs: [], name: 'ClaimPeriodExpired', type: 'error' }, { inputs: [ - { internalType: 'uint256', name: 'amount', type: 'uint256' }, - { internalType: 'uint256', name: 'available', type: 'uint256' } + { internalType: 'address', name: '_vault', type: 'address' }, + { internalType: 'address', name: '_user', type: 'address' }, + { internalType: 'uint8', name: '_tier', type: 'uint8' }, + { internalType: 'uint32', name: '_prizeIndex', type: 'uint32' } ], - name: 'ContributionGTDeltaBalance', - type: 'error' + name: 'isWinner', + outputs: [{ internalType: 'bool', name: '', type: 'bool' }], + stateMutability: 'view', + type: 'function' }, - { inputs: [], name: 'CreatorIsZeroAddress', type: 'error' }, { - inputs: [ - { internalType: 'address', name: 'vault', type: 'address' }, - { internalType: 'address', name: 'winner', type: 'address' }, - { internalType: 'uint8', name: 'tier', type: 'uint8' }, - { internalType: 'uint32', name: 'prizeIndex', type: 'uint32' } - ], - name: 'DidNotWin', - type: 'error' + inputs: [], + name: 'lastAwardedDrawAwardedAt', + outputs: [{ internalType: 'uint48', name: '', type: 'uint48' }], + stateMutability: 'view', + type: 'function' }, { - inputs: [ - { internalType: 'uint24', name: 'drawId', type: 'uint24' }, - { internalType: 'uint24', name: 'newestDrawId', type: 'uint24' } - ], - name: 'DrawAwarded', - type: 'error' + inputs: [], + name: 'numberOfTiers', + outputs: [{ internalType: 'uint8', name: '', type: 'uint8' }], + stateMutability: 'view', + type: 'function' }, - { inputs: [], name: 'DrawManagerAlreadySet', type: 'error' }, - { inputs: [], name: 'DrawTimeoutGTGrandPrizePeriodDraws', type: 'error' }, - { inputs: [], name: 'DrawTimeoutIsZero', type: 'error' }, - { inputs: [], name: 'FirstDrawOpensInPast', type: 'error' }, - { inputs: [], name: 'IncompatibleTwabPeriodLength', type: 'error' }, - { inputs: [], name: 'IncompatibleTwabPeriodOffset', type: 'error' }, { - inputs: [{ internalType: 'uint104', name: 'requestedLiquidity', type: 'uint104' }], - name: 'InsufficientLiquidity', - type: 'error' + inputs: [], + name: 'pendingReserveContributions', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function' }, { - inputs: [ - { internalType: 'uint104', name: 'amount', type: 'uint104' }, - { internalType: 'uint104', name: 'reserve', type: 'uint104' } - ], - name: 'InsufficientReserve', - type: 'error' + inputs: [], + name: 'prizeToken', + outputs: [{ internalType: 'contract IERC20', name: '', type: 'address' }], + stateMutability: 'view', + type: 'function' }, { - inputs: [ - { internalType: 'uint256', name: 'requested', type: 'uint256' }, - { internalType: 'uint256', name: 'available', type: 'uint256' } - ], - name: 'InsufficientRewardsError', - type: 'error' + inputs: [], + name: 'prizeTokenPerShare', + outputs: [{ internalType: 'UD34x4', name: '', type: 'uint128' }], + stateMutability: 'view', + type: 'function' }, { - inputs: [ - { internalType: 'uint24', name: 'startDrawId', type: 'uint24' }, - { internalType: 'uint24', name: 'endDrawId', type: 'uint24' } - ], - name: 'InvalidDrawRange', - type: 'error' + inputs: [], + name: 'reserve', + outputs: [{ internalType: 'uint96', name: '', type: 'uint96' }], + stateMutability: 'view', + type: 'function' }, { - inputs: [ - { internalType: 'uint32', name: 'invalidPrizeIndex', type: 'uint32' }, - { internalType: 'uint32', name: 'prizeCount', type: 'uint32' }, - { internalType: 'uint8', name: 'tier', type: 'uint8' } - ], - name: 'InvalidPrizeIndex', - type: 'error' + inputs: [], + name: 'reserveShares', + outputs: [{ internalType: 'uint8', name: '', type: 'uint8' }], + stateMutability: 'view', + type: 'function' }, { - inputs: [ - { internalType: 'uint8', name: 'tier', type: 'uint8' }, - { internalType: 'uint8', name: 'numberOfTiers', type: 'uint8' } - ], - name: 'InvalidTier', - type: 'error' + inputs: [{ internalType: 'address', name: '_recipient', type: 'address' }], + name: 'rewardBalance', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function' }, - { inputs: [], name: 'NoDrawsAwarded', type: 'error' }, { - inputs: [{ internalType: 'uint8', name: 'numTiers', type: 'uint8' }], - name: 'NumberOfTiersGreaterThanMaximum', - type: 'error' + inputs: [{ internalType: 'address', name: '_drawManager', type: 'address' }], + name: 'setDrawManager', + outputs: [], + stateMutability: 'nonpayable', + type: 'function' }, { - inputs: [{ internalType: 'uint8', name: 'numTiers', type: 'uint8' }], - name: 'NumberOfTiersLessThanMinimum', - type: 'error' + inputs: [], + name: 'shutdownAt', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function' }, - { inputs: [], name: 'OnlyCreator', type: 'error' }, { inputs: [ - { internalType: 'uint256', name: 'x', type: 'uint256' }, - { internalType: 'uint256', name: 'y', type: 'uint256' } + { internalType: 'address', name: '_vault', type: 'address' }, + { internalType: 'address', name: '_account', type: 'address' } ], - name: 'PRBMath_MulDiv18_Overflow', - type: 'error' + name: 'shutdownBalanceOf', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function' }, { - inputs: [ - { internalType: 'uint256', name: 'x', type: 'uint256' }, - { internalType: 'uint256', name: 'y', type: 'uint256' }, - { internalType: 'uint256', name: 'denominator', type: 'uint256' } - ], - name: 'PRBMath_MulDiv_Overflow', - type: 'error' + inputs: [], + name: 'tierLiquidityUtilizationRate', + outputs: [{ internalType: 'UD60x18', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function' }, { - inputs: [{ internalType: 'SD59x18', name: 'x', type: 'int256' }], - name: 'PRBMath_SD59x18_Ceil_Overflow', - type: 'error' + inputs: [], + name: 'tierShares', + outputs: [{ internalType: 'uint8', name: '', type: 'uint8' }], + stateMutability: 'view', + type: 'function' }, { - inputs: [{ internalType: 'int256', name: 'x', type: 'int256' }], - name: 'PRBMath_SD59x18_Convert_Overflow', - type: 'error' + inputs: [], + name: 'totalWithdrawn', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function' }, { - inputs: [{ internalType: 'int256', name: 'x', type: 'int256' }], - name: 'PRBMath_SD59x18_Convert_Underflow', - type: 'error' + inputs: [], + name: 'twabController', + outputs: [{ internalType: 'contract TwabController', name: '', type: 'address' }], + stateMutability: 'view', + type: 'function' }, - { inputs: [], name: 'PRBMath_SD59x18_Div_InputTooSmall', type: 'error' }, { inputs: [ - { internalType: 'SD59x18', name: 'x', type: 'int256' }, - { internalType: 'SD59x18', name: 'y', type: 'int256' } + { internalType: 'address', name: '_vault', type: 'address' }, + { internalType: 'address', name: '_winner', type: 'address' }, + { internalType: 'uint8', name: '_tier', type: 'uint8' }, + { internalType: 'uint32', name: '_prizeIndex', type: 'uint32' } ], - name: 'PRBMath_SD59x18_Div_Overflow', - type: 'error' - }, - { - inputs: [{ internalType: 'SD59x18', name: 'x', type: 'int256' }], - name: 'PRBMath_SD59x18_Exp2_InputTooBig', - type: 'error' - }, - { - inputs: [{ internalType: 'SD59x18', name: 'x', type: 'int256' }], - name: 'PRBMath_SD59x18_Log_InputTooSmall', - type: 'error' + name: 'wasClaimed', + outputs: [{ internalType: 'bool', name: '', type: 'bool' }], + stateMutability: 'view', + type: 'function' }, - { inputs: [], name: 'PRBMath_SD59x18_Mul_InputTooSmall', type: 'error' }, { inputs: [ - { internalType: 'SD59x18', name: 'x', type: 'int256' }, - { internalType: 'SD59x18', name: 'y', type: 'int256' } + { internalType: 'address', name: '_to', type: 'address' }, + { internalType: 'uint256', name: '_amount', type: 'uint256' } ], - name: 'PRBMath_SD59x18_Mul_Overflow', - type: 'error' - }, - { - inputs: [{ internalType: 'uint256', name: 'x', type: 'uint256' }], - name: 'PRBMath_UD34x4_fromUD60x18_Convert_Overflow', - type: 'error' - }, - { - inputs: [{ internalType: 'uint256', name: 'x', type: 'uint256' }], - name: 'PRBMath_UD60x18_Convert_Overflow', - type: 'error' + name: 'withdrawRewards', + outputs: [], + stateMutability: 'nonpayable', + type: 'function' }, - { inputs: [], name: 'PrizeIsZero', type: 'error' }, - { inputs: [], name: 'PrizePoolNotShutdown', type: 'error' }, - { inputs: [], name: 'PrizePoolShutdown', type: 'error' }, - { inputs: [], name: 'RandomNumberIsZero', type: 'error' }, - { inputs: [], name: 'RangeSizeZero', type: 'error' }, - { inputs: [], name: 'RewardRecipientZeroAddress', type: 'error' }, { inputs: [ - { internalType: 'uint256', name: 'reward', type: 'uint256' }, - { internalType: 'uint256', name: 'maxReward', type: 'uint256' } + { internalType: 'address', name: '_vault', type: 'address' }, + { internalType: 'address', name: '_recipient', type: 'address' } ], - name: 'RewardTooLarge', - type: 'error' - }, - { inputs: [], name: 'TierLiquidityUtilizationRateCannotBeZero', type: 'error' }, - { inputs: [], name: 'TierLiquidityUtilizationRateGreaterThanOne', type: 'error' }, - { inputs: [], name: 'UpperBoundGtZero', type: 'error' } + name: 'withdrawShutdownBalance', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'nonpayable', + type: 'function' + } ] as const diff --git a/shared/utilities/abis/twabController.ts b/shared/utilities/abis/twabController.ts index 80c792df..b96d14dc 100644 --- a/shared/utilities/abis/twabController.ts +++ b/shared/utilities/abis/twabController.ts @@ -1,4 +1,164 @@ export const twabControllerABI = [ + { + inputs: [ + { internalType: 'uint32', name: '_periodLength', type: 'uint32' }, + { internalType: 'uint32', name: '_periodOffset', type: 'uint32' } + ], + stateMutability: 'nonpayable', + type: 'constructor' + }, + { + inputs: [ + { internalType: 'uint96', name: 'balance', type: 'uint96' }, + { internalType: 'uint96', name: 'amount', type: 'uint96' }, + { internalType: 'string', name: 'message', type: 'string' } + ], + name: 'BalanceLTAmount', + type: 'error' + }, + { inputs: [], name: 'CannotTransferToSponsorshipAddress', type: 'error' }, + { + inputs: [ + { internalType: 'uint96', name: 'delegateBalance', type: 'uint96' }, + { internalType: 'uint96', name: 'delegateAmount', type: 'uint96' }, + { internalType: 'string', name: 'message', type: 'string' } + ], + name: 'DelegateBalanceLTAmount', + type: 'error' + }, + { + inputs: [ + { internalType: 'PeriodOffsetRelativeTimestamp', name: 'requestedTimestamp', type: 'uint32' }, + { internalType: 'PeriodOffsetRelativeTimestamp', name: 'oldestTimestamp', type: 'uint32' } + ], + name: 'InsufficientHistory', + type: 'error' + }, + { + inputs: [ + { internalType: 'uint256', name: 'start', type: 'uint256' }, + { internalType: 'uint256', name: 'end', type: 'uint256' } + ], + name: 'InvalidTimeRange', + type: 'error' + }, + { inputs: [], name: 'PeriodLengthTooShort', type: 'error' }, + { + inputs: [{ internalType: 'uint32', name: 'periodOffset', type: 'uint32' }], + name: 'PeriodOffsetInFuture', + type: 'error' + }, + { + inputs: [{ internalType: 'address', name: 'delegate', type: 'address' }], + name: 'SameDelegateAlreadySet', + type: 'error' + }, + { + inputs: [ + { internalType: 'uint256', name: 'timestamp', type: 'uint256' }, + { internalType: 'uint256', name: 'currentOverwritePeriodStartedAt', type: 'uint256' } + ], + name: 'TimestampNotFinalized', + type: 'error' + }, + { inputs: [], name: 'TransferToZeroAddress', type: 'error' }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: 'address', name: 'vault', type: 'address' }, + { indexed: true, internalType: 'address', name: 'user', type: 'address' }, + { indexed: false, internalType: 'uint96', name: 'amount', type: 'uint96' }, + { indexed: false, internalType: 'uint96', name: 'delegateAmount', type: 'uint96' } + ], + name: 'DecreasedBalance', + type: 'event' + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: 'address', name: 'vault', type: 'address' }, + { indexed: false, internalType: 'uint96', name: 'amount', type: 'uint96' }, + { indexed: false, internalType: 'uint96', name: 'delegateAmount', type: 'uint96' } + ], + name: 'DecreasedTotalSupply', + type: 'event' + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: 'address', name: 'vault', type: 'address' }, + { indexed: true, internalType: 'address', name: 'delegator', type: 'address' }, + { indexed: true, internalType: 'address', name: 'delegate', type: 'address' } + ], + name: 'Delegated', + type: 'event' + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: 'address', name: 'vault', type: 'address' }, + { indexed: true, internalType: 'address', name: 'user', type: 'address' }, + { indexed: false, internalType: 'uint96', name: 'amount', type: 'uint96' }, + { indexed: false, internalType: 'uint96', name: 'delegateAmount', type: 'uint96' } + ], + name: 'IncreasedBalance', + type: 'event' + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: 'address', name: 'vault', type: 'address' }, + { indexed: false, internalType: 'uint96', name: 'amount', type: 'uint96' }, + { indexed: false, internalType: 'uint96', name: 'delegateAmount', type: 'uint96' } + ], + name: 'IncreasedTotalSupply', + type: 'event' + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: 'address', name: 'vault', type: 'address' }, + { indexed: true, internalType: 'address', name: 'user', type: 'address' }, + { indexed: false, internalType: 'uint96', name: 'balance', type: 'uint96' }, + { indexed: false, internalType: 'uint96', name: 'delegateBalance', type: 'uint96' }, + { indexed: false, internalType: 'bool', name: 'isNew', type: 'bool' }, + { + components: [ + { internalType: 'uint128', name: 'cumulativeBalance', type: 'uint128' }, + { internalType: 'uint96', name: 'balance', type: 'uint96' }, + { internalType: 'uint32', name: 'timestamp', type: 'uint32' } + ], + indexed: false, + internalType: 'struct ObservationLib.Observation', + name: 'observation', + type: 'tuple' + } + ], + name: 'ObservationRecorded', + type: 'event' + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: 'address', name: 'vault', type: 'address' }, + { indexed: false, internalType: 'uint96', name: 'balance', type: 'uint96' }, + { indexed: false, internalType: 'uint96', name: 'delegateBalance', type: 'uint96' }, + { indexed: false, internalType: 'bool', name: 'isNew', type: 'bool' }, + { + components: [ + { internalType: 'uint128', name: 'cumulativeBalance', type: 'uint128' }, + { internalType: 'uint96', name: 'balance', type: 'uint96' }, + { internalType: 'uint32', name: 'timestamp', type: 'uint32' } + ], + indexed: false, + internalType: 'struct ObservationLib.Observation', + name: 'observation', + type: 'tuple' + } + ], + name: 'TotalSupplyObservationRecorded', + type: 'event' + }, { inputs: [], name: 'PERIOD_LENGTH', @@ -347,157 +507,5 @@ export const twabControllerABI = [ outputs: [], stateMutability: 'nonpayable', type: 'function' - }, - { - anonymous: false, - inputs: [ - { indexed: true, internalType: 'address', name: 'vault', type: 'address' }, - { indexed: true, internalType: 'address', name: 'user', type: 'address' }, - { indexed: false, internalType: 'uint96', name: 'amount', type: 'uint96' }, - { indexed: false, internalType: 'uint96', name: 'delegateAmount', type: 'uint96' } - ], - name: 'DecreasedBalance', - type: 'event' - }, - { - anonymous: false, - inputs: [ - { indexed: true, internalType: 'address', name: 'vault', type: 'address' }, - { indexed: false, internalType: 'uint96', name: 'amount', type: 'uint96' }, - { indexed: false, internalType: 'uint96', name: 'delegateAmount', type: 'uint96' } - ], - name: 'DecreasedTotalSupply', - type: 'event' - }, - { - anonymous: false, - inputs: [ - { indexed: true, internalType: 'address', name: 'vault', type: 'address' }, - { indexed: true, internalType: 'address', name: 'delegator', type: 'address' }, - { indexed: true, internalType: 'address', name: 'delegate', type: 'address' } - ], - name: 'Delegated', - type: 'event' - }, - { - anonymous: false, - inputs: [ - { indexed: true, internalType: 'address', name: 'vault', type: 'address' }, - { indexed: true, internalType: 'address', name: 'user', type: 'address' }, - { indexed: false, internalType: 'uint96', name: 'amount', type: 'uint96' }, - { indexed: false, internalType: 'uint96', name: 'delegateAmount', type: 'uint96' } - ], - name: 'IncreasedBalance', - type: 'event' - }, - { - anonymous: false, - inputs: [ - { indexed: true, internalType: 'address', name: 'vault', type: 'address' }, - { indexed: false, internalType: 'uint96', name: 'amount', type: 'uint96' }, - { indexed: false, internalType: 'uint96', name: 'delegateAmount', type: 'uint96' } - ], - name: 'IncreasedTotalSupply', - type: 'event' - }, - { - anonymous: false, - inputs: [ - { indexed: true, internalType: 'address', name: 'vault', type: 'address' }, - { indexed: true, internalType: 'address', name: 'user', type: 'address' }, - { indexed: false, internalType: 'uint96', name: 'balance', type: 'uint96' }, - { indexed: false, internalType: 'uint96', name: 'delegateBalance', type: 'uint96' }, - { indexed: false, internalType: 'bool', name: 'isNew', type: 'bool' }, - { - components: [ - { internalType: 'uint128', name: 'cumulativeBalance', type: 'uint128' }, - { internalType: 'uint96', name: 'balance', type: 'uint96' }, - { internalType: 'uint32', name: 'timestamp', type: 'uint32' } - ], - indexed: false, - internalType: 'struct ObservationLib.Observation', - name: 'observation', - type: 'tuple' - } - ], - name: 'ObservationRecorded', - type: 'event' - }, - { - anonymous: false, - inputs: [ - { indexed: true, internalType: 'address', name: 'vault', type: 'address' }, - { indexed: false, internalType: 'uint96', name: 'balance', type: 'uint96' }, - { indexed: false, internalType: 'uint96', name: 'delegateBalance', type: 'uint96' }, - { indexed: false, internalType: 'bool', name: 'isNew', type: 'bool' }, - { - components: [ - { internalType: 'uint128', name: 'cumulativeBalance', type: 'uint128' }, - { internalType: 'uint96', name: 'balance', type: 'uint96' }, - { internalType: 'uint32', name: 'timestamp', type: 'uint32' } - ], - indexed: false, - internalType: 'struct ObservationLib.Observation', - name: 'observation', - type: 'tuple' - } - ], - name: 'TotalSupplyObservationRecorded', - type: 'event' - }, - { - inputs: [ - { internalType: 'uint96', name: 'balance', type: 'uint96' }, - { internalType: 'uint96', name: 'amount', type: 'uint96' }, - { internalType: 'string', name: 'message', type: 'string' } - ], - name: 'BalanceLTAmount', - type: 'error' - }, - { inputs: [], name: 'CannotTransferToSponsorshipAddress', type: 'error' }, - { - inputs: [ - { internalType: 'uint96', name: 'delegateBalance', type: 'uint96' }, - { internalType: 'uint96', name: 'delegateAmount', type: 'uint96' }, - { internalType: 'string', name: 'message', type: 'string' } - ], - name: 'DelegateBalanceLTAmount', - type: 'error' - }, - { - inputs: [ - { internalType: 'PeriodOffsetRelativeTimestamp', name: 'requestedTimestamp', type: 'uint32' }, - { internalType: 'PeriodOffsetRelativeTimestamp', name: 'oldestTimestamp', type: 'uint32' } - ], - name: 'InsufficientHistory', - type: 'error' - }, - { - inputs: [ - { internalType: 'uint256', name: 'start', type: 'uint256' }, - { internalType: 'uint256', name: 'end', type: 'uint256' } - ], - name: 'InvalidTimeRange', - type: 'error' - }, - { inputs: [], name: 'PeriodLengthTooShort', type: 'error' }, - { - inputs: [{ internalType: 'uint32', name: 'periodOffset', type: 'uint32' }], - name: 'PeriodOffsetInFuture', - type: 'error' - }, - { - inputs: [{ internalType: 'address', name: 'delegate', type: 'address' }], - name: 'SameDelegateAlreadySet', - type: 'error' - }, - { - inputs: [ - { internalType: 'uint256', name: 'timestamp', type: 'uint256' }, - { internalType: 'uint256', name: 'currentOverwritePeriodStartedAt', type: 'uint256' } - ], - name: 'TimestampNotFinalized', - type: 'error' - }, - { inputs: [], name: 'TransferToZeroAddress', type: 'error' } + } ] as const diff --git a/shared/utilities/abis/twabRewards.ts b/shared/utilities/abis/twabRewards.ts index a7bdb539..200bf2c7 100644 --- a/shared/utilities/abis/twabRewards.ts +++ b/shared/utilities/abis/twabRewards.ts @@ -1,4 +1,144 @@ export const twabRewardsABI = [ + { + inputs: [{ internalType: 'contract TwabController', name: '_twabController', type: 'address' }], + stateMutability: 'nonpayable', + type: 'constructor' + }, + { + inputs: [ + { internalType: 'uint48', name: 'epochDuration', type: 'uint48' }, + { internalType: 'uint32', name: 'twabPeriodLength', type: 'uint32' } + ], + name: 'EpochDurationNotMultipleOfTwabPeriod', + type: 'error' + }, + { + inputs: [{ internalType: 'uint64', name: 'epochEndTimestamp', type: 'uint64' }], + name: 'EpochNotOver', + type: 'error' + }, + { + inputs: [ + { internalType: 'uint8', name: 'epochExtension', type: 'uint8' }, + { internalType: 'uint8', name: 'currentEpochs', type: 'uint8' }, + { internalType: 'uint8', name: 'maxEpochs', type: 'uint8' } + ], + name: 'ExceedsMaxEpochs', + type: 'error' + }, + { + inputs: [{ internalType: 'uint256', name: 'gracePeriodEndTimestamp', type: 'uint256' }], + name: 'GracePeriodActive', + type: 'error' + }, + { + inputs: [ + { internalType: 'uint8', name: 'epochId', type: 'uint8' }, + { internalType: 'uint8', name: 'numberOfEpochs', type: 'uint8' } + ], + name: 'InvalidEpochId', + type: 'error' + }, + { + inputs: [{ internalType: 'uint256', name: 'promotionId', type: 'uint256' }], + name: 'InvalidPromotion', + type: 'error' + }, + { + inputs: [ + { internalType: 'address', name: 'sender', type: 'address' }, + { internalType: 'address', name: 'creator', type: 'address' } + ], + name: 'OnlyPromotionCreator', + type: 'error' + }, + { inputs: [], name: 'PayeeZeroAddress', type: 'error' }, + { + inputs: [{ internalType: 'uint256', name: 'promotionId', type: 'uint256' }], + name: 'PromotionInactive', + type: 'error' + }, + { + inputs: [ + { internalType: 'uint256', name: 'promotionId', type: 'uint256' }, + { internalType: 'address', name: 'user', type: 'address' }, + { internalType: 'uint8', name: 'epochId', type: 'uint8' } + ], + name: 'RewardsAlreadyClaimed', + type: 'error' + }, + { + inputs: [{ internalType: 'uint64', name: 'startTimePeriodOffset', type: 'uint64' }], + name: 'StartTimeNotAlignedWithTwabPeriod', + type: 'error' + }, + { + inputs: [ + { internalType: 'uint256', name: 'received', type: 'uint256' }, + { internalType: 'uint256', name: 'expected', type: 'uint256' } + ], + name: 'TokensReceivedLessThanExpected', + type: 'error' + }, + { inputs: [], name: 'TwabControllerZeroAddress', type: 'error' }, + { inputs: [], name: 'ZeroEpochDuration', type: 'error' }, + { inputs: [], name: 'ZeroEpochs', type: 'error' }, + { inputs: [], name: 'ZeroTokensPerEpoch', type: 'error' }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: 'uint256', name: 'promotionId', type: 'uint256' }, + { indexed: true, internalType: 'address', name: 'vault', type: 'address' }, + { indexed: true, internalType: 'contract IERC20', name: 'token', type: 'address' }, + { indexed: false, internalType: 'uint64', name: 'startTimestamp', type: 'uint64' }, + { indexed: false, internalType: 'uint256', name: 'tokensPerEpoch', type: 'uint256' }, + { indexed: false, internalType: 'uint48', name: 'epochDuration', type: 'uint48' }, + { indexed: false, internalType: 'uint8', name: 'initialNumberOfEpochs', type: 'uint8' } + ], + name: 'PromotionCreated', + type: 'event' + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: 'uint256', name: 'promotionId', type: 'uint256' }, + { indexed: true, internalType: 'address', name: 'recipient', type: 'address' }, + { indexed: false, internalType: 'uint256', name: 'amount', type: 'uint256' } + ], + name: 'PromotionDestroyed', + type: 'event' + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: 'uint256', name: 'promotionId', type: 'uint256' }, + { indexed: true, internalType: 'address', name: 'recipient', type: 'address' }, + { indexed: false, internalType: 'uint256', name: 'amount', type: 'uint256' }, + { indexed: false, internalType: 'uint8', name: 'epochNumber', type: 'uint8' } + ], + name: 'PromotionEnded', + type: 'event' + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: 'uint256', name: 'promotionId', type: 'uint256' }, + { indexed: false, internalType: 'uint256', name: 'numberOfEpochs', type: 'uint256' } + ], + name: 'PromotionExtended', + type: 'event' + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: 'uint256', name: 'promotionId', type: 'uint256' }, + { indexed: false, internalType: 'uint8[]', name: 'epochIds', type: 'uint8[]' }, + { indexed: true, internalType: 'address', name: 'user', type: 'address' }, + { indexed: false, internalType: 'uint256', name: 'amount', type: 'uint256' } + ], + name: 'RewardsClaimed', + type: 'event' + }, { inputs: [], name: 'GRACE_PERIOD', @@ -123,140 +263,5 @@ export const twabRewardsABI = [ outputs: [{ internalType: 'contract TwabController', name: '', type: 'address' }], stateMutability: 'view', type: 'function' - }, - { - anonymous: false, - inputs: [ - { indexed: true, internalType: 'uint256', name: 'promotionId', type: 'uint256' }, - { indexed: true, internalType: 'address', name: 'vault', type: 'address' }, - { indexed: true, internalType: 'contract IERC20', name: 'token', type: 'address' }, - { indexed: false, internalType: 'uint64', name: 'startTimestamp', type: 'uint64' }, - { indexed: false, internalType: 'uint256', name: 'tokensPerEpoch', type: 'uint256' }, - { indexed: false, internalType: 'uint48', name: 'epochDuration', type: 'uint48' }, - { indexed: false, internalType: 'uint8', name: 'initialNumberOfEpochs', type: 'uint8' } - ], - name: 'PromotionCreated', - type: 'event' - }, - { - anonymous: false, - inputs: [ - { indexed: true, internalType: 'uint256', name: 'promotionId', type: 'uint256' }, - { indexed: true, internalType: 'address', name: 'recipient', type: 'address' }, - { indexed: false, internalType: 'uint256', name: 'amount', type: 'uint256' } - ], - name: 'PromotionDestroyed', - type: 'event' - }, - { - anonymous: false, - inputs: [ - { indexed: true, internalType: 'uint256', name: 'promotionId', type: 'uint256' }, - { indexed: true, internalType: 'address', name: 'recipient', type: 'address' }, - { indexed: false, internalType: 'uint256', name: 'amount', type: 'uint256' }, - { indexed: false, internalType: 'uint8', name: 'epochNumber', type: 'uint8' } - ], - name: 'PromotionEnded', - type: 'event' - }, - { - anonymous: false, - inputs: [ - { indexed: true, internalType: 'uint256', name: 'promotionId', type: 'uint256' }, - { indexed: false, internalType: 'uint256', name: 'numberOfEpochs', type: 'uint256' } - ], - name: 'PromotionExtended', - type: 'event' - }, - { - anonymous: false, - inputs: [ - { indexed: true, internalType: 'uint256', name: 'promotionId', type: 'uint256' }, - { indexed: false, internalType: 'uint8[]', name: 'epochIds', type: 'uint8[]' }, - { indexed: true, internalType: 'address', name: 'user', type: 'address' }, - { indexed: false, internalType: 'uint256', name: 'amount', type: 'uint256' } - ], - name: 'RewardsClaimed', - type: 'event' - }, - { - inputs: [ - { internalType: 'uint48', name: 'epochDuration', type: 'uint48' }, - { internalType: 'uint32', name: 'twabPeriodLength', type: 'uint32' } - ], - name: 'EpochDurationNotMultipleOfTwabPeriod', - type: 'error' - }, - { - inputs: [{ internalType: 'uint64', name: 'epochEndTimestamp', type: 'uint64' }], - name: 'EpochNotOver', - type: 'error' - }, - { - inputs: [ - { internalType: 'uint8', name: 'epochExtension', type: 'uint8' }, - { internalType: 'uint8', name: 'currentEpochs', type: 'uint8' }, - { internalType: 'uint8', name: 'maxEpochs', type: 'uint8' } - ], - name: 'ExceedsMaxEpochs', - type: 'error' - }, - { - inputs: [{ internalType: 'uint256', name: 'gracePeriodEndTimestamp', type: 'uint256' }], - name: 'GracePeriodActive', - type: 'error' - }, - { - inputs: [ - { internalType: 'uint8', name: 'epochId', type: 'uint8' }, - { internalType: 'uint8', name: 'numberOfEpochs', type: 'uint8' } - ], - name: 'InvalidEpochId', - type: 'error' - }, - { - inputs: [{ internalType: 'uint256', name: 'promotionId', type: 'uint256' }], - name: 'InvalidPromotion', - type: 'error' - }, - { - inputs: [ - { internalType: 'address', name: 'sender', type: 'address' }, - { internalType: 'address', name: 'creator', type: 'address' } - ], - name: 'OnlyPromotionCreator', - type: 'error' - }, - { inputs: [], name: 'PayeeZeroAddress', type: 'error' }, - { - inputs: [{ internalType: 'uint256', name: 'promotionId', type: 'uint256' }], - name: 'PromotionInactive', - type: 'error' - }, - { - inputs: [ - { internalType: 'uint256', name: 'promotionId', type: 'uint256' }, - { internalType: 'address', name: 'user', type: 'address' }, - { internalType: 'uint8', name: 'epochId', type: 'uint8' } - ], - name: 'RewardsAlreadyClaimed', - type: 'error' - }, - { - inputs: [{ internalType: 'uint64', name: 'startTimePeriodOffset', type: 'uint64' }], - name: 'StartTimeNotAlignedWithTwabPeriod', - type: 'error' - }, - { - inputs: [ - { internalType: 'uint256', name: 'received', type: 'uint256' }, - { internalType: 'uint256', name: 'expected', type: 'uint256' } - ], - name: 'TokensReceivedLessThanExpected', - type: 'error' - }, - { inputs: [], name: 'TwabControllerZeroAddress', type: 'error' }, - { inputs: [], name: 'ZeroEpochDuration', type: 'error' }, - { inputs: [], name: 'ZeroEpochs', type: 'error' }, - { inputs: [], name: 'ZeroTokensPerEpoch', type: 'error' } + } ] as const diff --git a/shared/utilities/abis/vault.ts b/shared/utilities/abis/vault.ts index d027632e..637a2d20 100644 --- a/shared/utilities/abis/vault.ts +++ b/shared/utilities/abis/vault.ts @@ -1,4 +1,255 @@ export const vaultABI = [ + { + inputs: [ + { internalType: 'string', name: '_name', type: 'string' }, + { internalType: 'string', name: '_symbol', type: 'string' }, + { internalType: 'contract IERC4626', name: 'yieldVault_', type: 'address' }, + { internalType: 'contract PrizePool', name: '_prizePool', type: 'address' }, + { internalType: 'address', name: '_claimer', type: 'address' }, + { internalType: 'address', name: '_yieldFeeRecipient', type: 'address' }, + { internalType: 'uint32', name: '_yieldFeePercentage', type: 'uint32' }, + { internalType: 'address', name: '_owner', type: 'address' } + ], + stateMutability: 'nonpayable', + type: 'constructor' + }, + { inputs: [], name: 'BurnZeroShares', type: 'error' }, + { + inputs: [ + { internalType: 'address', name: 'caller', type: 'address' }, + { internalType: 'address', name: 'claimer', type: 'address' } + ], + name: 'CallerNotClaimer', + type: 'error' + }, + { + inputs: [ + { internalType: 'address', name: 'caller', type: 'address' }, + { internalType: 'address', name: 'liquidationPair', type: 'address' } + ], + name: 'CallerNotLP', + type: 'error' + }, + { + inputs: [ + { internalType: 'address', name: 'caller', type: 'address' }, + { internalType: 'address', name: 'yieldFeeRecipient', type: 'address' } + ], + name: 'CallerNotYieldFeeRecipient', + type: 'error' + }, + { inputs: [], name: 'ClaimRecipientZeroAddress', type: 'error' }, + { inputs: [], name: 'ClaimerZeroAddress', type: 'error' }, + { inputs: [], name: 'DepositZeroAssets', type: 'error' }, + { inputs: [], name: 'InvalidShortString', type: 'error' }, + { inputs: [], name: 'LPZeroAddress', type: 'error' }, + { inputs: [], name: 'LiquidationAmountOutZero', type: 'error' }, + { + inputs: [ + { internalType: 'uint256', name: 'totalToWithdraw', type: 'uint256' }, + { internalType: 'uint256', name: 'availableYield', type: 'uint256' } + ], + name: 'LiquidationExceedsAvailable', + type: 'error' + }, + { + inputs: [ + { internalType: 'address', name: 'tokenIn', type: 'address' }, + { internalType: 'address', name: 'prizeToken', type: 'address' } + ], + name: 'LiquidationTokenInNotPrizeToken', + type: 'error' + }, + { + inputs: [{ internalType: 'address', name: 'tokenOut', type: 'address' }], + name: 'LiquidationTokenOutNotSupported', + type: 'error' + }, + { + inputs: [ + { internalType: 'uint256', name: 'totalAssets', type: 'uint256' }, + { internalType: 'uint256', name: 'totalSupply', type: 'uint256' } + ], + name: 'LossyDeposit', + type: 'error' + }, + { inputs: [], name: 'MintZeroShares', type: 'error' }, + { inputs: [], name: 'OwnerZeroAddress', type: 'error' }, + { + inputs: [ + { internalType: 'address', name: 'caller', type: 'address' }, + { internalType: 'address', name: 'owner', type: 'address' } + ], + name: 'PermitCallerNotOwner', + type: 'error' + }, + { inputs: [], name: 'PrizePoolZeroAddress', type: 'error' }, + { + inputs: [ + { internalType: 'uint256', name: 'shares', type: 'uint256' }, + { internalType: 'uint256', name: 'yieldFeeBalance', type: 'uint256' } + ], + name: 'SharesExceedsYieldFeeBalance', + type: 'error' + }, + { + inputs: [{ internalType: 'string', name: 'str', type: 'string' }], + name: 'StringTooLong', + type: 'error' + }, + { inputs: [], name: 'SweepZeroAssets', type: 'error' }, + { inputs: [], name: 'TwabControllerZeroAddress', type: 'error' }, + { inputs: [], name: 'WithdrawZeroAssets', type: 'error' }, + { + inputs: [ + { internalType: 'uint256', name: 'yieldFeePercentage', type: 'uint256' }, + { internalType: 'uint256', name: 'maxYieldFeePercentage', type: 'uint256' } + ], + name: 'YieldFeePercentageExceedsMax', + type: 'error' + }, + { inputs: [], name: 'YieldVaultZeroAddress', type: 'error' }, + { inputs: [], name: 'ZeroTotalAssets', type: 'error' }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: 'address', name: 'owner', type: 'address' }, + { indexed: true, internalType: 'address', name: 'spender', type: 'address' }, + { indexed: false, internalType: 'uint256', name: 'value', type: 'uint256' } + ], + name: 'Approval', + type: 'event' + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: 'address', name: 'recipient', type: 'address' }, + { indexed: false, internalType: 'uint256', name: 'shares', type: 'uint256' } + ], + name: 'ClaimYieldFeeShares', + type: 'event' + }, + { + anonymous: false, + inputs: [{ indexed: true, internalType: 'address', name: 'claimer', type: 'address' }], + name: 'ClaimerSet', + type: 'event' + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: 'address', name: 'sender', type: 'address' }, + { indexed: true, internalType: 'address', name: 'owner', type: 'address' }, + { indexed: false, internalType: 'uint256', name: 'assets', type: 'uint256' }, + { indexed: false, internalType: 'uint256', name: 'shares', type: 'uint256' } + ], + name: 'Deposit', + type: 'event' + }, + { anonymous: false, inputs: [], name: 'EIP712DomainChanged', type: 'event' }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: 'address', name: 'tokenOut', type: 'address' }, + { indexed: true, internalType: 'address', name: 'liquidationPair', type: 'address' } + ], + name: 'LiquidationPairSet', + type: 'event' + }, + { + anonymous: false, + inputs: [{ indexed: true, internalType: 'address', name: 'pendingOwner', type: 'address' }], + name: 'OwnershipOffered', + type: 'event' + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: 'address', name: 'previousOwner', type: 'address' }, + { indexed: true, internalType: 'address', name: 'newOwner', type: 'address' } + ], + name: 'OwnershipTransferred', + type: 'event' + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: 'address', name: 'account', type: 'address' }, + { + components: [ + { internalType: 'bool', name: 'useBeforeClaimPrize', type: 'bool' }, + { internalType: 'bool', name: 'useAfterClaimPrize', type: 'bool' }, + { internalType: 'contract IVaultHooks', name: 'implementation', type: 'address' } + ], + indexed: false, + internalType: 'struct VaultHooks', + name: 'hooks', + type: 'tuple' + } + ], + name: 'SetHooks', + type: 'event' + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: 'address', name: 'caller', type: 'address' }, + { indexed: false, internalType: 'uint256', name: 'assets', type: 'uint256' }, + { indexed: false, internalType: 'uint256', name: 'shares', type: 'uint256' } + ], + name: 'Sponsor', + type: 'event' + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: 'address', name: 'from', type: 'address' }, + { indexed: true, internalType: 'address', name: 'to', type: 'address' }, + { indexed: false, internalType: 'uint256', name: 'value', type: 'uint256' } + ], + name: 'Transfer', + type: 'event' + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: 'address', name: 'liquidationPair', type: 'address' }, + { indexed: true, internalType: 'address', name: 'tokenOut', type: 'address' }, + { indexed: true, internalType: 'address', name: 'recipient', type: 'address' }, + { indexed: false, internalType: 'uint256', name: 'amountOut', type: 'uint256' }, + { indexed: false, internalType: 'uint256', name: 'yieldFee', type: 'uint256' } + ], + name: 'TransferYieldOut', + type: 'event' + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: 'address', name: 'sender', type: 'address' }, + { indexed: true, internalType: 'address', name: 'receiver', type: 'address' }, + { indexed: true, internalType: 'address', name: 'owner', type: 'address' }, + { indexed: false, internalType: 'uint256', name: 'assets', type: 'uint256' }, + { indexed: false, internalType: 'uint256', name: 'shares', type: 'uint256' } + ], + name: 'Withdraw', + type: 'event' + }, + { + anonymous: false, + inputs: [ + { indexed: false, internalType: 'uint256', name: 'yieldFeePercentage', type: 'uint256' } + ], + name: 'YieldFeePercentageSet', + type: 'event' + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: 'address', name: 'yieldFeeRecipient', type: 'address' } + ], + name: 'YieldFeeRecipientSet', + type: 'event' + }, { inputs: [], name: 'DOMAIN_SEPARATOR', @@ -563,242 +814,5 @@ export const vaultABI = [ outputs: [{ internalType: 'contract IERC4626', name: '', type: 'address' }], stateMutability: 'view', type: 'function' - }, - { - anonymous: false, - inputs: [ - { indexed: true, internalType: 'address', name: 'owner', type: 'address' }, - { indexed: true, internalType: 'address', name: 'spender', type: 'address' }, - { indexed: false, internalType: 'uint256', name: 'value', type: 'uint256' } - ], - name: 'Approval', - type: 'event' - }, - { - anonymous: false, - inputs: [ - { indexed: true, internalType: 'address', name: 'recipient', type: 'address' }, - { indexed: false, internalType: 'uint256', name: 'shares', type: 'uint256' } - ], - name: 'ClaimYieldFeeShares', - type: 'event' - }, - { - anonymous: false, - inputs: [{ indexed: true, internalType: 'address', name: 'claimer', type: 'address' }], - name: 'ClaimerSet', - type: 'event' - }, - { - anonymous: false, - inputs: [ - { indexed: true, internalType: 'address', name: 'sender', type: 'address' }, - { indexed: true, internalType: 'address', name: 'owner', type: 'address' }, - { indexed: false, internalType: 'uint256', name: 'assets', type: 'uint256' }, - { indexed: false, internalType: 'uint256', name: 'shares', type: 'uint256' } - ], - name: 'Deposit', - type: 'event' - }, - { anonymous: false, inputs: [], name: 'EIP712DomainChanged', type: 'event' }, - { - anonymous: false, - inputs: [ - { indexed: true, internalType: 'address', name: 'tokenOut', type: 'address' }, - { indexed: true, internalType: 'address', name: 'liquidationPair', type: 'address' } - ], - name: 'LiquidationPairSet', - type: 'event' - }, - { - anonymous: false, - inputs: [{ indexed: true, internalType: 'address', name: 'pendingOwner', type: 'address' }], - name: 'OwnershipOffered', - type: 'event' - }, - { - anonymous: false, - inputs: [ - { indexed: true, internalType: 'address', name: 'previousOwner', type: 'address' }, - { indexed: true, internalType: 'address', name: 'newOwner', type: 'address' } - ], - name: 'OwnershipTransferred', - type: 'event' - }, - { - anonymous: false, - inputs: [ - { indexed: true, internalType: 'address', name: 'account', type: 'address' }, - { - components: [ - { internalType: 'bool', name: 'useBeforeClaimPrize', type: 'bool' }, - { internalType: 'bool', name: 'useAfterClaimPrize', type: 'bool' }, - { internalType: 'contract IVaultHooks', name: 'implementation', type: 'address' } - ], - indexed: false, - internalType: 'struct VaultHooks', - name: 'hooks', - type: 'tuple' - } - ], - name: 'SetHooks', - type: 'event' - }, - { - anonymous: false, - inputs: [ - { indexed: true, internalType: 'address', name: 'caller', type: 'address' }, - { indexed: false, internalType: 'uint256', name: 'assets', type: 'uint256' }, - { indexed: false, internalType: 'uint256', name: 'shares', type: 'uint256' } - ], - name: 'Sponsor', - type: 'event' - }, - { - anonymous: false, - inputs: [ - { indexed: true, internalType: 'address', name: 'from', type: 'address' }, - { indexed: true, internalType: 'address', name: 'to', type: 'address' }, - { indexed: false, internalType: 'uint256', name: 'value', type: 'uint256' } - ], - name: 'Transfer', - type: 'event' - }, - { - anonymous: false, - inputs: [ - { indexed: true, internalType: 'address', name: 'liquidationPair', type: 'address' }, - { indexed: true, internalType: 'address', name: 'tokenOut', type: 'address' }, - { indexed: true, internalType: 'address', name: 'recipient', type: 'address' }, - { indexed: false, internalType: 'uint256', name: 'amountOut', type: 'uint256' }, - { indexed: false, internalType: 'uint256', name: 'yieldFee', type: 'uint256' } - ], - name: 'TransferYieldOut', - type: 'event' - }, - { - anonymous: false, - inputs: [ - { indexed: true, internalType: 'address', name: 'sender', type: 'address' }, - { indexed: true, internalType: 'address', name: 'receiver', type: 'address' }, - { indexed: true, internalType: 'address', name: 'owner', type: 'address' }, - { indexed: false, internalType: 'uint256', name: 'assets', type: 'uint256' }, - { indexed: false, internalType: 'uint256', name: 'shares', type: 'uint256' } - ], - name: 'Withdraw', - type: 'event' - }, - { - anonymous: false, - inputs: [ - { indexed: false, internalType: 'uint256', name: 'yieldFeePercentage', type: 'uint256' } - ], - name: 'YieldFeePercentageSet', - type: 'event' - }, - { - anonymous: false, - inputs: [ - { indexed: true, internalType: 'address', name: 'yieldFeeRecipient', type: 'address' } - ], - name: 'YieldFeeRecipientSet', - type: 'event' - }, - { inputs: [], name: 'BurnZeroShares', type: 'error' }, - { - inputs: [ - { internalType: 'address', name: 'caller', type: 'address' }, - { internalType: 'address', name: 'claimer', type: 'address' } - ], - name: 'CallerNotClaimer', - type: 'error' - }, - { - inputs: [ - { internalType: 'address', name: 'caller', type: 'address' }, - { internalType: 'address', name: 'liquidationPair', type: 'address' } - ], - name: 'CallerNotLP', - type: 'error' - }, - { - inputs: [ - { internalType: 'address', name: 'caller', type: 'address' }, - { internalType: 'address', name: 'yieldFeeRecipient', type: 'address' } - ], - name: 'CallerNotYieldFeeRecipient', - type: 'error' - }, - { inputs: [], name: 'ClaimRecipientZeroAddress', type: 'error' }, - { inputs: [], name: 'ClaimerZeroAddress', type: 'error' }, - { inputs: [], name: 'DepositZeroAssets', type: 'error' }, - { inputs: [], name: 'InvalidShortString', type: 'error' }, - { inputs: [], name: 'LPZeroAddress', type: 'error' }, - { inputs: [], name: 'LiquidationAmountOutZero', type: 'error' }, - { - inputs: [ - { internalType: 'uint256', name: 'totalToWithdraw', type: 'uint256' }, - { internalType: 'uint256', name: 'availableYield', type: 'uint256' } - ], - name: 'LiquidationExceedsAvailable', - type: 'error' - }, - { - inputs: [ - { internalType: 'address', name: 'tokenIn', type: 'address' }, - { internalType: 'address', name: 'prizeToken', type: 'address' } - ], - name: 'LiquidationTokenInNotPrizeToken', - type: 'error' - }, - { - inputs: [{ internalType: 'address', name: 'tokenOut', type: 'address' }], - name: 'LiquidationTokenOutNotSupported', - type: 'error' - }, - { - inputs: [ - { internalType: 'uint256', name: 'totalAssets', type: 'uint256' }, - { internalType: 'uint256', name: 'totalSupply', type: 'uint256' } - ], - name: 'LossyDeposit', - type: 'error' - }, - { inputs: [], name: 'MintZeroShares', type: 'error' }, - { inputs: [], name: 'OwnerZeroAddress', type: 'error' }, - { - inputs: [ - { internalType: 'address', name: 'caller', type: 'address' }, - { internalType: 'address', name: 'owner', type: 'address' } - ], - name: 'PermitCallerNotOwner', - type: 'error' - }, - { inputs: [], name: 'PrizePoolZeroAddress', type: 'error' }, - { - inputs: [ - { internalType: 'uint256', name: 'shares', type: 'uint256' }, - { internalType: 'uint256', name: 'yieldFeeBalance', type: 'uint256' } - ], - name: 'SharesExceedsYieldFeeBalance', - type: 'error' - }, - { - inputs: [{ internalType: 'string', name: 'str', type: 'string' }], - name: 'StringTooLong', - type: 'error' - }, - { inputs: [], name: 'SweepZeroAssets', type: 'error' }, - { inputs: [], name: 'TwabControllerZeroAddress', type: 'error' }, - { inputs: [], name: 'WithdrawZeroAssets', type: 'error' }, - { - inputs: [ - { internalType: 'uint256', name: 'yieldFeePercentage', type: 'uint256' }, - { internalType: 'uint256', name: 'maxYieldFeePercentage', type: 'uint256' } - ], - name: 'YieldFeePercentageExceedsMax', - type: 'error' - }, - { inputs: [], name: 'YieldVaultZeroAddress', type: 'error' }, - { inputs: [], name: 'ZeroTotalAssets', type: 'error' } + } ] as const diff --git a/shared/utilities/abis/vaultFactory.ts b/shared/utilities/abis/vaultFactory.ts index 16e26148..888a513e 100644 --- a/shared/utilities/abis/vaultFactory.ts +++ b/shared/utilities/abis/vaultFactory.ts @@ -1,4 +1,16 @@ export const vaultFactoryABI = [ + { + anonymous: false, + inputs: [ + { indexed: true, internalType: 'contract PrizeVault', name: 'vault', type: 'address' }, + { indexed: true, internalType: 'contract IERC4626', name: 'yieldVault', type: 'address' }, + { indexed: true, internalType: 'contract PrizePool', name: 'prizePool', type: 'address' }, + { indexed: false, internalType: 'string', name: 'name', type: 'string' }, + { indexed: false, internalType: 'string', name: 'symbol', type: 'string' } + ], + name: 'NewPrizeVault', + type: 'event' + }, { inputs: [], name: 'YIELD_BUFFER', @@ -49,17 +61,5 @@ export const vaultFactoryABI = [ outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], stateMutability: 'view', type: 'function' - }, - { - anonymous: false, - inputs: [ - { indexed: true, internalType: 'contract PrizeVault', name: 'vault', type: 'address' }, - { indexed: true, internalType: 'contract IERC4626', name: 'yieldVault', type: 'address' }, - { indexed: true, internalType: 'contract PrizePool', name: 'prizePool', type: 'address' }, - { indexed: false, internalType: 'string', name: 'name', type: 'string' }, - { indexed: false, internalType: 'string', name: 'symbol', type: 'string' } - ], - name: 'NewPrizeVault', - type: 'event' } ] as const From 23a604c850ae8e7fb07dad2d03bfd32c551c4f23 Mon Sep 17 00:00:00 2001 From: Ncookie Date: Tue, 26 Mar 2024 22:14:09 -0400 Subject: [PATCH 085/161] cleaned up old draw results code --- apps/analytics/src/constants/config.ts | 10 ---- apps/analytics/src/hooks/useDrawResults.tsx | 58 ++++++--------------- 2 files changed, 15 insertions(+), 53 deletions(-) diff --git a/apps/analytics/src/constants/config.ts b/apps/analytics/src/constants/config.ts index 0f9f1d3f..abd9a35d 100644 --- a/apps/analytics/src/constants/config.ts +++ b/apps/analytics/src/constants/config.ts @@ -35,16 +35,6 @@ export const QUERY_START_BLOCK: { [chainId: number]: bigint } = { [NETWORK.optimism_sepolia]: 9_801_300n } -/** - * Old draw results URL - */ -export const OLD_DRAW_RESULTS_URL: { [chainId: number]: { url: string; lastDrawId: number } } = { - [NETWORK.optimism]: { - url: `https://raw.githubusercontent.com/GenerationSoftware/pt-v5-draw-results-mainnet/main/prizes/${NETWORK.optimism}`, - lastDrawId: 157 - } -} - /** * Draw results URL */ diff --git a/apps/analytics/src/hooks/useDrawResults.tsx b/apps/analytics/src/hooks/useDrawResults.tsx index b2500ddb..bffcf6ae 100644 --- a/apps/analytics/src/hooks/useDrawResults.tsx +++ b/apps/analytics/src/hooks/useDrawResults.tsx @@ -3,7 +3,7 @@ import { NO_REFETCH } from '@shared/generic-react-hooks' import { Prize } from '@shared/types' import { useQuery } from '@tanstack/react-query' import { Address } from 'viem' -import { DRAW_RESULTS_URL, OLD_DRAW_RESULTS_URL } from '@constants/config' +import { DRAW_RESULTS_URL } from '@constants/config' import { useDrawStatus } from './useDrawStatus' export const useDrawResults = ( @@ -11,7 +11,7 @@ export const useDrawResults = ( drawId: number, options?: { refetchInterval?: number } ) => { - const queryKey = ['drawPrizes', prizePool?.chainId, drawId] + const queryKey = ['drawResults', prizePool?.chainId, drawId] const { status, isSkipped, isFetched: isFetchedStatus } = useDrawStatus(prizePool, drawId) @@ -26,55 +26,27 @@ export const useDrawResults = ( const prizePoolAddress = prizePool.address.toLowerCase() as Address try { - const lastDrawIdToQueryOldDrawResults = OLD_DRAW_RESULTS_URL[chainId]?.lastDrawId + const url = `${DRAW_RESULTS_URL[chainId]}/${prizePoolAddress}/draw/${drawId}/winners.json` - if (!!lastDrawIdToQueryOldDrawResults && drawId <= lastDrawIdToQueryOldDrawResults) { - const url = `${OLD_DRAW_RESULTS_URL[chainId].url}/${prizePoolAddress}/draw/${drawId}/prizes.json` + const result = await fetch(url) - const result = await fetch(url) + const drawResults: { + [vaultAddress: Address]: { user: Address; prizes: { [tier: string]: number[] } }[] + } = await result.json() - const drawResults: { - vault: Address - winner: Address - tier: number - prizeIndex: number - amount: string - }[] = await result.json() + Object.entries(drawResults).forEach(([_vault, vaultPrizes]) => { + const vault = _vault as Address - drawResults.forEach((prize) => - prizes.push({ - chainId, - drawId, - vault: prize.vault, - winner: prize.winner, - tier: prize.tier, - prizeIndex: prize.prizeIndex, - amount: BigInt(prize.amount) - }) - ) - } else { - const url = `${DRAW_RESULTS_URL[chainId]}/${prizePoolAddress}/draw/${drawId}/winners.json` - - const result = await fetch(url) - - const drawResults: { - [vaultAddress: Address]: { user: Address; prizes: { [tier: string]: number[] } }[] - } = await result.json() - - Object.entries(drawResults).forEach(([_vault, vaultPrizes]) => { - const vault = _vault as Address - - vaultPrizes.forEach((entry) => { - Object.entries(entry.prizes).forEach(([_tier, prizeIndexes]) => { - const tier = parseInt(_tier) + vaultPrizes.forEach((entry) => { + Object.entries(entry.prizes).forEach(([_tier, prizeIndexes]) => { + const tier = parseInt(_tier) - prizeIndexes.forEach((prizeIndex) => { - prizes.push({ chainId, drawId, vault, winner: entry.user, tier, prizeIndex }) - }) + prizeIndexes.forEach((prizeIndex) => { + prizes.push({ chainId, drawId, vault, winner: entry.user, tier, prizeIndex }) }) }) }) - } + }) } catch {} return prizes From 718424042fbbbed4e3811fe49270400cf52b2b43 Mon Sep 17 00:00:00 2001 From: Ncookiez Date: Tue, 26 Mar 2024 22:20:14 -0400 Subject: [PATCH 086/161] fixed github draw results url --- apps/analytics/src/constants/config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/analytics/src/constants/config.ts b/apps/analytics/src/constants/config.ts index abd9a35d..bb456bf5 100644 --- a/apps/analytics/src/constants/config.ts +++ b/apps/analytics/src/constants/config.ts @@ -39,7 +39,7 @@ export const QUERY_START_BLOCK: { [chainId: number]: bigint } = { * Draw results URL */ export const DRAW_RESULTS_URL: { [chainId: number]: string } = { - [NETWORK.optimism_sepolia]: `https://raw.githubusercontent.com/GenerationSoftware/pt-v5-winners-mainnet/main/winners/vaultAccounts/${NETWORK.optimism_sepolia}` + [NETWORK.optimism_sepolia]: `https://raw.githubusercontent.com/GenerationSoftware/pt-v5-winners-testnet/main/winners/vaultAccounts/${NETWORK.optimism_sepolia}` } /** From e62f4dff5f8e16965263386d0bc0f52f25153543 Mon Sep 17 00:00:00 2001 From: Ncookiez Date: Wed, 27 Mar 2024 12:39:16 -0400 Subject: [PATCH 087/161] fixed cabanalytics build --- apps/analytics/src/components/Prizes/PrizesTableRow.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/apps/analytics/src/components/Prizes/PrizesTableRow.tsx b/apps/analytics/src/components/Prizes/PrizesTableRow.tsx index 712e602b..2d3c2442 100644 --- a/apps/analytics/src/components/Prizes/PrizesTableRow.tsx +++ b/apps/analytics/src/components/Prizes/PrizesTableRow.tsx @@ -91,7 +91,9 @@ const PrizeSize = (props: PrizeSizeProps) => { const tierWins = wins.filter((win) => win.tier === tier) const prizeSize = - tierPrizes?.[0]?.amount ?? !!tierWins[0] ? tierWins[0].payout + tierWins[0].fee : undefined + tierPrizes?.[0]?.amount ?? !!tierWins[0] + ? tierWins[0].payout + tierWins[0].claimReward + : undefined return (
From 3e51f1cb9548cad66e34ee8d246064a2301d8fd7 Mon Sep 17 00:00:00 2001 From: Ncookiez Date: Wed, 27 Mar 2024 16:32:55 -0400 Subject: [PATCH 088/161] enabled op sepolia subgraph --- shared/utilities/constants.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/shared/utilities/constants.ts b/shared/utilities/constants.ts index e86c3ff0..2ea3ff45 100644 --- a/shared/utilities/constants.ts +++ b/shared/utilities/constants.ts @@ -197,7 +197,8 @@ export const OP_GAS_ORACLE_ADDRESS = '0x420000000000000000000000000000000000000f * Subgraph API URLs */ export const SUBGRAPH_API_URLS = { - // [NETWORK.optimism_sepolia]: 'https://api.studio.thegraph.com/query/63100/pt-v5-op-sepolia/version/latest' + [NETWORK.optimism_sepolia]: + 'https://api.studio.thegraph.com/query/63100/pt-v5-op-sepolia/version/latest' } as const /** From 8f20c41984b2a23461b289cd00f34581d0c29183 Mon Sep 17 00:00:00 2001 From: Ncookiez Date: Wed, 27 Mar 2024 18:01:41 -0400 Subject: [PATCH 089/161] fixed lp deployment flow --- apps/vault-factory/src/atoms.ts | 9 +- .../buttons/DeployLiquidationPairButton.tsx | 14 ++- .../forms/DeployLiquidationPairForm.tsx | 35 ++++-- .../forms/MinimumAuctionAmountInput.tsx | 102 ---------------- .../components/forms/SmoothingFactorInput.tsx | 2 +- .../forms/TargetAuctionPeriodInput.tsx | 85 +++++++++++++ .../forms/TargetAuctionPriceInput.tsx | 113 ++++++++++++++++++ apps/vault-factory/src/constants/config.ts | 8 +- .../src/hooks/useLiquidationPairInfo.ts | 24 ++-- .../useLiquidationPairMinimumAuctionAmount.ts | 31 ----- .../useLiquidationPairTargetAuctionPrice.ts | 39 ++++++ apps/vault-factory/src/types.ts | 3 +- ...useSendDeployLiquidationPairTransaction.ts | 8 +- shared/types/types/liquidations.ts | 2 +- 14 files changed, 300 insertions(+), 175 deletions(-) delete mode 100644 apps/vault-factory/src/components/forms/MinimumAuctionAmountInput.tsx create mode 100644 apps/vault-factory/src/components/forms/TargetAuctionPeriodInput.tsx create mode 100644 apps/vault-factory/src/components/forms/TargetAuctionPriceInput.tsx delete mode 100644 apps/vault-factory/src/hooks/useLiquidationPairMinimumAuctionAmount.ts create mode 100644 apps/vault-factory/src/hooks/useLiquidationPairTargetAuctionPrice.ts diff --git a/apps/vault-factory/src/atoms.ts b/apps/vault-factory/src/atoms.ts index 368c11d3..de0992c7 100644 --- a/apps/vault-factory/src/atoms.ts +++ b/apps/vault-factory/src/atoms.ts @@ -88,9 +88,14 @@ export const vaultIdsAtom = atom(getInitialVaultIds()) export const liquidationPairStepCounterAtom = atom(0) /** - * Liquidation Pair Minimum Auction Share Amount + * Liquidation Pair Target Auction Period */ -export const liquidationPairMinimumAuctionAmountAtom = atom(undefined) +export const liquidationPairTargetAuctionPeriodAtom = atom(undefined) + +/** + * Liquidation Pair Target Auction Price + */ +export const liquidationPairTargetAuctionPriceAtom = atom(undefined) /** * Liquidation Pair Smoothing Factor diff --git a/apps/vault-factory/src/components/buttons/DeployLiquidationPairButton.tsx b/apps/vault-factory/src/components/buttons/DeployLiquidationPairButton.tsx index 1b94c950..bedba556 100644 --- a/apps/vault-factory/src/components/buttons/DeployLiquidationPairButton.tsx +++ b/apps/vault-factory/src/components/buttons/DeployLiquidationPairButton.tsx @@ -3,11 +3,12 @@ import { ArrowRightIcon } from '@heroicons/react/24/outline' import { useAddRecentTransaction, useChainModal, useConnectModal } from '@rainbow-me/rainbowkit' import { createDeployLiquidationPairTxToast, TransactionButton } from '@shared/react-components' import { PairCreateInfo } from '@shared/types' +import { liquidationPairFactoryABI } from '@shared/utilities' import classNames from 'classnames' import { useSetAtom } from 'jotai' import { liquidationPairAddressAtom } from 'src/atoms' import { SupportedNetwork } from 'src/types' -import { Address, isAddress } from 'viem' +import { Address, decodeEventLog, isAddress } from 'viem' import { useLiquidationPairInfo } from '@hooks/useLiquidationPairInfo' interface DeployLiquidationPairButtonProps { @@ -40,9 +41,14 @@ export const DeployLiquidationPairButton = (props: DeployLiquidationPairButtonPr createDeployLiquidationPairTxToast({ chainId, txHash, addRecentTransaction }) }, onSuccess: (txReceipt) => { - const liquidationPairAddress = txReceipt.logs[0].address - if (isAddress(liquidationPairAddress)) { - setLiquidationPairAddress(liquidationPairAddress) + const lpCreatedEvent = decodeEventLog({ + abi: liquidationPairFactoryABI, + eventName: 'PairCreated', + data: txReceipt.logs[0].data, + topics: txReceipt.logs[0].topics + }) + if (isAddress(lpCreatedEvent.args.pair)) { + setLiquidationPairAddress(lpCreatedEvent.args.pair) } onSuccess?.() } diff --git a/apps/vault-factory/src/components/forms/DeployLiquidationPairForm.tsx b/apps/vault-factory/src/components/forms/DeployLiquidationPairForm.tsx index 6e36c4bc..bc0bb120 100644 --- a/apps/vault-factory/src/components/forms/DeployLiquidationPairForm.tsx +++ b/apps/vault-factory/src/components/forms/DeployLiquidationPairForm.tsx @@ -1,5 +1,7 @@ import { useToken } from '@generationsoftware/hyperstructure-react-hooks' +import { Token } from '@shared/types' import { Spinner } from '@shared/ui' +import { PRIZE_POOLS } from '@shared/utilities' import classNames from 'classnames' import { useAtomValue } from 'jotai' import { FormProvider, useForm } from 'react-hook-form' @@ -7,14 +9,17 @@ import { vaultAddressAtom, vaultChainIdAtom } from 'src/atoms' import { SupportedNetwork } from 'src/types' import { Address } from 'viem' import { DeployLiquidationPairButton } from '@components/buttons/DeployLiquidationPairButton' -import { useLiquidationPairMinimumAuctionAmount } from '@hooks/useLiquidationPairMinimumAuctionAmount' +import { NETWORK_CONFIG } from '@constants/config' import { useLiquidationPairSteps } from '@hooks/useLiquidationPairSteps' +import { useLiquidationPairTargetAuctionPrice } from '@hooks/useLiquidationPairTargetAuctionPrice' import { useVaultCreationSteps } from '@hooks/useVaultCreationSteps' -import { MinimumAuctionAmountInput } from './MinimumAuctionAmountInput' import { SmoothingFactorInput } from './SmoothingFactorInput' +import { TargetAuctionPeriodInput } from './TargetAuctionPeriodInput' +import { TargetAuctionPriceInput } from './TargetAuctionPriceInput' export interface DeployLiquidationPairFormValues { - minimumAuctionAmount: string + targetAuctionPeriod: string + targetAuctionPrice: string smoothingFactor: string } @@ -33,14 +38,17 @@ export const DeployLiquidationPairForm = (props: DeployLiquidationPairFormProps) const chainId = useAtomValue(vaultChainIdAtom) as SupportedNetwork const vaultAddress = useAtomValue(vaultAddressAtom) as Address - const { data: shareToken } = useToken(chainId, vaultAddress) + const prizeTokenAddress = PRIZE_POOLS.find( + (pool) => pool.chainId === chainId + )?.options.prizeTokenAddress.toLowerCase() as Address - const { data: defaultMinimumAuctionAmount } = useLiquidationPairMinimumAuctionAmount( - chainId, - vaultAddress + const { data: prizeToken } = useToken(chainId, prizeTokenAddress) + + const { data: defaultTargetAuctionPrice } = useLiquidationPairTargetAuctionPrice( + prizeToken as Token ) - if (!shareToken || !defaultMinimumAuctionAmount) { + if (!prizeToken || !defaultTargetAuctionPrice) { return } @@ -55,12 +63,17 @@ export const DeployLiquidationPairForm = (props: DeployLiquidationPairFormProps) onSubmit={formMethods.handleSubmit(() => {})} className={classNames('flex flex-col grow gap-12 items-center', className)} > - + + {/* TODO: add option to skip deploying an lp and just set one */} { - const { shareToken, vaultAddress, className, inputClassName } = props - - const [minimumAuctionAmount, setMinimumAuctionAmount] = useAtom( - liquidationPairMinimumAuctionAmountAtom - ) - - const { minimumAuctionAmount: _minimumAuctionAmount } = - useWatch() - - const { setValue } = useFormContext() - - const { data: defaultMinimumAuctionAmount } = useLiquidationPairMinimumAuctionAmount( - shareToken.chainId, - vaultAddress - ) - - const [isOverriden, setIsOverriden] = useState(false) - - useEffect(() => { - setValue( - 'minimumAuctionAmount', - formatUnits(minimumAuctionAmount ?? defaultMinimumAuctionAmount ?? 0n, shareToken.decimals), - { shouldValidate: true } - ) - if (!minimumAuctionAmount) { - setMinimumAuctionAmount(defaultMinimumAuctionAmount) - } - }, []) - - useEffect(() => { - if ( - !!_minimumAuctionAmount && - isValidMinimumAuctionAmount(_minimumAuctionAmount, shareToken.decimals) - ) { - const parsedMinimumAuctionAmount = parseUnits(_minimumAuctionAmount, shareToken.decimals) - setMinimumAuctionAmount(parsedMinimumAuctionAmount) - } - }, [_minimumAuctionAmount]) - - return ( -
- /^-?\d+\.?\d*$/.test(v) || 'Enter a valid number.', - isPositiveNumber: (v: string) => parseFloat(v) > 0 || 'Enter a number larger than 0.', - isNotTooPrecise: (v) => - v.split('.').length < 2 || - v.split('.')[1].length <= shareToken.decimals || - 'Too many decimals' - }} - label='Minimum Auction Amount' - defaultValue={ - !!defaultMinimumAuctionAmount - ? formatUnits(defaultMinimumAuctionAmount, shareToken.decimals) - : undefined - } - needsOverride={true} - keepValueOnOverride={true} - onOverride={setIsOverriden} - className={classNames('w-full', inputClassName)} - /> - - {shareToken.symbol} - -
- ) -} - -const isValidMinimumAuctionAmount = (val: string, maxDecimals: number) => { - return ( - !!val && - /^-?\d+\.?\d*$/.test(val) && - parseFloat(val) > 0 && - (val.split('.').length < 2 || val.split('.')[1].length <= maxDecimals) - ) -} diff --git a/apps/vault-factory/src/components/forms/SmoothingFactorInput.tsx b/apps/vault-factory/src/components/forms/SmoothingFactorInput.tsx index bdcf7944..058a9e1c 100644 --- a/apps/vault-factory/src/components/forms/SmoothingFactorInput.tsx +++ b/apps/vault-factory/src/components/forms/SmoothingFactorInput.tsx @@ -42,7 +42,7 @@ export const SmoothingFactorInput = (props: SmoothingFactorInputProps) => { v.split('.').length < 2 || v.split('.')[1].length <= 18 || 'Too many decimals' }} label={} - defaultValue={'0'} + defaultValue='0' needsOverride={true} keepValueOnOverride={true} className={className} diff --git a/apps/vault-factory/src/components/forms/TargetAuctionPeriodInput.tsx b/apps/vault-factory/src/components/forms/TargetAuctionPeriodInput.tsx new file mode 100644 index 00000000..18a54706 --- /dev/null +++ b/apps/vault-factory/src/components/forms/TargetAuctionPeriodInput.tsx @@ -0,0 +1,85 @@ +import { InformationCircleIcon } from '@heroicons/react/24/outline' +import { Tooltip } from '@shared/ui' +import { SECONDS_PER_HOUR } from '@shared/utilities' +import { useAtom } from 'jotai' +import { useEffect } from 'react' +import { useFormContext, useWatch } from 'react-hook-form' +import { liquidationPairTargetAuctionPeriodAtom } from 'src/atoms' +import { DeployLiquidationPairFormValues } from './DeployLiquidationPairForm' +import { SimpleInput } from './SimpleInput' + +interface TargetAuctionPeriodInputProps { + defaultPeriod?: number + className?: string +} + +export const TargetAuctionPeriodInput = (props: TargetAuctionPeriodInputProps) => { + const { defaultPeriod, className } = props + + const [targetAuctionPeriod, setTargetAuctionPeriod] = useAtom( + liquidationPairTargetAuctionPeriodAtom + ) + + const { targetAuctionPeriod: _targetAuctionPeriod } = useWatch() + + const { setValue } = useFormContext() + + useEffect(() => { + setValue( + 'targetAuctionPeriod', + (targetAuctionPeriod ?? defaultPeriod ?? SECONDS_PER_HOUR).toString(), + { + shouldValidate: true + } + ) + if (!targetAuctionPeriod) { + setTargetAuctionPeriod(defaultPeriod) + } + }, []) + + useEffect(() => { + if (!!_targetAuctionPeriod && isValidTargetAuctionPeriod(_targetAuctionPeriod)) { + setTargetAuctionPeriod(parseInt(_targetAuctionPeriod)) + } + }, [_targetAuctionPeriod]) + + return ( + /^-?\d+\.?\d*$/.test(v) || 'Enter a valid number.', + isPositiveNumber: (v: string) => + parseInt(v) > 0 || 'Enter a number larger than 0 (decimals are ignored).' + }} + label={} + defaultValue={defaultPeriod?.toString()} + needsOverride={true} + keepValueOnOverride={true} + className={className} + /> + ) +} + +const TargetAuctionPeriodInputLabel = () => { + return ( +
+ Auction Period + + + This defines the frequency of yield auctions; they will last this amount of seconds. + + Once a yield auction is over, another one begins immediately. +
+ } + > + + +
+ ) +} + +const isValidTargetAuctionPeriod = (val: string) => { + return !!val && /^-?\d+\.?\d*$/.test(val) && parseInt(val) > 0 +} diff --git a/apps/vault-factory/src/components/forms/TargetAuctionPriceInput.tsx b/apps/vault-factory/src/components/forms/TargetAuctionPriceInput.tsx new file mode 100644 index 00000000..d53dc28a --- /dev/null +++ b/apps/vault-factory/src/components/forms/TargetAuctionPriceInput.tsx @@ -0,0 +1,113 @@ +import { InformationCircleIcon } from '@heroicons/react/24/outline' +import { Token } from '@shared/types' +import { Tooltip } from '@shared/ui' +import classNames from 'classnames' +import { useAtom } from 'jotai' +import { useEffect, useState } from 'react' +import { useFormContext, useWatch } from 'react-hook-form' +import { liquidationPairTargetAuctionPriceAtom } from 'src/atoms' +import { formatUnits, parseUnits } from 'viem' +import { DeployLiquidationPairFormValues } from './DeployLiquidationPairForm' +import { SimpleInput } from './SimpleInput' + +interface TargetAuctionPriceInputProps { + prizeToken: Token + defaultPrice?: bigint + className?: string + inputClassName?: string +} + +export const TargetAuctionPriceInput = (props: TargetAuctionPriceInputProps) => { + const { prizeToken, defaultPrice, className, inputClassName } = props + + const [targetAuctionPrice, setTargetAuctionPrice] = useAtom(liquidationPairTargetAuctionPriceAtom) + + const { targetAuctionPrice: _targetAuctionPrice } = useWatch() + + const { setValue } = useFormContext() + + const [isOverriden, setIsOverriden] = useState(false) + + useEffect(() => { + setValue( + 'targetAuctionPrice', + formatUnits(targetAuctionPrice ?? defaultPrice ?? 0n, prizeToken.decimals), + { shouldValidate: true } + ) + if (!targetAuctionPrice) { + setTargetAuctionPrice(defaultPrice) + } + }, []) + + useEffect(() => { + if ( + !!_targetAuctionPrice && + isValidTargetAuctionPrice(_targetAuctionPrice, prizeToken.decimals) + ) { + setTargetAuctionPrice(parseUnits(_targetAuctionPrice, prizeToken.decimals)) + } + }, [_targetAuctionPrice]) + + return ( +
+ /^-?\d+\.?\d*$/.test(v) || 'Enter a valid number.', + isPositiveNumber: (v: string) => parseFloat(v) > 0 || 'Enter a number larger than 0.', + isNotTooPrecise: (v) => + v.split('.').length < 2 || + v.split('.')[1].length <= prizeToken.decimals || + 'Too many decimals' + }} + label={} + defaultValue={!!defaultPrice ? formatUnits(defaultPrice, prizeToken.decimals) : undefined} + needsOverride={true} + keepValueOnOverride={true} + onOverride={setIsOverriden} + className={classNames('w-full', inputClassName)} + /> + + {prizeToken.symbol} + +
+ ) +} + +const TargetAuctionPriceInputLabel = () => { + return ( +
+ First Auction Price + + + This is the price to be paid to liquidate the yield available on the first auction. + + + If you believe the first auction will have a lot more yield that this value, increase + this. + + Regardless, future auctions will self-adjust over time. +
+ } + > + + +
+ ) +} + +const isValidTargetAuctionPrice = (val: string, maxDecimals: number) => { + return ( + !!val && + /^-?\d+\.?\d*$/.test(val) && + parseFloat(val) > 0 && + (val.split('.').length < 2 || val.split('.')[1].length <= maxDecimals) + ) +} diff --git a/apps/vault-factory/src/constants/config.ts b/apps/vault-factory/src/constants/config.ts index 569258bf..3444cb12 100644 --- a/apps/vault-factory/src/constants/config.ts +++ b/apps/vault-factory/src/constants/config.ts @@ -17,7 +17,7 @@ import { xdefiWallet, zerionWallet } from '@rainbow-me/rainbowkit/wallets' -import { DEFAULT_CLAIMER_ADDRESSES, NETWORK } from '@shared/utilities' +import { DEFAULT_CLAIMER_ADDRESSES, NETWORK, SECONDS_PER_HOUR } from '@shared/utilities' import { SupportedNetwork, YieldSourceVaultTag } from 'src/types' import { Address } from 'viem' import { mainnet, optimism, optimismSepolia } from 'viem/chains' @@ -76,7 +76,7 @@ export const NETWORK_CONFIG: Record< description: string prizePool: Address claimer: Address - lp: { targetAuctionPeriodFraction: number; minAuctionAmountEth: number } + lp: { targetAuctionPeriod: number; targetAuctionPriceUsd: number } yieldSources: { id: string name: string @@ -90,14 +90,14 @@ export const NETWORK_CONFIG: Record< // description: 'The OG optimistic rollup on Ethereum.', // prizePool: '', // claimer: DEFAULT_CLAIMER_ADDRESSES[NETWORK.optimism], - // lp: { targetAuctionPeriodFraction: 0.5, minAuctionAmountEth: 0.001 }, + // lp: { targetAuctionPeriod: SECONDS_PER_HOUR, targetAuctionPriceUsd: 10 }, // yieldSources: [] // }, [NETWORK.optimism_sepolia]: { description: 'Sepolia testnet for the Optimism network.', prizePool: '0x31547D3c38F2F8dC92421C54B173F3B27Ab26EbB', claimer: DEFAULT_CLAIMER_ADDRESSES[NETWORK.optimism_sepolia], - lp: { targetAuctionPeriodFraction: 0.5, minAuctionAmountEth: 0.001 }, + lp: { targetAuctionPeriod: SECONDS_PER_HOUR, targetAuctionPriceUsd: 10 }, yieldSources: [ { id: 'aave', diff --git a/apps/vault-factory/src/hooks/useLiquidationPairInfo.ts b/apps/vault-factory/src/hooks/useLiquidationPairInfo.ts index 671755aa..3af0bca4 100644 --- a/apps/vault-factory/src/hooks/useLiquidationPairInfo.ts +++ b/apps/vault-factory/src/hooks/useLiquidationPairInfo.ts @@ -1,13 +1,13 @@ import { PairCreateInfo } from '@shared/types' -import { POOL_TOKEN_ADDRESSES, PRIZE_POOLS } from '@shared/utilities' +import { PRIZE_POOLS } from '@shared/utilities' import { useAtomValue } from 'jotai' import { - liquidationPairMinimumAuctionAmountAtom, - liquidationPairSmoothingFactorAtom + liquidationPairSmoothingFactorAtom, + liquidationPairTargetAuctionPeriodAtom, + liquidationPairTargetAuctionPriceAtom } from 'src/atoms' import { SupportedNetwork } from 'src/types' import { Address } from 'viem' -import { NETWORK_CONFIG } from '@constants/config' /** * Returns all info required to deploy a new liquidation pair @@ -19,24 +19,20 @@ export const useLiquidationPairInfo = ( chainId: SupportedNetwork, vaultAddress: Address ): Partial => { - const minimumAuctionAmount = useAtomValue(liquidationPairMinimumAuctionAmountAtom) + const targetAuctionPeriod = useAtomValue(liquidationPairTargetAuctionPeriodAtom) + const targetAuctionPrice = useAtomValue(liquidationPairTargetAuctionPriceAtom) const smoothingFactor = useAtomValue(liquidationPairSmoothingFactorAtom) - const prizePoolInfo = PRIZE_POOLS.find( - (pool) => pool.chainId === chainId - ) as (typeof PRIZE_POOLS)[number] - - const drawPeriodLength = prizePoolInfo.options.drawPeriodInSeconds - const targetAuctionPeriod = - NETWORK_CONFIG[chainId].lp.targetAuctionPeriodFraction * drawPeriodLength + const prizeTokenAddress = PRIZE_POOLS.find((pool) => pool.chainId === chainId)?.options + .prizeTokenAddress as Address return { chainId, source: vaultAddress, - tokenIn: POOL_TOKEN_ADDRESSES[chainId], + tokenIn: prizeTokenAddress, tokenOut: vaultAddress, targetAuctionPeriod, - minimumAuctionAmount, + targetAuctionPrice, smoothingFactor } } diff --git a/apps/vault-factory/src/hooks/useLiquidationPairMinimumAuctionAmount.ts b/apps/vault-factory/src/hooks/useLiquidationPairMinimumAuctionAmount.ts deleted file mode 100644 index 9f124776..00000000 --- a/apps/vault-factory/src/hooks/useLiquidationPairMinimumAuctionAmount.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { useVault, useVaultSharePrice } from '@generationsoftware/hyperstructure-react-hooks' -import { useMemo } from 'react' -import { SupportedNetwork } from 'src/types' -import { Address, parseUnits } from 'viem' -import { NETWORK_CONFIG } from '@constants/config' - -/** - * Returns a minimum share amount for a liquidation auction to begin - * @param chainId chain ID of the liquidation pair - * @param vaultAddress vault address to configure for - * @returns - */ -export const useLiquidationPairMinimumAuctionAmount = ( - chainId: SupportedNetwork, - vaultAddress: Address -) => { - const vault = useVault({ chainId, address: vaultAddress }) - - const { data: shareToken, isFetched } = useVaultSharePrice(vault) - - const data = useMemo(() => { - if (!!shareToken?.price) { - const numTokens = NETWORK_CONFIG[chainId].lp.minAuctionAmountEth / shareToken.price - return parseUnits(`${numTokens}`, shareToken.decimals) - } else if (isFetched) { - return 0n - } - }, [shareToken, isFetched]) - - return { data, isFetched } -} diff --git a/apps/vault-factory/src/hooks/useLiquidationPairTargetAuctionPrice.ts b/apps/vault-factory/src/hooks/useLiquidationPairTargetAuctionPrice.ts new file mode 100644 index 00000000..b7363599 --- /dev/null +++ b/apps/vault-factory/src/hooks/useLiquidationPairTargetAuctionPrice.ts @@ -0,0 +1,39 @@ +import { useTokenPrices } from '@generationsoftware/hyperstructure-react-hooks' +import { Token } from '@shared/types' +import { USDC_TOKEN_ADDRESSES } from '@shared/utilities' +import { useMemo } from 'react' +import { SupportedNetwork } from 'src/types' +import { Address, parseUnits } from 'viem' +import { NETWORK_CONFIG } from '@constants/config' + +/** + * Returns a target auction price for an auction + * @param prizeToken the prize token of the relevant prize pool + * @returns + */ +export const useLiquidationPairTargetAuctionPrice = (prizeToken: Token) => { + const chainId = prizeToken?.chainId as SupportedNetwork + + const { data: tokenPrices, isFetched: isFetchedTokenPrices } = useTokenPrices( + chainId, + !!prizeToken ? [prizeToken.address, USDC_TOKEN_ADDRESSES[chainId]] : [] + ) + + const data = useMemo(() => { + if (!!prizeToken && !!tokenPrices) { + const prizeTokenPrice = tokenPrices[prizeToken.address.toLowerCase() as Address] + const usdcPrice = tokenPrices[USDC_TOKEN_ADDRESSES[chainId]] + + if (!!prizeTokenPrice && !!usdcPrice) { + const prizeTokenPriceUsd = prizeTokenPrice / usdcPrice + const numTokens = NETWORK_CONFIG[chainId].lp.targetAuctionPriceUsd / prizeTokenPriceUsd + + return parseUnits(`${numTokens}`, prizeToken.decimals) + } + } + }, [prizeToken, tokenPrices]) + + const isFetched = !!prizeToken && isFetchedTokenPrices + + return { data, isFetched } +} diff --git a/apps/vault-factory/src/types.ts b/apps/vault-factory/src/types.ts index a6dbea7e..5b2e28ff 100644 --- a/apps/vault-factory/src/types.ts +++ b/apps/vault-factory/src/types.ts @@ -12,7 +12,8 @@ export type FormKey = | 'vaultName' | 'vaultSymbol' | 'vaultClaimer' - | 'minimumAuctionAmount' + | 'targetAuctionPeriod' + | 'targetAuctionPrice' | 'smoothingFactor' | 'deployedVaultChainId' | 'deployedVaultAddress' diff --git a/packages/hyperstructure-react-hooks/src/transactions/useSendDeployLiquidationPairTransaction.ts b/packages/hyperstructure-react-hooks/src/transactions/useSendDeployLiquidationPairTransaction.ts index 83aeefb8..79c66ab7 100644 --- a/packages/hyperstructure-react-hooks/src/transactions/useSendDeployLiquidationPairTransaction.ts +++ b/packages/hyperstructure-react-hooks/src/transactions/useSendDeployLiquidationPairTransaction.ts @@ -39,7 +39,7 @@ export const useSendDeployLiquidationPairTransaction = ( tokenIn, tokenOut, targetAuctionPeriod, - minimumAuctionAmount, + targetAuctionPrice, smoothingFactor } = pairCreateInfo @@ -57,7 +57,7 @@ export const useSendDeployLiquidationPairTransaction = ( !!tokenIn && !!tokenOut && !!targetAuctionPeriod && - !!minimumAuctionAmount && + !!targetAuctionPrice && smoothingFactor !== undefined && chain?.id === chainId @@ -70,8 +70,8 @@ export const useSendDeployLiquidationPairTransaction = ( source, tokenIn, tokenOut, - BigInt(targetAuctionPeriod), - minimumAuctionAmount, + BigInt(targetAuctionPeriod ?? 0), + targetAuctionPrice, parseEther(`${smoothingFactor}`) ], query: { enabled } diff --git a/shared/types/types/liquidations.ts b/shared/types/types/liquidations.ts index 7da61263..47ac802e 100644 --- a/shared/types/types/liquidations.ts +++ b/shared/types/types/liquidations.ts @@ -4,6 +4,6 @@ export interface PairCreateInfo { tokenIn: `0x${string}` tokenOut: `0x${string}` targetAuctionPeriod: number - minimumAuctionAmount: bigint + targetAuctionPrice: bigint smoothingFactor: number } From 79df967c9964bf425bf20c0d28d1c63c6918b564 Mon Sep 17 00:00:00 2001 From: Ncookiez Date: Wed, 27 Mar 2024 18:08:52 -0400 Subject: [PATCH 090/161] fixed swaps app build --- apps/swaps/src/pages/index.tsx | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/apps/swaps/src/pages/index.tsx b/apps/swaps/src/pages/index.tsx index 0df53bf9..b757a5c7 100644 --- a/apps/swaps/src/pages/index.tsx +++ b/apps/swaps/src/pages/index.tsx @@ -1,5 +1,5 @@ import { PrizePoolBadge } from '@shared/react-components' -import { NETWORK } from '@shared/utilities' +import { NETWORK, PRIZE_POOLS } from '@shared/utilities' import { Faq } from '@components/Faq' import { GrandPrize } from '@components/GrandPrize' import { Header } from '@components/Header' @@ -10,13 +10,19 @@ import { VaultCards } from '@components/VaultCards' export default function HomePage() { const chainId = NETWORK.optimism + const isValidChainId = !!PRIZE_POOLS.find((prizePool) => prizePool.chainId === chainId) + return (
- - - - + {isValidChainId && ( + <> + + + + + + )} ) From 957eac474cada65a8d3b2f74d207aa2a45f13047 Mon Sep 17 00:00:00 2001 From: Ncookiez Date: Thu, 28 Mar 2024 12:39:48 -0400 Subject: [PATCH 091/161] improved lp and claimer step flow --- .../src/components/CreateVaultStepContent.tsx | 4 +-- .../src/components/DeployedVaultCard.tsx | 4 +-- .../src/components/DeployedVaultsTable.tsx | 6 ++-- .../src/components/buttons/BackButton.tsx | 28 +++++++++++++++++++ .../forms/DeployLiquidationPairForm.tsx | 20 +++++++++---- .../{ClaimerForm.tsx => SetClaimerForm.tsx} | 24 +++++++++------- .../forms/SetLiquidationPairForm.tsx | 24 ++++++++++++---- .../claimer/[chainId]/[vaultAddress].tsx | 4 +-- 8 files changed, 84 insertions(+), 30 deletions(-) create mode 100644 apps/vault-factory/src/components/buttons/BackButton.tsx rename apps/vault-factory/src/components/forms/{ClaimerForm.tsx => SetClaimerForm.tsx} (78%) diff --git a/apps/vault-factory/src/components/CreateVaultStepContent.tsx b/apps/vault-factory/src/components/CreateVaultStepContent.tsx index a0d693e0..dd7154c1 100644 --- a/apps/vault-factory/src/components/CreateVaultStepContent.tsx +++ b/apps/vault-factory/src/components/CreateVaultStepContent.tsx @@ -2,11 +2,11 @@ import classNames from 'classnames' import { ReactNode, useMemo } from 'react' import { useVaultCreationSteps } from '@hooks/useVaultCreationSteps' import { DeployVaultView } from './DeployVaultView' -import { ClaimerForm } from './forms/ClaimerForm' import { DeployLiquidationPairForm } from './forms/DeployLiquidationPairForm' import { NameAndSymbolForm } from './forms/NameAndSymbolForm' import { NetworkForm } from './forms/NetworkForm' import { OwnerAndFeesForm } from './forms/OwnerAndFeesForm' +import { SetClaimerForm } from './forms/SetClaimerForm' import { SetLiquidationPairForm } from './forms/SetLiquidationPairForm' import { YieldVaultForm } from './forms/YieldVaultForm' import { YieldSourceView } from './YieldSourceView' @@ -17,7 +17,7 @@ const allVaultStepContent: ReactNode[] = [ , , , - , + , , , diff --git a/apps/vault-factory/src/components/DeployedVaultCard.tsx b/apps/vault-factory/src/components/DeployedVaultCard.tsx index ed6289eb..f8a8618a 100644 --- a/apps/vault-factory/src/components/DeployedVaultCard.tsx +++ b/apps/vault-factory/src/components/DeployedVaultCard.tsx @@ -159,7 +159,7 @@ const VaultActionsItem = (props: ItemProps) => { const { removeVault } = useUserDeployedVaults() - const onClickDeployLp = () => { + const onClickSetLp = () => { setLpStep(0) router.push(`/lp/${vault.chainId}/${vault.address}`) } @@ -183,7 +183,7 @@ const VaultActionsItem = (props: ItemProps) => { return (
{ const { removeVault } = useUserDeployedVaults() - const onClickDeployLp = () => { + const onClickSetLp = () => { setLpStep(0) router.push(`/lp/${vault.chainId}/${vault.address}`) } @@ -236,9 +236,9 @@ const VaultActionsItem = (props: ItemProps) => { return (
- + diff --git a/apps/vault-factory/src/components/buttons/BackButton.tsx b/apps/vault-factory/src/components/buttons/BackButton.tsx new file mode 100644 index 00000000..be3d7ccc --- /dev/null +++ b/apps/vault-factory/src/components/buttons/BackButton.tsx @@ -0,0 +1,28 @@ +import { ArrowLeftIcon } from '@heroicons/react/24/outline' +import classNames from 'classnames' +import { useRouter } from 'next/router' +import { PurpleButton, PurpleButtonProps } from './PurpleButton' + +interface BackButtonProps extends Omit {} + +export const BackButton = (props: BackButtonProps) => { + const { onClick, className, innerClassName, ...rest } = props + + const router = useRouter() + + const defaultOnClick = () => { + router.push('/') + } + + return ( + + Back + + ) +} diff --git a/apps/vault-factory/src/components/forms/DeployLiquidationPairForm.tsx b/apps/vault-factory/src/components/forms/DeployLiquidationPairForm.tsx index bc0bb120..8a960843 100644 --- a/apps/vault-factory/src/components/forms/DeployLiquidationPairForm.tsx +++ b/apps/vault-factory/src/components/forms/DeployLiquidationPairForm.tsx @@ -8,6 +8,7 @@ import { FormProvider, useForm } from 'react-hook-form' import { vaultAddressAtom, vaultChainIdAtom } from 'src/atoms' import { SupportedNetwork } from 'src/types' import { Address } from 'viem' +import { BackButton } from '@components/buttons/BackButton' import { DeployLiquidationPairButton } from '@components/buttons/DeployLiquidationPairButton' import { NETWORK_CONFIG } from '@constants/config' import { useLiquidationPairSteps } from '@hooks/useLiquidationPairSteps' @@ -73,12 +74,19 @@ export const DeployLiquidationPairForm = (props: DeployLiquidationPairFormProps) defaultPrice={defaultTargetAuctionPrice} className='w-full max-w-md' /> - {/* TODO: add option to skip deploying an lp and just set one */} - +
+
+ + +
+ +
) diff --git a/apps/vault-factory/src/components/forms/ClaimerForm.tsx b/apps/vault-factory/src/components/forms/SetClaimerForm.tsx similarity index 78% rename from apps/vault-factory/src/components/forms/ClaimerForm.tsx rename to apps/vault-factory/src/components/forms/SetClaimerForm.tsx index 14d309fc..b3c79924 100644 --- a/apps/vault-factory/src/components/forms/ClaimerForm.tsx +++ b/apps/vault-factory/src/components/forms/SetClaimerForm.tsx @@ -5,6 +5,7 @@ import { useEffect } from 'react' import { FormProvider, useForm } from 'react-hook-form' import { vaultAddressAtom, vaultChainIdAtom, vaultClaimerAddressAtom } from 'src/atoms' import { Address, isAddress } from 'viem' +import { BackButton } from '@components/buttons/BackButton' import { NextButton } from '@components/buttons/NextButton' import { PrevButton } from '@components/buttons/PrevButton' import { SetClaimerButton } from '@components/buttons/SetClaimerButton' @@ -12,21 +13,21 @@ import { NETWORK_CONFIG } from '@constants/config' import { useVaultCreationSteps } from '@hooks/useVaultCreationSteps' import { SimpleInput } from './SimpleInput' -export interface ClaimerFormValues { +export interface SetClaimerFormValues { vaultClaimer: string } -interface ClaimerFormProps { +interface SetClaimerFormProps { isOnlyStep?: boolean className?: string } -export const ClaimerForm = (props: ClaimerFormProps) => { +export const SetClaimerForm = (props: SetClaimerFormProps) => { const { isOnlyStep, className } = props const router = useRouter() - const formMethods = useForm({ mode: 'onChange' }) + const formMethods = useForm({ mode: 'onChange' }) const [vaultClaimer, setVaultClaimer] = useAtom(vaultClaimerAddressAtom) @@ -42,7 +43,7 @@ export const ClaimerForm = (props: ClaimerFormProps) => { }) }, []) - const onSubmit = (data: ClaimerFormValues) => { + const onSubmit = (data: SetClaimerFormValues) => { setVaultClaimer(data.vaultClaimer.trim() as Address) nextStep() } @@ -71,11 +72,14 @@ export const ClaimerForm = (props: ClaimerFormProps) => { ) : ( !!vaultChainId && !!vaultAddress && ( - router.push('/')} - /> +
+ + router.push('/')} + /> +
) )} diff --git a/apps/vault-factory/src/components/forms/SetLiquidationPairForm.tsx b/apps/vault-factory/src/components/forms/SetLiquidationPairForm.tsx index 0d793688..9fb37a90 100644 --- a/apps/vault-factory/src/components/forms/SetLiquidationPairForm.tsx +++ b/apps/vault-factory/src/components/forms/SetLiquidationPairForm.tsx @@ -5,7 +5,10 @@ import { FormProvider, useForm } from 'react-hook-form' import { vaultAddressAtom, vaultChainIdAtom } from 'src/atoms' import { SupportedNetwork } from 'src/types' import { Address } from 'viem' +import { PrevButton } from '@components/buttons/PrevButton' import { SetLiquidationPairButton } from '@components/buttons/SetLiquidationPairButton' +import { useLiquidationPairSteps } from '@hooks/useLiquidationPairSteps' +import { useVaultCreationSteps } from '@hooks/useVaultCreationSteps' import { LiquidationPairAddressInput } from './LiquidationPairAddressInput' export interface SetLiquidationPairFormValues { @@ -23,9 +26,17 @@ export const SetLiquidationPairForm = (props: SetLiquidationPairFormProps) => { const formMethods = useForm({ mode: 'onChange' }) + const { prevStep: prevVaultCreationStep } = useVaultCreationSteps() + const { prevStep: prevLpStep } = useLiquidationPairSteps() + const chainId = useAtomValue(vaultChainIdAtom) as SupportedNetwork const vaultAddress = useAtomValue(vaultAddressAtom) as Address + const prevStep = () => { + prevVaultCreationStep() + prevLpStep() + } + return (
{ className={classNames('flex flex-col grow gap-12 items-center', className)} > - router.push('/')} - /> +
+ + router.push('/')} + /> +
) diff --git a/apps/vault-factory/src/pages/claimer/[chainId]/[vaultAddress].tsx b/apps/vault-factory/src/pages/claimer/[chainId]/[vaultAddress].tsx index e44a56e6..79e21a6c 100644 --- a/apps/vault-factory/src/pages/claimer/[chainId]/[vaultAddress].tsx +++ b/apps/vault-factory/src/pages/claimer/[chainId]/[vaultAddress].tsx @@ -5,7 +5,7 @@ import { SupportedNetwork } from 'src/types' import { isAddress } from 'viem' import { allVaultStepInfo } from '@components/CreateVaultStepInfo' import { DeployedVaultInfo } from '@components/DeployedVaultInfo' -import { ClaimerForm } from '@components/forms/ClaimerForm' +import { SetClaimerForm } from '@components/forms/SetClaimerForm' import { Layout } from '@components/Layout' import { StepInfo } from '@components/StepInfo' import { SUPPORTED_NETWORKS } from '@constants/config' @@ -66,7 +66,7 @@ const ClaimerStepInfo = () => { const ClaimerStepContent = () => { return (
- +
) } From 5b25d37388c6b7a5d2b70f416f600875b55cc530 Mon Sep 17 00:00:00 2001 From: Ncookiez Date: Tue, 2 Apr 2024 13:42:47 -0400 Subject: [PATCH 092/161] updated testnet --- .../src/components/Draws/DrawAwardReward.tsx | 3 +- .../src/components/Draws/DrawRngReward.tsx | 38 ++---------- apps/analytics/src/constants/config.ts | 6 +- .../analytics/src/hooks/useAllDrawsStatus.tsx | 6 +- apps/analytics/src/hooks/useDrawStatus.tsx | 6 +- apps/analytics/src/hooks/useRngTxs.tsx | 11 ++-- apps/app/src/constants/config.ts | 2 +- apps/app/src/vaultLists/default.ts | 4 +- apps/app/src/vaultLists/testnet.ts | 28 ++++----- apps/rewards-builder/src/constants/config.ts | 2 +- apps/vault-factory/src/constants/config.ts | 16 ++--- shared/react-components/constants.ts | 8 +-- shared/utilities/abis/drawManager.ts | 16 ++--- shared/utilities/abis/liquidationPair.ts | 25 +++++--- .../utilities/abis/liquidationPairFactory.ts | 4 +- shared/utilities/abis/prizePool.ts | 22 ++++++- shared/utilities/abis/vault.ts | 58 ++++++++++++++++++- shared/utilities/constants.ts | 38 ++++++------ shared/utilities/utils/events.ts | 16 ++--- 19 files changed, 183 insertions(+), 126 deletions(-) diff --git a/apps/analytics/src/components/Draws/DrawAwardReward.tsx b/apps/analytics/src/components/Draws/DrawAwardReward.tsx index 7ccea475..f9fc29e8 100644 --- a/apps/analytics/src/components/Draws/DrawAwardReward.tsx +++ b/apps/analytics/src/components/Draws/DrawAwardReward.tsx @@ -20,8 +20,7 @@ export const DrawAwardReward = (props: DrawAwardRewardProps) => { const { status, isSkipped } = useDrawStatus(prizePool, drawId) const { data: allRngTxs, isFetched: isFetchedAllRngTxs } = useRngTxs(prizePool) - const rngTxs = allRngTxs?.find((txs) => txs.drawStart.drawId === drawId) - const drawFinishTx = rngTxs?.drawFinish + const drawFinishTx = allRngTxs?.find((txs) => txs.drawStart.drawId === drawId)?.drawFinish const { data: prizeToken } = usePrizeTokenData(prizePool) diff --git a/apps/analytics/src/components/Draws/DrawRngReward.tsx b/apps/analytics/src/components/Draws/DrawRngReward.tsx index 04dfbcd6..ea6dcae0 100644 --- a/apps/analytics/src/components/Draws/DrawRngReward.tsx +++ b/apps/analytics/src/components/Draws/DrawRngReward.tsx @@ -26,9 +26,6 @@ export const DrawRngReward = (props: DrawRngRewardProps) => { const { data: currentRngAuctionReward } = useCurrentRngAuctionReward(prizePool) - // TODO: query expected reward from draw manager if drawStartTx?.reward === undefined using `drawStartTx.elapsedTime` (not possible with current contract deployment) - const expectedDrawStartReward: bigint | undefined = undefined - const isRngCompletionPossible = status === 'closed' && !!currentRngAuctionReward && !isSkipped return ( @@ -40,35 +37,12 @@ export const DrawRngReward = (props: DrawRngRewardProps) => { {!!drawStartTx ? ( <> - {drawStartTx.reward !== undefined ? ( - <> - - {formatBigIntForDisplay(drawStartTx.reward, prizeToken.decimals, { - maximumFractionDigits: 5 - })} - {' '} - {prizeToken.symbol} - - ) : ( - <> - {expectedDrawStartReward !== undefined ? ( - <> - - {formatBigIntForDisplay(expectedDrawStartReward, prizeToken.decimals, { - maximumFractionDigits: 5 - })} - {' '} - {prizeToken.symbol} - - ) : ( - - )} - - )} + + {formatBigIntForDisplay(drawStartTx.reward, prizeToken.decimals, { + maximumFractionDigits: 5 + })} + {' '} + {prizeToken.symbol} ) : isRngCompletionPossible ? ( <> diff --git a/apps/analytics/src/constants/config.ts b/apps/analytics/src/constants/config.ts index bb456bf5..26c978fe 100644 --- a/apps/analytics/src/constants/config.ts +++ b/apps/analytics/src/constants/config.ts @@ -32,14 +32,14 @@ export const RPC_URLS = { * Queries' start blocks */ export const QUERY_START_BLOCK: { [chainId: number]: bigint } = { - [NETWORK.optimism_sepolia]: 9_801_300n + [NETWORK.optimism_sepolia]: 9_930_300n } /** * Draw results URL */ export const DRAW_RESULTS_URL: { [chainId: number]: string } = { - [NETWORK.optimism_sepolia]: `https://raw.githubusercontent.com/GenerationSoftware/pt-v5-winners-testnet/main/winners/vaultAccounts/${NETWORK.optimism_sepolia}` + [NETWORK.optimism_sepolia]: `https://raw.githubusercontent.com/chuckbergeron/wins/main/winners/vaultAccounts/${NETWORK.optimism_sepolia}` } /** @@ -66,7 +66,7 @@ export const BURN_SETTINGS: { }, [NETWORK.optimism_sepolia]: { burnTokenAddress: POOL_TOKEN_ADDRESSES[NETWORK.optimism_sepolia], - liquidationPairAddress: '0xd781b45644fb5b5d8c76a991da2365b8272e932d', + liquidationPairAddress: '0xe1b44a671e3410dc6f9ac1ef88bf7f87305349bf', burnAddresses: [DEAD_ADDRESS] } } diff --git a/apps/analytics/src/hooks/useAllDrawsStatus.tsx b/apps/analytics/src/hooks/useAllDrawsStatus.tsx index 69b026da..afd3150a 100644 --- a/apps/analytics/src/hooks/useAllDrawsStatus.tsx +++ b/apps/analytics/src/hooks/useAllDrawsStatus.tsx @@ -43,7 +43,7 @@ export const useAllDrawsStatus = (prizePool: PrizePool, drawIds: number[]) => { const openedAt = firstDrawOpenedAt + drawPeriod * (drawId - 1) const closedAt = openedAt + drawPeriod - const rngCompletedAt = rngTxs?.drawStart.timestamp + const startedAt = rngTxs?.drawStart.timestamp const awardedAt = rngTxs?.drawFinish?.timestamp const finalizedAt = closedAt + drawPeriod @@ -59,8 +59,8 @@ export const useAllDrawsStatus = (prizePool: PrizePool, drawIds: number[]) => { ? 'closed' : 'open' - const currentAuctionClosesAt = !!rngCompletedAt - ? rngCompletedAt + drawAuctionDuration + const currentAuctionClosesAt = !!startedAt + ? startedAt + drawAuctionDuration : closedAt + drawAuctionDuration const isSkipped = (status === 'finalized' && !isAwarded) || diff --git a/apps/analytics/src/hooks/useDrawStatus.tsx b/apps/analytics/src/hooks/useDrawStatus.tsx index ee7433dd..256a0087 100644 --- a/apps/analytics/src/hooks/useDrawStatus.tsx +++ b/apps/analytics/src/hooks/useDrawStatus.tsx @@ -31,7 +31,7 @@ export const useDrawStatus = (prizePool: PrizePool, drawId: number) => { const openedAt = firstDrawOpenedAt + drawPeriod * (drawId - 1) const closedAt = openedAt + drawPeriod - const rngCompletedAt = rngTxs?.drawStart.timestamp + const startedAt = rngTxs?.drawStart.timestamp const awardedAt = rngTxs?.drawFinish?.timestamp const finalizedAt = closedAt + drawPeriod @@ -48,8 +48,8 @@ export const useDrawStatus = (prizePool: PrizePool, drawId: number) => { ? 'closed' : 'open' - const currentAuctionClosesAt = !!rngCompletedAt - ? rngCompletedAt + drawAuctionDuration + const currentAuctionClosesAt = !!startedAt + ? startedAt + drawAuctionDuration : closedAt + drawAuctionDuration const isSkipped = (status === 'finalized' && !isAwarded) || diff --git a/apps/analytics/src/hooks/useRngTxs.tsx b/apps/analytics/src/hooks/useRngTxs.tsx index 98a89ad8..79d64255 100644 --- a/apps/analytics/src/hooks/useRngTxs.tsx +++ b/apps/analytics/src/hooks/useRngTxs.tsx @@ -11,7 +11,7 @@ import { QUERY_START_BLOCK } from '@constants/config' export interface DrawStartTx { drawId: number - reward?: bigint + reward: bigint rewardRecipient: Address elapsedTime: number hash: `0x${string}` @@ -86,6 +86,7 @@ export const useRngTxs = (prizePool: PrizePool) => { const drawStart: DrawStartTx = { drawId, + reward: drawStartedEvent.args.reward, rewardRecipient: drawStartedEvent.args.recipient, elapsedTime: drawStartedEvent.args.elapsedTime, hash: drawStartedEvent.transactionHash, @@ -107,19 +108,17 @@ export const useRngTxs = (prizePool: PrizePool) => { drawFinish = { drawId, - reward: drawFinishedEvent.args.finishReward, - rewardRecipient: drawFinishedEvent.args.finishRecipient, + reward: drawFinishedEvent.args.reward, + rewardRecipient: drawFinishedEvent.args.recipient, reserve: drawAwardedEvent.args.reserve, remainingReserve: drawFinishedEvent.args.remainingReserve, lastNumTiers: drawAwardedEvent.args.lastNumTiers, numTiers: drawAwardedEvent.args.numTiers, - elapsedTime: Number(drawFinishedEvent.args.elapsedTime), // TODO: remove number cast once contract is fixed + elapsedTime: drawFinishedEvent.args.elapsedTime, hash: drawAwardedEvent.transactionHash, blockNumber: drawAwardedEvent.blockNumber, timestamp: !!drawAwardedBlock ? Number(drawAwardedBlock.timestamp) : undefined } - - drawStart.reward = drawFinishedEvent.args.startReward } } diff --git a/apps/app/src/constants/config.ts b/apps/app/src/constants/config.ts index ee600d5f..ab25a861 100644 --- a/apps/app/src/constants/config.ts +++ b/apps/app/src/constants/config.ts @@ -100,7 +100,7 @@ export const TWAB_REWARDS_SETTINGS: { USDC_TOKEN_ADDRESSES[NETWORK.optimism_sepolia], POOL_TOKEN_ADDRESSES[NETWORK.optimism_sepolia] ], - fromBlock: 9_801_300n + fromBlock: 9_930_300n } } diff --git a/apps/app/src/vaultLists/default.ts b/apps/app/src/vaultLists/default.ts index f6b0900f..86fbf1e3 100644 --- a/apps/app/src/vaultLists/default.ts +++ b/apps/app/src/vaultLists/default.ts @@ -6,8 +6,8 @@ import { testnetVaults } from './testnet' const defaultVaultList: VaultList = { name: 'Cabana Vault List', keywords: ['pooltogether', 'cabana', 'g9', 'optimism'], - version: { major: 2, minor: 0, patch: 1 }, - timestamp: '2024-03-26T19:36:50Z', + version: { major: 2, minor: 0, patch: 2 }, + timestamp: '2024-04-02T15:57:37Z', logoURI: `${LINKS.app}/pooltogether-token-logo.svg`, tokens: [ // { diff --git a/apps/app/src/vaultLists/testnet.ts b/apps/app/src/vaultLists/testnet.ts index 47e5586e..6e22a3ae 100644 --- a/apps/app/src/vaultLists/testnet.ts +++ b/apps/app/src/vaultLists/testnet.ts @@ -4,14 +4,14 @@ import { NETWORK } from '@shared/utilities' export const testnetVaults: VaultList['tokens'] = [ { chainId: NETWORK.optimism_sepolia, - address: '0x8f8484f30F7A72c8059E6BD709f898606e38DedA', + address: '0xFaA0a8f7A7621A0Add12ddcFE940b3c634BD088e', name: 'Prize DAI - LY', decimals: 18, symbol: 'PDAI-LY', logoURI: 'https://assets.coingecko.com/coins/images/9956/small/4943.png?1636636734', extensions: { underlyingAsset: { - address: '0x8261Cb9519DD1D80B5ce66B0887C6fCEeA8a64eE', + address: '0x3eb488d3419496742963437378C2130a2EdcB87d', symbol: 'DAI', name: 'Dai Stablecoin' } @@ -19,14 +19,14 @@ export const testnetVaults: VaultList['tokens'] = [ }, { chainId: NETWORK.optimism_sepolia, - address: '0x5B0182E62Baee8Be36AC15696E5C78A0c89b465F', + address: '0xaB9f23574e0722b52fF67db1B49A5385066612CB', name: 'Prize DAI - HY', decimals: 18, symbol: 'PDAI-HY', logoURI: 'https://assets.coingecko.com/coins/images/9956/small/4943.png?1636636734', extensions: { underlyingAsset: { - address: '0x8261Cb9519DD1D80B5ce66B0887C6fCEeA8a64eE', + address: '0x3eb488d3419496742963437378C2130a2EdcB87d', symbol: 'DAI', name: 'Dai Stablecoin' } @@ -34,14 +34,14 @@ export const testnetVaults: VaultList['tokens'] = [ }, { chainId: NETWORK.optimism_sepolia, - address: '0x383E8D88De4E3999b43C51cA1819516617260e99', + address: '0x6d02b0CE229ABEe2f155248E66d8E090d3C86BB2', name: 'Prize USDC - LY', decimals: 6, symbol: 'PUSDC-LY', logoURI: 'https://etherscan.io/token/images/centre-usdc_28.png', extensions: { underlyingAsset: { - address: '0x0E13bF42f927575475894f2d5076a7Ac77060eA0', + address: '0x01ce79e045539F560AFa57943DB6CFF3FB097c4b', symbol: 'USDC', name: 'USD Coin' } @@ -49,14 +49,14 @@ export const testnetVaults: VaultList['tokens'] = [ }, { chainId: NETWORK.optimism_sepolia, - address: '0xe8AD34CB77b8DCE62DEd796DCB10b8f574d6A619', + address: '0x0eC4EbfbED7599640e8AA3E76F46BB5A29d42827', name: 'Prize USDC - HY', decimals: 6, symbol: 'PUSDC-HY', logoURI: 'https://etherscan.io/token/images/centre-usdc_28.png', extensions: { underlyingAsset: { - address: '0x0E13bF42f927575475894f2d5076a7Ac77060eA0', + address: '0x01ce79e045539F560AFa57943DB6CFF3FB097c4b', symbol: 'USDC', name: 'USD Coin' } @@ -64,7 +64,7 @@ export const testnetVaults: VaultList['tokens'] = [ }, { chainId: NETWORK.optimism_sepolia, - address: '0x7eb63F62f2E1E4646793D3dA9C1A232A5f5710B5', + address: '0x14b0c4f45Fe1BcC41DfA1C901D3dD1323735CDF3', name: 'Prize GUSD', decimals: 2, symbol: 'PGUSD', @@ -72,7 +72,7 @@ export const testnetVaults: VaultList['tokens'] = [ 'https://assets.coingecko.com/coins/images/5992/small/gemini-dollar-gusd.png?1536745278', extensions: { underlyingAsset: { - address: '0x493c7081FAab6e5B2d6b18d9311918580e88c6bF', + address: '0xF0F496Dc0558E9744963292eFFf344725218B1F5', symbol: 'GUSD', name: 'Gemini dollar' } @@ -80,14 +80,14 @@ export const testnetVaults: VaultList['tokens'] = [ }, { chainId: NETWORK.optimism_sepolia, - address: '0x1B751A1F3b558173DF9832d4564E6B38db7552c6', + address: '0xbc5405249D568A18C41714D32c9b3bC6521D3DD6', name: 'Prize WBTC', decimals: 8, symbol: 'PWBTC', logoURI: 'https://etherscan.io/token/images/wbtc_28.png?v=1', extensions: { underlyingAsset: { - address: '0x45bbc6B553D2Afc4d3e376B22f70A67d9a26f819', + address: '0xC21D6c8dD430CC97Aaa58391625B82f4681AE473', symbol: 'WBTC', name: 'Wrapped BTC' } @@ -95,14 +95,14 @@ export const testnetVaults: VaultList['tokens'] = [ }, { chainId: NETWORK.optimism_sepolia, - address: '0xf04Aa80EaC0043C8F8328Dd35385aaf2C0ed8E9a', + address: '0x3e5bC94A341481F742F5f573D341fA2540bC0992', name: 'Prize WETH', decimals: 18, symbol: 'PWETH', logoURI: 'https://etherscan.io/token/images/weth_28.png', extensions: { underlyingAsset: { - address: '0xD5C2a983D320a881F21Dc68fd89f905Ff1517B2C', + address: '0x0845842Ad2DCE40b83EddECf9C67df2C75caB844', symbol: 'WETH', name: 'Wrapped Ether' } diff --git a/apps/rewards-builder/src/constants/config.ts b/apps/rewards-builder/src/constants/config.ts index 30060cdb..484a3492 100644 --- a/apps/rewards-builder/src/constants/config.ts +++ b/apps/rewards-builder/src/constants/config.ts @@ -74,5 +74,5 @@ export const PROMOTION_FILTERS: { } = { [NETWORK.mainnet]: {}, [NETWORK.optimism]: { fromBlock: 112_933_000n }, - [NETWORK.optimism_sepolia]: { fromBlock: 9_801_300n } + [NETWORK.optimism_sepolia]: { fromBlock: 9_930_300n } } diff --git a/apps/vault-factory/src/constants/config.ts b/apps/vault-factory/src/constants/config.ts index 3444cb12..6240769c 100644 --- a/apps/vault-factory/src/constants/config.ts +++ b/apps/vault-factory/src/constants/config.ts @@ -95,7 +95,7 @@ export const NETWORK_CONFIG: Record< // }, [NETWORK.optimism_sepolia]: { description: 'Sepolia testnet for the Optimism network.', - prizePool: '0x31547D3c38F2F8dC92421C54B173F3B27Ab26EbB', + prizePool: '0x595806bc53dd4bE760EbbE63D78931A3601aA04b', claimer: DEFAULT_CLAIMER_ADDRESSES[NETWORK.optimism_sepolia], lp: { targetAuctionPeriod: SECONDS_PER_HOUR, targetAuctionPriceUsd: 10 }, yieldSources: [ @@ -105,13 +105,13 @@ export const NETWORK_CONFIG: Record< href: 'https://aave.com/', description: 'Lending and borrowing protocol', vaults: [ - { address: '0xeE71a7CdE1bA4896D5Bd7D33DEDEd67D0e8bA534', tags: ['stablecoin'] }, - { address: '0x6F626779fb5AB0F1Bba6EeE45F5D556A796e9341', tags: ['stablecoin'] }, - { address: '0x2332B17419a9F6BA122572Aa820Ba8f8E3D08c20', tags: ['stablecoin'] }, - { address: '0x8c2cbfeCd13344E48464c91bF7eA705aDD74D9D8', tags: ['stablecoin'] }, - { address: '0xB1126119dD12Bc11afB35A25D33c19ac60A64d1f', tags: ['stablecoin'] }, - { address: '0x5C28E1b31E88344606015479a4f2cfF4cB7bfAa1' }, - { address: '0x9CfC71e201fD7E9F2C758D1cF34D33c9Bd4c32E9' } + { address: '0x24021A2385889cfFB170519a0183272ceD343c33', tags: ['stablecoin'] }, + { address: '0x791f5549E748Fc728f584822b447a25bDcBF1279', tags: ['stablecoin'] }, + { address: '0xFb551dd465660960ED6c3A97A1F25D5CF8e4A5A5', tags: ['stablecoin'] }, + { address: '0xf6a2e371842a72A8e883e8f86D6dFB9D56Aa6ECc', tags: ['stablecoin'] }, + { address: '0x7F33173A9e242Dba743F1e0460fF3Be9459d6342', tags: ['stablecoin'] }, + { address: '0x534023cEb618509Aa85d491673D256A27B4f19a4' }, + { address: '0xBd3b8Da015B8CeB206c3ABD1cBd6760E719B33a4' } ] } ] diff --git a/shared/react-components/constants.ts b/shared/react-components/constants.ts index 08b286e5..c26471df 100644 --- a/shared/react-components/constants.ts +++ b/shared/react-components/constants.ts @@ -58,10 +58,10 @@ export const TOKEN_LOGO_OVERRIDES: Record [NETWORK.optimism_sepolia]: { [POOL_TOKEN_ADDRESSES[NETWORK.optimism_sepolia].toLowerCase()]: tokenLogoUrls.pool, [USDC_TOKEN_ADDRESSES[NETWORK.optimism_sepolia]]: tokenLogoUrls.usdc, - '0x8261cb9519dd1d80b5ce66b0887c6fceea8a64ee': tokenLogoUrls.dai, - '0x493c7081faab6e5b2d6b18d9311918580e88c6bf': tokenLogoUrls.gusd, - '0xd5c2a983d320a881f21dc68fd89f905ff1517b2c': tokenLogoUrls.weth, - '0x45bbc6b553d2afc4d3e376b22f70a67d9a26f819': tokenLogoUrls.wbtc + '0x3eb488d3419496742963437378c2130a2edcb87d': tokenLogoUrls.dai, + '0xf0f496dc0558e9744963292efff344725218b1f5': tokenLogoUrls.gusd, + '0x0845842ad2dce40b83eddecf9c67df2c75cab844': tokenLogoUrls.weth, + '0xc21d6c8dd430cc97aaa58391625b82f4681ae473': tokenLogoUrls.wbtc }, [NETWORK.avalanche]: { '0x2f2a2543b76a4166549f7aab2e75bef0aefc5b0f': tokenLogoUrls.wbtc diff --git a/shared/utilities/abis/drawManager.ts b/shared/utilities/abis/drawManager.ts index 770e9147..7713d58e 100644 --- a/shared/utilities/abis/drawManager.ts +++ b/shared/utilities/abis/drawManager.ts @@ -64,12 +64,11 @@ export const drawManagerABI = [ { anonymous: false, inputs: [ + { indexed: true, internalType: 'address', name: 'sender', type: 'address' }, + { indexed: true, internalType: 'address', name: 'recipient', type: 'address' }, { indexed: true, internalType: 'uint24', name: 'drawId', type: 'uint24' }, - { indexed: false, internalType: 'uint256', name: 'elapsedTime', type: 'uint256' }, - { indexed: true, internalType: 'address', name: 'startRecipient', type: 'address' }, - { indexed: false, internalType: 'uint256', name: 'startReward', type: 'uint256' }, - { indexed: true, internalType: 'address', name: 'finishRecipient', type: 'address' }, - { indexed: false, internalType: 'uint256', name: 'finishReward', type: 'uint256' }, + { indexed: false, internalType: 'uint48', name: 'elapsedTime', type: 'uint48' }, + { indexed: false, internalType: 'uint256', name: 'reward', type: 'uint256' }, { indexed: false, internalType: 'uint256', name: 'remainingReserve', type: 'uint256' } ], name: 'DrawFinished', @@ -80,9 +79,10 @@ export const drawManagerABI = [ inputs: [ { indexed: true, internalType: 'address', name: 'sender', type: 'address' }, { indexed: true, internalType: 'address', name: 'recipient', type: 'address' }, - { indexed: false, internalType: 'uint24', name: 'drawId', type: 'uint24' }, - { indexed: false, internalType: 'uint32', name: 'rngRequestId', type: 'uint32' }, - { indexed: false, internalType: 'uint48', name: 'elapsedTime', type: 'uint48' } + { indexed: true, internalType: 'uint24', name: 'drawId', type: 'uint24' }, + { indexed: false, internalType: 'uint48', name: 'elapsedTime', type: 'uint48' }, + { indexed: false, internalType: 'uint256', name: 'reward', type: 'uint256' }, + { indexed: false, internalType: 'uint32', name: 'rngRequestId', type: 'uint32' } ], name: 'DrawStarted', type: 'event' diff --git a/shared/utilities/abis/liquidationPair.ts b/shared/utilities/abis/liquidationPair.ts index bf96450a..8a456195 100644 --- a/shared/utilities/abis/liquidationPair.ts +++ b/shared/utilities/abis/liquidationPair.ts @@ -5,12 +5,14 @@ export const liquidationPairABI = [ { internalType: 'address', name: '__tokenIn', type: 'address' }, { internalType: 'address', name: '__tokenOut', type: 'address' }, { internalType: 'uint256', name: '_targetAuctionPeriod', type: 'uint256' }, - { internalType: 'uint192', name: '_minimumAuctionAmount', type: 'uint192' }, + { internalType: 'uint192', name: '_targetAuctionPrice', type: 'uint192' }, { internalType: 'uint256', name: '_smoothingFactor', type: 'uint256' } ], stateMutability: 'nonpayable', type: 'constructor' }, + { inputs: [], name: 'ReceiverIsZero', type: 'error' }, + { inputs: [], name: 'SmoothingGteOne', type: 'error' }, { inputs: [ { internalType: 'uint256', name: 'amountInMax', type: 'uint256' }, @@ -19,6 +21,20 @@ export const liquidationPairABI = [ name: 'SwapExceedsMax', type: 'error' }, + { inputs: [], name: 'ZeroAvailableBalance', type: 'error' }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: 'address', name: 'sender', type: 'address' }, + { indexed: true, internalType: 'address', name: 'receiver', type: 'address' }, + { indexed: false, internalType: 'uint256', name: 'amountOut', type: 'uint256' }, + { indexed: false, internalType: 'uint256', name: 'amountInMax', type: 'uint256' }, + { indexed: false, internalType: 'uint256', name: 'amountIn', type: 'uint256' }, + { indexed: false, internalType: 'bytes', name: 'flashSwapData', type: 'bytes' } + ], + name: 'SwappedExactAmountOut', + type: 'event' + }, { inputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], name: 'computeExactAmountIn', @@ -54,13 +70,6 @@ export const liquidationPairABI = [ stateMutability: 'nonpayable', type: 'function' }, - { - inputs: [], - name: 'minimumAuctionAmount', - outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], - stateMutability: 'view', - type: 'function' - }, { inputs: [], name: 'smoothingFactor', diff --git a/shared/utilities/abis/liquidationPairFactory.ts b/shared/utilities/abis/liquidationPairFactory.ts index 3ccb3393..8dd25776 100644 --- a/shared/utilities/abis/liquidationPairFactory.ts +++ b/shared/utilities/abis/liquidationPairFactory.ts @@ -17,7 +17,7 @@ export const liquidationPairFactoryABI = [ { indexed: true, internalType: 'address', name: 'tokenIn', type: 'address' }, { indexed: true, internalType: 'address', name: 'tokenOut', type: 'address' }, { indexed: false, internalType: 'uint256', name: 'targetAuctionPeriod', type: 'uint256' }, - { indexed: false, internalType: 'uint192', name: 'minimumAuctionAmount', type: 'uint192' }, + { indexed: false, internalType: 'uint192', name: 'targetAuctionPrice', type: 'uint192' }, { indexed: false, internalType: 'uint256', name: 'smoothingFactor', type: 'uint256' } ], name: 'PairCreated', @@ -36,7 +36,7 @@ export const liquidationPairFactoryABI = [ { internalType: 'address', name: '_tokenIn', type: 'address' }, { internalType: 'address', name: '_tokenOut', type: 'address' }, { internalType: 'uint256', name: '_targetAuctionPeriod', type: 'uint256' }, - { internalType: 'uint192', name: '_minimumAuctionAmount', type: 'uint192' }, + { internalType: 'uint192', name: '_targetAuctionPrice', type: 'uint192' }, { internalType: 'uint256', name: '_smoothingFactor', type: 'uint256' } ], name: 'createPair', diff --git a/shared/utilities/abis/prizePool.ts b/shared/utilities/abis/prizePool.ts index e762fbd2..afa3f98e 100644 --- a/shared/utilities/abis/prizePool.ts +++ b/shared/utilities/abis/prizePool.ts @@ -25,6 +25,16 @@ export const prizePoolABI = [ type: 'constructor' }, { inputs: [], name: 'AddToDrawZero', type: 'error' }, + { + inputs: [ + { internalType: 'address', name: 'vault', type: 'address' }, + { internalType: 'address', name: 'winner', type: 'address' }, + { internalType: 'uint8', name: 'tier', type: 'uint8' }, + { internalType: 'uint32', name: 'prizeIndex', type: 'uint32' } + ], + name: 'AlreadyClaimed', + type: 'error' + }, { inputs: [{ internalType: 'uint48', name: 'drawClosesAt', type: 'uint48' }], name: 'AwardingDrawNotClosed', @@ -190,6 +200,16 @@ export const prizePoolABI = [ name: 'PRBMath_SD59x18_Mul_Overflow', type: 'error' }, + { + inputs: [{ internalType: 'SD59x18', name: 'x', type: 'int256' }], + name: 'PRBMath_SD59x18_Sqrt_NegativeInput', + type: 'error' + }, + { + inputs: [{ internalType: 'SD59x18', name: 'x', type: 'int256' }], + name: 'PRBMath_SD59x18_Sqrt_Overflow', + type: 'error' + }, { inputs: [{ internalType: 'uint256', name: 'x', type: 'uint256' }], name: 'PRBMath_UD34x4_fromUD60x18_Convert_Overflow', @@ -645,7 +665,7 @@ export const prizePoolABI = [ { inputs: [], name: 'isShutdown', - outputs: [{ internalType: 'bool', name: 'shutdown', type: 'bool' }], + outputs: [{ internalType: 'bool', name: '', type: 'bool' }], stateMutability: 'view', type: 'function' }, diff --git a/shared/utilities/abis/vault.ts b/shared/utilities/abis/vault.ts index 637a2d20..bd7d2eb1 100644 --- a/shared/utilities/abis/vault.ts +++ b/shared/utilities/abis/vault.ts @@ -41,6 +41,11 @@ export const vaultABI = [ { inputs: [], name: 'ClaimRecipientZeroAddress', type: 'error' }, { inputs: [], name: 'ClaimerZeroAddress', type: 'error' }, { inputs: [], name: 'DepositZeroAssets', type: 'error' }, + { + inputs: [{ internalType: 'address', name: 'asset', type: 'address' }], + name: 'FailedToGetAssetDecimals', + type: 'error' + }, { inputs: [], name: 'InvalidShortString', type: 'error' }, { inputs: [], name: 'LPZeroAddress', type: 'error' }, { inputs: [], name: 'LiquidationAmountOutZero', type: 'error' }, @@ -73,6 +78,27 @@ export const vaultABI = [ name: 'LossyDeposit', type: 'error' }, + { + inputs: [ + { internalType: 'uint256', name: 'shares', type: 'uint256' }, + { internalType: 'uint256', name: 'maxShares', type: 'uint256' } + ], + name: 'MaxSharesExceeded', + type: 'error' + }, + { + inputs: [ + { internalType: 'uint256', name: 'assets', type: 'uint256' }, + { internalType: 'uint256', name: 'minAssets', type: 'uint256' } + ], + name: 'MinAssetsNotReached', + type: 'error' + }, + { + inputs: [{ internalType: 'uint256', name: 'excess', type: 'uint256' }], + name: 'MintLimitExceeded', + type: 'error' + }, { inputs: [], name: 'MintZeroShares', type: 'error' }, { inputs: [], name: 'OwnerZeroAddress', type: 'error' }, { @@ -97,7 +123,6 @@ export const vaultABI = [ name: 'StringTooLong', type: 'error' }, - { inputs: [], name: 'SweepZeroAssets', type: 'error' }, { inputs: [], name: 'TwabControllerZeroAddress', type: 'error' }, { inputs: [], name: 'WithdrawZeroAssets', type: 'error' }, { @@ -598,6 +623,18 @@ export const vaultABI = [ stateMutability: 'view', type: 'function' }, + { + inputs: [ + { internalType: 'uint256', name: '_shares', type: 'uint256' }, + { internalType: 'address', name: '_receiver', type: 'address' }, + { internalType: 'address', name: '_owner', type: 'address' }, + { internalType: 'uint256', name: '_minAssets', type: 'uint256' } + ], + name: 'redeem', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'nonpayable', + type: 'function' + }, { inputs: [ { internalType: 'uint256', name: '_shares', type: 'uint256' }, @@ -697,6 +734,13 @@ export const vaultABI = [ stateMutability: 'view', type: 'function' }, + { + inputs: [], + name: 'totalPreciseAssets', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function' + }, { inputs: [], name: 'totalSupply', @@ -769,6 +813,18 @@ export const vaultABI = [ stateMutability: 'nonpayable', type: 'function' }, + { + inputs: [ + { internalType: 'uint256', name: '_assets', type: 'uint256' }, + { internalType: 'address', name: '_receiver', type: 'address' }, + { internalType: 'address', name: '_owner', type: 'address' }, + { internalType: 'uint256', name: '_maxShares', type: 'uint256' } + ], + name: 'withdraw', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'nonpayable', + type: 'function' + }, { inputs: [ { internalType: 'uint256', name: '_assets', type: 'uint256' }, diff --git a/shared/utilities/constants.ts b/shared/utilities/constants.ts index 2ea3ff45..39a78bcd 100644 --- a/shared/utilities/constants.ts +++ b/shared/utilities/constants.ts @@ -31,7 +31,7 @@ export const POOL_TOKEN_ADDRESSES = { [NETWORK.mainnet]: '0x0cEC1A9154Ff802e7934Fc916Ed7Ca50bDE6844e', [NETWORK.polygon]: '0x25788a1a171ec66Da6502f9975a15B609fF54CF6', [NETWORK.optimism]: '0x395ae52bb17aef68c2888d941736a71dc6d4e125', - [NETWORK.optimism_sepolia]: '0x1e62Cf8A2C981B0AE39E0A52A06EA5679186938C' + [NETWORK.optimism_sepolia]: '0xBC8c3b5234c81c97304a33A78707430622c51935' } as const /** @@ -42,7 +42,7 @@ export const USDC_TOKEN_ADDRESSES: { [chainId: number]: Lowercase
} = { [NETWORK.polygon]: '0x2791bca1f2de4661ed88a30c99a7a9449aa84174', [NETWORK.optimism]: '0x7f5c764cbc14f9669b88837ca1490cca17c31607', [NETWORK.arbitrum]: '0xff970a61a04b1ca14834a43f5de4533ebddb5cc8', - [NETWORK.optimism_sepolia]: '0x0e13bf42f927575475894f2d5076a7ac77060ea0' + [NETWORK.optimism_sepolia]: '0x01ce79e045539f560afa57943db6cff3fb097c4b' } /** @@ -63,11 +63,11 @@ export const PRIZE_POOLS: { }[] = [ { chainId: NETWORK.optimism_sepolia, - address: '0x31547D3c38F2F8dC92421C54B173F3B27Ab26EbB', + address: '0x595806bc53dd4bE760EbbE63D78931A3601aA04b', options: { - prizeTokenAddress: '0xD5C2a983D320a881F21Dc68fd89f905Ff1517B2C', - drawManagerAddress: '0x1bEbF92C4502341785DDDe63d2f770954CA38e33', - twabControllerAddress: '0xB2549f4e7b919004b31925FD4271459273DE8A89', + prizeTokenAddress: '0x0845842Ad2DCE40b83EddECf9C67df2C75caB844', + drawManagerAddress: '0x5dF3eF8fbd4eD302f1425E0BB237C87458a4DFC7', + twabControllerAddress: '0xB919865C43a7C376a17a428D091E456DA71C068b', drawPeriodInSeconds: 7_200, drawAuctionDurationInSeconds: 2_400, tierShares: 100, @@ -102,9 +102,9 @@ export const STABLECOINS: Record = { '0xc40f949f8a4e094d1b49a23ea9241d289b7b2819': 'usd' // LUSD }, [NETWORK.optimism_sepolia]: { - '0x0e13bf42f927575475894f2d5076a7ac77060ea0': 'usd', // USDC - '0x8261cb9519dd1d80b5ce66b0887c6fceea8a64ee': 'usd', // DAI - '0x493c7081faab6e5b2d6b18d9311918580e88c6bf': 'usd' // GUSD + '0x01ce79e045539f560afa57943db6cff3fb097c4b': 'usd', // USDC + '0x3eb488d3419496742963437378c2130a2edcb87d': 'usd', // DAI + '0xf0f496dc0558e9744963292efff344725218b1f5': 'usd' // GUSD }, [NETWORK.avalanche]: { '0xa7d7079b0fead91f3e65f86e8915cb59c1a4c664': 'usd' // USDC.e @@ -147,35 +147,35 @@ export const WRAPPED_NATIVE_ASSETS: Record = { * TWAB rewards addresses */ export const TWAB_REWARDS_ADDRESSES: { [chainId: number]: Address } = { - [NETWORK.optimism_sepolia]: '0xC5c208DFAE3bA24132070E63aE964bA0D4A81a03' + [NETWORK.optimism_sepolia]: '0x644Ba78d965e276C9617F18AfD5357564B59a1Ae' } /** * Vault factory addresses */ export const VAULT_FACTORY_ADDRESSES: { [chainId: number]: Address } = { - [NETWORK.optimism_sepolia]: '0x65741e6C8fbCcD3d4BEC7E2179417236FbD33d3A' + [NETWORK.optimism_sepolia]: '0x86AD081EF9DC846b8612AD1a38CDc001F6bc4Af6' } /** * Liquidation pair factory addresses */ export const LIQUIDATION_PAIR_FACTORY_ADDRESSES: { [chainId: number]: Address } = { - [NETWORK.optimism_sepolia]: '0x0d2AD8f32E94605a9a7E797Ff494D27C691B16Dc' + [NETWORK.optimism_sepolia]: '0xf951D79AF0c2E4B2EA6B76318C6C2dAE5F9a1097' } /** * Default claimer addresses */ export const DEFAULT_CLAIMER_ADDRESSES: { [chainId: number]: Address } = { - [NETWORK.optimism_sepolia]: '0x189231eBe184a40A8AFb1659985C6D976729780D' + [NETWORK.optimism_sepolia]: '0x936b1256208D7f441871ba505F76fb7D3d55a2Bf' } /** * Liquidation router addresses */ export const LIQUIDATION_ROUTER_ADDRESSES: { [chainId: number]: Address } = { - [NETWORK.optimism_sepolia]: '0xB485D92896944D3f8Dd73A1a61371CDaDb1021f5' + [NETWORK.optimism_sepolia]: '0xf110Df037f964c1D4824BB7148eB80055e084108' } /** @@ -198,7 +198,7 @@ export const OP_GAS_ORACLE_ADDRESS = '0x420000000000000000000000000000000000000f */ export const SUBGRAPH_API_URLS = { [NETWORK.optimism_sepolia]: - 'https://api.studio.thegraph.com/query/63100/pt-v5-op-sepolia/version/latest' + 'https://api.studio.thegraph.com/query/63100/pt-v5-op-sepolia-hid/version/latest' } as const /** @@ -250,7 +250,7 @@ export const TOKEN_PRICE_REDIRECTS: { address: DOLPHIN_ADDRESS }, /* DAI */ - '0x8261cb9519dd1d80b5ce66b0887c6fceea8a64ee': { + '0x3eb488d3419496742963437378c2130a2edcb87d': { chainId: NETWORK.mainnet, address: '0x6b175474e89094c44da98b954eedeac495271d0f' }, @@ -260,17 +260,17 @@ export const TOKEN_PRICE_REDIRECTS: { address: USDC_TOKEN_ADDRESSES[NETWORK.mainnet] }, /* GUSD */ - '0x493c7081faab6e5b2d6b18d9311918580e88c6bf': { + '0xf0f496dc0558e9744963292efff344725218b1f5': { chainId: NETWORK.mainnet, address: '0x056fd409e1d7a124bd7017459dfea2f387b6d5cd' }, /* WBTC */ - '0x45bbc6b553d2afc4d3e376b22f70a67d9a26f819': { + '0xc21d6c8dd430cc97aaa58391625b82f4681ae473': { chainId: NETWORK.mainnet, address: '0x2260fac5e5542a773aa44fbcfedf7c193bc2c599' }, /* WETH */ - '0xd5c2a983d320a881f21dc68fd89f905ff1517b2c': { + '0x0845842ad2dce40b83eddecf9c67df2c75cab844': { chainId: NETWORK.mainnet, address: WRAPPED_NATIVE_ASSETS[NETWORK.mainnet] as Address }, diff --git a/shared/utilities/utils/events.ts b/shared/utilities/utils/events.ts index 624a19b1..ec2799ee 100644 --- a/shared/utilities/utils/events.ts +++ b/shared/utilities/utils/events.ts @@ -81,9 +81,10 @@ export const getDrawStartedEvents = async ( inputs: [ { indexed: true, internalType: 'address', name: 'sender', type: 'address' }, { indexed: true, internalType: 'address', name: 'recipient', type: 'address' }, - { indexed: false, internalType: 'uint24', name: 'drawId', type: 'uint24' }, - { indexed: false, internalType: 'uint32', name: 'rngRequestId', type: 'uint32' }, - { indexed: false, internalType: 'uint48', name: 'elapsedTime', type: 'uint48' } + { indexed: true, internalType: 'uint24', name: 'drawId', type: 'uint24' }, + { indexed: false, internalType: 'uint48', name: 'elapsedTime', type: 'uint48' }, + { indexed: false, internalType: 'uint256', name: 'reward', type: 'uint256' }, + { indexed: false, internalType: 'uint32', name: 'rngRequestId', type: 'uint32' } ], name: 'DrawStarted', type: 'event' @@ -143,12 +144,11 @@ export const getDrawFinishedEvents = async ( address: drawManagerAddress, event: { inputs: [ + { indexed: true, internalType: 'address', name: 'sender', type: 'address' }, + { indexed: true, internalType: 'address', name: 'recipient', type: 'address' }, { indexed: true, internalType: 'uint24', name: 'drawId', type: 'uint24' }, - { indexed: false, internalType: 'uint256', name: 'elapsedTime', type: 'uint256' }, - { indexed: true, internalType: 'address', name: 'startRecipient', type: 'address' }, - { indexed: false, internalType: 'uint256', name: 'startReward', type: 'uint256' }, - { indexed: true, internalType: 'address', name: 'finishRecipient', type: 'address' }, - { indexed: false, internalType: 'uint256', name: 'finishReward', type: 'uint256' }, + { indexed: false, internalType: 'uint48', name: 'elapsedTime', type: 'uint48' }, + { indexed: false, internalType: 'uint256', name: 'reward', type: 'uint256' }, { indexed: false, internalType: 'uint256', name: 'remainingReserve', type: 'uint256' } ], name: 'DrawFinished', From 14fe1b2508ae84d1de90e3943a4dd6b5677b9790 Mon Sep 17 00:00:00 2001 From: Ncookiez Date: Tue, 2 Apr 2024 15:21:32 -0400 Subject: [PATCH 093/161] added line through start reward if draw was never finished --- .../src/components/Draws/DrawRngReward.tsx | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/apps/analytics/src/components/Draws/DrawRngReward.tsx b/apps/analytics/src/components/Draws/DrawRngReward.tsx index ea6dcae0..b4befc9d 100644 --- a/apps/analytics/src/components/Draws/DrawRngReward.tsx +++ b/apps/analytics/src/components/Draws/DrawRngReward.tsx @@ -3,6 +3,7 @@ import { usePrizeTokenData } from '@generationsoftware/hyperstructure-react-hook import { ExternalLink, Spinner } from '@shared/ui' import { formatBigIntForDisplay, getBlockExplorerUrl, shorten } from '@shared/utilities' import classNames from 'classnames' +import { useCurrentDrawAwardReward } from '@hooks/useCurrentDrawAwardReward' import { useCurrentRngAuctionReward } from '@hooks/useCurrentRngAuctionReward' import { useDrawStatus } from '@hooks/useDrawStatus' import { useRngTxs } from '@hooks/useRngTxs' @@ -20,13 +21,17 @@ export const DrawRngReward = (props: DrawRngRewardProps) => { const { status, isSkipped } = useDrawStatus(prizePool, drawId) const { data: allRngTxs, isFetched: isFetchedAllRngTxs } = useRngTxs(prizePool) - const drawStartTx = allRngTxs?.find((txs) => txs.drawStart.drawId === drawId)?.drawStart + const rngTxs = allRngTxs?.find((txs) => txs.drawStart.drawId === drawId) + const drawStartTx = rngTxs?.drawStart + const drawFinishTx = rngTxs?.drawFinish const { data: prizeToken } = usePrizeTokenData(prizePool) const { data: currentRngAuctionReward } = useCurrentRngAuctionReward(prizePool) + const { data: currentDrawAwardReward } = useCurrentDrawAwardReward(prizePool) const isRngCompletionPossible = status === 'closed' && !!currentRngAuctionReward && !isSkipped + const isAwardPossible = status === 'closed' && !!currentDrawAwardReward && !isSkipped return (
@@ -37,7 +42,11 @@ export const DrawRngReward = (props: DrawRngRewardProps) => { {!!drawStartTx ? ( <> - + {formatBigIntForDisplay(drawStartTx.reward, prizeToken.decimals, { maximumFractionDigits: 5 })} From c953133c60d2a19d3e8a9131f9b340ba6090a588 Mon Sep 17 00:00:00 2001 From: Ncookiez Date: Tue, 2 Apr 2024 15:21:52 -0400 Subject: [PATCH 094/161] using `totalPreciseAssets` with fallback --- .../hyperstructure-client-js/src/Vault.ts | 24 +++++++++++++++---- shared/utilities/utils/vaults.ts | 6 ++++- 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/packages/hyperstructure-client-js/src/Vault.ts b/packages/hyperstructure-client-js/src/Vault.ts index c8645377..74c7bd8e 100644 --- a/packages/hyperstructure-client-js/src/Vault.ts +++ b/packages/hyperstructure-client-js/src/Vault.ts @@ -291,11 +291,25 @@ export class Vault { const tokenData = await this.getTokenData() - const totalAssets = await this.publicClient.readContract({ - address: this.address, - abi: vaultABI, - functionName: 'totalAssets' - }) + const getTotalAssets = () => + this.publicClient + .readContract({ + address: this.address, + abi: vaultABI, + functionName: 'totalPreciseAssets' + }) + .catch(() => { + console.warn( + `${source} | Could not query "totalPreciseAssets" for ${this.address} on network ${this.chainId}, falling back to "totalAssets"` + ) + return this.publicClient.readContract({ + address: this.address, + abi: vaultABI, + functionName: 'totalAssets' + }) + }) + + const totalAssets = await getTotalAssets() return { ...tokenData, amount: totalAssets } } diff --git a/shared/utilities/utils/vaults.ts b/shared/utilities/utils/vaults.ts index 64777d3b..abd38606 100644 --- a/shared/utilities/utils/vaults.ts +++ b/shared/utilities/utils/vaults.ts @@ -194,12 +194,16 @@ export const getVaultBalances = async ( if (filteredVaults.length > 0) { const vaultAddresses = filteredVaults.map((vault) => vault.address) const multicallResults = await getMulticallResults(publicClient, vaultAddresses, vaultABI, [ + { functionName: 'totalPreciseAssets' }, { functionName: 'totalAssets' } ]) filteredVaults.forEach((vault) => { const vaultId = getVaultId(vault) - vaultBalances[vaultId] = multicallResults[vault.address]?.['totalAssets'] ?? 0n + vaultBalances[vaultId] = + multicallResults[vault.address]?.['totalPreciseAssets'] ?? + multicallResults[vault.address]?.['totalAssets'] ?? + 0n }) } From 89254d9ba07c213a1af5b33a137bd8d7abbb92bb Mon Sep 17 00:00:00 2001 From: Ncookiez Date: Tue, 2 Apr 2024 16:08:04 -0400 Subject: [PATCH 095/161] using `minAssets` or `maxShares` for safer redeems/withdrawals --- .../hyperstructure-client-js/src/Vault.ts | 58 ++++++++++++++----- .../transactions/useSendRedeemTransaction.ts | 11 +++- .../useSendWithdrawTransaction.ts | 11 +++- .../Modals/WithdrawModal/WithdrawTxButton.tsx | 9 ++- 4 files changed, 66 insertions(+), 23 deletions(-) diff --git a/packages/hyperstructure-client-js/src/Vault.ts b/packages/hyperstructure-client-js/src/Vault.ts index 74c7bd8e..c04f5a0b 100644 --- a/packages/hyperstructure-client-js/src/Vault.ts +++ b/packages/hyperstructure-client-js/src/Vault.ts @@ -547,10 +547,10 @@ export class Vault { /** * Submits a transaction to withdraw from the vault * @param amount an unformatted token amount (w/ decimals) - * @param overrides optional overrides for this transaction + * @param options optional args or tx overrides * @returns */ - async withdraw(amount: bigint, overrides?: TxOverrides) { + async withdraw(amount: bigint, options?: { maxShares?: bigint; overrides?: TxOverrides }) { const source = 'Vault [withdraw]' if (!this.walletClient?.account) { @@ -562,9 +562,16 @@ export class Vault { address: this.address, abi: vaultABI, functionName: 'withdraw', - args: [amount, this.walletClient.account.address, this.walletClient.account.address], + args: !!options?.maxShares + ? [ + amount, + this.walletClient.account.address, + this.walletClient.account.address, + options.maxShares + ] + : [amount, this.walletClient.account.address, this.walletClient.account.address], chain: this.walletClient.chain, - ...overrides + ...options?.overrides }) const txHash = await this.walletClient.writeContract(request) @@ -576,10 +583,14 @@ export class Vault { * Submits a transaction to withdraw from the vault and send underlying assets to another address * @param amount an unformatted token amount (w/ decimals) * @param receiver the address to send assets to - * @param overrides optional overrides for this transaction + * @param options optional args or tx overrides * @returns */ - async withdrawTo(amount: bigint, receiver: Address, overrides?: TxOverrides) { + async withdrawTo( + amount: bigint, + receiver: Address, + options?: { maxShares?: bigint; overrides?: TxOverrides } + ) { const source = 'Vault [withdrawTo]' if (!this.walletClient?.account) { @@ -593,9 +604,11 @@ export class Vault { address: this.address, abi: vaultABI, functionName: 'withdraw', - args: [amount, receiver, this.walletClient.account.address], + args: !!options?.maxShares + ? [amount, receiver, this.walletClient.account.address, options.maxShares] + : [amount, receiver, this.walletClient.account.address], chain: this.walletClient.chain, - ...overrides + ...options?.overrides }) const txHash = await this.walletClient.writeContract(request) @@ -606,10 +619,10 @@ export class Vault { /** * Submits a transaction to redeem shares from the vault * @param amount an unformatted share amount (w/ decimals) - * @param overrides optional overrides for this transaction + * @param options optional args or tx overrides * @returns */ - async redeem(amount: bigint, overrides?: TxOverrides) { + async redeem(amount: bigint, options?: { minAssets?: bigint; overrides?: TxOverrides }) { const source = 'Vault [redeem]' if (!this.walletClient?.account) { @@ -621,9 +634,16 @@ export class Vault { address: this.address, abi: vaultABI, functionName: 'redeem', - args: [amount, this.walletClient.account.address, this.walletClient.account.address], + args: !!options?.minAssets + ? [ + amount, + this.walletClient.account.address, + this.walletClient.account.address, + options.minAssets + ] + : [amount, this.walletClient.account.address, this.walletClient.account.address], chain: this.walletClient.chain, - ...overrides + ...options?.overrides }) const txHash = await this.walletClient.writeContract(request) @@ -635,10 +655,14 @@ export class Vault { * Submits a transaction to redeem shares from the vault and send underlying assets to another address * @param amount an unformatted share amount (w/ decimals) * @param receiver the address to send assets to - * @param overrides optional overrides for this transaction + * @param options optional args or tx overrides * @returns */ - async redeemTo(amount: bigint, receiver: Address, overrides?: TxOverrides) { + async redeemTo( + amount: bigint, + receiver: Address, + options?: { minAssets?: bigint; overrides?: TxOverrides } + ) { const source = 'Vault [redeemTo]' if (!this.walletClient?.account) { @@ -652,9 +676,11 @@ export class Vault { address: this.address, abi: vaultABI, functionName: 'redeem', - args: [amount, receiver, this.walletClient.account.address], + args: !!options?.minAssets + ? [amount, receiver, this.walletClient.account.address, options.minAssets] + : [amount, receiver, this.walletClient.account.address], chain: this.walletClient.chain, - ...overrides + ...options?.overrides }) const txHash = await this.walletClient.writeContract(request) diff --git a/packages/hyperstructure-react-hooks/src/transactions/useSendRedeemTransaction.ts b/packages/hyperstructure-react-hooks/src/transactions/useSendRedeemTransaction.ts index 73f2ecd1..faed31c5 100644 --- a/packages/hyperstructure-react-hooks/src/transactions/useSendRedeemTransaction.ts +++ b/packages/hyperstructure-react-hooks/src/transactions/useSendRedeemTransaction.ts @@ -14,13 +14,14 @@ import { useGasAmountEstimate, useUserVaultShareBalance } from '..' * Prepares and submits a `redeem` transaction to a vault * @param amount the amount of shares to redeem * @param vault the vault to redeem from - * @param options optional callbacks + * @param options optional args or callbacks * @returns */ export const useSendRedeemTransaction = ( amount: bigint, vault: Vault, options?: { + minAssets?: bigint onSend?: (txHash: `0x${string}`) => void onSuccess?: (txReceipt: TransactionReceipt) => void onError?: () => void @@ -55,7 +56,9 @@ export const useSendRedeemTransaction = ( address: vault?.address, abi: vaultABI, functionName: 'redeem', - args: [amount, userAddress as Address, userAddress as Address], + args: !!options?.minAssets + ? [amount, userAddress as Address, userAddress as Address, options.minAssets] + : [amount, userAddress as Address, userAddress as Address], account: userAddress as Address }, { enabled } @@ -66,7 +69,9 @@ export const useSendRedeemTransaction = ( address: vault?.address, abi: vaultABI, functionName: 'redeem', - args: [amount, userAddress as Address, userAddress as Address], + args: !!options?.minAssets + ? [amount, userAddress as Address, userAddress as Address, options.minAssets] + : [amount, userAddress as Address, userAddress as Address], gas: !!gasEstimate ? calculatePercentageOfBigInt(gasEstimate, 1.2) : undefined, query: { enabled } }) diff --git a/packages/hyperstructure-react-hooks/src/transactions/useSendWithdrawTransaction.ts b/packages/hyperstructure-react-hooks/src/transactions/useSendWithdrawTransaction.ts index 32802207..3a264d25 100644 --- a/packages/hyperstructure-react-hooks/src/transactions/useSendWithdrawTransaction.ts +++ b/packages/hyperstructure-react-hooks/src/transactions/useSendWithdrawTransaction.ts @@ -14,13 +14,14 @@ import { useGasAmountEstimate, useUserVaultTokenBalance } from '..' * Prepares and submits a `withdraw` transaction to a vault * @param amount the amount of tokens to withdraw * @param vault the vault to withdraw from - * @param options optional callbacks + * @param options optional args or callbacks * @returns */ export const useSendWithdrawTransaction = ( amount: bigint, vault: Vault, options?: { + maxShares?: bigint onSend?: (txHash: `0x${string}`) => void onSuccess?: (txReceipt: TransactionReceipt) => void onError?: () => void @@ -55,7 +56,9 @@ export const useSendWithdrawTransaction = ( address: vault?.address, abi: vaultABI, functionName: 'withdraw', - args: [amount, userAddress as Address, userAddress as Address], + args: !!options?.maxShares + ? [amount, userAddress as Address, userAddress as Address, options.maxShares] + : [amount, userAddress as Address, userAddress as Address], account: userAddress as Address }, { enabled } @@ -66,7 +69,9 @@ export const useSendWithdrawTransaction = ( address: vault?.address, abi: vaultABI, functionName: 'withdraw', - args: [amount, userAddress as Address, userAddress as Address], + args: !!options?.maxShares + ? [amount, userAddress as Address, userAddress as Address, options.maxShares] + : [amount, userAddress as Address, userAddress as Address], gas: !!gasEstimate ? calculatePercentageOfBigInt(gasEstimate, 1.2) : undefined, query: { enabled } }) diff --git a/shared/react-components/components/Modals/WithdrawModal/WithdrawTxButton.tsx b/shared/react-components/components/Modals/WithdrawModal/WithdrawTxButton.tsx index 81048658..d5f6082d 100644 --- a/shared/react-components/components/Modals/WithdrawModal/WithdrawTxButton.tsx +++ b/shared/react-components/components/Modals/WithdrawModal/WithdrawTxButton.tsx @@ -1,4 +1,4 @@ -import { Vault } from '@generationsoftware/hyperstructure-client-js' +import { getAssetsFromShares, Vault } from '@generationsoftware/hyperstructure-client-js' import { useSendRedeemTransaction, useTokenBalance, @@ -94,6 +94,12 @@ export const WithdrawTxButton = (props: WithdrawTxButtonProps) => { ? parseUnits(formShareAmount, decimals as number) : 0n + // TODO: this should accept user input in case of lossy vaults + const expectedAssetAmount = + !!withdrawAmount && !!vaultExchangeRate + ? getAssetsFromShares(withdrawAmount, vaultExchangeRate, decimals as number) + : 0n + const { isWaiting: isWaitingWithdrawal, isConfirming: isConfirmingWithdrawal, @@ -101,6 +107,7 @@ export const WithdrawTxButton = (props: WithdrawTxButtonProps) => { txHash: withdrawTxHash, sendRedeemTransaction } = useSendRedeemTransaction(withdrawAmount, vault, { + minAssets: expectedAssetAmount, onSend: () => { setModalView('waiting') }, From fd5ce5bff145be1be1ddbbfa7d921d4f033928ad Mon Sep 17 00:00:00 2001 From: Ncookiez Date: Tue, 2 Apr 2024 17:50:17 -0400 Subject: [PATCH 096/161] fixed line-through logic for draw rng rewards --- apps/analytics/src/components/Draws/DrawRngReward.tsx | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/apps/analytics/src/components/Draws/DrawRngReward.tsx b/apps/analytics/src/components/Draws/DrawRngReward.tsx index b4befc9d..e1b73e00 100644 --- a/apps/analytics/src/components/Draws/DrawRngReward.tsx +++ b/apps/analytics/src/components/Draws/DrawRngReward.tsx @@ -3,7 +3,6 @@ import { usePrizeTokenData } from '@generationsoftware/hyperstructure-react-hook import { ExternalLink, Spinner } from '@shared/ui' import { formatBigIntForDisplay, getBlockExplorerUrl, shorten } from '@shared/utilities' import classNames from 'classnames' -import { useCurrentDrawAwardReward } from '@hooks/useCurrentDrawAwardReward' import { useCurrentRngAuctionReward } from '@hooks/useCurrentRngAuctionReward' import { useDrawStatus } from '@hooks/useDrawStatus' import { useRngTxs } from '@hooks/useRngTxs' @@ -21,17 +20,13 @@ export const DrawRngReward = (props: DrawRngRewardProps) => { const { status, isSkipped } = useDrawStatus(prizePool, drawId) const { data: allRngTxs, isFetched: isFetchedAllRngTxs } = useRngTxs(prizePool) - const rngTxs = allRngTxs?.find((txs) => txs.drawStart.drawId === drawId) - const drawStartTx = rngTxs?.drawStart - const drawFinishTx = rngTxs?.drawFinish + const drawStartTx = allRngTxs?.find((txs) => txs.drawStart.drawId === drawId)?.drawStart const { data: prizeToken } = usePrizeTokenData(prizePool) const { data: currentRngAuctionReward } = useCurrentRngAuctionReward(prizePool) - const { data: currentDrawAwardReward } = useCurrentDrawAwardReward(prizePool) const isRngCompletionPossible = status === 'closed' && !!currentRngAuctionReward && !isSkipped - const isAwardPossible = status === 'closed' && !!currentDrawAwardReward && !isSkipped return (
@@ -43,9 +38,7 @@ export const DrawRngReward = (props: DrawRngRewardProps) => { {!!drawStartTx ? ( <> {formatBigIntForDisplay(drawStartTx.reward, prizeToken.decimals, { maximumFractionDigits: 5 From 5d6c6f34679b62e857c2c0cf84baa067ac878812 Mon Sep 17 00:00:00 2001 From: Ncookiez Date: Wed, 3 Apr 2024 14:57:17 -0400 Subject: [PATCH 097/161] added testnet disclaimer + minor css fix --- apps/vault-factory/src/components/DeployedVaultsTable.tsx | 2 +- apps/vault-factory/src/components/forms/NetworkForm.tsx | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/apps/vault-factory/src/components/DeployedVaultsTable.tsx b/apps/vault-factory/src/components/DeployedVaultsTable.tsx index b5c71ba4..8b40c283 100644 --- a/apps/vault-factory/src/components/DeployedVaultsTable.tsx +++ b/apps/vault-factory/src/components/DeployedVaultsTable.tsx @@ -80,7 +80,7 @@ export const DeployedVaultsTable = (props: DeployedVaultsTableProps) => { return (
diff --git a/apps/vault-factory/src/components/forms/NetworkForm.tsx b/apps/vault-factory/src/components/forms/NetworkForm.tsx index c6afc64d..ed0cff5c 100644 --- a/apps/vault-factory/src/components/forms/NetworkForm.tsx +++ b/apps/vault-factory/src/components/forms/NetworkForm.tsx @@ -41,6 +41,13 @@ export const NetworkForm = (props: NetworkFormProps) => { onSubmit={formMethods.handleSubmit(onSubmit)} className={classNames('flex flex-col grow gap-12 items-center', className)} > + {/* TODO: remove on full deployment */} +
+ + In anticipation of a new prize pool deployment, this app only supports the most recent + testnet + +
Select Network
From 4b7784c5b352195b3a115fe823e7b4bd7d3884af Mon Sep 17 00:00:00 2001 From: Ncookiez Date: Wed, 3 Apr 2024 15:24:00 -0400 Subject: [PATCH 098/161] updated pool and usdc token addresses --- shared/utilities/constants.ts | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/shared/utilities/constants.ts b/shared/utilities/constants.ts index 39a78bcd..7e89d27f 100644 --- a/shared/utilities/constants.ts +++ b/shared/utilities/constants.ts @@ -31,17 +31,20 @@ export const POOL_TOKEN_ADDRESSES = { [NETWORK.mainnet]: '0x0cEC1A9154Ff802e7934Fc916Ed7Ca50bDE6844e', [NETWORK.polygon]: '0x25788a1a171ec66Da6502f9975a15B609fF54CF6', [NETWORK.optimism]: '0x395ae52bb17aef68c2888d941736a71dc6d4e125', + [NETWORK.arbitrum]: '0xCF934E2402A5e072928a39a956964eb8F2B5B79C', + [NETWORK.base]: '0xd652C5425aea2Afd5fb142e120FeCf79e18fafc3', [NETWORK.optimism_sepolia]: '0xBC8c3b5234c81c97304a33A78707430622c51935' -} as const +} as const satisfies { [chainId: number]: Address } /** * USDC token addresses */ export const USDC_TOKEN_ADDRESSES: { [chainId: number]: Lowercase
} = { [NETWORK.mainnet]: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48', - [NETWORK.polygon]: '0x2791bca1f2de4661ed88a30c99a7a9449aa84174', - [NETWORK.optimism]: '0x7f5c764cbc14f9669b88837ca1490cca17c31607', - [NETWORK.arbitrum]: '0xff970a61a04b1ca14834a43f5de4533ebddb5cc8', + [NETWORK.polygon]: '0x3c499c542cef5e3811e1192ce70d8cc03d5c3359', + [NETWORK.optimism]: '0x0b2c639c533813f4aa9d7837caf62653d097ff85', + [NETWORK.arbitrum]: '0xaf88d065e77c8cc2239327c5edb3a432268e5831', + [NETWORK.base]: '0x833589fcd6edb6e08f4c7c32d4f71b54bda02913', [NETWORK.optimism_sepolia]: '0x01ce79e045539f560afa57943db6cff3fb097c4b' } @@ -199,7 +202,7 @@ export const OP_GAS_ORACLE_ADDRESS = '0x420000000000000000000000000000000000000f export const SUBGRAPH_API_URLS = { [NETWORK.optimism_sepolia]: 'https://api.studio.thegraph.com/query/63100/pt-v5-op-sepolia-hid/version/latest' -} as const +} as const satisfies { [chainId: number]: `https://${string}` } /** * Token Prices API URL From d7aadaddbbee9f6545f650df0b6941e3d3f5a89a Mon Sep 17 00:00:00 2001 From: Ncookiez Date: Wed, 3 Apr 2024 15:59:45 -0400 Subject: [PATCH 099/161] added `.prettierignore` --- .prettierignore | 1 + 1 file changed, 1 insertion(+) create mode 100644 .prettierignore diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 00000000..eeeb7be5 --- /dev/null +++ b/.prettierignore @@ -0,0 +1 @@ +pnpm-lock.yaml \ No newline at end of file From f7a16bfafc45556c89772148ae7c5c1bd1b9c7a3 Mon Sep 17 00:00:00 2001 From: Ncookiez Date: Wed, 3 Apr 2024 16:00:17 -0400 Subject: [PATCH 100/161] moved constants from `shared/ui` to `shared/utilities` --- apps/analytics/src/pages/_document.tsx | 2 +- .../components/Account/AccountWinnings.tsx | 3 +- apps/app/src/components/AppContainer.tsx | 3 +- apps/app/src/components/Layout.tsx | 4 +- .../components/Vault/VaultPageExtraInfo.tsx | 4 +- .../src/components/Vault/VaultsDisclaimer.tsx | 3 +- apps/app/src/hooks/useFathom.ts | 2 +- apps/app/src/pages/_document.tsx | 2 +- apps/app/src/pages/prizes.tsx | 4 +- apps/app/src/vaultLists/default.ts | 3 +- .../src/components/Header.tsx | 2 +- .../src/components/Layout.tsx | 3 +- apps/flash-liquidator/src/pages/_document.tsx | 2 +- apps/incentives/src/pages/_document.tsx | 2 +- apps/incentives/src/pages/airdrops.tsx | 2 +- apps/incentives/src/pages/chat-bots.tsx | 2 +- apps/incentives/src/pages/group-savings.tsx | 2 +- apps/incentives/src/pages/index.tsx | 3 +- .../src/pages/no-loss-marketing.tsx | 2 +- apps/incentives/src/pages/on-ramps.tsx | 2 +- apps/incentives/src/pages/yield-sources.tsx | 2 +- apps/incentives/src/pages/yield-split.tsx | 2 +- apps/landing-page/src/components/Footer.tsx | 3 +- .../src/components/Home/DocsSection.tsx | 2 +- .../src/components/Home/FaqSection.tsx | 3 +- .../src/components/Home/HomeHeader.tsx | 3 +- apps/landing-page/src/components/Navbar.tsx | 3 +- .../src/components/Tools/DocsSection.tsx | 2 +- .../components/Tools/StartBuildingSection.tsx | 2 +- .../src/components/Tools/ToolsHeader.tsx | 3 +- apps/landing-page/src/pages/_document.tsx | 2 +- apps/migrations/src/components/Layout.tsx | 3 +- apps/migrations/src/hooks/useV5Tokens.ts | 3 +- apps/migrations/src/pages/_document.tsx | 2 +- .../src/components/DeployPromotionView.tsx | 2 +- .../src/components/DeployedPromotionCard.tsx | 4 +- .../components/DeployedPromotionsTable.tsx | 4 +- .../rewards-builder/src/components/Layout.tsx | 3 +- apps/rewards-builder/src/pages/_document.tsx | 2 +- apps/swaps/src/components/Faq.tsx | 3 +- apps/swaps/src/components/GrandPrize.tsx | 4 +- apps/swaps/src/components/Navbar.tsx | 3 +- apps/swaps/src/components/RecentWinners.tsx | 10 ++- apps/swaps/src/components/VaultCard.tsx | 3 +- apps/swaps/src/pages/_document.tsx | 2 +- .../src/components/CreateVaultStepInfo.tsx | 2 +- .../src/components/DeployedVaultCard.tsx | 4 +- .../src/components/DeployedVaultsTable.tsx | 4 +- .../src/components/HomePageContent.tsx | 3 +- apps/vault-factory/src/components/Layout.tsx | 3 +- .../src/components/forms/YieldVaultInput.tsx | 4 +- apps/vault-factory/src/pages/_document.tsx | 2 +- .../src/components/Layout.tsx | 2 +- .../vaultlist-creator/src/pages/_document.tsx | 2 +- .../components/Buttons/SocialShareButton.tsx | 3 +- .../components/Modals/DepositModal/index.tsx | 4 +- .../Modals/SettingsModal/Views/MenuView.tsx | 3 +- .../SettingsModal/Views/VaultListView.tsx | 4 +- .../Tooltips/DelegationDescriptionTooltip.tsx | 3 +- .../components/Tooltips/PrizeYieldTooltip.tsx | 3 +- shared/ui/components/Footer.tsx | 2 +- shared/ui/constants.ts | 72 ------------------ shared/ui/index.tsx | 5 -- shared/utilities/constants.ts | 73 +++++++++++++++++++ 64 files changed, 171 insertions(+), 154 deletions(-) delete mode 100644 shared/ui/constants.ts diff --git a/apps/analytics/src/pages/_document.tsx b/apps/analytics/src/pages/_document.tsx index 68e0d60f..ecb1f68f 100644 --- a/apps/analytics/src/pages/_document.tsx +++ b/apps/analytics/src/pages/_document.tsx @@ -1,4 +1,4 @@ -import { DOMAINS } from '@shared/ui' +import { DOMAINS } from '@shared/utilities' import Document, { DocumentContext, DocumentInitialProps, diff --git a/apps/app/src/components/Account/AccountWinnings.tsx b/apps/app/src/components/Account/AccountWinnings.tsx index 3d35be61..2ed66b52 100644 --- a/apps/app/src/components/Account/AccountWinnings.tsx +++ b/apps/app/src/components/Account/AccountWinnings.tsx @@ -3,7 +3,8 @@ import { useLastCheckedPrizesTimestamps } from '@generationsoftware/hyperstructure-react-hooks' import { Win } from '@shared/types' -import { ExternalLink, LINKS } from '@shared/ui' +import { ExternalLink } from '@shared/ui' +import { LINKS } from '@shared/utilities' import classNames from 'classnames' import { useTranslations } from 'next-intl' import { useMemo } from 'react' diff --git a/apps/app/src/components/AppContainer.tsx b/apps/app/src/components/AppContainer.tsx index b37800bd..e39ff404 100644 --- a/apps/app/src/components/AppContainer.tsx +++ b/apps/app/src/components/AppContainer.tsx @@ -1,6 +1,5 @@ import { useSelectedLanguage } from '@shared/generic-react-hooks' -import { Flowbite } from '@shared/ui' -import { Toaster } from '@shared/ui' +import { Flowbite, Toaster } from '@shared/ui' import { NextIntlProvider } from 'next-intl' import { AppProps } from 'next/app' import { useRouter } from 'next/router' diff --git a/apps/app/src/components/Layout.tsx b/apps/app/src/components/Layout.tsx index 50c6e16b..96d8c757 100644 --- a/apps/app/src/components/Layout.tsx +++ b/apps/app/src/components/Layout.tsx @@ -21,8 +21,8 @@ import { SettingsModal, WithdrawModal } from '@shared/react-components' -import { Footer, FooterItem, LINKS, Navbar, SocialIcon, toast } from '@shared/ui' -import { getDiscordInvite, NETWORK } from '@shared/utilities' +import { Footer, FooterItem, Navbar, SocialIcon, toast } from '@shared/ui' +import { getDiscordInvite, LINKS, NETWORK } from '@shared/utilities' import classNames from 'classnames' import * as fathom from 'fathom-client' import { useAtomValue } from 'jotai' diff --git a/apps/app/src/components/Vault/VaultPageExtraInfo.tsx b/apps/app/src/components/Vault/VaultPageExtraInfo.tsx index deb3e97a..445f4823 100644 --- a/apps/app/src/components/Vault/VaultPageExtraInfo.tsx +++ b/apps/app/src/components/Vault/VaultPageExtraInfo.tsx @@ -5,8 +5,8 @@ import { useVaultYieldSource } from '@generationsoftware/hyperstructure-react-hooks' import { AlertIcon } from '@shared/react-components' -import { Button, ExternalLink, LINKS } from '@shared/ui' -import { getBlockExplorerUrl, getVaultId } from '@shared/utilities' +import { Button, ExternalLink } from '@shared/ui' +import { getBlockExplorerUrl, getVaultId, LINKS } from '@shared/utilities' import classNames from 'classnames' import { useTranslations } from 'next-intl' import { useMemo } from 'react' diff --git a/apps/app/src/components/Vault/VaultsDisclaimer.tsx b/apps/app/src/components/Vault/VaultsDisclaimer.tsx index 5fe011b8..a60c7fdf 100644 --- a/apps/app/src/components/Vault/VaultsDisclaimer.tsx +++ b/apps/app/src/components/Vault/VaultsDisclaimer.tsx @@ -1,7 +1,8 @@ import { XMarkIcon } from '@heroicons/react/24/solid' import { useIsDismissed } from '@shared/generic-react-hooks' import { AlertIcon } from '@shared/react-components' -import { Button, ExternalLink, LINKS } from '@shared/ui' +import { Button, ExternalLink } from '@shared/ui' +import { LINKS } from '@shared/utilities' import classNames from 'classnames' import { useTranslations } from 'next-intl' diff --git a/apps/app/src/hooks/useFathom.ts b/apps/app/src/hooks/useFathom.ts index 359410af..b1b447e0 100644 --- a/apps/app/src/hooks/useFathom.ts +++ b/apps/app/src/hooks/useFathom.ts @@ -1,4 +1,4 @@ -import { DOMAINS } from '@shared/ui' +import { DOMAINS } from '@shared/utilities' import * as fathom from 'fathom-client' import { useRouter } from 'next/router' import { useEffect } from 'react' diff --git a/apps/app/src/pages/_document.tsx b/apps/app/src/pages/_document.tsx index 1b2b8477..01ea52d1 100644 --- a/apps/app/src/pages/_document.tsx +++ b/apps/app/src/pages/_document.tsx @@ -1,4 +1,4 @@ -import { DOMAINS } from '@shared/ui' +import { DOMAINS } from '@shared/utilities' import Document, { DocumentContext, DocumentInitialProps, diff --git a/apps/app/src/pages/prizes.tsx b/apps/app/src/pages/prizes.tsx index 191fdb95..a86d334d 100644 --- a/apps/app/src/pages/prizes.tsx +++ b/apps/app/src/pages/prizes.tsx @@ -1,5 +1,5 @@ -import { ExternalLink, LINKS } from '@shared/ui' -import { SECONDS_PER_DAY } from '@shared/utilities' +import { ExternalLink } from '@shared/ui' +import { LINKS, SECONDS_PER_DAY } from '@shared/utilities' import { GetStaticProps } from 'next' import { useTranslations } from 'next-intl' import Image from 'next/image' diff --git a/apps/app/src/vaultLists/default.ts b/apps/app/src/vaultLists/default.ts index 86fbf1e3..eef7ee12 100644 --- a/apps/app/src/vaultLists/default.ts +++ b/apps/app/src/vaultLists/default.ts @@ -1,6 +1,5 @@ import { VaultList } from '@shared/types' -import { LINKS } from '@shared/ui' -import { NETWORK } from '@shared/utilities' +import { LINKS, NETWORK } from '@shared/utilities' import { testnetVaults } from './testnet' const defaultVaultList: VaultList = { diff --git a/apps/flash-liquidator/src/components/Header.tsx b/apps/flash-liquidator/src/components/Header.tsx index 927d4bbb..1805ea3e 100644 --- a/apps/flash-liquidator/src/components/Header.tsx +++ b/apps/flash-liquidator/src/components/Header.tsx @@ -1,4 +1,4 @@ -import { LINKS } from '@shared/ui' +import { LINKS } from '@shared/utilities' import classNames from 'classnames' import Link from 'next/link' diff --git a/apps/flash-liquidator/src/components/Layout.tsx b/apps/flash-liquidator/src/components/Layout.tsx index 199cfe10..c4255aa9 100644 --- a/apps/flash-liquidator/src/components/Layout.tsx +++ b/apps/flash-liquidator/src/components/Layout.tsx @@ -1,6 +1,7 @@ import { ConnectButton } from '@rainbow-me/rainbowkit' import { useScreenSize } from '@shared/generic-react-hooks' -import { LINKS, Toaster } from '@shared/ui' +import { Toaster } from '@shared/ui' +import { LINKS } from '@shared/utilities' import classNames from 'classnames' import Head from 'next/head' import Image from 'next/image' diff --git a/apps/flash-liquidator/src/pages/_document.tsx b/apps/flash-liquidator/src/pages/_document.tsx index 726fe2c9..5f3e3507 100644 --- a/apps/flash-liquidator/src/pages/_document.tsx +++ b/apps/flash-liquidator/src/pages/_document.tsx @@ -1,4 +1,4 @@ -import { DOMAINS } from '@shared/ui' +import { DOMAINS } from '@shared/utilities' import Document, { DocumentContext, DocumentInitialProps, diff --git a/apps/incentives/src/pages/_document.tsx b/apps/incentives/src/pages/_document.tsx index ac0411ca..a6da438d 100644 --- a/apps/incentives/src/pages/_document.tsx +++ b/apps/incentives/src/pages/_document.tsx @@ -1,4 +1,4 @@ -import { DOMAINS } from '@shared/ui' +import { DOMAINS } from '@shared/utilities' import Document, { DocumentContext, DocumentInitialProps, diff --git a/apps/incentives/src/pages/airdrops.tsx b/apps/incentives/src/pages/airdrops.tsx index b0171e5f..39025847 100644 --- a/apps/incentives/src/pages/airdrops.tsx +++ b/apps/incentives/src/pages/airdrops.tsx @@ -1,4 +1,4 @@ -import { LINKS } from '@shared/ui' +import { LINKS } from '@shared/utilities' import { Layout } from '@components/Layout' import { RecipesPageContent } from '@components/RecipesPageContent' import { ResourceLink } from '@components/ResourceLink' diff --git a/apps/incentives/src/pages/chat-bots.tsx b/apps/incentives/src/pages/chat-bots.tsx index 66f185a1..26a77762 100644 --- a/apps/incentives/src/pages/chat-bots.tsx +++ b/apps/incentives/src/pages/chat-bots.tsx @@ -1,4 +1,4 @@ -import { LINKS } from '@shared/ui' +import { LINKS } from '@shared/utilities' import { ExtensionsPageContent } from '@components/ExtensionsPageContent' import { Layout } from '@components/Layout' diff --git a/apps/incentives/src/pages/group-savings.tsx b/apps/incentives/src/pages/group-savings.tsx index 3325e8bf..fd963f5e 100644 --- a/apps/incentives/src/pages/group-savings.tsx +++ b/apps/incentives/src/pages/group-savings.tsx @@ -1,4 +1,4 @@ -import { LINKS } from '@shared/ui' +import { LINKS } from '@shared/utilities' import { Layout } from '@components/Layout' import { RecipesPageContent } from '@components/RecipesPageContent' import { ResourceLink } from '@components/ResourceLink' diff --git a/apps/incentives/src/pages/index.tsx b/apps/incentives/src/pages/index.tsx index 7a59178b..6d705a36 100644 --- a/apps/incentives/src/pages/index.tsx +++ b/apps/incentives/src/pages/index.tsx @@ -1,4 +1,5 @@ -import { Button, ExternalLink, LINKS } from '@shared/ui' +import { Button, ExternalLink } from '@shared/ui' +import { LINKS } from '@shared/utilities' import classNames from 'classnames' import Image from 'next/image' import Link from 'next/link' diff --git a/apps/incentives/src/pages/no-loss-marketing.tsx b/apps/incentives/src/pages/no-loss-marketing.tsx index e14b19f1..b539cab1 100644 --- a/apps/incentives/src/pages/no-loss-marketing.tsx +++ b/apps/incentives/src/pages/no-loss-marketing.tsx @@ -1,4 +1,4 @@ -import { LINKS } from '@shared/ui' +import { LINKS } from '@shared/utilities' import { Layout } from '@components/Layout' import { RecipesPageContent } from '@components/RecipesPageContent' import { ResourceLink } from '@components/ResourceLink' diff --git a/apps/incentives/src/pages/on-ramps.tsx b/apps/incentives/src/pages/on-ramps.tsx index 5ed5e571..bd4ac98d 100644 --- a/apps/incentives/src/pages/on-ramps.tsx +++ b/apps/incentives/src/pages/on-ramps.tsx @@ -1,4 +1,4 @@ -import { LINKS } from '@shared/ui' +import { LINKS } from '@shared/utilities' import { ExtensionsPageContent } from '@components/ExtensionsPageContent' import { Layout } from '@components/Layout' diff --git a/apps/incentives/src/pages/yield-sources.tsx b/apps/incentives/src/pages/yield-sources.tsx index a7b15902..25c56bee 100644 --- a/apps/incentives/src/pages/yield-sources.tsx +++ b/apps/incentives/src/pages/yield-sources.tsx @@ -1,4 +1,4 @@ -import { LINKS } from '@shared/ui' +import { LINKS } from '@shared/utilities' import { ExtensionsPageContent } from '@components/ExtensionsPageContent' import { Layout } from '@components/Layout' diff --git a/apps/incentives/src/pages/yield-split.tsx b/apps/incentives/src/pages/yield-split.tsx index 4fcf7227..ba7547d8 100644 --- a/apps/incentives/src/pages/yield-split.tsx +++ b/apps/incentives/src/pages/yield-split.tsx @@ -1,4 +1,4 @@ -import { LINKS } from '@shared/ui' +import { LINKS } from '@shared/utilities' import { Layout } from '@components/Layout' import { RecipesPageContent } from '@components/RecipesPageContent' import { ResourceLink } from '@components/ResourceLink' diff --git a/apps/landing-page/src/components/Footer.tsx b/apps/landing-page/src/components/Footer.tsx index cc1dbbab..1ab747b5 100644 --- a/apps/landing-page/src/components/Footer.tsx +++ b/apps/landing-page/src/components/Footer.tsx @@ -1,4 +1,5 @@ -import { LINKS, SocialIcon, SocialIconProps } from '@shared/ui' +import { SocialIcon, SocialIconProps } from '@shared/ui' +import { LINKS } from '@shared/utilities' import classNames from 'classnames' import Image from 'next/image' import Link from 'next/link' diff --git a/apps/landing-page/src/components/Home/DocsSection.tsx b/apps/landing-page/src/components/Home/DocsSection.tsx index 37e6f407..785932d1 100644 --- a/apps/landing-page/src/components/Home/DocsSection.tsx +++ b/apps/landing-page/src/components/Home/DocsSection.tsx @@ -1,4 +1,4 @@ -import { LINKS } from '@shared/ui' +import { LINKS } from '@shared/utilities' import classNames from 'classnames' import Image from 'next/image' import Link from 'next/link' diff --git a/apps/landing-page/src/components/Home/FaqSection.tsx b/apps/landing-page/src/components/Home/FaqSection.tsx index 13ae32f6..3268f240 100644 --- a/apps/landing-page/src/components/Home/FaqSection.tsx +++ b/apps/landing-page/src/components/Home/FaqSection.tsx @@ -1,4 +1,5 @@ -import { Accordion, LINKS } from '@shared/ui' +import { Accordion } from '@shared/ui' +import { LINKS } from '@shared/utilities' import classNames from 'classnames' import { ReactNode } from 'react' diff --git a/apps/landing-page/src/components/Home/HomeHeader.tsx b/apps/landing-page/src/components/Home/HomeHeader.tsx index 9d4bfbbe..296c9f80 100644 --- a/apps/landing-page/src/components/Home/HomeHeader.tsx +++ b/apps/landing-page/src/components/Home/HomeHeader.tsx @@ -1,5 +1,6 @@ import { useScreenSize } from '@shared/generic-react-hooks' -import { Button, LINKS } from '@shared/ui' +import { Button } from '@shared/ui' +import { LINKS } from '@shared/utilities' import classNames from 'classnames' import Image from 'next/image' diff --git a/apps/landing-page/src/components/Navbar.tsx b/apps/landing-page/src/components/Navbar.tsx index 84c6308d..5a606757 100644 --- a/apps/landing-page/src/components/Navbar.tsx +++ b/apps/landing-page/src/components/Navbar.tsx @@ -1,5 +1,6 @@ import { useScreenSize } from '@shared/generic-react-hooks' -import { Button, LINKS, Logo } from '@shared/ui' +import { Button, Logo } from '@shared/ui' +import { LINKS } from '@shared/utilities' import classNames from 'classnames' import Image from 'next/image' import Link from 'next/link' diff --git a/apps/landing-page/src/components/Tools/DocsSection.tsx b/apps/landing-page/src/components/Tools/DocsSection.tsx index 2bb398bb..d32ac328 100644 --- a/apps/landing-page/src/components/Tools/DocsSection.tsx +++ b/apps/landing-page/src/components/Tools/DocsSection.tsx @@ -1,4 +1,4 @@ -import { LINKS } from '@shared/ui' +import { LINKS } from '@shared/utilities' import classNames from 'classnames' import Image from 'next/image' import Link from 'next/link' diff --git a/apps/landing-page/src/components/Tools/StartBuildingSection.tsx b/apps/landing-page/src/components/Tools/StartBuildingSection.tsx index cdd5f5dc..e52f2e95 100644 --- a/apps/landing-page/src/components/Tools/StartBuildingSection.tsx +++ b/apps/landing-page/src/components/Tools/StartBuildingSection.tsx @@ -1,4 +1,4 @@ -import { LINKS } from '@shared/ui' +import { LINKS } from '@shared/utilities' import classNames from 'classnames' import Image from 'next/image' import Link from 'next/link' diff --git a/apps/landing-page/src/components/Tools/ToolsHeader.tsx b/apps/landing-page/src/components/Tools/ToolsHeader.tsx index d9a24ba0..ca794cbf 100644 --- a/apps/landing-page/src/components/Tools/ToolsHeader.tsx +++ b/apps/landing-page/src/components/Tools/ToolsHeader.tsx @@ -1,5 +1,6 @@ import { useScreenSize } from '@shared/generic-react-hooks' -import { Button, LINKS } from '@shared/ui' +import { Button } from '@shared/ui' +import { LINKS } from '@shared/utilities' import classNames from 'classnames' import Image from 'next/image' diff --git a/apps/landing-page/src/pages/_document.tsx b/apps/landing-page/src/pages/_document.tsx index f3a750e9..de52304e 100644 --- a/apps/landing-page/src/pages/_document.tsx +++ b/apps/landing-page/src/pages/_document.tsx @@ -1,4 +1,4 @@ -import { DOMAINS } from '@shared/ui' +import { DOMAINS } from '@shared/utilities' import Document, { DocumentContext, DocumentInitialProps, diff --git a/apps/migrations/src/components/Layout.tsx b/apps/migrations/src/components/Layout.tsx index 9929e921..37a163d2 100644 --- a/apps/migrations/src/components/Layout.tsx +++ b/apps/migrations/src/components/Layout.tsx @@ -1,6 +1,7 @@ import { ArrowUturnLeftIcon } from '@heroicons/react/24/outline' import { ConnectButton } from '@rainbow-me/rainbowkit' -import { LINKS, Toaster } from '@shared/ui' +import { Toaster } from '@shared/ui' +import { LINKS } from '@shared/utilities' import classNames from 'classnames' import { Footer as FlowbiteFooter } from 'flowbite-react' import Head from 'next/head' diff --git a/apps/migrations/src/hooks/useV5Tokens.ts b/apps/migrations/src/hooks/useV5Tokens.ts index ee7e6ec6..d73e6c33 100644 --- a/apps/migrations/src/hooks/useV5Tokens.ts +++ b/apps/migrations/src/hooks/useV5Tokens.ts @@ -1,7 +1,6 @@ import { NO_REFETCH } from '@shared/generic-react-hooks' import { TokenWithLogo, VaultInfo } from '@shared/types' -import { DOMAINS } from '@shared/ui' -import { getVaultList } from '@shared/utilities' +import { DOMAINS, getVaultList } from '@shared/utilities' import { useQuery } from '@tanstack/react-query' import { useMemo } from 'react' import { SUPPORTED_NETWORKS } from '@constants/config' diff --git a/apps/migrations/src/pages/_document.tsx b/apps/migrations/src/pages/_document.tsx index dd957a62..fcd53fe4 100644 --- a/apps/migrations/src/pages/_document.tsx +++ b/apps/migrations/src/pages/_document.tsx @@ -1,4 +1,4 @@ -import { DOMAINS } from '@shared/ui' +import { DOMAINS } from '@shared/utilities' import Document, { DocumentContext, DocumentInitialProps, diff --git a/apps/rewards-builder/src/components/DeployPromotionView.tsx b/apps/rewards-builder/src/components/DeployPromotionView.tsx index 7d364b68..4ef6146a 100644 --- a/apps/rewards-builder/src/components/DeployPromotionView.tsx +++ b/apps/rewards-builder/src/components/DeployPromotionView.tsx @@ -1,4 +1,4 @@ -import { LINKS } from '@shared/ui' +import { LINKS } from '@shared/utilities' import classNames from 'classnames' import { useRouter } from 'next/router' import { DeployPromotionButton } from './buttons/DeployPromotionButton' diff --git a/apps/rewards-builder/src/components/DeployedPromotionCard.tsx b/apps/rewards-builder/src/components/DeployedPromotionCard.tsx index 6f1efc3c..e6a3ddbf 100644 --- a/apps/rewards-builder/src/components/DeployedPromotionCard.tsx +++ b/apps/rewards-builder/src/components/DeployedPromotionCard.tsx @@ -6,8 +6,8 @@ import { SquaresPlusIcon } from '@heroicons/react/24/outline' import { TokenIcon, VaultBadge } from '@shared/react-components' -import { LINKS, Spinner, Tooltip } from '@shared/ui' -import { getBlockExplorerUrl, getSimpleDate, isTestnet, shorten } from '@shared/utilities' +import { Spinner, Tooltip } from '@shared/ui' +import { getBlockExplorerUrl, getSimpleDate, isTestnet, LINKS, shorten } from '@shared/utilities' import classNames from 'classnames' import Link from 'next/link' import { useRouter } from 'next/router' diff --git a/apps/rewards-builder/src/components/DeployedPromotionsTable.tsx b/apps/rewards-builder/src/components/DeployedPromotionsTable.tsx index 11f04ece..420a893e 100644 --- a/apps/rewards-builder/src/components/DeployedPromotionsTable.tsx +++ b/apps/rewards-builder/src/components/DeployedPromotionsTable.tsx @@ -7,8 +7,8 @@ import { } from '@heroicons/react/24/outline' import { useScreenSize } from '@shared/generic-react-hooks' import { TokenIcon, VaultBadge } from '@shared/react-components' -import { LINKS, Spinner, Table, TableData, Tooltip } from '@shared/ui' -import { getBlockExplorerUrl, getSimpleDate, isTestnet, shorten } from '@shared/utilities' +import { Spinner, Table, TableData, Tooltip } from '@shared/ui' +import { getBlockExplorerUrl, getSimpleDate, isTestnet, LINKS, shorten } from '@shared/utilities' import classNames from 'classnames' import Link from 'next/link' import { useRouter } from 'next/router' diff --git a/apps/rewards-builder/src/components/Layout.tsx b/apps/rewards-builder/src/components/Layout.tsx index 62266f4e..a1d0698f 100644 --- a/apps/rewards-builder/src/components/Layout.tsx +++ b/apps/rewards-builder/src/components/Layout.tsx @@ -1,5 +1,6 @@ import { ConnectButton } from '@rainbow-me/rainbowkit' -import { LINKS, Toaster } from '@shared/ui' +import { Toaster } from '@shared/ui' +import { LINKS } from '@shared/utilities' import classNames from 'classnames' import Head from 'next/head' import Image from 'next/image' diff --git a/apps/rewards-builder/src/pages/_document.tsx b/apps/rewards-builder/src/pages/_document.tsx index b69e4491..ef3cfcbf 100644 --- a/apps/rewards-builder/src/pages/_document.tsx +++ b/apps/rewards-builder/src/pages/_document.tsx @@ -1,4 +1,4 @@ -import { DOMAINS } from '@shared/ui' +import { DOMAINS } from '@shared/utilities' import Document, { DocumentContext, DocumentInitialProps, diff --git a/apps/swaps/src/components/Faq.tsx b/apps/swaps/src/components/Faq.tsx index 0d61fb59..bb178eb1 100644 --- a/apps/swaps/src/components/Faq.tsx +++ b/apps/swaps/src/components/Faq.tsx @@ -1,4 +1,5 @@ -import { Accordion, LINKS } from '@shared/ui' +import { Accordion } from '@shared/ui' +import { LINKS } from '@shared/utilities' import classNames from 'classnames' import Link from 'next/link' import { ReactNode } from 'react' diff --git a/apps/swaps/src/components/GrandPrize.tsx b/apps/swaps/src/components/GrandPrize.tsx index ea5d9b29..e744fe5e 100644 --- a/apps/swaps/src/components/GrandPrize.tsx +++ b/apps/swaps/src/components/GrandPrize.tsx @@ -4,8 +4,8 @@ import { usePrizeTokenPrice } from '@generationsoftware/hyperstructure-react-hooks' import { CurrencyValue } from '@shared/react-components' -import { ExternalLink, LINKS, Spinner } from '@shared/ui' -import { PRIZE_POOLS } from '@shared/utilities' +import { ExternalLink, Spinner } from '@shared/ui' +import { LINKS, PRIZE_POOLS } from '@shared/utilities' import classNames from 'classnames' import { formatUnits } from 'viem' diff --git a/apps/swaps/src/components/Navbar.tsx b/apps/swaps/src/components/Navbar.tsx index b49ca12d..8849a60b 100644 --- a/apps/swaps/src/components/Navbar.tsx +++ b/apps/swaps/src/components/Navbar.tsx @@ -1,4 +1,5 @@ -import { LINKS, Logo } from '@shared/ui' +import { Logo } from '@shared/ui' +import { LINKS } from '@shared/utilities' import classNames from 'classnames' import Image from 'next/image' import Link from 'next/link' diff --git a/apps/swaps/src/components/RecentWinners.tsx b/apps/swaps/src/components/RecentWinners.tsx index 3b336e4d..6af4bcdc 100644 --- a/apps/swaps/src/components/RecentWinners.tsx +++ b/apps/swaps/src/components/RecentWinners.tsx @@ -5,8 +5,14 @@ import { } from '@generationsoftware/hyperstructure-react-hooks' import { CurrencyValue } from '@shared/react-components' import { SubgraphDraw, TokenWithPrice } from '@shared/types' -import { ExternalLink, LINKS, Spinner } from '@shared/ui' -import { getSecondsSinceEpoch, PRIZE_POOLS, SECONDS_PER_DAY, shorten } from '@shared/utilities' +import { ExternalLink, Spinner } from '@shared/ui' +import { + getSecondsSinceEpoch, + LINKS, + PRIZE_POOLS, + SECONDS_PER_DAY, + shorten +} from '@shared/utilities' import classNames from 'classnames' import { useMemo } from 'react' import { formatUnits } from 'viem' diff --git a/apps/swaps/src/components/VaultCard.tsx b/apps/swaps/src/components/VaultCard.tsx index 346c932f..4db5bdf9 100644 --- a/apps/swaps/src/components/VaultCard.tsx +++ b/apps/swaps/src/components/VaultCard.tsx @@ -5,9 +5,8 @@ import { } from '@generationsoftware/hyperstructure-react-hooks' import { TokenIcon } from '@shared/react-components' import { Token } from '@shared/types' -import { LINKS } from '@shared/ui' import { ExternalLink } from '@shared/ui' -import { DOLPHIN_ADDRESS, getNetworkNameByChainId } from '@shared/utilities' +import { DOLPHIN_ADDRESS, getNetworkNameByChainId, LINKS } from '@shared/utilities' import classNames from 'classnames' import { ReactNode } from 'react' import { Address, zeroAddress } from 'viem' diff --git a/apps/swaps/src/pages/_document.tsx b/apps/swaps/src/pages/_document.tsx index f7a40ed6..5d3b5dd3 100644 --- a/apps/swaps/src/pages/_document.tsx +++ b/apps/swaps/src/pages/_document.tsx @@ -1,4 +1,4 @@ -import { DOMAINS } from '@shared/ui' +import { DOMAINS } from '@shared/utilities' import Document, { DocumentContext, DocumentInitialProps, diff --git a/apps/vault-factory/src/components/CreateVaultStepInfo.tsx b/apps/vault-factory/src/components/CreateVaultStepInfo.tsx index 130b9883..2346416a 100644 --- a/apps/vault-factory/src/components/CreateVaultStepInfo.tsx +++ b/apps/vault-factory/src/components/CreateVaultStepInfo.tsx @@ -1,4 +1,4 @@ -import { LINKS } from '@shared/ui' +import { LINKS } from '@shared/utilities' import { useAtomValue } from 'jotai' import { ReactNode, useEffect, useMemo } from 'react' import { isUsingCustomYieldSourceAtom } from 'src/atoms' diff --git a/apps/vault-factory/src/components/DeployedVaultCard.tsx b/apps/vault-factory/src/components/DeployedVaultCard.tsx index f8a8618a..8727b439 100644 --- a/apps/vault-factory/src/components/DeployedVaultCard.tsx +++ b/apps/vault-factory/src/components/DeployedVaultCard.tsx @@ -6,8 +6,8 @@ import { } from '@generationsoftware/hyperstructure-react-hooks' import { ArrowPathRoundedSquareIcon, TrashIcon, WrenchIcon } from '@heroicons/react/24/outline' import { VaultBadge } from '@shared/react-components' -import { LINKS, Spinner } from '@shared/ui' -import { getBlockExplorerUrl, shorten } from '@shared/utilities' +import { Spinner } from '@shared/ui' +import { getBlockExplorerUrl, LINKS, shorten } from '@shared/utilities' import classNames from 'classnames' import Link from 'next/link' import { useRouter } from 'next/router' diff --git a/apps/vault-factory/src/components/DeployedVaultsTable.tsx b/apps/vault-factory/src/components/DeployedVaultsTable.tsx index 8b40c283..ff36a585 100644 --- a/apps/vault-factory/src/components/DeployedVaultsTable.tsx +++ b/apps/vault-factory/src/components/DeployedVaultsTable.tsx @@ -8,8 +8,8 @@ import { import { ArrowPathRoundedSquareIcon, TrashIcon, WrenchIcon } from '@heroicons/react/24/outline' import { useScreenSize } from '@shared/generic-react-hooks' import { VaultBadge } from '@shared/react-components' -import { LINKS, Spinner, Table, TableData, Tooltip } from '@shared/ui' -import { getBlockExplorerUrl, shorten } from '@shared/utilities' +import { Spinner, Table, TableData, Tooltip } from '@shared/ui' +import { getBlockExplorerUrl, LINKS, shorten } from '@shared/utilities' import classNames from 'classnames' import Link from 'next/link' import { useRouter } from 'next/router' diff --git a/apps/vault-factory/src/components/HomePageContent.tsx b/apps/vault-factory/src/components/HomePageContent.tsx index 965f9b5a..2acf7e05 100644 --- a/apps/vault-factory/src/components/HomePageContent.tsx +++ b/apps/vault-factory/src/components/HomePageContent.tsx @@ -1,4 +1,5 @@ -import { Button, LINKS } from '@shared/ui' +import { Button } from '@shared/ui' +import { LINKS } from '@shared/utilities' import { useRouter } from 'next/router' import { useEffect, useState } from 'react' import { useAccount } from 'wagmi' diff --git a/apps/vault-factory/src/components/Layout.tsx b/apps/vault-factory/src/components/Layout.tsx index 5a1061a4..f053b7fc 100644 --- a/apps/vault-factory/src/components/Layout.tsx +++ b/apps/vault-factory/src/components/Layout.tsx @@ -1,5 +1,6 @@ import { ConnectButton } from '@rainbow-me/rainbowkit' -import { LINKS, Toaster } from '@shared/ui' +import { Toaster } from '@shared/ui' +import { LINKS } from '@shared/utilities' import classNames from 'classnames' import Head from 'next/head' import Image from 'next/image' diff --git a/apps/vault-factory/src/components/forms/YieldVaultInput.tsx b/apps/vault-factory/src/components/forms/YieldVaultInput.tsx index 7cad1916..ae9567d1 100644 --- a/apps/vault-factory/src/components/forms/YieldVaultInput.tsx +++ b/apps/vault-factory/src/components/forms/YieldVaultInput.tsx @@ -1,8 +1,8 @@ import { useToken } from '@generationsoftware/hyperstructure-react-hooks' import { InformationCircleIcon } from '@heroicons/react/24/outline' import { TokenIcon } from '@shared/react-components' -import { Card, ExternalLink, LINKS, Spinner, Tooltip } from '@shared/ui' -import { getBlockExplorerUrl, getVaultId, shorten } from '@shared/utilities' +import { Card, ExternalLink, Spinner, Tooltip } from '@shared/ui' +import { getBlockExplorerUrl, getVaultId, LINKS, shorten } from '@shared/utilities' import classNames from 'classnames' import { useAtomValue } from 'jotai' import { useMemo } from 'react' diff --git a/apps/vault-factory/src/pages/_document.tsx b/apps/vault-factory/src/pages/_document.tsx index 22a452b4..9238b4c2 100644 --- a/apps/vault-factory/src/pages/_document.tsx +++ b/apps/vault-factory/src/pages/_document.tsx @@ -1,4 +1,4 @@ -import { DOMAINS } from '@shared/ui' +import { DOMAINS } from '@shared/utilities' import Document, { DocumentContext, DocumentInitialProps, diff --git a/apps/vaultlist-creator/src/components/Layout.tsx b/apps/vaultlist-creator/src/components/Layout.tsx index 2a04d313..ef256dcf 100644 --- a/apps/vaultlist-creator/src/components/Layout.tsx +++ b/apps/vaultlist-creator/src/components/Layout.tsx @@ -1,4 +1,4 @@ -import { LINKS } from '@shared/ui' +import { LINKS } from '@shared/utilities' import classNames from 'classnames' import Head from 'next/head' import Image from 'next/image' diff --git a/apps/vaultlist-creator/src/pages/_document.tsx b/apps/vaultlist-creator/src/pages/_document.tsx index 72ad302c..7d2f6e0b 100644 --- a/apps/vaultlist-creator/src/pages/_document.tsx +++ b/apps/vaultlist-creator/src/pages/_document.tsx @@ -1,4 +1,4 @@ -import { DOMAINS } from '@shared/ui' +import { DOMAINS } from '@shared/utilities' import Document, { DocumentContext, DocumentInitialProps, diff --git a/shared/react-components/components/Buttons/SocialShareButton.tsx b/shared/react-components/components/Buttons/SocialShareButton.tsx index 84ddb2ed..6ddb3793 100644 --- a/shared/react-components/components/Buttons/SocialShareButton.tsx +++ b/shared/react-components/components/Buttons/SocialShareButton.tsx @@ -1,4 +1,5 @@ -import { Button, ButtonProps, LINKS, SocialIcon } from '@shared/ui' +import { Button, ButtonProps, SocialIcon } from '@shared/ui' +import { LINKS } from '@shared/utilities' interface SocialShareButtonProps extends Omit { platform: 'twitter' | 'warpcast' | 'hey' diff --git a/shared/react-components/components/Modals/DepositModal/index.tsx b/shared/react-components/components/Modals/DepositModal/index.tsx index 400c0782..91f7f983 100644 --- a/shared/react-components/components/Modals/DepositModal/index.tsx +++ b/shared/react-components/components/Modals/DepositModal/index.tsx @@ -7,8 +7,8 @@ import { } from '@generationsoftware/hyperstructure-react-hooks' import { MODAL_KEYS, useIsModalOpen } from '@shared/generic-react-hooks' import { Intl, RichIntl } from '@shared/types' -import { LINKS, Modal } from '@shared/ui' -import { formatNumberForDisplay } from '@shared/utilities' +import { Modal } from '@shared/ui' +import { formatNumberForDisplay, LINKS } from '@shared/utilities' import classNames from 'classnames' import { useAtomValue } from 'jotai' import { ReactNode, useMemo, useState } from 'react' diff --git a/shared/react-components/components/Modals/SettingsModal/Views/MenuView.tsx b/shared/react-components/components/Modals/SettingsModal/Views/MenuView.tsx index e033e168..ac72edcb 100644 --- a/shared/react-components/components/Modals/SettingsModal/Views/MenuView.tsx +++ b/shared/react-components/components/Modals/SettingsModal/Views/MenuView.tsx @@ -5,7 +5,8 @@ import { useSelectedLanguage } from '@shared/generic-react-hooks' import { Intl } from '@shared/types' -import { BasicIcon, LINKS } from '@shared/ui' +import { BasicIcon } from '@shared/ui' +import { LINKS } from '@shared/utilities' import classNames from 'classnames' import { ReactNode } from 'react' import { SettingsModalOption, SettingsModalView } from '..' diff --git a/shared/react-components/components/Modals/SettingsModal/Views/VaultListView.tsx b/shared/react-components/components/Modals/SettingsModal/Views/VaultListView.tsx index c42c570e..a14b1130 100644 --- a/shared/react-components/components/Modals/SettingsModal/Views/VaultListView.tsx +++ b/shared/react-components/components/Modals/SettingsModal/Views/VaultListView.tsx @@ -5,8 +5,8 @@ import { import { TrashIcon } from '@heroicons/react/24/outline' import { VaultList } from '@shared/types' import { Intl } from '@shared/types' -import { BasicIcon, Button, ExternalLink, LINKS, Spinner, Toggle } from '@shared/ui' -import { getVaultList, NETWORK } from '@shared/utilities' +import { BasicIcon, Button, ExternalLink, Spinner, Toggle } from '@shared/ui' +import { getVaultList, LINKS, NETWORK } from '@shared/utilities' import classNames from 'classnames' import { useMemo, useState } from 'react' import { useForm } from 'react-hook-form' diff --git a/shared/react-components/components/Tooltips/DelegationDescriptionTooltip.tsx b/shared/react-components/components/Tooltips/DelegationDescriptionTooltip.tsx index fc930563..da5da769 100644 --- a/shared/react-components/components/Tooltips/DelegationDescriptionTooltip.tsx +++ b/shared/react-components/components/Tooltips/DelegationDescriptionTooltip.tsx @@ -1,6 +1,7 @@ import { InformationCircleIcon } from '@heroicons/react/24/outline' import { Intl } from '@shared/types' -import { ExternalLink, LINKS, Tooltip } from '@shared/ui' +import { ExternalLink, Tooltip } from '@shared/ui' +import { LINKS } from '@shared/utilities' import classNames from 'classnames' export interface DelegationDescriptionTooltipProps { diff --git a/shared/react-components/components/Tooltips/PrizeYieldTooltip.tsx b/shared/react-components/components/Tooltips/PrizeYieldTooltip.tsx index 4e750b9f..ea20cfa2 100644 --- a/shared/react-components/components/Tooltips/PrizeYieldTooltip.tsx +++ b/shared/react-components/components/Tooltips/PrizeYieldTooltip.tsx @@ -1,5 +1,6 @@ import { InformationCircleIcon } from '@heroicons/react/24/outline' -import { LINKS, Tooltip } from '@shared/ui' +import { Tooltip } from '@shared/ui' +import { LINKS } from '@shared/utilities' import classNames from 'classnames' export interface PrizeYieldTooltipProps { diff --git a/shared/ui/components/Footer.tsx b/shared/ui/components/Footer.tsx index c2c0606c..e4854d83 100644 --- a/shared/ui/components/Footer.tsx +++ b/shared/ui/components/Footer.tsx @@ -1,7 +1,7 @@ +import { LINKS } from '@shared/utilities' import classNames from 'classnames' import { Footer as FlowbiteFooter, FooterProps as FlowbiteFooterProps } from 'flowbite-react' import { ReactNode } from 'react' -import { LINKS } from '../constants' export interface FooterItem { title: string diff --git a/shared/ui/constants.ts b/shared/ui/constants.ts deleted file mode 100644 index 8ed82a66..00000000 --- a/shared/ui/constants.ts +++ /dev/null @@ -1,72 +0,0 @@ -/** - * Domains - */ -export const DOMAINS = { - app: 'https://app.cabana.fi', - app_v4: 'https://app.pooltogether.com', - landingPage: 'https://cabana.fi', - protocolLandingPage: 'https://pooltogether.com', - docs: 'https://docs.cabana.fi', - protocolDocs: 'https://docs.pooltogether.com', - protocolDevDocs: 'https://dev.pooltogether.com', - governance: 'https://gov.pooltogether.com', - poolExplorer: 'https://poolexplorer.win', - tools_v4: 'https://tools.pooltogether.com', - notion: 'https://pooltogetherdao.notion.site', - vaultListCreator: 'https://lists.cabana.fi', - vaultFactory: 'https://factory.cabana.fi', - analytics: 'https://analytics.cabana.fi', - swaps: 'https://swap.cabana.fi', - rewardsBuilder: 'https://rewards.cabana.fi', - flashLiquidator: 'https://flash.cabana.fi', - migrations: 'https://migrate.cabana.fi', - builders: 'https://builders.cabana.fi' -} as const - -/** - * Links - */ -export const LINKS = { - ...DOMAINS, - termsOfService: `${DOMAINS.landingPage}/terms`, - privacyPolicy: `${DOMAINS.landingPage}/privacy`, - ecosystem: `${DOMAINS.protocolLandingPage}/ecosystem`, - discord: `${DOMAINS.protocolLandingPage}/discord`, - appDocs: `${DOMAINS.docs}/#the-cabana-app`, - toolDocs: `${DOMAINS.docs}/#cabana-tools`, - protocolBasicsDocs: `${DOMAINS.docs}/protocol/the-basics`, - delegateDocs: `${DOMAINS.docs}/cabana-app/delegation`, - prizeYieldDocs: `${DOMAINS.docs}/cabana-app/prize-yield`, - factoryDocs: `${DOMAINS.docs}/cabana-tools/cabana-factory`, - listDocs: `${DOMAINS.docs}/cabana-tools/cabana-lists`, - analyticsDocs: `${DOMAINS.docs}/cabana-tools/cabanalytics`, - swapDocs: `${DOMAINS.docs}/cabana-tools/cabana-swaps`, - flashDocs: `${DOMAINS.docs}/cabana-tools/cabana-flash`, - appGuides: `${DOMAINS.docs}/cabana-app/guides`, - toolGuides: `${DOMAINS.docs}/cabana-tools/guides`, - protocolFaqs: `${DOMAINS.docs}/protocol/faqs`, - appFaqs: `${DOMAINS.docs}/cabana-app/faqs`, - toolFaqs: `${DOMAINS.docs}/cabana-tools/faqs`, - rewardTokenWhitelist: `${DOMAINS.docs}/cabana-app/bonus-rewards#reward-token-whitelist`, - risks: `${DOMAINS.protocolDocs}/security/risks`, - audits: `${DOMAINS.protocolDocs}/security/audits`, - devDocs_v4: `${DOMAINS.protocolDevDocs}/protocol/V4/introduction`, - depositDelegator: `${DOMAINS.tools_v4}/delegate`, - prizeTierController: `${DOMAINS.tools_v4}/prize-tier-controller`, - communityCalendar: `${DOMAINS.notion}/Community-Calendar-4ce3024241dd464db96215e6729a78e0`, - brandKit: `https://www.figma.com/community/file/1212805243917604494`, - twitter: `https://twitter.com/PoolTogether_`, - github: `https://github.com/pooltogether`, - medium: `https://medium.com/pooltogether`, - tally: `https://www.tally.xyz/gov/pooltogether`, - treasury: `https://info.pooltogether.com/treasury`, - dune_v4: `https://dune.com/sarfang/PoolTogetherV4`, - prizeCalc: `https://prizecalc.com`, - grants: `https://poolgrants.org`, - hey: `https://hey.xyz/u/pooltogether`, - mirror: `https://pooltogether.mirror.xyz/`, - warpcast: `https://warpcast.com/~/channel/pool-together`, - clientJs: `https://www.npmjs.com/package/@generationsoftware/hyperstructure-client-js`, - clientJs_v4: `https://www.npmjs.com/package/@pooltogether/v4-client-js`, - reactHooks: `https://www.npmjs.com/package/@generationsoftware/hyperstructure-react-hooks` -} as const diff --git a/shared/ui/index.tsx b/shared/ui/index.tsx index d1be138a..c6dd50b0 100644 --- a/shared/ui/index.tsx +++ b/shared/ui/index.tsx @@ -30,8 +30,3 @@ export * from './components/Tabs' export * from './components/Toaster' export * from './components/Toggle' export * from './components/Tooltip' - -/** - * Constants - */ -export * from './constants' diff --git a/shared/utilities/constants.ts b/shared/utilities/constants.ts index 7e89d27f..93cc6927 100644 --- a/shared/utilities/constants.ts +++ b/shared/utilities/constants.ts @@ -307,6 +307,79 @@ export const TOKEN_DATA_REDIRECTS: { } } +/** + * Domains + */ +export const DOMAINS = { + app: 'https://app.cabana.fi', + app_v4: 'https://app.pooltogether.com', + landingPage: 'https://cabana.fi', + protocolLandingPage: 'https://pooltogether.com', + docs: 'https://docs.cabana.fi', + protocolDocs: 'https://docs.pooltogether.com', + protocolDevDocs: 'https://dev.pooltogether.com', + governance: 'https://gov.pooltogether.com', + poolExplorer: 'https://poolexplorer.win', + tools_v4: 'https://tools.pooltogether.com', + notion: 'https://pooltogetherdao.notion.site', + vaultListCreator: 'https://lists.cabana.fi', + vaultFactory: 'https://factory.cabana.fi', + analytics: 'https://analytics.cabana.fi', + swaps: 'https://swap.cabana.fi', + rewardsBuilder: 'https://rewards.cabana.fi', + flashLiquidator: 'https://flash.cabana.fi', + migrations: 'https://migrate.cabana.fi', + builders: 'https://builders.cabana.fi' +} as const satisfies { [name: string]: `https://${string}` } + +/** + * Links + */ +export const LINKS = { + ...DOMAINS, + termsOfService: `${DOMAINS.landingPage}/terms`, + privacyPolicy: `${DOMAINS.landingPage}/privacy`, + ecosystem: `${DOMAINS.protocolLandingPage}/ecosystem`, + discord: `${DOMAINS.protocolLandingPage}/discord`, + appDocs: `${DOMAINS.docs}/#the-cabana-app`, + toolDocs: `${DOMAINS.docs}/#cabana-tools`, + protocolBasicsDocs: `${DOMAINS.docs}/protocol/the-basics`, + delegateDocs: `${DOMAINS.docs}/cabana-app/delegation`, + prizeYieldDocs: `${DOMAINS.docs}/cabana-app/prize-yield`, + factoryDocs: `${DOMAINS.docs}/cabana-tools/cabana-factory`, + listDocs: `${DOMAINS.docs}/cabana-tools/cabana-lists`, + analyticsDocs: `${DOMAINS.docs}/cabana-tools/cabanalytics`, + swapDocs: `${DOMAINS.docs}/cabana-tools/cabana-swaps`, + flashDocs: `${DOMAINS.docs}/cabana-tools/cabana-flash`, + appGuides: `${DOMAINS.docs}/cabana-app/guides`, + toolGuides: `${DOMAINS.docs}/cabana-tools/guides`, + protocolFaqs: `${DOMAINS.docs}/protocol/faqs`, + appFaqs: `${DOMAINS.docs}/cabana-app/faqs`, + toolFaqs: `${DOMAINS.docs}/cabana-tools/faqs`, + rewardTokenWhitelist: `${DOMAINS.docs}/cabana-app/bonus-rewards#reward-token-whitelist`, + risks: `${DOMAINS.protocolDocs}/security/risks`, + audits: `${DOMAINS.protocolDocs}/security/audits`, + devDocs_v4: `${DOMAINS.protocolDevDocs}/protocol/V4/introduction`, + depositDelegator: `${DOMAINS.tools_v4}/delegate`, + prizeTierController: `${DOMAINS.tools_v4}/prize-tier-controller`, + communityCalendar: `${DOMAINS.notion}/Community-Calendar-4ce3024241dd464db96215e6729a78e0`, + brandKit: `https://www.figma.com/community/file/1212805243917604494`, + twitter: `https://twitter.com/PoolTogether_`, + github: `https://github.com/pooltogether`, + medium: `https://medium.com/pooltogether`, + tally: `https://www.tally.xyz/gov/pooltogether`, + treasury: `https://info.pooltogether.com/treasury`, + dune_v4: `https://dune.com/sarfang/PoolTogetherV4`, + prizeCalc: `https://prizecalc.com`, + grants: `https://poolgrants.org`, + hey: `https://hey.xyz/u/pooltogether`, + mirror: `https://pooltogether.mirror.xyz/`, + warpcast: `https://warpcast.com/~/channel/pool-together`, + clientJs: `https://www.npmjs.com/package/@generationsoftware/hyperstructure-client-js`, + clientJs_v4: `https://www.npmjs.com/package/@pooltogether/v4-client-js`, + reactHooks: `https://www.npmjs.com/package/@generationsoftware/hyperstructure-react-hooks` +} as const satisfies { [name: string]: `https://${string}` } + /** * Block explorer mapping */ From ac216a9658c8b3c9815f55285f7300c6dfc112ec Mon Sep 17 00:00:00 2001 From: Ncookiez Date: Wed, 3 Apr 2024 16:07:09 -0400 Subject: [PATCH 101/161] cleaned up tsconfigs --- README.md | 2 +- packages/hyperstructure-client-js/tsconfig.json | 2 +- shared/react-components/tsconfig.json | 5 ++++- shared/types/tsconfig.json | 2 +- shared/ui/tsconfig.json | 2 +- shared/utilities/tsconfig.json | 2 +- 6 files changed, 9 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index eb4b667f..a4affcf4 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ This monorepo includes many of PoolTogether's apps and packages in order to faci Make sure you have [pnpm](https://pnpm.io/) installed, as it is the package manager used throughout this monorepo. -`pnpm install` +`pnpm i` ## 🏎️   Quickstart diff --git a/packages/hyperstructure-client-js/tsconfig.json b/packages/hyperstructure-client-js/tsconfig.json index af763d1d..a5331880 100644 --- a/packages/hyperstructure-client-js/tsconfig.json +++ b/packages/hyperstructure-client-js/tsconfig.json @@ -1,7 +1,7 @@ { "extends": "../../shared/config/base.tsconfig.json", "include": ["."], - "exclude": ["dist", "test", "node_modules"], + "exclude": ["dist", "node_modules"], "compilerOptions": { "lib": ["dom", "esnext"], "rootDirs": ["./src", "../../shared"], diff --git a/shared/react-components/tsconfig.json b/shared/react-components/tsconfig.json index e49b8c64..b31a1a6b 100644 --- a/shared/react-components/tsconfig.json +++ b/shared/react-components/tsconfig.json @@ -1,5 +1,8 @@ { "extends": "../config/react.tsconfig.json", "include": ["."], - "exclude": ["dist", "build", "node_modules"] + "exclude": ["dist", "node_modules"], + "compilerOptions": { + "outDir": "dist" + } } diff --git a/shared/types/tsconfig.json b/shared/types/tsconfig.json index 5feb13a9..a6d1bc2a 100644 --- a/shared/types/tsconfig.json +++ b/shared/types/tsconfig.json @@ -1,7 +1,7 @@ { "extends": "../config/base.tsconfig.json", "include": ["."], - "exclude": ["dist", "build", "test", "node_modules"], + "exclude": ["dist", "node_modules"], "compilerOptions": { "lib": ["esnext"], "outDir": "dist" diff --git a/shared/ui/tsconfig.json b/shared/ui/tsconfig.json index fe3be7b6..b31a1a6b 100644 --- a/shared/ui/tsconfig.json +++ b/shared/ui/tsconfig.json @@ -1,7 +1,7 @@ { "extends": "../config/react.tsconfig.json", "include": ["."], - "exclude": ["dist", "build", "node_modules"], + "exclude": ["dist", "node_modules"], "compilerOptions": { "outDir": "dist" } diff --git a/shared/utilities/tsconfig.json b/shared/utilities/tsconfig.json index 089345c1..9b15466d 100644 --- a/shared/utilities/tsconfig.json +++ b/shared/utilities/tsconfig.json @@ -1,7 +1,7 @@ { "extends": "../config/base.tsconfig.json", "include": ["."], - "exclude": ["dist", "build", "test", "node_modules"], + "exclude": ["dist", "node_modules"], "compilerOptions": { "lib": ["dom", "esnext"], "outDir": "dist" From fe28b3aaef02ff33df3d69ef72596ad0957d7643 Mon Sep 17 00:00:00 2001 From: Ncookiez Date: Wed, 3 Apr 2024 16:18:55 -0400 Subject: [PATCH 102/161] fixed shared react-components/ui exports --- shared/react-components/README.md | 47 ++++++++++--------- .../components/Buttons/DelegateButton.tsx | 2 +- .../components/Buttons/DepositButton.tsx | 2 +- .../components/Buttons/SocialShareButton.tsx | 2 +- .../TransactionButton.tsx | 0 .../components/Buttons/WithdrawButton.tsx | 2 +- shared/react-components/index.tsx | 11 ++--- shared/ui/components/Card.tsx | 2 +- 8 files changed, 35 insertions(+), 33 deletions(-) rename shared/react-components/components/{Transaction => Buttons}/TransactionButton.tsx (100%) diff --git a/shared/react-components/README.md b/shared/react-components/README.md index ce80ef96..2580c182 100644 --- a/shared/react-components/README.md +++ b/shared/react-components/README.md @@ -18,47 +18,41 @@ A React componponent library utilizing some simpler components from the internal ## 🐱‍👤   Available Components -### Badge Components +### Badges - `ImportedBadge` - `NetworkBadge` - `PrizePoolBadge` - `VaultBadge` -### Button Components +### Buttons - `DelegateButton` - `DepositButton` - `SocialShareButton` +- `TransactionButton` - `WithdrawButton` -### Currency Components +### Currency - `CurrencyValue` - `TokenAmount` - `TokenValue` - `TokenValueAndAmount` -### Modals - -- `DepositModal` -- `CheckPrizesModal` -- `DrawModal` -- `SettingsModal` -- `WithdrawModal` - -### Form Components +### Forms +- `DelegateForm` - `DepositForm` -- `WithdrawForm` - `TxFormInput` +- `WithdrawForm` -### Graphic Components +### Graphics - `ErrorPooly` - `SuccessPooly` -### Icon Components +### Icons - `AlertIcon` - `ClipboardListIcon` @@ -67,25 +61,38 @@ A React componponent library utilizing some simpler components from the internal - `SuccessIcon` - `TokenIcon` -### Prize Pool Components +### Modals + +- `CaptchaModal` +- `CheckPrizesModal` +- `DelegateModal` +- `DepositModal` +- `DrawModal` +- `SettingsModal` +- `WithdrawModal` + +### Prize Pool - `PrizePoolCard` - `PrizePoolDropdown` -### Toast Components +### Toasts +- `DelegateTxToast` - `DeployLiquidationPairTxToast` - `DeployVaultTxToast` - `DepositTxToast` +- `SetClaimerTxToast` - `SetLiquidationPairTxToast` - `VaultListToast` - `WithdrawTxToast` -### Tooltip Components +### Tooltips - `ApprovalTooltip` - `BadPrecisionPerDollarTooltip` - `BonusRewardsTooltip` +- `DelegationDescriptionTooltip` - `DeprecatedVaultTooltip` - `ImportedVaultTooltip` - `PrizeYieldTooltip` @@ -93,7 +100,3 @@ A React componponent library utilizing some simpler components from the internal - `VaultFeeTooltip` - `WinChanceTooltip` - `YieldSourceURITooltip` - -### Transaction Components - -- `TransactionButton` diff --git a/shared/react-components/components/Buttons/DelegateButton.tsx b/shared/react-components/components/Buttons/DelegateButton.tsx index e362e376..60366482 100644 --- a/shared/react-components/components/Buttons/DelegateButton.tsx +++ b/shared/react-components/components/Buttons/DelegateButton.tsx @@ -5,7 +5,7 @@ import { Button, ButtonProps } from '@shared/ui' import classNames from 'classnames' import { ReactNode } from 'react' -interface DelegateButtonProps extends Omit { +export interface DelegateButtonProps extends Omit { vault: Vault children?: ReactNode className?: string diff --git a/shared/react-components/components/Buttons/DepositButton.tsx b/shared/react-components/components/Buttons/DepositButton.tsx index af7068ae..08d6eeff 100644 --- a/shared/react-components/components/Buttons/DepositButton.tsx +++ b/shared/react-components/components/Buttons/DepositButton.tsx @@ -13,7 +13,7 @@ import { Address } from 'viem' import { BadPrecisionPerDollarTooltip } from '../Tooltips/BadPrecisionPerDollarTooltip' import { DeprecatedVaultTooltip } from '../Tooltips/DeprecatedVaultTooltip' -interface DepositButtonProps extends Omit { +export interface DepositButtonProps extends Omit { vault: Vault intl?: { base: Intl<'deposit'> diff --git a/shared/react-components/components/Buttons/SocialShareButton.tsx b/shared/react-components/components/Buttons/SocialShareButton.tsx index 6ddb3793..cb5d8802 100644 --- a/shared/react-components/components/Buttons/SocialShareButton.tsx +++ b/shared/react-components/components/Buttons/SocialShareButton.tsx @@ -1,7 +1,7 @@ import { Button, ButtonProps, SocialIcon } from '@shared/ui' import { LINKS } from '@shared/utilities' -interface SocialShareButtonProps extends Omit { +export interface SocialShareButtonProps extends Omit { platform: 'twitter' | 'warpcast' | 'hey' text?: string hashTags?: string[] diff --git a/shared/react-components/components/Transaction/TransactionButton.tsx b/shared/react-components/components/Buttons/TransactionButton.tsx similarity index 100% rename from shared/react-components/components/Transaction/TransactionButton.tsx rename to shared/react-components/components/Buttons/TransactionButton.tsx diff --git a/shared/react-components/components/Buttons/WithdrawButton.tsx b/shared/react-components/components/Buttons/WithdrawButton.tsx index 710ad35c..318805b9 100644 --- a/shared/react-components/components/Buttons/WithdrawButton.tsx +++ b/shared/react-components/components/Buttons/WithdrawButton.tsx @@ -4,7 +4,7 @@ import { MODAL_KEYS, useIsModalOpen } from '@shared/generic-react-hooks' import { Button, ButtonProps } from '@shared/ui' import classNames from 'classnames' -interface WithdrawButtonProps extends Omit { +export interface WithdrawButtonProps extends Omit { vault: Vault } diff --git a/shared/react-components/index.tsx b/shared/react-components/index.tsx index 6e76f668..7267cbf5 100644 --- a/shared/react-components/index.tsx +++ b/shared/react-components/index.tsx @@ -12,6 +12,7 @@ export * from './components/Badges/VaultBadge' export * from './components/Buttons/DelegateButton' export * from './components/Buttons/DepositButton' export * from './components/Buttons/SocialShareButton' +export * from './components/Buttons/TransactionButton' export * from './components/Buttons/WithdrawButton' /** @@ -23,8 +24,9 @@ export * from './components/Currency/TokenValue' export * from './components/Currency/TokenValueAndAmount' /** - * Form + * Forms */ +export * from './components/Form/DelegateForm' export * from './components/Form/DepositForm' export * from './components/Form/TxFormInput' export * from './components/Form/WithdrawForm' @@ -65,6 +67,7 @@ export * from './components/PrizePool/PrizePoolDropdown' /** * Toasts */ +export * from './components/Toasts/DelegateTxToast' export * from './components/Toasts/DeployLiquidationPairTxToast' export * from './components/Toasts/DeployVaultTxToast' export * from './components/Toasts/DepositTxToast' @@ -79,6 +82,7 @@ export * from './components/Toasts/WithdrawTxToast' export * from './components/Tooltips/ApprovalTooltip' export * from './components/Tooltips/BadPrecisionPerDollarTooltip' export * from './components/Tooltips/BonusRewardsTooltip' +export * from './components/Tooltips/DelegationDescriptionTooltip' export * from './components/Tooltips/DeprecatedVaultTooltip' export * from './components/Tooltips/ImportedVaultTooltip' export * from './components/Tooltips/PrizeYieldTooltip' @@ -87,11 +91,6 @@ export * from './components/Tooltips/VaultFeeTooltip' export * from './components/Tooltips/WinChanceTooltip' export * from './components/Tooltips/YieldSourceURITooltip' -/** - * Transaction - */ -export * from './components/Transaction/TransactionButton' - /** * Constants */ diff --git a/shared/ui/components/Card.tsx b/shared/ui/components/Card.tsx index 7dea869b..63d40000 100644 --- a/shared/ui/components/Card.tsx +++ b/shared/ui/components/Card.tsx @@ -1,7 +1,7 @@ import classNames from 'classnames' import { Card as FlowbiteCard, CardProps as FlowbiteCardProps } from 'flowbite-react' -type CardProps = FlowbiteCardProps & { +export type CardProps = FlowbiteCardProps & { className?: string wrapperClassName?: string } From 4445f1e395ad40ad81df745a1ccfdb78094cbddf Mon Sep 17 00:00:00 2001 From: Ncookiez Date: Wed, 3 Apr 2024 16:23:08 -0400 Subject: [PATCH 103/161] simplified app's `getMessages` --- apps/app/src/pages/404.tsx | 2 +- apps/app/src/pages/account/[user].tsx | 2 +- apps/app/src/pages/account/index.tsx | 2 +- apps/app/src/pages/index.tsx | 2 +- apps/app/src/pages/prizes.tsx | 2 +- apps/app/src/pages/vault/[chainId]/[vaultAddress].tsx | 2 +- apps/app/src/pages/vaults.tsx | 2 +- apps/app/src/utils.ts | 7 ++----- 8 files changed, 9 insertions(+), 12 deletions(-) diff --git a/apps/app/src/pages/404.tsx b/apps/app/src/pages/404.tsx index 04140089..2686e25c 100644 --- a/apps/app/src/pages/404.tsx +++ b/apps/app/src/pages/404.tsx @@ -9,7 +9,7 @@ interface Custom404PageProps { } export const getStaticProps: GetStaticProps = async ({ locale }) => { - const messages = await getMessages(locale, { useDefault: true }) + const messages = await getMessages(locale) return { props: { messages }, diff --git a/apps/app/src/pages/account/[user].tsx b/apps/app/src/pages/account/[user].tsx index 3f6aaf34..adfbd0d5 100644 --- a/apps/app/src/pages/account/[user].tsx +++ b/apps/app/src/pages/account/[user].tsx @@ -17,7 +17,7 @@ interface ExternalAccountPageProps { } export const getStaticProps: GetStaticProps = async ({ locale }) => { - const messages = await getMessages(locale, { useDefault: true }) + const messages = await getMessages(locale) return { props: { messages }, diff --git a/apps/app/src/pages/account/index.tsx b/apps/app/src/pages/account/index.tsx index 79ff0d5b..0416519c 100644 --- a/apps/app/src/pages/account/index.tsx +++ b/apps/app/src/pages/account/index.tsx @@ -14,7 +14,7 @@ interface AccountPageProps { } export const getStaticProps: GetStaticProps = async ({ locale }) => { - const messages = await getMessages(locale, { useDefault: true }) + const messages = await getMessages(locale) return { props: { messages }, diff --git a/apps/app/src/pages/index.tsx b/apps/app/src/pages/index.tsx index f821583d..82ffabba 100644 --- a/apps/app/src/pages/index.tsx +++ b/apps/app/src/pages/index.tsx @@ -13,7 +13,7 @@ interface HomePageProps { } export const getStaticProps: GetStaticProps = async ({ locale }) => { - const messages = await getMessages(locale, { useDefault: true }) + const messages = await getMessages(locale) return { props: { messages }, diff --git a/apps/app/src/pages/prizes.tsx b/apps/app/src/pages/prizes.tsx index a86d334d..7b030be9 100644 --- a/apps/app/src/pages/prizes.tsx +++ b/apps/app/src/pages/prizes.tsx @@ -14,7 +14,7 @@ interface PrizesPageProps { } export const getStaticProps: GetStaticProps = async ({ locale }) => { - const messages = await getMessages(locale, { useDefault: true }) + const messages = await getMessages(locale) return { props: { messages }, diff --git a/apps/app/src/pages/vault/[chainId]/[vaultAddress].tsx b/apps/app/src/pages/vault/[chainId]/[vaultAddress].tsx index a0ea816b..f497bb90 100644 --- a/apps/app/src/pages/vault/[chainId]/[vaultAddress].tsx +++ b/apps/app/src/pages/vault/[chainId]/[vaultAddress].tsx @@ -17,7 +17,7 @@ interface VaultPageProps { } export const getStaticProps: GetStaticProps = async ({ locale }) => { - const messages = await getMessages(locale, { useDefault: true }) + const messages = await getMessages(locale) return { props: { messages }, diff --git a/apps/app/src/pages/vaults.tsx b/apps/app/src/pages/vaults.tsx index 23a9d3d7..505bb620 100644 --- a/apps/app/src/pages/vaults.tsx +++ b/apps/app/src/pages/vaults.tsx @@ -11,7 +11,7 @@ interface VaultsPageProps { } export const getStaticProps: GetStaticProps = async ({ locale }) => { - const messages = await getMessages(locale, { useDefault: true }) + const messages = await getMessages(locale) return { props: { messages }, diff --git a/apps/app/src/utils.ts b/apps/app/src/utils.ts index 447538fb..d9cf9e13 100644 --- a/apps/app/src/utils.ts +++ b/apps/app/src/utils.ts @@ -119,18 +119,15 @@ const getNetworkTransports = ( /** * Returns messages for localization through next-intl * @param locale the locale to fetch messages for - * @param options optional settings * @returns */ -export const getMessages = async (locale?: string, options?: { useDefault?: boolean }) => { +export const getMessages = async (locale?: string) => { const defaultMessages: IntlMessages = (await import(`../messages/en.json`)).default if (!locale) return defaultMessages const localeMessages: IntlMessages = (await import(`../messages/${locale}.json`)).default - const messages = options?.useDefault - ? deepmerge(defaultMessages, localeMessages) - : localeMessages + const messages = deepmerge(defaultMessages, localeMessages) return messages } From da58dd93d2411c7e2d5bfbcebbbbca0be9500fef Mon Sep 17 00:00:00 2001 From: Ncookiez Date: Wed, 3 Apr 2024 16:25:33 -0400 Subject: [PATCH 104/161] updated app's meta keywords --- apps/analytics/src/pages/_document.tsx | 2 +- apps/app/src/pages/_document.tsx | 3 ++- apps/flash-liquidator/src/pages/_document.tsx | 2 +- apps/incentives/src/pages/_document.tsx | 2 +- apps/landing-page/src/pages/_document.tsx | 2 +- apps/migrations/src/pages/_document.tsx | 2 +- apps/rewards-builder/src/pages/_document.tsx | 2 +- apps/swaps/src/pages/_document.tsx | 3 ++- apps/vault-factory/src/pages/_document.tsx | 3 ++- apps/vaultlist-creator/src/pages/_document.tsx | 2 +- 10 files changed, 13 insertions(+), 10 deletions(-) diff --git a/apps/analytics/src/pages/_document.tsx b/apps/analytics/src/pages/_document.tsx index ecb1f68f..d6792a7e 100644 --- a/apps/analytics/src/pages/_document.tsx +++ b/apps/analytics/src/pages/_document.tsx @@ -19,7 +19,7 @@ class MyDocument extends Document { const title = 'Cabanalytics' const description = 'View analytics and health metrics for the PoolTogether Hyperstructure.' const keywords = - 'prize savings win save protocol blockchain vault ethereum stats analytics draws liquidations bots' + 'pooltogether prize savings win save protocol blockchain vault ethereum stats analytics draws liquidations bots' return ( diff --git a/apps/app/src/pages/_document.tsx b/apps/app/src/pages/_document.tsx index 01ea52d1..96f442da 100644 --- a/apps/app/src/pages/_document.tsx +++ b/apps/app/src/pages/_document.tsx @@ -18,7 +18,8 @@ class MyDocument extends Document { render() { const title = 'Cabana App' const description = 'Browse, deposit into and withdraw from any number of PoolTogether vaults.' - const keywords = 'prize savings win save protocol blockchain vault vaultlist 4626 ethereum' + const keywords = + 'pooltogether prize savings win save protocol blockchain vault vaultlist 4626 ethereum' return ( diff --git a/apps/flash-liquidator/src/pages/_document.tsx b/apps/flash-liquidator/src/pages/_document.tsx index 5f3e3507..cf1a91a7 100644 --- a/apps/flash-liquidator/src/pages/_document.tsx +++ b/apps/flash-liquidator/src/pages/_document.tsx @@ -19,7 +19,7 @@ class MyDocument extends Document { const title = 'Cabana Flash Liquidator' const description = 'Flash liquidate yield from any PoolTogether prize vault.' const keywords = - 'prize savings win save protocol blockchain ethereum optimism tool flash liquidate liquidations' + 'pooltogether prize savings win save protocol blockchain ethereum optimism tool flash liquidate liquidations' return ( diff --git a/apps/incentives/src/pages/_document.tsx b/apps/incentives/src/pages/_document.tsx index a6da438d..4b4bfaf4 100644 --- a/apps/incentives/src/pages/_document.tsx +++ b/apps/incentives/src/pages/_document.tsx @@ -20,7 +20,7 @@ class MyDocument extends Document { const description = 'Want to contribute to the global prize savings hyperstructure? View all the tools and incentives at your disposal.' const keywords = - 'prize savings win save protocol blockchain pool together incentives contribute builders' + 'pooltogether prize savings win save protocol blockchain incentives contribute builders' return ( diff --git a/apps/landing-page/src/pages/_document.tsx b/apps/landing-page/src/pages/_document.tsx index de52304e..8eef1808 100644 --- a/apps/landing-page/src/pages/_document.tsx +++ b/apps/landing-page/src/pages/_document.tsx @@ -19,7 +19,7 @@ class MyDocument extends Document { const title = 'Cabana' const description = 'Welcome to Cabana, a suite of open source interfaces and tools for the PoolTogether Hyperstructure.' - const keywords = 'prize savings win save protocol blockchain pool together tools' + const keywords = 'pooltogether prize savings win save protocol blockchain tools' return ( diff --git a/apps/migrations/src/pages/_document.tsx b/apps/migrations/src/pages/_document.tsx index fcd53fe4..90764ed4 100644 --- a/apps/migrations/src/pages/_document.tsx +++ b/apps/migrations/src/pages/_document.tsx @@ -19,7 +19,7 @@ class MyDocument extends Document { const title = 'PoolTogether Migrations' const description = 'Easily migrate funds in old versions of the PoolTogether protocol.' const keywords = - 'prize savings win save protocol blockchain vault ethereum polygon avalanche celo v3 v4 v5' + 'pooltogether prize savings win save protocol blockchain vault ethereum polygon avalanche celo v3 v4 v5' return ( diff --git a/apps/rewards-builder/src/pages/_document.tsx b/apps/rewards-builder/src/pages/_document.tsx index ef3cfcbf..cd334be3 100644 --- a/apps/rewards-builder/src/pages/_document.tsx +++ b/apps/rewards-builder/src/pages/_document.tsx @@ -19,7 +19,7 @@ class MyDocument extends Document { const title = 'Cabana Rewards Builder' const description = 'Create and manage rewards for any PoolTogether prize vault.' const keywords = - 'prize savings win save protocol blockchain vault 4626 ethereum optimism arbitrum tool rewards' + 'pooltogether prize savings win save protocol blockchain vault 4626 ethereum optimism arbitrum tool rewards' return ( diff --git a/apps/swaps/src/pages/_document.tsx b/apps/swaps/src/pages/_document.tsx index 5d3b5dd3..5998ba2b 100644 --- a/apps/swaps/src/pages/_document.tsx +++ b/apps/swaps/src/pages/_document.tsx @@ -18,7 +18,8 @@ class MyDocument extends Document { render() { const title = 'Cabana Swaps' const description = 'Browse and swap into your favorite PoolTogether vaults.' - const keywords = 'prize savings win save protocol blockchain vault ethereum swap swaps' + const keywords = + 'pooltogether prize savings win save protocol blockchain vault ethereum swap swaps' return ( diff --git a/apps/vault-factory/src/pages/_document.tsx b/apps/vault-factory/src/pages/_document.tsx index 9238b4c2..488b5457 100644 --- a/apps/vault-factory/src/pages/_document.tsx +++ b/apps/vault-factory/src/pages/_document.tsx @@ -18,7 +18,8 @@ class MyDocument extends Document { render() { const title = 'Cabana Factory' const description = 'Create and manage your PoolTogether Hyperstructure ERC-4626 vaults.' - const keywords = 'prize savings win save protocol blockchain vault 4626 ethereum tool factory' + const keywords = + 'pooltogether prize savings win save protocol blockchain vault 4626 ethereum tool factory' return ( diff --git a/apps/vaultlist-creator/src/pages/_document.tsx b/apps/vaultlist-creator/src/pages/_document.tsx index 7d2f6e0b..ea008d8b 100644 --- a/apps/vaultlist-creator/src/pages/_document.tsx +++ b/apps/vaultlist-creator/src/pages/_document.tsx @@ -18,7 +18,7 @@ class MyDocument extends Document { render() { const title = 'Cabana Lists' const description = 'Create your very own PoolTogether vaultlists.' - const keywords = 'prize savings win save protocol blockchain vaultlist' + const keywords = 'pooltogether prize savings win save protocol blockchain vaultlist' return ( From 98d96f8e88efbe58e87815ccbd3dd8595c0852fd Mon Sep 17 00:00:00 2001 From: Ncookiez Date: Wed, 3 Apr 2024 16:26:06 -0400 Subject: [PATCH 105/161] removed `prizeCalc` url --- shared/utilities/constants.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/shared/utilities/constants.ts b/shared/utilities/constants.ts index 93cc6927..49880ca9 100644 --- a/shared/utilities/constants.ts +++ b/shared/utilities/constants.ts @@ -370,7 +370,6 @@ export const LINKS = { tally: `https://www.tally.xyz/gov/pooltogether`, treasury: `https://info.pooltogether.com/treasury`, dune_v4: `https://dune.com/sarfang/PoolTogetherV4`, - prizeCalc: `https://prizecalc.com`, grants: `https://poolgrants.org`, hey: `https://hey.xyz/u/pooltogether`, mirror: `https://pooltogether.mirror.xyz/`, From 276b488985a38070a1a60c8b727953f43f67c4f0 Mon Sep 17 00:00:00 2001 From: Ncookiez Date: Wed, 3 Apr 2024 16:57:29 -0400 Subject: [PATCH 106/161] fixed `TransactionButton` ref --- .../components/Modals/DelegateModal/DelegateTxButton.tsx | 2 +- .../components/Modals/DepositModal/DepositTxButton.tsx | 2 +- .../Modals/DepositModal/DepositWithPermitTxButton.tsx | 2 +- .../components/Modals/WithdrawModal/WithdrawTxButton.tsx | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/shared/react-components/components/Modals/DelegateModal/DelegateTxButton.tsx b/shared/react-components/components/Modals/DelegateModal/DelegateTxButton.tsx index ab9b477c..348dc582 100644 --- a/shared/react-components/components/Modals/DelegateModal/DelegateTxButton.tsx +++ b/shared/react-components/components/Modals/DelegateModal/DelegateTxButton.tsx @@ -10,9 +10,9 @@ import { useEffect } from 'react' import { Address, isAddress } from 'viem' import { useAccount } from 'wagmi' import { DelegateModalView } from '.' +import { TransactionButton } from '../../Buttons/TransactionButton' import { delegateFormNewDelegateAddressAtom } from '../../Form/DelegateForm' import { createDelegateTxToast, DelegateTxToastProps } from '../../Toasts/DelegateTxToast' -import { TransactionButton } from '../../Transaction/TransactionButton' interface DelegateTxButtonProps { twabController: Address diff --git a/shared/react-components/components/Modals/DepositModal/DepositTxButton.tsx b/shared/react-components/components/Modals/DepositModal/DepositTxButton.tsx index 2e07278f..3c1e2e3f 100644 --- a/shared/react-components/components/Modals/DepositModal/DepositTxButton.tsx +++ b/shared/react-components/components/Modals/DepositModal/DepositTxButton.tsx @@ -16,10 +16,10 @@ import { useEffect } from 'react' import { Address, parseUnits } from 'viem' import { useAccount } from 'wagmi' import { DepositModalView } from '.' +import { TransactionButton } from '../../Buttons/TransactionButton' import { depositFormTokenAmountAtom } from '../../Form/DepositForm' import { isValidFormInput } from '../../Form/TxFormInput' import { ApprovalTooltip } from '../../Tooltips/ApprovalTooltip' -import { TransactionButton } from '../../Transaction/TransactionButton' interface DepositTxButtonProps { vault: Vault diff --git a/shared/react-components/components/Modals/DepositModal/DepositWithPermitTxButton.tsx b/shared/react-components/components/Modals/DepositModal/DepositWithPermitTxButton.tsx index 5fd95b14..2759ea12 100644 --- a/shared/react-components/components/Modals/DepositModal/DepositWithPermitTxButton.tsx +++ b/shared/react-components/components/Modals/DepositModal/DepositWithPermitTxButton.tsx @@ -17,9 +17,9 @@ import { useEffect, useState } from 'react' import { Address, parseUnits } from 'viem' import { useAccount } from 'wagmi' import { DepositModalView } from '.' +import { TransactionButton } from '../../Buttons/TransactionButton' import { depositFormTokenAmountAtom } from '../../Form/DepositForm' import { isValidFormInput } from '../../Form/TxFormInput' -import { TransactionButton } from '../../Transaction/TransactionButton' interface DepositWithPermitTxButtonProps { vault: Vault diff --git a/shared/react-components/components/Modals/WithdrawModal/WithdrawTxButton.tsx b/shared/react-components/components/Modals/WithdrawModal/WithdrawTxButton.tsx index d5f6082d..d357c84c 100644 --- a/shared/react-components/components/Modals/WithdrawModal/WithdrawTxButton.tsx +++ b/shared/react-components/components/Modals/WithdrawModal/WithdrawTxButton.tsx @@ -16,9 +16,9 @@ import { useEffect } from 'react' import { Address, parseUnits } from 'viem' import { useAccount } from 'wagmi' import { WithdrawModalView } from '.' +import { TransactionButton } from '../../Buttons/TransactionButton' import { isValidFormInput } from '../../Form/TxFormInput' import { withdrawFormShareAmountAtom } from '../../Form/WithdrawForm' -import { TransactionButton } from '../../Transaction/TransactionButton' interface WithdrawTxButtonProps { vault: Vault From 275dfb989a3e5e340262ab71653f78535f218c6c Mon Sep 17 00:00:00 2001 From: Ncookiez Date: Wed, 3 Apr 2024 16:57:43 -0400 Subject: [PATCH 107/161] updated `next-intl` to latest --- apps/app/package.json | 2 +- apps/app/src/components/AppContainer.tsx | 6 +- pnpm-lock.yaml | 10908 +++++---------------- 3 files changed, 2707 insertions(+), 8209 deletions(-) diff --git a/apps/app/package.json b/apps/app/package.json index 1e6286d9..ec9bd5bc 100644 --- a/apps/app/package.json +++ b/apps/app/package.json @@ -23,7 +23,7 @@ "jotai": "^1.13.1", "lottie-react": "^2.4.0", "next": "14.1.0", - "next-intl": "^2.15.1", + "next-intl": "^3.11.0", "react": "^18.2.0", "react-dom": "^18.2.0", "react-hook-form": "^7.43.2", diff --git a/apps/app/src/components/AppContainer.tsx b/apps/app/src/components/AppContainer.tsx index e39ff404..faa9907f 100644 --- a/apps/app/src/components/AppContainer.tsx +++ b/apps/app/src/components/AppContainer.tsx @@ -1,6 +1,6 @@ import { useSelectedLanguage } from '@shared/generic-react-hooks' import { Flowbite, Toaster } from '@shared/ui' -import { NextIntlProvider } from 'next-intl' +import { NextIntlClientProvider } from 'next-intl' import { AppProps } from 'next/app' import { useRouter } from 'next/router' import { useEffect, useState } from 'react' @@ -34,10 +34,10 @@ export const AppContainer = (props: AppProps) => { return ( - +