@ledgerhq/coin-sui 0.15.0-nightly.2 → 0.15.0-nightly.4
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/.turbo/turbo-build.log +1 -1
- package/CHANGELOG.md +16 -0
- package/lib/network/sdk.d.ts +4 -1
- package/lib/network/sdk.d.ts.map +1 -1
- package/lib/network/sdk.js +37 -18
- package/lib/network/sdk.js.map +1 -1
- package/lib/network/sdk.test.js +44 -43
- package/lib/network/sdk.test.js.map +1 -1
- package/lib-es/network/sdk.d.ts +4 -1
- package/lib-es/network/sdk.d.ts.map +1 -1
- package/lib-es/network/sdk.js +34 -16
- package/lib-es/network/sdk.js.map +1 -1
- package/lib-es/network/sdk.test.js +44 -43
- package/lib-es/network/sdk.test.js.map +1 -1
- package/package.json +4 -4
- package/src/network/sdk.test.ts +81 -71
- package/src/network/sdk.ts +58 -22
package/src/network/sdk.test.ts
CHANGED
|
@@ -185,7 +185,7 @@ const mockTransaction = {
|
|
|
185
185
|
],
|
|
186
186
|
timestampMs: "1742294454878",
|
|
187
187
|
checkpoint: "313024",
|
|
188
|
-
};
|
|
188
|
+
} as SuiTransactionBlockResponse;
|
|
189
189
|
|
|
190
190
|
const mockApi = new SuiClient({ url: "mock" }) as jest.Mocked<SuiClient>;
|
|
191
191
|
|
|
@@ -254,16 +254,12 @@ describe("SDK Functions", () => {
|
|
|
254
254
|
|
|
255
255
|
test("getOperationType should return IN for incoming tx", () => {
|
|
256
256
|
const address = "0x33444cf803c690db96527cec67e3c9ab512596f4ba2d4eace43f0b4f716e0164";
|
|
257
|
-
expect(sdk.getOperationType(address, mockTransaction
|
|
258
|
-
"IN",
|
|
259
|
-
);
|
|
257
|
+
expect(sdk.getOperationType(address, mockTransaction)).toBe("IN");
|
|
260
258
|
});
|
|
261
259
|
|
|
262
260
|
test("getOperationType should return OUT for outgoing tx", () => {
|
|
263
261
|
const address = "0x65449f57946938c84c512732f1d69405d1fce417d9c9894696ddf4522f479e24";
|
|
264
|
-
expect(sdk.getOperationType(address, mockTransaction
|
|
265
|
-
"OUT",
|
|
266
|
-
);
|
|
262
|
+
expect(sdk.getOperationType(address, mockTransaction)).toBe("OUT");
|
|
267
263
|
});
|
|
268
264
|
|
|
269
265
|
test("getOperationSenders should return sender address", () => {
|
|
@@ -278,36 +274,12 @@ describe("SDK Functions", () => {
|
|
|
278
274
|
).toEqual(["0x6e143fe0a8ca010a86580dafac44298e5b1b7d73efc345356a59a15f0d7824f0"]);
|
|
279
275
|
});
|
|
280
276
|
|
|
281
|
-
test("getOperationAmount should calculate amount correctly for SUI", () => {
|
|
282
|
-
const address = "0x6e143fe0a8ca010a86580dafac44298e5b1b7d73efc345356a59a15f0d7824f0";
|
|
283
|
-
expect(
|
|
284
|
-
sdk.getOperationAmount(
|
|
285
|
-
address,
|
|
286
|
-
mockTransaction as SuiTransactionBlockResponse,
|
|
287
|
-
sdk.DEFAULT_COIN_TYPE,
|
|
288
|
-
),
|
|
289
|
-
).toEqual(new BigNumber("9998990120"));
|
|
290
|
-
});
|
|
291
|
-
|
|
292
|
-
test("getOperationAmount should calculate amount correctly for tokens", () => {
|
|
293
|
-
const address = "0x6e143fe0a8ca010a86580dafac44298e5b1b7d73efc345356a59a15f0d7824f0";
|
|
294
|
-
expect(
|
|
295
|
-
sdk.getOperationAmount(
|
|
296
|
-
address,
|
|
297
|
-
mockTransaction as SuiTransactionBlockResponse,
|
|
298
|
-
"0x123::test::TOKEN",
|
|
299
|
-
),
|
|
300
|
-
).toEqual(new BigNumber("500000"));
|
|
301
|
-
});
|
|
302
|
-
|
|
303
277
|
test("getOperationFee should calculate fee correctly", () => {
|
|
304
|
-
expect(sdk.getOperationFee(mockTransaction
|
|
305
|
-
new BigNumber(1009880),
|
|
306
|
-
);
|
|
278
|
+
expect(sdk.getOperationFee(mockTransaction)).toEqual(new BigNumber(1009880));
|
|
307
279
|
});
|
|
308
280
|
|
|
309
281
|
test("getOperationDate should return correct date", () => {
|
|
310
|
-
const date = sdk.getOperationDate(mockTransaction
|
|
282
|
+
const date = sdk.getOperationDate(mockTransaction);
|
|
311
283
|
expect(date).toBeDefined();
|
|
312
284
|
expect(date).toBeInstanceOf(Date);
|
|
313
285
|
});
|
|
@@ -477,7 +449,7 @@ describe("SDK Functions", () => {
|
|
|
477
449
|
],
|
|
478
450
|
};
|
|
479
451
|
|
|
480
|
-
const operation = sdk.
|
|
452
|
+
const operation = sdk.alpacaTransactionToOp(address, tokenTx as SuiTransactionBlockResponse);
|
|
481
453
|
expect(operation.id).toEqual("DhKLpX5kwuKuyRa71RGqpX5EY2M8Efw535ZVXYXsRiDt");
|
|
482
454
|
expect(operation.type).toEqual("IN");
|
|
483
455
|
expect(operation.senders).toEqual([
|
|
@@ -643,41 +615,34 @@ describe("Staking Operations", () => {
|
|
|
643
615
|
});
|
|
644
616
|
|
|
645
617
|
describe("Operation Amount Calculation", () => {
|
|
646
|
-
|
|
647
|
-
const address = "0x65449f57946938c84c512732f1d69405d1fce417d9c9894696ddf4522f479e24";
|
|
618
|
+
const address = "0x6e143fe0a8ca010a86580dafac44298e5b1b7d73efc345356a59a15f0d7824f0";
|
|
648
619
|
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
},
|
|
620
|
+
const mockStakingTx = {
|
|
621
|
+
transaction: {
|
|
622
|
+
data: {
|
|
623
|
+
transaction: {
|
|
624
|
+
kind: "ProgrammableTransaction",
|
|
625
|
+
transactions: [
|
|
626
|
+
{
|
|
627
|
+
MoveCall: {
|
|
628
|
+
function: "request_add_stake",
|
|
659
629
|
},
|
|
660
|
-
|
|
661
|
-
|
|
630
|
+
},
|
|
631
|
+
],
|
|
662
632
|
},
|
|
663
633
|
},
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
const amount = sdk.getOperationAmount(address, mockStakingTx, sdk.DEFAULT_COIN_TYPE);
|
|
674
|
-
expect(amount).toEqual(new BigNumber("1000000000")); // The function returns minus of the balance change
|
|
675
|
-
});
|
|
676
|
-
|
|
677
|
-
test("getOperationAmount should calculate unstaking amount correctly", () => {
|
|
678
|
-
const address = "0x65449f57946938c84c512732f1d69405d1fce417d9c9894696ddf4522f479e24";
|
|
634
|
+
},
|
|
635
|
+
balanceChanges: [
|
|
636
|
+
{
|
|
637
|
+
owner: { AddressOwner: address },
|
|
638
|
+
coinType: "0x2::sui::SUI",
|
|
639
|
+
amount: "-1000000000",
|
|
640
|
+
},
|
|
641
|
+
],
|
|
642
|
+
} as SuiTransactionBlockResponse;
|
|
679
643
|
|
|
680
|
-
|
|
644
|
+
function mockUnstakingTx(amount: string) {
|
|
645
|
+
return {
|
|
681
646
|
transaction: {
|
|
682
647
|
data: {
|
|
683
648
|
transaction: {
|
|
@@ -696,14 +661,59 @@ describe("Staking Operations", () => {
|
|
|
696
661
|
{
|
|
697
662
|
owner: { AddressOwner: address },
|
|
698
663
|
coinType: "0x2::sui::SUI",
|
|
699
|
-
amount:
|
|
664
|
+
amount: amount,
|
|
700
665
|
},
|
|
701
666
|
],
|
|
702
|
-
} as
|
|
667
|
+
} as SuiTransactionBlockResponse;
|
|
668
|
+
}
|
|
703
669
|
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
670
|
+
function bridgeOperationAmount(
|
|
671
|
+
mock: SuiTransactionBlockResponse,
|
|
672
|
+
coinType: string = sdk.DEFAULT_COIN_TYPE,
|
|
673
|
+
) {
|
|
674
|
+
return sdk.getOperationAmount(address, mock, coinType);
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
test("getOperationAmount should calculate staking amount", () =>
|
|
678
|
+
expect(bridgeOperationAmount(mockStakingTx)).toEqual(new BigNumber("1000000000")));
|
|
679
|
+
|
|
680
|
+
test("getOperationAmount should calculate unstaking amount of 1000", () =>
|
|
681
|
+
expect(bridgeOperationAmount(mockUnstakingTx("1000"))).toEqual(new BigNumber("-1000")));
|
|
682
|
+
|
|
683
|
+
test("getOperationAmount should calculate unstaking amount of 0", () =>
|
|
684
|
+
expect(bridgeOperationAmount(mockUnstakingTx("0"))).toEqual(new BigNumber("0")));
|
|
685
|
+
|
|
686
|
+
test("getOperationAmount should calculate amount correctly for SUI", () =>
|
|
687
|
+
expect(bridgeOperationAmount(mockTransaction)).toEqual(new BigNumber("9998990120")));
|
|
688
|
+
|
|
689
|
+
test("getOperationAmount should calculate amount correctly for tokens", () =>
|
|
690
|
+
expect(bridgeOperationAmount(mockTransaction, "0x123::test::TOKEN")).toEqual(
|
|
691
|
+
new BigNumber("500000"),
|
|
692
|
+
));
|
|
693
|
+
|
|
694
|
+
function alpacaOperationAmount(
|
|
695
|
+
mock: SuiTransactionBlockResponse,
|
|
696
|
+
coinType: string = sdk.DEFAULT_COIN_TYPE,
|
|
697
|
+
) {
|
|
698
|
+
return sdk.alpacaGetOperationAmount(address, mock, coinType);
|
|
699
|
+
}
|
|
700
|
+
|
|
701
|
+
test("alpaca getOperationAmount should calculate staking amount", () =>
|
|
702
|
+
expect(alpacaOperationAmount(mockStakingTx)).toEqual(new BigNumber("1000000000")));
|
|
703
|
+
|
|
704
|
+
test("alpaca getOperationAmount should calculate unstaking amount of 1000", () =>
|
|
705
|
+
expect(alpacaOperationAmount(mockUnstakingTx("1000"))).toEqual(new BigNumber("1000")));
|
|
706
|
+
|
|
707
|
+
test("alpaca getOperationAmount should calculate unstaking amount of 0", () =>
|
|
708
|
+
expect(alpacaOperationAmount(mockUnstakingTx("0"))).toEqual(new BigNumber("0")));
|
|
709
|
+
|
|
710
|
+
test("alpaca getOperationAmount should calculate amount correctly for SUI", () =>
|
|
711
|
+
expect(alpacaOperationAmount(mockTransaction)).toEqual(new BigNumber("9998990120")));
|
|
712
|
+
|
|
713
|
+
test("alpaca getOperationAmount should calculate amount correctly for tokens", () =>
|
|
714
|
+
expect(alpacaOperationAmount(mockTransaction, "0x123::test::TOKEN")).toEqual(
|
|
715
|
+
new BigNumber("500000"),
|
|
716
|
+
));
|
|
707
717
|
});
|
|
708
718
|
|
|
709
719
|
describe("Operation Recipients", () => {
|
|
@@ -984,7 +994,7 @@ describe("Staking Operations", () => {
|
|
|
984
994
|
checkpoint: "313024",
|
|
985
995
|
} as unknown as SuiTransactionBlockResponse;
|
|
986
996
|
|
|
987
|
-
const operation = sdk.
|
|
997
|
+
const operation = sdk.alpacaTransactionToOp(address, mockStakingTx);
|
|
988
998
|
|
|
989
999
|
expect(operation.id).toEqual("delegate_tx_digest_123");
|
|
990
1000
|
expect(operation.type).toEqual("DELEGATE");
|
|
@@ -1035,7 +1045,7 @@ describe("Staking Operations", () => {
|
|
|
1035
1045
|
checkpoint: "313024",
|
|
1036
1046
|
} as unknown as SuiTransactionBlockResponse;
|
|
1037
1047
|
|
|
1038
|
-
const operation = sdk.
|
|
1048
|
+
const operation = sdk.alpacaTransactionToOp(address, mockUnstakingTx);
|
|
1039
1049
|
|
|
1040
1050
|
expect(operation.id).toEqual("undelegate_tx_digest_456");
|
|
1041
1051
|
expect(operation.type).toEqual("UNDELEGATE");
|
package/src/network/sdk.ts
CHANGED
|
@@ -108,32 +108,31 @@ export const getAllBalancesCached = makeLRUCache(
|
|
|
108
108
|
(owner: string) => owner,
|
|
109
109
|
minutes(1),
|
|
110
110
|
);
|
|
111
|
-
|
|
111
|
+
|
|
112
|
+
type ProgrammableTransaction = {
|
|
112
113
|
inputs: SuiCallArg[];
|
|
113
114
|
kind: "ProgrammableTransaction";
|
|
114
115
|
transactions: SuiTransaction[];
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
function isMoveCallWithFunction(
|
|
119
|
+
functionName: string,
|
|
120
|
+
block?: SuiTransactionBlockKind,
|
|
121
|
+
): block is ProgrammableTransaction {
|
|
122
|
+
if (block?.kind === "ProgrammableTransaction") {
|
|
118
123
|
const move = block.transactions.find(item => "MoveCall" in item) as any;
|
|
119
|
-
return move?.MoveCall.function ===
|
|
124
|
+
return move?.MoveCall.function === functionName;
|
|
125
|
+
} else {
|
|
126
|
+
return false;
|
|
120
127
|
}
|
|
121
|
-
return false;
|
|
122
128
|
}
|
|
123
129
|
|
|
124
|
-
function
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
if (block.kind === "ProgrammableTransaction") {
|
|
131
|
-
const move = block.transactions.find(
|
|
132
|
-
item => "MoveCall" in item && item["MoveCall"].function === "request_withdraw_stake",
|
|
133
|
-
) as any;
|
|
134
|
-
return Boolean(move);
|
|
135
|
-
}
|
|
136
|
-
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);
|
|
137
136
|
}
|
|
138
137
|
|
|
139
138
|
/**
|
|
@@ -342,11 +341,48 @@ export function transactionToOperation(
|
|
|
342
341
|
};
|
|
343
342
|
}
|
|
344
343
|
|
|
344
|
+
// This function is only used by alpaca code path
|
|
345
|
+
// Logic is similar to getOperationAmount, but we guarantee to return a positive amount in any case
|
|
346
|
+
// If there is need to display negative amount for staking or unstaking, the view can handle it based on the type of the operation
|
|
347
|
+
export const alpacaGetOperationAmount = (
|
|
348
|
+
address: string,
|
|
349
|
+
transaction: SuiTransactionBlockResponse,
|
|
350
|
+
coinType: string,
|
|
351
|
+
): BigNumber => {
|
|
352
|
+
const absoluteAmount = (balanceChange: BalanceChange | undefined) =>
|
|
353
|
+
new BigNumber(balanceChange?.amount || 0).abs();
|
|
354
|
+
|
|
355
|
+
const zero = BigNumber(0);
|
|
356
|
+
|
|
357
|
+
const tx = transaction.transaction?.data.transaction;
|
|
358
|
+
|
|
359
|
+
if (isStaking(tx) || isUnstaking(tx)) return absoluteAmount(transaction.balanceChanges?.[0]);
|
|
360
|
+
else {
|
|
361
|
+
return (
|
|
362
|
+
transaction.balanceChanges
|
|
363
|
+
?.filter(
|
|
364
|
+
balanceChange =>
|
|
365
|
+
typeof balanceChange.owner !== "string" &&
|
|
366
|
+
"AddressOwner" in balanceChange.owner &&
|
|
367
|
+
balanceChange.owner.AddressOwner === address &&
|
|
368
|
+
balanceChange.coinType === coinType,
|
|
369
|
+
)
|
|
370
|
+
.map(absoluteAmount)
|
|
371
|
+
.reduce((acc, curr) => acc.plus(curr), zero) || zero
|
|
372
|
+
);
|
|
373
|
+
}
|
|
374
|
+
};
|
|
375
|
+
|
|
345
376
|
/**
|
|
377
|
+
* This function is only used by alpaca code path
|
|
378
|
+
*
|
|
346
379
|
* @returns the operation converted. Note that if param `transaction` was retrieved as an "IN" operations, the type may be converted to "OUT".
|
|
347
380
|
* It happens for most "OUT" operations because the sender receive a new version of the coin objects.
|
|
348
381
|
*/
|
|
349
|
-
export function
|
|
382
|
+
export function alpacaTransactionToOp(
|
|
383
|
+
address: string,
|
|
384
|
+
transaction: SuiTransactionBlockResponse,
|
|
385
|
+
): Op {
|
|
350
386
|
const type = getOperationType(address, transaction);
|
|
351
387
|
const coinType = getOperationCoinType(transaction);
|
|
352
388
|
const hash = transaction.digest;
|
|
@@ -365,7 +401,7 @@ export function transactionToOp(address: string, transaction: SuiTransactionBloc
|
|
|
365
401
|
recipients: getOperationRecipients(transaction.transaction?.data),
|
|
366
402
|
senders: getOperationSenders(transaction.transaction?.data),
|
|
367
403
|
type,
|
|
368
|
-
value: BigInt(
|
|
404
|
+
value: BigInt(alpacaGetOperationAmount(address, transaction, coinType).toString()),
|
|
369
405
|
};
|
|
370
406
|
}
|
|
371
407
|
|
|
@@ -576,7 +612,7 @@ export const getListOperations = async (
|
|
|
576
612
|
|
|
577
613
|
const operations = ops.operations
|
|
578
614
|
.sort((a, b) => Number(b.timestampMs) - Number(a.timestampMs))
|
|
579
|
-
.map(t =>
|
|
615
|
+
.map(t => alpacaTransactionToOp(addr, t));
|
|
580
616
|
|
|
581
617
|
return {
|
|
582
618
|
items: operations,
|