@forgedevv/core 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +142 -2
- package/dist/addresses.d.ts +25 -6
- package/dist/addresses.js +27 -5
- package/dist/claims.d.ts +31 -4
- package/dist/claims.js +46 -5
- package/dist/config.d.ts +8 -0
- package/dist/config.js +17 -5
- package/dist/constants.d.ts +16 -0
- package/dist/constants.js +20 -0
- package/dist/index.d.ts +7 -5
- package/dist/index.js +12 -6
- package/dist/jupiter-referral.d.ts +219 -4
- package/dist/jupiter-referral.js +382 -11
- package/dist/launch-metadata.d.ts +2 -0
- package/dist/launch-metadata.js +2 -0
- package/dist/meteora-referral.d.ts +119 -0
- package/dist/meteora-referral.js +188 -0
- package/dist/payments.d.ts +17 -0
- package/dist/payments.js +20 -2
- package/dist/pool.d.ts +40 -0
- package/dist/pool.js +128 -24
- package/dist/position-claims.d.ts +9 -1
- package/dist/position-claims.js +21 -4
- package/dist/priority-fee.d.ts +202 -0
- package/dist/priority-fee.js +322 -0
- package/dist/reads.d.ts +20 -0
- package/dist/reads.js +39 -2
- package/dist/swap.d.ts +35 -16
- package/dist/swap.js +68 -19
- package/dist/tx.d.ts +2 -0
- package/dist/tx.js +4 -2
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -3,9 +3,149 @@
|
|
|
3
3
|
All notable changes to `@forge/core`. Versions follow semantic versioning. Consumers (the
|
|
4
4
|
launchpad template, the signer, the web app) pin an exact version, never a range.
|
|
5
5
|
|
|
6
|
-
## 0.
|
|
6
|
+
## 0.3.0 — 2026-10-17
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
Changes after 0.2.0. Publish `@forgedevv/shared` 0.3.0 with it (new kill switch `revenue_paused` in `FlagKey`).
|
|
9
|
+
|
|
10
|
+
### Changed (Jupiter fixes)
|
|
11
|
+
|
|
12
|
+
- **Jupiter referral fee.** `FEES.jupiterIntegratorFeeBps` (re-exported from `@forge/shared`) is
|
|
13
|
+
50 bps, was 30: the Jupiter Plugin passes `referralFee` to Ultra `/order`, which refuses any
|
|
14
|
+
value outside 50..255 bps, so every swap of a graduated coin failed. Jupiter keeps 20% of it.
|
|
15
|
+
`FEES.platformFeeBps` (30 bps, `PLATFORM_FEE_BPS` on swaps built by core) is unchanged.
|
|
16
|
+
- **Jupiter referral claims.** `buildJupiterReferralClaimTx` refuses a referral account of another
|
|
17
|
+
project than Jupiter's Ultra project (`project_mismatch`; the new `expectedProject` parameter
|
|
18
|
+
overrides the default `JUPITER_ULTRA_REFERRAL_PROJECT`). A funded v2 collection account is only
|
|
19
|
+
claimed for a named referral account at the PDA `["referral", project, name]`, the only kind
|
|
20
|
+
`claim_v2` accepts: `referral_account_unnamed` or `referral_account_not_pda` otherwise (new
|
|
21
|
+
`JupiterReferralErrorCode` values; the whole build is refused). With an empty v2 account, an
|
|
22
|
+
unnamed account still claims its v1 collection account. Devnet is unchanged: any cluster but
|
|
23
|
+
mainnet-beta is still refused (`wrong_cluster`) before these reads.
|
|
24
|
+
|
|
25
|
+
### Added (Jupiter fixes)
|
|
26
|
+
|
|
27
|
+
- `JUPITER_REFERRAL_FEE_BPS_RANGE` (`{ min: 50, max: 255 }`) and
|
|
28
|
+
`assertJupiterReferralFeeBps(bps)` (constants.ts): returns a whole number of bps within the range
|
|
29
|
+
Jupiter Ultra accepts, throws a `RangeError` otherwise. The launchpad template runs the plugin
|
|
30
|
+
fee through it and fails closed outside it.
|
|
31
|
+
- `JUPITER_ULTRA_REFERRAL_PROJECT` (`DkiqsTrw1u1bYFumumC7sCG2S8K25qc2vemJFHyW2wJc`) and
|
|
32
|
+
`deriveJupiterReferralAccount(project, name, programId?)` (jupiter-referral.ts).
|
|
33
|
+
|
|
34
|
+
### Added (revenue wallet referral accounts setup)
|
|
35
|
+
|
|
36
|
+
Pure builders of the two accounts the revenue wallet must hold (docs/MAINNET.md section 5), for
|
|
37
|
+
the signer's one-off `--setup-revenue-referrals` command. Only the payer signs: neither the
|
|
38
|
+
revenue wallet nor the new accounts do.
|
|
39
|
+
|
|
40
|
+
- **`meteora-referral.ts`** (re-exported by the index): `deriveMeteoraReferralAccount(payer,
|
|
41
|
+
seed?)` (`createWithSeed(payer, seed, SPL Token)`, default seed
|
|
42
|
+
`METEORA_REFERRAL_ACCOUNT_SEED` = `forge-meteora-referral`), `buildCreateMeteoraReferralAccountIxs`
|
|
43
|
+
/ `buildCreateMeteoraReferralAccountTx({ payer, owner, seed?, rentLamports, blockhash,
|
|
44
|
+
lastValidBlockHeight, priorityFee? })`: System `createAccountWithSeed` (from = base = payer,
|
|
45
|
+
the rent of 165 bytes, SPL Token owned) then SPL Token `InitializeAccount3` (wrapped SOL,
|
|
46
|
+
owner = the revenue wallet, no owner signature), the compute budget pair first when the quote
|
|
47
|
+
has a price (`METEORA_REFERRAL_SETUP_COMPUTE_UNITS` = 30,000); `inspectMeteoraReferralAccount`
|
|
48
|
+
(pure: `absent`, `ready`, or `mismatch` with a reason: not a token account, wrong mint or owner,
|
|
49
|
+
the owner's associated account, frozen, delegated, closable by someone else) and
|
|
50
|
+
`readMeteoraReferralAccount` (any cluster); `MeteoraReferralError` (`invalid_params`).
|
|
51
|
+
- **Jupiter referral setup** (jupiter-referral.ts), verified against the program source
|
|
52
|
+
(`initialize_referral_account_with_name.rs`, `lib.rs`, `claim_v2.rs`) and the SDK 0.3.0 IDL:
|
|
53
|
+
`JUPITER_INITIALIZE_REFERRAL_ACCOUNT_WITH_NAME_DISCRIMINATOR`, `JUPITER_REFERRAL_ACCOUNT_SIZE`
|
|
54
|
+
(274), `JUPITER_REFERRAL_NAME_MAX_CHARS` (19: the program requires fewer than 20 characters)
|
|
55
|
+
and `JUPITER_REFERRAL_NAME_MAX_BYTES` (32: a PDA seed), `assertJupiterReferralName` (also
|
|
56
|
+
refuses whitespace and control characters), `encodeJupiterReferralName` (Borsh),
|
|
57
|
+
`buildJupiterInitializeReferralAccountWithNameIx({ payer, partner, project, referralAccount },
|
|
58
|
+
name)` (the IDL's accounts: payer the only signer, partner read-only and not a signer, the
|
|
59
|
+
referral account the PDA `["referral", project, name]`),
|
|
60
|
+
`buildJupiterReferralTokenAccountV2Ix({ payer, referralAccount, mint, tokenProgram })` (the v2
|
|
61
|
+
collection account `claim_v2` empties is the referral account's associated token account: an
|
|
62
|
+
idempotent creation, what the SDK's `initializeReferralTokenAccountV2` sends),
|
|
63
|
+
`buildJupiterReferralSetupTx({ payer, partner, project?, name, createReferralAccount,
|
|
64
|
+
tokenAccounts, blockhash, lastValidBlockHeight, priorityFee? })` (Ultra project by default,
|
|
65
|
+
`JUPITER_REFERRAL_SETUP_COMPUTE_UNITS` = 150,000), `inspectJupiterReferralAccount` /
|
|
66
|
+
`inspectJupiterReferralTokenAccountV2` (pure statuses with mismatch reasons: partner, project,
|
|
67
|
+
name, owner, mint) and `readJupiterReferralSetup({ connection, partner, name, mints })`
|
|
68
|
+
(mainnet-beta only, `wrong_cluster` before any read; reads the project, the mints' token
|
|
69
|
+
programs, the referral account and its collection accounts).
|
|
70
|
+
|
|
71
|
+
### Changed (revenue wallet, docs/DECISIONS.md D34)
|
|
72
|
+
|
|
73
|
+
- **New address `FORGE_REVENUE_WALLET`** (`FORGE_ADDRESS_NAMES`, `getRevenueWallet`): the
|
|
74
|
+
signer-held wallet where the non-native trading revenue lands before the signer converts it to
|
|
75
|
+
SOL and forwards it to the multisig vault. It replaces the vault as the holder of the Meteora
|
|
76
|
+
referral account and as the partner of the Jupiter referral account; the platform fee goes to
|
|
77
|
+
it too (`FORGE_PLATFORM_FEE_WALLET` must be that wallet).
|
|
78
|
+
- **Swaps.** `swapFeeAddresses` returns `revenueWallet` (was `multisigVault`), read from
|
|
79
|
+
`FORGE_REVENUE_WALLET` (optional, as before): when set, the Meteora referral token account must
|
|
80
|
+
be held by it (`REFERRAL_ACCOUNT_INVALID`, `assertReferralAccountReady(..., expectedOwner?)`)
|
|
81
|
+
and `FORGE_PLATFORM_FEE_WALLET` must be it (`PLATFORM_FEE_WALLET_MISMATCH`, checked before any
|
|
82
|
+
network call by `buildBuyTx`, `buildSellTx` and `assertSwapFeeAccountsReady`). Client sites
|
|
83
|
+
receive `NEXT_PUBLIC_FORGE_REVENUE_WALLET` instead of `NEXT_PUBLIC_FORGE_MULTISIG_VAULT`.
|
|
84
|
+
- `buildJupiterReferralClaimTx` is unchanged: `expectedPartner` is now the revenue wallet.
|
|
85
|
+
|
|
86
|
+
### Added (priority fees)
|
|
87
|
+
|
|
88
|
+
- **`priority-fee.ts`** (browser-safe, re-exported by the index): `computePriorityFee` (pure: the
|
|
89
|
+
nearest-rank `percentile` of `getRecentPrioritizationFees`, at least `floorMicroLamports`, at
|
|
90
|
+
most `maxMicroLamports` per CU and `maxLamports` for the whole transaction; an empty list or a
|
|
91
|
+
failed read prices at the floor, reported in `source`), `estimatePriorityFee` (reads the fees
|
|
92
|
+
for the transaction's writable accounts, at most `MAX_PRIORITY_FEE_ACCOUNTS` = 32),
|
|
93
|
+
`readRecentPriorityFees`, `resolvePriorityFeePolicy`, `feePercentile`, `maxPriceForBudget`,
|
|
94
|
+
`maxPriorityFeeLamports` (the worst case of a setting, to show before building),
|
|
95
|
+
`fixedPriorityFee`, `priorityFeeInstructions` (unit limit then price; `priceOnly`),
|
|
96
|
+
`writableAccountsOf`, and `checkComputeBudgetInstructions` / `ComputeBudgetCheckError` for
|
|
97
|
+
transaction policies (no account, `SetComputeUnitLimit` / `SetComputeUnitPrice` only, at most
|
|
98
|
+
one of each, bounded values and fee; without a limit the fee is counted for 1.4M CU).
|
|
99
|
+
`DEFAULT_PRIORITY_FEE_POLICY`: 75th percentile, floor 10,000 micro-lamports per CU, at most
|
|
100
|
+
1,000,000 per CU and 500,000 lamports (0.0005 SOL) per transaction; hard ceilings
|
|
101
|
+
`MAX_PRIORITY_FEE_MICRO_LAMPORTS` (10 lamports per CU) and `MAX_PRIORITY_FEE_LAMPORTS`
|
|
102
|
+
(0.01 SOL). Types `PriorityFeeSetting`, `PriorityFeePolicy`, `PriorityFeeQuote`,
|
|
103
|
+
`PriorityFeeSource`, `RecentPrioritizationFee`.
|
|
104
|
+
- **Builders accept an optional `priority` setting** (exclusive with their fixed price, if any),
|
|
105
|
+
which puts `setComputeUnitLimit` then `setComputeUnitPrice` first (after the nonce advance):
|
|
106
|
+
`buildBuyTx` / `buildSellTx` (`SwapBuildOptions.priority`; the pure `buildSwapTransaction`
|
|
107
|
+
refuses it), `buildPaymentTx` (`PaymentTxOptions.priority`, limit `PAYMENT_COMPUTE_UNITS` =
|
|
108
|
+
50,000), `buildLaunchCoinTx` and `buildUserCoinLaunchTx`, `buildCreateConfigTx`, the creator,
|
|
109
|
+
partner and pool creation fee claims (`ClaimOptions.priority`, limits `CLAIM_COMPUTE_UNITS` =
|
|
110
|
+
200,000 and `POOL_CREATION_FEE_CLAIM_COMPUTE_UNITS` = 100,000), the DAMM v2 position claim
|
|
111
|
+
(`positionClaimComputeUnits`) and `buildJupiterReferralClaimTx`
|
|
112
|
+
(`JUPITER_REFERRAL_CLAIM_COMPUTE_UNITS` = 300,000). Their results report the quote
|
|
113
|
+
(`priorityFee`), and the claim costs count the fee. `CREATE_NONCE_ACCOUNT_COMPUTE_UNITS`
|
|
114
|
+
(10,000) names the limit of the nonce account builders.
|
|
115
|
+
- **Launch sizes.** The launchpad coin launch keeps the 148-byte metadata budget: with a priority
|
|
116
|
+
fee it carries the unit limit and the price up to 136 bytes of metadata, the price alone up to
|
|
117
|
+
144 (priced for `MAX_TRANSACTION_COMPUTE_UNITS`), and no price beyond
|
|
118
|
+
(`LaunchCoinSummary.priorityFeePlacement`: `limit_and_price`, `price_only`,
|
|
119
|
+
`omitted_for_size`). A priced swap or user coin launch is 12 bytes larger.
|
|
120
|
+
|
|
121
|
+
### Changed (priority fees)
|
|
122
|
+
|
|
123
|
+
- `BuiltSwapTransaction.priorityFee`, `PaymentTxResult.priorityFee`, `CreateConfigTx.priorityFee`,
|
|
124
|
+
`ClaimSummary.priorityFee`, `PoolCreationFeeClaimSummary.priorityFee`,
|
|
125
|
+
`PositionClaimSummary.priorityFee`, `JupiterReferralClaimTx.priorityFee` and
|
|
126
|
+
`LaunchCoinSummary` / `UserCoinLaunchSummary` `.priorityFee` and `.priorityFeePlacement` are new
|
|
127
|
+
required fields: code that builds these objects itself (test fakes) must set them. Without a
|
|
128
|
+
`priority` setting every transaction is byte for byte what 0.2.0 built.
|
|
129
|
+
- `ClaimCosts.networkFeeLamports` and `PositionClaimCosts.networkFeeLamports` include the
|
|
130
|
+
priority fee (0 without a setting).
|
|
131
|
+
- Consumers: the launchpad template prices its trades, coin creations and creator fee claims with
|
|
132
|
+
the defaults, so client sites need this version, and the FORGE RPC relay must serve
|
|
133
|
+
`getRecentPrioritizationFees` (apps/web, same release).
|
|
134
|
+
|
|
135
|
+
### Added (on-chain fallback of the coin data)
|
|
136
|
+
|
|
137
|
+
- `listPoolStatesOfConfig(connection, config, options?)` (reads.ts): the decoded pools of a config
|
|
138
|
+
with the config state (`DbcPoolState[]`, sorted by pool address), from the SDK's
|
|
139
|
+
`getPoolsByConfig`; a pool whose decoded config differs is dropped. `listCoinsOfConfig` now
|
|
140
|
+
summarizes its result (unchanged output). The launchpad template lists its coins with it when
|
|
141
|
+
the Jupiter data API is unavailable (and always on devnet).
|
|
142
|
+
- `poolSpotPrice(sqrtPrice, baseDecimals, quoteDecimals = 9)` (reads.ts): display price of one
|
|
143
|
+
whole coin in whole quote tokens from the pool's Q64.64 `sqrtPrice` (same value as the SDK's
|
|
144
|
+
`getPriceFromSqrtPrice`, as a float).
|
|
145
|
+
|
|
146
|
+
## 0.2.0 — 2026-10-17
|
|
147
|
+
|
|
148
|
+
Everything below was added after 0.1.0 and published on npm on 2026-10-17 with `@forgedevv/shared` 0.2.0.
|
|
9
149
|
|
|
10
150
|
### Changed (security review)
|
|
11
151
|
|
package/dist/addresses.d.ts
CHANGED
|
@@ -9,14 +9,20 @@
|
|
|
9
9
|
* Validation choice: a value is valid when the `PublicKey` constructor accepts it (base58 that
|
|
10
10
|
* decodes to exactly 32 bytes) and it re-encodes to the same string. Being on the ed25519 curve is
|
|
11
11
|
* NOT required, because some of these addresses are token accounts or PDAs (e.g. the Meteora
|
|
12
|
-
* referral account, which is a WSOL token account held by the
|
|
12
|
+
* referral account, which is a WSOL token account held by the revenue wallet, or a Squads vault
|
|
13
|
+
* PDA).
|
|
14
|
+
*
|
|
15
|
+
* The revenue wallet (`FORGE_REVENUE_WALLET`, docs/DECISIONS.md D34) is the signer-held wallet
|
|
16
|
+
* where the non-native trading revenue lands: the platform fee (`FORGE_PLATFORM_FEE_WALLET` must
|
|
17
|
+
* be that wallet), the Meteora referral WSOL account it holds, and the Jupiter referral claims
|
|
18
|
+
* (it is the referral account's partner). The signer converts and forwards it to the vault.
|
|
13
19
|
* The all-zero key (`11111111111111111111111111111111`, the System Program) is rejected: fees
|
|
14
20
|
* sent there would be lost.
|
|
15
21
|
*
|
|
16
22
|
* Error messages list variable names only, never values.
|
|
17
23
|
*/
|
|
18
24
|
import { PublicKey } from '@solana/web3.js';
|
|
19
|
-
export declare const FORGE_ADDRESS_NAMES: readonly ["FORGE_MULTISIG_VAULT", "FORGE_METEORA_REFERRAL_ACCOUNT", "FORGE_PLATFORM_FEE_WALLET", "FORGE_JUPITER_REFERRAL_ACCOUNT", "FORGE_CASHBOX_WALLET", "FORGE_MINT", "FORGE_SQUADS_MULTISIG", "FORGE_SQUADS_SPENDING_LIMIT"];
|
|
25
|
+
export declare const FORGE_ADDRESS_NAMES: readonly ["FORGE_MULTISIG_VAULT", "FORGE_METEORA_REFERRAL_ACCOUNT", "FORGE_PLATFORM_FEE_WALLET", "FORGE_REVENUE_WALLET", "FORGE_JUPITER_REFERRAL_ACCOUNT", "FORGE_CASHBOX_WALLET", "FORGE_MINT", "FORGE_SQUADS_MULTISIG", "FORGE_SQUADS_SPENDING_LIMIT"];
|
|
20
26
|
export type ForgeAddressName = (typeof FORGE_ADDRESS_NAMES)[number];
|
|
21
27
|
/**
|
|
22
28
|
* Addresses that may be absent. `FORGE_MINT` is absent before the $FORGE launch; the Squads
|
|
@@ -48,17 +54,30 @@ export declare function requireAddresses<N extends ForgeAddressName>(names: read
|
|
|
48
54
|
* One FORGE address when it is set, `null` when it is absent or empty. A value that is set but is
|
|
49
55
|
* not a valid public key is refused, exactly as `requireAddresses` does. For checks that run
|
|
50
56
|
* wherever the address is known and are skipped elsewhere (e.g. the owner of the Meteora referral
|
|
51
|
-
* account, `
|
|
57
|
+
* account, `FORGE_REVENUE_WALLET`, in a browser that was not given it).
|
|
52
58
|
*
|
|
53
59
|
* @throws ForgeAddressError (invalid value; names only).
|
|
54
60
|
*/
|
|
55
61
|
export declare function readOptionalAddress(name: ForgeAddressName, env?: AddressEnv): PublicKey | null;
|
|
56
|
-
/**
|
|
62
|
+
/**
|
|
63
|
+
* Squads multisig vault: receives the creator fees, the cashbox sweeps and the revenue wallet's
|
|
64
|
+
* forwards (the converted trading revenue).
|
|
65
|
+
*/
|
|
57
66
|
export declare function getMultisigVault(env?: AddressEnv): PublicKey;
|
|
58
|
-
/** Meteora referral token account (WSOL, held by the
|
|
67
|
+
/** Meteora referral token account (WSOL, held by the revenue wallet), passed as `referralTokenAccount`. */
|
|
59
68
|
export declare function getMeteoraReferralAccount(env?: AddressEnv): PublicKey;
|
|
60
|
-
/**
|
|
69
|
+
/**
|
|
70
|
+
* Wallet receiving the 0.3% platform fee on swaps built by @forge/core: the revenue wallet
|
|
71
|
+
* (`FORGE_REVENUE_WALLET`, D34). Kept as its own variable so the fee destination stays explicit;
|
|
72
|
+
* `swapFeeAddresses` refuses an environment where the two differ.
|
|
73
|
+
*/
|
|
61
74
|
export declare function getPlatformFeeWallet(env?: AddressEnv): PublicKey;
|
|
75
|
+
/**
|
|
76
|
+
* Revenue wallet (D34): held by the signer (keystore role `revenue`), it receives the platform
|
|
77
|
+
* fee, holds the Meteora referral WSOL account and is the partner of the Jupiter referral
|
|
78
|
+
* account. The signer regularly converts what it holds to SOL and forwards it to the vault.
|
|
79
|
+
*/
|
|
80
|
+
export declare function getRevenueWallet(env?: AddressEnv): PublicKey;
|
|
62
81
|
/** Jupiter referral account (integrator fee after graduation). */
|
|
63
82
|
export declare function getJupiterReferralAccount(env?: AddressEnv): PublicKey;
|
|
64
83
|
/** Cashbox wallet (held by the signer) receiving client payments. */
|
package/dist/addresses.js
CHANGED
|
@@ -9,7 +9,13 @@
|
|
|
9
9
|
* Validation choice: a value is valid when the `PublicKey` constructor accepts it (base58 that
|
|
10
10
|
* decodes to exactly 32 bytes) and it re-encodes to the same string. Being on the ed25519 curve is
|
|
11
11
|
* NOT required, because some of these addresses are token accounts or PDAs (e.g. the Meteora
|
|
12
|
-
* referral account, which is a WSOL token account held by the
|
|
12
|
+
* referral account, which is a WSOL token account held by the revenue wallet, or a Squads vault
|
|
13
|
+
* PDA).
|
|
14
|
+
*
|
|
15
|
+
* The revenue wallet (`FORGE_REVENUE_WALLET`, docs/DECISIONS.md D34) is the signer-held wallet
|
|
16
|
+
* where the non-native trading revenue lands: the platform fee (`FORGE_PLATFORM_FEE_WALLET` must
|
|
17
|
+
* be that wallet), the Meteora referral WSOL account it holds, and the Jupiter referral claims
|
|
18
|
+
* (it is the referral account's partner). The signer converts and forwards it to the vault.
|
|
13
19
|
* The all-zero key (`11111111111111111111111111111111`, the System Program) is rejected: fees
|
|
14
20
|
* sent there would be lost.
|
|
15
21
|
*
|
|
@@ -20,6 +26,7 @@ export const FORGE_ADDRESS_NAMES = [
|
|
|
20
26
|
'FORGE_MULTISIG_VAULT',
|
|
21
27
|
'FORGE_METEORA_REFERRAL_ACCOUNT',
|
|
22
28
|
'FORGE_PLATFORM_FEE_WALLET',
|
|
29
|
+
'FORGE_REVENUE_WALLET',
|
|
23
30
|
'FORGE_JUPITER_REFERRAL_ACCOUNT',
|
|
24
31
|
'FORGE_CASHBOX_WALLET',
|
|
25
32
|
'FORGE_MINT',
|
|
@@ -112,7 +119,7 @@ export function requireAddresses(names, env = defaultEnv()) {
|
|
|
112
119
|
* One FORGE address when it is set, `null` when it is absent or empty. A value that is set but is
|
|
113
120
|
* not a valid public key is refused, exactly as `requireAddresses` does. For checks that run
|
|
114
121
|
* wherever the address is known and are skipped elsewhere (e.g. the owner of the Meteora referral
|
|
115
|
-
* account, `
|
|
122
|
+
* account, `FORGE_REVENUE_WALLET`, in a browser that was not given it).
|
|
116
123
|
*
|
|
117
124
|
* @throws ForgeAddressError (invalid value; names only).
|
|
118
125
|
*/
|
|
@@ -122,18 +129,33 @@ export function readOptionalAddress(name, env = defaultEnv()) {
|
|
|
122
129
|
return null;
|
|
123
130
|
return requireAddresses([name], env)[name];
|
|
124
131
|
}
|
|
125
|
-
/**
|
|
132
|
+
/**
|
|
133
|
+
* Squads multisig vault: receives the creator fees, the cashbox sweeps and the revenue wallet's
|
|
134
|
+
* forwards (the converted trading revenue).
|
|
135
|
+
*/
|
|
126
136
|
export function getMultisigVault(env) {
|
|
127
137
|
return requireAddresses(['FORGE_MULTISIG_VAULT'], env).FORGE_MULTISIG_VAULT;
|
|
128
138
|
}
|
|
129
|
-
/** Meteora referral token account (WSOL, held by the
|
|
139
|
+
/** Meteora referral token account (WSOL, held by the revenue wallet), passed as `referralTokenAccount`. */
|
|
130
140
|
export function getMeteoraReferralAccount(env) {
|
|
131
141
|
return requireAddresses(['FORGE_METEORA_REFERRAL_ACCOUNT'], env).FORGE_METEORA_REFERRAL_ACCOUNT;
|
|
132
142
|
}
|
|
133
|
-
/**
|
|
143
|
+
/**
|
|
144
|
+
* Wallet receiving the 0.3% platform fee on swaps built by @forge/core: the revenue wallet
|
|
145
|
+
* (`FORGE_REVENUE_WALLET`, D34). Kept as its own variable so the fee destination stays explicit;
|
|
146
|
+
* `swapFeeAddresses` refuses an environment where the two differ.
|
|
147
|
+
*/
|
|
134
148
|
export function getPlatformFeeWallet(env) {
|
|
135
149
|
return requireAddresses(['FORGE_PLATFORM_FEE_WALLET'], env).FORGE_PLATFORM_FEE_WALLET;
|
|
136
150
|
}
|
|
151
|
+
/**
|
|
152
|
+
* Revenue wallet (D34): held by the signer (keystore role `revenue`), it receives the platform
|
|
153
|
+
* fee, holds the Meteora referral WSOL account and is the partner of the Jupiter referral
|
|
154
|
+
* account. The signer regularly converts what it holds to SOL and forwards it to the vault.
|
|
155
|
+
*/
|
|
156
|
+
export function getRevenueWallet(env) {
|
|
157
|
+
return requireAddresses(['FORGE_REVENUE_WALLET'], env).FORGE_REVENUE_WALLET;
|
|
158
|
+
}
|
|
137
159
|
/** Jupiter referral account (integrator fee after graduation). */
|
|
138
160
|
export function getJupiterReferralAccount(env) {
|
|
139
161
|
return requireAddresses(['FORGE_JUPITER_REFERRAL_ACCOUNT'], env).FORGE_JUPITER_REFERRAL_ACCOUNT;
|
package/dist/claims.d.ts
CHANGED
|
@@ -1,8 +1,17 @@
|
|
|
1
|
-
import { PublicKey, Transaction, type Commitment, type Connection } from '@solana/web3.js';
|
|
1
|
+
import { PublicKey, Transaction, type Commitment, type Connection, type TransactionInstruction } from '@solana/web3.js';
|
|
2
2
|
import { type AddressEnv } from './addresses.js';
|
|
3
|
+
import { type PriorityFeeQuote, type PriorityFeeSetting } from './priority-fee.js';
|
|
3
4
|
import { type DbcPoolState, type RetryOptions, type TokenAmounts } from './reads.js';
|
|
4
|
-
/** Base fee per signature (lamports);
|
|
5
|
+
/** Base fee per signature (lamports); a priority fee comes on top with `ClaimOptions.priority`. */
|
|
5
6
|
export declare const CLAIM_LAMPORTS_PER_SIGNATURE = 5000n;
|
|
7
|
+
/**
|
|
8
|
+
* Compute unit limit of a trading fee claim with a priority fee: two idempotent token account
|
|
9
|
+
* creations (about 25,000 CU each when they create), the DBC claim (two token transfers and its
|
|
10
|
+
* event), a token self-transfer, a close and a SOL transfer, about 100,000 CU at most: 2x margin.
|
|
11
|
+
*/
|
|
12
|
+
export declare const CLAIM_COMPUTE_UNITS = 200000;
|
|
13
|
+
/** Compute unit limit of a pool creation fee claim (one DBC instruction moving lamports). */
|
|
14
|
+
export declare const POOL_CREATION_FEE_CLAIM_COMPUTE_UNITS = 100000;
|
|
6
15
|
export { PARTNER_POOL_CREATION_FEE_CLAIMED_BIT, partnerPoolCreationFeeShare } from './reads.js';
|
|
7
16
|
export type ClaimErrorCode = 'not_pool_creator' | 'not_fee_claimer' | 'unsupported_quote_mint' | 'invalid_receiver' | 'receiver_mismatch' | 'receiver_not_rent_exempt' | 'claimer_wsol_not_empty' | 'unexpected_sdk_instructions' | 'not_migrated' | 'damm_pool_not_found' | 'damm_pool_mismatch' | 'position_not_found' | 'position_mismatch' | 'position_not_owned';
|
|
8
17
|
export declare class ClaimError extends Error {
|
|
@@ -12,7 +21,7 @@ export declare class ClaimError extends Error {
|
|
|
12
21
|
export type ClaimKind = 'creator' | 'partner';
|
|
13
22
|
/** Lamport costs of a trading fee claim, as bigint. */
|
|
14
23
|
export interface ClaimCosts {
|
|
15
|
-
/** Signature fees (signers x 5000 lamports
|
|
24
|
+
/** Signature fees (signers x 5000 lamports) plus the priority fee, if any; paid by the payer. */
|
|
16
25
|
networkFeeLamports: bigint;
|
|
17
26
|
/**
|
|
18
27
|
* Rent of the receiver's coin account, created on the first claim of a pool (paid by the payer,
|
|
@@ -56,6 +65,8 @@ export interface ClaimSummary {
|
|
|
56
65
|
* costs are paid (negative when it costs more than it collects). Base tokens are not valued.
|
|
57
66
|
*/
|
|
58
67
|
netLamports: bigint;
|
|
68
|
+
/** The priority fee of the transaction (price, fee, cap), or null without one. */
|
|
69
|
+
priorityFee: PriorityFeeQuote | null;
|
|
59
70
|
}
|
|
60
71
|
export type ClaimSkipReason = 'nothing_to_claim' | 'not_worthwhile';
|
|
61
72
|
export interface ClaimTxResult {
|
|
@@ -75,7 +86,21 @@ export interface ClaimOptions {
|
|
|
75
86
|
* than this many lamports (see `isClaimWorthwhile`). Default: never skip a non-empty claim.
|
|
76
87
|
*/
|
|
77
88
|
minNetLamports?: bigint;
|
|
89
|
+
/**
|
|
90
|
+
* Priority fee read from the cluster for the claim's writable accounts, bounded by this setting
|
|
91
|
+
* (`{}` = `DEFAULT_PRIORITY_FEE_POLICY`, at most 0.0005 SOL). Default: none.
|
|
92
|
+
*/
|
|
93
|
+
priority?: PriorityFeeSetting;
|
|
78
94
|
}
|
|
95
|
+
/** Checks `options.priority` before any network call. @throws RangeError. */
|
|
96
|
+
export declare function assertClaimPriority(options: {
|
|
97
|
+
priority?: PriorityFeeSetting;
|
|
98
|
+
}): void;
|
|
99
|
+
/** The priced compute budget of a claim, or nothing without `priority`. */
|
|
100
|
+
export declare function claimPriorityFee(connection: Connection, instructions: readonly TransactionInstruction[], computeUnitLimit: number, priority: PriorityFeeSetting | undefined): Promise<{
|
|
101
|
+
quote: PriorityFeeQuote | null;
|
|
102
|
+
instructions: TransactionInstruction[];
|
|
103
|
+
}>;
|
|
79
104
|
export interface CreatorClaimParams {
|
|
80
105
|
pool: PublicKey;
|
|
81
106
|
/** Pool creator (must match the pool state); signs the claim. */
|
|
@@ -163,10 +188,12 @@ export interface PoolCreationFeeClaimSummary {
|
|
|
163
188
|
alreadyClaimed: boolean;
|
|
164
189
|
/** SOL the receiver gets from the transaction (0 when there is none), lamports. */
|
|
165
190
|
claimableLamports: bigint;
|
|
166
|
-
/** Signature fees of the transaction (0 when there is none)
|
|
191
|
+
/** Signature fees plus the priority fee of the transaction (0 when there is none). */
|
|
167
192
|
networkFeeLamports: bigint;
|
|
168
193
|
/** `claimableLamports - networkFeeLamports` (0 when there is no transaction). */
|
|
169
194
|
netLamports: bigint;
|
|
195
|
+
/** The priority fee of the transaction (price, fee, cap), or null without one. */
|
|
196
|
+
priorityFee: PriorityFeeQuote | null;
|
|
170
197
|
}
|
|
171
198
|
export type PoolCreationFeeSkipReason = 'no_pool_creation_fee' | 'already_claimed';
|
|
172
199
|
export interface PoolCreationFeeClaimTxResult {
|
package/dist/claims.js
CHANGED
|
@@ -34,6 +34,12 @@
|
|
|
34
34
|
* claim (FORGE configs collect fees in SOL only). It is the receiver's associated account, created
|
|
35
35
|
* idempotently by the payer: the first claim of each pool costs the payer that account's rent
|
|
36
36
|
* (~0.00204 SOL), which stays in an account owned by the receiver (recoverable by closing it).
|
|
37
|
+
*
|
|
38
|
+
* Priority fee (`ClaimOptions.priority`, priority-fee.ts): two compute budget instructions come
|
|
39
|
+
* first, `setComputeUnitLimit` (`CLAIM_COMPUTE_UNITS`, or `POOL_CREATION_FEE_CLAIM_COMPUTE_UNITS`)
|
|
40
|
+
* then `setComputeUnitPrice`, priced from the recent fees of the claim's writable accounts and
|
|
41
|
+
* bounded by the setting; the costs (network fee, worthwhile check) count it. Without the option
|
|
42
|
+
* the claims carry no compute budget instruction, as before.
|
|
37
43
|
*/
|
|
38
44
|
import { ACCOUNT_SIZE, NATIVE_MINT, TOKEN_2022_PROGRAM_ID, TOKEN_PROGRAM_ID, createAssociatedTokenAccountIdempotentInstruction, createCloseAccountInstruction, createTransferInstruction, getAssociatedTokenAddressSync, unpackAccount, } from '@solana/spl-token';
|
|
39
45
|
import { PublicKey, SystemProgram, Transaction, } from '@solana/web3.js';
|
|
@@ -41,9 +47,18 @@ import { CreatorService, DYNAMIC_BONDING_CURVE_PROGRAM_ID, PartnerService, Token
|
|
|
41
47
|
import BN from 'bn.js';
|
|
42
48
|
import { getMultisigVault } from './addresses.js';
|
|
43
49
|
import { SOL_QUOTE_MINT } from './constants.js';
|
|
50
|
+
import { estimatePriorityFee, priorityFeeInstructions, resolvePriorityFeePolicy, writableAccountsOf, } from './priority-fee.js';
|
|
44
51
|
import { READ_COMMITMENT, feeMetrics, getDbcPoolState, poolCreationFeeStatus, retryRpc, } from './reads.js';
|
|
45
|
-
/** Base fee per signature (lamports);
|
|
52
|
+
/** Base fee per signature (lamports); a priority fee comes on top with `ClaimOptions.priority`. */
|
|
46
53
|
export const CLAIM_LAMPORTS_PER_SIGNATURE = 5000n;
|
|
54
|
+
/**
|
|
55
|
+
* Compute unit limit of a trading fee claim with a priority fee: two idempotent token account
|
|
56
|
+
* creations (about 25,000 CU each when they create), the DBC claim (two token transfers and its
|
|
57
|
+
* event), a token self-transfer, a close and a SOL transfer, about 100,000 CU at most: 2x margin.
|
|
58
|
+
*/
|
|
59
|
+
export const CLAIM_COMPUTE_UNITS = 200_000;
|
|
60
|
+
/** Compute unit limit of a pool creation fee claim (one DBC instruction moving lamports). */
|
|
61
|
+
export const POOL_CREATION_FEE_CLAIM_COMPUTE_UNITS = 100_000;
|
|
47
62
|
// Pool creation fee helpers live in reads.ts (CoinOfConfig uses them); re-exported here.
|
|
48
63
|
export { PARTNER_POOL_CREATION_FEE_CLAIMED_BIT, partnerPoolCreationFeeShare } from './reads.js';
|
|
49
64
|
export class ClaimError extends Error {
|
|
@@ -54,6 +69,23 @@ export class ClaimError extends Error {
|
|
|
54
69
|
this.code = code;
|
|
55
70
|
}
|
|
56
71
|
}
|
|
72
|
+
/** Checks `options.priority` before any network call. @throws RangeError. */
|
|
73
|
+
export function assertClaimPriority(options) {
|
|
74
|
+
if (options.priority !== undefined)
|
|
75
|
+
resolvePriorityFeePolicy(options.priority);
|
|
76
|
+
}
|
|
77
|
+
/** The priced compute budget of a claim, or nothing without `priority`. */
|
|
78
|
+
export async function claimPriorityFee(connection, instructions, computeUnitLimit, priority) {
|
|
79
|
+
if (priority === undefined)
|
|
80
|
+
return { quote: null, instructions: [] };
|
|
81
|
+
const quote = await estimatePriorityFee({
|
|
82
|
+
connection,
|
|
83
|
+
writableAccounts: writableAccountsOf(instructions),
|
|
84
|
+
computeUnitLimit,
|
|
85
|
+
setting: priority,
|
|
86
|
+
});
|
|
87
|
+
return { quote, instructions: priorityFeeInstructions(quote) };
|
|
88
|
+
}
|
|
57
89
|
// ---------------------------------------------------------------------------------------------
|
|
58
90
|
// Pure helpers
|
|
59
91
|
// ---------------------------------------------------------------------------------------------
|
|
@@ -123,6 +155,7 @@ async function buildTradingClaim(connection, input, options) {
|
|
|
123
155
|
existingWsolLamports: 0n,
|
|
124
156
|
costs: ZERO_COSTS,
|
|
125
157
|
netLamports: 0n,
|
|
158
|
+
priorityFee: null,
|
|
126
159
|
},
|
|
127
160
|
};
|
|
128
161
|
}
|
|
@@ -189,12 +222,13 @@ async function buildTradingClaim(connection, input, options) {
|
|
|
189
222
|
if (exact && quote > 0n) {
|
|
190
223
|
instructions.push(SystemProgram.transfer({ fromPubkey: payer, toPubkey: receiver, lamports: quote }));
|
|
191
224
|
}
|
|
225
|
+
const priority = await claimPriorityFee(connection, instructions, CLAIM_COMPUTE_UNITS, options.priority);
|
|
192
226
|
const { blockhash, lastValidBlockHeight } = await retryRpc(() => connection.getLatestBlockhash(commitment), options.retry);
|
|
193
227
|
const transaction = new Transaction({ feePayer: payer, blockhash, lastValidBlockHeight });
|
|
194
|
-
transaction.add(...instructions);
|
|
228
|
+
transaction.add(...priority.instructions, ...instructions);
|
|
195
229
|
// 4. Costs and net.
|
|
196
230
|
const signatures = BigInt(transaction.compileMessage().header.numRequiredSignatures);
|
|
197
|
-
const networkFeeLamports = signatures * CLAIM_LAMPORTS_PER_SIGNATURE;
|
|
231
|
+
const networkFeeLamports = signatures * CLAIM_LAMPORTS_PER_SIGNATURE + (priority.quote?.priorityFeeLamports ?? 0n);
|
|
198
232
|
const receiverTokenAccountRentLamports = receiverBaseInfo ? 0n : BigInt(tokenAccountRent);
|
|
199
233
|
const temporaryLamports = claimerWsolInfo ? 0n : BigInt(tokenAccountRent);
|
|
200
234
|
const payerTotalLamports = networkFeeLamports + receiverTokenAccountRentLamports;
|
|
@@ -212,6 +246,7 @@ async function buildTradingClaim(connection, input, options) {
|
|
|
212
246
|
existingWsolLamports,
|
|
213
247
|
costs,
|
|
214
248
|
netLamports: receiverQuoteLamports - payerTotalLamports,
|
|
249
|
+
priorityFee: priority.quote,
|
|
215
250
|
};
|
|
216
251
|
if (options.minNetLamports !== undefined && !isClaimWorthwhile(summary, options.minNetLamports)) {
|
|
217
252
|
return { transaction: null, lastValidBlockHeight: null, skipReason: 'not_worthwhile', summary };
|
|
@@ -227,6 +262,7 @@ async function buildTradingClaim(connection, input, options) {
|
|
|
227
262
|
export async function buildCreatorClaimTx(connection, params, options = {}) {
|
|
228
263
|
const commitment = options.commitment ?? READ_COMMITMENT;
|
|
229
264
|
assertReceiver(params.receiver);
|
|
265
|
+
assertClaimPriority(options);
|
|
230
266
|
if (params.expectedReceiver && !params.expectedReceiver.equals(params.receiver)) {
|
|
231
267
|
throw new ClaimError('receiver_mismatch', `Creator fees of pool ${params.pool.toBase58()} must go to ${params.expectedReceiver.toBase58()}, not ${params.receiver.toBase58()}`);
|
|
232
268
|
}
|
|
@@ -278,6 +314,7 @@ export async function buildPartnerClaimTx(connection, params, options = {}) {
|
|
|
278
314
|
const commitment = options.commitment ?? READ_COMMITMENT;
|
|
279
315
|
const receiver = params.receiver ?? params.feeClaimer;
|
|
280
316
|
assertReceiver(receiver);
|
|
317
|
+
assertClaimPriority(options);
|
|
281
318
|
const state = await getDbcPoolState(connection, params.pool, {
|
|
282
319
|
commitment,
|
|
283
320
|
retry: options.retry,
|
|
@@ -317,6 +354,7 @@ export async function buildPartnerPoolCreationFeeClaimTx(connection, params, opt
|
|
|
317
354
|
const commitment = options.commitment ?? READ_COMMITMENT;
|
|
318
355
|
const receiver = params.receiver ?? params.feeClaimer;
|
|
319
356
|
assertReceiver(receiver);
|
|
357
|
+
assertClaimPriority(options);
|
|
320
358
|
const state = await getDbcPoolState(connection, params.pool, {
|
|
321
359
|
commitment,
|
|
322
360
|
retry: options.retry,
|
|
@@ -341,6 +379,7 @@ export async function buildPartnerPoolCreationFeeClaimTx(connection, params, opt
|
|
|
341
379
|
claimableLamports: 0n,
|
|
342
380
|
networkFeeLamports: 0n,
|
|
343
381
|
netLamports: 0n,
|
|
382
|
+
priorityFee: null,
|
|
344
383
|
};
|
|
345
384
|
if (partnerShareLamports === 0n || alreadyClaimed) {
|
|
346
385
|
return {
|
|
@@ -366,11 +405,12 @@ export async function buildPartnerPoolCreationFeeClaimTx(connection, params, opt
|
|
|
366
405
|
!claimIx.keys.some((k) => k.isWritable && k.pubkey.equals(receiver))) {
|
|
367
406
|
throw new ClaimError('unexpected_sdk_instructions', 'The SDK pool creation fee claim does not have the expected instruction');
|
|
368
407
|
}
|
|
408
|
+
const priority = await claimPriorityFee(connection, [claimIx], POOL_CREATION_FEE_CLAIM_COMPUTE_UNITS, options.priority);
|
|
369
409
|
const { blockhash, lastValidBlockHeight } = await retryRpc(() => connection.getLatestBlockhash(commitment), options.retry);
|
|
370
410
|
const transaction = new Transaction({ feePayer: payer, blockhash, lastValidBlockHeight });
|
|
371
|
-
transaction.add(claimIx);
|
|
411
|
+
transaction.add(...priority.instructions, claimIx);
|
|
372
412
|
const signatures = BigInt(transaction.compileMessage().header.numRequiredSignatures);
|
|
373
|
-
const networkFeeLamports = signatures * CLAIM_LAMPORTS_PER_SIGNATURE;
|
|
413
|
+
const networkFeeLamports = signatures * CLAIM_LAMPORTS_PER_SIGNATURE + (priority.quote?.priorityFeeLamports ?? 0n);
|
|
374
414
|
return {
|
|
375
415
|
transaction,
|
|
376
416
|
lastValidBlockHeight,
|
|
@@ -380,6 +420,7 @@ export async function buildPartnerPoolCreationFeeClaimTx(connection, params, opt
|
|
|
380
420
|
claimableLamports: partnerShareLamports,
|
|
381
421
|
networkFeeLamports,
|
|
382
422
|
netLamports: partnerShareLamports - networkFeeLamports,
|
|
423
|
+
priorityFee: priority.quote,
|
|
383
424
|
},
|
|
384
425
|
};
|
|
385
426
|
}
|
package/dist/config.d.ts
CHANGED
|
@@ -28,6 +28,7 @@
|
|
|
28
28
|
import { type BuildCurveParams, type ConfigParameters, type PoolConfig, type SwapQuoteConfig } from '@meteora-ag/dynamic-bonding-curve-sdk';
|
|
29
29
|
import { PublicKey, Transaction, type Connection } from '@solana/web3.js';
|
|
30
30
|
import { LaunchpadSpec } from '@forge/shared';
|
|
31
|
+
import { type PriorityFeeQuote, type PriorityFeeSetting } from './priority-fee.js';
|
|
31
32
|
export { ANTI_SNIPER_FEE_SCHEDULE, FORGE_ACTIVATION_TYPE, FORGE_MIGRATION_SETTINGS, FORGE_TOKEN_SETTINGS, FORGE_TOKEN_SUPPLY_RAW, forgeBaseFee, forgeFeeSchedulerParam, forgeReferenceCurve, type ForgeReferenceCurve, } from './settings.js';
|
|
32
33
|
/**
|
|
33
34
|
* Pool creation fee of the launchpad coin config: none. The only pool ever created on it is the
|
|
@@ -170,6 +171,11 @@ export interface BuildCreateConfigTxParams {
|
|
|
170
171
|
payer: PublicKey;
|
|
171
172
|
/** Priority fee, in micro-lamports per compute unit (default 0). */
|
|
172
173
|
computeUnitPriceMicroLamports?: number;
|
|
174
|
+
/**
|
|
175
|
+
* Priority fee read from the cluster for the payer and the config account, bounded by this
|
|
176
|
+
* setting (priority-fee.ts). Not with `computeUnitPriceMicroLamports`.
|
|
177
|
+
*/
|
|
178
|
+
priority?: PriorityFeeSetting;
|
|
173
179
|
/** Blockhash to use; fetched from the cluster when absent. */
|
|
174
180
|
recentBlockhash?: {
|
|
175
181
|
blockhash: string;
|
|
@@ -187,6 +193,8 @@ export interface CreateConfigTx {
|
|
|
187
193
|
lastValidBlockHeight: number;
|
|
188
194
|
/** Who must sign: the payer (fee payer) and the config keypair. */
|
|
189
195
|
signers: PublicKey[];
|
|
196
|
+
/** The priority fee (price, fee, cap; `fixed` without a `priority` setting). */
|
|
197
|
+
priorityFee: PriorityFeeQuote;
|
|
190
198
|
}
|
|
191
199
|
/**
|
|
192
200
|
* Unsigned transaction creating one of the two configs (`createConfig`). The parameters are
|
package/dist/config.js
CHANGED
|
@@ -32,7 +32,7 @@ import { LaunchpadSpec } from '@forge/shared';
|
|
|
32
32
|
import { CLIENT_BOUNDS, CLIENT_POOL_CREATION_FEE_LAMPORTS, FEES, LAMPORTS_PER_SOL_BIGINT, SOL_QUOTE_MINT, solToLamports, } from './constants.js';
|
|
33
33
|
import { LaunchCoinError, assertSpecLaunchable } from './launch-metadata.js';
|
|
34
34
|
import { ANTI_SNIPER_FEE_SCHEDULE, FORGE_ACTIVATION_TYPE, FORGE_MIGRATION_SETTINGS, FORGE_TOKEN_SETTINGS, forgeFeeSchedulerParam, } from './settings.js';
|
|
35
|
-
import {
|
|
35
|
+
import { estimatePriorityFee, fixedPriorityFee, priorityFeeInstructions, resolvePriorityFeePolicy, } from './priority-fee.js';
|
|
36
36
|
import { ValidationError, assertValid, validateLaunchpadCoinConfigParams, validateLaunchpadConfigParams, } from './validate.js';
|
|
37
37
|
// ---------------------------------------------------------------------------------------------
|
|
38
38
|
// Settings
|
|
@@ -570,6 +570,12 @@ export class CreateConfigError extends Error {
|
|
|
570
570
|
*/
|
|
571
571
|
export async function buildCreateConfigTx(params) {
|
|
572
572
|
const configAddress = params.config instanceof PublicKey ? params.config : params.config.publicKey;
|
|
573
|
+
if (params.priority !== undefined) {
|
|
574
|
+
if (params.computeUnitPriceMicroLamports !== undefined) {
|
|
575
|
+
throw new RangeError('pass either priority or computeUnitPriceMicroLamports, not both');
|
|
576
|
+
}
|
|
577
|
+
resolvePriorityFeePolicy(params.priority);
|
|
578
|
+
}
|
|
573
579
|
const configParams = buildConfigParams(params.spec, params.kind, params.metadataUri !== undefined ? { metadataUri: params.metadataUri } : {});
|
|
574
580
|
if (configAddress.equals(params.payer) ||
|
|
575
581
|
configAddress.equals(configParams.feeClaimer) ||
|
|
@@ -588,11 +594,16 @@ export async function buildCreateConfigTx(params) {
|
|
|
588
594
|
});
|
|
589
595
|
const rentLamports = BigInt(await connection.getMinimumBalanceForRentExemption(client.partner.getProgram().account.poolConfig.size));
|
|
590
596
|
const { blockhash, lastValidBlockHeight } = params.recentBlockhash ?? (await connection.getLatestBlockhash('confirmed'));
|
|
597
|
+
const priorityFee = params.priority === undefined
|
|
598
|
+
? fixedPriorityFee(CREATE_CONFIG_COMPUTE_UNITS, params.computeUnitPriceMicroLamports ?? 0)
|
|
599
|
+
: await estimatePriorityFee({
|
|
600
|
+
connection,
|
|
601
|
+
writableAccounts: [params.payer, configAddress],
|
|
602
|
+
computeUnitLimit: CREATE_CONFIG_COMPUTE_UNITS,
|
|
603
|
+
setting: params.priority,
|
|
604
|
+
});
|
|
591
605
|
const transaction = new Transaction({ feePayer: params.payer, blockhash, lastValidBlockHeight });
|
|
592
|
-
transaction.add(...
|
|
593
|
-
units: CREATE_CONFIG_COMPUTE_UNITS,
|
|
594
|
-
microLamports: params.computeUnitPriceMicroLamports ?? 0,
|
|
595
|
-
}), ...sdkTx.instructions);
|
|
606
|
+
transaction.add(...priorityFeeInstructions(priorityFee), ...sdkTx.instructions);
|
|
596
607
|
return {
|
|
597
608
|
transaction,
|
|
598
609
|
configAddress,
|
|
@@ -600,5 +611,6 @@ export async function buildCreateConfigTx(params) {
|
|
|
600
611
|
rentLamports,
|
|
601
612
|
lastValidBlockHeight,
|
|
602
613
|
signers: [params.payer, configAddress],
|
|
614
|
+
priorityFee,
|
|
603
615
|
};
|
|
604
616
|
}
|
package/dist/constants.d.ts
CHANGED
|
@@ -45,3 +45,19 @@ export declare const CLIENT_POOL_CREATION_FEE_LAMPORTS: {
|
|
|
45
45
|
readonly max: bigint;
|
|
46
46
|
readonly allowZero: true;
|
|
47
47
|
};
|
|
48
|
+
/**
|
|
49
|
+
* Referral fee range of Jupiter Ultra, in bps. The Jupiter Plugin passes `referralFee` as is to
|
|
50
|
+
* Ultra `/order`, which refuses any value outside 50..255 ("must be between 50 and 255
|
|
51
|
+
* (inclusive)", checked on 2026-10-17); Jupiter keeps 20% of the fee.
|
|
52
|
+
* @see https://developers.jup.ag/docs/swap/fees
|
|
53
|
+
*/
|
|
54
|
+
export declare const JUPITER_REFERRAL_FEE_BPS_RANGE: {
|
|
55
|
+
readonly min: 50;
|
|
56
|
+
readonly max: 255;
|
|
57
|
+
};
|
|
58
|
+
/**
|
|
59
|
+
* Returns `bps` when Jupiter Ultra accepts it as a referral fee: a whole number of bps within
|
|
60
|
+
* `JUPITER_REFERRAL_FEE_BPS_RANGE`. Throws a `RangeError` otherwise: with such a fee Jupiter
|
|
61
|
+
* refuses every swap, so it must never reach the plugin.
|
|
62
|
+
*/
|
|
63
|
+
export declare function assertJupiterReferralFeeBps(bps: number): number;
|
package/dist/constants.js
CHANGED
|
@@ -68,3 +68,23 @@ export const CLIENT_POOL_CREATION_FEE_LAMPORTS = {
|
|
|
68
68
|
max: solToLamports(CLIENT_BOUNDS.poolCreationFeeSol.max),
|
|
69
69
|
allowZero: CLIENT_BOUNDS.poolCreationFeeSol.allowZero,
|
|
70
70
|
};
|
|
71
|
+
/**
|
|
72
|
+
* Referral fee range of Jupiter Ultra, in bps. The Jupiter Plugin passes `referralFee` as is to
|
|
73
|
+
* Ultra `/order`, which refuses any value outside 50..255 ("must be between 50 and 255
|
|
74
|
+
* (inclusive)", checked on 2026-10-17); Jupiter keeps 20% of the fee.
|
|
75
|
+
* @see https://developers.jup.ag/docs/swap/fees
|
|
76
|
+
*/
|
|
77
|
+
export const JUPITER_REFERRAL_FEE_BPS_RANGE = { min: 50, max: 255 };
|
|
78
|
+
/**
|
|
79
|
+
* Returns `bps` when Jupiter Ultra accepts it as a referral fee: a whole number of bps within
|
|
80
|
+
* `JUPITER_REFERRAL_FEE_BPS_RANGE`. Throws a `RangeError` otherwise: with such a fee Jupiter
|
|
81
|
+
* refuses every swap, so it must never reach the plugin.
|
|
82
|
+
*/
|
|
83
|
+
export function assertJupiterReferralFeeBps(bps) {
|
|
84
|
+
const { min, max } = JUPITER_REFERRAL_FEE_BPS_RANGE;
|
|
85
|
+
if (!Number.isInteger(bps) || bps < min || bps > max) {
|
|
86
|
+
throw new RangeError(`Jupiter referral fee must be a whole number of bps between ${min} and ${max} ` +
|
|
87
|
+
`(Jupiter Ultra refuses any other value), got ${String(bps)}`);
|
|
88
|
+
}
|
|
89
|
+
return bps;
|
|
90
|
+
}
|