@epicentral/sos-sdk 0.2.4 → 0.2.5
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/accounts/fetchers.ts +38 -0
- package/index.ts +1 -0
- package/long/exercise.ts +7 -2
- package/package.json +1 -1
- package/shared/balances.ts +57 -0
package/accounts/fetchers.ts
CHANGED
|
@@ -129,3 +129,41 @@ export async function fetchManyAccounts(
|
|
|
129
129
|
exists: infos[index] !== null,
|
|
130
130
|
}));
|
|
131
131
|
}
|
|
132
|
+
|
|
133
|
+
const optionDecoder = getOptionAccountDecoder();
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Batch-fetches option accounts via getMultipleAccounts (one RPC round-trip).
|
|
137
|
+
* Returns a Map from address to OptionAccount or null if missing/invalid.
|
|
138
|
+
*/
|
|
139
|
+
export async function fetchOptionAccounts(
|
|
140
|
+
rpc: KitRpc,
|
|
141
|
+
addresses: AddressLike[]
|
|
142
|
+
): Promise<Map<Address, OptionAccount | null>> {
|
|
143
|
+
if (addresses.length === 0) return new Map();
|
|
144
|
+
const keys = addresses.map((value) => toAddress(value));
|
|
145
|
+
const response = await rpc.getMultipleAccounts(keys, { encoding: "base64" }).send();
|
|
146
|
+
const infos = response.value;
|
|
147
|
+
const result = new Map<Address, OptionAccount | null>();
|
|
148
|
+
for (let i = 0; i < keys.length; i++) {
|
|
149
|
+
const accountInfo = infos[i];
|
|
150
|
+
if (!accountInfo) {
|
|
151
|
+
result.set(keys[i], null);
|
|
152
|
+
continue;
|
|
153
|
+
}
|
|
154
|
+
const [b64] = accountInfo.data;
|
|
155
|
+
if (!b64) {
|
|
156
|
+
result.set(keys[i], null);
|
|
157
|
+
continue;
|
|
158
|
+
}
|
|
159
|
+
const binary = atob(b64);
|
|
160
|
+
const data = new Uint8Array(binary.length);
|
|
161
|
+
for (let j = 0; j < binary.length; j++) data[j] = binary.charCodeAt(j);
|
|
162
|
+
try {
|
|
163
|
+
result.set(keys[i], optionDecoder.decode(data));
|
|
164
|
+
} catch {
|
|
165
|
+
result.set(keys[i], null);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
return result;
|
|
169
|
+
}
|
package/index.ts
CHANGED
|
@@ -9,6 +9,7 @@ export * from "./accounts/list";
|
|
|
9
9
|
export * from "./accounts/resolve-option";
|
|
10
10
|
|
|
11
11
|
export * from "./shared/amounts";
|
|
12
|
+
export * from "./shared/balances";
|
|
12
13
|
export * from "./shared/errors";
|
|
13
14
|
export * from "./shared/remaining-accounts";
|
|
14
15
|
export * from "./shared/transactions";
|
package/long/exercise.ts
CHANGED
|
@@ -18,6 +18,10 @@ export interface BuildOptionExerciseParams {
|
|
|
18
18
|
tokenProgram?: AddressLike;
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
+
/**
|
|
22
|
+
* Legacy escrow-based option exercise. Prefer pool flows: close_long_to_pool and auto_exercise_expired.
|
|
23
|
+
* @deprecated Use buildCloseLongToPoolTransaction for closing longs and rely on auto_exercise_expired for expiration.
|
|
24
|
+
*/
|
|
21
25
|
export function buildOptionExerciseInstruction(
|
|
22
26
|
params: BuildOptionExerciseParams
|
|
23
27
|
): Instruction<string> {
|
|
@@ -38,8 +42,9 @@ export function buildOptionExerciseInstruction(
|
|
|
38
42
|
}
|
|
39
43
|
|
|
40
44
|
/**
|
|
41
|
-
* Builds an option exercise transaction
|
|
42
|
-
*
|
|
45
|
+
* Builds an option exercise transaction (escrow/ask-based flow).
|
|
46
|
+
* Prefer pool-based flows: buildCloseLongToPoolTransaction for closing longs and auto_exercise_expired for expired ITM.
|
|
47
|
+
* @deprecated Use buildCloseLongToPoolTransaction and auto_exercise_expired; do not use for new flows.
|
|
43
48
|
*/
|
|
44
49
|
export function buildOptionExerciseTransaction(
|
|
45
50
|
params: BuildOptionExerciseParams
|
package/package.json
CHANGED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import type { Address } from "@solana/kit";
|
|
2
|
+
import { deriveAssociatedTokenAddress } from "../accounts/pdas";
|
|
3
|
+
import { toAddress } from "../client/program";
|
|
4
|
+
import type { AddressLike, KitRpc } from "../client/types";
|
|
5
|
+
import { NATIVE_MINT } from "../wsol/instructions";
|
|
6
|
+
|
|
7
|
+
/** SPL Token account data: amount field offset (u64 LE). */
|
|
8
|
+
const TOKEN_ACCOUNT_AMOUNT_OFFSET = 64;
|
|
9
|
+
|
|
10
|
+
function decodeTokenAccountAmount(data: Uint8Array): bigint {
|
|
11
|
+
if (data.length < TOKEN_ACCOUNT_AMOUNT_OFFSET + 8) return BigInt(0);
|
|
12
|
+
const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
|
|
13
|
+
return view.getBigUint64(TOKEN_ACCOUNT_AMOUNT_OFFSET, true);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
async function fetchTokenAccountBalance(rpc: KitRpc, ata: Address): Promise<bigint> {
|
|
17
|
+
const response = await rpc.getAccountInfo(ata, { encoding: "base64" }).send();
|
|
18
|
+
const accountInfo = response.value;
|
|
19
|
+
if (!accountInfo) return BigInt(0);
|
|
20
|
+
const [b64] = accountInfo.data;
|
|
21
|
+
if (!b64) return BigInt(0);
|
|
22
|
+
const binary = atob(b64);
|
|
23
|
+
const data = new Uint8Array(binary.length);
|
|
24
|
+
for (let i = 0; i < binary.length; i++) data[i] = binary.charCodeAt(i);
|
|
25
|
+
return decodeTokenAccountAmount(data);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Returns the SPL token balance for an owner and mint in base units (smallest units).
|
|
30
|
+
* Derives the associated token account; returns 0n if the ATA does not exist or has no data.
|
|
31
|
+
*/
|
|
32
|
+
export async function getTokenBalance(
|
|
33
|
+
owner: AddressLike,
|
|
34
|
+
mint: AddressLike,
|
|
35
|
+
rpc: KitRpc
|
|
36
|
+
): Promise<bigint> {
|
|
37
|
+
const ata = await deriveAssociatedTokenAddress(owner, mint);
|
|
38
|
+
return fetchTokenAccountBalance(rpc, ata);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Returns native SOL balance (lamports), wrapped SOL (WSOL) balance (base units), and total (native + wrapped).
|
|
43
|
+
* Use for SOL pools when the UI should show combined "total SOL".
|
|
44
|
+
*/
|
|
45
|
+
export async function getCombinedSOLBalance(
|
|
46
|
+
owner: AddressLike,
|
|
47
|
+
rpc: KitRpc
|
|
48
|
+
): Promise<{ native: bigint; wrapped: bigint; total: bigint }> {
|
|
49
|
+
const ownerAddress = toAddress(owner);
|
|
50
|
+
const [nativeResponse, wrappedBalance] = await Promise.all([
|
|
51
|
+
rpc.getBalance(ownerAddress).send(),
|
|
52
|
+
getTokenBalance(ownerAddress, NATIVE_MINT, rpc),
|
|
53
|
+
]);
|
|
54
|
+
const native = nativeResponse.value;
|
|
55
|
+
const total = native + wrappedBalance;
|
|
56
|
+
return { native, wrapped: wrappedBalance, total };
|
|
57
|
+
}
|