use ephemeral_rollups_sdk::access_control::structs::{ Member, AUTHORITY_FLAG, TX_LOGS_FLAG, TX_BALANCES_FLAG, TX_MESSAGE_FLAG, ACCOUNT_SIGNATURES_FLAG,};// Set flags by combining them with bitwise ORlet flags = AUTHORITY_FLAG | TX_LOGS_FLAG;// Create a member with combined flagslet mut member = Member { flags, pubkey: user_pubkey,};// Check if member has a specific flag using bitwise ANDlet is_authority = (member.flags & AUTHORITY_FLAG) != 0;let can_see_logs = (member.flags & TX_LOGS_FLAG) != 0;// Use helper methods to set/remove flagsmember.set_flags(TX_BALANCES_FLAG); // Add a flagmember.remove_flags(TX_LOGS_FLAG); // Remove a flag
use ephemeral_rollups_pinocchio::types::{Member, MemberFlags};use pinocchio::Address;// Create and set flags using individual methodslet mut flags = MemberFlags::new();flags.set(MemberFlags::AUTHORITY);flags.set(MemberFlags::TX_LOGS);flags.set(MemberFlags::TX_BALANCES);// Create a member with flagslet member = Member { flags, pubkey: user_address,};// Remove a flagflags.remove(MemberFlags::TX_LOGS);// Create flags from individual boolean valueslet flags = MemberFlags::from_acl_flags( true, // authority true, // tx_logs false, // tx_balances true, // tx_message false, // account_signatures);// Convert flags to byte valuelet flag_byte = flags.to_acl_flag_byte();// Create flags from byte valuelet flags = MemberFlags::from_acl_flag_byte(flag_byte);
import { PublicKey } from "@solana/web3.js";import { AUTHORITY_FLAG, TX_LOGS_FLAG, TX_BALANCES_FLAG, TX_MESSAGE_FLAG, ACCOUNT_SIGNATURES_FLAG, type Member,} from "@magicblock-labs/ephemeral-rollups-sdk";// Set flags by combining them with bitwise ORconst flags = AUTHORITY_FLAG | TX_LOGS_FLAG;// Create a member with combined flagsconst member: Member = { flags, pubkey: new PublicKey(userAddress),};// Check if a flag is present using bitwise ANDconst isAuthority = (member.flags & AUTHORITY_FLAG) !== 0;const canSeeLogs = (member.flags & TX_LOGS_FLAG) !== 0;const canSeeBalances = (member.flags & TX_BALANCES_FLAG) !== 0;// Add a flag to existing flagsconst updatedFlags = member.flags | TX_BALANCES_FLAG;// Remove a flag from existing flagsconst removedFlags = member.flags & ~TX_LOGS_FLAG;
import { AUTHORITY_FLAG, TX_LOGS_FLAG, TX_BALANCES_FLAG, TX_MESSAGE_FLAG, ACCOUNT_SIGNATURES_FLAG, isAuthority, canSeeTxLogs, canSeeTxBalances, canSeeTxMessages, canSeeAccountSignatures, type Member,} from "@magicblock-labs/ephemeral-rollups-sdk";// Set flags by combining them with bitwise ORconst flags = AUTHORITY_FLAG | TX_LOGS_FLAG | TX_BALANCES_FLAG;// Create a member with combined flagsconst member: Member = { flags, pubkey: userAddress,};// Use helper functions to check specific permissionsconst canModifyPermission = isAuthority(member, userAddress);const canViewLogs = canSeeTxLogs(member, userAddress);const canViewBalances = canSeeTxBalances(member, userAddress);const canViewMessages = canSeeTxMessages(member, userAddress);const canViewSignatures = canSeeAccountSignatures(member, userAddress);// Add a flag to existing memberconst updatedFlags = member.flags | TX_MESSAGE_FLAG;// Remove a flag from existing memberconst removedFlags = member.flags & ~TX_LOGS_FLAG;
use ephemeral_rollups_sdk::access_control::{ instructions::CreateEphemeralPermissionCpi, structs::{EphemeralMembersArgs, Member},};// Counter PDA pays for its own permission rent (it carries lamports onto the ER// after delegation and signs as PDA via seeds).let signers = [ COUNTER_SEED, ctx.accounts.counter.authority.as_ref(), &[ctx.bumps.counter],];CreateEphemeralPermissionCpi { payer: ctx.accounts.counter.to_account_info(), // pays ephemeral rent permissioned_account: ctx.accounts.counter.to_account_info(), // what the permission gates permission: ctx.accounts.permission.to_account_info(), vault: ctx.accounts.ephemeral_vault.to_account_info(), magic_program: ctx.accounts.magic_program.to_account_info(), permission_program: ctx.accounts.permission_program.to_account_info(), args: EphemeralMembersArgs { is_private: false, // start public — flip via UpdateEphemeralPermission members: vec![], },}.invoke_signed(&[&signers])?;
use ephemeral_rollups_sdk::access_control::{ instructions::CreateEphemeralPermissionCpi, structs::{EphemeralMembersArgs, Member},};// `permissioned_account` (here a counter PDA) signs as PDA via seeds; pass the// same seeds you used for `find_program_address` to derive it.let seeds: &[&[u8]] = &[ COUNTER_SEED, permissioned_account_authority.as_ref(), &[bump],];CreateEphemeralPermissionCpi { payer: &counter_account_info, // pays ephemeral rent permissioned_account: &counter_account_info, // what the permission gates permission: &permission_account_info, vault: &ephemeral_vault_account_info, magic_program: &magic_program_account_info, permission_program: &permission_program_account_info, args: EphemeralMembersArgs { is_private: false, // start public — flip via UpdateEphemeralPermission members: vec![], },}.invoke_signed(&[seeds])?;
use ephemeral_rollups_pinocchio::acl::{ CreateEphemeralPermission, EphemeralMembersArgs, Member,};use pinocchio::cpi::{Seed, Signer};// Buffer size: discriminator (8) + EphemeralMembersArgs body.// 64 bytes covers up to 1 member with slack for future Update calls.const PERMISSION_CPI_BUF: usize = 64;// PDA-signed CPI — the counter PDA pays rent and authorizes the permission.let bump_seed = [bump];let seeds_array: [Seed; 3] = [ Seed::from(b"counter"), Seed::from(authority.address().as_ref()), Seed::from(&bump_seed),];let signer = Signer::from(&seeds_array);let members: [Member; 0] = []; // start public; toggle via UpdateCreateEphemeralPermission { payer: counter_account, permissioned_account: counter_account, permission, vault, magic_program, permission_program, args: EphemeralMembersArgs { is_private: false, members: &members, },}.invoke_signed::<PERMISSION_CPI_BUF>(&[signer])?;
import { MAGIC_PROGRAM_ID, PERMISSION_PROGRAM_ID, EPHEMERAL_VAULT_ID,} from "@magicblock-labs/ephemeral-rollups-sdk";import { pipe, createTransactionMessage, appendTransactionMessageInstructions } from "@solana/kit";// EphemeralPermissions are created on the ER by the delegated PDA (via the// user-program's wrapper instruction). Submit to the ER connection, not base.const initIx = await counterProgram.methods .initPermission() .accountsPartial({ authority: tempKeypair.address, counter: counterPda, permission: permissionPda, permissionProgram: PERMISSION_PROGRAM_ID, ephemeralVault: EPHEMERAL_VAULT_ID, magicProgram: MAGIC_PROGRAM_ID, }) .instruction();const transactionMessage = pipe( createTransactionMessage({ version: 0 }), (tx) => appendTransactionMessageInstructions([initIx], tx),);const sig = await ephemeralConnection.sendAndConfirmTransaction( transactionMessage, [tempKeypair], { commitment: "confirmed" },);console.log("init_permission tx:", sig);
import { MAGIC_PROGRAM_ID, PERMISSION_PROGRAM_ID, EPHEMERAL_VAULT_ID,} from "@magicblock-labs/ephemeral-rollups-sdk";import { Transaction, sendAndConfirmTransaction } from "@solana/web3.js";// EphemeralPermissions are created on the ER by the delegated PDA (via the// user-program's wrapper instruction). Submit to the ER connection, not base.const initIx = await counterProgram.methods .initPermission() .accountsPartial({ authority: tempKeypair.publicKey, counter: counterPda, permission: permissionPda, permissionProgram: PERMISSION_PROGRAM_ID, ephemeralVault: EPHEMERAL_VAULT_ID, magicProgram: MAGIC_PROGRAM_ID, }) .instruction();const tx = new Transaction().add(initIx);const sig = await sendAndConfirmTransaction(ephemeralConnection, tx, [tempKeypair]);console.log("init_permission tx:", sig);