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.
- package/dist/verify.js +108 -68
- 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
|
-
//
|
|
668
|
-
|
|
669
|
-
|
|
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
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
}
|
|
686
|
-
|
|
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
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
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
|
-
//
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
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
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
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
|
|
780
|
+
console.log('✓ On-chain proof recorded');
|
|
741
781
|
}
|
|
742
782
|
catch (e) {
|
|
743
|
-
console.error('Protocol fee payment failed
|
|
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
|
-
|
|
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.
|
|
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",
|