From 6869c52771949a044d50f1b4cd1ab19f234ccb19 Mon Sep 17 00:00:00 2001 From: Tal Derei <70081547+TalDerei@users.noreply.github.com> Date: Sun, 26 Jan 2025 19:41:55 -0800 Subject: [PATCH] chore: extend alternative fees to LPs (#1980) * extend alternative fees to LPs * changeset * LPs default to priority fee selection * fix comment * prioritize usdc alt fees * linting * Update packages/storage/src/indexed-db/index.ts Co-authored-by: Erwan Or * linting * lint please --------- Co-authored-by: Erwan Or --- .changeset/kind-coins-tap.md | 7 ++++ packages/services/src/view-service/fees.ts | 48 +++++++++++++++++++--- packages/storage/src/indexed-db/index.ts | 28 ++++++++++++- packages/types/src/indexed-db.ts | 2 + 4 files changed, 78 insertions(+), 7 deletions(-) create mode 100644 .changeset/kind-coins-tap.md diff --git a/.changeset/kind-coins-tap.md b/.changeset/kind-coins-tap.md new file mode 100644 index 0000000000..9b0cdd4e9a --- /dev/null +++ b/.changeset/kind-coins-tap.md @@ -0,0 +1,7 @@ +--- +'@penumbra-zone/services': minor +'@penumbra-zone/storage': minor +'@penumbra-zone/types': minor +--- + +extend alternative fees to LPs diff --git a/packages/services/src/view-service/fees.ts b/packages/services/src/view-service/fees.ts index 7a243ef02e..c24da5b808 100644 --- a/packages/services/src/view-service/fees.ts +++ b/packages/services/src/view-service/fees.ts @@ -3,6 +3,16 @@ import { TransactionPlannerRequest } from '@penumbra-zone/protobuf/penumbra/view import { assetIdFromBaseDenom } from '@penumbra-zone/wasm/asset'; import { IndexedDbInterface } from '@penumbra-zone/types/indexed-db'; +// TODO: change other transaction planner request types to default to priority fee selection +// that's agonsitic to the underlying action. +const prioritySelection = (request: TransactionPlannerRequest): boolean => { + return ( + request.positionOpens.length > 0 || + request.positionCloses.length > 0 || + request.positionWithdraws.length > 0 + ); +}; + // Attempts to extract a fee token, with priority in descending order, from the assets used // in the actions of the transaction planner request (TPR). If no fee token is found from the // specified assets, it falls back to checking the gas prices table for an asset with a positive balance. @@ -89,6 +99,30 @@ export const extractAltFee = async ( } } + const positionOpen = request.positionOpens.map(assetIn => assetIn.position).find(Boolean); + if (positionOpen) { + const assetId = await getAssetFromGasPriceTable(request, indexedDb); + if (assetId) { + return assetId; + } + } + + const positionClose = request.positionCloses.map(a => a.positionId).find(Boolean); + if (positionClose) { + const assetId = await getAssetFromGasPriceTable(request, indexedDb); + if (assetId) { + return assetId; + } + } + + const positonWithdraw = request.positionWithdraws.map(a => a.positionId).find(Boolean); + if (positonWithdraw) { + const assetId = await getAssetFromGasPriceTable(request, indexedDb); + if (assetId) { + return assetId; + } + } + if (request.undelegations.length > 0) { const assetId = await getAssetFromGasPriceTable(request, indexedDb); if (assetId) { @@ -116,12 +150,14 @@ export const getAssetFromGasPriceTable = async ( // If a specific asset ID is provided, extracted from the transaction request, check its balance is // positive and GasPrices for that asset exist. - if (assetId) { - const balance = await indexedDb.hasTokenBalance(request.source.account, assetId); - // This check ensures that the alternative fee token is a valid fee token, for example, TestUSD is not. - const isInGasTable = altGasPrices.find(gp => gp.assetId?.equals(assetId)); - if (balance && isInGasTable) { - return assetId; + if (!prioritySelection(request)) { + if (assetId) { + const balance = await indexedDb.hasTokenBalance(request.source.account, assetId); + // This check ensures that the alternative fee token is a valid fee token, for example, TestUSD is not. + const isInGasTable = altGasPrices.find(gp => gp.assetId?.equals(assetId)); + if (balance && isInGasTable) { + return assetId; + } } } diff --git a/packages/storage/src/indexed-db/index.ts b/packages/storage/src/indexed-db/index.ts index fc9ec47c00..77d83969da 100644 --- a/packages/storage/src/indexed-db/index.ts +++ b/packages/storage/src/indexed-db/index.ts @@ -472,9 +472,24 @@ export class IndexedDb implements IndexedDbInterface { async getAltGasPrices(): Promise { const allGasPrices = await this.db.getAll('GAS_PRICES'); + const usdcPriorityAssetId = 'drPksQaBNYwSOzgfkGOEdrd4kEDkeALeh58Ps+7cjQs='; + + // Retrieve gas prices from the database and prioritize USDC as the preferred asset. return allGasPrices .map(gp => GasPrices.fromJson(gp)) - .filter(gp => !gp.assetId?.equals(this.stakingTokenAssetId)); + .filter(gp => gp.assetId?.inner && !gp.assetId.equals(this.stakingTokenAssetId)) + .sort((a, b) => { + const assetA = a.assetId?.inner ? uint8ArrayToBase64(a.assetId.inner) : ''; + const assetB = b.assetId?.inner ? uint8ArrayToBase64(b.assetId.inner) : ''; + + if (assetA === usdcPriorityAssetId) { + return -1; + } + if (assetB === usdcPriorityAssetId) { + return 1; + } + return 0; + }); } async saveGasPrices(value: Required>): Promise { @@ -993,4 +1008,15 @@ export class IndexedDb implements IndexedDbInterface { new Amount({ hi: 0n, lo: 0n }), ); } + + async getPosition(positionId: PositionId): Promise { + assertPositionId(positionId); + const position = await this.db.get('POSITIONS', uint8ArrayToBase64(positionId.inner)); + + if (!position) { + return undefined; + } + + return Position.fromJson(position.position); + } } diff --git a/packages/types/src/indexed-db.ts b/packages/types/src/indexed-db.ts index 45395dfd26..bfc1137665 100644 --- a/packages/types/src/indexed-db.ts +++ b/packages/types/src/indexed-db.ts @@ -153,6 +153,8 @@ export interface IndexedDbInterface { hasTokenBalance(addressIndex: number, assetId: AssetId): Promise; totalNoteBalance(accountIndex: number, assetId: AssetId): Promise; + + getPosition(positionId: PositionId): Promise; } export interface PenumbraDb extends DBSchema {