@skalenetwork/privacy-sdk 0.1.0-develop.0 → 0.1.0-develop.2

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/index.d.cts CHANGED
@@ -1,7 +1,8 @@
1
1
  import { Hex, PublicClient } from 'viem';
2
+ export { Hex } from 'viem';
2
3
  import { C as ConfidentialTokenConfig, T as TransferData } from './types-WaeCtQlG.cjs';
3
4
  export { S as Signer, U as UnsignedTx, V as ViewerKeypair } from './types-WaeCtQlG.cjs';
4
- import { A as ActionConfig } from './types-CBDYydn0.cjs';
5
+ import { A as ActionConfig } from './types-T84pCSPm.cjs';
5
6
  import { C as CtxPromise } from './ctx-ifn_jhPL.cjs';
6
7
  import '@skalenetwork/bite';
7
8
 
@@ -45,6 +46,10 @@ declare class ConfidentialWrapper extends ConfidentialToken {
45
46
 
46
47
  declare const confidentialWrapperAbi: readonly [{
47
48
  readonly inputs: readonly [{
49
+ readonly internalType: "bool";
50
+ readonly name: "proxyMode";
51
+ readonly type: "bool";
52
+ }, {
48
53
  readonly internalType: "contract IERC20Metadata";
49
54
  readonly name: "underlyingToken";
50
55
  readonly type: "address";
@@ -463,6 +468,10 @@ declare const confidentialWrapperAbi: readonly [{
463
468
  }];
464
469
  readonly name: "InvalidDataOffset";
465
470
  readonly type: "error";
471
+ }, {
472
+ readonly inputs: readonly [];
473
+ readonly name: "InvalidInitialization";
474
+ readonly type: "error";
466
475
  }, {
467
476
  readonly inputs: readonly [];
468
477
  readonly name: "InvalidPublicKey";
@@ -485,7 +494,7 @@ declare const confidentialWrapperAbi: readonly [{
485
494
  readonly type: "error";
486
495
  }, {
487
496
  readonly inputs: readonly [];
488
- readonly name: "InvalidShortString";
497
+ readonly name: "InvalidSaltForTransactionValue";
489
498
  readonly type: "error";
490
499
  }, {
491
500
  readonly inputs: readonly [];
@@ -519,6 +528,10 @@ declare const confidentialWrapperAbi: readonly [{
519
528
  }];
520
529
  readonly name: "NoViewerRegisteredForHolder";
521
530
  readonly type: "error";
531
+ }, {
532
+ readonly inputs: readonly [];
533
+ readonly name: "NotInitializing";
534
+ readonly type: "error";
522
535
  }, {
523
536
  readonly inputs: readonly [{
524
537
  readonly internalType: "address";
@@ -547,14 +560,6 @@ declare const confidentialWrapperAbi: readonly [{
547
560
  }];
548
561
  readonly name: "SafeERC20FailedOperation";
549
562
  readonly type: "error";
550
- }, {
551
- readonly inputs: readonly [{
552
- readonly internalType: "string";
553
- readonly name: "str";
554
- readonly type: "string";
555
- }];
556
- readonly name: "StringTooLong";
557
- readonly type: "error";
558
563
  }, {
559
564
  readonly inputs: readonly [{
560
565
  readonly internalType: "uint256";
@@ -599,6 +604,10 @@ declare const confidentialWrapperAbi: readonly [{
599
604
  readonly inputs: readonly [];
600
605
  readonly name: "ValueWasNotEncryptedCorrectly";
601
606
  readonly type: "error";
607
+ }, {
608
+ readonly inputs: readonly [];
609
+ readonly name: "WrongInitializer";
610
+ readonly type: "error";
602
611
  }, {
603
612
  readonly inputs: readonly [];
604
613
  readonly name: "WrongPlaintextFormat";
@@ -881,6 +890,16 @@ declare const confidentialWrapperAbi: readonly [{
881
890
  }];
882
891
  readonly name: "HistoricViewTransferIdRevoked";
883
892
  readonly type: "event";
893
+ }, {
894
+ readonly anonymous: false;
895
+ readonly inputs: readonly [{
896
+ readonly indexed: false;
897
+ readonly internalType: "uint64";
898
+ readonly name: "version";
899
+ readonly type: "uint64";
900
+ }];
901
+ readonly name: "Initialized";
902
+ readonly type: "event";
884
903
  }, {
885
904
  readonly anonymous: false;
886
905
  readonly inputs: readonly [{
@@ -1370,6 +1389,24 @@ declare const confidentialWrapperAbi: readonly [{
1370
1389
  }];
1371
1390
  readonly stateMutability: "view";
1372
1391
  readonly type: "function";
1392
+ }, {
1393
+ readonly inputs: readonly [{
1394
+ readonly internalType: "address";
1395
+ readonly name: "holder";
1396
+ readonly type: "address";
1397
+ }, {
1398
+ readonly internalType: "uint256";
1399
+ readonly name: "value";
1400
+ readonly type: "uint256";
1401
+ }];
1402
+ readonly name: "encryptValue";
1403
+ readonly outputs: readonly [{
1404
+ readonly internalType: "bytes";
1405
+ readonly name: "encryptedValue";
1406
+ readonly type: "bytes";
1407
+ }];
1408
+ readonly stateMutability: "view";
1409
+ readonly type: "function";
1373
1410
  }, {
1374
1411
  readonly inputs: readonly [{
1375
1412
  readonly internalType: "address";
@@ -1424,7 +1461,7 @@ declare const confidentialWrapperAbi: readonly [{
1424
1461
  }];
1425
1462
  readonly name: "encryptedReceiveWithAuthorization";
1426
1463
  readonly outputs: readonly [];
1427
- readonly stateMutability: "nonpayable";
1464
+ readonly stateMutability: "payable";
1428
1465
  readonly type: "function";
1429
1466
  }, {
1430
1467
  readonly inputs: readonly [{
@@ -1524,6 +1561,46 @@ declare const confidentialWrapperAbi: readonly [{
1524
1561
  }];
1525
1562
  readonly stateMutability: "view";
1526
1563
  readonly type: "function";
1564
+ }, {
1565
+ readonly inputs: readonly [{
1566
+ readonly internalType: "string";
1567
+ readonly name: "";
1568
+ readonly type: "string";
1569
+ }, {
1570
+ readonly internalType: "string";
1571
+ readonly name: "";
1572
+ readonly type: "string";
1573
+ }, {
1574
+ readonly internalType: "string";
1575
+ readonly name: "";
1576
+ readonly type: "string";
1577
+ }, {
1578
+ readonly internalType: "address";
1579
+ readonly name: "";
1580
+ readonly type: "address";
1581
+ }];
1582
+ readonly name: "initialize";
1583
+ readonly outputs: readonly [];
1584
+ readonly stateMutability: "pure";
1585
+ readonly type: "function";
1586
+ }, {
1587
+ readonly inputs: readonly [{
1588
+ readonly internalType: "contract IERC20Metadata";
1589
+ readonly name: "underlyingToken";
1590
+ readonly type: "address";
1591
+ }, {
1592
+ readonly internalType: "string";
1593
+ readonly name: "version_";
1594
+ readonly type: "string";
1595
+ }, {
1596
+ readonly internalType: "address";
1597
+ readonly name: "initialAuthority";
1598
+ readonly type: "address";
1599
+ }];
1600
+ readonly name: "initialize";
1601
+ readonly outputs: readonly [];
1602
+ readonly stateMutability: "nonpayable";
1603
+ readonly type: "function";
1527
1604
  }, {
1528
1605
  readonly inputs: readonly [];
1529
1606
  readonly name: "isConsumingScheduledOp";
package/dist/index.d.ts CHANGED
@@ -1,7 +1,8 @@
1
1
  import { Hex, PublicClient } from 'viem';
2
+ export { Hex } from 'viem';
2
3
  import { C as ConfidentialTokenConfig, T as TransferData } from './types-WaeCtQlG.js';
3
4
  export { S as Signer, U as UnsignedTx, V as ViewerKeypair } from './types-WaeCtQlG.js';
4
- import { A as ActionConfig } from './types-Gn0F4pQf.js';
5
+ import { A as ActionConfig } from './types-CPLzL9IK.js';
5
6
  import { C as CtxPromise } from './ctx-ifn_jhPL.js';
6
7
  import '@skalenetwork/bite';
7
8
 
@@ -45,6 +46,10 @@ declare class ConfidentialWrapper extends ConfidentialToken {
45
46
 
46
47
  declare const confidentialWrapperAbi: readonly [{
47
48
  readonly inputs: readonly [{
49
+ readonly internalType: "bool";
50
+ readonly name: "proxyMode";
51
+ readonly type: "bool";
52
+ }, {
48
53
  readonly internalType: "contract IERC20Metadata";
49
54
  readonly name: "underlyingToken";
50
55
  readonly type: "address";
@@ -463,6 +468,10 @@ declare const confidentialWrapperAbi: readonly [{
463
468
  }];
464
469
  readonly name: "InvalidDataOffset";
465
470
  readonly type: "error";
471
+ }, {
472
+ readonly inputs: readonly [];
473
+ readonly name: "InvalidInitialization";
474
+ readonly type: "error";
466
475
  }, {
467
476
  readonly inputs: readonly [];
468
477
  readonly name: "InvalidPublicKey";
@@ -485,7 +494,7 @@ declare const confidentialWrapperAbi: readonly [{
485
494
  readonly type: "error";
486
495
  }, {
487
496
  readonly inputs: readonly [];
488
- readonly name: "InvalidShortString";
497
+ readonly name: "InvalidSaltForTransactionValue";
489
498
  readonly type: "error";
490
499
  }, {
491
500
  readonly inputs: readonly [];
@@ -519,6 +528,10 @@ declare const confidentialWrapperAbi: readonly [{
519
528
  }];
520
529
  readonly name: "NoViewerRegisteredForHolder";
521
530
  readonly type: "error";
531
+ }, {
532
+ readonly inputs: readonly [];
533
+ readonly name: "NotInitializing";
534
+ readonly type: "error";
522
535
  }, {
523
536
  readonly inputs: readonly [{
524
537
  readonly internalType: "address";
@@ -547,14 +560,6 @@ declare const confidentialWrapperAbi: readonly [{
547
560
  }];
548
561
  readonly name: "SafeERC20FailedOperation";
549
562
  readonly type: "error";
550
- }, {
551
- readonly inputs: readonly [{
552
- readonly internalType: "string";
553
- readonly name: "str";
554
- readonly type: "string";
555
- }];
556
- readonly name: "StringTooLong";
557
- readonly type: "error";
558
563
  }, {
559
564
  readonly inputs: readonly [{
560
565
  readonly internalType: "uint256";
@@ -599,6 +604,10 @@ declare const confidentialWrapperAbi: readonly [{
599
604
  readonly inputs: readonly [];
600
605
  readonly name: "ValueWasNotEncryptedCorrectly";
601
606
  readonly type: "error";
607
+ }, {
608
+ readonly inputs: readonly [];
609
+ readonly name: "WrongInitializer";
610
+ readonly type: "error";
602
611
  }, {
603
612
  readonly inputs: readonly [];
604
613
  readonly name: "WrongPlaintextFormat";
@@ -881,6 +890,16 @@ declare const confidentialWrapperAbi: readonly [{
881
890
  }];
882
891
  readonly name: "HistoricViewTransferIdRevoked";
883
892
  readonly type: "event";
893
+ }, {
894
+ readonly anonymous: false;
895
+ readonly inputs: readonly [{
896
+ readonly indexed: false;
897
+ readonly internalType: "uint64";
898
+ readonly name: "version";
899
+ readonly type: "uint64";
900
+ }];
901
+ readonly name: "Initialized";
902
+ readonly type: "event";
884
903
  }, {
885
904
  readonly anonymous: false;
886
905
  readonly inputs: readonly [{
@@ -1370,6 +1389,24 @@ declare const confidentialWrapperAbi: readonly [{
1370
1389
  }];
1371
1390
  readonly stateMutability: "view";
1372
1391
  readonly type: "function";
1392
+ }, {
1393
+ readonly inputs: readonly [{
1394
+ readonly internalType: "address";
1395
+ readonly name: "holder";
1396
+ readonly type: "address";
1397
+ }, {
1398
+ readonly internalType: "uint256";
1399
+ readonly name: "value";
1400
+ readonly type: "uint256";
1401
+ }];
1402
+ readonly name: "encryptValue";
1403
+ readonly outputs: readonly [{
1404
+ readonly internalType: "bytes";
1405
+ readonly name: "encryptedValue";
1406
+ readonly type: "bytes";
1407
+ }];
1408
+ readonly stateMutability: "view";
1409
+ readonly type: "function";
1373
1410
  }, {
1374
1411
  readonly inputs: readonly [{
1375
1412
  readonly internalType: "address";
@@ -1424,7 +1461,7 @@ declare const confidentialWrapperAbi: readonly [{
1424
1461
  }];
1425
1462
  readonly name: "encryptedReceiveWithAuthorization";
1426
1463
  readonly outputs: readonly [];
1427
- readonly stateMutability: "nonpayable";
1464
+ readonly stateMutability: "payable";
1428
1465
  readonly type: "function";
1429
1466
  }, {
1430
1467
  readonly inputs: readonly [{
@@ -1524,6 +1561,46 @@ declare const confidentialWrapperAbi: readonly [{
1524
1561
  }];
1525
1562
  readonly stateMutability: "view";
1526
1563
  readonly type: "function";
1564
+ }, {
1565
+ readonly inputs: readonly [{
1566
+ readonly internalType: "string";
1567
+ readonly name: "";
1568
+ readonly type: "string";
1569
+ }, {
1570
+ readonly internalType: "string";
1571
+ readonly name: "";
1572
+ readonly type: "string";
1573
+ }, {
1574
+ readonly internalType: "string";
1575
+ readonly name: "";
1576
+ readonly type: "string";
1577
+ }, {
1578
+ readonly internalType: "address";
1579
+ readonly name: "";
1580
+ readonly type: "address";
1581
+ }];
1582
+ readonly name: "initialize";
1583
+ readonly outputs: readonly [];
1584
+ readonly stateMutability: "pure";
1585
+ readonly type: "function";
1586
+ }, {
1587
+ readonly inputs: readonly [{
1588
+ readonly internalType: "contract IERC20Metadata";
1589
+ readonly name: "underlyingToken";
1590
+ readonly type: "address";
1591
+ }, {
1592
+ readonly internalType: "string";
1593
+ readonly name: "version_";
1594
+ readonly type: "string";
1595
+ }, {
1596
+ readonly internalType: "address";
1597
+ readonly name: "initialAuthority";
1598
+ readonly type: "address";
1599
+ }];
1600
+ readonly name: "initialize";
1601
+ readonly outputs: readonly [];
1602
+ readonly stateMutability: "nonpayable";
1603
+ readonly type: "function";
1527
1604
  }, {
1528
1605
  readonly inputs: readonly [];
1529
1606
  readonly name: "isConsumingScheduledOp";
package/dist/index.js CHANGED
@@ -3,7 +3,6 @@ import {
3
3
  authorizeHistoricViewForRange,
4
4
  authorizeHistoricViewForTransfer,
5
5
  confidentialWrapperAbi,
6
- decryptHistoricTransferData,
7
6
  decryptTokenBalance,
8
7
  registerViewerKey,
9
8
  requestTransferDecryption,
@@ -11,12 +10,14 @@ import {
11
10
  transfer,
12
11
  unwrap,
13
12
  wrap
14
- } from "./chunk-YEII26VS.js";
13
+ } from "./chunk-PMT6KSGL.js";
15
14
  import {
16
15
  createCtxPromise,
17
16
  waitForCtx
18
17
  } from "./chunk-Y6NM73JA.js";
19
- import "./chunk-K5WS3F4Q.js";
18
+ import {
19
+ decryptTransferData
20
+ } from "./chunk-K5WS3F4Q.js";
20
21
 
21
22
  // src/ConfidentialToken.ts
22
23
  import { createPublicClient, http, parseEventLogs } from "viem";
@@ -93,42 +94,40 @@ var ConfidentialToken = class {
93
94
  if (!this.viewerPrivateKey) {
94
95
  throw new Error("Viewer key is required to decrypt balance.");
95
96
  }
96
- return decryptTokenBalance(this.actionConfig, { viewerKey: this.viewerPrivateKey });
97
+ return decryptTokenBalance(this.actionConfig, this.viewerPrivateKey);
97
98
  }
98
99
  // --- Standard ERC-20 writes ---
99
100
  async approve(spender, amount) {
100
- return approve(this.actionConfig, { spender, amount });
101
+ return approve(this.actionConfig, spender, amount);
101
102
  }
102
103
  // --- Privacy-specific writes ---
103
104
  transfer(to, amount) {
104
- return createCtxPromise(
105
- transfer(this.actionConfig, { to, amount }),
106
- this.client
107
- );
105
+ return createCtxPromise(transfer(this.actionConfig, to, amount), this.client);
108
106
  }
109
107
  // --- Viewer key management ---
110
108
  async registerViewerPublicKey(publicKey) {
111
- return registerViewerKey(this.actionConfig, { publicKey });
109
+ return registerViewerKey(this.actionConfig, publicKey);
112
110
  }
113
111
  async authorizeHistoricViewForRange(address, fromTimestamp, toTimestamp) {
114
- return authorizeHistoricViewForRange(this.actionConfig, {
112
+ return authorizeHistoricViewForRange(
113
+ this.actionConfig,
115
114
  address,
116
115
  fromTimestamp,
117
116
  toTimestamp
118
- });
117
+ );
119
118
  }
120
119
  async authorizeHistoricViewForTransfer(address, transferId) {
121
- return authorizeHistoricViewForTransfer(this.actionConfig, { address, transferId });
120
+ return authorizeHistoricViewForTransfer(this.actionConfig, address, transferId);
122
121
  }
123
122
  async revokeHistoricView(address) {
124
- return revokeHistoricView(this.actionConfig, { address });
123
+ return revokeHistoricView(this.actionConfig, address);
125
124
  }
126
125
  // --- Decrypt / history ---
127
126
  async requestTransferDecryption(ctxHash) {
128
127
  if (!this.viewerPrivateKey) {
129
128
  throw new Error("Viewer key is required to decrypt transfer data.");
130
129
  }
131
- const txHash = await requestTransferDecryption(this.actionConfig, { ctxHash });
130
+ const txHash = await requestTransferDecryption(this.actionConfig, ctxHash);
132
131
  const { ctxReceipt } = await waitForCtx(txHash, this.client);
133
132
  const events = parseEventLogs({
134
133
  abi: confidentialWrapperAbi,
@@ -143,7 +142,7 @@ var ConfidentialToken = class {
143
142
  if (!encryptedData) {
144
143
  throw new Error("CTX receipt does not contain a ReEncryptedTransfer event.");
145
144
  }
146
- return decryptHistoricTransferData({ encryptedData, viewerKey: this.viewerPrivateKey });
145
+ return decryptTransferData(encryptedData, this.viewerPrivateKey);
147
146
  }
148
147
  };
149
148
 
@@ -157,10 +156,10 @@ var ConfidentialWrapper = class extends ConfidentialToken {
157
156
  });
158
157
  }
159
158
  wrap(receiver, amount) {
160
- return createCtxPromise(wrap(this.actionConfig, { receiver, amount }), this.client);
159
+ return createCtxPromise(wrap(this.actionConfig, receiver, amount), this.client);
161
160
  }
162
161
  unwrap(receiver, amount) {
163
- return createCtxPromise(unwrap(this.actionConfig, { receiver, amount }), this.client);
162
+ return createCtxPromise(unwrap(this.actionConfig, receiver, amount), this.client);
164
163
  }
165
164
  };
166
165
  export {
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/ConfidentialToken.ts","../src/ConfidentialWrapper.ts"],"sourcesContent":["import { createPublicClient, http, parseEventLogs, type Hex, type PublicClient } from \"viem\";\nimport { BITE } from \"@skalenetwork/bite\";\n\nimport type { ConfidentialTokenConfig, TransferData } from \"./types.js\";\nimport type { ActionConfig } from \"./actions/types.js\";\nimport * as actions from \"./actions/index.js\";\nimport { confidentialWrapperAbi } from \"./abi/confidentialWrapper.js\";\nimport { createCtxPromise, type CtxPromise, waitForCtx } from \"./utils/ctx.js\";\n\nexport class ConfidentialToken {\n readonly rpcUrl: string;\n readonly address: Hex;\n readonly signer: {\n address: Hex;\n sendTransaction(tx: { to: Hex; data: Hex; value?: bigint }): Promise<Hex>;\n };\n private viewerPrivateKey?: Hex;\n protected client: PublicClient;\n private bite: BITE;\n\n constructor(config: ConfidentialTokenConfig) {\n this.rpcUrl = config.rpcUrl;\n this.address = config.address;\n this.signer = config.signer;\n this.viewerPrivateKey = config.viewerPrivateKey;\n this.client = createPublicClient({ transport: http(config.rpcUrl) }) as PublicClient;\n this.bite = new BITE(config.rpcUrl);\n }\n\n protected get actionConfig(): ActionConfig {\n return {\n rpcUrl: this.rpcUrl,\n address: this.address,\n publicClient: this.client,\n signer: this.signer,\n bite: this.bite,\n };\n }\n\n setViewerPrivateKey(privateKey: Hex): void {\n this.viewerPrivateKey = privateKey;\n }\n\n // --- Standard ERC-20 reads ---\n\n async name(): Promise<string> {\n return (await this.client.readContract({\n address: this.address,\n abi: confidentialWrapperAbi,\n functionName: \"name\",\n })) as string;\n }\n\n async symbol(): Promise<string> {\n return (await this.client.readContract({\n address: this.address,\n abi: confidentialWrapperAbi,\n functionName: \"symbol\",\n })) as string;\n }\n\n async decimals(): Promise<number> {\n return Number(\n await this.client.readContract({\n address: this.address,\n abi: confidentialWrapperAbi,\n functionName: \"decimals\",\n }),\n );\n }\n\n async allowance(owner: Hex, spender: Hex): Promise<bigint> {\n return (await this.client.readContract({\n address: this.address,\n abi: confidentialWrapperAbi,\n functionName: \"allowance\",\n args: [owner, spender],\n })) as bigint;\n }\n\n // --- Privacy-specific reads ---\n\n async viewerAddress(): Promise<Hex> {\n return (await this.client.readContract({\n address: this.address,\n abi: confidentialWrapperAbi,\n functionName: \"viewerAddresses\",\n args: [this.signer.address],\n })) as Hex;\n }\n\n async decryptBalance(): Promise<bigint> {\n if (!this.viewerPrivateKey) {\n throw new Error(\"Viewer key is required to decrypt balance.\");\n }\n return actions.decryptTokenBalance(this.actionConfig, { viewerKey: this.viewerPrivateKey });\n }\n\n // --- Standard ERC-20 writes ---\n\n async approve(spender: Hex, amount: bigint): Promise<Hex> {\n return actions.approve(this.actionConfig, { spender, amount });\n }\n\n // --- Privacy-specific writes ---\n\n transfer(to: Hex, amount: bigint): CtxPromise {\n return createCtxPromise(\n actions.transfer(this.actionConfig, { to, amount }),\n this.client,\n );\n }\n\n // --- Viewer key management ---\n\n async registerViewerPublicKey(publicKey: Hex): Promise<Hex> {\n return actions.registerViewerKey(this.actionConfig, { publicKey });\n }\n\n async authorizeHistoricViewForRange(\n address: Hex,\n fromTimestamp: bigint,\n toTimestamp: bigint,\n ): Promise<Hex> {\n return actions.authorizeHistoricViewForRange(this.actionConfig, {\n address,\n fromTimestamp,\n toTimestamp,\n });\n }\n\n async authorizeHistoricViewForTransfer(address: Hex, transferId: bigint): Promise<Hex> {\n return actions.authorizeHistoricViewForTransfer(this.actionConfig, { address, transferId });\n }\n\n async revokeHistoricView(address: Hex): Promise<Hex> {\n return actions.revokeHistoricView(this.actionConfig, { address });\n }\n\n // --- Decrypt / history ---\n\n async requestTransferDecryption(ctxHash: Hex): Promise<TransferData> {\n if (!this.viewerPrivateKey) {\n throw new Error(\"Viewer key is required to decrypt transfer data.\");\n }\n const txHash = await actions.requestTransferDecryption(this.actionConfig, { ctxHash });\n const { ctxReceipt } = await waitForCtx(txHash, this.client);\n const events = parseEventLogs({\n abi: confidentialWrapperAbi,\n logs: ctxReceipt.logs,\n eventName: \"ReEncryptedTransfer\",\n });\n const event = events[0];\n if (!event) {\n throw new Error(\"CTX receipt does not contain a ReEncryptedTransfer event.\");\n }\n const encryptedData = (event.args as { encryptedTransfer?: Hex }).encryptedTransfer;\n if (!encryptedData) {\n throw new Error(\"CTX receipt does not contain a ReEncryptedTransfer event.\");\n }\n return actions.decryptHistoricTransferData({ encryptedData, viewerKey: this.viewerPrivateKey });\n }\n}\n","import type { Hex } from \"viem\";\n\nimport { ConfidentialToken } from \"./ConfidentialToken.js\";\nimport { confidentialWrapperAbi } from \"./abi/confidentialWrapper.js\";\nimport * as actions from \"./actions/index.js\";\nimport { createCtxPromise, type CtxPromise } from \"./utils/ctx.js\";\n\nexport class ConfidentialWrapper extends ConfidentialToken {\n async underlying(): Promise<Hex> {\n return (await this.client.readContract({\n address: this.address,\n abi: confidentialWrapperAbi,\n functionName: \"underlying\",\n })) as Hex;\n }\n\n wrap(receiver: Hex, amount: bigint): CtxPromise {\n return createCtxPromise(actions.wrap(this.actionConfig, { receiver, amount }), this.client);\n }\n\n unwrap(receiver: Hex, amount: bigint): CtxPromise {\n return createCtxPromise(actions.unwrap(this.actionConfig, { receiver, amount }), this.client);\n }\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/ConfidentialToken.ts","../src/ConfidentialWrapper.ts"],"sourcesContent":["import { createPublicClient, http, parseEventLogs, type Hex, type PublicClient } from \"viem\";\nimport { BITE } from \"@skalenetwork/bite\";\n\nimport type { ConfidentialTokenConfig, TransferData } from \"./types.js\";\nimport type { ActionConfig } from \"./actions/types.js\";\nimport * as actions from \"./actions/index.js\";\nimport { confidentialWrapperAbi } from \"./abi/confidentialWrapper.js\";\nimport { createCtxPromise, type CtxPromise, waitForCtx } from \"./utils/ctx.js\";\nimport { decryptTransferData } from \"./utils/crypto.js\";\n\nexport class ConfidentialToken {\n readonly rpcUrl: string;\n readonly address: Hex;\n readonly signer: {\n address: Hex;\n sendTransaction(tx: { to: Hex; data: Hex; value?: bigint }): Promise<Hex>;\n };\n private viewerPrivateKey?: Hex;\n protected client: PublicClient;\n private bite: BITE;\n\n constructor(config: ConfidentialTokenConfig) {\n this.rpcUrl = config.rpcUrl;\n this.address = config.address;\n this.signer = config.signer;\n this.viewerPrivateKey = config.viewerPrivateKey;\n this.client = createPublicClient({ transport: http(config.rpcUrl) }) as PublicClient;\n this.bite = new BITE(config.rpcUrl);\n }\n\n protected get actionConfig(): ActionConfig {\n return {\n rpcUrl: this.rpcUrl,\n address: this.address,\n publicClient: this.client,\n signer: this.signer,\n bite: this.bite,\n };\n }\n\n setViewerPrivateKey(privateKey: Hex): void {\n this.viewerPrivateKey = privateKey;\n }\n\n // --- Standard ERC-20 reads ---\n\n async name(): Promise<string> {\n return (await this.client.readContract({\n address: this.address,\n abi: confidentialWrapperAbi,\n functionName: \"name\",\n })) as string;\n }\n\n async symbol(): Promise<string> {\n return (await this.client.readContract({\n address: this.address,\n abi: confidentialWrapperAbi,\n functionName: \"symbol\",\n })) as string;\n }\n\n async decimals(): Promise<number> {\n return Number(\n await this.client.readContract({\n address: this.address,\n abi: confidentialWrapperAbi,\n functionName: \"decimals\",\n }),\n );\n }\n\n async allowance(owner: Hex, spender: Hex): Promise<bigint> {\n return (await this.client.readContract({\n address: this.address,\n abi: confidentialWrapperAbi,\n functionName: \"allowance\",\n args: [owner, spender],\n })) as bigint;\n }\n\n // --- Privacy-specific reads ---\n\n async viewerAddress(): Promise<Hex> {\n return (await this.client.readContract({\n address: this.address,\n abi: confidentialWrapperAbi,\n functionName: \"viewerAddresses\",\n args: [this.signer.address],\n })) as Hex;\n }\n\n async decryptBalance(): Promise<bigint> {\n if (!this.viewerPrivateKey) {\n throw new Error(\"Viewer key is required to decrypt balance.\");\n }\n return actions.decryptTokenBalance(this.actionConfig, this.viewerPrivateKey);\n }\n\n // --- Standard ERC-20 writes ---\n\n async approve(spender: Hex, amount: bigint): Promise<Hex> {\n return actions.approve(this.actionConfig, spender, amount);\n }\n\n // --- Privacy-specific writes ---\n\n transfer(to: Hex, amount: bigint): CtxPromise {\n return createCtxPromise(actions.transfer(this.actionConfig, to, amount), this.client);\n }\n\n // --- Viewer key management ---\n\n async registerViewerPublicKey(publicKey: Hex): Promise<Hex> {\n return actions.registerViewerKey(this.actionConfig, publicKey);\n }\n\n async authorizeHistoricViewForRange(\n address: Hex,\n fromTimestamp: bigint,\n toTimestamp: bigint,\n ): Promise<Hex> {\n return actions.authorizeHistoricViewForRange(\n this.actionConfig,\n address,\n fromTimestamp,\n toTimestamp,\n );\n }\n\n async authorizeHistoricViewForTransfer(address: Hex, transferId: bigint): Promise<Hex> {\n return actions.authorizeHistoricViewForTransfer(this.actionConfig, address, transferId);\n }\n\n async revokeHistoricView(address: Hex): Promise<Hex> {\n return actions.revokeHistoricView(this.actionConfig, address);\n }\n\n // --- Decrypt / history ---\n\n async requestTransferDecryption(ctxHash: Hex): Promise<TransferData> {\n if (!this.viewerPrivateKey) {\n throw new Error(\"Viewer key is required to decrypt transfer data.\");\n }\n const txHash = await actions.requestTransferDecryption(this.actionConfig, ctxHash);\n const { ctxReceipt } = await waitForCtx(txHash, this.client);\n const events = parseEventLogs({\n abi: confidentialWrapperAbi,\n logs: ctxReceipt.logs,\n eventName: \"ReEncryptedTransfer\",\n });\n const event = events[0];\n if (!event) {\n throw new Error(\"CTX receipt does not contain a ReEncryptedTransfer event.\");\n }\n const encryptedData = (event.args as { encryptedTransfer?: Hex }).encryptedTransfer;\n if (!encryptedData) {\n throw new Error(\"CTX receipt does not contain a ReEncryptedTransfer event.\");\n }\n return decryptTransferData(encryptedData, this.viewerPrivateKey);\n }\n}\n","import type { Hex } from \"viem\";\n\nimport { ConfidentialToken } from \"./ConfidentialToken.js\";\nimport { confidentialWrapperAbi } from \"./abi/confidentialWrapper.js\";\nimport * as actions from \"./actions/index.js\";\nimport { createCtxPromise, type CtxPromise } from \"./utils/ctx.js\";\n\nexport class ConfidentialWrapper extends ConfidentialToken {\n async underlying(): Promise<Hex> {\n return (await this.client.readContract({\n address: this.address,\n abi: confidentialWrapperAbi,\n functionName: \"underlying\",\n })) as Hex;\n }\n\n wrap(receiver: Hex, amount: bigint): CtxPromise {\n return createCtxPromise(actions.wrap(this.actionConfig, receiver, amount), this.client);\n }\n\n unwrap(receiver: Hex, amount: bigint): CtxPromise {\n return createCtxPromise(actions.unwrap(this.actionConfig, receiver, amount), this.client);\n }\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,13 @@
1
+ import { Hex, PublicClient } from 'viem';
2
+ import { BITE } from '@skalenetwork/bite';
3
+ import { S as Signer } from './types-WaeCtQlG.js';
4
+
5
+ type ActionConfig = {
6
+ rpcUrl: string;
7
+ address: Hex;
8
+ publicClient: PublicClient;
9
+ signer: Signer;
10
+ bite: BITE;
11
+ };
12
+
13
+ export type { ActionConfig as A };
@@ -0,0 +1,13 @@
1
+ import { Hex, PublicClient } from 'viem';
2
+ import { BITE } from '@skalenetwork/bite';
3
+ import { S as Signer } from './types-WaeCtQlG.cjs';
4
+
5
+ type ActionConfig = {
6
+ rpcUrl: string;
7
+ address: Hex;
8
+ publicClient: PublicClient;
9
+ signer: Signer;
10
+ bite: BITE;
11
+ };
12
+
13
+ export type { ActionConfig as A };
package/package.json CHANGED
@@ -1,13 +1,12 @@
1
1
  {
2
2
  "name": "@skalenetwork/privacy-sdk",
3
- "version": "0.1.0-develop.0",
3
+ "version": "0.1.0-develop.2",
4
4
  "description": "SDK for interacting with SKALE Programmable Privacy",
5
5
  "repository": {
6
6
  "type": "git",
7
- "url": "https://github.com/skalenetwork/private-pay.git",
8
- "directory": "packages/privacy-sdk"
7
+ "url": "https://github.com/skalenetwork/privacy-sdk.git"
9
8
  },
10
- "homepage": "https://github.com/skalenetwork/private-pay/tree/main/packages/privacy-sdk#readme",
9
+ "homepage": "https://github.com/skalenetwork/privacy-sdk#readme",
11
10
  "type": "module",
12
11
  "main": "./dist/index.cjs",
13
12
  "module": "./dist/index.js",
@@ -43,27 +42,25 @@
43
42
  "typecheck": "tsc --noEmit",
44
43
  "typecheck:all": "tsc --project tsconfig.test.json"
45
44
  },
46
- "peerDependencies": {
47
- "viem": ">=2.0.0"
48
- },
49
45
  "dependencies": {
50
46
  "@noble/ciphers": "^1.2.1",
51
47
  "@noble/curves": "^1.8.2",
52
48
  "@noble/hashes": "^1.7.2",
53
- "@skalenetwork/bite": "^0.8.2-develop.0"
49
+ "@skalenetwork/bite": "^0.8.2-develop.0",
50
+ "viem": "^2.47.0"
54
51
  },
55
52
  "devDependencies": {
56
53
  "@eslint/js": "^10.0.1",
57
54
  "@types/node": "^25.9.3",
58
55
  "@typescript-eslint/eslint-plugin": "^8.60.1",
59
56
  "@typescript-eslint/parser": "^8.60.1",
57
+ "dotenv": "^17.4.2",
60
58
  "eslint": "^10.4.1",
61
59
  "eslint-config-prettier": "^10.1.8",
62
60
  "prettier": "^3.8.4",
63
61
  "tsup": "^8.0.0",
64
62
  "typescript": "^5.5.0",
65
63
  "typescript-eslint": "^8.60.1",
66
- "viem": "^2.47.0",
67
64
  "vitest": "^2.1.9"
68
65
  }
69
66
  }