Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions packages/blockchain-api/src/lib/constants/tokens.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
import { Connection, PublicKey } from "@solana/web3.js";
import { getMint } from "@solana/spl-token";

/**
* Common token mint addresses on Solana mainnet
*/
Expand Down Expand Up @@ -33,3 +36,20 @@ export const TOKEN_DECIMALS: Record<string, number> = {
[TOKEN_MINTS.IOT]: 6,
[TOKEN_MINTS.DC]: 0,
};

const decimalsCache = new Map<string, number>(Object.entries(TOKEN_DECIMALS));

/**
* Get decimals for a token mint. Returns from static map for known tokens,
* otherwise fetches from RPC and caches the result.
*/
export async function getTokenDecimals(mint: string): Promise<number> {
const cached = decimalsCache.get(mint);
if (cached !== undefined) return cached;

const { env } = await import("@/lib/env");
const connection = new Connection(env.SOLANA_RPC_URL);
const mintInfo = await getMint(connection, new PublicKey(mint));
decimalsCache.set(mint, mintInfo.decimals);
return mintInfo.decimals;
}
24 changes: 11 additions & 13 deletions packages/blockchain-api/src/lib/utils/token-math.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,11 @@ import type {
TokenAmountInput,
TokenAmountOutput,
} from "@helium/blockchain-api/schemas/common";
import { TOKEN_DECIMALS, TOKEN_MINTS } from "@/lib/constants/tokens";
import {
TOKEN_DECIMALS,
TOKEN_MINTS,
getTokenDecimals,
} from "@/lib/constants/tokens";

export const HNT_DECIMALS = TOKEN_DECIMALS[TOKEN_MINTS.HNT];
const HNT_DIVISOR = new BN(10).pow(new BN(HNT_DECIMALS));
Expand All @@ -27,19 +31,16 @@ export function solToLamportsBN(sol: number): BN {
return new BN(Math.round(sol * 10 ** SOL_DECIMALS));
}

