@ledgerhq/live-cli 24.40.1-nightly.20260506192049 → 24.40.1

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.
@@ -6,7 +6,7 @@ const __rslib_import_meta_url__ = /*#__PURE__*/ (function () {
6
6
  new URL('main.js', document.baseURI).href;
7
7
  })();
8
8
  ;
9
- exports.ids = ["722"];
9
+ exports.ids = ["550"];
10
10
  exports.modules = {
11
11
  "../../libs/ledger-live-common/lib-es/bridge/generic-alpaca/alpaca/local/tezos.js"(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
12
12
  // ESM COMPAT FLAG
@@ -90,6 +90,20 @@ var utils = __webpack_require__("../../node_modules/.pnpm/@taquito+ledger-signer
90
90
  * the increased fee component when computing send-max in fallback mode.
91
91
  * Chosen to match Taquito’s behavior closely in integration tests.
92
92
  */ const OP_SIZE_XTZ_TRANSFER = 154;
93
+ /**
94
+ * Helper function to map generic staking intents to Tezos operation modes
95
+ */ function mapIntentTypeToTezosMode(intentType) {
96
+ switch(intentType){
97
+ case "stake":
98
+ case "delegate":
99
+ return "delegate";
100
+ case "unstake":
101
+ case "undelegate":
102
+ return "undelegate";
103
+ default:
104
+ return "send";
105
+ }
106
+ }
93
107
  /**
94
108
  * Parse FA1.2 / FA2 token contract + token id from Alpaca `assetReference`
95
109
  * (`KT1…` or `KT1…:tokenId` as produced by getBlock / listOperations).
@@ -115,7 +129,7 @@ var utils = __webpack_require__("../../node_modules/.pnpm/@taquito+ledger-signer
115
129
  /**
116
130
  * Resolves Tezos operation mode from intent type and asset (native XTZ vs token).
117
131
  */ function resolveTezosOperationMode(intentType, asset) {
118
- const base = intentType;
132
+ const base = mapIntentTypeToTezosMode(intentType);
119
133
  if (base === "send" && parseTezosTokenAsset(asset) !== null) {
120
134
  return "send_token";
121
135
  }
@@ -309,34 +323,8 @@ async function craftTransaction(account, transaction, publicKey) {
309
323
  });
310
324
  break;
311
325
  }
312
- case "stake":
313
- case "unstake":
314
- case "finalize_unstake":
315
- {
316
- const typeMap = {
317
- stake: "STAKE",
318
- unstake: "UNSTAKE",
319
- finalize_unstake: "FINALIZE_UNSTAKE"
320
- };
321
- type = typeMap[transaction.type];
322
- contents.push({
323
- kind: taquito_rpc_es6/* .OpKind.TRANSACTION */.w9.TRANSACTION,
324
- amount: transaction.type === "finalize_unstake" ? "0" : transaction.amount.toString(),
325
- destination: address,
326
- source: address,
327
- counter: (counter + 1 + contents.length).toString(),
328
- parameters: {
329
- entrypoint: transaction.type,
330
- value: {
331
- prim: "Unit"
332
- }
333
- },
334
- ...transactionFees
335
- });
336
- break;
337
- }
338
326
  default:
339
- throw new types_errors/* .UnsupportedTransactionMode */.VJ("unsupported mode", {
327
+ throw new types_errors/* .UnsupportedTransactionMode */.V("unsupported mode", {
340
328
  mode: transaction.type
341
329
  });
342
330
  }
@@ -435,21 +423,6 @@ async function craftTransaction(account, transaction, publicKey) {
435
423
  source: account.address
436
424
  });
437
425
  break;
438
- case "stake":
439
- estimate = await tezosToolkit.estimate.stake({
440
- amount: Number(amount),
441
- mutez: true
442
- });
443
- break;
444
- case "unstake":
445
- estimate = await tezosToolkit.estimate.unstake({
446
- amount: Number(amount),
447
- mutez: true
448
- });
449
- break;
450
- case "finalize_unstake":
451
- estimate = await tezosToolkit.estimate.finalizeUnstake({});
452
- break;
453
426
  case "send_token":
454
427
  {
455
428
  if (!transaction.contractAddress || transaction.tokenId === undefined) {
@@ -477,7 +450,7 @@ async function craftTransaction(account, transaction, publicKey) {
477
450
  break;
478
451
  }
479
452
  default:
480
- throw new types_errors/* .UnsupportedTransactionMode */.VJ("unsupported mode", {
453
+ throw new types_errors/* .UnsupportedTransactionMode */.V("unsupported mode", {
481
454
  mode: transaction.mode
482
455
  });
483
456
  }
@@ -627,26 +600,6 @@ const clearUndefined = (obj)=>{
627
600
  Object.entries(newObj).forEach(([key, value])=>value === undefined && delete newObj[key]);
628
601
  return newObj;
629
602
  };
630
- /**
631
- * Internal helper shared by `getOperationsTransactions` and `getOperationsOrigination`.
632
- * Both endpoints accept the same query shape; only the URL path differs.
633
- */ async function getOperationsByType(type, level, cursor, apiQueryParams = {}) {
634
- // "sort.asc": "id" guarantees forward progress for cursor-based paging (offset.cr).
635
- // Without an explicit sort the API default may be descending, which would cause the
636
- // cursor to go backwards and produce duplicates or an infinite loop.
637
- const params = {
638
- "level.gte": level,
639
- limit: BLOCK_PAGE_SIZE,
640
- "sort.asc": "id",
641
- ...clearUndefined(apiQueryParams)
642
- };
643
- if (cursor !== undefined) params["offset.cr"] = cursor;
644
- const { data } = await (0,live_network_lib_es/* ["default"] */.A)({
645
- url: `${getExplorerUrl()}/v1/operations/${type}`,
646
- params
647
- });
648
- return data;
649
- }
650
603
  const tzkt_api = {
651
604
  async getBlockCount () {
652
605
  const { data } = await (0,live_network_lib_es/* ["default"] */.A)({
@@ -692,25 +645,6 @@ const tzkt_api = {
692
645
  });
693
646
  return data;
694
647
  },
695
- /**
696
- * Resolves block hashes for the given levels in a single request.
697
- * Uses `/v1/blocks?level.in=...&select.values=level,hash`, which TzKT honours
698
- * (unlike `/v1/blocks/{level}?select=...`, where `select` is ignored). Used
699
- * for cheap backfill of `block.hash` on operations whose level is known but
700
- * whose response omits the block field (e.g. `/accounts/{addr}/operations`
701
- * for staking ops). Levels that don't resolve are absent from the result map.
702
- */ async getBlockHashesByLevels (levels) {
703
- if (levels.length === 0) return new Map();
704
- const { data } = await (0,live_network_lib_es/* ["default"] */.A)({
705
- url: `${getExplorerUrl()}/v1/blocks`,
706
- params: {
707
- "level.in": levels.join(","),
708
- "select.values": "level,hash",
709
- limit: levels.length
710
- }
711
- });
712
- return new Map(data);
713
- },
714
648
  /**
715
649
  * Fetches a single page of `transaction` operations at the given block level.
716
650
  * Internal — used by `fetchBlockTransactions` which handles pagination.
@@ -735,13 +669,21 @@ const tzkt_api = {
735
669
  * Fetches a list of `transaction` operations after the given level.
736
670
  * https://api.tzkt.io/#operation/Operations_GetTransactions
737
671
  */ async getOperationsTransactions (level, cursor, apiQueryParams = {}) {
738
- return getOperationsByType("transactions", level, cursor, apiQueryParams);
739
- },
740
- /**
741
- * Fetches a list of `originations` operations after the given level.
742
- * https://api.tzkt.io/#operation/Operations_GetOriginations
743
- */ async getOperationsOrigination (level, cursor, apiQueryParams = {}) {
744
- return getOperationsByType("originations", level, cursor, apiQueryParams);
672
+ // "sort.asc": "id" guarantees forward progress for cursor-based paging (offset.cr).
673
+ // Without an explicit sort the API default may be descending, which would cause the
674
+ // cursor to go backwards and produce duplicates or an infinite loop.
675
+ const params = {
676
+ "level.gte": level,
677
+ limit: BLOCK_PAGE_SIZE,
678
+ "sort.asc": "id",
679
+ ...clearUndefined(apiQueryParams)
680
+ };
681
+ if (cursor !== undefined) params["offset.cr"] = cursor;
682
+ const { data } = await (0,live_network_lib_es/* ["default"] */.A)({
683
+ url: `${getExplorerUrl()}/v1/operations/transactions`,
684
+ params
685
+ });
686
+ return data;
745
687
  },
746
688
  /**
747
689
  * Fetches a single page of FA token transfers at the given block level.
@@ -765,10 +707,16 @@ const tzkt_api = {
765
707
  /**
766
708
  * Fetches the latest FA token transfers since the given level.
767
709
  * https://api.tzkt.io/#operation/Tokens_GetTokenTransfers
768
- */ async getTokenTransfers (apiQueryParams = {}) {
710
+ */ async getTokenTransfers (level, cursor, apiQueryParams = {}) {
711
+ // Same rationale as getBlockTransactionsPage: explicit ascending sort keeps the
712
+ // offset.cr cursor advancing forward regardless of the API's default ordering.;
769
713
  const params = {
714
+ "level.gte": level,
715
+ limit: BLOCK_PAGE_SIZE,
716
+ "sort.asc": "id",
770
717
  ...clearUndefined(apiQueryParams)
771
718
  };
719
+ if (cursor !== undefined) params["offset.cr"] = cursor;
772
720
  const { data } = await (0,live_network_lib_es/* ["default"] */.A)({
773
721
  url: `${getExplorerUrl()}/v1/tokens/transfers`,
774
722
  params
@@ -792,75 +740,31 @@ const tzkt_api = {
792
740
  });
793
741
  return data;
794
742
  },
795
- /**
796
- * Fetches a single page of `staking` operations at the given block level.
797
- * Internal — used by `fetchBlockStaking` which handles pagination.
798
- * https://api.tzkt.io/#operation/Operations_GetStaking
799
- */ async getBlockStakingPage (level, cursor) {
800
- const params = {
801
- level,
802
- limit: BLOCK_PAGE_SIZE,
803
- "sort.asc": "id"
804
- };
805
- if (cursor !== undefined) params["offset.cr"] = cursor;
806
- const { data } = await (0,live_network_lib_es/* ["default"] */.A)({
807
- url: `${getExplorerUrl()}/v1/operations/staking`,
808
- params
809
- });
810
- return data;
811
- },
812
743
  /**
813
744
  * Fetches FA2 token transfers (tokenId = 0 only) for a given account.
814
745
  * This is limited to `token.standard=fa2` and `token.tokenId=0` on the TzKT API.
815
- * Translates `query.sort` to TzKT's `sort.asc=id` / `sort.desc=id`.
816
- * The lower-level `getTokenTransfers` helper is a generic pass-through and does not pin the sort.
817
746
  * https://api.tzkt.io/#operation/Tokens_GetTokenTransfers
818
747
  */ async getAccountTokenTransfers (address, query) {
819
- const sortKey = query.sort === "Descending" ? "sort.desc" : "sort.asc";
820
748
  const params = {
821
749
  "anyof.from.to": address,
822
750
  "token.tokenId": "0",
823
- "token.standard": "fa2",
824
- [sortKey]: "id",
825
- limit: query.limit,
826
- "level.ge": query["level.ge"],
827
- "level.lt": query["level.lt"],
828
- "level.gt": query["level.gt"],
829
- "id.lt": query["id.lt"],
830
- "id.gt": query["id.gt"]
751
+ "token.standard": "fa2"
831
752
  };
832
- const data = await tzkt_api.getTokenTransfers(clearUndefined(params));
753
+ const data = await tzkt_api.getTokenTransfers(query["level.ge"], query["lastId"], params);
833
754
  const transactionIds = data.map((t)=>t.transactionId).filter((id)=>typeof id === "number");
834
- const originationIds = data.map((t)=>t.originationId).filter((id)=>typeof id === "number");
835
- if (transactionIds.length === 0 && originationIds.length === 0) {
836
- return [];
755
+ if (transactionIds.length === 0) {
756
+ return data.map((token)=>({
757
+ ...token,
758
+ hash: ""
759
+ }));
837
760
  }
838
- const transactions = transactionIds.length ? await tzkt_api.getOperationsTransactions(query["level.ge"] || 0, undefined, {
761
+ const transactions = await tzkt_api.getOperationsTransactions(query["level.ge"] || 0, undefined, {
839
762
  "id.in": transactionIds.join(",")
840
- }) : [];
841
- const originations = originationIds.length ? await tzkt_api.getOperationsOrigination(query["level.ge"] || 0, undefined, {
842
- "id.in": originationIds.join(",")
843
- }) : [];
844
- // Build id -> operation maps once so per-transfer lookups are O(1) instead of O(n).
845
- // Keys are widened to `number | undefined` so lookups with a missing id naturally
846
- // return `undefined` (no entry is ever stored under the `undefined` key).
847
- const transactionsById = new Map(transactions.map((t)=>[
848
- t.id,
849
- t
850
- ]));
851
- const originationsById = new Map(originations.map((o)=>[
852
- o.id,
853
- o
854
- ]));
855
- return data.map((token)=>{
856
- const transaction = transactionsById.get(token.transactionId);
857
- const origination = originationsById.get(token.originationId);
858
- return {
859
- ...token,
860
- hash: transaction?.hash ?? origination?.hash ?? "",
861
- block: transaction?.block ?? origination?.block ?? ""
862
- };
863
763
  });
764
+ return data.map((token)=>({
765
+ ...token,
766
+ hash: transactions.find((t)=>t.id === token.transactionId)?.hash ?? ""
767
+ }));
864
768
  },
865
769
  /**
866
770
  * Fetches FA token balances for a given account.
@@ -972,104 +876,14 @@ const fetchAllTransactions = async (address, lastId)=>{
972
876
  }
973
877
  return delegations;
974
878
  };
975
- /**
976
- * Fetches ALL `staking` operations for a given block level, paginating through
977
- * TzKT's cursor-based pages (`offset.cr`) until exhausted.
978
- */ const fetchBlockStaking = async (level)=>{
979
- const stakingOps = [];
980
- let cursor;
981
- let maxIteration = lib_es_config/* ["default"].getCoinConfig */.A.getCoinConfig().explorer.maxTxQuery;
982
- do {
983
- const page = await tzkt_api.getBlockStakingPage(level, cursor);
984
- if (page.length === 0) break;
985
- stakingOps.push(...page);
986
- if (page.length < BLOCK_PAGE_SIZE) break;
987
- cursor = page.at(-1).id;
988
- }while (--maxIteration > 0);
989
- if (maxIteration === 0) {
990
- (0,logs_lib_es/* .log */.Rm)("tezos", `fetchBlockStaking: maxTxQuery limit reached at level ${level}, result may be incomplete`);
991
- }
992
- return stakingOps;
993
- };
994
879
  /* export default */ const tzkt = (tzkt_api); //# sourceMappingURL=tzkt.js.map
995
880
 
996
- ;// CONCATENATED MODULE: ../../libs/coin-modules/coin-tezos/lib-es/logic/getStakes.js
997
-
998
- /**
999
- * Build the staking positions exposed by a Tezos account, per Paris upgrade semantics:
1000
- * - delegation position (when a delegate is set) for the non-staked, delegated amount
1001
- * - active staking position (when `stakedBalance > 0`)
1002
- * - deactivating unstake position (when `unstakedBalance > 0`)
1003
- *
1004
- * Each entry inherits the account `delegate` when set, since on Tezos a staked or unstaked
1005
- * portion is necessarily delegated to the same baker as the rest of the balance.
1006
- */ function buildStakesForAccount(address, account) {
1007
- const balance = BigInt(account.balance ?? 0);
1008
- const stakedBalance = BigInt(account.stakedBalance ?? 0);
1009
- const unstakedBalance = BigInt(account.unstakedBalance ?? 0);
1010
- const delegateAddress = account.delegate?.address;
1011
- const stakes = [];
1012
- if (delegateAddress) {
1013
- stakes.push({
1014
- uid: `delegation-${address}`,
1015
- address,
1016
- delegate: delegateAddress,
1017
- state: "active",
1018
- asset: {
1019
- type: "native"
1020
- },
1021
- amount: balance - stakedBalance
1022
- });
1023
- }
1024
- if (stakedBalance > 0n) {
1025
- stakes.push({
1026
- uid: `stake-${address}`,
1027
- address,
1028
- ...delegateAddress && {
1029
- delegate: delegateAddress
1030
- },
1031
- state: "active",
1032
- asset: {
1033
- type: "native"
1034
- },
1035
- amount: stakedBalance
1036
- });
1037
- }
1038
- if (unstakedBalance > 0n) {
1039
- stakes.push({
1040
- uid: `unstaking-${address}`,
1041
- address,
1042
- ...delegateAddress && {
1043
- delegate: delegateAddress
1044
- },
1045
- state: "deactivating",
1046
- asset: {
1047
- type: "native"
1048
- },
1049
- amount: unstakedBalance
1050
- });
1051
- }
1052
- return stakes;
1053
- }
1054
- async function getStakes(address, _cursor) {
1055
- const accountInfo = await tzkt.getAccountByAddress(address);
1056
- if (accountInfo.type !== "user") return {
1057
- items: []
1058
- };
1059
- return {
1060
- items: buildStakesForAccount(address, accountInfo)
1061
- };
1062
- } //# sourceMappingURL=getStakes.js.map
1063
-
1064
881
  ;// CONCATENATED MODULE: ../../libs/coin-modules/coin-tezos/lib-es/logic/getBalance.js
1065
882
 
1066
-
1067
883
  /**
1068
884
  * Returns the balances of the given address as an array of Balance objects.
1069
- * The first entry represents the native balance (with value 0n for empty accounts).
1070
- * For delegated/staked accounts, additional native entries are appended carrying each
1071
- * staking position (delegation, active staking, deactivating unstake) per the Paris upgrade.
1072
- * Token balances are appended after.
885
+ * The first entry represents the native balance (with value 0n for empty accounts),
886
+ * followed by any token balances associated with the address.
1073
887
  */ async function getBalance(address) {
1074
888
  const [apiAccountResult, tokensBalancesResult] = await Promise.allSettled([
1075
889
  tzkt.getAccountByAddress(address),
@@ -1081,13 +895,16 @@ async function getStakes(address, _cursor) {
1081
895
  const apiAccount = apiAccountResult.value;
1082
896
  const tokensBalancesRaw = tokensBalancesResult.status === "fulfilled" ? tokensBalancesResult.value : [];
1083
897
  const normalized = apiAccount.type === "user" ? BigInt(apiAccount.balance) : 0n;
1084
- const stakeBalances = apiAccount.type === "user" ? buildStakesForAccount(address, apiAccount).map((stake)=>({
1085
- value: stake.amount,
1086
- asset: {
1087
- type: "native"
1088
- },
1089
- stake
1090
- })) : [];
898
+ const stake = apiAccount.type === "user" && apiAccount.delegate?.address ? {
899
+ uid: address,
900
+ address,
901
+ delegate: apiAccount.delegate.address,
902
+ state: "active",
903
+ asset: {
904
+ type: "native"
905
+ },
906
+ amount: normalized
907
+ } : undefined;
1091
908
  const tokensBalance = tokensBalancesRaw.map(({ balance, token })=>{
1092
909
  const magnitude = Number.parseInt(token.metadata?.decimals || "0", 10);
1093
910
  const name = token.metadata?.name ?? token.contract.alias ?? "";
@@ -1115,9 +932,11 @@ async function getStakes(address, _cursor) {
1115
932
  value: normalized,
1116
933
  asset: {
1117
934
  type: "native"
935
+ },
936
+ ...stake && {
937
+ stake
1118
938
  }
1119
939
  },
1120
- ...stakeBalances,
1121
940
  ...tokensBalance
1122
941
  ];
1123
942
  } //# sourceMappingURL=getBalance.js.map
@@ -1129,16 +948,8 @@ var bakers = __webpack_require__("../../libs/coin-modules/coin-tezos/lib-es/netw
1129
948
 
1130
949
  //# sourceMappingURL=index.js.map
1131
950
 
1132
- ;// CONCATENATED MODULE: ../../libs/coin-modules/coin-tezos/lib-es/constants.js
1133
- const STAKING_ACTION_TO_OP_TYPE = {
1134
- stake: "STAKE",
1135
- unstake: "UNSTAKE",
1136
- finalize: "FINALIZE_UNSTAKE"
1137
- }; //# sourceMappingURL=constants.js.map
1138
-
1139
951
  ;// CONCATENATED MODULE: ../../libs/coin-modules/coin-tezos/lib-es/logic/getBlock.js
1140
952
 
1141
-
1142
953
  const NATIVE_ASSET = {
1143
954
  type: "native",
1144
955
  name: "XTZ"
@@ -1273,51 +1084,6 @@ function buildBlockTransactionFromDelegation(op) {
1273
1084
  };
1274
1085
  }
1275
1086
  // ---------------------------------------------------------------------------
1276
- // Staking helpers (Paris adaptive issuance)
1277
- // ---------------------------------------------------------------------------
1278
- function computeStakingFees(op) {
1279
- return BigInt(op.bakerFee ?? 0) + BigInt(op.storageFee ?? 0) + BigInt(op.allocationFee ?? 0);
1280
- }
1281
- function buildStakingOperations(op) {
1282
- const senderAddr = op.sender?.address;
1283
- if (!senderAddr) return [];
1284
- const operationType = STAKING_ACTION_TO_OP_TYPE[op.action];
1285
- const bakerAddr = op.baker?.address;
1286
- return [
1287
- {
1288
- type: "other",
1289
- address: senderAddr,
1290
- asset: NATIVE_ASSET,
1291
- amount: 0n,
1292
- details: {
1293
- operationType,
1294
- stakedAmount: BigInt(op.amount),
1295
- ...bakerAddr && {
1296
- delegate: bakerAddr
1297
- },
1298
- counter: op.counter,
1299
- gasLimit: op.gasLimit,
1300
- storageLimit: op.storageLimit,
1301
- ledgerOpType: operationType
1302
- }
1303
- }
1304
- ];
1305
- }
1306
- function buildBlockTransactionFromStaking(op) {
1307
- if (!op.hash) return null;
1308
- const feesPayer = op.sender?.address;
1309
- const succeeded = !op.status || op.status === "applied";
1310
- return {
1311
- hash: op.hash,
1312
- failed: !succeeded,
1313
- fees: computeStakingFees(op),
1314
- ...feesPayer && {
1315
- feesPayer
1316
- },
1317
- operations: succeeded ? buildStakingOperations(op) : []
1318
- };
1319
- }
1320
- // ---------------------------------------------------------------------------
1321
1087
  // FA token helpers
1322
1088
  // ---------------------------------------------------------------------------
1323
1089
  /**
@@ -1424,21 +1190,7 @@ function buildBlockTransactionFromStaking(op) {
1424
1190
  // ---------------------------------------------------------------------------
1425
1191
  // Transaction grouping — public orchestrator
1426
1192
  // ---------------------------------------------------------------------------
1427
- function mergeAuxiliaryTx(blockTxByHash, auxTx) {
1428
- const existing = blockTxByHash.get(auxTx.hash);
1429
- if (!existing) {
1430
- blockTxByHash.set(auxTx.hash, auxTx);
1431
- return;
1432
- }
1433
- if (auxTx.failed) {
1434
- existing.failed = true;
1435
- existing.operations = [];
1436
- } else if (!existing.failed && auxTx.operations.length > 0) {
1437
- existing.operations.push(...auxTx.operations);
1438
- }
1439
- existing.fees += auxTx.fees;
1440
- }
1441
- function groupAndMapTransactions(transactions, tokenTransfers, delegations, stakings) {
1193
+ function groupAndMapTransactions(transactions, tokenTransfers, delegations) {
1442
1194
  const groups = groupTransactionsByHash(transactions);
1443
1195
  const txIdToHash = new Map();
1444
1196
  for (const tx of transactions){
@@ -1450,11 +1202,19 @@ function groupAndMapTransactions(transactions, tokenTransfers, delegations, stak
1450
1202
  }
1451
1203
  for (const delegation of delegations){
1452
1204
  const delegationTx = buildBlockTransactionFromDelegation(delegation);
1453
- if (delegationTx) mergeAuxiliaryTx(blockTxByHash, delegationTx);
1454
- }
1455
- for (const staking of stakings){
1456
- const stakingTx = buildBlockTransactionFromStaking(staking);
1457
- if (stakingTx) mergeAuxiliaryTx(blockTxByHash, stakingTx);
1205
+ if (!delegationTx) continue;
1206
+ const existing = blockTxByHash.get(delegationTx.hash);
1207
+ if (!existing) {
1208
+ blockTxByHash.set(delegationTx.hash, delegationTx);
1209
+ continue;
1210
+ }
1211
+ if (delegationTx.failed) {
1212
+ existing.failed = true;
1213
+ existing.operations = [];
1214
+ } else if (!existing.failed && delegationTx.operations.length > 0) {
1215
+ existing.operations.push(...delegationTx.operations);
1216
+ }
1217
+ existing.fees += delegationTx.fees;
1458
1218
  }
1459
1219
  const standaloneByKey = new Map();
1460
1220
  for (const transfer of tokenTransfers){
@@ -1472,7 +1232,7 @@ function groupAndMapTransactions(transactions, tokenTransfers, delegations, stak
1472
1232
  * Returns the full block at the given Tezos level: metadata + all transactions
1473
1233
  * with their XTZ and FA token balance changes.
1474
1234
  *
1475
- * - Fetches block metadata, native transactions, delegations, FA token transfers, and staking operations in parallel.
1235
+ * - Fetches block metadata, native transactions, delegations, and FA token transfers in parallel.
1476
1236
  * - Also fetches the predecessor block in parallel to populate `BlockInfo.parent`.
1477
1237
  * - Groups operations by hash, aggregates fees, and determines the fee payer.
1478
1238
  * - Appends FA token transfer operations to the owning BlockTransaction when a
@@ -1481,17 +1241,16 @@ function groupAndMapTransactions(transactions, tokenTransfers, delegations, stak
1481
1241
  if (!Number.isSafeInteger(height) || height <= 0) {
1482
1242
  throw new Error(`getBlock: height must be a positive integer, got ${height}`);
1483
1243
  }
1484
- const [block, parentBlock, transactions, tokenTransfers, delegations, stakings] = await Promise.all([
1244
+ const [block, parentBlock, transactions, tokenTransfers, delegations] = await Promise.all([
1485
1245
  tzkt.getBlockByLevel(height),
1486
1246
  tzkt.getBlockByLevel(height - 1),
1487
1247
  fetchBlockTransactions(height),
1488
1248
  fetchBlockTokenTransfers(height),
1489
- fetchBlockDelegations(height),
1490
- fetchBlockStaking(height)
1249
+ fetchBlockDelegations(height)
1491
1250
  ]);
1492
1251
  return {
1493
1252
  info: mapBlockInfo(block, parentBlock),
1494
- transactions: groupAndMapTransactions(transactions, tokenTransfers, delegations, stakings)
1253
+ transactions: groupAndMapTransactions(transactions, tokenTransfers, delegations)
1495
1254
  };
1496
1255
  } //# sourceMappingURL=getBlock.js.map
1497
1256
 
@@ -1550,203 +1309,26 @@ function isAPIStakingType(op) {
1550
1309
 
1551
1310
 
1552
1311
 
1553
-
1554
- function parseCursor(token) {
1555
- if (!token) return undefined;
1312
+ /** Cursor: native + token transfer last ids. Legacy: JSON number = native only. */ function parseCursor(token) {
1313
+ if (!token) return {};
1556
1314
  try {
1557
1315
  const parsed = JSON.parse(token);
1558
- if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
1559
- const o = parsed;
1560
- if (typeof o.lastLevel === "number" && Number.isFinite(o.lastLevel)) {
1561
- const cursor = {
1562
- lastLevel: o.lastLevel
1563
- };
1564
- if (typeof o.nativeLastId === "number" && Number.isFinite(o.nativeLastId)) {
1565
- cursor.nativeLastId = o.nativeLastId;
1566
- }
1567
- if (typeof o.tokenLastId === "number" && Number.isFinite(o.tokenLastId)) {
1568
- cursor.tokenLastId = o.tokenLastId;
1569
- }
1570
- return cursor;
1571
- }
1572
- }
1573
- } catch {
1574
- // ignore invalid cursor
1575
- }
1576
- return undefined;
1577
- }
1578
- function minLevel(items) {
1579
- if (items.length === 0) return undefined;
1580
- return Math.min(...items.map((i)=>i.level));
1581
- }
1582
- function maxLevel(items) {
1583
- if (items.length === 0) return undefined;
1584
- return Math.max(...items.map((i)=>i.level));
1585
- }
1586
- /** When the API returned a full page, the trailing block level may be incomplete — drop it. */ function trimPartialLastLevel(items, full) {
1587
- if (!full || items.length === 0) return {
1588
- trimmed: items
1589
- };
1590
- const last = items.at(-1);
1591
- if (!last) return {
1592
- trimmed: items
1593
- };
1594
- const lastLevel = last.level;
1595
- const filtered = items.filter((op)=>op.level !== lastLevel);
1596
- if (filtered.length === 0) {
1597
- (0,logs_lib_es/* .log */.Rm)("coin:tezos", "listOperations: full page single level — keeping all rows", {
1598
- lastLevel,
1599
- count: items.length
1600
- });
1601
- return {
1602
- trimmed: items,
1603
- intraLevelLastId: last.id
1604
- };
1605
- }
1606
- return {
1607
- trimmed: filtered
1608
- };
1609
- }
1610
- function buildNativeOptions(sort, cursor, minHeight) {
1611
- if (!cursor) {
1612
- return {
1613
- sort,
1614
- "level.ge": minHeight
1615
- };
1616
- }
1617
- const { lastLevel, nativeLastId } = cursor;
1618
- if (sort === "Descending") {
1619
- if (nativeLastId !== undefined) {
1620
- return {
1621
- sort,
1622
- "level.ge": minHeight,
1623
- "level.lt": lastLevel + 1,
1624
- lastId: nativeLastId
1625
- };
1626
- }
1627
- return {
1628
- sort,
1629
- "level.ge": minHeight,
1630
- "level.lt": lastLevel
1631
- };
1632
- }
1633
- if (nativeLastId !== undefined) {
1634
- return {
1635
- sort,
1636
- "level.ge": Math.max(minHeight, lastLevel),
1637
- lastId: nativeLastId
1316
+ if (typeof parsed === "number") return {
1317
+ nativeLastId: parsed
1638
1318
  };
1639
- }
1640
- return {
1641
- sort,
1642
- "level.ge": Math.max(minHeight, lastLevel + 1)
1643
- };
1644
- }
1645
- function buildTokenOptions(sort, cursor, minHeight) {
1646
- if (!cursor) {
1647
- return {
1648
- sort,
1649
- "level.ge": minHeight
1650
- };
1651
- }
1652
- const { lastLevel, tokenLastId } = cursor;
1653
- if (sort === "Descending") {
1654
- if (tokenLastId !== undefined) {
1319
+ if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
1320
+ const output = parsed;
1321
+ const nativeLastId = typeof output.nativeLastId === "number" ? output.nativeLastId : undefined;
1322
+ const tokenLastId = typeof output.tokenLastId === "number" ? output.tokenLastId : undefined;
1655
1323
  return {
1656
- sort,
1657
- "level.ge": minHeight,
1658
- "level.lt": lastLevel + 1,
1659
- "id.lt": tokenLastId
1324
+ nativeLastId,
1325
+ tokenLastId
1660
1326
  };
1661
1327
  }
1662
- return {
1663
- sort,
1664
- "level.ge": minHeight,
1665
- "level.lt": lastLevel
1666
- };
1667
- }
1668
- if (tokenLastId !== undefined) {
1669
- return {
1670
- sort,
1671
- "level.ge": Math.max(minHeight, lastLevel),
1672
- "id.gt": tokenLastId
1673
- };
1674
- }
1675
- return {
1676
- sort,
1677
- "level.ge": Math.max(minHeight, lastLevel + 1)
1678
- };
1679
- }
1680
- function computeBoundary(nativeTrim, tokenTrim, sort) {
1681
- if (sort === "Descending") {
1682
- const mn = minLevel(nativeTrim);
1683
- const mt = minLevel(tokenTrim);
1684
- if (mn === undefined && mt === undefined) return undefined;
1685
- if (mn === undefined) return mt;
1686
- if (mt === undefined) return mn;
1687
- return Math.max(mn, mt);
1688
- }
1689
- const xn = maxLevel(nativeTrim);
1690
- const xt = maxLevel(tokenTrim);
1691
- if (xn === undefined && xt === undefined) return undefined;
1692
- if (xn === undefined) return xt;
1693
- if (xt === undefined) return xn;
1694
- return Math.min(xn, xt);
1695
- }
1696
- function alignToBoundary(items, boundary, sort) {
1697
- if (sort === "Descending") {
1698
- return items.filter((op)=>op.level >= boundary);
1699
- }
1700
- return items.filter((op)=>op.level <= boundary);
1701
- }
1702
- function clampPage(raw, limit) {
1703
- if (limit === undefined) {
1704
- return {
1705
- sliced: raw,
1706
- full: false
1707
- };
1708
- }
1709
- return {
1710
- sliced: raw.slice(0, limit),
1711
- full: raw.length >= limit
1712
- };
1713
- }
1714
- function buildParentMap(ops) {
1715
- const parentMap = new Map();
1716
- for (const op of ops){
1717
- if (isAPITransactionType(op) && op.id !== null) {
1718
- parentMap.set(op.id, op);
1719
- }
1720
- }
1721
- return parentMap;
1722
- }
1723
- function keepNativeOp(op, address) {
1724
- if (!(isAPITransactionType(op) || isAPIDelegationType(op) || isAPIRevealType(op) || isAPIStakingType(op))) {
1725
- return false;
1726
- }
1727
- if (op.status !== "applied" && isAPITransactionType(op)) {
1728
- const isIn = op.target?.address === address;
1729
- if (isIn) {
1730
- return false;
1731
- }
1328
+ } catch {
1329
+ // ignore invalid cursor
1732
1330
  }
1733
- return true;
1734
- }
1735
- function convertNativeOps(ops, address, stakingBlockHashes) {
1736
- return ops.filter((op)=>keepNativeOp(op, address)).map((op)=>convertOperation(address, op, stakingBlockHashes));
1737
- }
1738
- function convertTokenOps(transfers, parentMap, address) {
1739
- return transfers.map((transfer)=>convertTokenOperation(address, transfer, transfer.transactionId ? parentMap.get(transfer.transactionId) : undefined));
1740
- }
1741
- function computeNextToken(boundary, nativeFull, tokenFull, hasResults, nativeIntraLastId, tokenIntraLastId) {
1742
- const shouldEmitNext = boundary !== undefined && (nativeFull || tokenFull) && hasResults;
1743
- if (!shouldEmitNext) return "";
1744
- const payload = {
1745
- lastLevel: boundary
1746
- };
1747
- if (nativeIntraLastId !== undefined) payload.nativeLastId = nativeIntraLastId;
1748
- if (tokenIntraLastId !== undefined) payload.tokenLastId = tokenIntraLastId;
1749
- return JSON.stringify(payload);
1331
+ return {};
1750
1332
  }
1751
1333
  /**
1752
1334
  * Returns list of "Transfer", "Delegate" and "Undelegate" Operations associated to an account.
@@ -1760,31 +1342,53 @@ function computeNextToken(boundary, nativeFull, tokenFull, hasResults, nativeInt
1760
1342
  * @param token a token to be used for pagination
1761
1343
  * @returns a list of operations is descending (newest first) order and a token to be used for pagination
1762
1344
  */ async function listOperations(address, { token, limit, sort, minHeight }) {
1763
- const cursor = parseCursor(token);
1345
+ const { nativeLastId, tokenLastId } = parseCursor(token);
1764
1346
  const nativeOptions = {
1765
1347
  limit,
1766
- ...buildNativeOptions(sort, cursor, minHeight)
1348
+ sort,
1349
+ "level.ge": minHeight,
1350
+ ...nativeLastId ? {
1351
+ lastId: nativeLastId
1352
+ } : {}
1767
1353
  };
1768
1354
  const tokenOptions = {
1769
1355
  limit,
1770
- ...buildTokenOptions(sort, cursor, minHeight)
1356
+ sort,
1357
+ "level.ge": minHeight,
1358
+ ...tokenLastId ? {
1359
+ lastId: tokenLastId
1360
+ } : {}
1771
1361
  };
1772
- const [nativeOpsRaw, tokenTransfersRaw] = await Promise.all([
1362
+ const [nativeOps, tokenTransfers] = await Promise.all([
1773
1363
  tzkt.getAccountOperations(address, nativeOptions),
1774
1364
  tzkt.getAccountTokenTransfers(address, tokenOptions)
1775
1365
  ]);
1776
- const nativePage = clampPage(nativeOpsRaw, limit);
1777
- const tokenPage = clampPage(tokenTransfersRaw, limit);
1778
- const nativeTrimmed = trimPartialLastLevel(nativePage.sliced, nativePage.full);
1779
- const tokenTrimmed = trimPartialLastLevel(tokenPage.sliced, tokenPage.full);
1780
- const boundary = computeBoundary(nativeTrimmed.trimmed, tokenTrimmed.trimmed, sort);
1781
- const nativeAligned = boundary === undefined ? nativeTrimmed.trimmed : alignToBoundary(nativeTrimmed.trimmed, boundary, sort);
1782
- const tokenAligned = boundary === undefined ? tokenTrimmed.trimmed : alignToBoundary(tokenTrimmed.trimmed, boundary, sort);
1783
- const stakingBlockHashes = await fetchMissingStakingBlockHashes(nativeAligned);
1784
- const parentMap = buildParentMap(nativeAligned);
1785
- const nextToken = computeNextToken(boundary, nativePage.full, tokenPage.full, nativeAligned.length > 0 || tokenAligned.length > 0, nativeTrimmed.intraLevelLastId, tokenTrimmed.intraLevelLastId);
1786
- const filteredNativeOps = convertNativeOps(nativeAligned, address, stakingBlockHashes);
1787
- const tokenConverted = convertTokenOps(tokenAligned, parentMap, address);
1366
+ // Apply limit after fetching since tzkt API might not respect the limit parameter
1367
+ const limitedNativeOps = limit ? nativeOps.slice(0, limit) : nativeOps;
1368
+ const limitedTokenTransfers = limit ? tokenTransfers.slice(0, limit) : tokenTransfers;
1369
+ const parentMap = new Map();
1370
+ for (const op of nativeOps){
1371
+ if (isAPITransactionType(op) && op.id !== null) {
1372
+ parentMap.set(op.id, op);
1373
+ }
1374
+ }
1375
+ const lastNativeOp = limitedNativeOps.at(-1);
1376
+ const lastTokenOp = limitedTokenTransfers.at(-1);
1377
+ const nextToken = lastNativeOp || lastTokenOp ? JSON.stringify({
1378
+ nativeLastId: lastNativeOp?.id,
1379
+ tokenLastId: lastTokenOp?.id
1380
+ }) : "";
1381
+ const filteredNativeOps = limitedNativeOps.filter((op)=>isAPITransactionType(op) || isAPIDelegationType(op) || isAPIRevealType(op)).filter((op)=>{
1382
+ const hasFailed = op.status !== "applied";
1383
+ if (hasFailed && isAPITransactionType(op)) {
1384
+ const isIn = op.target?.address === address;
1385
+ if (isIn) {
1386
+ return false;
1387
+ }
1388
+ }
1389
+ return true;
1390
+ }).map((op)=>convertOperation(address, op)).flat();
1391
+ const tokenConverted = limitedTokenTransfers.map((transfer)=>convertTokenOperation(address, transfer, transfer.transactionId ? parentMap.get(transfer.transactionId) : undefined));
1788
1392
  const sortedOperations = [
1789
1393
  ...filteredNativeOps,
1790
1394
  ...tokenConverted
@@ -1795,110 +1399,63 @@ function computeNextToken(boundary, nativeFull, tokenFull, hasResults, nativeInt
1795
1399
  ];
1796
1400
  }
1797
1401
  /**
1798
- * TzKT omits `block` on staking ops returned by /accounts/{addr}/operations.
1799
- * Returns a level → block-hash map covering exactly those ops, so the caller
1800
- * can populate `tx.block.hash` without mutating the API response. Network
1801
- * failures are swallowed: callers fall back to `""` for levels not in the map.
1802
- */ async function fetchMissingStakingBlockHashes(ops) {
1803
- const missingLevels = new Set();
1804
- for (const op of ops){
1805
- if (isAPIStakingType(op) && !op.block) missingLevels.add(op.level);
1806
- }
1807
- if (missingLevels.size === 0) return new Map();
1808
- try {
1809
- return await tzkt.getBlockHashesByLevels([
1810
- ...missingLevels
1811
- ]);
1812
- } catch (err) {
1813
- (0,logs_lib_es/* .log */.Rm)("coin:tezos", "fetchMissingStakingBlockHashes: skipped on fetch error", {
1814
- reason: String(err)
1815
- });
1816
- return new Map();
1817
- }
1818
- }
1819
- function resolveBlockHash(operation, stakingBlockHashes) {
1820
- const fromOp = typeof operation.block === "string" ? operation.block : operation.block?.hash;
1821
- return fromOp ?? stakingBlockHashes.get(operation.level) ?? "";
1822
- }
1823
- function resolveTargetAddress(operation) {
1824
- if (isAPITransactionType(operation)) return operation.target?.address;
1825
- if (isAPIDelegationType(operation)) {
1826
- return operation.newDelegate?.address || operation.prevDelegate?.address;
1827
- }
1828
- if (isAPIStakingType(operation)) return operation.baker?.address;
1829
- return undefined;
1830
- }
1831
- // finalize_unstake's protocol sender is the gas payer (anyone may call it),
1832
- // not the staker; map staking ops from the staker's perspective so the op
1833
- // stays visible in their wallet.
1834
- function resolveStakingAddresses(op) {
1835
- const stakerAddr = op.staker?.address ?? op.sender?.address;
1836
- const bakerAddr = op.baker?.address;
1837
- const stakerArr = stakerAddr ? [
1838
- stakerAddr
1839
- ] : [];
1840
- const bakerArr = bakerAddr ? [
1841
- bakerAddr
1842
- ] : [];
1843
- if (op.action === "finalize") return {
1844
- senders: bakerArr,
1845
- recipients: stakerArr
1846
- };
1847
- return {
1848
- senders: stakerArr,
1849
- recipients: bakerArr
1850
- };
1851
- }
1852
- function resolveNormalizedType(operation, address, targetAddress, amount) {
1853
- if (isAPIDelegationType(operation)) {
1854
- return operation.newDelegate?.address ? "DELEGATE" : "UNDELEGATE";
1855
- }
1856
- if (isAPIStakingType(operation)) return STAKING_ACTION_TO_OP_TYPE[operation.action];
1857
- if (isAPIRevealType(operation)) return "REVEAL";
1858
- if (!isAPITransactionType(operation)) {
1859
- (0,logs_lib_es/* .log */.Rm)("coin:tezos", "(logic/operations): Unknown operation type, defaulting to OUT");
1860
- return "OUT";
1861
- }
1862
- const isOut = operation.sender?.address === address;
1863
- const isIn = targetAddress === address;
1864
- if (isOut && isIn || amount === 0n) return "FEES";
1865
- if (isOut) return "OUT";
1866
- if (isIn) return "IN";
1867
- return "OUT";
1868
- }
1869
- function getLedgerOpType(operation, normalizedType) {
1402
+ * Helper function to get the ledgerOpType for an operation
1403
+ */ function getLedgerOpType(operation, normalizedType) {
1870
1404
  if (isAPIDelegationType(operation)) {
1871
1405
  return operation.newDelegate?.address ? "DELEGATE" : "UNDELEGATE";
1872
1406
  } else if (isAPIRevealType(operation)) {
1873
1407
  return "REVEAL";
1874
- } else if (isAPIStakingType(operation)) {
1875
- return STAKING_ACTION_TO_OP_TYPE[operation.action];
1876
1408
  } else if (normalizedType === "FEES") {
1877
1409
  return "FEES";
1878
1410
  }
1879
1411
  return undefined;
1880
1412
  }
1881
- function convertOperation(address, operation, stakingBlockHashes) {
1413
+ function convertOperation(address, operation) {
1882
1414
  const { hash, sender, id } = operation;
1883
1415
  // For transactions, the initiator (if present) is the fee payer (internal/sub-operations triggered by contracts).
1884
- // Otherwise, the sender is the fee payer. For delegation/reveal/staking there is no initiator; sender is the fee payer.
1416
+ // Otherwise, the sender is the fee payer. For delegation/reveal there is no initiator; sender is the fee payer.
1885
1417
  const feesPayer = isAPITransactionType(operation) ? operation.initiator?.address ?? sender?.address : sender?.address;
1886
- const targetAddress = resolveTargetAddress(operation);
1887
- // reveal has no target by design; staking resolves senders/recipients separately.
1888
- if (!targetAddress && !isAPIRevealType(operation) && !isAPIStakingType(operation)) {
1418
+ let targetAddress = undefined;
1419
+ if (isAPITransactionType(operation)) {
1420
+ targetAddress = operation?.target?.address;
1421
+ } else if (isAPIDelegationType(operation)) {
1422
+ // delegate and undelegate has the type, but hold the address in different fields
1423
+ targetAddress = operation?.newDelegate?.address || operation?.prevDelegate?.address;
1424
+ }
1425
+ const recipients = targetAddress ? [
1426
+ targetAddress
1427
+ ] : [];
1428
+ if (!targetAddress) {
1889
1429
  (0,logs_lib_es/* .log */.Rm)("coin:tezos", "(logic/operations): No target address found for operation", operation);
1890
1430
  }
1891
- const { senders, recipients } = isAPIStakingType(operation) ? resolveStakingAddresses(operation) : {
1892
- senders: sender?.address ? [
1893
- sender.address
1894
- ] : [],
1895
- recipients: targetAddress ? [
1896
- targetAddress
1897
- ] : []
1898
- };
1431
+ const senders = sender?.address ? [
1432
+ sender.address
1433
+ ] : [];
1899
1434
  const amount = isAPIRevealType(operation) || isAPIDelegationType(operation) ? 0n : BigInt(operation.amount);
1900
1435
  const fee = BigInt(operation.storageFee ?? 0) + BigInt(operation.bakerFee ?? 0) + BigInt(operation.allocationFee ?? 0);
1901
- const normalizedType = resolveNormalizedType(operation, address, targetAddress, amount);
1436
+ // Determine operation type inline
1437
+ let normalizedType;
1438
+ if (isAPIDelegationType(operation)) {
1439
+ normalizedType = operation.newDelegate?.address ? "DELEGATE" : "UNDELEGATE";
1440
+ } else if (isAPITransactionType(operation)) {
1441
+ const isOut = sender?.address === address;
1442
+ const isIn = targetAddress === address;
1443
+ if (isOut && isIn || amount === 0n) {
1444
+ normalizedType = "FEES";
1445
+ } else if (isOut) {
1446
+ normalizedType = "OUT";
1447
+ } else if (isIn) {
1448
+ normalizedType = "IN";
1449
+ } else {
1450
+ normalizedType = "OUT"; // fallback
1451
+ }
1452
+ } else if (isAPIRevealType(operation)) {
1453
+ normalizedType = "REVEAL";
1454
+ } else {
1455
+ // fallback for unknown types
1456
+ (0,logs_lib_es/* .log */.Rm)("coin:tezos", "(logic/operations): Unknown operation type, defaulting to OUT");
1457
+ normalizedType = "OUT";
1458
+ }
1902
1459
  // Tezos uses "applied" for every success operation (something else=failed )
1903
1460
  const hasFailed = operation.status && operation.status !== "applied";
1904
1461
  return {
@@ -1915,7 +1472,7 @@ function convertOperation(address, operation, stakingBlockHashes) {
1915
1472
  feesPayer
1916
1473
  } : {},
1917
1474
  block: {
1918
- hash: resolveBlockHash(operation, stakingBlockHashes),
1475
+ hash: operation.block,
1919
1476
  height: operation.level,
1920
1477
  time: new Date(operation.timestamp)
1921
1478
  },
@@ -1973,7 +1530,7 @@ function convertTokenOperation(address, transfer, parent) {
1973
1530
  feesPayer
1974
1531
  } : {},
1975
1532
  block: {
1976
- hash: transfer.block ?? parent?.block ?? "",
1533
+ hash: parent?.block ?? "",
1977
1534
  height: transfer.level,
1978
1535
  time: new Date(transfer.timestamp)
1979
1536
  },
@@ -2006,25 +1563,6 @@ function convertTokenOperation(address, transfer, parent) {
2006
1563
 
2007
1564
 
2008
1565
 
2009
- function resolveValidationOperationMode(intent) {
2010
- switch(intent.type){
2011
- case "stake":
2012
- case "unstake":
2013
- case "finalize_unstake":
2014
- return intent.type;
2015
- default:
2016
- return resolveTezosOperationMode(intent.type, intent.asset);
2017
- }
2018
- }
2019
- function validateStrictlyPositiveAmount(amount) {
2020
- if (amount === 0n) {
2021
- return new lib_es/* .AmountRequired */.qA();
2022
- }
2023
- if (amount < 0n) {
2024
- return new lib_es/* .NotEnoughBalance */.cC();
2025
- }
2026
- return undefined;
2027
- }
2028
1566
  /**
2029
1567
  * Validates basic recipient and amount for send transactions
2030
1568
  */ function validateBasicSendParams(intent) {
@@ -2053,38 +1591,14 @@ function validateStrictlyPositiveAmount(amount) {
2053
1591
  */ function validateTransactionConstraints(intent, senderInfo) {
2054
1592
  const errors = {};
2055
1593
  // send max not allowed on delegated accounts (must undelegate acc first); native XTZ only
2056
- if (intent.type === "send" && intent.useAllAmount && resolveValidationOperationMode(intent) === "send" && senderInfo.delegate?.address) {
1594
+ if (intent.type === "send" && intent.useAllAmount && resolveTezosOperationMode(intent.type, intent.asset) === "send" && senderInfo.delegate?.address) {
2057
1595
  errors.amount = new lib_es/* .RecommendUndelegation */.Ql();
2058
1596
  }
1597
+ // stake requires non-zero balance
2059
1598
  if (intent.type === "stake") {
2060
- if (!senderInfo.delegate?.address) {
2061
- errors.amount = new types_errors/* .MustDelegateBeforeStaking */.$V();
2062
- return errors;
2063
- }
2064
- const amountError = validateStrictlyPositiveAmount(intent.amount);
2065
- if (amountError) {
2066
- errors.amount = amountError;
2067
- }
2068
- }
2069
- if (intent.type === "unstake") {
2070
- const stakedBalance = BigInt(senderInfo.stakedBalance ?? 0);
2071
- if (stakedBalance <= 0n) {
2072
- errors.amount = new lib_es/* .NotEnoughBalance */.cC();
2073
- return errors;
2074
- }
2075
- const amountError = validateStrictlyPositiveAmount(intent.amount);
2076
- if (amountError) {
2077
- errors.amount = amountError;
2078
- return errors;
2079
- }
2080
- if (intent.amount > stakedBalance) {
2081
- errors.amount = new lib_es/* .NotEnoughBalance */.cC();
2082
- }
2083
- }
2084
- if (intent.type === "finalize_unstake") {
2085
- const unstakedFinalizable = BigInt(senderInfo.unstakedFinalizable ?? 0);
2086
- if (unstakedFinalizable <= 0n) {
2087
- errors.amount = new lib_es/* .NotEnoughBalance */.cC();
1599
+ const balance = BigInt(senderInfo.balance || "0");
1600
+ if (balance === 0n) {
1601
+ errors.amount = new lib_es/* .NotEnoughBalanceToDelegate */.s$();
2088
1602
  }
2089
1603
  }
2090
1604
  return errors;
@@ -2099,12 +1613,8 @@ function validateStrictlyPositiveAmount(amount) {
2099
1613
  } else {
2100
1614
  errors.amount = new lib_es/* .NotEnoughBalance */.cC();
2101
1615
  }
2102
- } else if (taquitoError.endsWith("staking.too_much_unstaked")) {
2103
- errors.amount = new lib_es/* .NotEnoughBalance */.cC();
2104
- } else if (taquitoError.endsWith("contract.must_be_delegated_to_stake")) {
2105
- errors.amount = new types_errors/* .MustDelegateBeforeStaking */.$V();
2106
1616
  } else if (taquitoError.endsWith("delegate.unchanged") && intentType === "stake") {
2107
- errors.recipient = new types_errors/* .InvalidAddressBecauseAlreadyDelegated */.f1();
1617
+ errors.recipient = new types_errors/* .InvalidAddressBecauseAlreadyDelegated */.f();
2108
1618
  } else if (taquitoError.includes("empty_implicit_contract")) {
2109
1619
  errors.amount = new lib_es/* .NotEnoughBalanceToDelegate */.s$();
2110
1620
  } else if (taquitoError.includes("script_rejected")) {
@@ -2127,19 +1637,7 @@ function calculateNativeSendMaxAmountForUser(balance, estimatedFees, estimatedAm
2127
1637
  * Calculates final amounts based on transaction type
2128
1638
  * @param tokenBalanceForSendMax When set, FA2 send-max: full token amount; fees are paid in XTZ only
2129
1639
  */ function calculateAmounts(intent, senderInfo, estimatedFees, estimatedAmount, tokenBalanceForSendMax) {
2130
- if (intent.type === "stake") {
2131
- return {
2132
- amount: intent.amount,
2133
- totalSpent: intent.amount + estimatedFees
2134
- };
2135
- }
2136
- if (intent.type === "unstake") {
2137
- return {
2138
- amount: intent.amount,
2139
- totalSpent: estimatedFees
2140
- };
2141
- }
2142
- if (intent.type === "finalize_unstake") {
1640
+ if (intent.type === "stake" || intent.type === "unstake") {
2143
1641
  return {
2144
1642
  amount: 0n,
2145
1643
  totalSpent: estimatedFees
@@ -2178,7 +1676,7 @@ async function estimateFeesForIntent(intent, senderInfo) {
2178
1676
  errors: {}
2179
1677
  };
2180
1678
  }
2181
- const tezosMode = resolveValidationOperationMode(intent);
1679
+ const tezosMode = resolveTezosOperationMode(intent.type, intent.asset);
2182
1680
  const tokenInfo = tezosMode === "send_token" ? parseTezosTokenAsset(intent.asset) : undefined;
2183
1681
  const estimation = await estimateFees({
2184
1682
  account: {
@@ -2190,9 +1688,7 @@ async function estimateFeesForIntent(intent, senderInfo) {
2190
1688
  transaction: {
2191
1689
  mode: tezosMode,
2192
1690
  recipient: intent.recipient,
2193
- // finalize_unstake is a parameter-less operation; normalize amount to 0n so
2194
- // fee estimation and the returned validation amount stay consistent.
2195
- amount: intent.type === "finalize_unstake" ? 0n : intent.amount,
1691
+ amount: intent.amount,
2196
1692
  useAllAmount: !!intent.useAllAmount,
2197
1693
  ...tokenInfo && {
2198
1694
  contractAddress: tokenInfo.contractAddress,
@@ -2286,6 +1782,30 @@ async function validateIntent(intent) {
2286
1782
  };
2287
1783
  } //# sourceMappingURL=validateIntent.js.map
2288
1784
 
1785
+ ;// CONCATENATED MODULE: ../../libs/coin-modules/coin-tezos/lib-es/logic/getStakes.js
1786
+
1787
+ async function getStakes(address, _cursor) {
1788
+ // tezos exposes a single staking position via delegation when a delegate is set
1789
+ const accountInfo = await tzkt.getAccountByAddress(address);
1790
+ if (accountInfo.type !== "user" || !accountInfo.delegate?.address) return {
1791
+ items: []
1792
+ };
1793
+ return {
1794
+ items: [
1795
+ {
1796
+ uid: address,
1797
+ address,
1798
+ delegate: accountInfo.delegate.address,
1799
+ state: "active",
1800
+ asset: {
1801
+ type: "native"
1802
+ },
1803
+ amount: BigInt(accountInfo.balance ?? 0)
1804
+ }
1805
+ ]
1806
+ };
1807
+ } //# sourceMappingURL=getStakes.js.map
1808
+
2289
1809
  ;// CONCATENATED MODULE: ../../libs/coin-modules/coin-tezos/lib-es/logic/index.js
2290
1810
 
2291
1811
 
@@ -2327,18 +1847,6 @@ function createApi(config) {
2327
1847
  }
2328
1848
  }));
2329
1849
  return {
2330
- computeIntentType: (transaction)=>{
2331
- switch(transaction.mode){
2332
- case "delegate":
2333
- case "undelegate":
2334
- case "stake":
2335
- case "unstake":
2336
- case "finalize_unstake":
2337
- return transaction.mode;
2338
- default:
2339
- return "send";
2340
- }
2341
- },
2342
1850
  broadcast: broadcast,
2343
1851
  combine: combine,
2344
1852
  craftTransaction: craft,
@@ -2373,8 +1881,7 @@ function isTezosTransactionType(type) {
2373
1881
  "delegate",
2374
1882
  "undelegate",
2375
1883
  "stake",
2376
- "unstake",
2377
- "finalize_unstake"
1884
+ "unstake"
2378
1885
  ].includes(type);
2379
1886
  }
2380
1887
  async function craft(transactionIntent, customFees) {
@@ -2389,10 +1896,10 @@ async function craft(transactionIntent, customFees) {
2389
1896
  storageLimit: estimation.parameters?.storageLimit?.toString()
2390
1897
  };
2391
1898
  const tezosMode = resolveTezosOperationMode(transactionIntent.type, transactionIntent.asset);
2392
- const mappedType = tezosMode === "send_token" ? "send_token" : transactionIntent.type;
1899
+ const mappedType = tezosMode === "send_token" ? "send_token" : mapIntentTypeToTezosMode(transactionIntent.type);
2393
1900
  const tokenCraftInfo = tezosMode === "send_token" ? parseTezosTokenAsset(transactionIntent.asset) : undefined;
2394
1901
  // Guard: send max is incompatible with delegated accounts (native XTZ only)
2395
- let amountToUse = tezosMode === "finalize_unstake" ? 0n : transactionIntent.amount;
1902
+ let amountToUse = transactionIntent.amount;
2396
1903
  if (tezosMode === "send" && transactionIntent.useAllAmount) {
2397
1904
  const senderInfo = await tzkt.getAccountByAddress(transactionIntent.sender);
2398
1905
  if (senderInfo.type === "user" && senderInfo.delegate?.address) {
@@ -2512,7 +2019,7 @@ async function api_estimate(transactionIntent) {
2512
2019
  const transaction = {
2513
2020
  mode: tezosModeForEstimate,
2514
2021
  recipient: transactionIntent.recipient,
2515
- amount: tezosModeForEstimate === "finalize_unstake" ? 0n : transactionIntent.amount,
2022
+ amount: transactionIntent.amount,
2516
2023
  useAllAmount: !!transactionIntent.useAllAmount,
2517
2024
  ...tokenEstimationInfo && {
2518
2025
  contractAddress: tokenEstimationInfo.contractAddress,