@0xobelisk/client 0.4.7 → 1.2.0-pre.100
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/README.md +550 -2
- package/dist/browser/obelisk-client.js +102 -0
- package/dist/browser/obelisk-client.js.LICENSE.txt +16 -0
- package/dist/browser/obelisk-client.js.map +1 -0
- package/dist/browser/obelisk-client.min.js +101 -0
- package/dist/browser/obelisk-client.min.js.map +1 -0
- package/dist/index.d.ts +27 -9
- package/dist/sui/client.d.ts +59 -0
- package/dist/sui/index.d.mts +156 -0
- package/dist/sui/index.d.ts +19 -0
- package/dist/sui/index.js +93 -0
- package/dist/sui/index.js.map +1 -0
- package/dist/sui/index.mjs +88 -0
- package/dist/sui/index.mjs.map +1 -0
- package/dist/sui/types.d.ts +90 -0
- package/package.json +60 -121
- package/src/index.ts +31 -9
- package/src/sui/client.test.ts +277 -0
- package/src/sui/client.ts +157 -0
- package/src/sui/index.ts +30 -0
- package/src/sui/types.ts +94 -0
- package/LICENSE +0 -92
- package/dist/index.js +0 -1287
- package/dist/index.js.map +0 -1
- package/dist/index.mjs +0 -1268
- package/dist/index.mjs.map +0 -1
- package/dist/libs/suiAccountManager/crypto.d.ts +0 -1
- package/dist/libs/suiAccountManager/index.d.ts +0 -35
- package/dist/libs/suiAccountManager/keypair.d.ts +0 -21
- package/dist/libs/suiAccountManager/util.d.ts +0 -29
- package/dist/libs/suiContractFactory/index.d.ts +0 -20
- package/dist/libs/suiContractFactory/types.d.ts +0 -49
- package/dist/libs/suiInteractor/defaultConfig.d.ts +0 -10
- package/dist/libs/suiInteractor/index.d.ts +0 -2
- package/dist/libs/suiInteractor/suiInteractor.d.ts +0 -205
- package/dist/libs/suiInteractor/util.d.ts +0 -1
- package/dist/libs/suiModel/index.d.ts +0 -2
- package/dist/libs/suiModel/suiOwnedObject.d.ts +0 -24
- package/dist/libs/suiModel/suiSharedObject.d.ts +0 -12
- package/dist/libs/suiTxBuilder/index.d.ts +0 -544
- package/dist/libs/suiTxBuilder/util.d.ts +0 -76
- package/dist/metadata/index.d.ts +0 -34
- package/dist/obelisk.d.ts +0 -2566
- package/dist/types/index.d.ts +0 -141
- package/dist/utils/index.d.ts +0 -3
- package/src/libs/suiAccountManager/crypto.ts +0 -7
- package/src/libs/suiAccountManager/index.ts +0 -72
- package/src/libs/suiAccountManager/keypair.ts +0 -38
- package/src/libs/suiAccountManager/util.ts +0 -70
- package/src/libs/suiContractFactory/index.ts +0 -120
- package/src/libs/suiContractFactory/types.ts +0 -54
- package/src/libs/suiInteractor/defaultConfig.ts +0 -32
- package/src/libs/suiInteractor/index.ts +0 -2
- package/src/libs/suiInteractor/suiInteractor.ts +0 -319
- package/src/libs/suiInteractor/util.ts +0 -2
- package/src/libs/suiModel/index.ts +0 -2
- package/src/libs/suiModel/suiOwnedObject.ts +0 -62
- package/src/libs/suiModel/suiSharedObject.ts +0 -33
- package/src/libs/suiTxBuilder/index.ts +0 -245
- package/src/libs/suiTxBuilder/util.ts +0 -84
- package/src/metadata/index.ts +0 -22
- package/src/obelisk.ts +0 -600
- package/src/types/index.ts +0 -205
- package/src/utils/index.ts +0 -23
|
@@ -1,319 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
SuiTransactionBlockResponse,
|
|
3
|
-
SuiTransactionBlockResponseOptions,
|
|
4
|
-
JsonRpcProvider,
|
|
5
|
-
Connection,
|
|
6
|
-
getObjectDisplay,
|
|
7
|
-
getObjectFields,
|
|
8
|
-
getObjectId,
|
|
9
|
-
getObjectType,
|
|
10
|
-
getObjectVersion,
|
|
11
|
-
getSharedObjectInitialVersion,
|
|
12
|
-
DynamicFieldName,
|
|
13
|
-
SuiAddress,
|
|
14
|
-
} from '@mysten/sui.js';
|
|
15
|
-
import { requestSuiFromFaucetV0, getFaucetHost } from '@mysten/sui.js/faucet';
|
|
16
|
-
import {
|
|
17
|
-
SuiClient,
|
|
18
|
-
getFullnodeUrl,
|
|
19
|
-
GetBalanceParams,
|
|
20
|
-
} from '@mysten/sui.js/client';
|
|
21
|
-
import {
|
|
22
|
-
FaucetNetworkType,
|
|
23
|
-
NetworkType,
|
|
24
|
-
ObjectData,
|
|
25
|
-
ObjectFieldType,
|
|
26
|
-
EntityData,
|
|
27
|
-
} from '../../types';
|
|
28
|
-
import { SuiOwnedObject, SuiSharedObject } from '../suiModel';
|
|
29
|
-
import { delay } from './util';
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* `SuiTransactionSender` is used to send transaction with a given gas coin.
|
|
33
|
-
* It always uses the gas coin to pay for the gas,
|
|
34
|
-
* and update the gas coin after the transaction.
|
|
35
|
-
*/
|
|
36
|
-
export class SuiInteractor {
|
|
37
|
-
public readonly providers: JsonRpcProvider[];
|
|
38
|
-
public currentProvider: JsonRpcProvider;
|
|
39
|
-
public network?: NetworkType;
|
|
40
|
-
|
|
41
|
-
constructor(fullNodeUrls: string[], network?: NetworkType) {
|
|
42
|
-
if (fullNodeUrls.length === 0)
|
|
43
|
-
throw new Error('fullNodeUrls must not be empty');
|
|
44
|
-
this.providers = fullNodeUrls.map(
|
|
45
|
-
(url) => new JsonRpcProvider(new Connection({ fullnode: url }))
|
|
46
|
-
);
|
|
47
|
-
this.currentProvider = this.providers[0];
|
|
48
|
-
this.network = network;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
switchToNextProvider() {
|
|
52
|
-
const currentProviderIdx = this.providers.indexOf(this.currentProvider);
|
|
53
|
-
this.currentProvider =
|
|
54
|
-
this.providers[(currentProviderIdx + 1) % this.providers.length];
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
async sendTx(
|
|
58
|
-
transactionBlock: Uint8Array | string,
|
|
59
|
-
signature: string | string[]
|
|
60
|
-
): Promise<SuiTransactionBlockResponse> {
|
|
61
|
-
const txResOptions: SuiTransactionBlockResponseOptions = {
|
|
62
|
-
showEvents: true,
|
|
63
|
-
showEffects: true,
|
|
64
|
-
showObjectChanges: true,
|
|
65
|
-
showBalanceChanges: true,
|
|
66
|
-
};
|
|
67
|
-
|
|
68
|
-
// const currentProviderIdx = this.providers.indexOf(this.currentProvider);
|
|
69
|
-
// const providers = [
|
|
70
|
-
// ...this.providers.slice(currentProviderIdx, this.providers.length),
|
|
71
|
-
// ...this.providers.slice(0, currentProviderIdx),
|
|
72
|
-
// ]
|
|
73
|
-
|
|
74
|
-
for (const provider of this.providers) {
|
|
75
|
-
try {
|
|
76
|
-
const res = await provider.executeTransactionBlock({
|
|
77
|
-
transactionBlock,
|
|
78
|
-
signature,
|
|
79
|
-
options: txResOptions,
|
|
80
|
-
});
|
|
81
|
-
return res;
|
|
82
|
-
} catch (err) {
|
|
83
|
-
console.warn(
|
|
84
|
-
`Failed to send transaction with fullnode ${provider.connection.fullnode}: ${err}`
|
|
85
|
-
);
|
|
86
|
-
await delay(2000);
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
throw new Error('Failed to send transaction with all fullnodes');
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
async getObjects(ids: string[]) {
|
|
93
|
-
const options = {
|
|
94
|
-
showContent: true,
|
|
95
|
-
showDisplay: true,
|
|
96
|
-
showType: true,
|
|
97
|
-
showOwner: true,
|
|
98
|
-
};
|
|
99
|
-
|
|
100
|
-
// const currentProviderIdx = this.providers.indexOf(this.currentProvider);
|
|
101
|
-
// const providers = [
|
|
102
|
-
// ...this.providers.slice(currentProviderIdx, this.providers.length),
|
|
103
|
-
// ...this.providers.slice(0, currentProviderIdx),
|
|
104
|
-
// ]
|
|
105
|
-
|
|
106
|
-
for (const provider of this.providers) {
|
|
107
|
-
try {
|
|
108
|
-
const objects = await provider.multiGetObjects({ ids, options });
|
|
109
|
-
const parsedObjects = objects.map((object) => {
|
|
110
|
-
const objectId = getObjectId(object);
|
|
111
|
-
const objectType = getObjectType(object);
|
|
112
|
-
const objectVersion = getObjectVersion(object);
|
|
113
|
-
const objectDigest = object.data ? object.data.digest : undefined;
|
|
114
|
-
const initialSharedVersion = getSharedObjectInitialVersion(object);
|
|
115
|
-
const objectFields = getObjectFields(object);
|
|
116
|
-
const objectDisplay = getObjectDisplay(object);
|
|
117
|
-
return {
|
|
118
|
-
objectId,
|
|
119
|
-
objectType,
|
|
120
|
-
objectVersion,
|
|
121
|
-
objectDigest,
|
|
122
|
-
objectFields,
|
|
123
|
-
objectDisplay,
|
|
124
|
-
initialSharedVersion,
|
|
125
|
-
};
|
|
126
|
-
});
|
|
127
|
-
return parsedObjects as ObjectData[];
|
|
128
|
-
} catch (err) {
|
|
129
|
-
await delay(2000);
|
|
130
|
-
console.warn(
|
|
131
|
-
`Failed to get objects with fullnode ${provider.connection.fullnode}: ${err}`
|
|
132
|
-
);
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
throw new Error('Failed to get objects with all fullnodes');
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
async getObject(id: string) {
|
|
139
|
-
const objects = await this.getObjects([id]);
|
|
140
|
-
return objects[0];
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
async getEntitiesObjects(ids: string[]) {
|
|
144
|
-
const options = {
|
|
145
|
-
showContent: true,
|
|
146
|
-
showType: true,
|
|
147
|
-
};
|
|
148
|
-
|
|
149
|
-
// const currentProviderIdx = this.providers.indexOf(this.currentProvider);
|
|
150
|
-
// const providers = [
|
|
151
|
-
// ...this.providers.slice(currentProviderIdx, this.providers.length),
|
|
152
|
-
// ...this.providers.slice(0, currentProviderIdx),
|
|
153
|
-
// ]
|
|
154
|
-
|
|
155
|
-
for (const provider of this.providers) {
|
|
156
|
-
try {
|
|
157
|
-
const objects = await provider.multiGetObjects({ ids, options });
|
|
158
|
-
const parsedObjects = objects.map((object) => {
|
|
159
|
-
const objectId = getObjectId(object);
|
|
160
|
-
const objectFields = getObjectFields(object) as ObjectFieldType;
|
|
161
|
-
const index = objectFields.name;
|
|
162
|
-
const key = objectFields.value;
|
|
163
|
-
return {
|
|
164
|
-
objectId,
|
|
165
|
-
index,
|
|
166
|
-
key,
|
|
167
|
-
};
|
|
168
|
-
});
|
|
169
|
-
return parsedObjects as EntityData[];
|
|
170
|
-
} catch (err) {
|
|
171
|
-
await delay(2000);
|
|
172
|
-
console.warn(
|
|
173
|
-
`Failed to get objects with fullnode ${provider.connection.fullnode}: ${err}`
|
|
174
|
-
);
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
throw new Error('Failed to get objects with all fullnodes');
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
async getDynamicFieldObject(
|
|
181
|
-
parentId: string,
|
|
182
|
-
name: string | DynamicFieldName
|
|
183
|
-
) {
|
|
184
|
-
for (const provider of this.providers) {
|
|
185
|
-
try {
|
|
186
|
-
return provider.getDynamicFieldObject({ parentId, name });
|
|
187
|
-
} catch (err) {
|
|
188
|
-
await delay(2000);
|
|
189
|
-
console.warn(
|
|
190
|
-
`Failed to get objects with fullnode ${provider.connection.fullnode}: ${err}`
|
|
191
|
-
);
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
throw new Error('Failed to get objects with all fullnodes');
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
async getDynamicFields(parentId: string, cursor?: string, limit?: number) {
|
|
198
|
-
for (const provider of this.providers) {
|
|
199
|
-
try {
|
|
200
|
-
return provider.getDynamicFields({ parentId, cursor, limit });
|
|
201
|
-
} catch (err) {
|
|
202
|
-
await delay(2000);
|
|
203
|
-
console.warn(
|
|
204
|
-
`Failed to get objects with fullnode ${provider.connection.fullnode}: ${err}`
|
|
205
|
-
);
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
throw new Error('Failed to get objects with all fullnodes');
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
async getOwnedObjects(owner: SuiAddress, cursor?: string, limit?: number) {
|
|
212
|
-
for (const provider of this.providers) {
|
|
213
|
-
try {
|
|
214
|
-
return await provider.getOwnedObjects({ owner, cursor, limit });
|
|
215
|
-
} catch (err) {
|
|
216
|
-
await delay(2000);
|
|
217
|
-
console.warn(
|
|
218
|
-
`Failed to get objects with fullnode ${provider.connection.fullnode}: ${err}`
|
|
219
|
-
);
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
throw new Error('Failed to get objects with all fullnodes');
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
async getNormalizedMoveModulesByPackage(packageId: string) {
|
|
226
|
-
for (const provider of this.providers) {
|
|
227
|
-
try {
|
|
228
|
-
return provider.getNormalizedMoveModulesByPackage({
|
|
229
|
-
package: packageId,
|
|
230
|
-
});
|
|
231
|
-
} catch (err) {
|
|
232
|
-
await delay(2000);
|
|
233
|
-
console.warn(
|
|
234
|
-
`Failed to get objects with fullnode ${provider.connection.fullnode}: ${err}`
|
|
235
|
-
);
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
throw new Error('Failed to get objects with all fullnodes');
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
/**
|
|
242
|
-
* @description Update objects in a batch
|
|
243
|
-
* @param suiObjects
|
|
244
|
-
*/
|
|
245
|
-
async updateObjects(suiObjects: (SuiOwnedObject | SuiSharedObject)[]) {
|
|
246
|
-
const objectIds = suiObjects.map((obj) => obj.objectId);
|
|
247
|
-
const objects = await this.getObjects(objectIds);
|
|
248
|
-
for (const object of objects) {
|
|
249
|
-
const suiObject = suiObjects.find(
|
|
250
|
-
(obj) => obj.objectId === object.objectId
|
|
251
|
-
);
|
|
252
|
-
if (suiObject instanceof SuiSharedObject) {
|
|
253
|
-
suiObject.initialSharedVersion = object.initialSharedVersion;
|
|
254
|
-
} else if (suiObject instanceof SuiOwnedObject) {
|
|
255
|
-
suiObject.version = object.objectVersion;
|
|
256
|
-
suiObject.digest = object.objectDigest;
|
|
257
|
-
}
|
|
258
|
-
}
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
/**
|
|
262
|
-
* @description Select coins that add up to the given amount.
|
|
263
|
-
* @param addr the address of the owner
|
|
264
|
-
* @param amount the amount that is needed for the coin
|
|
265
|
-
* @param coinType the coin type, default is '0x2::SUI::SUI'
|
|
266
|
-
*/
|
|
267
|
-
async selectCoins(
|
|
268
|
-
addr: string,
|
|
269
|
-
amount: number,
|
|
270
|
-
coinType: string = '0x2::SUI::SUI'
|
|
271
|
-
) {
|
|
272
|
-
const selectedCoins: {
|
|
273
|
-
objectId: string;
|
|
274
|
-
digest: string;
|
|
275
|
-
version: string;
|
|
276
|
-
}[] = [];
|
|
277
|
-
let totalAmount = 0;
|
|
278
|
-
let hasNext = true,
|
|
279
|
-
nextCursor: string | null = null;
|
|
280
|
-
while (hasNext && totalAmount < amount) {
|
|
281
|
-
const coins = await this.currentProvider.getCoins({
|
|
282
|
-
owner: addr,
|
|
283
|
-
coinType: coinType,
|
|
284
|
-
cursor: nextCursor,
|
|
285
|
-
});
|
|
286
|
-
// Sort the coins by balance in descending order
|
|
287
|
-
coins.data.sort((a, b) => parseInt(b.balance) - parseInt(a.balance));
|
|
288
|
-
for (const coinData of coins.data) {
|
|
289
|
-
selectedCoins.push({
|
|
290
|
-
objectId: coinData.coinObjectId,
|
|
291
|
-
digest: coinData.digest,
|
|
292
|
-
version: coinData.version,
|
|
293
|
-
});
|
|
294
|
-
totalAmount = totalAmount + parseInt(coinData.balance);
|
|
295
|
-
if (totalAmount >= amount) {
|
|
296
|
-
break;
|
|
297
|
-
}
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
nextCursor = coins.nextCursor;
|
|
301
|
-
hasNext = coins.hasNextPage;
|
|
302
|
-
}
|
|
303
|
-
|
|
304
|
-
if (!selectedCoins.length) {
|
|
305
|
-
throw new Error('No valid coins found for the transaction.');
|
|
306
|
-
}
|
|
307
|
-
return selectedCoins;
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
async requestFaucet(address: SuiAddress, network: FaucetNetworkType) {
|
|
311
|
-
await requestSuiFromFaucetV0({
|
|
312
|
-
host: getFaucetHost(network),
|
|
313
|
-
recipient: address,
|
|
314
|
-
});
|
|
315
|
-
// let params = {
|
|
316
|
-
// owner: address
|
|
317
|
-
// } as GetBalanceParams;
|
|
318
|
-
}
|
|
319
|
-
}
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
import { Infer } from 'superstruct';
|
|
2
|
-
import {
|
|
3
|
-
getObjectChanges,
|
|
4
|
-
SuiTransactionBlockResponse,
|
|
5
|
-
ObjectCallArg,
|
|
6
|
-
ObjectId,
|
|
7
|
-
} from '@mysten/sui.js';
|
|
8
|
-
|
|
9
|
-
export class SuiOwnedObject {
|
|
10
|
-
public readonly objectId: string;
|
|
11
|
-
public version?: number | string;
|
|
12
|
-
public digest?: string;
|
|
13
|
-
|
|
14
|
-
constructor(param: { objectId: string; version?: string; digest?: string }) {
|
|
15
|
-
this.objectId = param.objectId;
|
|
16
|
-
this.version = param.version;
|
|
17
|
-
this.digest = param.digest;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* Check if the object is fully initialized.
|
|
22
|
-
* So that when it's used as an input, it won't be necessary to fetch from fullnode again.
|
|
23
|
-
* Which can save time when sending transactions.
|
|
24
|
-
*/
|
|
25
|
-
isFullObject(): boolean {
|
|
26
|
-
return !!this.version && !!this.digest;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
asCallArg(): Infer<typeof ObjectCallArg> | Infer<typeof ObjectId> {
|
|
30
|
-
if (!this.version || !this.digest) {
|
|
31
|
-
return this.objectId;
|
|
32
|
-
}
|
|
33
|
-
return {
|
|
34
|
-
Object: {
|
|
35
|
-
ImmOrOwned: {
|
|
36
|
-
objectId: this.objectId,
|
|
37
|
-
version: this.version,
|
|
38
|
-
digest: this.digest,
|
|
39
|
-
},
|
|
40
|
-
},
|
|
41
|
-
};
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
* Update object version & digest based on the transaction response.
|
|
46
|
-
* @param txResponse
|
|
47
|
-
*/
|
|
48
|
-
updateFromTxResponse(txResponse: SuiTransactionBlockResponse) {
|
|
49
|
-
const changes = getObjectChanges(txResponse);
|
|
50
|
-
if (!changes) {
|
|
51
|
-
throw new Error('Bad transaction response!');
|
|
52
|
-
}
|
|
53
|
-
for (const change of changes) {
|
|
54
|
-
if (change.type === 'mutated' && change.objectId === this.objectId) {
|
|
55
|
-
this.digest = change.digest;
|
|
56
|
-
this.version = change.version;
|
|
57
|
-
return;
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
throw new Error('Could not find object in transaction response!');
|
|
61
|
-
}
|
|
62
|
-
}
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
import { Infer } from 'superstruct';
|
|
2
|
-
import { ObjectCallArg, ObjectId } from '@mysten/sui.js';
|
|
3
|
-
|
|
4
|
-
export class SuiSharedObject {
|
|
5
|
-
public readonly objectId: string;
|
|
6
|
-
public initialSharedVersion?: number | string;
|
|
7
|
-
|
|
8
|
-
constructor(param: {
|
|
9
|
-
objectId: string;
|
|
10
|
-
initialSharedVersion?: number;
|
|
11
|
-
mutable?: boolean;
|
|
12
|
-
}) {
|
|
13
|
-
this.objectId = param.objectId;
|
|
14
|
-
this.initialSharedVersion = param.initialSharedVersion;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
asCallArg(
|
|
18
|
-
mutable: boolean = false
|
|
19
|
-
): Infer<typeof ObjectCallArg> | Infer<typeof ObjectId> {
|
|
20
|
-
if (!this.initialSharedVersion) {
|
|
21
|
-
return this.objectId;
|
|
22
|
-
}
|
|
23
|
-
return {
|
|
24
|
-
Object: {
|
|
25
|
-
Shared: {
|
|
26
|
-
objectId: this.objectId,
|
|
27
|
-
initialSharedVersion: this.initialSharedVersion,
|
|
28
|
-
mutable,
|
|
29
|
-
},
|
|
30
|
-
},
|
|
31
|
-
};
|
|
32
|
-
}
|
|
33
|
-
}
|
|
@@ -1,245 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
TransactionBlock,
|
|
3
|
-
SUI_SYSTEM_STATE_OBJECT_ID,
|
|
4
|
-
TransactionExpiration,
|
|
5
|
-
SuiObjectRef,
|
|
6
|
-
SharedObjectRef,
|
|
7
|
-
JsonRpcProvider,
|
|
8
|
-
TransactionType,
|
|
9
|
-
Transactions,
|
|
10
|
-
ObjectCallArg,
|
|
11
|
-
} from '@mysten/sui.js';
|
|
12
|
-
import { convertArgs } from './util';
|
|
13
|
-
import type { SuiTxArg, SuiObjectArg, SuiVecTxArg } from '../../types';
|
|
14
|
-
|
|
15
|
-
export class SuiTxBlock {
|
|
16
|
-
public txBlock: TransactionBlock;
|
|
17
|
-
constructor(transaction?: TransactionBlock) {
|
|
18
|
-
this.txBlock = new TransactionBlock(transaction);
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
//======== override methods of TransactionBlock ============
|
|
22
|
-
|
|
23
|
-
address(value: string) {
|
|
24
|
-
return this.txBlock.pure(value, 'address');
|
|
25
|
-
}
|
|
26
|
-
pure(value: unknown, type?: string) {
|
|
27
|
-
return this.txBlock.pure(value, type);
|
|
28
|
-
}
|
|
29
|
-
object(value: string | ObjectCallArg) {
|
|
30
|
-
return this.txBlock.object(value);
|
|
31
|
-
}
|
|
32
|
-
objectRef(ref: SuiObjectRef) {
|
|
33
|
-
return this.txBlock.objectRef(ref);
|
|
34
|
-
}
|
|
35
|
-
sharedObjectRef(ref: SharedObjectRef) {
|
|
36
|
-
return this.txBlock.sharedObjectRef(ref);
|
|
37
|
-
}
|
|
38
|
-
setSender(sender: string) {
|
|
39
|
-
return this.txBlock.setSender(sender);
|
|
40
|
-
}
|
|
41
|
-
setSenderIfNotSet(sender: string) {
|
|
42
|
-
return this.txBlock.setSenderIfNotSet(sender);
|
|
43
|
-
}
|
|
44
|
-
setExpiration(expiration?: TransactionExpiration) {
|
|
45
|
-
return this.txBlock.setExpiration(expiration);
|
|
46
|
-
}
|
|
47
|
-
setGasPrice(price: number | bigint) {
|
|
48
|
-
return this.txBlock.setGasPrice(price);
|
|
49
|
-
}
|
|
50
|
-
setGasBudget(budget: number | bigint) {
|
|
51
|
-
return this.txBlock.setGasBudget(budget);
|
|
52
|
-
}
|
|
53
|
-
setGasOwner(owner: string) {
|
|
54
|
-
return this.txBlock.setGasOwner(owner);
|
|
55
|
-
}
|
|
56
|
-
setGasPayment(payments: SuiObjectRef[]) {
|
|
57
|
-
return this.txBlock.setGasPayment(payments);
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
add(transaction: TransactionType) {
|
|
61
|
-
return this.txBlock.add(transaction);
|
|
62
|
-
}
|
|
63
|
-
serialize() {
|
|
64
|
-
return this.txBlock.serialize();
|
|
65
|
-
}
|
|
66
|
-
build(
|
|
67
|
-
params: {
|
|
68
|
-
provider?: JsonRpcProvider;
|
|
69
|
-
onlyTransactionKind?: boolean;
|
|
70
|
-
} = {}
|
|
71
|
-
) {
|
|
72
|
-
return this.txBlock.build(params);
|
|
73
|
-
}
|
|
74
|
-
getDigest({ provider }: { provider?: JsonRpcProvider } = {}) {
|
|
75
|
-
return this.txBlock.getDigest({ provider });
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
get gas() {
|
|
79
|
-
return this.txBlock.gas;
|
|
80
|
-
}
|
|
81
|
-
get blockData() {
|
|
82
|
-
return this.txBlock.blockData;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
transferObjects(objects: SuiObjectArg[], recipient: string) {
|
|
86
|
-
const tx = this.txBlock;
|
|
87
|
-
tx.transferObjects(convertArgs(this.txBlock, objects), tx.pure(recipient));
|
|
88
|
-
return this;
|
|
89
|
-
}
|
|
90
|
-
splitCoins(coin: SuiObjectArg, amounts: number[]) {
|
|
91
|
-
const tx = this.txBlock;
|
|
92
|
-
const coinObject = convertArgs(this.txBlock, [coin])[0];
|
|
93
|
-
const res = tx.splitCoins(
|
|
94
|
-
coinObject,
|
|
95
|
-
amounts.map((m) => tx.pure(m))
|
|
96
|
-
);
|
|
97
|
-
return amounts.map((_, i) => res[i]);
|
|
98
|
-
}
|
|
99
|
-
mergeCoins(destination: SuiObjectArg, sources: SuiObjectArg[]) {
|
|
100
|
-
const destinationObject = convertArgs(this.txBlock, [destination])[0];
|
|
101
|
-
const sourceObjects = convertArgs(this.txBlock, sources);
|
|
102
|
-
return this.txBlock.mergeCoins(destinationObject, sourceObjects);
|
|
103
|
-
}
|
|
104
|
-
publish(...args: Parameters<(typeof Transactions)['Publish']>) {
|
|
105
|
-
return this.txBlock.publish(...args);
|
|
106
|
-
}
|
|
107
|
-
upgrade(...args: Parameters<(typeof Transactions)['Upgrade']>) {
|
|
108
|
-
return this.txBlock.upgrade(...args);
|
|
109
|
-
}
|
|
110
|
-
makeMoveVec(...args: Parameters<(typeof Transactions)['MakeMoveVec']>) {
|
|
111
|
-
return this.txBlock.makeMoveVec(...args);
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
/**
|
|
115
|
-
* @description Move call
|
|
116
|
-
* @param target `${string}::${string}::${string}`, e.g. `0x3::sui_system::request_add_stake`
|
|
117
|
-
* @param args the arguments of the move call, such as `['0x1', '0x2']`
|
|
118
|
-
* @param typeArgs the type arguments of the move call, such as `['0x2::sui::SUI']`
|
|
119
|
-
*/
|
|
120
|
-
moveCall(
|
|
121
|
-
target: string,
|
|
122
|
-
args: (SuiTxArg | SuiVecTxArg)[] = [],
|
|
123
|
-
typeArgs: string[] = []
|
|
124
|
-
) {
|
|
125
|
-
// a regex for pattern `${string}::${string}::${string}`
|
|
126
|
-
const regex =
|
|
127
|
-
/(?<package>[a-zA-Z0-9]+)::(?<module>[a-zA-Z0-9_]+)::(?<function>[a-zA-Z0-9_]+)/;
|
|
128
|
-
const match = target.match(regex);
|
|
129
|
-
if (match === null)
|
|
130
|
-
throw new Error(
|
|
131
|
-
'Invalid target format. Expected `${string}::${string}::${string}`'
|
|
132
|
-
);
|
|
133
|
-
const convertedArgs = convertArgs(this.txBlock, args);
|
|
134
|
-
const tx = this.txBlock;
|
|
135
|
-
return tx.moveCall({
|
|
136
|
-
target: target as `${string}::${string}::${string}`,
|
|
137
|
-
arguments: convertedArgs,
|
|
138
|
-
typeArguments: typeArgs,
|
|
139
|
-
});
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
//======== enhance methods ============
|
|
143
|
-
transferSuiToMany(recipients: string[], amounts: number[]) {
|
|
144
|
-
// require recipients.length === amounts.length
|
|
145
|
-
if (recipients.length !== amounts.length) {
|
|
146
|
-
throw new Error(
|
|
147
|
-
'transferSuiToMany: recipients.length !== amounts.length'
|
|
148
|
-
);
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
const tx = this.txBlock;
|
|
152
|
-
const coins = tx.splitCoins(
|
|
153
|
-
tx.gas,
|
|
154
|
-
amounts.map((amount) => tx.pure(amount))
|
|
155
|
-
);
|
|
156
|
-
recipients.forEach((recipient, index) => {
|
|
157
|
-
tx.transferObjects([coins[index]], tx.pure(recipient));
|
|
158
|
-
});
|
|
159
|
-
return this;
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
transferSui(recipient: string, amount: number) {
|
|
163
|
-
return this.transferSuiToMany([recipient], [amount]);
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
takeAmountFromCoins(coins: SuiObjectArg[], amount: number) {
|
|
167
|
-
const tx = this.txBlock;
|
|
168
|
-
const coinObjects = convertArgs(this.txBlock, coins);
|
|
169
|
-
const mergedCoin = coinObjects[0];
|
|
170
|
-
if (coins.length > 1) {
|
|
171
|
-
tx.mergeCoins(mergedCoin, coinObjects.slice(1));
|
|
172
|
-
}
|
|
173
|
-
const [sendCoin] = tx.splitCoins(mergedCoin, [tx.pure(amount)]);
|
|
174
|
-
return [sendCoin, mergedCoin];
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
splitSUIFromGas(amounts: number[]) {
|
|
178
|
-
const tx = this.txBlock;
|
|
179
|
-
return tx.splitCoins(
|
|
180
|
-
tx.gas,
|
|
181
|
-
amounts.map((m) => tx.pure(m))
|
|
182
|
-
);
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
splitMultiCoins(coins: SuiObjectArg[], amounts: number[]) {
|
|
186
|
-
const tx = this.txBlock;
|
|
187
|
-
const coinObjects = convertArgs(this.txBlock, coins);
|
|
188
|
-
const mergedCoin = coinObjects[0];
|
|
189
|
-
if (coins.length > 1) {
|
|
190
|
-
tx.mergeCoins(mergedCoin, coinObjects.slice(1));
|
|
191
|
-
}
|
|
192
|
-
const splitedCoins = tx.splitCoins(
|
|
193
|
-
mergedCoin,
|
|
194
|
-
amounts.map((m) => tx.pure(m))
|
|
195
|
-
);
|
|
196
|
-
return { splitedCoins, mergedCoin };
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
transferCoinToMany(
|
|
200
|
-
inputCoins: SuiObjectArg[],
|
|
201
|
-
sender: string,
|
|
202
|
-
recipients: string[],
|
|
203
|
-
amounts: number[]
|
|
204
|
-
) {
|
|
205
|
-
// require recipients.length === amounts.length
|
|
206
|
-
if (recipients.length !== amounts.length) {
|
|
207
|
-
throw new Error(
|
|
208
|
-
'transferSuiToMany: recipients.length !== amounts.length'
|
|
209
|
-
);
|
|
210
|
-
}
|
|
211
|
-
const tx = this.txBlock;
|
|
212
|
-
const { splitedCoins, mergedCoin } = this.splitMultiCoins(
|
|
213
|
-
inputCoins,
|
|
214
|
-
amounts
|
|
215
|
-
);
|
|
216
|
-
recipients.forEach((recipient, index) => {
|
|
217
|
-
tx.transferObjects([splitedCoins[index]], tx.pure(recipient));
|
|
218
|
-
});
|
|
219
|
-
tx.transferObjects([mergedCoin], tx.pure(sender));
|
|
220
|
-
return this;
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
transferCoin(
|
|
224
|
-
inputCoins: SuiObjectArg[],
|
|
225
|
-
sender: string,
|
|
226
|
-
recipient: string,
|
|
227
|
-
amount: number
|
|
228
|
-
) {
|
|
229
|
-
return this.transferCoinToMany(inputCoins, sender, [recipient], [amount]);
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
stakeSui(amount: number, validatorAddr: string) {
|
|
233
|
-
const tx = this.txBlock;
|
|
234
|
-
const [stakeCoin] = tx.splitCoins(tx.gas, [tx.pure(amount)]);
|
|
235
|
-
tx.moveCall({
|
|
236
|
-
target: '0x3::sui_system::request_add_stake',
|
|
237
|
-
arguments: [
|
|
238
|
-
tx.object(SUI_SYSTEM_STATE_OBJECT_ID),
|
|
239
|
-
stakeCoin,
|
|
240
|
-
tx.pure(validatorAddr),
|
|
241
|
-
],
|
|
242
|
-
});
|
|
243
|
-
return tx;
|
|
244
|
-
}
|
|
245
|
-
}
|