@ledgerhq/coin-sui 0.15.0 → 0.16.0-nightly.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.
Files changed (102) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/CHANGELOG.md +22 -0
  3. package/lib/api/index.d.ts.map +1 -1
  4. package/lib/api/index.integration.test.js +1 -0
  5. package/lib/api/index.integration.test.js.map +1 -1
  6. package/lib/api/index.js +10 -2
  7. package/lib/api/index.js.map +1 -1
  8. package/lib/api/index.test.js +1 -1
  9. package/lib/api/index.test.js.map +1 -1
  10. package/lib/bridge/buildTransaction.d.ts.map +1 -1
  11. package/lib/bridge/buildTransaction.js +1 -0
  12. package/lib/bridge/buildTransaction.js.map +1 -1
  13. package/lib/bridge/buildTransaction.test.js +2 -0
  14. package/lib/bridge/buildTransaction.test.js.map +1 -1
  15. package/lib/bridge/getFeesForTransaction.d.ts.map +1 -1
  16. package/lib/bridge/getFeesForTransaction.js +4 -0
  17. package/lib/bridge/getFeesForTransaction.js.map +1 -1
  18. package/lib/bridge/index.d.ts.map +1 -1
  19. package/lib/bridge/index.js +3 -0
  20. package/lib/bridge/index.js.map +1 -1
  21. package/lib/logic/craftTransaction.d.ts +1 -1
  22. package/lib/logic/craftTransaction.d.ts.map +1 -1
  23. package/lib/logic/craftTransaction.integration.test.js +42 -0
  24. package/lib/logic/craftTransaction.integration.test.js.map +1 -1
  25. package/lib/logic/craftTransaction.js +3 -4
  26. package/lib/logic/craftTransaction.js.map +1 -1
  27. package/lib/logic/craftTransaction.test.js +19 -5
  28. package/lib/logic/craftTransaction.test.js.map +1 -1
  29. package/lib/logic/estimateFees.integration.test.js +4 -1
  30. package/lib/logic/estimateFees.integration.test.js.map +1 -1
  31. package/lib/logic/estimateFees.test.js +2 -0
  32. package/lib/logic/estimateFees.test.js.map +1 -1
  33. package/lib/network/index.d.ts +1 -1
  34. package/lib/network/sdk.d.ts +8 -4
  35. package/lib/network/sdk.d.ts.map +1 -1
  36. package/lib/network/sdk.integration.test.js +2 -2
  37. package/lib/network/sdk.integration.test.js.map +1 -1
  38. package/lib/network/sdk.js +78 -31
  39. package/lib/network/sdk.js.map +1 -1
  40. package/lib/network/sdk.test.js +148 -333
  41. package/lib/network/sdk.test.js.map +1 -1
  42. package/lib/types/model.d.ts +3 -0
  43. package/lib/types/model.d.ts.map +1 -1
  44. package/lib-es/api/index.d.ts.map +1 -1
  45. package/lib-es/api/index.integration.test.js +1 -0
  46. package/lib-es/api/index.integration.test.js.map +1 -1
  47. package/lib-es/api/index.js +10 -2
  48. package/lib-es/api/index.js.map +1 -1
  49. package/lib-es/api/index.test.js +1 -1
  50. package/lib-es/api/index.test.js.map +1 -1
  51. package/lib-es/bridge/buildTransaction.d.ts.map +1 -1
  52. package/lib-es/bridge/buildTransaction.js +1 -0
  53. package/lib-es/bridge/buildTransaction.js.map +1 -1
  54. package/lib-es/bridge/buildTransaction.test.js +2 -0
  55. package/lib-es/bridge/buildTransaction.test.js.map +1 -1
  56. package/lib-es/bridge/getFeesForTransaction.d.ts.map +1 -1
  57. package/lib-es/bridge/getFeesForTransaction.js +4 -0
  58. package/lib-es/bridge/getFeesForTransaction.js.map +1 -1
  59. package/lib-es/bridge/index.d.ts.map +1 -1
  60. package/lib-es/bridge/index.js +3 -0
  61. package/lib-es/bridge/index.js.map +1 -1
  62. package/lib-es/logic/craftTransaction.d.ts +1 -1
  63. package/lib-es/logic/craftTransaction.d.ts.map +1 -1
  64. package/lib-es/logic/craftTransaction.integration.test.js +42 -0
  65. package/lib-es/logic/craftTransaction.integration.test.js.map +1 -1
  66. package/lib-es/logic/craftTransaction.js +3 -4
  67. package/lib-es/logic/craftTransaction.js.map +1 -1
  68. package/lib-es/logic/craftTransaction.test.js +19 -5
  69. package/lib-es/logic/craftTransaction.test.js.map +1 -1
  70. package/lib-es/logic/estimateFees.integration.test.js +4 -1
  71. package/lib-es/logic/estimateFees.integration.test.js.map +1 -1
  72. package/lib-es/logic/estimateFees.test.js +2 -0
  73. package/lib-es/logic/estimateFees.test.js.map +1 -1
  74. package/lib-es/network/index.d.ts +1 -1
  75. package/lib-es/network/sdk.d.ts +8 -4
  76. package/lib-es/network/sdk.d.ts.map +1 -1
  77. package/lib-es/network/sdk.integration.test.js +2 -2
  78. package/lib-es/network/sdk.integration.test.js.map +1 -1
  79. package/lib-es/network/sdk.js +75 -29
  80. package/lib-es/network/sdk.js.map +1 -1
  81. package/lib-es/network/sdk.test.js +148 -333
  82. package/lib-es/network/sdk.test.js.map +1 -1
  83. package/lib-es/types/model.d.ts +3 -0
  84. package/lib-es/types/model.d.ts.map +1 -1
  85. package/package.json +7 -7
  86. package/src/api/index.integration.test.ts +1 -0
  87. package/src/api/index.test.ts +1 -1
  88. package/src/api/index.ts +15 -2
  89. package/src/bridge/buildTransaction.test.ts +2 -0
  90. package/src/bridge/buildTransaction.ts +1 -0
  91. package/src/bridge/getFeesForTransaction.ts +4 -0
  92. package/src/bridge/index.ts +3 -0
  93. package/src/logic/craftTransaction.integration.test.ts +52 -0
  94. package/src/logic/craftTransaction.test.ts +55 -25
  95. package/src/logic/craftTransaction.ts +25 -20
  96. package/src/logic/estimateFees.integration.test.ts +4 -1
  97. package/src/logic/estimateFees.test.ts +2 -0
  98. package/src/network/sdk.integration.test.ts +2 -2
  99. package/src/network/sdk.test.ts +210 -369
  100. package/src/network/sdk.ts +114 -36
  101. package/src/types/model.ts +4 -0
  102. package/index.d.ts +0 -0
