@loyal-labs/smart-account-vaults
v0.1.1
Published
High-level read/write helpers for Loyal's Squads-derived smart-account vault flow.
Downloads
89
Readme
@loyal-labs/smart-account-vaults
High-level read/write helpers for Loyal's Squads-derived smart-account vault flow.
This package is a convenience layer over:
@loyal-labs/loyal-smart-accounts@loyal-labs/loyal-smart-accounts-core@loyal-labs/solana-wallet
It is intended for app-facing vault, proposal, and approval/execution flows rather than full protocol access.
What It Exposes
The package root re-exports everything from:
src/client.tssrc/messages.tssrc/spending-limits.tssrc/types.tssrc/wallet.ts
Main factory
createSmartAccountVaultsClient(config)
Creates a client bound to a Solana connection, an optional smart-account programId, and an optional walletDataClient.
Returned client shape:
connectionprogramIdsdkfetchVault(args)listVaults(args)listSpendingLimitPolicies(args)listSpendingLimits(args)listProposals(args)fetchOverview(args)prepareSolTransferProposal(args)prepareSplTransferProposal(args)prepareCustomInstructionProposal(args)preparePolicyCustomInstructionProposal(args)prepareAddInitiateSigner(args)prepareRemoveInitiateSigner(args)prepareSetSpendingLimitPolicy(args)prepareRemoveSpendingLimitPolicy(args)prepareUseSolSpendingLimitPolicy(args)prepareApproveProposal(args)prepareRejectProposal(args)prepareExecuteProposal(args)prepareExecuteSettingsProposal(args)prepareExecutePolicyProposal(args)
Notes:
sdkis the underlying Loyal smart-accounts client. This package is a wrapper, not a replacement for the lower-level SDK.listPolicies()exists internally but is not returned as part of the public client surface.
Message helpers
createVaultSolTransferMessage(args)createVaultSplTransferMessage(args)createVaultCustomInstructionMessage(args)isSupportedTokenProgram(programId)resolveVaultAccountIndex(accountIndex)
These build TransactionMessage payloads where the vault PDA is the payer/executor account.
Wallet helpers
sendPreparedWithWallet(args)isWalletAdapterLike(value)
sendPreparedWithWallet() compiles a prepared operation to a versioned transaction, signs/sends with a wallet adapter, and optionally confirms it.
Exported types
Read-model types:
SmartAccountOverviewSmartAccountVaultSnapshotSmartAccountProposalSnapshotSmartAccountProposalSummarySmartAccountPolicySnapshotSmartAccountSignerSnapshot
Proposal/input types:
SmartAccountTransferProposalInputSmartAccountTokenTransferProposalInputSmartAccountCustomInstructionProposalInputSmartAccountPolicyCustomInstructionProposalInput
Adapter/config types:
SmartAccountVaultsClientConfigWalletAdapterLikeSendPreparedWithWalletArgs
Status/enum-like types:
SmartAccountProposalStatusSmartAccountProposalPayloadTypeSmartAccountProposalSummaryKindSmartAccountSignerPermissionSmartAccountSignerScope
Spending-limit helpers:
getSpendingLimitPeriodSecondsgetEffectiveSpendingLimitRemainingAmountgetSpendingLimitNextResetformatTokenAmounttokenAmountToNumbertoSpendingLimitPeriodLabelSOL_SPENDING_LIMIT_MINT
How It Works
1. Underlying SDK
createSmartAccountVaultsClient() constructs a lower-level client with createLoyalSmartAccountsClient(...) and fixes the default commitment to confirmed.
This package does not implement the protocol itself. It delegates PDA derivation, account decoding, prepared operation building, and execution helpers to the Loyal smart-accounts SDK.
2. Vault reads
fetchVault():
- Resolves
accountIndexwith a default of0. - Derives the vault PDA from
settingsPda + accountIndex. - Fetches:
- lamports from RPC
- portfolio from
walletDataClient.getPortfolio(...) - activity from
walletDataClient.getActivity(...)
- Returns a normalized
SmartAccountVaultSnapshot.
listVaults():
- Loads smart-account settings unless
accountUtilizationis supplied. - Expands vault indexes from
0..accountUtilization. - Calls
fetchVault()for each vault.
3. Policy and proposal reads
listProposals() scans on-chain program accounts using getProgramAccounts(...) with discriminator-based memcmp filters for:
- proposals
- transactions
- settings transactions
- policies
It then joins those accounts by consensus PDA and transaction index.
For summaries, it understands:
- native SOL transfers
- SPL
transferCheckedtransfers - settings transactions
Anything else is represented as unknown, with the program id surfaced when possible.
fetchOverview() combines:
- root settings
- vaults
- policy signers
- proposals
into a single SmartAccountOverview payload that is suitable for sidebar/read-model style UI use.
4. Proposal creation
For standard vault-originated proposals:
prepareSolTransferProposal()prepareSplTransferProposal()prepareCustomInstructionProposal()
the flow is:
- Load current settings.
- Compute
transactionIndex = current + 1. - Derive the target vault PDA.
- Build a
TransactionMessage. - Prepare the transaction account creation.
- Prepare the proposal account creation.
- Merge both prepared operations into one frozen prepared operation.
For policy-based custom proposals:
preparePolicyCustomInstructionProposal()
the package:
- Loads the policy account.
- Uses the policy PDA as the consensus account.
- Serializes the transaction message into multisig/smart-account transaction bytes.
- Wraps the payload in a generated
PolicyPayload. - Prepares the policy transaction and proposal creation operations.
5. Voting and execution
prepareApproveProposal()wraps proposal approval.prepareRejectProposal()wraps proposal rejection.prepareExecuteProposal()executes a regular stored transaction.prepareExecuteSettingsProposal()first derives any extra execution accounts required by settings actions, then prepares the settings-transaction execution.prepareExecutePolicyProposal()resolves execution accounts for stored policy transactions and prepares policy execution.
The send step is intentionally separate. Typical usage is:
- Prepare an operation with the client.
- Send it with
sendPreparedWithWallet(...).
Relationship To Squads
This package follows Squads-style smart-account concepts:
- a root config account controls membership, threshold, and timelock
- vaults hold assets
- transactions are proposed and then voted on
- approved transactions are executed from vault PDAs
- policy and spending-limit mechanisms extend the base flow
The important local detail is that Loyal is not depending directly on Squads' unpublished package. The local SDK is pinned to an upstream snapshot of the newer Squads smart-account program:
- upstream repo:
https://github.com/Squads-Protocol/smart-account-program - pinned commit in this monorepo:
80bf1f7ad28fd1176c364879776982730b8e9c80 - fetched on:
2026-03-20 - local manifest:
sdk/loyal-smart-accounts/upstream/manifest.json - pinned program id there:
SMRTzfY6DfH5ik3TKiyLFfXexV8uSG3d2UksSCYdunG
That means this package sits conceptually between:
- the public Squads v4 multisig/vault/proposal model
- the newer Squads Smart Account Program and hosted developer API
Relevant Squads Context
As of April 23, 2026, the official Squads materials split across two tracks:
- Squads v4 multisig docs:
https://docs.squads.so/main/development/typescript/overviewhttps://docs.squads.so/main/development/reference/accounts
- newer Smart Account API / Smart Account Program docs:
https://developers.squads.so/squads-api/introductionhttps://developers.squads.so/squads-api/api-reference/v1/policieshttps://github.com/Squads-Protocol/smart-account-program
Useful mappings:
- Squads "multisig" config account maps to this package's root smart-account settings flow.
- Squads vaults/sub-accounts map to this package's
accountIndex-selected vault PDAs. - Squads proposal approval/execution maps to this package's
prepareApproveProposal(),prepareRejectProposal(), and execute helpers. - Squads permission concepts map closely to:
initiatevoteexecute
Known Limitations And Gotchas
walletDataClientis optional in the config type, butfetchVault(),listVaults(), andfetchOverview()require it at runtime.- Proposal creation uses
current transaction index + 1, so concurrent proposers can race and produce stale prepared operations. - Proposal summaries are intentionally lossy. Only common transfer/settings payloads are decoded into first-class summaries.
- Stored policy proposal execution currently supports spending-limit payloads and async program-interaction payloads. Other policy payloads may still require dropping to
client.sdk. - Package-local tests cover spending-limit reset and policy-update preservation behavior in
src/__tests__/spending-limits.test.ts.
Where It Is Used In This Repo
frontend/src/features/smart-accounts/server/read-model.tsfrontend/src/hooks/use-smart-account-sidebar-data.tsscripts/propose-smart-account-transaction.ts
Those consumers use this package as a read-model and wallet-action adapter on top of the lower-level Loyal smart-accounts SDK.
