Skip to content

Commit

Permalink
chore: extend alternative fees to LPs (#1980)
Browse files Browse the repository at this point in the history
* 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 <erwan.ounn.84@gmail.com>

* linting

* lint please

---------

Co-authored-by: Erwan Or <erwan.ounn.84@gmail.com>
  • Loading branch information
TalDerei and erwanor authored Jan 27, 2025
1 parent 0c9e1ea commit 6869c52
Show file tree
Hide file tree
Showing 4 changed files with 78 additions and 7 deletions.
7 changes: 7 additions & 0 deletions .changeset/kind-coins-tap.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'@penumbra-zone/services': minor
'@penumbra-zone/storage': minor
'@penumbra-zone/types': minor
---

extend alternative fees to LPs
48 changes: 42 additions & 6 deletions packages/services/src/view-service/fees.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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;
}
}
}

Expand Down
28 changes: 27 additions & 1 deletion packages/storage/src/indexed-db/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -472,9 +472,24 @@ export class IndexedDb implements IndexedDbInterface {

async getAltGasPrices(): Promise<GasPrices[]> {
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<PlainMessage<GasPrices>>): Promise<void> {
Expand Down Expand Up @@ -993,4 +1008,15 @@ export class IndexedDb implements IndexedDbInterface {
new Amount({ hi: 0n, lo: 0n }),
);
}

async getPosition(positionId: PositionId): Promise<Position | undefined> {
assertPositionId(positionId);
const position = await this.db.get('POSITIONS', uint8ArrayToBase64(positionId.inner));

if (!position) {
return undefined;
}

return Position.fromJson(position.position);
}
}
2 changes: 2 additions & 0 deletions packages/types/src/indexed-db.ts
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,8 @@ export interface IndexedDbInterface {
hasTokenBalance(addressIndex: number, assetId: AssetId): Promise<boolean>;

totalNoteBalance(accountIndex: number, assetId: AssetId): Promise<Amount>;

getPosition(positionId: PositionId): Promise<Position | undefined>;
}

export interface PenumbraDb extends DBSchema {
Expand Down

0 comments on commit 6869c52

Please sign in to comment.