@xitadel-fi/sdk 0.2.4 → 0.2.13
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/dist/sdk/src/admin-action.d.ts +38 -0
- package/dist/sdk/src/admin-action.js +37 -0
- package/dist/sdk/src/program.d.ts +14 -8
- package/dist/sdk/src/program.js +57 -23
- package/dist/sdk/src/squads-proposal-client.d.ts +21 -0
- package/dist/sdk/src/squads-proposal-client.js +115 -0
- package/dist/sdk/src/squads-wallet-modes.d.ts +46 -0
- package/dist/sdk/src/squads-wallet-modes.js +67 -0
- package/dist/sdk/src/squads-wrap.d.ts +40 -0
- package/dist/sdk/src/squads-wrap.js +122 -0
- package/dist/target/idl/xitadel.json +35 -0
- package/dist/target/types/xitadel.d.ts +35 -0
- package/package.json +3 -3
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { Connection, PublicKey, Transaction, TransactionInstruction } from '@solana/web3.js';
|
|
2
|
+
import { SquadsContext, WalletMode } from './squads-wallet-modes';
|
|
3
|
+
import { SquadsProposalBundle } from './squads-wrap';
|
|
4
|
+
/**
|
|
5
|
+
* Options driving the submission strategy for an admin instruction.
|
|
6
|
+
*
|
|
7
|
+
* - eoa → caller assembles + signs a plain tx targeting xitadel.
|
|
8
|
+
* - squads → SDK wraps the instruction into a Squads proposal bundle.
|
|
9
|
+
* Caller is responsible for getting threshold approvals +
|
|
10
|
+
* submitting the bundle's three transactions.
|
|
11
|
+
*/
|
|
12
|
+
export type AdminActionOpts = {
|
|
13
|
+
mode: 'eoa';
|
|
14
|
+
} | {
|
|
15
|
+
mode: 'squads';
|
|
16
|
+
squads: SquadsContext;
|
|
17
|
+
};
|
|
18
|
+
export interface AdminActionPlan {
|
|
19
|
+
mode: WalletMode;
|
|
20
|
+
/** Plain unsigned transaction for EOA mode. Undefined for Squads. */
|
|
21
|
+
eoaTx?: Transaction;
|
|
22
|
+
/** Squads proposal lifecycle bundle for Squads mode. Undefined for EOA. */
|
|
23
|
+
squads?: SquadsProposalBundle;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Produce the transaction(s) needed to perform `innerIx` under the chosen
|
|
27
|
+
* admin wallet mode. The function is purely transaction-building: callers
|
|
28
|
+
* are responsible for fetching blockhash, signing, sending, and waiting
|
|
29
|
+
* for confirmation. Keeps this SDK helper free of wallet-adapter coupling.
|
|
30
|
+
*/
|
|
31
|
+
export declare function planAdminAction(innerIx: TransactionInstruction, opts: AdminActionOpts, connection: Connection): Promise<AdminActionPlan>;
|
|
32
|
+
/**
|
|
33
|
+
* Resolve the manager pubkey to embed as the signer slot inside the inner
|
|
34
|
+
* xitadel instruction. EOA mode uses the operator's wallet directly;
|
|
35
|
+
* Squads mode uses the derived vault PDA — Squads runs `invoke_signed`
|
|
36
|
+
* for it at execute time so Anchor's Signer<'info> accepts the same value.
|
|
37
|
+
*/
|
|
38
|
+
export declare function resolveManagerSigner(opts: AdminActionOpts, operator: PublicKey): PublicKey;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.planAdminAction = planAdminAction;
|
|
4
|
+
exports.resolveManagerSigner = resolveManagerSigner;
|
|
5
|
+
const web3_js_1 = require("@solana/web3.js");
|
|
6
|
+
const squads_wallet_modes_1 = require("./squads-wallet-modes");
|
|
7
|
+
const squads_wrap_1 = require("./squads-wrap");
|
|
8
|
+
/**
|
|
9
|
+
* Produce the transaction(s) needed to perform `innerIx` under the chosen
|
|
10
|
+
* admin wallet mode. The function is purely transaction-building: callers
|
|
11
|
+
* are responsible for fetching blockhash, signing, sending, and waiting
|
|
12
|
+
* for confirmation. Keeps this SDK helper free of wallet-adapter coupling.
|
|
13
|
+
*/
|
|
14
|
+
async function planAdminAction(innerIx, opts, connection) {
|
|
15
|
+
if (opts.mode === 'eoa') {
|
|
16
|
+
return {
|
|
17
|
+
mode: 'eoa',
|
|
18
|
+
eoaTx: new web3_js_1.Transaction().add(innerIx),
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
const bundle = await (0, squads_wrap_1.wrapWithSquads)(innerIx, opts.squads, connection);
|
|
22
|
+
return {
|
|
23
|
+
mode: 'squads',
|
|
24
|
+
squads: bundle,
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Resolve the manager pubkey to embed as the signer slot inside the inner
|
|
29
|
+
* xitadel instruction. EOA mode uses the operator's wallet directly;
|
|
30
|
+
* Squads mode uses the derived vault PDA — Squads runs `invoke_signed`
|
|
31
|
+
* for it at execute time so Anchor's Signer<'info> accepts the same value.
|
|
32
|
+
*/
|
|
33
|
+
function resolveManagerSigner(opts, operator) {
|
|
34
|
+
if (opts.mode === 'eoa')
|
|
35
|
+
return operator;
|
|
36
|
+
return (0, squads_wallet_modes_1.getSquadsVaultPda)(opts.squads);
|
|
37
|
+
}
|
|
@@ -481,15 +481,12 @@ export declare class XitadelProgram {
|
|
|
481
481
|
harvestLTT(lttId: PublicKey, manager: PublicKey, positionNftMint: PublicKey): Promise<TransactionInstruction[]>;
|
|
482
482
|
getHarvestVaultPda(lttId: PublicKey): PublicKey;
|
|
483
483
|
/**
|
|
484
|
-
* Claim LP fees
|
|
485
|
-
*
|
|
486
|
-
*
|
|
487
|
-
*
|
|
488
|
-
* @param ammConfig The AMM config
|
|
489
|
-
* @param cpAmmProgramId The CP AMM program ID
|
|
490
|
-
* @returns Transaction instruction for claiming fees
|
|
484
|
+
* Claim LP fees from both cp_amm positions of an LTT.
|
|
485
|
+
* Pool B accounts default to pool A accounts when LTT is single-pool
|
|
486
|
+
* (positionNftMintB == default). The on-chain program skips the pool B
|
|
487
|
+
* CPI in that case.
|
|
491
488
|
*/
|
|
492
|
-
claimFees(signer: PublicKey, lttId: PublicKey, positionNftMint: PublicKey, ammConfig: PublicKey, cpAmmProgramId: PublicKey, receiver: PublicKey): Promise<TransactionInstruction>;
|
|
489
|
+
claimFees(signer: PublicKey, lttId: PublicKey, positionNftMint: PublicKey, ammConfig: PublicKey, cpAmmProgramId: PublicKey, receiver: PublicKey, positionNftMintB?: PublicKey, ammConfigB?: PublicKey): Promise<TransactionInstruction>;
|
|
493
490
|
/**
|
|
494
491
|
* Deposit stake to flash trade from collateral vault
|
|
495
492
|
* @param lttId The LTT ID
|
|
@@ -541,4 +538,13 @@ export declare class XitadelProgram {
|
|
|
541
538
|
* @returns Transaction instruction for withdrawing stake from flash trade
|
|
542
539
|
*/
|
|
543
540
|
withdrawStakeFlashTrade(lttId: PublicKey, authority: PublicKey, unstakeAmount: BN, lpTokenMint: PublicKey, flashTradeProgramId: PublicKey, transferAuthority: PublicKey, perpetuals: PublicKey, pool: PublicKey, flpStakeAccount: PublicKey, poolStakedLpVault: PublicKey, rewardCustody: PublicKey, eventAuthority: PublicKey): Promise<TransactionInstruction>;
|
|
541
|
+
/**
|
|
542
|
+
* Build a `version` instruction.
|
|
543
|
+
*/
|
|
544
|
+
versionInstruction(): Promise<TransactionInstruction>;
|
|
545
|
+
/**
|
|
546
|
+
* Return the deployed program's git commit hash by simulating
|
|
547
|
+
* the `version` instruction and parsing its log output.
|
|
548
|
+
*/
|
|
549
|
+
getVersion(): Promise<string>;
|
|
544
550
|
}
|
package/dist/sdk/src/program.js
CHANGED
|
@@ -22,16 +22,17 @@ exports.SEEDS = {
|
|
|
22
22
|
};
|
|
23
23
|
class XitadelProgram {
|
|
24
24
|
constructor(provider, address) {
|
|
25
|
+
// Always construct from bundled IDL + optional address override.
|
|
26
|
+
// The previous `NODE_ENV === 'development'` branch unconditionally
|
|
27
|
+
// pulled `anchor.workspace.Xitadel`, which silently ignored the
|
|
28
|
+
// caller-supplied `address` (e.g. NEXT_PUBLIC_PROGRAM_ID in `pnpm dev`).
|
|
29
|
+
// Workspace lookup is only meaningful inside `anchor test`, and tests
|
|
30
|
+
// can construct `Program` directly without this wrapper.
|
|
25
31
|
const idl = Object.assign(xitadel_json_1.default, {});
|
|
26
32
|
if (address) {
|
|
27
33
|
idl.address = address;
|
|
28
34
|
}
|
|
29
35
|
this.program = new anchor_1.Program(idl, provider);
|
|
30
|
-
// if (process.env.NODE_ENV === 'development') {
|
|
31
|
-
// const workspace = require('@coral-xyz/anchor').workspace;
|
|
32
|
-
// this.program = workspace.Xitadel as Program<Xitadel>;
|
|
33
|
-
// } else {
|
|
34
|
-
// }
|
|
35
36
|
}
|
|
36
37
|
getProgramId() {
|
|
37
38
|
return this.program.programId;
|
|
@@ -1034,37 +1035,46 @@ class XitadelProgram {
|
|
|
1034
1035
|
return web3_js_1.PublicKey.findProgramAddressSync([Buffer.from('harvest_vault'), lttId.toBuffer()], this.program.programId)[0];
|
|
1035
1036
|
}
|
|
1036
1037
|
/**
|
|
1037
|
-
* Claim LP fees
|
|
1038
|
-
*
|
|
1039
|
-
*
|
|
1040
|
-
*
|
|
1041
|
-
* @param ammConfig The AMM config
|
|
1042
|
-
* @param cpAmmProgramId The CP AMM program ID
|
|
1043
|
-
* @returns Transaction instruction for claiming fees
|
|
1038
|
+
* Claim LP fees from both cp_amm positions of an LTT.
|
|
1039
|
+
* Pool B accounts default to pool A accounts when LTT is single-pool
|
|
1040
|
+
* (positionNftMintB == default). The on-chain program skips the pool B
|
|
1041
|
+
* CPI in that case.
|
|
1044
1042
|
*/
|
|
1045
|
-
async claimFees(signer, lttId, positionNftMint, ammConfig, cpAmmProgramId, receiver) {
|
|
1043
|
+
async claimFees(signer, lttId, positionNftMint, ammConfig, cpAmmProgramId, receiver, positionNftMintB, ammConfigB) {
|
|
1046
1044
|
const lttConfigPda = this.getLTTConfigPda(lttId);
|
|
1047
1045
|
const configPda = this.getConfigPda();
|
|
1048
1046
|
const lttConfig = await this.getLttConfig(lttId);
|
|
1049
1047
|
const lpAuthority = this.getLpAuthority();
|
|
1050
|
-
//
|
|
1048
|
+
// Pool A
|
|
1051
1049
|
const pool = (0, utils_1.derivePoolKey)(ammConfig, lttId, lttConfig.fundingTokenMint, cpAmmProgramId);
|
|
1052
|
-
// Derive position PDA
|
|
1053
1050
|
const [position] = web3_js_1.PublicKey.findProgramAddressSync([constants_1.POSITION_SEED, positionNftMint.toBuffer()], cpAmmProgramId);
|
|
1054
|
-
// Derive pool authority
|
|
1055
1051
|
const [poolAuthority] = web3_js_1.PublicKey.findProgramAddressSync([constants_1.POOL_AUTHORITY_SEED], cpAmmProgramId);
|
|
1056
|
-
// Derive event authority
|
|
1057
1052
|
const [eventAuthority] = web3_js_1.PublicKey.findProgramAddressSync([Buffer.from('__event_authority')], cpAmmProgramId);
|
|
1058
|
-
// Derive vault addresses
|
|
1059
1053
|
const [lttVault, stableVault] = [
|
|
1060
1054
|
(0, utils_1.getVaultPda)(lttId, cpAmmProgramId, pool),
|
|
1061
1055
|
(0, utils_1.getVaultPda)(lttConfig.fundingTokenMint, cpAmmProgramId, pool),
|
|
1062
1056
|
];
|
|
1063
|
-
|
|
1057
|
+
const [positionNftAccount] = web3_js_1.PublicKey.findProgramAddressSync([Buffer.from('position_nft_account'), positionNftMint.toBuffer()], cpAmmProgramId);
|
|
1064
1058
|
const receiverTokenAAccount = (0, spl_token_1.getAssociatedTokenAddressSync)(lttId, receiver, true);
|
|
1065
1059
|
const receiverTokenBAccount = (0, spl_token_1.getAssociatedTokenAddressSync)(lttConfig.fundingTokenMint, receiver, true);
|
|
1066
|
-
//
|
|
1067
|
-
const
|
|
1060
|
+
// Pool B: prefer explicit args; fall back to on-chain position_nft_mint_b
|
|
1061
|
+
const onChainMintB = lttConfig.positionNftMintB;
|
|
1062
|
+
const hasPoolB = (positionNftMintB && !positionNftMintB.equals(web3_js_1.PublicKey.default)) ||
|
|
1063
|
+
(onChainMintB && !onChainMintB.equals(web3_js_1.PublicKey.default));
|
|
1064
|
+
let poolB = pool;
|
|
1065
|
+
let positionB = position;
|
|
1066
|
+
let lttVaultB = lttVault;
|
|
1067
|
+
let stableVaultB = stableVault;
|
|
1068
|
+
let positionNftAccountB = positionNftAccount;
|
|
1069
|
+
if (hasPoolB) {
|
|
1070
|
+
const mintB = (positionNftMintB ?? onChainMintB);
|
|
1071
|
+
const cfgB = ammConfigB ?? ammConfig;
|
|
1072
|
+
poolB = (0, utils_1.derivePoolKey)(cfgB, lttId, lttConfig.fundingTokenMint, cpAmmProgramId);
|
|
1073
|
+
[positionB] = web3_js_1.PublicKey.findProgramAddressSync([constants_1.POSITION_SEED, mintB.toBuffer()], cpAmmProgramId);
|
|
1074
|
+
lttVaultB = (0, utils_1.getVaultPda)(lttId, cpAmmProgramId, poolB);
|
|
1075
|
+
stableVaultB = (0, utils_1.getVaultPda)(lttConfig.fundingTokenMint, cpAmmProgramId, poolB);
|
|
1076
|
+
[positionNftAccountB] = web3_js_1.PublicKey.findProgramAddressSync([Buffer.from('position_nft_account'), mintB.toBuffer()], cpAmmProgramId);
|
|
1077
|
+
}
|
|
1068
1078
|
return await this.program.methods
|
|
1069
1079
|
.claimFees()
|
|
1070
1080
|
.accountsPartial({
|
|
@@ -1079,9 +1089,14 @@ class XitadelProgram {
|
|
|
1079
1089
|
stableCoinMint: lttConfig.fundingTokenMint,
|
|
1080
1090
|
lttVaultAta: lttVault,
|
|
1081
1091
|
stableCoinVaultAta: stableVault,
|
|
1082
|
-
receiverTokenAAccount
|
|
1083
|
-
receiverTokenBAccount
|
|
1092
|
+
receiverTokenAAccount,
|
|
1093
|
+
receiverTokenBAccount,
|
|
1084
1094
|
positionNftAccount,
|
|
1095
|
+
poolB,
|
|
1096
|
+
positionB,
|
|
1097
|
+
lttVaultAtaB: lttVaultB,
|
|
1098
|
+
stableCoinVaultAtaB: stableVaultB,
|
|
1099
|
+
positionNftAccountB,
|
|
1085
1100
|
eventAuthority,
|
|
1086
1101
|
tokenAProgram: spl_token_1.TOKEN_PROGRAM_ID,
|
|
1087
1102
|
tokenBProgram: spl_token_1.TOKEN_PROGRAM_ID,
|
|
@@ -1227,5 +1242,24 @@ class XitadelProgram {
|
|
|
1227
1242
|
.remainingAccounts([...tokenStakeAccounts])
|
|
1228
1243
|
.instruction();
|
|
1229
1244
|
}
|
|
1245
|
+
/**
|
|
1246
|
+
* Build a `version` instruction.
|
|
1247
|
+
*/
|
|
1248
|
+
async versionInstruction() {
|
|
1249
|
+
return this.program.methods.version().accounts({}).instruction();
|
|
1250
|
+
}
|
|
1251
|
+
/**
|
|
1252
|
+
* Return the deployed program's git commit hash by simulating
|
|
1253
|
+
* the `version` instruction and parsing its log output.
|
|
1254
|
+
*/
|
|
1255
|
+
async getVersion() {
|
|
1256
|
+
const sim = await this.program.methods.version().accounts({}).simulate();
|
|
1257
|
+
const logs = sim.raw ?? [];
|
|
1258
|
+
const versionLog = logs.find((l) => l.includes('program_version:'));
|
|
1259
|
+
if (!versionLog) {
|
|
1260
|
+
throw new Error('program_version log not found in simulation output');
|
|
1261
|
+
}
|
|
1262
|
+
return versionLog.split('program_version:')[1].trim();
|
|
1263
|
+
}
|
|
1230
1264
|
}
|
|
1231
1265
|
exports.XitadelProgram = XitadelProgram;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { Connection, PublicKey, Transaction } from '@solana/web3.js';
|
|
2
|
+
export type ProposalStatusKind = 'Draft' | 'Active' | 'Approved' | 'Executing' | 'Executed' | 'Rejected' | 'Cancelled' | 'Unknown';
|
|
3
|
+
export interface ProposalState {
|
|
4
|
+
multisig: PublicKey;
|
|
5
|
+
proposalPda: PublicKey;
|
|
6
|
+
transactionIndex: bigint;
|
|
7
|
+
status: ProposalStatusKind;
|
|
8
|
+
approvedBy: PublicKey[];
|
|
9
|
+
rejectedBy: PublicKey[];
|
|
10
|
+
cancelledBy: PublicKey[];
|
|
11
|
+
/** Snapshot of multisig threshold at fetch time (caller may cache separately). */
|
|
12
|
+
threshold: number;
|
|
13
|
+
/** True once approvedBy.length >= threshold AND not yet executed. */
|
|
14
|
+
isExecutable: boolean;
|
|
15
|
+
}
|
|
16
|
+
/** Read on-chain Proposal + Multisig accounts; derive a flat status snapshot. */
|
|
17
|
+
export declare function fetchProposalState(multisigPda: PublicKey, transactionIndex: bigint, connection: Connection): Promise<ProposalState>;
|
|
18
|
+
/** Build a fresh approve tx for the given proposal — caller signs + sends. */
|
|
19
|
+
export declare function buildApproveTx(multisigPda: PublicKey, transactionIndex: bigint, member: PublicKey): Transaction;
|
|
20
|
+
/** Build an execute tx for an approved proposal — caller signs + sends. */
|
|
21
|
+
export declare function buildExecuteTx(multisigPda: PublicKey, transactionIndex: bigint, member: PublicKey, connection: Connection): Promise<Transaction>;
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.fetchProposalState = fetchProposalState;
|
|
37
|
+
exports.buildApproveTx = buildApproveTx;
|
|
38
|
+
exports.buildExecuteTx = buildExecuteTx;
|
|
39
|
+
const web3_js_1 = require("@solana/web3.js");
|
|
40
|
+
const multisig = __importStar(require("@sqds/multisig"));
|
|
41
|
+
/** Read on-chain Proposal + Multisig accounts; derive a flat status snapshot. */
|
|
42
|
+
async function fetchProposalState(multisigPda, transactionIndex, connection) {
|
|
43
|
+
const [proposalPda] = multisig.getProposalPda({
|
|
44
|
+
multisigPda,
|
|
45
|
+
transactionIndex,
|
|
46
|
+
});
|
|
47
|
+
const [proposal, multisigAccount] = await Promise.all([
|
|
48
|
+
multisig.accounts.Proposal.fromAccountAddress(connection, proposalPda),
|
|
49
|
+
multisig.accounts.Multisig.fromAccountAddress(connection, multisigPda),
|
|
50
|
+
]);
|
|
51
|
+
const status = decodeStatus(proposal.status);
|
|
52
|
+
const approvedBy = proposal.approved;
|
|
53
|
+
const isExecutable = status === 'Approved' ||
|
|
54
|
+
(status === 'Active' && approvedBy.length >= multisigAccount.threshold);
|
|
55
|
+
return {
|
|
56
|
+
multisig: multisigPda,
|
|
57
|
+
proposalPda,
|
|
58
|
+
transactionIndex,
|
|
59
|
+
status,
|
|
60
|
+
approvedBy,
|
|
61
|
+
rejectedBy: proposal.rejected,
|
|
62
|
+
cancelledBy: proposal.cancelled,
|
|
63
|
+
threshold: multisigAccount.threshold,
|
|
64
|
+
isExecutable,
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
function decodeStatus(raw) {
|
|
68
|
+
if (!raw || typeof raw !== 'object')
|
|
69
|
+
return 'Unknown';
|
|
70
|
+
const key = Object.keys(raw)[0];
|
|
71
|
+
switch (key) {
|
|
72
|
+
case 'draft':
|
|
73
|
+
case 'Draft':
|
|
74
|
+
return 'Draft';
|
|
75
|
+
case 'active':
|
|
76
|
+
case 'Active':
|
|
77
|
+
return 'Active';
|
|
78
|
+
case 'approved':
|
|
79
|
+
case 'Approved':
|
|
80
|
+
return 'Approved';
|
|
81
|
+
case 'executing':
|
|
82
|
+
case 'Executing':
|
|
83
|
+
return 'Executing';
|
|
84
|
+
case 'executed':
|
|
85
|
+
case 'Executed':
|
|
86
|
+
return 'Executed';
|
|
87
|
+
case 'rejected':
|
|
88
|
+
case 'Rejected':
|
|
89
|
+
return 'Rejected';
|
|
90
|
+
case 'cancelled':
|
|
91
|
+
case 'Cancelled':
|
|
92
|
+
return 'Cancelled';
|
|
93
|
+
default:
|
|
94
|
+
return 'Unknown';
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
/** Build a fresh approve tx for the given proposal — caller signs + sends. */
|
|
98
|
+
function buildApproveTx(multisigPda, transactionIndex, member) {
|
|
99
|
+
const ix = multisig.instructions.proposalApprove({
|
|
100
|
+
multisigPda,
|
|
101
|
+
transactionIndex,
|
|
102
|
+
member,
|
|
103
|
+
});
|
|
104
|
+
return new web3_js_1.Transaction().add(ix);
|
|
105
|
+
}
|
|
106
|
+
/** Build an execute tx for an approved proposal — caller signs + sends. */
|
|
107
|
+
async function buildExecuteTx(multisigPda, transactionIndex, member, connection) {
|
|
108
|
+
const result = await multisig.instructions.vaultTransactionExecute({
|
|
109
|
+
connection,
|
|
110
|
+
multisigPda,
|
|
111
|
+
transactionIndex,
|
|
112
|
+
member,
|
|
113
|
+
});
|
|
114
|
+
return new web3_js_1.Transaction().add(result.instruction);
|
|
115
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { PublicKey } from '@solana/web3.js';
|
|
2
|
+
/**
|
|
3
|
+
* Admin wallet mode resolved at SDK/frontend layer.
|
|
4
|
+
*
|
|
5
|
+
* The xitadel program treats `Config.manager` as a single Pubkey and is
|
|
6
|
+
* mode-agnostic on-chain. This type lets callers select the correct
|
|
7
|
+
* transaction shape:
|
|
8
|
+
* - 'eoa' → submit instruction directly with manager as signer
|
|
9
|
+
* - 'squads' → wrap instruction as a Squads VaultTransaction proposal
|
|
10
|
+
*/
|
|
11
|
+
export type WalletMode = 'eoa' | 'squads';
|
|
12
|
+
/**
|
|
13
|
+
* Squads V4 program ID — unified across devnet + mainnet.
|
|
14
|
+
* Re-exported from @sqds/multisig for caller convenience.
|
|
15
|
+
*/
|
|
16
|
+
export declare const SQUADS_PROGRAM_ID: PublicKey;
|
|
17
|
+
/**
|
|
18
|
+
* The minimum information needed to identify a Squads vault PDA acting as
|
|
19
|
+
* xitadel admin. Both fields must be provided up-front by the operator
|
|
20
|
+
* (typically via app ENV) — vault PDAs are System-owned, so the SDK cannot
|
|
21
|
+
* infer them from on-chain state alone.
|
|
22
|
+
*/
|
|
23
|
+
export interface SquadsBinding {
|
|
24
|
+
multisig: PublicKey;
|
|
25
|
+
vaultIndex: number;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Per-tx context bundling a binding with the wallet currently in use
|
|
29
|
+
* (a member of the multisig submitting / approving proposals).
|
|
30
|
+
*/
|
|
31
|
+
export interface SquadsContext extends SquadsBinding {
|
|
32
|
+
proposer: PublicKey;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Derive the Squads vault PDA for a given binding. Thin wrapper around
|
|
36
|
+
* @sqds/multisig getVaultPda — aliased to avoid clashing with the existing
|
|
37
|
+
* SDK `getVaultPda` (Meteora pool vault).
|
|
38
|
+
*/
|
|
39
|
+
export declare function getSquadsVaultPda(binding: SquadsBinding): PublicKey;
|
|
40
|
+
/**
|
|
41
|
+
* Confirm a given manager pubkey is actually the vault PDA of the
|
|
42
|
+
* supplied binding. Hard guard against silently routing admin actions
|
|
43
|
+
* through the wrong path — callers MUST check this before treating
|
|
44
|
+
* `Config.manager` as a Squads-managed authority.
|
|
45
|
+
*/
|
|
46
|
+
export declare function verifySquadsBinding(manager: PublicKey, binding: SquadsBinding): boolean;
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.SQUADS_PROGRAM_ID = void 0;
|
|
37
|
+
exports.getSquadsVaultPda = getSquadsVaultPda;
|
|
38
|
+
exports.verifySquadsBinding = verifySquadsBinding;
|
|
39
|
+
const multisig = __importStar(require("@sqds/multisig"));
|
|
40
|
+
/**
|
|
41
|
+
* Squads V4 program ID — unified across devnet + mainnet.
|
|
42
|
+
* Re-exported from @sqds/multisig for caller convenience.
|
|
43
|
+
*/
|
|
44
|
+
exports.SQUADS_PROGRAM_ID = multisig.PROGRAM_ID;
|
|
45
|
+
/**
|
|
46
|
+
* Derive the Squads vault PDA for a given binding. Thin wrapper around
|
|
47
|
+
* @sqds/multisig getVaultPda — aliased to avoid clashing with the existing
|
|
48
|
+
* SDK `getVaultPda` (Meteora pool vault).
|
|
49
|
+
*/
|
|
50
|
+
function getSquadsVaultPda(binding) {
|
|
51
|
+
const [pda] = multisig.getVaultPda({
|
|
52
|
+
multisigPda: binding.multisig,
|
|
53
|
+
index: binding.vaultIndex,
|
|
54
|
+
});
|
|
55
|
+
return pda;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Confirm a given manager pubkey is actually the vault PDA of the
|
|
59
|
+
* supplied binding. Hard guard against silently routing admin actions
|
|
60
|
+
* through the wrong path — callers MUST check this before treating
|
|
61
|
+
* `Config.manager` as a Squads-managed authority.
|
|
62
|
+
*/
|
|
63
|
+
function verifySquadsBinding(manager, binding) {
|
|
64
|
+
if (binding.vaultIndex < 0 || binding.vaultIndex > 255)
|
|
65
|
+
return false;
|
|
66
|
+
return getSquadsVaultPda(binding).equals(manager);
|
|
67
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { Connection, PublicKey, Transaction, TransactionInstruction } from '@solana/web3.js';
|
|
2
|
+
import { SquadsBinding, SquadsContext } from './squads-wallet-modes';
|
|
3
|
+
/**
|
|
4
|
+
* Bundle of the three Solana transactions required to push a single inner
|
|
5
|
+
* instruction through a Squads vault transaction lifecycle.
|
|
6
|
+
*
|
|
7
|
+
* 1. createTx — vaultTransactionCreate + proposalCreate (proposer signs)
|
|
8
|
+
* 2. approveTx — proposalApprove from the proposer (counts toward threshold)
|
|
9
|
+
* 3. executeTx — vaultTransactionExecute, callable once threshold met
|
|
10
|
+
*
|
|
11
|
+
* Callers submit createTx + approveTx immediately; remaining members
|
|
12
|
+
* approve separately; finally any member submits executeTx.
|
|
13
|
+
*/
|
|
14
|
+
export interface SquadsProposalBundle {
|
|
15
|
+
multisig: PublicKey;
|
|
16
|
+
vaultPda: PublicKey;
|
|
17
|
+
transactionIndex: bigint;
|
|
18
|
+
proposalPda: PublicKey;
|
|
19
|
+
transactionPda: PublicKey;
|
|
20
|
+
createTx: Transaction;
|
|
21
|
+
approveTx: Transaction;
|
|
22
|
+
executeTx: Transaction;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Wrap a single xitadel instruction as a Squads VaultTransaction proposal.
|
|
26
|
+
*
|
|
27
|
+
* The inner instruction MUST list the vault PDA (derived from the binding)
|
|
28
|
+
* as the signer for any account that would normally be signed by
|
|
29
|
+
* `Config.manager`. Anchor's `Signer<'info>` constraint accepts the PDA
|
|
30
|
+
* identically once Squads runs `invoke_signed` at execute time.
|
|
31
|
+
*
|
|
32
|
+
* Throws if the binding does not match the on-chain vault PDA — defensive
|
|
33
|
+
* guard against silently routing admin actions through the wrong path.
|
|
34
|
+
*/
|
|
35
|
+
export declare function wrapWithSquads(innerIx: TransactionInstruction, ctx: SquadsContext, connection: Connection): Promise<SquadsProposalBundle>;
|
|
36
|
+
/** Refetch the threshold + member count to render Squads(N/M) badges. */
|
|
37
|
+
export declare function fetchSquadsThreshold(binding: SquadsBinding, connection: Connection): Promise<{
|
|
38
|
+
threshold: number;
|
|
39
|
+
memberCount: number;
|
|
40
|
+
}>;
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.wrapWithSquads = wrapWithSquads;
|
|
37
|
+
exports.fetchSquadsThreshold = fetchSquadsThreshold;
|
|
38
|
+
const web3_js_1 = require("@solana/web3.js");
|
|
39
|
+
const multisig = __importStar(require("@sqds/multisig"));
|
|
40
|
+
const squads_wallet_modes_1 = require("./squads-wallet-modes");
|
|
41
|
+
/**
|
|
42
|
+
* Wrap a single xitadel instruction as a Squads VaultTransaction proposal.
|
|
43
|
+
*
|
|
44
|
+
* The inner instruction MUST list the vault PDA (derived from the binding)
|
|
45
|
+
* as the signer for any account that would normally be signed by
|
|
46
|
+
* `Config.manager`. Anchor's `Signer<'info>` constraint accepts the PDA
|
|
47
|
+
* identically once Squads runs `invoke_signed` at execute time.
|
|
48
|
+
*
|
|
49
|
+
* Throws if the binding does not match the on-chain vault PDA — defensive
|
|
50
|
+
* guard against silently routing admin actions through the wrong path.
|
|
51
|
+
*/
|
|
52
|
+
async function wrapWithSquads(innerIx, ctx, connection) {
|
|
53
|
+
const vaultPda = (0, squads_wallet_modes_1.getSquadsVaultPda)(ctx);
|
|
54
|
+
if (!(0, squads_wallet_modes_1.verifySquadsBinding)(vaultPda, ctx)) {
|
|
55
|
+
throw new Error('Squads binding mismatch: derived vault PDA does not match the supplied multisig + vaultIndex');
|
|
56
|
+
}
|
|
57
|
+
// Read current transactionIndex; next proposal sits at + 1.
|
|
58
|
+
const multisigAccount = await multisig.accounts.Multisig.fromAccountAddress(connection, ctx.multisig);
|
|
59
|
+
const currentIndex = BigInt(multisigAccount.transactionIndex.toString());
|
|
60
|
+
const transactionIndex = currentIndex + 1n;
|
|
61
|
+
// Wrap inner ix into a v0 TransactionMessage with vault PDA as payer.
|
|
62
|
+
// recentBlockhash here is a placeholder consumed by Squads serializer;
|
|
63
|
+
// the on-chain execute step does not enforce it.
|
|
64
|
+
const transactionMessage = new web3_js_1.TransactionMessage({
|
|
65
|
+
payerKey: vaultPda,
|
|
66
|
+
recentBlockhash: web3_js_1.PublicKey.default.toBase58(),
|
|
67
|
+
instructions: [innerIx],
|
|
68
|
+
});
|
|
69
|
+
const createIx = multisig.instructions.vaultTransactionCreate({
|
|
70
|
+
multisigPda: ctx.multisig,
|
|
71
|
+
transactionIndex,
|
|
72
|
+
creator: ctx.proposer,
|
|
73
|
+
vaultIndex: ctx.vaultIndex,
|
|
74
|
+
ephemeralSigners: 0,
|
|
75
|
+
transactionMessage,
|
|
76
|
+
});
|
|
77
|
+
const proposalIx = multisig.instructions.proposalCreate({
|
|
78
|
+
multisigPda: ctx.multisig,
|
|
79
|
+
creator: ctx.proposer,
|
|
80
|
+
transactionIndex,
|
|
81
|
+
});
|
|
82
|
+
const approveIx = multisig.instructions.proposalApprove({
|
|
83
|
+
multisigPda: ctx.multisig,
|
|
84
|
+
transactionIndex,
|
|
85
|
+
member: ctx.proposer,
|
|
86
|
+
});
|
|
87
|
+
const executeResult = await multisig.instructions.vaultTransactionExecute({
|
|
88
|
+
connection,
|
|
89
|
+
multisigPda: ctx.multisig,
|
|
90
|
+
transactionIndex,
|
|
91
|
+
member: ctx.proposer,
|
|
92
|
+
});
|
|
93
|
+
const [transactionPda] = multisig.getTransactionPda({
|
|
94
|
+
multisigPda: ctx.multisig,
|
|
95
|
+
index: transactionIndex,
|
|
96
|
+
});
|
|
97
|
+
const [proposalPda] = multisig.getProposalPda({
|
|
98
|
+
multisigPda: ctx.multisig,
|
|
99
|
+
transactionIndex,
|
|
100
|
+
});
|
|
101
|
+
const createTx = new web3_js_1.Transaction().add(createIx, proposalIx);
|
|
102
|
+
const approveTx = new web3_js_1.Transaction().add(approveIx);
|
|
103
|
+
const executeTx = new web3_js_1.Transaction().add(executeResult.instruction);
|
|
104
|
+
return {
|
|
105
|
+
multisig: ctx.multisig,
|
|
106
|
+
vaultPda,
|
|
107
|
+
transactionIndex,
|
|
108
|
+
proposalPda,
|
|
109
|
+
transactionPda,
|
|
110
|
+
createTx,
|
|
111
|
+
approveTx,
|
|
112
|
+
executeTx,
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
/** Refetch the threshold + member count to render Squads(N/M) badges. */
|
|
116
|
+
async function fetchSquadsThreshold(binding, connection) {
|
|
117
|
+
const account = await multisig.accounts.Multisig.fromAccountAddress(connection, binding.multisig);
|
|
118
|
+
return {
|
|
119
|
+
threshold: account.threshold,
|
|
120
|
+
memberCount: account.members.length,
|
|
121
|
+
};
|
|
122
|
+
}
|
|
@@ -650,6 +650,26 @@
|
|
|
650
650
|
"name": "position_nft_account",
|
|
651
651
|
"writable": true
|
|
652
652
|
},
|
|
653
|
+
{
|
|
654
|
+
"name": "pool_b",
|
|
655
|
+
"writable": true
|
|
656
|
+
},
|
|
657
|
+
{
|
|
658
|
+
"name": "position_b",
|
|
659
|
+
"writable": true
|
|
660
|
+
},
|
|
661
|
+
{
|
|
662
|
+
"name": "ltt_vault_ata_b",
|
|
663
|
+
"writable": true
|
|
664
|
+
},
|
|
665
|
+
{
|
|
666
|
+
"name": "stable_coin_vault_ata_b",
|
|
667
|
+
"writable": true
|
|
668
|
+
},
|
|
669
|
+
{
|
|
670
|
+
"name": "position_nft_account_b",
|
|
671
|
+
"writable": true
|
|
672
|
+
},
|
|
653
673
|
{
|
|
654
674
|
"name": "event_authority",
|
|
655
675
|
"writable": true
|
|
@@ -5022,6 +5042,21 @@
|
|
|
5022
5042
|
}
|
|
5023
5043
|
]
|
|
5024
5044
|
},
|
|
5045
|
+
{
|
|
5046
|
+
"name": "version",
|
|
5047
|
+
"discriminator": [
|
|
5048
|
+
118,
|
|
5049
|
+
65,
|
|
5050
|
+
195,
|
|
5051
|
+
198,
|
|
5052
|
+
129,
|
|
5053
|
+
216,
|
|
5054
|
+
252,
|
|
5055
|
+
192
|
|
5056
|
+
],
|
|
5057
|
+
"accounts": [],
|
|
5058
|
+
"args": []
|
|
5059
|
+
},
|
|
5025
5060
|
{
|
|
5026
5061
|
"name": "withdraw_collateral",
|
|
5027
5062
|
"discriminator": [
|
|
@@ -656,6 +656,26 @@ export type Xitadel = {
|
|
|
656
656
|
"name": "positionNftAccount";
|
|
657
657
|
"writable": true;
|
|
658
658
|
},
|
|
659
|
+
{
|
|
660
|
+
"name": "poolB";
|
|
661
|
+
"writable": true;
|
|
662
|
+
},
|
|
663
|
+
{
|
|
664
|
+
"name": "positionB";
|
|
665
|
+
"writable": true;
|
|
666
|
+
},
|
|
667
|
+
{
|
|
668
|
+
"name": "lttVaultAtaB";
|
|
669
|
+
"writable": true;
|
|
670
|
+
},
|
|
671
|
+
{
|
|
672
|
+
"name": "stableCoinVaultAtaB";
|
|
673
|
+
"writable": true;
|
|
674
|
+
},
|
|
675
|
+
{
|
|
676
|
+
"name": "positionNftAccountB";
|
|
677
|
+
"writable": true;
|
|
678
|
+
},
|
|
659
679
|
{
|
|
660
680
|
"name": "eventAuthority";
|
|
661
681
|
"writable": true;
|
|
@@ -5028,6 +5048,21 @@ export type Xitadel = {
|
|
|
5028
5048
|
}
|
|
5029
5049
|
];
|
|
5030
5050
|
},
|
|
5051
|
+
{
|
|
5052
|
+
"name": "version";
|
|
5053
|
+
"discriminator": [
|
|
5054
|
+
118,
|
|
5055
|
+
65,
|
|
5056
|
+
195,
|
|
5057
|
+
198,
|
|
5058
|
+
129,
|
|
5059
|
+
216,
|
|
5060
|
+
252,
|
|
5061
|
+
192
|
|
5062
|
+
];
|
|
5063
|
+
"accounts": [];
|
|
5064
|
+
"args": [];
|
|
5065
|
+
},
|
|
5031
5066
|
{
|
|
5032
5067
|
"name": "withdrawCollateral";
|
|
5033
5068
|
"discriminator": [
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"private": false,
|
|
3
3
|
"name": "@xitadel-fi/sdk",
|
|
4
|
-
"version": "0.2.
|
|
4
|
+
"version": "0.2.13",
|
|
5
5
|
"description": "SDK for interacting with the Xitadel program",
|
|
6
6
|
"main": "dist/sdk/src/index.js",
|
|
7
7
|
"types": "dist/sdk/src/index.d.ts",
|
|
@@ -13,8 +13,8 @@
|
|
|
13
13
|
"url": "git+https://github.com/xitadel-fi/xitadel-svm.git"
|
|
14
14
|
},
|
|
15
15
|
"publishConfig": {
|
|
16
|
-
"registry": "https://
|
|
17
|
-
"access": "
|
|
16
|
+
"registry": "https://npm.pkg.github.com/",
|
|
17
|
+
"access": "restricted"
|
|
18
18
|
},
|
|
19
19
|
"scripts": {
|
|
20
20
|
"build": "tsc",
|