@zill-protocol/client 4.1.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.
Files changed (108) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/dist/index.d.ts +2 -0
  3. package/dist/index.d.ts.map +1 -0
  4. package/dist/index.js +18 -0
  5. package/dist/index.js.map +1 -0
  6. package/dist/package.json +58 -0
  7. package/dist/src/NocturneClient.d.ts +68 -0
  8. package/dist/src/NocturneClient.d.ts.map +1 -0
  9. package/dist/src/NocturneClient.js +264 -0
  10. package/dist/src/NocturneClient.js.map +1 -0
  11. package/dist/src/NocturneDB.d.ts +100 -0
  12. package/dist/src/NocturneDB.d.ts.map +1 -0
  13. package/dist/src/NocturneDB.js +525 -0
  14. package/dist/src/NocturneDB.js.map +1 -0
  15. package/dist/src/OpTracker.d.ts +13 -0
  16. package/dist/src/OpTracker.d.ts.map +1 -0
  17. package/dist/src/OpTracker.js +34 -0
  18. package/dist/src/OpTracker.js.map +1 -0
  19. package/dist/src/conversion/converter.d.ts +5 -0
  20. package/dist/src/conversion/converter.d.ts.map +1 -0
  21. package/dist/src/conversion/converter.js +15 -0
  22. package/dist/src/conversion/converter.js.map +1 -0
  23. package/dist/src/conversion/index.d.ts +3 -0
  24. package/dist/src/conversion/index.d.ts.map +1 -0
  25. package/dist/src/conversion/index.js +21 -0
  26. package/dist/src/conversion/index.js.map +1 -0
  27. package/dist/src/conversion/mock.d.ts +6 -0
  28. package/dist/src/conversion/mock.d.ts.map +1 -0
  29. package/dist/src/conversion/mock.js +14 -0
  30. package/dist/src/conversion/mock.js.map +1 -0
  31. package/dist/src/index.d.ts +14 -0
  32. package/dist/src/index.d.ts.map +1 -0
  33. package/dist/src/index.js +39 -0
  34. package/dist/src/index.js.map +1 -0
  35. package/dist/src/opRequestGas.d.ts +20 -0
  36. package/dist/src/opRequestGas.d.ts.map +1 -0
  37. package/dist/src/opRequestGas.js +321 -0
  38. package/dist/src/opRequestGas.js.map +1 -0
  39. package/dist/src/operationRequest/builder.d.ts +40 -0
  40. package/dist/src/operationRequest/builder.d.ts.map +1 -0
  41. package/dist/src/operationRequest/builder.js +192 -0
  42. package/dist/src/operationRequest/builder.js.map +1 -0
  43. package/dist/src/operationRequest/index.d.ts +3 -0
  44. package/dist/src/operationRequest/index.d.ts.map +1 -0
  45. package/dist/src/operationRequest/index.js +6 -0
  46. package/dist/src/operationRequest/index.js.map +1 -0
  47. package/dist/src/operationRequest/operationRequest.d.ts +50 -0
  48. package/dist/src/operationRequest/operationRequest.d.ts.map +1 -0
  49. package/dist/src/operationRequest/operationRequest.js +16 -0
  50. package/dist/src/operationRequest/operationRequest.js.map +1 -0
  51. package/dist/src/prepareOperation.d.ts +21 -0
  52. package/dist/src/prepareOperation.d.ts.map +1 -0
  53. package/dist/src/prepareOperation.js +256 -0
  54. package/dist/src/prepareOperation.js.map +1 -0
  55. package/dist/src/proveOperation.d.ts +7 -0
  56. package/dist/src/proveOperation.d.ts.map +1 -0
  57. package/dist/src/proveOperation.js +79 -0
  58. package/dist/src/proveOperation.js.map +1 -0
  59. package/dist/src/signOperation.d.ts +3 -0
  60. package/dist/src/signOperation.d.ts.map +1 -0
  61. package/dist/src/signOperation.js +61 -0
  62. package/dist/src/signOperation.js.map +1 -0
  63. package/dist/src/snapJsonRpc.d.ts +55 -0
  64. package/dist/src/snapJsonRpc.d.ts.map +1 -0
  65. package/dist/src/snapJsonRpc.js +63 -0
  66. package/dist/src/snapJsonRpc.js.map +1 -0
  67. package/dist/src/syncSDK.d.ts +17 -0
  68. package/dist/src/syncSDK.d.ts.map +1 -0
  69. package/dist/src/syncSDK.js +188 -0
  70. package/dist/src/syncSDK.js.map +1 -0
  71. package/dist/src/types.d.ts +60 -0
  72. package/dist/src/types.d.ts.map +1 -0
  73. package/dist/src/types.js +3 -0
  74. package/dist/src/types.js.map +1 -0
  75. package/dist/src/utils/constants.d.ts +3 -0
  76. package/dist/src/utils/constants.d.ts.map +1 -0
  77. package/dist/src/utils/constants.js +20 -0
  78. package/dist/src/utils/constants.js.map +1 -0
  79. package/dist/src/utils/index.d.ts +3 -0
  80. package/dist/src/utils/index.d.ts.map +1 -0
  81. package/dist/src/utils/index.js +19 -0
  82. package/dist/src/utils/index.js.map +1 -0
  83. package/dist/src/utils/misc.d.ts +13 -0
  84. package/dist/src/utils/misc.d.ts.map +1 -0
  85. package/dist/src/utils/misc.js +77 -0
  86. package/dist/src/utils/misc.js.map +1 -0
  87. package/dist/tsconfig.tsbuildinfo +1 -0
  88. package/package.json +58 -0
  89. package/src/NocturneClient.ts +415 -0
  90. package/src/NocturneDB.ts +761 -0
  91. package/src/OpTracker.ts +44 -0
  92. package/src/conversion/converter.ts +22 -0
  93. package/src/conversion/index.ts +2 -0
  94. package/src/conversion/mock.ts +11 -0
  95. package/src/index.ts +14 -0
  96. package/src/opRequestGas.ts +487 -0
  97. package/src/operationRequest/builder.ts +359 -0
  98. package/src/operationRequest/index.ts +16 -0
  99. package/src/operationRequest/operationRequest.ts +87 -0
  100. package/src/prepareOperation.ts +420 -0
  101. package/src/proveOperation.ts +124 -0
  102. package/src/signOperation.ts +116 -0
  103. package/src/snapJsonRpc.ts +109 -0
  104. package/src/syncSDK.ts +285 -0
  105. package/src/types.ts +83 -0
  106. package/src/utils/constants.ts +16 -0
  107. package/src/utils/index.ts +2 -0
  108. package/src/utils/misc.ts +107 -0
