@pear-protocol/exchanges-sdk 0.8.0 → 0.9.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/dist/client/lighter/rest.js +42 -23
- package/dist/client/lighter/ws.js +8 -0
- package/dist/helper/lighter/asset-decimals.helper.js +25 -0
- package/dist/helper/lighter/cctp-deposit.helper.js +30 -105
- package/dist/helper/lighter/deposit-settlement.helper.js +100 -0
- package/dist/helper/lighter/deposit.helper.js +28 -0
- package/dist/helper/lighter/ethereum/usdc.helper.js +17 -7
- package/dist/helper/lighter/ethereum-deposit.helper.js +44 -0
- package/dist/helper/lighter/funxyz-deposit.helper.js +257 -0
- package/dist/helper/lighter/helper.js +38 -55
- package/dist/helper/lighter/index.js +3 -1
- package/dist/helper/lighter/types.js +34 -1
- package/dist/index.d.ts +329 -57
- package/dist/sdk.js +2 -0
- package/dist/status/lighter/status.js +6 -1
- package/dist/syncer/lighter/syncer.js +3 -1
- package/dist/tracker/index.js +1 -0
- package/dist/tracker/lighter/mapper.js +17 -1
- package/dist/tracker/lighter/tracker.js +170 -18
- package/package.json +9 -6
|
@@ -66,11 +66,7 @@ async function fetchDepositHistory(params, demo = false) {
|
|
|
66
66
|
l1_address: params.l1Address,
|
|
67
67
|
filter: "all"
|
|
68
68
|
});
|
|
69
|
-
const response = await
|
|
70
|
-
headers: {
|
|
71
|
-
authorization: params.authToken
|
|
72
|
-
}
|
|
73
|
-
});
|
|
69
|
+
const response = await authenticatedLighterFetch(`${getLighterBaseUrl(demo)}/api/v1/deposit/history?${query.toString()}`, params.authToken);
|
|
74
70
|
const data = await readLighterResponse(response, "/deposit/history");
|
|
75
71
|
const deposits = [];
|
|
76
72
|
for (const deposit of data.deposits ?? []) {
|
|
@@ -139,18 +135,31 @@ async function fetchAccountsByL1Address(l1Address, demo = false) {
|
|
|
139
135
|
};
|
|
140
136
|
}
|
|
141
137
|
__name(fetchAccountsByL1Address, "fetchAccountsByL1Address");
|
|
142
|
-
async function fetchAccount(accountIndex, demo = false) {
|
|
143
|
-
const response = await
|
|
138
|
+
async function fetchAccount(accountIndex, authToken, demo = false) {
|
|
139
|
+
const response = await authenticatedLighterFetch(`${getLighterBaseUrl(demo)}/api/v1/account?by=index&value=${accountIndex}`, authToken);
|
|
144
140
|
return readLighterResponse(response, "/account");
|
|
145
141
|
}
|
|
146
142
|
__name(fetchAccount, "fetchAccount");
|
|
147
|
-
async function
|
|
148
|
-
const response = await proxyFetch(`${getLighterBaseUrl(demo)}/api/v1/
|
|
143
|
+
async function fetchPublicAccount(accountIndex, demo = false) {
|
|
144
|
+
const response = await proxyFetch(`${getLighterBaseUrl(demo)}/api/v1/account?by=index&value=${accountIndex}`);
|
|
145
|
+
return readLighterResponse(response, "/account");
|
|
146
|
+
}
|
|
147
|
+
__name(fetchPublicAccount, "fetchPublicAccount");
|
|
148
|
+
async function fetchAccountLimits(accountIndex, authToken, demo = false) {
|
|
149
|
+
const response = await proxyFetch(`${getLighterBaseUrl(demo)}/api/v1/accountLimits?account_index=${accountIndex}`, {
|
|
149
150
|
headers: {
|
|
150
|
-
accept: "application/json",
|
|
151
151
|
authorization: authToken
|
|
152
152
|
}
|
|
153
153
|
});
|
|
154
|
+
return readLighterResponse(response, "/accountLimits");
|
|
155
|
+
}
|
|
156
|
+
__name(fetchAccountLimits, "fetchAccountLimits");
|
|
157
|
+
async function fetchAccountMetadata(accountIndex, authToken, demo = false) {
|
|
158
|
+
const response = await authenticatedLighterFetch(`${getLighterBaseUrl(demo)}/api/v1/accountMetadata?by=index&value=${accountIndex}`, authToken, {
|
|
159
|
+
headers: {
|
|
160
|
+
accept: "application/json"
|
|
161
|
+
}
|
|
162
|
+
});
|
|
154
163
|
const data = await readLighterResponse(response, "/accountMetadata");
|
|
155
164
|
const matchesAccount = data.account_metadatas?.some((metadata) => metadata.account_index === accountIndex);
|
|
156
165
|
if (!matchesAccount) {
|
|
@@ -158,8 +167,8 @@ async function fetchAccountMetadata(accountIndex, authToken, demo = false) {
|
|
|
158
167
|
}
|
|
159
168
|
}
|
|
160
169
|
__name(fetchAccountMetadata, "fetchAccountMetadata");
|
|
161
|
-
async function fetchOrderBookDetails(demo = false) {
|
|
162
|
-
const response = await
|
|
170
|
+
async function fetchOrderBookDetails(authToken, demo = false) {
|
|
171
|
+
const response = await authenticatedLighterFetch(`${getLighterBaseUrl(demo)}/api/v1/orderBookDetails`, authToken);
|
|
163
172
|
const data = await readLighterResponse(response, "/orderBookDetails");
|
|
164
173
|
return {
|
|
165
174
|
perp: data.order_book_details ?? [],
|
|
@@ -167,6 +176,15 @@ async function fetchOrderBookDetails(demo = false) {
|
|
|
167
176
|
};
|
|
168
177
|
}
|
|
169
178
|
__name(fetchOrderBookDetails, "fetchOrderBookDetails");
|
|
179
|
+
async function fetchPublicOrderBookDetails(demo = false) {
|
|
180
|
+
const response = await proxyFetch(`${getLighterBaseUrl(demo)}/api/v1/orderBookDetails`);
|
|
181
|
+
const data = await readLighterResponse(response, "/orderBookDetails");
|
|
182
|
+
return {
|
|
183
|
+
perp: data.order_book_details ?? [],
|
|
184
|
+
spot: data.spot_order_book_details ?? []
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
__name(fetchPublicOrderBookDetails, "fetchPublicOrderBookDetails");
|
|
170
188
|
async function fetchAssetDetails(demo) {
|
|
171
189
|
const response = await proxyFetch(`${getLighterBaseUrl(demo)}/api/v1/assetDetails`);
|
|
172
190
|
const data = await readLighterResponse(response, "/assetDetails");
|
|
@@ -192,11 +210,7 @@ async function fetchTradesSince(accountIndex, authToken, since, demo = false) {
|
|
|
192
210
|
cursor
|
|
193
211
|
} : {}
|
|
194
212
|
});
|
|
195
|
-
const response = await
|
|
196
|
-
headers: {
|
|
197
|
-
authorization: authToken
|
|
198
|
-
}
|
|
199
|
-
});
|
|
213
|
+
const response = await authenticatedLighterFetch(`${getLighterBaseUrl(demo)}/api/v1/trades?${params.toString()}`, authToken);
|
|
200
214
|
const data = await readLighterResponse(response, "/trades");
|
|
201
215
|
const page = data.trades ?? [];
|
|
202
216
|
results.push(...page.filter((trade) => trade.timestamp >= since.getTime()));
|
|
@@ -229,11 +243,7 @@ async function fetchPositionFundingSince(accountIndex, authToken, since, demo =
|
|
|
229
243
|
cursor
|
|
230
244
|
} : {}
|
|
231
245
|
});
|
|
232
|
-
const response = await
|
|
233
|
-
headers: {
|
|
234
|
-
authorization: authToken
|
|
235
|
-
}
|
|
236
|
-
});
|
|
246
|
+
const response = await authenticatedLighterFetch(`${getLighterBaseUrl(demo)}/api/v1/positionFunding?${params.toString()}`, authToken);
|
|
237
247
|
const data = await readLighterResponse(response, "/positionFunding");
|
|
238
248
|
for (const funding of data.position_fundings ?? []) {
|
|
239
249
|
if (funding.timestamp >= sinceSeconds) {
|
|
@@ -249,6 +259,15 @@ async function fetchPositionFundingSince(accountIndex, authToken, since, demo =
|
|
|
249
259
|
return Array.from(results.values());
|
|
250
260
|
}
|
|
251
261
|
__name(fetchPositionFundingSince, "fetchPositionFundingSince");
|
|
262
|
+
async function authenticatedLighterFetch(url, authToken, init) {
|
|
263
|
+
const headers = new Headers(init?.headers);
|
|
264
|
+
headers.set("authorization", authToken);
|
|
265
|
+
return proxyFetch(url, {
|
|
266
|
+
...init,
|
|
267
|
+
headers
|
|
268
|
+
});
|
|
269
|
+
}
|
|
270
|
+
__name(authenticatedLighterFetch, "authenticatedLighterFetch");
|
|
252
271
|
async function fetchDepositIntentWithRetry(url, init) {
|
|
253
272
|
for (let attempt = 1; attempt <= INTENT_REQUEST_ATTEMPTS; attempt += 1) {
|
|
254
273
|
const response = await proxyFetch(url, init);
|
|
@@ -283,4 +302,4 @@ async function readLighterResponse(response, endpoint, acceptedCodes = [
|
|
|
283
302
|
}
|
|
284
303
|
__name(readLighterResponse, "readLighterResponse");
|
|
285
304
|
|
|
286
|
-
export { createCctpDepositIntentAddress, fetchAccount, fetchAccountMetadata, fetchAccountsByL1Address, fetchApiKeys, fetchAssetDetails, fetchDepositHistory, fetchDepositNetworks, fetchOrderBookDetails, fetchPositionFundingSince, fetchTradesSince };
|
|
305
|
+
export { createCctpDepositIntentAddress, fetchAccount, fetchAccountLimits, fetchAccountMetadata, fetchAccountsByL1Address, fetchApiKeys, fetchAssetDetails, fetchDepositHistory, fetchDepositNetworks, fetchOrderBookDetails, fetchPositionFundingSince, fetchPublicAccount, fetchPublicOrderBookDetails, fetchTradesSince };
|
|
@@ -23,6 +23,14 @@ class LighterWs extends BaseWs {
|
|
|
23
23
|
type: "ping"
|
|
24
24
|
};
|
|
25
25
|
}
|
|
26
|
+
/** Subscribes to one account channel with the authentication Lighter requires. */
|
|
27
|
+
subscribe(channel, authToken) {
|
|
28
|
+
this.send({
|
|
29
|
+
type: "subscribe",
|
|
30
|
+
channel,
|
|
31
|
+
auth: authToken
|
|
32
|
+
});
|
|
33
|
+
}
|
|
26
34
|
}
|
|
27
35
|
|
|
28
36
|
export { LighterWs };
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { fetchAssetDetails } from '../../client/lighter/rest';
|
|
2
|
+
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
5
|
+
async function resolveAssetDecimals(assetId, field, suppliedDecimals, demo) {
|
|
6
|
+
if (suppliedDecimals !== void 0) {
|
|
7
|
+
return validateDecimals(suppliedDecimals, field);
|
|
8
|
+
}
|
|
9
|
+
const assets = await fetchAssetDetails(demo);
|
|
10
|
+
const asset = assets.find((candidate) => candidate.asset_id === assetId);
|
|
11
|
+
if (!asset) {
|
|
12
|
+
throw new Error(`Lighter asset ${assetId} was not returned by assetDetails`);
|
|
13
|
+
}
|
|
14
|
+
return validateDecimals(asset[field], `assetDetails.${field}`);
|
|
15
|
+
}
|
|
16
|
+
__name(resolveAssetDecimals, "resolveAssetDecimals");
|
|
17
|
+
function validateDecimals(decimals, source) {
|
|
18
|
+
if (!Number.isSafeInteger(decimals) || decimals < 0 || decimals > 255) {
|
|
19
|
+
throw new Error(`Invalid ${source} decimals: ${decimals}`);
|
|
20
|
+
}
|
|
21
|
+
return decimals;
|
|
22
|
+
}
|
|
23
|
+
__name(validateDecimals, "validateDecimals");
|
|
24
|
+
|
|
25
|
+
export { resolveAssetDecimals };
|
|
@@ -2,24 +2,19 @@ import { isAddress } from 'viem';
|
|
|
2
2
|
import { fetchDepositNetworks, createCctpDepositIntentAddress, fetchAccountsByL1Address, fetchDepositHistory } from '../../client/lighter/rest';
|
|
3
3
|
import { parseUsdcAmount } from '../subaccount.helper';
|
|
4
4
|
import { retrieveLighterAuthToken } from './auth-token.helper';
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
5
|
+
import { assertOwnerWallet, readUsdcAmountSyntaxError, readDepositMinimumError, formatUsdcUnits, emitProgress, watchAccountRegistration, waitForDepositPoll, SETTLEMENT_WATCH_LIMIT_MS } from './deposit-settlement.helper';
|
|
6
|
+
import { getLighterNativeUsdcAddress, writeUsdcTransfer } from './ethereum/usdc.helper';
|
|
7
7
|
import { MIN_LIGHTER_CCTP_DEPOSIT_USDC } from './types';
|
|
8
8
|
|
|
9
9
|
var __defProp = Object.defineProperty;
|
|
10
10
|
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
11
|
-
const DEPOSIT_POLL_INTERVAL_MS = 5e3;
|
|
12
11
|
const EXTERNAL_INTENT_LIFETIME_MS = 9 * 60 * 1e3;
|
|
13
|
-
const REGISTRATION_WATCH_LIMIT_MS = 60 * 60 * 1e3;
|
|
14
|
-
const USDC_AMOUNT_PATTERN = /^\d+(?:\.\d{1,6})?$/;
|
|
15
|
-
const MINIMUM_LABEL = `Minimum deposit: $${MIN_LIGHTER_CCTP_DEPOSIT_USDC} USDC`;
|
|
16
|
-
const MINIMUM_UNITS = parseUsdcAmount(MIN_LIGHTER_CCTP_DEPOSIT_USDC);
|
|
17
12
|
async function listCctpDepositNetworks(demo) {
|
|
18
13
|
assertCctpEnvironment(demo);
|
|
19
14
|
return fetchDepositNetworks(demo);
|
|
20
15
|
}
|
|
21
16
|
__name(listCctpDepositNetworks, "listCctpDepositNetworks");
|
|
22
|
-
async function
|
|
17
|
+
async function createCctpDepositAddress(params, demo) {
|
|
23
18
|
await validateIntentRoute(params, demo);
|
|
24
19
|
const intentAddress = await createCctpDepositIntentAddress({
|
|
25
20
|
chainId: params.chainId,
|
|
@@ -28,23 +23,28 @@ async function createExternalCctpDepositIntent(params, demo) {
|
|
|
28
23
|
external: true
|
|
29
24
|
}, demo);
|
|
30
25
|
return {
|
|
26
|
+
route: "cctp",
|
|
31
27
|
intentAddress,
|
|
32
28
|
expiresAt: Date.now() + EXTERNAL_INTENT_LIFETIME_MS
|
|
33
29
|
};
|
|
34
30
|
}
|
|
35
|
-
__name(
|
|
31
|
+
__name(createCctpDepositAddress, "createCctpDepositAddress");
|
|
36
32
|
async function depositUsdcViaCctp(sdk, params, demo) {
|
|
37
33
|
assertCctpEnvironment(demo);
|
|
38
34
|
assertOwnerWallet(params.ownerAddress, params.connectedAddress);
|
|
39
|
-
const usdcAddress =
|
|
35
|
+
const usdcAddress = getLighterNativeUsdcAddress(params.chainId);
|
|
40
36
|
if (!usdcAddress) {
|
|
41
37
|
throw new Error(`Lighter CCTP chain ID ${params.chainId} has no known native USDC token.`);
|
|
42
38
|
}
|
|
43
|
-
const
|
|
44
|
-
if (
|
|
45
|
-
throw new Error(
|
|
39
|
+
const syntaxError = readUsdcAmountSyntaxError(params.amount);
|
|
40
|
+
if (syntaxError) {
|
|
41
|
+
throw new Error(syntaxError);
|
|
46
42
|
}
|
|
47
43
|
const units = parseUsdcAmount(params.amount);
|
|
44
|
+
const minimumError = readDepositMinimumError(units, MIN_LIGHTER_CCTP_DEPOSIT_USDC);
|
|
45
|
+
if (minimumError) {
|
|
46
|
+
throw new Error(minimumError);
|
|
47
|
+
}
|
|
48
48
|
const balance = await params.wallet.readUsdcBalance(params.chainId, params.ownerAddress);
|
|
49
49
|
if (units > balance) {
|
|
50
50
|
throw new Error(`Your wallet holds ${formatUsdcUnits(balance)} USDC.`);
|
|
@@ -82,22 +82,12 @@ async function depositUsdcViaCctp(sdk, params, demo) {
|
|
|
82
82
|
});
|
|
83
83
|
await followDepositSettlement(params, txHash, sdk, demo);
|
|
84
84
|
return {
|
|
85
|
+
route: "cctp",
|
|
85
86
|
txHash,
|
|
86
87
|
intentAddress
|
|
87
88
|
};
|
|
88
89
|
}
|
|
89
90
|
__name(depositUsdcViaCctp, "depositUsdcViaCctp");
|
|
90
|
-
function readCctpDepositAmountError(amount) {
|
|
91
|
-
if (!USDC_AMOUNT_PATTERN.test(amount)) {
|
|
92
|
-
return "Enter a USDC amount with up to six decimal places.";
|
|
93
|
-
}
|
|
94
|
-
const units = parseUsdcAmount(amount);
|
|
95
|
-
if (units < MINIMUM_UNITS) {
|
|
96
|
-
return `${MINIMUM_LABEL}.`;
|
|
97
|
-
}
|
|
98
|
-
return void 0;
|
|
99
|
-
}
|
|
100
|
-
__name(readCctpDepositAmountError, "readCctpDepositAmountError");
|
|
101
91
|
async function validateIntentRoute(params, demo) {
|
|
102
92
|
assertCctpEnvironment(demo);
|
|
103
93
|
if (!isAddress(params.ownerAddress)) {
|
|
@@ -110,12 +100,6 @@ async function validateIntentRoute(params, demo) {
|
|
|
110
100
|
}
|
|
111
101
|
}
|
|
112
102
|
__name(validateIntentRoute, "validateIntentRoute");
|
|
113
|
-
function assertOwnerWallet(ownerAddress, connectedAddress) {
|
|
114
|
-
if (connectedAddress?.toLowerCase() !== ownerAddress.toLowerCase()) {
|
|
115
|
-
throw new Error(`Connect the Lighter owner wallet ${ownerAddress} and try again.`);
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
__name(assertOwnerWallet, "assertOwnerWallet");
|
|
119
103
|
function assertCctpEnvironment(demo) {
|
|
120
104
|
if (demo) {
|
|
121
105
|
throw new Error("Lighter demo CCTP deposits are disabled because safe testnet funding is not documented");
|
|
@@ -141,11 +125,11 @@ async function followDepositSettlement(params, txHash, sdk, demo) {
|
|
|
141
125
|
});
|
|
142
126
|
return;
|
|
143
127
|
}
|
|
144
|
-
await watchCctpDeposit(params.ownerAddress, txHash, watch, params.onProgress, sdk, demo);
|
|
128
|
+
await watchCctpDeposit(params.ownerAddress, txHash, watch, params.onProgress, sdk, demo, params.settlementTimeoutMs);
|
|
145
129
|
return;
|
|
146
130
|
}
|
|
147
131
|
case "account-registration": {
|
|
148
|
-
await watchAccountRegistration(params.ownerAddress, txHash, params.onProgress, params.signal, demo);
|
|
132
|
+
await watchAccountRegistration(params.ownerAddress, txHash, params.onProgress, params.signal, demo, params.settlementTimeoutMs);
|
|
149
133
|
return;
|
|
150
134
|
}
|
|
151
135
|
}
|
|
@@ -166,12 +150,20 @@ async function resolveDepositWatch(ownerAddress, settlement, signal, demo) {
|
|
|
166
150
|
};
|
|
167
151
|
}
|
|
168
152
|
__name(resolveDepositWatch, "resolveDepositWatch");
|
|
169
|
-
async function watchCctpDeposit(ownerAddress, txHash, watch, onProgress, sdk, demo) {
|
|
153
|
+
async function watchCctpDeposit(ownerAddress, txHash, watch, onProgress, sdk, demo, timeoutMs) {
|
|
154
|
+
const deadline = Date.now() + (timeoutMs ?? SETTLEMENT_WATCH_LIMIT_MS);
|
|
170
155
|
while (!watch.signal?.aborted) {
|
|
171
156
|
await waitForDepositPoll(watch.signal);
|
|
172
157
|
if (watch.signal?.aborted) {
|
|
173
158
|
return;
|
|
174
159
|
}
|
|
160
|
+
if (Date.now() >= deadline) {
|
|
161
|
+
emitProgress(onProgress, watch.signal, {
|
|
162
|
+
state: "unsettled",
|
|
163
|
+
txHash
|
|
164
|
+
});
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
175
167
|
let deposits;
|
|
176
168
|
try {
|
|
177
169
|
const authToken = await retrieveLighterAuthToken(sdk, watch, demo);
|
|
@@ -202,7 +194,10 @@ async function watchCctpDeposit(ownerAddress, txHash, watch, onProgress, sdk, de
|
|
|
202
194
|
emitProgress(onProgress, watch.signal, {
|
|
203
195
|
state: "credited",
|
|
204
196
|
txHash,
|
|
205
|
-
|
|
197
|
+
credit: {
|
|
198
|
+
source: "lighter-history",
|
|
199
|
+
deposit
|
|
200
|
+
}
|
|
206
201
|
});
|
|
207
202
|
return;
|
|
208
203
|
case "failed":
|
|
@@ -223,75 +218,5 @@ async function watchCctpDeposit(ownerAddress, txHash, watch, onProgress, sdk, de
|
|
|
223
218
|
}
|
|
224
219
|
}
|
|
225
220
|
__name(watchCctpDeposit, "watchCctpDeposit");
|
|
226
|
-
async function watchAccountRegistration(ownerAddress, txHash, onProgress, signal, demo) {
|
|
227
|
-
const deadline = Date.now() + REGISTRATION_WATCH_LIMIT_MS;
|
|
228
|
-
while (!signal?.aborted) {
|
|
229
|
-
await waitForDepositPoll(signal);
|
|
230
|
-
if (signal?.aborted) {
|
|
231
|
-
return;
|
|
232
|
-
}
|
|
233
|
-
if (Date.now() >= deadline) {
|
|
234
|
-
emitProgress(onProgress, signal, {
|
|
235
|
-
state: "unsettled",
|
|
236
|
-
txHash
|
|
237
|
-
});
|
|
238
|
-
return;
|
|
239
|
-
}
|
|
240
|
-
let status;
|
|
241
|
-
try {
|
|
242
|
-
status = await readOnboardingStatus(ownerAddress, demo);
|
|
243
|
-
} catch {
|
|
244
|
-
continue;
|
|
245
|
-
}
|
|
246
|
-
switch (status.step) {
|
|
247
|
-
case "deposit-required":
|
|
248
|
-
emitProgress(onProgress, signal, {
|
|
249
|
-
state: "bridging",
|
|
250
|
-
txHash
|
|
251
|
-
});
|
|
252
|
-
break;
|
|
253
|
-
case "account-ready":
|
|
254
|
-
emitProgress(onProgress, signal, {
|
|
255
|
-
state: "registered",
|
|
256
|
-
txHash,
|
|
257
|
-
mainAccountIndex: status.mainAccountIndex,
|
|
258
|
-
subAccountIndexes: status.subAccountIndexes
|
|
259
|
-
});
|
|
260
|
-
return;
|
|
261
|
-
}
|
|
262
|
-
}
|
|
263
|
-
}
|
|
264
|
-
__name(watchAccountRegistration, "watchAccountRegistration");
|
|
265
|
-
function emitProgress(onProgress, signal, progress) {
|
|
266
|
-
if (signal?.aborted) {
|
|
267
|
-
return;
|
|
268
|
-
}
|
|
269
|
-
onProgress(progress);
|
|
270
|
-
}
|
|
271
|
-
__name(emitProgress, "emitProgress");
|
|
272
|
-
async function waitForDepositPoll(signal) {
|
|
273
|
-
await new Promise((resolve) => {
|
|
274
|
-
let timeout;
|
|
275
|
-
const stopWaiting = /* @__PURE__ */ __name(() => {
|
|
276
|
-
clearTimeout(timeout);
|
|
277
|
-
resolve();
|
|
278
|
-
}, "stopWaiting");
|
|
279
|
-
timeout = setTimeout(() => {
|
|
280
|
-
signal?.removeEventListener("abort", stopWaiting);
|
|
281
|
-
resolve();
|
|
282
|
-
}, DEPOSIT_POLL_INTERVAL_MS);
|
|
283
|
-
signal?.addEventListener("abort", stopWaiting, {
|
|
284
|
-
once: true
|
|
285
|
-
});
|
|
286
|
-
});
|
|
287
|
-
}
|
|
288
|
-
__name(waitForDepositPoll, "waitForDepositPoll");
|
|
289
|
-
function formatUsdcUnits(units) {
|
|
290
|
-
const value = units.toString().padStart(7, "0");
|
|
291
|
-
const whole = value.slice(0, -6);
|
|
292
|
-
const fraction = value.slice(-6).replace(/0+$/, "");
|
|
293
|
-
return fraction ? `${whole}.${fraction}` : whole;
|
|
294
|
-
}
|
|
295
|
-
__name(formatUsdcUnits, "formatUsdcUnits");
|
|
296
221
|
|
|
297
|
-
export {
|
|
222
|
+
export { createCctpDepositAddress, depositUsdcViaCctp, listCctpDepositNetworks };
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { parseUsdcAmount } from '../subaccount.helper';
|
|
2
|
+
import { readOnboardingStatus } from './onboarding.helper';
|
|
3
|
+
|
|
4
|
+
var __defProp = Object.defineProperty;
|
|
5
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
6
|
+
const DEPOSIT_POLL_INTERVAL_MS = 5e3;
|
|
7
|
+
const SETTLEMENT_WATCH_LIMIT_MS = 60 * 60 * 1e3;
|
|
8
|
+
const USDC_AMOUNT_PATTERN = /^\d+(?:\.\d{1,6})?$/;
|
|
9
|
+
function readUsdcAmountSyntaxError(amount) {
|
|
10
|
+
if (!USDC_AMOUNT_PATTERN.test(amount)) {
|
|
11
|
+
return "Enter a USDC amount with up to six decimal places.";
|
|
12
|
+
}
|
|
13
|
+
return void 0;
|
|
14
|
+
}
|
|
15
|
+
__name(readUsdcAmountSyntaxError, "readUsdcAmountSyntaxError");
|
|
16
|
+
function readDepositMinimumError(units, minimumUsd) {
|
|
17
|
+
if (units < parseUsdcAmount(minimumUsd)) {
|
|
18
|
+
return `Minimum deposit: $${minimumUsd} USDC.`;
|
|
19
|
+
}
|
|
20
|
+
return void 0;
|
|
21
|
+
}
|
|
22
|
+
__name(readDepositMinimumError, "readDepositMinimumError");
|
|
23
|
+
function assertOwnerWallet(ownerAddress, connectedAddress) {
|
|
24
|
+
if (connectedAddress?.toLowerCase() !== ownerAddress.toLowerCase()) {
|
|
25
|
+
throw new Error(`Connect the Lighter owner wallet ${ownerAddress} and try again.`);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
__name(assertOwnerWallet, "assertOwnerWallet");
|
|
29
|
+
async function watchAccountRegistration(ownerAddress, txHash, onProgress, signal, demo, timeoutMs) {
|
|
30
|
+
const deadline = Date.now() + (timeoutMs ?? SETTLEMENT_WATCH_LIMIT_MS);
|
|
31
|
+
while (!signal?.aborted) {
|
|
32
|
+
await waitForDepositPoll(signal);
|
|
33
|
+
if (signal?.aborted) {
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
if (Date.now() >= deadline) {
|
|
37
|
+
emitProgress(onProgress, signal, {
|
|
38
|
+
state: "unsettled",
|
|
39
|
+
txHash
|
|
40
|
+
});
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
let status;
|
|
44
|
+
try {
|
|
45
|
+
status = await readOnboardingStatus(ownerAddress, demo);
|
|
46
|
+
} catch {
|
|
47
|
+
continue;
|
|
48
|
+
}
|
|
49
|
+
switch (status.step) {
|
|
50
|
+
case "deposit-required":
|
|
51
|
+
emitProgress(onProgress, signal, {
|
|
52
|
+
state: "bridging",
|
|
53
|
+
txHash
|
|
54
|
+
});
|
|
55
|
+
break;
|
|
56
|
+
case "account-ready":
|
|
57
|
+
emitProgress(onProgress, signal, {
|
|
58
|
+
state: "registered",
|
|
59
|
+
txHash,
|
|
60
|
+
mainAccountIndex: status.mainAccountIndex,
|
|
61
|
+
subAccountIndexes: status.subAccountIndexes
|
|
62
|
+
});
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
__name(watchAccountRegistration, "watchAccountRegistration");
|
|
68
|
+
function emitProgress(onProgress, signal, progress) {
|
|
69
|
+
if (signal?.aborted) {
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
onProgress(progress);
|
|
73
|
+
}
|
|
74
|
+
__name(emitProgress, "emitProgress");
|
|
75
|
+
async function waitForDepositPoll(signal) {
|
|
76
|
+
await new Promise((resolve) => {
|
|
77
|
+
let timeout;
|
|
78
|
+
const stopWaiting = /* @__PURE__ */ __name(() => {
|
|
79
|
+
clearTimeout(timeout);
|
|
80
|
+
resolve();
|
|
81
|
+
}, "stopWaiting");
|
|
82
|
+
timeout = setTimeout(() => {
|
|
83
|
+
signal?.removeEventListener("abort", stopWaiting);
|
|
84
|
+
resolve();
|
|
85
|
+
}, DEPOSIT_POLL_INTERVAL_MS);
|
|
86
|
+
signal?.addEventListener("abort", stopWaiting, {
|
|
87
|
+
once: true
|
|
88
|
+
});
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
__name(waitForDepositPoll, "waitForDepositPoll");
|
|
92
|
+
function formatUsdcUnits(units) {
|
|
93
|
+
const value = units.toString().padStart(7, "0");
|
|
94
|
+
const whole = value.slice(0, -6);
|
|
95
|
+
const fraction = value.slice(-6).replace(/0+$/, "");
|
|
96
|
+
return fraction ? `${whole}.${fraction}` : whole;
|
|
97
|
+
}
|
|
98
|
+
__name(formatUsdcUnits, "formatUsdcUnits");
|
|
99
|
+
|
|
100
|
+
export { DEPOSIT_POLL_INTERVAL_MS, SETTLEMENT_WATCH_LIMIT_MS, assertOwnerWallet, emitProgress, formatUsdcUnits, readDepositMinimumError, readUsdcAmountSyntaxError, waitForDepositPoll, watchAccountRegistration };
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { depositUsdcViaCctp, createCctpDepositAddress } from './cctp-deposit.helper';
|
|
2
|
+
import { depositViaEthereumGateway } from './ethereum-deposit.helper';
|
|
3
|
+
import { depositUsdcViaFunxyz, createFunxyzDepositAddress } from './funxyz-deposit.helper';
|
|
4
|
+
|
|
5
|
+
var __defProp = Object.defineProperty;
|
|
6
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
7
|
+
async function depositThroughRoute(sdk, params, demo) {
|
|
8
|
+
switch (params.route) {
|
|
9
|
+
case "ethereum":
|
|
10
|
+
return depositViaEthereumGateway(params, demo);
|
|
11
|
+
case "cctp":
|
|
12
|
+
return depositUsdcViaCctp(sdk, params, demo);
|
|
13
|
+
case "funxyz":
|
|
14
|
+
return depositUsdcViaFunxyz(sdk, params, demo);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
__name(depositThroughRoute, "depositThroughRoute");
|
|
18
|
+
async function createDepositAddressForRoute(sdk, params, demo) {
|
|
19
|
+
switch (params.route) {
|
|
20
|
+
case "cctp":
|
|
21
|
+
return createCctpDepositAddress(params, demo);
|
|
22
|
+
case "funxyz":
|
|
23
|
+
return createFunxyzDepositAddress(sdk, params, demo);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
__name(createDepositAddressForRoute, "createDepositAddressForRoute");
|
|
27
|
+
|
|
28
|
+
export { createDepositAddressForRoute, depositThroughRoute };
|
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
var __defProp = Object.defineProperty;
|
|
2
2
|
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
3
|
-
const
|
|
3
|
+
const LIGHTER_NATIVE_USDC_ADDRESSES = {
|
|
4
|
+
// Ethereum
|
|
5
|
+
1: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
|
|
6
|
+
// OP Mainnet
|
|
7
|
+
10: "0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85",
|
|
8
|
+
// Polygon PoS
|
|
9
|
+
137: "0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359",
|
|
10
|
+
// Monad
|
|
11
|
+
143: "0x754704Bc059F8C67012fEd69BC8A327a5aafb603",
|
|
4
12
|
// Arbitrum One
|
|
5
13
|
42161: "0xaf88d065e77c8cC2239327C5EDb3A432268e5831",
|
|
6
14
|
// Base
|
|
@@ -8,9 +16,11 @@ const LIGHTER_CCTP_USDC_ADDRESSES = {
|
|
|
8
16
|
// Avalanche C-Chain
|
|
9
17
|
43114: "0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E",
|
|
10
18
|
// HyperEVM
|
|
11
|
-
999: "0xb88339CB7199b77E23DB6E890353E22632Ba630f"
|
|
19
|
+
999: "0xb88339CB7199b77E23DB6E890353E22632Ba630f",
|
|
20
|
+
// Ink
|
|
21
|
+
57073: "0x2D270e6886d130D724215A266106e6832161EAEd"
|
|
12
22
|
};
|
|
13
|
-
const
|
|
23
|
+
const LIGHTER_USDC_DECIMALS = 6;
|
|
14
24
|
const usdcAbi = [
|
|
15
25
|
{
|
|
16
26
|
inputs: [
|
|
@@ -56,10 +66,10 @@ const usdcAbi = [
|
|
|
56
66
|
type: "function"
|
|
57
67
|
}
|
|
58
68
|
];
|
|
59
|
-
function
|
|
60
|
-
return
|
|
69
|
+
function getLighterNativeUsdcAddress(chainId) {
|
|
70
|
+
return LIGHTER_NATIVE_USDC_ADDRESSES[chainId];
|
|
61
71
|
}
|
|
62
|
-
__name(
|
|
72
|
+
__name(getLighterNativeUsdcAddress, "getLighterNativeUsdcAddress");
|
|
63
73
|
async function writeUsdcTransfer(walletClient, params) {
|
|
64
74
|
return walletClient.writeContract({
|
|
65
75
|
chain: walletClient.chain,
|
|
@@ -74,4 +84,4 @@ async function writeUsdcTransfer(walletClient, params) {
|
|
|
74
84
|
}
|
|
75
85
|
__name(writeUsdcTransfer, "writeUsdcTransfer");
|
|
76
86
|
|
|
77
|
-
export {
|
|
87
|
+
export { LIGHTER_NATIVE_USDC_ADDRESSES, LIGHTER_USDC_DECIMALS, getLighterNativeUsdcAddress, usdcAbi, writeUsdcTransfer };
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { parseUnits, parseEther } from 'viem';
|
|
2
|
+
import { resolveAssetDecimals } from './asset-decimals.helper';
|
|
3
|
+
import { writeDeposit } from './ethereum';
|
|
4
|
+
import { AssetId } from './types';
|
|
5
|
+
|
|
6
|
+
var __defProp = Object.defineProperty;
|
|
7
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
8
|
+
async function depositViaEthereumGateway(params, demo) {
|
|
9
|
+
if (demo) {
|
|
10
|
+
throw new Error("Lighter demo deposits are unavailable because the testnet gateway is not verified");
|
|
11
|
+
}
|
|
12
|
+
const l1Decimals = await resolveAssetDecimals(params.assetId, "l1_decimals", params.l1Decimals, demo);
|
|
13
|
+
const amount = parseUnits(params.amount, l1Decimals);
|
|
14
|
+
const value = readNativeValue(params, amount);
|
|
15
|
+
const txHash = await writeDeposit(params.walletClient, {
|
|
16
|
+
to: params.to,
|
|
17
|
+
assetIndex: params.assetId,
|
|
18
|
+
routeType: params.routeType,
|
|
19
|
+
// Ethereum deposits use the L1 token precision, not Lighter's L2/base-amount precision.
|
|
20
|
+
amount,
|
|
21
|
+
value
|
|
22
|
+
});
|
|
23
|
+
return {
|
|
24
|
+
route: "ethereum",
|
|
25
|
+
txHash
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
__name(depositViaEthereumGateway, "depositViaEthereumGateway");
|
|
29
|
+
function readNativeValue(params, amount) {
|
|
30
|
+
if (params.assetId === AssetId.ETH) {
|
|
31
|
+
const value = parseEther(params.nativeValue ?? params.amount);
|
|
32
|
+
if (value !== amount) {
|
|
33
|
+
throw new Error("Lighter native ETH deposit amount and msg.value must match");
|
|
34
|
+
}
|
|
35
|
+
return value;
|
|
36
|
+
}
|
|
37
|
+
if (params.nativeValue !== void 0 && parseEther(params.nativeValue) !== 0n) {
|
|
38
|
+
throw new Error("Lighter nativeValue is only valid for ETH deposits");
|
|
39
|
+
}
|
|
40
|
+
return void 0;
|
|
41
|
+
}
|
|
42
|
+
__name(readNativeValue, "readNativeValue");
|
|
43
|
+
|
|
44
|
+
export { depositViaEthereumGateway };
|