Skip to content

feat: Privy wallet integration (Node.js + React)#24

Merged
tilo-14 merged 15 commits intomainfrom
add-privy
Feb 15, 2026
Merged

feat: Privy wallet integration (Node.js + React)#24
tilo-14 merged 15 commits intomainfrom
add-privy

Conversation

@tilo-14
Copy link
Contributor

@tilo-14 tilo-14 commented Feb 15, 2026

Summary

  • Node.js scripts (privy/nodejs/): Server-side Privy wallet signing for transfer, wrap, unwrap, load, balances, and transaction history — all targeting devnet
  • React app (privy/react/): Browser-based embedded wallet with hooks for light-token operations (transfer, wrap, unwrap, balances, history) + unit tests
  • Setup scripts (privy/scripts/): Mint creation, SPL minting, and SPL interface registration using local keypair

Details

  • Privy server wallet signing pattern: build tx → serialize unsigned → Privy API sign → send raw
  • React hooks use @lightprotocol/compressed-token/unified subpath for SDK actions
  • Multi-mint balance queries across hot (ATA), cold (compressed), and SPL/T22 accounts
  • Tested end-to-end on devnet with Privy server wallet

Test plan

  • Node.js transfer, wrap, unwrap verified on devnet
  • React transfer verified on devnet
  • React wrap/unwrap testing (removed from TransferForm, send-only for now)

Open with Devin

tilo-14 added 8 commits February 11, 2026 13:45
Server-side (nodejs) and client-side (react) Privy wallet examples
for light-token transfers, wrap, unwrap, load, and balances.

Restructured privy/ layout:
- nodejs/: server wallet signing via @privy-io/node
- react/: embedded wallet signing via @privy-io/react-auth
- scripts/: setup helpers (mint creation, SPL interface registration)

Transfer creates destination associated token account idempotently
before transferring.
React hooks (useTransfer, useUnwrap) now call high-level SDK functions
(createTransferInterfaceInstructions, createUnwrapInstructions) instead
of manually assembling instructions. Shared signAndSendBatches helper
handles multi-tx flows from batched instruction arrays.

Balance hooks (react + nodejs) refactored to per-mint accumulator
pattern that queries all mints in one pass instead of single-mint.
TokenBalance now exposes hot/cold/spl/t22/unified breakdown.

Other changes:
- useWrap: imports from /unified subpath, uses idempotent ATA create
- unwrap (nodejs + react): auto-detect token program from mint owner
- mint-light-token script: --spl flag for SPL token program mints
- mint-spl script: auto-detect token program from mint account
- Remove standalone load.ts (load is handled by transfer/unwrap SDK)
Remove hidden wrap-then-transfer flow from Send button.
Add explicit Unify button for wrapping SPL/T22 into unified balance.
Send only enabled when unified balance > 0.
devin-ai-integration[bot]

This comment was marked as resolved.

Copy link
Contributor

@devin-ai-integration devin-ai-integration bot left a comment

Choose a reason for hiding this comment

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

Devin Review found 1 new potential issue.

View 14 additional findings in Devin Review.

Open in Devin Review

Comment on lines +7 to +8
"mint:spl-and-wrap": "tsx src/mint-spl-and-wrap.ts",
"mint:spl-and-wrap:spl": "tsx src/mint-spl-and-wrap.ts --spl",
Copy link
Contributor

Choose a reason for hiding this comment

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

🔴 Setup scripts reference non-existent file mint-light-token.ts

The privy/scripts/package.json scripts mint:light-token and mint:light-token:spl reference tsx src/mint-light-token.ts, but this file does not exist. The actual file created in this PR is privy/scripts/src/mint-spl-and-wrap.ts, which implements the intended functionality (create mint, mint tokens, wrap, and transfer). Running npm run mint:light-token will fail immediately with a file-not-found error.

Root Cause

The file was likely renamed from mint-light-token.ts to mint-spl-and-wrap.ts during development, but the package.json script references were not updated to match.

The scripts at privy/scripts/package.json:7-8 point to:

"mint:light-token": "tsx src/mint-light-token.ts",
"mint:light-token:spl": "tsx src/mint-light-token.ts --spl",

But only privy/scripts/src/mint-spl-and-wrap.ts exists. The README and quick-start guides for both the Node.js and React examples instruct users to run npm run mint:light-token as the first setup step, so this breaks the entire onboarding flow.

Impact: Both npm run mint:light-token and npm run mint:light-token:spl are completely broken. Users cannot create test mints, which is the prerequisite for all other operations.

Suggested change
"mint:spl-and-wrap": "tsx src/mint-spl-and-wrap.ts",
"mint:spl-and-wrap:spl": "tsx src/mint-spl-and-wrap.ts --spl",
"mint:light-token": "tsx src/mint-spl-and-wrap.ts",
"mint:light-token:spl": "tsx src/mint-spl-and-wrap.ts --spl",
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

@tilo-14 tilo-14 merged commit d87ce0a into main Feb 15, 2026
18 checks passed
@tilo-14 tilo-14 deleted the add-privy branch February 15, 2026 23:53
Copy link
Contributor

@devin-ai-integration devin-ai-integration bot left a comment

Choose a reason for hiding this comment

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

Devin Review found 1 new potential issue.

View 12 additional findings in Devin Review.

Open in Devin Review

Comment on lines +87 to +90
return rpc.sendRawTransaction(signedTxBuffer, {
skipPreflight: false,
preflightCommitment: 'confirmed',
});
Copy link
Contributor

Choose a reason for hiding this comment

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

🟡 useWrap missing confirmTransaction — returns signature for potentially unconfirmed transaction

The useWrap hook sends the signed transaction via sendRawTransaction and immediately returns the resulting signature without calling confirmTransaction. This is inconsistent with every other signing path in the codebase.

Root cause and impact

Compare useWrap.ts:87-90 which returns the sendRawTransaction promise directly:

const signedTxBuffer = Buffer.from(signedTx.signedTransaction);
return rpc.sendRawTransaction(signedTxBuffer, {
  skipPreflight: false,
  preflightCommitment: 'confirmed',
});

…with the shared signAndSendBatches.ts:35-39 used by useTransfer and useUnwrap:

const sig = await rpc.sendRawTransaction(signedTxBuffer, { ... });
await rpc.confirmTransaction(sig, 'confirmed');

…and the Node.js equivalent at privy/nodejs/src/wrap.ts:75-79:

await connection.confirmTransaction(signature, 'confirmed');

Impact: When useWrap returns, the transaction may still be pending or may ultimately fail on-chain. Any caller (like handleTransferSuccess in privy/react/src/App.tsx:52-56) that immediately refreshes balances via fetchBalances will read stale data because the wrap hasn't been confirmed yet. The UI would show "Success" with unchanged balances.

Suggested change
return rpc.sendRawTransaction(signedTxBuffer, {
skipPreflight: false,
preflightCommitment: 'confirmed',
});
const signedTxBuffer = Buffer.from(signedTx.signedTransaction);
const signature = await rpc.sendRawTransaction(signedTxBuffer, {
skipPreflight: false,
preflightCommitment: 'confirmed',
});
await rpc.confirmTransaction(signature, 'confirmed');
return signature;
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

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.

1 participant