x402z-shared 0.0.1 → 0.0.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/README.md +37 -0
- package/dist/chunk-LTE4V3LT.mjs +156 -0
- package/dist/index.d.mts +4 -35
- package/dist/index.d.ts +4 -35
- package/dist/index.js +95 -3
- package/dist/index.mjs +53 -14
- package/dist/types-gx3OAvqG.d.mts +266 -0
- package/dist/types-gx3OAvqG.d.ts +266 -0
- package/dist/web.d.mts +13 -2
- package/dist/web.d.ts +13 -2
- package/dist/web.js +119 -3
- package/dist/web.mjs +76 -14
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -53,6 +53,10 @@ const result = await viewConfidentialBalance({
|
|
|
53
53
|
console.log(result.balance?.toString());
|
|
54
54
|
```
|
|
55
55
|
|
|
56
|
+
Notes:
|
|
57
|
+
- Balance decryption is allowed for the account or its `observer` (ERC7984ObserverAccess).
|
|
58
|
+
- Unauthorized observer errors throw `confidentialErrorCodes.observerNotAuthorized` (`ConfidentialErrorCode`).
|
|
59
|
+
|
|
56
60
|
## Transfer amount helper (Node)
|
|
57
61
|
|
|
58
62
|
```ts
|
|
@@ -70,6 +74,39 @@ const transfers = await viewConfidentialTransferAmounts({
|
|
|
70
74
|
console.log(transfers[0]?.amount?.toString());
|
|
71
75
|
```
|
|
72
76
|
|
|
77
|
+
Notes:
|
|
78
|
+
- Transfer amount decryption is allowed for `holder`, `payee`, or an `observer` set via `ERC7984ObserverAccess`.
|
|
79
|
+
- Unauthorized observer errors throw `confidentialErrorCodes.observerNotAuthorized` (`ConfidentialErrorCode`).
|
|
80
|
+
|
|
81
|
+
## Observer helper (Node)
|
|
82
|
+
|
|
83
|
+
```ts
|
|
84
|
+
import { setObserver } from "x402z-shared";
|
|
85
|
+
|
|
86
|
+
const txHash = await setObserver({
|
|
87
|
+
rpcUrl: "https://sepolia.infura.io/v3/...",
|
|
88
|
+
tokenAddress: "0xToken",
|
|
89
|
+
account: "0xHolder",
|
|
90
|
+
observer: "0xObserver",
|
|
91
|
+
signer,
|
|
92
|
+
});
|
|
93
|
+
console.log(txHash);
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
## Observer helper (Browser)
|
|
97
|
+
|
|
98
|
+
```ts
|
|
99
|
+
import { setObserverWeb } from "x402z-shared/web";
|
|
100
|
+
|
|
101
|
+
const txHash = await setObserverWeb({
|
|
102
|
+
tokenAddress: "0xToken",
|
|
103
|
+
account: "0xHolder",
|
|
104
|
+
observer: "0xObserver",
|
|
105
|
+
walletClient,
|
|
106
|
+
});
|
|
107
|
+
console.log(txHash);
|
|
108
|
+
```
|
|
109
|
+
|
|
73
110
|
## Balance helper (Browser)
|
|
74
111
|
|
|
75
112
|
```ts
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
// src/abi.ts
|
|
2
|
+
var confidentialTokenAbi = [
|
|
3
|
+
{
|
|
4
|
+
inputs: [
|
|
5
|
+
{
|
|
6
|
+
components: [
|
|
7
|
+
{ internalType: "address", name: "holder", type: "address" },
|
|
8
|
+
{ internalType: "address", name: "payee", type: "address" },
|
|
9
|
+
{ internalType: "uint256", name: "maxClearAmount", type: "uint256" },
|
|
10
|
+
{ internalType: "bytes32", name: "resourceHash", type: "bytes32" },
|
|
11
|
+
{ internalType: "uint48", name: "validAfter", type: "uint48" },
|
|
12
|
+
{ internalType: "uint48", name: "validBefore", type: "uint48" },
|
|
13
|
+
{ internalType: "bytes32", name: "nonce", type: "bytes32" },
|
|
14
|
+
{ internalType: "bytes32", name: "encryptedAmountHash", type: "bytes32" }
|
|
15
|
+
],
|
|
16
|
+
internalType: "struct FHEToken.ConfidentialPayment",
|
|
17
|
+
name: "p",
|
|
18
|
+
type: "tuple"
|
|
19
|
+
},
|
|
20
|
+
{ internalType: "externalEuint64", name: "encryptedAmountInput", type: "bytes32" },
|
|
21
|
+
{ internalType: "bytes", name: "inputProof", type: "bytes" },
|
|
22
|
+
{ internalType: "bytes", name: "sig", type: "bytes" }
|
|
23
|
+
],
|
|
24
|
+
name: "confidentialTransferWithAuthorization",
|
|
25
|
+
outputs: [{ internalType: "euint64", name: "transferred", type: "bytes32" }],
|
|
26
|
+
stateMutability: "nonpayable",
|
|
27
|
+
type: "function"
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
anonymous: false,
|
|
31
|
+
inputs: [
|
|
32
|
+
{ indexed: true, internalType: "address", name: "holder", type: "address" },
|
|
33
|
+
{ indexed: true, internalType: "address", name: "payee", type: "address" },
|
|
34
|
+
{ indexed: false, internalType: "uint256", name: "maxClearAmount", type: "uint256" },
|
|
35
|
+
{ indexed: true, internalType: "bytes32", name: "resourceHash", type: "bytes32" },
|
|
36
|
+
{ indexed: false, internalType: "bytes32", name: "nonce", type: "bytes32" },
|
|
37
|
+
{ indexed: false, internalType: "bytes32", name: "transferredAmount", type: "bytes32" }
|
|
38
|
+
],
|
|
39
|
+
name: "ConfidentialPaymentExecuted",
|
|
40
|
+
type: "event"
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
inputs: [
|
|
44
|
+
{ internalType: "address", name: "", type: "address" },
|
|
45
|
+
{ internalType: "bytes32", name: "", type: "bytes32" }
|
|
46
|
+
],
|
|
47
|
+
name: "usedNonces",
|
|
48
|
+
outputs: [{ internalType: "bool", name: "", type: "bool" }],
|
|
49
|
+
stateMutability: "view",
|
|
50
|
+
type: "function"
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
inputs: [{ internalType: "address", name: "account", type: "address" }],
|
|
54
|
+
name: "observer",
|
|
55
|
+
outputs: [{ internalType: "address", name: "", type: "address" }],
|
|
56
|
+
stateMutability: "view",
|
|
57
|
+
type: "function"
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
inputs: [
|
|
61
|
+
{ internalType: "address", name: "account", type: "address" },
|
|
62
|
+
{ internalType: "address", name: "newObserver", type: "address" }
|
|
63
|
+
],
|
|
64
|
+
name: "setObserver",
|
|
65
|
+
outputs: [],
|
|
66
|
+
stateMutability: "nonpayable",
|
|
67
|
+
type: "function"
|
|
68
|
+
}
|
|
69
|
+
];
|
|
70
|
+
|
|
71
|
+
// src/constants.ts
|
|
72
|
+
var confidentialPaymentTypes = {
|
|
73
|
+
ConfidentialPayment: [
|
|
74
|
+
{ name: "holder", type: "address" },
|
|
75
|
+
{ name: "payee", type: "address" },
|
|
76
|
+
{ name: "maxClearAmount", type: "uint256" },
|
|
77
|
+
{ name: "resourceHash", type: "bytes32" },
|
|
78
|
+
{ name: "validAfter", type: "uint48" },
|
|
79
|
+
{ name: "validBefore", type: "uint48" },
|
|
80
|
+
{ name: "nonce", type: "bytes32" },
|
|
81
|
+
{ name: "encryptedAmountHash", type: "bytes32" }
|
|
82
|
+
]
|
|
83
|
+
};
|
|
84
|
+
var confidentialErrorCodes = {
|
|
85
|
+
observerNotAuthorized: "observer_not_authorized"
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
// src/utils.ts
|
|
89
|
+
import { encodeAbiParameters, keccak256, toHex } from "viem";
|
|
90
|
+
function createNonce() {
|
|
91
|
+
const cryptoObj = typeof globalThis.crypto !== "undefined" ? globalThis.crypto : globalThis.crypto;
|
|
92
|
+
if (!cryptoObj) {
|
|
93
|
+
throw new Error("Crypto API not available");
|
|
94
|
+
}
|
|
95
|
+
return toHex(cryptoObj.getRandomValues(new Uint8Array(32)));
|
|
96
|
+
}
|
|
97
|
+
function hashEncryptedAmountInput(encryptedAmountInput) {
|
|
98
|
+
return keccak256(
|
|
99
|
+
encodeAbiParameters([{ type: "bytes32" }], [encryptedAmountInput])
|
|
100
|
+
);
|
|
101
|
+
}
|
|
102
|
+
function normalizeAmount(amount) {
|
|
103
|
+
if (typeof amount === "string") {
|
|
104
|
+
return amount;
|
|
105
|
+
}
|
|
106
|
+
if (typeof amount === "number") {
|
|
107
|
+
if (!Number.isFinite(amount)) {
|
|
108
|
+
throw new Error("Invalid amount");
|
|
109
|
+
}
|
|
110
|
+
return Math.trunc(amount).toString();
|
|
111
|
+
}
|
|
112
|
+
return amount.toString();
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// src/observer.ts
|
|
116
|
+
import { createPublicClient, getAddress, http, isAddress } from "viem";
|
|
117
|
+
async function setObserver(options) {
|
|
118
|
+
if (!isAddress(options.tokenAddress)) {
|
|
119
|
+
throw new Error(`Invalid token address: ${options.tokenAddress}`);
|
|
120
|
+
}
|
|
121
|
+
if (!isAddress(options.account)) {
|
|
122
|
+
throw new Error(`Invalid account address: ${options.account}`);
|
|
123
|
+
}
|
|
124
|
+
if (!isAddress(options.observer)) {
|
|
125
|
+
throw new Error(`Invalid observer address: ${options.observer}`);
|
|
126
|
+
}
|
|
127
|
+
const tokenAddress = getAddress(options.tokenAddress);
|
|
128
|
+
const account = getAddress(options.account);
|
|
129
|
+
const observer = getAddress(options.observer);
|
|
130
|
+
const publicClient = createPublicClient({ transport: http(options.rpcUrl) });
|
|
131
|
+
const existing = await publicClient.readContract({
|
|
132
|
+
address: tokenAddress,
|
|
133
|
+
abi: confidentialTokenAbi,
|
|
134
|
+
functionName: "observer",
|
|
135
|
+
args: [account]
|
|
136
|
+
});
|
|
137
|
+
if (existing && isAddress(existing) && getAddress(existing) === observer) {
|
|
138
|
+
return "0x" + "00".repeat(32);
|
|
139
|
+
}
|
|
140
|
+
return options.signer.writeContract({
|
|
141
|
+
address: tokenAddress,
|
|
142
|
+
abi: confidentialTokenAbi,
|
|
143
|
+
functionName: "setObserver",
|
|
144
|
+
args: [account, observer]
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
export {
|
|
149
|
+
confidentialTokenAbi,
|
|
150
|
+
confidentialPaymentTypes,
|
|
151
|
+
confidentialErrorCodes,
|
|
152
|
+
createNonce,
|
|
153
|
+
hashEncryptedAmountInput,
|
|
154
|
+
normalizeAmount,
|
|
155
|
+
setObserver
|
|
156
|
+
};
|
package/dist/index.d.mts
CHANGED
|
@@ -1,38 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
export { SepoliaConfig } from '@zama-fhe/relayer-sdk/node';
|
|
1
|
+
import { R as RelayerInstance, a as RelayerSigner } from './types-gx3OAvqG.mjs';
|
|
2
|
+
export { C as ConfidentialErrorCode, i as ConfidentialPaymentAuthorization, l as ConfidentialPaymentInput, j as ConfidentialPaymentPayload, k as ConfidentialRequirementsExtra, S as SetObserverOptions, d as confidentialErrorCodes, b as confidentialPaymentTypes, c as confidentialTokenAbi, g as createEncryptedAmountInput, e as createNonce, f as createRelayerInstance, h as hashEncryptedAmountInput, n as normalizeAmount, p as publicDecrypt, s as setObserver, u as userDecryptEuint64 } from './types-gx3OAvqG.mjs';
|
|
4
3
|
export * from '@x402/core/types';
|
|
5
|
-
|
|
6
|
-
type RelayerInstance = Awaited<ReturnType<typeof createInstance>>;
|
|
7
|
-
type RelayerSigner = {
|
|
8
|
-
address: string;
|
|
9
|
-
signTypedData: ((domain: Record<string, unknown>, types: Record<string, Array<{
|
|
10
|
-
name: string;
|
|
11
|
-
type: string;
|
|
12
|
-
}>>, message: Record<string, unknown>) => Promise<string>) | ((args: {
|
|
13
|
-
domain: Record<string, unknown>;
|
|
14
|
-
types: Record<string, Array<{
|
|
15
|
-
name: string;
|
|
16
|
-
type: string;
|
|
17
|
-
}>>;
|
|
18
|
-
primaryType: string;
|
|
19
|
-
message: Record<string, unknown>;
|
|
20
|
-
}) => Promise<string>);
|
|
21
|
-
};
|
|
22
|
-
declare function createRelayerInstance(config: unknown): Promise<RelayerInstance>;
|
|
23
|
-
|
|
24
|
-
declare function createEncryptedAmountInput(relayer: RelayerInstance, contractAddress: string, senderAddress: string, amount: number): Promise<{
|
|
25
|
-
handle: `0x${string}`;
|
|
26
|
-
inputProof: `0x${string}`;
|
|
27
|
-
}>;
|
|
28
|
-
declare function userDecryptEuint64(relayer: RelayerInstance, handle: string, contractAddress: string, signer: RelayerSigner, options?: {
|
|
29
|
-
durationDays?: string;
|
|
30
|
-
startTimestamp?: string;
|
|
31
|
-
}): Promise<bigint>;
|
|
32
|
-
declare function publicDecrypt(relayer: RelayerInstance, handles: string[]): Promise<{
|
|
33
|
-
clearValues: Record<string, bigint>;
|
|
34
|
-
decryptionProof: string;
|
|
35
|
-
}>;
|
|
4
|
+
export { FhevmInstanceConfig, SepoliaConfig } from '@zama-fhe/relayer-sdk/node';
|
|
36
5
|
|
|
37
6
|
type ViewConfidentialBalanceOptions = {
|
|
38
7
|
rpcUrl: string;
|
|
@@ -68,4 +37,4 @@ type ViewConfidentialTransferOptions = {
|
|
|
68
37
|
};
|
|
69
38
|
declare function viewConfidentialTransferAmounts(options: ViewConfidentialTransferOptions): Promise<ConfidentialTransferAmount[]>;
|
|
70
39
|
|
|
71
|
-
export { type ConfidentialTransferAmount,
|
|
40
|
+
export { type ConfidentialTransferAmount, RelayerInstance, RelayerSigner, type ViewConfidentialBalanceOptions, type ViewConfidentialTransferOptions, viewConfidentialBalance, viewConfidentialTransferAmounts };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,38 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
export { SepoliaConfig } from '@zama-fhe/relayer-sdk/node';
|
|
1
|
+
import { R as RelayerInstance, a as RelayerSigner } from './types-gx3OAvqG.js';
|
|
2
|
+
export { C as ConfidentialErrorCode, i as ConfidentialPaymentAuthorization, l as ConfidentialPaymentInput, j as ConfidentialPaymentPayload, k as ConfidentialRequirementsExtra, S as SetObserverOptions, d as confidentialErrorCodes, b as confidentialPaymentTypes, c as confidentialTokenAbi, g as createEncryptedAmountInput, e as createNonce, f as createRelayerInstance, h as hashEncryptedAmountInput, n as normalizeAmount, p as publicDecrypt, s as setObserver, u as userDecryptEuint64 } from './types-gx3OAvqG.js';
|
|
4
3
|
export * from '@x402/core/types';
|
|
5
|
-
|
|
6
|
-
type RelayerInstance = Awaited<ReturnType<typeof createInstance>>;
|
|
7
|
-
type RelayerSigner = {
|
|
8
|
-
address: string;
|
|
9
|
-
signTypedData: ((domain: Record<string, unknown>, types: Record<string, Array<{
|
|
10
|
-
name: string;
|
|
11
|
-
type: string;
|
|
12
|
-
}>>, message: Record<string, unknown>) => Promise<string>) | ((args: {
|
|
13
|
-
domain: Record<string, unknown>;
|
|
14
|
-
types: Record<string, Array<{
|
|
15
|
-
name: string;
|
|
16
|
-
type: string;
|
|
17
|
-
}>>;
|
|
18
|
-
primaryType: string;
|
|
19
|
-
message: Record<string, unknown>;
|
|
20
|
-
}) => Promise<string>);
|
|
21
|
-
};
|
|
22
|
-
declare function createRelayerInstance(config: unknown): Promise<RelayerInstance>;
|
|
23
|
-
|
|
24
|
-
declare function createEncryptedAmountInput(relayer: RelayerInstance, contractAddress: string, senderAddress: string, amount: number): Promise<{
|
|
25
|
-
handle: `0x${string}`;
|
|
26
|
-
inputProof: `0x${string}`;
|
|
27
|
-
}>;
|
|
28
|
-
declare function userDecryptEuint64(relayer: RelayerInstance, handle: string, contractAddress: string, signer: RelayerSigner, options?: {
|
|
29
|
-
durationDays?: string;
|
|
30
|
-
startTimestamp?: string;
|
|
31
|
-
}): Promise<bigint>;
|
|
32
|
-
declare function publicDecrypt(relayer: RelayerInstance, handles: string[]): Promise<{
|
|
33
|
-
clearValues: Record<string, bigint>;
|
|
34
|
-
decryptionProof: string;
|
|
35
|
-
}>;
|
|
4
|
+
export { FhevmInstanceConfig, SepoliaConfig } from '@zama-fhe/relayer-sdk/node';
|
|
36
5
|
|
|
37
6
|
type ViewConfidentialBalanceOptions = {
|
|
38
7
|
rpcUrl: string;
|
|
@@ -68,4 +37,4 @@ type ViewConfidentialTransferOptions = {
|
|
|
68
37
|
};
|
|
69
38
|
declare function viewConfidentialTransferAmounts(options: ViewConfidentialTransferOptions): Promise<ConfidentialTransferAmount[]>;
|
|
70
39
|
|
|
71
|
-
export { type ConfidentialTransferAmount,
|
|
40
|
+
export { type ConfidentialTransferAmount, RelayerInstance, RelayerSigner, type ViewConfidentialBalanceOptions, type ViewConfidentialTransferOptions, viewConfidentialBalance, viewConfidentialTransferAmounts };
|
package/dist/index.js
CHANGED
|
@@ -21,6 +21,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
21
21
|
var index_exports = {};
|
|
22
22
|
__export(index_exports, {
|
|
23
23
|
SepoliaConfig: () => import_node.SepoliaConfig,
|
|
24
|
+
confidentialErrorCodes: () => confidentialErrorCodes,
|
|
24
25
|
confidentialPaymentTypes: () => confidentialPaymentTypes,
|
|
25
26
|
confidentialTokenAbi: () => confidentialTokenAbi,
|
|
26
27
|
createEncryptedAmountInput: () => createEncryptedAmountInput,
|
|
@@ -29,6 +30,7 @@ __export(index_exports, {
|
|
|
29
30
|
hashEncryptedAmountInput: () => hashEncryptedAmountInput,
|
|
30
31
|
normalizeAmount: () => normalizeAmount,
|
|
31
32
|
publicDecrypt: () => publicDecrypt,
|
|
33
|
+
setObserver: () => setObserver,
|
|
32
34
|
userDecryptEuint64: () => userDecryptEuint64,
|
|
33
35
|
viewConfidentialBalance: () => viewConfidentialBalance,
|
|
34
36
|
viewConfidentialTransferAmounts: () => viewConfidentialTransferAmounts
|
|
@@ -85,6 +87,23 @@ var confidentialTokenAbi = [
|
|
|
85
87
|
outputs: [{ internalType: "bool", name: "", type: "bool" }],
|
|
86
88
|
stateMutability: "view",
|
|
87
89
|
type: "function"
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
inputs: [{ internalType: "address", name: "account", type: "address" }],
|
|
93
|
+
name: "observer",
|
|
94
|
+
outputs: [{ internalType: "address", name: "", type: "address" }],
|
|
95
|
+
stateMutability: "view",
|
|
96
|
+
type: "function"
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
inputs: [
|
|
100
|
+
{ internalType: "address", name: "account", type: "address" },
|
|
101
|
+
{ internalType: "address", name: "newObserver", type: "address" }
|
|
102
|
+
],
|
|
103
|
+
name: "setObserver",
|
|
104
|
+
outputs: [],
|
|
105
|
+
stateMutability: "nonpayable",
|
|
106
|
+
type: "function"
|
|
88
107
|
}
|
|
89
108
|
];
|
|
90
109
|
|
|
@@ -101,6 +120,9 @@ var confidentialPaymentTypes = {
|
|
|
101
120
|
{ name: "encryptedAmountHash", type: "bytes32" }
|
|
102
121
|
]
|
|
103
122
|
};
|
|
123
|
+
var confidentialErrorCodes = {
|
|
124
|
+
observerNotAuthorized: "observer_not_authorized"
|
|
125
|
+
};
|
|
104
126
|
|
|
105
127
|
// src/utils.ts
|
|
106
128
|
var import_viem = require("viem");
|
|
@@ -133,7 +155,11 @@ function normalizeAmount(amount) {
|
|
|
133
155
|
var import_node = require("@zama-fhe/relayer-sdk/node");
|
|
134
156
|
var import_viem2 = require("viem");
|
|
135
157
|
async function createRelayerInstance(config) {
|
|
136
|
-
|
|
158
|
+
const instance = await (0, import_node.createInstance)(config);
|
|
159
|
+
if (typeof config.network === "string") {
|
|
160
|
+
instance.network = config.network;
|
|
161
|
+
}
|
|
162
|
+
return instance;
|
|
137
163
|
}
|
|
138
164
|
async function createEncryptedAmountInput(relayer, contractAddress, senderAddress, amount) {
|
|
139
165
|
const normalizedContract = (0, import_viem2.getAddress)(contractAddress);
|
|
@@ -214,6 +240,18 @@ async function viewConfidentialBalance(options) {
|
|
|
214
240
|
if (!options.signer) {
|
|
215
241
|
throw new Error("Missing signer for decryption");
|
|
216
242
|
}
|
|
243
|
+
const signerAddress = (0, import_viem3.getAddress)(options.signer.address);
|
|
244
|
+
if (!(0, import_viem3.isAddressEqual)(signerAddress, (0, import_viem3.getAddress)(account))) {
|
|
245
|
+
const observer = await publicClient.readContract({
|
|
246
|
+
address: options.tokenAddress,
|
|
247
|
+
abi: confidentialTokenAbi,
|
|
248
|
+
functionName: "observer",
|
|
249
|
+
args: [account]
|
|
250
|
+
});
|
|
251
|
+
if (!observer || !(0, import_viem3.isAddressEqual)(observer, signerAddress)) {
|
|
252
|
+
throw new Error(confidentialErrorCodes.observerNotAuthorized);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
217
255
|
if (handle === ZERO_HANDLE) {
|
|
218
256
|
return { handle, balance: 0n };
|
|
219
257
|
}
|
|
@@ -279,8 +317,27 @@ async function viewConfidentialTransferAmounts(options) {
|
|
|
279
317
|
throw new Error("Missing signer for decryption");
|
|
280
318
|
}
|
|
281
319
|
const signerAddress = (0, import_viem4.getAddress)(options.signer.address);
|
|
282
|
-
|
|
283
|
-
|
|
320
|
+
const holderAddress = (0, import_viem4.getAddress)(entry.holder);
|
|
321
|
+
const payeeAddress = (0, import_viem4.getAddress)(entry.payee);
|
|
322
|
+
if (!(0, import_viem4.isAddressEqual)(signerAddress, holderAddress) && !(0, import_viem4.isAddressEqual)(signerAddress, payeeAddress)) {
|
|
323
|
+
const [holderObserver, payeeObserver] = await Promise.all([
|
|
324
|
+
publicClient.readContract({
|
|
325
|
+
address: tokenAddress,
|
|
326
|
+
abi: confidentialTokenAbi,
|
|
327
|
+
functionName: "observer",
|
|
328
|
+
args: [holderAddress]
|
|
329
|
+
}),
|
|
330
|
+
publicClient.readContract({
|
|
331
|
+
address: tokenAddress,
|
|
332
|
+
abi: confidentialTokenAbi,
|
|
333
|
+
functionName: "observer",
|
|
334
|
+
args: [payeeAddress]
|
|
335
|
+
})
|
|
336
|
+
]);
|
|
337
|
+
const allowed = holderObserver && (0, import_viem4.isAddressEqual)(holderObserver, signerAddress) || payeeObserver && (0, import_viem4.isAddressEqual)(payeeObserver, signerAddress);
|
|
338
|
+
if (!allowed) {
|
|
339
|
+
throw new Error(confidentialErrorCodes.observerNotAuthorized);
|
|
340
|
+
}
|
|
284
341
|
}
|
|
285
342
|
entry.amount = await userDecryptEuint64(
|
|
286
343
|
options.relayer,
|
|
@@ -298,9 +355,43 @@ async function viewConfidentialTransferAmounts(options) {
|
|
|
298
355
|
}
|
|
299
356
|
return transfers;
|
|
300
357
|
}
|
|
358
|
+
|
|
359
|
+
// src/observer.ts
|
|
360
|
+
var import_viem5 = require("viem");
|
|
361
|
+
async function setObserver(options) {
|
|
362
|
+
if (!(0, import_viem5.isAddress)(options.tokenAddress)) {
|
|
363
|
+
throw new Error(`Invalid token address: ${options.tokenAddress}`);
|
|
364
|
+
}
|
|
365
|
+
if (!(0, import_viem5.isAddress)(options.account)) {
|
|
366
|
+
throw new Error(`Invalid account address: ${options.account}`);
|
|
367
|
+
}
|
|
368
|
+
if (!(0, import_viem5.isAddress)(options.observer)) {
|
|
369
|
+
throw new Error(`Invalid observer address: ${options.observer}`);
|
|
370
|
+
}
|
|
371
|
+
const tokenAddress = (0, import_viem5.getAddress)(options.tokenAddress);
|
|
372
|
+
const account = (0, import_viem5.getAddress)(options.account);
|
|
373
|
+
const observer = (0, import_viem5.getAddress)(options.observer);
|
|
374
|
+
const publicClient = (0, import_viem5.createPublicClient)({ transport: (0, import_viem5.http)(options.rpcUrl) });
|
|
375
|
+
const existing = await publicClient.readContract({
|
|
376
|
+
address: tokenAddress,
|
|
377
|
+
abi: confidentialTokenAbi,
|
|
378
|
+
functionName: "observer",
|
|
379
|
+
args: [account]
|
|
380
|
+
});
|
|
381
|
+
if (existing && (0, import_viem5.isAddress)(existing) && (0, import_viem5.getAddress)(existing) === observer) {
|
|
382
|
+
return "0x" + "00".repeat(32);
|
|
383
|
+
}
|
|
384
|
+
return options.signer.writeContract({
|
|
385
|
+
address: tokenAddress,
|
|
386
|
+
abi: confidentialTokenAbi,
|
|
387
|
+
functionName: "setObserver",
|
|
388
|
+
args: [account, observer]
|
|
389
|
+
});
|
|
390
|
+
}
|
|
301
391
|
// Annotate the CommonJS export names for ESM import in node:
|
|
302
392
|
0 && (module.exports = {
|
|
303
393
|
SepoliaConfig,
|
|
394
|
+
confidentialErrorCodes,
|
|
304
395
|
confidentialPaymentTypes,
|
|
305
396
|
confidentialTokenAbi,
|
|
306
397
|
createEncryptedAmountInput,
|
|
@@ -309,6 +400,7 @@ async function viewConfidentialTransferAmounts(options) {
|
|
|
309
400
|
hashEncryptedAmountInput,
|
|
310
401
|
normalizeAmount,
|
|
311
402
|
publicDecrypt,
|
|
403
|
+
setObserver,
|
|
312
404
|
userDecryptEuint64,
|
|
313
405
|
viewConfidentialBalance,
|
|
314
406
|
viewConfidentialTransferAmounts
|
package/dist/index.mjs
CHANGED
|
@@ -1,16 +1,22 @@
|
|
|
1
1
|
import {
|
|
2
|
+
confidentialErrorCodes,
|
|
2
3
|
confidentialPaymentTypes,
|
|
3
4
|
confidentialTokenAbi,
|
|
4
5
|
createNonce,
|
|
5
6
|
hashEncryptedAmountInput,
|
|
6
|
-
normalizeAmount
|
|
7
|
-
|
|
7
|
+
normalizeAmount,
|
|
8
|
+
setObserver
|
|
9
|
+
} from "./chunk-LTE4V3LT.mjs";
|
|
8
10
|
|
|
9
11
|
// src/relayer.ts
|
|
10
12
|
import { createInstance, SepoliaConfig } from "@zama-fhe/relayer-sdk/node";
|
|
11
13
|
import { getAddress, toHex } from "viem";
|
|
12
14
|
async function createRelayerInstance(config) {
|
|
13
|
-
|
|
15
|
+
const instance = await createInstance(config);
|
|
16
|
+
if (typeof config.network === "string") {
|
|
17
|
+
instance.network = config.network;
|
|
18
|
+
}
|
|
19
|
+
return instance;
|
|
14
20
|
}
|
|
15
21
|
async function createEncryptedAmountInput(relayer, contractAddress, senderAddress, amount) {
|
|
16
22
|
const normalizedContract = getAddress(contractAddress);
|
|
@@ -58,7 +64,7 @@ async function publicDecrypt(relayer, handles) {
|
|
|
58
64
|
}
|
|
59
65
|
|
|
60
66
|
// src/balance.ts
|
|
61
|
-
import { createPublicClient, http, isAddress } from "viem";
|
|
67
|
+
import { createPublicClient, getAddress as getAddress2, http, isAddress, isAddressEqual } from "viem";
|
|
62
68
|
var ZERO_HANDLE = "0x" + "00".repeat(32);
|
|
63
69
|
async function viewConfidentialBalance(options) {
|
|
64
70
|
if (!isAddress(options.tokenAddress)) {
|
|
@@ -91,6 +97,18 @@ async function viewConfidentialBalance(options) {
|
|
|
91
97
|
if (!options.signer) {
|
|
92
98
|
throw new Error("Missing signer for decryption");
|
|
93
99
|
}
|
|
100
|
+
const signerAddress = getAddress2(options.signer.address);
|
|
101
|
+
if (!isAddressEqual(signerAddress, getAddress2(account))) {
|
|
102
|
+
const observer = await publicClient.readContract({
|
|
103
|
+
address: options.tokenAddress,
|
|
104
|
+
abi: confidentialTokenAbi,
|
|
105
|
+
functionName: "observer",
|
|
106
|
+
args: [account]
|
|
107
|
+
});
|
|
108
|
+
if (!observer || !isAddressEqual(observer, signerAddress)) {
|
|
109
|
+
throw new Error(confidentialErrorCodes.observerNotAuthorized);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
94
112
|
if (handle === ZERO_HANDLE) {
|
|
95
113
|
return { handle, balance: 0n };
|
|
96
114
|
}
|
|
@@ -104,7 +122,7 @@ async function viewConfidentialBalance(options) {
|
|
|
104
122
|
}
|
|
105
123
|
|
|
106
124
|
// src/transfer.ts
|
|
107
|
-
import { createPublicClient as createPublicClient2, decodeEventLog, getAddress as
|
|
125
|
+
import { createPublicClient as createPublicClient2, decodeEventLog, getAddress as getAddress3, http as http2, isAddress as isAddress2, isHex, isAddressEqual as isAddressEqual2 } from "viem";
|
|
108
126
|
async function viewConfidentialTransferAmounts(options) {
|
|
109
127
|
if (!isAddress2(options.tokenAddress)) {
|
|
110
128
|
throw new Error(`Invalid token address: ${options.tokenAddress}`);
|
|
@@ -122,10 +140,10 @@ async function viewConfidentialTransferAmounts(options) {
|
|
|
122
140
|
const receipt = await publicClient.getTransactionReceipt({
|
|
123
141
|
hash: options.txHash
|
|
124
142
|
});
|
|
125
|
-
const tokenAddress =
|
|
126
|
-
const fromFilter = options.from ?
|
|
127
|
-
const toFilter = options.to ?
|
|
128
|
-
const logs = receipt.logs.filter((log) =>
|
|
143
|
+
const tokenAddress = getAddress3(options.tokenAddress);
|
|
144
|
+
const fromFilter = options.from ? getAddress3(options.from) : void 0;
|
|
145
|
+
const toFilter = options.to ? getAddress3(options.to) : void 0;
|
|
146
|
+
const logs = receipt.logs.filter((log) => getAddress3(log.address) === tokenAddress);
|
|
129
147
|
const transfers = [];
|
|
130
148
|
for (const log of logs) {
|
|
131
149
|
try {
|
|
@@ -137,8 +155,8 @@ async function viewConfidentialTransferAmounts(options) {
|
|
|
137
155
|
});
|
|
138
156
|
const args = decoded.args;
|
|
139
157
|
const entry = {
|
|
140
|
-
holder:
|
|
141
|
-
payee:
|
|
158
|
+
holder: getAddress3(args.holder),
|
|
159
|
+
payee: getAddress3(args.payee),
|
|
142
160
|
maxClearAmount: BigInt(args.maxClearAmount),
|
|
143
161
|
resourceHash: args.resourceHash,
|
|
144
162
|
nonce: args.nonce,
|
|
@@ -155,9 +173,28 @@ async function viewConfidentialTransferAmounts(options) {
|
|
|
155
173
|
if (!options.signer) {
|
|
156
174
|
throw new Error("Missing signer for decryption");
|
|
157
175
|
}
|
|
158
|
-
const signerAddress =
|
|
159
|
-
|
|
160
|
-
|
|
176
|
+
const signerAddress = getAddress3(options.signer.address);
|
|
177
|
+
const holderAddress = getAddress3(entry.holder);
|
|
178
|
+
const payeeAddress = getAddress3(entry.payee);
|
|
179
|
+
if (!isAddressEqual2(signerAddress, holderAddress) && !isAddressEqual2(signerAddress, payeeAddress)) {
|
|
180
|
+
const [holderObserver, payeeObserver] = await Promise.all([
|
|
181
|
+
publicClient.readContract({
|
|
182
|
+
address: tokenAddress,
|
|
183
|
+
abi: confidentialTokenAbi,
|
|
184
|
+
functionName: "observer",
|
|
185
|
+
args: [holderAddress]
|
|
186
|
+
}),
|
|
187
|
+
publicClient.readContract({
|
|
188
|
+
address: tokenAddress,
|
|
189
|
+
abi: confidentialTokenAbi,
|
|
190
|
+
functionName: "observer",
|
|
191
|
+
args: [payeeAddress]
|
|
192
|
+
})
|
|
193
|
+
]);
|
|
194
|
+
const allowed = holderObserver && isAddressEqual2(holderObserver, signerAddress) || payeeObserver && isAddressEqual2(payeeObserver, signerAddress);
|
|
195
|
+
if (!allowed) {
|
|
196
|
+
throw new Error(confidentialErrorCodes.observerNotAuthorized);
|
|
197
|
+
}
|
|
161
198
|
}
|
|
162
199
|
entry.amount = await userDecryptEuint64(
|
|
163
200
|
options.relayer,
|
|
@@ -177,6 +214,7 @@ async function viewConfidentialTransferAmounts(options) {
|
|
|
177
214
|
}
|
|
178
215
|
export {
|
|
179
216
|
SepoliaConfig,
|
|
217
|
+
confidentialErrorCodes,
|
|
180
218
|
confidentialPaymentTypes,
|
|
181
219
|
confidentialTokenAbi,
|
|
182
220
|
createEncryptedAmountInput,
|
|
@@ -185,6 +223,7 @@ export {
|
|
|
185
223
|
hashEncryptedAmountInput,
|
|
186
224
|
normalizeAmount,
|
|
187
225
|
publicDecrypt,
|
|
226
|
+
setObserver,
|
|
188
227
|
userDecryptEuint64,
|
|
189
228
|
viewConfidentialBalance,
|
|
190
229
|
viewConfidentialTransferAmounts
|