KAGURA 神楽

KAGURA is a continuous-time DeFi primitive on Solana. Two on-chain Anchor programs: a tick-attestation registry, and a USDC funding vault that compounds yield every block instead of every hour.

contact: hello@kagura.network
神楽KAGURA/ docs
v0.1.0 · pre-deployment← back to sitegithub →
integration·typescript client

tstypescript client

all instructions are exposed via the standard anchor ts client. shipped scripts in the repo demonstrate every usage.

setup

terminalbash
1yarn add @coral-xyz/anchor @solana/web3.js @solana/spl-token
setup.tsts
1import * as anchor from "@coral-xyz/anchor";2import { Program } from "@coral-xyz/anchor";3import { KaguraCore } from "../target/types/kagura_core";4import { KaguraVault } from "../target/types/kagura_vault";5 6const provider = anchor.AnchorProvider.env();7anchor.setProvider(provider);8 9const core  = anchor.workspace.kaguraCore  as Program<KaguraCore>;10const vault = anchor.workspace.kaguraVault as Program<KaguraVault>;

initialize config (once per network)

init-config.tsts
1const [configPda] = PublicKey.findProgramAddressSync(2    [Buffer.from("kagura-config")],3    core.programId,4);5 6await core.methods7    .initializeConfig()8    .accountsPartial({9        authority: wallet.publicKey,10        config: configPda,11        systemProgram: SystemProgram.programId,12    })13    .rpc();

register protocol

register.tsts
1const [protocolPda] = PublicKey.findProgramAddressSync(2    [Buffer.from("kagura-protocol"), wallet.publicKey.toBuffer()],3    core.programId,4);5 6await core.methods7    .registerProtocol("my-protocol", 1000)  // tick interval ms8    .accountsPartial({9        authority: wallet.publicKey,10        config: configPda,11        protocol: protocolPda,12        systemProgram: SystemProgram.programId,13    })14    .rpc();

initialize vault

init-vault.tsts
1const [vaultPda] = PublicKey.findProgramAddressSync(2    [Buffer.from("kagura-vault"), wallet.publicKey.toBuffer()],3    vault.programId,4);5const [shareMintPda] = PublicKey.findProgramAddressSync(6    [Buffer.from("share-mint"), vaultPda.toBuffer()],7    vault.programId,8);9// (... derive principalAuthPda, treasuryAuthPda, principalPda, treasuryPda similarly)10 11await vault.methods12    .initializeVault(2200)            // 22% APR13    .accountsPartial({14        authority: wallet.publicKey,15        usdcMint,16        vault: vaultPda,17        shareMint: shareMintPda,18        principalAuthority: principalAuthPda,19        treasuryAuthority: treasuryAuthPda,20        principalAccount: principalPda,21        treasuryAccount: treasuryPda,22        kaguraProtocol: protocolPda,23        tokenProgram: TOKEN_PROGRAM_ID,24        systemProgram: SystemProgram.programId,25        rent: SYSVAR_RENT_PUBKEY,26    })27    .rpc();

deposit

deposit.tsts
1await vault.methods2    .deposit(new BN(10_000_000_000))   // 10,000 USDC (6 decimals)3    .accountsPartial({4        user: wallet.publicKey,5        vault: vaultPda,6        shareMint: shareMintPda,7        principalAccount: principalPda,8        userTokenAccount: userUsdcAta,9        userShareAccount: userShareAta,10        tokenProgram: TOKEN_PROGRAM_ID,11    })12    .rpc();

tick funding

tick.tsts
1// long-running ticker bot loop2while (true) {3    const start = Date.now();4    try {5        await vault.methods6            .tickFunding()7            .accountsPartial({8                authority: wallet.publicKey,9                vault: vaultPda,10                principalAccount: principalPda,11                treasuryAccount: treasuryPda,12                treasuryAuthority: treasuryAuthPda,13                shareMint: shareMintPda,14                kaguraConfig: configPda,15                kaguraProtocol: protocolPda,16                kaguraCoreProgram: core.programId,17                tokenProgram: TOKEN_PROGRAM_ID,18            })19            .rpc({ skipPreflight: false, commitment: "confirmed" });20    } catch (e: any) {21        console.error("tick failed:", e.message);22    }23    const wait = Math.max(0, 1500 - (Date.now() - start));24    if (wait > 0) await new Promise((r) => setTimeout(r, wait));25}

withdraw

withdraw.tsts
1await vault.methods2    .withdraw(new BN(allShares.toString()))3    .accountsPartial({4        user: wallet.publicKey,5        vault: vaultPda,6        shareMint: shareMintPda,7        principalAccount: principalPda,8        principalAuthority: principalAuthPda,9        userTokenAccount: userUsdcAta,10        userShareAccount: userShareAta,11        tokenProgram: TOKEN_PROGRAM_ID,12    })13    .rpc();

event subscription

watch-events.tsts
1const listener = vault.addEventListener("FundingTicked", (ev, slot) => {2    console.log(`tick #${ev.tickNumber} +${ev.accrued} usdc @ slot ${slot}`);3});4 5// ... later6await vault.removeEventListener(listener);