@@ -34,13 +34,19 @@ import uniqBy from "lodash/unionBy";
34
34
  import { encodeOperationId } from "@ledgerhq/coin-framework/operation";
35
35
  import { log } from "@ledgerhq/logs";
36
36
  import { makeLRUCache, minutes } from "@ledgerhq/live-network/cache";
37
- import type { Transaction as TransactionType, SuiValidator, CreateExtrinsicArg } from "../types";
37
+ import type {
38
+ Transaction as TransactionType,
39
+ SuiValidator,
40
+ CreateExtrinsicArg,
41
+ CoreTransaction,
42
+ } from "../types";
38
43
  import { ensureAddressFormat } from "../utils";
39
44
  import coinConfig from "../config";
40
45
  import { getEnv } from "@ledgerhq/live-env";
41
46
  import { SUI_SYSTEM_STATE_OBJECT_ID } from "@mysten/sui/utils";
42
47
  import { getCurrentSuiPreloadData } from "../bridge/preload";
43
48
  import { ONE_SUI } from "../constants";
49
+ import { getInputObjects } from "@mysten/signers/ledger";
44
50
 
45
51
  const apiMap: Record<string, SuiClient> = {};
46
52
  type AsyncApiFunction<T> = (api: SuiClient) => Promise<T>;
@@ -102,32 +108,31 @@ export const getAllBalancesCached = makeLRUCache(
102
108
  (owner: string) => owner,
103
109
  minutes(1),
104
110
  );
