@lemmaoracle/x402 0.1.1 → 0.1.3
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/advanced/index.d.ts +14 -0
- package/dist/advanced/index.d.ts.map +1 -0
- package/dist/advanced/index.js +14 -0
- package/dist/advanced/index.js.map +1 -0
- package/dist/index.d.ts +25 -42
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +25 -77
- package/dist/index.js.map +1 -1
- package/dist/lemma-config.d.ts +41 -0
- package/dist/lemma-config.d.ts.map +1 -0
- package/dist/lemma-config.js +12 -0
- package/dist/lemma-config.js.map +1 -0
- package/dist/lemma-discovery.d.ts +37 -0
- package/dist/lemma-discovery.d.ts.map +1 -0
- package/dist/lemma-discovery.js +104 -0
- package/dist/lemma-discovery.js.map +1 -0
- package/dist/lemma-server.d.ts +30 -0
- package/dist/lemma-server.d.ts.map +1 -0
- package/dist/lemma-server.js +169 -0
- package/dist/lemma-server.js.map +1 -0
- package/dist/lemma-submission.d.ts +44 -0
- package/dist/lemma-submission.d.ts.map +1 -0
- package/dist/lemma-submission.js +81 -0
- package/dist/lemma-submission.js.map +1 -0
- package/package.json +14 -14
- package/broadcast/DeployPaymentVerifier.s.sol/10143/run-1775996174982.json +0 -34
- package/broadcast/DeployPaymentVerifier.s.sol/10143/run-1775996423983.json +0 -51
- package/broadcast/DeployPaymentVerifier.s.sol/10143/run-1775996907850.json +0 -51
- package/broadcast/DeployPaymentVerifier.s.sol/10143/run-latest.json +0 -51
- package/cache/DeployPaymentVerifier.s.sol/10143/run-1775996174982.json +0 -7
- package/cache/DeployPaymentVerifier.s.sol/10143/run-1775996423983.json +0 -7
- package/cache/DeployPaymentVerifier.s.sol/10143/run-1775996907850.json +0 -7
- package/cache/DeployPaymentVerifier.s.sol/10143/run-latest.json +0 -7
- package/cache/solidity-files-cache.json +0 -1
- package/circuits/README.md +0 -78
- package/circuits/payment-comprehensive.test.mjs +0 -272
- package/circuits/payment.circom +0 -89
- package/circuits/payment.test.mjs +0 -173
- package/dist/proof-generator.d.ts +0 -26
- package/dist/proof-generator.d.ts.map +0 -1
- package/dist/proof-generator.js +0 -154
- package/dist/proof-generator.js.map +0 -1
- package/dist/proof-generator.test.d.ts +0 -7
- package/dist/proof-generator.test.d.ts.map +0 -1
- package/dist/proof-generator.test.js +0 -121
- package/dist/proof-generator.test.js.map +0 -1
- package/dist/transaction-watcher.d.ts +0 -42
- package/dist/transaction-watcher.d.ts.map +0 -1
- package/dist/transaction-watcher.js +0 -88
- package/dist/transaction-watcher.js.map +0 -1
- package/dist/transaction-watcher.test.d.ts +0 -7
- package/dist/transaction-watcher.test.d.ts.map +0 -1
- package/dist/transaction-watcher.test.js +0 -111
- package/dist/transaction-watcher.test.js.map +0 -1
- package/dist/types.d.ts +0 -76
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js +0 -2
- package/dist/types.js.map +0 -1
- package/foundry.lock +0 -11
- package/foundry.toml +0 -16
- package/lib/forge-std/.gitattributes +0 -1
- package/lib/forge-std/.github/CODEOWNERS +0 -1
- package/lib/forge-std/.github/dependabot.yml +0 -6
- package/lib/forge-std/.github/workflows/ci.yml +0 -161
- package/lib/forge-std/.github/workflows/sync.yml +0 -36
- package/lib/forge-std/CONTRIBUTING.md +0 -193
- package/lib/forge-std/LICENSE-APACHE +0 -203
- package/lib/forge-std/LICENSE-MIT +0 -25
- package/lib/forge-std/README.md +0 -314
- package/lib/forge-std/RELEASE_CHECKLIST.md +0 -12
- package/lib/forge-std/foundry.toml +0 -18
- package/lib/forge-std/package.json +0 -16
- package/lib/forge-std/scripts/vm.py +0 -636
- package/lib/forge-std/src/Base.sol +0 -48
- package/lib/forge-std/src/Config.sol +0 -60
- package/lib/forge-std/src/LibVariable.sol +0 -477
- package/lib/forge-std/src/Script.sol +0 -28
- package/lib/forge-std/src/StdAssertions.sol +0 -1300
- package/lib/forge-std/src/StdChains.sol +0 -303
- package/lib/forge-std/src/StdCheats.sol +0 -825
- package/lib/forge-std/src/StdConfig.sol +0 -632
- package/lib/forge-std/src/StdConstants.sol +0 -30
- package/lib/forge-std/src/StdError.sol +0 -15
- package/lib/forge-std/src/StdInvariant.sol +0 -161
- package/lib/forge-std/src/StdJson.sol +0 -275
- package/lib/forge-std/src/StdMath.sol +0 -47
- package/lib/forge-std/src/StdStorage.sol +0 -476
- package/lib/forge-std/src/StdStyle.sol +0 -333
- package/lib/forge-std/src/StdToml.sol +0 -275
- package/lib/forge-std/src/StdUtils.sol +0 -200
- package/lib/forge-std/src/Test.sol +0 -32
- package/lib/forge-std/src/Vm.sol +0 -2533
- package/lib/forge-std/src/console.sol +0 -1551
- package/lib/forge-std/src/console2.sol +0 -4
- package/lib/forge-std/src/interfaces/IERC1155.sol +0 -105
- package/lib/forge-std/src/interfaces/IERC165.sol +0 -12
- package/lib/forge-std/src/interfaces/IERC20.sol +0 -43
- package/lib/forge-std/src/interfaces/IERC4626.sol +0 -190
- package/lib/forge-std/src/interfaces/IERC6909.sol +0 -72
- package/lib/forge-std/src/interfaces/IERC721.sol +0 -164
- package/lib/forge-std/src/interfaces/IERC7540.sol +0 -145
- package/lib/forge-std/src/interfaces/IERC7575.sol +0 -241
- package/lib/forge-std/src/interfaces/IMulticall3.sol +0 -68
- package/lib/forge-std/src/safeconsole.sol +0 -13248
- package/lib/forge-std/test/CommonBase.t.sol +0 -44
- package/lib/forge-std/test/Config.t.sol +0 -381
- package/lib/forge-std/test/LibVariable.t.sol +0 -452
- package/lib/forge-std/test/StdAssertions.t.sol +0 -141
- package/lib/forge-std/test/StdChains.t.sol +0 -227
- package/lib/forge-std/test/StdCheats.t.sol +0 -638
- package/lib/forge-std/test/StdConstants.t.sol +0 -38
- package/lib/forge-std/test/StdError.t.sol +0 -119
- package/lib/forge-std/test/StdJson.t.sol +0 -49
- package/lib/forge-std/test/StdMath.t.sol +0 -202
- package/lib/forge-std/test/StdStorage.t.sol +0 -532
- package/lib/forge-std/test/StdStyle.t.sol +0 -110
- package/lib/forge-std/test/StdToml.t.sol +0 -49
- package/lib/forge-std/test/StdUtils.t.sol +0 -342
- package/lib/forge-std/test/Vm.t.sol +0 -18
- package/lib/forge-std/test/compilation/CompilationScript.sol +0 -8
- package/lib/forge-std/test/compilation/CompilationScriptBase.sol +0 -8
- package/lib/forge-std/test/compilation/CompilationTest.sol +0 -8
- package/lib/forge-std/test/compilation/CompilationTestBase.sol +0 -8
- package/lib/forge-std/test/fixtures/broadcast.log.json +0 -187
- package/lib/forge-std/test/fixtures/config.toml +0 -81
- package/lib/forge-std/test/fixtures/test.json +0 -8
- package/lib/forge-std/test/fixtures/test.toml +0 -6
- package/package.json.backup +0 -55
- package/scripts/DeployPaymentVerifier.s.sol +0 -18
- package/scripts/build.sh +0 -61
- package/scripts/deploy.sh +0 -65
- package/scripts/fix-verifier.mjs +0 -64
- package/scripts/register-circuit.ts +0 -213
- package/scripts/test-with-circuit.mjs +0 -88
- package/src/index.ts +0 -115
- package/src/proof-generator.test.ts +0 -139
- package/src/proof-generator.ts +0 -220
- package/src/transaction-watcher.test.ts +0 -153
- package/src/transaction-watcher.ts +0 -154
- package/src/types.ts +0 -110
- package/tsconfig.json +0 -14
- package/tsconfig.tsbuildinfo +0 -1
- package/vitest.config.ts +0 -18
- package/workers/x402-facilitator/src/index.ts +0 -582
- package/workers/x402-facilitator/src/x402-env.d.ts +0 -25
- package/workers/x402-facilitator/wrangler.toml +0 -19
|
@@ -1,173 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Local test for payment.circom proof generation and verification
|
|
3
|
-
* Usage: node payment.test.mjs
|
|
4
|
-
*/
|
|
5
|
-
import * as snarkjs from "snarkjs";
|
|
6
|
-
import { readFileSync, existsSync } from "fs";
|
|
7
|
-
import { poseidon6 } from "poseidon-lite"; // npm install poseidon-lite
|
|
8
|
-
|
|
9
|
-
// File path configuration
|
|
10
|
-
const WASM_PATH = "build/payment_js/payment.wasm";
|
|
11
|
-
const ZKEY_PATH = "build/payment_final.zkey";
|
|
12
|
-
const VKEY_PATH = "build/verification_key.json";
|
|
13
|
-
|
|
14
|
-
// Generate test input data
|
|
15
|
-
function generateTestInputs() {
|
|
16
|
-
// Test transaction hash (256-bit)
|
|
17
|
-
const txHash = 0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdefn;
|
|
18
|
-
|
|
19
|
-
// Recipient address (160-bit)
|
|
20
|
-
const recipient = 0x2222222222222222222222222222222222222222n;
|
|
21
|
-
|
|
22
|
-
// Payment amount (smallest unit)
|
|
23
|
-
const amount = 1000n;
|
|
24
|
-
|
|
25
|
-
// Timestamp
|
|
26
|
-
const timestamp = 1712000000n;
|
|
27
|
-
|
|
28
|
-
// Minimum amount requirement
|
|
29
|
-
const minAmount = 1000n;
|
|
30
|
-
|
|
31
|
-
// Maximum timestamp (freshness check)
|
|
32
|
-
const timestampMax = 1712003600n; // 1 hour later
|
|
33
|
-
|
|
34
|
-
// Split 256-bit transaction hash into two 128-bit field elements
|
|
35
|
-
const txHashUpper = txHash >> 128n;
|
|
36
|
-
const txHashLower = txHash & ((1n << 128n) - 1n);
|
|
37
|
-
|
|
38
|
-
// Split 160-bit recipient address into two field elements
|
|
39
|
-
const recipientLow = recipient & ((1n << 128n) - 1n);
|
|
40
|
-
const recipientHigh = recipient >> 128n;
|
|
41
|
-
|
|
42
|
-
// Compute commitment (Poseidon(6) hash)
|
|
43
|
-
const commitment = poseidon6([
|
|
44
|
-
txHashUpper,
|
|
45
|
-
txHashLower,
|
|
46
|
-
recipientLow,
|
|
47
|
-
amount,
|
|
48
|
-
timestamp,
|
|
49
|
-
minAmount
|
|
50
|
-
]);
|
|
51
|
-
|
|
52
|
-
return {
|
|
53
|
-
// Private inputs
|
|
54
|
-
txHashPacked: [txHashUpper.toString(), txHashLower.toString()],
|
|
55
|
-
recipientLow: recipientLow.toString(),
|
|
56
|
-
recipientHigh: recipientHigh.toString(),
|
|
57
|
-
amount: amount.toString(),
|
|
58
|
-
timestamp: timestamp.toString(),
|
|
59
|
-
minAmount: minAmount.toString(),
|
|
60
|
-
|
|
61
|
-
// Public inputs
|
|
62
|
-
commitment: commitment.toString(),
|
|
63
|
-
minAmountPublic: minAmount.toString(),
|
|
64
|
-
timestampMax: timestampMax.toString()
|
|
65
|
-
};
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
// Check if build files exist
|
|
69
|
-
function checkBuildFiles() {
|
|
70
|
-
const files = [WASM_PATH, ZKEY_PATH, VKEY_PATH];
|
|
71
|
-
const missingFiles = files.filter(file => !existsSync(file));
|
|
72
|
-
|
|
73
|
-
if (missingFiles.length > 0) {
|
|
74
|
-
console.error("❌ Missing build files:");
|
|
75
|
-
missingFiles.forEach(file => console.error(` - ${file}`));
|
|
76
|
-
console.error("\n⚠️ Please run the build script first:");
|
|
77
|
-
console.error(" npm run build:circuit");
|
|
78
|
-
console.error(" or");
|
|
79
|
-
console.error(" bash scripts/build.sh");
|
|
80
|
-
return false;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
return true;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
async function main() {
|
|
87
|
-
console.log("=== X402 Payment Circuit Test ===\n");
|
|
88
|
-
|
|
89
|
-
// Check build files
|
|
90
|
-
if (!checkBuildFiles()) {
|
|
91
|
-
process.exit(1);
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
// Generate test input data
|
|
95
|
-
const input = generateTestInputs();
|
|
96
|
-
|
|
97
|
-
console.log("Generated test inputs:");
|
|
98
|
-
console.log("- Commitment:", input.commitment);
|
|
99
|
-
console.log("- Min Amount:", input.minAmountPublic);
|
|
100
|
-
console.log("- Timestamp Max:", input.timestampMax);
|
|
101
|
-
console.log("- Amount:", input.amount);
|
|
102
|
-
console.log("- Timestamp:", input.timestamp);
|
|
103
|
-
console.log();
|
|
104
|
-
|
|
105
|
-
try {
|
|
106
|
-
console.log("Generating proof...");
|
|
107
|
-
|
|
108
|
-
// Generate proof
|
|
109
|
-
const { proof, publicSignals } = await snarkjs.groth16.fullProve(
|
|
110
|
-
input,
|
|
111
|
-
WASM_PATH,
|
|
112
|
-
ZKEY_PATH
|
|
113
|
-
);
|
|
114
|
-
|
|
115
|
-
console.log("Proof generated successfully!");
|
|
116
|
-
console.log("Public signals:", publicSignals);
|
|
117
|
-
console.log();
|
|
118
|
-
|
|
119
|
-
// Load verification key
|
|
120
|
-
const vKey = JSON.parse(readFileSync(VKEY_PATH, "utf8"));
|
|
121
|
-
|
|
122
|
-
// Verify proof
|
|
123
|
-
const valid = await snarkjs.groth16.verify(vKey, publicSignals, proof);
|
|
124
|
-
|
|
125
|
-
if (valid) {
|
|
126
|
-
console.log("✅ Proof is VALID!");
|
|
127
|
-
console.log("\nCircuit verification successful!");
|
|
128
|
-
|
|
129
|
-
// Additional verification: check if commitment matches
|
|
130
|
-
if (publicSignals[0] === input.commitment) {
|
|
131
|
-
console.log("✅ Commitment matches expected value!");
|
|
132
|
-
} else {
|
|
133
|
-
console.log("⚠️ Commitment mismatch:");
|
|
134
|
-
console.log(` Expected: ${input.commitment}`);
|
|
135
|
-
console.log(` Got: ${publicSignals[0]}`);
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
// Explicitly exit
|
|
139
|
-
console.log("\n✅ All tests completed successfully!");
|
|
140
|
-
process.exit(0);
|
|
141
|
-
} else {
|
|
142
|
-
console.log("❌ Proof is INVALID!");
|
|
143
|
-
console.log("\nCircuit verification failed!");
|
|
144
|
-
process.exit(1);
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
} catch (error) {
|
|
148
|
-
console.error("❌ Error during proof generation/verification:");
|
|
149
|
-
console.error(error.message);
|
|
150
|
-
|
|
151
|
-
if (error.message.includes("ENOENT") || error.message.includes("no such file")) {
|
|
152
|
-
console.error("\n⚠️ Build files not found. Please run the build script first:");
|
|
153
|
-
console.error(" npm run build:circuit");
|
|
154
|
-
console.error(" or");
|
|
155
|
-
console.error(" bash scripts/build.sh");
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
process.exit(1);
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
// Execute main function
|
|
163
|
-
main().catch(error => {
|
|
164
|
-
console.error("Unhandled error:", error);
|
|
165
|
-
process.exit(1);
|
|
166
|
-
});
|
|
167
|
-
|
|
168
|
-
// Fallback to force process exit
|
|
169
|
-
// snarkjs may leave background processes running
|
|
170
|
-
setTimeout(() => {
|
|
171
|
-
console.warn("⚠️ Force exiting process after timeout");
|
|
172
|
-
process.exit(0);
|
|
173
|
-
}, 30000); // Force exit after 30 seconds
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* X402 Payment Proof Generator
|
|
3
|
-
*
|
|
4
|
-
* Generates ZK proofs for x402 payment transactions so that
|
|
5
|
-
* Lemma's disclosure.condition API can verify payments without
|
|
6
|
-
* exposing transaction details.
|
|
7
|
-
*/
|
|
8
|
-
import { type LemmaClient } from "@lemmaoracle/sdk";
|
|
9
|
-
import type { ProofResult, Config, Transaction, Proof } from "./types.js";
|
|
10
|
-
/**
|
|
11
|
-
* Generates x402 payment proofs using Lemma's prover infrastructure.
|
|
12
|
-
*
|
|
13
|
-
* Usage:
|
|
14
|
-
* const generator = new X402ProofGenerator(config, lemmaClient);
|
|
15
|
-
* const result = await generator.generateProof(txHash);
|
|
16
|
-
*/
|
|
17
|
-
declare const createProofGenerator: (config: Config, lemmaClient: LemmaClient) => Readonly<{
|
|
18
|
-
generateProof: (txHash: `0x${string}`) => Promise<ProofResult>;
|
|
19
|
-
toFieldElements: (payment: Transaction, config: Config) => Readonly<{
|
|
20
|
-
witness: Record<string, string>;
|
|
21
|
-
publicInputs: string[];
|
|
22
|
-
}>;
|
|
23
|
-
}>;
|
|
24
|
-
export type { ProofResult, Config, Proof, Transaction, };
|
|
25
|
-
export { createProofGenerator };
|
|
26
|
-
//# sourceMappingURL=proof-generator.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"proof-generator.d.ts","sourceRoot":"","sources":["../src/proof-generator.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EAAU,KAAK,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAE5D,OAAO,KAAK,EACV,WAAW,EACX,MAAM,EACN,WAAW,EACX,KAAK,EACN,MAAM,YAAY,CAAC;AAmBpB;;;;;;GAMG;AACH,QAAA,MAAM,oBAAoB,GACxB,QAAQ,MAAM,EACd,aAAa,WAAW,KACvB,QAAQ,CAAC;IACV,aAAa,EAAE,CAAC,MAAM,EAAE,KAAK,MAAM,EAAE,KAAK,OAAO,CAAC,WAAW,CAAC,CAAC;IAC/D,eAAe,EAAE,CACf,OAAO,EAAE,WAAW,EACpB,MAAM,EAAE,MAAM,KACX,QAAQ,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAAC,YAAY,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC,CAAC;CAC5E,CAqEA,CAAC;AA4FF,YAAY,EACV,WAAW,EACX,MAAM,EACN,KAAK,EACL,WAAW,GACZ,CAAC;AAEF,OAAO,EAAE,oBAAoB,EAAE,CAAC"}
|
package/dist/proof-generator.js
DELETED
|
@@ -1,154 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* X402 Payment Proof Generator
|
|
3
|
-
*
|
|
4
|
-
* Generates ZK proofs for x402 payment transactions so that
|
|
5
|
-
* Lemma's disclosure.condition API can verify payments without
|
|
6
|
-
* exposing transaction details.
|
|
7
|
-
*/
|
|
8
|
-
import { createPublicClient, http } from "viem";
|
|
9
|
-
import { prover } from "@lemmaoracle/sdk";
|
|
10
|
-
import * as R from "ramda";
|
|
11
|
-
// ---------------------------------------------------------------------------
|
|
12
|
-
// Constants
|
|
13
|
-
// ---------------------------------------------------------------------------
|
|
14
|
-
/** Default IPFS gateway if not specified in config */
|
|
15
|
-
const _DEFAULT_IPFS_GATEWAY = "https://ipfs.io/ipfs/";
|
|
16
|
-
/** Poseidon hash function for field element hashing */
|
|
17
|
-
const toFieldElement = (value) => BigInt(value) < 0n
|
|
18
|
-
? String(BigInt(value) % 21888242871839275222246405745257275088548364400416034343698204186575808495617n)
|
|
19
|
-
: value;
|
|
20
|
-
// ---------------------------------------------------------------------------
|
|
21
|
-
// Proof Generator Class
|
|
22
|
-
// ---------------------------------------------------------------------------
|
|
23
|
-
/**
|
|
24
|
-
* Generates x402 payment proofs using Lemma's prover infrastructure.
|
|
25
|
-
*
|
|
26
|
-
* Usage:
|
|
27
|
-
* const generator = new X402ProofGenerator(config, lemmaClient);
|
|
28
|
-
* const result = await generator.generateProof(txHash);
|
|
29
|
-
*/
|
|
30
|
-
const createProofGenerator = (config, lemmaClient) => {
|
|
31
|
-
/** Create public client for transaction inspection */
|
|
32
|
-
const publicClient = createPublicClient({
|
|
33
|
-
transport: http(config.ethereumRpcUrl),
|
|
34
|
-
});
|
|
35
|
-
return {
|
|
36
|
-
/**
|
|
37
|
-
* Generate a payment proof for a given transaction hash.
|
|
38
|
-
* This fetches the transaction details, computes the witness,
|
|
39
|
-
* and generates the ZK proof.
|
|
40
|
-
*/
|
|
41
|
-
generateProof: async (txHash) => {
|
|
42
|
-
// Step 1: Fetch transaction details from blockchain
|
|
43
|
-
const payment = await fetchPaymentTransaction(txHash, publicClient);
|
|
44
|
-
// Step 2: Generate proof
|
|
45
|
-
const proofResult = await generateZKProof(lemmaClient, payment, config);
|
|
46
|
-
return R.always({
|
|
47
|
-
payment,
|
|
48
|
-
proof: proofResult,
|
|
49
|
-
})();
|
|
50
|
-
},
|
|
51
|
-
/**
|
|
52
|
-
* Convert payment transaction details to circuit field elements.
|
|
53
|
-
*/
|
|
54
|
-
toFieldElements: (payment, cfg) => {
|
|
55
|
-
// Split 256-bit txHash into two 128-bit elements
|
|
56
|
-
const txHashBigInt = BigInt(payment.txHash);
|
|
57
|
-
const upper128 = toFieldElement(String(txHashBigInt >> 128n));
|
|
58
|
-
const lower128 = toFieldElement(String(txHashBigInt & ((1n << 128n) - 1n)));
|
|
59
|
-
// Split 160-bit recipient address
|
|
60
|
-
const recipientBigInt = BigInt(payment.to);
|
|
61
|
-
const recipientLow = toFieldElement(String(recipientBigInt & ((1n << 128n) - 1n)));
|
|
62
|
-
const recipientHigh = toFieldElement(String(recipientBigInt >> 128n));
|
|
63
|
-
// Amount and timestamp
|
|
64
|
-
const amount = toFieldElement(String(payment.amount));
|
|
65
|
-
const timestamp = toFieldElement(String(payment.timestamp));
|
|
66
|
-
const minAmount = toFieldElement(String(cfg.minAmount));
|
|
67
|
-
return R.always({
|
|
68
|
-
witness: {
|
|
69
|
-
txHashPacked_0: lower128,
|
|
70
|
-
txHashPacked_1: upper128,
|
|
71
|
-
recipientLow,
|
|
72
|
-
recipientHigh,
|
|
73
|
-
amount,
|
|
74
|
-
timestamp,
|
|
75
|
-
minAmount,
|
|
76
|
-
},
|
|
77
|
-
publicInputs: [
|
|
78
|
-
// commitment will be computed during proof generation
|
|
79
|
-
toFieldElement(String(cfg.minAmount)), // minAmountPublic
|
|
80
|
-
toFieldElement(String(cfg.maxProofAge)), // timestampMax
|
|
81
|
-
],
|
|
82
|
-
})();
|
|
83
|
-
},
|
|
84
|
-
};
|
|
85
|
-
};
|
|
86
|
-
// ---------------------------------------------------------------------------
|
|
87
|
-
// Private Helpers
|
|
88
|
-
// ---------------------------------------------------------------------------
|
|
89
|
-
/**
|
|
90
|
-
* Fetch payment transaction details from the blockchain.
|
|
91
|
-
*/
|
|
92
|
-
const fetchPaymentTransaction = async (txHash, client) => {
|
|
93
|
-
const txPromise = client.getTransaction({ hash: txHash });
|
|
94
|
-
const receiptPromise = client.getTransactionReceipt({ hash: txHash });
|
|
95
|
-
const blockPromise = client.getBlock({ blockTag: "latest" });
|
|
96
|
-
const [tx, receipt, block] = await Promise.all([
|
|
97
|
-
txPromise,
|
|
98
|
-
receiptPromise,
|
|
99
|
-
blockPromise,
|
|
100
|
-
]);
|
|
101
|
-
return receipt.status !== "success"
|
|
102
|
-
? Promise.reject(new Error(`Transaction ${txHash} failed`))
|
|
103
|
-
: client.getBlock({ blockNumber: receipt.blockNumber }).then((blockData) => R.always({
|
|
104
|
-
txHash,
|
|
105
|
-
from: tx.from,
|
|
106
|
-
to: tx.to ?? "0x",
|
|
107
|
-
amount: tx.value + receipt.effectiveGasPrice * receipt.gasUsed,
|
|
108
|
-
timestamp: Number(blockData.timestamp),
|
|
109
|
-
blockNumber: receipt.blockNumber,
|
|
110
|
-
confirmations: Number(block.number - receipt.blockNumber),
|
|
111
|
-
})());
|
|
112
|
-
};
|
|
113
|
-
/**
|
|
114
|
-
* Generate ZK proof for the payment transaction.
|
|
115
|
-
*/
|
|
116
|
-
const generateZKProof = async (lemmaClient, payment, config) => {
|
|
117
|
-
// Build witness from payment transaction
|
|
118
|
-
const builder = createProofGenerator(config, lemmaClient);
|
|
119
|
-
const { witness, publicInputs } = builder.toFieldElements(payment, config);
|
|
120
|
-
// Generate proof using Lemma SDK
|
|
121
|
-
const proofResult = await prover.prove(lemmaClient, {
|
|
122
|
-
circuitId: config.circuitId,
|
|
123
|
-
witness,
|
|
124
|
-
});
|
|
125
|
-
// Compute the commitment for public inputs
|
|
126
|
-
const commitment = computeCommitment(witness, publicInputs);
|
|
127
|
-
return R.always({
|
|
128
|
-
proof: proofResult.proof,
|
|
129
|
-
inputs: [commitment, ...publicInputs],
|
|
130
|
-
circuitId: config.circuitId,
|
|
131
|
-
generatedAt: Date.now(),
|
|
132
|
-
})();
|
|
133
|
-
};
|
|
134
|
-
/**
|
|
135
|
-
* Compute the commitment hash for the circuit public inputs.
|
|
136
|
-
*/
|
|
137
|
-
const computeCommitment = (witness, _publicInputs) => {
|
|
138
|
-
// The commitment is computed from:
|
|
139
|
-
// poseidon(txHashPacked[0], txHashPacked[1], recipientLow, amount, timestamp, minAmount)
|
|
140
|
-
// This should match the public commitment used in the circuit
|
|
141
|
-
const values = [
|
|
142
|
-
witness.txHashPacked_0,
|
|
143
|
-
witness.txHashPacked_1,
|
|
144
|
-
witness.recipientLow,
|
|
145
|
-
witness.amount,
|
|
146
|
-
witness.timestamp,
|
|
147
|
-
witness.minAmount,
|
|
148
|
-
];
|
|
149
|
-
// In a real implementation, use poseidon from circomlib
|
|
150
|
-
// For now, we use a simple hash placeholder
|
|
151
|
-
return values.join(",");
|
|
152
|
-
};
|
|
153
|
-
export { createProofGenerator };
|
|
154
|
-
//# sourceMappingURL=proof-generator.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"proof-generator.js","sourceRoot":"","sources":["../src/proof-generator.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"proof-generator.test.d.ts","sourceRoot":"","sources":["../src/proof-generator.test.ts"],"names":[],"mappings":"AAAA;;;;GAIG"}
|
|
@@ -1,121 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Tests for x402 payment proof generator.
|
|
3
|
-
*
|
|
4
|
-
* Test files are exempt from FP rules.
|
|
5
|
-
*/
|
|
6
|
-
import { describe, it, expect, vi, beforeEach } from "vitest";
|
|
7
|
-
import { createProofGenerator } from "./proof-generator.js";
|
|
8
|
-
// Mock viem
|
|
9
|
-
vi.mock("viem", async () => {
|
|
10
|
-
const actual = await vi.importActual("viem");
|
|
11
|
-
return {
|
|
12
|
-
...actual,
|
|
13
|
-
createPublicClient: vi.fn(() => ({
|
|
14
|
-
getTransaction: vi.fn().mockResolvedValue({
|
|
15
|
-
hash: "0xabc123",
|
|
16
|
-
from: "0xsender",
|
|
17
|
-
to: "0x2222222222222222222222222222222222222222",
|
|
18
|
-
value: 1000n,
|
|
19
|
-
}),
|
|
20
|
-
getTransactionReceipt: vi.fn().mockResolvedValue({
|
|
21
|
-
status: "success",
|
|
22
|
-
blockNumber: 1000n,
|
|
23
|
-
gasUsed: 21000n,
|
|
24
|
-
effectiveGasPrice: 1000000000n,
|
|
25
|
-
confirmations: 6,
|
|
26
|
-
}),
|
|
27
|
-
getBlock: vi.fn().mockResolvedValue({
|
|
28
|
-
number: 1006n,
|
|
29
|
-
timestamp: 1712000000n,
|
|
30
|
-
}),
|
|
31
|
-
})),
|
|
32
|
-
};
|
|
33
|
-
});
|
|
34
|
-
// Mock Lemma SDK
|
|
35
|
-
vi.mock("@lemmaoracle/sdk", async () => {
|
|
36
|
-
const actual = await vi.importActual("@lemmaoracle/sdk");
|
|
37
|
-
return {
|
|
38
|
-
...actual,
|
|
39
|
-
prover: {
|
|
40
|
-
prove: vi.fn().mockResolvedValue({
|
|
41
|
-
proof: "mock-proof-base64",
|
|
42
|
-
publicInputs: ["input1", "input2"],
|
|
43
|
-
}),
|
|
44
|
-
},
|
|
45
|
-
createClient: vi.fn().mockReturnValue({
|
|
46
|
-
apiBase: "https://workers.lemma.workers.dev",
|
|
47
|
-
}),
|
|
48
|
-
};
|
|
49
|
-
});
|
|
50
|
-
const mockConfig = {
|
|
51
|
-
payToAddress: "0x2222222222222222222222222222222222222222",
|
|
52
|
-
network: "eip155:84532",
|
|
53
|
-
price: "$0.001",
|
|
54
|
-
ethereumRpcUrl: "https://sepolia.base.org",
|
|
55
|
-
chainId: 84532,
|
|
56
|
-
lemmaApiBase: "https://workers.lemma.workers.dev",
|
|
57
|
-
circuitId: "x402-payment-v1",
|
|
58
|
-
minAmount: 1000n,
|
|
59
|
-
requiredConfirmations: 6,
|
|
60
|
-
maxProofAge: 3600,
|
|
61
|
-
ipfsGateway: "https://ipfs.io/ipfs/",
|
|
62
|
-
};
|
|
63
|
-
const mockLemmaClient = {
|
|
64
|
-
apiBase: "https://workers.lemma.workers.dev",
|
|
65
|
-
};
|
|
66
|
-
describe("X402 Proof Generator", () => {
|
|
67
|
-
beforeEach(() => {
|
|
68
|
-
vi.clearAllMocks();
|
|
69
|
-
});
|
|
70
|
-
it("should create a proof generator", () => {
|
|
71
|
-
const generator = createProofGenerator(mockConfig, mockLemmaClient);
|
|
72
|
-
expect(generator).toBeDefined();
|
|
73
|
-
expect(typeof generator.generateProof).toBe("function");
|
|
74
|
-
expect(typeof generator.toFieldElements).toBe("function");
|
|
75
|
-
});
|
|
76
|
-
it("should convert payment details to field elements", async () => {
|
|
77
|
-
const generator = createProofGenerator(mockConfig, mockLemmaClient);
|
|
78
|
-
const mockPayment = {
|
|
79
|
-
txHash: "0xabc123",
|
|
80
|
-
from: "0x1111111111111111111111111111111111111111",
|
|
81
|
-
to: "0x2222222222222222222222222222222222222222",
|
|
82
|
-
amount: 1000n,
|
|
83
|
-
timestamp: 1712000000,
|
|
84
|
-
blockNumber: 1000n,
|
|
85
|
-
confirmations: 6,
|
|
86
|
-
};
|
|
87
|
-
const result = await generator.toFieldElements(mockPayment, mockConfig);
|
|
88
|
-
expect(result).toBeDefined();
|
|
89
|
-
expect(result.witness).toBeDefined();
|
|
90
|
-
expect(result.publicInputs).toBeDefined();
|
|
91
|
-
expect(result.witness.amount).toBeDefined();
|
|
92
|
-
expect(result.witness.minAmount).toBeDefined();
|
|
93
|
-
});
|
|
94
|
-
it("should handle empty txHash gracefully", async () => {
|
|
95
|
-
const generator = createProofGenerator(mockConfig, mockLemmaClient);
|
|
96
|
-
expect(generator.generateProof).toBeDefined();
|
|
97
|
-
});
|
|
98
|
-
});
|
|
99
|
-
describe("Field Element Conversion", () => {
|
|
100
|
-
it("should convert addresses to field elements", async () => {
|
|
101
|
-
const generator = createProofGenerator(mockConfig, mockLemmaClient);
|
|
102
|
-
const mockPayment = {
|
|
103
|
-
txHash: "0xabc123",
|
|
104
|
-
from: "0x1111111111111111111111111111111111111111",
|
|
105
|
-
to: "0x2222222222222222222222222222222222222222",
|
|
106
|
-
amount: 1000n,
|
|
107
|
-
timestamp: 1712000000,
|
|
108
|
-
blockNumber: 1000n,
|
|
109
|
-
confirmations: 6,
|
|
110
|
-
};
|
|
111
|
-
const { witness } = await generator.toFieldElements(mockPayment, mockConfig);
|
|
112
|
-
// Verify field elements are present and not null
|
|
113
|
-
expect(witness.txHashPacked_0).toBeDefined();
|
|
114
|
-
expect(witness.txHashPacked_1).toBeDefined();
|
|
115
|
-
expect(witness.recipientLow).toBeDefined();
|
|
116
|
-
expect(witness.amount).toBeDefined();
|
|
117
|
-
expect(witness.timestamp).toBeDefined();
|
|
118
|
-
expect(witness.minAmount).toBeDefined();
|
|
119
|
-
});
|
|
120
|
-
});
|
|
121
|
-
//# sourceMappingURL=proof-generator.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"proof-generator.test.js","sourceRoot":"","sources":["../src/proof-generator.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* X402 Transaction Watcher
|
|
3
|
-
*
|
|
4
|
-
* Monitors the blockchain for x402 payment transactions to the configured
|
|
5
|
-
* recipient address and triggers proof generation when payments are detected.
|
|
6
|
-
*/
|
|
7
|
-
import type { Transaction as ViemTransaction, TransactionReceipt } from "viem";
|
|
8
|
-
import type { Config, Transaction } from "./types.js";
|
|
9
|
-
/** Callback invoked when a valid payment is detected */
|
|
10
|
-
type PaymentDetectedCallback = (payment: Transaction) => Promise<void>;
|
|
11
|
-
/** State of the transaction watcher */
|
|
12
|
-
type WatcherState = Readonly<{
|
|
13
|
-
isRunning: boolean;
|
|
14
|
-
lastCheckedBlock: bigint;
|
|
15
|
-
detectedPayments: ReadonlyArray<PaymentDetectedCallback>;
|
|
16
|
-
}>;
|
|
17
|
-
/**
|
|
18
|
-
* Creates a transaction watcher that monitors for payments to the configured address.
|
|
19
|
-
*
|
|
20
|
-
* Uses an immutable state cell (single-element tuple) as a controlled mutable reference.
|
|
21
|
-
*/
|
|
22
|
-
declare const createTransactionWatcher: (_config: Config, _publicClient: unknown) => Readonly<{
|
|
23
|
-
start: (_?: undefined) => Promise<void>;
|
|
24
|
-
stop: (_?: undefined) => void;
|
|
25
|
-
onPaymentDetected: (callback: PaymentDetectedCallback) => Promise<void>;
|
|
26
|
-
getState: (_?: undefined) => WatcherState;
|
|
27
|
-
}>;
|
|
28
|
-
/**
|
|
29
|
-
* Validate that a transaction is a valid x402 payment:
|
|
30
|
-
* - Transaction was successful
|
|
31
|
-
* - Sent to the correct recipient
|
|
32
|
-
* - Amount meets the minimum requirement
|
|
33
|
-
* - Has sufficient confirmations
|
|
34
|
-
*/
|
|
35
|
-
declare const isValidPayment: (tx: ViemTransaction, receipt: TransactionReceipt, config: Config, currentBlockNumber?: bigint) => boolean;
|
|
36
|
-
/**
|
|
37
|
-
* Extract payment details from transaction and receipt.
|
|
38
|
-
*/
|
|
39
|
-
declare const extractPaymentDetails: (tx: ViemTransaction, receipt: TransactionReceipt, currentBlockNumber: bigint) => Transaction;
|
|
40
|
-
export type { PaymentDetectedCallback, WatcherState, };
|
|
41
|
-
export { createTransactionWatcher, isValidPayment, extractPaymentDetails, };
|
|
42
|
-
//# sourceMappingURL=transaction-watcher.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"transaction-watcher.d.ts","sourceRoot":"","sources":["../src/transaction-watcher.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EACV,WAAW,IAAI,eAAe,EAC9B,kBAAkB,EACnB,MAAM,MAAM,CAAC;AAEd,OAAO,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAMtD,wDAAwD;AACxD,KAAK,uBAAuB,GAAG,CAC7B,OAAO,EAAE,WAAW,KACjB,OAAO,CAAC,IAAI,CAAC,CAAC;AAEnB,uCAAuC;AACvC,KAAK,YAAY,GAAG,QAAQ,CAAC;IAC3B,SAAS,EAAE,OAAO,CAAC;IACnB,gBAAgB,EAAE,MAAM,CAAC;IACzB,gBAAgB,EAAE,aAAa,CAAC,uBAAuB,CAAC,CAAC;CAC1D,CAAC,CAAC;AAYH;;;;GAIG;AACH,QAAA,MAAM,wBAAwB,GAC5B,SAAS,MAAM,EACf,eAAe,OAAO,KACrB,QAAQ,CAAC;IACV,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,SAAS,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACxC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,SAAS,KAAK,IAAI,CAAC;IAC9B,iBAAiB,EAAE,CAAC,QAAQ,EAAE,uBAAuB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACxE,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,SAAS,KAAK,YAAY,CAAC;CAC3C,CAsCA,CAAC;AAMF;;;;;;GAMG;AACH,QAAA,MAAM,cAAc,GAClB,IAAI,eAAe,EACnB,SAAS,kBAAkB,EAC3B,QAAQ,MAAM,EACd,qBAAoB,MAAW,KAC9B,OAUG,CAAC;AAEP;;GAEG;AACH,QAAA,MAAM,qBAAqB,GACzB,IAAI,eAAe,EACnB,SAAS,kBAAkB,EAC3B,oBAAoB,MAAM,KACzB,WAcF,CAAC;AAEF,YAAY,EACV,uBAAuB,EACvB,YAAY,GACb,CAAC;AAEF,OAAO,EACL,wBAAwB,EACxB,cAAc,EACd,qBAAqB,GACtB,CAAC"}
|
|
@@ -1,88 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* X402 Transaction Watcher
|
|
3
|
-
*
|
|
4
|
-
* Monitors the blockchain for x402 payment transactions to the configured
|
|
5
|
-
* recipient address and triggers proof generation when payments are detected.
|
|
6
|
-
*/
|
|
7
|
-
import * as R from "ramda";
|
|
8
|
-
// ---------------------------------------------------------------------------
|
|
9
|
-
// Watcher Implementation
|
|
10
|
-
// ---------------------------------------------------------------------------
|
|
11
|
-
const initialState = {
|
|
12
|
-
isRunning: false,
|
|
13
|
-
lastCheckedBlock: 0n,
|
|
14
|
-
detectedPayments: [],
|
|
15
|
-
};
|
|
16
|
-
/**
|
|
17
|
-
* Creates a transaction watcher that monitors for payments to the configured address.
|
|
18
|
-
*
|
|
19
|
-
* Uses an immutable state cell (single-element tuple) as a controlled mutable reference.
|
|
20
|
-
*/
|
|
21
|
-
const createTransactionWatcher = (_config, _publicClient) => {
|
|
22
|
-
const stateCell = { current: initialState };
|
|
23
|
-
const start = (_) => {
|
|
24
|
-
// eslint-disable-next-line functional/no-expression-statements, functional/immutable-data
|
|
25
|
-
stateCell.current = {
|
|
26
|
-
...stateCell.current,
|
|
27
|
-
isRunning: true,
|
|
28
|
-
lastCheckedBlock: 0n,
|
|
29
|
-
};
|
|
30
|
-
return Promise.resolve();
|
|
31
|
-
};
|
|
32
|
-
const stop = (_) => {
|
|
33
|
-
// eslint-disable-next-line functional/no-expression-statements, functional/immutable-data
|
|
34
|
-
stateCell.current = R.assoc("isRunning", false, stateCell.current);
|
|
35
|
-
};
|
|
36
|
-
const onPaymentDetected = (callback) => {
|
|
37
|
-
// eslint-disable-next-line functional/no-expression-statements, functional/immutable-data
|
|
38
|
-
stateCell.current = {
|
|
39
|
-
...stateCell.current,
|
|
40
|
-
detectedPayments: R.append(callback, stateCell.current.detectedPayments),
|
|
41
|
-
};
|
|
42
|
-
return Promise.resolve();
|
|
43
|
-
};
|
|
44
|
-
const getState = (_) => stateCell.current;
|
|
45
|
-
return {
|
|
46
|
-
start,
|
|
47
|
-
stop,
|
|
48
|
-
onPaymentDetected,
|
|
49
|
-
getState,
|
|
50
|
-
};
|
|
51
|
-
};
|
|
52
|
-
// ---------------------------------------------------------------------------
|
|
53
|
-
// Utility Functions
|
|
54
|
-
// ---------------------------------------------------------------------------
|
|
55
|
-
/**
|
|
56
|
-
* Validate that a transaction is a valid x402 payment:
|
|
57
|
-
* - Transaction was successful
|
|
58
|
-
* - Sent to the correct recipient
|
|
59
|
-
* - Amount meets the minimum requirement
|
|
60
|
-
* - Has sufficient confirmations
|
|
61
|
-
*/
|
|
62
|
-
const isValidPayment = (tx, receipt, config, currentBlockNumber = 0n) => R.allPass([
|
|
63
|
-
R.always(tx.to === config.payToAddress),
|
|
64
|
-
R.always(tx.value >= config.minAmount),
|
|
65
|
-
R.always(receipt.status === "success"),
|
|
66
|
-
R.always(currentBlockNumber > 0n
|
|
67
|
-
? Number(currentBlockNumber - receipt.blockNumber) >= config.requiredConfirmations
|
|
68
|
-
: true),
|
|
69
|
-
])();
|
|
70
|
-
/**
|
|
71
|
-
* Extract payment details from transaction and receipt.
|
|
72
|
-
*/
|
|
73
|
-
const extractPaymentDetails = (tx, receipt, currentBlockNumber) => {
|
|
74
|
-
const txRecord = tx;
|
|
75
|
-
const rawTimestamp = txRecord["blockTimestamp"];
|
|
76
|
-
const timestamp = typeof rawTimestamp === "bigint" ? Number(rawTimestamp) : 0;
|
|
77
|
-
return R.always({
|
|
78
|
-
txHash: tx.hash,
|
|
79
|
-
from: tx.from,
|
|
80
|
-
to: tx.to ?? "0x",
|
|
81
|
-
amount: tx.value,
|
|
82
|
-
timestamp,
|
|
83
|
-
blockNumber: receipt.blockNumber,
|
|
84
|
-
confirmations: Number(currentBlockNumber - receipt.blockNumber),
|
|
85
|
-
})();
|
|
86
|
-
};
|
|
87
|
-
export { createTransactionWatcher, isValidPayment, extractPaymentDetails, };
|
|
88
|
-
//# sourceMappingURL=transaction-watcher.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"transaction-watcher.js","sourceRoot":"","sources":["../src/transaction-watcher.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"transaction-watcher.test.d.ts","sourceRoot":"","sources":["../src/transaction-watcher.test.ts"],"names":[],"mappings":"AAAA;;;;GAIG"}
|