@shroud-fi/payments 0.1.0
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/LICENSE +21 -0
- package/README.md +61 -0
- package/dist/cjs/amount-privacy.d.ts +30 -0
- package/dist/cjs/amount-privacy.d.ts.map +1 -0
- package/dist/cjs/amount-privacy.js +30 -0
- package/dist/cjs/amount-privacy.js.map +1 -0
- package/dist/cjs/constants.d.ts +7 -0
- package/dist/cjs/constants.d.ts.map +1 -0
- package/dist/cjs/constants.js +10 -0
- package/dist/cjs/constants.js.map +1 -0
- package/dist/cjs/errors.d.ts +57 -0
- package/dist/cjs/errors.d.ts.map +1 -0
- package/dist/cjs/errors.js +91 -0
- package/dist/cjs/errors.js.map +1 -0
- package/dist/cjs/index.d.ts +10 -0
- package/dist/cjs/index.d.ts.map +1 -0
- package/dist/cjs/index.js +42 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/package.json +1 -0
- package/dist/cjs/payments.d.ts +49 -0
- package/dist/cjs/payments.d.ts.map +1 -0
- package/dist/cjs/payments.js +266 -0
- package/dist/cjs/payments.js.map +1 -0
- package/dist/cjs/send-to-wallet.d.ts +57 -0
- package/dist/cjs/send-to-wallet.d.ts.map +1 -0
- package/dist/cjs/send-to-wallet.js +104 -0
- package/dist/cjs/send-to-wallet.js.map +1 -0
- package/dist/cjs/sweep.d.ts +47 -0
- package/dist/cjs/sweep.d.ts.map +1 -0
- package/dist/cjs/sweep.js +241 -0
- package/dist/cjs/sweep.js.map +1 -0
- package/dist/cjs/types.d.ts +27 -0
- package/dist/cjs/types.d.ts.map +1 -0
- package/dist/cjs/types.js +3 -0
- package/dist/cjs/types.js.map +1 -0
- package/dist/esm/amount-privacy.d.ts +30 -0
- package/dist/esm/amount-privacy.d.ts.map +1 -0
- package/dist/esm/amount-privacy.js +25 -0
- package/dist/esm/amount-privacy.js.map +1 -0
- package/dist/esm/constants.d.ts +7 -0
- package/dist/esm/constants.d.ts.map +1 -0
- package/dist/esm/constants.js +7 -0
- package/dist/esm/constants.js.map +1 -0
- package/dist/esm/errors.d.ts +57 -0
- package/dist/esm/errors.d.ts.map +1 -0
- package/dist/esm/errors.js +78 -0
- package/dist/esm/errors.js.map +1 -0
- package/dist/esm/index.d.ts +10 -0
- package/dist/esm/index.d.ts.map +1 -0
- package/dist/esm/index.js +14 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/payments.d.ts +49 -0
- package/dist/esm/payments.d.ts.map +1 -0
- package/dist/esm/payments.js +261 -0
- package/dist/esm/payments.js.map +1 -0
- package/dist/esm/send-to-wallet.d.ts +57 -0
- package/dist/esm/send-to-wallet.d.ts.map +1 -0
- package/dist/esm/send-to-wallet.js +100 -0
- package/dist/esm/send-to-wallet.js.map +1 -0
- package/dist/esm/sweep.d.ts +47 -0
- package/dist/esm/sweep.d.ts.map +1 -0
- package/dist/esm/sweep.js +237 -0
- package/dist/esm/sweep.js.map +1 -0
- package/dist/esm/types.d.ts +27 -0
- package/dist/esm/types.d.ts.map +1 -0
- package/dist/esm/types.js +2 -0
- package/dist/esm/types.js.map +1 -0
- package/dist/tsconfig.cjs.tsbuildinfo +1 -0
- package/dist/tsconfig.esm.tsbuildinfo +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/package.json +64 -0
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.sweepETH = sweepETH;
|
|
4
|
+
exports.sweepERC20 = sweepERC20;
|
|
5
|
+
const viem_1 = require("viem");
|
|
6
|
+
const accounts_1 = require("viem/accounts");
|
|
7
|
+
const transport_1 = require("@shroud-fi/transport");
|
|
8
|
+
const errors_js_1 = require("./errors.js");
|
|
9
|
+
const constants_js_1 = require("./constants.js");
|
|
10
|
+
/**
|
|
11
|
+
* Fetch EIP-1559 fee suggestions with a safe fallback. viem's
|
|
12
|
+
* `estimateFeesPerGas` returns the recommended {maxFeePerGas, maxPriorityFeePerGas}
|
|
13
|
+
* given the current base fee; on chains where the method 404s we fall back to
|
|
14
|
+
* the legacy `getGasPrice` + a small priority tip so the tx remains valid.
|
|
15
|
+
*
|
|
16
|
+
* Crucially we DON'T set maxPriorityFeePerGas == maxFeePerGas — Geth-derived
|
|
17
|
+
* RPCs reject EIP-1559 transactions where the priority cap equals the total
|
|
18
|
+
* cap and the base fee is non-zero (effective tip becomes 0, but the producer
|
|
19
|
+
* still gates on `priority < maxFee - baseFee`). Splitting them keeps Base
|
|
20
|
+
* Sepolia + mainnet RPCs from returning TransactionRejectedRpcError (-32003).
|
|
21
|
+
*/
|
|
22
|
+
async function suggestEip1559Fees(transport, options) {
|
|
23
|
+
if (options?.maxFeePerGas !== undefined &&
|
|
24
|
+
options.maxPriorityFeePerGas !== undefined) {
|
|
25
|
+
return {
|
|
26
|
+
maxFeePerGas: options.maxFeePerGas,
|
|
27
|
+
maxPriorityFeePerGas: options.maxPriorityFeePerGas,
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
try {
|
|
31
|
+
const fees = await transport.publicClient.estimateFeesPerGas();
|
|
32
|
+
return {
|
|
33
|
+
maxFeePerGas: options?.maxFeePerGas ?? fees.maxFeePerGas,
|
|
34
|
+
maxPriorityFeePerGas: options?.maxPriorityFeePerGas ?? fees.maxPriorityFeePerGas,
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
const legacy = await transport.publicClient.getGasPrice();
|
|
39
|
+
const priority = options?.maxPriorityFeePerGas ?? legacy / 10n;
|
|
40
|
+
const fee = options?.maxFeePerGas ?? legacy * 2n;
|
|
41
|
+
return { maxFeePerGas: fee, maxPriorityFeePerGas: priority };
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* L2 chains (Base, Optimism, etc.) deduct an L1 data-posting fee from the
|
|
46
|
+
* sender's balance on top of the L2 gas. The sweep formula `balance - L2gas`
|
|
47
|
+
* doesn't account for it and the RPC rejects the broadcast as underfunded.
|
|
48
|
+
*
|
|
49
|
+
* We reserve a small portion of the swept value to cover the L1 fee plus
|
|
50
|
+
* fluctuation headroom. Magnitude: keep min(balance * 2%, 0.0001 ETH).
|
|
51
|
+
*/
|
|
52
|
+
function l2DataFeeReserve(balance) {
|
|
53
|
+
const percent = balance / 50n; // 2 %
|
|
54
|
+
const cap = 100000000000000n; // 0.0001 ETH
|
|
55
|
+
return percent < cap ? percent : cap;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Apply gas multiplier (basis-of-100 percent). Default 120n = 120% headroom.
|
|
59
|
+
* Performs ceil-division to avoid undershooting fees.
|
|
60
|
+
*/
|
|
61
|
+
function applyGasMultiplier(gas, multiplier) {
|
|
62
|
+
// ceil((gas * multiplier) / 100)
|
|
63
|
+
return (gas * multiplier + 99n) / 100n;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Compute the required ETH gas reserve for a transaction.
|
|
67
|
+
*
|
|
68
|
+
* No amounts are logged or surfaced in errors — privacy invariant #5.
|
|
69
|
+
*/
|
|
70
|
+
async function resolveGasCost(transport, gasEstimate, options) {
|
|
71
|
+
const multiplier = options?.gasMultiplier ?? constants_js_1.DEFAULT_GAS_MULTIPLIER;
|
|
72
|
+
const adjustedGas = applyGasMultiplier(gasEstimate, multiplier);
|
|
73
|
+
const feePerGas = options?.maxFeePerGas ?? (await transport.publicClient.getGasPrice());
|
|
74
|
+
return adjustedGas * feePerGas;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Sweep the entire ETH balance from a stealth address to a destination.
|
|
78
|
+
*
|
|
79
|
+
* @param transport - ShroudFi transport (publicClient must reach the target chain)
|
|
80
|
+
* @param stealthPrivateKey - one-time stealth address private key. Treat as
|
|
81
|
+
* sensitive: caller MUST NOT log, persist, or transmit this value. The SDK
|
|
82
|
+
* does not retain it after the call returns.
|
|
83
|
+
* @param destination - final address that receives swept ETH
|
|
84
|
+
* @param options - optional fee/nonce overrides
|
|
85
|
+
*
|
|
86
|
+
* @remarks Phase 1: self-funded sweep. The stealth address pays its own gas in ETH,
|
|
87
|
+
* which creates a gas-funding correlation vector documented in research (Umbra deanonymization
|
|
88
|
+
* heuristic H2). This will be addressed in Phase 5 by a gasless relayer flow.
|
|
89
|
+
*
|
|
90
|
+
* @remarks Balance/nonce/gas-price are queried separately before signing. Callers running
|
|
91
|
+
* sweeps concurrently against the same stealth address should pass an explicit `nonce` in
|
|
92
|
+
* options to avoid races. Stack traces of thrown errors should NOT be logged by callers —
|
|
93
|
+
* they may contain RPC payload metadata.
|
|
94
|
+
*/
|
|
95
|
+
async function sweepETH(transport, stealthPrivateKey, destination, options) {
|
|
96
|
+
if (!destination || destination === constants_js_1.ZERO_ADDRESS) {
|
|
97
|
+
throw new errors_js_1.SweepError('Invalid destination');
|
|
98
|
+
}
|
|
99
|
+
const account = (0, accounts_1.privateKeyToAccount)(stealthPrivateKey);
|
|
100
|
+
const balance = await transport.publicClient.getBalance({
|
|
101
|
+
address: account.address,
|
|
102
|
+
});
|
|
103
|
+
if (balance === 0n) {
|
|
104
|
+
throw new errors_js_1.InsufficientBalanceError();
|
|
105
|
+
}
|
|
106
|
+
const gasCost = await resolveGasCost(transport, constants_js_1.ETH_TRANSFER_GAS_ESTIMATE, options);
|
|
107
|
+
const l2Reserve = l2DataFeeReserve(balance);
|
|
108
|
+
if (balance <= gasCost + l2Reserve) {
|
|
109
|
+
throw new errors_js_1.InsufficientBalanceError();
|
|
110
|
+
}
|
|
111
|
+
const valueToSend = balance - gasCost - l2Reserve;
|
|
112
|
+
const chain = transport.chain;
|
|
113
|
+
const nonce = options?.nonce ??
|
|
114
|
+
(await transport.publicClient.getTransactionCount({
|
|
115
|
+
address: account.address,
|
|
116
|
+
}));
|
|
117
|
+
const { maxFeePerGas, maxPriorityFeePerGas } = await suggestEip1559Fees(transport, options);
|
|
118
|
+
const serializedTransaction = await account.signTransaction({
|
|
119
|
+
to: destination,
|
|
120
|
+
value: valueToSend,
|
|
121
|
+
gas: constants_js_1.ETH_TRANSFER_GAS_ESTIMATE,
|
|
122
|
+
maxFeePerGas,
|
|
123
|
+
maxPriorityFeePerGas,
|
|
124
|
+
nonce,
|
|
125
|
+
chainId: chain.id,
|
|
126
|
+
type: 'eip1559',
|
|
127
|
+
});
|
|
128
|
+
let txHash;
|
|
129
|
+
try {
|
|
130
|
+
txHash = await transport.publicClient.sendRawTransaction({
|
|
131
|
+
serializedTransaction,
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
catch (err) {
|
|
135
|
+
// Privacy: surface only the error class name + a structured tag; never
|
|
136
|
+
// include the serialized transaction (which contains the signature) or
|
|
137
|
+
// the raw RPC error payload (which may quote bytes).
|
|
138
|
+
const tag = err instanceof Error ? err.name : 'unknown';
|
|
139
|
+
throw new errors_js_1.SweepError(`sweep broadcast failed (${tag})`);
|
|
140
|
+
}
|
|
141
|
+
const receipt = await transport.publicClient.waitForTransactionReceipt({
|
|
142
|
+
hash: txHash,
|
|
143
|
+
});
|
|
144
|
+
const swept = {
|
|
145
|
+
txHash,
|
|
146
|
+
destination,
|
|
147
|
+
token: constants_js_1.ETH_SENTINEL,
|
|
148
|
+
blockNumber: receipt.blockNumber,
|
|
149
|
+
};
|
|
150
|
+
return swept;
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Sweep the entire ERC20 balance from a stealth address to a destination.
|
|
154
|
+
*
|
|
155
|
+
* The stealth address must already hold enough ETH to pay gas for the
|
|
156
|
+
* ERC20 transfer. Funding it from another account links the two — see
|
|
157
|
+
* privacy notes below.
|
|
158
|
+
*
|
|
159
|
+
* @param transport - ShroudFi transport
|
|
160
|
+
* @param stealthPrivateKey - one-time stealth private key (see sweepETH note)
|
|
161
|
+
* @param token - ERC20 contract address
|
|
162
|
+
* @param destination - final address that receives swept tokens
|
|
163
|
+
* @param options - optional fee/nonce overrides
|
|
164
|
+
*
|
|
165
|
+
* @remarks Phase 1: self-funded sweep. The stealth address pays its own gas in ETH,
|
|
166
|
+
* which creates a gas-funding correlation vector documented in research (Umbra deanonymization
|
|
167
|
+
* heuristic H2). This will be addressed in Phase 5 by a gasless relayer flow.
|
|
168
|
+
*
|
|
169
|
+
* @remarks Balance/nonce/gas-price are queried separately before signing. Callers running
|
|
170
|
+
* sweeps concurrently against the same stealth address should pass an explicit `nonce` in
|
|
171
|
+
* options to avoid races. Stack traces of thrown errors should NOT be logged by callers —
|
|
172
|
+
* they may contain RPC payload metadata.
|
|
173
|
+
*/
|
|
174
|
+
async function sweepERC20(transport, stealthPrivateKey, token, destination, options) {
|
|
175
|
+
if (!destination || destination === constants_js_1.ZERO_ADDRESS) {
|
|
176
|
+
throw new errors_js_1.SweepError('Invalid destination');
|
|
177
|
+
}
|
|
178
|
+
if (!token || token === constants_js_1.ZERO_ADDRESS) {
|
|
179
|
+
throw new errors_js_1.SweepError('Invalid token');
|
|
180
|
+
}
|
|
181
|
+
const account = (0, accounts_1.privateKeyToAccount)(stealthPrivateKey);
|
|
182
|
+
const tokenBalance = (await transport.publicClient.readContract({
|
|
183
|
+
address: token,
|
|
184
|
+
abi: transport_1.ERC20Abi,
|
|
185
|
+
functionName: 'balanceOf',
|
|
186
|
+
args: [account.address],
|
|
187
|
+
}));
|
|
188
|
+
if (tokenBalance === 0n) {
|
|
189
|
+
throw new errors_js_1.InsufficientBalanceError();
|
|
190
|
+
}
|
|
191
|
+
const ethBalance = await transport.publicClient.getBalance({
|
|
192
|
+
address: account.address,
|
|
193
|
+
});
|
|
194
|
+
const gasCost = await resolveGasCost(transport, constants_js_1.ERC20_TRANSFER_GAS_ESTIMATE, options);
|
|
195
|
+
if (ethBalance < gasCost) {
|
|
196
|
+
throw new errors_js_1.InsufficientBalanceError();
|
|
197
|
+
}
|
|
198
|
+
const data = (0, viem_1.encodeFunctionData)({
|
|
199
|
+
abi: transport_1.ERC20Abi,
|
|
200
|
+
functionName: 'transfer',
|
|
201
|
+
args: [destination, tokenBalance],
|
|
202
|
+
});
|
|
203
|
+
const chain = transport.chain;
|
|
204
|
+
const nonce = options?.nonce ??
|
|
205
|
+
(await transport.publicClient.getTransactionCount({
|
|
206
|
+
address: account.address,
|
|
207
|
+
}));
|
|
208
|
+
const { maxFeePerGas, maxPriorityFeePerGas } = await suggestEip1559Fees(transport, options);
|
|
209
|
+
const serializedTransaction = await account.signTransaction({
|
|
210
|
+
to: token,
|
|
211
|
+
value: 0n,
|
|
212
|
+
data,
|
|
213
|
+
gas: constants_js_1.ERC20_TRANSFER_GAS_ESTIMATE,
|
|
214
|
+
maxFeePerGas,
|
|
215
|
+
maxPriorityFeePerGas,
|
|
216
|
+
nonce,
|
|
217
|
+
chainId: chain.id,
|
|
218
|
+
type: 'eip1559',
|
|
219
|
+
});
|
|
220
|
+
let txHash;
|
|
221
|
+
try {
|
|
222
|
+
txHash = await transport.publicClient.sendRawTransaction({
|
|
223
|
+
serializedTransaction,
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
catch (err) {
|
|
227
|
+
const tag = err instanceof Error ? err.name : 'unknown';
|
|
228
|
+
throw new errors_js_1.SweepError(`sweep broadcast failed (${tag})`);
|
|
229
|
+
}
|
|
230
|
+
const receipt = await transport.publicClient.waitForTransactionReceipt({
|
|
231
|
+
hash: txHash,
|
|
232
|
+
});
|
|
233
|
+
const swept = {
|
|
234
|
+
txHash,
|
|
235
|
+
destination,
|
|
236
|
+
token,
|
|
237
|
+
blockNumber: receipt.blockNumber,
|
|
238
|
+
};
|
|
239
|
+
return swept;
|
|
240
|
+
}
|
|
241
|
+
//# sourceMappingURL=sweep.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sweep.js","sourceRoot":"","sources":["../../src/sweep.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { Address, Hash, Hex } from 'viem';
|
|
2
|
+
export interface SendOptions {
|
|
3
|
+
readonly gasMultiplier?: bigint;
|
|
4
|
+
readonly maxFeePerGas?: bigint;
|
|
5
|
+
readonly maxPriorityFeePerGas?: bigint;
|
|
6
|
+
readonly nonce?: number;
|
|
7
|
+
}
|
|
8
|
+
export interface PaymentReceipt {
|
|
9
|
+
readonly txHash: Hash;
|
|
10
|
+
readonly stealthAddress: Address;
|
|
11
|
+
readonly ephemeralPubKey: Hex;
|
|
12
|
+
readonly viewTag: number;
|
|
13
|
+
readonly blockNumber: bigint;
|
|
14
|
+
readonly token: Address;
|
|
15
|
+
}
|
|
16
|
+
export interface SweepReceipt {
|
|
17
|
+
readonly txHash: Hash;
|
|
18
|
+
readonly destination: Address;
|
|
19
|
+
readonly token: Address;
|
|
20
|
+
readonly blockNumber: bigint;
|
|
21
|
+
}
|
|
22
|
+
export interface PreparedStealthPayment {
|
|
23
|
+
readonly stealthAddress: Address;
|
|
24
|
+
readonly ephemeralPubKey: Hex;
|
|
25
|
+
readonly viewTag: number;
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,MAAM,CAAC;AAE/C,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,oBAAoB,CAAC,EAAE,MAAM,CAAC;IACvC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAC;IACtB,QAAQ,CAAC,cAAc,EAAE,OAAO,CAAC;IACjC,QAAQ,CAAC,eAAe,EAAE,GAAG,CAAC;IAC9B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;CACzB;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAC;IACtB,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC;IAC9B,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;CAC9B;AAED,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,cAAc,EAAE,OAAO,CAAC;IACjC,QAAQ,CAAC,eAAe,EAAE,GAAG,CAAC;IAC9B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { Address } from 'viem';
|
|
2
|
+
export interface ShieldResult {
|
|
3
|
+
readonly txHash: string;
|
|
4
|
+
readonly noteId?: string;
|
|
5
|
+
}
|
|
6
|
+
export interface PrivateTransferResult {
|
|
7
|
+
readonly txHash: string;
|
|
8
|
+
readonly recipient: Address;
|
|
9
|
+
}
|
|
10
|
+
export interface UnshieldResult {
|
|
11
|
+
readonly txHash: string;
|
|
12
|
+
}
|
|
13
|
+
export interface AmountPrivacyProvider {
|
|
14
|
+
readonly name: string;
|
|
15
|
+
shield(token: Address, amount: bigint): Promise<ShieldResult>;
|
|
16
|
+
privateTransfer(to: Address, amount: bigint, token: Address): Promise<PrivateTransferResult>;
|
|
17
|
+
unshield(amount: bigint, token: Address): Promise<UnshieldResult>;
|
|
18
|
+
grantViewAccess(viewer: Address): Promise<void>;
|
|
19
|
+
estimateGas(token: Address, amount: bigint): Promise<bigint>;
|
|
20
|
+
}
|
|
21
|
+
export declare class NullAmountPrivacyProvider implements AmountPrivacyProvider {
|
|
22
|
+
readonly name = "null";
|
|
23
|
+
shield(_token?: Address, _amount?: bigint): Promise<ShieldResult>;
|
|
24
|
+
privateTransfer(_to?: Address, _amount?: bigint, _token?: Address): Promise<PrivateTransferResult>;
|
|
25
|
+
unshield(_amount?: bigint, _token?: Address): Promise<UnshieldResult>;
|
|
26
|
+
grantViewAccess(_viewer?: Address): Promise<void>;
|
|
27
|
+
estimateGas(_token?: Address, _amount?: bigint): Promise<bigint>;
|
|
28
|
+
}
|
|
29
|
+
export declare function assertSupported(provider: AmountPrivacyProvider): void;
|
|
30
|
+
//# sourceMappingURL=amount-privacy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"amount-privacy.d.ts","sourceRoot":"","sources":["../../src/amount-privacy.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAGpC,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;CAC7B;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;IAC9D,eAAe,CAAC,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,qBAAqB,CAAC,CAAC;IAC7F,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;IAClE,eAAe,CAAC,MAAM,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAChD,WAAW,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CAC9D;AAED,qBAAa,yBAA0B,YAAW,qBAAqB;IACrE,QAAQ,CAAC,IAAI,UAAU;IAEjB,MAAM,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;IAIjE,eAAe,CACnB,GAAG,CAAC,EAAE,OAAO,EACb,OAAO,CAAC,EAAE,MAAM,EAChB,MAAM,CAAC,EAAE,OAAO,GACf,OAAO,CAAC,qBAAqB,CAAC;IAI3B,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,cAAc,CAAC;IAIrE,eAAe,CAAC,OAAO,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAIjD,WAAW,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;CAGvE;AAED,wBAAgB,eAAe,CAAC,QAAQ,EAAE,qBAAqB,GAAG,IAAI,CAIrE"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { AmountPrivacyNotSupportedError } from './errors.js';
|
|
2
|
+
export class NullAmountPrivacyProvider {
|
|
3
|
+
name = 'null';
|
|
4
|
+
async shield(_token, _amount) {
|
|
5
|
+
throw new AmountPrivacyNotSupportedError('shield');
|
|
6
|
+
}
|
|
7
|
+
async privateTransfer(_to, _amount, _token) {
|
|
8
|
+
throw new AmountPrivacyNotSupportedError('privateTransfer');
|
|
9
|
+
}
|
|
10
|
+
async unshield(_amount, _token) {
|
|
11
|
+
throw new AmountPrivacyNotSupportedError('unshield');
|
|
12
|
+
}
|
|
13
|
+
async grantViewAccess(_viewer) {
|
|
14
|
+
throw new AmountPrivacyNotSupportedError('grantViewAccess');
|
|
15
|
+
}
|
|
16
|
+
async estimateGas(_token, _amount) {
|
|
17
|
+
throw new AmountPrivacyNotSupportedError('estimateGas');
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
export function assertSupported(provider) {
|
|
21
|
+
if (provider.name === 'null') {
|
|
22
|
+
throw new AmountPrivacyNotSupportedError(provider.name);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=amount-privacy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"amount-privacy.js","sourceRoot":"","sources":["../../src/amount-privacy.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,8BAA8B,EAAE,MAAM,aAAa,CAAC;AAyB7D,MAAM,OAAO,yBAAyB;IAC3B,IAAI,GAAG,MAAM,CAAC;IAEvB,KAAK,CAAC,MAAM,CAAC,MAAgB,EAAE,OAAgB;QAC7C,MAAM,IAAI,8BAA8B,CAAC,QAAQ,CAAC,CAAC;IACrD,CAAC;IAED,KAAK,CAAC,eAAe,CACnB,GAAa,EACb,OAAgB,EAChB,MAAgB;QAEhB,MAAM,IAAI,8BAA8B,CAAC,iBAAiB,CAAC,CAAC;IAC9D,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,OAAgB,EAAE,MAAgB;QAC/C,MAAM,IAAI,8BAA8B,CAAC,UAAU,CAAC,CAAC;IACvD,CAAC;IAED,KAAK,CAAC,eAAe,CAAC,OAAiB;QACrC,MAAM,IAAI,8BAA8B,CAAC,iBAAiB,CAAC,CAAC;IAC9D,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,MAAgB,EAAE,OAAgB;QAClD,MAAM,IAAI,8BAA8B,CAAC,aAAa,CAAC,CAAC;IAC1D,CAAC;CACF;AAED,MAAM,UAAU,eAAe,CAAC,QAA+B;IAC7D,IAAI,QAAQ,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;QAC7B,MAAM,IAAI,8BAA8B,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;IAC1D,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export declare const DEFAULT_GAS_MULTIPLIER = 120n;
|
|
2
|
+
export declare const ETH_SENTINEL: "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE";
|
|
3
|
+
export declare const ZERO_ADDRESS: "0x0000000000000000000000000000000000000000";
|
|
4
|
+
export declare const SCHEME_ID = 1n;
|
|
5
|
+
export declare const ERC20_TRANSFER_GAS_ESTIMATE = 65000n;
|
|
6
|
+
export declare const ETH_TRANSFER_GAS_ESTIMATE = 21000n;
|
|
7
|
+
//# sourceMappingURL=constants.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/constants.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,sBAAsB,OAAO,CAAC;AAE3C,eAAO,MAAM,YAAY,8CAA0E,CAAC;AAEpG,eAAO,MAAM,YAAY,8CAA0E,CAAC;AAEpG,eAAO,MAAM,SAAS,KAAK,CAAC;AAE5B,eAAO,MAAM,2BAA2B,SAAU,CAAC;AACnD,eAAO,MAAM,yBAAyB,SAAU,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export const DEFAULT_GAS_MULTIPLIER = 120n;
|
|
2
|
+
export const ETH_SENTINEL = '0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE';
|
|
3
|
+
export const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000';
|
|
4
|
+
export const SCHEME_ID = 1n;
|
|
5
|
+
export const ERC20_TRANSFER_GAS_ESTIMATE = 65000n;
|
|
6
|
+
export const ETH_TRANSFER_GAS_ESTIMATE = 21000n;
|
|
7
|
+
//# sourceMappingURL=constants.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/constants.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,sBAAsB,GAAG,IAAI,CAAC;AAE3C,MAAM,CAAC,MAAM,YAAY,GAAG,4CAAuE,CAAC;AAEpG,MAAM,CAAC,MAAM,YAAY,GAAG,4CAAuE,CAAC;AAEpG,MAAM,CAAC,MAAM,SAAS,GAAG,EAAE,CAAC;AAE5B,MAAM,CAAC,MAAM,2BAA2B,GAAG,MAAO,CAAC;AACnD,MAAM,CAAC,MAAM,yBAAyB,GAAG,MAAO,CAAC"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
export declare class PaymentError extends Error {
|
|
2
|
+
readonly name: string;
|
|
3
|
+
constructor(message: string);
|
|
4
|
+
}
|
|
5
|
+
export declare class SweepError extends Error {
|
|
6
|
+
readonly name: string;
|
|
7
|
+
constructor(message: string);
|
|
8
|
+
}
|
|
9
|
+
export declare class InvalidRecipientError extends PaymentError {
|
|
10
|
+
readonly name: string;
|
|
11
|
+
constructor();
|
|
12
|
+
}
|
|
13
|
+
export declare class InsufficientBalanceError extends SweepError {
|
|
14
|
+
readonly name: string;
|
|
15
|
+
constructor();
|
|
16
|
+
}
|
|
17
|
+
export declare class ZeroAmountError extends PaymentError {
|
|
18
|
+
readonly name: string;
|
|
19
|
+
constructor();
|
|
20
|
+
}
|
|
21
|
+
export declare class AmountPrivacyNotSupportedError extends Error {
|
|
22
|
+
readonly name: string;
|
|
23
|
+
constructor(method: string);
|
|
24
|
+
}
|
|
25
|
+
export declare class MissingWalletClientError extends PaymentError {
|
|
26
|
+
readonly name: string;
|
|
27
|
+
constructor();
|
|
28
|
+
}
|
|
29
|
+
export declare class StealthPaymentContractNotConfiguredError extends PaymentError {
|
|
30
|
+
readonly name: string;
|
|
31
|
+
constructor();
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Thrown when a sender tries to pay a wallet that has not yet registered a
|
|
35
|
+
* stealth meta-address in the canonical ERC-6538 registry. The recipient must
|
|
36
|
+
* onboard first (publish their (S, B) pubkeys) before stealth payments are
|
|
37
|
+
* possible.
|
|
38
|
+
*
|
|
39
|
+
* Privacy note: the offending wallet address is NOT placed in `.message`. It
|
|
40
|
+
* is exposed via the `wallet` property so callers can show a useful UI hint
|
|
41
|
+
* without leaking the address into logs that only capture `.message`.
|
|
42
|
+
*/
|
|
43
|
+
export declare class RecipientNotOnboardedError extends PaymentError {
|
|
44
|
+
readonly name: string;
|
|
45
|
+
readonly wallet: `0x${string}`;
|
|
46
|
+
constructor(wallet: `0x${string}`);
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Thrown when the bytes returned by `stealthMetaAddressOf` are not the
|
|
50
|
+
* expected 66 raw bytes (33 spending pubkey + 33 viewing pubkey) with valid
|
|
51
|
+
* compressed-point prefixes. Indicates registry corruption or off-spec usage.
|
|
52
|
+
*/
|
|
53
|
+
export declare class MalformedMetaAddressError extends PaymentError {
|
|
54
|
+
readonly name: string;
|
|
55
|
+
constructor();
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/errors.ts"],"names":[],"mappings":"AAAA,qBAAa,YAAa,SAAQ,KAAK;IACrC,SAAkB,IAAI,EAAE,MAAM,CAAkB;gBACpC,OAAO,EAAE,MAAM;CAG5B;AAED,qBAAa,UAAW,SAAQ,KAAK;IACnC,SAAkB,IAAI,EAAE,MAAM,CAAgB;gBAClC,OAAO,EAAE,MAAM;CAG5B;AAED,qBAAa,qBAAsB,SAAQ,YAAY;IACrD,SAAkB,IAAI,EAAE,MAAM,CAA2B;;CAI1D;AAED,qBAAa,wBAAyB,SAAQ,UAAU;IACtD,SAAkB,IAAI,EAAE,MAAM,CAA8B;;CAI7D;AAED,qBAAa,eAAgB,SAAQ,YAAY;IAC/C,SAAkB,IAAI,EAAE,MAAM,CAAqB;;CAIpD;AAED,qBAAa,8BAA+B,SAAQ,KAAK;IACvD,SAAkB,IAAI,EAAE,MAAM,CAAoC;gBACtD,MAAM,EAAE,MAAM;CAG3B;AAED,qBAAa,wBAAyB,SAAQ,YAAY;IACxD,SAAkB,IAAI,EAAE,MAAM,CAA8B;;CAI7D;AAED,qBAAa,wCAAyC,SAAQ,YAAY;IACxE,SAAkB,IAAI,EAAE,MAAM,CAA8C;;CAI7E;AAED;;;;;;;;;GASG;AACH,qBAAa,0BAA2B,SAAQ,YAAY;IAC1D,SAAkB,IAAI,EAAE,MAAM,CAAgC;IAC9D,QAAQ,CAAC,MAAM,EAAE,KAAK,MAAM,EAAE,CAAC;gBACnB,MAAM,EAAE,KAAK,MAAM,EAAE;CAIlC;AAED;;;;GAIG;AACH,qBAAa,yBAA0B,SAAQ,YAAY;IACzD,SAAkB,IAAI,EAAE,MAAM,CAA+B;;CAI9D"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
export class PaymentError extends Error {
|
|
2
|
+
name = 'PaymentError';
|
|
3
|
+
constructor(message) {
|
|
4
|
+
super(message);
|
|
5
|
+
}
|
|
6
|
+
}
|
|
7
|
+
export class SweepError extends Error {
|
|
8
|
+
name = 'SweepError';
|
|
9
|
+
constructor(message) {
|
|
10
|
+
super(message);
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
export class InvalidRecipientError extends PaymentError {
|
|
14
|
+
name = 'InvalidRecipientError';
|
|
15
|
+
constructor() {
|
|
16
|
+
super('Invalid recipient meta-address');
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
export class InsufficientBalanceError extends SweepError {
|
|
20
|
+
name = 'InsufficientBalanceError';
|
|
21
|
+
constructor() {
|
|
22
|
+
super('Insufficient balance to cover gas');
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
export class ZeroAmountError extends PaymentError {
|
|
26
|
+
name = 'ZeroAmountError';
|
|
27
|
+
constructor() {
|
|
28
|
+
super('Amount must be greater than zero');
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
export class AmountPrivacyNotSupportedError extends Error {
|
|
32
|
+
name = 'AmountPrivacyNotSupportedError';
|
|
33
|
+
constructor(method) {
|
|
34
|
+
super(`Amount privacy not supported: ${method}`);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
export class MissingWalletClientError extends PaymentError {
|
|
38
|
+
name = 'MissingWalletClientError';
|
|
39
|
+
constructor() {
|
|
40
|
+
super('Transport has no walletClient configured');
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
export class StealthPaymentContractNotConfiguredError extends PaymentError {
|
|
44
|
+
name = 'StealthPaymentContractNotConfiguredError';
|
|
45
|
+
constructor() {
|
|
46
|
+
super('ShroudFiStealth contract address not configured');
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Thrown when a sender tries to pay a wallet that has not yet registered a
|
|
51
|
+
* stealth meta-address in the canonical ERC-6538 registry. The recipient must
|
|
52
|
+
* onboard first (publish their (S, B) pubkeys) before stealth payments are
|
|
53
|
+
* possible.
|
|
54
|
+
*
|
|
55
|
+
* Privacy note: the offending wallet address is NOT placed in `.message`. It
|
|
56
|
+
* is exposed via the `wallet` property so callers can show a useful UI hint
|
|
57
|
+
* without leaking the address into logs that only capture `.message`.
|
|
58
|
+
*/
|
|
59
|
+
export class RecipientNotOnboardedError extends PaymentError {
|
|
60
|
+
name = 'RecipientNotOnboardedError';
|
|
61
|
+
wallet;
|
|
62
|
+
constructor(wallet) {
|
|
63
|
+
super('Recipient wallet has not registered a stealth meta-address');
|
|
64
|
+
this.wallet = wallet;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Thrown when the bytes returned by `stealthMetaAddressOf` are not the
|
|
69
|
+
* expected 66 raw bytes (33 spending pubkey + 33 viewing pubkey) with valid
|
|
70
|
+
* compressed-point prefixes. Indicates registry corruption or off-spec usage.
|
|
71
|
+
*/
|
|
72
|
+
export class MalformedMetaAddressError extends PaymentError {
|
|
73
|
+
name = 'MalformedMetaAddressError';
|
|
74
|
+
constructor() {
|
|
75
|
+
super('Registry returned a malformed stealth meta-address');
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/errors.ts"],"names":[],"mappings":"AAAA,MAAM,OAAO,YAAa,SAAQ,KAAK;IACnB,IAAI,GAAW,cAAc,CAAC;IAChD,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;IACjB,CAAC;CACF;AAED,MAAM,OAAO,UAAW,SAAQ,KAAK;IACjB,IAAI,GAAW,YAAY,CAAC;IAC9C,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;IACjB,CAAC;CACF;AAED,MAAM,OAAO,qBAAsB,SAAQ,YAAY;IACnC,IAAI,GAAW,uBAAuB,CAAC;IACzD;QACE,KAAK,CAAC,gCAAgC,CAAC,CAAC;IAC1C,CAAC;CACF;AAED,MAAM,OAAO,wBAAyB,SAAQ,UAAU;IACpC,IAAI,GAAW,0BAA0B,CAAC;IAC5D;QACE,KAAK,CAAC,mCAAmC,CAAC,CAAC;IAC7C,CAAC;CACF;AAED,MAAM,OAAO,eAAgB,SAAQ,YAAY;IAC7B,IAAI,GAAW,iBAAiB,CAAC;IACnD;QACE,KAAK,CAAC,kCAAkC,CAAC,CAAC;IAC5C,CAAC;CACF;AAED,MAAM,OAAO,8BAA+B,SAAQ,KAAK;IACrC,IAAI,GAAW,gCAAgC,CAAC;IAClE,YAAY,MAAc;QACxB,KAAK,CAAC,iCAAiC,MAAM,EAAE,CAAC,CAAC;IACnD,CAAC;CACF;AAED,MAAM,OAAO,wBAAyB,SAAQ,YAAY;IACtC,IAAI,GAAW,0BAA0B,CAAC;IAC5D;QACE,KAAK,CAAC,0CAA0C,CAAC,CAAC;IACpD,CAAC;CACF;AAED,MAAM,OAAO,wCAAyC,SAAQ,YAAY;IACtD,IAAI,GAAW,0CAA0C,CAAC;IAC5E;QACE,KAAK,CAAC,iDAAiD,CAAC,CAAC;IAC3D,CAAC;CACF;AAED;;;;;;;;;GASG;AACH,MAAM,OAAO,0BAA2B,SAAQ,YAAY;IACxC,IAAI,GAAW,4BAA4B,CAAC;IACrD,MAAM,CAAgB;IAC/B,YAAY,MAAqB;QAC/B,KAAK,CAAC,4DAA4D,CAAC,CAAC;QACpE,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;CACF;AAED;;;;GAIG;AACH,MAAM,OAAO,yBAA0B,SAAQ,YAAY;IACvC,IAAI,GAAW,2BAA2B,CAAC;IAC7D;QACE,KAAK,CAAC,oDAAoD,CAAC,CAAC;IAC9D,CAAC;CACF"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export { sendETHPayment, sendERC20Payment, prepareStealthPayment, } from './payments.js';
|
|
2
|
+
export { sweepETH, sweepERC20, } from './sweep.js';
|
|
3
|
+
export { sendToWallet, lookupMetaAddress, } from './send-to-wallet.js';
|
|
4
|
+
export { NullAmountPrivacyProvider, assertSupported, } from './amount-privacy.js';
|
|
5
|
+
export type { SendOptions, PaymentReceipt, SweepReceipt, PreparedStealthPayment, } from './types.js';
|
|
6
|
+
export type { SendToWalletAsset } from './send-to-wallet.js';
|
|
7
|
+
export type { AmountPrivacyProvider, ShieldResult, PrivateTransferResult, UnshieldResult, } from './amount-privacy.js';
|
|
8
|
+
export { DEFAULT_GAS_MULTIPLIER, ETH_SENTINEL, ZERO_ADDRESS, SCHEME_ID, ETH_TRANSFER_GAS_ESTIMATE, ERC20_TRANSFER_GAS_ESTIMATE, } from './constants.js';
|
|
9
|
+
export { PaymentError, SweepError, InvalidRecipientError, InsufficientBalanceError, ZeroAmountError, AmountPrivacyNotSupportedError, MissingWalletClientError, StealthPaymentContractNotConfiguredError, RecipientNotOnboardedError, MalformedMetaAddressError, } from './errors.js';
|
|
10
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAMA,OAAO,EACL,cAAc,EACd,gBAAgB,EAChB,qBAAqB,GACtB,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,QAAQ,EACR,UAAU,GACX,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,YAAY,EACZ,iBAAiB,GAClB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,yBAAyB,EACzB,eAAe,GAChB,MAAM,qBAAqB,CAAC;AAG7B,YAAY,EACV,WAAW,EACX,cAAc,EACd,YAAY,EACZ,sBAAsB,GACvB,MAAM,YAAY,CAAC;AACpB,YAAY,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAC7D,YAAY,EACV,qBAAqB,EACrB,YAAY,EACZ,qBAAqB,EACrB,cAAc,GACf,MAAM,qBAAqB,CAAC;AAG7B,OAAO,EACL,sBAAsB,EACtB,YAAY,EACZ,YAAY,EACZ,SAAS,EACT,yBAAyB,EACzB,2BAA2B,GAC5B,MAAM,gBAAgB,CAAC;AAGxB,OAAO,EACL,YAAY,EACZ,UAAU,EACV,qBAAqB,EACrB,wBAAwB,EACxB,eAAe,EACf,8BAA8B,EAC9B,wBAAwB,EACxB,wCAAwC,EACxC,0BAA0B,EAC1B,yBAAyB,GAC1B,MAAM,aAAa,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
// Public surface — @shroud-fi/payments
|
|
2
|
+
// Phase 1: stealth payment construction + sweep (self-funded).
|
|
3
|
+
// Sweep timing (log-normal delay, destination rotation) lives in @shroud-fi/scanning (P3).
|
|
4
|
+
// Relayer-funded sweep + EIP-2612 permit lives in the relayer service (P5).
|
|
5
|
+
// Functions
|
|
6
|
+
export { sendETHPayment, sendERC20Payment, prepareStealthPayment, } from './payments.js';
|
|
7
|
+
export { sweepETH, sweepERC20, } from './sweep.js';
|
|
8
|
+
export { sendToWallet, lookupMetaAddress, } from './send-to-wallet.js';
|
|
9
|
+
export { NullAmountPrivacyProvider, assertSupported, } from './amount-privacy.js';
|
|
10
|
+
// Constants
|
|
11
|
+
export { DEFAULT_GAS_MULTIPLIER, ETH_SENTINEL, ZERO_ADDRESS, SCHEME_ID, ETH_TRANSFER_GAS_ESTIMATE, ERC20_TRANSFER_GAS_ESTIMATE, } from './constants.js';
|
|
12
|
+
// Errors
|
|
13
|
+
export { PaymentError, SweepError, InvalidRecipientError, InsufficientBalanceError, ZeroAmountError, AmountPrivacyNotSupportedError, MissingWalletClientError, StealthPaymentContractNotConfiguredError, RecipientNotOnboardedError, MalformedMetaAddressError, } from './errors.js';
|
|
14
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,+DAA+D;AAC/D,2FAA2F;AAC3F,4EAA4E;AAE5E,YAAY;AACZ,OAAO,EACL,cAAc,EACd,gBAAgB,EAChB,qBAAqB,GACtB,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,QAAQ,EACR,UAAU,GACX,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,YAAY,EACZ,iBAAiB,GAClB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,yBAAyB,EACzB,eAAe,GAChB,MAAM,qBAAqB,CAAC;AAiB7B,YAAY;AACZ,OAAO,EACL,sBAAsB,EACtB,YAAY,EACZ,YAAY,EACZ,SAAS,EACT,yBAAyB,EACzB,2BAA2B,GAC5B,MAAM,gBAAgB,CAAC;AAExB,SAAS;AACT,OAAO,EACL,YAAY,EACZ,UAAU,EACV,qBAAqB,EACrB,wBAAwB,EACxB,eAAe,EACf,8BAA8B,EAC9B,wBAAwB,EACxB,wCAAwC,EACxC,0BAA0B,EAC1B,yBAAyB,GAC1B,MAAM,aAAa,CAAC"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ShroudFi Payments - Stealth Payment Construction
|
|
3
|
+
*
|
|
4
|
+
* Builds and submits stealth payments through the ShroudFiStealth contract.
|
|
5
|
+
* Uses generateStealthAddress from @shroud-fi/core for derivation.
|
|
6
|
+
*
|
|
7
|
+
* Privacy invariants enforced:
|
|
8
|
+
* - No private key material in any error message
|
|
9
|
+
* - No plaintext amounts in any error message
|
|
10
|
+
* - No console.log/warn/error anywhere
|
|
11
|
+
* - Non-custodial: only constructs transactions, never holds funds
|
|
12
|
+
*/
|
|
13
|
+
import type { Address } from 'viem';
|
|
14
|
+
import type { StealthMetaAddress } from '@shroud-fi/core';
|
|
15
|
+
import type { ShroudFiTransport } from '@shroud-fi/transport';
|
|
16
|
+
import type { PaymentReceipt, PreparedStealthPayment, SendOptions } from './types.js';
|
|
17
|
+
/**
|
|
18
|
+
* Prepare stealth payment material from a recipient meta-address.
|
|
19
|
+
* Pure helper - does not submit any transaction.
|
|
20
|
+
*
|
|
21
|
+
* @throws InvalidRecipientError if the meta-address is malformed or invalid.
|
|
22
|
+
*/
|
|
23
|
+
export declare function prepareStealthPayment(metaAddress: StealthMetaAddress): PreparedStealthPayment;
|
|
24
|
+
/**
|
|
25
|
+
* Send native ETH to a stealth address derived from `metaAddress`.
|
|
26
|
+
*
|
|
27
|
+
* Privacy notes:
|
|
28
|
+
* - The contract emits a StealthPayment event with the stealth address.
|
|
29
|
+
* - The amount is on-chain by necessity (no native ETH amount privacy).
|
|
30
|
+
* - Caller pays gas - relayer abstraction is a separate concern.
|
|
31
|
+
*
|
|
32
|
+
* @throws MissingWalletClientError if transport has no walletClient configured.
|
|
33
|
+
* @throws ZeroAmountError if valueWei is 0n.
|
|
34
|
+
* @throws InvalidRecipientError if the meta-address is invalid.
|
|
35
|
+
*/
|
|
36
|
+
export declare function sendETHPayment(transport: ShroudFiTransport, contractAddress: Address, metaAddress: StealthMetaAddress, valueWei: bigint, options?: SendOptions): Promise<PaymentReceipt>;
|
|
37
|
+
/**
|
|
38
|
+
* Send an ERC-20 token to a stealth address derived from `metaAddress`.
|
|
39
|
+
*
|
|
40
|
+
* **Pre-approval required:** the caller MUST have already approved
|
|
41
|
+
* `contractAddress` to spend at least `amount` of `token` from the sender's
|
|
42
|
+
* account. v1 does not include an approve flow.
|
|
43
|
+
*
|
|
44
|
+
* @throws MissingWalletClientError if transport has no walletClient configured.
|
|
45
|
+
* @throws ZeroAmountError if amount is 0n.
|
|
46
|
+
* @throws InvalidRecipientError if the meta-address is invalid.
|
|
47
|
+
*/
|
|
48
|
+
export declare function sendERC20Payment(transport: ShroudFiTransport, contractAddress: Address, metaAddress: StealthMetaAddress, token: Address, amount: bigint, options?: SendOptions): Promise<PaymentReceipt>;
|
|
49
|
+
//# sourceMappingURL=payments.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"payments.d.ts","sourceRoot":"","sources":["../../src/payments.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,OAAO,EAA+C,MAAM,MAAM,CAAC;AAGjF,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAE1D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAC9D,OAAO,KAAK,EACV,cAAc,EACd,sBAAsB,EACtB,WAAW,EACZ,MAAM,YAAY,CAAC;AA4BpB;;;;;GAKG;AACH,wBAAgB,qBAAqB,CACnC,WAAW,EAAE,kBAAkB,GAC9B,sBAAsB,CAaxB;AAoDD;;;;;;;;;;;GAWG;AACH,wBAAsB,cAAc,CAClC,SAAS,EAAE,iBAAiB,EAC5B,eAAe,EAAE,OAAO,EACxB,WAAW,EAAE,kBAAkB,EAC/B,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE,WAAW,GACpB,OAAO,CAAC,cAAc,CAAC,CA2EzB;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,gBAAgB,CACpC,SAAS,EAAE,iBAAiB,EAC5B,eAAe,EAAE,OAAO,EACxB,WAAW,EAAE,kBAAkB,EAC/B,KAAK,EAAE,OAAO,EACd,MAAM,EAAE,MAAM,EACd,OAAO,CAAC,EAAE,WAAW,GACpB,OAAO,CAAC,cAAc,CAAC,CAiFzB"}
|