The TypeScript package is @loyal-labs/loyal-smart-accounts.
What It Exposes
The public surface is split by feature namespace instead of one flat API:
programConfig
smartAccounts
proposals
transactions
batches
policies
spendingLimits
execution
It also exports lower-level protocol helpers:
generated
accounts
pda
codecs
errors
Install
bun add @loyal-labs/loyal-smart-accounts @solana/web3.js
# or
npm install @loyal-labs/loyal-smart-accounts @solana/web3.js
Create A Client
import {
createLoyalSmartAccountsClient,
pda,
} from "@loyal-labs/loyal-smart-accounts";
import { Connection } from "@solana/web3.js";
const connection = new Connection("https://api.devnet.solana.com");
const client = createLoyalSmartAccountsClient({ connection });
const [settingsPda] = pda.getSettingsPda({
accountIndex: 1n,
});
Three Ways To Work
This is the most important pattern in the SDK:
- Build a raw instruction
- Build a prepared operation
- Use the client send flow
1. Raw Instruction
Use smartAccounts.instructions.create(...) when you want full transaction assembly control.
import {
codecs,
smartAccounts,
} from "@loyal-labs/loyal-smart-accounts";
import { Keypair } from "@solana/web3.js";
const creator = Keypair.generate();
const instruction = smartAccounts.instructions.create({
treasury: creator.publicKey,
creator: creator.publicKey,
settings: settingsPda,
settingsAuthority: null,
threshold: 1,
signers: [
{
key: creator.publicKey,
permissions: codecs.Permissions.all(),
},
],
timeLock: 0,
rentCollector: null,
});
2. Prepared Operation
Use smartAccounts.prepare.create(...) when you want the SDK to package the operation cleanly before sending it yourself.
const prepared = await smartAccounts.prepare.create({
treasury: creator.publicKey,
creator: creator.publicKey,
settings: settingsPda,
settingsAuthority: null,
threshold: 1,
signers: [
{
key: creator.publicKey,
permissions: codecs.Permissions.all(),
},
],
timeLock: 0,
rentCollector: null,
});
await client.send(prepared, {
signers: [creator],
});
3. Client Send Flow
Use client.smartAccounts.create(...) when you want the highest-level path.
await client.smartAccounts.create({
treasury: creator.publicKey,
creator,
settings: settingsPda,
settingsAuthority: null,
threshold: 1,
signers: [
{
key: creator.publicKey,
permissions: codecs.Permissions.all(),
},
],
timeLock: 0,
rentCollector: null,
});
Choosing The Right Level
| Use this | When you want |
|---|
instructions.* | Full control over transaction composition |
prepare.* | A reusable prepared operation before send |
client.* | The shortest path from request to signature |
PDA Helpers You Will Use Early
Two helpers matter immediately:
pda.getSettingsPda({ accountIndex })
pda.getSmartAccountPda({ settingsPda, accountIndex })
The first derives the configuration root. The second derives a sub-account that can actually hold assets and execute.
Do not send funds to the settings PDA by accident. In most integrations, the sub-account or vault PDA is the address users should treat as the asset-holding account.
What To Read Next
The TS SDK already exposes the broader feature namespaces listed above. This page stays centered on the create flow and the main integration pattern so it remains useful instead of turning into a dump of every operation.