@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
@@ -0,0 +1,126 @@
1
+ import {
2
+ getBuyFromPoolInstructionAsync,
3
+ getCloseLongToPoolInstructionAsync,
4
+ } from "../generated/instructions";
5
+ import type { Instruction } from "@solana/kit";
6
+ import { toAddress } from "../client/program";
7
+ import type { AddressLike, BuiltTransaction } from "../client/types";
8
+ import { assertPositiveAmount } from "../shared/amounts";
9
+ import { invariant } from "../shared/errors";
10
+ import {
11
+ appendRemainingAccounts,
12
+ type RemainingAccountInput,
13
+ } from "../shared/remaining-accounts";
14
+
15
+ export interface BuildBuyFromPoolParams {
16
+ optionPool: AddressLike;
17
+ optionAccount: AddressLike;
18
+ longMint: AddressLike;
19
+ underlyingMint: AddressLike;
20
+ marketData: AddressLike;
21
+ priceUpdate: AddressLike;
22
+ buyer: AddressLike;
23
+ buyerPaymentAccount: AddressLike;
24
+ escrowLongAccount: AddressLike;
25
+ premiumVault: AddressLike;
26
+ quantity: bigint | number;
27
+ premiumAmount: bigint | number;
28
+ buyerPosition?: AddressLike;
29
+ buyerOptionAccount?: AddressLike;
30
+ remainingAccounts?: RemainingAccountInput[];
31
+ }
32
+
33
+ export interface BuildCloseLongToPoolParams {
34
+ optionPool: AddressLike;
35
+ optionAccount: AddressLike;
36
+ collateralPool: AddressLike;
37
+ underlyingMint: AddressLike;
38
+ longMint: AddressLike;
39
+ escrowLongAccount: AddressLike;
40
+ premiumVault: AddressLike;
41
+ marketData: AddressLike;
42
+ priceUpdate: AddressLike;
43
+ buyer: AddressLike;
44
+ buyerLongAccount: AddressLike;
45
+ buyerPayoutAccount: AddressLike;
46
+ collateralVault: AddressLike;
47
+ quantity: bigint | number;
48
+ minPayoutAmount: bigint | number;
49
+ buyerPosition?: AddressLike;
50
+ omlpVault?: AddressLike;
51
+ remainingAccounts?: RemainingAccountInput[];
52
+ }
53
+
54
+ export async function buildBuyFromPoolInstruction(
55
+ params: BuildBuyFromPoolParams
56
+ ): Promise<Instruction<string>> {
57
+ assertPositiveAmount(params.quantity, "quantity");
58
+ assertPositiveAmount(params.premiumAmount, "premiumAmount");
59
+
60
+ const kitInstruction = await getBuyFromPoolInstructionAsync({
61
+ optionPool: toAddress(params.optionPool),
62
+ optionAccount: toAddress(params.optionAccount),
63
+ longMint: toAddress(params.longMint),
64
+ underlyingMint: toAddress(params.underlyingMint),
65
+ marketData: toAddress(params.marketData),
66
+ priceUpdate: toAddress(params.priceUpdate),
67
+ buyer: toAddress(params.buyer) as any,
68
+ buyerPosition: params.buyerPosition ? toAddress(params.buyerPosition) : undefined,
69
+ buyerOptionAccount: params.buyerOptionAccount
70
+ ? toAddress(params.buyerOptionAccount)
71
+ : undefined,
72
+ buyerPaymentAccount: toAddress(params.buyerPaymentAccount),
73
+ escrowLongAccount: toAddress(params.escrowLongAccount),
74
+ premiumVault: toAddress(params.premiumVault),
75
+ quantity: params.quantity,
76
+ premiumAmount: params.premiumAmount,
77
+ });
78
+
79
+ return appendRemainingAccounts(kitInstruction, params.remainingAccounts);
80
+ }
81
+
82
+ export async function buildBuyFromPoolTransaction(
83
+ params: BuildBuyFromPoolParams
84
+ ): Promise<BuiltTransaction> {
85
+ const instruction = await buildBuyFromPoolInstruction(params);
86
+ return { instructions: [instruction] };
87
+ }
88
+
89
+ export async function buildCloseLongToPoolInstruction(
90
+ params: BuildCloseLongToPoolParams
91
+ ): Promise<Instruction<string>> {
92
+ assertPositiveAmount(params.quantity, "quantity");
93
+ invariant(
94
+ BigInt(params.minPayoutAmount) >= 0n,
95
+ "minPayoutAmount must be greater than or equal to zero."
96
+ );
97
+
98
+ const kitInstruction = await getCloseLongToPoolInstructionAsync({
99
+ optionPool: toAddress(params.optionPool),
100
+ optionAccount: toAddress(params.optionAccount),
101
+ collateralPool: toAddress(params.collateralPool),
102
+ underlyingMint: toAddress(params.underlyingMint),
103
+ longMint: toAddress(params.longMint),
104
+ escrowLongAccount: toAddress(params.escrowLongAccount),
105
+ premiumVault: toAddress(params.premiumVault),
106
+ marketData: toAddress(params.marketData),
107
+ priceUpdate: toAddress(params.priceUpdate),
108
+ buyer: toAddress(params.buyer) as any,
109
+ buyerLongAccount: toAddress(params.buyerLongAccount),
110
+ buyerPayoutAccount: toAddress(params.buyerPayoutAccount),
111
+ collateralVault: toAddress(params.collateralVault),
112
+ buyerPosition: params.buyerPosition ? toAddress(params.buyerPosition) : undefined,
113
+ omlpVault: params.omlpVault ? toAddress(params.omlpVault) : undefined,
114
+ quantity: params.quantity,
115
+ minPayoutAmount: params.minPayoutAmount,
116
+ });
117
+
118
+ return appendRemainingAccounts(kitInstruction, params.remainingAccounts);
119
+ }
120
+
121
+ export async function buildCloseLongToPoolTransaction(
122
+ params: BuildCloseLongToPoolParams
123
+ ): Promise<BuiltTransaction> {
124
+ const instruction = await buildCloseLongToPoolInstruction(params);
125
+ return { instructions: [instruction] };
126
+ }
@@ -0,0 +1,49 @@
1
+ import { getOptionExerciseInstruction } from "../generated/instructions";
2
+ import type { Instruction } from "@solana/kit";
3
+ import { toAddress } from "../client/program";
4
+ import type { AddressLike, BuiltTransaction } from "../client/types";
5
+
6
+ export interface BuildOptionExerciseParams {
7
+ optionAccount: AddressLike;
8
+ positionAccount: AddressLike;
9
+ marketData: AddressLike;
10
+ underlyingMint: AddressLike;
11
+ priceUpdate: AddressLike;
12
+ buyerPaymentAccount: AddressLike;
13
+ makerCollateralAccount: AddressLike;
14
+ escrowState: AddressLike;
15
+ escrowTokenAccount: AddressLike;
16
+ escrowAuthority: AddressLike;
17
+ buyer: AddressLike;
18
+ tokenProgram?: AddressLike;
19
+ }
20
+
21
+ export function buildOptionExerciseInstruction(
22
+ params: BuildOptionExerciseParams
23
+ ): Instruction<string> {
24
+ return getOptionExerciseInstruction({
25
+ optionAccount: toAddress(params.optionAccount),
26
+ positionAccount: toAddress(params.positionAccount),
27
+ marketData: toAddress(params.marketData),
28
+ underlyingMint: toAddress(params.underlyingMint),
29
+ priceUpdate: toAddress(params.priceUpdate),
30
+ buyerPaymentAccount: toAddress(params.buyerPaymentAccount),
31
+ makerCollateralAccount: toAddress(params.makerCollateralAccount),
32
+ escrowState: toAddress(params.escrowState),
33
+ escrowTokenAccount: toAddress(params.escrowTokenAccount),
34
+ escrowAuthority: toAddress(params.escrowAuthority),
35
+ buyer: toAddress(params.buyer) as any,
36
+ tokenProgram: params.tokenProgram ? toAddress(params.tokenProgram) : undefined,
37
+ });
38
+ }
39
+
40
+ /**
41
+ * Builds an option exercise transaction instruction set.
42
+ * Use `priceUpdate` from a fresh Pyth receiver update for accurate exercise pricing.
43
+ */
44
+ export function buildOptionExerciseTransaction(
45
+ params: BuildOptionExerciseParams
46
+ ): BuiltTransaction {
47
+ const instruction = buildOptionExerciseInstruction(params);
48
+ return { instructions: [instruction] };
49
+ }
package/long/quotes.ts ADDED
@@ -0,0 +1,48 @@
1
+ import { assertPositiveAmount } from "../shared/amounts";
2
+ import { SdkValidationError } from "../shared/errors";
3
+
4
+ export function applySlippageBps(amount: bigint | number, slippageBps: number): bigint {
5
+ if (slippageBps < 0) {
6
+ throw new SdkValidationError("slippageBps cannot be negative.");
7
+ }
8
+
9
+ const base = BigInt(amount);
10
+ return (base * BigInt(10_000 + slippageBps)) / 10_000n;
11
+ }
12
+
13
+ export function applyMinSlippageBps(amount: bigint | number, slippageBps: number): bigint {
14
+ if (slippageBps < 0) {
15
+ throw new SdkValidationError("slippageBps cannot be negative.");
16
+ }
17
+
18
+ const base = BigInt(amount);
19
+ return (base * BigInt(10_000 - slippageBps)) / 10_000n;
20
+ }
21
+
22
+ export function buildBuyQuote(params: {
23
+ quantity: bigint | number;
24
+ premiumPerContract: bigint | number;
25
+ maxSlippageBps: number;
26
+ }): { expectedPremium: bigint; maxPremium: bigint } {
27
+ assertPositiveAmount(params.quantity, "quantity");
28
+ assertPositiveAmount(params.premiumPerContract, "premiumPerContract");
29
+
30
+ const expectedPremium = BigInt(params.quantity) * BigInt(params.premiumPerContract);
31
+ return {
32
+ expectedPremium,
33
+ maxPremium: applySlippageBps(expectedPremium, params.maxSlippageBps),
34
+ };
35
+ }
36
+
37
+ export function buildCloseQuote(params: {
38
+ expectedPayout: bigint | number;
39
+ maxSlippageBps: number;
40
+ }): { expectedPayout: bigint; minPayout: bigint } {
41
+ assertPositiveAmount(params.expectedPayout, "expectedPayout");
42
+
43
+ const expectedPayout = BigInt(params.expectedPayout);
44
+ return {
45
+ expectedPayout,
46
+ minPayout: applyMinSlippageBps(expectedPayout, params.maxSlippageBps),
47
+ };
48
+ }
@@ -0,0 +1,74 @@
1
+ import {
2
+ getDepositToPositionInstructionAsync,
3
+ getWithdrawFromPositionInstructionAsync,
4
+ } from "../generated/instructions";
5
+ import type { Instruction } from "@solana/kit";
6
+ import { toAddress } from "../client/program";
7
+ import type { AddressLike, BuiltTransaction } from "../client/types";
8
+ import { assertPositiveAmount } from "../shared/amounts";
9
+
10
+ export interface BuildDepositToPositionParams {
11
+ vault: AddressLike;
12
+ lenderTokenAccount: AddressLike;
13
+ vaultTokenAccount: AddressLike;
14
+ lender: AddressLike;
15
+ amount: bigint | number;
16
+ position?: AddressLike;
17
+ }
18
+
19
+ export interface BuildWithdrawFromPositionParams {
20
+ vault: AddressLike;
21
+ vaultTokenAccount: AddressLike;
22
+ lenderTokenAccount: AddressLike;
23
+ lender: AddressLike;
24
+ amount: bigint | number;
25
+ position?: AddressLike;
26
+ }
27
+
28
+ export async function buildDepositToPositionInstruction(
29
+ params: BuildDepositToPositionParams
30
+ ): Promise<Instruction<string>> {
31
+ assertPositiveAmount(params.amount, "amount");
32
+
33
+ const kitInstruction = await getDepositToPositionInstructionAsync({
34
+ position: params.position ? toAddress(params.position) : undefined,
35
+ vault: toAddress(params.vault),
36
+ lenderTokenAccount: toAddress(params.lenderTokenAccount),
37
+ vaultTokenAccount: toAddress(params.vaultTokenAccount),
38
+ lender: toAddress(params.lender) as any,
39
+ amount: params.amount,
40
+ });
41
+
42
+ return kitInstruction;
43
+ }
44
+
45
+ export async function buildDepositToPositionTransaction(
46
+ params: BuildDepositToPositionParams
47
+ ): Promise<BuiltTransaction> {
48
+ const instruction = await buildDepositToPositionInstruction(params);
49
+ return { instructions: [instruction] };
50
+ }
51
+
52
+ export async function buildWithdrawFromPositionInstruction(
53
+ params: BuildWithdrawFromPositionParams
54
+ ): Promise<Instruction<string>> {
55
+ assertPositiveAmount(params.amount, "amount");
56
+
57
+ const kitInstruction = await getWithdrawFromPositionInstructionAsync({
58
+ position: params.position ? toAddress(params.position) : undefined,
59
+ vault: toAddress(params.vault),
60
+ vaultTokenAccount: toAddress(params.vaultTokenAccount),
61
+ lenderTokenAccount: toAddress(params.lenderTokenAccount),
62
+ lender: toAddress(params.lender) as any,
63
+ amount: params.amount,
64
+ });
65
+
66
+ return kitInstruction;
67
+ }
68
+
69
+ export async function buildWithdrawFromPositionTransaction(
70
+ params: BuildWithdrawFromPositionParams
71
+ ): Promise<BuiltTransaction> {
72
+ const instruction = await buildWithdrawFromPositionInstruction(params);
73
+ return { instructions: [instruction] };
74
+ }
@@ -0,0 +1,94 @@
1
+ import { fetchLenderPosition, fetchVault } from "../accounts/fetchers";
2
+ import type { KitRpc } from "../client/types";
3
+ import {
4
+ buildDepositToPositionTransaction,
5
+ buildWithdrawFromPositionTransaction,
6
+ type BuildDepositToPositionParams,
7
+ type BuildWithdrawFromPositionParams,
8
+ } from "./builders";
9
+
10
+ function positiveDiff(a: bigint, b: bigint): bigint {
11
+ return a > b ? a - b : 0n;
12
+ }
13
+
14
+ export async function depositToPosition(
15
+ params: BuildDepositToPositionParams
16
+ ) {
17
+ return buildDepositToPositionTransaction(params);
18
+ }
19
+
20
+ export async function withdrawFromPosition(
21
+ params: BuildWithdrawFromPositionParams
22
+ ) {
23
+ return buildWithdrawFromPositionTransaction(params);
24
+ }
25
+
26
+ export async function withdrawAllFromPosition(
27
+ rpc: KitRpc,
28
+ params: Omit<BuildWithdrawFromPositionParams, "amount"> & {
29
+ position: NonNullable<BuildWithdrawFromPositionParams["position"]>;
30
+ }
31
+ ): Promise<{ instructions: Awaited<ReturnType<typeof buildWithdrawFromPositionTransaction>>["instructions"]; amount: bigint }> {
32
+ const [position, vault] = await Promise.all([
33
+ fetchLenderPosition(rpc, params.position),
34
+ fetchVault(rpc, params.vault),
35
+ ]);
36
+
37
+ if (!position) {
38
+ throw new Error("Lender position not found. Provide position PDA or deposit first.");
39
+ }
40
+ if (!vault) {
41
+ throw new Error("Vault account not found.");
42
+ }
43
+
44
+ const unclaimedInterest = positiveDiff(
45
+ position.totalInterestEarned,
46
+ position.interestClaimed
47
+ );
48
+ const userMax = position.deposited + unclaimedInterest;
49
+ const poolAvailable = positiveDiff(vault.totalLiquidity, vault.totalLoans);
50
+ const amount = userMax < poolAvailable ? userMax : poolAvailable;
51
+ if (amount <= 0n) {
52
+ throw new Error("No withdrawable balance available right now.");
53
+ }
54
+
55
+ const built = await buildWithdrawFromPositionTransaction({ ...params, amount });
56
+ return { instructions: built.instructions, amount };
57
+ }
58
+
59
+ export async function withdrawInterestFromPosition(
60
+ rpc: KitRpc,
61
+ params: Omit<BuildWithdrawFromPositionParams, "amount"> & {
62
+ position: NonNullable<BuildWithdrawFromPositionParams["position"]>;
63
+ }
64
+ ): Promise<{ instructions: Awaited<ReturnType<typeof buildWithdrawFromPositionTransaction>>["instructions"]; amount: bigint }> {
65
+ const [position, vault] = await Promise.all([
66
+ fetchLenderPosition(rpc, params.position),
67
+ fetchVault(rpc, params.vault),
68
+ ]);
69
+
70
+ if (!position) {
71
+ throw new Error("Lender position not found. Provide position PDA or deposit first.");
72
+ }
73
+ if (!vault) {
74
+ throw new Error("Vault account not found.");
75
+ }
76
+
77
+ const unclaimedInterest = positiveDiff(
78
+ position.totalInterestEarned,
79
+ position.interestClaimed
80
+ );
81
+ const poolAvailable = positiveDiff(vault.totalLiquidity, vault.totalLoans);
82
+ const amount = unclaimedInterest < poolAvailable ? unclaimedInterest : poolAvailable;
83
+ if (amount <= 0n) {
84
+ throw new Error("No claimable interest available right now.");
85
+ }
86
+
87
+ const built = await buildWithdrawFromPositionTransaction({ ...params, amount });
88
+ return { instructions: built.instructions, amount };
89
+ }
90
+
91
+ export const omlpBuilders = {
92
+ buildDepositToPositionTransaction,
93
+ buildWithdrawFromPositionTransaction,
94
+ };
package/package.json ADDED
@@ -0,0 +1,22 @@
1
+ {
2
+ "name": "@epicentral/sos-sdk",
3
+ "version": "0.1.0",
4
+ "private": false,
5
+ "description": "Solana Option Standard SDK. The frontend-first SDK for Native Options Trading on Solana. Created by Epicentral Labs.",
6
+ "type": "module",
7
+ "sideEffects": false,
8
+ "main": "./index.ts",
9
+ "types": "./index.ts",
10
+ "exports": {
11
+ ".": "./index.ts",
12
+ "./*": "./*"
13
+ },
14
+ "scripts": {
15
+ "typecheck": "tsc --project tsconfig.json --noEmit"
16
+ },
17
+ "dependencies": {
18
+ "@solana/kit": "^6.1.0",
19
+ "bs58": "^6.0.0",
20
+ "decimal.js": "^10.4.3"
21
+ }
22
+ }
@@ -0,0 +1,32 @@
1
+ import Decimal from "decimal.js";
2
+ import { SdkValidationError } from "./errors";
3
+
4
+ export function toBaseUnits(amount: Decimal.Value, decimals: number): bigint {
5
+ const scaled = new Decimal(amount).mul(new Decimal(10).pow(decimals));
6
+ return BigInt(scaled.floor().toFixed(0));
7
+ }
8
+
9
+ export function fromBaseUnits(amount: bigint | number, decimals: number): Decimal {
10
+ return new Decimal(amount.toString()).div(new Decimal(10).pow(decimals));
11
+ }
12
+
13
+ export function assertPositiveAmount(value: bigint | number, label: string): void {
14
+ const bigintValue = typeof value === "bigint" ? value : BigInt(value);
15
+ if (bigintValue <= 0n) {
16
+ throw new SdkValidationError(`${label} must be greater than zero.`);
17
+ }
18
+ }
19
+
20
+ export function assertNonNegativeAmount(value: bigint | number, label: string): void {
21
+ const bigintValue = typeof value === "bigint" ? value : BigInt(value);
22
+ if (bigintValue < 0n) {
23
+ throw new SdkValidationError(`${label} cannot be negative.`);
24
+ }
25
+ }
26
+
27
+ export function calculateRequiredCollateral(
28
+ quantity: bigint | number,
29
+ strikePrice: number
30
+ ): number {
31
+ return Number(quantity) * 100 * strikePrice;
32
+ }
@@ -0,0 +1,12 @@
1
+ export class SdkValidationError extends Error {
2
+ constructor(message: string) {
3
+ super(message);
4
+ this.name = "SdkValidationError";
5
+ }
6
+ }
7
+
8
+ export function invariant(condition: boolean, message: string): asserts condition {
9
+ if (!condition) {
10
+ throw new SdkValidationError(message);
11
+ }
12
+ }
@@ -0,0 +1,41 @@
1
+ import { AccountRole, type AccountMeta, type Instruction } from "@solana/kit";
2
+ import { toAddress } from "../client/program";
3
+ import type { AddressLike } from "../client/types";
4
+
5
+ export interface RemainingAccountInput {
6
+ address: AddressLike;
7
+ isWritable: boolean;
8
+ isSigner?: boolean;
9
+ }
10
+
11
+ function toAccountRole(input: RemainingAccountInput): AccountRole {
12
+ if (input.isWritable) {
13
+ return input.isSigner ? AccountRole.WRITABLE_SIGNER : AccountRole.WRITABLE;
14
+ }
15
+
16
+ return input.isSigner ? AccountRole.READONLY_SIGNER : AccountRole.READONLY;
17
+ }
18
+
19
+ export function appendRemainingAccounts(
20
+ instruction: Instruction<string>,
21
+ remainingAccounts: RemainingAccountInput[] | undefined
22
+ ): Instruction<string> {
23
+ if (!remainingAccounts?.length) {
24
+ return instruction;
25
+ }
26
+
27
+ const extras = remainingAccounts.map(
28
+ (account) =>
29
+ ({
30
+ address: toAddress(account.address),
31
+ role: toAccountRole(account),
32
+ }) as AccountMeta<string>
33
+ );
34
+
35
+ const existingAccounts = instruction.accounts ?? [];
36
+
37
+ return {
38
+ ...instruction,
39
+ accounts: [...existingAccounts, ...extras],
40
+ };
41
+ }
@@ -0,0 +1,49 @@
1
+ import {
2
+ appendTransactionMessageInstructions,
3
+ createTransactionMessage,
4
+ getSignatureFromTransaction,
5
+ pipe,
6
+ sendAndConfirmTransactionFactory,
7
+ setTransactionMessageFeePayerSigner,
8
+ setTransactionMessageLifetimeUsingBlockhash,
9
+ signTransactionMessageWithSigners,
10
+ type RpcSubscriptions,
11
+ type SolanaRpcSubscriptionsApi,
12
+ type TransactionSigner,
13
+ } from "@solana/kit";
14
+ import type { BuiltTransaction, KitRpc } from "../client/types";
15
+
16
+ export interface SendBuiltTransactionParams extends BuiltTransaction {
17
+ rpc: KitRpc;
18
+ rpcSubscriptions: RpcSubscriptions<SolanaRpcSubscriptionsApi>;
19
+ feePayer: TransactionSigner<string>;
20
+ commitment?: "processed" | "confirmed" | "finalized";
21
+ }
22
+
23
+ /**
24
+ * Sends a built SDK transaction with common Solana Kit defaults.
25
+ * The caller still controls the RPC clients and fee-payer signer.
26
+ */
27
+ export async function sendBuiltTransaction(
28
+ params: SendBuiltTransactionParams
29
+ ): Promise<string> {
30
+ const commitment = params.commitment ?? "confirmed";
31
+ const { value: latestBlockhash } = await params.rpc.getLatestBlockhash().send();
32
+
33
+ const txMessage = pipe(
34
+ createTransactionMessage({ version: 0 }),
35
+ (tx) => setTransactionMessageFeePayerSigner(params.feePayer, tx),
36
+ (tx) => setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, tx),
37
+ (tx) => appendTransactionMessageInstructions(params.instructions, tx)
38
+ );
39
+
40
+ const signedTx = await signTransactionMessageWithSigners(txMessage);
41
+ const sendAndConfirm = sendAndConfirmTransactionFactory({
42
+ rpc: params.rpc,
43
+ rpcSubscriptions: params.rpcSubscriptions,
44
+ });
45
+ type SendableTransaction = Parameters<typeof sendAndConfirm>[0];
46
+
47
+ await sendAndConfirm(signedTx as SendableTransaction, { commitment });
48
+ return getSignatureFromTransaction(signedTx);
49
+ }