@ledgerhq/coin-sui 0.11.0 → 0.12.0-nightly.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/.eslintrc.js +1 -0
- package/.unimportedrc.json +1 -0
- package/CHANGELOG.md +11 -0
- package/index.d.ts +0 -1
- package/jest.config.js +1 -1
- package/lib/bridge/broadcast.d.ts.map +1 -1
- package/lib/bridge/broadcast.js +3 -0
- package/lib/bridge/broadcast.js.map +1 -1
- package/lib/bridge/buildOptimisticOperation.js +31 -0
- package/lib/bridge/buildOptimisticOperation.js.map +1 -1
- package/lib/bridge/buildTransaction.d.ts +1 -1
- package/lib/bridge/buildTransaction.d.ts.map +1 -1
- package/lib/bridge/buildTransaction.js +3 -1
- package/lib/bridge/buildTransaction.js.map +1 -1
- package/lib/bridge/buildTransaction.test.js +4 -0
- package/lib/bridge/buildTransaction.test.js.map +1 -1
- package/lib/bridge/estimateMaxSpendable.d.ts.map +1 -1
- package/lib/bridge/estimateMaxSpendable.js +15 -3
- package/lib/bridge/estimateMaxSpendable.js.map +1 -1
- package/lib/bridge/estimateMaxSpendable.test.js +27 -0
- package/lib/bridge/estimateMaxSpendable.test.js.map +1 -1
- package/lib/bridge/getFeesForTransaction.d.ts.map +1 -1
- package/lib/bridge/getFeesForTransaction.js +13 -1
- package/lib/bridge/getFeesForTransaction.js.map +1 -1
- package/lib/bridge/getOperationExtra.d.ts +2 -0
- package/lib/bridge/getOperationExtra.d.ts.map +1 -0
- package/lib/bridge/getOperationExtra.js +6 -0
- package/lib/bridge/getOperationExtra.js.map +1 -0
- package/lib/bridge/getTransactionStatus.d.ts.map +1 -1
- package/lib/bridge/getTransactionStatus.js +45 -20
- package/lib/bridge/getTransactionStatus.js.map +1 -1
- package/lib/bridge/preload.d.ts.map +1 -1
- package/lib/bridge/preload.js +5 -3
- package/lib/bridge/preload.js.map +1 -1
- package/lib/bridge/preload.test.js +13 -217
- package/lib/bridge/preload.test.js.map +1 -1
- package/lib/bridge/prepareTransaction.js +1 -1
- package/lib/bridge/prepareTransaction.js.map +1 -1
- package/lib/bridge/synchronisation.d.ts.map +1 -1
- package/lib/bridge/synchronisation.js +5 -2
- package/lib/bridge/synchronisation.js.map +1 -1
- package/lib/bridge/synchronisation.test.js +355 -7
- package/lib/bridge/synchronisation.test.js.map +1 -1
- package/lib/bridge/utils.d.ts +1 -1
- package/lib/bridge/utils.d.ts.map +1 -1
- package/lib/bridge/utils.js +22 -0
- package/lib/bridge/utils.js.map +1 -1
- package/lib/constants.d.ts +4 -0
- package/lib/constants.d.ts.map +1 -0
- package/lib/constants.js +7 -0
- package/lib/constants.js.map +1 -0
- package/lib/errors.d.ts +13 -0
- package/lib/errors.d.ts.map +1 -0
- package/lib/errors.js +21 -0
- package/lib/errors.js.map +1 -0
- package/lib/logic/craftTransaction.d.ts +5 -10
- package/lib/logic/craftTransaction.d.ts.map +1 -1
- package/lib/logic/craftTransaction.js +2 -1
- package/lib/logic/craftTransaction.js.map +1 -1
- package/lib/logic/estimateFees.d.ts +1 -1
- package/lib/logic/estimateFees.d.ts.map +1 -1
- package/lib/logic/estimateFees.js +14 -2
- package/lib/logic/estimateFees.js.map +1 -1
- package/lib/logic/index.d.ts +2 -1
- package/lib/logic/index.d.ts.map +1 -1
- package/lib/logic/index.js +3 -1
- package/lib/logic/index.js.map +1 -1
- package/lib/logic/stake.d.ts +3 -0
- package/lib/logic/stake.d.ts.map +1 -0
- package/lib/logic/stake.js +12 -0
- package/lib/logic/stake.js.map +1 -0
- package/lib/network/index.d.ts +5 -4
- package/lib/network/index.d.ts.map +1 -1
- package/lib/network/index.js +5 -3
- package/lib/network/index.js.map +1 -1
- package/lib/network/sdk.d.ts +5 -3
- package/lib/network/sdk.d.ts.map +1 -1
- package/lib/network/sdk.js +148 -26
- package/lib/network/sdk.js.map +1 -1
- package/lib/network/sdk.test.js +491 -6
- package/lib/network/sdk.test.js.map +1 -1
- package/lib/types/bridge.d.ts +33 -6
- package/lib/types/bridge.d.ts.map +1 -1
- package/lib-es/bridge/broadcast.d.ts.map +1 -1
- package/lib-es/bridge/broadcast.js +3 -0
- package/lib-es/bridge/broadcast.js.map +1 -1
- package/lib-es/bridge/buildOptimisticOperation.js +31 -0
- package/lib-es/bridge/buildOptimisticOperation.js.map +1 -1
- package/lib-es/bridge/buildTransaction.d.ts +1 -1
- package/lib-es/bridge/buildTransaction.d.ts.map +1 -1
- package/lib-es/bridge/buildTransaction.js +3 -1
- package/lib-es/bridge/buildTransaction.js.map +1 -1
- package/lib-es/bridge/buildTransaction.test.js +4 -0
- package/lib-es/bridge/buildTransaction.test.js.map +1 -1
- package/lib-es/bridge/estimateMaxSpendable.d.ts.map +1 -1
- package/lib-es/bridge/estimateMaxSpendable.js +15 -3
- package/lib-es/bridge/estimateMaxSpendable.js.map +1 -1
- package/lib-es/bridge/estimateMaxSpendable.test.js +27 -0
- package/lib-es/bridge/estimateMaxSpendable.test.js.map +1 -1
- package/lib-es/bridge/getFeesForTransaction.d.ts.map +1 -1
- package/lib-es/bridge/getFeesForTransaction.js +13 -1
- package/lib-es/bridge/getFeesForTransaction.js.map +1 -1
- package/lib-es/bridge/getOperationExtra.d.ts +2 -0
- package/lib-es/bridge/getOperationExtra.d.ts.map +1 -0
- package/lib-es/bridge/getOperationExtra.js +2 -0
- package/lib-es/bridge/getOperationExtra.js.map +1 -0
- package/lib-es/bridge/getTransactionStatus.d.ts.map +1 -1
- package/lib-es/bridge/getTransactionStatus.js +46 -21
- package/lib-es/bridge/getTransactionStatus.js.map +1 -1
- package/lib-es/bridge/preload.d.ts.map +1 -1
- package/lib-es/bridge/preload.js +5 -3
- package/lib-es/bridge/preload.js.map +1 -1
- package/lib-es/bridge/preload.test.js +14 -218
- package/lib-es/bridge/preload.test.js.map +1 -1
- package/lib-es/bridge/prepareTransaction.js +1 -1
- package/lib-es/bridge/prepareTransaction.js.map +1 -1
- package/lib-es/bridge/synchronisation.d.ts.map +1 -1
- package/lib-es/bridge/synchronisation.js +6 -3
- package/lib-es/bridge/synchronisation.js.map +1 -1
- package/lib-es/bridge/synchronisation.test.js +332 -7
- package/lib-es/bridge/synchronisation.test.js.map +1 -1
- package/lib-es/bridge/utils.d.ts +1 -1
- package/lib-es/bridge/utils.d.ts.map +1 -1
- package/lib-es/bridge/utils.js +22 -0
- package/lib-es/bridge/utils.js.map +1 -1
- package/lib-es/constants.d.ts +4 -0
- package/lib-es/constants.d.ts.map +1 -0
- package/lib-es/constants.js +4 -0
- package/lib-es/constants.js.map +1 -0
- package/lib-es/errors.d.ts +13 -0
- package/lib-es/errors.d.ts.map +1 -0
- package/lib-es/errors.js +18 -0
- package/lib-es/errors.js.map +1 -0
- package/lib-es/logic/craftTransaction.d.ts +5 -10
- package/lib-es/logic/craftTransaction.d.ts.map +1 -1
- package/lib-es/logic/craftTransaction.js +2 -1
- package/lib-es/logic/craftTransaction.js.map +1 -1
- package/lib-es/logic/estimateFees.d.ts +1 -1
- package/lib-es/logic/estimateFees.d.ts.map +1 -1
- package/lib-es/logic/estimateFees.js +14 -2
- package/lib-es/logic/estimateFees.js.map +1 -1
- package/lib-es/logic/index.d.ts +2 -1
- package/lib-es/logic/index.d.ts.map +1 -1
- package/lib-es/logic/index.js +1 -0
- package/lib-es/logic/index.js.map +1 -1
- package/lib-es/logic/stake.d.ts +3 -0
- package/lib-es/logic/stake.d.ts.map +1 -0
- package/lib-es/logic/stake.js +8 -0
- package/lib-es/logic/stake.js.map +1 -0
- package/lib-es/network/index.d.ts +5 -4
- package/lib-es/network/index.d.ts.map +1 -1
- package/lib-es/network/index.js +4 -3
- package/lib-es/network/index.js.map +1 -1
- package/lib-es/network/sdk.d.ts +5 -3
- package/lib-es/network/sdk.d.ts.map +1 -1
- package/lib-es/network/sdk.js +144 -25
- package/lib-es/network/sdk.js.map +1 -1
- package/lib-es/network/sdk.test.js +491 -6
- package/lib-es/network/sdk.test.js.map +1 -1
- package/lib-es/types/bridge.d.ts +33 -6
- package/lib-es/types/bridge.d.ts.map +1 -1
- package/package.json +17 -9
- package/src/bridge/broadcast.ts +3 -0
- package/src/bridge/buildOptimisticOperation.ts +47 -4
- package/src/bridge/buildTransaction.test.ts +4 -0
- package/src/bridge/buildTransaction.ts +3 -1
- package/src/bridge/estimateMaxSpendable.test.ts +33 -0
- package/src/bridge/estimateMaxSpendable.ts +17 -3
- package/src/bridge/getFeesForTransaction.ts +14 -1
- package/src/bridge/getOperationExtra.ts +1 -0
- package/src/bridge/getTransactionStatus.ts +53 -21
- package/src/bridge/preload.test.ts +13 -279
- package/src/bridge/preload.ts +5 -3
- package/src/bridge/prepareTransaction.ts +1 -1
- package/src/bridge/synchronisation.test.ts +389 -7
- package/src/bridge/synchronisation.ts +6 -3
- package/src/bridge/utils.ts +25 -1
- package/src/constants.ts +4 -0
- package/src/errors.ts +21 -0
- package/src/logic/craftTransaction.ts +6 -9
- package/src/logic/estimateFees.ts +16 -1
- package/src/logic/index.ts +2 -1
- package/src/logic/stake.ts +9 -0
- package/src/network/index.ts +6 -3
- package/src/network/sdk.test.ts +538 -10
- package/src/network/sdk.ts +179 -31
- package/src/types/bridge.ts +32 -6
package/src/network/sdk.ts
CHANGED
|
@@ -8,11 +8,13 @@ import {
|
|
|
8
8
|
SuiClient,
|
|
9
9
|
SuiHTTPTransport,
|
|
10
10
|
SuiTransactionBlockResponse,
|
|
11
|
+
SuiTransaction,
|
|
12
|
+
SuiTransactionBlockKind,
|
|
13
|
+
TransactionEffects,
|
|
11
14
|
SuiTransactionBlockResponseOptions,
|
|
12
15
|
DelegatedStake,
|
|
13
16
|
StakeObject,
|
|
14
17
|
TransactionBlockData,
|
|
15
|
-
TransactionEffects,
|
|
16
18
|
} from "@mysten/sui/client";
|
|
17
19
|
import { Transaction } from "@mysten/sui/transactions";
|
|
18
20
|
import { BigNumber } from "bignumber.js";
|
|
@@ -31,15 +33,16 @@ import uniqBy from "lodash/unionBy";
|
|
|
31
33
|
import { encodeOperationId } from "@ledgerhq/coin-framework/operation";
|
|
32
34
|
import { log } from "@ledgerhq/logs";
|
|
33
35
|
import { makeLRUCache, minutes } from "@ledgerhq/live-network/cache";
|
|
34
|
-
import type { Transaction as TransactionType } from "../types";
|
|
35
|
-
import type { CreateExtrinsicArg } from "../logic/craftTransaction";
|
|
36
|
+
import type { Transaction as TransactionType, SuiValidator, CreateExtrinsicArg } from "../types";
|
|
36
37
|
import { ensureAddressFormat } from "../utils";
|
|
37
38
|
import coinConfig from "../config";
|
|
38
39
|
import { getEnv } from "@ledgerhq/live-env";
|
|
39
|
-
|
|
40
|
-
|
|
40
|
+
import { SUI_SYSTEM_STATE_OBJECT_ID } from "@mysten/sui/utils";
|
|
41
|
+
import { getCurrentSuiPreloadData } from "../bridge/preload";
|
|
42
|
+
import { ONE_SUI } from "../constants";
|
|
41
43
|
|
|
42
44
|
const apiMap: Record<string, SuiClient> = {};
|
|
45
|
+
type AsyncApiFunction<T> = (api: SuiClient) => Promise<T>;
|
|
43
46
|
|
|
44
47
|
export const TRANSACTIONS_LIMIT_PER_QUERY = 50;
|
|
45
48
|
export const TRANSACTIONS_LIMIT = 300;
|
|
@@ -58,10 +61,12 @@ type GenericInput<T> = T extends (...args: infer K) => unknown ? K : never;
|
|
|
58
61
|
type Inputs = GenericInput<typeof fetch>;
|
|
59
62
|
|
|
60
63
|
const fetcher = (url: Inputs[0], options: Inputs[1], retry = 3): Promise<Response> => {
|
|
64
|
+
const version = getEnv("LEDGER_CLIENT_VERSION") || "";
|
|
65
|
+
const isCI = version.includes("ll-ci") || version === "";
|
|
61
66
|
if (options) {
|
|
62
67
|
options.headers = {
|
|
63
68
|
...options.headers,
|
|
64
|
-
"X-Ledger-Client-Version":
|
|
69
|
+
"X-Ledger-Client-Version": isCI ? "lld/2.124.0-dev" : version, // for integration cli tests
|
|
65
70
|
};
|
|
66
71
|
}
|
|
67
72
|
if (retry === 1) return fetch(url, options);
|
|
@@ -96,6 +101,33 @@ export const getAllBalancesCached = makeLRUCache(
|
|
|
96
101
|
(owner: string) => owner,
|
|
97
102
|
minutes(1),
|
|
98
103
|
);
|
|
104
|
+
function isStaking(block?: SuiTransactionBlockKind): block is {
|
|
105
|
+
inputs: SuiCallArg[];
|
|
106
|
+
kind: "ProgrammableTransaction";
|
|
107
|
+
transactions: SuiTransaction[];
|
|
108
|
+
} {
|
|
109
|
+
if (!block) return false;
|
|
110
|
+
if (block.kind === "ProgrammableTransaction") {
|
|
111
|
+
const move = block.transactions.find(item => "MoveCall" in item) as any;
|
|
112
|
+
return move?.MoveCall.function === "request_add_stake";
|
|
113
|
+
}
|
|
114
|
+
return false;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
function isUnstaking(block?: SuiTransactionBlockKind): block is {
|
|
118
|
+
inputs: SuiCallArg[];
|
|
119
|
+
kind: "ProgrammableTransaction";
|
|
120
|
+
transactions: SuiTransaction[];
|
|
121
|
+
} {
|
|
122
|
+
if (!block) return false;
|
|
123
|
+
if (block.kind === "ProgrammableTransaction") {
|
|
124
|
+
const move = block.transactions.find(
|
|
125
|
+
item => "MoveCall" in item && item["MoveCall"].function === "request_withdraw_stake",
|
|
126
|
+
) as any;
|
|
127
|
+
return Boolean(move);
|
|
128
|
+
}
|
|
129
|
+
return false;
|
|
130
|
+
}
|
|
99
131
|
|
|
100
132
|
/**
|
|
101
133
|
* Get account balance (native and tokens)
|
|
@@ -119,8 +151,20 @@ export function isSender(addr: string, transaction?: TransactionBlockData): bool
|
|
|
119
151
|
/**
|
|
120
152
|
* Map transaction to an Operation Type
|
|
121
153
|
*/
|
|
122
|
-
export function getOperationType(
|
|
123
|
-
|
|
154
|
+
export function getOperationType(
|
|
155
|
+
addr: string,
|
|
156
|
+
{ transaction }: SuiTransactionBlockResponse,
|
|
157
|
+
): OperationType {
|
|
158
|
+
if (!isSender(addr, transaction?.data)) {
|
|
159
|
+
return "IN";
|
|
160
|
+
}
|
|
161
|
+
if (isStaking(transaction?.data.transaction)) {
|
|
162
|
+
return "DELEGATE";
|
|
163
|
+
}
|
|
164
|
+
if (isUnstaking(transaction?.data.transaction)) {
|
|
165
|
+
return "UNDELEGATE";
|
|
166
|
+
}
|
|
167
|
+
return "OUT";
|
|
124
168
|
}
|
|
125
169
|
|
|
126
170
|
/**
|
|
@@ -134,14 +178,17 @@ export const getOperationSenders = (transaction?: TransactionBlockData): string[
|
|
|
134
178
|
* Extract recipients from transaction
|
|
135
179
|
*/
|
|
136
180
|
export const getOperationRecipients = (transaction?: TransactionBlockData): string[] => {
|
|
137
|
-
if (transaction
|
|
138
|
-
|
|
181
|
+
if (!transaction) return [];
|
|
182
|
+
|
|
183
|
+
if (transaction.transaction.kind === "ProgrammableTransaction") {
|
|
184
|
+
if (!transaction.transaction.inputs) return [];
|
|
139
185
|
const recipients: string[] = [];
|
|
140
186
|
transaction.transaction.inputs.forEach((input: SuiCallArg) => {
|
|
141
187
|
if ("valueType" in input && input.valueType === "address") {
|
|
142
188
|
recipients.push(String(input.value));
|
|
143
189
|
}
|
|
144
190
|
});
|
|
191
|
+
if (isUnstaking(transaction.transaction) || isStaking(transaction.transaction)) return [];
|
|
145
192
|
return recipients;
|
|
146
193
|
}
|
|
147
194
|
return [];
|
|
@@ -157,6 +204,14 @@ export const getOperationAmount = (
|
|
|
157
204
|
): BigNumber => {
|
|
158
205
|
let amount = new BigNumber(0);
|
|
159
206
|
if (!transaction?.balanceChanges) return amount;
|
|
207
|
+
if (
|
|
208
|
+
isStaking(transaction.transaction?.data.transaction) ||
|
|
209
|
+
isUnstaking(transaction.transaction?.data.transaction)
|
|
210
|
+
) {
|
|
211
|
+
const balanceChange = transaction.balanceChanges[0];
|
|
212
|
+
return amount.minus(balanceChange?.amount || 0);
|
|
213
|
+
}
|
|
214
|
+
|
|
160
215
|
for (const balanceChange of transaction.balanceChanges) {
|
|
161
216
|
if (
|
|
162
217
|
typeof balanceChange.owner !== "string" &&
|
|
@@ -186,6 +241,39 @@ export const getOperationFee = (transaction: SuiTransactionBlockResponse): BigNu
|
|
|
186
241
|
return computationCost.plus(storageCost).minus(storageRebate);
|
|
187
242
|
};
|
|
188
243
|
|
|
244
|
+
export const getOperationExtra = (digest: string): Promise<Record<string, string>> =>
|
|
245
|
+
withApi(async api => {
|
|
246
|
+
const response = await api.getTransactionBlock({
|
|
247
|
+
digest,
|
|
248
|
+
options: {
|
|
249
|
+
showInput: true,
|
|
250
|
+
showBalanceChanges: true,
|
|
251
|
+
showEffects: true,
|
|
252
|
+
showEvents: true,
|
|
253
|
+
},
|
|
254
|
+
});
|
|
255
|
+
const tx = response.transaction?.data?.transaction;
|
|
256
|
+
if (isStaking(tx)) {
|
|
257
|
+
const inputs = tx.inputs;
|
|
258
|
+
const pure = inputs.filter(x => x.type === "pure") as { valueType: string; value: string }[];
|
|
259
|
+
const amount = pure.find(x => x.valueType === "u64")?.value as string;
|
|
260
|
+
const address = pure.find(x => x.valueType === "address")?.value as string;
|
|
261
|
+
const name = getCurrentSuiPreloadData().validators.find(x => x.suiAddress === address)?.name;
|
|
262
|
+
return { amount, address, name: name || "" };
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
if (isUnstaking(response.transaction?.data?.transaction)) {
|
|
266
|
+
const { principal_amount: amount, validator_address: address } = response.events?.find(
|
|
267
|
+
e => e.type === "0x3::validator::UnstakingRequestEvent",
|
|
268
|
+
)?.parsedJson as Record<string, string>;
|
|
269
|
+
const name = getCurrentSuiPreloadData().validators.find(x => x.suiAddress === address)?.name;
|
|
270
|
+
|
|
271
|
+
return { amount, address, name: name || "" };
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
return {};
|
|
275
|
+
});
|
|
276
|
+
|
|
189
277
|
/**
|
|
190
278
|
* Extract date from transaction
|
|
191
279
|
*/
|
|
@@ -193,6 +281,11 @@ export const getOperationDate = (transaction: SuiTransactionBlockResponse): Date
|
|
|
193
281
|
return new Date(parseInt(transaction.timestampMs!));
|
|
194
282
|
};
|
|
195
283
|
|
|
284
|
+
export const getStakesRaw = (owner: string) =>
|
|
285
|
+
withApi(async api => {
|
|
286
|
+
return api.getStakes({ owner });
|
|
287
|
+
});
|
|
288
|
+
|
|
196
289
|
/**
|
|
197
290
|
* Extract operation coin type from transaction
|
|
198
291
|
*/
|
|
@@ -217,7 +310,7 @@ export function transactionToOperation(
|
|
|
217
310
|
address: string,
|
|
218
311
|
transaction: SuiTransactionBlockResponse,
|
|
219
312
|
): Operation {
|
|
220
|
-
const type = getOperationType(address, transaction
|
|
313
|
+
const type = getOperationType(address, transaction);
|
|
221
314
|
|
|
222
315
|
const coinType = getOperationCoinType(transaction);
|
|
223
316
|
const hash = transaction.digest;
|
|
@@ -232,7 +325,7 @@ export function transactionToOperation(
|
|
|
232
325
|
coinType,
|
|
233
326
|
},
|
|
234
327
|
fee: getOperationFee(transaction),
|
|
235
|
-
hasFailed: transaction.effects?.status.status
|
|
328
|
+
hasFailed: transaction.effects?.status.status !== "success",
|
|
236
329
|
hash,
|
|
237
330
|
recipients: getOperationRecipients(transaction.transaction?.data),
|
|
238
331
|
senders: getOperationSenders(transaction.transaction?.data),
|
|
@@ -242,7 +335,7 @@ export function transactionToOperation(
|
|
|
242
335
|
}
|
|
243
336
|
|
|
244
337
|
export function transactionToOp(address: string, transaction: SuiTransactionBlockResponse): Op {
|
|
245
|
-
const type = getOperationType(address, transaction
|
|
338
|
+
const type = getOperationType(address, transaction);
|
|
246
339
|
const coinType = getOperationCoinType(transaction);
|
|
247
340
|
const hash = transaction.digest;
|
|
248
341
|
return {
|
|
@@ -278,7 +371,7 @@ export function toBlockInfo(checkpoint: Checkpoint): BlockInfo {
|
|
|
278
371
|
time: new Date(parseInt(checkpoint.timestampMs)),
|
|
279
372
|
};
|
|
280
373
|
|
|
281
|
-
if (typeof checkpoint.previousDigest
|
|
374
|
+
if (typeof checkpoint.previousDigest === "string")
|
|
282
375
|
return {
|
|
283
376
|
...info,
|
|
284
377
|
parent: {
|
|
@@ -303,7 +396,7 @@ export function toBlockInfo(checkpoint: Checkpoint): BlockInfo {
|
|
|
303
396
|
export function toBlockTransaction(transaction: SuiTransactionBlockResponse): BlockTransaction {
|
|
304
397
|
return {
|
|
305
398
|
hash: transaction.digest,
|
|
306
|
-
failed: transaction.effects?.status.status
|
|
399
|
+
failed: transaction.effects?.status.status !== "success",
|
|
307
400
|
operations: transaction.balanceChanges?.flatMap(toBlockOperation) || [],
|
|
308
401
|
fees: BigInt(getOperationFee(transaction).toString()),
|
|
309
402
|
feesPayer: transaction.transaction?.data.sender || "",
|
|
@@ -316,7 +409,7 @@ export function toBlockTransaction(transaction: SuiTransactionBlockResponse): Bl
|
|
|
316
409
|
* @param change balance change
|
|
317
410
|
*/
|
|
318
411
|
export function toBlockOperation(change: BalanceChange): BlockOperation[] {
|
|
319
|
-
if (typeof change.owner
|
|
412
|
+
if (typeof change.owner === "string" || !("AddressOwner" in change.owner)) return [];
|
|
320
413
|
return [
|
|
321
414
|
{
|
|
322
415
|
type: "transfer",
|
|
@@ -537,27 +630,65 @@ export const createTransaction = async (address: string, transaction: CreateExtr
|
|
|
537
630
|
withApi(async api => {
|
|
538
631
|
const tx = new Transaction();
|
|
539
632
|
tx.setSender(ensureAddressFormat(address));
|
|
633
|
+
const { mode, amount } = transaction;
|
|
634
|
+
switch (mode) {
|
|
635
|
+
case "delegate": {
|
|
636
|
+
const coins = tx.splitCoins(tx.gas, [amount.toNumber()]);
|
|
637
|
+
tx.moveCall({
|
|
638
|
+
target: "0x3::sui_system::request_add_stake",
|
|
639
|
+
arguments: [
|
|
640
|
+
tx.object(SUI_SYSTEM_STATE_OBJECT_ID),
|
|
641
|
+
coins,
|
|
642
|
+
tx.pure.address(transaction.recipient),
|
|
643
|
+
],
|
|
644
|
+
});
|
|
645
|
+
|
|
646
|
+
tx.setGasBudgetIfNotSet(ONE_SUI / 10);
|
|
647
|
+
break;
|
|
648
|
+
}
|
|
649
|
+
case "undelegate": {
|
|
650
|
+
if (transaction.useAllAmount) {
|
|
651
|
+
tx.moveCall({
|
|
652
|
+
target: "0x3::sui_system::request_withdraw_stake",
|
|
653
|
+
arguments: [tx.object(SUI_SYSTEM_STATE_OBJECT_ID), tx.object(transaction.stakedSuiId!)],
|
|
654
|
+
});
|
|
655
|
+
} else {
|
|
656
|
+
const res = tx.moveCall({
|
|
657
|
+
target: "0x3::staking_pool::split",
|
|
658
|
+
arguments: [tx.object(transaction.stakedSuiId!), tx.pure.u64(amount.toString())],
|
|
659
|
+
});
|
|
660
|
+
tx.moveCall({
|
|
661
|
+
target: "0x3::sui_system::request_withdraw_stake",
|
|
662
|
+
arguments: [tx.object(SUI_SYSTEM_STATE_OBJECT_ID), res],
|
|
663
|
+
});
|
|
664
|
+
}
|
|
665
|
+
|
|
666
|
+
tx.setGasBudgetIfNotSet(ONE_SUI / 10);
|
|
667
|
+
break;
|
|
668
|
+
}
|
|
669
|
+
default: {
|
|
670
|
+
if (transaction.coinType !== DEFAULT_COIN_TYPE) {
|
|
671
|
+
const requiredAmount = transaction.amount.toNumber();
|
|
540
672
|
|
|
541
|
-
|
|
542
|
-
const requiredAmount = transaction.amount.toNumber();
|
|
673
|
+
const coins = await getCoinsForAmount(api, address, transaction.coinType, requiredAmount);
|
|
543
674
|
|
|
544
|
-
|
|
675
|
+
if (coins.length === 0) {
|
|
676
|
+
throw new Error(`No coins found for type ${transaction.coinType}`);
|
|
677
|
+
}
|
|
545
678
|
|
|
546
|
-
|
|
547
|
-
throw new Error(`No coins found for type ${transaction.coinType}`);
|
|
548
|
-
}
|
|
679
|
+
const coinObjects = coins.map(coin => tx.object(coin.coinObjectId));
|
|
549
680
|
|
|
550
|
-
|
|
681
|
+
if (coinObjects.length > 1) {
|
|
682
|
+
tx.mergeCoins(coinObjects[0], coinObjects.slice(1));
|
|
683
|
+
}
|
|
551
684
|
|
|
552
|
-
|
|
553
|
-
|
|
685
|
+
const [coin] = tx.splitCoins(coinObjects[0], [transaction.amount.toNumber()]);
|
|
686
|
+
tx.transferObjects([coin], transaction.recipient);
|
|
687
|
+
} else {
|
|
688
|
+
const [coin] = tx.splitCoins(tx.gas, [transaction.amount.toNumber()]);
|
|
689
|
+
tx.transferObjects([coin], transaction.recipient);
|
|
690
|
+
}
|
|
554
691
|
}
|
|
555
|
-
|
|
556
|
-
const [coin] = tx.splitCoins(coinObjects[0], [transaction.amount.toNumber()]);
|
|
557
|
-
tx.transferObjects([coin], transaction.recipient);
|
|
558
|
-
} else {
|
|
559
|
-
const [coin] = tx.splitCoins(tx.gas, [transaction.amount.toNumber()]);
|
|
560
|
-
tx.transferObjects([coin], transaction.recipient);
|
|
561
692
|
}
|
|
562
693
|
|
|
563
694
|
return tx.build({ client: api });
|
|
@@ -726,3 +857,20 @@ export const toStakeAmounts = (stake: StakeObject): { deposited: bigint; rewarde
|
|
|
726
857
|
return { deposited: BigInt(stake.principal), rewarded: 0n }; // note: we lose reward information in unstaked state here
|
|
727
858
|
}
|
|
728
859
|
};
|
|
860
|
+
|
|
861
|
+
export const getValidators = (): Promise<SuiValidator[]> =>
|
|
862
|
+
withApi(async api => {
|
|
863
|
+
const [{ activeValidators }, { apys }] = await Promise.all([
|
|
864
|
+
api.getLatestSuiSystemState(),
|
|
865
|
+
api.getValidatorsApy(),
|
|
866
|
+
]);
|
|
867
|
+
const hash = apys.reduce(
|
|
868
|
+
(acc, item) => {
|
|
869
|
+
acc[item.address] = item.apy;
|
|
870
|
+
return acc;
|
|
871
|
+
},
|
|
872
|
+
{} as Record<string, number>,
|
|
873
|
+
);
|
|
874
|
+
|
|
875
|
+
return activeValidators.map(item => ({ ...item, apy: hash[item.suiAddress] }));
|
|
876
|
+
});
|
package/src/types/bridge.ts
CHANGED
|
@@ -8,18 +8,29 @@ import type {
|
|
|
8
8
|
OperationRaw,
|
|
9
9
|
} from "@ledgerhq/types-live";
|
|
10
10
|
import type { Account, AccountRaw } from "@ledgerhq/types-live";
|
|
11
|
+
import { DelegatedStake, StakeObject, SuiValidatorSummary } from "@mysten/sui/client";
|
|
12
|
+
|
|
13
|
+
export type MappedStake = StakeObject & {
|
|
14
|
+
rank: number;
|
|
15
|
+
validator: SuiValidator;
|
|
16
|
+
stakedSuiId: string;
|
|
17
|
+
formattedAmount: string;
|
|
18
|
+
};
|
|
11
19
|
|
|
12
20
|
/**
|
|
13
21
|
* Sui account resources
|
|
14
22
|
*/
|
|
15
|
-
export type SuiResources =
|
|
23
|
+
export type SuiResources = {
|
|
24
|
+
stakes?: DelegatedStake[];
|
|
25
|
+
cachedOps?: Record<string, Record<string, string>>;
|
|
26
|
+
};
|
|
16
27
|
|
|
17
28
|
/**
|
|
18
29
|
* Sui account resources from raw JSON
|
|
19
30
|
*/
|
|
20
31
|
export type SuiResourcesRaw = object;
|
|
21
32
|
|
|
22
|
-
export type SuiTransactionMode = "send" | "token.send";
|
|
33
|
+
export type SuiTransactionMode = "send" | "token.send" | "delegate" | "undelegate";
|
|
23
34
|
|
|
24
35
|
/**
|
|
25
36
|
* Sui transaction
|
|
@@ -29,12 +40,22 @@ export type Transaction = TransactionCommon & {
|
|
|
29
40
|
family: "sui";
|
|
30
41
|
amount: BigNumber | null;
|
|
31
42
|
fees?: BigNumber | null;
|
|
32
|
-
errors
|
|
43
|
+
errors?: Record<string, Error>;
|
|
33
44
|
skipVerify?: boolean;
|
|
34
45
|
coinType: string;
|
|
46
|
+
stakedSuiId?: string;
|
|
35
47
|
// add here all transaction-specific fields when implement other modes than "send"
|
|
36
48
|
};
|
|
37
49
|
|
|
50
|
+
export type CreateExtrinsicArg = {
|
|
51
|
+
amount: BigNumber;
|
|
52
|
+
coinType: string;
|
|
53
|
+
mode: SuiTransactionMode;
|
|
54
|
+
recipient: string;
|
|
55
|
+
useAllAmount?: boolean;
|
|
56
|
+
stakedSuiId?: string;
|
|
57
|
+
};
|
|
58
|
+
|
|
38
59
|
/**
|
|
39
60
|
* Sui transaction from a raw JSON
|
|
40
61
|
*/
|
|
@@ -46,12 +67,17 @@ export type TransactionRaw = TransactionCommonRaw & {
|
|
|
46
67
|
// also the transaction fields as raw JSON data
|
|
47
68
|
};
|
|
48
69
|
|
|
70
|
+
/**
|
|
71
|
+
* Sui validator metadata
|
|
72
|
+
*/
|
|
73
|
+
export type SuiValidator = SuiValidatorSummary & { apy: number };
|
|
74
|
+
|
|
49
75
|
/**
|
|
50
76
|
* Sui currency data that will be preloaded.
|
|
51
77
|
* You can for instance add a list of validators for Proof-of-Stake blockchains,
|
|
52
78
|
* or any volatile data that could not be set as constants in the code (staking progress, fee estimation variables, etc.)
|
|
53
79
|
*/
|
|
54
|
-
export type SuiPreloadData =
|
|
80
|
+
export type SuiPreloadData = { validators: SuiValidator[] };
|
|
55
81
|
|
|
56
82
|
export type SuiAccount = Account & {
|
|
57
83
|
// On some blockchain, an account can have resources (gained, delegated, ...)
|
|
@@ -84,14 +110,14 @@ export type SuiSignedOperation = {
|
|
|
84
110
|
};
|
|
85
111
|
|
|
86
112
|
export type TransferCommand = {
|
|
87
|
-
kind:
|
|
113
|
+
kind: SuiTransactionMode;
|
|
88
114
|
sender: string;
|
|
89
115
|
recipient: string;
|
|
90
116
|
amount: number;
|
|
91
117
|
};
|
|
92
118
|
|
|
93
119
|
export type TokenTransferCommand = {
|
|
94
|
-
kind:
|
|
120
|
+
kind: string;
|
|
95
121
|
sender: string;
|
|
96
122
|
recipient: string;
|
|
97
123
|
amount: number;
|