export function resolveTokenAmountInput(
export async function resolveTokenAmountInput(
input: TokenAmountInput,
expectedMint?: string,
): BN {
): Promise<BN> {
if (expectedMint && input.mint !== expectedMint) {
throw new Error(
`Mint mismatch: expected ${expectedMint}, got ${input.mint}`,
);
}
const decimals = TOKEN_DECIMALS[input.mint];
if (decimals === undefined) {
throw new Error(`Unknown mint: ${input.mint}`);
}
await getTokenDecimals(input.mint);
return new BN(input.amount);
}

Expand All @@ -54,14 +55,11 @@ function formatTokenAmount(raw: string, decimals: number): string {
return isNegative ? `-${result}` : result;
}

export function toTokenAmountOutput(
export async function toTokenAmountOutput(
rawAmount: BN,
mint: string,
): TokenAmountOutput {
const decimals = TOKEN_DECIMALS[mint];
if (decimals === undefined) {
throw new Error(`Unknown mint: ${mint}`);
}
): Promise<TokenAmountOutput> {
const decimals = await getTokenDecimals(mint);

const amount = rawAmount.toString();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -632,7 +632,7 @@ const sendFunds = publicProcedure.fiat.sendFunds.handler(
tag,
actionMetadata: { type: "bank_send", usdAmount: (parseFloat(quoteResponse.outAmount) / 1e6).toFixed(2), bankAccountId: id },
},
estimatedSolFee: toTokenAmountOutput(
estimatedSolFee: await toTokenAmountOutput(
new BN(getTransactionFee(tx) + rentCost),
NATIVE_MINT.toBase58(),
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ export const claimRewards =
return {
transactionData: { transactions: [], parallel: false, tag },
hasMore: false,
estimatedSolFee: toTokenAmountOutput(
estimatedSolFee: await toTokenAmountOutput(
new BN(0),
NATIVE_MINT.toBase58(),
),
Expand Down Expand Up @@ -154,7 +154,7 @@ export const claimRewards =
actionMetadata: { type: "delegation_claim_rewards", positionCount: positionMints.length },
},
hasMore: claimResult.hasMore || batchHasMore,
estimatedSolFee: toTokenAmountOutput(
estimatedSolFee: await toTokenAmountOutput(
new BN(txFee),
NATIVE_MINT.toBase58(),
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,7 @@ export const delegate = publicProcedure.governance.delegatePositions.handler(
tag,
},
hasMore: true,
estimatedSolFee: toTokenAmountOutput(
estimatedSolFee: await toTokenAmountOutput(
new BN(claimTxFee),
NATIVE_MINT.toBase58(),
),
Expand Down Expand Up @@ -599,7 +599,7 @@ export const delegate = publicProcedure.governance.delegatePositions.handler(
return {
transactionData: { transactions: [], parallel: false, tag },
hasMore: false,
estimatedSolFee: toTokenAmountOutput(new BN(0), NATIVE_MINT.toBase58()),
estimatedSolFee: await toTokenAmountOutput(new BN(0), NATIVE_MINT.toBase58()),
};
}

Expand Down Expand Up @@ -644,7 +644,7 @@ export const delegate = publicProcedure.governance.delegatePositions.handler(
tag,
actionMetadata: { type: "delegation_delegate", subDaoMint, positionCount: positionMints.length },
},
estimatedSolFee: toTokenAmountOutput(
estimatedSolFee: await toTokenAmountOutput(
new BN(estimatedSolFeeLamports),
NATIVE_MINT.toBase58(),
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ export const extend = publicProcedure.governance.extendDelegation.handler(
if (delegatedPositionAcc.expirationTs.gte(newExpirationTs)) {
return {
transactionData: { transactions: [], parallel: false, tag },
estimatedSolFee: toTokenAmountOutput(new BN(0), NATIVE_MINT.toBase58()),
estimatedSolFee: await toTokenAmountOutput(new BN(0), NATIVE_MINT.toBase58()),
};
}

Expand Down Expand Up @@ -182,7 +182,7 @@ export const extend = publicProcedure.governance.extendDelegation.handler(
tag,
actionMetadata: { type: "delegation_extend", positionMint },
},
estimatedSolFee: toTokenAmountOutput(
estimatedSolFee: await toTokenAmountOutput(
new BN(txFee),
NATIVE_MINT.toBase58(),
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ export const undelegate = publicProcedure.governance.undelegatePosition.handler(
tag,
},
hasMore: true,
estimatedSolFee: toTokenAmountOutput(
estimatedSolFee: await toTokenAmountOutput(
new BN(txFee),
NATIVE_MINT.toBase58(),
),
Expand Down Expand Up @@ -231,7 +231,7 @@ export const undelegate = publicProcedure.governance.undelegatePosition.handler(
actionMetadata: { type: "delegation_undelegate", positionMint },
},
hasMore: batchHasMore,
estimatedSolFee: toTokenAmountOutput(
estimatedSolFee: await toTokenAmountOutput(
new BN(txFee),
NATIVE_MINT.toBase58(),
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ export async function buildClaimInstructions(
const bitmapWindowEnd = lastClaimedEpoch.add(new BN(129)).toNumber();
const rawEndEpoch = isDecayed
? decayedEpoch.add(new BN(1)).toNumber()
: currentEpoch.sub(new BN(1)).toNumber();
: currentEpoch.toNumber();
const endEpoch = Math.min(rawEndEpoch, bitmapWindowEnd);

if (rawEndEpoch > bitmapWindowEnd) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ export const close = publicProcedure.governance.closePosition.handler(
tag,
actionMetadata: { type: "position_close", positionMint },
},
estimatedSolFee: toTokenAmountOutput(
estimatedSolFee: await toTokenAmountOutput(
new BN(txFee),
NATIVE_MINT.toBase58(),
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ export const create = publicProcedure.governance.createPosition.handler(
const { connection, provider } = createSolanaConnection(walletAddress);
const walletPubkey = new PublicKey(walletAddress);
const mintPubkey = new PublicKey(tokenAmount.mint);
const amount = resolveTokenAmountInput(tokenAmount);
const amount = await resolveTokenAmountInput(tokenAmount);

const hsdProgram = await initHsd(provider);
const vsrProgram = await initVsr(provider);
Expand Down Expand Up @@ -355,7 +355,7 @@ export const create = publicProcedure.governance.createPosition.handler(
tag,
actionMetadata: {
type: "position_create",
tokenAmount: toTokenAmountOutput(
tokenAmount: await toTokenAmountOutput(
new BN(tokenAmount.amount),
tokenAmount.mint,
),
Expand All @@ -364,7 +364,7 @@ export const create = publicProcedure.governance.createPosition.handler(
lockupPeriodDays: lockupPeriodsInDays,
},
},
estimatedSolFee: toTokenAmountOutput(
estimatedSolFee: await toTokenAmountOutput(
new BN(estimatedSolFeeLamports),
NATIVE_MINT.toBase58(),
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ export const extend = publicProcedure.governance.extendPosition.handler(
tag,
actionMetadata: { type: "position_extend", positionMint, lockupPeriodDays: lockupPeriodsInDays },
},
estimatedSolFee: toTokenAmountOutput(
estimatedSolFee: await toTokenAmountOutput(
new BN(txFee),
NATIVE_MINT.toBase58(),
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ export const flipLockupKind = publicProcedure.governance.flipLockupKind.handler(
tag,
actionMetadata: { type: "position_flip_lockup", positionMint },
},
estimatedSolFee: toTokenAmountOutput(
estimatedSolFee: await toTokenAmountOutput(
new BN(txFee),
NATIVE_MINT.toBase58(),
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ export const resetLockup = publicProcedure.governance.resetLockup.handler(
tag,
actionMetadata: { type: "position_reset_lockup", positionMint, lockupKind, lockupPeriodDays: lockupPeriodsInDays },
},
estimatedSolFee: toTokenAmountOutput(
estimatedSolFee: await toTokenAmountOutput(
new BN(txFee),
NATIVE_MINT.toBase58(),
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -195,11 +195,11 @@ export const split = publicProcedure.governance.splitPosition.handler(
actionMetadata: {
type: "position_split",
positionMint,
tokenAmount: toTokenAmountOutput(amountBN, depositMintStr),
tokenAmount: await toTokenAmountOutput(amountBN, depositMintStr),
tokenName: TOKEN_NAMES[depositMintStr],
},
},
estimatedSolFee: toTokenAmountOutput(
estimatedSolFee: await toTokenAmountOutput(
new BN(estimatedSolFeeLamports),
NATIVE_MINT.toBase58(),
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ export const transferOwnership =
tag,
actionMetadata: { type: "position_transfer_ownership", positionMint, from, to },
},
estimatedSolFee: toTokenAmountOutput(
estimatedSolFee: await toTokenAmountOutput(
new BN(txFee),
NATIVE_MINT.toBase58(),
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -163,11 +163,11 @@ export const transfer = publicProcedure.governance.transferPosition.handler(
type: "position_transfer",
positionMint,
targetPositionMint,
tokenAmount: toTokenAmountOutput(amountBN, depositMintStr),
tokenAmount: await toTokenAmountOutput(amountBN, depositMintStr),
tokenName: TOKEN_NAMES[depositMintStr],
},
},
estimatedSolFee: toTokenAmountOutput(
estimatedSolFee: await toTokenAmountOutput(
new BN(txFee),
NATIVE_MINT.toBase58(),
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -353,7 +353,7 @@ export const assign = publicProcedure.governance.assignProxies.handler(
actionMetadata: { type: "proxy_assign", proxyKey, positionCount: positionMints.length },
},
hasMore,
estimatedSolFee: toTokenAmountOutput(
estimatedSolFee: await toTokenAmountOutput(
new BN(totalFee),
NATIVE_MINT.toBase58(),
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ export const unassign = publicProcedure.governance.unassignProxies.handler(
actionMetadata: { type: "proxy_unassign", proxyKey, positionCount: positionMints.length },
},
hasMore,
estimatedSolFee: toTokenAmountOutput(
estimatedSolFee: await toTokenAmountOutput(
new BN(totalFee),
NATIVE_MINT.toBase58(),
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ export const relinquishPositionVotes =
actionMetadata: { type: "voting_relinquish_position", positionMint, organization },
},
hasMore,
estimatedSolFee: toTokenAmountOutput(
estimatedSolFee: await toTokenAmountOutput(
new BN(totalFee),
NATIVE_MINT.toBase58(),
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,7 @@ export const relinquishVote = publicProcedure.governance.relinquishVote.handler(
actionMetadata: { type: "voting_relinquish", proposalKey, choice, positionCount: positionMints.length },
},
hasMore,
estimatedSolFee: toTokenAmountOutput(
estimatedSolFee: await toTokenAmountOutput(
new BN(totalFee),
NATIVE_MINT.toBase58(),
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -398,7 +398,7 @@ export const vote = publicProcedure.governance.vote.handler(
actionMetadata: { type: "voting_vote", proposalKey, choice, positionCount: positionMints.length },
},
hasMore,
estimatedSolFee: toTokenAmountOutput(
estimatedSolFee: await toTokenAmountOutput(
new BN(totalFee),
NATIVE_MINT.toBase58(),
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ export const claimRewards = publicProcedure.hotspots.claimRewards.handler(
estimatedPendingRewards,
},
},
estimatedSolFee: toTokenAmountOutput(
estimatedSolFee: await toTokenAmountOutput(
new BN(0),
NATIVE_MINT.toBase58(),
),
Expand Down Expand Up @@ -303,7 +303,7 @@ export const claimRewards = publicProcedure.hotspots.claimRewards.handler(
estimatedPendingRewards,
},
},
estimatedSolFee: toTokenAmountOutput(
estimatedSolFee: await toTokenAmountOutput(
new BN(txFees + rentCost),
NATIVE_MINT.toBase58(),
),
Expand Down Expand Up @@ -449,7 +449,7 @@ export const claimRewards = publicProcedure.hotspots.claimRewards.handler(
estimatedPendingRewards,
},
},
estimatedSolFee: toTokenAmountOutput(
estimatedSolFee: await toTokenAmountOutput(
new BN(txFees + rentCost),
NATIVE_MINT.toBase58(),
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ export const closeAutomation = publicProcedure.hotspots.closeAutomation.handler(
tag: `close_automation:${walletAddress}`,
actionMetadata: { type: "close_automation" },
},
estimatedSolFee: toTokenAmountOutput(
estimatedSolFee: await toTokenAmountOutput(
new BN(txFees),
NATIVE_MINT.toBase58(),
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -316,7 +316,7 @@ export const createAutomation =
tag: `setup_automation:${walletAddress}`,
actionMetadata: { type: "setup_automation", schedule, duration },
},
estimatedSolFee: toTokenAmountOutput(
estimatedSolFee: await toTokenAmountOutput(
new BN(estimatedSolFeeLamports),
NATIVE_MINT.toBase58(),
),
Expand Down
Loading
Loading