@nullpay/mcp 1.0.4 → 1.0.6
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/aleo.js +49 -39
- package/dist/setup.js +6 -3
- package/package.json +1 -1
package/dist/aleo.js
CHANGED
|
@@ -24,7 +24,8 @@ const crypto_1 = __importDefault(require("crypto"));
|
|
|
24
24
|
const esm_1 = require("./esm");
|
|
25
25
|
const env_1 = require("./env");
|
|
26
26
|
exports.PROGRAM_ID = 'zk_pay_proofs_privacy_v22.aleo';
|
|
27
|
-
const
|
|
27
|
+
const USDCX_FREEZELIST_PROGRAM_ID = 'test_usdcx_freezelist.aleo';
|
|
28
|
+
const USAD_FREEZELIST_PROGRAM_ID = 'test_usad_freezelist.aleo';
|
|
28
29
|
const EXPLORER_BASE = 'https://api.explorer.provable.com/v1';
|
|
29
30
|
const MAPPING_BASE = 'https://api.provable.com/v2/testnet/program';
|
|
30
31
|
const SCANNER_BASE = 'https://api.provable.com/scanner/testnet';
|
|
@@ -548,43 +549,54 @@ async function findSpendableRecord(session, programFilter, recordName, amountReq
|
|
|
548
549
|
}
|
|
549
550
|
return null;
|
|
550
551
|
}
|
|
551
|
-
|
|
552
|
+
function getFreezeListProgramId(tokenProgram) {
|
|
553
|
+
if (tokenProgram === 'test_usdcx_stablecoin.aleo') {
|
|
554
|
+
return USDCX_FREEZELIST_PROGRAM_ID;
|
|
555
|
+
}
|
|
556
|
+
if (tokenProgram === 'test_usad_stablecoin.aleo') {
|
|
557
|
+
return USAD_FREEZELIST_PROGRAM_ID;
|
|
558
|
+
}
|
|
559
|
+
return null;
|
|
560
|
+
}
|
|
561
|
+
async function getFreezeListIndex(programId, index) {
|
|
552
562
|
const { AleoNetworkClient } = await (0, esm_1.dynamicImport)('@provablehq/sdk');
|
|
553
563
|
const client = new AleoNetworkClient(EXPLORER_BASE);
|
|
554
|
-
const value = await client.getProgramMappingValue(
|
|
564
|
+
const value = await client.getProgramMappingValue(programId, 'freeze_list_index', `${index}u32`);
|
|
555
565
|
return value ? value.replace(/"/g, '') : null;
|
|
556
566
|
}
|
|
557
|
-
async function
|
|
558
|
-
const
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
567
|
+
async function getFreezeListCount(programId) {
|
|
568
|
+
const response = await fetch(`${MAPPING_BASE}/${programId}/mapping/freeze_list_last_index/true`);
|
|
569
|
+
if (!response.ok) {
|
|
570
|
+
return 0;
|
|
571
|
+
}
|
|
572
|
+
const value = await response.json();
|
|
573
|
+
if (!value) {
|
|
574
|
+
return 0;
|
|
575
|
+
}
|
|
576
|
+
const parsed = Number.parseInt(String(value).replace(/u32|["']/g, ''), 10);
|
|
577
|
+
return Number.isFinite(parsed) ? parsed + 1 : 0;
|
|
578
|
+
}
|
|
579
|
+
async function generateFreezeListProof(ownerAddress, tokenProgram) {
|
|
580
|
+
const freezeListProgramId = getFreezeListProgramId(tokenProgram);
|
|
581
|
+
if (!freezeListProgramId) {
|
|
582
|
+
throw new Error(`Unsupported freeze list program for ${tokenProgram}`);
|
|
583
|
+
}
|
|
584
|
+
const { SealanceMerkleTree } = await (0, esm_1.dynamicImport)('@provablehq/sdk');
|
|
585
|
+
const count = Math.max(1, await getFreezeListCount(freezeListProgramId));
|
|
586
|
+
const addresses = [];
|
|
587
|
+
for (let index = 0; index < count; index += 1) {
|
|
588
|
+
const address = await getFreezeListIndex(freezeListProgramId, index);
|
|
589
|
+
if (address) {
|
|
590
|
+
addresses.push(address);
|
|
580
591
|
}
|
|
581
|
-
proofSiblings.push(siblingHash);
|
|
582
|
-
currentHash = isLeft
|
|
583
|
-
? hashFields([currentHash, siblingHash])
|
|
584
|
-
: hashFields([siblingHash, currentHash]);
|
|
585
|
-
currentIndex = Math.floor(currentIndex / 2);
|
|
586
592
|
}
|
|
587
|
-
|
|
593
|
+
const sealance = new SealanceMerkleTree();
|
|
594
|
+
const leaves = sealance.generateLeaves(addresses, 16);
|
|
595
|
+
const tree = sealance.buildTree(leaves);
|
|
596
|
+
const [leftIdx, rightIdx] = sealance.getLeafIndices(tree, ownerAddress);
|
|
597
|
+
const proofLeft = sealance.getSiblingPath(tree, leftIdx, 16);
|
|
598
|
+
const proofRight = sealance.getSiblingPath(tree, rightIdx, 16);
|
|
599
|
+
return sealance.formatMerkleProof([proofLeft, proofRight]);
|
|
588
600
|
}
|
|
589
601
|
async function createSponsoredPaymentAuthorization(args) {
|
|
590
602
|
const session = await getScannerSession(args.walletPrivateKey);
|
|
@@ -602,14 +614,12 @@ async function createSponsoredPaymentAuthorization(args) {
|
|
|
602
614
|
}
|
|
603
615
|
let proofsInput;
|
|
604
616
|
if (paymentMode.tokenProgram !== 'credits.aleo') {
|
|
605
|
-
const
|
|
606
|
-
|
|
607
|
-
if (
|
|
608
|
-
|
|
609
|
-
index0Field = Address.from_string(firstIndex).toGroup().toXCoordinate().toString();
|
|
617
|
+
const ownerMatch = record.match(/owner\s*:\s*([a-z0-9]+)/i);
|
|
618
|
+
const ownerAddress = ownerMatch?.[1];
|
|
619
|
+
if (!ownerAddress || !ownerAddress.startsWith('aleo')) {
|
|
620
|
+
throw new Error(`Failed to read token record owner for ${paymentMode.tokenProgram}.`);
|
|
610
621
|
}
|
|
611
|
-
|
|
612
|
-
proofsInput = `[${proof}, ${proof}]`;
|
|
622
|
+
proofsInput = await generateFreezeListProof(ownerAddress, paymentMode.tokenProgram);
|
|
613
623
|
}
|
|
614
624
|
const { AleoKeyProvider, AleoNetworkClient, NetworkRecordProvider, ProgramManager } = await (0, esm_1.dynamicImport)('@provablehq/sdk');
|
|
615
625
|
const keyProvider = new AleoKeyProvider();
|
package/dist/setup.js
CHANGED
|
@@ -33,7 +33,7 @@ function buildServerEntry(answers) {
|
|
|
33
33
|
const env = {
|
|
34
34
|
NULLPAY_MAIN_ADDRESS: answers.address,
|
|
35
35
|
NULLPAY_MAIN_PRIVATE_KEY: answers.privateKey,
|
|
36
|
-
NULLPAY_MAIN_PASSWORD: answers.password,
|
|
36
|
+
...(answers.password ? { NULLPAY_MAIN_PASSWORD: answers.password } : {}),
|
|
37
37
|
};
|
|
38
38
|
if (process.platform === 'win32') {
|
|
39
39
|
return {
|
|
@@ -79,7 +79,7 @@ function writeMcpConfig(configPath, serverName, entry) {
|
|
|
79
79
|
}
|
|
80
80
|
async function askChoice(rl) {
|
|
81
81
|
process_1.stdout.write('Where do you want to install NullPay MCP?\n');
|
|
82
|
-
process_1.stdout.write('1. Claude Code\n');
|
|
82
|
+
process_1.stdout.write('1. Claude Code (beta version)\n');
|
|
83
83
|
process_1.stdout.write('2. Claude Desktop\n');
|
|
84
84
|
process_1.stdout.write('3. Cancel\n');
|
|
85
85
|
while (true) {
|
|
@@ -102,11 +102,14 @@ async function askRequired(rl, label) {
|
|
|
102
102
|
process_1.stdout.write(`${label} is required.\n`);
|
|
103
103
|
}
|
|
104
104
|
}
|
|
105
|
+
async function askOptional(rl, label) {
|
|
106
|
+
return (await rl.question(`${label}: `)).trim();
|
|
107
|
+
}
|
|
105
108
|
async function collectAnswers(rl) {
|
|
106
109
|
process_1.stdout.write('\nNullPay will configure Claude automatically. You only need to provide your wallet credentials here.\n\n');
|
|
107
110
|
const address = await askRequired(rl, 'Main wallet address');
|
|
108
111
|
const privateKey = await askRequired(rl, 'Main wallet private key');
|
|
109
|
-
const password = await
|
|
112
|
+
const password = await askOptional(rl, 'NullPay password (optional if you have it backed up in your records)');
|
|
110
113
|
return {
|
|
111
114
|
address,
|
|
112
115
|
privateKey,
|