@scallop-io/sui-kit 2.1.0 → 2.2.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.
@@ -1,311 +1,312 @@
1
- import { Transaction, TransactionObjectInput } from '@mysten/sui/transactions';
2
- import { SUI_SYSTEM_STATE_OBJECT_ID } from '@mysten/sui/utils';
1
+ import type { bcs } from "@mysten/sui/bcs";
2
+ import type { ClientWithCoreApi } from "@mysten/sui/client";
3
+ import type { Keypair } from "@mysten/sui/cryptography";
3
4
  import {
4
- convertArgs,
5
- convertAddressArg,
6
- convertObjArg,
7
- convertAmounts,
8
- partitionArray,
9
- } from './util.js';
10
- import type { ClientWithCoreApi } from '@mysten/sui/client';
11
- import type { Keypair } from '@mysten/sui/cryptography';
5
+ Transaction,
6
+ type TransactionObjectInput,
7
+ } from "@mysten/sui/transactions";
8
+ import { SUI_SYSTEM_STATE_OBJECT_ID } from "@mysten/sui/utils";
12
9
  import type {
13
- SuiTxArg,
14
- SuiAddressArg,
15
- SuiObjectArg,
16
- SuiVecTxArg,
17
- SuiAmountsArg,
18
- } from '../../types/index.js';
19
- import type { bcs } from '@mysten/sui/bcs';
10
+ SuiAddressArg,
11
+ SuiAmountsArg,
12
+ SuiObjectArg,
13
+ SuiTxArg,
14
+ SuiVecTxArg,
15
+ } from "../../types/index.js";
16
+ import {
17
+ convertAddressArg,
18
+ convertAmounts,
19
+ convertArgs,
20
+ convertObjArg,
21
+ partitionArray,
22
+ } from "./util.js";
20
23
 
21
24
  // Object reference type
22
25
  interface SuiObjectRef {
23
- objectId: string;
24
- version: number | string;
25
- digest: string;
26
+ objectId: string;
27
+ version: number | string;
28
+ digest: string;
26
29
  }
27
30
 
