x402z-shared-web 0.0.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/README.md +93 -0
- package/dist/index.d.mts +391 -0
- package/dist/index.d.ts +391 -0
- package/dist/index.js +573 -0
- package/dist/index.mjs +531 -0
- package/package.json +31 -0
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,531 @@
|
|
|
1
|
+
// src/core/abi.ts
|
|
2
|
+
var confidentialTokenAbi = [
|
|
3
|
+
{
|
|
4
|
+
inputs: [
|
|
5
|
+
{ internalType: "address", name: "to", type: "address" },
|
|
6
|
+
{ internalType: "bytes32", name: "encryptedAmountInput", type: "bytes32" },
|
|
7
|
+
{ internalType: "bytes", name: "inputProof", type: "bytes" }
|
|
8
|
+
],
|
|
9
|
+
name: "confidentialTransfer",
|
|
10
|
+
outputs: [{ internalType: "euint64", name: "transferred", type: "bytes32" }],
|
|
11
|
+
stateMutability: "nonpayable",
|
|
12
|
+
type: "function"
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
inputs: [
|
|
16
|
+
{
|
|
17
|
+
components: [
|
|
18
|
+
{ internalType: "address", name: "holder", type: "address" },
|
|
19
|
+
{ internalType: "address", name: "payee", type: "address" },
|
|
20
|
+
{ internalType: "uint256", name: "maxClearAmount", type: "uint256" },
|
|
21
|
+
{ internalType: "bytes32", name: "resourceHash", type: "bytes32" },
|
|
22
|
+
{ internalType: "uint48", name: "validAfter", type: "uint48" },
|
|
23
|
+
{ internalType: "uint48", name: "validBefore", type: "uint48" },
|
|
24
|
+
{ internalType: "bytes32", name: "nonce", type: "bytes32" },
|
|
25
|
+
{ internalType: "bytes32", name: "encryptedAmountHash", type: "bytes32" }
|
|
26
|
+
],
|
|
27
|
+
internalType: "struct FHEToken.ConfidentialPayment",
|
|
28
|
+
name: "p",
|
|
29
|
+
type: "tuple"
|
|
30
|
+
},
|
|
31
|
+
{ internalType: "externalEuint64", name: "encryptedAmountInput", type: "bytes32" },
|
|
32
|
+
{ internalType: "bytes", name: "inputProof", type: "bytes" },
|
|
33
|
+
{ internalType: "bytes", name: "sig", type: "bytes" }
|
|
34
|
+
],
|
|
35
|
+
name: "confidentialTransferWithAuthorization",
|
|
36
|
+
outputs: [{ internalType: "euint64", name: "transferred", type: "bytes32" }],
|
|
37
|
+
stateMutability: "nonpayable",
|
|
38
|
+
type: "function"
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
inputs: [
|
|
42
|
+
{ internalType: "address", name: "to", type: "address" },
|
|
43
|
+
{ internalType: "uint256", name: "amount", type: "uint256" }
|
|
44
|
+
],
|
|
45
|
+
name: "wrap",
|
|
46
|
+
outputs: [],
|
|
47
|
+
stateMutability: "nonpayable",
|
|
48
|
+
type: "function"
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
inputs: [
|
|
52
|
+
{ internalType: "address", name: "from", type: "address" },
|
|
53
|
+
{ internalType: "address", name: "to", type: "address" },
|
|
54
|
+
{ internalType: "bytes32", name: "encryptedAmountInput", type: "bytes32" },
|
|
55
|
+
{ internalType: "bytes", name: "inputProof", type: "bytes" }
|
|
56
|
+
],
|
|
57
|
+
name: "unwrap",
|
|
58
|
+
outputs: [],
|
|
59
|
+
stateMutability: "nonpayable",
|
|
60
|
+
type: "function"
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
anonymous: false,
|
|
64
|
+
inputs: [
|
|
65
|
+
{ indexed: true, internalType: "address", name: "holder", type: "address" },
|
|
66
|
+
{ indexed: true, internalType: "address", name: "payee", type: "address" },
|
|
67
|
+
{ indexed: false, internalType: "uint256", name: "maxClearAmount", type: "uint256" },
|
|
68
|
+
{ indexed: true, internalType: "bytes32", name: "resourceHash", type: "bytes32" },
|
|
69
|
+
{ indexed: false, internalType: "bytes32", name: "nonce", type: "bytes32" },
|
|
70
|
+
{ indexed: false, internalType: "bytes32", name: "transferredAmount", type: "bytes32" }
|
|
71
|
+
],
|
|
72
|
+
name: "ConfidentialPaymentExecuted",
|
|
73
|
+
type: "event"
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
inputs: [
|
|
77
|
+
{ internalType: "address", name: "", type: "address" },
|
|
78
|
+
{ internalType: "bytes32", name: "", type: "bytes32" }
|
|
79
|
+
],
|
|
80
|
+
name: "usedNonces",
|
|
81
|
+
outputs: [{ internalType: "bool", name: "", type: "bool" }],
|
|
82
|
+
stateMutability: "view",
|
|
83
|
+
type: "function"
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
inputs: [{ internalType: "address", name: "account", type: "address" }],
|
|
87
|
+
name: "observer",
|
|
88
|
+
outputs: [{ internalType: "address", name: "", type: "address" }],
|
|
89
|
+
stateMutability: "view",
|
|
90
|
+
type: "function"
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
inputs: [
|
|
94
|
+
{ internalType: "address", name: "account", type: "address" },
|
|
95
|
+
{ internalType: "address", name: "newObserver", type: "address" }
|
|
96
|
+
],
|
|
97
|
+
name: "setObserver",
|
|
98
|
+
outputs: [],
|
|
99
|
+
stateMutability: "nonpayable",
|
|
100
|
+
type: "function"
|
|
101
|
+
}
|
|
102
|
+
];
|
|
103
|
+
|
|
104
|
+
// src/core/constants.ts
|
|
105
|
+
var confidentialPaymentTypes = {
|
|
106
|
+
ConfidentialPayment: [
|
|
107
|
+
{ name: "holder", type: "address" },
|
|
108
|
+
{ name: "payee", type: "address" },
|
|
109
|
+
{ name: "maxClearAmount", type: "uint256" },
|
|
110
|
+
{ name: "resourceHash", type: "bytes32" },
|
|
111
|
+
{ name: "validAfter", type: "uint48" },
|
|
112
|
+
{ name: "validBefore", type: "uint48" },
|
|
113
|
+
{ name: "nonce", type: "bytes32" },
|
|
114
|
+
{ name: "encryptedAmountHash", type: "bytes32" }
|
|
115
|
+
]
|
|
116
|
+
};
|
|
117
|
+
var confidentialErrorCodes = {
|
|
118
|
+
observerNotAuthorized: "observer_not_authorized"
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
// src/core/utils.ts
|
|
122
|
+
import { encodeAbiParameters, keccak256, toHex } from "viem";
|
|
123
|
+
function createNonce() {
|
|
124
|
+
const cryptoObj = typeof globalThis.crypto !== "undefined" ? globalThis.crypto : globalThis.crypto;
|
|
125
|
+
if (!cryptoObj) {
|
|
126
|
+
throw new Error("Crypto API not available");
|
|
127
|
+
}
|
|
128
|
+
return toHex(cryptoObj.getRandomValues(new Uint8Array(32)));
|
|
129
|
+
}
|
|
130
|
+
function hashEncryptedAmountInput(encryptedAmountInput) {
|
|
131
|
+
return keccak256(
|
|
132
|
+
encodeAbiParameters([{ type: "bytes32" }], [encryptedAmountInput])
|
|
133
|
+
);
|
|
134
|
+
}
|
|
135
|
+
function normalizeAmount(amount) {
|
|
136
|
+
if (typeof amount === "string") {
|
|
137
|
+
return amount;
|
|
138
|
+
}
|
|
139
|
+
if (typeof amount === "number") {
|
|
140
|
+
if (!Number.isFinite(amount)) {
|
|
141
|
+
throw new Error("Invalid amount");
|
|
142
|
+
}
|
|
143
|
+
return Math.trunc(amount).toString();
|
|
144
|
+
}
|
|
145
|
+
return amount.toString();
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// src/relayer/index.ts
|
|
149
|
+
import { getAddress, toHex as toHex2 } from "viem";
|
|
150
|
+
var relayerSdk = null;
|
|
151
|
+
var SepoliaConfig;
|
|
152
|
+
async function getRelayerSdk() {
|
|
153
|
+
if (relayerSdk) {
|
|
154
|
+
return relayerSdk;
|
|
155
|
+
}
|
|
156
|
+
throw new Error(
|
|
157
|
+
"Relayer SDK not configured. Call configureRelayerSdk() with the CDN module before initSDK/createRelayer."
|
|
158
|
+
);
|
|
159
|
+
}
|
|
160
|
+
function configureRelayerSdk(sdk) {
|
|
161
|
+
relayerSdk = sdk;
|
|
162
|
+
SepoliaConfig = sdk.SepoliaConfig;
|
|
163
|
+
}
|
|
164
|
+
function getSepoliaConfig() {
|
|
165
|
+
if (!SepoliaConfig) {
|
|
166
|
+
throw new Error("SepoliaConfig is not available; call configureRelayerSdk or initSDK first");
|
|
167
|
+
}
|
|
168
|
+
return SepoliaConfig;
|
|
169
|
+
}
|
|
170
|
+
async function createRelayer(config) {
|
|
171
|
+
const sdk = await getRelayerSdk();
|
|
172
|
+
const instance = await sdk.createInstance(config);
|
|
173
|
+
if (typeof config.network === "string") {
|
|
174
|
+
instance.network = config.network;
|
|
175
|
+
}
|
|
176
|
+
return instance;
|
|
177
|
+
}
|
|
178
|
+
async function initSDK(params) {
|
|
179
|
+
const sdk = await getRelayerSdk();
|
|
180
|
+
return sdk.initSDK(params);
|
|
181
|
+
}
|
|
182
|
+
async function createEncryptedAmountInput(relayer, contractAddress, senderAddress, amount) {
|
|
183
|
+
const normalizedContract = getAddress(contractAddress);
|
|
184
|
+
const normalizedSender = getAddress(senderAddress);
|
|
185
|
+
const encrypted = await relayer.createEncryptedInput(normalizedContract, normalizedSender).add64(amount).encrypt();
|
|
186
|
+
const handle = typeof encrypted.handles[0] === "string" ? encrypted.handles[0] : toHex2(encrypted.handles[0]);
|
|
187
|
+
const inputProof = typeof encrypted.inputProof === "string" ? encrypted.inputProof : toHex2(encrypted.inputProof);
|
|
188
|
+
return {
|
|
189
|
+
handle,
|
|
190
|
+
inputProof
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
async function decryptEuint64(relayer, handle, contractAddress, signer, options) {
|
|
194
|
+
const keypair = relayer.generateKeypair();
|
|
195
|
+
const startTimestamp = options?.startTimestamp ?? Math.floor(Date.now() / 1e3).toString();
|
|
196
|
+
const durationDays = options?.durationDays ?? "10";
|
|
197
|
+
const contractAddresses = [contractAddress];
|
|
198
|
+
const eip712 = relayer.createEIP712(keypair.publicKey, contractAddresses, startTimestamp, durationDays);
|
|
199
|
+
const types = { UserDecryptRequestVerification: eip712.types.UserDecryptRequestVerification };
|
|
200
|
+
const sign = signer.signTypedData;
|
|
201
|
+
const signature = sign.length >= 3 ? await sign(eip712.domain, types, eip712.message) : await sign({
|
|
202
|
+
domain: eip712.domain,
|
|
203
|
+
types,
|
|
204
|
+
primaryType: "UserDecryptRequestVerification",
|
|
205
|
+
message: eip712.message
|
|
206
|
+
});
|
|
207
|
+
const result = await relayer.userDecrypt(
|
|
208
|
+
[{ handle, contractAddress }],
|
|
209
|
+
keypair.privateKey,
|
|
210
|
+
keypair.publicKey,
|
|
211
|
+
signature.replace("0x", ""),
|
|
212
|
+
contractAddresses,
|
|
213
|
+
signer.address,
|
|
214
|
+
startTimestamp,
|
|
215
|
+
durationDays
|
|
216
|
+
);
|
|
217
|
+
return result[handle];
|
|
218
|
+
}
|
|
219
|
+
async function publicDecrypt(relayer, handles) {
|
|
220
|
+
const result = await relayer.publicDecrypt(handles);
|
|
221
|
+
return {
|
|
222
|
+
clearValues: result.clearValues,
|
|
223
|
+
decryptionProof: result.decryptionProof
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
// src/token/transfer.ts
|
|
228
|
+
import { createPublicClient, decodeEventLog, getAddress as getAddress2, http, isAddress, isHex, isAddressEqual } from "viem";
|
|
229
|
+
async function getTransferAmounts(options) {
|
|
230
|
+
if (!isAddress(options.tokenAddress)) {
|
|
231
|
+
throw new Error(`Invalid token address: ${options.tokenAddress}`);
|
|
232
|
+
}
|
|
233
|
+
if (!isHex(options.txHash, { strict: true })) {
|
|
234
|
+
throw new Error(`Invalid transaction hash: ${options.txHash}`);
|
|
235
|
+
}
|
|
236
|
+
if (options.from && !isAddress(options.from)) {
|
|
237
|
+
throw new Error(`Invalid from address: ${options.from}`);
|
|
238
|
+
}
|
|
239
|
+
if (options.to && !isAddress(options.to)) {
|
|
240
|
+
throw new Error(`Invalid to address: ${options.to}`);
|
|
241
|
+
}
|
|
242
|
+
const publicClient = createPublicClient({ transport: http(options.rpcUrl) });
|
|
243
|
+
const receipt = await publicClient.getTransactionReceipt({
|
|
244
|
+
hash: options.txHash
|
|
245
|
+
});
|
|
246
|
+
const tokenAddress = getAddress2(options.tokenAddress);
|
|
247
|
+
const fromFilter = options.from ? getAddress2(options.from) : void 0;
|
|
248
|
+
const toFilter = options.to ? getAddress2(options.to) : void 0;
|
|
249
|
+
const logs = receipt.logs.filter((log) => getAddress2(log.address) === tokenAddress);
|
|
250
|
+
const transfers = [];
|
|
251
|
+
for (const log of logs) {
|
|
252
|
+
try {
|
|
253
|
+
const decoded = decodeEventLog({
|
|
254
|
+
abi: confidentialTokenAbi,
|
|
255
|
+
eventName: "ConfidentialPaymentExecuted",
|
|
256
|
+
data: log.data,
|
|
257
|
+
topics: log.topics
|
|
258
|
+
});
|
|
259
|
+
const args = decoded.args;
|
|
260
|
+
const entry = {
|
|
261
|
+
holder: getAddress2(args.holder),
|
|
262
|
+
payee: getAddress2(args.payee),
|
|
263
|
+
maxClearAmount: BigInt(args.maxClearAmount),
|
|
264
|
+
resourceHash: args.resourceHash,
|
|
265
|
+
nonce: args.nonce,
|
|
266
|
+
handle: args.transferredAmount
|
|
267
|
+
};
|
|
268
|
+
if (fromFilter && entry.holder !== fromFilter) {
|
|
269
|
+
continue;
|
|
270
|
+
}
|
|
271
|
+
if (toFilter && entry.payee !== toFilter) {
|
|
272
|
+
continue;
|
|
273
|
+
}
|
|
274
|
+
const shouldDecrypt = options.decrypt ?? true;
|
|
275
|
+
if (shouldDecrypt) {
|
|
276
|
+
if (!options.signer) {
|
|
277
|
+
throw new Error("Missing signer for decryption");
|
|
278
|
+
}
|
|
279
|
+
const signerAddress = getAddress2(options.signer.address);
|
|
280
|
+
const holderAddress = getAddress2(entry.holder);
|
|
281
|
+
const payeeAddress = getAddress2(entry.payee);
|
|
282
|
+
if (!isAddressEqual(signerAddress, holderAddress) && !isAddressEqual(signerAddress, payeeAddress)) {
|
|
283
|
+
const [holderObserver, payeeObserver] = await Promise.all([
|
|
284
|
+
publicClient.readContract({
|
|
285
|
+
address: tokenAddress,
|
|
286
|
+
abi: confidentialTokenAbi,
|
|
287
|
+
functionName: "observer",
|
|
288
|
+
args: [holderAddress]
|
|
289
|
+
}),
|
|
290
|
+
publicClient.readContract({
|
|
291
|
+
address: tokenAddress,
|
|
292
|
+
abi: confidentialTokenAbi,
|
|
293
|
+
functionName: "observer",
|
|
294
|
+
args: [payeeAddress]
|
|
295
|
+
})
|
|
296
|
+
]);
|
|
297
|
+
const allowed = holderObserver && isAddressEqual(holderObserver, signerAddress) || payeeObserver && isAddressEqual(payeeObserver, signerAddress);
|
|
298
|
+
if (!allowed) {
|
|
299
|
+
throw new Error(confidentialErrorCodes.observerNotAuthorized);
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
entry.amount = await decryptEuint64(
|
|
303
|
+
options.relayer,
|
|
304
|
+
entry.handle,
|
|
305
|
+
tokenAddress,
|
|
306
|
+
options.signer
|
|
307
|
+
);
|
|
308
|
+
}
|
|
309
|
+
transfers.push(entry);
|
|
310
|
+
} catch (error) {
|
|
311
|
+
if (error instanceof Error && error.message.includes("ConfidentialPaymentExecuted")) {
|
|
312
|
+
throw error;
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
return transfers;
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
// src/token/token.ts
|
|
320
|
+
import { getAddress as getAddress5, isAddress as isAddress4 } from "viem";
|
|
321
|
+
|
|
322
|
+
// src/token/balance.ts
|
|
323
|
+
import { createPublicClient as createPublicClient2, getAddress as getAddress3, http as http2, isAddress as isAddress2, isAddressEqual as isAddressEqual2 } from "viem";
|
|
324
|
+
var ZERO_HANDLE = "0x" + "00".repeat(32);
|
|
325
|
+
async function readBalance(options) {
|
|
326
|
+
if (!isAddress2(options.tokenAddress)) {
|
|
327
|
+
throw new Error(`Invalid token address: ${options.tokenAddress}`);
|
|
328
|
+
}
|
|
329
|
+
const account = options.account ?? options.signer?.address;
|
|
330
|
+
if (!account || !isAddress2(account)) {
|
|
331
|
+
throw new Error(`Invalid account address: ${account ?? "undefined"}`);
|
|
332
|
+
}
|
|
333
|
+
const publicClient = createPublicClient2({ transport: http2(options.rpcUrl) });
|
|
334
|
+
const confidentialBalanceAbi = [
|
|
335
|
+
{
|
|
336
|
+
inputs: [{ internalType: "address", name: "account", type: "address" }],
|
|
337
|
+
name: "confidentialBalanceOf",
|
|
338
|
+
outputs: [{ internalType: "bytes32", name: "", type: "bytes32" }],
|
|
339
|
+
stateMutability: "view",
|
|
340
|
+
type: "function"
|
|
341
|
+
}
|
|
342
|
+
];
|
|
343
|
+
const handle = await publicClient.readContract({
|
|
344
|
+
address: options.tokenAddress,
|
|
345
|
+
abi: confidentialBalanceAbi,
|
|
346
|
+
functionName: "confidentialBalanceOf",
|
|
347
|
+
args: [account]
|
|
348
|
+
});
|
|
349
|
+
const shouldDecrypt = options.decrypt ?? true;
|
|
350
|
+
if (!shouldDecrypt) {
|
|
351
|
+
return { handle };
|
|
352
|
+
}
|
|
353
|
+
if (!options.signer) {
|
|
354
|
+
throw new Error("Missing signer for decryption");
|
|
355
|
+
}
|
|
356
|
+
const signerAddress = getAddress3(options.signer.address);
|
|
357
|
+
if (!isAddressEqual2(signerAddress, getAddress3(account))) {
|
|
358
|
+
const observer = await publicClient.readContract({
|
|
359
|
+
address: options.tokenAddress,
|
|
360
|
+
abi: confidentialTokenAbi,
|
|
361
|
+
functionName: "observer",
|
|
362
|
+
args: [account]
|
|
363
|
+
});
|
|
364
|
+
if (!observer || !isAddressEqual2(observer, signerAddress)) {
|
|
365
|
+
throw new Error(confidentialErrorCodes.observerNotAuthorized);
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
if (handle === ZERO_HANDLE) {
|
|
369
|
+
return { handle, balance: 0n };
|
|
370
|
+
}
|
|
371
|
+
const balance = await decryptEuint64(options.relayer, handle, options.tokenAddress, options.signer);
|
|
372
|
+
return { handle, balance };
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
// src/token/observer.ts
|
|
376
|
+
import { getAddress as getAddress4, isAddress as isAddress3 } from "viem";
|
|
377
|
+
async function setObserver(options) {
|
|
378
|
+
if (!isAddress3(options.tokenAddress)) {
|
|
379
|
+
throw new Error(`Invalid token address: ${options.tokenAddress}`);
|
|
380
|
+
}
|
|
381
|
+
if (!isAddress3(options.account)) {
|
|
382
|
+
throw new Error(`Invalid account address: ${options.account}`);
|
|
383
|
+
}
|
|
384
|
+
if (!isAddress3(options.observer)) {
|
|
385
|
+
throw new Error(`Invalid observer address: ${options.observer}`);
|
|
386
|
+
}
|
|
387
|
+
return options.walletClient.writeContract({
|
|
388
|
+
address: getAddress4(options.tokenAddress),
|
|
389
|
+
abi: confidentialTokenAbi,
|
|
390
|
+
functionName: "setObserver",
|
|
391
|
+
args: [getAddress4(options.account), getAddress4(options.observer)],
|
|
392
|
+
chain: options.walletClient.chain ?? null,
|
|
393
|
+
account: options.signer ?? options.walletClient.account ?? null
|
|
394
|
+
});
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
// src/token/token.ts
|
|
398
|
+
function assertAddress(value, label) {
|
|
399
|
+
if (!isAddress4(value)) {
|
|
400
|
+
throw new Error(`Invalid ${label}: ${value}`);
|
|
401
|
+
}
|
|
402
|
+
return getAddress5(value);
|
|
403
|
+
}
|
|
404
|
+
function resolveSignerAddress(signer, walletClient) {
|
|
405
|
+
if (signer?.address) {
|
|
406
|
+
return assertAddress(signer.address, "signer address");
|
|
407
|
+
}
|
|
408
|
+
const account = walletClient.account;
|
|
409
|
+
if (typeof account === "string") {
|
|
410
|
+
return assertAddress(account, "wallet address");
|
|
411
|
+
}
|
|
412
|
+
if (account && typeof account === "object" && "address" in account && account.address) {
|
|
413
|
+
return assertAddress(account.address, "wallet address");
|
|
414
|
+
}
|
|
415
|
+
throw new Error("Missing signer address");
|
|
416
|
+
}
|
|
417
|
+
function resolveWriteAccount(signer, walletClient) {
|
|
418
|
+
if (signer?.address) {
|
|
419
|
+
return assertAddress(signer.address, "signer address");
|
|
420
|
+
}
|
|
421
|
+
const account = walletClient.account;
|
|
422
|
+
if (typeof account === "string") {
|
|
423
|
+
return assertAddress(account, "wallet address");
|
|
424
|
+
}
|
|
425
|
+
return account ?? null;
|
|
426
|
+
}
|
|
427
|
+
var ConfidentialToken = class {
|
|
428
|
+
constructor(config) {
|
|
429
|
+
this.rpcUrl = config.rpcUrl;
|
|
430
|
+
this.tokenAddress = config.tokenAddress;
|
|
431
|
+
this.relayer = config.relayer;
|
|
432
|
+
this.walletClient = config.walletClient;
|
|
433
|
+
this.signer = config.signer;
|
|
434
|
+
}
|
|
435
|
+
async balanceOf(account) {
|
|
436
|
+
const result = await readBalance({
|
|
437
|
+
rpcUrl: this.rpcUrl,
|
|
438
|
+
tokenAddress: this.tokenAddress,
|
|
439
|
+
account,
|
|
440
|
+
relayer: this.relayer,
|
|
441
|
+
signer: this.signer,
|
|
442
|
+
decrypt: true
|
|
443
|
+
});
|
|
444
|
+
return result.balance ?? 0n;
|
|
445
|
+
}
|
|
446
|
+
async setObserver(account, observer) {
|
|
447
|
+
return setObserver({
|
|
448
|
+
tokenAddress: this.tokenAddress,
|
|
449
|
+
account,
|
|
450
|
+
observer,
|
|
451
|
+
signer: this.signer?.address ? assertAddress(this.signer.address, "signer address") : void 0,
|
|
452
|
+
walletClient: this.walletClient
|
|
453
|
+
});
|
|
454
|
+
}
|
|
455
|
+
async transfer(to, amount) {
|
|
456
|
+
const tokenAddress = assertAddress(this.tokenAddress, "token address");
|
|
457
|
+
const toAddress = assertAddress(to, "recipient address");
|
|
458
|
+
const fromAddress = resolveSignerAddress(this.signer, this.walletClient);
|
|
459
|
+
if (!Number.isSafeInteger(amount)) {
|
|
460
|
+
throw new Error("Transfer amount must be a safe integer");
|
|
461
|
+
}
|
|
462
|
+
const { handle, inputProof } = await createEncryptedAmountInput(
|
|
463
|
+
this.relayer,
|
|
464
|
+
tokenAddress,
|
|
465
|
+
fromAddress,
|
|
466
|
+
amount
|
|
467
|
+
);
|
|
468
|
+
return this.walletClient.writeContract({
|
|
469
|
+
address: tokenAddress,
|
|
470
|
+
abi: confidentialTokenAbi,
|
|
471
|
+
functionName: "confidentialTransfer",
|
|
472
|
+
args: [toAddress, handle, inputProof],
|
|
473
|
+
chain: this.walletClient.chain ?? null,
|
|
474
|
+
account: resolveWriteAccount(this.signer, this.walletClient)
|
|
475
|
+
});
|
|
476
|
+
}
|
|
477
|
+
async wrap(to, amount) {
|
|
478
|
+
const tokenAddress = assertAddress(this.tokenAddress, "token address");
|
|
479
|
+
const toAddress = assertAddress(to, "recipient address");
|
|
480
|
+
const normalizedAmount = BigInt(normalizeAmount(amount));
|
|
481
|
+
return this.walletClient.writeContract({
|
|
482
|
+
address: tokenAddress,
|
|
483
|
+
abi: confidentialTokenAbi,
|
|
484
|
+
functionName: "wrap",
|
|
485
|
+
args: [toAddress, normalizedAmount],
|
|
486
|
+
chain: this.walletClient.chain ?? null,
|
|
487
|
+
account: resolveWriteAccount(this.signer, this.walletClient)
|
|
488
|
+
});
|
|
489
|
+
}
|
|
490
|
+
async unwrap(from, to, amount) {
|
|
491
|
+
const tokenAddress = assertAddress(this.tokenAddress, "token address");
|
|
492
|
+
const fromAddress = assertAddress(from, "from address");
|
|
493
|
+
const toAddress = assertAddress(to, "to address");
|
|
494
|
+
const signerAddress = resolveSignerAddress(this.signer, this.walletClient);
|
|
495
|
+
if (!Number.isSafeInteger(amount)) {
|
|
496
|
+
throw new Error("Unwrap amount must be a safe integer");
|
|
497
|
+
}
|
|
498
|
+
const { handle, inputProof } = await createEncryptedAmountInput(
|
|
499
|
+
this.relayer,
|
|
500
|
+
tokenAddress,
|
|
501
|
+
signerAddress,
|
|
502
|
+
amount
|
|
503
|
+
);
|
|
504
|
+
return this.walletClient.writeContract({
|
|
505
|
+
address: tokenAddress,
|
|
506
|
+
abi: confidentialTokenAbi,
|
|
507
|
+
functionName: "unwrap",
|
|
508
|
+
args: [fromAddress, toAddress, handle, inputProof],
|
|
509
|
+
chain: this.walletClient.chain ?? null,
|
|
510
|
+
account: resolveWriteAccount(this.signer, this.walletClient)
|
|
511
|
+
});
|
|
512
|
+
}
|
|
513
|
+
};
|
|
514
|
+
export {
|
|
515
|
+
ConfidentialToken,
|
|
516
|
+
SepoliaConfig,
|
|
517
|
+
confidentialErrorCodes,
|
|
518
|
+
confidentialPaymentTypes,
|
|
519
|
+
confidentialTokenAbi,
|
|
520
|
+
configureRelayerSdk,
|
|
521
|
+
createEncryptedAmountInput,
|
|
522
|
+
createNonce,
|
|
523
|
+
createRelayer,
|
|
524
|
+
decryptEuint64,
|
|
525
|
+
getSepoliaConfig,
|
|
526
|
+
getTransferAmounts,
|
|
527
|
+
hashEncryptedAmountInput,
|
|
528
|
+
initSDK,
|
|
529
|
+
normalizeAmount,
|
|
530
|
+
publicDecrypt
|
|
531
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "x402z-shared-web",
|
|
3
|
+
"version": "0.0.9",
|
|
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
|
+
},
|
|
17
|
+
"dependencies": {
|
|
18
|
+
"@x402/core": "^2.0.0",
|
|
19
|
+
"@zama-fhe/relayer-sdk": "0.3.0-8",
|
|
20
|
+
"viem": "^2.39.3"
|
|
21
|
+
},
|
|
22
|
+
"devDependencies": {
|
|
23
|
+
"jest": "^29.7.0",
|
|
24
|
+
"ts-jest": "^29.2.5",
|
|
25
|
+
"@types/jest": "^29.5.12"
|
|
26
|
+
},
|
|
27
|
+
"scripts": {
|
|
28
|
+
"build": "tsup src/index.ts --format cjs,esm --dts",
|
|
29
|
+
"test": "jest"
|
|
30
|
+
}
|
|
31
|
+
}
|