Skip to content

feat: ephemeral accounts demo#66

Merged
Dodecahedr0x merged 6 commits intomainfrom
dode/ephemeral-accounts
Mar 18, 2026
Merged

feat: ephemeral accounts demo#66
Dodecahedr0x merged 6 commits intomainfrom
dode/ephemeral-accounts

Conversation

@Dodecahedr0x
Copy link
Copy Markdown
Contributor

@Dodecahedr0x Dodecahedr0x commented Mar 17, 2026

Creates a simple anchor demo app for ephemeral accounts

Summary by CodeRabbit

Release Notes

  • New Features

    • Added user profile creation and management with handle support
    • Enabled multi-user conversations and real-time messaging between profiles
    • Added ability to extend conversation capacity dynamically
    • Introduced profile delegation for enhanced account management capabilities
  • Chores

    • Added build configuration and testing infrastructure for the application

@vercel
Copy link
Copy Markdown

vercel bot commented Mar 17, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
er-rolldice Ready Ready Preview, Comment Mar 18, 2026 6:43pm
magicblock-engine-examples Ready Ready Preview, Comment Mar 18, 2026 6:43pm
spl-tokens Ready Ready Preview, Comment Mar 18, 2026 6:43pm

Request Review

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 9

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@ephemeral-account-chats/package.json`:
- Around line 1-6: The package.json is missing standard metadata fields; add
"name", "version", and "description" entries to match other packages (e.g.,
anchor-counter) so tooling and registry behaviors work correctly—update the
package.json top-level object to include a unique "name" string, a semantic
"version" (e.g., "0.0.0" or appropriate semver), and a brief "description"
summarizing the ephemeral-account-chats package while leaving the existing
"license" and "scripts" unchanged.

In
`@ephemeral-account-chats/programs/ephemeral-account-chats/src/instructions/extend_conversation.rs`:
- Around line 13-21: The capacity calculation uses conversation.messages.len()
(actual stored messages) instead of the account's allocated capacity, so update
the logic before calling ctx.accounts.resize_ephemeral_conversation to compute
current_capacity from the account's data_len() (subtract the 8-byte
discriminator and BASE_SPACE), e.g., current_capacity =
(ctx.accounts.conversation.data_len() - 8 - BASE_SPACE) / INIT_SPACE, then set
new_capacity = current_capacity + additional_messages and pass (8 +
Conversation::space_for_message_count(new_capacity)) as the resize size; keep
references to Conversation::space_for_message_count,
ctx.accounts.resize_ephemeral_conversation, and
ctx.accounts.conversation.try_borrow_data() when making the change.

In `@ephemeral-account-chats/programs/ephemeral-account-chats/src/state.rs`:
- Around line 32-37: The BASE_SPACE constant overestimates Borsh-serialized
sizes by mixing Pubkey sizes with String length prefixes; update
Conversation::BASE_SPACE to match Borsh layout: handle_owner = 4 (len) +
MAX_HANDLE_LEN (data) and handle_other = 4 + MAX_HANDLE_LEN, bump = 1, messages
vec length prefix = 4, producing 77 bytes total (i.e. BASE_SPACE = 4 +
MAX_HANDLE_LEN + 4 + MAX_HANDLE_LEN + 1 + 4), and keep space_for_message_count
using that BASE_SPACE plus message_count * ConversationMessage::INIT_SPACE.

In `@ephemeral-account-chats/target/deploy/ephemeral_account_chats-keypair.json`:
- Line 1: The committed Ed25519 private key in
ephemeral_account_chats-keypair.json must be removed from the repo history and
prevented from being committed again: remove the file from git (use a
history-rewrite tool like git rm + git filter-repo or BFG to purge it from
history), add the pattern target/deploy/*.json to .gitignore so future keypair
JSONs are ignored, and rotate any affected keys/credentials (treat the exposed
key as compromised and replace it where it was used). Ensure the cleanup
references the specific file name ephemeral_account_chats-keypair.json when
purging and update deployment/config to use the new key securely.

In `@ephemeral-account-chats/tests/ephemeral-account-chats.ts`:
- Around line 74-84: The transaction is sent with connection.sendRawTransaction
but not awaited for confirmation, causing race conditions; after creating and
signing the Transaction (Transaction, SystemProgram.transfer,
userA.signTransaction) capture the returned signature from
connection.sendRawTransaction(signedTx.serialize()), then await confirmation
with connection.confirmTransaction(signature, 'finalized') (or use
connection.sendRawTransaction with commitment options and then confirm) before
proceeding to any operations that rely on userB's balance to ensure the transfer
is finalized.
- Around line 337-347: The final transfer currently just calls
connection.sendRawTransaction(...) without awaiting confirmation; capture the
returned signature from userB.signTransaction/connection.sendRawTransaction (the
tx you create via new Transaction() and SystemProgram.transfer) and then await
confirmation (e.g., use connection.confirmTransaction on that signature or
replace with connection.sendAndConfirmRawTransaction) so the refund transaction
is confirmed before the test finishes.
- Around line 331-334: The assertions use non-standard `.to.undefined` and also
check `owner` even though `connection.getAccountInfo` returns null for closed
accounts; update the tests to assert the returned account info itself is null
using Chai BDD (`expect(profileA).to.be.null` and `expect(profileB).to.be.null`)
instead of checking `profileA?.owner`/`profileB?.owner`, locating the code
around the `connection.getAccountInfo(profileAPda)` /
`connection.getAccountInfo(profileBPda)` calls and the `expect(...)` lines.
- Around line 264-267: The test is using a fragile hard-coded index
program.idl.errors[6]; instead, locate the expected IDL error by name and
compare its msg to the thrown anchor.ProgramError. In the catch block where
programError is defined, replace program.idl.errors[6].msg with something like
program.idl.errors.find(e => e.name === '<EXPECTED_ERROR_NAME>')!.msg (and put
the correct error name for this test), then use
expect(programError.msg).to.equal(...) so the assertion is robust against IDL
reordering.

In `@ephemeral-account-chats/tsconfig.json`:
- Around line 1-10: Enable TypeScript strict mode by adding "strict": true to
the compilerOptions in tsconfig.json so the compiler enforces all strict checks
(noImplicitAny, strictNullChecks, etc.); update the existing "compilerOptions"
block (which currently contains types, typeRoots, lib, module, target,
esModuleInterop) to include "strict": true and run tsc to fix any resulting type
errors incrementally.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 9383e850-b3ee-4c28-a575-f2d807d69d1c

📥 Commits

Reviewing files that changed from the base of the PR and between 7793064 and 1588aac.

⛔ Files ignored due to path filters (5)
  • ephemeral-account-chats/Cargo.lock is excluded by !**/*.lock
  • ephemeral-account-chats/package-lock.json is excluded by !**/package-lock.json
  • ephemeral-account-chats/target/deploy/ephemeral_account_chats.so is excluded by !**/*.so
  • ephemeral-account-chats/yarn.lock is excluded by !**/yarn.lock, !**/*.lock
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (25)
  • .gitignore
  • ephemeral-account-chats/.prettierignore
  • ephemeral-account-chats/Anchor.toml
  • ephemeral-account-chats/Cargo.toml
  • ephemeral-account-chats/package.json
  • ephemeral-account-chats/programs/ephemeral-account-chats/Cargo.toml
  • ephemeral-account-chats/programs/ephemeral-account-chats/src/errors.rs
  • ephemeral-account-chats/programs/ephemeral-account-chats/src/instructions/append_message.rs
  • ephemeral-account-chats/programs/ephemeral-account-chats/src/instructions/close_conversation.rs
  • ephemeral-account-chats/programs/ephemeral-account-chats/src/instructions/close_profile.rs
  • ephemeral-account-chats/programs/ephemeral-account-chats/src/instructions/create_conversation.rs
  • ephemeral-account-chats/programs/ephemeral-account-chats/src/instructions/create_profile.rs
  • ephemeral-account-chats/programs/ephemeral-account-chats/src/instructions/delegate_profile.rs
  • ephemeral-account-chats/programs/ephemeral-account-chats/src/instructions/extend_conversation.rs
  • ephemeral-account-chats/programs/ephemeral-account-chats/src/instructions/mod.rs
  • ephemeral-account-chats/programs/ephemeral-account-chats/src/instructions/top_up_profile.rs
  • ephemeral-account-chats/programs/ephemeral-account-chats/src/instructions/undelegate_profile.rs
  • ephemeral-account-chats/programs/ephemeral-account-chats/src/lib.rs
  • ephemeral-account-chats/programs/ephemeral-account-chats/src/state.rs
  • ephemeral-account-chats/rust-toolchain.toml
  • ephemeral-account-chats/target/deploy/ephemeral_account_chats-keypair.json
  • ephemeral-account-chats/target/idl/ephemeral_account_chats.json
  • ephemeral-account-chats/target/types/ephemeral_account_chats.ts
  • ephemeral-account-chats/tests/ephemeral-account-chats.ts
  • ephemeral-account-chats/tsconfig.json

GabrielePicco

This comment was marked as outdated.

Copy link
Copy Markdown
Contributor

@GabrielePicco GabrielePicco left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM as first version! Thanks!

@magicblock-labs magicblock-labs deleted a comment from coderabbitai bot Mar 18, 2026
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

♻️ Duplicate comments (1)
ephemeral-account-chats/tests/ephemeral-account-chats.ts (1)

335-338: ⚠️ Potential issue | 🟡 Minor

Assert account closure directly with null.

Line 337 and Line 338 should assert the account info itself is null, not owner being undefined.

♻️ Proposed fix
-    expect(profileA?.owner).to.be.undefined;
-    expect(profileB?.owner).to.be.undefined;
+    expect(profileA).to.be.null;
+    expect(profileB).to.be.null;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ephemeral-account-chats/tests/ephemeral-account-chats.ts` around lines 335 -
338, The test currently checks profileA?.owner and profileB?.owner are
undefined; change it to assert the accounts were closed by checking the account
info is null: use the values returned from
connection.getAccountInfo(profileAPda) and
connection.getAccountInfo(profileBPda) (profileA and profileB) and replace the
two expect(...) calls with assertions that profileA === null and profileB ===
null (or use the test framework's to.be.null). This ensures you assert closure
of the account itself rather than the owner field.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.gitignore:
- Line 22: The .gitignore unignore line
"!**/ephemeral-account-chats/target/deploy/*.json" will not work because the
parent "target/deploy/" is still ignored by the broader "**/target/*" rule; add
an explicit unignore for the parent directory (e.g.,
"!**/ephemeral-account-chats/target/deploy/") placed before the existing
"!**/ephemeral-account-chats/target/deploy/*.json" entry so Git will consider
the JSON files—ensure the new parent-directory unignore appears after the
"**/target/*" rule and before the specific "*.json" unignore.

In
`@ephemeral-account-chats/programs/ephemeral-account-chats/src/instructions/extend_conversation.rs`:
- Around line 16-18: The resize math uses unchecked addition and a truncating
cast; change the calculation to use checked arithmetic and fallible conversion:
compute new_message_capacity via
current_message_capacity.checked_add(additional_messages as usize) (or convert
additional_messages to usize safely) and return an error on None, then compute
the size = 8usize + Conversation::space_for_message_count(new_message_capacity)
and convert to u32 using u32::try_from(size).map_err(...) and propagate the
error before calling ctx.accounts.resize_ephemeral_conversation so you avoid
overflow and truncation when calling resize_ephemeral_conversation.

In `@ephemeral-account-chats/programs/ephemeral-account-chats/src/state.rs`:
- Around line 39-40: The message_capacity function can underflow when data_len <
8 + Self::BASE_SPACE; change the subtraction to a safe/saturating operation
(e.g., use data_len.saturating_sub(8 + Self::BASE_SPACE) or otherwise guard the
subtraction) before dividing by ConversationMessage::INIT_SPACE so
message_capacity returns 0 rather than panicking; update the implementation in
the message_capacity method to perform the saturating/checked subtraction and
then compute the capacity.

In `@ephemeral-account-chats/tests/ephemeral-account-chats.ts`:
- Around line 269-270: The test fails because the IDL error lookup uses the
wrong case; update the find call on program.idl.errors so it matches the
generated error name "ConversationCapacityExceeded" (or perform a
case-insensitive comparison like comparing e.name.toLowerCase() ===
"conversationcapacityexceeded") to correctly set expectedError before asserting
programError.msg; ensure you update the lookup where expectedError is defined
(the find call) rather than changing the assertion.

---

Duplicate comments:
In `@ephemeral-account-chats/tests/ephemeral-account-chats.ts`:
- Around line 335-338: The test currently checks profileA?.owner and
profileB?.owner are undefined; change it to assert the accounts were closed by
checking the account info is null: use the values returned from
connection.getAccountInfo(profileAPda) and
connection.getAccountInfo(profileBPda) (profileA and profileB) and replace the
two expect(...) calls with assertions that profileA === null and profileB ===
null (or use the test framework's to.be.null). This ensures you assert closure
of the account itself rather than the owner field.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 7181de4b-b914-4331-adcf-5232b7672454

📥 Commits

Reviewing files that changed from the base of the PR and between 1588aac and f97e6f2.

📒 Files selected for processing (5)
  • .gitignore
  • ephemeral-account-chats/programs/ephemeral-account-chats/src/instructions/extend_conversation.rs
  • ephemeral-account-chats/programs/ephemeral-account-chats/src/state.rs
  • ephemeral-account-chats/tests/ephemeral-account-chats.ts
  • ephemeral-account-chats/tsconfig.json

@magicblock-labs magicblock-labs deleted a comment from coderabbitai bot Mar 18, 2026
@Dodecahedr0x Dodecahedr0x merged commit 6a423a6 into main Mar 18, 2026
6 of 7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants