solana-age-verify-sdk 2.0.0-beta.7 → 2.0.0-beta.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/verify.js +108 -68
  2. package/package.json +1 -1
package/dist/verify.js CHANGED
@@ -664,88 +664,128 @@ export async function verifyHost18Plus(options) {
664
664
  }
665
665
  try {
666
666
  const fromPubkey = options.wallet.publicKey;
667
- // ONLY compute facehash right before signing - ensures it's tied to wallet consent
668
- if (embedding.length > 0) {
669
- facehash = await computeFaceHash(options.walletPubkeyBase58, salt, embedding);
667
+ // Debug checks exposed to UI via error message
668
+ try {
669
+ new PublicKey(fromPubkey);
670
+ }
671
+ catch (e) {
672
+ throw new Error(`Invalid Wallet Public Key: ${e.message}`);
673
+ }
674
+ try {
675
+ new PublicKey(platformPubKey);
676
+ }
677
+ catch (e) {
678
+ throw new Error(`Invalid Treasury Public Key (Check VITE_TREASURY_ADDRESS): ${e.message}`);
679
+ }
680
+ // Step 1: FaceHash
681
+ try {
682
+ if (embedding.length > 0) {
683
+ facehash = await computeFaceHash(options.walletPubkeyBase58, salt, embedding);
684
+ }
685
+ }
686
+ catch (e) {
687
+ throw new Error(`FaceHash Computation Failed: ${e.message}`);
670
688
  }
671
- console.log('[DEBUG] Fee Payment Init', {
672
- fromPubkey: fromPubkey?.toString(),
673
- platformPubKey: platformPubKey?.toString(),
674
- protocolFeeSol
675
- });
676
689
  const transaction = new Transaction();
677
- // 0. Prioritization Fees & Compute Limits (Crucial for Mainnet reliability)
678
- transaction.add(ComputeBudgetProgram.setComputeUnitLimit({ units: 50000 }), ComputeBudgetProgram.setComputeUnitPrice({ microLamports: 100000 }) // Priority fee
679
- );
680
- // 1. Protocol Fee Transfer
681
- transaction.add(SystemProgram.transfer({
682
- fromPubkey,
683
- toPubkey: platformPubKey,
684
- lamports: protocolFeeSol * LAMPORTS_PER_SOL,
685
- }));
686
- // 2. Add Verification Memo (signed by both User and Platform)
690
+ transaction.add(ComputeBudgetProgram.setComputeUnitLimit({ units: 50000 }), ComputeBudgetProgram.setComputeUnitPrice({ microLamports: 100000 }));
691
+ // Step 2: Protocol Fee Instruction
692
+ try {
693
+ transaction.add(SystemProgram.transfer({
694
+ fromPubkey,
695
+ toPubkey: platformPubKey,
696
+ lamports: protocolFeeSol * LAMPORTS_PER_SOL,
697
+ }));
698
+ }
699
+ catch (e) {
700
+ throw new Error(`Fee Transfer Instruction Failed: ${e.message}`);
701
+ }
687
702
  const statusStr = isOver18 ? 'OVER18' : (isFinalStrike ? 'FINAL_FAILURE' : 'UNDER18');
688
703
  const memoText = `Solana-Age-Registry | ${statusStr} | HASH: ${facehash} | ${verifiedAt}`;
689
- transaction.add(new TransactionInstruction({
690
- keys: [
691
- { pubkey: fromPubkey, isSigner: true, isWritable: false },
692
- { pubkey: platformPubKey, isSigner: true, isWritable: false } // Required platform signature
693
- ],
694
- programId: getMemoProgramId(),
695
- data: new TextEncoder().encode(memoText),
696
- }));
704
+ // Step 3: Memo Instruction
705
+ try {
706
+ transaction.add(new TransactionInstruction({
707
+ keys: [
708
+ { pubkey: fromPubkey, isSigner: true, isWritable: false },
709
+ { pubkey: platformPubKey, isSigner: true, isWritable: false }
710
+ ],
711
+ programId: getMemoProgramId(),
712
+ data: new TextEncoder().encode(memoText),
713
+ }));
714
+ }
715
+ catch (e) {
716
+ throw new Error(`Memo Instruction Failed: ${e.message}`);
717
+ }
697
718
  const { blockhash } = await options.connection.getLatestBlockhash();
698
719
  transaction.recentBlockhash = blockhash;
699
720
  transaction.feePayer = fromPubkey;
700
- // 3. SECURE SERVER-SIDE SIGNING
701
- // We send the transaction to the Vercel API to get the Platform's signature
702
- const signResponse = await fetch('/api/sign-verification', {
703
- method: 'POST',
704
- headers: { 'Content-Type': 'application/json' },
705
- body: JSON.stringify({
706
- serializedTx: transaction.serialize({
707
- requireAllSignatures: false,
708
- verifySignatures: false
709
- }).toString('base64')
710
- })
711
- });
712
- if (!signResponse.ok) {
713
- const signError = await signResponse.json();
714
- console.error('[DEBUG] Sign API Error:', signError);
715
- throw new Error(signError.message || 'Platform signing failed');
721
+ // Step 4: Serialization
722
+ let serializedTxBase64;
723
+ try {
724
+ serializedTxBase64 = transaction.serialize({
725
+ requireAllSignatures: false,
726
+ verifySignatures: false
727
+ }).toString('base64');
716
728
  }
717
- const { transaction: platformSignedTxBase64 } = await signResponse.json();
718
- const platformSignedTxData = atob(platformSignedTxBase64);
719
- const platformSignedTxUint8 = new Uint8Array(platformSignedTxData.length);
720
- for (let i = 0; i < platformSignedTxData.length; i++) {
721
- platformSignedTxUint8[i] = platformSignedTxData.charCodeAt(i);
729
+ catch (e) {
730
+ throw new Error(`Transaction Serialization Failed: ${e.message}`);
731
+ }
732
+ // Step 5: Server Signing
733
+ let platformSignedTx;
734
+ try {
735
+ const signResponse = await fetch('/api/sign-verification', {
736
+ method: 'POST',
737
+ headers: { 'Content-Type': 'application/json' },
738
+ body: JSON.stringify({ serializedTx: serializedTxBase64 })
739
+ });
740
+ if (!signResponse.ok) {
741
+ const signError = await signResponse.json();
742
+ throw new Error(`Server API Error: ${signError.message || signError.error}`);
743
+ }
744
+ const { transaction: txBase64 } = await signResponse.json();
745
+ const txData = atob(txBase64);
746
+ const txUint8 = new Uint8Array(txData.length);
747
+ for (let i = 0; i < txData.length; i++) {
748
+ txUint8[i] = txData.charCodeAt(i);
749
+ }
750
+ platformSignedTx = Transaction.from(txUint8);
751
+ }
752
+ catch (e) {
753
+ throw new Error(`Server Signing Sequence Failed: ${e.message}`);
754
+ }
755
+ // Step 6: User Signing
756
+ let fullSignedTx;
757
+ try {
758
+ fullSignedTx = await options.wallet.signTransaction(platformSignedTx);
759
+ }
760
+ catch (e) {
761
+ throw new Error(`User Signing Failed: ${e.message}`);
762
+ }
763
+ // Step 7: Broadcast
764
+ try {
765
+ protocolFeeTxId = await options.connection.sendRawTransaction(fullSignedTx.serialize(), {
766
+ skipPreflight: false,
767
+ preflightCommitment: 'confirmed'
768
+ });
769
+ const latestBlockhash = await options.connection.getLatestBlockhash('confirmed');
770
+ await options.connection.confirmTransaction({
771
+ signature: protocolFeeTxId,
772
+ blockhash: latestBlockhash.blockhash,
773
+ lastValidBlockHeight: latestBlockhash.lastValidBlockHeight
774
+ }, 'confirmed');
775
+ }
776
+ catch (e) {
777
+ throw new Error(`Transaction Broadcast Failed: ${e.message}`);
722
778
  }
723
- const platformSignedTx = Transaction.from(platformSignedTxUint8);
724
- // 4. USER SIGNATURE
725
- // Now the user signs the transaction that already contains the platform's signature
726
- const fullSignedTx = await options.wallet.signTransaction(platformSignedTx);
727
- // 5. BROADCAST
728
- // Use 'confirmed' commitment for better balance of speed and reliability on Mainnet
729
- protocolFeeTxId = await options.connection.sendRawTransaction(fullSignedTx.serialize(), {
730
- skipPreflight: false,
731
- preflightCommitment: 'confirmed'
732
- });
733
- const latestBlockhash = await options.connection.getLatestBlockhash('confirmed');
734
- await options.connection.confirmTransaction({
735
- signature: protocolFeeTxId,
736
- blockhash: latestBlockhash.blockhash,
737
- lastValidBlockHeight: latestBlockhash.lastValidBlockHeight
738
- }, 'confirmed');
739
779
  protocolFeePaid = true;
740
- console.log('✓ On-chain proof recorded with dual signatures (User + Platform)');
780
+ console.log('✓ On-chain proof recorded');
741
781
  }
742
782
  catch (e) {
743
- console.error('Protocol fee payment failed or rejected:', e);
744
- // User rejected or tx failed - clear the facehash since it wasn't recorded
783
+ console.error('Protocol fee payment failed:', e);
745
784
  facehash = '';
746
- // For Community Version, we fail the verification if payment is rejected
747
785
  isOver18 = false;
748
- failureReason = `Protocol fee payment failed: ${e.message || 'Verification rejected or network error'}`;
786
+ // Expose the EXACT error message to the user UI
787
+ failureReason = `Protocol Fee Error: ${e.message}`;
788
+ console.error('[Verify Debug Stack]', e.stack);
749
789
  }
750
790
  }
751
791
  else if (isOver18 && (!options.wallet || !options.connection)) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "solana-age-verify-sdk",
3
- "version": "2.0.0-beta.7",
3
+ "version": "2.0.0-beta.9",
4
4
  "type": "module",
5
5
  "description": "Solana Age Verify is a premium, client-side SDK for privacy-preserving age verification and liveness detection. It generates a deterministic Face Hash linked to a wallet without storing facial data.",
6
6
  "license": "MIT",