nara-sdk 1.0.81 → 1.0.83

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 (2) hide show
  1. package/package.json +1 -1
  2. package/src/bridge.ts +38 -6
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nara-sdk",
3
- "version": "1.0.81",
3
+ "version": "1.0.83",
4
4
  "description": "SDK for the Nara chain (Solana-compatible)",
5
5
  "module": "index.ts",
6
6
  "main": "index.ts",
package/src/bridge.ts CHANGED
@@ -49,6 +49,10 @@ export interface BridgeTokenSide {
49
49
  export interface BridgeTokenConfig {
50
50
  symbol: string;
51
51
  decimals: number;
52
+ /** Minimum per-transfer amount in raw units (rejected if below) */
53
+ minAmount: bigint;
54
+ /** Minimum fee floor in raw units (fee = max(amount * bps, minFee)) */
55
+ minFee: bigint;
52
56
  solana: BridgeTokenSide;
53
57
  nara: BridgeTokenSide;
54
58
  }
@@ -128,6 +132,8 @@ export const BRIDGE_TOKENS: Record<string, BridgeTokenConfig> = {
128
132
  USDC: {
129
133
  symbol: "USDC",
130
134
  decimals: 6,
135
+ minAmount: 5_000_000n, // 5 USDC
136
+ minFee: 500_000n, // 0.5 USDC (fee floor)
131
137
  solana: {
132
138
  warpProgram: new PublicKey("4GcZJTa8s9vxtTz97Vj1RrwKMqPkT3DiiJkvUQDwsuZP"),
133
139
  mode: "collateral",
@@ -144,6 +150,8 @@ export const BRIDGE_TOKENS: Record<string, BridgeTokenConfig> = {
144
150
  USDT: {
145
151
  symbol: "USDT",
146
152
  decimals: 6,
153
+ minAmount: 5_000_000n, // 5 USDT
154
+ minFee: 500_000n, // 0.5 USDT (fee floor)
147
155
  solana: {
148
156
  warpProgram: new PublicKey("DCTt9H3pwwU89qC3Z4voYNThZypV68AwhYNzMNBxWXoy"),
149
157
  mode: "collateral",
@@ -160,6 +168,8 @@ export const BRIDGE_TOKENS: Record<string, BridgeTokenConfig> = {
160
168
  SOL: {
161
169
  symbol: "SOL",
162
170
  decimals: 9,
171
+ minAmount: 100_000_000n, // 0.1 SOL
172
+ minFee: 10_000_000n, // 0.01 SOL (fee floor)
163
173
  solana: {
164
174
  warpProgram: new PublicKey("46MmAWwKRAt9uvn7m44NXbVq2DCWBQE2r1TDw25nyXrt"),
165
175
  mode: "native",
@@ -321,19 +331,32 @@ export function encodeTransferRemote(
321
331
  // ─── Fee calculation ──────────────────────────────────────────────
322
332
 
323
333
  export interface FeeSplit {
334
+ /** Total fee (max of percentage and minFee) in raw units */
324
335
  feeAmount: bigint;
336
+ /** Net amount bridged after fee */
325
337
  bridgeAmount: bigint;
338
+ /** Percentage part (bps) used */
326
339
  feeBps: number;
340
+ /** Fee floor in raw units */
341
+ minFee: bigint;
327
342
  }
328
343
 
329
- export function calculateBridgeFee(amount: bigint, feeBps?: number): FeeSplit {
344
+ /**
345
+ * Calculate the bridge fee: max(amount * bps / 10000, minFee)
346
+ */
347
+ export function calculateBridgeFee(
348
+ amount: bigint,
349
+ feeBps?: number,
350
+ minFee: bigint = 0n
351
+ ): FeeSplit {
330
352
  const bps = feeBps ?? DEFAULT_BRIDGE_FEE_BPS;
331
353
  if (bps < 0 || bps > BRIDGE_FEE_BPS_DENOMINATOR) {
332
354
  throw new Error(`Invalid feeBps: ${bps}`);
333
355
  }
334
- const feeAmount = (amount * BigInt(bps)) / BigInt(BRIDGE_FEE_BPS_DENOMINATOR);
356
+ const pctFee = (amount * BigInt(bps)) / BigInt(BRIDGE_FEE_BPS_DENOMINATOR);
357
+ const feeAmount = pctFee > minFee ? pctFee : minFee;
335
358
  const bridgeAmount = amount - feeAmount;
336
- return { feeAmount, bridgeAmount, feeBps: bps };
359
+ return { feeAmount, bridgeAmount, feeBps: bps, minFee };
337
360
  }
338
361
 
339
362
  // ─── Fee instruction builder ──────────────────────────────────────
@@ -523,12 +546,21 @@ export function makeBridgeIxs(params: BridgeTransferParams): BridgeIxsResult {
523
546
 
524
547
  if (amount <= 0n) throw new Error("amount must be > 0");
525
548
 
549
+ // Enforce per-token minimum transfer amount
550
+ const tokenCfg = getToken(token);
551
+ if (amount < tokenCfg.minAmount) {
552
+ const min = Number(tokenCfg.minAmount) / Math.pow(10, tokenCfg.decimals);
553
+ throw new Error(
554
+ `Bridge amount too small: minimum for ${token} is ${min} (raw ${tokenCfg.minAmount})`
555
+ );
556
+ }
557
+
526
558
  const split = skipFee
527
- ? { feeAmount: 0n, bridgeAmount: amount, feeBps: 0 }
528
- : calculateBridgeFee(amount, feeBps);
559
+ ? { feeAmount: 0n, bridgeAmount: amount, feeBps: 0, minFee: 0n }
560
+ : calculateBridgeFee(amount, feeBps, tokenCfg.minFee);
529
561
 
530
562
  if (split.bridgeAmount <= 0n) {
531
- throw new Error("bridge amount after fee is zero — increase amount or lower feeBps");
563
+ throw new Error("bridge amount after fee is zero — increase amount or lower fee");
532
564
  }
533
565
 
534
566
  const recipientForFee = feeRecipient ?? getBridgeFeeRecipient(fromChain);