105
- function isStaking(block?: SuiTransactionBlockKind): block is {
111
+
112
+ type ProgrammableTransaction = {
106
113
  inputs: SuiCallArg[];
107
114
  kind: "ProgrammableTransaction";
108
115
  transactions: SuiTransaction[];
109
- } {
110
- if (!block) return false;
111
- if (block.kind === "ProgrammableTransaction") {
116
+ };
117
+
118
+ function isMoveCallWithFunction(
119
+ functionName: string,
120
+ block?: SuiTransactionBlockKind,
121
+ ): block is ProgrammableTransaction {
122
+ if (block?.kind === "ProgrammableTransaction") {
112
123
  const move = block.transactions.find(item => "MoveCall" in item) as any;
113
- return move?.MoveCall.function === "request_add_stake";
124
+ return move?.MoveCall.function === functionName;
125
+ } else {
126
+ return false;
114
127
  }
115
- return false;
116
128
  }
117
129
 
118
- function isUnstaking(block?: SuiTransactionBlockKind): block is {
119
- inputs: SuiCallArg[];
120
- kind: "ProgrammableTransaction";
121
- transactions: SuiTransaction[];
122
- } {
123
- if (!block) return false;
124
- if (block.kind === "ProgrammableTransaction") {
125
- const move = block.transactions.find(
126
- item => "MoveCall" in item && item["MoveCall"].function === "request_withdraw_stake",
127
- ) as any;
128
- return Boolean(move);
129
- }
130
- return false;
130
+ function isStaking(block?: SuiTransactionBlockKind): block is ProgrammableTransaction {
131
+ return isMoveCallWithFunction("request_add_stake", block);
132
+ }
133
+
134
+ function isUnstaking(block?: SuiTransactionBlockKind): block is ProgrammableTransaction {
135
+ return isMoveCallWithFunction("request_withdraw_stake", block);
131
136
  }
132
137
 
133
138
  /**
@@ -336,11 +341,49 @@ export function transactionToOperation(
336
341
  };
337
342
  }
338
343
 
344
+ function absoluteAmount(balanceChange: BalanceChange | undefined): BigNumber {
345
+ return new BigNumber(balanceChange?.amount || 0).abs();
346
+ }
347
+
348
+ // This function is only used by alpaca code path
349
+ // Logic is similar to getOperationAmount, but we guarantee to return a positive amount in any case
350
+ // If there is need to display negative amount for staking or unstaking, the view can handle it based on the type of the operation
351
+ export const alpacaGetOperationAmount = (
352
+ address: string,
353
+ transaction: SuiTransactionBlockResponse,
354
+ coinType: string,
355
+ ): BigNumber => {
356
+ const zero = BigNumber(0);
357
+
358
+ const tx = transaction.transaction?.data.transaction;
359
+
360
+ if (isStaking(tx) || isUnstaking(tx)) return absoluteAmount(transaction.balanceChanges?.[0]);
361
+ else {
362
+ return (
363
+ transaction.balanceChanges
364
+ ?.filter(
365
+ balanceChange =>
366
+ typeof balanceChange.owner !== "string" &&
367
+ "AddressOwner" in balanceChange.owner &&
368
+ balanceChange.owner.AddressOwner === address &&
369
+ balanceChange.coinType === coinType,
370
+ )
371
+ .map(absoluteAmount)
372
+ .reduce((acc, curr) => acc.plus(curr), zero) || zero
373
+ );
374
+ }
375
+ };
376
+
339
377
  /**
378
+ * This function is only used by alpaca code path
379
+ *
340
380
  * @returns the operation converted. Note that if param `transaction` was retrieved as an "IN" operations, the type may be converted to "OUT".
341
381
  * It happens for most "OUT" operations because the sender receive a new version of the coin objects.
342
382
  */
343
- export function transactionToOp(address: string, transaction: SuiTransactionBlockResponse): Op {
383
+ export function alpacaTransactionToOp(
384
+ address: string,
385
+ transaction: SuiTransactionBlockResponse,
386
+ ): Op {
344
387
  const type = getOperationType(address, transaction);
345
388
  const coinType = getOperationCoinType(transaction);
346
389
  const hash = transaction.digest;
@@ -359,7 +402,7 @@ export function transactionToOp(address: string, transaction: SuiTransactionBloc
359
402
  recipients: getOperationRecipients(transaction.transaction?.data),
360
403
  senders: getOperationSenders(transaction.transaction?.data),
361
404
  type,
362
- value: BigInt(getOperationAmount(address, transaction, coinType).toString()),
405
+ value: BigInt(alpacaGetOperationAmount(address, transaction, coinType).toString()),
363
406
  };
364
407
  }
365
408
 
@@ -401,7 +444,8 @@ export function toBlockTransaction(transaction: SuiTransactionBlockResponse): Bl
401
444
  return {
402
445
  hash: transaction.digest,
403
446
  failed: transaction.effects?.status.status !== "success",
404
- operations: transaction.balanceChanges?.flatMap(toBlockOperation) || [],
447
+ operations:
448
+ transaction.balanceChanges?.flatMap(change => toBlockOperation(transaction, change)) || [],
405
449
  fees: BigInt(getOperationFee(transaction).toString()),
406
450
  feesPayer: transaction.transaction?.data.sender || "",
407
451
  };
@@ -412,16 +456,38 @@ export function toBlockTransaction(transaction: SuiTransactionBlockResponse): Bl
412
456
  *
413
457
  * @param change balance change
414
458
  */
415
- export function toBlockOperation(change: BalanceChange): BlockOperation[] {
459
+ export function toBlockOperation(
460
+ transaction: SuiTransactionBlockResponse,
461
+ change: BalanceChange,
462
+ ): BlockOperation[] {
416
463
  if (typeof change.owner === "string" || !("AddressOwner" in change.owner)) return [];
417
- return [
418
- {
419
- type: "transfer",
420
- address: change.owner.AddressOwner,
421
- asset: toSuiAsset(change.coinType),
422
- amount: BigInt(change.amount),
423
- },
424
- ];
464
+ const address = change.owner.AddressOwner;
465
+ const operationType = getOperationType(address, transaction);
466
+ switch (operationType) {
467
+ case "IN":
468
+ case "OUT":
469
+ return [
470
+ {
471
+ type: "transfer",
472
+ address: change.owner.AddressOwner,
473
+ asset: toSuiAsset(change.coinType),
474
+ amount: BigInt(change.amount),
475
+ },
476
+ ];
477
+ case "DELEGATE":
478
+ case "UNDELEGATE":
479
+ return [
480
+ {
481
+ type: "other",
482
+ operationType: operationType,
483
+ address: change.owner.AddressOwner,
484
+ asset: toSuiAsset(change.coinType),
485
+ amount: BigInt(absoluteAmount(change).toString()),
486
+ },
487
+ ];
488
+ default:
489
+ return [];
490
+ }
425
491
  }
426
492
 
427
493
  /**
@@ -570,7 +636,7 @@ export const getListOperations = async (
570
636
 
571
637
  const operations = ops.operations
572
638
  .sort((a, b) => Number(b.timestampMs) - Number(a.timestampMs))
573
- .map(t => transactionToOp(addr, t));
639
+ .map(t => alpacaTransactionToOp(addr, t));
574
640
 
575
641
  return {
576
642
  items: operations,
@@ -732,10 +798,15 @@ export const getCoinsForAmount = async (
732
798
  *
733
799
  * @param address - The sender's address
734
800
  * @param transaction - The transaction details including recipient, amount, and coin type
801
+ * @param withObjects - Return serialized input objects used in the transaction
735
802
  * @returns Promise<TransactionBlock> - A built transaction block ready for execution
736
803
  *
737
804
  */
738
- export const createTransaction = async (address: string, transaction: CreateExtrinsicArg) =>
805
+ export const createTransaction = async (
806
+ address: string,
807
+ transaction: CreateExtrinsicArg,
808
+ withObjects: boolean = false,
809
+ ): Promise<CoreTransaction> =>
739
810
  withApi(async api => {
740
811
  const tx = new Transaction();
741
812
  tx.setSender(ensureAddressFormat(address));
@@ -800,7 +871,14 @@ export const createTransaction = async (address: string, transaction: CreateExtr
800
871
  }
801
872
  }
802
873
 
803
- return tx.build({ client: api });
874
+ const serialized = await tx.build({ client: api });
875
+
876
+ if (withObjects) {
877
+ const { bcsObjects } = await getInputObjects(tx, api);
878
+ return { unsigned: serialized, objects: bcsObjects as Uint8Array[] };
879
+ }
880
+
881
+ return { unsigned: serialized };
804
882
  });
805
883
 
806
884
  /**
@@ -808,7 +886,7 @@ export const createTransaction = async (address: string, transaction: CreateExtr
808
886
  */
809
887
  export const paymentInfo = async (sender: string, fakeTransaction: TransactionType) =>
810
888
  withApi(async api => {
811
- const txb = await createTransaction(sender, fakeTransaction);
889
+ const { unsigned: txb } = await createTransaction(sender, fakeTransaction);
812
890
  const dryRunTxResponse = await api.dryRunTransactionBlock({ transactionBlock: txb });
813
891
  const fees = getTotalGasUsed(dryRunTxResponse.effects);
814
892
 
@@ -3,5 +3,9 @@ export type SuiOperationMode = "send";
3
3
  export type AccountInfoResponse = Record<string, string>;
4
4
 
5
5
  export type CoreTransaction = {
6
+ /** The transaction in a serialized format, ready to be signed. */
6
7
  unsigned: Uint8Array;
8
+
9
+ /** The input objects referenced in the transaction, in serialized form.. */
10
+ objects?: Uint8Array[];
7
11
  };
package/index.d.ts DELETED
File without changes