x402z-shared 0.0.1

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/web.js ADDED
@@ -0,0 +1,312 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/web.ts
21
+ var web_exports = {};
22
+ __export(web_exports, {
23
+ SepoliaConfig: () => import_bundle.SepoliaConfig,
24
+ confidentialPaymentTypes: () => confidentialPaymentTypes,
25
+ confidentialTokenAbi: () => confidentialTokenAbi,
26
+ createEncryptedAmountInput: () => createEncryptedAmountInput,
27
+ createNonce: () => createNonce,
28
+ createRelayerInstance: () => createRelayerInstance,
29
+ hashEncryptedAmountInput: () => hashEncryptedAmountInput,
30
+ initSDK: () => import_bundle.initSDK,
31
+ normalizeAmount: () => normalizeAmount,
32
+ publicDecrypt: () => publicDecrypt,
33
+ userDecryptEuint64: () => userDecryptEuint64,
34
+ viewConfidentialBalance: () => viewConfidentialBalance,
35
+ viewConfidentialTransferAmounts: () => viewConfidentialTransferAmounts
36
+ });
37
+ module.exports = __toCommonJS(web_exports);
38
+
39
+ // src/abi.ts
40
+ var confidentialTokenAbi = [
41
+ {
42
+ inputs: [
43
+ {
44
+ components: [
45
+ { internalType: "address", name: "holder", type: "address" },
46
+ { internalType: "address", name: "payee", type: "address" },
47
+ { internalType: "uint256", name: "maxClearAmount", type: "uint256" },
48
+ { internalType: "bytes32", name: "resourceHash", type: "bytes32" },
49
+ { internalType: "uint48", name: "validAfter", type: "uint48" },
50
+ { internalType: "uint48", name: "validBefore", type: "uint48" },
51
+ { internalType: "bytes32", name: "nonce", type: "bytes32" },
52
+ { internalType: "bytes32", name: "encryptedAmountHash", type: "bytes32" }
53
+ ],
54
+ internalType: "struct FHEToken.ConfidentialPayment",
55
+ name: "p",
56
+ type: "tuple"
57
+ },
58
+ { internalType: "externalEuint64", name: "encryptedAmountInput", type: "bytes32" },
59
+ { internalType: "bytes", name: "inputProof", type: "bytes" },
60
+ { internalType: "bytes", name: "sig", type: "bytes" }
61
+ ],
62
+ name: "confidentialTransferWithAuthorization",
63
+ outputs: [{ internalType: "euint64", name: "transferred", type: "bytes32" }],
64
+ stateMutability: "nonpayable",
65
+ type: "function"
66
+ },
67
+ {
68
+ anonymous: false,
69
+ inputs: [
70
+ { indexed: true, internalType: "address", name: "holder", type: "address" },
71
+ { indexed: true, internalType: "address", name: "payee", type: "address" },
72
+ { indexed: false, internalType: "uint256", name: "maxClearAmount", type: "uint256" },
73
+ { indexed: true, internalType: "bytes32", name: "resourceHash", type: "bytes32" },
74
+ { indexed: false, internalType: "bytes32", name: "nonce", type: "bytes32" },
75
+ { indexed: false, internalType: "bytes32", name: "transferredAmount", type: "bytes32" }
76
+ ],
77
+ name: "ConfidentialPaymentExecuted",
78
+ type: "event"
79
+ },
80
+ {
81
+ inputs: [
82
+ { internalType: "address", name: "", type: "address" },
83
+ { internalType: "bytes32", name: "", type: "bytes32" }
84
+ ],
85
+ name: "usedNonces",
86
+ outputs: [{ internalType: "bool", name: "", type: "bool" }],
87
+ stateMutability: "view",
88
+ type: "function"
89
+ }
90
+ ];
91
+
92
+ // src/constants.ts
93
+ var confidentialPaymentTypes = {
94
+ ConfidentialPayment: [
95
+ { name: "holder", type: "address" },
96
+ { name: "payee", type: "address" },
97
+ { name: "maxClearAmount", type: "uint256" },
98
+ { name: "resourceHash", type: "bytes32" },
99
+ { name: "validAfter", type: "uint48" },
100
+ { name: "validBefore", type: "uint48" },
101
+ { name: "nonce", type: "bytes32" },
102
+ { name: "encryptedAmountHash", type: "bytes32" }
103
+ ]
104
+ };
105
+
106
+ // src/utils.ts
107
+ var import_viem = require("viem");
108
+ function createNonce() {
109
+ const cryptoObj = typeof globalThis.crypto !== "undefined" ? globalThis.crypto : globalThis.crypto;
110
+ if (!cryptoObj) {
111
+ throw new Error("Crypto API not available");
112
+ }
113
+ return (0, import_viem.toHex)(cryptoObj.getRandomValues(new Uint8Array(32)));
114
+ }
115
+ function hashEncryptedAmountInput(encryptedAmountInput) {
116
+ return (0, import_viem.keccak256)(
117
+ (0, import_viem.encodeAbiParameters)([{ type: "bytes32" }], [encryptedAmountInput])
118
+ );
119
+ }
120
+ function normalizeAmount(amount) {
121
+ if (typeof amount === "string") {
122
+ return amount;
123
+ }
124
+ if (typeof amount === "number") {
125
+ if (!Number.isFinite(amount)) {
126
+ throw new Error("Invalid amount");
127
+ }
128
+ return Math.trunc(amount).toString();
129
+ }
130
+ return amount.toString();
131
+ }
132
+
133
+ // src/relayer-web.ts
134
+ var import_bundle = require("@zama-fhe/relayer-sdk/bundle");
135
+ var import_viem2 = require("viem");
136
+ async function createRelayerInstance(config) {
137
+ return (0, import_bundle.createInstance)(config);
138
+ }
139
+ async function createEncryptedAmountInput(relayer, contractAddress, senderAddress, amount) {
140
+ const normalizedContract = (0, import_viem2.getAddress)(contractAddress);
141
+ const normalizedSender = (0, import_viem2.getAddress)(senderAddress);
142
+ const encrypted = await relayer.createEncryptedInput(normalizedContract, normalizedSender).add64(amount).encrypt();
143
+ const handle = typeof encrypted.handles[0] === "string" ? encrypted.handles[0] : (0, import_viem2.toHex)(encrypted.handles[0]);
144
+ const inputProof = typeof encrypted.inputProof === "string" ? encrypted.inputProof : (0, import_viem2.toHex)(encrypted.inputProof);
145
+ return {
146
+ handle,
147
+ inputProof
148
+ };
149
+ }
150
+ async function userDecryptEuint64(relayer, handle, contractAddress, signer, options) {
151
+ const keypair = relayer.generateKeypair();
152
+ const startTimestamp = options?.startTimestamp ?? Math.floor(Date.now() / 1e3).toString();
153
+ const durationDays = options?.durationDays ?? "10";
154
+ const contractAddresses = [contractAddress];
155
+ const eip712 = relayer.createEIP712(keypair.publicKey, contractAddresses, startTimestamp, durationDays);
156
+ const types = { UserDecryptRequestVerification: eip712.types.UserDecryptRequestVerification };
157
+ const sign = signer.signTypedData;
158
+ const signature = sign.length >= 3 ? await sign(eip712.domain, types, eip712.message) : await sign({
159
+ domain: eip712.domain,
160
+ types,
161
+ primaryType: "UserDecryptRequestVerification",
162
+ message: eip712.message
163
+ });
164
+ const result = await relayer.userDecrypt(
165
+ [{ handle, contractAddress }],
166
+ keypair.privateKey,
167
+ keypair.publicKey,
168
+ signature.replace("0x", ""),
169
+ contractAddresses,
170
+ signer.address,
171
+ startTimestamp,
172
+ durationDays
173
+ );
174
+ return result[handle];
175
+ }
176
+ async function publicDecrypt(relayer, handles) {
177
+ const result = await relayer.publicDecrypt(handles);
178
+ return {
179
+ clearValues: result.clearValues,
180
+ decryptionProof: result.decryptionProof
181
+ };
182
+ }
183
+
184
+ // src/balance-web.ts
185
+ var import_viem3 = require("viem");
186
+ var ZERO_HANDLE = "0x" + "00".repeat(32);
187
+ async function viewConfidentialBalance(options) {
188
+ if (!(0, import_viem3.isAddress)(options.tokenAddress)) {
189
+ throw new Error(`Invalid token address: ${options.tokenAddress}`);
190
+ }
191
+ const account = options.account ?? options.signer?.address;
192
+ if (!account || !(0, import_viem3.isAddress)(account)) {
193
+ throw new Error(`Invalid account address: ${account ?? "undefined"}`);
194
+ }
195
+ const publicClient = (0, import_viem3.createPublicClient)({ transport: (0, import_viem3.http)(options.rpcUrl) });
196
+ const confidentialBalanceAbi = [
197
+ {
198
+ inputs: [{ internalType: "address", name: "account", type: "address" }],
199
+ name: "confidentialBalanceOf",
200
+ outputs: [{ internalType: "bytes32", name: "", type: "bytes32" }],
201
+ stateMutability: "view",
202
+ type: "function"
203
+ }
204
+ ];
205
+ const handle = await publicClient.readContract({
206
+ address: options.tokenAddress,
207
+ abi: confidentialBalanceAbi,
208
+ functionName: "confidentialBalanceOf",
209
+ args: [account]
210
+ });
211
+ const shouldDecrypt = options.decrypt ?? true;
212
+ if (!shouldDecrypt) {
213
+ return { handle };
214
+ }
215
+ if (!options.signer) {
216
+ throw new Error("Missing signer for decryption");
217
+ }
218
+ if (handle === ZERO_HANDLE) {
219
+ return { handle, balance: 0n };
220
+ }
221
+ const balance = await userDecryptEuint64(options.relayer, handle, options.tokenAddress, options.signer);
222
+ return { handle, balance };
223
+ }
224
+
225
+ // src/transfer-web.ts
226
+ var import_viem4 = require("viem");
227
+ async function viewConfidentialTransferAmounts(options) {
228
+ if (!(0, import_viem4.isAddress)(options.tokenAddress)) {
229
+ throw new Error(`Invalid token address: ${options.tokenAddress}`);
230
+ }
231
+ if (!(0, import_viem4.isHex)(options.txHash, { strict: true })) {
232
+ throw new Error(`Invalid transaction hash: ${options.txHash}`);
233
+ }
234
+ if (options.from && !(0, import_viem4.isAddress)(options.from)) {
235
+ throw new Error(`Invalid from address: ${options.from}`);
236
+ }
237
+ if (options.to && !(0, import_viem4.isAddress)(options.to)) {
238
+ throw new Error(`Invalid to address: ${options.to}`);
239
+ }
240
+ const publicClient = (0, import_viem4.createPublicClient)({ transport: (0, import_viem4.http)(options.rpcUrl) });
241
+ const receipt = await publicClient.getTransactionReceipt({
242
+ hash: options.txHash
243
+ });
244
+ const tokenAddress = (0, import_viem4.getAddress)(options.tokenAddress);
245
+ const fromFilter = options.from ? (0, import_viem4.getAddress)(options.from) : void 0;
246
+ const toFilter = options.to ? (0, import_viem4.getAddress)(options.to) : void 0;
247
+ const logs = receipt.logs.filter((log) => (0, import_viem4.getAddress)(log.address) === tokenAddress);
248
+ const transfers = [];
249
+ for (const log of logs) {
250
+ try {
251
+ const decoded = (0, import_viem4.decodeEventLog)({
252
+ abi: confidentialTokenAbi,
253
+ eventName: "ConfidentialPaymentExecuted",
254
+ data: log.data,
255
+ topics: log.topics
256
+ });
257
+ const args = decoded.args;
258
+ const entry = {
259
+ holder: (0, import_viem4.getAddress)(args.holder),
260
+ payee: (0, import_viem4.getAddress)(args.payee),
261
+ maxClearAmount: BigInt(args.maxClearAmount),
262
+ resourceHash: args.resourceHash,
263
+ nonce: args.nonce,
264
+ handle: args.transferredAmount
265
+ };
266
+ if (fromFilter && entry.holder !== fromFilter) {
267
+ continue;
268
+ }
269
+ if (toFilter && entry.payee !== toFilter) {
270
+ continue;
271
+ }
272
+ const shouldDecrypt = options.decrypt ?? true;
273
+ if (shouldDecrypt) {
274
+ if (!options.signer) {
275
+ throw new Error("Missing signer for decryption");
276
+ }
277
+ const signerAddress = (0, import_viem4.getAddress)(options.signer.address);
278
+ if (signerAddress !== (0, import_viem4.getAddress)(entry.holder) && signerAddress !== (0, import_viem4.getAddress)(entry.payee)) {
279
+ throw new Error("Signer must be the holder or payee to decrypt transfer amount");
280
+ }
281
+ entry.amount = await userDecryptEuint64(
282
+ options.relayer,
283
+ entry.handle,
284
+ tokenAddress,
285
+ options.signer
286
+ );
287
+ }
288
+ transfers.push(entry);
289
+ } catch (error) {
290
+ if (error instanceof Error && error.message.includes("ConfidentialPaymentExecuted")) {
291
+ throw error;
292
+ }
293
+ }
294
+ }
295
+ return transfers;
296
+ }
297
+ // Annotate the CommonJS export names for ESM import in node:
298
+ 0 && (module.exports = {
299
+ SepoliaConfig,
300
+ confidentialPaymentTypes,
301
+ confidentialTokenAbi,
302
+ createEncryptedAmountInput,
303
+ createNonce,
304
+ createRelayerInstance,
305
+ hashEncryptedAmountInput,
306
+ initSDK,
307
+ normalizeAmount,
308
+ publicDecrypt,
309
+ userDecryptEuint64,
310
+ viewConfidentialBalance,
311
+ viewConfidentialTransferAmounts
312
+ });
package/dist/web.mjs ADDED
@@ -0,0 +1,187 @@
1
+ import {
2
+ confidentialPaymentTypes,
3
+ confidentialTokenAbi,
4
+ createNonce,
5
+ hashEncryptedAmountInput,
6
+ normalizeAmount
7
+ } from "./chunk-V7Z3OAXS.mjs";
8
+
9
+ // src/relayer-web.ts
10
+ import { createInstance, initSDK, SepoliaConfig } from "@zama-fhe/relayer-sdk/bundle";
11
+ import { getAddress, toHex } from "viem";
12
+ async function createRelayerInstance(config) {
13
+ return createInstance(config);
14
+ }
15
+ async function createEncryptedAmountInput(relayer, contractAddress, senderAddress, amount) {
16
+ const normalizedContract = getAddress(contractAddress);
17
+ const normalizedSender = getAddress(senderAddress);
18
+ const encrypted = await relayer.createEncryptedInput(normalizedContract, normalizedSender).add64(amount).encrypt();
19
+ const handle = typeof encrypted.handles[0] === "string" ? encrypted.handles[0] : toHex(encrypted.handles[0]);
20
+ const inputProof = typeof encrypted.inputProof === "string" ? encrypted.inputProof : toHex(encrypted.inputProof);
21
+ return {
22
+ handle,
23
+ inputProof
24
+ };
25
+ }
26
+ async function userDecryptEuint64(relayer, handle, contractAddress, signer, options) {
27
+ const keypair = relayer.generateKeypair();
28
+ const startTimestamp = options?.startTimestamp ?? Math.floor(Date.now() / 1e3).toString();
29
+ const durationDays = options?.durationDays ?? "10";
30
+ const contractAddresses = [contractAddress];
31
+ const eip712 = relayer.createEIP712(keypair.publicKey, contractAddresses, startTimestamp, durationDays);
32
+ const types = { UserDecryptRequestVerification: eip712.types.UserDecryptRequestVerification };
33
+ const sign = signer.signTypedData;
34
+ const signature = sign.length >= 3 ? await sign(eip712.domain, types, eip712.message) : await sign({
35
+ domain: eip712.domain,
36
+ types,
37
+ primaryType: "UserDecryptRequestVerification",
38
+ message: eip712.message
39
+ });
40
+ const result = await relayer.userDecrypt(
41
+ [{ handle, contractAddress }],
42
+ keypair.privateKey,
43
+ keypair.publicKey,
44
+ signature.replace("0x", ""),
45
+ contractAddresses,
46
+ signer.address,
47
+ startTimestamp,
48
+ durationDays
49
+ );
50
+ return result[handle];
51
+ }
52
+ async function publicDecrypt(relayer, handles) {
53
+ const result = await relayer.publicDecrypt(handles);
54
+ return {
55
+ clearValues: result.clearValues,
56
+ decryptionProof: result.decryptionProof
57
+ };
58
+ }
59
+
60
+ // src/balance-web.ts
61
+ import { createPublicClient, http, isAddress } from "viem";
62
+ var ZERO_HANDLE = "0x" + "00".repeat(32);
63
+ async function viewConfidentialBalance(options) {
64
+ if (!isAddress(options.tokenAddress)) {
65
+ throw new Error(`Invalid token address: ${options.tokenAddress}`);
66
+ }
67
+ const account = options.account ?? options.signer?.address;
68
+ if (!account || !isAddress(account)) {
69
+ throw new Error(`Invalid account address: ${account ?? "undefined"}`);
70
+ }
71
+ const publicClient = createPublicClient({ transport: http(options.rpcUrl) });
72
+ const confidentialBalanceAbi = [
73
+ {
74
+ inputs: [{ internalType: "address", name: "account", type: "address" }],
75
+ name: "confidentialBalanceOf",
76
+ outputs: [{ internalType: "bytes32", name: "", type: "bytes32" }],
77
+ stateMutability: "view",
78
+ type: "function"
79
+ }
80
+ ];
81
+ const handle = await publicClient.readContract({
82
+ address: options.tokenAddress,
83
+ abi: confidentialBalanceAbi,
84
+ functionName: "confidentialBalanceOf",
85
+ args: [account]
86
+ });
87
+ const shouldDecrypt = options.decrypt ?? true;
88
+ if (!shouldDecrypt) {
89
+ return { handle };
90
+ }
91
+ if (!options.signer) {
92
+ throw new Error("Missing signer for decryption");
93
+ }
94
+ if (handle === ZERO_HANDLE) {
95
+ return { handle, balance: 0n };
96
+ }
97
+ const balance = await userDecryptEuint64(options.relayer, handle, options.tokenAddress, options.signer);
98
+ return { handle, balance };
99
+ }
100
+
101
+ // src/transfer-web.ts
102
+ import { createPublicClient as createPublicClient2, decodeEventLog, getAddress as getAddress2, http as http2, isAddress as isAddress2, isHex } from "viem";
103
+ async function viewConfidentialTransferAmounts(options) {
104
+ if (!isAddress2(options.tokenAddress)) {
105
+ throw new Error(`Invalid token address: ${options.tokenAddress}`);
106
+ }
107
+ if (!isHex(options.txHash, { strict: true })) {
108
+ throw new Error(`Invalid transaction hash: ${options.txHash}`);
109
+ }
110
+ if (options.from && !isAddress2(options.from)) {
111
+ throw new Error(`Invalid from address: ${options.from}`);
112
+ }
113
+ if (options.to && !isAddress2(options.to)) {
114
+ throw new Error(`Invalid to address: ${options.to}`);
115
+ }
116
+ const publicClient = createPublicClient2({ transport: http2(options.rpcUrl) });
117
+ const receipt = await publicClient.getTransactionReceipt({
118
+ hash: options.txHash
119
+ });
120
+ const tokenAddress = getAddress2(options.tokenAddress);
121
+ const fromFilter = options.from ? getAddress2(options.from) : void 0;
122
+ const toFilter = options.to ? getAddress2(options.to) : void 0;
123
+ const logs = receipt.logs.filter((log) => getAddress2(log.address) === tokenAddress);
124
+ const transfers = [];
125
+ for (const log of logs) {
126
+ try {
127
+ const decoded = decodeEventLog({
128
+ abi: confidentialTokenAbi,
129
+ eventName: "ConfidentialPaymentExecuted",
130
+ data: log.data,
131
+ topics: log.topics
132
+ });
133
+ const args = decoded.args;
134
+ const entry = {
135
+ holder: getAddress2(args.holder),
136
+ payee: getAddress2(args.payee),
137
+ maxClearAmount: BigInt(args.maxClearAmount),
138
+ resourceHash: args.resourceHash,
139
+ nonce: args.nonce,
140
+ handle: args.transferredAmount
141
+ };
142
+ if (fromFilter && entry.holder !== fromFilter) {
143
+ continue;
144
+ }
145
+ if (toFilter && entry.payee !== toFilter) {
146
+ continue;
147
+ }
148
+ const shouldDecrypt = options.decrypt ?? true;
149
+ if (shouldDecrypt) {
150
+ if (!options.signer) {
151
+ throw new Error("Missing signer for decryption");
152
+ }
153
+ const signerAddress = getAddress2(options.signer.address);
154
+ if (signerAddress !== getAddress2(entry.holder) && signerAddress !== getAddress2(entry.payee)) {
155
+ throw new Error("Signer must be the holder or payee to decrypt transfer amount");
156
+ }
157
+ entry.amount = await userDecryptEuint64(
158
+ options.relayer,
159
+ entry.handle,
160
+ tokenAddress,
161
+ options.signer
162
+ );
163
+ }
164
+ transfers.push(entry);
165
+ } catch (error) {
166
+ if (error instanceof Error && error.message.includes("ConfidentialPaymentExecuted")) {
167
+ throw error;
168
+ }
169
+ }
170
+ }
171
+ return transfers;
172
+ }
173
+ export {
174
+ SepoliaConfig,
175
+ confidentialPaymentTypes,
176
+ confidentialTokenAbi,
177
+ createEncryptedAmountInput,
178
+ createNonce,
179
+ createRelayerInstance,
180
+ hashEncryptedAmountInput,
181
+ initSDK,
182
+ normalizeAmount,
183
+ publicDecrypt,
184
+ userDecryptEuint64,
185
+ viewConfidentialBalance,
186
+ viewConfidentialTransferAmounts
187
+ };
package/package.json ADDED
@@ -0,0 +1,36 @@
1
+ {
2
+ "name": "x402z-shared",
3
+ "version": "0.0.1",
4
+ "main": "./dist/index.js",
5
+ "module": "./dist/index.mjs",
6
+ "types": "./dist/index.d.ts",
7
+ "files": [
8
+ "dist"
9
+ ],
10
+ "exports": {
11
+ ".": {
12
+ "types": "./dist/index.d.ts",
13
+ "import": "./dist/index.mjs",
14
+ "require": "./dist/index.js"
15
+ },
16
+ "./web": {
17
+ "types": "./dist/web.d.ts",
18
+ "import": "./dist/web.mjs",
19
+ "require": "./dist/web.js"
20
+ }
21
+ },
22
+ "dependencies": {
23
+ "@x402/core": "^2.0.0",
24
+ "viem": "^2.39.3",
25
+ "@zama-fhe/relayer-sdk": "^0.3.0-5"
26
+ },
27
+ "devDependencies": {
28
+ "jest": "^29.7.0",
29
+ "ts-jest": "^29.2.5",
30
+ "@types/jest": "^29.5.12"
31
+ },
32
+ "scripts": {
33
+ "build": "tsup src/index.ts src/web.ts --format cjs,esm --dts",
34
+ "test": "jest"
35
+ }
36
+ }