@@ -0,0 +1,359 @@
1
+ import {
2
+ NocturneConfig,
3
+ loadNocturneConfigBuiltin,
4
+ } from "@zill-protocol/config";
5
+ import { CanonAddress, StealthAddress } from "@zill-protocol/crypto";
6
+ import {
7
+ ConfidentialPayment,
8
+ OperationGasParams,
9
+ OperationRequestWithMetadata,
10
+ OperationRequest,
11
+ UnwrapRequest,
12
+ ConfidentialPaymentRequest,
13
+ RefundRequest,
14
+ } from "./operationRequest";
15
+ import {
16
+ Action,
17
+ Address,
18
+ Asset,
19
+ AssetTrait,
20
+ MapWithObjectKeys,
21
+ } from "@zill-protocol/core";
22
+ import { ethers } from "ethers";
23
+ import { OperationMetadata, OperationMetadataItem } from "../types";
24
+ import { chainIdToNetworkName } from "../utils/constants";
25
+
26
+ export type OpRequestBuilder = OpRequestBuilderExt<BaseOpRequestBuilder>;
27
+
28
+ export interface BuilderItemToProcess {
29
+ unwraps: UnwrapRequest[];
30
+ confidentialPayments: ConfidentialPaymentRequest[];
31
+ refunds: RefundRequest[];
32
+ actions: Action[];
33
+ metadatas: OperationMetadataItem[];
34
+ }
35
+
36
+ // generic type for an `OpRequestBuilder` that can be "extended" via plugins
37
+ export type OpRequestBuilderExt<E extends BaseOpRequestBuilder> = E & {
38
+ // "extend" the builder's functionality by applying a `plugin`
39
+ use<E2 extends E>(
40
+ plugin: OpRequestBuilderPlugin<E, E2>
41
+ ): OpRequestBuilderExt<E2>;
42
+ };
43
+
44
+ // methods that are available by default on any implementor of `OpRequestBuilderExt`
45
+ export interface BaseOpRequestBuilder {
46
+ provider: ethers.providers.JsonRpcProvider;
47
+ config: NocturneConfig;
48
+
49
+ _op: OperationRequest;
50
+ _builderItemsToProcess: Promise<BuilderItemToProcess>[];
51
+
52
+ build(): Promise<OperationRequestWithMetadata>;
53
+
54
+ // add a plugin promise to await, resolves to unwraps, refunds, and actions to enqueue
55
+ // returns `this` so it's chainable
56
+ pluginFn(pluginPromise: Promise<BuilderItemToProcess>): this;
57
+
58
+ // add an action to the operation
59
+ // returns `this` so it's chainable
60
+ // CAUTION: this is a low-level method that should only be used by plugins
61
+ __action(contractAddress: Address, encodedFunction: string): this;
62
+
63
+ // specify the operation should unwrap `amountUnits` of `asset`
64
+ // `ammountUnits` is the amount in EVM (uint256) representation. It is up to
65
+ // the caller to handle decimal conversions
66
+ // returns `this` so it's chainable
67
+ // CAUTION: this is a low-level method that should only be used by plugins
68
+ __unwrap(asset: Asset, amountUnits: bigint): this;
69
+
70
+ // add a confidential payment to the operation
71
+ // returns `this` so it's chainable
72
+ confidentialPayment(
73
+ asset: Asset,
74
+ amountUnits: bigint,
75
+ receiver: CanonAddress
76
+ ): this;
77
+
78
+ // indicates that the operation expects a refund of asset `Asset`.
79
+ // CAUTION: this is a low-level method that should only be used by plugins
80
+ __refund(refund: RefundRequest): this;
81
+
82
+ // set the operation's `refundAddr` stealth address up-front.
83
+ // if this is not set, the wallet will generate a new one
84
+ // returns `this` so it's chainable
85
+ refundAddr(addr: StealthAddress): this;
86
+
87
+ // set deadline to operation
88
+ // TODO: what's the unit?
89
+ deadline(deadline: bigint): this;
90
+
91
+ // Specify gas parameters up-front.
92
+ // this is optional - if not given, the SDK will estimate it for you.
93
+ // it's recommended to just let the SDK estimate this instead.
94
+ // returns `this` so it's chainable
95
+ gas(gasParams: OperationGasParams): this;
96
+ gasPrice(gasPrice: bigint): this;
97
+ }
98
+
99
+ // an `OpRequestBuilder` plugin
100
+ // this is simply a function from `OpRequestBuilderExt<E>` to `OpRequestBuilderExt<E2>`,
101
+ // where `E2` extends `E`, and both represent the extra "stuff" the plugin adds to the builder,
102
+ // which may include arbitrary properties and/or methods
103
+ export type OpRequestBuilderPlugin<
104
+ E extends BaseOpRequestBuilder,
105
+ E2 extends E
106
+ > = (inner: OpRequestBuilderExt<E>) => OpRequestBuilderExt<E2>;
107
+
108
+ // utility type used in `OpRequestBuilder` to match together
109
+ // conf payments and join split requests
110
+ export type UnwrapAmountAndPaymentsForAsset = {
111
+ unwrapAmount: bigint;
112
+ payments: ConfidentialPayment[];
113
+ };
114
+
115
+ // the base OpRequestBuilder. This is the only thing users should explicitly construct.
116
+ // to add functionality (erc20s, protocol integrations, etc), user should call `.use(plugin)` with the relevant plugin
117
+ export function newOpRequestBuilder(
118
+ provider: ethers.providers.JsonRpcProvider,
119
+ chainId: bigint,
120
+ config?: NocturneConfig // use override config instead of defaulting to builtin for chainid (for testing purposes)
121
+ ): OpRequestBuilderExt<BaseOpRequestBuilder> {
122
+ if (!config) {
123
+ const networkName = chainIdToNetworkName(chainId);
124
+ config = loadNocturneConfigBuiltin(networkName);
125
+ }
126
+
127
+ const _op: OperationRequest = {
128
+ chainId,
129
+ tellerContract: config.tellerAddress,
130
+ joinSplitRequests: [],
131
+ refunds: [],
132
+ actions: [],
133
+ deadline: 0n,
134
+ };
135
+
136
+ const _builderItemsToProcess: Promise<BuilderItemToProcess>[] = [];
137
+
138
+ return {
139
+ provider,
140
+ config,
141
+ _op,
142
+ _builderItemsToProcess,
143
+
144
+ use<E2 extends BaseOpRequestBuilder>(
145
+ plugin: OpRequestBuilderPlugin<BaseOpRequestBuilder, E2>
146
+ ): OpRequestBuilderExt<E2> {
147
+ return plugin(this);
148
+ },
149
+
150
+ pluginFn(pluginPromise: Promise<BuilderItemToProcess>) {
151
+ this._builderItemsToProcess.push(pluginPromise);
152
+ return this;
153
+ },
154
+
155
+ __action(contractAddress: Address, encodedFunction: string) {
156
+ const action: Action = {
157
+ contractAddress: ethers.utils.getAddress(contractAddress),
158
+ encodedFunction,
159
+ };
160
+
161
+ this._builderItemsToProcess.push(
162
+ Promise.resolve({
163
+ unwraps: [],
164
+ confidentialPayments: [],
165
+ refunds: [],
166
+ actions: [action],
167
+ metadatas: [],
168
+ })
169
+ );
170
+
171
+ return this;
172
+ },
173
+
174
+ __unwrap(asset: Asset, amountUnits: bigint) {
175
+ const unwrap: UnwrapRequest = {
176
+ asset,
177
+ unwrapValue: amountUnits,
178
+ };
179
+
180
+ this._builderItemsToProcess.push(
181
+ Promise.resolve({
182
+ unwraps: [unwrap],
183
+ confidentialPayments: [],
184
+ refunds: [],
185
+ actions: [],
186
+ metadatas: [],
187
+ })
188
+ );
189
+
190
+ return this;
191
+ },
192
+
193
+ confidentialPayment(
194
+ asset: Asset,
195
+ amountUnits: bigint,
196
+ receiver: CanonAddress
197
+ ) {
198
+ const payment: ConfidentialPaymentRequest = {
199
+ value: amountUnits,
200
+ receiver,
201
+ asset,
202
+ };
203
+
204
+ this._builderItemsToProcess.push(
205
+ Promise.resolve({
206
+ unwraps: [],
207
+ confidentialPayments: [payment],
208
+ refunds: [],
209
+ actions: [],
210
+ metadatas: [],
211
+ })
212
+ );
213
+
214
+ return this;
215
+ },
216
+
217
+ __refund(refund: RefundRequest) {
218
+ this._builderItemsToProcess.push(
219
+ Promise.resolve({
220
+ unwraps: [],
221
+ confidentialPayments: [],
222
+ refunds: [refund],
223
+ actions: [],
224
+ metadatas: [],
225
+ })
226
+ );
227
+ return this;
228
+ },
229
+
230
+ refundAddr(addr: StealthAddress) {
231
+ this._op.refundAddr = addr;
232
+ return this;
233
+ },
234
+
235
+ deadline(deadline: bigint) {
236
+ this._op.deadline = deadline;
237
+ return this;
238
+ },
239
+
240
+ gas(gasParams: OperationGasParams) {
241
+ const { executionGasLimit, gasPrice } = gasParams;
242
+ this._op.executionGasLimit = executionGasLimit;
243
+ this._op.gasPrice = gasPrice;
244
+ return this;
245
+ },
246
+
247
+ gasPrice(gasPrice: bigint) {
248
+ this._op.gasPrice = gasPrice;
249
+ return this;
250
+ },
251
+
252
+ async build(): Promise<OperationRequestWithMetadata> {
253
+ const metadata: OperationMetadata = {
254
+ items: [],
255
+ };
256
+
257
+ // Await any promises resolving to items to process, then process items
258
+ const netBalanceMap = new MapWithObjectKeys<Asset, bigint>();
259
+ const unwrapAmountsByAsset = new MapWithObjectKeys<Asset, bigint>();
260
+ const confPaymentsByAsset = new MapWithObjectKeys<
261
+ Asset,
262
+ ConfidentialPayment[]
263
+ >();
264
+ for (const prom of this._builderItemsToProcess) {
265
+ const result = await prom;
266
+
267
+ for (const { asset, unwrapValue } of result.unwraps) {
268
+ // Subtract unwrap value from net amount (value being spent from teller)
269
+ netBalanceMap.set(
270
+ asset,
271
+ (netBalanceMap.get(asset) ?? 0n) - unwrapValue
272
+ );
273
+
274
+ // If net amount is negative, must add value to unwrap amount to make action possible
275
+ if ((netBalanceMap.get(asset) ?? 0n) < 0n) {
276
+ unwrapAmountsByAsset.set(
277
+ asset,
278
+ (unwrapAmountsByAsset.get(asset) ?? 0n) + unwrapValue
279
+ );
280
+ netBalanceMap.set(asset, 0n); // Reset net back to 0 now that we've added to unwrap amount
281
+ }
282
+ }
283
+ for (const { asset, value, receiver } of result.confidentialPayments) {
284
+ const existingConfPayments = confPaymentsByAsset.get(asset) ?? [];
285
+ confPaymentsByAsset.set(
286
+ asset,
287
+ existingConfPayments.concat({ value, receiver })
288
+ );
289
+
290
+ metadata.items.push({
291
+ type: "ConfidentialPayment",
292
+ recipient: receiver,
293
+ asset,
294
+ amount: value,
295
+ });
296
+ }
297
+ for (const { contractAddress, encodedFunction } of result.actions) {
298
+ const action: Action = {
299
+ contractAddress: ethers.utils.getAddress(contractAddress),
300
+ encodedFunction,
301
+ };
302
+ this._op.actions.push(action);
303
+ }
304
+ for (const { asset, minRefundValue } of result.refunds) {
305
+ // Refund value adds funds to net balance (value being received to Handler able to spend
306
+ // in subsequent calls)
307
+ netBalanceMap.set(
308
+ asset,
309
+ (netBalanceMap.get(asset) ?? 0n) + minRefundValue
310
+ );
311
+ }
312
+ for (const metadataItem of result.metadatas) {
313
+ metadata.items.push(metadataItem);
314
+ }
315
+ }
316
+
317
+ // Turn unwraps into joinsplit requests and attach payments
318
+ for (const [asset, unwrapAmount] of unwrapAmountsByAsset.entries()) {
319
+ this._op.joinSplitRequests.push({
320
+ asset,
321
+ unwrapValue: unwrapAmount,
322
+ });
323
+ }
324
+ for (const [asset, payments] of confPaymentsByAsset.entries()) {
325
+ for (const payment of payments) {
326
+ const joinSplit = this._op.joinSplitRequests.find(
327
+ (js) =>
328
+ AssetTrait.isSameAsset(js.asset, asset) &&
329
+ js.payment === undefined
330
+ );
331
+ if (joinSplit) {
332
+ joinSplit.payment = payment;
333
+ } else {
334
+ this._op.joinSplitRequests.push({
335
+ asset,
336
+ unwrapValue: 0n,
337
+ payment,
338
+ });
339
+ }
340
+ }
341
+ }
342
+
343
+ // Add refunds for expected outstanding assets
344
+ for (const [asset, netBalance] of netBalanceMap.entries()) {
345
+ if (netBalance > 0n) {
346
+ this._op.refunds.push({
347
+ encodedAsset: AssetTrait.encode(asset),
348
+ minRefundValue: netBalance,
349
+ });
350
+ }
351
+ }
352
+
353
+ return {
354
+ request: this._op,
355
+ meta: metadata,
356
+ };
357
+ },
358
+ };
359
+ }
@@ -0,0 +1,16 @@
1
+ export {
2
+ OperationRequest,
3
+ OperationGasParams,
4
+ OperationRequestWithMetadata,
5
+ UnwrapRequest,
6
+ RefundRequest,
7
+ JoinSplitRequest,
8
+ } from "./operationRequest";
9
+ export {
10
+ OpRequestBuilder,
11
+ BaseOpRequestBuilder,
12
+ OpRequestBuilderExt,
13
+ OpRequestBuilderPlugin,
14
+ BuilderItemToProcess,
15
+ newOpRequestBuilder,
16
+ } from "./builder";
@@ -0,0 +1,87 @@
1
+ import { ethers } from "ethers";
2
+ import { CanonAddress, StealthAddress } from "@zill-protocol/crypto";
3
+ import { OperationMetadata } from "../types";
4
+ import {
5
+ Action,
6
+ Address,
7
+ Asset,
8
+ ExpectedRefund,
9
+ IncludedNote,
10
+ } from "@zill-protocol/core";
11
+
12
+ const ONE_DAY_SECONDS = 24 * 60 * 60;
13
+
14
+ // A joinsplit request is an unwrapRequest plus an optional payment
15
+ export interface JoinSplitRequest {
16
+ asset: Asset;
17
+ unwrapValue: bigint;
18
+ payment?: ConfidentialPayment;
19
+ notes?: IncludedNote[];
20
+ allowGasCompensation?: boolean;
21
+ }
22
+
23
+ export type UnwrapRequest = Omit<JoinSplitRequest, "payment">;
24
+
25
+ export interface RefundRequest extends Omit<ExpectedRefund, "encodedAsset"> {
26
+ asset: Asset;
27
+ }
28
+
29
+ export interface ConfidentialPaymentRequest extends ConfidentialPayment {
30
+ asset: Asset;
31
+ }
32
+
33
+ export interface OperationRequest {
34
+ joinSplitRequests: JoinSplitRequest[];
35
+ refunds: ExpectedRefund[];
36
+ actions: Action[];
37
+ chainId: bigint;
38
+ tellerContract: Address;
39
+ deadline: bigint;
40
+ refundAddr?: StealthAddress;
41
+ // If set, gas simulation is skipped and this limit is used directly.
42
+ executionGasLimit?: bigint;
43
+ gasPrice?: bigint;
44
+ }
45
+
46
+ export interface OperationRequestWithMetadata {
47
+ request: OperationRequest;
48
+ meta: OperationMetadata;
49
+ }
50
+
51
+ export interface GasAccountedOperationRequest
52
+ extends Omit<OperationRequest, "executionGasLimit" | "gasPrice"> {
53
+ gasAssetRefundThreshold: bigint;
54
+ executionGasLimit: bigint;
55
+ gasPrice: bigint;
56
+ gasAsset: Asset;
57
+ totalGasLimit: bigint;
58
+ }
59
+
60
+ export interface OperationGasParams {
61
+ executionGasLimit: bigint;
62
+ gasPrice?: bigint;
63
+ }
64
+
65
+ export interface ConfidentialPayment {
66
+ value: bigint;
67
+ receiver: CanonAddress;
68
+ }
69
+
70
+ export async function ensureOpRequestChainInfo(
71
+ opRequest: OperationRequest,
72
+ provider: ethers.providers.Provider
73
+ ): Promise<OperationRequest> {
74
+ if (opRequest.chainId === 0n) {
75
+ const chainId = BigInt((await provider.getNetwork()).chainId);
76
+ opRequest.chainId = chainId;
77
+ }
78
+
79
+ if (opRequest.deadline === 0n) {
80
+ const deadline = BigInt(
81
+ (await provider.getBlock("latest")).timestamp + ONE_DAY_SECONDS
82
+ );
83
+ opRequest.deadline = deadline;
84
+ }
85
+
86
+ return opRequest;
87
+ }