@pafi-dev/trading 0.12.0 → 0.13.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/index.d.cts CHANGED
@@ -350,6 +350,36 @@ interface ApiErc20TransferResponse {
350
350
  /** Echo of `tokenAddress` (checksummed). Use as a sanity tag in FE logs. */
351
351
  tokenAddress: Address;
352
352
  }
353
+ interface ApiAsterDepositRequest {
354
+ chainId: number;
355
+ userAddress: Address;
356
+ /** USDT amount to deposit (6-decimal raw units). Credited to the user's Aster account. */
357
+ amount: bigint;
358
+ /** ERC-4337 account nonce for the user's EOA (from EntryPoint). */
359
+ aaNonce: bigint;
360
+ /**
361
+ * USDT operator fee — input-token transfer prepended to the batch
362
+ * (token-availability rule). `undefined` = auto-quote via
363
+ * `quoteOperatorFeeUsdt`; `0n` = strip fee (unsponsored); explicit = override.
364
+ */
365
+ gasFee?: bigint;
366
+ }
367
+ interface ApiAsterDepositResponse {
368
+ /** Unsigned sponsored UserOp — [USDT fee, USDT approve, Bridge.deposit]. */
369
+ userOp: PartialUserOperation;
370
+ /** Fee-stripped fallback (paymaster-refused path). Present only when `gasFee > 0n`. */
371
+ userOpFallback?: PartialUserOperation;
372
+ /** USDT operator fee embedded — echoes auto-quote or override. `0n` if no-fee mode. */
373
+ feeAmount: bigint;
374
+ /** Recipient used for the fee transfer (= `pafiFeeRecipient`). */
375
+ feeRecipient: Address;
376
+ /** Aster Deposit Bridge target the deposit call is pinned to. */
377
+ bridgeAddress: Address;
378
+ /** Deposit token (Arbitrum USDT). */
379
+ token: Address;
380
+ /** PAFI Aster broker id used for referral attribution. */
381
+ broker: bigint;
382
+ }
353
383
 
