nara-sdk 1.0.40 → 1.0.41
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/index.ts +1 -0
- package/package.json +1 -1
- package/src/zkid.ts +93 -1
package/index.ts
CHANGED
package/package.json
CHANGED
package/src/zkid.ts
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* - Ownership can be transferred via ZK proof without revealing the owner's wallet
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
-
import { Connection, Keypair, PublicKey } from "@solana/web3.js";
|
|
10
|
+
import { Connection, Keypair, PublicKey, TransactionInstruction } from "@solana/web3.js";
|
|
11
11
|
import * as anchor from "@coral-xyz/anchor";
|
|
12
12
|
import { Program, AnchorProvider, Wallet } from "@coral-xyz/anchor";
|
|
13
13
|
import { buildPoseidon as _buildPoseidon } from "circomlibjs";
|
|
@@ -542,6 +542,98 @@ export async function withdraw(
|
|
|
542
542
|
.rpc();
|
|
543
543
|
}
|
|
544
544
|
|
|
545
|
+
/**
|
|
546
|
+
* Build a withdraw instruction without executing it.
|
|
547
|
+
* Useful for composing into an existing transaction.
|
|
548
|
+
*
|
|
549
|
+
* Same ZK proof generation as withdraw(), but returns a TransactionInstruction
|
|
550
|
+
* instead of sending the transaction.
|
|
551
|
+
*
|
|
552
|
+
* @param authority - The payer/signer public key (does not need Keypair since we don't sign)
|
|
553
|
+
* @param depositInfo - From scanClaimableDeposits()
|
|
554
|
+
* @param recipient - Destination address. Must satisfy isValidRecipient().
|
|
555
|
+
*/
|
|
556
|
+
export async function makeWithdrawIx(
|
|
557
|
+
connection: Connection,
|
|
558
|
+
authority: PublicKey,
|
|
559
|
+
name: string,
|
|
560
|
+
idSecret: bigint,
|
|
561
|
+
depositInfo: ClaimableDeposit,
|
|
562
|
+
recipient: PublicKey,
|
|
563
|
+
options?: ZkIdOptions
|
|
564
|
+
): Promise<TransactionInstruction> {
|
|
565
|
+
if (!isValidRecipient(recipient)) {
|
|
566
|
+
throw new Error(
|
|
567
|
+
"Recipient pubkey is >= BN254 field prime. Use generateValidRecipient() to get a compatible address."
|
|
568
|
+
);
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
const program = createReadProgram(connection, options?.programId);
|
|
572
|
+
const programId = new PublicKey(options?.programId ?? DEFAULT_ZKID_PROGRAM_ID);
|
|
573
|
+
const denominationBN = new BN(depositInfo.denomination.toString());
|
|
574
|
+
|
|
575
|
+
// Fetch Merkle tree state
|
|
576
|
+
const [treePda] = PublicKey.findProgramAddressSync(
|
|
577
|
+
[new TextEncoder().encode("tree"), denomBuf(denominationBN)],
|
|
578
|
+
programId
|
|
579
|
+
);
|
|
580
|
+
const treeData = await program.account.merkleTreeAccount.fetch(treePda);
|
|
581
|
+
|
|
582
|
+
const rootIdx: number = treeData.currentRootIndex;
|
|
583
|
+
const root = new Uint8Array((treeData.roots as number[][])[rootIdx]!);
|
|
584
|
+
const filledSubtrees = (treeData.filledSubtrees as number[][]).map(s =>
|
|
585
|
+
new Uint8Array(s)
|
|
586
|
+
);
|
|
587
|
+
const zeros = (treeData.zeros as number[][]).map(z =>
|
|
588
|
+
bytes32ToBigInt(new Uint8Array(z))
|
|
589
|
+
);
|
|
590
|
+
|
|
591
|
+
const { pathElements, pathIndices } = await buildMerklePath(
|
|
592
|
+
depositInfo.leafIndex,
|
|
593
|
+
filledSubtrees,
|
|
594
|
+
zeros
|
|
595
|
+
);
|
|
596
|
+
|
|
597
|
+
const nullifier = await poseidonHash([idSecret, BigInt(depositInfo.depositIndex)]);
|
|
598
|
+
const nullifierHashBuf = bigIntToBytes32BE(nullifier);
|
|
599
|
+
const recipientField = bytes32ToBigInt(recipient.toBytes());
|
|
600
|
+
|
|
601
|
+
const input = {
|
|
602
|
+
idSecret: idSecret.toString(),
|
|
603
|
+
depositIndex: depositInfo.depositIndex.toString(),
|
|
604
|
+
pathElements: pathElements.map(e => e.toString()),
|
|
605
|
+
pathIndices: pathIndices.map(i => i.toString()),
|
|
606
|
+
root: bytes32ToBigInt(root).toString(),
|
|
607
|
+
nullifierHash: nullifier.toString(),
|
|
608
|
+
recipient: recipientField.toString(),
|
|
609
|
+
};
|
|
610
|
+
|
|
611
|
+
let wasmSource = options?.withdrawWasm;
|
|
612
|
+
let zkeySource = options?.withdrawZkey;
|
|
613
|
+
if (!wasmSource || !zkeySource) {
|
|
614
|
+
const defaults = await resolveDefaultZkPaths();
|
|
615
|
+
wasmSource ??= defaults.withdrawWasm;
|
|
616
|
+
zkeySource ??= defaults.withdrawZkey;
|
|
617
|
+
}
|
|
618
|
+
|
|
619
|
+
const { proof } = await silentProve(input, wasmSource, zkeySource);
|
|
620
|
+
const packedProof = packProof(proof);
|
|
621
|
+
|
|
622
|
+
return program.methods
|
|
623
|
+
.withdraw(
|
|
624
|
+
Buffer.from(packedProof) as any,
|
|
625
|
+
toBytes32(root),
|
|
626
|
+
toBytes32(nullifierHashBuf),
|
|
627
|
+
recipient,
|
|
628
|
+
denominationBN
|
|
629
|
+
)
|
|
630
|
+
.accounts({
|
|
631
|
+
payer: authority,
|
|
632
|
+
recipient,
|
|
633
|
+
} as any)
|
|
634
|
+
.instruction();
|
|
635
|
+
}
|
|
636
|
+
|
|
545
637
|
/**
|
|
546
638
|
* Transfer ZK ID ownership to a new identity.
|
|
547
639
|
*
|