28
31
  export class SuiTxBlock {
29
- public txBlock: Transaction;
30
-
31
- constructor(transaction?: Transaction) {
32
- this.txBlock = transaction
33
- ? Transaction.from(transaction)
34
- : new Transaction();
35
- }
36
-
37
- /* Directly wrap methods and properties of TransactionBlock */
38
- get gas() {
39
- return this.txBlock.gas;
40
- }
41
-
42
- getData() {
43
- return this.txBlock.getData();
44
- }
45
-
46
- address(value: string) {
47
- return this.txBlock.pure.address(value);
48
- }
49
-
50
- get pure(): typeof this.txBlock.pure {
51
- return this.txBlock.pure;
52
- }
53
-
54
- object(value: string | TransactionObjectInput) {
55
- return this.txBlock.object(value);
56
- }
57
-
58
- objectRef(ref: SuiObjectRef) {
59
- return this.txBlock.objectRef(ref);
60
- }
61
- sharedObjectRef(ref: typeof bcs.SharedObjectRef.$inferType) {
62
- return this.txBlock.sharedObjectRef(ref);
63
- }
64
- setSender(sender: string) {
65
- return this.txBlock.setSender(sender);
66
- }
67
- setSenderIfNotSet(sender: string) {
68
- return this.txBlock.setSenderIfNotSet(sender);
69
- }
70
- setExpiration(expiration?: Parameters<typeof this.txBlock.setExpiration>[0]) {
71
- return this.txBlock.setExpiration(expiration);
72
- }
73
- setGasPrice(price: number | bigint) {
74
- return this.txBlock.setGasPrice(price);
75
- }
76
- setGasBudget(budget: number | bigint) {
77
- return this.txBlock.setGasBudget(budget);
78
- }
79
- setGasOwner(owner: string) {
80
- return this.txBlock.setGasOwner(owner);
81
- }
82
- setGasPayment(payments: SuiObjectRef[]) {
83
- return this.txBlock.setGasPayment(payments);
84
- }
85
- /**
86
- * @deprecated Use toJSON instead.
87
- * For synchronous serialization, you can use `getData()`
88
- * */
89
- serialize() {
90
- // TODO: need to update this method to use the new serialize method
91
- return this.txBlock.serialize();
92
- }
93
-
94
- toJSON() {
95
- return this.txBlock.toJSON();
96
- }
97
-
98
- sign(params: {
99
- signer: Keypair;
100
- client?: ClientWithCoreApi;
101
- onlyTransactionKind?: boolean;
102
- }) {
103
- return this.txBlock.sign(params);
104
- }
105
- build(
106
- params: {
107
- client?: ClientWithCoreApi;
108
- onlyTransactionKind?: boolean;
109
- } = {}
110
- ) {
111
- return this.txBlock.build(params);
112
- }
113
- getDigest(params: { client?: ClientWithCoreApi } = {}) {
114
- return this.txBlock.getDigest(params);
115
- }
116
- add(...args: Parameters<typeof this.txBlock.add>) {
117
- return this.txBlock.add(...args);
118
- }
119
- publish({
120
- modules,
121
- dependencies,
122
- }: {
123
- modules: number[][] | string[];
124
- dependencies: string[];
125
- }) {
126
- return this.txBlock.publish({ modules, dependencies });
127
- }
128
- upgrade(...args: Parameters<typeof this.txBlock.upgrade>) {
129
- return this.txBlock.upgrade(...args);
130
- }
131
-
132
- makeMoveVec(...args: Parameters<typeof this.txBlock.makeMoveVec>) {
133
- return this.txBlock.makeMoveVec(...args);
134
- }
135
-
136
- /* Override methods of TransactionBlock */
137
-
138
- transferObjects(objects: SuiObjectArg[], address: SuiAddressArg) {
139
- return this.txBlock.transferObjects(
140
- objects.map((object) => convertObjArg(this.txBlock, object)),
141
- convertAddressArg(this.txBlock, address)
142
- );
143
- }
144
-
145
- splitCoins(coin: SuiObjectArg, amounts: SuiAmountsArg[]) {
146
- const res = this.txBlock.splitCoins(
147
- convertObjArg(this.txBlock, coin),
148
- convertAmounts(this.txBlock, amounts)
149
- );
150
- return amounts.map((_, i) => res[i]);
151
- }
152
-
153
- mergeCoins(destination: SuiObjectArg, sources: SuiObjectArg[]) {
154
- const destinationObject = convertObjArg(this.txBlock, destination);
155
- const sourceObjects = sources.map((source) =>
156
- convertObjArg(this.txBlock, source)
157
- );
158
- return this.txBlock.mergeCoins(destinationObject, sourceObjects);
159
- }
160
-
161
- /**
162
- * @description Move call
163
- * @param target `${string}::${string}::${string}`, e.g. `0x3::sui_system::request_add_stake`
164
- * @param args the arguments of the move call, such as `['0x1', '0x2']`
165
- * @param typeArgs the type arguments of the move call, such as `['0x2::sui::SUI']`
166
- */
167
- moveCall(
168
- target: string,
169
- args: (SuiTxArg | SuiVecTxArg | SuiObjectArg | SuiAmountsArg)[] = [],
170
- typeArgs: string[] = []
171
- ) {
172
- // a regex for pattern `${string}::${string}::${string}`
173
- const regex =
174
- /(?<package>[a-zA-Z0-9]+)::(?<module>[a-zA-Z0-9_]+)::(?<function>[a-zA-Z0-9_]+)/;
175
- const match = target.match(regex);
176
- if (match === null)
177
- throw new Error(
178
- 'Invalid target format. Expected `${string}::${string}::${string}`'
179
- );
180
- const convertedArgs = convertArgs(this.txBlock, args);
181
- return this.txBlock.moveCall({
182
- target: target as `${string}::${string}::${string}`,
183
- arguments: convertedArgs,
184
- typeArguments: typeArgs,
185
- });
186
- }
187
-
188
- /* Enhance methods of TransactionBlock */
189
- transferSuiToMany(recipients: SuiAddressArg[], amounts: SuiAmountsArg[]) {
190
- // require recipients.length === amounts.length
191
- if (recipients.length !== amounts.length) {
192
- throw new Error(
193
- 'transferSuiToMany: recipients.length !== amounts.length'
194
- );
195
- }
196
- const coins = this.txBlock.splitCoins(
197
- this.txBlock.gas,
198
- convertAmounts(this.txBlock, amounts)
199
- );
200
-
201
- const recipientObjects = recipients.map((recipient) =>
202
- convertAddressArg(this.txBlock, recipient)
203
- );
204
-
205
- // Transfer splitted coins to recipients
206
- recipientObjects.forEach((address, index) => {
207
- this.txBlock.transferObjects([coins[index]], address);
208
- });
209
-
210
- return this;
211
- }
212
-
213
- transferSui(address: SuiAddressArg, amount: SuiAmountsArg) {
214
- return this.transferSuiToMany([address], [amount]);
215
- }
216
-
217
- takeAmountFromCoins(coins: SuiObjectArg[], amount: SuiAmountsArg) {
218
- const { splitedCoins, mergedCoin } = this.splitMultiCoins(
219
- coins,
220
- convertAmounts(this.txBlock, [amount])
221
- );
222
-
223
- return [splitedCoins, mergedCoin];
224
- }
225
-
226
- splitSUIFromGas(amounts: SuiAmountsArg[]) {
227
- return this.txBlock.splitCoins(
228
- this.txBlock.gas,
229
- convertAmounts(this.txBlock, amounts)
230
- );
231
- }
232
-
233
- splitMultiCoins(coins: SuiObjectArg[], amounts: SuiAmountsArg[]) {
234
- if (coins.length === 0) {
235
- throw new Error('takeAmountFromCoins: coins array is empty');
236
- }
237
-
238
- const partitions = partitionArray(coins.slice(1), 511);
239
- const mergedCoin = convertObjArg(this.txBlock, coins[0]);
240
- for (const partition of partitions) {
241
- const coinObjects = partition.map((coin) =>
242
- convertObjArg(this.txBlock, coin)
243
- );
244
- this.txBlock.mergeCoins(mergedCoin, coinObjects);
245
- }
246
- const splitedCoins = this.txBlock.splitCoins(
247
- mergedCoin,
248
- convertAmounts(this.txBlock, amounts)
249
- );
250
- return { splitedCoins, mergedCoin };
251
- }
252
-
253
- transferCoinToMany(
254
- coins: SuiObjectArg[],
255
- sender: SuiAddressArg,
256
- recipients: SuiAddressArg[],
257
- amounts: SuiAmountsArg[]
258
- ) {
259
- // require recipients.length === amounts.length
260
- if (recipients.length !== amounts.length) {
261
- throw new Error(
262
- 'transferCoinToMany: recipients.length !== amounts.length'
263
- );
264
- }
265
- const coinObjects = coins.map((coin) => convertObjArg(this.txBlock, coin));
266
- const { splitedCoins, mergedCoin } = this.splitMultiCoins(
267
- coinObjects,
268
- convertAmounts(this.txBlock, amounts)
269
- );
270
- const recipientObjects = recipients.map((recipient) =>
271
- convertAddressArg(this.txBlock, recipient)
272
- );
273
-
274
- // Transfer splitted coins to recipients
275
- recipientObjects.forEach((address, index) => {
276
- this.txBlock.transferObjects([splitedCoins[index]], address);
277
- });
278
-
279
- // Return the remaining coin back to sender
280
- this.txBlock.transferObjects(
281
- [mergedCoin],
282
- convertAddressArg(this.txBlock, sender)
283
- );
284
-
285
- return this;
286
- }
287
-
288
- transferCoin(
289
- coins: SuiObjectArg[],
290
- sender: SuiAddressArg,
291
- recipient: SuiAddressArg,
292
- amount: SuiAmountsArg
293
- ) {
294
- return this.transferCoinToMany(coins, sender, [recipient], [amount]);
295
- }
296
-
297
- stakeSui(amount: SuiAmountsArg, validatorAddr: SuiAddressArg) {
298
- const [stakeCoin] = this.txBlock.splitCoins(
299
- this.txBlock.gas,
300
- convertAmounts(this.txBlock, [amount])
301
- );
302
- return this.txBlock.moveCall({
303
- target: '0x3::sui_system::request_add_stake',
304
- arguments: convertArgs(this.txBlock, [
305
- this.txBlock.object(SUI_SYSTEM_STATE_OBJECT_ID),
306
- stakeCoin,
307
- convertAddressArg(this.txBlock, validatorAddr),
308
- ]),
309
- });
310
- }
32
+ public txBlock: Transaction;
33
+
34
+ constructor(transaction?: Transaction) {
35
+ this.txBlock = transaction
36
+ ? Transaction.from(transaction)
37
+ : new Transaction();
38
+ }
39
+
40
+ /* Directly wrap methods and properties of TransactionBlock */
41
+ get gas() {
42
+ return this.txBlock.gas;
43
+ }
44
+
45
+ getData() {
46
+ return this.txBlock.getData();
47
+ }
48
+
49
+ address(value: string) {
50
+ return this.txBlock.pure.address(value);
51
+ }
52
+
53
+ get pure(): typeof this.txBlock.pure {
54
+ return this.txBlock.pure;
55
+ }
56
+
57
+ object(value: string | TransactionObjectInput) {
58
+ return this.txBlock.object(value);
59
+ }
60
+
61
+ objectRef(ref: SuiObjectRef) {
62
+ return this.txBlock.objectRef(ref);
63
+ }
64
+ sharedObjectRef(ref: typeof bcs.SharedObjectRef.$inferType) {
65
+ return this.txBlock.sharedObjectRef(ref);
66
+ }
67
+ setSender(sender: string) {
68
+ return this.txBlock.setSender(sender);
69
+ }
70
+ setSenderIfNotSet(sender: string) {
71
+ return this.txBlock.setSenderIfNotSet(sender);
72
+ }
73
+ setExpiration(expiration?: Parameters<typeof this.txBlock.setExpiration>[0]) {
74
+ return this.txBlock.setExpiration(expiration);
75
+ }
76
+ setGasPrice(price: number | bigint) {
77
+ return this.txBlock.setGasPrice(price);
78
+ }
79
+ setGasBudget(budget: number | bigint) {
80
+ return this.txBlock.setGasBudget(budget);
81
+ }
82
+ setGasOwner(owner: string) {
83
+ return this.txBlock.setGasOwner(owner);
84
+ }
85
+ setGasPayment(payments: SuiObjectRef[]) {
86
+ return this.txBlock.setGasPayment(payments);
87
+ }
88
+ /**
89
+ * @deprecated Use toJSON instead.
90
+ * For synchronous serialization, you can use `getData()`
91
+ * */
92
+ serialize() {
93
+ // TODO: need to update this method to use the new serialize method
94
+ return this.txBlock.serialize();
95
+ }
96
+
97
+ toJSON() {
98
+ return this.txBlock.toJSON();
99
+ }
100
+
101
+ sign(params: {
102
+ signer: Keypair;
103
+ client?: ClientWithCoreApi;
104
+ onlyTransactionKind?: boolean;
105
+ }) {
106
+ return this.txBlock.sign(params);
107
+ }
108
+ build(
109
+ params: { client?: ClientWithCoreApi; onlyTransactionKind?: boolean } = {},
110
+ ) {
111
+ return this.txBlock.build(params);
112
+ }
113
+ getDigest(params: { client?: ClientWithCoreApi } = {}) {
114
+ return this.txBlock.getDigest(params);
115
+ }
116
+ add(...args: Parameters<typeof this.txBlock.add>) {
117
+ return this.txBlock.add(...args);
118
+ }
119
+ publish({
120
+ modules,
121
+ dependencies,
122
+ }: {
123
+ modules: number[][] | string[];
124
+ dependencies: string[];
125
+ }) {
126
+ return this.txBlock.publish({ modules, dependencies });
127
+ }
128
+ upgrade(...args: Parameters<typeof this.txBlock.upgrade>) {
129
+ return this.txBlock.upgrade(...args);
130
+ }
131
+
132
+ makeMoveVec(...args: Parameters<typeof this.txBlock.makeMoveVec>) {
133
+ return this.txBlock.makeMoveVec(...args);
134
+ }
135
+
136
+ /* Override methods of TransactionBlock */
137
+
138
+ transferObjects(objects: SuiObjectArg[], address: SuiAddressArg) {
139
+ return this.txBlock.transferObjects(
140
+ objects.map((object) => convertObjArg(this.txBlock, object)),
141
+ convertAddressArg(this.txBlock, address),
142
+ );
143
+ }
144
+
145
+ splitCoins(coin: SuiObjectArg, amounts: SuiAmountsArg[]) {
146
+ const res = this.txBlock.splitCoins(
147
+ convertObjArg(this.txBlock, coin),
148
+ convertAmounts(this.txBlock, amounts),
149
+ );
150
+ return amounts.map((_, i) => res[i]);
151
+ }
152
+
153
+ mergeCoins(destination: SuiObjectArg, sources: SuiObjectArg[]) {
154
+ const destinationObject = convertObjArg(this.txBlock, destination);
155
+ const sourceObjects = sources.map((source) =>
156
+ convertObjArg(this.txBlock, source),
157
+ );
158
+ return this.txBlock.mergeCoins(destinationObject, sourceObjects);
159
+ }
160
+
161
+ /**
162
+ * @description Move call
163
+ * @param target `${string}::${string}::${string}`, e.g. `0x3::sui_system::request_add_stake`
164
+ * @param args the arguments of the move call, such as `['0x1', '0x2']`
165
+ * @param typeArgs the type arguments of the move call, such as `['0x2::sui::SUI']`
166
+ */
167
+ moveCall(
168
+ target: string,
169
+ args: (SuiTxArg | SuiVecTxArg | SuiObjectArg | SuiAmountsArg)[] = [],
170
+ typeArgs: string[] = [],
171
+ ) {
172
+ // a regex for pattern `${string}::${string}::${string}`
173
+ const regex =
174
+ /(?<package>[a-zA-Z0-9]+)::(?<module>[a-zA-Z0-9_]+)::(?<function>[a-zA-Z0-9_]+)/;
175
+ const match = target.match(regex);
176
+ if (match === null)
177
+ throw new Error(
178
+ // biome-ignore lint/suspicious/noTemplateCurlyInString: Intended error message format
179
+ "Invalid target format. Expected `${string}::${string}::${string}`",
180
+ );
181
+ const convertedArgs = convertArgs(this.txBlock, args);
182
+ return this.txBlock.moveCall({
183
+ target: target as `${string}::${string}::${string}`,
184
+ arguments: convertedArgs,
185
+ typeArguments: typeArgs,
186
+ });
187
+ }
188
+
189
+ /* Enhance methods of TransactionBlock */
190
+ transferSuiToMany(recipients: SuiAddressArg[], amounts: SuiAmountsArg[]) {
191
+ // require recipients.length === amounts.length
192
+ if (recipients.length !== amounts.length) {
193
+ throw new Error(
194
+ "transferSuiToMany: recipients.length !== amounts.length",
195
+ );
196
+ }
197
+ const coins = this.txBlock.splitCoins(
198
+ this.txBlock.gas,
199
+ convertAmounts(this.txBlock, amounts),
200
+ );
201
+
202
+ const recipientObjects = recipients.map((recipient) =>
203
+ convertAddressArg(this.txBlock, recipient),
204
+ );
205
+
206
+ // Transfer splitted coins to recipients
207
+ recipientObjects.forEach((address, index) => {
208
+ this.txBlock.transferObjects([coins[index]], address);
209
+ });
210
+
211
+ return this;
212
+ }
213
+
214
+ transferSui(address: SuiAddressArg, amount: SuiAmountsArg) {
215
+ return this.transferSuiToMany([address], [amount]);
216
+ }
217
+
218
+ takeAmountFromCoins(coins: SuiObjectArg[], amount: SuiAmountsArg) {
219
+ const { splitedCoins, mergedCoin } = this.splitMultiCoins(
220
+ coins,
221
+ convertAmounts(this.txBlock, [amount]),
222
+ );
223
+
224
+ return [splitedCoins, mergedCoin];
225
+ }
226
+
227
+ splitSUIFromGas(amounts: SuiAmountsArg[]) {
228
+ return this.txBlock.splitCoins(
229
+ this.txBlock.gas,
230
+ convertAmounts(this.txBlock, amounts),
231
+ );
232
+ }
233
+
234
+ splitMultiCoins(coins: SuiObjectArg[], amounts: SuiAmountsArg[]) {
235
+ if (coins.length === 0) {
236
+ throw new Error("takeAmountFromCoins: coins array is empty");
237
+ }
238
+
239
+ const partitions = partitionArray(coins.slice(1), 511);
240
+ const mergedCoin = convertObjArg(this.txBlock, coins[0]);
241
+ for (const partition of partitions) {
242
+ const coinObjects = partition.map((coin) =>
243
+ convertObjArg(this.txBlock, coin),
244
+ );
245
+ this.txBlock.mergeCoins(mergedCoin, coinObjects);
246
+ }
247
+ const splitedCoins = this.txBlock.splitCoins(
248
+ mergedCoin,
249
+ convertAmounts(this.txBlock, amounts),
250
+ );
251
+ return { splitedCoins, mergedCoin };
252
+ }
253
+
254
+ transferCoinToMany(
255
+ coins: SuiObjectArg[],
256
+ sender: SuiAddressArg,
257
+ recipients: SuiAddressArg[],
258
+ amounts: SuiAmountsArg[],
259
+ ) {
260
+ // require recipients.length === amounts.length
261
+ if (recipients.length !== amounts.length) {
262
+ throw new Error(
263
+ "transferCoinToMany: recipients.length !== amounts.length",
264
+ );
265
+ }
266
+ const coinObjects = coins.map((coin) => convertObjArg(this.txBlock, coin));
267
+ const { splitedCoins, mergedCoin } = this.splitMultiCoins(
268
+ coinObjects,
269
+ convertAmounts(this.txBlock, amounts),
270
+ );
271
+ const recipientObjects = recipients.map((recipient) =>
272
+ convertAddressArg(this.txBlock, recipient),
273
+ );
274
+
275
+ // Transfer splitted coins to recipients
276
+ recipientObjects.forEach((address, index) => {
277
+ this.txBlock.transferObjects([splitedCoins[index]], address);
278
+ });
279
+
280
+ // Return the remaining coin back to sender
281
+ this.txBlock.transferObjects(
282
+ [mergedCoin],
283
+ convertAddressArg(this.txBlock, sender),
284
+ );
285
+
286
+ return this;
287
+ }
288
+
289
+ transferCoin(
290
+ coins: SuiObjectArg[],
291
+ sender: SuiAddressArg,
292
+ recipient: SuiAddressArg,
293
+ amount: SuiAmountsArg,
294
+ ) {
295
+ return this.transferCoinToMany(coins, sender, [recipient], [amount]);
296
+ }
297
+
298
+ stakeSui(amount: SuiAmountsArg, validatorAddr: SuiAddressArg) {
299
+ const [stakeCoin] = this.txBlock.splitCoins(
300
+ this.txBlock.gas,
301
+ convertAmounts(this.txBlock, [amount]),
302
+ );
303
+ return this.txBlock.moveCall({
304
+ target: "0x3::sui_system::request_add_stake",
305
+ arguments: convertArgs(this.txBlock, [
306
+ this.txBlock.object(SUI_SYSTEM_STATE_OBJECT_ID),
307
+ stakeCoin,
308
+ convertAddressArg(this.txBlock, validatorAddr),
309
+ ]),
310
+ });
311
+ }
311
312
  }