354
384
  interface TradingHandlersConfig {
355
385
  provider: PublicClient;
@@ -455,6 +485,20 @@ declare class TradingHandlers {
455
485
  * sentinel (Relay not deployed for that chain).
456
486
  */
457
487
  handlePerpDeposit(authenticatedAddress: Address, request: ApiPerpDepositRequest): Promise<ApiPerpDepositResponse>;
488
+ /**
489
+ * Build a sponsored Aster deposit UserOp pair (sponsored + fallback).
490
+ *
491
+ * Aster is same-chain (Arbitrum), so — unlike Orderly — there is NO Relay,
492
+ * Vault, broker-hash, or LayerZero msg.value. The user's own delegated
493
+ * account deposits USDT straight into the Aster Deposit Bridge:
494
+ * sponsored: `[USDT.transfer(PAFI, fee), USDT.approve(bridge, amount), Bridge.deposit(token, amount, broker)]`
495
+ * fallback: `[ USDT.approve(bridge, amount), Bridge.deposit(token, amount, broker)]`
496
+ *
497
+ * ⚠️ Built against an ASSUMED Aster Deposit Bridge ABI (`ASTER_DEPOSIT_ABI`
498
+ * in @pafi-dev/core) — Aster has not published it. Confirm the deposit
499
+ * signature + PAFI's `broker` id before mainnet.
500
+ */
501
+ handleAsterDeposit(authenticatedAddress: Address, request: ApiAsterDepositRequest): Promise<ApiAsterDepositResponse>;
458
502
  /**
459
503
  * Build a sponsored ERC-20 transfer UserOp pair (sponsored + fallback).
460
504
  *
package/dist/index.d.ts CHANGED
@@ -350,6 +350,36 @@ interface ApiErc20TransferResponse {
350
350
  /** Echo of `tokenAddress` (checksummed). Use as a sanity tag in FE logs. */
351
351
  tokenAddress: Address;
352
352
  }
353
+ interface ApiAsterDepositRequest {
354
+ chainId: number;
355
+ userAddress: Address;
356
+ /** USDT amount to deposit (6-decimal raw units). Credited to the user's Aster account. */
357
+ amount: bigint;
358
+ /** ERC-4337 account nonce for the user's EOA (from EntryPoint). */
359
+ aaNonce: bigint;
360
+ /**
361
+ * USDT operator fee — input-token transfer prepended to the batch
362
+ * (token-availability rule). `undefined` = auto-quote via
363
+ * `quoteOperatorFeeUsdt`; `0n` = strip fee (unsponsored); explicit = override.
364
+ */
365
+ gasFee?: bigint;
366
+ }
367
+ interface ApiAsterDepositResponse {
368
+ /** Unsigned sponsored UserOp — [USDT fee, USDT approve, Bridge.deposit]. */
369
+ userOp: PartialUserOperation;
370
+ /** Fee-stripped fallback (paymaster-refused path). Present only when `gasFee > 0n`. */
371
+ userOpFallback?: PartialUserOperation;
372
+ /** USDT operator fee embedded — echoes auto-quote or override. `0n` if no-fee mode. */
373
+ feeAmount: bigint;
374
+ /** Recipient used for the fee transfer (= `pafiFeeRecipient`). */
375
+ feeRecipient: Address;
376
+ /** Aster Deposit Bridge target the deposit call is pinned to. */
377
+ bridgeAddress: Address;
378
+ /** Deposit token (Arbitrum USDT). */
379
+ token: Address;
380
+ /** PAFI Aster broker id used for referral attribution. */
381
+ broker: bigint;
382
+ }
353
383
 
354
384
  interface TradingHandlersConfig {
355
385
  provider: PublicClient;
@@ -455,6 +485,20 @@ declare class TradingHandlers {
455
485
  * sentinel (Relay not deployed for that chain).
456
486
  */
457
487
  handlePerpDeposit(authenticatedAddress: Address, request: ApiPerpDepositRequest): Promise<ApiPerpDepositResponse>;
488
+ /**
489
+ * Build a sponsored Aster deposit UserOp pair (sponsored + fallback).
490
+ *
491
+ * Aster is same-chain (Arbitrum), so — unlike Orderly — there is NO Relay,
492
+ * Vault, broker-hash, or LayerZero msg.value. The user's own delegated
493
+ * account deposits USDT straight into the Aster Deposit Bridge:
494
+ * sponsored: `[USDT.transfer(PAFI, fee), USDT.approve(bridge, amount), Bridge.deposit(token, amount, broker)]`
495
+ * fallback: `[ USDT.approve(bridge, amount), Bridge.deposit(token, amount, broker)]`
496
+ *
497
+ * ⚠️ Built against an ASSUMED Aster Deposit Bridge ABI (`ASTER_DEPOSIT_ABI`
498
+ * in @pafi-dev/core) — Aster has not published it. Confirm the deposit
499
+ * signature + PAFI's `broker` id before mainnet.
500
+ */
501
+ handleAsterDeposit(authenticatedAddress: Address, request: ApiAsterDepositRequest): Promise<ApiAsterDepositResponse>;
458
502
  /**
459
503
  * Build a sponsored ERC-20 transfer UserOp pair (sponsored + fallback).
460
504
  *
package/dist/index.js CHANGED
@@ -3,6 +3,8 @@ import { getAddress } from "viem";
3
3
  import {
4
4
  buildPerpDepositWithGasDeduction,
5
5
  buildPerpDepositViaRelay,
6
+ buildAsterDeposit,
7
+ getAsterBrokerId,
6
8
  buildErc20TransferUserOp,
7
9
  ORDERLY_RELAY_ABI,
8
10
  getContractAddresses,
@@ -1111,6 +1113,80 @@ var TradingHandlers = class {
1111
1113
  };
1112
1114
  }
1113
1115
  // =========================================================================
1116
+ // POST /aster-deposit — Aster perp deposit (same-chain on Arbitrum)
1117
+ // =========================================================================
1118
+ /**
1119
+ * Build a sponsored Aster deposit UserOp pair (sponsored + fallback).
1120
+ *
1121
+ * Aster is same-chain (Arbitrum), so — unlike Orderly — there is NO Relay,
1122
+ * Vault, broker-hash, or LayerZero msg.value. The user's own delegated
1123
+ * account deposits USDT straight into the Aster Deposit Bridge:
1124
+ * sponsored: `[USDT.transfer(PAFI, fee), USDT.approve(bridge, amount), Bridge.deposit(token, amount, broker)]`
1125
+ * fallback: `[ USDT.approve(bridge, amount), Bridge.deposit(token, amount, broker)]`
1126
+ *
1127
+ * ⚠️ Built against an ASSUMED Aster Deposit Bridge ABI (`ASTER_DEPOSIT_ABI`
1128
+ * in @pafi-dev/core) — Aster has not published it. Confirm the deposit
1129
+ * signature + PAFI's `broker` id before mainnet.
1130
+ */
1131
+ async handleAsterDeposit(authenticatedAddress, request) {
1132
+ const userAddress = getAddress(request.userAddress);
1133
+ if (getAddress(authenticatedAddress) !== userAddress) {
1134
+ throw new ValidationError(
1135
+ "ADDRESS_MISMATCH",
1136
+ `handleAsterDeposit: authenticatedAddress (${authenticatedAddress}) does not match request.userAddress (${request.userAddress})`
1137
+ );
1138
+ }
1139
+ if (request.chainId !== this.chainId) {
1140
+ throw new ValidationError(
1141
+ "CHAIN_MISMATCH",
1142
+ `handleAsterDeposit: unsupported chainId ${request.chainId}`
1143
+ );
1144
+ }
1145
+ if (request.amount <= 0n) {
1146
+ throw new ValidationError(
1147
+ "INVALID_AMOUNT",
1148
+ "handleAsterDeposit: amount must be positive"
1149
+ );
1150
+ }
1151
+ const { asterDepositBridge, usdt, pafiFeeRecipient } = getContractAddresses(
1152
+ request.chainId
1153
+ );
1154
+ if (!asterDepositBridge) {
1155
+ throw new ValidationError(
1156
+ "ASTER_NOT_AVAILABLE",
1157
+ `handleAsterDeposit: Aster is not deployed on chainId ${request.chainId} (no Deposit Bridge)`
1158
+ );
1159
+ }
1160
+ const broker = getAsterBrokerId(request.chainId);
1161
+ const gasFee = request.gasFee !== void 0 ? request.gasFee : await quoteOperatorFeeUsdt({
1162
+ provider: this.provider,
1163
+ chainId: request.chainId
1164
+ }).catch(() => 0n);
1165
+ const common = {
1166
+ userAddress,
1167
+ aaNonce: request.aaNonce,
1168
+ bridgeAddress: asterDepositBridge,
1169
+ token: usdt,
1170
+ amount: request.amount,
1171
+ broker
1172
+ };
1173
+ const userOp = buildAsterDeposit({
1174
+ ...common,
1175
+ gasFee: gasFee > 0n ? gasFee : void 0,
1176
+ gasFeeRecipient: gasFee > 0n ? pafiFeeRecipient : void 0
1177
+ });
1178
+ const userOpFallback = gasFee > 0n ? buildAsterDeposit(common) : void 0;
1179
+ return {
1180
+ userOp,
1181
+ userOpFallback,
1182
+ feeAmount: gasFee > 0n ? gasFee : 0n,
1183
+ feeRecipient: pafiFeeRecipient,
1184
+ bridgeAddress: asterDepositBridge,
1185
+ token: usdt,
1186
+ broker
1187
+ };
1188
+ }
1189
+ // =========================================================================
1114
1190
  // POST /erc20-transfer — gasless ERC-20 send (USDC/USDT/active-PT)
1115
1191
  // =========================================================================
1116
1192
  /**