@epicentral/sos-sdk 0.1.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.
Files changed (110) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +239 -0
  3. package/accounts/fetchers.ts +140 -0
  4. package/accounts/list.ts +152 -0
  5. package/accounts/pdas.ts +308 -0
  6. package/client/lookup-table.ts +32 -0
  7. package/client/program.ts +13 -0
  8. package/client/types.ts +8 -0
  9. package/generated/accounts/collateralPool.ts +217 -0
  10. package/generated/accounts/config.ts +156 -0
  11. package/generated/accounts/dualSourceContract.ts +235 -0
  12. package/generated/accounts/escrowState.ts +183 -0
  13. package/generated/accounts/index.ts +24 -0
  14. package/generated/accounts/lenderPosition.ts +211 -0
  15. package/generated/accounts/liquidityRouter.ts +223 -0
  16. package/generated/accounts/makerCollateralShare.ts +229 -0
  17. package/generated/accounts/makerPoolShare.ts +203 -0
  18. package/generated/accounts/marketDataAccount.ts +176 -0
  19. package/generated/accounts/optionAccount.ts +247 -0
  20. package/generated/accounts/optionPool.ts +253 -0
  21. package/generated/accounts/poolLoan.ts +220 -0
  22. package/generated/accounts/positionAccount.ts +187 -0
  23. package/generated/accounts/priceUpdateV2.ts +163 -0
  24. package/generated/accounts/vault.ts +304 -0
  25. package/generated/accounts/writerPosition.ts +297 -0
  26. package/generated/errors/index.ts +9 -0
  27. package/generated/errors/optionProgram.ts +392 -0
  28. package/generated/index.ts +13 -0
  29. package/generated/instructions/acceptAdmin.ts +230 -0
  30. package/generated/instructions/autoExerciseAllExpired.ts +523 -0
  31. package/generated/instructions/autoExerciseExpired.ts +623 -0
  32. package/generated/instructions/borrowFromPool.ts +554 -0
  33. package/generated/instructions/buyFromPool.ts +684 -0
  34. package/generated/instructions/claimPremium.ts +377 -0
  35. package/generated/instructions/closeLongToPool.ts +716 -0
  36. package/generated/instructions/closeOption.ts +235 -0
  37. package/generated/instructions/createEscrowV2.ts +518 -0
  38. package/generated/instructions/createLiquidityRouter.ts +361 -0
  39. package/generated/instructions/depositCollateral.ts +624 -0
  40. package/generated/instructions/depositToPool.ts +497 -0
  41. package/generated/instructions/depositToPosition.ts +429 -0
  42. package/generated/instructions/index.ts +45 -0
  43. package/generated/instructions/initCollateralPool.ts +513 -0
  44. package/generated/instructions/initConfig.ts +279 -0
  45. package/generated/instructions/initOptionPool.ts +587 -0
  46. package/generated/instructions/initializeMarketData.ts +359 -0
  47. package/generated/instructions/liquidateWriterPosition.ts +592 -0
  48. package/generated/instructions/omlpCreateVault.ts +547 -0
  49. package/generated/instructions/omlpTakeOfferWithFailover.ts +606 -0
  50. package/generated/instructions/omlpUpdateMaxLeverage.ts +304 -0
  51. package/generated/instructions/omlpUpdateProtocolFee.ts +304 -0
  52. package/generated/instructions/omlpUpdateSupplyLimit.ts +304 -0
  53. package/generated/instructions/optionExercise.ts +540 -0
  54. package/generated/instructions/optionMint.ts +1349 -0
  55. package/generated/instructions/optionValidate.ts +255 -0
  56. package/generated/instructions/repayPoolLoan.ts +499 -0
  57. package/generated/instructions/repayPoolLoanFromCollateral.ts +514 -0
  58. package/generated/instructions/settleMakerCollateral.ts +472 -0
  59. package/generated/instructions/syncWriterPosition.ts +206 -0
  60. package/generated/instructions/transferAdmin.ts +245 -0
  61. package/generated/instructions/unwindWriterUnsold.ts +668 -0
  62. package/generated/instructions/updateImpliedVolatility.ts +226 -0
  63. package/generated/instructions/updateMarketData.ts +315 -0
  64. package/generated/instructions/withdrawFromPool.ts +429 -0
  65. package/generated/instructions/withdrawFromPosition.ts +405 -0
  66. package/generated/instructions/writeToPool.ts +594 -0
  67. package/generated/programs/index.ts +9 -0
  68. package/generated/programs/optionProgram.ts +832 -0
  69. package/generated/shared/index.ts +164 -0
  70. package/generated/types/borrowedFromSAP1.ts +75 -0
  71. package/generated/types/borrowedFromSAP2.ts +83 -0
  72. package/generated/types/failoverTriggered.ts +85 -0
  73. package/generated/types/impliedVolatilityUpdated.ts +73 -0
  74. package/generated/types/index.ts +32 -0
  75. package/generated/types/liquidationExecuted.ts +73 -0
  76. package/generated/types/liquidityMetrics.ts +69 -0
  77. package/generated/types/liquidityRouterCreated.ts +79 -0
  78. package/generated/types/marketDataInitialized.ts +61 -0
  79. package/generated/types/marketDataUpdated.ts +69 -0
  80. package/generated/types/optionClosed.ts +56 -0
  81. package/generated/types/optionExercised.ts +62 -0
  82. package/generated/types/optionExpired.ts +49 -0
  83. package/generated/types/optionMinted.ts +78 -0
  84. package/generated/types/optionType.ts +38 -0
  85. package/generated/types/optionValidated.ts +82 -0
  86. package/generated/types/poolLoanCreated.ts +74 -0
  87. package/generated/types/poolLoanRepaid.ts +74 -0
  88. package/generated/types/positionDeposited.ts +73 -0
  89. package/generated/types/positionWithdrawn.ts +81 -0
  90. package/generated/types/priceFeedMessage.ts +117 -0
  91. package/generated/types/protocolFeeUpdated.ts +69 -0
  92. package/generated/types/sap2Provider.ts +38 -0
  93. package/generated/types/vaultCreated.ts +60 -0
  94. package/generated/types/verificationLevel.ts +95 -0
  95. package/index.ts +25 -0
  96. package/long/builders.ts +126 -0
  97. package/long/exercise.ts +49 -0
  98. package/long/quotes.ts +48 -0
  99. package/omlp/builders.ts +74 -0
  100. package/omlp/service.ts +94 -0
  101. package/package.json +22 -0
  102. package/shared/amounts.ts +32 -0
  103. package/shared/errors.ts +12 -0
  104. package/shared/remaining-accounts.ts +41 -0
  105. package/shared/transactions.ts +49 -0
  106. package/short/builders.ts +268 -0
  107. package/short/claim-premium.ts +37 -0
  108. package/short/close-option.ts +34 -0
  109. package/short/pool.ts +224 -0
  110. package/tsconfig.json +12 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Epicentral Labs, DAO LLC
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,239 @@
1
+ # SDK (Frontend-First)
2
+
3
+ This SDK is organized by feature and wraps the Codama-generated client for the `option_program`.
4
+ It is Kit-native and uses `@solana/kit` types (`Address`, `Instruction`, `Rpc`) across the public API.
5
+ The package entrypoint is `@epicentral/sos-sdk`.
6
+
7
+ ## Install
8
+
9
+ ```bash
10
+ pnpm add @solana/kit decimal.js
11
+ ```
12
+
13
+ In this repository, the SDK source lives at `epicentral/sos-sdk` and is packaged as
14
+ `@epicentral/sos-sdk`.
15
+
16
+ ## Structure
17
+
18
+ - `client/` shared program constants and address helpers for the option program.
19
+ - `accounts/` PDA derivation and account fetch helpers.
20
+ - `long/` LONG buy/close/exercise/quote builders.
21
+ - `short/` SHORT mint/unwind/sync/settle plus premium/pool/loan builders.
22
+ - `omlp/` lender deposit/withdraw instruction builders.
23
+ - `shared/` common amount, error, and remaining account helpers.
24
+ - `generated/` Codama-generated client (bundled; do not edit).
25
+
26
+ ## Updating the bundled client
27
+
28
+ The SDK bundles the program client in `generated/`. From the **option-program** repo root:
29
+
30
+ 1. Regenerate the client: `yarn generate:client`.
31
+ 2. Sync into the SDK and copy to the standalone repo: `yarn sync:sdk`.
32
+
33
+ Or run the full pipeline: `yarn generate:client:with-sdk`. The script copies the client into `epicentral/sos-sdk/generated` and then copies the entire SDK to the standalone repo (default `../sos-sdk`) so you can commit from there. Override the standalone path with `STANDALONE_SDK_PATH=/path/to/sos-sdk yarn sync:sdk`.
34
+
35
+ ## Usage model
36
+
37
+ Each flow exposes:
38
+
39
+ - `build*Instruction(params)` for single instruction composition.
40
+ - `build*Transaction(params)` for one-flow `Instruction[]` construction.
41
+ - optional domain services for multi-step flows (no send/confirm).
42
+
43
+ ## Core examples
44
+
45
+ ### Build + send (app-owned)
46
+
47
+ ```ts
48
+ import {
49
+ appendTransactionMessageInstructions,
50
+ createTransactionMessage,
51
+ getSignatureFromTransaction,
52
+ pipe,
53
+ sendAndConfirmTransactionFactory,
54
+ setTransactionMessageFeePayerSigner,
55
+ setTransactionMessageLifetimeUsingBlockhash,
56
+ signTransactionMessageWithSigners,
57
+ } from "@solana/kit";
58
+ import { buildBuyFromPoolTransaction } from "@epicentral/sos-sdk";
59
+
60
+ const built = await buildBuyFromPoolTransaction(params);
61
+ const { value: latestBlockhash } = await rpc.getLatestBlockhash().send();
62
+
63
+ const txMessage = pipe(
64
+ createTransactionMessage({ version: 0 }),
65
+ (tx) => setTransactionMessageFeePayerSigner(walletSigner, tx),
66
+ (tx) => setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, tx),
67
+ (tx) => appendTransactionMessageInstructions(built.instructions, tx)
68
+ );
69
+
70
+ const signedTx = await signTransactionMessageWithSigners(txMessage);
71
+ await sendAndConfirmTransactionFactory({ rpc, rpcSubscriptions })(signedTx, {
72
+ commitment: "confirmed",
73
+ });
74
+
75
+ const signature = getSignatureFromTransaction(signedTx);
76
+ ```
77
+
78
+ ### Build + send (SDK helper)
79
+
80
+ ```ts
81
+ import {
82
+ buildBuyFromPoolTransaction,
83
+ sendBuiltTransaction,
84
+ } from "@epicentral/sos-sdk";
85
+
86
+ const built = await buildBuyFromPoolTransaction(params);
87
+ const signature = await sendBuiltTransaction({
88
+ rpc,
89
+ rpcSubscriptions,
90
+ feePayer: walletSigner,
91
+ instructions: built.instructions,
92
+ });
93
+ ```
94
+
95
+ ### Open LONG / close LONG
96
+
97
+ ```ts
98
+ import {
99
+ buildBuyFromPoolTransaction,
100
+ buildCloseLongToPoolTransaction,
101
+ } from "@epicentral/sos-sdk";
102
+
103
+ const openLong = await buildBuyFromPoolTransaction(openLongParams);
104
+ const closeLong = await buildCloseLongToPoolTransaction(closeLongParams);
105
+ ```
106
+
107
+ ### Exercise LONG
108
+
109
+ ```ts
110
+ import { buildOptionExerciseTransaction } from "@epicentral/sos-sdk";
111
+
112
+ const exercise = buildOptionExerciseTransaction({
113
+ optionAccount,
114
+ positionAccount,
115
+ marketData,
116
+ underlyingMint,
117
+ priceUpdate,
118
+ buyerPaymentAccount,
119
+ makerCollateralAccount,
120
+ escrowState,
121
+ escrowTokenAccount,
122
+ escrowAuthority,
123
+ buyer,
124
+ });
125
+ ```
126
+
127
+ ### Open SHORT (option mint)
128
+
129
+ ```ts
130
+ import { buildOptionMintTransaction, OptionType } from "@epicentral/sos-sdk";
131
+
132
+ const built = await buildOptionMintTransaction({
133
+ optionType: OptionType.Call,
134
+ strikePrice,
135
+ expirationDate,
136
+ quantity,
137
+ underlyingAsset,
138
+ underlyingSymbol,
139
+ makerCollateralAmount,
140
+ borrowedAmount,
141
+ maker,
142
+ makerCollateralAccount,
143
+ underlyingMint,
144
+ });
145
+ ```
146
+
147
+ ### Unwind / Sync / Settle SHORT
148
+
149
+ ```ts
150
+ import {
151
+ buildSettleMakerCollateralTransaction,
152
+ buildSyncWriterPositionTransaction,
153
+ buildUnwindWriterUnsoldTransaction,
154
+ } from "@epicentral/sos-sdk";
155
+
156
+ const unwind = await buildUnwindWriterUnsoldTransaction(unwindParams);
157
+ const sync = buildSyncWriterPositionTransaction(syncParams);
158
+ const settle = await buildSettleMakerCollateralTransaction(settleParams);
159
+ ```
160
+
161
+ ### Claim premium / close option
162
+
163
+ ```ts
164
+ import {
165
+ buildClaimPremiumTransaction,
166
+ buildCloseOptionTransaction,
167
+ } from "@epicentral/sos-sdk";
168
+
169
+ const claim = await buildClaimPremiumTransaction({
170
+ optionPool,
171
+ makerPaymentAccount,
172
+ premiumVault,
173
+ maker,
174
+ });
175
+
176
+ const close = buildCloseOptionTransaction({
177
+ optionAccount,
178
+ optionMint,
179
+ makerOptionAccount,
180
+ maker,
181
+ });
182
+ ```
183
+
184
+ ### Pool liquidity / borrow / repay
185
+
186
+ ```ts
187
+ import {
188
+ buildBorrowFromPoolTransaction,
189
+ buildDepositToPoolTransaction,
190
+ buildRepayPoolLoanTransaction,
191
+ buildWithdrawFromPoolTransaction,
192
+ } from "@epicentral/sos-sdk";
193
+
194
+ const deposit = await buildDepositToPoolTransaction(depositToPoolParams);
195
+ const withdraw = await buildWithdrawFromPoolTransaction(withdrawFromPoolParams);
196
+ const borrow = await buildBorrowFromPoolTransaction(borrowFromPoolParams);
197
+ const repay = await buildRepayPoolLoanTransaction(repayPoolLoanParams);
198
+ ```
199
+
200
+ Repayment source behavior:
201
+
202
+ - `buildRepayPoolLoanTransaction`: principal is repaid from `escrowTokenAccount`; accrued interest + protocol fees are repaid from `makerTokenAccount`.
203
+ - `buildRepayPoolLoanFromCollateralTransaction`: full repayment is sourced from `collateralVault`.
204
+
205
+ ### OMLP deposit/withdraw
206
+
207
+ ```ts
208
+ import {
209
+ buildDepositToPositionTransaction,
210
+ buildWithdrawFromPositionTransaction,
211
+ } from "@epicentral/sos-sdk";
212
+
213
+ const deposit = await buildDepositToPositionTransaction(
214
+ { vault, lenderTokenAccount, vaultTokenAccount, lender, amount }
215
+ );
216
+
217
+ const withdraw = await buildWithdrawFromPositionTransaction(
218
+ { vault, vaultTokenAccount, lenderTokenAccount, lender, amount }
219
+ );
220
+ ```
221
+
222
+ ### Replace Anchor reads with SDK fetchers
223
+
224
+ ```ts
225
+ import { fetchOptionAccount, fetchOptionPool, fetchVault } from "@epicentral/sos-sdk";
226
+
227
+ const option = await fetchOptionAccount(rpc, optionAddress);
228
+ const pool = await fetchOptionPool(rpc, optionPoolAddress);
229
+ const vault = await fetchVault(rpc, vaultAddress);
230
+ ```
231
+
232
+ ## Migration notes
233
+
234
+ - This SDK is the only frontend integration surface for this repository.
235
+ - Legacy `frontend/constants`, `frontend/services`, and `frontend/utils` modules were removed.
236
+ - Replace Anchor `program.account.*` reads with SDK fetchers.
237
+ - Replace Anchor `program.methods.*` writes with SDK builders.
238
+ - App code should own message building, signing, send, and confirmation via `@solana/kit`.
239
+ - `long/service.ts` and `short/service.ts` were removed in favor of direct builder calls.
@@ -0,0 +1,140 @@
1
+ import {
2
+ getCollateralPoolDecoder,
3
+ getLenderPositionDecoder,
4
+ getMakerPoolShareDecoder,
5
+ getMarketDataAccountDecoder,
6
+ getOptionAccountDecoder,
7
+ getOptionPoolDecoder,
8
+ getPoolLoanDecoder,
9
+ getPositionAccountDecoder,
10
+ getVaultDecoder,
11
+ getWriterPositionDecoder,
12
+ type CollateralPool,
13
+ type LenderPosition,
14
+ type MakerPoolShare,
15
+ type MarketDataAccount,
16
+ type OptionAccount,
17
+ type OptionPool,
18
+ type PoolLoan,
19
+ type PositionAccount,
20
+ type Vault,
21
+ type WriterPosition,
22
+ } from "../generated/accounts";
23
+ import type { Address } from "@solana/kit";
24
+ import { toAddress } from "../client/program";
25
+ import type { AddressLike, KitRpc } from "../client/types";
26
+
27
+ async function fetchRawAccount(
28
+ rpc: KitRpc,
29
+ address: AddressLike
30
+ ): Promise<Uint8Array | null> {
31
+ const response = await rpc.getAccountInfo(toAddress(address), { encoding: "base64" }).send();
32
+ const accountInfo = response.value;
33
+ if (!accountInfo) return null;
34
+ const [data] = accountInfo.data;
35
+ const binary = atob(data);
36
+ const bytes = new Uint8Array(binary.length);
37
+ for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i);
38
+ return bytes;
39
+ }
40
+
41
+ async function decodeAccount<T>(
42
+ rpc: KitRpc,
43
+ address: AddressLike,
44
+ decoder: { decode: (value: Uint8Array) => T }
45
+ ): Promise<T | null> {
46
+ const data = await fetchRawAccount(rpc, address);
47
+ if (!data) return null;
48
+ return decoder.decode(data);
49
+ }
50
+
51
+ export async function fetchOptionAccount(
52
+ rpc: KitRpc,
53
+ optionAccount: AddressLike
54
+ ): Promise<OptionAccount | null> {
55
+ return decodeAccount(rpc, optionAccount, getOptionAccountDecoder());
56
+ }
57
+
58
+ export async function fetchOptionPool(
59
+ rpc: KitRpc,
60
+ optionPool: AddressLike
61
+ ): Promise<OptionPool | null> {
62
+ return decodeAccount(rpc, optionPool, getOptionPoolDecoder());
63
+ }
64
+
65
+ export async function fetchCollateralPool(
66
+ rpc: KitRpc,
67
+ collateralPool: AddressLike
68
+ ): Promise<CollateralPool | null> {
69
+ return decodeAccount(rpc, collateralPool, getCollateralPoolDecoder());
70
+ }
71
+
72
+ export async function fetchWriterPosition(
73
+ rpc: KitRpc,
74
+ writerPosition: AddressLike
75
+ ): Promise<WriterPosition | null> {
76
+ return decodeAccount(rpc, writerPosition, getWriterPositionDecoder());
77
+ }
78
+
79
+ export async function fetchLenderPosition(
80
+ rpc: KitRpc,
81
+ lenderPosition: AddressLike
82
+ ): Promise<LenderPosition | null> {
83
+ return decodeAccount(rpc, lenderPosition, getLenderPositionDecoder());
84
+ }
85
+
86
+ export async function fetchBuyerPosition(
87
+ rpc: KitRpc,
88
+ buyerPosition: AddressLike
89
+ ): Promise<PositionAccount | null> {
90
+ return decodeAccount(rpc, buyerPosition, getPositionAccountDecoder());
91
+ }
92
+
93
+ export async function fetchVault(
94
+ rpc: KitRpc,
95
+ vault: AddressLike
96
+ ): Promise<Vault | null> {
97
+ return decodeAccount(rpc, vault, getVaultDecoder());
98
+ }
99
+
100
+ export async function fetchMarketDataAccount(
101
+ rpc: KitRpc,
102
+ marketData: AddressLike
103
+ ): Promise<MarketDataAccount | null> {
104
+ return decodeAccount(rpc, marketData, getMarketDataAccountDecoder());
105
+ }
106
+
107
+ export async function fetchMakerPoolShare(
108
+ rpc: KitRpc,
109
+ makerPoolShare: AddressLike
110
+ ): Promise<MakerPoolShare | null> {
111
+ return decodeAccount(rpc, makerPoolShare, getMakerPoolShareDecoder());
112
+ }
113
+
114
+ export async function fetchPoolLoan(
115
+ rpc: KitRpc,
116
+ poolLoan: AddressLike
117
+ ): Promise<PoolLoan | null> {
118
+ return decodeAccount(rpc, poolLoan, getPoolLoanDecoder());
119
+ }
120
+
121
+ export async function accountExists(
122
+ rpc: KitRpc,
123
+ address: AddressLike
124
+ ): Promise<boolean> {
125
+ const response = await rpc.getAccountInfo(toAddress(address), { encoding: "base64" }).send();
126
+ return response.value !== null;
127
+ }
128
+
129
+ export async function fetchManyAccounts(
130
+ rpc: KitRpc,
131
+ addresses: AddressLike[]
132
+ ): Promise<Array<{ address: Address; exists: boolean }>> {
133
+ const keys = addresses.map((value) => toAddress(value));
134
+ const response = await rpc.getMultipleAccounts(keys, { encoding: "base64" }).send();
135
+ const infos = response.value;
136
+ return keys.map((key, index) => ({
137
+ address: key,
138
+ exists: infos[index] !== null,
139
+ }));
140
+ }
@@ -0,0 +1,152 @@
1
+ import bs58 from "bs58";
2
+ import type { Address } from "@solana/kit";
3
+ import {
4
+ MAKER_POOL_SHARE_DISCRIMINATOR,
5
+ OPTION_POOL_DISCRIMINATOR,
6
+ POOL_LOAN_DISCRIMINATOR,
7
+ POSITION_ACCOUNT_DISCRIMINATOR,
8
+ VAULT_DISCRIMINATOR,
9
+ WRITER_POSITION_DISCRIMINATOR,
10
+ getMakerPoolShareDecoder,
11
+ getOptionPoolDecoder,
12
+ getPoolLoanDecoder,
13
+ getPositionAccountDecoder,
14
+ getVaultDecoder,
15
+ getWriterPositionDecoder,
16
+ type MakerPoolShare,
17
+ type OptionPool,
18
+ type PoolLoan,
19
+ type PositionAccount,
20
+ type Vault,
21
+ type WriterPosition,
22
+ } from "../generated/accounts";
23
+ import { PROGRAM_ID, toAddress } from "../client/program";
24
+ import type { AddressLike, KitRpc } from "../client/types";
25
+
26
+ const DISCRIMINATOR_OFFSET = 0n;
27
+ const OWNER_OFFSET = 8n;
28
+ const ACTIVE_POOL_LOAN_STATUS = 1;
29
+
30
+ type ListedAccount<T> = {
31
+ address: Address;
32
+ data: T;
33
+ };
34
+
35
+ type ProgramAccountResponse = {
36
+ pubkey: Address;
37
+ account: {
38
+ data: [string, string];
39
+ };
40
+ };
41
+
42
+ function decodeBase64Data(data: string): Uint8Array {
43
+ const binary = atob(data);
44
+ const bytes = new Uint8Array(binary.length);
45
+ for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i);
46
+ return bytes;
47
+ }
48
+
49
+ function discriminatorFilter(discriminator: Uint8Array) {
50
+ return {
51
+ memcmp: {
52
+ offset: DISCRIMINATOR_OFFSET,
53
+ encoding: "base58",
54
+ bytes: bs58.encode(discriminator),
55
+ },
56
+ } as const;
57
+ }
58
+
59
+ function ownerFilter(owner: AddressLike) {
60
+ return {
61
+ memcmp: {
62
+ offset: OWNER_OFFSET,
63
+ encoding: "base58",
64
+ bytes: toAddress(owner),
65
+ },
66
+ } as const;
67
+ }
68
+
69
+ async function fetchAndDecodeProgramAccounts<T>(
70
+ rpc: KitRpc,
71
+ decoder: { decode: (value: Uint8Array) => T },
72
+ filters: ReadonlyArray<unknown>
73
+ ): Promise<Array<ListedAccount<T>>> {
74
+ const response = await rpc
75
+ .getProgramAccounts(PROGRAM_ID, {
76
+ encoding: "base64",
77
+ filters: filters as never,
78
+ })
79
+ .send();
80
+
81
+ const rawAccounts = Array.isArray(response)
82
+ ? (response as Array<ProgramAccountResponse>)
83
+ : (response as { value: Array<ProgramAccountResponse> }).value;
84
+
85
+ return rawAccounts.map(({ pubkey, account }) => {
86
+ const [base64Data] = account.data;
87
+ return {
88
+ address: pubkey,
89
+ data: decoder.decode(decodeBase64Data(base64Data)),
90
+ };
91
+ });
92
+ }
93
+
94
+ export async function fetchMakerPoolSharesByMaker(
95
+ rpc: KitRpc,
96
+ maker: AddressLike
97
+ ): Promise<Array<ListedAccount<MakerPoolShare>>> {
98
+ return fetchAndDecodeProgramAccounts(rpc, getMakerPoolShareDecoder(), [
99
+ discriminatorFilter(MAKER_POOL_SHARE_DISCRIMINATOR),
100
+ ownerFilter(maker),
101
+ ]);
102
+ }
103
+
104
+ export async function fetchWriterPositionsByWriter(
105
+ rpc: KitRpc,
106
+ writer: AddressLike
107
+ ): Promise<Array<ListedAccount<WriterPosition>>> {
108
+ return fetchAndDecodeProgramAccounts(rpc, getWriterPositionDecoder(), [
109
+ discriminatorFilter(WRITER_POSITION_DISCRIMINATOR),
110
+ ownerFilter(writer),
111
+ ]);
112
+ }
113
+
114
+ export async function fetchPositionAccountsByBuyer(
115
+ rpc: KitRpc,
116
+ buyer: AddressLike
117
+ ): Promise<Array<ListedAccount<PositionAccount>>> {
118
+ return fetchAndDecodeProgramAccounts(rpc, getPositionAccountDecoder(), [
119
+ discriminatorFilter(POSITION_ACCOUNT_DISCRIMINATOR),
120
+ ownerFilter(buyer),
121
+ ]);
122
+ }
123
+
124
+ export async function fetchPoolLoansByMaker(
125
+ rpc: KitRpc,
126
+ maker: AddressLike
127
+ ): Promise<Array<ListedAccount<PoolLoan>>> {
128
+ const decoded = await fetchAndDecodeProgramAccounts(rpc, getPoolLoanDecoder(), [
129
+ discriminatorFilter(POOL_LOAN_DISCRIMINATOR),
130
+ ownerFilter(maker),
131
+ ]);
132
+ return decoded.filter(
133
+ (item: { address: Address; data: PoolLoan }) =>
134
+ item.data.status === ACTIVE_POOL_LOAN_STATUS
135
+ );
136
+ }
137
+
138
+ export async function fetchAllOptionPools(
139
+ rpc: KitRpc
140
+ ): Promise<Array<ListedAccount<OptionPool>>> {
141
+ return fetchAndDecodeProgramAccounts(rpc, getOptionPoolDecoder(), [
142
+ discriminatorFilter(OPTION_POOL_DISCRIMINATOR),
143
+ ]);
144
+ }
145
+
146
+ export async function fetchAllVaults(
147
+ rpc: KitRpc
148
+ ): Promise<Array<ListedAccount<Vault>>> {
149
+ return fetchAndDecodeProgramAccounts(rpc, getVaultDecoder(), [
150
+ discriminatorFilter(VAULT_DISCRIMINATOR),
151
+ ]);
152
+ }