@augustdigital/sdk 9.11.0 → 9.12.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/lib/adapters/solana/constants.d.ts +12 -4
- package/lib/adapters/solana/constants.js +8 -3
- package/lib/adapters/solana/getters.d.ts +5 -0
- package/lib/adapters/solana/getters.js +35 -1
- package/lib/adapters/solana/idl/vault-idl.d.ts +334 -7
- package/lib/adapters/solana/idl/vault-idl.js +600 -59
- package/lib/adapters/solana/idl/withdrawal-queue-idl.d.ts +790 -0
- package/lib/adapters/solana/idl/withdrawal-queue-idl.js +1868 -0
- package/lib/adapters/solana/index.d.ts +108 -10
- package/lib/adapters/solana/index.js +137 -12
- package/lib/adapters/solana/pricing.d.ts +11 -0
- package/lib/adapters/solana/pricing.js +24 -8
- package/lib/adapters/solana/queue.actions.d.ts +98 -0
- package/lib/adapters/solana/queue.actions.js +488 -0
- package/lib/adapters/solana/token-reads.d.ts +108 -0
- package/lib/adapters/solana/token-reads.js +145 -0
- package/lib/adapters/solana/types.d.ts +200 -1
- package/lib/adapters/solana/utils.d.ts +16 -0
- package/lib/adapters/solana/utils.js +41 -4
- package/lib/adapters/solana/vault.actions.d.ts +17 -0
- package/lib/adapters/solana/vault.actions.js +14 -125
- package/lib/adapters/solana/withdrawal-queue.d.ts +125 -0
- package/lib/adapters/solana/withdrawal-queue.js +301 -0
- package/lib/core/analytics/method-taxonomy.js +2 -0
- package/lib/core/analytics/version.d.ts +1 -1
- package/lib/core/analytics/version.js +1 -1
- package/lib/main.d.ts +16 -0
- package/lib/main.js +16 -0
- package/lib/modules/vaults/getters.d.ts +2 -2
- package/lib/modules/vaults/getters.js +103 -3
- package/lib/modules/vaults/main.d.ts +12 -0
- package/lib/modules/vaults/main.js +17 -1
- package/lib/modules/vaults/types.d.ts +14 -1
- package/lib/sdk.d.ts +2389 -1723
- package/lib/types/vaults.d.ts +47 -1
- package/lib/types/vaults.js +5 -0
- package/lib/types/webserver.d.ts +8 -0
- package/package.json +1 -1
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.readPricingSnapshot = readPricingSnapshot;
|
|
4
|
+
exports.resolveUserTokenAccount = resolveUserTokenAccount;
|
|
5
|
+
/**
|
|
6
|
+
* Account reads shared by the Solana write handlers (`vault.actions.ts`,
|
|
7
|
+
* `queue.actions.ts`) and the withdrawal-queue readers.
|
|
8
|
+
*
|
|
9
|
+
* Internal: kept out of `vault.actions.ts` because `Solana.actions` is that
|
|
10
|
+
* whole module, so anything exported from it becomes public API.
|
|
11
|
+
*/
|
|
12
|
+
const spl_token_1 = require("@solana/spl-token");
|
|
13
|
+
const core_1 = require("../../core");
|
|
14
|
+
const utils_1 = require("./utils");
|
|
15
|
+
/**
|
|
16
|
+
* The vault state and share-mint supply as of a **single slot**.
|
|
17
|
+
*
|
|
18
|
+
* Both figures price the quote, so they have to come from one snapshot. Read
|
|
19
|
+
* independently — even concurrently, as two RPC requests — a deposit or
|
|
20
|
+
* redemption landing in between combines a supply and an asset total that
|
|
21
|
+
* never coexisted, and the quote is wrong in whichever direction the
|
|
22
|
+
* interleaving fell. Seeing a 10% deposit's new assets against the old supply
|
|
23
|
+
* quotes ~10% high, and the floor then rejects a redemption whose share price
|
|
24
|
+
* never moved; the opposite ordering quotes low and silently weakens the
|
|
25
|
+
* protection. `getMultipleAccountsInfo` is served from one slot, so the pair
|
|
26
|
+
* is always coherent — and it costs one round trip instead of two.
|
|
27
|
+
*
|
|
28
|
+
* @param program - Anchor program, used only for its account coder; the
|
|
29
|
+
* provider it was built with is irrelevant, so no read-only program is needed.
|
|
30
|
+
* @param vaultStatePda - Vault state account to decode.
|
|
31
|
+
* @param shareMintAddr - Share mint whose supply and decimals are read.
|
|
32
|
+
* @param extraAccounts - Further accounts to read in the same call and slot,
|
|
33
|
+
* returned raw and in order (`null` for an absent one). Lets a caller that
|
|
34
|
+
* also needs, say, token accounts avoid a second round trip.
|
|
35
|
+
* @returns The decoded `VaultState`, the share mint's raw `supply`, its
|
|
36
|
+
* `decimals`, and `extraAccountInfos` — all from the same slot.
|
|
37
|
+
* @throws {@link AugustSDKError} when either account is absent, or is not the
|
|
38
|
+
* account type it should be.
|
|
39
|
+
*/
|
|
40
|
+
async function readPricingSnapshot({ connection, program, vaultStatePda, shareMintAddr, extraAccounts = [], }) {
|
|
41
|
+
const [vaultStateInfo, shareMintInfo, ...extraAccountInfos] = await connection.getMultipleAccountsInfo([
|
|
42
|
+
vaultStatePda,
|
|
43
|
+
shareMintAddr,
|
|
44
|
+
...extraAccounts,
|
|
45
|
+
]);
|
|
46
|
+
if (!vaultStateInfo) {
|
|
47
|
+
throw new core_1.AugustSDKError('UNKNOWN', `Vault state account ${vaultStatePda.toBase58()} does not exist; it cannot be priced.`);
|
|
48
|
+
}
|
|
49
|
+
if (!shareMintInfo) {
|
|
50
|
+
throw new core_1.AugustSDKError('UNKNOWN', `Share mint ${shareMintAddr.toBase58()} does not exist; it cannot be priced.`);
|
|
51
|
+
}
|
|
52
|
+
// `vaultState`, not the IDL's own `VaultState`: `Program` runs the IDL
|
|
53
|
+
// through `convertIdlToCamelCase`, so its coder only answers to the
|
|
54
|
+
// camelCase name and the IDL spelling throws `Account not found`. (A coder
|
|
55
|
+
// built directly from the raw IDL behaves the opposite way — which is why
|
|
56
|
+
// this has to be checked against a real `Program`, as its test does.)
|
|
57
|
+
//
|
|
58
|
+
// Decoded by name rather than `decodeAny`, so a `vaultAddress` pointing at
|
|
59
|
+
// some other account of this program fails here instead of being decoded as
|
|
60
|
+
// whatever it happens to be.
|
|
61
|
+
let vaultStateData;
|
|
62
|
+
try {
|
|
63
|
+
vaultStateData = program.coder.accounts.decode('vaultState', vaultStateInfo.data);
|
|
64
|
+
}
|
|
65
|
+
catch (e) {
|
|
66
|
+
throw new core_1.AugustSDKError('UNKNOWN', `Account ${vaultStatePda.toBase58()} is not a vault state account for this program.`, { cause: e });
|
|
67
|
+
}
|
|
68
|
+
let mint;
|
|
69
|
+
try {
|
|
70
|
+
mint = (0, spl_token_1.unpackMint)(shareMintAddr, shareMintInfo, spl_token_1.TOKEN_PROGRAM_ID);
|
|
71
|
+
}
|
|
72
|
+
catch (e) {
|
|
73
|
+
throw new core_1.AugustSDKError('UNKNOWN', `Account ${shareMintAddr.toBase58()} is not an SPL Token mint.`, { cause: e });
|
|
74
|
+
}
|
|
75
|
+
return {
|
|
76
|
+
vaultStateData,
|
|
77
|
+
supply: mint.supply,
|
|
78
|
+
shareDecimals: mint.decimals,
|
|
79
|
+
extraAccountInfos,
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Pick which token account to hand the vault program for a given mint, and
|
|
84
|
+
* describe how to create it when the user has none.
|
|
85
|
+
*
|
|
86
|
+
* The vault program constrains these accounts by `token::mint` +
|
|
87
|
+
* `token::authority` (not `associated_token::…`), so any account the signer
|
|
88
|
+
* owns qualifies. We therefore keep an existing account when there is one —
|
|
89
|
+
* that is where the user's balance already lives — and fall back to the
|
|
90
|
+
* associated token account otherwise.
|
|
91
|
+
*
|
|
92
|
+
* Two deliberate choices:
|
|
93
|
+
*
|
|
94
|
+
* - **The create is returned, not sent.** Prepended to the deposit/redeem via
|
|
95
|
+
* `.preInstructions()` it is atomic with the transfer, so there is no window
|
|
96
|
+
* in which the vault instruction can reference an account that has not
|
|
97
|
+
* landed. Sent as its own transaction — as this module used to — it raced
|
|
98
|
+
* its own confirmation. Observed in production (2026-08-11):
|
|
99
|
+
* a deposit failed with `Simulation failed … Logs: []` while the share-ATA
|
|
100
|
+
* create was still in flight, then succeeded 17s later on retry. The empty
|
|
101
|
+
* log array means the transaction never reached program execution, so there
|
|
102
|
+
* was nothing on-chain to debug from.
|
|
103
|
+
* - **Idempotent.** `createAssociatedTokenAccountIdempotentInstruction` is a
|
|
104
|
+
* no-op when the account already exists, so a concurrent create — another
|
|
105
|
+
* tab, a wallet's auto-provisioning — cannot turn into an
|
|
106
|
+
* `SystemError::AccountAlreadyInUse` ("already in use") failure between our
|
|
107
|
+
* read and our submit.
|
|
108
|
+
*
|
|
109
|
+
* Which account wins when several exist is decided by
|
|
110
|
+
* {@link selectRichestTokenAccount} — the same rule every balance *read* in
|
|
111
|
+
* this adapter uses, so the account a UI reports and the account a transfer
|
|
112
|
+
* names are never different accounts.
|
|
113
|
+
*
|
|
114
|
+
* Classic SPL Token only: the ATA is derived under `TOKEN_PROGRAM_ID`, matching
|
|
115
|
+
* the `tokenProgram` both handlers pass, even though the program's
|
|
116
|
+
* `TokenInterface` would also accept Token-2022.
|
|
117
|
+
*
|
|
118
|
+
* @param owner - Wallet that owns the account and pays rent for any creation.
|
|
119
|
+
* @throws AugustSDKError when a candidate account's balance cannot be read
|
|
120
|
+
* (propagated from the shared selector).
|
|
121
|
+
*/
|
|
122
|
+
async function resolveUserTokenAccount({ connection, owner, mint, }) {
|
|
123
|
+
const existing = await connection.getParsedTokenAccountsByOwner(owner, {
|
|
124
|
+
mint,
|
|
125
|
+
});
|
|
126
|
+
const richest = (0, utils_1.selectRichestTokenAccount)(existing.value);
|
|
127
|
+
if (richest)
|
|
128
|
+
return {
|
|
129
|
+
address: richest.pubkey,
|
|
130
|
+
balance: richest.amount,
|
|
131
|
+
frozen: richest.frozen,
|
|
132
|
+
};
|
|
133
|
+
// Off-curve allowed: a multisig vault holds and signs as a PDA.
|
|
134
|
+
const ata = await (0, spl_token_1.getAssociatedTokenAddress)(mint, owner, true);
|
|
135
|
+
return {
|
|
136
|
+
address: ata,
|
|
137
|
+
balance: BigInt(0),
|
|
138
|
+
frozen: false,
|
|
139
|
+
createIx: (0, spl_token_1.createAssociatedTokenAccountIdempotentInstruction)(owner, // payer
|
|
140
|
+
ata, // associated token account
|
|
141
|
+
owner, // owner
|
|
142
|
+
mint),
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
//# sourceMappingURL=token-reads.js.map
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { AnchorProvider } from '@coral-xyz/anchor';
|
|
1
|
+
import type { AnchorProvider, BN } from '@coral-xyz/anchor';
|
|
2
2
|
import type { Connection, PublicKey } from '@solana/web3.js';
|
|
3
3
|
export type ISolanaRpcEndpoint = `https://${string}`;
|
|
4
4
|
export type ISolanaNetwork = 'devnet' | 'mainnet-beta' | 'testnet' | 'localnet';
|
|
@@ -17,11 +17,129 @@ export interface ISolanaVaultState {
|
|
|
17
17
|
withdrawalFee: number | null;
|
|
18
18
|
localAum: number | null;
|
|
19
19
|
deployedAum: number | null;
|
|
20
|
+
/**
|
|
21
|
+
* Virtual-share offset the program prices with (a power of ten). Absent on
|
|
22
|
+
* builds that predate it, and `0` on vaults created before it; read it
|
|
23
|
+
* through `resolveShareOffset`, which maps both to the default.
|
|
24
|
+
*/
|
|
25
|
+
shareOffset?: BN | null;
|
|
20
26
|
aumIncreaseLimit: number | null;
|
|
21
27
|
aumDecreaseLimit: number | null;
|
|
22
28
|
pdaBump: number[] | null;
|
|
23
29
|
vaultVersion: number[] | null;
|
|
24
30
|
paused: boolean | null;
|
|
31
|
+
/**
|
|
32
|
+
* The only key the vault accepts a redeem from, or the default (all-zero)
|
|
33
|
+
* public key when no withdrawal queue is attached. When set it is this
|
|
34
|
+
* vault's withdrawal-queue PDA: a direct holder redeem is refused with
|
|
35
|
+
* `WithdrawalQueueRequired` (6021), and holders exit through the queue
|
|
36
|
+
* instead. Vaults created before the queue existed read the default key.
|
|
37
|
+
*/
|
|
38
|
+
withdrawalQueueAuthority: PublicKey | null;
|
|
39
|
+
/**
|
|
40
|
+
* Number of registered operator subaccounts. Non-zero means operator
|
|
41
|
+
* transfers must go to a registered subaccount; `0` on vaults created before
|
|
42
|
+
* subaccounts existed, and on every mainnet vault today.
|
|
43
|
+
*/
|
|
44
|
+
subaccountCount: BN | null;
|
|
45
|
+
/**
|
|
46
|
+
* Raw deposit-mint units taken out to subaccounts and not yet returned,
|
|
47
|
+
* across all of them. Distinct from `deployedAum`, which the operator marks
|
|
48
|
+
* without moving tokens. Informational: nothing on-chain trusts it.
|
|
49
|
+
*/
|
|
50
|
+
deployedPrincipal: BN | null;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* A vault's withdrawal queue account (`WithdrawalQueue` in the
|
|
54
|
+
* august_withdrawal_queue program), as Anchor decodes it.
|
|
55
|
+
*
|
|
56
|
+
* One per vault, at the PDA `["withdrawal_queue", vault_state]`. Integer fields
|
|
57
|
+
* are `BN`s in raw on-chain units; times are in seconds.
|
|
58
|
+
*/
|
|
59
|
+
export interface ISolanaWithdrawalQueueState {
|
|
60
|
+
/** The vault this queue serves. */
|
|
61
|
+
vaultState: PublicKey;
|
|
62
|
+
/** The vault's deposit mint, copied at initialization. */
|
|
63
|
+
depositMint: PublicKey;
|
|
64
|
+
/** The vault's share mint, copied at initialization. */
|
|
65
|
+
shareMint: PublicKey;
|
|
66
|
+
/** The queue's share escrow: holds every pending request's shares. */
|
|
67
|
+
escrowShares: PublicKey;
|
|
68
|
+
/**
|
|
69
|
+
* The queue's deposit-mint escrow. Transit only: a payout passes through it
|
|
70
|
+
* within the finalizing transaction, so it normally holds nothing.
|
|
71
|
+
*/
|
|
72
|
+
escrowAssets: PublicKey;
|
|
73
|
+
/**
|
|
74
|
+
* Seconds between a request and its eligibility. Stamped on each request when
|
|
75
|
+
* it is created, so a change applies to later requests only.
|
|
76
|
+
*/
|
|
77
|
+
cooldownSeconds: BN;
|
|
78
|
+
/**
|
|
79
|
+
* Seconds after scheduled eligibility that a request may still be finalized,
|
|
80
|
+
* or `0` for no expiry. Stamped on each request when it is created.
|
|
81
|
+
*/
|
|
82
|
+
fulfillmentWindowSeconds: BN;
|
|
83
|
+
/** Queue-wide counter; the last value stamped on a request (the first is 1). */
|
|
84
|
+
sequence: BN;
|
|
85
|
+
/** Number of live (unfinalized, uncancelled) requests. */
|
|
86
|
+
pendingRequests: BN;
|
|
87
|
+
/** Raw shares escrowed across all live requests. */
|
|
88
|
+
pendingShares: BN;
|
|
89
|
+
/** Canonical bump of the queue PDA. */
|
|
90
|
+
bump: number;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* One withdrawal request (`WithdrawalRequest` in the august_withdrawal_queue
|
|
94
|
+
* program), as Anchor decodes it.
|
|
95
|
+
*
|
|
96
|
+
* At the PDA `["withdrawal_request", queue, owner, request_id as u64 LE]`. The
|
|
97
|
+
* account exists while the request is pending and is closed when it is
|
|
98
|
+
* finalized or cancelled. Integer fields are `BN`s; times are Unix seconds.
|
|
99
|
+
*/
|
|
100
|
+
export interface ISolanaWithdrawalRequestState {
|
|
101
|
+
/** The queue holding this request's shares. */
|
|
102
|
+
queue: PublicKey;
|
|
103
|
+
/** Who requested; may cancel, and may always finalize. */
|
|
104
|
+
owner: PublicKey;
|
|
105
|
+
/** Deposit-mint token account the payout goes to. */
|
|
106
|
+
recipientTokenAccount: PublicKey;
|
|
107
|
+
/**
|
|
108
|
+
* Who may finalize besides the owner, or the default (all-zero) public key
|
|
109
|
+
* for anyone.
|
|
110
|
+
*/
|
|
111
|
+
finalizer: PublicKey;
|
|
112
|
+
/** Raw shares escrowed for this request. */
|
|
113
|
+
shares: BN;
|
|
114
|
+
/** Owner-chosen id, unique per owner while the request exists. */
|
|
115
|
+
requestId: BN;
|
|
116
|
+
/**
|
|
117
|
+
* Queue-wide stamp given at creation. Instructions that target the request
|
|
118
|
+
* pass it as `expected_sequence`, so a delayed call cannot land on a
|
|
119
|
+
* recreated request with the same id.
|
|
120
|
+
*/
|
|
121
|
+
sequence: BN;
|
|
122
|
+
/** When the request was created. */
|
|
123
|
+
requestedAt: BN;
|
|
124
|
+
/** `requestedAt + cooldown` at creation. Never changes. */
|
|
125
|
+
scheduledEligibleAt: BN;
|
|
126
|
+
/**
|
|
127
|
+
* When finalization may begin. Equals `scheduledEligibleAt` unless an admin
|
|
128
|
+
* or operator expedited the request, which only ever moves it earlier.
|
|
129
|
+
*/
|
|
130
|
+
eligibleAt: BN;
|
|
131
|
+
/**
|
|
132
|
+
* When the request stops being finalizable (the instant itself counts as
|
|
133
|
+
* expired), or `0` for never. An expired request can only be cancelled.
|
|
134
|
+
*/
|
|
135
|
+
expiresAt: BN;
|
|
136
|
+
/** Bump of the request PDA. */
|
|
137
|
+
bump: number;
|
|
138
|
+
/**
|
|
139
|
+
* The owner's floor on the net payout, in raw deposit-mint units; `0` for
|
|
140
|
+
* none. A claim that would pay less is refused with `PayoutBelowFloor`.
|
|
141
|
+
*/
|
|
142
|
+
minAssetsOut: BN;
|
|
25
143
|
}
|
|
26
144
|
export interface ISolanaToken {
|
|
27
145
|
address: string;
|
|
@@ -117,4 +235,85 @@ export interface ISolanaRedeemOptions {
|
|
|
117
235
|
* silently dropped; with neither, the plain `redeem` is sent.
|
|
118
236
|
*/
|
|
119
237
|
minAssetsOut?: bigint;
|
|
238
|
+
/**
|
|
239
|
+
* Claim this withdrawal request instead of redeeming instantly: the request
|
|
240
|
+
* account's address, as `id` on the entries `getVaultAvailableRedemptions`
|
|
241
|
+
* returns. Its shares, recipient and vault come from the request, so the
|
|
242
|
+
* `redeemShares` and `vaultAddress` arguments are ignored. The queue pays
|
|
243
|
+
* at the share price of the moment it settles, held to the floor the request
|
|
244
|
+
* was made with, so `slippageBps` and `minAssetsOut` must not be set
|
|
245
|
+
* alongside it.
|
|
246
|
+
*
|
|
247
|
+
* Required on a vault with a withdrawal queue attached, which refuses a
|
|
248
|
+
* direct redeem. See {@link SolanaAdapter.vaultRequestRedeem}.
|
|
249
|
+
*/
|
|
250
|
+
request?: PublicKey | string;
|
|
251
|
+
}
|
|
252
|
+
/**
|
|
253
|
+
* Input to {@link SolanaAdapter.vaultRequestRedeem}.
|
|
254
|
+
*/
|
|
255
|
+
export interface ISolanaRequestRedeemParams {
|
|
256
|
+
/** The vault's `VaultState` account address. */
|
|
257
|
+
vault: PublicKey | string;
|
|
258
|
+
/** The holder, who signs, escrows the shares and pays rent for the request. */
|
|
259
|
+
wallet: PublicKey | string;
|
|
260
|
+
/** Shares to escrow: `bigint` in raw share units, or `number` as a UI amount. */
|
|
261
|
+
amount: number | bigint;
|
|
262
|
+
/**
|
|
263
|
+
* Wallet to pay when the request is claimed; its deposit-token account is
|
|
264
|
+
* created in the same transaction if it has none, at the holder's expense.
|
|
265
|
+
* Defaults to the holder.
|
|
266
|
+
*/
|
|
267
|
+
recipient?: PublicKey | string;
|
|
268
|
+
/**
|
|
269
|
+
* The one key besides the holder that may claim the request, e.g. a keeper.
|
|
270
|
+
* Defaults to anyone, which is what lets a keeper settle requests for
|
|
271
|
+
* holders who do not come back.
|
|
272
|
+
*/
|
|
273
|
+
finalizer?: PublicKey | string;
|
|
274
|
+
/**
|
|
275
|
+
* The request's id, unique per holder while it is pending. Defaults to a
|
|
276
|
+
* random `u64`; pass one only to choose it yourself.
|
|
277
|
+
*/
|
|
278
|
+
requestId?: bigint;
|
|
279
|
+
/**
|
|
280
|
+
* Tolerance below the quoted net payout, in basis points (`0` to `10000`).
|
|
281
|
+
* The floor is fixed now and checked when the request is claimed, so it
|
|
282
|
+
* guards against a fee rise or an AUM mark-down in between; yield earned in
|
|
283
|
+
* the meantime only raises the payout. Ignored when `minAssetsOut` is given.
|
|
284
|
+
* @defaultValue 50 (0.5%)
|
|
285
|
+
*/
|
|
286
|
+
slippageBps?: number;
|
|
287
|
+
/**
|
|
288
|
+
* Explicit floor on the net payout, in raw deposit-mint units, stored on the
|
|
289
|
+
* request as is. Skips the quote. `0n` means no floor: the claim pays
|
|
290
|
+
* whatever the shares are worth when it lands.
|
|
291
|
+
*
|
|
292
|
+
* Must be a `bigint` in `0 .. 2^64-1`; anything else throws
|
|
293
|
+
* {@link AugustValidationError} before the transaction is built.
|
|
294
|
+
*/
|
|
295
|
+
minAssetsOut?: bigint;
|
|
296
|
+
}
|
|
297
|
+
/**
|
|
298
|
+
* What {@link SolanaAdapter.vaultRequestRedeem} returns.
|
|
299
|
+
*/
|
|
300
|
+
export interface ISolanaRequestRedeemResult {
|
|
301
|
+
/** The confirmed transaction's signature. */
|
|
302
|
+
signature: string;
|
|
303
|
+
/**
|
|
304
|
+
* The new request account's address: pass it as `request` to claim or
|
|
305
|
+
* cancel. `getVaultAvailableRedemptions` lists it as `id`.
|
|
306
|
+
*/
|
|
307
|
+
request: string;
|
|
308
|
+
/** The request id, as a decimal string (a `u64`). */
|
|
309
|
+
requestId: string;
|
|
310
|
+
}
|
|
311
|
+
/**
|
|
312
|
+
* Input to {@link SolanaAdapter.vaultCancelRedeemRequest}.
|
|
313
|
+
*/
|
|
314
|
+
export interface ISolanaCancelRedeemRequestParams {
|
|
315
|
+
/** The holder who made the request; only they may cancel it. */
|
|
316
|
+
wallet: PublicKey | string;
|
|
317
|
+
/** The request account's address, as returned by `vaultRequestRedeem`. */
|
|
318
|
+
request: PublicKey | string;
|
|
120
319
|
}
|
|
@@ -2,6 +2,7 @@ import { AnchorProvider, BN, Program, type web3 } from '@coral-xyz/anchor';
|
|
|
2
2
|
import { PublicKey, type ParsedAccountData, type Transaction } from '@solana/web3.js';
|
|
3
3
|
import type { ISolanaConnectionOptions, ISolanaVaultState } from './types';
|
|
4
4
|
import { BlockhashConfirmingProvider } from './confirm';
|
|
5
|
+
import type { ISolanaProgramIds } from './constants';
|
|
5
6
|
declare function getExplorerLink({ signature, type, network, }: {
|
|
6
7
|
signature: string;
|
|
7
8
|
type: 'tx' | 'address' | 'token';
|
|
@@ -9,6 +10,19 @@ declare function getExplorerLink({ signature, type, network, }: {
|
|
|
9
10
|
import { isSolanaAddress } from '../../core/helpers/chain-address';
|
|
10
11
|
export { isSolanaAddress };
|
|
11
12
|
declare function isSolana(signature: string): boolean;
|
|
13
|
+
/**
|
|
14
|
+
* Throws unless `type` is a program type `programNames` maps. Checked at
|
|
15
|
+
* runtime for untyped callers: a typo would otherwise read as an undeployed
|
|
16
|
+
* program, and a prototype key like `toString` as a program id.
|
|
17
|
+
* @internal
|
|
18
|
+
*/
|
|
19
|
+
export declare function assertSolanaProgramType(type: unknown): asserts type is keyof ISolanaProgramIds;
|
|
20
|
+
/**
|
|
21
|
+
* Error text for `program` having no canonical deployment on `network`, naming
|
|
22
|
+
* the networks it is deployed on.
|
|
23
|
+
* @internal
|
|
24
|
+
*/
|
|
25
|
+
export declare function undeployedProgramMessage(program: keyof ISolanaProgramIds, network: string): string;
|
|
12
26
|
declare function getProgram({ provider, idl, programId, network, }: {
|
|
13
27
|
idl?: any;
|
|
14
28
|
programId?: string;
|
|
@@ -180,12 +194,14 @@ export declare const SolanaUtils: {
|
|
|
180
194
|
programIds: {
|
|
181
195
|
devnet: {
|
|
182
196
|
vault: string;
|
|
197
|
+
withdrawalQueue: string;
|
|
183
198
|
};
|
|
184
199
|
"mainnet-beta": {
|
|
185
200
|
vault: string;
|
|
186
201
|
};
|
|
187
202
|
localnet: {
|
|
188
203
|
vault: string;
|
|
204
|
+
withdrawalQueue: string;
|
|
189
205
|
};
|
|
190
206
|
};
|
|
191
207
|
getVaultMints: typeof getVaultMints;
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.SolanaUtils = exports.isSolanaAddress = void 0;
|
|
4
|
+
exports.assertSolanaProgramType = assertSolanaProgramType;
|
|
5
|
+
exports.undeployedProgramMessage = undeployedProgramMessage;
|
|
4
6
|
exports.selectRichestTokenAccount = selectRichestTokenAccount;
|
|
5
7
|
exports.uiAmountToRawBn = uiAmountToRawBn;
|
|
6
8
|
const anchor_1 = require("@coral-xyz/anchor");
|
|
@@ -40,8 +42,42 @@ function isSolana(signature) {
|
|
|
40
42
|
// Check length - Solana signatures are typically 88 characters
|
|
41
43
|
return (signature.length >= 80 && signature.length <= 100);
|
|
42
44
|
}
|
|
45
|
+
/** On-chain name (IDL `metadata.name`) of each program type. */
|
|
46
|
+
const programNames = {
|
|
47
|
+
vault: 'august_vault',
|
|
48
|
+
withdrawalQueue: 'august_withdrawal_queue',
|
|
49
|
+
};
|
|
50
|
+
/**
|
|
51
|
+
* Throws unless `type` is a program type `programNames` maps. Checked at
|
|
52
|
+
* runtime for untyped callers: a typo would otherwise read as an undeployed
|
|
53
|
+
* program, and a prototype key like `toString` as a program id.
|
|
54
|
+
* @internal
|
|
55
|
+
*/
|
|
56
|
+
function assertSolanaProgramType(type) {
|
|
57
|
+
if (typeof type !== 'string' || !Object.hasOwn(programNames, type)) {
|
|
58
|
+
throw new core_1.AugustValidationError('INVALID_INPUT', `Unknown Solana program type '${String(type)}'. Expected one of: ${Object.keys(programNames).join(', ')}.`);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Error text for `program` having no canonical deployment on `network`, naming
|
|
63
|
+
* the networks it is deployed on.
|
|
64
|
+
* @internal
|
|
65
|
+
*/
|
|
66
|
+
function undeployedProgramMessage(program, network) {
|
|
67
|
+
const deployed = Object.entries(constants_1.programIds)
|
|
68
|
+
.filter(([, ids]) => ids[program])
|
|
69
|
+
.map(([name]) => name);
|
|
70
|
+
return (`No canonical ${programNames[program]} deployment for Solana network '${network}'. ` +
|
|
71
|
+
`Deployed networks: ${deployed.join(', ')}.`);
|
|
72
|
+
}
|
|
43
73
|
function getProgram({ provider, idl, programId, network, }) {
|
|
44
74
|
const baseIdl = idl ?? constants_1.vaultIdl;
|
|
75
|
+
// The withdrawal queue IDL resolves through `programIds.withdrawalQueue`;
|
|
76
|
+
// anything else is treated as the vault. Recognised by name, so the queue IDL
|
|
77
|
+
// never has to be imported here (and pulled into every bundle).
|
|
78
|
+
const program = baseIdl?.metadata?.name === programNames.withdrawalQueue
|
|
79
|
+
? 'withdrawalQueue'
|
|
80
|
+
: 'vault';
|
|
45
81
|
// Precedence: explicit `programId` → a custom IDL's `address` → the network
|
|
46
82
|
// default → the bundled IDL's embedded `address`.
|
|
47
83
|
//
|
|
@@ -50,7 +86,9 @@ function getProgram({ provider, idl, programId, network, }) {
|
|
|
50
86
|
// copy (second bundle instance, or JSON round-tripped), silently retargeting
|
|
51
87
|
// devnet callers at mainnet. Every copy carries the same build stamp, so it
|
|
52
88
|
// still defers to the network default — but a genuinely custom IDL is honoured.
|
|
53
|
-
|
|
89
|
+
// A build stamp is the program's canonical id, which some network maps.
|
|
90
|
+
const isBuildStamp = Object.values(constants_1.programIds).some((ids) => ids[program] === baseIdl?.address);
|
|
91
|
+
const suppliedAddress = typeof baseIdl?.address === 'string' && !isBuildStamp
|
|
54
92
|
? baseIdl.address
|
|
55
93
|
: undefined;
|
|
56
94
|
const explicitId = programId ?? suppliedAddress;
|
|
@@ -58,10 +96,9 @@ function getProgram({ provider, idl, programId, network, }) {
|
|
|
58
96
|
return new anchor_1.Program({ ...baseIdl, address: explicitId }, provider);
|
|
59
97
|
}
|
|
60
98
|
if (network) {
|
|
61
|
-
const networkDefault = (0, constants_1.getDeployedProgramIds)(network)?.
|
|
99
|
+
const networkDefault = (0, constants_1.getDeployedProgramIds)(network)?.[program];
|
|
62
100
|
if (!networkDefault) {
|
|
63
|
-
throw new core_1.AugustValidationError('INVALID_INPUT',
|
|
64
|
-
`Deployed networks: ${Object.keys(constants_1.programIds).join(', ')}. ` +
|
|
101
|
+
throw new core_1.AugustValidationError('INVALID_INPUT', `${undeployedProgramMessage(program, network)} ` +
|
|
65
102
|
`Pass an explicit \`programId\` (or an IDL carrying the target \`address\`) to target a program on this network.`);
|
|
66
103
|
}
|
|
67
104
|
return new anchor_1.Program({ ...baseIdl, address: networkDefault }, provider);
|
|
@@ -35,6 +35,23 @@ export declare function describeSolanaError(e: unknown): string;
|
|
|
35
35
|
* program's message.
|
|
36
36
|
*/
|
|
37
37
|
export declare function slippageHint(e: unknown): string;
|
|
38
|
+
/**
|
|
39
|
+
* Validate a caller-supplied slippage floor before it reaches Anchor's `u64`
|
|
40
|
+
* encoder.
|
|
41
|
+
*
|
|
42
|
+
* Anchor serializes a `BN` to `u64` via `toArrayLike`, which writes the
|
|
43
|
+
* magnitude and drops the sign — a `-1n` floor would reach the program as a
|
|
44
|
+
* floor of `1`, inverting the caller's intent instead of failing. Values above
|
|
45
|
+
* `u64` fare no better: they surface as an untyped "byte array longer than
|
|
46
|
+
* desired length" from inside the encoder, naming nothing the caller passed.
|
|
47
|
+
* Both are caught here, at the public-API boundary.
|
|
48
|
+
*
|
|
49
|
+
* @param value - The caller's `minSharesOut` / `minAssetsOut`, in raw base units.
|
|
50
|
+
* @param label - Option name, quoted in the error.
|
|
51
|
+
* @returns `value`, once known to fit an unsigned 64-bit integer.
|
|
52
|
+
* @throws {@link AugustValidationError} when it is not a `bigint` in `0 .. 2^64-1`.
|
|
53
|
+
*/
|
|
54
|
+
export declare function validateExplicitFloor(value: bigint, label: string): bigint;
|
|
38
55
|
/**
|
|
39
56
|
* Deposit funds into a Solana August vault and mint share tokens.
|
|
40
57
|
*
|